feat: 扩展 ECharts 第二阶段图表支持
新增 tree、treemap、sunburst、graph、sankey、chord、funnel、gauge 和 pictorialBar 系列,并注册对应的 ECharts 按需模块。 完善层级与关系数据校验、节点和边数量限制、默认布局及错误占位规则,同时补充默认 Markdown 与 README 示例。 静态渲染全局关闭 ECharts 动画,修复 Treemap 标签冻结在透明动画帧的问题,并完成快速预览、精确 PDF、容器镜像和 147 项全项目测试验证。
This commit is contained in:
@@ -67,7 +67,7 @@ option:
|
||||
|
||||
## 系列验证规则
|
||||
|
||||
当前首版支持以下系列:
|
||||
当前支持以下系列:
|
||||
|
||||
| 系列 | 主要规则 |
|
||||
| --- | --- |
|
||||
@@ -79,6 +79,15 @@ option:
|
||||
| `heatmap` | 直角坐标数据为 `[x, y, value]`;日历数据为 `[date, value]` |
|
||||
| `boxplot` | 直接数据为 `[min, Q1, median, Q3, max]` |
|
||||
| `candlestick` | 直接数据为 `[open, close, lowest, highest]` |
|
||||
| `tree` | 必须提供非空层级 `data`;递归校验 `children` |
|
||||
| `treemap` | 必须提供非空层级 `data`;叶节点必须具有有限数值 |
|
||||
| `sunburst` | 必须提供非空层级 `data`;叶节点必须具有有限数值 |
|
||||
| `graph` | 必须提供 `data` 或 `nodes`;校验边引用;缺少坐标时默认 `force` 布局 |
|
||||
| `sankey` | 必须提供节点和关系边;边权重必须是非负有限数值 |
|
||||
| `chord` | 使用 ECharts 6 和弦图;必须提供节点、关系边和非负权重 |
|
||||
| `funnel` | 数据项必须是有限数值,或使用有效 `dataset` |
|
||||
| `gauge` | 数据项必须是有限数值,或使用有效 `dataset` |
|
||||
| `pictorialBar` | 需要有效数据和直角坐标系;允许安全的 `path://` 内嵌矢量符号 |
|
||||
|
||||
直角坐标系列缺少 `xAxis` 或 `yAxis` 时会补充空对象,让 ECharts
|
||||
使用自身的轴默认值。极坐标、雷达和日历坐标系表达了明确语义,
|
||||
@@ -87,6 +96,111 @@ option:
|
||||
使用 `dataset` 时,验证器只验证数据源是否存在,不重复实现
|
||||
ECharts 的维度推断和 `encode` 映射规则。
|
||||
|
||||
## 第二阶段系列示例
|
||||
|
||||
### 层级图
|
||||
|
||||
```yaml
|
||||
height: 60mm
|
||||
option:
|
||||
series:
|
||||
- type: treemap
|
||||
nodeClick: false
|
||||
breadcrumb:
|
||||
show: false
|
||||
label:
|
||||
show: true
|
||||
formatter: "{b}"
|
||||
color: "#1f2937"
|
||||
fontWeight: bold
|
||||
backgroundColor: "rgba(255, 255, 255, 0.88)"
|
||||
borderRadius: 3
|
||||
padding: [3, 6]
|
||||
itemStyle:
|
||||
borderColor: "#ffffff"
|
||||
borderWidth: 2
|
||||
gapWidth: 2
|
||||
levels:
|
||||
- itemStyle:
|
||||
borderWidth: 0
|
||||
gapWidth: 2
|
||||
- upperLabel:
|
||||
show: true
|
||||
height: 28
|
||||
color: "#1f2937"
|
||||
fontWeight: bold
|
||||
backgroundColor: "rgba(255, 255, 255, 0.88)"
|
||||
padding: [3, 6]
|
||||
itemStyle:
|
||||
borderColor: "#ffffff"
|
||||
borderWidth: 2
|
||||
gapWidth: 2
|
||||
- label:
|
||||
show: true
|
||||
formatter: "{b}"
|
||||
color: "#1f2937"
|
||||
fontWeight: bold
|
||||
backgroundColor: "rgba(255, 255, 255, 0.88)"
|
||||
borderRadius: 3
|
||||
padding: [3, 6]
|
||||
itemStyle:
|
||||
borderColor: "#ffffff"
|
||||
borderWidth: 2
|
||||
gapWidth: 2
|
||||
data:
|
||||
- name: 渲染
|
||||
children:
|
||||
- { name: Markdown, value: 32 }
|
||||
- { name: ECharts, value: 24 }
|
||||
- name: 导出
|
||||
children:
|
||||
- { name: PDF, value: 28 }
|
||||
```
|
||||
|
||||
`tree`、`treemap` 和 `sunburst` 共用递归 `children` 结构。
|
||||
`treemap` 与 `sunburst` 的叶节点需要数值;父节点可以省略数值,
|
||||
由 ECharts 根据子节点汇总。
|
||||
|
||||
### 关系图
|
||||
|
||||
```yaml
|
||||
height: 60mm
|
||||
option:
|
||||
series:
|
||||
- type: sankey
|
||||
data:
|
||||
- { name: Markdown }
|
||||
- { name: HTML }
|
||||
- { name: PDF }
|
||||
links:
|
||||
- { source: Markdown, target: HTML, value: 100 }
|
||||
- { source: HTML, target: PDF, value: 40 }
|
||||
```
|
||||
|
||||
`graph` 的关系边可以省略;`sankey` 和 ECharts 6 `chord` 必须
|
||||
具有非空 `links` 或 `edges`。`source`、`target` 必须引用节点
|
||||
名称、ID 或数组索引。
|
||||
|
||||
### 业务图表
|
||||
|
||||
```yaml
|
||||
height: 60mm
|
||||
option:
|
||||
series:
|
||||
- type: gauge
|
||||
min: 0
|
||||
max: 100
|
||||
progress:
|
||||
show: true
|
||||
detail:
|
||||
formatter: "{value}%"
|
||||
data:
|
||||
- { name: 完成率, value: 78 }
|
||||
```
|
||||
|
||||
`funnel` 和 `gauge` 使用有限数值数据;`pictorialBar` 复用柱图
|
||||
坐标系和数据规则,并允许不加载外部资源的 `path://` SVG 路径。
|
||||
|
||||
## 错误行为
|
||||
|
||||
配置错误不会中断整篇 Markdown。对应围栏会变成局部错误占位:
|
||||
@@ -133,7 +247,6 @@ import "@md-to-pdf/markdown-echarts/styles.css";
|
||||
|
||||
const outcomes = await renderEChartsBlocks(document, {
|
||||
outputMode: "inline-svg",
|
||||
animation: false,
|
||||
concurrency: 2,
|
||||
timeoutMs: 5000
|
||||
});
|
||||
@@ -148,6 +261,9 @@ const outcomes = await renderEChartsBlocks(document, {
|
||||
PDF 输出前应等待所有图表、字体和图片完成,再开始分页或调用
|
||||
Chromium `page.pdf()`。
|
||||
|
||||
浏览器引擎会强制关闭全局及各系列动画,Markdown 中的动画参数不会改变
|
||||
静态 SVG、快速预览、精确预览或 PDF,避免输出停留在动画中间帧。
|
||||
|
||||
## 安全边界
|
||||
|
||||
默认策略会拒绝:
|
||||
@@ -158,7 +274,8 @@ Chromium `page.pdf()`。
|
||||
- 原型污染属性;
|
||||
- 未允许的 toolbox 功能;
|
||||
- 非内置数据转换;
|
||||
- 超过节点数、深度、字符串、数组和系列数量上限的配置。
|
||||
- 超过节点数、深度、字符串、数组、系列、层级节点或关系边数量
|
||||
上限的配置。
|
||||
|
||||
这些限制适用于不受信任的 Markdown。宿主如需扩大能力,应在明确
|
||||
风险后扩展验证器,而不是直接执行 YAML 中的 JavaScript。
|
||||
|
||||
Reference in New Issue
Block a user