Not to mention Array
methods like filter
, map
, and forEach
, data types like Set
and the availability of objects as well as introspection (missing from JXA, though). And constant development – ECMA is working on JavaScript, Apple is doing nothing with AppleScript.
But as with all programming languages (and code editors), it’s largely a matter of preference. Every problem can be solved in every language – it’s just a matter of time and effort.
And it’s even possible to mix them, see for example:
I would request to kindly handle my request number 1 too. Please help me in adding the URL or item link in the output md file. Thank you
The item link is already included in the original script, just click the name and it will open the record in DEVONthink.
This new version also includes the URL.
Note: To open the URL you need to use the contextual menu
-- Create Markdown See Also Suggestion List including URL
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
property maxSeeAlsoResults : 20
property removeSuffix : true -- remove suffix of suggested records
property includeParagraphs : true -- fetch the "first" and "last" paragraph. which paragraphs should act as "first" and "last" can be set below
property skipMarkdownHeading : true -- skip the first non-blank line if it begins with # (independent of property firstParagraphOffset)
property firstParagraphOffset : 1 -- index of the paragraph which should act as the first. starting at 1. only lines which contain at least one word are counted in (independent of property addEmptyLines)
property firstParagraphsCount : 2 -- count of included paragraphs
property lastParagraphOffset : 1 -- index of the paragraph which should act as the last. starting at 1. second last would be 2 (and so on)
property theParagraphPlaceholder : "<span style=\"color: red\">Here's something to do!</span>" -- this is used if a paragraph couldn't be fetched, e.g. when property firstParagraphOffset > count of paragraphs. change to your liking
property maxCharacterCount : 100000 -- skip fetching paragraphs of records whose character count is higher. for skipped paragraphs the placeholder is used. add these paragraphs manually afterwards by clicking the suggestion's name
property removeSelectedRecordSuffix : true -- remove suffix of selected record's name for usage in output record's name and heading
property openOutputRecord : true -- only available if one record is selected
property excludeFromSeeAlso : true -- exclude output record from see also
property excludeFromSearch : false -- exclude output record from search
property includeURL : true
tell application id "DNtp"
try
set theRecords to selection of think window 1
if theRecords = {} then error "Please select some records"
set theDatabases to databases
show progress indicator "Creating See Also Suggestions List... " steps (count theRecords) as string with cancel button
repeat with thisRecord in theRecords
set thisRecordName to name of thisRecord
step progress indicator thisRecordName
set theContent to plain text of thisRecord
set theSeeAlsoResults_record to {}
repeat with thisDatabase in theDatabases
set theSeeAlsoResults to compare content theContent to thisDatabase
repeat with thisResult in theSeeAlsoResults
set theName to name of thisResult as string
if removeSuffix = true then set theName to my recordName(theName, proposed filename of thisResult)
set theName to ("[" & theName & "](" & (reference URL of thisResult) & ")") as string
if includeParagraphs = true then
set theCharacterCount to (character count of thisResult)
if theCharacterCount > 0 and theCharacterCount ≤ maxCharacterCount then
set thisResult_record to {name_:theName, score_:(score of thisResult), charactercount_:theCharacterCount, text_:(plain text of thisResult)}
else
set thisResult_record to {name_:theName, score_:(score of thisResult), charactercount_:theCharacterCount}
end if
else
set thisResult_record to {name_:theName, score_:(score of thisResult), charactercount_:0}
end if
if includeURL = true then
if URL of thisResult ≠ "" then
set thisResult_record to thisResult_record & {url_:URL of thisResult}
end if
end if
set end of theSeeAlsoResults_record to thisResult_record
end repeat
end repeat
set theSeeAlsoResults_record_sorted to my sort(theSeeAlsoResults_record)
if (count theSeeAlsoResults_record_sorted) > maxSeeAlsoResults then set theSeeAlsoResults_record_sorted to (items 1 thru maxSeeAlsoResults in theSeeAlsoResults_record_sorted)
set theMarkdownText_list to {"<style> a {text-decoration: none;} </style>" & linefeed}
repeat with thisResult in theSeeAlsoResults_record_sorted
if includeParagraphs = true then
set theCharacterCount to charactercount_ of thisResult
if theCharacterCount > 0 and theCharacterCount ≤ maxCharacterCount then
set theText to text_ of thisResult
set theParagraphs to paragraphs of theText
set theParagraphs_cleaned to {}
repeat with thisParagraph in theParagraphs
if words in thisParagraph as string > 0 then set end of theParagraphs_cleaned to thisParagraph as string
end repeat
if skipMarkdownHeading = true and (item 1 of theParagraphs_cleaned starts with "#") then set theParagraphs_cleaned to (items 2 thru -1 in theParagraphs_cleaned)
try
set firstParagraphs_list to items firstParagraphOffset thru ((firstParagraphOffset + firstParagraphsCount) - 1) of theParagraphs_cleaned
set firstParagraphs_list_clean to {}
repeat with thisParagraph in firstParagraphs_list
set thisParagraph to thisParagraph as string
if thisParagraph starts with "*" then set thisParagraph to ("\\*" & characters 2 thru -1 in thisParagraph) as string
set end of firstParagraphs_list_clean to thisParagraph & space & space
end repeat
set firstParagraphs to my tid(firstParagraphs_list_clean, linefeed)
on error
set firstParagraphs to theParagraphPlaceholder
end try
try
set lastParagraph to (item -lastParagraphOffset of theParagraphs_cleaned) & space & space
if lastParagraph starts with "*" then set lastParagraph to ("\\*" & characters 2 thru -1 in lastParagraph) as string
on error
set lastParagraph to theParagraphPlaceholder
end try
try
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & "<" & url_ of thisResult & ">" & space & space & linefeed & firstParagraphs & space & space & linefeed & lastParagraph & space & space & linefeed
on error
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & firstParagraphs & space & space & linefeed & lastParagraph & space & space & linefeed
end try
else if theCharacterCount > 0 and theCharacterCount > maxCharacterCount then
try
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & "<" & url_ of thisResult & ">" & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed
on error
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed & theParagraphPlaceholder & space & space & linefeed
end try
end if
else
try
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed & "<" & url_ of thisResult & ">" & space & space & linefeed
on error
set end of theMarkdownText_list to "* " & name_ of thisResult & space & space & linefeed
end try
end if
end repeat
set theMarkdownText to my tid(theMarkdownText_list, linefeed)
if removeSelectedRecordSuffix = true then set thisRecordName to my recordName(thisRecordName, proposed filename of thisRecord)
-- choose how your output groups should be named. deactivate a line by adding a # at the beginning
set theOutputGroup to create location (location of thisRecord) & my replace_String((name of parent 1 of thisRecord) & " - " & "seealsoresults", "/", "\\/") --> "Groupname - seealsoresults"
#set theOutputGroup to create location (location of thisRecord) & my replace_String((name of parent 1 of thisRecord) & "\\" & "seealsoresults" & "\\", "/", "\\/") --> "Groupname\seealsoresults\"
#set theOutputGroup to create location (location of thisRecord) & my replace_String("seealsoresults", "/", "\\/") --> "seealsoresults"
set theSeeAlsoListRecord to create record with {name:"See Also Suggestion List - " & "\"" & thisRecordName & "\"", type:markdown, plain text:("### See Also Suggestion List " & "[" & thisRecordName & "](" & (reference URL of thisRecord) as string) & ")" & linefeed & linefeed & theMarkdownText, exclude from see also:excludeFromSeeAlso, exclude from search:excludeFromSearch} in theOutputGroup
end repeat
hide progress indicator
if openOutputRecord = true and (count theRecords) = 1 then
open window for record theSeeAlsoListRecord
activate
end if
on error error_message number error_number
hide progress indicator
activate
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
return
end try
end tell
on recordName(theName, theFilename)
set theSuffix to my getSuffix(theFilename)
if theName ends with theSuffix and theName ≠ theSuffix then set theName to characters 1 thru -((length of theSuffix) + 2) in theName as string
return theName
end recordName
on getSuffix(thePath)
set revPath to reverse of characters in thePath as string
set theSuffix to reverse of characters 1 thru ((offset of "." in revPath) - 1) in revPath as string
end getSuffix
on sort(theList)
set anArray to current application's NSArray's arrayWithArray:theList
set theDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"score_" ascending:false selector:"compare:"
set newList to (anArray's sortedArrayUsingDescriptors:{theDesc}) as list
end sort
on tid(theInput, theDelimiter)
set d to AppleScript's text item delimiters
set AppleScript's text item delimiters to theDelimiter
if class of theInput = text then
set theOutput to text items of theInput
else if class of theInput = list then
set theOutput to theInput as text
end if
set AppleScript's text item delimiters to d
return theOutput
end tid
on replace_String(theText, oldString, newString)
local ASTID, theText, oldString, newString, lst
set ASTID to AppleScript's text item delimiters
try
considering case
set AppleScript's text item delimiters to oldString
set lst to every text item of theText
set AppleScript's text item delimiters to newString
set theText to lst as string
end considering
set AppleScript's text item delimiters to ASTID
return theText
on error eMsg number eNum
set AppleScript's text item delimiters to ASTID
error "Can't replaceString: " & eMsg number eNum
end try
end replace_String
Not really. See this thread for some basic ideas. And the AppleScript Language Guide.
The most challenging script you will ever write is your first one.
1 Like