fix: 增强DOCX字体实际使用门禁

This commit is contained in:
SkyJourney
2026-08-03 11:32:06 +08:00
parent f0fff7f726
commit a094dabf02
7 changed files with 226 additions and 9 deletions
@@ -101,6 +101,14 @@ export function readBundledThemeMatrixDefinitions(themesDirectory) {
compatibleProfiles: Array.isArray(manifest.compatibleProfiles)
? [...manifest.compatibleProfiles]
: [],
docxFontFaces: Array.isArray(manifest.docxFonts?.faces)
? manifest.docxFonts.faces.map((face) => ({
family: face.family,
aliases: Array.isArray(face.aliases) ? [...face.aliases] : [],
weight: face.weight ?? 400,
style: face.style ?? "normal"
}))
: [],
themeDefaultMargins: manifest.pageDefaults?.margins
? structuredClone(manifest.pageDefaults.margins)
: undefined
@@ -109,6 +117,68 @@ export function readBundledThemeMatrixDefinitions(themesDirectory) {
.sort((left, right) => left.id.localeCompare(right.id, "en"));
}
function normalizeFontName(value) {
return value
.replace(/^[A-Z]{6}\+/u, "")
.replace(/(?:[-, ](?:regular|bold|italic|bolditalic|roman|medium|light|black))+$/iu, "")
.replace(/[\s_-]+/gu, "")
.toLocaleLowerCase("en-US");
}
function isOfficeEmbeddedAlias(value, engine) {
return engine === "word"
? /^___WRD_EMBED_SUB_/iu.test(value)
: engine === "wps"
? /^WPSEMBED\d+$/iu.test(value)
: false;
}
export function getDocxFontGateFailures({
theme,
inspection,
renderedFonts,
engine
}) {
assert(theme && typeof theme.id === "string", "字体门禁缺少主题定义");
assert(inspection && typeof inspection === "object", "字体门禁缺少 DOCX 检查结果");
assert(Array.isArray(renderedFonts), "字体门禁缺少实际渲染字体");
assert(engine === "word" || engine === "wps", "字体门禁引擎必须为 word 或 wps");
const failures = [];
const declaredFaces = Array.isArray(theme.docxFontFaces)
? theme.docxFontFaces
: [];
const embeddedNames = Array.isArray(inspection.embeddedFontNames)
? inspection.embeddedFontNames
: [];
const embeddedPartCount = Number(inspection.embeddedFontPartCount ?? 0);
if (declaredFaces.length === 0) {
failures.push(`主题 ${theme.id} 未声明任何 DOCX 字体`);
}
if (embeddedPartCount === 0) {
failures.push(`主题 ${theme.id} 的 DOCX 没有嵌入字体部件`);
}
if (declaredFaces.length > 0 && embeddedPartCount !== declaredFaces.length) {
failures.push(
`主题 ${theme.id} 声明 ${declaredFaces.length} 个字体面,但 DOCX 实际嵌入 ${embeddedPartCount} 个部件`
);
}
if (embeddedPartCount > 0) {
const expected = new Set(embeddedNames.map(normalizeFontName));
const actuallyUsed = renderedFonts.some((font) => {
const name = typeof font === "string" ? font : font?.name;
return typeof name === "string" && (
isOfficeEmbeddedAlias(name, engine) || expected.has(normalizeFontName(name))
);
});
if (!actuallyUsed) {
failures.push(
`${engine === "word" ? "Microsoft Word" : "WPS Writer"} 输出未实际使用 DOCX 嵌入字体`
);
}
}
return failures;
}
function createPaperConfig(orientation, marginScenario) {
return {
format: "A4",