feat: 完成 DOCX 通用结构映射与严格收口
This commit is contained in:
@@ -46,6 +46,35 @@ interface SlotNormalizationContext {
|
||||
approximate: boolean;
|
||||
}
|
||||
|
||||
function cssLengthToPx(value: string): number {
|
||||
const valuePt = parseCssLengthToPt(value);
|
||||
return valuePt === undefined ? 0 : valuePt / 0.75;
|
||||
}
|
||||
|
||||
function resolveDocumentContentWidthPx(
|
||||
snapshot: DocxThemeStyleSnapshot
|
||||
): number | undefined {
|
||||
const computed = snapshot.slots.find(
|
||||
(entry) => entry.slot === "document"
|
||||
)?.computed;
|
||||
if (!computed) {
|
||||
return undefined;
|
||||
}
|
||||
const widthPt = parseCssLengthToPt(computed.width);
|
||||
if (widthPt === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const borderWidthPx = [computed.borderLeft, computed.borderRight]
|
||||
.map((value) => parseCssBorder(value)?.widthPt ?? 0)
|
||||
.reduce((total, valuePt) => total + valuePt / 0.75, 0);
|
||||
const contentWidthPx =
|
||||
widthPt / 0.75 -
|
||||
cssLengthToPx(computed.paddingLeft) -
|
||||
cssLengthToPx(computed.paddingRight) -
|
||||
borderWidthPx;
|
||||
return contentWidthPx > 0 ? contentWidthPx : widthPt / 0.75;
|
||||
}
|
||||
|
||||
const paragraphKinds = new Set<DocxStyleSlotKind>([
|
||||
"document",
|
||||
"paragraph",
|
||||
@@ -719,14 +748,7 @@ export function resolveDocxThemeTokens(
|
||||
): DocxThemeTokenSet {
|
||||
const snapshot = docxThemeStyleSnapshotSchema.parse(input.snapshot);
|
||||
const diagnostics: DocxThemeDiagnostic[] = [];
|
||||
const documentWidth = snapshot.slots.find(
|
||||
(entry) => entry.slot === "document"
|
||||
)?.computed?.width;
|
||||
const documentWidthPt = documentWidth
|
||||
? parseCssLengthToPt(documentWidth)
|
||||
: undefined;
|
||||
const documentWidthPx =
|
||||
documentWidthPt === undefined ? undefined : documentWidthPt / 0.75;
|
||||
const documentWidthPx = resolveDocumentContentWidthPx(snapshot);
|
||||
const snapshotBySlot = new Map(
|
||||
snapshot.slots.map((entry) => [entry.slot, entry])
|
||||
);
|
||||
|
||||
@@ -178,6 +178,31 @@ describe("DOCX 主题令牌归一化", () => {
|
||||
expect(tokens.slots).toHaveLength(DOCX_STYLE_SLOT_NAMES.length);
|
||||
});
|
||||
|
||||
it("按 border-box 文档的内容区宽度归一化全宽表格", () => {
|
||||
const tokens = resolveDocxThemeTokens({
|
||||
snapshot: createSnapshot({
|
||||
document: {
|
||||
width: "790px",
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
borderLeft: "0px none rgb(17, 34, 51)",
|
||||
borderRight: "0px none rgb(17, 34, 51)"
|
||||
},
|
||||
table: {
|
||||
width: "730px"
|
||||
}
|
||||
}),
|
||||
config: {
|
||||
mode: "auto",
|
||||
basePreset: "general",
|
||||
overrides: {},
|
||||
legacyPreset: false
|
||||
}
|
||||
});
|
||||
|
||||
expect(findSlot(tokens, "table").style.widthPercent).toBe(100);
|
||||
});
|
||||
|
||||
it("保留封面高度、垂直对齐、轮廓线和隐藏字段语义", () => {
|
||||
const tokens = resolveDocxThemeTokens({
|
||||
snapshot: createSnapshot({
|
||||
|
||||
Reference in New Issue
Block a user