Comark vs marked

marked compiles Markdown to an HTML string with zero dependencies. Comark parses Markdown into a serializable document with components and streaming, then renders it to HTML, frameworks, or the terminal.

TL;DR: marked is a fast, small Markdown compiler with zero dependencies. It turns Markdown into an HTML string and follows the CommonMark and GFM specifications closely. Comark parses Markdown into a serializable document with components, then renders that document to HTML, Vue, React, Svelte, Angular, or the terminal. If you only need an HTML string and want the smallest dependency, use marked.

At a glance

Comarkmarked
OutputMarkdownDocument, then HTML, framework components, or ANSIHTML string, or tokens from marked.lexer()
Spec complianceCommonMark and GFM with documented differencesReports near-complete CommonMark and GFM compliance
SizeLarger, includes markdown-exit, a YAML parser, and an HTML parserSmall, zero dependencies
APIAsync, parseMarkdown() and renderHtml() return promisesSync by default, async: true option
Custom components in contentYes, ::alert{type="info"}No, renderers return strings
Incomplete MarkdownautoClose completes the syntaxNo handling
SanitizationSecurity pluginNone, the docs recommend DOMPurify
ExtensionsComark plugins and markdown-it pluginsmarked.use() with renderer, tokenizer, hooks, and walkTokens
CLINoYes

Compiler or document model

marked is a compiler: Markdown goes in, and an HTML string comes out. You can change the output with renderer overrides, but the result is always a string.

Comark puts a document model between parsing and rendering. You can store, cache, transform, or send the document before you render it.

import { marked } from 'marked'

const html = marked.parse('# Hello **world**')

Both calls return <h1> HTML. Comark adds an id to every heading by default. To keep the document instead of a string, call parseMarkdown() from comark and render it later with renderHtmlFromDocument().

Components in the content

marked has no syntax for components that aren't HTML elements. Authors write raw HTML, or you add a custom extension with its own tokenizer.

Comark includes component syntax. With @comark/html, each component is an async function that returns a string:

import { renderHtml } from '@comark/html'

const html = await renderHtml('::alert{type="warning"}\nCheck your **API key**.\n::', {
  components: {
    alert: async ([, attrs, ...children], { render }) =>
      `<div class="alert alert-${attrs.type}">${await render(children)}</div>`,
  },
})

The same Markdown renders with Vue, React, Svelte, or Angular components when you switch renderers.

Streaming

marked expects complete input. An unterminated **bold in a partial LLM response renders as literal asterisks until the closing syntax arrives.

Comark closes unterminated syntax on every parse. Its framework renderers also have a streaming prop for token-by-token output. See AI chat streaming.

Security

marked doesn't sanitize its output. Its documentation recommends that you filter the HTML with a library such as DOMPurify.

Comark doesn't create a link from Markdown link syntax with a javascript:, vbscript:, or data:text/html URL. It keeps raw HTML, attributes, and component props as written. For untrusted input, add the security plugin. It removes event handlers and unsafe URLs, and drops the tags that you list in blockedTags:

import { renderHtml } from '@comark/html'
import security from '@comark/html/plugins/security'

const html = await renderHtml(userContent, {
  plugins: [security({ blockedTags: ['script', 'iframe', 'object', 'style'] })],
})

What marked does well

  • Size and dependencies: marked has zero dependencies. Comark is larger, and its async API adds a promise to every render.
  • Spec compliance: marked publishes its test results against CommonMark and GFM. Comark changes some output on purpose, for example with autoClose and span syntax. See Differences from CommonMark and GFM.
  • Extension model: renderer and tokenizer overrides in marked.use() are small and direct.
  • CLI: you can convert files from the command line without writing code.

If you convert trusted, complete Markdown to HTML and don't need components, streaming, or framework rendering, marked is the smaller tool.

FAQ

© 2026 Vercel, Inc.