@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.
- package/dist/core/tableModel.d.ts +22 -0
- package/dist/core/tableModel.d.ts.map +1 -1
- package/dist/index.js +377 -29
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +279 -29
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +30 -0
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/rules.d.ts +1 -0
- package/dist/quality/rules.d.ts.map +1 -1
- package/dist/templates/documents/proposal.docx.json +277 -42
- package/dist/templates/documents/technical-guide.docx.json +273 -39
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/templates/themes/vermilion.docx.theme.json +130 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -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":"AAAA
|
|
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
|
-
|
|
7041
|
-
size: merged.borderSize
|
|
7042
|
-
color: merged.borderColor
|
|
7043
|
-
hidden: isHidden(
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
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
|
-
...
|
|
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
|
|
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
|
|
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
|
|
11449
|
-
if (
|
|
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
|
};
|