Quick tips are random posts regarding something I discovered on my way to something bigger. They usually get longer than “quick” would imply, for which I refuse to apologize.

I have this crazy idea for an interactive blog post using an embedded MindMeister mind map. It basically allows me to explore a topic infinitely and in more detail than I would normally consider readable. It also allows me to organize in ways that I can’t in regular prose. The end result would be a post where I could expound on each topic as much (or as little) as I wanted, and you could drill down to topics you were interested in. You’d see my train of thought and the connections I was making. I have a couple of these started, and I think they’ll go over well once I get one finished and posted. There’s a downside, though…

Indexing takes a big hit. My own local search and external search engines will have nothing to work off of. This is bad news when you’re investing as much time as I have been in putting the posts together. I kludged together a solution this morning; it has applications beyond this project so I thought I’d share.

Basically, I wanted to take my mind map and turn it into Markdown/HTML for inclusion after the map. I needed to include all of my notes and keep things nested like the original map. The process I came up with loses hyperlinks, but maintains the text nicely.

The script below is a quick hack designed to work with Mindjet MindManager text output with “Format as outline” checked. I exported my current map from MindMeister in .mmap format and imported it in MindManager, then exported to the formatted text. The output looks like this:

#!/usr/bin/env ruby

input = ARGF.read
current_indent = 0

# Find MindManager-style headlines and convert them to Markdown hashes
input.gsub!(/={5,}\n\s*(.*?)\n={5,}/,"# \\1") # first-level
  .gsub!(/-{5,}\n\d+\s*(.*?)\n\-{5,}/,"\#\# \\1") # second-level
puts input.split("\n").map {|line|
  # remove the line from the array if empty
  next if line =~ /^\s*$/
  
  # replace trailing xx.xx with an asterisk, 
  line = line.gsub(/^([\d\.]+)*?(\d+\.\d+\s)/,"\\1* ")
  # then count the decimal points in the remiainder
  line.match(/^(\d+\.)*/)[0].scan(/\./).count.times do
    # replace with tabs
    line.sub!(/\d+\.([\*\t])/,"\t\\1")
  end
  if line =~ /^#(.*?)$/ # if it's a headline, add space above and below
    line = "\n#{line}\n\n"
  elsif line =~ /^\s*\*/ # if it's a list item, just one line break
    line = "#{line}\n"
    current_indent = line.match(/^\s*/)[0].length + 1 # record indentation level
  else # if line is neither, then it's a note.
    line.chomp! # clean it up
    current_indent.times do # prefix tabs for the current_indent level
      line = "\t" + line
    end
    line = "\n#{line}\n\n" # add space above and below note
  end

  line
}.join # join without newlines, already added to each element

The final output looks like:


## Coding

* iTerm2
* TextMate

	Looking forward to TextMate 2, or barring that, Sublime Text 2 

	* Custom bundles
* MacVim
* Xcode
* Changes
	* Kaleidoscope
* Tower/GitHub

	I do most of my git from the command line, but I'm not ashamed to admit that I'd just rather use a GUI for complex operations. The GitHub app makes reverting and rebasing seem so effortless...

Sub-lists are indented to become nested lists, and notes are indented such that they become a paragraph (or series of paragraphs) within the preceding list item. Works like a charm, though I’m sure the script doesn’t account for a lot of possible situations. If you’re looking for a quick way to get clean HTML out of your mind maps, this is one path you can try.

Why not OPML? Because I couldn’t get any mind mapping apps to include my notes in the export. I needed those. In my final MindMeister map, hovering over a node will pop up its note in a floating window, which is really handy for explaining things while keeping the map smaller. If you know a way to get any of the major mind mapping apps to handle notes in OPML, I’m curious.