@json-to-office/core-docx 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,10 +13,23 @@
13
13
  * result into their own vocabulary. Two copies of these rules would drift, and
14
14
  * the drift would be invisible until a border quietly changed colour.
15
15
  *
16
+ * Two rules keep a stated border side authoritative:
17
+ *
18
+ * - A side named in a per-side `borderColor`/`borderSize` object on the cell
19
+ * or its column is *explicit*. `hideBorders` silences only inherited
20
+ * table-level borders; an explicit side keeps its border. A scalar
21
+ * `borderColor`/`borderSize` restyles without claiming any side.
22
+ * - Every interior edge is adjudicated: when the two facing cell sides
23
+ * disagree, one winner is chosen — an explicit side beats an inherited one,
24
+ * equals fall to OOXML's own weight rules — and mirrored onto both cells.
25
+ * The emitted package then never contains a contested edge, so Word and
26
+ * LibreOffice (which resolve conflicts differently) draw the same table.
27
+ *
16
28
  * Everything returned is resolved: colours are 6-digit hex without `#`, border
17
29
  * sizes are points, padding and heights are points. Nothing here loads content
18
30
  * or touches the filesystem.
19
31
  */
32
+ import type { LineSpacing } from '@json-to-office/shared-docx';
20
33
  import type { ComponentDefinition } from '../types';
21
34
  import type { ThemeConfig } from '../styles';
22
35
  export type TableCellContent = string | ComponentDefinition;
@@ -27,6 +40,8 @@ export type TableFontConfig = {
27
40
  fontWeight?: number;
28
41
  italic?: boolean;
29
42
  underline?: boolean;
43
+ /** Line spacing of the cell's paragraph; overrides the theme's tableCell style. */
44
+ lineSpacing?: LineSpacing;
30
45
  };
31
46
  export type BorderColor = string | {
32
47
  bottom?: string;
@@ -110,6 +125,13 @@ export interface ResolvedBorder {
110
125
  color: string;
111
126
  /** True when `hideBorders` suppressed this side for this cell. */
112
127
  hidden: boolean;
128
+ /**
129
+ * True when the cell or its column named this side in a per-side
130
+ * `borderColor`/`borderSize` object. An explicit side keeps its border
131
+ * where `hideBorders` would have suppressed it, and wins its interior edge
132
+ * against a side that merely inherited — see `adjudicateInteriorEdges`.
133
+ */
134
+ explicit: boolean;
113
135
  }
114
136
  export interface ResolvedCell<TComment, TRevision> {
115
137
  content?: TableCellContent;
@@ -1 +1 @@
1
- {"version":3,"file":"tableModel.d.ts","sourceRoot":"","sources":["../../src/core/tableModel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tableModel.d.ts","sourceRoot":"","sources":["../../src/core/tableModel.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -937,6 +937,143 @@ var init_devportal_docx_theme = __esm({
937
937
  }
938
938
  });
939
939
 
940
+ // src/templates/themes/vermilion.docx.theme.json
941
+ var vermilion_docx_theme_default;
942
+ var init_vermilion_docx_theme = __esm({
943
+ "src/templates/themes/vermilion.docx.theme.json"() {
944
+ vermilion_docx_theme_default = {
945
+ name: "vermilion",
946
+ displayName: "Vermilion Editorial",
947
+ description: "Poster-red editorial system \u2014 vermilion display headings, ink text, warm creams and hairline rules",
948
+ version: "1.0.0",
949
+ colors: {
950
+ primary: "#282829",
951
+ secondary: "#58595B",
952
+ accent: "#EF4130",
953
+ text: "#282829",
954
+ background: "#FFFFFF",
955
+ border: "#E8E2DC",
956
+ textPrimary: "#282829",
957
+ textSecondary: "#58595B",
958
+ textMuted: "#939598",
959
+ borderPrimary: "#C7C8CA",
960
+ borderSecondary: "#EFEAE4",
961
+ backgroundPrimary: "#FFFFFF",
962
+ backgroundSecondary: "#FAF7F5"
963
+ },
964
+ fonts: {
965
+ heading: {
966
+ family: "Arial",
967
+ size: 24
968
+ },
969
+ body: {
970
+ family: "Calibri",
971
+ size: 10.5
972
+ },
973
+ mono: {
974
+ family: "Consolas",
975
+ size: 10
976
+ },
977
+ light: {
978
+ family: "Arial",
979
+ size: 24
980
+ }
981
+ },
982
+ page: {
983
+ size: "A4",
984
+ margins: {
985
+ top: 1360,
986
+ bottom: 1360,
987
+ left: 1180,
988
+ right: 1180,
989
+ header: 620,
990
+ footer: 620,
991
+ gutter: 0
992
+ }
993
+ },
994
+ styles: {
995
+ normal: {
996
+ font: "body",
997
+ color: "textPrimary",
998
+ lineSpacing: {
999
+ type: "multiple",
1000
+ value: 1.3
1001
+ },
1002
+ alignment: "left",
1003
+ spacing: {
1004
+ after: 8
1005
+ }
1006
+ },
1007
+ heading1: {
1008
+ font: "heading",
1009
+ size: 25,
1010
+ bold: false,
1011
+ color: "accent",
1012
+ characterSpacing: {
1013
+ type: "expanded",
1014
+ value: 50
1015
+ },
1016
+ spacing: {
1017
+ before: 22,
1018
+ after: 12
1019
+ },
1020
+ keepNext: true,
1021
+ alignment: "left"
1022
+ },
1023
+ heading2: {
1024
+ font: "heading",
1025
+ size: 12.5,
1026
+ bold: true,
1027
+ color: "accent",
1028
+ characterSpacing: {
1029
+ type: "expanded",
1030
+ value: 30
1031
+ },
1032
+ spacing: {
1033
+ before: 16,
1034
+ after: 7
1035
+ },
1036
+ keepNext: true,
1037
+ alignment: "left"
1038
+ },
1039
+ heading3: {
1040
+ font: "body",
1041
+ size: 11,
1042
+ bold: true,
1043
+ color: "textPrimary",
1044
+ spacing: {
1045
+ before: 12,
1046
+ after: 5
1047
+ },
1048
+ keepNext: true,
1049
+ alignment: "left"
1050
+ },
1051
+ title: {
1052
+ font: "heading",
1053
+ size: 38,
1054
+ bold: true,
1055
+ color: "primary",
1056
+ alignment: "left",
1057
+ spacing: {
1058
+ before: 0,
1059
+ after: 14
1060
+ }
1061
+ },
1062
+ subtitle: {
1063
+ font: "body",
1064
+ size: 14,
1065
+ color: "textSecondary",
1066
+ alignment: "left",
1067
+ spacing: {
1068
+ before: 0,
1069
+ after: 10
1070
+ }
1071
+ }
1072
+ }
1073
+ };
1074
+ }
1075
+ });
1076
+
940
1077
  // src/templates/themes/index.ts
941
1078
  import fs from "fs";
942
1079
  import path from "path";
@@ -953,7 +1090,8 @@ function loadThemesFromJson() {
953
1090
  corporate: ensureThemeDefaults(corporate_docx_theme_default),
954
1091
  modern: ensureThemeDefaults(modern_docx_theme_default),
955
1092
  apex: ensureThemeDefaults(apex_docx_theme_default),
956
- devportal: ensureThemeDefaults(devportal_docx_theme_default)
1093
+ devportal: ensureThemeDefaults(devportal_docx_theme_default),
1094
+ vermilion: ensureThemeDefaults(vermilion_docx_theme_default)
957
1095
  };
958
1096
  try {
959
1097
  const __filename = fileURLToPath(import.meta.url);
@@ -1001,6 +1139,7 @@ var init_themes = __esm({
1001
1139
  init_modern_docx_theme();
1002
1140
  init_apex_docx_theme();
1003
1141
  init_devportal_docx_theme();
1142
+ init_vermilion_docx_theme();
1004
1143
  _themesCache = null;
1005
1144
  themes = loadThemesFromJson();
1006
1145
  getTheme = (themeName) => {
@@ -1746,6 +1885,14 @@ async function rasterizeSvgFallback(svg, transformation) {
1746
1885
  }
1747
1886
  try {
1748
1887
  const markup = svg.toString("utf-8");
1888
+ if (/<(?:[A-Za-z][\w.-]*:)?text[\s>/]/.test(markup)) {
1889
+ reportWarning(
1890
+ "image",
1891
+ "IMAGE_SVG_RASTER_SKIPPED",
1892
+ "Inline SVG contains <text>, which would rasterize with machine-dependent fonts, so its fallback only renders in Word 2016+. Convert the text to paths for a portable fallback."
1893
+ );
1894
+ return void 0;
1895
+ }
1749
1896
  const probeImage = new Resvg(markup);
1750
1897
  const wide = probeImage.width / probeImage.height > transformation.width / transformation.height;
1751
1898
  const mode = wide ? "height" : "width";
@@ -6810,6 +6957,17 @@ function mergeBorderSizePerSide(...borders3) {
6810
6957
  left: pick("left")
6811
6958
  };
6812
6959
  }
6960
+ function statedSides(colors, sizes) {
6961
+ const namedColors = colors.filter((value) => typeof value === "object").map(normalizeBorderColor);
6962
+ const namedSizes = sizes.filter((value) => typeof value === "object").map(normalizeBorderSize);
6963
+ const stated = (side) => namedColors.some((c) => c !== void 0 && c[side] !== UNSET_COLOR) || namedSizes.some((s) => s !== void 0 && s[side] !== UNSET_SIZE);
6964
+ return {
6965
+ top: stated("top"),
6966
+ right: stated("right"),
6967
+ bottom: stated("bottom"),
6968
+ left: stated("left")
6969
+ };
6970
+ }
6813
6971
  function mergePaddingPerSide(...paddings) {
6814
6972
  const normalized = paddings.map(normalizePadding);
6815
6973
  if (!normalized.some((p) => p !== void 0)) return void 0;
@@ -6949,6 +7107,10 @@ function mergeCellDefaults(tableDef, columnDef, cellDef, position, tableOuterBor
6949
7107
  tableDef?.borderSize,
6950
7108
  tableOuterBorder.borderSize
6951
7109
  ),
7110
+ borderExplicit: statedSides(
7111
+ [cellDef?.borderColor, columnDef?.borderColor],
7112
+ [cellDef?.borderSize, columnDef?.borderSize]
7113
+ ),
6952
7114
  padding: mergePaddingPerSide(
6953
7115
  cellDef?.padding,
6954
7116
  columnDef?.padding,
@@ -7006,6 +7168,10 @@ function mergeHeaderCellDefaults(tableDef, headerTableDef, columnDef, headerDef,
7006
7168
  tableDef?.borderSize,
7007
7169
  tableOuterBorder.borderSize
7008
7170
  ),
7171
+ borderExplicit: statedSides(
7172
+ [headerDef?.borderColor, columnDef?.borderColor],
7173
+ [headerDef?.borderSize, columnDef?.borderSize]
7174
+ ),
7009
7175
  padding: mergePaddingPerSide(
7010
7176
  headerDef?.padding,
7011
7177
  headerTableDef?.padding,
@@ -7036,28 +7202,20 @@ function resolveTableModel(source, theme, themeName, options = {}) {
7036
7202
  return position.isLastCol ? hidden.right : hidden.insideVertical;
7037
7203
  }
7038
7204
  };
7039
- const borders3 = (merged, position) => ({
7040
- top: {
7041
- size: merged.borderSize.top,
7042
- color: merged.borderColor.top,
7043
- hidden: isHidden("top", position)
7044
- },
7045
- right: {
7046
- size: merged.borderSize.right,
7047
- color: merged.borderColor.right,
7048
- hidden: isHidden("right", position)
7049
- },
7050
- bottom: {
7051
- size: merged.borderSize.bottom,
7052
- color: merged.borderColor.bottom,
7053
- hidden: isHidden("bottom", position)
7054
- },
7055
- left: {
7056
- size: merged.borderSize.left,
7057
- color: merged.borderColor.left,
7058
- hidden: isHidden("left", position)
7059
- }
7060
- });
7205
+ const borders3 = (merged, position) => {
7206
+ const side = (name) => ({
7207
+ size: merged.borderSize[name],
7208
+ color: merged.borderColor[name],
7209
+ hidden: isHidden(name, position) && !merged.borderExplicit[name],
7210
+ explicit: merged.borderExplicit[name]
7211
+ });
7212
+ return {
7213
+ top: side("top"),
7214
+ right: side("right"),
7215
+ bottom: side("bottom"),
7216
+ left: side("left")
7217
+ };
7218
+ };
7061
7219
  const tallest = (heights) => heights.reduce(
7062
7220
  (max, height) => height === void 0 ? max : max === void 0 ? height : Math.max(max, height),
7063
7221
  void 0
@@ -7167,6 +7325,7 @@ function resolveTableModel(source, theme, themeName, options = {}) {
7167
7325
  };
7168
7326
  return row;
7169
7327
  });
7328
+ adjudicateInteriorEdges([header, ...rows]);
7170
7329
  return {
7171
7330
  ...resolveWidths(source, columns, theme, themeName),
7172
7331
  header,
@@ -7174,6 +7333,54 @@ function resolveTableModel(source, theme, themeName, options = {}) {
7174
7333
  repeatHeader: source.repeatHeaderOnPageBreak ?? true
7175
7334
  };
7176
7335
  }
7336
+ function drawsNothing(border3) {
7337
+ return border3.hidden || border3.size <= 0;
7338
+ }
7339
+ function channels(hex) {
7340
+ const digits = hex.startsWith("#") ? hex.slice(1) : hex;
7341
+ return [
7342
+ parseInt(digits.slice(0, 2), 16) || 0,
7343
+ parseInt(digits.slice(2, 4), 16) || 0,
7344
+ parseInt(digits.slice(4, 6), 16) || 0
7345
+ ];
7346
+ }
7347
+ function outweighs(a, b) {
7348
+ if (drawsNothing(a)) return false;
7349
+ if (drawsNothing(b)) return true;
7350
+ if (a.size !== b.size) return a.size > b.size;
7351
+ const [redA, greenA, blueA] = channels(a.color);
7352
+ const [redB, greenB, blueB] = channels(b.color);
7353
+ const brightness = [
7354
+ [redA + blueA + 2 * greenA, redB + blueB + 2 * greenB],
7355
+ [blueA + 2 * greenA, blueB + 2 * greenB],
7356
+ [greenA, greenB]
7357
+ ];
7358
+ for (const [ours, theirs] of brightness) {
7359
+ if (ours !== theirs) return ours < theirs;
7360
+ }
7361
+ return false;
7362
+ }
7363
+ function adjudicateInteriorEdges(rows) {
7364
+ const settle = (earlier, later) => {
7365
+ if (drawsNothing(earlier) && drawsNothing(later)) return;
7366
+ if (earlier.hidden === later.hidden && earlier.size === later.size && earlier.color === later.color) {
7367
+ return;
7368
+ }
7369
+ const winner = earlier.explicit !== later.explicit ? earlier.explicit ? earlier : later : outweighs(later, earlier) ? later : earlier;
7370
+ const loser = winner === earlier ? later : earlier;
7371
+ loser.size = winner.size;
7372
+ loser.color = winner.color;
7373
+ loser.hidden = winner.hidden;
7374
+ };
7375
+ rows.forEach((row, rowIndex) => {
7376
+ row.cells.forEach((cell, colIndex) => {
7377
+ const right = row.cells[colIndex + 1];
7378
+ if (right) settle(cell.borders.right, right.borders.left);
7379
+ const below = rows[rowIndex + 1]?.cells[colIndex];
7380
+ if (below) settle(cell.borders.bottom, below.borders.top);
7381
+ });
7382
+ });
7383
+ }
7177
7384
  function resolveWidths(source, columns, theme, themeName) {
7178
7385
  const hasExplicitWidths = columns.some((col) => col.width !== void 0);
7179
7386
  if (!hasExplicitWidths) {
@@ -10190,6 +10397,7 @@ function compileTableRow(row, spacing, baseStyle, scope) {
10190
10397
  };
10191
10398
  }
10192
10399
  function compileTableCell(cell, spacing, baseStyle, keepNext, scope, rowRevision, markRevision) {
10400
+ const cellLine = compileLineSpacing(cell.font?.lineSpacing);
10193
10401
  const paragraph2 = {
10194
10402
  kind: "paragraph",
10195
10403
  id: scope.id,
@@ -10203,7 +10411,10 @@ function compileTableCell(cell, spacing, baseStyle, keepNext, scope, rowRevision
10203
10411
  spacing: {
10204
10412
  beforeTwips: spacing.before,
10205
10413
  afterTwips: spacing.after,
10206
- ...spacing.line !== void 0 ? { lineTwips: spacing.line, lineRule: lineRule(spacing.lineRule) } : {}
10414
+ ...cellLine ? {
10415
+ ...cellLine.lineTwips !== void 0 ? { lineTwips: cellLine.lineTwips } : {},
10416
+ lineRule: cellLine.lineRule
10417
+ } : spacing.line !== void 0 ? { lineTwips: spacing.line, lineRule: lineRule(spacing.lineRule) } : {}
10207
10418
  },
10208
10419
  ...keepNext ? { keepNext: true } : {}
10209
10420
  },
@@ -11339,7 +11550,22 @@ function characterSpacingPt(spacing) {
11339
11550
  if (rule === void 0 || value === void 0) return 0;
11340
11551
  return rule.type === "condensed" ? -value / TWIPS_PER_POINT3 : value / TWIPS_PER_POINT3;
11341
11552
  }
11342
- function frameTextFact(props, path4, page) {
11553
+ function frameSignature(floating) {
11554
+ const horizontal = asRecord(floating.horizontalPosition);
11555
+ const vertical = asRecord(floating.verticalPosition);
11556
+ return JSON.stringify([
11557
+ floating.width ?? null,
11558
+ floating.height ?? null,
11559
+ horizontal?.offset ?? null,
11560
+ horizontal?.relative ?? null,
11561
+ horizontal?.align ?? null,
11562
+ vertical?.offset ?? null,
11563
+ vertical?.relative ?? null,
11564
+ vertical?.align ?? null,
11565
+ asRecord(floating.wrap)?.type ?? null
11566
+ ]);
11567
+ }
11568
+ function frameTextFact(props, path4, page, frameChainId, flowIndex) {
11343
11569
  const floating = asRecord(props.floating);
11344
11570
  const frameWidthTwips = finiteNumber(floating?.width);
11345
11571
  if (frameWidthTwips === void 0) return void 0;
@@ -11352,7 +11578,12 @@ function frameTextFact(props, path4, page) {
11352
11578
  (longest, word) => word.length > longest.length ? word : longest,
11353
11579
  ""
11354
11580
  );
11355
- const offsetY = finiteNumber(asRecord(floating?.verticalPosition)?.offset);
11581
+ const horizontal = asRecord(floating?.horizontalPosition);
11582
+ const vertical = asRecord(floating?.verticalPosition);
11583
+ const offsetX = finiteNumber(horizontal?.offset);
11584
+ const offsetY = finiteNumber(vertical?.offset);
11585
+ const absolutelyPinned = horizontal?.offset !== void 0 || vertical?.offset !== void 0;
11586
+ const resolvable = (horizontal?.offset === void 0 || offsetX !== void 0) && (vertical?.offset === void 0 || offsetY !== void 0);
11356
11587
  return {
11357
11588
  id: `docx:frame-text:${path4}`,
11358
11589
  kind: "docx/frame-text",
@@ -11367,7 +11598,14 @@ function frameTextFact(props, path4, page) {
11367
11598
  },
11368
11599
  ...offsetY !== void 0 && { offsetYTwips: offsetY },
11369
11600
  pageBottomTwips: page.pageBottomTwips,
11370
- longestWord
11601
+ longestWord,
11602
+ ...absolutelyPinned && resolvable && {
11603
+ absoluteOffsetTwips: { x: offsetX ?? 0, y: offsetY ?? 0 }
11604
+ },
11605
+ anchorHorizontal: typeof horizontal?.relative === "string" ? horizontal.relative : "page",
11606
+ anchorVertical: typeof vertical?.relative === "string" ? vertical.relative : "page",
11607
+ frameChainId,
11608
+ flowIndex
11371
11609
  };
11372
11610
  }
11373
11611
  var SVG_VIEWBOX = /viewBox\s*=\s*"\s*(-?[\d.]+)[\s,]+(-?[\d.]+)[\s,]+(-?[\d.]+)[\s,]+(-?[\d.]+)\s*"/;
@@ -11438,6 +11676,10 @@ function prepareDocxQualityDocument(document, options = {}) {
11438
11676
  ...fact.relatedPaths && { relatedPaths: fact.relatedPaths }
11439
11677
  };
11440
11678
  };
11679
+ let previousVisitPath;
11680
+ let lastFrame;
11681
+ let flowIndex = 0;
11682
+ const parentOf = (path4) => path4.slice(0, path4.lastIndexOf("/"));
11441
11683
  const visit = (node, path4, page) => {
11442
11684
  const props = asRecord(node.props) ?? {};
11443
11685
  if (node.name === "table") {
@@ -11445,8 +11687,14 @@ function prepareDocxQualityDocument(document, options = {}) {
11445
11687
  if (fact) addFact(fact);
11446
11688
  }
11447
11689
  if (node.name === "paragraph" || node.name === "text-box") {
11448
- const fact = frameTextFact(props, path4, page);
11449
- if (fact) addFact(fact);
11690
+ const floating = asRecord(props.floating);
11691
+ if (floating) {
11692
+ const signature = frameSignature(floating);
11693
+ const chainId = lastFrame !== void 0 && previousVisitPath === lastFrame.path && parentOf(lastFrame.path) === parentOf(path4) && lastFrame.signature === signature ? lastFrame.chainId : `docx:frame-chain:${path4}`;
11694
+ lastFrame = { path: path4, signature, chainId };
11695
+ const fact = frameTextFact(props, path4, page, chainId, flowIndex);
11696
+ if (fact) addFact(fact);
11697
+ }
11450
11698
  }
11451
11699
  if (node.name === "image" || node.name === "visual") {
11452
11700
  for (const fact of svgTextFacts(props, path4)) addFact(fact);
@@ -11464,9 +11712,11 @@ function prepareDocxQualityDocument(document, options = {}) {
11464
11712
  });
11465
11713
  previousHeadingLevel = level;
11466
11714
  }
11715
+ previousVisitPath = path4;
11467
11716
  };
11468
11717
  resolved.children.forEach((component, index) => {
11469
11718
  const rec = component;
11719
+ if (rec.name === "section") flowIndex += 1;
11470
11720
  const page = rec.name === "section" ? pageBox(resolved.theme, context.themeName, rec.props?.page) : basePage;
11471
11721
  walkActive(component, `/children/${index}`, page, visit);
11472
11722
  });
@@ -12135,6 +12385,103 @@ var docxTextFitRule = {
12135
12385
  return findings;
12136
12386
  }
12137
12387
  };
12388
+ var FRAME_COLLISION_MIN_WIDTH_TWIPS = 240;
12389
+ var docxFrameCollisionRule = {
12390
+ id: "docx/frame-collision",
12391
+ code: QUALITY_CODES.FRAME_COLLISION,
12392
+ category: "integrity",
12393
+ defaultSeverity: "warning",
12394
+ defaultCertainty: "estimated",
12395
+ formats: ["docx"],
12396
+ defaultParameters: {
12397
+ minOverlapWidthTwips: FRAME_COLLISION_MIN_WIDTH_TWIPS,
12398
+ minOverlapLines: 1
12399
+ },
12400
+ evaluate: ({ facts, configuration }) => {
12401
+ const minOverlapWidthTwips = numberParameter(
12402
+ configuration.parameters,
12403
+ "minOverlapWidthTwips",
12404
+ FRAME_COLLISION_MIN_WIDTH_TWIPS
12405
+ );
12406
+ const minOverlapLines = numberParameter(
12407
+ configuration.parameters,
12408
+ "minOverlapLines",
12409
+ 1
12410
+ );
12411
+ const chains = /* @__PURE__ */ new Map();
12412
+ for (const fact of frameTextFacts(facts)) {
12413
+ if (!fact.absoluteOffsetTwips || fact.anchorHorizontal === "text" || fact.anchorVertical === "text") {
12414
+ continue;
12415
+ }
12416
+ const lines = estimateWrappedLines(
12417
+ fact.text,
12418
+ fact.frameWidthTwips / TWIPS_PER_POINT4,
12419
+ fact.fontSizePt,
12420
+ fact.characterSpacingPt
12421
+ );
12422
+ const heightTwips = lines * fact.lineHeightPt * TWIPS_PER_POINT4;
12423
+ const lineTwips = fact.lineHeightPt * TWIPS_PER_POINT4;
12424
+ const chain = chains.get(fact.frameChainId);
12425
+ if (chain) {
12426
+ chain.heightTwips += heightTwips;
12427
+ chain.lineTwips = Math.max(chain.lineTwips, lineTwips);
12428
+ continue;
12429
+ }
12430
+ chains.set(fact.frameChainId, {
12431
+ path: fact.path,
12432
+ offsetYAuthored: fact.offsetYTwips !== void 0,
12433
+ x: fact.absoluteOffsetTwips.x,
12434
+ y: fact.absoluteOffsetTwips.y,
12435
+ widthTwips: fact.frameWidthTwips,
12436
+ heightTwips,
12437
+ lineTwips,
12438
+ // Offsets only compare within one page flow and one anchor pair.
12439
+ groupKey: `${fact.flowIndex}:${fact.anchorHorizontal}:${fact.anchorVertical}`
12440
+ });
12441
+ }
12442
+ const groups = /* @__PURE__ */ new Map();
12443
+ for (const chain of chains.values()) {
12444
+ const group = groups.get(chain.groupKey);
12445
+ if (group) group.push(chain);
12446
+ else groups.set(chain.groupKey, [chain]);
12447
+ }
12448
+ const findings = [];
12449
+ for (const group of groups.values()) {
12450
+ for (let i = 0; i < group.length; i += 1) {
12451
+ for (let j = i + 1; j < group.length; j += 1) {
12452
+ const a = group[i];
12453
+ const b = group[j];
12454
+ const overlapWidth = Math.min(a.x + a.widthTwips, b.x + b.widthTwips) - Math.max(a.x, b.x);
12455
+ if (overlapWidth <= minOverlapWidthTwips) continue;
12456
+ const overlapHeight = Math.min(a.y + a.heightTwips, b.y + b.heightTwips) - Math.max(a.y, b.y);
12457
+ const floorTwips = Math.max(a.lineTwips, b.lineTwips) * minOverlapLines;
12458
+ if (overlapHeight <= floorTwips) continue;
12459
+ const overlapHeightPt = Math.round(overlapHeight / TWIPS_PER_POINT4);
12460
+ const overlapWidthPt = Math.round(overlapWidth / TWIPS_PER_POINT4);
12461
+ findings.push({
12462
+ message: `This floating frame and an earlier one on the same page overlap by an estimated ${overlapHeightPt}pt of text across ${overlapWidthPt}pt of width \u2014 the two blocks paint on top of each other.`,
12463
+ path: b.offsetYAuthored ? `${b.path}/props/floating/verticalPosition/offset` : `${b.path}/props/floating`,
12464
+ suggestion: "Move one frame, shorten its text, or reduce fontSize until the blocks clear each other.",
12465
+ context: {
12466
+ partnerPath: a.path,
12467
+ overlapWidthTwips: Math.round(overlapWidth),
12468
+ overlapHeightTwips: Math.round(overlapHeight),
12469
+ frameTopTwips: b.y,
12470
+ partnerTopTwips: a.y
12471
+ },
12472
+ relatedPaths: [a.path],
12473
+ evidence: {
12474
+ actual: Math.round(overlapHeight),
12475
+ expected: Math.round(floorTwips),
12476
+ unit: "twips"
12477
+ }
12478
+ });
12479
+ }
12480
+ }
12481
+ }
12482
+ return findings;
12483
+ }
12484
+ };
12138
12485
  var docxSvgTextBoundsRule = {
12139
12486
  id: "docx/svg-text-bounds",
12140
12487
  code: QUALITY_CODES.SVG_TEXT_CLIPPED,
@@ -12172,6 +12519,7 @@ var DOCX_QUALITY_RULES = {
12172
12519
  docxTableWidthRule,
12173
12520
  docxHeadingHierarchyRule,
12174
12521
  docxTextFitRule,
12522
+ docxFrameCollisionRule,
12175
12523
  docxSvgTextBoundsRule
12176
12524
  ]
12177
12525
  };