feat: 增加 ECharts 渲染与预览交互增强
- 新增可复用的 markdown-echarts 工作区,支持安全的 YAML 围栏、默认值、语义校验、错误占位和 SVG 渲染 - 将 ECharts 接入统一 Markdown、快速预览、精确预览与 PDF 链路,并复用 Mermaid 的不可跨页和超高图单页适配策略 - 默认示例加入 ECharts,增加源文本折叠、顶部文档状态、页码输入跳转与滚动同步 - 快速预览改用外层容器滚动,使滚动条与精确预览统一贴在预览区域右侧,并兼容显示缩放 - 完善 Docker 工作区复制、可配置 Compose 镜像、测试覆盖和进度文档
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
normalizeAndValidateEChartsOption,
|
||||
validateAndApplyEChartsOptionDefaults
|
||||
} from "../src/index.js";
|
||||
|
||||
function validate(option: Record<string, unknown>) {
|
||||
return validateAndApplyEChartsOptionDefaults(
|
||||
normalizeAndValidateEChartsOption(option)
|
||||
);
|
||||
}
|
||||
|
||||
describe("ECharts 系列语义验证", () => {
|
||||
it("允许从 dataset.source 取数并补充坐标轴", () => {
|
||||
expect(
|
||||
validate({
|
||||
dataset: {
|
||||
source: [
|
||||
["name", "value"],
|
||||
["A", 12]
|
||||
]
|
||||
},
|
||||
series: [{ type: "bar" }]
|
||||
})
|
||||
).toMatchObject({
|
||||
xAxis: {},
|
||||
yAxis: {},
|
||||
series: [{ type: "bar" }]
|
||||
});
|
||||
});
|
||||
|
||||
it("缺少所有数据来源时报告精确路径", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [{ type: "line" }]
|
||||
})
|
||||
).toThrow(
|
||||
/option\.series\.0\.data 必须是非空数组/u
|
||||
);
|
||||
});
|
||||
|
||||
it("只有表头或空列的 dataset 不算有效数据", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
dataset: {
|
||||
source: [["name", "value"]]
|
||||
},
|
||||
series: [{ type: "bar" }]
|
||||
})
|
||||
).toThrow(/必须是非空数组/u);
|
||||
|
||||
expect(() =>
|
||||
validate({
|
||||
dataset: {
|
||||
source: {
|
||||
name: [],
|
||||
value: []
|
||||
}
|
||||
},
|
||||
series: [{ type: "bar" }]
|
||||
})
|
||||
).toThrow(/必须是非空数组/u);
|
||||
});
|
||||
|
||||
it("散点图要求二维坐标", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [{ type: "scatter", data: [12] }]
|
||||
})
|
||||
).toThrow(
|
||||
/option\.series\.0\.data\.0 必须是至少包含两个坐标值/u
|
||||
);
|
||||
});
|
||||
|
||||
it("饼图要求有限数值", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "pie",
|
||||
data: [{ name: "A", value: "12" }]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(
|
||||
/option\.series\.0\.data\.0\.value 必须是有限数值/u
|
||||
);
|
||||
});
|
||||
|
||||
it("雷达图要求指标并校验数据维数", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "radar",
|
||||
data: [{ value: [12, 18] }]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/option\.radar\.indicator/u);
|
||||
|
||||
expect(() =>
|
||||
validate({
|
||||
radar: {
|
||||
indicator: [
|
||||
{ name: "质量" },
|
||||
{ name: "速度" },
|
||||
{ name: "成本" }
|
||||
]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "radar",
|
||||
data: [{ value: [12, 18] }]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/至少包含 3 个指标值/u);
|
||||
});
|
||||
|
||||
it("热力图区分直角坐标系与日历坐标系", () => {
|
||||
expect(
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "heatmap",
|
||||
data: [[0, 1, 20]]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toMatchObject({ xAxis: {}, yAxis: {} });
|
||||
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "heatmap",
|
||||
coordinateSystem: "calendar",
|
||||
data: [["2026-01-01", 20]]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/option\.calendar/u);
|
||||
});
|
||||
|
||||
it("箱线图要求五数数据", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "boxplot",
|
||||
data: [[1, 2, 3, 4]]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/五元数组/u);
|
||||
});
|
||||
|
||||
it("K 线图要求 OHLC 四元数据", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "candlestick",
|
||||
data: [[20, 18, 16]]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/四元数组/u);
|
||||
});
|
||||
|
||||
it("极坐标折线图要求完整极坐标组件", () => {
|
||||
expect(() =>
|
||||
validate({
|
||||
series: [
|
||||
{
|
||||
type: "line",
|
||||
coordinateSystem: "polar",
|
||||
data: [[10, 20]]
|
||||
}
|
||||
]
|
||||
})
|
||||
).toThrow(/option\.polar/u);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user