Exporting OmniOutliner files to Markdown

Over the past year, I’ve been learning to use two programs for nearly everything I do. The first is OmniOutliner Pro, which I used to take notes in my University lectures. Its outlines fit well with how my lectures were presented and my note-taking style, making it a near perfect tool. For non-note taking, I’ve been using John Gruber’s Markdown, which provides a simple formatting syntax, which is clear and easy to read before it’s processed, and a processor to convert the plain text into HTML.

I often use Markdown for quick note taking and even some long form writing (I’m using it to write this post, for instance). I love Markdown because all its files are just plain text; OmniOutliner’s files, while rather open, can’t come close to the openness of Markdown. Were something to happen to the Omni Group, or I were for some reason unable to use OmniOutliner, I’d like to be able to access my notes. What I really wanted was a way to get all of my school notes, stored in OmniOutliner format, exported to Markdown syntax.

There is a Markdown export plugin available, but it doesn’t quite fit my needs. It exports each level as an HTML heading, starting at H1 going all the way to H6. While this may be useful for some, my ideal export would be as an HTML Unordered List, with each node indented, but otherwise presented as standard text.

While looking at the various export options, I discovered that the “Plain Text (with tabs)” exporter generates almost perfect Markdown, with a few problems. First, collapsed rows don’t show up. Secondly, status checkboxes are shown, and don’t look quite right. I only learnt how to disable them in the default template last year, so many of my notes have them shown, but not used. Finally, because the header of the notes is unstyled, the whole note parses as one paragraph, and the formatting is completely wrong. After some more tinkering, I found that by putting three hashes (###) at the beginning of the first line, making it a H3, the entire note would be processed correctly.

With these things in mind, I realized what I needed. I wanted something to automatically open every OmniOutliner note I took in school, expand the rows, hide the status checkboxes and export the file to Markdown format. When the word “automatically” pops up with respect to a Mac, especially with a very Mac-like program like OmniOutliner, the first thoughts should be of Automator and Applescript. Applescript allows Mac users to access parts of many applications through a simple English-like scripting language. Automator does something similar, but with a graphical interface and some limitations. I fiddled about in Automator, but was unable to get the proper files selected, so I moved on to Applescript.

OmniOutliner provides an extensive Applescript Dictionary, a list of all the objects and functions available to a script. I quickly found there were methods for doing everything I needed. First, a sample document which I would use this script on.

A Sample Outline

As you can see, the outline is very simple. The header is just the course and date of the note, and then the rest is a simple outline, with nodes and children. Here’s the finished script I made:

on open names
   tell application "OmniOutliner Professional"
       open names
        set theDocuments to every document
        repeat with currentDocument in theDocuments
           tell currentDocument
               expandAll
                set status visible to false
                set oldFirstColumn to the title of second column
                set newFirstColumn to "###" & oldFirstColumn
                set the title of second column to newFirstColumn
                export to path & ".markdown" as "NSStringPboardType"
                set the title of second column to oldFirstColumn
                save
                close
           end tell
       end repeat
   end tell
end open

Download the script See update below

Let’s walk through the script to see what’s happening. The first line, “on open names“, sets the script up to act as a droplet, which lets you drag any type of file from the Finder directly onto the script and have them operated on. A list of the files is stored in the names variable. The next line directs all the following commands to the OmniOutliner Professional application. The line “open names” tells OmniOutliner to open every file which was dropped onto the droplet. There are two things to note here: first, if a lot of files are done at once, this can take a long time and a lot of RAM. Second, if you try to do this with a file OmniOutliner cannot open, the program with stop and alert you. At this point, no files will have been modified, but there may be other outlines open. Just be aware of these facts. I used the script with nearly 200 OmniOutliner documents, and it worked flawlessly on all of them, though it was rather slow at it.

The script then asks OmniOutliner for a list of all its open documents (which the script itself just opened) and begins iterating over each one. First, it expands all the rows with the expandAll command, and it sets the status visible property to false. Next, the script adds the “###” to the beginning of the header so the exported file will parse as proper Markdown with the lines

set oldFirstColumn to the title of second column
set newFirstColumn to “###” & oldFirstColumn
set the title of second column to newFirstColumn

Now comes the exporting, with the command export to path & “.markdown” as “NSStringPboardType”. Each document has a path property, which contains the full path of the file. We can use this to save the exported file to the same location as the original. We add “.markdown” to the file path so the system can recognize the Markdown file and we don’t accidently overwrite our OmniOutliner document. The “NSStringPboardType” tells the export function to use the “Plain Text (with tabs)” format. With the file exported, we get rid of the “###” by restoring the old header text, with the command set the title of second column to oldFirstColumn. Finally, we save the document and close it.

Save the script as an Application and you can drag and drop files from the Finder onto the droplet. I used a Spotlight search to find all the files with Kind matching “OmniOutliner 3″ in my School folder and dragged them over. The 187 documents opened one after the other (giving 187 windows), made the changes, exported and closed. Running the script took a few minutes; it was probably about 1 second per file.

Some caveats

  • If there are any “LinkBack Items” to other Omni Group programs, like a Graffle object in the middle of the outline, they won’t be exported as images. They’ll simply have the text “LinkBack Item from OmniGraffle” inline. I suspect a proper Markdown export plugin may be able to export images as well.
  • Any Markdown syntax, like hashes or square brackets, in an outline will not be escaped. The exported file will still be human readable without any data loss, but it may need some modification before being run through a Markdown processor.
  • After running through this script, OmniOutliner documents will have their rows expanded and status checkboxes hidden. If this doesn’t suit you, you can remove or comment out the save command.
  • Once again, be wary of opening too many files with this script at once. It may severely slow down your computer.

I know the script is rather specialized, but it may be useful for you. Applescript is a powerful language that can take some getting used to, but using it can be quite fun and help you do a lot of things with your Mac.

UPDATE I’ve rewritten the script with a few changes. First and foremost, the script now opens a file, operates on it and closes it, rather than opening ALL the files, then operating and closing them. This should make it better for computers with limited resources. With that change I was able to have the script check if a dropped file is an oo3 file. If it ISN’T, the script ignores it. This should let you drag groups of files without worrying about if they’re all files.

The updated version, 1.1, can be downloaded here