feat: 将主题令牌接入 DOCX 动态模板
This commit is contained in:
@@ -6,6 +6,10 @@ import {
|
||||
type ExportConfig,
|
||||
type ThemeManifest
|
||||
} from "@md-to-pdf/core";
|
||||
import type {
|
||||
DocxResolvedStyleSlot,
|
||||
DocxThemeTokenSet
|
||||
} from "@md-to-pdf/docx-theme-engine";
|
||||
import {
|
||||
createDynamicReferenceDocx,
|
||||
validateGeneratedDocx,
|
||||
@@ -129,6 +133,21 @@ function theme(
|
||||
};
|
||||
}
|
||||
|
||||
function themeTokens(
|
||||
fingerprint = "c".repeat(64),
|
||||
slots: DocxResolvedStyleSlot[] = []
|
||||
): DocxThemeTokenSet {
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
themeId: "test-theme",
|
||||
themeFingerprint: fingerprint,
|
||||
mode: "auto-with-overrides",
|
||||
basePreset: "technical",
|
||||
slots,
|
||||
diagnostics: []
|
||||
};
|
||||
}
|
||||
|
||||
function createOptions(exportConfig: ExportConfig) {
|
||||
return {
|
||||
exportConfig,
|
||||
@@ -137,7 +156,8 @@ function createOptions(exportConfig: ExportConfig) {
|
||||
metadata: {
|
||||
title: "年度 <报告>",
|
||||
author: "测试人"
|
||||
}
|
||||
},
|
||||
themeTokens: themeTokens()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -159,6 +179,10 @@ describe("动态 reference.docx", () => {
|
||||
author: "测试人"
|
||||
}
|
||||
});
|
||||
const changedTokens = createDynamicReferenceDocx(baseline, {
|
||||
...createOptions(defaultExportConfig),
|
||||
themeTokens: themeTokens("d".repeat(64))
|
||||
});
|
||||
const entries = unzipSync(first.content);
|
||||
const documentXml = decoder.decode(entries["word/document.xml"]);
|
||||
const stylesXml = decoder.decode(entries["word/styles.xml"]);
|
||||
@@ -169,6 +193,7 @@ describe("动态 reference.docx", () => {
|
||||
);
|
||||
expect(first.cacheKey).toBe(second.cacheKey);
|
||||
expect(first.cacheKey).not.toBe(changedMetadata.cacheKey);
|
||||
expect(first.cacheKey).not.toBe(changedTokens.cacheKey);
|
||||
expect(documentXml).toContain('w:w="11906"');
|
||||
expect(documentXml).toContain('w:h="16838"');
|
||||
expect(documentXml).toContain('w:top="907"');
|
||||
@@ -186,6 +211,106 @@ describe("动态 reference.docx", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("将通用主题令牌写入标准样式、结构样式和字体部件", () => {
|
||||
const result = createDynamicReferenceDocx(
|
||||
createBaselineReference(),
|
||||
{
|
||||
...createOptions(defaultExportConfig),
|
||||
themeTokens: themeTokens("e".repeat(64), [
|
||||
{
|
||||
slot: "paragraph",
|
||||
source: "computed-css",
|
||||
confidence: "exact",
|
||||
style: {
|
||||
fontCandidates: [
|
||||
"Source Han Serif SC",
|
||||
"Times New Roman"
|
||||
],
|
||||
fontSizePt: 14,
|
||||
color: "#112233",
|
||||
lineSpacing: 1.8,
|
||||
firstLineIndentPt: 28
|
||||
}
|
||||
},
|
||||
{
|
||||
slot: "heading-1",
|
||||
source: "computed-css",
|
||||
confidence: "exact",
|
||||
style: {
|
||||
fontCandidates: ["SimHei", "Arial"],
|
||||
fontSizePt: 22,
|
||||
bold: true,
|
||||
color: "#aa0000",
|
||||
alignment: "center",
|
||||
keepWithNext: true
|
||||
}
|
||||
},
|
||||
{
|
||||
slot: "table",
|
||||
source: "computed-css",
|
||||
confidence: "exact",
|
||||
style: {
|
||||
fontCandidates: [],
|
||||
widthPercent: 100,
|
||||
paddingPt: {
|
||||
top: 3,
|
||||
right: 4,
|
||||
bottom: 3,
|
||||
left: 4
|
||||
},
|
||||
borders: {
|
||||
top: {
|
||||
widthPt: 1,
|
||||
color: "#445566",
|
||||
style: "single"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
slot: "official-title",
|
||||
source: "computed-css",
|
||||
confidence: "exact",
|
||||
style: {
|
||||
fontCandidates: ["SimSun"],
|
||||
fontSizePt: 22,
|
||||
color: "#ff0000",
|
||||
alignment: "center",
|
||||
keepWithNext: true
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
);
|
||||
const entries = unzipSync(result.content);
|
||||
const stylesXml = decoder.decode(entries["word/styles.xml"]);
|
||||
const fontTableXml = decoder.decode(
|
||||
entries["word/fontTable.xml"]
|
||||
);
|
||||
const themeXml = decoder.decode(
|
||||
entries["word/theme/theme1.xml"]
|
||||
);
|
||||
|
||||
expect(stylesXml).toContain('w:styleId="MdOfficialTitle"');
|
||||
expect(stylesXml).toContain('w:eastAsia="Source Han Serif SC"');
|
||||
expect(stylesXml).toContain('w:ascii="Times New Roman"');
|
||||
expect(stylesXml).toContain('w:val="112233"');
|
||||
expect(stylesXml).toContain('w:styleId="Heading1"');
|
||||
expect(stylesXml).toContain('w:val="AA0000"');
|
||||
expect(stylesXml).toContain('w:w="5000" w:type="pct"');
|
||||
expect(stylesXml).toContain('w:color="445566"');
|
||||
expect(fontTableXml).toContain(
|
||||
'w:name="Source Han Serif SC"'
|
||||
);
|
||||
expect(fontTableXml).toContain('w:name="SimHei"');
|
||||
expect(themeXml).toContain(
|
||||
'<a:latin typeface="Arial"'
|
||||
);
|
||||
expect(themeXml).toContain(
|
||||
'<a:ea typeface="SimHei"'
|
||||
);
|
||||
});
|
||||
|
||||
it("生成横向、自定义页边距和奇偶首页页眉页脚", () => {
|
||||
const exportConfig: ExportConfig = {
|
||||
...defaultExportConfig,
|
||||
|
||||
Reference in New Issue
Block a user