2.10.0
中文
Skip to content

Examples ​

Used to render the streamed Markdown returned by LLM. The following is arranged according to the @ant-design/x-markdown@2.10.0 “Code Examples.” Each one represents a capability already implemented in Vue.

The editable preview is at Online Experience, using the same input box as the basic usage.

Basic usage ​

Hello World

Welcome to XMarkdown!

  • Item 1
  • Item 2
  • Item 3
const a = 1;
Basic usage

Basic Markdown rendering. Edits in the textarea redraw immediately.

Streaming handling ​

Status: idle
Streaming handling

Feed incomplete content chunk by chunk, then turn streaming off.

Using plugins ​

plugin

Ship the TODO before Friday.

Using plugins

plugins’s transform rewrites the string before marked. Formulas, highlighting, and Mermaid see the corresponding plugin pages.

Custom components ​

Custom Blue Title

Normal H2

Paragraph with bold and italic.

Custom components

components maps tags to its own Vue components.

LaTeX ​

Pythagoras: .

LaTeX

Latex plugin.

Code highlighting ​

A fenced block picks up the language class:

ts
export const answer = 42;

Inline const x = 1 stays a plain code tag.

Code highlighting

HighlightCode。

Mermaid ​

```mermaid
graph TD
  A[Start] --> B[Answer]
```
Mermaid

When the fence language is mermaid, it is handled by Mermaid.

Theme ​

Theme sample

Body text with a link.

  • one
  • two

Theme sample

Body text with a link.

  • one
  • two
Theme

light / dark class names.

Custom tokenizer ​

Level 1 Heading

Level 2 Heading

Level 3 Heading

Level 4 Heading

Custom tokenizer

Uses marked extensions to parse % headings into heading elements.

Token handling with walkTokens ​

Please check: Invalid link

Token handling with walkTokens

Uses config.walkTokens to rewrite or intercept tokens.

Pre-render handling with renderer ​

🚀 Render Code Text

<html><form><button>Test</button><form></html>
Pre-render handling with renderer

Custom marked renderer, then with components replacing tags.

Untreated

Treated

Chinese link handling

When a bare URL is followed by Chinese text or parentheses, truncate the link and keep the suffix.

XSS defense ​

Cross-Site Scripting (XSS) Attack Vectors

1. Stored XSS (Persistent XSS)

2. Reflected XSS (Non-persistent XSS)

Malicious Link)

3. DOM-based XSS

4. Attribute-based XSS

5. Script Tag Injection

6. Event Handler XSS

Test Image

7. JavaScript Protocol XSS

Click Here

8. SVG Vector XSS

9. Form Input XSS

10. CSS Injection XSS

Test Content

11. Data URI XSS

12. Mouse Event XSS

Hover over this text

13. Button Tag XSS

14. Nested script evasion

XSS defense

DOMPurify strips dangerous scripts, event attributes, and javascript: links.

Streaming syntax ​

Markdown Source
Click Re-Render to start
Rendered Output
Streaming syntax

Incomplete links and tables use placeholders instead of half-parsed Markdown.

Streaming animation ​

Streaming animation

streaming.enableAnimation makes newly appearing paragraphs fade in.

openLinksInNewTab enabled

Open links in a new tab

Reference link

This is a reference-style link.

Default (same tab)

Open links in a new tab

Reference link

This is a reference-style link.

Open links in a new tab

openLinksInNewTab adds target="_blank" to links.

Thinking process ​

Check the constraint, then answer.

The answer is 42.

Thinking process

Hand a custom tag to Think.

API ​

PropDescriptionTypeDefault
contentMarkdown content to be renderedstring-
childrenMarkdown content, alias of contentstring-
componentsReplace HTML/custom tags with custom Vue components, see Component Overview for detailsRecord\<string, Component\>-
paragraphTagThe HTML tag used by the paragraph. When a custom component contains block-level elements, it can be changed to div to avoid illegal nestingstring'p'
streamingStreaming rendering configuration, see Streaming syntaxboolean | StreamingOption-
configmarked parsing and extension configurationMarkedExtension{ gfm: true }
pluginsCompatible with old writing methods: objects with transform(content) will rewrite the string before parsing; use config + marked extensions firstany[]-
openLinksInNewTabWhether to add target="_blank" (and rel="noopener noreferrer") to all a tagsbooleanfalse
dompurifyConfigDOMPurify configuration for HTML disinfection and XSS protectionDOMPurify.Config-
componentsPropsPass additional props to custom components in components according to tag names to keep component references stable and avoid repeated mounting caused by inline functionsRecord\<string, Record\<string, unknown\>\>-
protectCustomTagNewlinesWhether to protect blank line segments inside custom tags to prevent paragraph segmentation from destroying the tag structurebooleanfalse
disableCustomTagBlockMarkdownWhether disabled block-level Markdown parsing (list, title, quote, etc.) within custom tags; inline Markdown still takes effectbooleanfalse
escapeRawHtmlWhether to escape the original HTML in Markdown into plain text for display (not parsed into real HTML) to prevent XSS while retaining the contentbooleanfalse
debugEnable the FPS / memory performance overlay (development only)booleanfalse
disableDefaultStylesWhether to turn off the default style of built-in tags. true closes all, the array is closed by label (such as ['ul', 'ol', 'li']), used to avoid default styles from polluting internal elements of custom componentsboolean | Array<'p' | 'ul' | 'ol' | 'li' | 'pre' | 'code' | 'table' | 'th' | 'td' | 'img' | 'hr'\>false
classNameRoot node additional CSS class namestring-
rootClassNameAlias of classNamestring-
styleRoot inline styleCSSProperties-
prefixClsCSS Override class prefixstring-

StreamingOption ​

PropDescriptionTypeDefault
hasNextChunkWhether there is another chunk after it. Refresh the cache and complete rendering when falsebooleanfalse
enableAnimationEnable text fade-in for block-level elements (p, li, h1–h4)booleanfalse
animationConfigText appearance animation configurationAnimationConfig{ fadeDuration: 200, easing: 'ease-in-out' }
incompleteMarkdownComponentMapCustom component name corresponding to incomplete syntax. When streaming output encounters unclosed links, tables, HTML, etc., you can wrap the fragments with placeholder/loading componentsPartial\<Record\<Exclude\<StreamCacheTokenType, 'text'\>, string\>\>{}

AnimationConfig ​

PropDescriptionTypeDefault
fadeDurationFade-in animation duration (milliseconds)number200
easingeasing functionstring'ease-in-out'

ComponentProps ​

Customize the input parameters received by the components mapping component:

PropDescriptionTypeDefault
domNodeParsed DOM node information (tag name, attributes, child node structure)DOMNode-
streamStatusStreaming status: loading means the block is still outputting, done means it has been closed. Currently mainly covers HTML and fenced code; indented code blocks have no explicit end marker and are always done. code can also read data-state'loading' | 'done'-
blockOnly for code: block-level code when data-block="true"boolean-
childrenContent wrapped by the componentVNode[] | string-
OthersStandard HTML attributes (href, title, class / className, etc.) and custom data-*Record\<string, any\>-

StreamCacheTokenType ​

Consistent with the source code StreamCacheTokenType enum (note it is html, not heading / xml from the old document):

ts
type StreamCacheTokenType =
  | 'text' // 纯文本
  | 'link' // 链接 [text](url)
  | 'image' // 图片 ![alt](src)
  | 'html' // HTML / 自定义标签 <tag>
  | 'emphasis' // 强调 *斜体* **粗体**
  | 'list' // 列表 - + *
  | 'table'; // 表格 | header | content |

When hasNextChunk is true, unfinished tokens will be converted to incomplete-<token> (can be renamed using incompleteMarkdownComponentMap), and the original text is stored in data-raw (encodeURIComponent). text does not generate placeholder tags.

FAQ ​

Difference between components and config marked extensions ​

config marked extensions (parser extensions) ​

extensions in config take effect in the Markdown → HTML phase:

  • Phase: Markdown parsing
  • Purpose: Identify and transform special syntax
  • Example: Convert footnote syntax [^1] into <footnote>1</footnote>
  • Use case: Extend Markdown syntax
ts
const footnoteExtension = {
  name: 'footnote',
  level: 'inline',
  start(src) {
    return src.match(/\[\^/)?.index;
  },
  tokenizer(src) {
    const rule = /^\[\^([^\]]+)\]/;
    const match = rule.exec(src);
    if (match) {
      return {
        type: 'footnote',
        raw: match[0],
        text: match[1],
      };
    }
  },
  renderer(token) {
    return `<footnote>${token.text}</footnote>`;
  },
};

// <XMarkdown content="脚注示例[^1]" :config="{ extensions: [footnoteExtension] }" />

components (component replacement) ​

components replaces tags with Vue components during the HTML → VNode stage:

  • Stage: Rendering
  • Function: Replaces HTML/custom tags
  • Example: Replaces <footnote>1</footnote> with a clickable footnote component
  • Scenario: Custom styles and interactions

See full example in Custom Plugin.