Internal Link in a URL link's text

What I’m trying to do

I’m trying to add an internal link to the text of a URL link. For example:
Check out this URL on [[2023-07-10]] if you want to

But in edit view it is producing…
[Check out this URL on [2023-07-10 if you want to

(Notice the ending brackets are missing on the internal link)

But in reading view it is producing the intended result. The URL works and the internal link work…

Check out this URL on [[2023-07-10]] if you want to

I would like to avoid switching back and forth between edit and reading views.

Things I have tried

I’ve tried escaping the brackets and adding quotes.

First, when you post Markdown in the forum, surround it with backticks, or triple backticks, so we can see it without auto-formatting.

`One line of Markdown code`
```
two lines of
Markdown code
```

I highly doubt mixing syntax like that is supported. Wikilinks within wikilinks are also not supported.

The fact that it “works” in Reading Mode might just be a glitch/coincidence. It’s parsing it the best way that it can. Notice it stops formatting the link correctly after the closing wikilink brackets.

You can see why this is glitchy in the html it produces. The portions get split into different html elements.

<div class="cm-active cm-line">
    <span class="cm-formatting cm-formatting-link cm-hmd-barelink cm-link" spellcheck="false">[</span>
    <span class="cm-hmd-barelink cm-link">Check out this URL on </span>
    <span class="cm-formatting-link cm-formatting-link-start cm-hmd-barelink cm-link" spellcheck="false">[[</span>
    <span class="cm-hmd-internal-link cm-link">
    <span class="is-unresolved"><span class="cm-underline" draggable="true">2023-07-10</span></span></span>
    <img class="cm-widgetBuffer" aria-hidden="true">
    <span contenteditable="false"></span>
    <img class="cm-widgetBuffer" aria-hidden="true"> if you want to](google.com)
</div>

A link with a link sounds just wrong. You should separate the two links so they’re distinct links, and don’t share any parts.

Any other behavior is either a feature or a bug, and shouldn’t be trusted.

Yeah so the back story you probably didn’t need to know and doesn’t pertain exactly to Obsidian… I use a program called Hookmark. It will create a markdown link to anywhere in your computer local environment. In this example I am copying a markdown link to a specific email.

When Hookmark copies the link and it produces a markdown URL link, it includes the date of the email in the text portion of the hyperlink, surrounded by brackets. I thought to myself, if I could only configure Hookmark to make that date an internal link, it would then be tethered to my Obsidian daily note.

I’m not sure how to configure Hookmark to place the date at the end of the copied link, instead of being inside the hyperlink text portion. But again, I think that is outside the scope of this forum and maybe inappropriate for the discussion. Just thought you would like to know the intent.

Here is the script they allow you to edit…

-- set longFormName to false to exclude source, destination and date from the names of links to email
global longFormName
global placeMetaDataBeforeSubject
set longFormName to true
set placeMetaDataBeforeSubject to false

-- you may replace these labels if you like, such as "de" and "à" respectively in French
global sourceLabel
global destinationLabel
set sourceLabel to "From"
set destinationLabel to "to"

tell application "Mail"
	
	set frontWinIsMessageViewer to false
	
	set fid to id of front window
	repeat with v in message viewers
		set wid to id of window of v
		if fid = wid then
			set frontWinIsMessageViewer to true
		end if
	end repeat
	
	if frontWinIsMessageViewer then
		try
			set theSelection to selection
			set theMessage to item 1 of theSelection
			set mid to message id of theMessage
			set mid to my encodeText(mid, true, false)
			set sub to subject of theMessage
			set mTitle to my getMessageTitle(sub, theMessage)
			return "[" & mTitle & "](" & "email://" & mid & ")"
		on error eStr number enum
			display dialog eStr & "step 1"
			return
		end try
	end if
	
	try
		set theSelection to selection
		set theMessage to item 1 of theSelection
		set mid to message id of theMessage
		set mid to my encodeText(mid, true, false)
		
		set subj to subject of theMessage
		set wname to name of front window
		
		set astid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to {" ", ": "} -- to strip "re: ", "re:", "Re: ", "fwd:", etc
		repeat with i from 1 to count of text items of subj
			repeat with j from 1 to count of text items of wname
				if text item i of subj is equal to text item j of wname then
					repeat with k from j to (count of text items of subj) - i
						set window_title to text item k of wname
						set subj_name to text item (i + k - j) of subj
						if window_title is not equal to subj_name then
							set AppleScript's text item delimiters to astid
							return
						end if
					end repeat
					set AppleScript's text item delimiters to astid
					set mTitle to my getMessageTitle(subj, theMessage)
					
					return "[" & mTitle & "](" & "email://" & mid & ")" -- an old message
				end if
			end repeat
		end repeat
		set AppleScript's text item delimiters to astid
		
	on error eStr number enum
		display dialog eStr & "step 2"
		
	end try
	
	try
		set searchText to name of front window
		set astid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to {" — "} -- to strip " — mailbox"
		set searchText to text item 1 of searchText
		set AppleScript's text item delimiters to astid
		
		set matchText to paragraphs of (do shell script "mdfind \"kMDItemSubject == " & quoted form of searchText & "\"")
		
		if matchText ≠ {} then
			set targetMatch to (item 1 of matchText) as rich text
			if targetMatch ≠ "false" then
				set lns to paragraphs of (read targetMatch)
				repeat with ln in lns
					if ln starts with "Message-ID:" then
						set x to length of "Message-ID:"
						set ln to characters (x + 1) thru -1 of ln as string
						repeat while ln begins with " "
							set ln to characters (2) thru -1 of ln as string
						end repeat
						repeat while ln begins with "<"
							set ln to characters 2 thru -1 of ln as string
						end repeat
						repeat while ln ends with ">"
							set ln to characters 1 thru -2 of ln as string
						end repeat
						set ln to my encodeText(ln, true, false)
						return "email://" & ln
					end if
				end repeat
			end if
		end if
	on error eStr number enum
		display dialog eStr & "step 3"
		
	end try
end tell
on encodeText(theText, encodeCommonSpecialCharacters, encodeExtendedSpecialCharacters)
	set theStandardCharacters to "abcdefghijklmnopqrstuvwxyz0123456789"
	set theCommonSpecialCharacterList to "$+!'/?;&@=#%><{}\"~`^\\|*"
	set theExtendedSpecialCharacterList to ".-_:"
	set theAcceptableCharacters to theStandardCharacters
	if encodeCommonSpecialCharacters is false then set theAcceptableCharacters to theAcceptableCharacters & theCommonSpecialCharacterList
	if encodeExtendedSpecialCharacters is false then set theAcceptableCharacters to theAcceptableCharacters & theExtendedSpecialCharacterList
	set theEncodedText to ""
	repeat with theCurrentCharacter in theText
		if theCurrentCharacter is in theAcceptableCharacters then
			set theEncodedText to (theEncodedText & theCurrentCharacter)
		else
			set theEncodedText to (theEncodedText & encodeCharacter(theCurrentCharacter)) as string
		end if
	end repeat
	return theEncodedText
end encodeText

on encodeCharacter(theCharacter)
	set theASCIINumber to (the ASCII number theCharacter)
	set theHexList to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
	set theFirstItem to item ((theASCIINumber div 16) + 1) of theHexList
	set theSecondItem to item ((theASCIINumber mod 16) + 1) of theHexList
	return ("%" & theFirstItem & theSecondItem) as string
end encodeCharacter

on getMessageTitle(subj, theMessage)
	tell application "Mail"
		set subj to subject of theMessage
		if longFormName is false then
			return subj
		end if
		try
			set c to count of to recipients of theMessage
			if c > 0 then
				set toMail to address of item 1 of to recipients of theMessage
			else
				set toMail to ""
			end if
			set fromMail to extract address from sender of theMessage
			
			set d to date received of theMessage
			set mon to month of d as number
			if mon < 10 then
				set mon to "0" & mon
			end if
			set yy to year of d as string
			set dd to day of d as string
			set d to (yy & "-" & mon & "-" & dd)
			if placeMetaDataBeforeSubject then
				set subj to d & " " & sourceLabel & " " & fromMail & " " & destinationLabel & " " & toMail & " " & subj
				
			else
				set subj to subj & " " & d & " " & sourceLabel & " " & fromMail & " " & destinationLabel & " " & toMail
			end if
			
			
		end try
		return subj
	end tell
end getMessageTitle

This kind of context is very helpful, so maybe someone can help edit the script, or suggest workarounds for what you’re trying to do.

1 Like

Ok that sounds perfect. Any idea on how I would append the date in double brackets on the clipboard after the markdown link copy?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.