The Markdoc syntax
Markdoc syntax is a superset of Markdown, specifically the CommonMark specification. Markdoc adds a few extensions to the syntax, such as tags and annotations, which we describe below. These extensions enable Markdoc's powerful extensibility model.
For a formal grammar of the Markdoc tag syntax, refer to the Markdoc syntax spec.
Nodes
Nodes are elements that Markdoc inherits from Markdown.
# Headers **Bold** _Italic_ [Links](/docs/nodes) Lists - Item 1 - Item 1 - Item 1 > Quotes `Inline code` ``` Code fences ```
You can't change Markdoc syntax. But you can create custom nodes that change how this syntax is rendered. For instance, write a custom header
node to make # Header
produce a different result.
For more information, check out the Nodes docs.
Tags
Markdoc extends Markdown syntax with tags. Each tag is enclosed with {%
and %}
, and includes the tag name, attributes, and the content body. Similar to HTML, most tags can be nested, and tags with no content can be self-closing
{% alert %} {% icon src="alert.png" /%} An error occurred. {% /alert %}
The built-in tags are table
, if
, else
, and partial
. You can extend Markdoc by writing custom tags.
For more information, check out the Tags docs.
Attributes
Pass attributes to nodes and tags to customize their behavior. You can pass values of type: number
, string
, boolean
, JSON array
, or JSON object
, either directly or using variables.
With tags, you can use an HTML-like syntax:
{% city index=0 name="San Francisco" deleted=false coordinates=[1, 4, 9] meta={id: "id_123"} color=$color /%}
Because the HTML-like syntax doesn't work with nodes, we offer another option: write the attributes after the tag or node you're passing them to, in a separate set of {%
and %}
.
{% table %} * Cell * Cell --- * Cell {% colspan=2 %} {% /table %}
For more information, check out the Attributes docs.
Variables
Markdoc variables let you customize your Markdoc documents at runtime. Variables all have a $
prefix.
Here I am rendering a custom {% $variable %}
Variables must contain JSON-serializable content, such as strings, booleans, numbers, arrays, and JSON objects. You can access nested values using dot-notation, similar to JavaScript:
Here's a deeply nested variable {% $markdoc.frontmatter.title %}
For more information, check out the Variables docs.
Functions
Functions look and feel similar to JavaScript functions. They're callable from the body of the document or within an attribute. Function parameters are comma-separated. Trailing commas aren't supported in function calls.
# {% titleCase($markdoc.frontmatter.title) %} {% if equals(1, 2) %} Show the password {% /if %} {% tag title=uppercase($key) /%}
For more information, check out the Functions docs.
Comments
Note: comment support currently requires passing allowComments: true
to Markdoc.Tokenizer
.
This will be on by default in a future version of Markdoc.
Markdoc supports Markdown comment syntax adding comments to your documents without having the content show up in the renderable output.
<!-- comment goes here -->
Configuration
To pass options into the rendering process, use a config object. For instance, a config object is one way to provide values for variables:
const source = ` The answer is {% $x %}. `; const config = { variables: { x: 10 } } const ast = Markdoc.parse(source); const content = Markdoc.transform(source, config); return Markdoc.renderers.html(content);
<p>The answer is 42.</p>
For more information, check out the Configuration docs.