Rendering

Render to Markdown

Convert a Comark AST back to markdown, preserving frontmatter and component syntax.

The renderMarkdown function converts a ComarkTree back into a markdown string, preserving frontmatter, component syntax, and attributes. Use it for round-tripping (parse, transform, serialize), content migration, programmatic editing, or generating markdown from an AST.

renderMarkdown(tree, options?)

import { parse } from 'comark'import { renderMarkdown } from 'comark/render'const tree = await parse(`---title: Hello---# Hello **World**::alert{type="info"}This is an alert::`)const markdown = await renderMarkdown(tree)

The output is a complete markdown document including the frontmatter block:

---title: Hello---# Hello **World**::alert{type="info"}This is an alert::

Options

renderMarkdown accepts an optional RenderMarkdownOptions object:

OptionTypeDefaultDescription
maxInlineAttributesnumber3Maximum attributes before switching to YAML block syntax. Set to 0 to always use block syntax
componentsRecord<string, NodeHandler>{}Custom render handlers for specific elements
dataRecord<string, any>{}Additional data passed to render handlers

Inline vs Block Attributes

When a component has more attributes than maxInlineAttributes, Comark switches to YAML block syntax:

// Renders as inline when 3 or fewer attributes// ::card{title="Hello" icon="star" color="blue"}// Switches to block syntax when more than 3// ::card// ---// title: Hello// icon: star// color: blue// size: large// ---

Use Cases

Round-trip Transformation

Parse markdown, programmatically transform the AST, then serialize back:

import { parse } from 'comark'import { renderMarkdown } from 'comark/render'import { visit } from 'comark/utils'const tree = await parse(source)// Add an "external" class to all linksvisit(tree,  (node) => Array.isArray(node) && node[0] === 'a',  (node) => {    const el = node as [string, Record<string, any>, ...any[]]    if (el[1].href?.startsWith('http')) {      el[1].target = '_blank'    }  })const output = await renderMarkdown(tree)

Content Migration

Convert between attribute styles or normalize formatting:

import { parse } from 'comark'import { renderMarkdown } from 'comark/render'async function normalizeDocument(source: string) {  const tree = await parse(source)  // Re-serialize with consistent formatting  return renderMarkdown(tree, { maxInlineAttributes: 0 })}

Programmatic Document Generation

Build a Comark document from data:

import { renderMarkdown } from 'comark/render'import type { ComarkTree } from 'comark'const tree: ComarkTree = {  frontmatter: { title: 'API Reference', date: '2025-01-01' },  meta: {},  nodes: [    ['h1', {}, 'API Reference'],    ['p', {}, 'Welcome to the API docs.'],    ['alert', { type: 'info' }, 'This API is in beta.'],  ],}const markdown = await renderMarkdown(tree)

See Also

Copyright © 2026