@json-to-office/core-docx 6.1.0 → 6.4.1
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/index.js +514 -238
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +211 -2
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +55 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/rules.d.ts +73 -12
- package/dist/quality/rules.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -12970,6 +12970,7 @@ async function expandBlocksWithPlugins(document, theme, plugins, render, preserv
|
|
|
12970
12970
|
init_styleHelpers();
|
|
12971
12971
|
init_defaults();
|
|
12972
12972
|
init_widthUtils();
|
|
12973
|
+
import probe2 from "probe-image-size";
|
|
12973
12974
|
|
|
12974
12975
|
// src/quality/text-inventory.ts
|
|
12975
12976
|
function tocDepth(depth) {
|
|
@@ -13220,6 +13221,92 @@ function collectDocxTextInventory(children, basePath = "/children") {
|
|
|
13220
13221
|
return entries;
|
|
13221
13222
|
}
|
|
13222
13223
|
|
|
13224
|
+
// src/quality/text-metrics.ts
|
|
13225
|
+
var DEFAULT_ADVANCE = 556;
|
|
13226
|
+
var ADVANCE = {
|
|
13227
|
+
" ": 278,
|
|
13228
|
+
A: 667,
|
|
13229
|
+
B: 667,
|
|
13230
|
+
C: 722,
|
|
13231
|
+
D: 722,
|
|
13232
|
+
E: 667,
|
|
13233
|
+
F: 611,
|
|
13234
|
+
G: 778,
|
|
13235
|
+
H: 722,
|
|
13236
|
+
I: 278,
|
|
13237
|
+
J: 500,
|
|
13238
|
+
K: 667,
|
|
13239
|
+
L: 556,
|
|
13240
|
+
M: 833,
|
|
13241
|
+
N: 722,
|
|
13242
|
+
O: 778,
|
|
13243
|
+
P: 667,
|
|
13244
|
+
Q: 778,
|
|
13245
|
+
R: 722,
|
|
13246
|
+
S: 667,
|
|
13247
|
+
T: 611,
|
|
13248
|
+
U: 722,
|
|
13249
|
+
V: 667,
|
|
13250
|
+
W: 944,
|
|
13251
|
+
X: 667,
|
|
13252
|
+
Y: 667,
|
|
13253
|
+
Z: 611,
|
|
13254
|
+
a: 556,
|
|
13255
|
+
b: 556,
|
|
13256
|
+
c: 500,
|
|
13257
|
+
d: 556,
|
|
13258
|
+
e: 556,
|
|
13259
|
+
f: 278,
|
|
13260
|
+
g: 556,
|
|
13261
|
+
h: 556,
|
|
13262
|
+
i: 222,
|
|
13263
|
+
j: 222,
|
|
13264
|
+
k: 500,
|
|
13265
|
+
l: 222,
|
|
13266
|
+
m: 833,
|
|
13267
|
+
n: 556,
|
|
13268
|
+
o: 556,
|
|
13269
|
+
p: 556,
|
|
13270
|
+
q: 556,
|
|
13271
|
+
r: 333,
|
|
13272
|
+
s: 500,
|
|
13273
|
+
t: 278,
|
|
13274
|
+
u: 556,
|
|
13275
|
+
v: 500,
|
|
13276
|
+
w: 722,
|
|
13277
|
+
x: 500,
|
|
13278
|
+
y: 500,
|
|
13279
|
+
z: 500,
|
|
13280
|
+
".": 278,
|
|
13281
|
+
",": 278,
|
|
13282
|
+
":": 278,
|
|
13283
|
+
";": 278,
|
|
13284
|
+
"!": 278,
|
|
13285
|
+
"?": 556,
|
|
13286
|
+
"'": 191,
|
|
13287
|
+
'"': 355,
|
|
13288
|
+
"-": 333,
|
|
13289
|
+
"\u2013": 556,
|
|
13290
|
+
"\u2014": 1e3,
|
|
13291
|
+
"&": 667,
|
|
13292
|
+
"%": 889,
|
|
13293
|
+
"(": 333,
|
|
13294
|
+
")": 333,
|
|
13295
|
+
"/": 278,
|
|
13296
|
+
"@": 1015,
|
|
13297
|
+
"#": 556,
|
|
13298
|
+
"+": 584,
|
|
13299
|
+
"=": 584
|
|
13300
|
+
};
|
|
13301
|
+
function estimateTextWidthPt(text, fontSizePt, trackingPt = 0) {
|
|
13302
|
+
let units = 0;
|
|
13303
|
+
for (const character of text) {
|
|
13304
|
+
units += ADVANCE[character] ?? DEFAULT_ADVANCE;
|
|
13305
|
+
}
|
|
13306
|
+
const width = units / 1e3 * fontSizePt + text.length * trackingPt;
|
|
13307
|
+
return Math.max(0, width);
|
|
13308
|
+
}
|
|
13309
|
+
|
|
13223
13310
|
// src/quality/facts.ts
|
|
13224
13311
|
function asRecord2(value) {
|
|
13225
13312
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
@@ -13917,7 +14004,9 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13917
14004
|
)
|
|
13918
14005
|
]
|
|
13919
14006
|
});
|
|
13920
|
-
|
|
14007
|
+
const content = { ...document, props: { ...asRecord2(document.props) } };
|
|
14008
|
+
delete content.props.themeOverrides;
|
|
14009
|
+
collectColorLiterals(content).forEach((literal, index) => {
|
|
13921
14010
|
addFact({
|
|
13922
14011
|
id: `docx:color:${index}:${literal.path}`,
|
|
13923
14012
|
kind: "docx/color",
|
|
@@ -13926,7 +14015,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13926
14015
|
hex: literal.hex
|
|
13927
14016
|
});
|
|
13928
14017
|
});
|
|
13929
|
-
collectFontFamilies(
|
|
14018
|
+
collectFontFamilies(content).forEach((use, index) => {
|
|
13930
14019
|
addFact({
|
|
13931
14020
|
id: `docx:font:${index}:${use.path}`,
|
|
13932
14021
|
kind: "docx/font-family",
|
|
@@ -14031,14 +14120,29 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
14031
14120
|
}
|
|
14032
14121
|
if (node.name === "image" || node.name === "visual") {
|
|
14033
14122
|
for (const fact of svgTextFacts(props, path3)) addFact(fact);
|
|
14123
|
+
const drawn = drawnRatio(props);
|
|
14124
|
+
const natural = readableRatio(props);
|
|
14125
|
+
addFact({
|
|
14126
|
+
id: `docx:image:${path3}`,
|
|
14127
|
+
kind: "docx/image",
|
|
14128
|
+
path: path3,
|
|
14129
|
+
...typeof props.alt === "string" && props.alt.trim() !== "" && { alt: props.alt },
|
|
14130
|
+
captioned: isCaptioned(facts, authoredPath(path3)),
|
|
14131
|
+
...drawn !== void 0 && { drawnRatio: drawn },
|
|
14132
|
+
...natural !== void 0 && { naturalRatio: natural }
|
|
14133
|
+
});
|
|
14034
14134
|
}
|
|
14035
14135
|
if (node.name === "heading") {
|
|
14036
14136
|
const level = typeof props.level === "number" && Number.isFinite(props.level) ? props.level : 1;
|
|
14137
|
+
const styleKeepNext = asRecord2(
|
|
14138
|
+
typography.styles[`heading${level}`]
|
|
14139
|
+
)?.keepNext;
|
|
14037
14140
|
addFact({
|
|
14038
14141
|
id: `docx:heading:${path3}`,
|
|
14039
14142
|
kind: "docx/heading",
|
|
14040
14143
|
path: `${path3}/props/level`,
|
|
14041
14144
|
level,
|
|
14145
|
+
keepNext: props.keepNext === true || props.keepNext === void 0 && styleKeepNext === true,
|
|
14042
14146
|
...previousHeadingLevel !== void 0 && {
|
|
14043
14147
|
previousLevel: previousHeadingLevel
|
|
14044
14148
|
}
|
|
@@ -14053,6 +14157,65 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
14053
14157
|
const page = rec.name === "section" ? pageBox(resolved.theme, context.themeName, rec.props?.page) : basePage;
|
|
14054
14158
|
walkActive(component, `/children/${index}`, page, visit);
|
|
14055
14159
|
});
|
|
14160
|
+
const wordsOf = (text) => text.split(/\s+/).filter(Boolean).length;
|
|
14161
|
+
const bodyRoles = /* @__PURE__ */ new Set([
|
|
14162
|
+
"body",
|
|
14163
|
+
"list-item",
|
|
14164
|
+
"table-header",
|
|
14165
|
+
"table-cell",
|
|
14166
|
+
"statistic",
|
|
14167
|
+
"caption"
|
|
14168
|
+
]);
|
|
14169
|
+
const exhibitKinds = /* @__PURE__ */ new Set(["docx/table", "docx/chart", "docx/image"]);
|
|
14170
|
+
resolved.children.forEach((component, index) => {
|
|
14171
|
+
const rec = component;
|
|
14172
|
+
if (rec.name !== "section") return;
|
|
14173
|
+
const prefix = `/children/${index}/`;
|
|
14174
|
+
const own = facts.filter((fact) => fact.path.startsWith(prefix));
|
|
14175
|
+
const texts = own.filter(
|
|
14176
|
+
(fact) => fact.kind === "docx/text"
|
|
14177
|
+
);
|
|
14178
|
+
addFact({
|
|
14179
|
+
id: `docx:section:${index}`,
|
|
14180
|
+
kind: "docx/section",
|
|
14181
|
+
path: `/children/${index}`,
|
|
14182
|
+
index,
|
|
14183
|
+
words: texts.filter((fact) => bodyRoles.has(fact.role)).reduce((total, fact) => total + wordsOf(fact.text), 0),
|
|
14184
|
+
exhibits: own.filter((fact) => exhibitKinds.has(fact.kind)).length,
|
|
14185
|
+
headings: texts.filter((fact) => fact.role === "heading").length
|
|
14186
|
+
});
|
|
14187
|
+
if (hasColumnsComponent(rec)) return;
|
|
14188
|
+
const page = pageBox(
|
|
14189
|
+
resolved.theme,
|
|
14190
|
+
context.themeName,
|
|
14191
|
+
rec.props?.page
|
|
14192
|
+
);
|
|
14193
|
+
const fontSizePt = effectiveFontSize({ name: "paragraph" }, {}, typography)?.fontSizePt ?? 11;
|
|
14194
|
+
const widthPt = page.availableWidthTwips / 20;
|
|
14195
|
+
const averageAdvancePt = estimateTextWidthPt(MEASURE_SAMPLE, fontSizePt) / MEASURE_SAMPLE.length;
|
|
14196
|
+
if (averageAdvancePt > 0)
|
|
14197
|
+
addFact({
|
|
14198
|
+
id: `docx:measure:${index}`,
|
|
14199
|
+
kind: "docx/measure",
|
|
14200
|
+
path: `/children/${index}`,
|
|
14201
|
+
index,
|
|
14202
|
+
charactersPerLine: Math.round(widthPt / averageAdvancePt),
|
|
14203
|
+
widthTwips: page.availableWidthTwips,
|
|
14204
|
+
fontSizePt
|
|
14205
|
+
});
|
|
14206
|
+
});
|
|
14207
|
+
const headingCount = facts.filter(
|
|
14208
|
+
(fact) => fact.kind === "docx/text" && fact.role === "heading"
|
|
14209
|
+
).length;
|
|
14210
|
+
addFact({
|
|
14211
|
+
id: "docx:outline",
|
|
14212
|
+
kind: "docx/outline",
|
|
14213
|
+
path: "/props",
|
|
14214
|
+
headings: headingCount,
|
|
14215
|
+
contents: facts.some(
|
|
14216
|
+
(fact) => fact.kind === "docx/text" && fact.role === "toc-entry"
|
|
14217
|
+
)
|
|
14218
|
+
});
|
|
14056
14219
|
return {
|
|
14057
14220
|
format: "docx",
|
|
14058
14221
|
model: {
|
|
@@ -14083,6 +14246,52 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
14083
14246
|
}
|
|
14084
14247
|
};
|
|
14085
14248
|
}
|
|
14249
|
+
function hasColumnsComponent(node) {
|
|
14250
|
+
if (Array.isArray(node)) return node.some(hasColumnsComponent);
|
|
14251
|
+
const rec = asRecord2(node);
|
|
14252
|
+
if (!rec) return false;
|
|
14253
|
+
if (rec.name === "columns") return true;
|
|
14254
|
+
return Object.values(rec).some(hasColumnsComponent);
|
|
14255
|
+
}
|
|
14256
|
+
var CAPTION_LABEL = /^\s*(?:\*\*)?\s*(figure|exhibit|table|chart|image)\b/i;
|
|
14257
|
+
function isCaptioned(facts, image) {
|
|
14258
|
+
return facts.some((fact) => {
|
|
14259
|
+
if (fact.kind !== "docx/text") return false;
|
|
14260
|
+
const text = fact;
|
|
14261
|
+
const near = siblingOf(text.path) === siblingOf(image) || text.path.startsWith(`${image}/`) || image.startsWith(`${text.path}/`);
|
|
14262
|
+
return near && (text.role === "caption" || CAPTION_LABEL.test(text.text));
|
|
14263
|
+
});
|
|
14264
|
+
}
|
|
14265
|
+
function siblingOf(pointer) {
|
|
14266
|
+
return pointer.slice(0, pointer.lastIndexOf("/"));
|
|
14267
|
+
}
|
|
14268
|
+
var MEASURE_SAMPLE = "the quick brown fox jumps over the lazy dog and then settles under it ";
|
|
14269
|
+
function drawnRatio(props) {
|
|
14270
|
+
const width = finiteNumber(props.width);
|
|
14271
|
+
const height = finiteNumber(props.height);
|
|
14272
|
+
return width !== void 0 && height !== void 0 && height > 0 ? width / height : void 0;
|
|
14273
|
+
}
|
|
14274
|
+
function readableRatio(props) {
|
|
14275
|
+
if (typeof props.svg === "string") {
|
|
14276
|
+
const box = /viewBox\s*=\s*["']\s*[-\d.]+[ ,]+[-\d.]+[ ,]+([\d.]+)[ ,]+([\d.]+)/.exec(
|
|
14277
|
+
props.svg
|
|
14278
|
+
);
|
|
14279
|
+
const width = box ? Number(box[1]) : NaN;
|
|
14280
|
+
const height = box ? Number(box[2]) : NaN;
|
|
14281
|
+
return Number.isFinite(width) && Number.isFinite(height) && height > 0 ? width / height : void 0;
|
|
14282
|
+
}
|
|
14283
|
+
if (typeof props.base64 !== "string") return void 0;
|
|
14284
|
+
const comma = props.base64.indexOf(",");
|
|
14285
|
+
if (comma < 0) return void 0;
|
|
14286
|
+
try {
|
|
14287
|
+
const size = probe2.sync(
|
|
14288
|
+
Buffer.from(props.base64.slice(comma + 1), "base64")
|
|
14289
|
+
);
|
|
14290
|
+
return size && size.height > 0 ? size.width / size.height : void 0;
|
|
14291
|
+
} catch {
|
|
14292
|
+
return void 0;
|
|
14293
|
+
}
|
|
14294
|
+
}
|
|
14086
14295
|
function slotIsFilled(value) {
|
|
14087
14296
|
if (typeof value === "string") return value.trim() !== "";
|
|
14088
14297
|
return value !== void 0 && value !== null && value !== false && (!Array.isArray(value) || value.length > 0);
|