2.0 Migration Guide

Move a 1.x integration to the Comark parser and optional extension packages.

Version 2.0 replaces the mdast pipeline with Comark, renders its compact document directly, and moves large rendering runtimes behind optional extensions. The Markdown component and its core display options remain familiar, but parser customization and rich-renderer configuration have changed.

Parser return value

When using @markmend/parser directly, parse() returns the document and streaming completion information as one result. Replace direct document access on the parse result:

// Before
const document = await parser.parse(markdown)

// 2.0
const { document, completion } = await parser.parse(markdown)

getDocument() continues to return the latest successfully parsed document. Custom completion functions may continue returning a string, or return { markdown, completion } to describe the syntax they completed.

Package changes

The main package remains:

pnpm add vue-stream-markdown

Install rich renderers separately:

pnpm add @stream-markdown/code
pnpm add @stream-markdown/math
pnpm add @stream-markdown/mermaid
pnpm add @stream-markdown/beautiful-mermaid

Package changes:

  • @markmend/ast is replaced by @markmend/parser.
  • @stream-markdown/html is removed; native HTML and custom tags are supported by the main package.
  • Beautiful Mermaid is no longer bundled with @stream-markdown/mermaid.
  • Shiki, KaTeX, Mermaid, and Beautiful Mermaid types come from their corresponding extension packages.

Configure rich renderers

In 1.x, provider configuration was passed directly to Markdown:

<Markdown
  :shiki-options="shikiOptions"
  :katex-options="katexOptions"
  :mermaid-options="mermaidOptions"
  :cdn-options="cdnOptions"
/>

In 2.0, create extension instances and pass them through extensions:

<script setup lang="ts">
import { beautifulMermaid } from '@stream-markdown/beautiful-mermaid'
import { code } from '@stream-markdown/code'
import { math } from '@stream-markdown/math'
import { mermaid } from '@stream-markdown/mermaid'

const extensions = {
  code: code({ theme: ['github-light', 'github-dark'] }),
  math: math(),
  beautifulMermaid: beautifulMermaid(),
  mermaid: mermaid(),
}
</script>

<template>
  <Markdown :content="content" :extensions="extensions" />
</template>

When both diagram extensions are configured, supported diagrams use Beautiful Mermaid and other diagram types fall back to Mermaid.

Replace parser APIs

1.x2.0
mdastOptionsparserOptions
Markmend preprocessing hookscompletion / completionSteps
nodeRenderers keyed by mdast node typecomponents keyed by HTML/Comark tag
components for shared UI controlsuiComponents
getMarkdownParser()Removed
getParsedNodes()getDocument()
getProcessedContent()Removed

The removed lifecycle hooks include normalize, preprocess, parseMarkdownIntoBlocks, postnormalize, and postprocess. Use completion for a complete custom function or completionSteps to replace selected built-in steps. The built-in completion functions are now exported with a complete* prefix (for example, completeLink and completeMath) and are also available through defaultCompletionSteps.

Custom completion

<script setup lang="ts">
function completion(markdown: string) {
  return markdown.endsWith('**') ? markdown : markdown + '**'
}
</script>

<template>
  <Markdown :content="content" :completion="completion" />
</template>

Completion runs only in streaming mode. Static mode parses the original source.

To keep the default pipeline and replace one rule, pass a partial step map:

import { completeLink } from 'vue-stream-markdown'

const completion = {
  completionSteps: {
    link: (markdown, context) => completeLink(markdown, context),
  },
}

Comark plugins

<script setup lang="ts">
import myPlugin from './my-comark-plugin'

const parserOptions = {
  plugins: [myPlugin()],
}
</script>

<template>
  <Markdown :content="content" :parser-options="parserOptions" />
</template>

Replace custom renderers

In 1.x, nodeRenderers received mdast-oriented nodes. In 2.0, map the emitted tag name directly:

<script setup lang="ts">
import CustomHeading from './custom-heading.vue'
import GitHubCard from './github-card.vue'

const components = {
  h2: CustomHeading,
  github: GitHubCard,
}
</script>

<template>
  <Markdown :content="content" :components="components" />
</template>

The same mapping handles native Markdown elements and custom HTML-like tags.

For shared controls such as Button, move UI replacements from the 1.x components prop to uiComponents:

<Markdown :ui-components="{ Button: CustomButton }" />

For direct renderer reuse:

1.x2.0
NODE_RENDERERSNamed renderers, such as CodeBlockRenderer and LinkRenderer.
UI.CodeBlock / UI.TableContent overrides through components, with CodeBlockRenderer / TableRenderer for built-in behavior.
NodeListMarkdownNodes, with Comark nodes instead of mdast nodes.

Custom renderers now receive a Comark element tuple as node, plus nodeKey and loading. Forward these props when reusing a built-in renderer. MarkdownNodes uses nodes for its child list; the old deep, blocks, and nodeRenderers props are removed. See Components for props and examples.

Share configuration across messages

MarkdownProvider can supply extensions and theme defaults to a message list:

<MarkdownProvider :extensions="extensions">
  <Markdown
    v-for="message in messages"
    :key="message.id"
    :content="message.content"
  />
</MarkdownProvider>

An individual Markdown can override a provider value when one message needs different behavior.

Migration checklist

  • Install only the rich-renderer packages your application uses.
  • Move Shiki, KaTeX, Mermaid, and CDN options into extension factories.
  • Replace mdastOptions with parserOptions or completion.
  • Move content overrides to tag-based components and shared-control replacements to uiComponents.
  • Replace parsed-node access with getDocument().
  • Remove @stream-markdown/html and any mdast compatibility code.
  • Import katex/dist/katex.min.css when loading KaTeX locally.
  • Test custom tags, security rules, streaming-to-static transitions, and extension fallbacks.
© 2026 Vue Stream Markdown.