Skip to content

Spec

Tiny versioned chart language for Markdown. Source is tabular data. Path: fence | GFM table | HTML comment → parser → Chart IR → deterministic SVG (table always kept). Tags chart, markvis, vis share one parser. No JSON-as-default. No JS in the fence.

Aligned with repo root SPEC.md on branch v2. Agents that need a short brief should fetch /llms.txt.

Grammar

Order inside a fence:

  1. Optional markvis: 2
  2. Header fields, one key: value per line
  3. Blank line
  4. Data: CSV or one GFM table (header row required)
md
```chart
markvis: 2
type: bar
title: Feb led Q3 at 180
unit: USD k
x: month
y: revenue

month,revenue
Jan,120
Feb,180
Mar,150
```

Also valid under markvis or vis fences.

Progressive form — comment immediately followed by a GFM table:

md
<!-- chart: bar x=month y=revenue title="Feb led Q3 at 180" -->
| month | revenue |
| --- | --- |
| Jan | 120 |
| Feb | 180 |
| Mar | 150 |

Comment keys: type (required), x, y, title, unit, series, theme, palette. Same meaning as fence headers.

Fields

FieldRequiredDefaultNotes
markvisno2Language version.
typeyesbar | line | area | scatter | pie | hist only.
titlenoderivedConclusion title when present.
themenofolioGrammar only: folio | highcharts | shadcn | docs | ant | recharts.
palettenotheme defaultColors only: ink | porcelain | warm | cool | vivid. Omit → theme pack colors.
unitnoDisplay suffix for values.
xtypedfirst category / numeric colIndependent axis or labels.
ytypedfirst numeric colMeasure.
seriesnoOptional column that splits series.
datayesCSV or GFM after a blank line.

x / y / series must name real header columns.

Types

TypexyseriesRules
barcategorynumberoptional → groupedKeep input row order. Never sort x.
lineordered category or numbernumberoptional → multi-lineKeep input row order.
areasame as linenumberoptionalFill under line(s).
scatternumbernumberoptionalOne mark per row.
pielabelnumber ≥ 0ignoredDo not normalize to 100.
histnumberoptional weightignoredRenderer bins; table keeps raw rows.

Fallback

  1. Never drop recovered rows.
  2. Emit a table of those rows plus one line with the stable error code.
  3. Valid HTML: figure → SVG + figcaption + data table.
  4. Same IR → same SVG bytes.

Error codes

CodeWhen
E_UNKNOWN_TYPEtype not in the six.
E_TYPE_TYPONear-miss spelling of a known type.
E_JSON_DATAData body is JSON.
E_MISSING_HEADERNo CSV/GFM header row.
E_EMPTY_DATAHeader only, or zero data rows.
E_EXTRA_COLUMNRow width ≠ header width.
E_DUP_COLUMNDuplicate header names.
E_UNKNOWN_FIELDx / y / series name a missing column.
E_PIE_NEGATIVEPie value < 0.
E_YAML_TABLE_CONFLICTHeader fields disagree with progressive table mapping.
E_EMPTY_FENCEFence body empty.
E_UNKNOWN_THEMEtheme not in the allowed set.
E_UNKNOWN_PALETTEpalette not in ink | porcelain | warm | cool | vivid.

Themes

Optional theme: selects a named grammar pack. See Themes. Unknown → E_UNKNOWN_THEME with table fallback.

Optional palette: selects colors only (ink · porcelain · warm · cool · vivid). Omit → theme pack default colors. Unknown → E_UNKNOWN_PALETTE with table fallback. Never merge palette into the theme id.

Pipeline diagrams live in repo docs/architecture.md (architecture, parse/render workflow, package structure). This page stays prose so public sources stay free of competitor diagram fences.

0.0.13 lives under legacy/