feat: 完善 Mermaid 配置与预览缩放
This commit is contained in:
@@ -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 = {
|
||||
|
||||
@@ -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"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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"
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user