Customized OmniOutliner HTML export with AppleScript

Continuing my love affair with OmniOutliner, this script demonstrates how to generate HTML from an outline for a specific purpose.

The Script Debugger 7 Feature Comparison page on the LNS web site is generated from an OmniOutliner outline using AppleScript. While OmniOutliner provides its own HTML export facilities, the results don’t suite my purpose so I used AppleScript to create the HTML I need. In my outline, each top-level entry represents a separate HTML table within my feature comparison page. The items within each table are indented to follow the structure defined within my outline document.

Here is how my outline appears within OmniOutliner:

And the resulting HTML output looks like this:

As you can see, the resulting HTML follows the structure of my outline document but uses styling that matches my site.

Here is the AppleScript code that accomplishes all of this:

NOTE: MarksLib is needed to compile and run this script.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use MarksLib : script "MarksLib" version "1.0"

property nbspaces : {"   ", "   ", "   ", "   ", "   ", "   ", "   ", "   ", "   "}
property checkedColor : "#d9ecd0"
property uncheckedColor : "#e06377"

--	Begin the HTML output.  A list is used to collect the output because its faster than string concatination in AppleScript
set theOutput to {"<html><body>", ¬
	"<style>
	td.centered {
		text-align: center;
	}
	th {
		background-color:black;
		color:white;
		vertical-align: bottom;
	}
	th.centered {
		text-align: center;
	}
	td.checked {
		background-color:" & checkedColor & ";
		text-align: center;
	}
	td.unchecked { 
		background-color:" & uncheckedColor & ";
		text-align: center;
	}
</style>"}

tell application "OmniOutliner"
	--	Iterate over the level 1 items (these will become seperate HTML tables)
	repeat with aTableTopic in (get children of document 1)
		set tableTitle to name of aTableTopic
		set tableRows to my collectChildren(aTableTopic)
		
		set end of theOutput to my makeTable(tableTitle, tableRows)
	end repeat
end tell

--	Finish the output, and write it to a file on the Desktop
set end of theOutput to "</body></html>"
set theOutput to MarksLib's |join|(theOutput, return)
MarksLib's writeToFile("~/Desktop/SD7FeatureComparison.html", theOutput)


on collectChildren(theChild)
	--	Iterate over the children of a node, generating table rows as we go.  If a child has children of its
	--	own we recur and indent the table rows.
	set tableRows to {}
	tell application "OmniOutliner"
		repeat with aRow in children of theChild
			set rowLevel to level of aRow
			set rowText to name of aRow
			set rowIsInSD6 to (state of cell "6" of aRow) is checked
			set rowIsInSD7 to (state of cell "7" of aRow) is checked
			set rowIsInSD7Lite to (state of cell "7 Lite" of aRow) is checked
			
			if rowLevel > 2 then ¬
				set rowText to MarksLib's |join|(items 1 thru (rowLevel - 2) of my nbspaces, "") & rowText
			set end of tableRows to {level:rowLevel, text:rowText, isInSD6:rowIsInSD6, isInSD7:rowIsInSD7, isInSD7Lite:rowIsInSD7Lite}
			if (count of children of aRow) > 0 then ¬
				set tableRows to tableRows & my collectChildren(aRow)
		end repeat
	end tell
	
	return tableRows
end collectChildren


on makeTable(tableTitle, tableRows)
	--	Generate an HTML table for a list of rows
	local theResult
	
	set theResult to {"", "<h2>" & tableTitle & "</h2>", ¬
		"<table width=\"100%\"><tr><th>Feature</th><th width=\"40px\" class=\"centered\">7.0</th><th width=\"40px\" class=\"centered\">7.0<br />Lite</th><th width=\"40px\" class=\"centered\">6.0</th></tr>"}
	
	repeat with aRow in tableRows
		if isInSD6 of aRow then
			set sd6Text to "&bull;"
			set sd6Class to "checked"
		else
			set sd6Text to ""
			set sd6Class to "unchecked"
		end if
		if isInSD7 of aRow then
			set sd7Text to "&bull;"
			set sd7Class to "checked"
		else
			set sd7Text to ""
			set sd7Class to "unchecked"
		end if
		if isInSD7Lite of aRow then
			set sd7LiteText to "&bull;"
			set sd7LiteClass to "checked"
		else
			set sd7LiteText to ""
			set sd7LiteClass to "unchecked"
		end if
		set end of theResult to "<tr><td>" & text of aRow & "</td><td class=\"" & sd7Class & "\">" & sd7Text & "</td><td class=\"" & sd7LiteClass & "\">" & sd7LiteText & "</td><td class=\"" & sd6Class & "\">" & sd6Text & "</td></tr>"
	end repeat
	set end of theResult to "</table>"
	set end of theResult to ""
	
	--	Convert theResult from a list of strings to a single string and return it
	return MarksLib's |join|(theResult, return)
end makeTable

Here’s an excerpt from my OmniOutliner document you can use to test the script:

Script Debugger Feature Comparison Excerpt.zip (5.4 KB)

To use this code, open the excerpt OmniOutliner document in OmniOutliner, and then run the code above. The result will be a file named SD7FeatureComparison.html located on your desktop.

1 Like