新增通用 CSS 到 OOXML 翻译修复,统一字体、字距、精确行距、段落、列表、表格、引用、代码块与行内代码连续性,不引入按主题 ID 分支。 新增 MdTP Mono 并统一 Serif、Sans、Mono 三字体包的 Chromium 与 DOCX 使用链;字体声明、嵌入部件和 Word/WPS 实际采用均进入硬门禁。 重建封面整页及正文语义块视觉差分,14 套主题、纵横两个方向、五组页边距共 140 个真实场景全部通过,阻断失败和诊断失败均为零。 源码服务、Docker Web API 与实际安装 Desktop 的 red-briefing 导出均包含 5 个字体部件;Word/WPS 原生渲染和逐页复核通过。修复 Docker 构建上下文与运行层复用软链接,并完善 v0.6.1 版本、发行说明和发布归集。 验证:npm test(116 个文件、616 项测试)、npm run typecheck、npm run build、git diff --check 全部通过。Desktop 安装器与 ZIP、Docker v0.6.1 镜像已生成;Windows 产物仍为未签名内部发行。
176 lines
4.4 KiB
TypeScript
176 lines
4.4 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
||
import type { WebContents } from "electron";
|
||
import {
|
||
createPagedDocumentPayload,
|
||
defaultExportConfig,
|
||
type DocxMediaCapturePlan
|
||
} from "@md-to-pdf/core";
|
||
import { captureDocxMediaWithElectronWebContents } from "../src/electron-docx-media-capture.js";
|
||
|
||
const plan: DocxMediaCapturePlan = {
|
||
targets: [
|
||
{
|
||
id: "docx-media-1",
|
||
kind: "image",
|
||
ordinal: 1,
|
||
kindOrdinal: 1,
|
||
altText: "图片",
|
||
alignment: "center",
|
||
displayWidthPx: 200,
|
||
displayHeightPx: 100,
|
||
captureX: 12,
|
||
captureY: 24,
|
||
captureWidthPx: 200,
|
||
captureHeightPx: 100,
|
||
rasterScale: 3.125
|
||
}
|
||
],
|
||
echartsErrors: [],
|
||
mermaidErrors: []
|
||
};
|
||
|
||
const request = {
|
||
payload: createPagedDocumentPayload({
|
||
document: {
|
||
rendererVersion: 1,
|
||
articleHtml: '<article id="write"></article>',
|
||
bodyHtml: "",
|
||
metadata: {
|
||
title: "",
|
||
author: "",
|
||
subject: "",
|
||
keywords: [],
|
||
language: "zh-CN"
|
||
},
|
||
semanticDocument: {
|
||
schemaVersion: 1,
|
||
titlePolicy: {
|
||
metadataTitle: "emit",
|
||
firstBodyHeading: "keep"
|
||
},
|
||
regions: []
|
||
},
|
||
features: [],
|
||
warnings: []
|
||
},
|
||
fileName: "test.md",
|
||
themeCss: "",
|
||
exportConfig: defaultExportConfig
|
||
}),
|
||
dimensions: {
|
||
contentWidthPx: 600,
|
||
contentHeightPx: 900
|
||
}
|
||
};
|
||
|
||
describe("Electron DOCX 媒体捕获", () => {
|
||
it("复用隐藏 Chromium 并在捕获后释放调试会话", async () => {
|
||
let attached = false;
|
||
const attach = vi.fn(() => {
|
||
attached = true;
|
||
});
|
||
const detach = vi.fn(() => {
|
||
attached = false;
|
||
});
|
||
const sendCommand = vi.fn(async () => ({
|
||
data: Buffer.from("png").toString("base64")
|
||
}));
|
||
const webContents = {
|
||
executeJavaScript: vi.fn(async () => plan),
|
||
debugger: {
|
||
isAttached: vi.fn(() => attached),
|
||
attach,
|
||
detach,
|
||
sendCommand
|
||
}
|
||
} as unknown as WebContents;
|
||
|
||
const result = await captureDocxMediaWithElectronWebContents(
|
||
webContents,
|
||
request
|
||
);
|
||
|
||
expect(result.captures[0]).toEqual({
|
||
id: "docx-media-1",
|
||
png: Buffer.from("png")
|
||
});
|
||
expect(attach).toHaveBeenCalledWith("1.3");
|
||
expect(sendCommand).toHaveBeenCalledWith(
|
||
"Emulation.setEmulatedMedia",
|
||
{ media: "print" }
|
||
);
|
||
expect(sendCommand).toHaveBeenCalledWith(
|
||
"Emulation.setEmulatedMedia",
|
||
{ media: "screen" }
|
||
);
|
||
expect(sendCommand).toHaveBeenCalledWith(
|
||
"Page.captureScreenshot",
|
||
expect.objectContaining({
|
||
format: "png",
|
||
clip: expect.objectContaining({ scale: 3.125 })
|
||
})
|
||
);
|
||
expect(detach).toHaveBeenCalledOnce();
|
||
});
|
||
|
||
it("媒体布局永久不返回时报告局部超时", async () => {
|
||
let attached = false;
|
||
const webContents = {
|
||
executeJavaScript: vi.fn(() => new Promise(() => undefined)),
|
||
debugger: {
|
||
isAttached: vi.fn(() => attached),
|
||
attach: vi.fn(() => {
|
||
attached = true;
|
||
}),
|
||
detach: vi.fn(() => {
|
||
attached = false;
|
||
}),
|
||
sendCommand: vi.fn(async () => undefined)
|
||
}
|
||
} as unknown as WebContents;
|
||
|
||
await expect(
|
||
captureDocxMediaWithElectronWebContents(
|
||
webContents,
|
||
request,
|
||
undefined,
|
||
{ renderMs: 10, screenshotMs: 10 }
|
||
)
|
||
).rejects.toThrow("桌面 DOCX 媒体布局超过 10ms");
|
||
});
|
||
|
||
it("单个 PNG 永久不返回时报告媒体编号和类型", async () => {
|
||
let attached = false;
|
||
const detach = vi.fn(() => {
|
||
attached = false;
|
||
});
|
||
const webContents = {
|
||
executeJavaScript: vi.fn(async () => plan),
|
||
debugger: {
|
||
isAttached: vi.fn(() => attached),
|
||
attach: vi.fn(() => {
|
||
attached = true;
|
||
}),
|
||
detach,
|
||
sendCommand: vi.fn((method: string) =>
|
||
method === "Page.captureScreenshot"
|
||
? new Promise(() => undefined)
|
||
: Promise.resolve(undefined)
|
||
)
|
||
}
|
||
} as unknown as WebContents;
|
||
|
||
await expect(
|
||
captureDocxMediaWithElectronWebContents(
|
||
webContents,
|
||
request,
|
||
undefined,
|
||
{ renderMs: 10, screenshotMs: 10 }
|
||
)
|
||
).rejects.toThrow(
|
||
"桌面 DOCX 第 1/1 个媒体(image)PNG 捕获超过 10ms"
|
||
);
|
||
expect(detach).toHaveBeenCalledOnce();
|
||
});
|
||
});
|