---
title: "Comark vs marked"
description: "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."
canonical_url: "https://comark.dev/compare/comark-vs-marked"
---
# 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](https://github.com/markedjs/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

|                              | Comark                                                                                                                   | marked                                                           |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| Output                       | `MarkdownDocument`, then HTML, framework components, or ANSI                                                             | HTML string, or tokens from `marked.lexer()`                     |
| Spec compliance              | CommonMark and GFM with [documented differences](https://comark.dev/syntax/markdown#differences-from-commonmark-and-gfm) | Reports near-complete CommonMark and GFM compliance              |
| Size                         | Larger, includes markdown-exit, a YAML parser, and an HTML parser                                                        | Small, zero dependencies                                         |
| API                          | Async, `parseMarkdown()` and `renderHtml()` return promises                                                              | Sync by default, `async: true` option                            |
| Custom components in content | Yes, `::alert{type="info"}`                                                                                              | No, renderers return strings                                     |
| Incomplete Markdown          | [`autoClose`](https://comark.dev/reference/auto-close) completes the syntax                                              | No handling                                                      |
| Sanitization                 | [Security plugin](https://comark.dev/plugins/built-in/security)                                                          | None, the docs recommend DOMPurify                               |
| Extensions                   | Comark plugins and [markdown-it plugins](https://comark.dev/plugins/custom/markdown-it)                                  | `marked.use()` with renderer, tokenizer, hooks, and `walkTokens` |
| CLI                          | No                                                                                                                       | Yes                                                              |

## 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](https://comark.dev/getting-started/document-model) between parsing and rendering. You can store, cache, transform, or send the document before you render it.

::code-group
```ts [marked]
import { marked } from 'marked'

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

```ts [Comark]
import { renderHtml } from '@comark/html'

const html = await renderHtml('# 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](https://comark.dev/syntax/components). With `@comark/html`, each component is an async function that returns a string:

```ts
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](https://comark.dev/use-cases/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`:

```ts
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](https://comark.dev/syntax/markdown#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

::accordion
  :::accordion-item{label="Is Comark faster than marked?"}
  This page doesn't compare speed. Comark does more work per document, such as frontmatter, components, and the conversion to its document model. If speed is your main criterion, measure both with your own content. To render many documents with Comark, create the renderer once with `createHtmlRenderer()`.
  :::

  :::accordion-item{label="Can I keep my marked extensions?"}
  No. marked extensions use the marked API. Comark accepts markdown-it plugins and its own [plugin API](https://comark.dev/plugins/custom/plugin-api). Check that each extension you rely on has an equivalent before you switch.
  :::

  :::accordion-item{label="Does Comark render the same HTML as marked?"}
  Not always. Comark adds an `id` to every heading, and some constructs differ, such as shortcut reference links, tight and loose lists, and unterminated emphasis. Set `autoClose: false` for static content that must follow the spec.
  :::

  :::accordion-item{label="When does the extra size of Comark pay off?"}
  It pays off when you render the same content in several places. Examples are server HTML plus a Vue or React client, AI streaming, or components that authors write in Markdown.
  :::
::

---

- [Render to HTML](https://comark.dev/rendering/html)
- [Playground](https://comark.dev/play)


## Sitemap

See the full [sitemap](https://comark.dev/sitemap.md) for all pages.
