I have some code that converts rich text attribute runs (from the Text Suite) into Markdown. It works equally well with TextEdit and OmniOutliner (and probably other applications that support Text Suite renditions of rich text).
The problem is that I have to target some application’s terminology in order to get all this to compile. Presently, i’m using using terms from application "TextEdit"
, but this seems fragile. I cannot think of a way of using a particular suite independently from a target application.
Here’s the common code:
on isLink(linkText)
-- This is a very crude test if a string is a link.
ignoring case
return linkText begins with "http:" or ¬
linkText begins with "https:" or ¬
linkText begins with "ftp:" or ¬
linkText ends with ".com"
end ignoring
end isLink
on isEmail(emailText)
-- This is a very crude test if a string is an email address.
ignoring case
return emailText contains "@" and emailText ends with ".com"
end ignoring
end isEmail
on isBoldFont(fontName)
ignoring case
return fontName contains "Bold"
end ignoring
end isBoldFont
on isItalicFont(fontName)
ignoring case
return fontName contains "Italic"
end ignoring
end isItalicFont
on richTextToMarkdown(cellRef)
local markdownText, inBold, inItalic, rowText
set inBold to false
set inItalic to false
set rowText to {} -- use an array because its a bit faster
using terms from application "TextEdit"
repeat with anAttribute in attribute runs of cellRef
set {runText, runIsBold, runIsItalic} to ¬
{contents of anAttribute, my isBoldFont(font of anAttribute), my isItalicFont(font of anAttribute)}
-- close any existing attribute runs that have ended
if inBold and not runIsBold then
set end of rowText to "**"
set inBold to false
end if
if inItalic and not runIsItalic then
set end of rowText to "*"
set inItalic to false
end if
-- open new attribute runs
if not inBold and runIsBold then
set end of rowText to "**"
set inBold to true
end if
if not inItalic and runIsItalic then
set end of rowText to "*"
set inItalic to true
end if
-- add the attribute run's text
if my isEmail(runText) then
set end of rowText to "[" & runText & "](mailto:" & runText & ")"
else if my isLink(runText) then
set end of rowText to "[" & runText & "](" & runText & ")"
else
set end of rowText to runText
end if
end repeat
-- close any existing attribute runs
if inBold then
set end of rowText to "**"
set inBold to false
end if
if inItalic then
set end of rowText to "*"
set inItalic to false
end if
end using terms from
-- convert the array of Markdown texts into a single string
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {""}
set markdownText to rowText as text
set AppleScript's text item delimiters to saveTID
return markdownText
end richTextToMarkdown
and here is some code which uses richTextToMarkdown()
:
set markdownText to {}
tell application "OmniOutliner"
tell first document
repeat with aRow in (get selected rows)
set targetRow to contents of aRow
set end of markdownText to my richTextToMarkdown(a reference to topic of targetRow)
if targetRow's note is not "" then
set end of markdownText to my richTextToMarkdown(a reference to rich text of note cell of targetRow)
end if
end repeat
end tell
end tell
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {return & return}
set markdownText to markdownText as text
set AppleScript's text item delimiters to saveTID
…and…
tell application "TextEdit"
my richTextToMarkdown(a reference to document 1)
end tell
Any ideas?