Updated Version (V1b6) with three additional functions: copy item link, copy cited text link, copy bookmark link.
The source document can be pdf, rtf, plain text, or markdown file, the links are in markdown format, saved in clipboard for pasting to markdown file.
For my usage, I attached shift-ctrl-M to the script as a shortcut.
(1) If text is selected in a markdown file, this is the menu:
Formatting functions are available.
(2) If no text is selected in any types of current document, or text is selected in a non-markdown document, this is the menu:
The script assumes that the user is planning to use function 1-5 for the two scenarios mentioned above.
Scenario: Some text is selected in a pdf, function 3-5 are used respectively.
Configuration 1: The three types of link display filename as link’s name.
Configuration 2: The three types of link display simple link’s name.
DT Item link will always show the full filename regardless of the configuration.
Configuration 3: two other settings
Example 7: the link’s name is placed before the cited text.
Example 8: the search string in the DT’s link is based on a string instead of based on position.
There are quite a few changes, so I post the new script here:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
--By Ngan 2020.03.02
--v1b6 2020.03.11
--add 3 functions. Item-link, cite link, bookmark link
-- settings for "3. Cite Link", "4. Bookmark Link", "5. Item Link"
property linkName : "DF" -- DS:[position only] DF:[document name], "DA" [aliases name]
property linkBeforeCitedText : true -- true: put link as the first line before cited text. false: link after the cited text
property searchMethod : "S" -- "S" search by string "P" search by position (paragraph for rtf, page for pdf). For markdown always search by string
property queryWordLen : 10 -- number of words used in search string
--Note for "property useFilepathForImageLink"
-- if "useFilepathForImageLink: true", image link is based on file path. Image in md can only be viewed in one computer and external md editor.
--if "useFilepathForImageLink:false", image link is based on DT Link. Image in md can be viewed in DT3 and DTTG, BUT NOT in external md editor
property useFilepathForImageLink : false
-- Note for "property useOneImageAssetsGpForAllDBs"
--if useOneImageAssetsGpForAllDBs: true, use one image assets group for ALL databases
--if useOneImageAssetsGpForAllDBs: false, use one image assets group for EACH database
property useOneImageAssetsGpForAllDBs : true
--Note: only need to define "property imgAssetsUUID" if useOneImageAssetsGpForAllDBs : true
--if useFilepathForImageLink : true, this group must be an index group
property imgAssetsUUID : "9A72DEC0-A97E-XXXX-XXXXXXXXXXXX" -- uuid of the index folder for the centralised image assets
--Note: only need to define "property imgAssetsLocation" if useOneImageAssetsGpForAllDBs : false
--if useFilepathForImageLink : true, this group must be an index group
property imgAssetsLocation : "/your group/subgroup" -- example only
-- ignore these settings, for my personal used only
property characterToTrim : "- "
property regexForCardUID : "[c/n][0-9][0-9][0-9][0-9]"
property theCmd : missing value -- just for flexibility, probaby won't be used
--
-- How the list is displayed
property theStyle : {"I. Italic", "B. Bold", "S. Bold&Italic", "U. Underline", "C. Chapter", "S. Section", "X. Clear All Text Format"}
property theOtherFunction : {"1. Build Table", "2. Capture Image Link", "3. Cite Link", "4. Bookmark Link", "5. Item Link"}
global theWin, theDoc, theImgAsset
global theDocType, withText
global theCitedText
tell application id "DNtp"
set theWin to think window 1
set theDoc to content record of think window 1
set theCitedText to selected text of theWin as string
set theDocLoc to location of theDoc
if useOneImageAssetsGpForAllDBs then
if imgAssetsUUID is not missing value then set theImgAsset to get record with uuid imgAssetsUUID
else
if imgAssetsLocation is not missing value then set theImgAsset to get record at imgAssetsLocation
end if
if (type of theDoc is markdown) and (exists (selected text of think window 1)) then
set theList to theStyle & " " & theOtherFunction
else
set theList to theOtherFunction
end if
set theChoice to (choose from list theList with prompt "Items 1-5 are created in clipboard" with empty selection allowed) as string
set theChoice to text 1 of theChoice
if theChoice is "I" then
set (selected text of think window 1) to "*" & (selected text of think window 1) & "*"
else if theChoice is "B" then
set (selected text of think window 1) to "**" & (selected text of think window 1) & "**"
else if theChoice is "S" then
set (selected text of think window 1) to "***" & (selected text of think window 1) & "***"
else if theChoice is "U" then
set (selected text of think window 1) to "<u>" & (selected text of think window 1) & "</u>"
else if theChoice is "C" then
set (selected text of think window 1) to "### " & (selected text of think window 1)
else if theChoice is "S" then
set (selected text of think window 1) to "#### " & (selected text of think window 1)
else if theChoice is "X" then
set (selected text of think window 1) to my TrimText(my TrimText(my TrimText(my TrimText(my TrimText(selected text of think window 1, "*"), "<u>"), "</u>"), "#"), "==")
else if theChoice is "1" then
activate
my buildTable()
return
else if theChoice is "2" then
my grapImgandGetMDLink()
return
else if theChoice is "3" then
my getLink(theWin, theDoc, theCitedText, queryWordLen, "C")
else if theChoice is "4" then
my getLink(theWin, theDoc, theCitedText, queryWordLen, "B")
else if theChoice is "5" then
my getLink(theWin, theDoc, theCitedText, queryWordLen, "D")
end if
end tell
on buildTable()
local numRow, numCol, theHD1, theHD2
tell application id "DNtp"
set a to text returned of (display dialog "Row, Col" default answer "3,3")
set numRow to (item 1 of my strToList(a, ",")) as integer
set numCol to (item 2 of my strToList(a, ",")) as integer
set {theHD1, theHD2, theCol, theRow} to {" ", " ", " ", " "}
repeat numCol times
set theHD1 to theHD1 & " |"
set theHD2 to theHD2 & "---|"
end repeat
repeat numCol times
set theRow to theRow & " |"
end repeat
set theCol to ""
repeat numRow times
set theCol to theCol & return & theRow
end repeat
set the clipboard to theHD1 & return & theHD2 & theCol & return & return
display alert "paste the layout to the file" giving up after 1
end tell
end buildTable
on grapImgandGetMDLink()
set dateSting to my getDateString()
do shell script "screencapture -ci"
tell application id "DNtp"
set theImageFile to paste clipboard to theImgAsset
set the name of theImageFile to dateSting
if useFilepathForImageLink then
set theLink to path of theImageFile
set the clipboard to "<img src=\"" & theLink & "\" style=\"zoom:50%;\" >"
else
set theLink to reference URL of theImageFile
set the clipboard to ""
end if
end tell
end grapImgandGetMDLink
on getLink(theWin, theDoc, theCitedText, queryWordLen, linkType)
local rPos, cPos -- realPositionOfText, citedPositionOfText
local dl, pl, sl, cl -- docBackLink, positionBackLink, searchStringBackLink,customBackLink
local dldn, pldn, sldn, cldn -- name of dl,pl,sl,cl
local ctl, tq -- citedTextAsList, textQuery
local theID, theYear, theAuthor, theType
local dn, an, cn
local theBLDisplay, theBL
tell application id "DNtp"
set {dn, dl, an, cn} to {name of theDoc, reference URL of theDoc, aliases of theDoc, get custom meta data for theCmd from theDoc default value theCmd}
-- extract the search string of the selected text or page
if theCitedText is not "" then
set ctl to my strToList(theCitedText, " ")
set tq to items 1 thru (my min(queryWordLen, length of ctl)) of ctl
set tq to my listToStr(tq, "%20")
set sl to dl & "?search=" & tq
set sldn to "Goto"
else
set sl to ""
set sldn to ""
end if
-- extract the position of the selected text or page
if the kind of theDoc is in "PDF+Text" then
set {rPos, cPos} to {(current page of theWin), (current page of theWin) + 1}
set pl to dl & "?page=" & rPos
set pldn to " Page " & (rPos + 1)
else if kind of theDoc is "Markdown" then
if theCitedText is not "" then
set pl to dl & "?search=" & tq
set pldn to ""
else
set pl to dl
set pldn to ""
end if
else
if kind of theDoc is not "Markdown Document" then
set {rPos, cPos} to {(current line of theWin), my getNonBlankParagraphNum(theWin, current line of theWin)}
else
set {rPos, cPos} to {0, 0}
end if
set pl to dl & "?line=" & rPos
set pldn to " Paragraph " & cPos
end if
if searchMethod is "S" then
set theBL to sl
else if searchMethod is "P" then
set theBL to pl
end if
if linkName is "DF" then
-- display full filename as name of link
set theBLDisplay to dn & pldn
else if linkName is "DA" then
-- display aliases name as name of link
set theBLDisplay to an & pldn
else if linkName is "DC" then
-- display content of a cmd as name of link
set theBLDisplay to cn & pldn
else if linkName is "DS" then
-- display "Link" as name of link
set theBLDisplay to "" & pldn
else if linkName is "DM" then
set dldn to dn
set {theID, theYear, theAuthor, theType} to my getCitationInfo(dldn)
set theType to my firstN(1, theType)
if theCitedText is not "" then
set cl to sl -- use pl fot page/paragraph link, sl for search link
else
set cl to pl
end if
if theType is "O" then -- other source
set cldn to dldn & ": " & pldn
else if theType is "R" then -- source is literature
set cldn to " (" & theAuthor & ", " & theYear & ": " & (cPos) & " " & theID & ") "
else if (theType is "A") or (theType is "C") then -- source is annotationNote or card
set cldn to " (" & theAuthor & ", " & theYear & ": para " & (cPos) & " " & theID & "-" & theType & ")"
end if
set theBLDisplay to cldn
set theBL to cl
end if
if linkType = "C" then
if linkBeforeCitedText then
set theFullLink to "> [" & theBLDisplay & "](" & theBL & ")" & return & return & ">" & theCitedText
else
set theFullLink to ">" & theCitedText & " [" & theBLDisplay & "](" & theBL & ")"
end if
else if linkType = "B" then
set theFullLink to "*Bookmark:* [" & theBLDisplay & "](" & theBL & ")"
else if linkType = "D" then
set theFullLink to "[" & dn & "](" & dl & ")"
end if
set the clipboard to theFullLink
end tell
end getLink
on strToList(thestr, d)
local theList
set {tid, text item delimiters} to {text item delimiters, d}
set theList to every text item of thestr
set text item delimiters to tid
return theList
end strToList
on listToStr(theList, theDelimiter)
set {tid, text item delimiters} to {text item delimiters, theDelimiter}
set thestr to theList as text
set text item delimiters to tid
return thestr
end listToStr
on TrimText(theText, theTrim)
set AppleScript's text item delimiters to the theTrim
set the item_list to every text item of theText
set AppleScript's text item delimiters to the ""
set theText to the item_list as string
set AppleScript's text item delimiters to ""
return theText
end TrimText
on getDateString()
set y to get year of (current date) as string
set m to month of (current date) as integer
set m to my PadNum(m, 2) as string
set d to get day of (current date)
set d to my PadNum(d, 2) as string
set t to get time string of (current date) as string
set t to my findAndReplaceInText(t, ":", ".") as string
return y & "." & m & "." & d & "." & t
end getDateString
on findAndReplaceInText(theText, theSearchString, theReplacementString)
set AppleScript's text item delimiters to theSearchString
set theTextItems to every text item of theText
set AppleScript's text item delimiters to theReplacementString
set theText to theTextItems as string
set AppleScript's text item delimiters to ""
return theText
end findAndReplaceInText
on getNonBlankParagraphNum(theWin, theCurrentLine)
local ap, nep -- all-paragraphs, non-empty-paragraphs
tell application id "DNtp"
set ap to every paragraph of the text of theWin
set nep to {}
repeat with i from 1 to (theCurrentLine + 1)
if (item i of ap) is not "
" then
set end of nep to item i of ap
end if
end repeat
return count nep
end tell
end getNonBlankParagraphNum
on PadNum(lngNum, lngDigits)
set strNum to lngNum as string
set lngGap to (lngDigits - (length of strNum))
repeat while lngGap > 0
set strNum to "0" & strNum
set lngGap to lngGap - 1
end repeat
strNum
end PadNum
on min(x, y)
if x ≤ y then
return x
else
return y
end if
end min
-- ignore these handlers
on getCitationInfo(theDocNm)
local theNmlist, firstWord, thePos, lastWord, theType, theID, theYear, theAuthor
set theNmlist to my strToList(theDocNm, " ")
set thePos to my getItemPosInList("-", theNmlist)
set firstWord to item 1 of theNmlist
set lastWord to item -1 of theNmlist
set theType to my getDocType(theDocNm)
if theType is "O" then
return {"", "", "", theType} -- no citation info
else
set theID to item 1 of theNmlist
set theYear to item 2 of theNmlist
if thePos is 0 then
set theAuthor to item 3 of theNmlist
else
set theAuthor to items 3 thru thePos of theNmlist
if the length of theAuthor ≤ 4 then
set theAuthor to my listToStr(items 3 thru (thePos - 1) of theNmlist, " ")
else
set theAuthor to my listToStr((my TrimText((item 3 of theNmlist), ",") & " et al."), " ")
end if
end if
return {theID, theYear, theAuthor, theType}
end if
end getCitationInfo
on getDocType(theDocNm)
local lnm
set lnm to my strToList(theDocNm, " ")
if my regexMatch(lnm's item -1, regexForCardUID) then
return "C" --card
else if lnm's item -1 contains "(annotation)" then
return "A" -- annotation
else if lnm's item 1 contains "." then
return "R" --ref literature
else
return "O" -- other ref
end if
end getDocType
on getItemPosInList(theItem, theList)
repeat with a from 1 to count of theList
if item a of theList is theItem then return a
end repeat
return 0
end getItemPosInList
on regexMatch(s, regex)
-- ignore case
local ignoreCase, extraCommand
set ignoreCase to true
if ignoreCase then
set extraCommand to "shopt -s nocasematch; "
else
set extraCommand to ""
end if
do shell script "export LANG='" & user locale of (system info) & ".UTF-8'; shopt -s compat31; " & extraCommand & "[[ " & quoted form of s & " =~ " & quoted form of regex & " ]] && printf '%s\\n' \"${BASH_REMATCH[@]}\" || printf ''"
if result is not "" then
return true
else
return false
end if
end regexMatch
on firstN(n, s)
return text from character 1 to character n of s
end firstN