feat: 完善 Mermaid 配置与预览缩放

This commit is contained in:
SkyJourney
2026-07-26 23:10:22 +08:00
parent 15dd2acfc0
commit d93728bb8b
25 changed files with 870 additions and 56 deletions
+36 -1
View File
@@ -1,10 +1,30 @@
import { z } from "zod";
export const EXPORT_CONFIG_VERSION = 2;
export const EXPORT_CONFIG_VERSION = 3;
export const CSS_PIXELS_PER_INCH = 96;
export const PDF_POINTS_PER_INCH = 72;
export const MILLIMETERS_PER_INCH = 25.4;
export const supportedMermaidLayouts = ["dagre", "elk"] as const;
export const supportedMermaidThemes = [
"default",
"base",
"dark",
"forest",
"neutral",
"neo",
"neo-dark",
"redux",
"redux-dark",
"redux-color",
"redux-dark-color"
] as const;
export const supportedMermaidLooks = [
"classic",
"handDrawn",
"neo"
] as const;
export const supportedPaperFormats = [
"A3",
"A4",
@@ -147,10 +167,18 @@ const paperSchema = z
}
});
export const mermaidConfigSchema = z.object({
layout: z.enum(supportedMermaidLayouts),
theme: z.enum(supportedMermaidThemes),
look: z.enum(supportedMermaidLooks),
fontFamily: z.string().trim().min(1).max(300)
});
export const exportConfigSchema = z.object({
version: z.literal(EXPORT_CONFIG_VERSION),
name: z.string().min(1).max(100),
themeId: z.string().min(1),
mermaid: mermaidConfigSchema,
paper: paperSchema,
header: headerSchema,
footer: footerSchema,
@@ -169,6 +197,7 @@ export const exportConfigSchema = z.object({
});
export type ExportConfig = z.infer<typeof exportConfigSchema>;
export type MermaidExportConfig = ExportConfig["mermaid"];
export type PaperFormat = ExportConfig["paper"]["format"];
export type PaperOrientation = ExportConfig["paper"]["orientation"];
export type HeaderConfig = ExportConfig["header"];
@@ -193,6 +222,12 @@ export const defaultExportConfig: ExportConfig = {
version: EXPORT_CONFIG_VERSION,
name: "默认 A4 文档",
themeId: "typora-github",
mermaid: {
layout: "dagre",
theme: "default",
look: "classic",
fontFamily: "Segoe UI, Microsoft YaHei, sans-serif"
},
paper: {
format: "A4",
orientation: "portrait",
+40
View File
@@ -7,6 +7,9 @@ import {
millimetersToCssPixels,
millimetersToPdfPoints,
paperDimensionsMm,
supportedMermaidLayouts,
supportedMermaidLooks,
supportedMermaidThemes,
supportedPaperFormats
} from "../src/export-config.js";
@@ -42,6 +45,43 @@ describe("导出配置", () => {
expect(exportConfigSchema.safeParse(defaultExportConfig).success).toBe(true);
});
it("提供 Mermaid 官方布局、主题、外观和字体默认值", () => {
expect(supportedMermaidLayouts).toEqual(["dagre", "elk"]);
expect(supportedMermaidLooks).toEqual([
"classic",
"handDrawn",
"neo"
]);
expect(supportedMermaidThemes).toContain("redux-dark-color");
expect(defaultExportConfig.mermaid).toEqual({
layout: "dagre",
theme: "default",
look: "classic",
fontFamily: "Segoe UI, Microsoft YaHei, sans-serif"
});
});
it("拒绝 Mermaid 未支持的导出配置", () => {
expect(
exportConfigSchema.safeParse({
...defaultExportConfig,
mermaid: {
...defaultExportConfig.mermaid,
layout: "unknown"
}
}).success
).toBe(false);
expect(
exportConfigSchema.safeParse({
...defaultExportConfig,
mermaid: {
...defaultExportConfig.mermaid,
fontFamily: ""
}
}).success
).toBe(false);
});
it("使用统一的 96 CSS px/in 和 72 PDF pt/in 换算物理尺寸", () => {
expect(millimetersToCssPixels(25.4)).toBeCloseTo(96);
expect(cssPixelsToMillimeters(96)).toBeCloseTo(25.4);