Skip to content

Nodes

Markdoc nodes enable you to customize how your document renders without using any custom syntax—it consists entirely of Markdown.
Customizing nodes lets you extend your implementation incrementally.

Customizing Markdoc nodes

Nodes are elements that Markdoc inherits from Markdown, specifically the CommonMark specification.

You define custom nodes by passing a custom Node to your Config, like:

import { heading } from './schema/Heading.markdoc';

const config = {
  nodes: {
    heading
  }
};

const ast = Markdoc.parse(doc);
const content = Markdoc.transform(ast, config);

const children = Markdoc.renderers.react(content, React, { components });

where heading looks something like:

// ./schema/Heading.markdoc.js

import { Tag } from '@markdoc/markdoc';

// Or replace this with your own function
function generateID(children, attributes) {
  if (attributes.id && typeof attributes.id === 'string') {
    return attributes.id;
  }
  return children
    .filter((child) => typeof child === 'string')
    .join(' ')
    .replace(/[?]/g, '')
    .replace(/\s+/g, '-')
    .toLowerCase();
}

export const heading = {
  children: ['inline'],
  attributes: {
    id: { type: String },
    level: { type: Number, required: true, default: 1 }
  },
  transform(node, config) {
    const attributes = node.transformAttributes(config);
    const children = node.transformChildren(config);

    const id = generateID(children, attributes);

    return new Tag(
      `h${node.attributes['level']}`,
      { ...attributes, id },
      children
    );
  }
};

After registering this custom node, you can then use it in your Markdoc, like:

#### My header

Options

These are the optional fields you can use to customize your Node:

OptionTypeDescription
renderstringName of the output (for example, HTML tag, React component name) to render
childrenstring[]Determines which tag or node types can be rendered as children of this node. Used in schema validation.
attributes{ [string]: SchemaAttribute }Determines which values (and their types) can be passed to this node.
transform
(Ast.Node, ?Options) =>
  | RenderableTreeNode
  | RenderableTreeNode[]
  | null
Customize the Markdoc transform function for this node, returning the custom output you want to eventually render. This is called during the transform step.
validate
(Node, ?Options) => ValidationError[];
Extend Markdoc validation. This validates that the content meets validation requirements, and is called during the validate step

Built-in nodes

Markdoc comes out of the box with built-in nodes for each of the CommonMark types:

Node typeAttributes
documentfrontmatter
headinglevel
paragraph
hr
imagesrc, alt
fencecontent, language, process
blockquote
listordered
item
table
thead
tbody
tr
tdalign, colspan, rowspan
thalign, width
inline
strong
em
s
linkhref, title
codecontent
textcontent
hardbreak
softbreak
error

Next steps