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
+37 -7
View File
@@ -2,24 +2,32 @@ import { describe, expect, it } from "vitest";
import { defaultExportConfig } from "@md-to-pdf/core";
import {
EXPORT_CONFIG_STORAGE_KEY,
LEGACY_EXPORT_CONFIG_STORAGE_KEY,
loadExportConfig,
parseStoredExportConfig,
saveExportConfig
} from "../src/export-settings";
function createMemoryStorage(initialValue: string | null = null) {
let value = initialValue;
function createMemoryStorage(
initialValue: string | null = null,
legacyValue: string | null = null
) {
const values = new Map<string, string>();
if (initialValue) {
values.set(EXPORT_CONFIG_STORAGE_KEY, initialValue);
}
if (legacyValue) {
values.set(LEGACY_EXPORT_CONFIG_STORAGE_KEY, legacyValue);
}
return {
getItem(key: string) {
return key === EXPORT_CONFIG_STORAGE_KEY ? value : null;
return values.get(key) ?? null;
},
setItem(key: string, nextValue: string) {
if (key === EXPORT_CONFIG_STORAGE_KEY) {
value = nextValue;
}
values.set(key, nextValue);
},
read() {
return value;
return values.get(EXPORT_CONFIG_STORAGE_KEY) ?? null;
}
};
}
@@ -44,6 +52,28 @@ describe("导出设置缓存", () => {
).toEqual(defaultExportConfig);
});
it("将 v2 缓存迁移为 v3 并保留已有设置", () => {
const legacyConfig = {
...defaultExportConfig,
version: 2,
mermaid: undefined,
paper: {
...defaultExportConfig.paper,
format: "A5"
}
};
const storage = createMemoryStorage(
null,
JSON.stringify(legacyConfig)
);
const migrated = loadExportConfig(storage);
expect(migrated.version).toBe(3);
expect(migrated.paper.format).toBe("A5");
expect(migrated.mermaid).toEqual(defaultExportConfig.mermaid);
expect(storage.read()).toContain('"version":3');
});
it("保存并恢复经过校验的配置", () => {
const storage = createMemoryStorage();
const config = {
+20 -3
View File
@@ -1,4 +1,5 @@
import { describe, expect, it } from "vitest";
import { defaultExportConfig } from "@md-to-pdf/core";
import {
createMermaidSiteConfig,
MERMAID_SECURE_CONFIG_KEYS
@@ -6,7 +7,7 @@ import {
describe("Mermaid 站点配置", () => {
it("默认使用 default 主题和 classic 外观", () => {
const config = createMermaidSiteConfig();
const config = createMermaidSiteConfig(defaultExportConfig.mermaid);
expect(config.theme).toBe("default");
expect(config.look).toBe("classic");
expect(config.securityLevel).toBe("strict");
@@ -29,9 +30,25 @@ describe("Mermaid 站点配置", () => {
});
it("每次创建独立的 secure 配置数组", () => {
const first = createMermaidSiteConfig();
const second = createMermaidSiteConfig();
const first = createMermaidSiteConfig(defaultExportConfig.mermaid);
const second = createMermaidSiteConfig(defaultExportConfig.mermaid);
expect(first.secure).toEqual(second.secure);
expect(first.secure).not.toBe(second.secure);
});
it("应用导出配置中的布局、主题、外观和字体", () => {
const config = createMermaidSiteConfig({
layout: "elk",
theme: "forest",
look: "handDrawn",
fontFamily: "Microsoft YaHei, sans-serif"
});
expect(config).toMatchObject({
layout: "elk",
theme: "forest",
look: "handDrawn",
fontFamily: "Microsoft YaHei, sans-serif"
});
});
});
+9
View File
@@ -16,6 +16,15 @@ describe("精确 PDF 页面尺寸", () => {
});
});
it("按预览缩放比例调整 PDF 页面显示尺寸", () => {
expect(
getPdfPageCssDimensions(595.275591, 841.889764, 1.5)
).toEqual({
width: expect.closeTo(1190.551182, 5),
height: expect.closeTo(1683.779528, 5)
});
});
it("结合显示宽度和设备像素比计算 Canvas 比例", () => {
expect(getPdfCanvasRenderScale(600, 800, 2)).toBeCloseTo(
8 / 3
@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest";
import {
beginPreviewFrameRender,
completePreviewFrameRender
} from "../src/preview-frame-visibility";
function createTarget() {
return {
dataset: {} as DOMStringMap
};
}
describe("分页 iframe 渲染可见性", () => {
it("渲染期间隐藏,当前请求完成后恢复显示", () => {
const target = createTarget();
beginPreviewFrameRender(target, 12);
expect(target.dataset).toMatchObject({
rendering: "true",
renderingRequestId: "12"
});
expect(completePreviewFrameRender(target, 12)).toBe(true);
expect(target.dataset.rendering).toBeUndefined();
expect(target.dataset.renderingRequestId).toBeUndefined();
});
it("旧请求完成时不会提前显示新请求的半成品", () => {
const target = createTarget();
beginPreviewFrameRender(target, 12);
beginPreviewFrameRender(target, 13);
expect(completePreviewFrameRender(target, 12)).toBe(false);
expect(target.dataset).toMatchObject({
rendering: "true",
renderingRequestId: "13"
});
});
});
+49
View File
@@ -0,0 +1,49 @@
import { describe, expect, it } from "vitest";
import {
DEFAULT_PREVIEW_ZOOM,
MAXIMUM_PREVIEW_ZOOM,
MINIMUM_PREVIEW_ZOOM,
PREVIEW_ZOOM_STORAGE_KEY,
loadPreviewZoom,
normalizePreviewZoom,
parsePreviewZoom,
savePreviewZoom
} from "../src/preview-zoom";
function createMemoryStorage(initialValue: string | null = null) {
let value = initialValue;
return {
getItem(key: string) {
return key === PREVIEW_ZOOM_STORAGE_KEY ? value : null;
},
setItem(key: string, nextValue: string) {
if (key === PREVIEW_ZOOM_STORAGE_KEY) {
value = nextValue;
}
},
read() {
return value;
}
};
}
describe("预览缩放", () => {
it("默认使用 100%,并限制在 50% 到 400%", () => {
expect(parsePreviewZoom(null)).toBe(DEFAULT_PREVIEW_ZOOM);
expect(normalizePreviewZoom(20)).toBe(MINIMUM_PREVIEW_ZOOM);
expect(normalizePreviewZoom(450)).toBe(MAXIMUM_PREVIEW_ZOOM);
expect(normalizePreviewZoom(124.6)).toBe(125);
});
it("无效手动输入回退到当前缩放值", () => {
expect(parsePreviewZoom("", 135)).toBe(135);
expect(parsePreviewZoom("not-a-number", 135)).toBe(135);
});
it("保存并恢复浏览器缩放偏好", () => {
const storage = createMemoryStorage();
savePreviewZoom(145, storage);
expect(storage.read()).toBe("145");
expect(loadPreviewZoom(storage)).toBe(145);
});
});