@json-to-office/core-docx 4.0.0 → 4.2.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +295 -40
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +294 -40
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +2 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/text-inventory.d.ts +58 -0
- package/dist/quality/text-inventory.d.ts.map +1 -0
- package/dist/templates/themes/index.d.ts +5 -5
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { isNodeEnvironment, hasNodeBuiltins } from './utils/environment';
|
|
|
13
13
|
export { analyzeDocxQuality } from './quality/preflight';
|
|
14
14
|
export type { DocxQualityAnalysisOptions, DocxQualityOptions, } from './quality/preflight';
|
|
15
15
|
export { prepareDocxQualityDocument, type DocxHeadingFact, type DocxQualityFact, type DocxQualityModel, type DocxTableWidthFact, type PrepareDocxQualityOptions, } from './quality/facts';
|
|
16
|
+
export { collectDocxTextInventory, type DocxTextFact, type DocxTextRole, } from './quality/text-inventory';
|
|
16
17
|
export { DOCX_DEFAULT_QUALITY_PROFILE, DOCX_QUALITY_PROFILES, DOCX_QUALITY_RULES, docxQualityEngine, declaredDocxQualityProfile, resolveDocxQualityProfile, } from './quality/rules';
|
|
17
18
|
export { generateWarningsDocument, formatWarningsText, } from './utils/warningsDocument';
|
|
18
19
|
export { themes, minimalTheme, devportalTheme, vermilionTheme, consultingTheme, } from './styles/index';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAID,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,IAAI,qBAAqB,EAC1C,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,kBAAkB,GACxB,MAAM,4BAA4B,CAAC;AAKpC,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,YAAY,EACV,yBAAyB,EACzB,4BAA4B,EAE5B,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EACV,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,MAAM,EACN,YAAY,EACZ,cAAc,EACd,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,aAAa,EACb,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,kBAAkB,EAClB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC7E,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChF,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,QAAQ,EACR,UAAU,EACV,eAAe,EACf,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,oBAAoB,CAAC;AAG5B,YAAY,EAEV,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,EAEL,eAAe,EACf,aAAa,EACb,uBAAuB,EAGvB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,8BAA8B,EAG9B,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,YAAY,EAGZ,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,IAAI,sBAAsB,EAC5C,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAGpB,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12396,9 +12396,260 @@ async function expandBlocksWithPlugins(document, theme, plugins, render, preserv
|
|
|
12396
12396
|
init_styleHelpers();
|
|
12397
12397
|
init_defaults();
|
|
12398
12398
|
init_widthUtils();
|
|
12399
|
+
|
|
12400
|
+
// src/quality/text-inventory.ts
|
|
12401
|
+
function tocDepth(depth) {
|
|
12402
|
+
const range = asRecord(depth) ?? {};
|
|
12403
|
+
const from = typeof range.from === "number" ? range.from : 1;
|
|
12404
|
+
const to = typeof range.to === "number" ? range.to : 3;
|
|
12405
|
+
return { from, to };
|
|
12406
|
+
}
|
|
12399
12407
|
function asRecord(value) {
|
|
12400
12408
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
12401
12409
|
}
|
|
12410
|
+
function twipsToPt(value) {
|
|
12411
|
+
return typeof value === "number" && Number.isFinite(value) ? value / 20 : void 0;
|
|
12412
|
+
}
|
|
12413
|
+
function frameOf(props) {
|
|
12414
|
+
const widthPt = twipsToPt(asRecord(props.floating)?.width);
|
|
12415
|
+
return widthPt === void 0 ? void 0 : { widthPt };
|
|
12416
|
+
}
|
|
12417
|
+
function collectDocxTextInventory(children, basePath = "/children") {
|
|
12418
|
+
const entries = [];
|
|
12419
|
+
const add = (path4, text, role, extra = {}) => {
|
|
12420
|
+
if (typeof text !== "string" || text.trim() === "") return;
|
|
12421
|
+
entries.push({
|
|
12422
|
+
id: `docx:text:${path4}`,
|
|
12423
|
+
kind: "docx/text",
|
|
12424
|
+
path: path4,
|
|
12425
|
+
text,
|
|
12426
|
+
role,
|
|
12427
|
+
// Renumbered once the walk is done: contents entries are spliced in.
|
|
12428
|
+
order: -1,
|
|
12429
|
+
...extra
|
|
12430
|
+
});
|
|
12431
|
+
};
|
|
12432
|
+
const headings = [];
|
|
12433
|
+
const tocs = [];
|
|
12434
|
+
let sectionCount = 0;
|
|
12435
|
+
const visitCell = (cell, path4, role, inherited) => {
|
|
12436
|
+
const cellRole = inherited.repeats ? "chrome" : role;
|
|
12437
|
+
const extra = inherited.repeats ? { repeats: true } : {};
|
|
12438
|
+
if (typeof cell === "string") {
|
|
12439
|
+
add(path4, cell, cellRole, extra);
|
|
12440
|
+
return;
|
|
12441
|
+
}
|
|
12442
|
+
const rec = asRecord(cell);
|
|
12443
|
+
if (!rec) return;
|
|
12444
|
+
if ("content" in rec) {
|
|
12445
|
+
if (typeof rec.content === "string")
|
|
12446
|
+
add(`${path4}/content`, rec.content, cellRole, extra);
|
|
12447
|
+
else {
|
|
12448
|
+
const inner = asRecord(rec.content);
|
|
12449
|
+
if (inner)
|
|
12450
|
+
visitNode(inner, `${path4}/content`, { ...inherited, inCell: true });
|
|
12451
|
+
}
|
|
12452
|
+
return;
|
|
12453
|
+
}
|
|
12454
|
+
if (typeof rec.name === "string")
|
|
12455
|
+
visitNode(rec, path4, { ...inherited, inCell: true });
|
|
12456
|
+
};
|
|
12457
|
+
const visitNode = (node, path4, inherited) => {
|
|
12458
|
+
if (node.enabled === false) return;
|
|
12459
|
+
const props = asRecord(node.props) ?? {};
|
|
12460
|
+
const name = typeof node.name === "string" ? node.name : "";
|
|
12461
|
+
const extra = {
|
|
12462
|
+
...inherited.repeats && { repeats: true }
|
|
12463
|
+
};
|
|
12464
|
+
const scope = name === "section" ? { ...inherited, section: ++sectionCount } : inherited;
|
|
12465
|
+
switch (name) {
|
|
12466
|
+
case "heading": {
|
|
12467
|
+
if (inherited.repeats) {
|
|
12468
|
+
add(`${path4}/props/text`, props.text, "chrome", extra);
|
|
12469
|
+
break;
|
|
12470
|
+
}
|
|
12471
|
+
const level = typeof props.level === "number" && Number.isFinite(props.level) ? props.level : 1;
|
|
12472
|
+
add(`${path4}/props/text`, props.text, "heading", { ...extra, level });
|
|
12473
|
+
if (typeof props.text === "string" && props.text.trim() !== "" && !scope.inCell) {
|
|
12474
|
+
headings.push({ text: props.text, level, section: scope.section });
|
|
12475
|
+
}
|
|
12476
|
+
break;
|
|
12477
|
+
}
|
|
12478
|
+
case "toc": {
|
|
12479
|
+
add(`${path4}/props/title`, props.title, "toc-entry", extra);
|
|
12480
|
+
const styles = /* @__PURE__ */ new Set();
|
|
12481
|
+
if (Array.isArray(props.styles)) {
|
|
12482
|
+
for (const mapping of props.styles) {
|
|
12483
|
+
const id = asRecord(mapping)?.styleId;
|
|
12484
|
+
if (typeof id === "string") styles.add(id);
|
|
12485
|
+
}
|
|
12486
|
+
}
|
|
12487
|
+
tocs.push({
|
|
12488
|
+
at: entries.length,
|
|
12489
|
+
path: path4,
|
|
12490
|
+
depth: tocDepth(props.depth),
|
|
12491
|
+
styles,
|
|
12492
|
+
section: props.scope === "document" ? void 0 : scope.section
|
|
12493
|
+
});
|
|
12494
|
+
break;
|
|
12495
|
+
}
|
|
12496
|
+
case "paragraph": {
|
|
12497
|
+
const frame = frameOf(props);
|
|
12498
|
+
add(
|
|
12499
|
+
`${path4}/props/text`,
|
|
12500
|
+
props.text,
|
|
12501
|
+
inherited.repeats ? "chrome" : "body",
|
|
12502
|
+
{
|
|
12503
|
+
...extra,
|
|
12504
|
+
...frame && { frame }
|
|
12505
|
+
}
|
|
12506
|
+
);
|
|
12507
|
+
if (typeof props.themeStyle === "string" && typeof props.text === "string" && props.text.trim() !== "" && !scope.inCell) {
|
|
12508
|
+
headings.push({
|
|
12509
|
+
text: props.text,
|
|
12510
|
+
themeStyle: props.themeStyle,
|
|
12511
|
+
section: scope.section
|
|
12512
|
+
});
|
|
12513
|
+
}
|
|
12514
|
+
break;
|
|
12515
|
+
}
|
|
12516
|
+
case "list": {
|
|
12517
|
+
if (Array.isArray(props.items)) {
|
|
12518
|
+
props.items.forEach((item, index) => {
|
|
12519
|
+
const itemPath = `${path4}/props/items/${index}`;
|
|
12520
|
+
if (typeof item === "string")
|
|
12521
|
+
add(itemPath, item, "list-item", extra);
|
|
12522
|
+
else {
|
|
12523
|
+
const rec = asRecord(item);
|
|
12524
|
+
if (rec) add(`${itemPath}/text`, rec.text, "list-item", extra);
|
|
12525
|
+
}
|
|
12526
|
+
});
|
|
12527
|
+
}
|
|
12528
|
+
break;
|
|
12529
|
+
}
|
|
12530
|
+
case "table": {
|
|
12531
|
+
const columns = Array.isArray(props.columns) ? props.columns.map(asRecord) : [];
|
|
12532
|
+
columns.forEach((column, columnIndex) => {
|
|
12533
|
+
if (!column) return;
|
|
12534
|
+
visitCell(
|
|
12535
|
+
column.header,
|
|
12536
|
+
`${path4}/props/columns/${columnIndex}/header`,
|
|
12537
|
+
"table-header",
|
|
12538
|
+
inherited
|
|
12539
|
+
);
|
|
12540
|
+
});
|
|
12541
|
+
const rows = Math.max(
|
|
12542
|
+
0,
|
|
12543
|
+
...columns.map(
|
|
12544
|
+
(column) => Array.isArray(column?.cells) ? column.cells.length : 0
|
|
12545
|
+
)
|
|
12546
|
+
);
|
|
12547
|
+
for (let row = 0; row < rows; row++) {
|
|
12548
|
+
columns.forEach((column, columnIndex) => {
|
|
12549
|
+
if (!column || !Array.isArray(column.cells)) return;
|
|
12550
|
+
if (row >= column.cells.length) return;
|
|
12551
|
+
visitCell(
|
|
12552
|
+
column.cells[row],
|
|
12553
|
+
`${path4}/props/columns/${columnIndex}/cells/${row}`,
|
|
12554
|
+
"table-cell",
|
|
12555
|
+
inherited
|
|
12556
|
+
);
|
|
12557
|
+
});
|
|
12558
|
+
}
|
|
12559
|
+
break;
|
|
12560
|
+
}
|
|
12561
|
+
case "statistic": {
|
|
12562
|
+
add(`${path4}/props/number`, props.number, "statistic", extra);
|
|
12563
|
+
add(`${path4}/props/description`, props.description, "statistic", extra);
|
|
12564
|
+
break;
|
|
12565
|
+
}
|
|
12566
|
+
case "chart": {
|
|
12567
|
+
if (props.showTitle !== false) {
|
|
12568
|
+
add(`${path4}/props/title`, props.title, "caption", extra);
|
|
12569
|
+
}
|
|
12570
|
+
if (props.type !== "pie" && props.type !== "doughnut") {
|
|
12571
|
+
add(
|
|
12572
|
+
`${path4}/props/catAxisTitle`,
|
|
12573
|
+
props.catAxisTitle,
|
|
12574
|
+
"caption",
|
|
12575
|
+
extra
|
|
12576
|
+
);
|
|
12577
|
+
add(
|
|
12578
|
+
`${path4}/props/valAxisTitle`,
|
|
12579
|
+
props.valAxisTitle,
|
|
12580
|
+
"caption",
|
|
12581
|
+
extra
|
|
12582
|
+
);
|
|
12583
|
+
}
|
|
12584
|
+
add(`${path4}/props/caption`, props.caption, "caption", extra);
|
|
12585
|
+
break;
|
|
12586
|
+
}
|
|
12587
|
+
case "image":
|
|
12588
|
+
case "highcharts":
|
|
12589
|
+
case "visual":
|
|
12590
|
+
case "visual-native": {
|
|
12591
|
+
add(`${path4}/props/caption`, props.caption, "caption", extra);
|
|
12592
|
+
break;
|
|
12593
|
+
}
|
|
12594
|
+
case "section": {
|
|
12595
|
+
for (const part of ["header", "footer"]) {
|
|
12596
|
+
const components = props[part];
|
|
12597
|
+
if (!Array.isArray(components)) continue;
|
|
12598
|
+
components.forEach((component, index) => {
|
|
12599
|
+
const rec = asRecord(component);
|
|
12600
|
+
if (rec) {
|
|
12601
|
+
visitNode(rec, `${path4}/props/${part}/${index}`, {
|
|
12602
|
+
repeats: true
|
|
12603
|
+
});
|
|
12604
|
+
}
|
|
12605
|
+
});
|
|
12606
|
+
}
|
|
12607
|
+
break;
|
|
12608
|
+
}
|
|
12609
|
+
default:
|
|
12610
|
+
break;
|
|
12611
|
+
}
|
|
12612
|
+
if (Array.isArray(node.children)) {
|
|
12613
|
+
node.children.forEach((child, index) => {
|
|
12614
|
+
const rec = asRecord(child);
|
|
12615
|
+
if (rec) visitNode(rec, `${path4}/children/${index}`, scope);
|
|
12616
|
+
});
|
|
12617
|
+
}
|
|
12618
|
+
};
|
|
12619
|
+
children.forEach((child, index) => {
|
|
12620
|
+
const rec = asRecord(child);
|
|
12621
|
+
if (rec) visitNode(rec, `${basePath}/${index}`, {});
|
|
12622
|
+
});
|
|
12623
|
+
for (const toc of [...tocs].reverse()) {
|
|
12624
|
+
const collected = headings.filter(
|
|
12625
|
+
(heading) => (toc.section === void 0 || heading.section === toc.section) && (heading.level !== void 0 ? heading.level >= toc.depth.from && heading.level <= toc.depth.to : heading.themeStyle !== void 0 && toc.styles.has(heading.themeStyle))
|
|
12626
|
+
);
|
|
12627
|
+
entries.splice(
|
|
12628
|
+
toc.at,
|
|
12629
|
+
0,
|
|
12630
|
+
...collected.map(
|
|
12631
|
+
(heading, index) => ({
|
|
12632
|
+
id: `docx:text:${toc.path}:entry:${index}`,
|
|
12633
|
+
kind: "docx/text",
|
|
12634
|
+
path: toc.path,
|
|
12635
|
+
text: heading.text,
|
|
12636
|
+
role: "toc-entry",
|
|
12637
|
+
order: 0,
|
|
12638
|
+
optional: true
|
|
12639
|
+
})
|
|
12640
|
+
)
|
|
12641
|
+
);
|
|
12642
|
+
}
|
|
12643
|
+
entries.forEach((entry, index) => {
|
|
12644
|
+
entry.order = index;
|
|
12645
|
+
});
|
|
12646
|
+
return entries;
|
|
12647
|
+
}
|
|
12648
|
+
|
|
12649
|
+
// src/quality/facts.ts
|
|
12650
|
+
function asRecord2(value) {
|
|
12651
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
12652
|
+
}
|
|
12402
12653
|
function pageBox(theme, themeName, pageOverride) {
|
|
12403
12654
|
const page = createSectionProperties(
|
|
12404
12655
|
getColumnSettings("single"),
|
|
@@ -12424,7 +12675,7 @@ function tableFact(props, path4, availableWidthTwips) {
|
|
|
12424
12675
|
let percentSum = 0;
|
|
12425
12676
|
const explicitWidths = [];
|
|
12426
12677
|
columns.forEach((column, index) => {
|
|
12427
|
-
const width =
|
|
12678
|
+
const width = asRecord2(column)?.width;
|
|
12428
12679
|
if (typeof width === "number" && Number.isFinite(width)) {
|
|
12429
12680
|
hasExplicitWidth = true;
|
|
12430
12681
|
explicitWidths.push({ index, width });
|
|
@@ -12505,7 +12756,7 @@ function chartFact(node, props, path4, paletteTokens) {
|
|
|
12505
12756
|
const categoryCount = Math.max(
|
|
12506
12757
|
0,
|
|
12507
12758
|
...series.map((entry) => {
|
|
12508
|
-
const record =
|
|
12759
|
+
const record = asRecord2(entry);
|
|
12509
12760
|
const labels = Array.isArray(record?.labels) ? record.labels.length : 0;
|
|
12510
12761
|
const values = Array.isArray(record?.values) ? record.values.length : 0;
|
|
12511
12762
|
return Math.max(labels, values);
|
|
@@ -12547,8 +12798,8 @@ function statesOwnBorders(authored) {
|
|
|
12547
12798
|
return true;
|
|
12548
12799
|
}
|
|
12549
12800
|
const layers = [
|
|
12550
|
-
|
|
12551
|
-
|
|
12801
|
+
asRecord2(authored.cellDefaults),
|
|
12802
|
+
asRecord2(authored.headerCellDefaults)
|
|
12552
12803
|
];
|
|
12553
12804
|
if (layers.some(
|
|
12554
12805
|
(layer) => layer?.borderSize !== void 0 || layer?.borderColor !== void 0
|
|
@@ -12557,8 +12808,8 @@ function statesOwnBorders(authored) {
|
|
|
12557
12808
|
}
|
|
12558
12809
|
const columns = Array.isArray(authored.columns) ? authored.columns : [];
|
|
12559
12810
|
return columns.some((column) => {
|
|
12560
|
-
const record =
|
|
12561
|
-
const defaults =
|
|
12811
|
+
const record = asRecord2(column);
|
|
12812
|
+
const defaults = asRecord2(record?.cellDefaults);
|
|
12562
12813
|
return defaults?.borderSize !== void 0 || defaults?.borderColor !== void 0;
|
|
12563
12814
|
});
|
|
12564
12815
|
}
|
|
@@ -12582,7 +12833,7 @@ function tableDesignFact(props, path4, theme, themeName, authored) {
|
|
|
12582
12833
|
);
|
|
12583
12834
|
const columns = authoredColumns.map(
|
|
12584
12835
|
(column, index) => {
|
|
12585
|
-
const authoredColumn =
|
|
12836
|
+
const authoredColumn = asRecord2(column) ?? {};
|
|
12586
12837
|
const cells = Array.isArray(authoredColumn.cells) ? authoredColumn.cells : [];
|
|
12587
12838
|
const alignments = /* @__PURE__ */ new Set();
|
|
12588
12839
|
const values = [];
|
|
@@ -12601,11 +12852,11 @@ function tableDesignFact(props, path4, theme, themeName, authored) {
|
|
|
12601
12852
|
},
|
|
12602
12853
|
values,
|
|
12603
12854
|
alignment: alignments.size === 1 ? [...alignments][0] : alignments.size === 0 ? "left" : "mixed",
|
|
12604
|
-
hasCellDefaults:
|
|
12605
|
-
hasHeader:
|
|
12855
|
+
hasCellDefaults: asRecord2(authoredColumn.cellDefaults) !== void 0,
|
|
12856
|
+
hasHeader: asRecord2(authoredColumn.header) !== void 0,
|
|
12606
12857
|
generated: false,
|
|
12607
12858
|
cellsWithOwnAlignment: cells.flatMap((cell, cellIndex) => {
|
|
12608
|
-
const alignment2 =
|
|
12859
|
+
const alignment2 = asRecord2(cell)?.horizontalAlignment;
|
|
12609
12860
|
return typeof alignment2 === "string" && DOCX_ALIGNMENTS.has(alignment2) && alignment2 !== "right" ? [cellIndex] : [];
|
|
12610
12861
|
})
|
|
12611
12862
|
};
|
|
@@ -12626,7 +12877,7 @@ function finiteNumber(value) {
|
|
|
12626
12877
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
12627
12878
|
}
|
|
12628
12879
|
function lineHeightPt(fontSizePt, spacing) {
|
|
12629
|
-
const rule =
|
|
12880
|
+
const rule = asRecord2(spacing);
|
|
12630
12881
|
const value = finiteNumber(rule?.value);
|
|
12631
12882
|
switch (rule?.type) {
|
|
12632
12883
|
// `exactly` is an absolute line box, and display type routinely sets it
|
|
@@ -12643,7 +12894,7 @@ function lineHeightPt(fontSizePt, spacing) {
|
|
|
12643
12894
|
}
|
|
12644
12895
|
}
|
|
12645
12896
|
function characterSpacingPt(spacing) {
|
|
12646
|
-
const rule =
|
|
12897
|
+
const rule = asRecord2(spacing);
|
|
12647
12898
|
const value = finiteNumber(rule?.value);
|
|
12648
12899
|
if (rule === void 0 || value === void 0) return 0;
|
|
12649
12900
|
return rule.type === "condensed" ? -value / TWIPS_PER_POINT3 : value / TWIPS_PER_POINT3;
|
|
@@ -12657,7 +12908,7 @@ function nodeAtPointer(root, pointer) {
|
|
|
12657
12908
|
current = current[index];
|
|
12658
12909
|
continue;
|
|
12659
12910
|
}
|
|
12660
|
-
const record =
|
|
12911
|
+
const record = asRecord2(current);
|
|
12661
12912
|
if (!record) return void 0;
|
|
12662
12913
|
current = record[token];
|
|
12663
12914
|
}
|
|
@@ -12673,10 +12924,10 @@ function styleKey(node, props) {
|
|
|
12673
12924
|
return typeof props.themeStyle === "string" && props.themeStyle !== "" ? props.themeStyle : "normal";
|
|
12674
12925
|
}
|
|
12675
12926
|
function effectiveFontSize(node, props, typography) {
|
|
12676
|
-
const authored = finiteNumber(
|
|
12927
|
+
const authored = finiteNumber(asRecord2(props.font)?.size);
|
|
12677
12928
|
if (authored !== void 0) return { fontSizePt: authored, authored: true };
|
|
12678
12929
|
const { styles, theme } = typography;
|
|
12679
|
-
const style =
|
|
12930
|
+
const style = asRecord2(styles[styleKey(node, props)]) ?? asRecord2(styles.normal);
|
|
12680
12931
|
const stated = finiteNumber(style?.size);
|
|
12681
12932
|
if (stated !== void 0) return { fontSizePt: stated, authored: false };
|
|
12682
12933
|
const reference = style?.font === "heading" || style?.font === "body" || style?.font === "mono" || style?.font === "light" ? style.font : void 0;
|
|
@@ -12686,11 +12937,11 @@ function effectiveFontSize(node, props, typography) {
|
|
|
12686
12937
|
function pinnedLineBox(props, path4) {
|
|
12687
12938
|
const candidates = [
|
|
12688
12939
|
[props.lineSpacing, `${path4}/props/lineSpacing`],
|
|
12689
|
-
[
|
|
12940
|
+
[asRecord2(props.font)?.lineSpacing, `${path4}/props/font/lineSpacing`]
|
|
12690
12941
|
];
|
|
12691
12942
|
for (const [spacing, pointer] of candidates) {
|
|
12692
12943
|
if (spacing === void 0) continue;
|
|
12693
|
-
const rule =
|
|
12944
|
+
const rule = asRecord2(spacing);
|
|
12694
12945
|
if (rule?.type !== "exactly") return void 0;
|
|
12695
12946
|
const lineBoxPt = finiteNumber(rule.value);
|
|
12696
12947
|
return lineBoxPt === void 0 ? void 0 : { lineBoxPt, pointer };
|
|
@@ -12716,8 +12967,8 @@ function lineBoxFact(node, props, path4, typography, authored) {
|
|
|
12716
12967
|
};
|
|
12717
12968
|
}
|
|
12718
12969
|
function frameSignature(floating) {
|
|
12719
|
-
const horizontal =
|
|
12720
|
-
const vertical =
|
|
12970
|
+
const horizontal = asRecord2(floating.horizontalPosition);
|
|
12971
|
+
const vertical = asRecord2(floating.verticalPosition);
|
|
12721
12972
|
return JSON.stringify([
|
|
12722
12973
|
floating.width ?? null,
|
|
12723
12974
|
floating.height ?? null,
|
|
@@ -12727,24 +12978,24 @@ function frameSignature(floating) {
|
|
|
12727
12978
|
vertical?.offset ?? null,
|
|
12728
12979
|
vertical?.relative ?? null,
|
|
12729
12980
|
vertical?.align ?? null,
|
|
12730
|
-
|
|
12981
|
+
asRecord2(floating.wrap)?.type ?? null
|
|
12731
12982
|
]);
|
|
12732
12983
|
}
|
|
12733
12984
|
function frameTextFact(props, path4, page, frameChainId, flowIndex) {
|
|
12734
|
-
const floating =
|
|
12985
|
+
const floating = asRecord2(props.floating);
|
|
12735
12986
|
const frameWidthTwips = finiteNumber(floating?.width);
|
|
12736
12987
|
if (frameWidthTwips === void 0) return void 0;
|
|
12737
12988
|
const text = typeof props.text === "string" ? props.text : "";
|
|
12738
12989
|
if (text.trim() === "") return void 0;
|
|
12739
|
-
const font =
|
|
12990
|
+
const font = asRecord2(props.font);
|
|
12740
12991
|
const fontSizePt = finiteNumber(font?.size);
|
|
12741
12992
|
if (fontSizePt === void 0) return void 0;
|
|
12742
12993
|
const longestWord = text.split(/\s+/).reduce(
|
|
12743
12994
|
(longest, word) => word.length > longest.length ? word : longest,
|
|
12744
12995
|
""
|
|
12745
12996
|
);
|
|
12746
|
-
const horizontal =
|
|
12747
|
-
const vertical =
|
|
12997
|
+
const horizontal = asRecord2(floating?.horizontalPosition);
|
|
12998
|
+
const vertical = asRecord2(floating?.verticalPosition);
|
|
12748
12999
|
const offsetX = finiteNumber(horizontal?.offset);
|
|
12749
13000
|
const offsetY = finiteNumber(vertical?.offset);
|
|
12750
13001
|
const absolutelyPinned = horizontal?.offset !== void 0 || vertical?.offset !== void 0;
|
|
@@ -12815,7 +13066,7 @@ function svgTextFacts(props, path4) {
|
|
|
12815
13066
|
return facts;
|
|
12816
13067
|
}
|
|
12817
13068
|
function walkActive(node, path4, page, visit) {
|
|
12818
|
-
const rec =
|
|
13069
|
+
const rec = asRecord2(node);
|
|
12819
13070
|
if (!rec || rec.enabled === false) return;
|
|
12820
13071
|
visit(rec, path4, page);
|
|
12821
13072
|
const children = Array.isArray(rec.children) ? rec.children : [];
|
|
@@ -12838,7 +13089,7 @@ function textSizeFact(node, props, path4, typography, role) {
|
|
|
12838
13089
|
}
|
|
12839
13090
|
function tableTextSizeFacts(props, authored, path4, typography, page) {
|
|
12840
13091
|
const facts = [];
|
|
12841
|
-
const sizeOf = (holder) => finiteNumber(
|
|
13092
|
+
const sizeOf = (holder) => finiteNumber(asRecord2(asRecord2(holder)?.font)?.size);
|
|
12842
13093
|
const authoredSize = (holder, pointer, role) => {
|
|
12843
13094
|
const size = sizeOf(holder);
|
|
12844
13095
|
if (size === void 0) return;
|
|
@@ -12853,11 +13104,11 @@ function tableTextSizeFacts(props, authored, path4, typography, page) {
|
|
|
12853
13104
|
});
|
|
12854
13105
|
};
|
|
12855
13106
|
const cellContent = (holder, pointer, role) => {
|
|
12856
|
-
const content =
|
|
12857
|
-
if (
|
|
13107
|
+
const content = asRecord2(holder)?.content;
|
|
13108
|
+
if (asRecord2(content) === void 0) return;
|
|
12858
13109
|
walkActive(content, `${pointer}/content`, page, (node, nodePath) => {
|
|
12859
13110
|
if (node.name !== "paragraph" && node.name !== "heading") return;
|
|
12860
|
-
const nodeProps =
|
|
13111
|
+
const nodeProps = asRecord2(node.props) ?? {};
|
|
12861
13112
|
if (typeof nodeProps.text !== "string" || nodeProps.text.trim() === "")
|
|
12862
13113
|
return;
|
|
12863
13114
|
const fact = textSizeFact(node, nodeProps, nodePath, typography, role);
|
|
@@ -12877,7 +13128,7 @@ function tableTextSizeFacts(props, authored, path4, typography, page) {
|
|
|
12877
13128
|
);
|
|
12878
13129
|
const columns = Array.isArray(authored.columns) ? authored.columns : [];
|
|
12879
13130
|
columns.forEach((column, index) => {
|
|
12880
|
-
const record =
|
|
13131
|
+
const record = asRecord2(column) ?? {};
|
|
12881
13132
|
const columnPath = `${path4}/props/columns/${index}`;
|
|
12882
13133
|
authoredSize(
|
|
12883
13134
|
record.cellDefaults,
|
|
@@ -12974,7 +13225,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12974
13225
|
let inherited = {};
|
|
12975
13226
|
topLevel.forEach((node, index) => {
|
|
12976
13227
|
if (node?.name !== "section") return;
|
|
12977
|
-
const props =
|
|
13228
|
+
const props = asRecord2(node.props) ?? {};
|
|
12978
13229
|
const part = (kind) => props[kind] === "linkToPrevious" ? inherited[kind] : props[kind];
|
|
12979
13230
|
const header = part("header");
|
|
12980
13231
|
const footer = part("footer");
|
|
@@ -12982,8 +13233,8 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12982
13233
|
for (const kind of ["header", "footer"]) {
|
|
12983
13234
|
if (!Array.isArray(props[kind])) continue;
|
|
12984
13235
|
const drawnByBlock = !Array.isArray(
|
|
12985
|
-
|
|
12986
|
-
|
|
13236
|
+
asRecord2(
|
|
13237
|
+
asRecord2(
|
|
12987
13238
|
(Array.isArray(themed.document.children) ? themed.document.children : [])[index]
|
|
12988
13239
|
)?.props
|
|
12989
13240
|
)?.[kind]
|
|
@@ -12991,7 +13242,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12991
13242
|
const part2 = props[kind];
|
|
12992
13243
|
const visitChrome = (child, childPath) => {
|
|
12993
13244
|
if (child.name !== "paragraph" && child.name !== "heading") return;
|
|
12994
|
-
const childProps =
|
|
13245
|
+
const childProps = asRecord2(child.props) ?? {};
|
|
12995
13246
|
if (typeof childProps.text !== "string" || childProps.text.trim() === "")
|
|
12996
13247
|
return;
|
|
12997
13248
|
const fact = textSizeFact(
|
|
@@ -13048,7 +13299,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13048
13299
|
const paletteTokens = resolved.theme.palette?.chart?.map(
|
|
13049
13300
|
(value) => `#${resolveDesignColor2(value, visualColors)}`
|
|
13050
13301
|
) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
|
|
13051
|
-
const authoredPropsAt = (pointer) =>
|
|
13302
|
+
const authoredPropsAt = (pointer) => asRecord2(asRecord2(nodeAtPointer(context.document, pointer))?.props);
|
|
13052
13303
|
const roleSizesPt = {};
|
|
13053
13304
|
for (const key of Object.keys(typography.styles)) {
|
|
13054
13305
|
const size = effectiveFontSize(
|
|
@@ -13084,7 +13335,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13084
13335
|
fontFamilies: [
|
|
13085
13336
|
...new Set(
|
|
13086
13337
|
["heading", "body"].flatMap((role) => {
|
|
13087
|
-
const family =
|
|
13338
|
+
const family = asRecord2(
|
|
13088
13339
|
resolved.theme.fonts?.[role]
|
|
13089
13340
|
)?.family;
|
|
13090
13341
|
return typeof family === "string" && family.trim() !== "" ? [family] : [];
|
|
@@ -13120,12 +13371,15 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13120
13371
|
excerpt: occurrence.match.excerpt
|
|
13121
13372
|
});
|
|
13122
13373
|
});
|
|
13374
|
+
for (const entry of collectDocxTextInventory(resolved.children)) {
|
|
13375
|
+
addFact({ ...entry, generated: authoredPath(entry.path) !== entry.path });
|
|
13376
|
+
}
|
|
13123
13377
|
let previousVisitPath;
|
|
13124
13378
|
let lastFrame;
|
|
13125
13379
|
let flowIndex = 0;
|
|
13126
13380
|
const parentOf = (path4) => path4.slice(0, path4.lastIndexOf("/"));
|
|
13127
13381
|
const visit = (node, path4, page) => {
|
|
13128
|
-
const props =
|
|
13382
|
+
const props = asRecord2(node.props) ?? {};
|
|
13129
13383
|
if (node.name === "table") {
|
|
13130
13384
|
const fact = tableFact(props, path4, page.availableWidthTwips);
|
|
13131
13385
|
if (fact) addFact(fact);
|
|
@@ -13154,7 +13408,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13154
13408
|
return {
|
|
13155
13409
|
...column,
|
|
13156
13410
|
path: authored,
|
|
13157
|
-
generated: table2 === void 0 ||
|
|
13411
|
+
generated: table2 === void 0 || asRecord2(nodeAtPointer(themed.document, table2))?.name !== "table"
|
|
13158
13412
|
};
|
|
13159
13413
|
})
|
|
13160
13414
|
});
|
|
@@ -13170,7 +13424,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13170
13424
|
addFact({
|
|
13171
13425
|
...fact,
|
|
13172
13426
|
generated: !["chart", "highcharts"].includes(
|
|
13173
|
-
String(
|
|
13427
|
+
String(asRecord2(nodeAtPointer(themed.document, authored))?.name)
|
|
13174
13428
|
),
|
|
13175
13429
|
seriesColorsPath: authoredPath(fact.seriesColorsPath),
|
|
13176
13430
|
...fact.annotation && {
|
|
@@ -13184,7 +13438,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13184
13438
|
}
|
|
13185
13439
|
}
|
|
13186
13440
|
if (node.name === "paragraph" || node.name === "text-box") {
|
|
13187
|
-
const floating =
|
|
13441
|
+
const floating = asRecord2(props.floating);
|
|
13188
13442
|
if (floating) {
|
|
13189
13443
|
const signature = frameSignature(floating);
|
|
13190
13444
|
const chainId = lastFrame !== void 0 && previousVisitPath === lastFrame.path && parentOf(lastFrame.path) === parentOf(path4) && lastFrame.signature === signature ? lastFrame.chainId : `docx:frame-chain:${path4}`;
|
|
@@ -16324,6 +16578,7 @@ export {
|
|
|
16324
16578
|
analyzeDocxQuality,
|
|
16325
16579
|
blockSlotBudgets,
|
|
16326
16580
|
cleanComponentProps,
|
|
16581
|
+
collectDocxTextInventory,
|
|
16327
16582
|
consultingTheme,
|
|
16328
16583
|
createComponent,
|
|
16329
16584
|
createDocumentGenerator,
|