Still interested in Markdown support in OmniOutliner

Here’s a script to convert the current OO document to markdown. (@steve, this will give you your minimum ask at least – pop this in your OO scripts folder and you’ll be able to export markdown from the script menubar with two clicks.)

Thanks to @SGIII for figuring out how to handle markdown conversion within rows, and to @draft8 for cleaning up some of the code. You guys are great. The script doesn’t support all markdown tags (e.g. code blocks, underlined text), but it does support headings/blockquotes/bold/italics/lists. Adding the rest should be fairly easy. NB not tested very thoroughly, though I ran a number of longer outlines through it and it worked as expected.

If you want conversion to tex/pdf, an extended version of the script that does that is here.

function run() {

// Setup

var app = Application.currentApplication();
app.includeStandardAdditions = true;
var OmniOutliner = Application('OmniOutliner');
var doc = OmniOutliner.documents[0];
var fileName = "outline.md";
var desktopString = app.pathTo("desktop").toString()

// The text of the document

var outlineText = "";

// Loop through rows and append their text to outlineText

doc.rows().forEach(function(theRow) {
	if (Object.keys(theRow.style.namedStyles).length > 0) {
		switch(theRow.style.namedStyles[0].name()) {
			case "Heading 1":
				outlineText += "# ";
				break;
			case "Heading 2":
				outlineText += "## ";
				break;
			case "Heading 3":
				outlineText += "### ";
				break;
			case "Blockquote":
				outlineText += "> ";
				break;
			case "Ordered List":
				outlineText += "1. ";
				break;
			case "Unordered List":
				outlineText += "* ";
				break;
		}	
	}
	outlineText += rowTextMD(theRow);
	outlineText += "\r";
});

// Convert the text of the paper to UTF8 encoding

outlineText = $.NSString.alloc.initWithUTF8String(outlineText);

// Write outlineText to a new markdown file

var file = `${desktopString}/${fileName}.md`
outlineText.writeToFileAtomicallyEncodingError(file, true, $.NSUTF8StringEncoding, null);

return true;

}

// From apple's documentation for Javascript for Automation
 
function writeTextToFile(text, file, overwriteExistingContent) {
    try {
 
        // Convert the file to a string
        var fileString = file.toString()
 
        // Open the file for writing
        var openedFile = app.openForAccess(Path(fileString), { writePermission: true })
 
        // Clear the file if content should be overwritten
        if (overwriteExistingContent) {
            app.setEof(openedFile, { to: 0 })
        }
 
        // Write the new content to the file
        app.write(text, { to: openedFile, startingAt: app.getEof(openedFile) })
 
        // Close the file
        app.closeAccess(openedFile)
 
        // Return a boolean indicating that writing was successful
        return true
    }
    catch(error) {
 
        try {
            // Close the file
            app.closeAccess(file)
        }
        catch(error) {
            // Report the error is closing failed
            console.log(`Couldn't close file: ${error}`)
        }
 
        // Return a boolean indicating that writing was successful
        return false
    }
}

// Code below written by draft8, based on code written by SGIII, in turn adapted from AppleScript code written by Rob Trew

const rowTextMD = row => {
        const
            as = row.topic.attributeRuns;
        return enumFromTo(0, as.length - 1)
            .reduce((s, i) => {
                const
                    attrib = as.at(i),
                    fnt = attrib.font(),
                    bld = (fnt.includes('Bold') || fnt.includes('Black')) ? (
                        '**'
                    ) : '',
                    ital = fnt.includes('Italic') ? '*' : '';
                return s + bld + ital + attrib.text() + ital + bld;
            }, '') + '\n';
    };
	
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
	Array.from({
	length: Math.floor(n - m) + 1
    }, (_, i) => m + i);
2 Likes