
X Markdown
- 5 installs
- 71 repo stars
- Updated August 4, 2026
- antdv-next/x
x-markdown (antdv-next) is a Claude Code skill for rendering Markdown with the @antdv-next/x-markdown Vue package, including streaming LLM output, custom component mapping, plugins, and themes.
About
This skill covers rendering Markdown with the @antdv-next/x-markdown Vue package, including streaming LLM output. A developer uses it to render assistant replies chunk-by-chunk, map custom tags to business components, add plugins or themes, and handle incomplete syntax safely. It sits at the render layer after @antdv-next/x and @antdv-next/x-sdk have produced the message data.
- Renders Markdown with @antdv-next/x-markdown, including LLM streaming chunks
- Handles incomplete syntax recovery via hasNextChunk and streamStatus
- Covers custom component mapping, plugins, themes, and safe HTML defaults
X Markdown by the numbers
- 5 all-time installs (skills.sh)
- Ranked #1,790 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
x-markdown capabilities & compatibility
- Capabilities
- markdown rendering · streaming adapter · ai chat ui
- Use cases
- frontend
What x-markdown says it does
This skill focuses on one job**: render Markdown correctly and predictably with `@antdv-next/x-markdown`.
Use `streaming.hasNextChunk = false` on the final chunk, otherwise incomplete placeholders will not flush into final content.
npx skills add https://github.com/antdv-next/x --skill x-markdownAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 71 |
| Last updated | August 4, 2026 |
| Repository | antdv-next/x ↗ |
What it does
Render streaming Markdown from an LLM inside an @antdv-next/x Vue chat UI.
Who is it for?
Rendering streaming LLM Markdown replies inside an @antdv-next/x Vue chat UI
Skip if: Managing chat state or adapting APIs, which the x-chat-provider and use-x-chat skills handle
When should I use this skill?
You need to render Markdown, especially streaming chunks, in an Antdv Next X chat interface
What you get
Predictable Markdown rendering that recovers incomplete streaming syntax
- Streaming Markdown renderer configuration
- Custom component map for tags
By the numbers
- Four-step recommended workflow from core render to extensions
Files
🎯 Skill Positioning
This skill focuses on one job: render Markdown correctly and predictably with @antdv-next/x-markdown.
It covers:
- Basic rendering and package boundaries
- LLM streaming output and incomplete syntax handling
- Custom component mapping for rich chat or data-display blocks
- Plugins, themes, and safe rendering defaults
Table of Contents
- 📦 Package Boundaries
- 🚀 Quick Start Decision Guide
- 🛠 Recommended Workflow
- 🚨 Development Rules
- 🤝 Skill Collaboration
- 🔗 Reference Resources
📦 Package Boundaries
| Layer | Package | Responsibility |
|---|---|---|
| UI layer | @antdv-next/x | Chat UI, bubble lists, sender, rich interaction components |
| Data layer | @antdv-next/x-sdk | Providers, requests, streaming data flow, state management |
| Render layer | @antdv-next/x-markdown | Markdown parsing, streaming rendering, plugins, themes, custom renderers |
⚠️x-markdownis not a chat-state tool. Use it to render content after@antdv-next/xand@antdv-next/x-sdkhave already produced the message data.
🚀 Quick Start Decision Guide
| If you need to... | Read first | Typical outcome |
|---|---|---|
| Render Markdown with the smallest setup | CORE.md | XMarkdown renders trusted content with basic styling |
| Render LLM streaming chunks | STREAMING.md | Correct hasNextChunk, placeholders, tail indicator, loading states |
| Replace tags with business components | EXTENSIONS.md | Stable components map for custom tags and code blocks |
| Add plugins or theme overrides | EXTENSIONS.md | Plugin imports, theme class wiring, minimal CSS overrides |
| Check prop details and defaults | API.md | Full prop table for XMarkdown and streaming options |
🛠 Recommended Workflow
1. Start with CORE.md and get a plain render working first. 2. Add STREAMING.md only when the content arrives chunk-by-chunk. 3. Add EXTENSIONS.md when you need custom tags, plugins, syntax blocks, or themes. 4. Use API.md to confirm prop names and defaults instead of guessing.
Minimal Setup Reminder
import { XMarkdown } from "@antdv-next/x-markdown";
export default () => <XMarkdown content="# Hello" />;🚨 Development Rules
- Prefer a stable
componentsobject. Do not create new inline component mappings on every render. - Use
streaming.hasNextChunk = falseon the final chunk, otherwise incomplete placeholders will not flush into final content. - Treat raw HTML carefully. Prefer
escapeRawHtmlwhen raw HTML should stay visible as text. - If raw HTML must be rendered, keep
dompurifyConfigexplicit and minimal. - Keep theme overrides small. Start from
x-markdown-lightorx-markdown-darkand override only the variables you need. - If a custom component depends on complete syntax, branch on
streamStatus === 'done'.
🤝 Skill Collaboration
| Scenario | Recommended skill combination | Why |
|---|---|---|
| Rich assistant replies in chat | x-chat-provider → x-request → use-x-chat → x-markdown | Provider and request handle data flow, x-markdown handles final rendering |
| Built-in provider with Markdown replies | x-request → use-x-chat → x-markdown | Keep request config and rendering concerns separate |
| Standalone Markdown page or docs viewer | x-markdown only | No chat data flow needed |
Boundary Rules
- Use `x-chat-provider` when adapting an API shape.
- Use `x-request` when configuring transport, auth, retries, or streaming separators.
- Use `use-x-chat` when managing chat state in Vue.
- Use `x-markdown` when the content itself needs Markdown parsing, streaming recovery, or rich component rendering.
🔗 Reference Resources
- CORE.md - Package boundaries, install/setup, safe defaults, common render patterns
- STREAMING.md - Chunked rendering, incomplete syntax recovery, loading vs done behavior
- EXTENSIONS.md - Components, plugins, themes, custom tag guidance
- API.md - Generated API reference from the official
x-markdowndocs
Official Docs
| Property | Description | Type | Default |
|---|---|---|---|
| content | Markdown content to render | string | - |
| children | Markdown content (use either content or children) | string | - |
| components | Map HTML nodes to custom Vue components | `Record<string, Component \ | keyof HTMLElementTagNameMap>` |
| streaming | Streaming behavior config | StreamingOption | - |
| config | Marked parse config, applied last and may override built-in renderers | `MarkedExtension` | { gfm: true } |
| rootClassName | Extra CSS class for the root element | string | - |
| className | Extra CSS class for the root container | string | - |
| paragraphTag | HTML tag for paragraphs (avoids validation issues when custom components contain block elements) | keyof HTMLElementTagNameMap | 'p' |
| style | Inline styles for the root container | CSSProperties | - |
| prefixCls | CSS class name prefix for component nodes | string | - |
| openLinksInNewTab | Add target="_blank" to all links so they open in a new tab | boolean | false |
| dompurifyConfig | DOMPurify config for HTML sanitization and XSS protection | `DOMPurify.Config` | - |
| protectCustomTagNewlines | Whether to preserve newlines inside custom tags | boolean | false |
| escapeRawHtml | Escape raw HTML in Markdown as plain text (do not parse as real HTML), to prevent XSS while keeping content visible | boolean | false |
| debug | Enable debug mode (performance overlay) | boolean | false |
StreamingOption
| Field | Description | Type | Default |
|---|---|---|---|
| hasNextChunk | Whether more chunks are expected. Set false to flush cache and finish rendering | boolean | false |
| enableAnimation | Whether to enable fade-in animation for block elements | boolean | false |
| animationConfig | Animation options (for example fade duration and easing) | AnimationConfig | - |
| tail | Enable tail indicator | `boolean \ | TailConfig` |
| incompleteMarkdownComponentMap | Map incomplete Markdown fragments to custom loading components | `Partial<Record<'link' \ | 'image' \ |
TailConfig
| Property | Description | Type | Default |
|---|---|---|---|
| content | Content to display as tail | string | '▋' |
| component | Custom tail component, takes precedence over content | Component | - |
AnimationConfig
| Property | Description | Type | Default |
|---|---|---|---|
| fadeDuration | Duration in ms | number | 200 |
| easing | CSS easing function | string | 'ease-in-out' |
Related Docs
- Component Extension
- Streaming
Core Guide
Package Boundaries
| Need | Package |
|---|---|
| Render message content as Markdown | @antdv-next/x-markdown |
| Build chat UI containers | @antdv-next/x |
| Manage provider/request/message state | @antdv-next/x-sdk |
Install and Minimal Render
npm install @antdv-next/x-markdownimport { XMarkdown } from "@antdv-next/x-markdown";
const content = `
# Hello
- item 1
- item 2
`;
export default () => <XMarkdown content={content} />;Safe Defaults
- Use
contentorchildren, not both. - Start with plain Markdown before adding plugins or custom components.
- Use
openLinksInNewTabwhen model output may contain external links. - Use
escapeRawHtmlwhen raw HTML should remain visible but should not execute. - If real HTML rendering is required, explicitly review
dompurifyConfig.
Common Integration Patterns
Basic content block
<XMarkdown content={message} className="x-markdown-light" />Chat message rendering
Render plain text or Markdown from message data after useXChat has already produced the message list.
<XMarkdown content={message.message.content} openLinksInNewTab escapeRawHtml />Minimal checklist
- Confirm the content is actually Markdown, not a structured component schema.
- Keep rendering concerns out of Provider classes.
- Keep transport concerns out of
XMarkdown. - Add themes and custom components only after basic rendering works.
When to Read Other References
- Read STREAMING.md when content arrives incrementally from an LLM.
- Read EXTENSIONS.md when you need custom tags, code blocks, plugins, or themes.
- Read
API.mdfor the full prop tables.
Extensions Guide
Components
components is the main extension point. Use it to map Markdown or custom HTML tags to Vue components.
import { Mermaid, Sources, Think } from "@antdv-next/x";
import { XMarkdown } from "@antdv-next/x-markdown";
<XMarkdown
content={content}
components={{
mermaid: Mermaid,
think: Think,
sources: Sources,
}}
/>;Rules for component mappings
- Keep the mapping object stable across renders.
- Use
streamStatusto separate temporary loading UI from final rendering. - If a custom component contains block children, consider
paragraphTagto avoid invalid nested markup. - Keep custom tags semantically clear and avoid ambiguous mixed Markdown/HTML blocks.
Plugins
Built-in plugins are imported from @antdv-next/x-markdown/plugins/... and wired through config.
import Latex from "@antdv-next/x-markdown/plugins/Latex";
<XMarkdown
content={content}
config={{
extensions: Latex(),
}}
/>;Use a plugin when the syntax extension belongs in parsing, not when it is only a visual replacement of a rendered node.
Themes
Start from a built-in theme stylesheet.
import "@antdv-next/x-markdown/themes/light.css";
<XMarkdown className="x-markdown-light" content={content} />;For customization:
1. Keep the built-in theme class. 2. Add one custom class. 3. Override only the CSS variables you actually need.
Custom Tag Guidance
- Keep custom tag blocks well formed.
- Avoid stray blank lines inside custom HTML blocks unless the syntax is intentional.
- If newlines inside custom tags matter, review
protectCustomTagNewlines.
Pick the Right Tool
- Use
componentsfor replacing rendered nodes with Vue components. - Use plugins for parsing new syntax.
- Use themes for typography, spacing, and color.
- Use
dompurifyConfigandescapeRawHtmlfor safety, not for visual customization.
Streaming Guide
When to Use
Use streaming mode when the Markdown content is appended chunk-by-chunk and may temporarily contain incomplete syntax.
Typical examples:
- partial links like
[docs](https://example - partial tables
- unfinished code fences
- a tail cursor while the assistant is still generating
Core Rule
hasNextChunk must reflect reality:
truewhile more chunks are expectedfalsefor the final chunk so cached incomplete fragments flush into the final render
Minimal Streaming Setup
<XMarkdown
content={content}
streaming={{
hasNextChunk,
enableAnimation: true,
tail: true,
}}
/>Incomplete Syntax Handling
Use incompleteMarkdownComponentMap when unfinished fragments should show custom loading UI instead of broken Markdown.
<XMarkdown
content={content}
streaming={{
hasNextChunk,
incompleteMarkdownComponentMap: {
link: "link-loading",
table: "table-loading",
},
}}
components={{
"link-loading": LinkSkeleton,
"table-loading": TableSkeleton,
}}
/>Loading vs Done
Custom components receive streamStatus:
loading: syntax may still be incompletedone: final content is available
Use this to delay expensive parsing or API calls until the syntax is complete.
Chat-Oriented Guidance
- Use a tail indicator only while the assistant is still generating.
- Keep placeholder components lightweight.
- If a component depends on a closed block or fenced payload, wait for
streamStatus === 'done'. - Do not keep
hasNextChunkstuck attrue, or the final Markdown will never settle.
Debugging Checklist
- Final chunk still looks incomplete: confirm
hasNextChunkbecomesfalse. - Placeholder never disappears: confirm the mapped tag name exists in
components. - Performance looks unstable: disable animation and placeholder components first, then add them back selectively.
Related skills
FAQ
How do I flush incomplete streaming placeholders?
Set streaming.hasNextChunk to false on the final chunk, otherwise incomplete placeholders will not flush into final content.
How is raw HTML handled?
Prefer escapeRawHtml to keep raw HTML visible as text; if it must render, keep dompurifyConfig explicit and minimal.