Comark: Parse and Render Markdown Anywhere

Comark gives JavaScript applications one Markdown pipeline for standards-based parsing, serializable documents, multiple renderers, plugins, and streaming.

Markdown won the authoring war. It is readable, portable, widely supported, and understood by both humans and machines. The remaining challenge is everything that happens after authoring: parsing it reliably, transforming it as data, rendering it to different targets, and displaying it while content is still arriving.

Comark provides one JavaScript library for that complete Markdown pipeline.

Why Markdown?

Every piece of web content serves two audiences:

  • Humans who need scannable prose
  • Machines who need predictable structure

HTML is powerful but verbose. That verbosity costs even more in an era where AI agents pay per token. JSON is structured but no one wants to write a blog post in it.

Markdown occupies rare middle ground. The source text is comfortable prose for a human author and token-efficient structured data for a machine consumer. That convergence wasn't part of Gruber's original design. He was solving for readability in 2004. But it explains why Markdown has become the default format for both human authoring and AI consumption.

Why Machines Prefer Markdown

The evidence is clearest in token economics.

The same page served as HTML versus Markdown to an AI agent can use 80% fewer tokens in Markdown form. At scale, that is not a formatting preference, it is an infrastructure decision. Lower token counts mean faster responses, lower costs, and longer effective context windows.

Beyond token count, Markdown's explicit structure maps cleanly to how language models reason. A ## heading is unambiguously a section boundary. HTML carries the same information buried in <h2 class="..."> but the signal-to-noise ratio is far worse.

AI as a First-Class Audience

The tooling industry has converged on this conclusion. Streamdown (an open-source renderer by Hayden Bleasel, DX Engineer at Vercel) was built precisely because LLMs stream token by token and existing renderers like react-markdown assume a complete document, making them unable to handle unterminated blocks gracefully. Because LLMs tend to produce Markdown by default, Streamdown is a React component designed to render it correctly as chunks arrive, pairing naturally with useChat and other streaming patterns from @ai-sdk/react. Together they reflect a deliberate recognition that AI agents are now a primary consumer of content, not a secondary one (Comark vs Streamdown).

The same shift is visible in developer tooling. Files like AGENTS.md and .cursorrules are Markdown documents that configure AI coding assistants. GitHub Copilot reads them across sessions. Cursor injects them into every prompt. Claude Code uses CLAUDE.md. The format that humans write is the same format that machines act on.

This is new. For most of computing history, human-authored content and machine-readable configuration were different artifacts in different formats. Markdown is collapsing that boundary.

Why Comark?

The JavaScript ecosystem has excellent Markdown parsers and renderers, but most tools solve only one part of the pipeline. A renderer may be tied to one UI framework. A build-time compiler may not accept content from a database or live API. A conventional parser may assume the document is complete, which causes broken formatting during an AI stream.

Comark separates these concerns. It parses Markdown into a shared document model, lets you transform or store that document, and renders it through the output package you choose. The same API works at build time or runtime, on the server or in the browser, and with complete or streaming input.

Built on markdown-it Foundations

Comark supports CommonMark and GitHub Flavored Markdown (GFM) through markdown-exit, a TypeScript rewrite of markdown-it that preserves its plugin API. Existing Markdown stays familiar, and existing markdown-it plugins can work alongside Comark plugins.

This foundation gives Comark a mature parsing model without limiting how or where the parsed document is rendered.

Markdown as Data, Not Code

parseMarkdown(markdown) returns a compact, serializable MarkdownDocument. Text stays as strings, elements use tuples such as ['tag', props, ...children], and plugins can attach structured metadata.

That shared document boundary enables a complete content pipeline:

  1. A file, database, CMS, or API provides the raw Markdown
  2. On request, the server runs parseMarkdown(markdown) and gets the MarkdownDocument object
  3. Your application inspects, transforms, caches, or sends the document as JSON
  4. An HTML, ANSI, Vue, React, Svelte, or Angular renderer produces the final output

You can parse once and render many times without coupling stored content to a framework or build pipeline.

You can store the MarkdownDocument directly in the database to skip re-parsing on every request.

One Source, Every Renderer

Most Markdown rendering libraries are designed around one output target. Comark decouples parsing from rendering so the same source can produce:

Your content outlasts your output target and framework choice.

Streaming Is Part of the Parser

AI models emit Markdown token by token, but conventional parsers expect complete documents. Comark's auto-close support completes unterminated emphasis, links, code fences, and component blocks so each intermediate frame renders correctly.

Framework renderers expose streaming directly, while the core parser lets any integration opt into the same behavior. You can display content as soon as it arrives without maintaining a separate streaming syntax or renderer.

Extend Markdown Without Embedding Code

Standard Markdown does not express a warning callout, tabbed code group, video embed, or pricing card. Raw HTML can represent them, but it adds verbosity and couples content to markup. MDX allows executable JSX, but it also makes content part of a framework-specific build pipeline (full comparison).

Comark keeps extensions in readable plain text. Its component syntax is inspired by the Markdown directives proposal and builds on more than five years of production use in MDC:

::alert{type="warning"}
This action cannot be undone.
::

A human can read the source, while the parser sees a component named alert with a type attribute and text content. The renderer only instantiates components registered by the application, so content remains data rather than executable code.

Attributes provide the same plain-text approach for adding classes, IDs, styles, and metadata to standard Markdown elements. Both extensions are available when you need them; plain CommonMark and GFM continue to work unchanged.

First-Class Slots

Components can accept rich Markdown in named regions. #slotname markers let you compose full Markdown into each slot without falling back to HTML or framework templates:

::hero
#title
Build UIs from **Markdown**

#description
Comark parses component syntax at runtime: no compiler, no rebuild.
Renders to HTML, ANSI, Vue, React, Svelte, and Angular.

#cta
[Get started](/getting-started)
::

This is still Markdown. Readable in a text editor, parseable by a machine, renderable by any framework.


Markdown gives humans and machines a shared language. Comark gives that language one pipeline: parse once, render anywhere, and stream in real time.