feat: 完成 DOCX R4 元素级视觉门禁

建立 Chromium、Word 与 WPS 的可编辑内容、段落几何、页眉页脚、封面、媒体和逐页视觉比较链路。

支持封面独立分节、正文页码重启、主题页边距与横向纸张,并将自然分页差异降为诊断项。

修正代码块内边距和折叠表格单元格边框映射,14 套主题生产矩阵与六组布局视觉矩阵通过。
This commit is contained in:
SkyJourney
2026-08-02 03:27:11 +08:00
parent f9f5fccfc9
commit 58f87cc19f
100 changed files with 10409 additions and 386 deletions
+38 -1
View File
@@ -11,6 +11,7 @@ import {
export interface PandocMediaMapItem {
id: string;
binding: string;
path: string;
alt_text: string;
caption?: string;
@@ -18,6 +19,19 @@ export interface PandocMediaMapItem {
height: string;
}
export interface PandocMediaLayoutItem {
id: string;
binding: string;
kind: DocxMediaKind;
ordinal: number;
altText: string;
alignment: PreparedDocxMedia["resources"][number]["alignment"];
displayWidthPx: number;
displayHeightPx: number;
widthEmu: number;
heightEmu: number;
}
export interface PandocMediaMap {
image: PandocMediaMapItem[];
mermaid: PandocMediaMapItem[];
@@ -32,8 +46,12 @@ export interface PandocMediaFile {
export interface PreparedPandocMedia {
map: PandocMediaMap;
files: PandocMediaFile[];
layout: PandocMediaLayoutItem[];
}
export const DOCX_MEDIA_BINDING_PREFIX = "mdtp-media:";
const EMUS_PER_CSS_PIXEL = 9_525;
function pixelsToMillimeters(value: number) {
return (value * 25.4) / DOCX_MEDIA_CSS_DPI;
}
@@ -91,6 +109,7 @@ export function preparePandocMedia(
echarts: []
};
const files: PandocMediaFile[] = [];
const layout: PandocMediaLayoutItem[] = [];
const ids = new Set<string>();
let totalBytes = 0;
const kindCounts: Record<DocxMediaKind, number> = {
@@ -129,8 +148,10 @@ export function preparePandocMedia(
const relativePath = `media/media-${String(
resource.ordinal
).padStart(3, "0")}.png`;
const binding = `${DOCX_MEDIA_BINDING_PREFIX}${resource.id}`;
map[resource.kind].push({
id: resource.id,
binding,
path: relativePath,
alt_text: resource.altText || `${resource.kind} 图片`,
...(resource.caption
@@ -139,6 +160,22 @@ export function preparePandocMedia(
width: physicalLength(resource.displayWidthPx),
height: physicalLength(resource.displayHeightPx)
});
layout.push({
id: resource.id,
binding,
kind: resource.kind,
ordinal: resource.ordinal,
altText: resource.altText || `${resource.kind} 图片`,
alignment: resource.alignment,
displayWidthPx: resource.displayWidthPx,
displayHeightPx: resource.displayHeightPx,
widthEmu: Math.round(
resource.displayWidthPx * EMUS_PER_CSS_PIXEL
),
heightEmu: Math.round(
resource.displayHeightPx * EMUS_PER_CSS_PIXEL
)
});
files.push({
relativePath,
content: resource.content
@@ -147,5 +184,5 @@ export function preparePandocMedia(
if (media.totalBytes !== totalBytes) {
throw new Error("DOCX 媒体总大小声明不一致");
}
return { map, files };
return { map, files, layout };
}