GitHub - broofa/runmd: Executable markdown files (original) (raw)

Run code blocks in your markdown and annotate them with the output.

Creating README files is a pain, especially when it comes to writing code samples. Code gets out of date, authors get sloppy, details get omitted, etc. RunMD takes the pain out of this process.

With RunMD, your readers can trust your code blocks are runnable and that code output will be as-claimed.

Install

Usage

runmd [options] input_file

Where options may be zero or more of:

For example, to port an existing README.md file:

cp README.md README_js.md

Edit README_js.md to add Markdown Options (below) to your ````javascript` blocks, then ...

runmd README_js.md --output README.md

Limitations

RunMD scripts are run using Node.js' vm module. This environment is limited in "interesting" ways, and RunMD runs fast and loose with some APIs. Specifically:

[Note: PRs fleshing out these and other missing APIs would be "well received"]

ES6 Imports

Some ES6 import incantations will work, however this feature should be considered very experimental at this point. Read the source for details.

NPM Integration

To avoid publishing when compilation of your README file fails:

"scripts": {
  "prepare": "runmd README_js.md --output README.md"
}

Markdown API

--run

Runs the script, appending any console.log output. E.g.:

```javascript --run
console.log('Hello, World!');

... becomes:
console.log('Hello, World!');

⇒ Hello, World!

`--run` may be omitted if other options are present.

### \--run \[context\_name\]

[](#--run-context%5Fname)

If a `context_name` is provided, all blocks with that name will share the same runtime context. E.g.
let text = 'World';

Continuing on ...

console.log(text);

... becomes:
let text = 'Hello';

Continuing on ...

console.log(text);

⇒ Hello

... but trying to reference `text` in a new context or other named context will fail:
console.log(text);

(Results in `ReferenceError: text is not defined`.)

### \--hide

[](#--hide)

Run the script, but do not render the script source or output. This is useful for setting up context that's necessary for code, but not germane to documentation.

Welcome!

// Setup/utility code or whatever ...
function hello() {
  console.log('Hello, World!');
}

Here is a code snippet:

hello();

... becomes:

Welcome!

Here's a code snippet:

hello();

⇒ Hello, World!

### "// RESULT"

[](#-result)

Inline values **_for single line expressions_** may be displayed by appending "// RESULT" to the end of a line. Note: RunMD will error if the line is not a self-contained, evaluate-able, expression.
['Hello', ' World!'].join(','); // RESULT

... becomes:
['Hello', ' World!'].join(','); // ⇨ 'Hello, World!'

## runmd Object

[](#runmd-object)

A global `runmd` object is provided all contexts, and supports the following:

### runmd.onRequire

[](#runmdonrequire)

The `onRequire` event gives pages the opportunity to transform module require paths. This is useful if the module context in which you render markdown is different from what your readers will typically encounter. (Often the case with npm-published modules).
// Remap `require('uuid/*') to `require('./*')
runmd.onRequire = function(path) {
  return path.replace(/^uuid\//, './');
}

### runmd.onOutputLine

[](#runmdonoutputline)

The `onOutputLine` event gives pages the opportunity to transform markdown output.
runmd.onOutputLine = function(line, isRunning) {
  return !isRunning ? line.toUpperCase() : line);
}

```

The isRunning argument will be true for any lines that are interpreted as code by this module. Transformations do not affect interpreted source, only how source is rendered.

Return null to omit the line from the rendered output.

There's more than one way to visualize changes to Markdown files as you edit them, but the following works pretty well for me:


Markdown generated from src/README_js.md by