markdown_player
▶️ Executable markdown files.
Write markdown documentation, run markdown documentation!
Install
Install the CLI:
deno install --unstable -f -A -n markdown_player "https://deno.land/x/markdown_player@v1.2.0/src/bin.ts"
Install the deno
library:
import * as markdownPlayer from "https://deno.land/x/markdown_player@v1.2.0/src/mod.ts";
markdownPlayer.playFile("readme.md");
How it works
- Reads a markdown file
- Parses all fenced code blocks
- Executes each code fence in an independent or shared process
- Captures and re-emits command output!
Preview
- Write code in code blocks
- Run
markdown_player /path/to/file.md --appendOutput
- Observe the output
import { getEmojiByName } from "https://deno.land/x/getmoji@1.2.0/mod.ts";
const fileType = "markdown";
const description = `Runs code fences in a ${fileType} file`;
console.log(`${description} ${await getEmojiByName("pizza")}`);
Runs code fences in a markdown file 🍕
The above output was auto written to this document by using the --appendOutput
flag!
Features
- share execution environments between code blocks
- configure code blocks to be run with custom commands
- optionally write code blocks to files, with support for optional auto-removal
API
Code fences can be configured via single line yaml in the meta section. Consider the following markdown meta:
```bash {file: {name: greeting.sh}}
Now, apply it to a real code block (warning, the meta is hidden by real codeblocks, unless you look at the markdown source):
# creates a file called "greeting.sh"
echo "hello $USER!"
hello cdaringe!
…and that file gets run!
meta-option | type | description |
---|---|---|
skipRun |
boolean? | Do not execute this code block |
group |
string? | Run any same named group code blocks in the same file |
cmd |
string? | Executable to run |
args |
string[]? | Args to pass to the executable. Use the string “$ARG” to get the contents of the code fence |
file |
object? | Flush the code block to a file then execute it. This is the default operation mode. |
file.name |
string? | Name the file. Otherwise, a random filename is generated |
file.autoRemove |
boolean? | Set to false to keep the file. Otherwise, it is deleted by default |
isExecutionOutput |
boolean? | Signify that this block is for capturing stdio from the above code block. Generally considered a private API |
skipOutput |
boolean? | Run the block, but skip writing output if appendOutput mode is also requested |
You can verify your compact YAML syntax using https://yaml-online-parser.appspot.com/.
Examples
Meta blocks
The following block has meta: ```js {cmd: node, args: ["--eval", $ARG]}
// no file is written
console.log(123);
123
The following block has meta:
```js {file: {name: 456-demo.js, autoRemove: true}, cmd: node, args: [456-demo.js]}
console.log(456);
456
Share execution context
Sharing variables can be achieved by adding a {group: name}
to the codeblock
meta. All items in a group
eventually get run from a single file, where all
blocks are combined into a single file.
Math is important. Learn math! Consider this function:
const square = (x: number) => x * x;
What if we passed a two?
const twoSquared = square(2);
console.log(twoSquared);
4
What about the square of a square?
console.log(square(twoSquared));
16
Run a code block, but skip output
use the skipOutput
meta flag: ```ts {skipOutput: true}
// print out an enormous string!
console.log([...Array(1e4)].join("a\n"));
FAQ
Error: Exec format error (os error 8)
Did you try to execute a file that was not a binary, or had no
#!/usr/env/bin LANG
block?