Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![CI](https://github.com/microsoft/flint-chart/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/flint-chart/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

**Please visit:** [**Flint Project Site**](https://microsoft.github.io/flint-chart/) | [**MCP Server Guide**](https://microsoft.github.io/flint-chart/#/mcp)
**Please visit:** [**Flint Project Site**](https://microsoft.github.io/flint-chart/) | [**MCP Server Guide**](https://microsoft.github.io/flint-chart/#/mcp) | [**中文主页**](https://microsoft.github.io/flint-chart/#/zh)

Flint is a visualization intermediate language that lets **AI agents create
expressive, polished visualizations from simple, human-editable chart specs**.
Expand Down
23 changes: 12 additions & 11 deletions agent-skills/flint-chart-author/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,15 @@ properties"). Required channels are noted.
| `"Ranged Dot Plot"` | x, y, color | dumbbell of two x per category |
| `"Strip Plot"` | x, y, color, size, column, row | jittered points; props `stepWidth`, `pointSize`, `opacity` |
| `"Bar Chart"` | x, y, color, opacity, column, row | one discrete + one measure; prop `cornerRadius` |
| `"Grouped Bar Chart"` | x, y, group, column, row | `group` = the clustering category |
| `"Grouped Bar Chart"` | x, y, group, column, row | `group` = the clustering category; prop `dodge` |
| `"Stacked Bar Chart"` | x, y, color, column, row | prop `stackMode` |
| `"Pyramid Chart"` | x, y, color | diverging horizontal bars |
| `"Lollipop Chart"` | x, y, color, column, row | prop `dotSize` |
| `"Waterfall Chart"` | x, y, color, column, row | `color` = Type column, values `start`/`delta`/`end` only; omit it for auto sign coloring; props `cornerRadius`, `totals` |
| `"Gantt Chart"` | y, x, x2, color, detail, column, row | x = start, x2 = end |
| `"Bullet Chart"` | y, x, goal, color, column, row | `goal` required (target) |
| `"Histogram"` | x, color, column, row | x = measure to bin; prop `binCount` |
| `"Boxplot"` | x, y, color, opacity, column, row | category + measure; props `whiskerMethod`, `showOutliers` |
| `"Boxplot"` | x, y, color, opacity, column, row | category + measure; props `whiskerMethod`, `showOutliers`, `dodge` |
| `"ECDF Plot"` | x, color, detail, column, row | x = measure; cumulative distribution (step line); prop `showPoints` |
| `"Heatmap"` | x, y, color, column, row | color = the measure |
| `"Line Chart"` | x, y, color, strokeDash, detail, opacity, column, row | props `interpolate`, `showPoints` |
Expand All @@ -199,11 +199,11 @@ properties"). Required channels are noted.
| `"Slope Chart"` | x, y, color, detail, column, row | two-period value change; straight segments + end points, one line per category |
| `"Area Chart"` | x, y, color, opacity, column, row | props `interpolate`, `opacity`, `stackMode` |
| `"Range Area Chart"` | x, y, y2, color, column, row | x + y + y2 required; translucent band from `y` (low) to `y2` (high), value axis fits the band (not zero) |
| `"Violin Plot"` | x, y, color, row | x (category) + y (measure) required; mirrored KDE density per category, prop `bandwidth`; **Vega-Lite only**; `column` is used internally for the per-category panels |
| `"Violin Plot"` | x, y, color, row | x (category) + y (measure) required; mirrored KDE density per category, prop `bandwidth`; **Vega-Lite only**; a genuine `color` subgroup splits two groups or grids 3+ groups |
| `"Streamgraph"` | x, y, color, column, row | centre-stacked areas |
| `"Density Plot"` | x, color, column, row | prop `bandwidth` |
| `"Pie Chart"` | size, color, column, row | `size` = slice value (→ angle), `color` = category |
| `"Rose Chart"` | x, y, color, column, row | polar bars; props `alignment`, `innerRadius`, `padAngle` |
| `"Pie Chart"` | size, color, column, row | `size` = slice value (→ angle), `color` = category; props `innerRadius`, `sortSlices` |
| `"Rose Chart"` | x, y, color, column, row | polar bars; props `alignment`, `padAngle`, `sortSlices` |
| `"Radar Chart"` | x, y, color, column, row | props `filled`, `fillOpacity`, `strokeWidth` |
| `"Candlestick Chart"` | x, open, high, low, close, column, row | OHLC all required |
| `"Bar Table"` | y, x, color, column, row | compact bars + value labels |
Expand All @@ -218,10 +218,9 @@ category on `x` (or `y`) plus one measure. They differ in how a **second**
category is shown — and each reads that second category from a **different
channel**:

- `"Bar Chart"` — no second category. One bar per `x` value. A `color`
encoding just tints the bars (or stacks segments if multiple rows share an
`x`). It has **no `group` channel**, so a `group` encoding is silently
ignored.
- `"Bar Chart"` — use for a single series. When multiple rows share an `x`, a
second category on `color` produces stacked segments. For side-by-side bars,
use `"Grouped Bar Chart"` with the second category on `group`.
- `"Stacked Bar Chart"` — second category on `color`, drawn as **stacked**
segments within each bar (totals matter). Tune with `stackMode`
(`stacked` / `normalize` / `layered`).
Expand Down Expand Up @@ -344,7 +343,8 @@ derived). Values are clamped to the ranges shown.
| Chart type | Property | Type / range (default) | Effect |
|---|---|---|---|
| Bar Chart | `cornerRadius` | 0–15 (0) | Round bar corners (px) |
| Bar / Area / Stacked Bar | `stackMode` | `stacked` \| `normalize` \| `layered` (unset) | Stacking behavior; `normalize` = 100% |
| Area / Stacked Bar | `stackMode` | `stacked` \| `normalize` \| `center` \| `layered` (unset) | Stacking behavior; `normalize` = 100%, `center` = streamgraph |
| Grouped Bar / Boxplot | `dodge` | `auto` \| `local` \| `global` (`auto`) | `local` compacts sparse groups per category; `global` preserves aligned group lanes; leave `auto` unless the user requests one |
| Line / Area / Sparkline | `interpolate` | `linear` \| `monotone` \| `step` \| `step-before` \| `step-after` \| `basis` \| `cardinal` \| `catmull-rom` (`linear`) | Curve shape |
| Line / ECDF Plot | `showPoints` | boolean (false) | Draw point markers on the line |
| Sparkline | `baseline` | `mean` \| `zero` \| `median` \| `none` (`mean`) | Reference line per spark row |
Expand All @@ -359,12 +359,13 @@ derived). Values are clamped to the ranges shown.
| Histogram | `binCount` | 5–50 (10) | Number of bins |
| Density Plot | `bandwidth` | 0.05–2 (0=auto) | Kernel bandwidth |
| Pie Chart | `innerRadius` | 0–100 (0) | Donut hole size (>0 → donut) |
| Pie / Rose | `sortSlices` | `none` \| `descending` \| `ascending` (`none`) | Order wedges and their legend by slice value |
| Rose Chart | `alignment` | `left` \| `center` (`left`) | Wedge alignment |
| Rose Chart | `innerRadius` | 0–100 (0) | Inner radius |
| Rose Chart | `padAngle` | 0–0.1 (0) | Gap between slices |
| Lollipop | `dotSize` | 20–300 (80) | Circle size (px) |
| Waterfall | `cornerRadius` | 0–8 (0) | Round bar corners |
| Waterfall | `totals` | `auto` \| `none` \| `first` \| `last` \| `both` (`auto`) | Which bars anchor to zero as totals (only when no Type column) |
| Waterfall | `showTextLabels` | boolean (false) | Render value labels on bars |
| Regression | `regressionMethod` | `linear` \| `log` \| `exp` \| `pow` \| `quad` \| `poly` (`linear`) | Fit method |
| Regression | `polyOrder` | 1–5 (3) | Polynomial order (when `poly`) |
| Radar | `filled` | boolean (true) | Fill the polygon |
Expand Down
2 changes: 1 addition & 1 deletion docs/reference-vegalite.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ The **Availability** column shows whether a parameter is `always` available or `

### ![](chart-icon-column.svg) Bar Chart

**Encoding channels:** `x`, `y`, `color`, `group`, `opacity`, `column`, `row`
**Encoding channels:** `x`, `y`, `color`, `opacity`, `column`, `row`

| Parameter | Control | Domain | Default | Availability | Description |
|---|---|---|---|---|---|
Expand Down
72 changes: 72 additions & 0 deletions docs/zh-CN/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 开发指南

使用本页在本地搭建 **flint-chart**、运行常用检查,并在需要添加新能力时找到合适的扩展路径。

## 前置条件

- Node 18+(见 [`packages/flint-js/.nvmrc`](../packages/flint-js/.nvmrc);若使用 nvm,请运行 `nvm use`)
- npm 9+(workspaces)

## 首次设置

```bash
git clone https://github.com/microsoft/flint-chart
cd flint-chart
npm install # root workspace: packages/flint-js, packages/flint-mcp, site
```

## 日常命令

在**仓库根目录**运行以下命令:

| 命令 | 作用 |
|---------|----------------|
| `npm run typecheck` | 构建/类型检查 `packages/flint-js`,并对 `packages/flint-mcp` 做类型检查 |
| `npm run test` | 在 `packages/flint-js` 和 `packages/flint-mcp` 中运行 Vitest |
| `npm run build` | 构建 `packages/flint-js` 和 `packages/flint-mcp` |
| `npm run site` | 演示站点,地址 http://localhost:5274/ |
| `npm run site:build` | 生产构建 → `site/dist/` |
| `npm run build:mcp` | 构建 MCP 服务器 workspace |

演示站点通过 Vite 将 `flint-chart` 别名指向 `packages/flint-js/src`,因此库代码的修改会在画廊和编辑器中热重载,无需重新构建 `dist/`。

## 仓库结构

```
flint-chart/
├── packages/
│ ├── flint-js/ npm package `flint-chart`
│ │ ├── src/core/ semantics, layout, types
│ │ ├── src/vegalite/ Vega-Lite backend
│ │ ├── src/echarts/ ECharts backend
│ │ ├── src/chartjs/ Chart.js backend
│ │ └── src/test-data/ gallery fixtures
│ ├── flint-py/ Python port preview (PyPI package planned later)
│ └── flint-mcp/ npm package `flint-chart-mcp`
├── site/ landing, gallery, editor, docs browser
├── docs/ architecture + site documentation sources
├── agent-skills/ AI agent skill (SKILL.md)
└── shared/test-data/ JSON fixtures (JS + Python)
```

## 图表组装流程

1. **Phase 0 — 语义解析**(`packages/flint-js/src/core/resolve-semantics.ts`)
2. **Phase 1 — 布局**(`packages/flint-js/src/core/compute-layout.ts`)
3. **Phase 2 — 实例化**(各后端的 `assemble.ts` + templates)

完整流程见 [Architecture](/documentation/architecture)。

## 扩展指南

根据你要扩展的层面选择对应指南:

- [Extending chart templates](/documentation/adding-a-chart-template) — 在现有后端中添加新图表类型。
- [Extending semantic types](/documentation/adding-a-semantic-type) — 让 Flint 识别新的字段含义,从而改变格式化、聚合、比例尺或颜色行为。
- [Extending backends](/documentation/adding-a-backend) — 添加消费共享编译器输出的新渲染目标。

## 测试覆盖

- **冒烟测试:** `packages/flint-js/tests/smoke.test.ts`
- **视觉覆盖:** [Gallery](/gallery),由 test-data 中的 `TEST_GENERATORS` 驱动
- **共享 fixtures:** `shared/test-data/`,供 JS 与 Python 测试共用
138 changes: 138 additions & 0 deletions docs/zh-CN/adding-a-backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# 扩展后端

当 Flint 需要面向新的渲染库或 spec 格式时,添加后端。后端是 `assemble<Backend>(input)` 编排器加上 `templates/` 注册表;二者共同将共享编译器输出转换为原生图表 spec。现有参考实现位于 `packages/flint-js/src/` 下的 `vegalite/`、`echarts/` 和 `chartjs/`。

流水线阶段与仓库结构见 [Architecture](/documentation/architecture)。

---

## 目录

- [§1 创建骨架](#1-创建骨架)
- [§2 遵循组装契约](#2-遵循组装契约)
- [§3 添加模板](#3-添加模板)
- [§4 接入包](#4-接入包)
- [§5 站点与画廊](#5-站点与画廊)
- [§6 验收清单](#6-验收清单)
- [§7 相关文档](#7-相关文档)

---

# §1 创建骨架

```
packages/flint-js/src/<backend>/
├── index.ts # public barrel
├── assemble.ts # 编排入口:ChartAssemblyInput → 后端配置
├── instantiate-spec.ts # encoding + layout → spec (optional; some backends inline this)
├── recommendation.ts # chart-type recommendations (optional)
└── templates/
├── index.ts # category map + getTemplateDef()
├── bar.ts
├── line.ts
└── …
```

从零开始前,先复制最接近的现有后端。Vega-Lite 是共享流水线最完整的参考;ECharts 额外包含 `colormap.ts` 和 `facet.ts` 以处理后端特定关注点。

---

# §2 遵循组装契约

```typescript
function assemble<Backend>(input: ChartAssemblyInput): <BackendSpec>
```

`ChartAssemblyInput` 定义于 `packages/flint-js/src/core/types.ts`,包含 `data`、`chart_spec`、`semantic_types`、`options` 及相关字段。

### 流水线(不要跳过 core 阶段)

编排器**协调** `core/`,不应从原始字段类型重新推导格式、零基线或颜色。

```text
PRE-PHASE normalizeStaticSeries(), applyEncodingOverrides()
(may need a preliminary resolveChannelSemantics for types)

PHASE 0 resolveChannelSemantics() → Record<channel, ChannelSemantics>
computeZeroDecision() per quantitative x/y (needs template mark)
chartProperties overrides (includeZero_*, logScale_*, …)

STEP 0a template.declareLayoutMode?.() → LayoutDeclaration

STEP 0b convertTemporalData()

STEP 0c computeChannelBudgets() + filterOverflow()

PHASE 1 computeLayout() → LayoutResult

PHASE 2 build backend encodings
template.instantiate(spec, InstantiateContext)
apply layout (vlApplyLayoutToSpec / ecApplyLayoutToSpec / …)
postProcess?, tooltips, facet combine
```

规范顺序见 `packages/flint-js/src/vegalite/assemble.ts`(文件头 + `assembleVegaLite`)。

**IR 边界:** 下游代码读取扁平的 `ChannelSemantics` 和 `LayoutResult`,而不是重新检查语义类型字符串。

---

# §3 添加模板

模板编码**形状**,而非**决策**。若模板需要按 `field.type === 'temporal'` 分支,应将该逻辑移到 `core/`。

每个模板导出一个 `ChartTemplateDef`(`core/types.ts`):

| 字段 | 作用 |
|---|---|
| `chart` | 显示名称 — 必须与 `chart_spec.chartType` 一致 |
| `template` | 原生 spec 骨架(mark + encoding 结构) |
| `channels` | 允许的编码槽位 |
| `markCognitiveChannel` | `position` / `length` / `area` / `color` — 驱动零基线与压缩 |
| `declareLayoutMode?` | 布局前的轴标志(banded vs continuous、σ 覆盖) |
| `instantiate` | 根据 `InstantiateContext` 修改 spec(encodings、layout、semantics) |
| `properties?` | 可配置的图表属性 |
| `postProcess?` | 布局后的最终视觉微调 |

在 `templates/index.ts` 中注册:导入 defs,加入 category map,并暴露 `*GetTemplateDef(chartType)` 为 `find(t => t.chart === chartType)`。

---

# §4 接入包

1. **Barrel** — 在 `packages/flint-js/src/index.ts` 中 `export * from './<backend>'`
2. **Bundle** — 在 `packages/flint-js/tsup.config.ts` 中添加 `<backend>/index` 入口
3. **Exports** — 在 `packages/flint-js/package.json#exports` 中添加 `"./<backend>"` 子路径
4. **冒烟测试** — 在 `packages/flint-js/tests/smoke.test.ts` 中扩展一条 `assemble<Backend>()` 形状断言
5. **Gallery 数据** — 在 `src/test-data/` 中添加 `gen<Backend>*Tests()`,并在 `TEST_GENERATORS` 中注册

---

# §5 站点与画廊

- **Gallery 开发服务器:** 在仓库根目录运行 `npm run site`,然后打开 `/gallery`
- **Supported backends:** 若新后端应出现在 UI 中,更新 `site/src/shared/supported-backends.ts`
- **Renderers:** 仅当 spec 格式无法复用 `VegaLiteView`、`EChartsView` 或 `ChartjsView` 时,才添加新的 React 视图(`site/src/components/`)。`TripleChart` 当前覆盖 VL + ECharts + Chart.js。

可选:若 MCP 客户端应能调用该组装器,将其接入 `agent-skills/mcp-server/`。

---

# §6 验收清单

后端就绪的标志:

- [ ] Bar、line、area 和 scatter 模板在标准 gallery 矩阵上渲染正确
- [ ] `tests/smoke.test.ts` 对新组装器通过
- [ ] 仓库根目录的 `npm run typecheck` 和 `npm run test` 通过
- [ ] 至少有一个专用 test-data 生成器覆盖后端特定选项

**对等说明:** 并非每个 `chart` 名称目前在各后端都存在。记录你移植了哪些模板;跨后端对等是目标,而非首次合并的前置条件。

---

# §7 相关文档

- [Extending chart templates](/documentation/adding-a-chart-template) — `ChartTemplateDef` 编写
- [Auto Layout Algorithm](/documentation/layout-model) — `computeLayout()` 的期望输入
- [API reference](/documentation/api-reference) — `ChartAssemblyInput` 与组装器入口
Loading
Loading