Script that automates the conversion from markdown to html

Hello!

I use John Grubers original Markdown Daring Fireball: Markdown to create html from Markdown with either BBEdit or TextWrangler. You can read from the properties of the script where it is supposed to be installed.

It will try to find the counterpart document within the current source tree, which is defined to be on level above, and two levels below the placement of the current markdown file.

It refuses to do anything for you, if there are several html files within that area with the same name.

The final html is rendered in Safari, so that you can edit, convert, and look at the result.
The script from MacScripter / Locate and edit markdown counterpart of html file displayed in Safari lets you access the markdown file behind the html in Safari after you have followed the instructions for installing it.

Enjoy! :wink:

This image shows you the marks BBEdit and TextWrangler sets for you, by using your markdown headings.


property warnIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:CoreTypes.bundle:Contents:Resources:AlertCautionIcon.icns")
-- intitalization 
-- © McUsr 2012 and put in Public Domain. You may not post,and not store this in a public accessible repository
-- but refer to the link here: http://macscripter.net/viewtopic.php?pid=154877#p154877
property tpath : (path to application support folder from user domain) & "BBEdit:Unix Support:Unix Filters:" as text

property filtSmartyPants : tpath & "SmartyPants.pl" as alias
property filtMarkDown : tpath & "Markdown.pl" as alias
property templateDir : ((path to documents folder as text) & "DocumentationTemplates:")
property docTemplate : (templateDir & "Documentation.tmpl") as alias

on run
    
    local aLang, tText, tLen, theDoc, docname, firstEd, theFile, pxPath, pxFolder, nm, suf, parFol, mustDefineCounterPart, counterPart, ct, hfsHtmlCounterPart, foundit, theDoclist, hfsCounterPartDefLoc, hfsCounterPartPath, originalMarkdownDocId, uxFilterOutputDocId, uxFilterOutputDoc, constructedHtmlDoc, newConstructedHtmlText, tc, a, startmarker, endMarker
    try
        -- is the doc saved? if it
        tell application "BBEdit"
            activate
            set aLang to source language of text window 1
            if aLang is not in "Markdown" then error "The source language isn't Markdown!" number 3000
            set tText to text of text window 1
            set tLen to length of tText
            if tLen = 0 then error "The Document is emtpy!" number 3000
            set theDoc to a reference to front document
            set docname to name of theDoc as text
            if docname starts with "untitled text" then
                set firstEd to true
            else
                set firstEd to false
            end if
            try
                save theDoc
                set docname to name of theDoc as text -- got a new name now!
            on error
                error "The Document is not saved!" number 3000
            end try
            
            -- Needs the path to the counterpart which will be updated, or created with the new html (recreated)
            set theFile to file of text window 1 as text
            set pxPath to POSIX path of theFile
            set {pxFolder, nm, suf} to splitPxFile of me for pxPath
            set parFol to parentFol of me for pxFolder
            set mustDefineCounterPart to false
            if (not firstEd) then
                -- have a looksie
                
                set counterPart to paragraphs of (do shell script "find " & quoted form of parFol & " -name " & quoted form of (nm & ".html") & " -maxdepth 3  -print 2>/dev/null  || echo >/dev/null")
                set ct to length of counterPart
                if ct > 1 then
                    error "Ambiguity: more than one file named  " & (nm & ".html") & " in sourcetree." number 3000
                else if ct = 1 then
                    set hfsHtmlCounterPart to POSIX file counterPart as alias as text
                    -- time to take a stroll and see if we have it open in a window!
                    set foundit to false
                    repeat with i from 1 to count text windows
                        
                        set theDoclist to (every text document of text window i whose name is (nm & ".html"))
                        
                        repeat with aDoc in theDoclist
                            log (file of aDoc) as text
                            if (file of aDoc) as text is hfsHtmlCounterPart then
                                close aDoc
                                set foundit to true
                                exit repeat
                            end if
                            
                        end repeat
                        if foundit then exit repeat
                    end repeat
                    
                else
                    set mustDefineCounterPart to true
                    -- no html at the moment. 
                    -- choose folder  place to store stuff 
                end if
            else
                -- first time usage     
                set mustDefineCounterPart to true
            end if
            
            if mustDefineCounterPart then
                
                set hfsCounterPartDefLoc to POSIX path of pxFolder as text
                try
                    set hfsCounterPartPath to (choose folder with prompt "Choose where to save " & (nm & ".html") default location hfsCounterPartDefLoc)
                on error e number n
                    error e number 3000
                end try
                
                set hfsHtmlCounterPart to (hfsCounterPartPath as text) & (nm & ".html")
                
                if (firstEd = true) then
                    -- check to see that it isn't a file with that name lurking in our current directory tree!
                    set counterPart to paragraphs of (do shell script "find " & quoted form of parFol & " -name " & quoted form of (nm & ".html") & " -maxdepth 3  -print 2>/dev/null  || echo >/dev/null")
                    set ct to length of counterPart
                    if ct > 0 then error "Ambiguity: more than one file named  " & (nm & ".html") & " in sourcetree." number 3000
                end if
            end if
            
            -- can start worry about figuring out of the new document
            set originalMarkdownDocId to (get ID of theDoc)
            tell its text window 1
                -- shamlessly stolen from Crhistopher Stone and Pierre Igot http://www.betalogue.com/2012/08/22/applescript-scripts-for-paragraph-selection-in-bbedit-continued/
                set a to selection of its text
                if length of a > 1 then
                    set startmarker to characterOffset of a
                    set endMarker to (characterOffset of a) + (length of a) - 1
                    select insertion point before character startmarker of its text
                end if
                
                select insertion point before character (get characterOffset of (selection of its text))
                run unix filter filtMarkDown without replacing selection
                run unix filter filtSmartyPants with replacing selection
                set htmlTranslatedFromMarkup to its text
                set uxFilterOutputDocId to (get ID of its front text document)
            end tell
            
            set uxFilterOutputDoc to a reference to text document id uxFilterOutputDocId
            
            set constructedHtmlDoc to make at front text window new document with data my docTemplate
            
            set insertPlace to find "#DOCUMENT_TITLE#" searching in text window 1 options {starting at top:true}
            if (found of insertPlace) then
                set text of (found object of result) to nm
            else
                error "MAJOR FAULT!!! YOUR TEMPLATE DOESN'T CONTAIN #DOCUMENT_TITLE# ... Bailing out!" number 3001
            end if
            
            set insertPlace to find "#BODYTEXT#" searching in text window 1 options {starting at top:true}
            if (found of insertPlace) then
                set text of (found object of result) to htmlTranslatedFromMarkup
            else
                error "MAJOR FAULT!!! YOUR TEMPLATE DOESN'T CONTAIN #BODYTEXT# ... Bailing out!" number 3001
            end if
            
            set newConstructedHtmlText to a reference to front text document
            
            close uxFilterOutputDoc saving no
            
            if mustDefineCounterPart then
                try
                    set tc to contents of (contents of newConstructedHtmlText)
                on error e number n
                    error e number 3002
                end try
                try
                    my writeToFileAsUtf8(hfsHtmlCounterPart, tc)
                on error e number n
                    error e number 3003
                end try
                
            end if
            
            save newConstructedHtmlText to alias hfsHtmlCounterPart
            
            -- set theResult to 
            check syntax hfsHtmlCounterPart
            
            update alias hfsHtmlCounterPart
            
            save newConstructedHtmlText to alias hfsHtmlCounterPart
            
            select document id originalMarkdownDocId
            tell its text window 1
                if length of a > 1 then
                    select (characters startmarker thru endMarker) of its text
                end if
            end tell
            
        end tell
        
        do shell script "open -a /Applications/Safari.app " & quoted form of (POSIX path of (hfsHtmlCounterPart as alias) as text)
        
        tell application "Safari" to activate
        
    on error e number n
        tell application "SystemUIServer"
            activate
            try
                display dialog e & " " & n with title "WebpageHelper" with icon warnIcon
            end try
        end tell
    end try
end run

to parentFol for aPxPath
    local tids, parFol
    set {tids, my text item delimiters} to {my text item delimiters, "/"}
    
    if (character (length of aPxPath) of aPxPath) = "/" then
        set parFol to text items 1 thru -3 of aPxPath as text
    else
        set parFol to text items 1 thru -2 of aPxPath as text
    end if
    set my text item delimiters to tids
    return parFol
end parentFol

to splitPxFile for pxPath
    -- http://macscripter.net/viewtopic.php?id=39332
    local ppl, sl, s, tids, f
    set ppl to length of pxPath
    set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
    
    set s to item -1 of text items of pxPath
    set sl to length of s
    if sl = ppl then
        set s to missing value
        set pxPath to text items 1 thru -1 of pxPath as text
    else
        set pxPath to text items 1 thru -2 of pxPath as text
    end if
    set AppleScript's text item delimiters to "/"
    
    set f to item -1 of text items of pxPath
    if f = "" then set f to missing value
    try
        set pxPath to (items 1 thru -2 of text items of pxPath)
        set pxPath to (pxPath as text) & "/"
    on error
        set pxPath to missing value
    end try
    set AppleScript's text item delimiters to tids
    return {pxPath, f, s}
end splitPxFile

on writeToFileAsUtf8(fname, stuff)
    local fRef, n, fsz
    try
        set fRef to open for access fname with write permission
        
        write stuff to fRef as «class utf8» starting at 0
        set fsz to get eof fRef
        close access fRef
        return fsz
    on error e number n
        try
            close access fRef
        end try
        error e number n
    end try
end writeToFileAsUtf8


Documentation.tmpl : fill in with css to your liking!

[code]

#DOCUMENT_TITLE#

html {

}

body {

}

a {

}

a:link
{

}

a:visited {

}

p
{

}

h1 {

}

h2 {

}

h1 + h2 {

}

h2 + h3 {

}

h3 {

}

p + h3 {

}

pre + h3 {

}

h6 + h2 {

}

h4, h5, h6
{

}

h2,h3,h4,h5,h6,ul,li + p {

}

strong {

}

em {

}

strong strong {

}

blockquote {

}

blockquote strong {

}

cite {

}

img {

}

thead {

}

ul, ol {

}

pre {

}

code {

}

p + ul {

}

ul { }

ul ul {

}

ul ul ul {

}

li {

}
hr {

}
#BODYTEXT# [/code]

Hello.

It is updated, with handlers from my library, :smiley: , a run handler, and declared local variables

:slight_smile:
The run handler is reinforced, due to permission errors from the find command when running it high up in the folder hierarchy.

Hi!

It now unmarks any marked block, and leaves the cursor in front of it, as otherwise the markdown script only runs on the marked block.

I’m sorry that I didn’t anticipate that!

:slight_smile:

It now reselects any selected text, after the html has been generated.

:slight_smile:

I have changed the open statement so the resulting html is guarranteed to open in Safari, if it wasn’t there from before. It will reuse any tab it was in from before, should such a tab exist!

Hello. I have cleaned up the documentation a little, and the script now inserts a title into the html.

Hello!

There is one bug in here, I am not sure how to deal with.

The id of documents, at least in my now old version of BBEdit (8.7.2) isn’t unique, So sometimes, after having updated the browser with fresh html, the wrong document in another window is opened.

If that should happen to you as well, I think the remedy is to close either of the two “colliding” documents, and reopen them, to assure a unique document id. (After saving of course)

This is not something very likely to happen!