Safe, streaming-ready charts for Markdown.
Turn strict JSON code fences into interactive ECharts visualizations and responsive KPI cards.
English · 简体中文
markdown-chart is a small, framework-friendly toolkit for rendering charts
inside Markdown—including Markdown that is still streaming from an AI or data
application. It keeps data inspectable, chart specifications portable, and
renderer code outside your Markdown pipeline.
- Built for streaming Markdown. Completed chart fences render immediately and stay mounted while the rest of the document continues to arrive.
- Inspectable by default. Canonical data is separate from the renderer specification, enabling a built-in Chart/Data switch and bounded data table.
- Safe for generated content. Document input is strict JSON—never executable JavaScript—and is protected by schema, size, and option limits.
- Works with your stack. Use the ready-made React + react-markdown or Vue 3
- markdown-it components, or integrate the framework-neutral core.
- Charts and KPIs. ECharts table, graph, and hierarchy charts plus responsive multi-KPI cards are included as independent renderers.
- Extensible without lock-in. Register another renderer, resolve application-owned data references, or handle reference clicks in the host.
pnpm add echarts @datafe-open/markdown-chart-reactimport { MarkdownChart } from '@datafe-open/markdown-chart-react';
const source = `## Monthly sales
\`\`\`markdown-chart
{
"version": 1,
"renderer": "echarts",
"data": {
"kind": "inline",
"dimensions": ["month", "sales"],
"source": [["Jan", 100], ["Feb", 180], ["Mar", 260]]
},
"spec": {
"xAxis": { "type": "category" },
"yAxis": {},
"series": [{ "type": "bar", "encode": { "x": "month", "y": "sales" } }]
}
}
\`\`\``;
export function Report() {
return <MarkdownChart source={source} />;
}The component configures react-markdown plus the ECharts and KPI renderers. If your application already owns the Markdown parser or renderer registry, use the advanced React example instead.
pnpm add echarts @datafe-open/markdown-chart-vue<script setup lang="ts">
import { MarkdownChart } from '@datafe-open/markdown-chart-vue';
defineProps<{ source: string; streaming?: boolean }>();
</script>
<template>
<MarkdownChart :source="source" :streaming="streaming" />
</template>The Vue component configures markdown-it plus the same built-in renderers. See the simple and advanced examples for complete runnable apps.
Use renderer: "echarts" with renderer-neutral data and a strict JSON
ECharts spec. Explicit ECharts values win over the presentation defaults.
Inline data—and referenced data returned by your resolver—automatically gets a
Chart/Data switch.
Use data.shape: "graph" for canonical nodes/links rendered as Sankey or
relationship graphs, and data.shape: "hierarchy" for canonical children
rendered as tree, treemap, or sunburst. The renderer maps that one source into
ECharts while the shared card exposes Nodes/Links or flattened hierarchy data.
Structured series never duplicate facts in series.data or series.links.
Use renderer: "kpi" for a responsive group of 1–12 metrics. KPI items can
bind values from shared or named datasets, format numbers with structured
Intl.NumberFormat options, display semantic status, draw line or area
sparklines, and expose optional host-owned references.
```markdown-chart
{
"version": 1,
"renderer": "kpi",
"data": {
"kind": "inline",
"source": [
{ "day": "2026-09-01", "conversion": 0.38, "revenue": 16800000 },
{ "day": "2026-09-02", "conversion": 0.42, "revenue": 18000000 }
]
},
"spec": {
"timeField": "day",
"items": [
{
"id": "conversion",
"title": "Conversion",
"value": { "field": "conversion", "format": { "style": "percent" } },
"trend": { "type": "area", "compare": { "lag": 1, "mode": "absolute" } }
},
{
"id": "revenue",
"title": "Revenue",
"value": {
"field": "revenue",
"format": { "style": "currency", "currency": "CNY", "notation": "compact" }
}
}
]
}
}
```Pass the outer document state while tokens are arriving:
<MarkdownChart source={source} streaming={isStreaming} /><MarkdownChart :source="source" :streaming="isStreaming" />Closed fences render as soon as they are complete. Only the active, unterminated tail fence waits for more input, and pending parsing, data resolution, or runtime mounting shows a built-in loading state.
Canonical data can be inline or an opaque reference such as
dataset://forecast. The library never chooses a transport or fetches that
reference itself: the host validates it and provides a resolver. KPI reference
controls follow the same boundary—the renderer forwards an opaque event, while
the host decides whether and how to open it.
This keeps application data access, authorization, navigation, and domain protocols outside the public renderer.
The ECharts renderer defaults to at most 100,000 rows, 1,000,000 cells, and
1,200,000 JSON nodes. Legacy ChatBI CSV adapters additionally allow up to
64 MiB and 200 columns. These budgets target narrow-table trends resolved through
data.kind: "ref" or a host adapter; the core Markdown fence remains bounded
separately and is not intended to carry 100,000 inline rows. Hosts with tighter
resource budgets can lower any renderer limit through
createEChartsRenderer({ limits }).
Core separately bounds structured data to 2,000 nodes, 4,000 graph links, and
20 hierarchy levels by default. Configure these registry budgets with
new ChartRendererRegistry({ dataLimits: { ... } }); ECharts-specific table
row/cell limits retain their existing behavior.
| Package | Purpose |
|---|---|
@datafe-open/markdown-chart |
Framework-neutral registry, canonical parser, data view, and lifecycle controller |
@datafe-open/markdown-chart-echarts |
Strict JSON ECharts renderer |
@datafe-open/markdown-chart-kpi |
Responsive multi-KPI renderer |
@datafe-open/markdown-chart-markdown-it |
markdown-it placeholder plugin and environment channel |
@datafe-open/markdown-chart-react |
React + react-markdown component and adapter |
@datafe-open/markdown-chart-vue |
Vue 3 + markdown-it component and composable |
- Protocol specification
- Security model and supported ECharts profile
- Runnable examples
- React package guide
- Vue package guide
- Release process
pnpm install
pnpm test
pnpm typecheck
pnpm build
pnpm check:packIssues and pull requests are welcome. Published-package changes use Changesets; the root build also validates all React and Vue examples.
MIT. Portions are adapted from Qwen Code under Apache-2.0; see Third-party notices.
