I’ve started using Obsidian.md alongside DEVONthink 3 for my academic notes.
Obsidian uses their own flavor of markdown syntax for images , ![[image.png]], which unfortunately isn’t readable by other external editors.
Ideally, I’d like to use a Smart Rule to monitor my markdown notes and Search and Replace the contents, changing ![[image.png]] to ![](image.png), possibly with RegEX (\!\[\[)(.*)(\]\]) built into the script.
Is it possible to do this?
Grateful in advance for any help, suggestions or solutions.
If i could, I’d do it in JavaScript and it would be a ten liner or so. Unfortunately, JS doesn’t work in smart rules, only in scripts. You could try to do it in
AppleScript, but reg exes are not really available there
-- Replace Obsidian image links with DEVONthink image links
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
tell application id "DNtp"
try
set theRecords to selection of think window 1
if theRecords = {} then error "Nothing selected."
repeat with thisRecord in theRecords
set theType to (type of thisRecord) as string
if theType = "markdown" or theType = "«constant Ctypmkdn»" then
set theText to plain text of thisRecord as string
if theText ≠ "" then
set newText to my replaceImageLinks(theText)
if newText ≠ theText and newText ≠ "" and newText ≠ "missing value" then set plain text of thisRecord to newText
end if
end if
end repeat
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
end try
end tell
on replaceImageLinks(theText)
try
set ca to a reference to current application
set theString to ca's NSString's stringWithString:theText
set newString to theString's stringByReplacingOccurrencesOfString:("!\\[\\[(.*?)\\]\\]") withString:("![]($1)") options:(ca's NSRegularExpressionSearch) range:{location:0, |length|:length of theText}
set newText to newString as string
on error error_message number error_number
error number -128
end try
end replaceImageLinks
This is not a good RE, because you’re using a greedy quantifier (.*). That will gobble up everything from the first pair of [ to the last pair of ] on the same logical line. In other words, if you have more then one image one the same line or an image and a link (which might be noted as [[URL]] in your software?), this RE wrecks havoc.
It should be non-greedy like !\[\[([^[]+\]\]
No need to escape the !, no need to group the brackets either, since they’re not changing. Now the group inside the parenthesis gobbled up everything that is not a closing bracket followed by two closing brackets.
@pete31 had those fixed already in his script. I just wanted to point out the amendments in case they go unnoticed
Important point. I index Obsidian folders in DEVONthink but if I have to edit an indexed Obsidian note, I use Obsidian syntax, knowing it might not work in DEVONthink.
@pete31, you are fast becoming my favorite person! Thank you so much for your help with this script and the previous one! Has made my life so much easier. All my images that originally used Obsidian’s syntax have now been updated using this script and are now showing across all external editors, including DEVONthink.
@Bluefrog, regarding the reason, Obsidian can read both syntax formats (conventional and their own), and as @lsievert correctly pointed out, the app does have an option to select [[wiki-links]] or markdown syntax… but it’s a one or the other deal. I use [[wiki-links]] to link notes and make connections, and I use ![](image.png) to insert images. Because of the current limitations of Obsidian (still in beta), I needed a work around. Thankfully DEVONthink and this wonderful community just keeps on giving
I’ve adapted it to search for a specific keyword in the markdown file’s contents, and replace it with an empty string.
I use the keyword to automatically move notes indexed from TheBrain into specific DevonThink folders, but it is no longer needed once that smart rule has been triggered. So it would be awesome if the keyword could be somehow removed automatically.
Can you perhaps give a hint on how to make this script smart rule compatible? Any input is on this is much appreciated.
I’ve saved the script library to the location specified in your linked post. Then I used the instructions in that post to try to integrate the code from the script above into the general Smart Rule code.
I’m a total beginner in AppleScript, so I think there must be some kind of syntax error or something. In any case, when it is run the script returns the error message «script» doesn’t understand the “replacekeyword” message.
This is the smart rule script I came up with:
on performSmartRule(theRecords)
tell application id "DNtp"
try
repeat with theRecord in theRecords
set theText to plain text of theRecord as string
if theText ≠ "" then
set newText to my replacekeyword(theText)
if newText ≠ theText and newText ≠ "" and newText ≠ "missing value" then set plain text of thisRecord to newText
end if
end repeat
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
end try
end tell
end performSmartRule
And this is the code in the script library, which is named “Script Library - replacekeyword.scpt”
-- Script Library - replacekeyword
use AppleScript version "2.7"
use framework "Foundation"
use scripting additions
on replacekeyword(theText)
try
set ca to a reference to current application
set theString to ca's NSString's stringWithString:theText
set newString to theString's stringByReplacingOccurrencesOfString:("DT_Inbox") withString:("A") options:(ca's NSRegularExpressionSearch) range:{location:0, |length|:length of theText}
set newText to newString as string
on error error_message number error_number
error number -128
end try
end replacekeyword
Is there anything obvious here that needs to be fixed?
remove the handler
(as it can’t be used embedded in a Smart Rule script. That’s the only reason why it’s necessary to use a Script Library: to be able to remove it from the Smart Rule script)
call the Script Library from the Smart Rule
(which means replacing my with script "[name of the Script Library]"'s. my is only used to call an embedded handler.)
Ah, I see your edit, so you’ve found the first mistake. Replace my and it should work.
If you use an external Smart Rule script: remember to restart DEVONthink as scripts are cached
Feels like I’m getting close! Really appreciate your guidance here.
Something still isn’t 100% right though. Now there’s the following error message when using the code below: “Can’t make «script “ScriptLibraryReplacekeyword”» into type Unicode text.”
Maybe I misunderstood how to replace the “my” part in some way due to my current ignorance regarding general AppleScript syntax?
on performSmartRule(theRecords)
tell application id "DNtp"
try
repeat with theRecord in theRecords
set theText to plain text of theRecord as string
if theText ≠ "" then
set newText to script "ScriptLibraryReplacekeyword.scpt"
if newText ≠ theText and newText ≠ "" and newText ≠ "missing value" then set plain text of theRecord to newText
end if
end repeat
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
end try
end tell
end performSmartRule