@json-to-office/core-docx 1.3.0 → 1.5.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/generateFromIr.d.ts +5 -1
- package/dist/core/generateFromIr.d.ts.map +1 -1
- package/dist/core/generator.d.ts +4 -0
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/structure.d.ts +13 -0
- package/dist/core/structure.d.ts.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1084 -348
- package/dist/index.js.map +1 -1
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/plugin/example/index.js +572 -251
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +82 -0
- package/dist/quality/facts.d.ts.map +1 -0
- package/dist/quality/preflight.d.ts +15 -0
- package/dist/quality/preflight.d.ts.map +1 -0
- package/dist/quality/rules.d.ts +38 -0
- package/dist/quality/rules.d.ts.map +1 -0
- package/dist/quality/text-metrics.d.ts +34 -0
- package/dist/quality/text-metrics.d.ts.map +1 -0
- package/dist/renderers/docxjs/index.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/renderers/registry.d.ts +18 -4
- package/dist/renderers/registry.d.ts.map +1 -1
- package/dist/styles/themeToStyles.d.ts +35 -1
- package/dist/styles/themeToStyles.d.ts.map +1 -1
- package/dist/templates/themes/apex.docx.theme.json +1 -2
- package/dist/templates/themes/corporate.docx.theme.json +1 -2
- package/dist/templates/themes/devportal.docx.theme.json +1 -2
- package/dist/templates/themes/minimal.docx.theme.json +1 -2
- package/dist/templates/themes/modern.docx.theme.json +1 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -14
|
@@ -355,8 +355,7 @@ var init_minimal_docx_theme = __esm({
|
|
|
355
355
|
},
|
|
356
356
|
list: {
|
|
357
357
|
format: "bullet",
|
|
358
|
-
bullet: "\u2022"
|
|
359
|
-
indent: 3
|
|
358
|
+
bullet: "\u2022"
|
|
360
359
|
},
|
|
361
360
|
image: {
|
|
362
361
|
alignment: "left"
|
|
@@ -480,8 +479,7 @@ var init_corporate_docx_theme = __esm({
|
|
|
480
479
|
},
|
|
481
480
|
list: {
|
|
482
481
|
format: "bullet",
|
|
483
|
-
bullet: "\u2022"
|
|
484
|
-
indent: 3
|
|
482
|
+
bullet: "\u2022"
|
|
485
483
|
},
|
|
486
484
|
statistic: {
|
|
487
485
|
alignment: "center"
|
|
@@ -594,8 +592,7 @@ var init_modern_docx_theme = __esm({
|
|
|
594
592
|
},
|
|
595
593
|
list: {
|
|
596
594
|
format: "bullet",
|
|
597
|
-
bullet: "\u2013"
|
|
598
|
-
indent: 3
|
|
595
|
+
bullet: "\u2013"
|
|
599
596
|
},
|
|
600
597
|
image: {
|
|
601
598
|
alignment: "center"
|
|
@@ -719,8 +716,7 @@ var init_apex_docx_theme = __esm({
|
|
|
719
716
|
},
|
|
720
717
|
list: {
|
|
721
718
|
format: "bullet",
|
|
722
|
-
bullet: "\u2022"
|
|
723
|
-
indent: 3
|
|
719
|
+
bullet: "\u2022"
|
|
724
720
|
},
|
|
725
721
|
image: {
|
|
726
722
|
alignment: "center"
|
|
@@ -852,8 +848,7 @@ var init_devportal_docx_theme = __esm({
|
|
|
852
848
|
},
|
|
853
849
|
list: {
|
|
854
850
|
format: "bullet",
|
|
855
|
-
bullet: "\u2013"
|
|
856
|
-
indent: 3
|
|
851
|
+
bullet: "\u2013"
|
|
857
852
|
},
|
|
858
853
|
image: {
|
|
859
854
|
alignment: "center"
|
|
@@ -2751,99 +2746,6 @@ var init_styles2 = __esm({
|
|
|
2751
2746
|
}
|
|
2752
2747
|
});
|
|
2753
2748
|
|
|
2754
|
-
// src/ir/features.ts
|
|
2755
|
-
var DOCX_FEATURES, ALL_DOCX_FEATURES;
|
|
2756
|
-
var init_features = __esm({
|
|
2757
|
-
"src/ir/features.ts"() {
|
|
2758
|
-
"use strict";
|
|
2759
|
-
DOCX_FEATURES = [
|
|
2760
|
-
/** Paragraphs and text runs — the floor of the format. */
|
|
2761
|
-
"paragraphs",
|
|
2762
|
-
/** Named paragraph and character styles in `styles.xml`. */
|
|
2763
|
-
"styles",
|
|
2764
|
-
/** Numbering definitions and numbered paragraphs. */
|
|
2765
|
-
"numbering",
|
|
2766
|
-
/** Multiple sections with their own page setup. */
|
|
2767
|
-
"sections",
|
|
2768
|
-
/** Multi-column section layout. */
|
|
2769
|
-
"columns",
|
|
2770
|
-
/** Header and footer parts, including first/even variants. */
|
|
2771
|
-
"headers-footers",
|
|
2772
|
-
"tables",
|
|
2773
|
-
/** Merged table cells — column span or vertical merge. */
|
|
2774
|
-
"table-merged-cells",
|
|
2775
|
-
/** A table positioned out of the text flow. */
|
|
2776
|
-
"floating-tables",
|
|
2777
|
-
/** Inline images. */
|
|
2778
|
-
"images",
|
|
2779
|
-
/** Anchored images with text wrapping. */
|
|
2780
|
-
"floating-images",
|
|
2781
|
-
/** SVG images with a raster fallback. */
|
|
2782
|
-
"svg-images",
|
|
2783
|
-
/** A paragraph positioned as a floating frame. */
|
|
2784
|
-
"text-frames",
|
|
2785
|
-
/** Native shape text boxes. */
|
|
2786
|
-
"text-boxes",
|
|
2787
|
-
/**
|
|
2788
|
-
* A DrawingML group: shapes, text boxes and pictures sharing one child
|
|
2789
|
-
* coordinate space, drawn as a single anchored or inline object.
|
|
2790
|
-
*
|
|
2791
|
-
* Separate from `text-boxes` because a lone `wps:wsp` run is a far smaller
|
|
2792
|
-
* ask than `wpg:wgp` with child transforms, preset geometry and grouped
|
|
2793
|
-
* pictures — a backend can plausibly have the first and not the second.
|
|
2794
|
-
*/
|
|
2795
|
-
"drawing-groups",
|
|
2796
|
-
/**
|
|
2797
|
-
* A native chart part: a `c:chartSpace` with its own embedded workbook.
|
|
2798
|
-
*
|
|
2799
|
-
* Separate from `images` because a chart is not a picture with extra data —
|
|
2800
|
-
* it is its own part, its own relationship and its own workbook, and a
|
|
2801
|
-
* backend either writes all three or writes none. docx.js has no chart
|
|
2802
|
-
* primitive at all, which is what turns a `chart` component sent to that
|
|
2803
|
-
* backend into a named capability error rather than a document missing a
|
|
2804
|
-
* figure.
|
|
2805
|
-
*/
|
|
2806
|
-
"charts",
|
|
2807
|
-
/** A table-of-contents field. */
|
|
2808
|
-
"toc",
|
|
2809
|
-
/** TOC entries baked in so an unrefreshed reader still shows them. */
|
|
2810
|
-
"cached-toc",
|
|
2811
|
-
/** Arbitrary Word fields, e.g. PAGE, NUMPAGES, REF. */
|
|
2812
|
-
"fields",
|
|
2813
|
-
/** Field results cached for readers that never refresh. */
|
|
2814
|
-
"cached-fields",
|
|
2815
|
-
"hyperlinks",
|
|
2816
|
-
"bookmarks",
|
|
2817
|
-
/** Links and REF fields that target a bookmark. */
|
|
2818
|
-
"cross-references",
|
|
2819
|
-
"comments",
|
|
2820
|
-
/** Threaded and resolvable comments. */
|
|
2821
|
-
"comment-threads",
|
|
2822
|
-
"footnotes",
|
|
2823
|
-
"endnotes",
|
|
2824
|
-
/** Inserted and deleted content. */
|
|
2825
|
-
"revisions",
|
|
2826
|
-
/** Page, column and line breaks. */
|
|
2827
|
-
"breaks",
|
|
2828
|
-
/** Paragraph and table shading. */
|
|
2829
|
-
"shading",
|
|
2830
|
-
/** Paragraph, table and page borders. */
|
|
2831
|
-
"borders",
|
|
2832
|
-
/** Tab stops. */
|
|
2833
|
-
"tab-stops",
|
|
2834
|
-
/** Per-run proofing language and no-proof. */
|
|
2835
|
-
"proofing-language",
|
|
2836
|
-
/** Custom document properties. */
|
|
2837
|
-
"custom-properties",
|
|
2838
|
-
/** Right-to-left paragraph direction. */
|
|
2839
|
-
"rtl"
|
|
2840
|
-
];
|
|
2841
|
-
ALL_DOCX_FEATURES = new Set(
|
|
2842
|
-
DOCX_FEATURES
|
|
2843
|
-
);
|
|
2844
|
-
}
|
|
2845
|
-
});
|
|
2846
|
-
|
|
2847
2749
|
// src/utils/packageDocument.ts
|
|
2848
2750
|
import AdmZip from "adm-zip";
|
|
2849
2751
|
function resolveGenerationDate(options) {
|
|
@@ -3251,37 +3153,47 @@ function coreProperties(ir) {
|
|
|
3251
3153
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
3252
3154
|
};
|
|
3253
3155
|
}
|
|
3254
|
-
var DOCXJS_RENDERER_ID,
|
|
3156
|
+
var DOCXJS_RENDERER_ID, DOCXJS_CAPABILITIES;
|
|
3255
3157
|
var init_docxjs = __esm({
|
|
3256
3158
|
"src/renderers/docxjs/index.ts"() {
|
|
3257
3159
|
"use strict";
|
|
3258
3160
|
init_styles2();
|
|
3259
3161
|
init_imageUtils();
|
|
3260
|
-
init_features();
|
|
3261
3162
|
init_packageDocument();
|
|
3262
3163
|
init_fixFloatingImageIds();
|
|
3263
3164
|
init_emit();
|
|
3264
3165
|
init_units();
|
|
3265
3166
|
DOCXJS_RENDERER_ID = "docxjs";
|
|
3266
|
-
|
|
3267
|
-
"
|
|
3268
|
-
"
|
|
3269
|
-
"
|
|
3270
|
-
"
|
|
3271
|
-
"
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
"
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
"
|
|
3167
|
+
DOCXJS_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
3168
|
+
"paragraphs",
|
|
3169
|
+
"styles",
|
|
3170
|
+
"numbering",
|
|
3171
|
+
"sections",
|
|
3172
|
+
"columns",
|
|
3173
|
+
"headers-footers",
|
|
3174
|
+
"tables",
|
|
3175
|
+
"floating-tables",
|
|
3176
|
+
"images",
|
|
3177
|
+
"floating-images",
|
|
3178
|
+
"svg-images",
|
|
3179
|
+
"text-frames",
|
|
3180
|
+
"text-boxes",
|
|
3181
|
+
"toc",
|
|
3182
|
+
"cached-toc",
|
|
3183
|
+
"fields",
|
|
3184
|
+
"hyperlinks",
|
|
3185
|
+
"bookmarks",
|
|
3186
|
+
"cross-references",
|
|
3187
|
+
"comments",
|
|
3188
|
+
"comment-threads",
|
|
3189
|
+
"footnotes",
|
|
3190
|
+
"endnotes",
|
|
3191
|
+
"revisions",
|
|
3192
|
+
"breaks",
|
|
3193
|
+
"tab-stops",
|
|
3194
|
+
"proofing-language",
|
|
3195
|
+
"custom-properties"
|
|
3281
3196
|
]);
|
|
3282
|
-
DOCXJS_CAPABILITIES = new Set(
|
|
3283
|
-
[...ALL_DOCX_FEATURES].filter((feature) => !NOT_YET_EMITTED.has(feature))
|
|
3284
|
-
);
|
|
3285
3197
|
}
|
|
3286
3198
|
});
|
|
3287
3199
|
|
|
@@ -4539,11 +4451,10 @@ function coreProperties2(ir) {
|
|
|
4539
4451
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
4540
4452
|
};
|
|
4541
4453
|
}
|
|
4542
|
-
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX,
|
|
4454
|
+
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX, OFFICE_OPEN_CAPABILITIES;
|
|
4543
4455
|
var init_office_open = __esm({
|
|
4544
4456
|
"src/renderers/office-open/index.ts"() {
|
|
4545
4457
|
"use strict";
|
|
4546
|
-
init_features();
|
|
4547
4458
|
init_chartParts();
|
|
4548
4459
|
init_imageUtils();
|
|
4549
4460
|
init_packageDocument();
|
|
@@ -4551,17 +4462,37 @@ var init_office_open = __esm({
|
|
|
4551
4462
|
init_styles3();
|
|
4552
4463
|
OFFICE_OPEN_DOCX_RENDERER_ID = "office-open";
|
|
4553
4464
|
OFFICE_OPEN_DOCX = "@office-open/docx";
|
|
4554
|
-
|
|
4555
|
-
"
|
|
4556
|
-
"
|
|
4557
|
-
"
|
|
4558
|
-
"
|
|
4559
|
-
"
|
|
4560
|
-
"
|
|
4465
|
+
OFFICE_OPEN_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
4466
|
+
"paragraphs",
|
|
4467
|
+
"styles",
|
|
4468
|
+
"numbering",
|
|
4469
|
+
"sections",
|
|
4470
|
+
"columns",
|
|
4471
|
+
"headers-footers",
|
|
4472
|
+
"tables",
|
|
4473
|
+
"floating-tables",
|
|
4474
|
+
"images",
|
|
4475
|
+
"floating-images",
|
|
4476
|
+
"svg-images",
|
|
4477
|
+
"text-frames",
|
|
4478
|
+
"text-boxes",
|
|
4479
|
+
"drawing-groups",
|
|
4480
|
+
"charts",
|
|
4481
|
+
"toc",
|
|
4482
|
+
"cached-toc",
|
|
4483
|
+
"fields",
|
|
4484
|
+
"hyperlinks",
|
|
4485
|
+
"bookmarks",
|
|
4486
|
+
"cross-references",
|
|
4487
|
+
"comments",
|
|
4488
|
+
"footnotes",
|
|
4489
|
+
"endnotes",
|
|
4490
|
+
"revisions",
|
|
4491
|
+
"breaks",
|
|
4492
|
+
"tab-stops",
|
|
4493
|
+
"proofing-language",
|
|
4494
|
+
"custom-properties"
|
|
4561
4495
|
]);
|
|
4562
|
-
OFFICE_OPEN_CAPABILITIES = new Set(
|
|
4563
|
-
[...ALL_DOCX_FEATURES].filter((feature) => !UNSUPPORTED.has(feature))
|
|
4564
|
-
);
|
|
4565
4496
|
}
|
|
4566
4497
|
});
|
|
4567
4498
|
|
|
@@ -5275,88 +5206,6 @@ async function prerasterizeVisuals(root, serviceConfig, options = {}) {
|
|
|
5275
5206
|
return map;
|
|
5276
5207
|
}
|
|
5277
5208
|
|
|
5278
|
-
// src/json/normalizer.ts
|
|
5279
|
-
function normalizeComponent(component) {
|
|
5280
|
-
if (component.name === "columns") {
|
|
5281
|
-
return normalizeColumnsComponent(component);
|
|
5282
|
-
}
|
|
5283
|
-
if ("children" in component && component.children) {
|
|
5284
|
-
return {
|
|
5285
|
-
...component,
|
|
5286
|
-
// Preserve ALL properties from validated component
|
|
5287
|
-
children: component.children.map(normalizeComponent)
|
|
5288
|
-
};
|
|
5289
|
-
}
|
|
5290
|
-
if (component.name === "section") {
|
|
5291
|
-
return normalizeSectionComponent(component);
|
|
5292
|
-
}
|
|
5293
|
-
return component;
|
|
5294
|
-
}
|
|
5295
|
-
function normalizeColumnsComponent(component) {
|
|
5296
|
-
const cfg = component.props || {};
|
|
5297
|
-
const applyTopLevelGap = (cols, topGap) => cols.map((c, i) => {
|
|
5298
|
-
const isLast = i === cols.length - 1;
|
|
5299
|
-
if (!isLast && c.gap === void 0 && topGap !== void 0) {
|
|
5300
|
-
return { ...c, gap: topGap };
|
|
5301
|
-
}
|
|
5302
|
-
return c;
|
|
5303
|
-
});
|
|
5304
|
-
const normalizeAutoWidth = (cols) => cols.map((c) => ({
|
|
5305
|
-
...c,
|
|
5306
|
-
width: c.width === "auto" ? void 0 : c.width
|
|
5307
|
-
}));
|
|
5308
|
-
let columnsArray;
|
|
5309
|
-
if (typeof cfg.columns === "number" && cfg.columns > 0) {
|
|
5310
|
-
const n = cfg.columns;
|
|
5311
|
-
const base = Array.from(
|
|
5312
|
-
{ length: n },
|
|
5313
|
-
() => ({})
|
|
5314
|
-
);
|
|
5315
|
-
const topLevelGap = cfg.gap !== void 0 ? cfg.gap : "5%";
|
|
5316
|
-
columnsArray = applyTopLevelGap(base, topLevelGap);
|
|
5317
|
-
} else if (Array.isArray(cfg.columns)) {
|
|
5318
|
-
columnsArray = cfg.columns;
|
|
5319
|
-
const topLevelGap = cfg.gap !== void 0 ? cfg.gap : "5%";
|
|
5320
|
-
columnsArray = applyTopLevelGap(columnsArray, topLevelGap);
|
|
5321
|
-
columnsArray = normalizeAutoWidth(columnsArray);
|
|
5322
|
-
} else {
|
|
5323
|
-
columnsArray = [{}];
|
|
5324
|
-
}
|
|
5325
|
-
const normalizedProps = {
|
|
5326
|
-
columns: columnsArray
|
|
5327
|
-
};
|
|
5328
|
-
return {
|
|
5329
|
-
...component,
|
|
5330
|
-
// Preserve any additional properties
|
|
5331
|
-
name: "columns",
|
|
5332
|
-
props: normalizedProps,
|
|
5333
|
-
children: component.children ? component.children.map(normalizeComponent) : void 0
|
|
5334
|
-
};
|
|
5335
|
-
}
|
|
5336
|
-
function normalizeSectionComponent(component) {
|
|
5337
|
-
const props = component.props || {};
|
|
5338
|
-
return {
|
|
5339
|
-
...component,
|
|
5340
|
-
// Preserve ALL properties
|
|
5341
|
-
props: {
|
|
5342
|
-
...props,
|
|
5343
|
-
// Preserve ALL props properties
|
|
5344
|
-
header: props.header ? props.header === "linkToPrevious" ? "linkToPrevious" : props.header.map((m) => normalizeComponent(m)) : void 0,
|
|
5345
|
-
footer: props.footer ? props.footer === "linkToPrevious" ? "linkToPrevious" : props.footer.map((m) => normalizeComponent(m)) : void 0
|
|
5346
|
-
},
|
|
5347
|
-
children: component.children ? component.children.map(normalizeComponent) : void 0
|
|
5348
|
-
};
|
|
5349
|
-
}
|
|
5350
|
-
function normalizeDocument(document) {
|
|
5351
|
-
if (document.name !== "docx") {
|
|
5352
|
-
throw new Error(
|
|
5353
|
-
'Top-level document must be a docx component with name="docx"'
|
|
5354
|
-
);
|
|
5355
|
-
}
|
|
5356
|
-
const normalized = normalizeComponent(document);
|
|
5357
|
-
return [normalized];
|
|
5358
|
-
}
|
|
5359
|
-
|
|
5360
5209
|
// src/core/desugarExternals.ts
|
|
5361
5210
|
import {
|
|
5362
5211
|
clampVisualDpi as clampVisualDpi2,
|
|
@@ -6192,6 +6041,13 @@ init_themes();
|
|
|
6192
6041
|
init_colorUtils();
|
|
6193
6042
|
init_styleHelpers();
|
|
6194
6043
|
var RIGHT_MARGIN_TAB_TWIPS = 9026 * 2;
|
|
6044
|
+
var STATISTIC_NUMBER_STYLE_ID = "StatisticNumber";
|
|
6045
|
+
var STATISTIC_DESCRIPTION_STYLE_ID = "StatisticDescription";
|
|
6046
|
+
var STATISTIC_SIZE_POINTS = {
|
|
6047
|
+
small: 20,
|
|
6048
|
+
medium: 28,
|
|
6049
|
+
large: 40
|
|
6050
|
+
};
|
|
6195
6051
|
function isValidStyleName(name) {
|
|
6196
6052
|
return [
|
|
6197
6053
|
"normal",
|
|
@@ -6830,6 +6686,67 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
|
|
|
6830
6686
|
}
|
|
6831
6687
|
};
|
|
6832
6688
|
}
|
|
6689
|
+
function createStatisticStyles(theme) {
|
|
6690
|
+
const definitions = [
|
|
6691
|
+
{
|
|
6692
|
+
id: STATISTIC_NUMBER_STYLE_ID,
|
|
6693
|
+
name: "Statistic Number",
|
|
6694
|
+
font: "heading",
|
|
6695
|
+
sizePoints: STATISTIC_SIZE_POINTS.medium,
|
|
6696
|
+
color: theme.colors.primary,
|
|
6697
|
+
bold: true,
|
|
6698
|
+
// Space above separates the figure from whatever preceded it; none below,
|
|
6699
|
+
// because the description is the other half of the same block.
|
|
6700
|
+
spacing: { before: 12, after: 0 },
|
|
6701
|
+
next: STATISTIC_DESCRIPTION_STYLE_ID,
|
|
6702
|
+
// The figure and its caption are one unit; a page break between them
|
|
6703
|
+
// reads as a number with no label.
|
|
6704
|
+
keepNext: true
|
|
6705
|
+
},
|
|
6706
|
+
{
|
|
6707
|
+
id: STATISTIC_DESCRIPTION_STYLE_ID,
|
|
6708
|
+
name: "Statistic Description",
|
|
6709
|
+
font: "body",
|
|
6710
|
+
sizePoints: 10,
|
|
6711
|
+
color: theme.colors.textMuted,
|
|
6712
|
+
bold: false,
|
|
6713
|
+
spacing: { before: 0, after: 12 },
|
|
6714
|
+
next: "Normal",
|
|
6715
|
+
keepNext: false
|
|
6716
|
+
}
|
|
6717
|
+
];
|
|
6718
|
+
return definitions.filter(
|
|
6719
|
+
(definition) => !(theme.styles && Object.prototype.hasOwnProperty.call(theme.styles, definition.id))
|
|
6720
|
+
).map((definition) => {
|
|
6721
|
+
const fontProps = resolveFontProperties(theme, definition.font);
|
|
6722
|
+
return {
|
|
6723
|
+
id: definition.id,
|
|
6724
|
+
name: definition.name,
|
|
6725
|
+
basedOn: "Normal",
|
|
6726
|
+
next: definition.next,
|
|
6727
|
+
quickFormat: true,
|
|
6728
|
+
run: {
|
|
6729
|
+
fontFamily: fontProps.family || "Arial",
|
|
6730
|
+
// Pinned, not inherited: the whole point of the style is that the
|
|
6731
|
+
// figure is not body text, so a theme's body size must not decide it.
|
|
6732
|
+
sizeHalfPoints: definition.sizePoints * 2,
|
|
6733
|
+
color: { hex: resolveColor(definition.color, theme) },
|
|
6734
|
+
bold: definition.bold
|
|
6735
|
+
},
|
|
6736
|
+
paragraph: {
|
|
6737
|
+
spacing: {
|
|
6738
|
+
...resolveSpacing(definition.spacing),
|
|
6739
|
+
...irLineSpacing(fontProps.lineSpacing)
|
|
6740
|
+
},
|
|
6741
|
+
// Centred, matching the compiler's own alignment default — a KPI
|
|
6742
|
+
// reads as a block, and an author who wants otherwise says so on the
|
|
6743
|
+
// component, which overrides this on the paragraph.
|
|
6744
|
+
alignment: convertAlignment("center"),
|
|
6745
|
+
keepNext: definition.keepNext
|
|
6746
|
+
}
|
|
6747
|
+
};
|
|
6748
|
+
});
|
|
6749
|
+
}
|
|
6833
6750
|
|
|
6834
6751
|
// src/ir/compiler.ts
|
|
6835
6752
|
init_styleHelpers();
|
|
@@ -8140,6 +8057,7 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
8140
8057
|
resourcesByHash: /* @__PURE__ */ new Map(),
|
|
8141
8058
|
nextBookmarkId: CONTENT_BOOKMARK_ID_BASE + 1,
|
|
8142
8059
|
bookmarkNames: /* @__PURE__ */ new Set(),
|
|
8060
|
+
usesStatistic: false,
|
|
8143
8061
|
styleIds: /* @__PURE__ */ new Set([
|
|
8144
8062
|
...styles.paragraph.map((s) => s.id),
|
|
8145
8063
|
...styles.character.map((s) => s.id)
|
|
@@ -8188,7 +8106,17 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
8188
8106
|
trackRevisions: structure.trackRevisions === true,
|
|
8189
8107
|
...noProofWords(structure.theme) ? { noProofWords: noProofWords(structure.theme) } : {}
|
|
8190
8108
|
},
|
|
8191
|
-
styles
|
|
8109
|
+
// The statistic styles are appended rather than built with the rest: a
|
|
8110
|
+
// document that uses no statistic must keep the exact style set it had
|
|
8111
|
+
// before the component had styles, or every recorded golden moves for a
|
|
8112
|
+
// component the document does not contain.
|
|
8113
|
+
styles: ctx.usesStatistic ? {
|
|
8114
|
+
...styles,
|
|
8115
|
+
paragraph: [
|
|
8116
|
+
...styles.paragraph,
|
|
8117
|
+
...createStatisticStyles(structure.theme)
|
|
8118
|
+
]
|
|
8119
|
+
} : styles,
|
|
8192
8120
|
numbering: ctx.numbering,
|
|
8193
8121
|
resources: ctx.resources,
|
|
8194
8122
|
sections,
|
|
@@ -8203,6 +8131,21 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
8203
8131
|
unsupported: ctx.unsupported
|
|
8204
8132
|
};
|
|
8205
8133
|
}
|
|
8134
|
+
var AFTER_TABLE_TWIPS = 120;
|
|
8135
|
+
var BODY_STYLE_IDS = /* @__PURE__ */ new Set([void 0, "Normal"]);
|
|
8136
|
+
function separateFromTables(blocks) {
|
|
8137
|
+
for (let i = 1; i < blocks.length; i += 1) {
|
|
8138
|
+
const block2 = blocks[i];
|
|
8139
|
+
if (blocks[i - 1].kind !== "table") continue;
|
|
8140
|
+
if (block2.kind !== "paragraph") continue;
|
|
8141
|
+
if (!BODY_STYLE_IDS.has(block2.styleId)) continue;
|
|
8142
|
+
if (block2.formatting?.spacing?.beforeTwips !== void 0) continue;
|
|
8143
|
+
block2.formatting = {
|
|
8144
|
+
...block2.formatting,
|
|
8145
|
+
spacing: { ...block2.formatting?.spacing, beforeTwips: AFTER_TABLE_TWIPS }
|
|
8146
|
+
};
|
|
8147
|
+
}
|
|
8148
|
+
}
|
|
8206
8149
|
function collectOutline(layout, warnings) {
|
|
8207
8150
|
try {
|
|
8208
8151
|
return collectDocumentOutline(layout.sections);
|
|
@@ -8279,6 +8222,7 @@ function compileSection(section2, index, ordinal, chrome, ctx) {
|
|
|
8279
8222
|
})
|
|
8280
8223
|
);
|
|
8281
8224
|
});
|
|
8225
|
+
separateFromTables(children);
|
|
8282
8226
|
const compiled = {
|
|
8283
8227
|
id: `s${index}`,
|
|
8284
8228
|
path: path3,
|
|
@@ -9049,35 +8993,83 @@ function compileToc(component, scope) {
|
|
|
9049
8993
|
});
|
|
9050
8994
|
return blocks;
|
|
9051
8995
|
}
|
|
8996
|
+
var TREND_GLYPHS = {
|
|
8997
|
+
up: "\u25B2",
|
|
8998
|
+
down: "\u25BC",
|
|
8999
|
+
neutral: "\u2013"
|
|
9000
|
+
};
|
|
9052
9001
|
function compileStatistic(component, scope) {
|
|
9053
|
-
const { path: path3 } = scope;
|
|
9002
|
+
const { ctx, path: path3 } = scope;
|
|
9054
9003
|
const props = component.props ?? {};
|
|
9055
9004
|
const alignment2 = compileAlignment(props.alignment) ?? "center";
|
|
9005
|
+
ctx.usesStatistic = true;
|
|
9056
9006
|
const spacing = props.spacing ? {
|
|
9057
9007
|
...props.spacing.before !== void 0 ? { beforeTwips: props.spacing.before } : {},
|
|
9058
9008
|
...props.spacing.after !== void 0 ? { afterTwips: props.spacing.after } : {}
|
|
9059
9009
|
} : void 0;
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9010
|
+
if (props.format !== void 0) {
|
|
9011
|
+
warnOnce(
|
|
9012
|
+
ctx,
|
|
9013
|
+
"statistic",
|
|
9014
|
+
'statistic "format" is not implemented and was ignored \u2014 format the value yourself and pass the result as "number".',
|
|
9015
|
+
"W_STATISTIC_FORMAT_IGNORED"
|
|
9016
|
+
);
|
|
9017
|
+
}
|
|
9018
|
+
const text = (value) => normalizeUnicodeText(String(value ?? ""));
|
|
9019
|
+
const numberPoints = STATISTIC_SIZE_POINTS[String(props.size)] ?? STATISTIC_SIZE_POINTS.medium;
|
|
9020
|
+
const resized = numberPoints !== STATISTIC_SIZE_POINTS.medium;
|
|
9021
|
+
const suffixHalfPoints = Math.max(12, Math.round(numberPoints));
|
|
9022
|
+
const numberRuns = [];
|
|
9023
|
+
const numberText = text(props.number);
|
|
9024
|
+
if (numberText) {
|
|
9025
|
+
numberRuns.push({
|
|
9026
|
+
kind: "text",
|
|
9027
|
+
text: numberText,
|
|
9028
|
+
...resized ? { formatting: { sizeHalfPoints: numberPoints * 2 } } : {}
|
|
9029
|
+
});
|
|
9030
|
+
}
|
|
9031
|
+
const unitText = text(props.unit);
|
|
9032
|
+
if (unitText) {
|
|
9033
|
+
numberRuns.push({
|
|
9034
|
+
kind: "text",
|
|
9035
|
+
text: unitText,
|
|
9036
|
+
formatting: { sizeHalfPoints: suffixHalfPoints }
|
|
9037
|
+
});
|
|
9038
|
+
}
|
|
9039
|
+
const glyph = typeof props.trend === "string" ? TREND_GLYPHS[props.trend] : void 0;
|
|
9040
|
+
const trendValue = text(props.trendValue);
|
|
9041
|
+
if (glyph || trendValue) {
|
|
9042
|
+
numberRuns.push({
|
|
9043
|
+
kind: "text",
|
|
9044
|
+
text: `${numberRuns.length > 0 ? " " : ""}${[glyph, trendValue].filter(Boolean).join(" ")}`,
|
|
9045
|
+
formatting: {
|
|
9046
|
+
sizeHalfPoints: suffixHalfPoints,
|
|
9047
|
+
color: irColor(resolveColor(ctx.theme.colors.textMuted, ctx.theme))
|
|
9048
|
+
}
|
|
9049
|
+
});
|
|
9050
|
+
}
|
|
9051
|
+
const line = (children, styleId, suffix, formatting) => ({
|
|
9052
|
+
kind: "paragraph",
|
|
9053
|
+
id: `${scope.id}:${suffix}`,
|
|
9054
|
+
path: `${path3}.${suffix}`,
|
|
9055
|
+
styleId,
|
|
9056
|
+
formatting,
|
|
9057
|
+
// Nothing to say is not the same as saying nothing: an empty statistic
|
|
9058
|
+
// line is a styled blank paragraph, with no run inside it at all.
|
|
9059
|
+
children
|
|
9060
|
+
});
|
|
9061
|
+
const descriptionText = text(props.description);
|
|
9073
9062
|
return [
|
|
9074
|
-
line(
|
|
9063
|
+
line(numberRuns, STATISTIC_NUMBER_STYLE_ID, "number", {
|
|
9075
9064
|
alignment: alignment2,
|
|
9076
9065
|
...spacing ? { spacing } : {}
|
|
9077
9066
|
}),
|
|
9078
|
-
line(
|
|
9079
|
-
|
|
9080
|
-
|
|
9067
|
+
line(
|
|
9068
|
+
descriptionText ? [{ kind: "text", text: descriptionText }] : [],
|
|
9069
|
+
STATISTIC_DESCRIPTION_STYLE_ID,
|
|
9070
|
+
"description",
|
|
9071
|
+
{ alignment: alignment2 }
|
|
9072
|
+
)
|
|
9081
9073
|
];
|
|
9082
9074
|
}
|
|
9083
9075
|
function compileList(component, scope, referencePrefix = "list", explicitLevels) {
|
|
@@ -9150,12 +9142,12 @@ function compileList(component, scope, referencePrefix = "list", explicitLevels)
|
|
|
9150
9142
|
}
|
|
9151
9143
|
function itemSpacing(spacing, index, count) {
|
|
9152
9144
|
const out = {};
|
|
9153
|
-
if (index === 0 && spacing?.before) {
|
|
9145
|
+
if (index === 0 && spacing?.before !== void 0) {
|
|
9154
9146
|
out.beforeTwips = pointsToTwips2(spacing.before);
|
|
9155
9147
|
}
|
|
9156
|
-
if (index === count - 1 && spacing?.after) {
|
|
9148
|
+
if (index === count - 1 && spacing?.after !== void 0) {
|
|
9157
9149
|
out.afterTwips = pointsToTwips2(spacing.after);
|
|
9158
|
-
} else if (spacing?.item) {
|
|
9150
|
+
} else if (spacing?.item !== void 0) {
|
|
9159
9151
|
out.afterTwips = pointsToTwips2(spacing.item);
|
|
9160
9152
|
}
|
|
9161
9153
|
return out;
|
|
@@ -10626,7 +10618,9 @@ function warnOnce(ctx, component, message, code) {
|
|
|
10626
10618
|
}
|
|
10627
10619
|
|
|
10628
10620
|
// src/renderers/registry.ts
|
|
10629
|
-
import {
|
|
10621
|
+
import {
|
|
10622
|
+
RendererRegistry
|
|
10623
|
+
} from "@json-to-office/shared/rendering";
|
|
10630
10624
|
|
|
10631
10625
|
// src/renderers/types.ts
|
|
10632
10626
|
import {
|
|
@@ -11122,8 +11116,7 @@ function resolveComponentTree(components, theme) {
|
|
|
11122
11116
|
}
|
|
11123
11117
|
|
|
11124
11118
|
// src/core/structure.ts
|
|
11125
|
-
|
|
11126
|
-
const metadata = createDocumentMetadata(document.props, generationDate);
|
|
11119
|
+
function resolveDocumentTree(document, theme) {
|
|
11127
11120
|
const docDefaults = document.props.componentDefaults;
|
|
11128
11121
|
const mergedComponentDefaults = docDefaults ? mergeWithDefaults2(docDefaults, theme.componentDefaults || {}) : void 0;
|
|
11129
11122
|
const docNoProofWords = document.props.noProofWords;
|
|
@@ -11137,6 +11130,14 @@ async function processDocument(document, theme, themeName, generationDate) {
|
|
|
11137
11130
|
},
|
|
11138
11131
|
...mergedNoProofWords && { noProofWords: mergedNoProofWords }
|
|
11139
11132
|
} : theme;
|
|
11133
|
+
return {
|
|
11134
|
+
theme: effectiveTheme,
|
|
11135
|
+
children: resolveComponentTree(document.children || [], effectiveTheme)
|
|
11136
|
+
};
|
|
11137
|
+
}
|
|
11138
|
+
async function processResolvedDocument(document, resolved, themeName, generationDate) {
|
|
11139
|
+
const metadata = createDocumentMetadata(document.props, generationDate);
|
|
11140
|
+
const effectiveTheme = resolved.theme;
|
|
11140
11141
|
const context = createRenderContext(
|
|
11141
11142
|
{
|
|
11142
11143
|
metadata,
|
|
@@ -11147,11 +11148,7 @@ async function processDocument(document, theme, themeName, generationDate) {
|
|
|
11147
11148
|
effectiveTheme,
|
|
11148
11149
|
themeName
|
|
11149
11150
|
);
|
|
11150
|
-
const
|
|
11151
|
-
document.children || [],
|
|
11152
|
-
effectiveTheme
|
|
11153
|
-
);
|
|
11154
|
-
const sections = await extractSections(resolvedChildren, context);
|
|
11151
|
+
const sections = await extractSections(resolved.children, context);
|
|
11155
11152
|
return {
|
|
11156
11153
|
metadata,
|
|
11157
11154
|
sections,
|
|
@@ -11251,6 +11248,326 @@ function createRenderContext(document, theme, themeName) {
|
|
|
11251
11248
|
};
|
|
11252
11249
|
}
|
|
11253
11250
|
|
|
11251
|
+
// src/quality/facts.ts
|
|
11252
|
+
import { DEFAULT_DOCX_RENDERER_ID as DEFAULT_DOCX_RENDERER_ID2 } from "@json-to-office/shared-docx";
|
|
11253
|
+
|
|
11254
|
+
// src/json/normalizer.ts
|
|
11255
|
+
function normalizeComponent(component) {
|
|
11256
|
+
if (component.name === "columns") {
|
|
11257
|
+
return normalizeColumnsComponent(component);
|
|
11258
|
+
}
|
|
11259
|
+
if ("children" in component && component.children) {
|
|
11260
|
+
return {
|
|
11261
|
+
...component,
|
|
11262
|
+
// Preserve ALL properties from validated component
|
|
11263
|
+
children: component.children.map(normalizeComponent)
|
|
11264
|
+
};
|
|
11265
|
+
}
|
|
11266
|
+
if (component.name === "section") {
|
|
11267
|
+
return normalizeSectionComponent(component);
|
|
11268
|
+
}
|
|
11269
|
+
return component;
|
|
11270
|
+
}
|
|
11271
|
+
function normalizeColumnsComponent(component) {
|
|
11272
|
+
const cfg = component.props || {};
|
|
11273
|
+
const applyTopLevelGap = (cols, topGap) => cols.map((c, i) => {
|
|
11274
|
+
const isLast = i === cols.length - 1;
|
|
11275
|
+
if (!isLast && c.gap === void 0 && topGap !== void 0) {
|
|
11276
|
+
return { ...c, gap: topGap };
|
|
11277
|
+
}
|
|
11278
|
+
return c;
|
|
11279
|
+
});
|
|
11280
|
+
const normalizeAutoWidth = (cols) => cols.map((c) => ({
|
|
11281
|
+
...c,
|
|
11282
|
+
width: c.width === "auto" ? void 0 : c.width
|
|
11283
|
+
}));
|
|
11284
|
+
let columnsArray;
|
|
11285
|
+
if (typeof cfg.columns === "number" && cfg.columns > 0) {
|
|
11286
|
+
const n = cfg.columns;
|
|
11287
|
+
const base = Array.from(
|
|
11288
|
+
{ length: n },
|
|
11289
|
+
() => ({})
|
|
11290
|
+
);
|
|
11291
|
+
const topLevelGap = cfg.gap !== void 0 ? cfg.gap : "5%";
|
|
11292
|
+
columnsArray = applyTopLevelGap(base, topLevelGap);
|
|
11293
|
+
} else if (Array.isArray(cfg.columns)) {
|
|
11294
|
+
columnsArray = cfg.columns;
|
|
11295
|
+
const topLevelGap = cfg.gap !== void 0 ? cfg.gap : "5%";
|
|
11296
|
+
columnsArray = applyTopLevelGap(columnsArray, topLevelGap);
|
|
11297
|
+
columnsArray = normalizeAutoWidth(columnsArray);
|
|
11298
|
+
} else {
|
|
11299
|
+
columnsArray = [{}];
|
|
11300
|
+
}
|
|
11301
|
+
const normalizedProps = {
|
|
11302
|
+
columns: columnsArray
|
|
11303
|
+
};
|
|
11304
|
+
return {
|
|
11305
|
+
...component,
|
|
11306
|
+
// Preserve any additional properties
|
|
11307
|
+
name: "columns",
|
|
11308
|
+
props: normalizedProps,
|
|
11309
|
+
children: component.children ? component.children.map(normalizeComponent) : void 0
|
|
11310
|
+
};
|
|
11311
|
+
}
|
|
11312
|
+
function normalizeSectionComponent(component) {
|
|
11313
|
+
const props = component.props || {};
|
|
11314
|
+
return {
|
|
11315
|
+
...component,
|
|
11316
|
+
// Preserve ALL properties
|
|
11317
|
+
props: {
|
|
11318
|
+
...props,
|
|
11319
|
+
// Preserve ALL props properties
|
|
11320
|
+
header: props.header ? props.header === "linkToPrevious" ? "linkToPrevious" : props.header.map((m) => normalizeComponent(m)) : void 0,
|
|
11321
|
+
footer: props.footer ? props.footer === "linkToPrevious" ? "linkToPrevious" : props.footer.map((m) => normalizeComponent(m)) : void 0
|
|
11322
|
+
},
|
|
11323
|
+
children: component.children ? component.children.map(normalizeComponent) : void 0
|
|
11324
|
+
};
|
|
11325
|
+
}
|
|
11326
|
+
function normalizeDocument(document) {
|
|
11327
|
+
if (document.name !== "docx") {
|
|
11328
|
+
throw new Error(
|
|
11329
|
+
'Top-level document must be a docx component with name="docx"'
|
|
11330
|
+
);
|
|
11331
|
+
}
|
|
11332
|
+
const normalized = normalizeComponent(document);
|
|
11333
|
+
return [normalized];
|
|
11334
|
+
}
|
|
11335
|
+
|
|
11336
|
+
// src/quality/facts.ts
|
|
11337
|
+
init_widthUtils();
|
|
11338
|
+
function asRecord(value) {
|
|
11339
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
11340
|
+
}
|
|
11341
|
+
function pageBox(theme, themeName, pageOverride) {
|
|
11342
|
+
const page = createSectionProperties(
|
|
11343
|
+
getColumnSettings("single"),
|
|
11344
|
+
theme,
|
|
11345
|
+
themeName,
|
|
11346
|
+
"nextPage",
|
|
11347
|
+
pageOverride
|
|
11348
|
+
).page;
|
|
11349
|
+
return {
|
|
11350
|
+
availableWidthTwips: Math.max(
|
|
11351
|
+
0,
|
|
11352
|
+
page.size.width - page.margin.left - page.margin.right
|
|
11353
|
+
),
|
|
11354
|
+
pageBottomTwips: page.size.height
|
|
11355
|
+
};
|
|
11356
|
+
}
|
|
11357
|
+
function tableFact(props, path3, availableWidthTwips) {
|
|
11358
|
+
const columns = Array.isArray(props.columns) ? props.columns : void 0;
|
|
11359
|
+
if (!columns) return void 0;
|
|
11360
|
+
let totalWidthTwips = 0;
|
|
11361
|
+
let hasExplicitWidth = false;
|
|
11362
|
+
let pointSum = 0;
|
|
11363
|
+
let percentSum = 0;
|
|
11364
|
+
const explicitWidths = [];
|
|
11365
|
+
columns.forEach((column, index) => {
|
|
11366
|
+
const width = asRecord(column)?.width;
|
|
11367
|
+
if (typeof width === "number" && Number.isFinite(width)) {
|
|
11368
|
+
hasExplicitWidth = true;
|
|
11369
|
+
explicitWidths.push({ index, width });
|
|
11370
|
+
totalWidthTwips += relativeLengthToTwips(width, availableWidthTwips);
|
|
11371
|
+
pointSum += width;
|
|
11372
|
+
} else if (typeof width === "string") {
|
|
11373
|
+
hasExplicitWidth = true;
|
|
11374
|
+
const percent = width.trim().endsWith("%") ? Number(width.trim().slice(0, -1)) : Number.NaN;
|
|
11375
|
+
if (Number.isFinite(percent)) {
|
|
11376
|
+
explicitWidths.push({ index, width });
|
|
11377
|
+
percentSum += percent;
|
|
11378
|
+
totalWidthTwips += Math.max(
|
|
11379
|
+
0,
|
|
11380
|
+
Math.round(availableWidthTwips * percent / 100)
|
|
11381
|
+
);
|
|
11382
|
+
}
|
|
11383
|
+
}
|
|
11384
|
+
});
|
|
11385
|
+
return {
|
|
11386
|
+
id: `docx:table-width:${path3}`,
|
|
11387
|
+
kind: "docx/table-width",
|
|
11388
|
+
path: `${path3}/props/columns`,
|
|
11389
|
+
totalWidthTwips,
|
|
11390
|
+
availableWidthTwips,
|
|
11391
|
+
hasExplicitWidth,
|
|
11392
|
+
allColumnsExplicit: explicitWidths.length === columns.length,
|
|
11393
|
+
pointSum,
|
|
11394
|
+
percentSum,
|
|
11395
|
+
explicitWidths
|
|
11396
|
+
};
|
|
11397
|
+
}
|
|
11398
|
+
var TWIPS_PER_POINT3 = 20;
|
|
11399
|
+
var SINGLE_LINE_RATIO = 1.2;
|
|
11400
|
+
function finiteNumber(value) {
|
|
11401
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
11402
|
+
}
|
|
11403
|
+
function lineHeightPt(fontSizePt, spacing) {
|
|
11404
|
+
const rule = asRecord(spacing);
|
|
11405
|
+
const value = finiteNumber(rule?.value);
|
|
11406
|
+
switch (rule?.type) {
|
|
11407
|
+
// `exactly` is an absolute line box, and display type routinely sets it
|
|
11408
|
+
// below the font size — reading it as a multiplier would inflate every
|
|
11409
|
+
// estimate on exactly the headings that matter most.
|
|
11410
|
+
case "exactly":
|
|
11411
|
+
return value ?? fontSizePt * SINGLE_LINE_RATIO;
|
|
11412
|
+
case "atLeast":
|
|
11413
|
+
return Math.max(value ?? 0, fontSizePt * SINGLE_LINE_RATIO);
|
|
11414
|
+
case "multiple":
|
|
11415
|
+
return fontSizePt * SINGLE_LINE_RATIO * (value ?? 1);
|
|
11416
|
+
default:
|
|
11417
|
+
return fontSizePt * SINGLE_LINE_RATIO;
|
|
11418
|
+
}
|
|
11419
|
+
}
|
|
11420
|
+
function characterSpacingPt(spacing) {
|
|
11421
|
+
const rule = asRecord(spacing);
|
|
11422
|
+
const value = finiteNumber(rule?.value);
|
|
11423
|
+
if (rule === void 0 || value === void 0) return 0;
|
|
11424
|
+
return rule.type === "condensed" ? -value / TWIPS_PER_POINT3 : value / TWIPS_PER_POINT3;
|
|
11425
|
+
}
|
|
11426
|
+
function frameTextFact(props, path3, page) {
|
|
11427
|
+
const floating = asRecord(props.floating);
|
|
11428
|
+
const frameWidthTwips = finiteNumber(floating?.width);
|
|
11429
|
+
if (frameWidthTwips === void 0) return void 0;
|
|
11430
|
+
const text = typeof props.text === "string" ? props.text : "";
|
|
11431
|
+
if (text.trim() === "") return void 0;
|
|
11432
|
+
const font = asRecord(props.font);
|
|
11433
|
+
const fontSizePt = finiteNumber(font?.size);
|
|
11434
|
+
if (fontSizePt === void 0) return void 0;
|
|
11435
|
+
const longestWord = text.split(/\s+/).reduce(
|
|
11436
|
+
(longest, word) => word.length > longest.length ? word : longest,
|
|
11437
|
+
""
|
|
11438
|
+
);
|
|
11439
|
+
const offsetY = finiteNumber(asRecord(floating?.verticalPosition)?.offset);
|
|
11440
|
+
return {
|
|
11441
|
+
id: `docx:frame-text:${path3}`,
|
|
11442
|
+
kind: "docx/frame-text",
|
|
11443
|
+
path: path3,
|
|
11444
|
+
text,
|
|
11445
|
+
fontSizePt,
|
|
11446
|
+
lineHeightPt: lineHeightPt(fontSizePt, font?.lineSpacing),
|
|
11447
|
+
characterSpacingPt: characterSpacingPt(font?.characterSpacing),
|
|
11448
|
+
frameWidthTwips,
|
|
11449
|
+
...finiteNumber(floating?.height) !== void 0 && {
|
|
11450
|
+
frameHeightTwips: finiteNumber(floating?.height)
|
|
11451
|
+
},
|
|
11452
|
+
...offsetY !== void 0 && { offsetYTwips: offsetY },
|
|
11453
|
+
pageBottomTwips: page.pageBottomTwips,
|
|
11454
|
+
longestWord
|
|
11455
|
+
};
|
|
11456
|
+
}
|
|
11457
|
+
var SVG_VIEWBOX = /viewBox\s*=\s*"\s*(-?[\d.]+)[\s,]+(-?[\d.]+)[\s,]+(-?[\d.]+)[\s,]+(-?[\d.]+)\s*"/;
|
|
11458
|
+
var SVG_TEXT = /<text\b([^>]*)>([^<]*)<\/text>/g;
|
|
11459
|
+
var SVG_ATTR = (name) => new RegExp(`\\b${name}\\s*=\\s*"(-?[\\d.]+)"`);
|
|
11460
|
+
function svgTextFacts(props, path3) {
|
|
11461
|
+
const svg = typeof props.svg === "string" ? props.svg : void 0;
|
|
11462
|
+
if (!svg) return [];
|
|
11463
|
+
const box = SVG_VIEWBOX.exec(svg);
|
|
11464
|
+
if (!box) return [];
|
|
11465
|
+
const viewBoxMinY = Number(box[2]);
|
|
11466
|
+
const viewBoxHeight = Number(box[4]);
|
|
11467
|
+
if (!Number.isFinite(viewBoxMinY) || !Number.isFinite(viewBoxHeight)) {
|
|
11468
|
+
return [];
|
|
11469
|
+
}
|
|
11470
|
+
const facts = [];
|
|
11471
|
+
let match;
|
|
11472
|
+
SVG_TEXT.lastIndex = 0;
|
|
11473
|
+
let index = 0;
|
|
11474
|
+
while ((match = SVG_TEXT.exec(svg)) !== null) {
|
|
11475
|
+
const [, attributes, content] = match;
|
|
11476
|
+
const baselineY = Number(SVG_ATTR("y").exec(attributes)?.[1]);
|
|
11477
|
+
if (!Number.isFinite(baselineY)) {
|
|
11478
|
+
index += 1;
|
|
11479
|
+
continue;
|
|
11480
|
+
}
|
|
11481
|
+
const fontSizeUnits = Number(
|
|
11482
|
+
SVG_ATTR("font-size").exec(attributes)?.[1] ?? 0
|
|
11483
|
+
);
|
|
11484
|
+
facts.push({
|
|
11485
|
+
id: `docx:svg-text:${path3}:${index}`,
|
|
11486
|
+
kind: "docx/svg-text",
|
|
11487
|
+
path: `${path3}/props/svg`,
|
|
11488
|
+
content: content.trim(),
|
|
11489
|
+
baselineY,
|
|
11490
|
+
fontSizeUnits: Number.isFinite(fontSizeUnits) ? fontSizeUnits : 0,
|
|
11491
|
+
viewBoxMinY,
|
|
11492
|
+
viewBoxHeight
|
|
11493
|
+
});
|
|
11494
|
+
index += 1;
|
|
11495
|
+
}
|
|
11496
|
+
return facts;
|
|
11497
|
+
}
|
|
11498
|
+
function walkActive(node, path3, page, visit) {
|
|
11499
|
+
const rec = asRecord(node);
|
|
11500
|
+
if (!rec || rec.enabled === false) return;
|
|
11501
|
+
visit(rec, path3, page);
|
|
11502
|
+
const children = Array.isArray(rec.children) ? rec.children : [];
|
|
11503
|
+
children.forEach(
|
|
11504
|
+
(child, index) => walkActive(child, `${path3}/children/${index}`, page, visit)
|
|
11505
|
+
);
|
|
11506
|
+
}
|
|
11507
|
+
function prepareDocxQualityDocument(document, options = {}) {
|
|
11508
|
+
const context = options.context ?? resolveThemeContext(normalizeDocument(document)[0], {
|
|
11509
|
+
customThemes: options.customThemes,
|
|
11510
|
+
fonts: options.fonts,
|
|
11511
|
+
warnings: options.warnings
|
|
11512
|
+
});
|
|
11513
|
+
const resolved = resolveDocumentTree(context.document, context.theme);
|
|
11514
|
+
const basePage = pageBox(resolved.theme, context.themeName);
|
|
11515
|
+
const facts = [];
|
|
11516
|
+
const provenance = {};
|
|
11517
|
+
let previousHeadingLevel;
|
|
11518
|
+
const addFact = (fact) => {
|
|
11519
|
+
facts.push(fact);
|
|
11520
|
+
provenance[fact.id] = {
|
|
11521
|
+
path: fact.path,
|
|
11522
|
+
...fact.relatedPaths && { relatedPaths: fact.relatedPaths }
|
|
11523
|
+
};
|
|
11524
|
+
};
|
|
11525
|
+
const visit = (node, path3, page) => {
|
|
11526
|
+
const props = asRecord(node.props) ?? {};
|
|
11527
|
+
if (node.name === "table") {
|
|
11528
|
+
const fact = tableFact(props, path3, page.availableWidthTwips);
|
|
11529
|
+
if (fact) addFact(fact);
|
|
11530
|
+
}
|
|
11531
|
+
if (node.name === "paragraph" || node.name === "text-box") {
|
|
11532
|
+
const fact = frameTextFact(props, path3, page);
|
|
11533
|
+
if (fact) addFact(fact);
|
|
11534
|
+
}
|
|
11535
|
+
if (node.name === "image" || node.name === "visual") {
|
|
11536
|
+
for (const fact of svgTextFacts(props, path3)) addFact(fact);
|
|
11537
|
+
}
|
|
11538
|
+
if (node.name === "heading") {
|
|
11539
|
+
const level = typeof props.level === "number" && Number.isFinite(props.level) ? props.level : 1;
|
|
11540
|
+
addFact({
|
|
11541
|
+
id: `docx:heading:${path3}`,
|
|
11542
|
+
kind: "docx/heading",
|
|
11543
|
+
path: `${path3}/props/level`,
|
|
11544
|
+
level,
|
|
11545
|
+
...previousHeadingLevel !== void 0 && {
|
|
11546
|
+
previousLevel: previousHeadingLevel
|
|
11547
|
+
}
|
|
11548
|
+
});
|
|
11549
|
+
previousHeadingLevel = level;
|
|
11550
|
+
}
|
|
11551
|
+
};
|
|
11552
|
+
resolved.children.forEach((component, index) => {
|
|
11553
|
+
const rec = component;
|
|
11554
|
+
const page = rec.name === "section" ? pageBox(resolved.theme, context.themeName, rec.props?.page) : basePage;
|
|
11555
|
+
walkActive(component, `/children/${index}`, page, visit);
|
|
11556
|
+
});
|
|
11557
|
+
return {
|
|
11558
|
+
format: "docx",
|
|
11559
|
+
model: {
|
|
11560
|
+
authored: document,
|
|
11561
|
+
context,
|
|
11562
|
+
document: resolved,
|
|
11563
|
+
themeName: context.themeName
|
|
11564
|
+
},
|
|
11565
|
+
facts,
|
|
11566
|
+
provenance,
|
|
11567
|
+
renderer: options.renderer ?? DEFAULT_DOCX_RENDERER_ID2
|
|
11568
|
+
};
|
|
11569
|
+
}
|
|
11570
|
+
|
|
11254
11571
|
// src/core/generateFromIr.ts
|
|
11255
11572
|
var UncompiledComponentError = class extends Error {
|
|
11256
11573
|
code = "UNCOMPILED_COMPONENT";
|
|
@@ -11278,11 +11595,14 @@ async function compileDocumentToIr(document, options = {}, collector) {
|
|
|
11278
11595
|
);
|
|
11279
11596
|
}
|
|
11280
11597
|
async function compileDocumentScoped(document, options, warnings) {
|
|
11281
|
-
const
|
|
11598
|
+
const prepared = options.prepared ?? prepareDocxQualityDocument(document, {
|
|
11282
11599
|
customThemes: options.customThemes,
|
|
11283
11600
|
fonts: options.fonts,
|
|
11284
|
-
warnings
|
|
11601
|
+
warnings,
|
|
11602
|
+
context: options.context,
|
|
11603
|
+
renderer: options.renderer
|
|
11285
11604
|
});
|
|
11605
|
+
const { context } = prepared.model;
|
|
11286
11606
|
const hasVisual = collectVisualProps(context.document).length > 0;
|
|
11287
11607
|
const resolvedFonts = await resolveDocumentFonts(
|
|
11288
11608
|
context.document,
|
|
@@ -11298,9 +11618,10 @@ async function compileDocumentScoped(document, options, warnings) {
|
|
|
11298
11618
|
...options.baseDir !== void 0 ? { baseDir: options.baseDir } : {},
|
|
11299
11619
|
...visualFonts.length > 0 ? { visualFonts } : {}
|
|
11300
11620
|
});
|
|
11301
|
-
const
|
|
11621
|
+
const resolved = desugared === context.document ? prepared.model.document : resolveDocumentTree(desugared, context.theme);
|
|
11622
|
+
const structure = await processResolvedDocument(
|
|
11302
11623
|
desugared,
|
|
11303
|
-
|
|
11624
|
+
resolved,
|
|
11304
11625
|
context.themeName,
|
|
11305
11626
|
resolveGenerationDate(options)
|
|
11306
11627
|
);
|