Rendering

Render Comark to HTML

Render Comark AST to HTML or Markdown strings without any framework dependency.

The comark/string module provides framework-free rendering of Comark AST to HTML or Markdown strings. Use it for server-side rendering, static site generation, RSS feeds, emails, or any context where you don't need Vue or React.

renderHTML(tree, options?)

Convert a Comark AST to an HTML string:

import { parse } from 'comark'
import { renderHTML } from 'comark/string'

const tree = await parse(`
# Getting Started

This is a **bold** statement with a [link](https://example.com).

- Item 1
- Item 2
`)

const html = renderHTML(tree)

Custom Components

When your content uses Comark components (like ::alert), provide custom render functions to control their HTML output:

import { parse } from 'comark'
import { renderHTML } from 'comark/string'

const tree = await parse(`
::alert{type="warning"}
This is a warning message!
::
`)

const html = renderHTML(tree, {
  components: {
    alert: ([tag, attrs, ...children], { render }) => {
      return `<div class="alert alert-${attrs.type}" role="alert">${render(children)}</div>`
    }
  }
})

Each component render function receives:

  • The full ComarkElement tuple [tag, attributes, ...children]
  • A context object with:
    • render(children: ComarkNode[]) — renders the element's children to HTML
    • data — frontmatter data passed via options.data

With Frontmatter Data

Pass frontmatter data so component renderers can access it:

const tree = await parse(`---
siteName: My Blog
---

::header
Welcome!
::
`)

const html = renderHTML(tree, {
  data,
  components: {
    header: ([tag, attrs, ...children], { render, data }) => {
      return `<header><h1>${data?.siteName}</h1>${render(children)}</header>`
    }
  }
})

With Syntax Highlighting

Use parse with the highlight plugin to get syntax-highlighted code blocks in the HTML output:

render.ts
import { parse } from 'comark'
import { renderHTML } from 'comark/string'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

const tree = await parse('```js\nconsole.log("hi")\n```', {
  plugins: [
    highlight({
      themes: { light: githubLight, dark: githubDark }
    })
  ]
})

const html = renderHTML(tree)

renderMarkdown(tree, data?)

Converts a Comark AST back to Markdown. Optionally includes frontmatter data.

import { parse } from 'comark'
import { renderMarkdown } from 'comark/string'

const source = `---
title: Hello
---

# Hello **World**

::alert{type="info"}
This is an alert.
::
`

const tree = await parse(source)

const markdown = renderMarkdown(tree)

This is useful for normalizing content, programmatic transformations, or roundtrip testing.


Use Cases

Static Site Generation

build.ts
import { readFile, writeFile } from 'node:fs/promises'
import { parse } from 'comark'
import { renderHTML } from 'comark/string'
import highlight from 'comark/plugins/highlight'

async function buildPage(filePath: string) {
  const source = await readFile(filePath, 'utf-8')
  const tree = await parse(source, {
    plugins: [highlight()]
  })

  const html = renderHTML(tree)

  await writeFile('out/index.html', `
    <!DOCTYPE html>
    <html>
      <head><title>${tree.frontmatter.title}</title></head>
      <body>${html}</body>
    </html>
  `)
}

RSS Feed

rss.ts
import { parse } from 'comark'
import { renderHTML } from 'comark/string'

async function generateRSSItem(source: string) {
  const tree = await parse(source)
  return `
    <item>
      <title>${tree.frontmatter.title}</title>
      <description><![CDATA[${renderHTML(tree)}]]></description>
    </item>
  `
}

API Response

server.ts
import { parse } from 'comark'
import { renderHTML } from 'comark/string'

async function handleRequest(markdownContent: string) {
  const tree = await parse(markdownContent)

  return tree
}

See Also

Copyright © 2026