npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@damoqiongqiu/ice-chart-dsl

v0.2.9

Published

A JSON-first DSL layer for AI agents to build charts with ice-chart.

Downloads

1,635

Readme

ice-chart-dsl

JSON-first DSL for AI agents to build charts with @damoqiongqiu/ice-chart.

ice-chart 的 ChartOption 本来就是纯 JSON(toJSON() / fromJSONString()),所以这个包不是把 option 换个写法。 它补的是 option 不做、而模型最容易写错的三件事:

| | ChartOption | ice-chart-dsl | | --- | --- | --- | | 输入 | 自己把数据拍成 series[].data | 一张表 + encoding{ x: '月份', y: '销量', series: '渠道' } | | 默认值 | 逐项自己写 | 轴类型 / 图例显隐 / 提示框触发方式按类型自动定,显式写的优先 | | 出错时 | 画出来是空的,只能自己猜 | 结构化诊断:列不存在(带可用列名)、类型不匹配、空数据、公式错误(带字符位置) |

编译产物就是普通的 ChartOption —— 悬停、缩放、框选、序列化、跨图联动全部照旧。

Install

npm install @damoqiongqiu/ice-chart-dsl @damoqiongqiu/ice-chart ice-render

30 秒

{
  "schemaVersion": 1,
  "kind": "line",
  "title": "月度销量",
  "data": {
    "columns": ["月份", "销量", "渠道"],
    "rows": [["1月", 120, "线上"], ["1月", 86, "线下"], ["2月", 142, "线上"], ["2月", 92, "线下"]]
  },
  "encoding": { "x": "月份", "y": "销量", "series": "渠道" }
}
import { renderChartDsl, validateChartDsl, compileChartDsl } from '@damoqiongqiu/ice-chart-dsl';

const { chart, option, diagnostics } = renderChartDsl('canvas-id', dsl);

// 或者只要配置:编译出来的就是 ChartOption
const option = compileChartDsl(dsl);

// 或者只要诊断(validate 不抛异常,任何输入都能吃)
const result = validateChartDsl(dsl);
if (!result.valid) console.log(result.errors.map((e) => e.message).join('\n'));

浏览器直接用(UMD,注意顺序):

<canvas id="chart" width="900" height="480"></canvas>
<script src="https://unpkg.com/ice-render/dist/index.umd.js"></script>
<script src="https://unpkg.com/@damoqiongqiu/ice-chart/dist/index.umd.js"></script>
<script src="https://unpkg.com/@damoqiongqiu/ice-chart-dsl/dist/index.umd.js"></script>
<script>
  ICEChartDSL.renderChartDsl('chart', { kind: 'line', data: {...}, encoding: { x: '月份', y: '销量' } });
</script>

数据集两种写法

{ "columns": ["月份", "销量"], "rows": [["1月", 120], ["2月", 132]] }
[{ "月份": "1月", "销量": 120 }, { "月份": "2月", "销量": 132 }]

对象数组是模型最常吐的形态,两种都收;columns 按对象 key 首次出现顺序推出来。

kind 与覆盖范围

| kind | 需要的通道 | 说明 | | --- | --- | --- | | line / area | x + y(+ series) | 数值 x 自动用数值轴 + [x, y] 数据点 | | bar | x + y(+ series) | 堆叠用 options.stack | | scatter | x + y(+ size) | 绑 size 即气泡图 | | pie | name + value | 负值会被警告(饼图不表达负值) | | radar | x(指标)+ y(数值)+ series | 指标名从 x 列推,上限自动取整到好看的刻度 | | heatmap | x + y(两个类目列)+ value | 二维矩阵表直接画 | | candlestick | x + y四列 [开, 收, 低, 高] | 少给列会明确报错 | | waterfall | name + value(+ total) | total 列非 0 的行当合计项 | | funnel / gauge / liquid | name + value | 仪表盘/水位球只取第一行(多行会警告) | | sankey | source + target + value | 一张「起点 / 终点 / 流量」的连线表 | | function | expression(+ domain / params) | 不需要 data |

直通treemap / graph / parametric / boxplot 等直接给 seriesoptions 照常透传)。 逃生舱options 里的键覆盖编译结果(series 除外),所以 DSL 跟不上核心演进时不会把人堵死。

标注:目标线 / 阈值线 / 异常点 / 目标区间

业务图上最高频的参考线不是「一种新图表」,而是一条配置 —— 顶层 annotation(与 encoding 平级):

{
  "schemaVersion": 1,
  "kind": "line",
  "title": "月度销量与目标",
  "data": { "columns": ["月份", "销量"], "rows": [["1月", 120], ["2月", 132], ["3月", 101]] },
  "encoding": { "x": "月份", "y": "销量" },
  "annotation": {
    "lines": [
      { "axis": "y", "value": 150, "text": "目标 150" },
      { "axis": "y", "value": 100, "text": "告警阈值", "color": "#dc3545" },
      { "axis": "x", "value": "2月", "text": "上线" }
    ],
    "points": [{ "x": "3月", "y": 101, "text": "异常点", "symbol": "diamond" }],
    "areas": [{ "axis": "y", "from": 0, "to": 100, "text": "达标区" }]
  }
}
  • lines[].value / areas[].fromto / points[].xy 都是数据值(不是像素): 数值轴写数字、类目轴写类目名或下标、时间轴写时间戳或日期串。
  • 它挂在坐标系上,所以跟着缩放 / 平移走,不进图例、不占数据下标、不抢命中测试; 越界的标注不画,原因由 ice-chart 的 chart.annotationDiagnostics() 给出。
  • 只对直角坐标的 kind 有意义(line / area / bar / scatter); 给饼图 / 雷达 / 桑基等会被警告 annotation-non-cartesian
  • 编译期诊断:缺 value / 缺 from+to错误(带 annotation.lines[0].value 这样的路径), 类目不存在(annotation-unknown-category)、数值轴写了非数字(annotation-value-type)、 区间宽度为 0(annotation-empty-area)是警告
  • 逃生舱照常:options.annotation 能整体覆盖顶层 annotation

主题:一条链路贯通图表与引擎

DSL 里的主题走图表的 options.theme'light' / 'dark' / 'auto' / 部分主题片段), 图表层再把它映射到引擎主题(引擎 2.4 起):图表实例里那些「引擎自己画的东西」 (引擎默认样式、选中框 / 手柄 / 插槽这些交互外壳、应用后加的自定义图元)会跟着一起换。

{
  "kind": "line",
  "data": { "columns": ["月份", "销量"], "rows": [["1月", 120], ["2月", 132]] },
  "encoding": { "x": "月份", "y": "销量" },
  "options": {
    "theme": "dark"
  }
}
  • theme: 'auto' = 跟随引擎实例主题(按引擎主题背景色的亮度判定明暗)—— 图表渲染在别人的暗色画布上时,写 auto 即可,不用自己判断。
  • 需要品牌色就传片段:"theme": { "colorPalette": ["#0d6efd", "#10b981"], "textColor": "#212529" } (浅合并到亮色主题),映射到引擎的那一份会自动跟着算。
  • 完整的映射表见 ice-chart 仓库的 src/theme/chartEngineBridge.ts

诊断:给 agent 的自修复反馈

validateChartDsl() 不抛异常,返回结构化诊断({ severity, code, message, path }):

[错误] 列「销售额」不存在。可用列:月份 / 销量 / 渠道。(encoding.y)
[错误] 列「渠道」不是数值列(数字占比 0%),不能当 y 用。(encoding.y)
[错误] 第 3 行有 2 个值,但列数是 3。(data.rows[2])
[警告] 饼图 / 玫瑰图不适合表达负值,检测到 2 行负数。(encoding.value)
[错误] 表达式错误:缺少右括号(位置 6)… (expression)
[警告] 参数「b」定义了但表达式没有用到。(expression)
[错误] annotation.lines[0] 缺少 value(数值轴写数字、类目轴写类目名或下标)。(annotation.lines[0].value)
[警告] annotation.lines[1].value 的类目名「13月」不在 x 列里(该列有 3 个类目),这条标注不会画出来。(annotation.lines[1].value)

公式类会采样一遍再诊断:静态检查抓语法错误,运行层抓「整段开不出来」「输出恒定」—— 这两种恰恰是"公式写错了但没报错"最常见的表现。

API

| 导出 | 说明 | | --- | --- | | CHART_DSL_SCHEMA_VERSION / CHART_DSL_KINDS | 版本与支持的 kind | | CHART_DSL_COMPILED_KINDS | 走 data/encoding 编译的 kind 清单 | | validateChartDsl(dsl) | 结构 + 语义校验,返回 { valid, errors, warnings } | | formatDiagnostics(result) | 诊断 → 多行文本 | | compileChartDsl(dsl) | DSL → ChartOption(不合法时抛 ChartDslCompileError.diagnostics 带原因) | | chartDslToJsonString(dsl) | 直接拿编译产物的 JSON 字符串 | | renderChartDsl(target, dsl, chartOptions?) | 编译并渲染,返回 { chart, option, diagnostics } | | resolveDataset / columnIndex / numericRatio | 数据集工具(自建通道映射时用得上) |

JSON Schema:src/schema/chart-dsl.schema.json

Example

npm install
npm run build
# 起一个静态服务打开 examples/chart-dsl.html

左边写 DSL,右边实时渲染,下面是诊断面板(含「错误示例」预设,可以直接看到列名纠错长什么样)。

Agent discovery

License

MIT