feat: 完成 DOCX R4 元素级视觉门禁
建立 Chromium、Word 与 WPS 的可编辑内容、段落几何、页眉页脚、封面、媒体和逐页视觉比较链路。 支持封面独立分节、正文页码重启、主题页边距与横向纸张,并将自然分页差异降为诊断项。 修正代码块内边距和折叠表格单元格边框映射,14 套主题生产矩阵与六组布局视觉矩阵通过。
This commit is contained in:
@@ -186,13 +186,25 @@ const htmlRoles: Readonly<Record<SemanticDocumentRole, HtmlRole>> = {
|
||||
}
|
||||
};
|
||||
|
||||
function renderNode(node: SemanticDocumentNode): string {
|
||||
function renderNode(
|
||||
node: SemanticDocumentNode,
|
||||
options: {
|
||||
regionKind?: "cover";
|
||||
breakAfter?: "next-page";
|
||||
} = {}
|
||||
): string {
|
||||
const role = htmlRoles[node.role];
|
||||
const content =
|
||||
node.kind === "group"
|
||||
? node.children.map(renderNode).join("")
|
||||
? node.children.map((child) => renderNode(child)).join("")
|
||||
: `${node.label ? `<span>${escapeHtml(node.label)}</span>` : ""}${escapeHtml(node.text)}`;
|
||||
return `<${role.tagName} class="${role.className}">${content}</${role.tagName}>`;
|
||||
const regionAttribute = options.regionKind
|
||||
? ` data-semantic-region="${options.regionKind}"`
|
||||
: "";
|
||||
const breakAttribute = options.breakAfter
|
||||
? ` data-semantic-break-after="${options.breakAfter}"`
|
||||
: "";
|
||||
return `<${role.tagName} class="${role.className}"${regionAttribute}${breakAttribute}>${content}</${role.tagName}>`;
|
||||
}
|
||||
|
||||
export function renderDocumentStructure(
|
||||
@@ -206,13 +218,24 @@ export function renderDocumentStructure(
|
||||
(region) =>
|
||||
region.kind === "cover" || region.kind === "prefix"
|
||||
)
|
||||
.flatMap((region) => region.nodes)
|
||||
.map(renderNode)
|
||||
.flatMap((region) =>
|
||||
region.nodes.map((node, index) =>
|
||||
renderNode(node, {
|
||||
...(region.kind === "cover"
|
||||
? { regionKind: "cover" as const }
|
||||
: {}),
|
||||
...(index === region.nodes.length - 1 &&
|
||||
region.section?.breakAfter
|
||||
? { breakAfter: region.section.breakAfter }
|
||||
: {})
|
||||
})
|
||||
)
|
||||
)
|
||||
.join("");
|
||||
const suffixHtml = model.regions
|
||||
.filter((region) => region.kind === "suffix")
|
||||
.flatMap((region) => region.nodes)
|
||||
.map(renderNode)
|
||||
.map((node) => renderNode(node))
|
||||
.join("");
|
||||
return {
|
||||
profile: model.profile,
|
||||
|
||||
@@ -199,6 +199,12 @@ document:
|
||||
expect(projectReport.articleHtml).toContain(
|
||||
'class="doc-cover doc-cover-project-report"'
|
||||
);
|
||||
expect(projectReport.articleHtml).toContain(
|
||||
'data-semantic-region="cover"'
|
||||
);
|
||||
expect(projectReport.articleHtml).toContain(
|
||||
'data-semantic-break-after="next-page"'
|
||||
);
|
||||
expect(tender.articleHtml).toContain(
|
||||
'class="doc-cover doc-cover-tender"'
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user