免费

账本图表包

用你的真实数据生成可直接粘贴的图表,像账本一样工整好看,不依赖任何图表库,每个数字都算得清。

安装

把“账本图表包”技能安装到 ~/.claude/skills/ledger-charts。
下载下面每个文件,保存到这个文件夹:
https://skilllift.pages.dev/packs/ledger-charts/SKILL.zh.md → SKILL.md
https://skilllift.pages.dev/packs/ledger-charts/references/style.md → references/style.md
https://skilllift.pages.dev/packs/ledger-charts/assets/tokens.css → assets/tokens.css
https://skilllift.pages.dev/packs/ledger-charts/assets/page.css → assets/page.css
https://skilllift.pages.dev/packs/ledger-charts/assets/ledger-charts.js → assets/ledger-charts.js
https://skilllift.pages.dev/packs/ledger-charts/assets/react/LedgerChart.jsx → assets/react/LedgerChart.jsx
https://skilllift.pages.dev/packs/ledger-charts/assets/vue/LedgerChart.vue → assets/vue/LedgerChart.vue
https://skilllift.pages.dev/packs/ledger-charts/assets/sample-data.json → assets/sample-data.json
https://skilllift.pages.dev/packs/ledger-charts/scripts/check.mjs → scripts/check.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/make.mjs → scripts/make.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/page.mjs → scripts/page.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/lib-build.mjs → scripts/lib-build.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/recolour.mjs → scripts/recolour.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/stress.mjs → scripts/stress.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/drive.mjs → scripts/drive.mjs
https://skilllift.pages.dev/packs/ledger-charts/scripts/paste-test.mjs → scripts/paste-test.mjs
然后读一遍 SKILL.md,告诉我它是做什么的,并提醒我开一个新会话。

解压到 ~/.claude/skills

同一个技能,不同的需求

左边是预览。右边由另一个 Agent 按不同需求制作,它只有安装好的技能,没看过预览。

预览
预览
新需求,由另一个 Agent 制作
新需求,由另一个 Agent 制作

这是按虚构需求做的一次测试。系统字体不同时,字形可能略有差异。

把真实的 CSV 或 JSON 数据变成可直接粘贴的数据图表,不依赖任何图表库,适用于普通 HTML、React 和 Vue,风格是会计账本,并带夜间主题。动手前先按问题选出如实的图表形式(趋势、比较、部分与整体、分布、流程或漏斗、日历活动、详细表格),并说明理由。每张图的数值都是精确算出来的,都支持键盘操作、悬停详情和读屏数据表。当用户要可粘贴到页面的图表、仪表盘、KPI 行、热力图、漏斗图、瀑布图或数据表,或直接点名这个风格时使用。

交付前必须通过

  • check.mjs 打印了 OK,并且确实运行了浏览器检查
  • 用一句话说明了选用的形式及理由
  • statement.txt 里是一句真实的话
  • 每张图都在 1280、768、390 宽度下看过
  • 亲手试过悬停、键盘和“查看明细数字”
  • 列出了推断内容和假设
  • 示例数据已标为虚构,或没有使用
  • 颜色只存在于 tokens 文件
阅读完整 SKILL.md
---
name: ledger-charts
description: 把真实的 CSV 或 JSON 数据变成可直接粘贴的数据图表,不依赖任何图表库,适用于普通 HTML、React 和 Vue,风格是会计账本,并带夜间主题。动手前先按问题选出如实的图表形式(趋势、比较、部分与整体、分布、流程或漏斗、日历活动、详细表格),并说明理由。每张图的数值都是精确算出来的,都支持键盘操作、悬停详情和读屏数据表。当用户要可粘贴到页面的图表、仪表盘、KPI 行、热力图、漏斗图、瀑布图或数据表,或直接点名这个风格时使用。
version: 1.0.0
---

# 账本图表包

样式都在引擎和 tokens 文件里。你负责提供真实数据、问题和文字,不要手绘图表,也不要改 `assets/ledger-charts.js`。`scripts/check.mjs` 看的是渲染后的结果,读者能看出来的毛病,它都会拦下。

精确的 token 和规则见 `references/style.md`。

## 需要询问的内容

需求里没给的,一次性在一条消息里问清。

必需:
1. 真实数据:CSV 或 JSON 文件,或直接粘贴的数据行。
2. 图表要回答的问题,一句话。
3. 技术栈:普通 HTML、React 或 Vue。

可选:单位、来源、小数位、页面语言、日间或夜间主题、配色。

## 步骤

一页要回答多个问题时,看“整页答案”一节。只做一张图时:

1. 把数据存成文件,然后运行:
   `node scripts/make.mjs --data data.csv --question "……" --stack html --out out [--unit "$"] [--source "……"] [--lang zh]`
   问题决定任务,任务决定图表形式。它会打印任务、形式和理由,把理由用一句话告诉用户。
2. 如果打印的任务不是问题要问的,用 `--job` 传下面七个值之一,并说明原因。如果 `make.mjs` 拒绝绘制,就改用它指定的形式。
3. 打开 `out/spec.json`,填写 `title`,用 `names` 改掉原始列名,按“怎么写那句话”写好 `statement`。然后用 `node scripts/make.mjs --spec out/spec.json --stack html --out out` 重新生成,任务和理由保存在 spec 里,不会丢。
4. 运行 `node scripts/check.mjs out/chart.html`,按报告修改,直到打印 OK。一个页面只要几秒。
5. 按正常尺寸亲眼看。在 1280、768、390 三种宽度打开 `usage.html`,每张图都要看。运行 `node scripts/drive.mjs out/usage.html --shots shots`,它还会实测悬停、键盘和明细数字。要证明粘贴后不受宿主页面样式影响,运行 `node scripts/paste-test.mjs --chart out/chart.html --out paste`。
6. 交付下面的文件。`chart.html` 要整段粘贴。

如果 `check.mjs` 找不到 Playwright:运行 `npm install playwright` 和 `npx playwright install chromium`,或把 `NODE_PATH` 指向含有它的 `node_modules`。没有它,渲染检查就没跑过,不能说已检查。

## 七种任务

| `--job` | 问题在问 | 对应的形式 |
|---|---|---|
| `trend` | 随时间如何变化 | `lines`、`multiples`、`summary` |
| `comparison` | 哪个最多、最少、最好或更大 | `ranked`、`paired`、`slope` |
| `part` | 一个整体如何拆分,钱花到哪里 | 带分段条的 `ranked`、`stacked` |
| `distribution` | 数值如何分布,或两个指标是否一起变化 | `histogram`、`scatter` |
| `flow` | 每个阶段还剩多少,或一步步走到期末数 | `funnel`、`waterfall` |
| `calendar` | 哪些日子活跃 | `calendar` |
| `table` | 哪些记录,或各列合计多少 | `records`、`sheet` |

最高级优先于时间词:“哪个月卖得最多?”属于 `comparison`,所以按月排名。如果问题里看不出任务,就由数据形状决定,`why.txt` 会写明;不对就传 `--job`。

## 怎么写那句话

这句话是读者最先读到的。要用问题自己的说法来回答问题:

- 说出对象,用问题里的动词,给出精确数字,再加一个最要紧的比较。如:“红茶卖得最好,4,210,占总销量 12,920 的 32.6%。”
- 趋势要说出走势:“营收到九月前都在 1,980 到 2,800 之间,之后一路升到十二月的 4,800。”
- 不要写成“标签加冒号”(如“First: Black at 4,210”),`check.mjs` 会拒绝。
- 最多 160 字符。每个数字都必须能从这张图的数据算出,`check.mjs` 会重新计算。
- 需求单薄时:不填 `statement`,引擎会写一句正确但较平淡的话。它不知道问题里的动词,所以能写就自己写。

## 整页答案

超过一个问题,或要的是一个页面而不是粘贴片段时,用页面路线,不要手工拼页面。运行 `node scripts/page.mjs --page page.json --out out`,再运行 `node scripts/check.mjs out/page.html`。

```json
{
  "title": "榅桲与茶壶:全年销售",
  "subtitle": "一行背景说明",
  "lang": "zh",
  "theme": "ledger",
  "fictional": true,
  "dataFile": "data.json",
  "notes": ["只给了十二月的成本。"],
  "charts": [
    { "question": "哪种茶卖得最好?", "from": "sales_by_tea", "job": "comparison", "x": "tea", "y": "sales",
      "statement": "红茶卖得最好,4,210,占总销量 12,920 的 32.6%。" }
  ]
}
```

它会生成带背景和主题的账本页面、日夜切换按钮、顶部的答案账目(问题、那句话、关键数字),以及所有图表,并把同一行的图表拉平到同样高度。手机上,答案账目在第一屏内放得下,`check.mjs` 会实测。

| 页面字段 | 含义 | 限制 | 需求信息不足时 |
|---|---|---|---|
| `title` | 这是什么页面 | 60 | 用用户对它的称呼。必填。 |
| `subtitle` | 一行背景说明 | 90 | 不填。 |
| `theme` | `ledger`、`night` 或 `auto`,作用于整页 | | 不填即日间。 |
| `fictional` | 给页面和每张图盖上虚构章 | true | 只用于虚构数字。 |
| `notes` | 读者不能错过的事:数据缺口、表与表之间对不上 | 每条 160;数字会被检查 | 只写真实存在的缺口。 |
| `dataFile` | CSV 或 JSON 文件,路径相对于 page.json | | 也可以给每张图 `data`。 |
| `charts[].from` | JSON `dataFile` 中的表名 | | |
| `charts[].span` | 占 12 列中的几列 | 4 到 12 | 不填:1 张图占 12,3 张各占 4,其余各占 6。 |
| `charts[].key` | `{ "label", "value" }`,账目里的关键数字 | 数字会被检查 | 不填,由引擎选择。 |
| `charts[].answer` | `false` 表示不进入答案账目 | 账目最多 4 行 | 辅助图表不要进账目。 |

下面的图表字段也都可以写在单张图上。如果两张表对同一件事的数字对不上,写进 `notes` 并问用户,不要自己调和。如果问题只能部分回答,就回答这部分,并在 `notes` 或图表的 `note` 里说明缺什么。

如要手工设置页面主题:在 `<html>` 上加 `data-lc-theme`,在 `<body>` 上加 `class="lc-page"`,内联 `tokens.css` 和 `assets/page.css`,再调用 `LedgerCharts.alignRows()`。

## 交付物

- 可读的源码:`ledger-charts.js`,不用图表库,没有依赖;另加 `react/LedgerChart.jsx` 或 `vue/LedgerChart.vue`。
- 可运行的用法示例:`usage.html`、`react/Usage.jsx` 或 `vue/Usage.vue`。
- 一个 tokens 文件:`tokens.css`。
- `statement.txt`:一句话说明这张图显示了什么。
- `why.txt`:选了什么形式、为什么。可粘贴的整段代码:`chart.html`。页面则是 `page.html` 和 `statements.txt`。

## 选择形式

| 数据要回答的 | 形式(`kind`) | 容量 | 无法如实呈现时 |
|---|---|---|---|
| 当前的一个数值 | `summary` | 最多 6 个指标 | 超过 6 个:用 `multiples` |
| 趋势 | `lines` | 最多 4 条序列,500 个点也可以 | 超过 4 条:用 `multiples` |
| 分组趋势 | `multiples` | 2 到 24 个面板,同一比例尺 | 1 个面板:`lines`;超过 24 个:`ranked` |
| 比较两三个指标 | `paired` | 2 或 3 个指标,最多 24 个类别 | 超过 24 个:`ranked`;超过 100 个:`lines` |
| 比较各类别 | `ranked` | 一个指标,最多 100 行,印出占比;超过 40 行时尾部并入有标注的“其他” | 超过 100 行:`histogram` |
| 比较两个时点 | `slope` | 恰好 2 列,最多 14 项 | 超过 14 项:`ranked` |
| 多个整体的部分与整体 | `stacked` | 2 到 4 个部分,最多 24 根柱 | 超过 4 个部分:`multiples`;只有 1 个部分:`events` |
| 一个整体的部分与整体 | 带分段条的 `ranked` | 分段条最多 6 个部分,印出占比 | 不用饼图和环形图 |
| 标出什么影响了序列 | `events` | 一个指标,最多 60 根柱,最多 9 条注记 | 注记不在数据中:改正;超过 60 根:`lines` |
| 一个指标的分布 | `histogram` | 至少 8 个值 | 不足 8 个:`ranked` |
| 两个指标的关系 | `scatter` | 最多 3,000 个点,3 个分组 | 超过 3 组:`multiples`;超过 3,000 点:`histogram` |
| 只减不增的流程 | `funnel` | 2 到 8 个阶段,无负数;上升的阶段会被标出 | 1 个阶段:`summary`;超过 8 个:`ranked`;有负数:`waterfall` |
| 增减走向合计 | `waterfall` | 最多 24 步,可有负数和穿零 | 超过 24 步:`records` |
| 按日的活动 | `calendar` | ISO 日期,最多 3 年;负值画成空心 | 没有日期:`events`;超过 3 年:`lines` |
| 查找特定记录 | `records` | 排序、筛选,每页 25 行 | 无 |
| 逐格阅读和合计 | `sheet` | 冻结表头和合计行,最多 2,000 行 | 超过 2,000 行:`records` |

每种形式都能处理负数、缺失值(显示空缺和叉号,绝不当作零)、单个数据点(附说明)、很长的标签(先换行,再截断,完整文字保留在详情和数据表中)和中文标签。特别大和特别小的数值放在一起时保持真实比例,不足一像素的值留一道短线和一条说明。

## 可以填写的字段

都写在 `spec.json` 里。不要编造任何值。

| 字段 | 含义 | 限制 | 需求信息不足时 |
|---|---|---|---|
| `title` | 说明画的是什么,不写结论 | 60 字符 | 根据问题写。必填。 |
| `question` | 图表要回答的问题 | 90 | 复述用户的话。没人能回答时,说明你的假设。必填。 |
| `statement` | 回答问题的一句话 | 160;每个数字都必须能从数据算出 | 不填,引擎会根据数据写一句较平淡的话。 |
| `note` | 写在图表页边的话:数据回答不了什么 | 120;数字会被检查 | 只写真实存在的缺口。 |
| `highlight` | 重点行,用那一种红色画出 | 必须与标签一致 | 不填,最大的一行为红色。 |
| `whole` | 给排名图加一根分段条,`--job part` 会自动设置 | 最多 6 个正数部分 | 让任务来设置。 |
| `shares` | `false` 表示不在排名行上印占比 | | 保持开启。 |
| `extremes` | `false` 表示不在折线上印最低和最高 | | 保持开启。 |
| `unit` | 数值的前缀或后缀,如 `$`、`%`、`元` | 6 | 不填。不要猜币种。 |
| `units` | 按列设置不同单位,如 `{ "visits": "" }` | 每项 6 | 与金额并列的计数设为 `""`。 |
| `decimals` | 显示时舍入,并有说明 | 整数 | 不填,数字保持精确。 |
| `source` | 数据来源 | 60 | 不填,不要猜。 |
| `emptyText` | 空状态告诉读者的话 | 80 | 只在确实没有数据时填,如“暂未记录销售。” |
| `events` | `[{ "at": "<x 的值>", "note": "……" }]` | 9 条,每条 60;`at` 必须对应数据行 | 用户没提到事件就不填。 |
| `axisFrom` | 折线或散点的坐标轴从非零开始,图上会标注 | 数字 | 不填。柱形拒绝使用。 |
| `names` | 各列的显示名称 | 简短 | 整理明显的列名,并列出改动。 |
| `x`、`y`、`facet`、`label`、`group`、`columns` | 列映射 | 必须存在于数据中 | 由 `make.mjs` 填写。 |
| `total: false` | 不求和,用于比率和平均值 | | 求和没有意义时就要设。单位是百分比时已自动关闭。 |
| `lang` | `en` 或 `zh`,每张图一种语言 | | 跟随用户的语言。 |
| `theme` | `ledger`、`night` 或 `auto` | | 不填即日间。 |
| `fictional` | 显示虚构标签 | true | 只用于虚构数字。 |

## 改配色

只需两到四个输入:`node scripts/recolour.mjs --paper "#fff8ee" --ink "#201a14" [--mark "#……"] [--red "#……"] [--theme night] --out out`,其中 `out` 是输出文件夹。它会测量对比度,不合格就拒绝写入;合格则重写 `tokens.css`,写入 `colours.json`,并把新颜色内联到该文件夹里的每个 HTML 文件。之后用 `make.mjs` 或 `page.mjs` 重新生成也会保留。然后运行 `node scripts/check.mjs out/chart.html`,只要有输出没换上新颜色就会失败。不要把颜色写到其他地方。

## 信息缺失时

- 需求单薄:在回复中复述用户给的事实,逐条列出你推断的内容,不编造。
- 没人能回答:根据数据继续做,并列出假设:任务类型、列映射、单位、整理过什么。
- 没有数据:不要编数字,去要数据。只是想看效果,运行 `make.mjs --sample`,它会自带虚构标签。数据确实为空:传 `--empty-text`。
- 尺寸不同:图表会填满容器,设置容器宽度即可。高度由形式决定,坐标标签不会被裁切。
- 来源没有真实链接:不要写 `source`,也不要引用无法确认的链接。
- 无法识别的值(如“12万”“大约 40”)按缺失处理,并在说明中计数。请先换算,并告诉用户。

## 交付前检查

- [ ] `check.mjs` 打印了 OK,并且确实运行了浏览器检查
- [ ] 用一句话说明了选用的形式及理由
- [ ] `statement.txt` 里是一句真实的话
- [ ] 每张图都在 1280、768、390 宽度下看过
- [ ] 亲手试过悬停、键盘和“查看明细数字”
- [ ] 列出了推断内容和假设
- [ ] 示例数据已标为虚构,或没有使用
- [ ] 颜色只存在于 tokens 文件

## 不适用的情况

- 地图、网络图或 3D 图,这里都没有。
- 超过 3,000 个点或实时流数据,请用 canvas 类工具。
- 一句话就能回答的问题,直接写那句话。
- 品牌不接受衬线账本风格。改配色改变不了这种气质。

## 运行要求

Node 18 或更新版本。2023 年以后的浏览器(需要 `color-mix` 和 Shadow DOM)。除 React 18+ 或 Vue 3 外没有运行时依赖。Playwright 只用于渲染检查。`make.mjs` 不到一秒。

用在这些流程里

相似技能