A common use case with plugins involves generating MyST AST and inserting it into the document. This page covers a few ways that you can do so.
Parse MyST markdown to AST in a directive or role¶
With a function call¶
The parseMyst function (available in the ctx variable) provides an explicit method to parse MyST text into MyST AST.
Here’s an example of using the parseMyst function within a directive plugin to parse the body of the directive into MyST AST:
const myDirective = {
name: "mydirective",
doc: "My new directive!",
// Here the body is passed as a string
body: { type: String, doc: "To be parsed into MyST AST." },
run(data, vfile, ctx) {
// Here we parse the body into MyST AST
const ast = ctx.parseMyst(data.body);
return ast.children[0];
},
};ctx.parseMyst returns a root node which contains the parsed MyST as children.
The directive plugin example above returns ast.children[0] (the first child of the root node) to avoid creating a malformed document (there can only be one “root”).
You can use the parseMyst function to construct MyST outputs from text generated with string interpolation, for example:
const myDirective = {
name: "justacard",
doc: "Basically does what a card directive does!",
arg: { type: String, doc: "To be parsed into MyST AST." },
body: { type: String, doc: "The body of the directive." },
run(data, vfile, ctx) {
// Here we parse a string that defines a multi-line card directive
const ast = ctx.parseMyst(`:::{card} ${data.arg}\n${data.body}\n:::`);
return ast.children[0];
},
};If you need to use multi-line strings you must dedent them
The example above puts a multi-line string onto one line by manually coding the \n characters.
If you instead want to show a multi-line string in your code, you will need to remove the indentation manually, for example like the following:
const myDirective = {
name: "justacard",
doc: "Basically does what a card directive does!",
arg: { type: String, doc: "To be parsed into MyST AST." },
body: { type: String, doc: "The body of the directive." },
run(data, vfile, ctx) {
// By removing the indentation white-space the string is correctly parsed
const ast = ctx.parseMyst(`
:::{card} ${data.arg}
${data.body}
:::`);
return ast.children[0];
},
};With automatic parsing¶
You can define a plugin’s argument or body as {type: 'myst'} instead of {type: String} to enable those parameters to be autuomatically parsed into AST nodes.
In this case, data.body will be a list of AST nodes instead of text:
1 2 3 4 5 6 7 8 9 10 11 12const myDirective = { name: "mydirective", doc: "My new directive!", // By defining type: 'myst', the directive body will automatically be parsed into MyST AST body: { type: 'myst', doc: "Pre-parsed and immediately usable as MyST AST.", }, run(data) { return data.body[0]; }, };
Use the MyST Sandbox to identify AST structure¶
The MyST interactive sandbox is a great way to explore what MyST looks like when it is rendered, and what its underlying AST structure looks like. This is particularly useful if you’re generating MyST AST from scratch. For example, as part of a plugin role or directive.
Here’s how you can use the MyST sandbox to explore the structure of a card directive and preview its AST.
Click here to see the full output of the MyST sandbox
The output of the sandbox AST generator can be seen in Program 1. The highlighted outer root and block nodes are always included in the output, and contain the interesting AST (in this case, a card).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33{ "type": "root", "children": [ { "type": "block", "children": [ { "type": "card", "children": [ { "type": "cardTitle", "children": [ { "type": "text", "value": "My title" } ] }, { "type": "paragraph", "children": [ { "type": "text", "value": "My card body." } ] } ] } ] } ] }
Program 1:The AST of a card directive, produced by the MyST sandbox.