Draft demos: Copy As Markdown & Save As Markdown

I know that @jesse has thoughts about scripting for later builds of Bike, but as a rough demo of what Bike’s file format already lets us do with standard tools, here are sketches of:

  • Copy As Markdown, and
  • Save As Markdown

for the Bike.app preview builds (23 +).

See the attached zip for two versions (standalone and Keyboard Maestro) of each draft script. (Both rough and illustrative, rather than intended for production).

demo.zip (215.3 KB)

Preview of rendered MD output from a Bike document in the zip

Draft Demo


One use of Bike – preparing well structured Markdown documents.

You already can do a lot of different things with Bike, and its ability to read and write outlines in three formats:

  • Standard HTML nested lists (Bike’s default and link-supporting native format)
  • OPML
  • Tab-indented indented plain text (Taskpaper’s native format)

The flexible and widely-supported HTML nested list format is supported by quite a rich ecosystem of standard tools. Here are a couple of draft demos of using just one of those tools (Apple’s built-in NSXMLDocument library, accessed through JavaScript for Automation) to provide:

  • Copy As Markdown
  • Save As Markdown

From a Markdown version of a Bike document, or copied Bike snippet, free tools like Pandoc let us automatically write out other formats, like MS Word .docx

Save as Markdown, and Copy as Markdown, for Bike (preview) builds

JavaScript for Automation is one option

Even where Bike itself is not installed, Bike files can be viewed in browsers, and any standard XML and HTML tools can be used for viewing and converting them.

In this demo, we are using JavaScript for Automation, with Apple’s built-in NSXMLDocument library, which can read the outline structure of a Bike file directly.

Other options

We could also have written a custom Copy As or Save As using widely-available standard tools like XSLT and XQuery.

Mapping from outline levels to Markdown structure

Markdown Heading levels

We can map an outline structure to a Markdown document in any way that we like. In this demo, we are interpreting the top N levels of the outline as Markdown hash headings.

Quote blocks

Any line, at any level in the outline, which starts with > is interpreted as the start of a Markdown quote block. The quote block ends at the first blank line that follows it. Here we have two quote blocks:

From sounds in the air to inscriptions on the printed page, the material structures of language both reflect, and then systematically transform, out thinking and reasoning about the world. Andy Clark, Supersizing the Mind, 2008 Oxford University Press.

We were promised bicycles for the mind, but we got aircraft carriers instead.
Jonathan Edwards, quoted by @jesse

Code blocks

Any line, at any indent level, which starts with three backticks is interpreted as marking the start or end of a code-block. The top-level Bike-reading function in this draft JavaScript demo is:

// treeFromBikeStringLR :: Bike String ->
// Either String [Tree String]
const treeFromBikeStringLR = s => {
        error = $(),
        node = $.NSXMLDocument.alloc
            s, 0, error
    return node.isNil() ? (() => {
            problem = ObjC.unwrap(
        return Left(
            `Not parseable as Bike:\n\n${problem}`
    })() : treeFromBikeXMLNodeLR(node);

Script options

Number of heading levels ?

  • How many of the top outline levels do we want to use for headings ? (6 is the maximum)
const howManyHeadingLevels = 1;

Top heading level ?

  • Which MD heading level do we want to start the document with ?
  • We might want to reserve # for example, and skip straight to ##.
  • The lowest available Markdown heading is ######
const startHeadingLevel = 2;

Outline items as paragraphs or sentences ?

  • Markdown expects paragraphs to be separated by a blank line (two \n characters).

  • Lines separated only by a single \n in Markdown are run together as continuous sentences inside a paragraph, until the next blank line.

  • If we set the option nodesAreParagraphs to true, the export script adds a blank line after every outline item, turning each item into a Markdown paragraph on its own.

  • If we set nodesAreParagraphs to false, then we can add our own blank lines in the outline, and each series of outline items can be run together, by default, into a paragraph, until a blank line is found.

const nodesAreParagraphs = true;

Versions of the script

Each of these two demos is provided in two flavours:

A stand-alone script, which you could attach to a keyboard shortcut with something like FastScripts, and a Keyboard Maestro version, which supports an options dialog for the Save As operation.

Copy Bike as Markdown

Select some lines in Bike, and run the script to copy the selection as Markdown.

Save Bike as Markdown

With a Bike document open:

  • Run the script
  • Confirm the formatting options if you are using the Keyboard Maestro version
  • and choose an output file name

Previewing Markdown


You can preview and print from Markdown texts and clipboards, applying different CSS stylesheets, with Marked 2.

Converting Markdown to MS Word .docx


The free Pandoc tool, which can be run from the command line, and included in script and macro flows, provides conversion from Markdown to .docx and a number of other formats.


PS, I forgot to say, if you are not using Keyboard Maestro, you should set the following option near the top of the standalone scripts:

    // Set this to true if you don't have Keyboard Maestro
    // installed, or prefer to use the values above
    // directly, rather than than import values set in KM.
    // (See the readSettings function below)
    const ignoreKeyboardMaestro = true;

if ignoreKeyboardMaestro is set to false then the scripts will look for their options settings in the following Keyboard Maestro variables:

  • HowManyHeadingLevels (number)
  • TopHeadingLevel (number)
  • NodesAreParagraphs (boolean switch)

This is really nice!

Even after expanding the above preview of rendered MD I didn’t realize everything it was doing… my my mind thought it was just turning levels into headlines… my eyes missed all the other features, thinking they were inserted by the forum software. Impressive!

1 Like

Still rough, but I’m finding I can use it : -)

(One thing I wondered about this morning is prefacing a branch root with | in Bike, and writing out its descendants as a - possibly nested - multimarkdown table)

I just tried to use the provided script to copy markdown content. However it’s failing with: No clipboard content found for type 'com.hogbaysoftware.bike.xml. I assume some changes in Bike since this script was written, are at fault. I don’t have any internal knowledge about Bike (or this script) so if anyone can help me to get this running, i would be very grateful. Thank you!

I’m in the mountains with a phone but no computer – should be back by the end of this month.

@jessegrosjean may be able to advise if the clipboard bundle id has changed – otherwise I will take a look when I get back.


@complexpoint @skrach The script is working for me on latest Bike, but it requires that you’ve made a text selection. If you just have cursor showing in your frontmost document then I also see that error.

Thanks for testing that – the Save As version defaults to rendering the whole text, I think.

Perhaps when I get back it might be helpful to adjust the Copy As version – to copy the whole text by default if the selection isn’t extended.

(I’ll also update them both to use the AppleScript interface – quicker to maintain and possibly faster to execute too)

Thank you very much @jessegrosjean and @complexpoint. I can confirm that it’s working if text is selected in Bike.

1 Like

I’ve added updated Keyboard Maestro versions of these scripts:

  • now using the osascript (AppleScript / JavaScript) interface
  • in the case of Copy As MD copying either selected rows, or all rows if the selection is not extended

and including JS source text, for use with Script Editor etc, at:

BIKE Outliner :: Copy as Markdown - Macro Library - Keyboard Maestro Discourse

BIKE Outliner :: Save As Markdown - Macro Library - Keyboard Maestro Discourse


(I’ve just updated both – on the Keyboard Maestro pages – to reduce redundant blank lines in the generated Markdown)

1 Like

Thanks for these macros!

1 Like

@complexpoint I have used these Keyboard Maestro macros a lot (Save As and Copy As). It makes it so easy for me to go from Bike to the next state (writing app or mind map). Perfect complement to the Bike app itself. Many many continued thanks.


Thanks ! Very good to hear that. I must schedule a review and update in my diary for later in the summer – not least to absorb Bike’s new inline formatting.

1 Like

The dialogue box below is the “secret sauce” (for me) of this macro. Depending on the outline, and the subsequent usage, these 2 settings can differ a LOT. It’s fantastic to have this level of control over the MD output.

1 Like

Thank you for these macros! I am trialing Keyboard Maestro and may end up purchasing. Neat tool!

Is there a way to modify the script to Save “Selection” As Markdown? I sometimes end up with several notes in one Bike file, and I’d love to split them out into different files.

Possibly – I might take a look next week. The risk, I suppose, is that people might have saved less than they think.

Another approach might just be a two-step:

  • Copy selection As MD,
  • and paste to fresh file.
1 Like

Thanks so much for this, @complexpoint. I had been trying to figure out how to do this with pandoc, and it wasn’t really working out.

@jessegrosjean It would be terrific if something like this could be built into Bike at some stage. The reason these scripts are so useful to me is that they let me rapidly turn an outline in Bike into professional-looking handouts to give to my students or to use in talks. I give several lectures a week and have research and service to do as well, so it’s important for me to be as efficient as possible. I had stopped using Bike to write up lecture notes because of the extra steps required to generate handouts (pandoc doesn’t really do the job, as I still have to do a lot of formatting by hand)—with the extra friction, it’s more efficient to just use Word or Typora.

I agree with a user above that the options that complexpoint provides are crucial to the usefulness of the scripts. In my case, they let me produce something that looks like a professional academic handout almost instantaneously in conjunction with Typora or pandoc/LaTeX. (Top level bullets become headings, one below that becomes paragraphs, one below that becomes bullets.)

Thanks again @complexpoint, and many thanks to @jessegrosjean for building such a useful tool!

1 Like

Planning to share, at some point in the next few weeks, a more general and flexible pair of scripts, using Pandoc as their engine.

( Bike outline → transforms like top N levels as headings etc → Pandoc AST → any Pandoc output format )

I hope so. I have a long list of future Bike features, unlikely that I’ll ever get them all done, but “publishing” is one thing on feature this list.

1 Like