feat: 完善导出设置与打印预览

This commit is contained in:
SkyJourney
2026-07-26 01:36:51 +08:00
parent ec14f7970a
commit 52cf816683
20 changed files with 1552 additions and 146 deletions
+62
View File
@@ -0,0 +1,62 @@
import { describe, expect, it } from "vitest";
import { defaultExportConfig } from "@md-to-pdf/core";
import {
EXPORT_CONFIG_STORAGE_KEY,
loadExportConfig,
parseStoredExportConfig,
saveExportConfig
} from "../src/export-settings";
function createMemoryStorage(initialValue: string | null = null) {
let value = initialValue;
return {
getItem(key: string) {
return key === EXPORT_CONFIG_STORAGE_KEY ? value : null;
},
setItem(key: string, nextValue: string) {
if (key === EXPORT_CONFIG_STORAGE_KEY) {
value = nextValue;
}
},
read() {
return value;
}
};
}
describe("导出设置缓存", () => {
it("在没有缓存时返回独立的默认配置", () => {
const first = parseStoredExportConfig(null);
const second = parseStoredExportConfig(null);
expect(first).toEqual(defaultExportConfig);
expect(first).not.toBe(second);
});
it("缓存损坏或版本过期时恢复默认配置", () => {
expect(parseStoredExportConfig("{")).toEqual(defaultExportConfig);
expect(
parseStoredExportConfig(
JSON.stringify({
...defaultExportConfig,
version: 1
})
)
).toEqual(defaultExportConfig);
});
it("保存并恢复经过校验的配置", () => {
const storage = createMemoryStorage();
const config = {
...defaultExportConfig,
paper: {
...defaultExportConfig.paper,
format: "A3" as const,
orientation: "landscape" as const
}
};
saveExportConfig(config, storage);
expect(storage.read()).toContain('"format":"A3"');
expect(loadExportConfig(storage)).toEqual(config);
});
});
+36
View File
@@ -0,0 +1,36 @@
import { describe, expect, it } from "vitest";
import {
createMermaidSiteConfig,
MERMAID_SECURE_CONFIG_KEYS
} from "../src/mermaid-config";
describe("Mermaid 站点配置", () => {
it("默认使用 default 主题和 classic 外观", () => {
const config = createMermaidSiteConfig();
expect(config.theme).toBe("default");
expect(config.look).toBe("classic");
expect(config.securityLevel).toBe("strict");
expect(config.startOnLoad).toBe(false);
});
it("锁定安全限制和原始主题 CSS", () => {
expect(MERMAID_SECURE_CONFIG_KEYS).toEqual(
expect.arrayContaining([
"secure",
"securityLevel",
"startOnLoad",
"maxTextSize",
"maxEdges",
"suppressErrorRendering",
"themeCSS"
])
);
});
it("每次创建独立的 secure 配置数组", () => {
const first = createMermaidSiteConfig();
const second = createMermaidSiteConfig();
expect(first.secure).toEqual(second.secure);
expect(first.secure).not.toBe(second.secure);
});
});
+26
View File
@@ -0,0 +1,26 @@
import { describe, expect, it, vi } from "vitest";
import { renderMermaidDefinitions } from "../src/mermaid-renderer";
describe("Mermaid 独立图表渲染", () => {
it("单个图表失败后继续渲染后续图表", async () => {
const renderDefinition = vi
.fn()
.mockRejectedValueOnce(new Error("语法错误"))
.mockResolvedValueOnce({ svg: "<svg>第二张图</svg>" });
const outcomes = await renderMermaidDefinitions(
["invalid", "flowchart LR\nA --> B"],
renderDefinition
);
expect(renderDefinition).toHaveBeenCalledTimes(2);
expect(outcomes[0]).toMatchObject({
success: false,
error: expect.any(Error)
});
expect(outcomes[1]).toEqual({
success: true,
svg: "<svg>第二张图</svg>"
});
});
});
+37
View File
@@ -0,0 +1,37 @@
import { describe, expect, it } from "vitest";
import { enablePrintMediaForPreview } from "../src/preview-styles";
describe("打印媒体预览", () => {
it("将打印媒体规则转换为屏幕预览规则", () => {
const css = `
html { font-size: 16px; }
@media print {
html { font-size: 13px; }
}
`;
expect(enablePrintMediaForPreview(css)).toContain("@media screen {");
expect(enablePrintMediaForPreview(css)).toContain(
"html { font-size: 13px; }"
);
});
it("支持 only print 和带条件的打印媒体规则", () => {
const css = [
"@media only print { body { color: black; } }",
"@media print and (color) { body { background: white; } }"
].join("\n");
expect(enablePrintMediaForPreview(css)).toBe(
[
"@media only screen { body { color: black; } }",
"@media screen and (color) { body { background: white; } }"
].join("\n")
);
});
it("不改变普通屏幕媒体规则", () => {
const css = "@media screen and (min-width: 800px) { body { margin: 0; } }";
expect(enablePrintMediaForPreview(css)).toBe(css);
});
});