I’ve been trying and not succeeding at modifiying a script so that it can run via a smart rule.
The script adds the obsidian URL of an indexed item to a custom metadata field. It works when I select the item in DevonThink and run the script, but the version I modified to run it through a smart rule doesn’t produce any effect when that smart rule is applied. There are also no visible errors.
I tried different variations but can’t get it to work. Would really appreciate some hints
Here’s the non smart rule version (working for selected items):
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
on urlEncode(input) -- with thanks to @BlueM on Stack Overflow: https://stackoverflow.com/a/43562220
tell current application's NSString to set rawUrl to stringWithString_(input)
set theEncodedURL to rawUrl's stringByAddingPercentEscapesUsingEncoding:4 -- 4 is NSUTF8StringEncoding
return theEncodedURL as Unicode text
end urlEncode
tell application id "DNtp"
set selectedItems to get the selection
set theSelection to the first item in selectedItems
set recordFilename to proposed filename of theSelection as string
set URLEncodedFilename to my urlEncode(recordFilename)
set URLEncodedVaultName to my urlEncode("B10")
set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
add custom meta data newobsidianURL for "obsidianurl" to theSelection
end tell
And this is the attempted smart rule-compatible version (not working):
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
on urlEncode(input) -- with thanks to @BlueM on Stack Overflow: https://stackoverflow.com/a/43562220
tell current application's NSString to set rawUrl to stringWithString_(input)
set theEncodedURL to rawUrl's stringByAddingPercentEscapesUsingEncoding:4 -- 4 is NSUTF8StringEncoding
return theEncodedURL as Unicode text
end urlEncode
on performSmartRule(theRecords)
tell application id "DNtp"
repeat with thisRecord in theRecords
set recordFilename to proposed filename of thisRecord as string
set URLEncodedFilename to my urlEncode(recordFilename)
set URLEncodedVaultName to my urlEncode("B10")
set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
add custom meta data newobsidianURL for "obsidianurl" to thisRecord
end repeat
end tell
end performSmartRule
It’s one of these weird side-effects when using scripting additions and/or frameworks. This revision works (and uses filename instead of proposed filename which might be not be identical to the current filename)
on urlEncode(input)
run script "encodeURIComponent(" & (the quoted form of input) & ");" in "JavaScript"
end urlEncode
on performSmartRule(theRecords)
tell application id "DNtp"
repeat with thisRecord in theRecords
set recordFilename to filename of thisRecord
set URLEncodedFilename to my urlEncode(recordFilename)
set URLEncodedVaultName to my urlEncode("B10")
set newobsidianURL to "obsidian://open?vault=" & URLEncodedVaultName & "&file=" & URLEncodedFilename
add custom meta data newobsidianURL for "obsidianurl" to thisRecord
end repeat
end tell
end performSmartRule
However, while now the script does take effect, for some reason it’s not processing all records in the smart rule scope. I’ve run the modified version multiple times, and it always correctly processes the same 20 records, but does not change the remaining 200 or so.
I’m trying to identify some kind of a pattern that distinguishes the records where it worked from the others, but currently can’t identify anything obvious.
// Edit for future readers of this thread: The version above works as intended. This issue was caused by apostrophe’s in my file names, which the URL encoding can’t handle.
In fact, don’t URLencode it at all. B10 first contain any special characters that would require URLencoding.
I’d, of course, wrote the whole snippet in JavaScript and avoid three script call that way, as well as quoting the string first.
Interesting. I have got to get started learning some JavaScript.
While I understand that it’s the more capable coding language compared to AppleScript, I find that the latter is just way more accessible and “readable” for non-techies.
Readable – perhaps, for English speaking people. Writeable – not so. Not even in the minds of the people who invented it. And, personally, I find the habit of beginning variable names with “the” the opposite of “readable”. Three meaningless characters that have to be mentally skipped to get to the relevant part.
function performsmartrule(records) {
const app = Application ("DEVONthink 3");
records.forEach( r => {
const obsidianURL =`obsidian://open?vault=${encodeURIComponent(r.name)}&file=B10`;
app.addCustomMetaData(obsidianURL, {for: "obsidianurl", to: r})
})
}
I’ve noticed some mysterious behavior in Obsidian, where links with (and without) the file extension open on Mac but on iOS they only open if there is no file extension.
Is there a way to modify the script such that the filename without extension is used for the URL encoding, instead of the full filename? I tried “filename without extension” but that leads to invalid code.
Instead of this link generated by the current script: obsidian://open?vault=B10&file=Specialties%20of%20the%20Stoic%20philosophers.md
I would like to generate this one: obsidian://open?vault=B10&file=Specialties%20of%20the%20Stoic%20philosophers
Honestly, my first intuition was that there’s probably a simple way to exclude the extension via the script and be done It’s part of a pattern where I use DevonThink to address the bugs and inadequacies in certain other applications…
If that’s not possible in this case, then I would contact the Obsidian people in hopes that they address this in some future update.
Alternatively, I’d chop off the extension in JavaScript with const noExtension = r.name().replace(/(.*)\.*/,"$1")
In AppleScript, you’d use some set text delimiter magic.
In any case, treating an extension as if it were not there seems like a bug to me – what if you have two files that differ only in the existence of an extension?
After checking the AppleScript dictionary for DevonThink (note to self: make that a habit before asking in the forum ), I found that the error was in this line of the modified script I was experimenting with:
set recordFilename to filename without extension of thisRecord
For the script to run, it needs to be instead:
set recordFilename to name without extension of thisRecord
The script now works as expected.
To be honest, I realized that this was user error and the links for Obsidian on iOS actually work correctly. When I set up the Obsidian sync vault on my iPhone, I gave a slightly different name to one of the vaults than on the Mac. So when the link with extension didn’t work it was because it was related to the incorrectly named sync vault, and when it worked without extension I was coincidentally testing with a link for the vault that was named correctly. So my conclusion that the extension is the issue was premature and ultimately false. Some efforts modifying the script were therefore in vain, but hey… I learned something once again!
Interesting alternative, which I wasn’t aware of and will keep in mind for future scripting scenarios. Thanks for the hint.