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.
npm install runmd
runmd [options] input_file
Where options
may be zero or more of:
--output=output_file
file to write specify an output file--watch
Watchinput_file
for changes and rerender--lame
Suppress attribution footer
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
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:
console.log()
works, but no otherconsole
methods are supported at this timesetTimeout()
works, but all timers fire immediately at the end of script execution.clearTimeout
,setInterval
, andclearInterval
are not supported
[Note: PRs fleshing out these and other missing APIs would be "well received"]
Some ES6 import incantations will work, however this feature should be considered very experimental at this point. Read the source for details.
To avoid publishing when compilation of your README file fails:
"scripts": {
"prepare": "runmd README_js.md --output README.md"
}
Runs the script, appending any console.log output. E.g.:
Input | Output |
---|---|
```javascript --run console.log('Hello, World!'); ``` |
```javascript console.log('Hello, World!'); ⇨ Hello, World! ``` |
--run
may be omitted if other options are present.
Allows for the creation of different JS contexts with different variable name spaces. Blocks with the same context name share the same variables. E.g...
Input | Output |
---|---|
```javascript --run sample let text = 'World'; ``` |
```javascript let text = 'Hello'; ``` |
Continuing on ... | |
```javascript --run sample console.log(text); ``` |
```javascript console.log(text); ⇨ Hello ``` |
Attempting to reference state in a different context will error... | |
```javascript --run console.log(text); ``` |
ReferenceError: text is not defined |
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.
Input | Output |
---|---|
Welcome! ```javascript --run foo --hide // Setup/utility code or whatever ... function hello() { console.log('Hello, World!'); } ``` Here is a code snippet: ```javascript --run foo hello(); ``` |
Welcome! Here's a code snippet: ```javascript hello(); ⇨ Hello, World! ``` |
Result values may be displayed for for single line expressions by appending "// RESULT" to the end of a line.
RunMD will error if the line is not a self-contained, evaluate-able, expression.
Input | Output |
---|---|
```javascript --run var x = 'foo' + 'bar'; // RESULT ``` |
```javascript var x = 'foo' + 'bar'; // ⇨ 'foobar' ``` |
A global runmd
object is provided to all contexts. It supports the following
events:
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).
```javascript --hide
// Remap `require('uuid/*') to `require('./*')
runmd.onRequire = function(path) {
return path.replace(/^uuid\//, './');
}
```
The onOutputLine
event gives pages the opportunity to transform markdown output.
```javascript --hide
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:
- Install the Markdown Preview Plus Chrome
- ... Allow it to access file URLs" (in chrome://extensions tab)
- ... Set Reload Frequency to "1 second" (in the extension options)
- Launch
runmd
with the--watch
option to have it continuously re-render your output file as you make changes - Open the output file in Chrome, and it will update in realtime as you make changes to your runmd input file(s)