fix: 增强DOCX字体实际使用门禁
This commit is contained in:
@@ -172,6 +172,11 @@ function inspectDocx(content) {
|
|||||||
const fontNames = [
|
const fontNames = [
|
||||||
...fontTableXml.matchAll(/<w:font\s+w:name="([^"]+)"/gu)
|
...fontTableXml.matchAll(/<w:font\s+w:name="([^"]+)"/gu)
|
||||||
].map((match) => match[1]);
|
].map((match) => match[1]);
|
||||||
|
const embeddedFontNames = [
|
||||||
|
...fontTableXml.matchAll(/<w:font\s+w:name="([^"]+)"[\s\S]*?<\/w:font>/gu)
|
||||||
|
].flatMap((match) => /<w:embed(?:Regular|Bold|Italic|BoldItalic)\b/u.test(match[0])
|
||||||
|
? [match[1]]
|
||||||
|
: []);
|
||||||
const paragraphs = [
|
const paragraphs = [
|
||||||
...documentXml.matchAll(/<w:p(?:\s|>)[\s\S]*?<\/w:p>/gu)
|
...documentXml.matchAll(/<w:p(?:\s|>)[\s\S]*?<\/w:p>/gu)
|
||||||
].map((match) => match[0]);
|
].map((match) => match[0]);
|
||||||
@@ -205,6 +210,9 @@ function inspectDocx(content) {
|
|||||||
fontNames: [...new Set(fontNames)].sort((first, second) =>
|
fontNames: [...new Set(fontNames)].sort((first, second) =>
|
||||||
first.localeCompare(second, "en")
|
first.localeCompare(second, "en")
|
||||||
),
|
),
|
||||||
|
embeddedFontNames: [...new Set(embeddedFontNames)].sort((first, second) =>
|
||||||
|
first.localeCompare(second, "en")
|
||||||
|
),
|
||||||
optionalFontPackApplied: fontTableXml.includes("MdTP Serif SC"),
|
optionalFontPackApplied: fontTableXml.includes("MdTP Serif SC"),
|
||||||
hasAltChunk: /<w:altChunk(?:\s|>)/u.test(documentXml),
|
hasAltChunk: /<w:altChunk(?:\s|>)/u.test(documentXml),
|
||||||
internalMarkerCount:
|
internalMarkerCount:
|
||||||
@@ -448,12 +456,6 @@ try {
|
|||||||
const enhancedThemes = results.filter(
|
const enhancedThemes = results.filter(
|
||||||
(result) => result.docx.inspection.optionalFontPackApplied
|
(result) => result.docx.inspection.optionalFontPackApplied
|
||||||
);
|
);
|
||||||
if (themes.some((theme) => theme.id === "gov-red-standard")) {
|
|
||||||
assert(
|
|
||||||
enhancedThemes.some((result) => result.id === "gov-red-standard"),
|
|
||||||
"有效字体包未增强 gov-red-standard"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
assert(
|
assert(
|
||||||
result.pdf.diagnostics.pageCount > 0,
|
result.pdf.diagnostics.pageCount > 0,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { aggregatePdfTextLines, buildPageContentText, normalizePdfText } from ".
|
|||||||
import type {
|
import type {
|
||||||
CreatePdfSnapshotOptions,
|
CreatePdfSnapshotOptions,
|
||||||
PdfDocumentSnapshot,
|
PdfDocumentSnapshot,
|
||||||
|
PdfFontSnapshot,
|
||||||
PdfPageSnapshot,
|
PdfPageSnapshot,
|
||||||
PdfSnapshotLimits,
|
PdfSnapshotLimits,
|
||||||
PdfTextItemSnapshot,
|
PdfTextItemSnapshot,
|
||||||
@@ -25,6 +26,13 @@ interface PdfJsTextStyle {
|
|||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PdfJsResolvedFont {
|
||||||
|
name?: string;
|
||||||
|
fallbackName?: string;
|
||||||
|
isType3Font?: boolean;
|
||||||
|
missingFile?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const DEFAULT_PDF_SNAPSHOT_LIMITS: PdfSnapshotLimits = {
|
export const DEFAULT_PDF_SNAPSHOT_LIMITS: PdfSnapshotLimits = {
|
||||||
maxPdfBytes: 100 * 1024 * 1024,
|
maxPdfBytes: 100 * 1024 * 1024,
|
||||||
maxPages: 500,
|
maxPages: 500,
|
||||||
@@ -60,6 +68,7 @@ function createTextItemSnapshot(
|
|||||||
item: PdfJsTextItem,
|
item: PdfJsTextItem,
|
||||||
pageHeightPt: number,
|
pageHeightPt: number,
|
||||||
styles: Readonly<Record<string, PdfJsTextStyle>>,
|
styles: Readonly<Record<string, PdfJsTextStyle>>,
|
||||||
|
fonts: ReadonlyMap<string, PdfFontSnapshot>,
|
||||||
): PdfTextItemSnapshot | undefined {
|
): PdfTextItemSnapshot | undefined {
|
||||||
const normalizedText = normalizePdfText(item.str);
|
const normalizedText = normalizePdfText(item.str);
|
||||||
if (!normalizedText) {
|
if (!normalizedText) {
|
||||||
@@ -77,7 +86,8 @@ function createTextItemSnapshot(
|
|||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
const baselineY = pageHeightPt - baselineFromBottom;
|
const baselineY = pageHeightPt - baselineFromBottom;
|
||||||
const fontFamily = styles[item.fontName]?.fontFamily;
|
const font = fonts.get(item.fontName);
|
||||||
|
const fontFamily = font?.name ?? styles[item.fontName]?.fontFamily;
|
||||||
return {
|
return {
|
||||||
text: item.str,
|
text: item.str,
|
||||||
normalizedText,
|
normalizedText,
|
||||||
@@ -90,10 +100,45 @@ function createTextItemSnapshot(
|
|||||||
baselineY,
|
baselineY,
|
||||||
fontName: item.fontName,
|
fontName: item.fontName,
|
||||||
...(fontFamily ? { fontFamily } : {}),
|
...(fontFamily ? { fontFamily } : {}),
|
||||||
|
...(font?.fallbackFamily
|
||||||
|
? { fallbackFontFamily: font.fallbackFamily }
|
||||||
|
: {}),
|
||||||
hasEol: item.hasEOL,
|
hasEol: item.hasEOL,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePdfFontName(value: string) {
|
||||||
|
return value.replace(/^[A-Z]{6}\+/u, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePageFonts(
|
||||||
|
page: Awaited<ReturnType<Awaited<ReturnType<typeof getDocument>["promise"]>["getPage"]>>,
|
||||||
|
fontNames: readonly string[],
|
||||||
|
) {
|
||||||
|
const fonts = new Map<string, PdfFontSnapshot>();
|
||||||
|
for (const internalName of fontNames) {
|
||||||
|
try {
|
||||||
|
const resolved = page.commonObjs.get(internalName) as PdfJsResolvedFont;
|
||||||
|
const name = resolved.name?.trim();
|
||||||
|
if (!name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fonts.set(internalName, {
|
||||||
|
internalName,
|
||||||
|
name: normalizePdfFontName(name),
|
||||||
|
...(resolved.fallbackName
|
||||||
|
? { fallbackFamily: resolved.fallbackName }
|
||||||
|
: {}),
|
||||||
|
isType3Font: resolved.isType3Font === true,
|
||||||
|
missingFile: resolved.missingFile === true,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// PDF.js 可能不给未实际绘制的字体建立公共对象;保留文本但不伪造字体。
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fonts;
|
||||||
|
}
|
||||||
|
|
||||||
function resolveLimits(
|
function resolveLimits(
|
||||||
input: Partial<PdfSnapshotLimits> | undefined,
|
input: Partial<PdfSnapshotLimits> | undefined,
|
||||||
): PdfSnapshotLimits {
|
): PdfSnapshotLimits {
|
||||||
@@ -145,6 +190,17 @@ export async function createPdfDocumentSnapshot(
|
|||||||
disableNormalization: false,
|
disableNormalization: false,
|
||||||
includeMarkedContent: false,
|
includeMarkedContent: false,
|
||||||
});
|
});
|
||||||
|
await page.getOperatorList();
|
||||||
|
const pageFonts = resolvePageFonts(
|
||||||
|
page,
|
||||||
|
[
|
||||||
|
...new Set(
|
||||||
|
textContent.items.flatMap((item) =>
|
||||||
|
isTextItem(item) ? [item.fontName] : [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
const styles = textContent.styles as Readonly<
|
const styles = textContent.styles as Readonly<
|
||||||
Record<string, PdfJsTextStyle>
|
Record<string, PdfJsTextStyle>
|
||||||
>;
|
>;
|
||||||
@@ -156,6 +212,7 @@ export async function createPdfDocumentSnapshot(
|
|||||||
item,
|
item,
|
||||||
pointViewport.height,
|
pointViewport.height,
|
||||||
styles,
|
styles,
|
||||||
|
pageFonts,
|
||||||
);
|
);
|
||||||
return snapshot ? [snapshot] : [];
|
return snapshot ? [snapshot] : [];
|
||||||
});
|
});
|
||||||
@@ -168,6 +225,9 @@ export async function createPdfDocumentSnapshot(
|
|||||||
items,
|
items,
|
||||||
lines,
|
lines,
|
||||||
contentText: buildPageContentText(lines),
|
contentText: buildPageContentText(lines),
|
||||||
|
fonts: [...pageFonts.values()].sort((left, right) =>
|
||||||
|
left.name.localeCompare(right.name, "en"),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
const pageNumberLine = lines.find((line) => line.role === "page-number");
|
const pageNumberLine = lines.find((line) => line.role === "page-number");
|
||||||
if (pageNumberLine) {
|
if (pageNumberLine) {
|
||||||
@@ -218,12 +278,20 @@ export async function createPdfDocumentSnapshot(
|
|||||||
.map((page) => page.contentText)
|
.map((page) => page.contentText)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join("\n\f\n");
|
.join("\n\f\n");
|
||||||
|
const fonts = [
|
||||||
|
...new Map(
|
||||||
|
pages
|
||||||
|
.flatMap((page) => page.fonts)
|
||||||
|
.map((font) => [font.name.toLocaleLowerCase("en-US"), font]),
|
||||||
|
).values(),
|
||||||
|
].sort((left, right) => left.name.localeCompare(right.name, "en"));
|
||||||
return {
|
return {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
source: options.source,
|
source: options.source,
|
||||||
sha256: sha256(pdfBytes),
|
sha256: sha256(pdfBytes),
|
||||||
pageCount: pages.length,
|
pageCount: pages.length,
|
||||||
contentText,
|
contentText,
|
||||||
|
fonts,
|
||||||
pages,
|
pages,
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -20,9 +20,18 @@ export interface PdfTextItemSnapshot {
|
|||||||
baselineY: number;
|
baselineY: number;
|
||||||
fontName?: string;
|
fontName?: string;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
|
fallbackFontFamily?: string;
|
||||||
hasEol: boolean;
|
hasEol: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PdfFontSnapshot {
|
||||||
|
internalName: string;
|
||||||
|
name: string;
|
||||||
|
fallbackFamily?: string;
|
||||||
|
isType3Font: boolean;
|
||||||
|
missingFile: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type PdfTextLineRole = "content" | "page-number";
|
export type PdfTextLineRole = "content" | "page-number";
|
||||||
|
|
||||||
export interface PdfTextLineSnapshot {
|
export interface PdfTextLineSnapshot {
|
||||||
@@ -132,6 +141,7 @@ export interface PdfPageSnapshot {
|
|||||||
items: PdfTextItemSnapshot[];
|
items: PdfTextItemSnapshot[];
|
||||||
lines: PdfTextLineSnapshot[];
|
lines: PdfTextLineSnapshot[];
|
||||||
contentText: string;
|
contentText: string;
|
||||||
|
fonts: PdfFontSnapshot[];
|
||||||
pageNumberText?: string;
|
pageNumberText?: string;
|
||||||
raster?: PdfPageRaster;
|
raster?: PdfPageRaster;
|
||||||
}
|
}
|
||||||
@@ -142,6 +152,7 @@ export interface PdfDocumentSnapshot {
|
|||||||
sha256: string;
|
sha256: string;
|
||||||
pageCount: number;
|
pageCount: number;
|
||||||
contentText: string;
|
contentText: string;
|
||||||
|
fonts: PdfFontSnapshot[];
|
||||||
pages: PdfPageSnapshot[];
|
pages: PdfPageSnapshot[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,18 @@ describe("PDF.js 页面快照", () => {
|
|||||||
expect(first.pages[0]?.widthPt).toBeCloseTo(595, 3);
|
expect(first.pages[0]?.widthPt).toBeCloseTo(595, 3);
|
||||||
expect(first.pages[0]?.heightPt).toBeCloseTo(842, 3);
|
expect(first.pages[0]?.heightPt).toBeCloseTo(842, 3);
|
||||||
expect(first.contentText).toContain("Visual diff fixture");
|
expect(first.contentText).toContain("Visual diff fixture");
|
||||||
|
expect(first.fonts).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
name: "Helvetica",
|
||||||
|
fallbackFamily: "sans-serif",
|
||||||
|
isType3Font: false,
|
||||||
|
missingFile: true,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
expect(first.pages[0]?.items[0]).toMatchObject({
|
||||||
|
fontFamily: "Helvetica",
|
||||||
|
fallbackFontFamily: "sans-serif",
|
||||||
|
});
|
||||||
expect(first.pages[0]?.raster).toMatchObject({
|
expect(first.pages[0]?.raster).toMatchObject({
|
||||||
widthPx: 1190,
|
widthPx: 1190,
|
||||||
heightPx: 1684,
|
heightPx: 1684,
|
||||||
|
|||||||
@@ -101,6 +101,14 @@ export function readBundledThemeMatrixDefinitions(themesDirectory) {
|
|||||||
compatibleProfiles: Array.isArray(manifest.compatibleProfiles)
|
compatibleProfiles: Array.isArray(manifest.compatibleProfiles)
|
||||||
? [...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
|
themeDefaultMargins: manifest.pageDefaults?.margins
|
||||||
? structuredClone(manifest.pageDefaults.margins)
|
? structuredClone(manifest.pageDefaults.margins)
|
||||||
: undefined
|
: undefined
|
||||||
@@ -109,6 +117,68 @@ export function readBundledThemeMatrixDefinitions(themesDirectory) {
|
|||||||
.sort((left, right) => left.id.localeCompare(right.id, "en"));
|
.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) {
|
function createPaperConfig(orientation, marginScenario) {
|
||||||
return {
|
return {
|
||||||
format: "A4",
|
format: "A4",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
createDocxLayoutVisualMatrixCases,
|
createDocxLayoutVisualMatrixCases,
|
||||||
DOCX_LAYOUT_MATRIX_MARGIN_SCENARIOS,
|
DOCX_LAYOUT_MATRIX_MARGIN_SCENARIOS,
|
||||||
DOCX_LAYOUT_MATRIX_ORIENTATIONS,
|
DOCX_LAYOUT_MATRIX_ORIENTATIONS,
|
||||||
|
getDocxFontGateFailures,
|
||||||
readBundledThemeMatrixDefinitions,
|
readBundledThemeMatrixDefinitions,
|
||||||
summarizeDocxLayoutVisualMatrix
|
summarizeDocxLayoutVisualMatrix
|
||||||
} from "./docx-layout-visual-matrix-cases.mjs";
|
} from "./docx-layout-visual-matrix-cases.mjs";
|
||||||
@@ -34,6 +35,38 @@ test("生成 14×2×5 的完整 DOCX 布局视觉矩阵", () => {
|
|||||||
assert.deepEqual(summary.orientations, ["portrait", "landscape"]);
|
assert.deepEqual(summary.orientations, ["portrait", "landscape"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("字体门禁区分缺少声明、缺少嵌入和 Office 未实际采用", () => {
|
||||||
|
const missing = getDocxFontGateFailures({
|
||||||
|
theme: { id: "missing", docxFontFaces: [] },
|
||||||
|
inspection: { embeddedFontPartCount: 0, embeddedFontNames: [] },
|
||||||
|
renderedFonts: [],
|
||||||
|
engine: "word"
|
||||||
|
});
|
||||||
|
assert.equal(missing.length, 2);
|
||||||
|
|
||||||
|
const fallback = getDocxFontGateFailures({
|
||||||
|
theme: {
|
||||||
|
id: "declared",
|
||||||
|
docxFontFaces: [{ family: "FandolSong", aliases: [], weight: 400, style: "normal" }]
|
||||||
|
},
|
||||||
|
inspection: { embeddedFontPartCount: 1, embeddedFontNames: ["MdTP Serif SC"] },
|
||||||
|
renderedFonts: [{ name: "SimSun" }],
|
||||||
|
engine: "word"
|
||||||
|
});
|
||||||
|
assert.deepEqual(fallback, ["Microsoft Word 输出未实际使用 DOCX 嵌入字体"]);
|
||||||
|
|
||||||
|
const embedded = getDocxFontGateFailures({
|
||||||
|
theme: {
|
||||||
|
id: "declared",
|
||||||
|
docxFontFaces: [{ family: "FandolSong", aliases: [], weight: 400, style: "normal" }]
|
||||||
|
},
|
||||||
|
inspection: { embeddedFontPartCount: 1, embeddedFontNames: ["MdTP Serif SC"] },
|
||||||
|
renderedFonts: [{ name: "___WRD_EMBED_SUB_65" }],
|
||||||
|
engine: "word"
|
||||||
|
});
|
||||||
|
assert.deepEqual(embedded, []);
|
||||||
|
});
|
||||||
|
|
||||||
test("每套主题都覆盖两个方向和五组边距", () => {
|
test("每套主题都覆盖两个方向和五组边距", () => {
|
||||||
const { themes, cases } = matrix();
|
const { themes, cases } = matrix();
|
||||||
for (const theme of themes) {
|
for (const theme of themes) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
} from "../packages/preview-engine/dist/index.js";
|
} from "../packages/preview-engine/dist/index.js";
|
||||||
import {
|
import {
|
||||||
createDocxLayoutVisualMatrixCases,
|
createDocxLayoutVisualMatrixCases,
|
||||||
|
getDocxFontGateFailures,
|
||||||
readBundledThemeMatrixDefinitions,
|
readBundledThemeMatrixDefinitions,
|
||||||
summarizeDocxLayoutVisualMatrix
|
summarizeDocxLayoutVisualMatrix
|
||||||
} from "./docx-layout-visual-matrix-cases.mjs";
|
} from "./docx-layout-visual-matrix-cases.mjs";
|
||||||
@@ -568,14 +569,26 @@ for (const caseDefinition of selectedCases) {
|
|||||||
writeReportArtifacts(rasterDirectory, "wps", wpsReport);
|
writeReportArtifacts(rasterDirectory, "wps", wpsReport);
|
||||||
writeReportArtifacts(rasterDirectory, "office", officeReport);
|
writeReportArtifacts(rasterDirectory, "office", officeReport);
|
||||||
|
|
||||||
const currentFailures = [
|
const currentFailures = [...new Set([
|
||||||
...pageGeometryFailures(chromium, caseDefinition, "Chromium"),
|
...pageGeometryFailures(chromium, caseDefinition, "Chromium"),
|
||||||
...pageGeometryFailures(word, caseDefinition, "Microsoft Word"),
|
...pageGeometryFailures(word, caseDefinition, "Microsoft Word"),
|
||||||
...pageGeometryFailures(wps, caseDefinition, "WPS Writer"),
|
...pageGeometryFailures(wps, caseDefinition, "WPS Writer"),
|
||||||
|
...getDocxFontGateFailures({
|
||||||
|
theme: themeDefinitions.find((theme) => theme.id === caseDefinition.themeId),
|
||||||
|
inspection: result.docx.inspection,
|
||||||
|
renderedFonts: word.fonts,
|
||||||
|
engine: "word"
|
||||||
|
}),
|
||||||
|
...getDocxFontGateFailures({
|
||||||
|
theme: themeDefinitions.find((theme) => theme.id === caseDefinition.themeId),
|
||||||
|
inspection: result.docx.inspection,
|
||||||
|
renderedFonts: wps.fonts,
|
||||||
|
engine: "wps"
|
||||||
|
}),
|
||||||
...reportGateFailures(wordReport, "Chromium/Word"),
|
...reportGateFailures(wordReport, "Chromium/Word"),
|
||||||
...reportGateFailures(wpsReport, "Chromium/WPS"),
|
...reportGateFailures(wpsReport, "Chromium/WPS"),
|
||||||
...reportGateFailures(officeReport, "Word/WPS")
|
...reportGateFailures(officeReport, "Word/WPS")
|
||||||
];
|
])];
|
||||||
gateFailures.push(
|
gateFailures.push(
|
||||||
...currentFailures.map((failure) => `${caseDefinition.id}: ${failure}`)
|
...currentFailures.map((failure) => `${caseDefinition.id}: ${failure}`)
|
||||||
);
|
);
|
||||||
@@ -595,6 +608,14 @@ for (const caseDefinition of selectedCases) {
|
|||||||
word: word.pageCount,
|
word: word.pageCount,
|
||||||
wps: wps.pageCount
|
wps: wps.pageCount
|
||||||
},
|
},
|
||||||
|
fonts: {
|
||||||
|
declared: themeDefinitions.find((theme) => theme.id === caseDefinition.themeId)?.docxFontFaces ?? [],
|
||||||
|
embeddedNames: result.docx.inspection.embeddedFontNames,
|
||||||
|
embeddedPartCount: result.docx.inspection.embeddedFontPartCount,
|
||||||
|
chromium: chromium.fonts,
|
||||||
|
word: word.fonts,
|
||||||
|
wps: wps.fonts
|
||||||
|
},
|
||||||
editableParagraphCount: editable.paragraphs.length,
|
editableParagraphCount: editable.paragraphs.length,
|
||||||
reports: {
|
reports: {
|
||||||
word: reportSummary(wordReport),
|
word: reportSummary(wordReport),
|
||||||
|
|||||||
Reference in New Issue
Block a user