@json-to-office/core-docx 0.35.0 → 0.37.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/components/heading.d.ts.map +1 -1
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/text-box.d.ts +1 -1
- package/dist/components/text-box.d.ts.map +1 -1
- package/dist/components/toc/index.d.ts.map +1 -1
- package/dist/core/cached-render.d.ts +2 -2
- package/dist/core/cached-render.d.ts.map +1 -1
- package/dist/core/collectTocHeadings.d.ts +27 -1
- package/dist/core/collectTocHeadings.d.ts.map +1 -1
- package/dist/core/content.d.ts +10 -0
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/render.d.ts +8 -2
- package/dist/core/render.d.ts.map +1 -1
- package/dist/index.js +690 -181
- package/dist/index.js.map +1 -1
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.js +687 -181
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/templates/themes/apex.docx.theme.json +0 -3
- package/dist/templates/themes/corporate.docx.theme.json +0 -3
- package/dist/templates/themes/devportal.docx.theme.json +0 -3
- package/dist/templates/themes/index.d.ts +4 -0
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/templates/themes/minimal.docx.theme.json +0 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/bookmarkRegistry.d.ts +14 -0
- package/dist/utils/bookmarkRegistry.d.ts.map +1 -1
- package/dist/utils/generationContext.d.ts +9 -0
- package/dist/utils/generationContext.d.ts.map +1 -1
- package/dist/utils/imageUtils.d.ts +7 -3
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/listLevels.d.ts +38 -0
- package/dist/utils/listLevels.d.ts.map +1 -0
- package/dist/utils/numberFormatting.d.ts +11 -0
- package/dist/utils/numberFormatting.d.ts.map +1 -0
- package/dist/utils/numberedItemsRegistry.d.ts +38 -0
- package/dist/utils/numberedItemsRegistry.d.ts.map +1 -0
- package/dist/utils/numberingConfig.d.ts +31 -0
- package/dist/utils/numberingConfig.d.ts.map +1 -1
- package/dist/utils/placeholderProcessor.d.ts +2 -2
- package/dist/utils/placeholderProcessor.d.ts.map +1 -1
- package/dist/utils/textParser.d.ts +6 -0
- package/dist/utils/textParser.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -377,9 +377,6 @@ var init_minimal_docx_theme = __esm({
|
|
|
377
377
|
},
|
|
378
378
|
section: {
|
|
379
379
|
pageBreak: false
|
|
380
|
-
},
|
|
381
|
-
heading: {
|
|
382
|
-
numbering: false
|
|
383
380
|
}
|
|
384
381
|
}
|
|
385
382
|
};
|
|
@@ -502,9 +499,6 @@ var init_corporate_docx_theme = __esm({
|
|
|
502
499
|
},
|
|
503
500
|
section: {
|
|
504
501
|
pageBreak: false
|
|
505
|
-
},
|
|
506
|
-
heading: {
|
|
507
|
-
numbering: false
|
|
508
502
|
}
|
|
509
503
|
}
|
|
510
504
|
};
|
|
@@ -747,9 +741,6 @@ var init_apex_docx_theme = __esm({
|
|
|
747
741
|
},
|
|
748
742
|
section: {
|
|
749
743
|
pageBreak: false
|
|
750
|
-
},
|
|
751
|
-
heading: {
|
|
752
|
-
numbering: false
|
|
753
744
|
}
|
|
754
745
|
}
|
|
755
746
|
};
|
|
@@ -883,9 +874,6 @@ var init_devportal_docx_theme = __esm({
|
|
|
883
874
|
},
|
|
884
875
|
section: {
|
|
885
876
|
pageBreak: false
|
|
886
|
-
},
|
|
887
|
-
heading: {
|
|
888
|
-
numbering: false
|
|
889
877
|
}
|
|
890
878
|
}
|
|
891
879
|
};
|
|
@@ -2146,10 +2134,68 @@ function resolveFromBaseDir(filePath) {
|
|
|
2146
2134
|
if (!base || isAbsolute(filePath)) return filePath;
|
|
2147
2135
|
return resolve(base, filePath);
|
|
2148
2136
|
}
|
|
2137
|
+
var warningsStorage = new AsyncLocalStorage();
|
|
2138
|
+
function runWithWarnings(warnings, callback) {
|
|
2139
|
+
return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
|
|
2140
|
+
}
|
|
2141
|
+
function reportWarning(component, code, message, context) {
|
|
2142
|
+
const warnings = warningsStorage.getStore();
|
|
2143
|
+
if (warnings) {
|
|
2144
|
+
warnings.push({
|
|
2145
|
+
component,
|
|
2146
|
+
message,
|
|
2147
|
+
severity: "warning",
|
|
2148
|
+
context: { code, ...context }
|
|
2149
|
+
});
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
console.warn(`[json-to-docx] [${code}] ${message}`);
|
|
2153
|
+
}
|
|
2149
2154
|
|
|
2150
2155
|
// src/utils/imageUtils.ts
|
|
2151
2156
|
init_widthUtils();
|
|
2152
2157
|
import { ImageRun } from "docx";
|
|
2158
|
+
var SVG_RASTER_SCALE = 3;
|
|
2159
|
+
var SVG_MAX_EDGE_PX = 4096;
|
|
2160
|
+
var SVG_MIN_EDGE_PX = 16;
|
|
2161
|
+
var resvgModule;
|
|
2162
|
+
function loadResvg() {
|
|
2163
|
+
resvgModule ??= import("@resvg/resvg-js");
|
|
2164
|
+
return resvgModule;
|
|
2165
|
+
}
|
|
2166
|
+
function toRasterPx(px) {
|
|
2167
|
+
return Math.min(
|
|
2168
|
+
SVG_MAX_EDGE_PX,
|
|
2169
|
+
Math.max(SVG_MIN_EDGE_PX, Math.round(px * SVG_RASTER_SCALE))
|
|
2170
|
+
);
|
|
2171
|
+
}
|
|
2172
|
+
async function rasterizeSvgFallback(svg, transformation) {
|
|
2173
|
+
let Resvg;
|
|
2174
|
+
try {
|
|
2175
|
+
({ Resvg } = await loadResvg());
|
|
2176
|
+
} catch (error) {
|
|
2177
|
+
reportWarning(
|
|
2178
|
+
"image",
|
|
2179
|
+
"IMAGE_SVG_RASTER_FAILED",
|
|
2180
|
+
`Could not load the SVG rasterizer, so inline SVG keeps a fallback that only Word 2016+ can draw: ${String(error)}`
|
|
2181
|
+
);
|
|
2182
|
+
return void 0;
|
|
2183
|
+
}
|
|
2184
|
+
try {
|
|
2185
|
+
const markup = svg.toString("utf-8");
|
|
2186
|
+
const probeImage = new Resvg(markup);
|
|
2187
|
+
const wide = probeImage.width / probeImage.height > transformation.width / transformation.height;
|
|
2188
|
+
const fitTo = wide ? { mode: "height", value: toRasterPx(transformation.height) } : { mode: "width", value: toRasterPx(transformation.width) };
|
|
2189
|
+
return Buffer.from(new Resvg(markup, { fitTo }).render().asPng());
|
|
2190
|
+
} catch (error) {
|
|
2191
|
+
reportWarning(
|
|
2192
|
+
"image",
|
|
2193
|
+
"IMAGE_SVG_RASTER_FAILED",
|
|
2194
|
+
`Could not rasterize inline SVG, so its fallback only renders in Word 2016+: ${String(error)}`
|
|
2195
|
+
);
|
|
2196
|
+
return void 0;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2153
2199
|
function parseWidthValue(width, availableWidthPx) {
|
|
2154
2200
|
if (typeof width === "number") {
|
|
2155
2201
|
return width;
|
|
@@ -2259,17 +2305,18 @@ function detectImageType(imagePath, responseContentType) {
|
|
|
2259
2305
|
if (typeFromExtension) return typeFromExtension;
|
|
2260
2306
|
return "png";
|
|
2261
2307
|
}
|
|
2262
|
-
function createTypedImageRun(opts) {
|
|
2308
|
+
async function createTypedImageRun(opts) {
|
|
2263
2309
|
const base = {
|
|
2264
2310
|
data: opts.data,
|
|
2265
2311
|
transformation: opts.transformation,
|
|
2266
2312
|
...opts.floating && { floating: opts.floating }
|
|
2267
2313
|
};
|
|
2268
2314
|
if (opts.type === "svg") {
|
|
2315
|
+
const raster = await rasterizeSvgFallback(opts.data, opts.transformation);
|
|
2269
2316
|
return new ImageRun({
|
|
2270
2317
|
type: "svg",
|
|
2271
2318
|
...base,
|
|
2272
|
-
fallback: { type: "png", data: opts.data }
|
|
2319
|
+
fallback: { type: "png", data: raster ?? opts.data }
|
|
2273
2320
|
});
|
|
2274
2321
|
}
|
|
2275
2322
|
return new ImageRun({ type: opts.type, ...base });
|
|
@@ -2399,6 +2446,8 @@ import {
|
|
|
2399
2446
|
InternalHyperlink as InternalHyperlink2,
|
|
2400
2447
|
FootnoteReferenceRun as FootnoteReferenceRun2,
|
|
2401
2448
|
EndnoteReferenceRun as EndnoteReferenceRun2,
|
|
2449
|
+
NumberedItemReference,
|
|
2450
|
+
NumberedItemReferenceFormat,
|
|
2402
2451
|
Tab
|
|
2403
2452
|
} from "docx";
|
|
2404
2453
|
|
|
@@ -2599,6 +2648,45 @@ function initializeBuiltinPlaceholders() {
|
|
|
2599
2648
|
}
|
|
2600
2649
|
initializeBuiltinPlaceholders();
|
|
2601
2650
|
|
|
2651
|
+
// src/utils/numberedItemsRegistry.ts
|
|
2652
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
2653
|
+
var NumberedItemsRegistry = class {
|
|
2654
|
+
fallback = {
|
|
2655
|
+
items: /* @__PURE__ */ new Map(),
|
|
2656
|
+
seeded: false
|
|
2657
|
+
};
|
|
2658
|
+
scopes = new AsyncLocalStorage2();
|
|
2659
|
+
get state() {
|
|
2660
|
+
return this.scopes.getStore() ?? this.fallback;
|
|
2661
|
+
}
|
|
2662
|
+
/** Run work with an isolated registry that follows its async call chain. */
|
|
2663
|
+
runScoped(callback) {
|
|
2664
|
+
return this.scopes.run({ items: /* @__PURE__ */ new Map(), seeded: false }, callback);
|
|
2665
|
+
}
|
|
2666
|
+
/** Replace the contents with the pre-pass result. */
|
|
2667
|
+
seed(items) {
|
|
2668
|
+
const state = this.state;
|
|
2669
|
+
state.items = new Map(items);
|
|
2670
|
+
state.seeded = true;
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* False outside a render (a unit test calling `createText` directly). An
|
|
2674
|
+
* unresolved reference is then expected rather than an authoring mistake, so
|
|
2675
|
+
* the caller stays quiet about it.
|
|
2676
|
+
*/
|
|
2677
|
+
isSeeded() {
|
|
2678
|
+
return this.state.seeded;
|
|
2679
|
+
}
|
|
2680
|
+
get(id) {
|
|
2681
|
+
return this.state.items.get(id);
|
|
2682
|
+
}
|
|
2683
|
+
clear() {
|
|
2684
|
+
this.state.items.clear();
|
|
2685
|
+
this.state.seeded = false;
|
|
2686
|
+
}
|
|
2687
|
+
};
|
|
2688
|
+
var globalNumberedItemsRegistry = new NumberedItemsRegistry();
|
|
2689
|
+
|
|
2602
2690
|
// src/utils/textParser.ts
|
|
2603
2691
|
var FOOTNOTE_MARKER_REGEX = /\[\^([^\]\s]+)\]/;
|
|
2604
2692
|
function escapeRegExp(s) {
|
|
@@ -2815,13 +2903,59 @@ function splitNoteMarkers(text, noteRef, runs) {
|
|
|
2815
2903
|
if (trailing) out.push(...runs(trailing));
|
|
2816
2904
|
return out;
|
|
2817
2905
|
}
|
|
2906
|
+
var CROSS_REFERENCE_PATTERN = "\\[@([^\\]\\s:]+)(?::(relative|no_context|full_context|none))?\\]";
|
|
2907
|
+
var INLINE_TOKEN_REGEX = `\\[([^\\]]+)\\]\\(([^)]+)\\)|${CROSS_REFERENCE_PATTERN}`;
|
|
2908
|
+
function hasCrossReference(text) {
|
|
2909
|
+
return new RegExp(CROSS_REFERENCE_PATTERN).test(text);
|
|
2910
|
+
}
|
|
2911
|
+
var REFERENCE_FORMATS = {
|
|
2912
|
+
relative: NumberedItemReferenceFormat.RELATIVE,
|
|
2913
|
+
no_context: NumberedItemReferenceFormat.NO_CONTEXT,
|
|
2914
|
+
full_context: NumberedItemReferenceFormat.FULL_CONTEXT,
|
|
2915
|
+
none: NumberedItemReferenceFormat.NONE
|
|
2916
|
+
};
|
|
2917
|
+
function createCrossReference(id, format2, token, baseStyle, options) {
|
|
2918
|
+
const info = globalNumberedItemsRegistry.get(id);
|
|
2919
|
+
if (!info) {
|
|
2920
|
+
if (globalNumberedItemsRegistry.isSeeded()) {
|
|
2921
|
+
console.warn(
|
|
2922
|
+
`[core-docx] Cross-reference ${token} has no target: no heading or list item declares the id "${id}". Rendering the token as literal text.`
|
|
2923
|
+
);
|
|
2924
|
+
}
|
|
2925
|
+
return buildTextRuns(
|
|
2926
|
+
token,
|
|
2927
|
+
buildRunCommonProps(baseStyle, { boldColor: options.boldColor }),
|
|
2928
|
+
{ noProof: baseStyle.noProof, noProofWords: options.noProofWords }
|
|
2929
|
+
);
|
|
2930
|
+
}
|
|
2931
|
+
if (format2 === "none") {
|
|
2932
|
+
return [
|
|
2933
|
+
new NumberedItemReference(id, info.text, {
|
|
2934
|
+
hyperlink: true,
|
|
2935
|
+
referenceFormat: REFERENCE_FORMATS.none
|
|
2936
|
+
})
|
|
2937
|
+
];
|
|
2938
|
+
}
|
|
2939
|
+
const cachedValue = format2 === "no_context" ? info.own : info.full;
|
|
2940
|
+
if (cachedValue === void 0) {
|
|
2941
|
+
console.warn(
|
|
2942
|
+
`[core-docx] Cross-reference ${token} targets an unnumbered ${info.kind} ("${id}"), so the field carries no cached number and reads blank until the reader updates fields. Use [@${id}:none] to reference its text instead.`
|
|
2943
|
+
);
|
|
2944
|
+
}
|
|
2945
|
+
return [
|
|
2946
|
+
new NumberedItemReference(id, cachedValue, {
|
|
2947
|
+
hyperlink: true,
|
|
2948
|
+
referenceFormat: REFERENCE_FORMATS[format2]
|
|
2949
|
+
})
|
|
2950
|
+
];
|
|
2951
|
+
}
|
|
2818
2952
|
function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
2819
2953
|
const normalizedText = normalizeUnicodeText(text);
|
|
2820
2954
|
const runs = [];
|
|
2821
|
-
const
|
|
2955
|
+
const tokenRegex = new RegExp(INLINE_TOKEN_REGEX, "g");
|
|
2822
2956
|
let lastIndex = 0;
|
|
2823
2957
|
let match;
|
|
2824
|
-
while ((match =
|
|
2958
|
+
while ((match = tokenRegex.exec(normalizedText)) !== null) {
|
|
2825
2959
|
if (match.index > lastIndex) {
|
|
2826
2960
|
const plainText = normalizedText.substring(lastIndex, match.index);
|
|
2827
2961
|
if (plainText) {
|
|
@@ -2833,6 +2967,19 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
2833
2967
|
runs.push(...plainRuns);
|
|
2834
2968
|
}
|
|
2835
2969
|
}
|
|
2970
|
+
lastIndex = match.index + match[0].length;
|
|
2971
|
+
if (match[1] === void 0) {
|
|
2972
|
+
runs.push(
|
|
2973
|
+
...createCrossReference(
|
|
2974
|
+
match[3],
|
|
2975
|
+
match[4] ?? "relative",
|
|
2976
|
+
match[0],
|
|
2977
|
+
baseStyle,
|
|
2978
|
+
options
|
|
2979
|
+
)
|
|
2980
|
+
);
|
|
2981
|
+
continue;
|
|
2982
|
+
}
|
|
2836
2983
|
const linkText = match[1];
|
|
2837
2984
|
const linkUrl = match[2];
|
|
2838
2985
|
const isInternal = linkUrl.startsWith("#");
|
|
@@ -2859,7 +3006,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
2859
3006
|
})
|
|
2860
3007
|
);
|
|
2861
3008
|
}
|
|
2862
|
-
lastIndex = match.index + match[0].length;
|
|
2863
3009
|
}
|
|
2864
3010
|
if (lastIndex < normalizedText.length) {
|
|
2865
3011
|
const remainingText = normalizedText.substring(lastIndex);
|
|
@@ -3553,10 +3699,21 @@ function getStyleIdForLevel(level) {
|
|
|
3553
3699
|
}
|
|
3554
3700
|
|
|
3555
3701
|
// src/utils/bookmarkRegistry.ts
|
|
3556
|
-
import { AsyncLocalStorage as
|
|
3702
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
3703
|
+
function slugifyBookmarkText(text) {
|
|
3704
|
+
return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 40);
|
|
3705
|
+
}
|
|
3706
|
+
function dedupeBookmarkId(base, taken) {
|
|
3707
|
+
let id = base;
|
|
3708
|
+
let attempt = 0;
|
|
3709
|
+
while (taken(id) && attempt < 100) {
|
|
3710
|
+
id = `${base}-${++attempt}`;
|
|
3711
|
+
}
|
|
3712
|
+
return id;
|
|
3713
|
+
}
|
|
3557
3714
|
var BookmarkRegistry = class {
|
|
3558
3715
|
fallback = { bookmarks: /* @__PURE__ */ new Map() };
|
|
3559
|
-
scopes = new
|
|
3716
|
+
scopes = new AsyncLocalStorage3();
|
|
3560
3717
|
get state() {
|
|
3561
3718
|
return this.scopes.getStore() ?? this.fallback;
|
|
3562
3719
|
}
|
|
@@ -3580,13 +3737,10 @@ var BookmarkRegistry = class {
|
|
|
3580
3737
|
* Converts text to a URL-friendly format
|
|
3581
3738
|
*/
|
|
3582
3739
|
generateId(text, _type = "bookmark") {
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
id = `${baseId}-${++attempt}`;
|
|
3588
|
-
}
|
|
3589
|
-
return id;
|
|
3740
|
+
return dedupeBookmarkId(
|
|
3741
|
+
slugifyBookmarkText(text),
|
|
3742
|
+
(id) => this.state.bookmarks.has(id)
|
|
3743
|
+
);
|
|
3590
3744
|
}
|
|
3591
3745
|
/**
|
|
3592
3746
|
* Check if a bookmark exists
|
|
@@ -3630,7 +3784,7 @@ var globalBookmarkRegistry = new BookmarkRegistry();
|
|
|
3630
3784
|
|
|
3631
3785
|
// src/utils/revisionUtils.ts
|
|
3632
3786
|
import { TextRun as TextRun3, InsertedTextRun, DeletedTextRun } from "docx";
|
|
3633
|
-
import { AsyncLocalStorage as
|
|
3787
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
3634
3788
|
|
|
3635
3789
|
// src/utils/componentAnnotations.ts
|
|
3636
3790
|
function isRecord(value) {
|
|
@@ -3681,7 +3835,7 @@ var DEFAULT_REVISION_AUTHOR = "json-to-office";
|
|
|
3681
3835
|
var DEFAULT_REVISION_DATE = "1970-01-01T00:00:00Z";
|
|
3682
3836
|
var RevisionIdRegistry = class {
|
|
3683
3837
|
fallbackCounter = 0;
|
|
3684
|
-
scopes = new
|
|
3838
|
+
scopes = new AsyncLocalStorage4();
|
|
3685
3839
|
runScoped(callback) {
|
|
3686
3840
|
return this.scopes.run({ counter: 0 }, callback);
|
|
3687
3841
|
}
|
|
@@ -3792,7 +3946,7 @@ import {
|
|
|
3792
3946
|
|
|
3793
3947
|
// src/utils/commentRegistry.ts
|
|
3794
3948
|
import { Paragraph, TextRun as TextRun4 } from "docx";
|
|
3795
|
-
import { AsyncLocalStorage as
|
|
3949
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
|
|
3796
3950
|
var DEFAULT_COMMENT_AUTHOR = "json-to-office";
|
|
3797
3951
|
var DEFAULT_COMMENT_DATE = "1970-01-01T00:00:00Z";
|
|
3798
3952
|
function createState() {
|
|
@@ -3807,7 +3961,7 @@ function bodyParagraphs(text) {
|
|
|
3807
3961
|
}
|
|
3808
3962
|
var CommentRegistry = class {
|
|
3809
3963
|
fallback = createState();
|
|
3810
|
-
scopes = new
|
|
3964
|
+
scopes = new AsyncLocalStorage5();
|
|
3811
3965
|
get state() {
|
|
3812
3966
|
return this.scopes.getStore() ?? this.fallback;
|
|
3813
3967
|
}
|
|
@@ -3902,7 +4056,7 @@ function closeCommentRange(ids) {
|
|
|
3902
4056
|
|
|
3903
4057
|
// src/utils/noteRegistry.ts
|
|
3904
4058
|
import { Paragraph as Paragraph2, TextRun as TextRun6 } from "docx";
|
|
3905
|
-
import { AsyncLocalStorage as
|
|
4059
|
+
import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
|
|
3906
4060
|
function createState2() {
|
|
3907
4061
|
return {
|
|
3908
4062
|
footnoteCounter: 0,
|
|
@@ -3921,7 +4075,7 @@ function bodyParagraphs2(text, style) {
|
|
|
3921
4075
|
}
|
|
3922
4076
|
var NoteRegistry = class {
|
|
3923
4077
|
fallback = createState2();
|
|
3924
|
-
scopes = new
|
|
4078
|
+
scopes = new AsyncLocalStorage6();
|
|
3925
4079
|
get state() {
|
|
3926
4080
|
return this.scopes.getStore() ?? this.fallback;
|
|
3927
4081
|
}
|
|
@@ -4277,7 +4431,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4277
4431
|
if (commentAnchor) {
|
|
4278
4432
|
children.push(...commentAnchor.start);
|
|
4279
4433
|
}
|
|
4280
|
-
const
|
|
4434
|
+
const hasInlineSyntax = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText) || hasCrossReference(normalizedText);
|
|
4281
4435
|
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4282
4436
|
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
4283
4437
|
const headingWeighted = applyFontWeightAlias({
|
|
@@ -4344,7 +4498,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4344
4498
|
"heading"
|
|
4345
4499
|
);
|
|
4346
4500
|
const headingTextChildren = [];
|
|
4347
|
-
if (
|
|
4501
|
+
if (hasInlineSyntax) {
|
|
4348
4502
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4349
4503
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
4350
4504
|
enableHyperlinks: true,
|
|
@@ -4361,7 +4515,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4361
4515
|
})
|
|
4362
4516
|
);
|
|
4363
4517
|
} else {
|
|
4364
|
-
if (
|
|
4518
|
+
if (hasInlineSyntax) {
|
|
4365
4519
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4366
4520
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
4367
4521
|
enableHyperlinks: true,
|
|
@@ -4383,7 +4537,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4383
4537
|
spacing: hasExplicitSpacing ? spacing : void 0,
|
|
4384
4538
|
...options.keepNext !== void 0 && { keepNext: options.keepNext },
|
|
4385
4539
|
...options.keepLines !== void 0 && { keepLines: options.keepLines },
|
|
4386
|
-
...options.indent && { indent: options.indent }
|
|
4540
|
+
...options.indent && { indent: options.indent },
|
|
4541
|
+
// docx creates the concrete numbering instance for the reference itself,
|
|
4542
|
+
// in ParagraphProperties.prepForXml.
|
|
4543
|
+
...options.numbering !== void 0 && { numbering: options.numbering }
|
|
4387
4544
|
});
|
|
4388
4545
|
}
|
|
4389
4546
|
async function createImage(path3, theme, themeName, options = {}) {
|
|
@@ -4428,7 +4585,7 @@ async function createImage(path3, theme, themeName, options = {}) {
|
|
|
4428
4585
|
const { mapFloatingOptions: mapFloatingOptions2 } = await Promise.resolve().then(() => (init_docxImagePositioning(), docxImagePositioning_exports));
|
|
4429
4586
|
const floating = isFloating ? mapFloatingOptions2(options.floating, theme, themeName) : void 0;
|
|
4430
4587
|
const imageType = detectImageType(imagePath, responseContentType);
|
|
4431
|
-
const imageRun = createTypedImageRun({
|
|
4588
|
+
const imageRun = await createTypedImageRun({
|
|
4432
4589
|
type: imageType,
|
|
4433
4590
|
data: imageBuffer,
|
|
4434
4591
|
transformation: { width: dimensions.width, height: dimensions.height },
|
|
@@ -4543,9 +4700,17 @@ function createList(items, _theme, _themeName, options = {}) {
|
|
|
4543
4700
|
} else if (options.spacing?.item) {
|
|
4544
4701
|
spacing.after = pointsToTwips(options.spacing.item);
|
|
4545
4702
|
}
|
|
4703
|
+
const itemId = typeof item === "object" ? item.id : void 0;
|
|
4704
|
+
let itemContent = textRuns;
|
|
4705
|
+
if (itemId) {
|
|
4706
|
+
globalBookmarkRegistry.register(itemId, itemText, "list-item");
|
|
4707
|
+
itemContent = [
|
|
4708
|
+
new Bookmark({ id: itemId, children: textRuns })
|
|
4709
|
+
];
|
|
4710
|
+
}
|
|
4546
4711
|
const paragraphChildren = [
|
|
4547
4712
|
...commentAnchor && index === firstRendered ? commentAnchor.start : [],
|
|
4548
|
-
...
|
|
4713
|
+
...itemContent,
|
|
4549
4714
|
...commentAnchor && index === lastRendered ? closeCommentRange(commentAnchor.ids) : []
|
|
4550
4715
|
];
|
|
4551
4716
|
const paragraph = new Paragraph3({
|
|
@@ -4973,7 +5138,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4973
5138
|
// fallback height
|
|
4974
5139
|
);
|
|
4975
5140
|
const imgType = detectImageType(imageSource, imageResult.contentType);
|
|
4976
|
-
const imageRun = createTypedImageRun({
|
|
5141
|
+
const imageRun = await createTypedImageRun({
|
|
4977
5142
|
type: imgType,
|
|
4978
5143
|
data: imageResult.buffer,
|
|
4979
5144
|
transformation: {
|
|
@@ -6748,54 +6913,14 @@ async function renderComponentWithCache(component, theme, themeName, context, by
|
|
|
6748
6913
|
return rendered;
|
|
6749
6914
|
}
|
|
6750
6915
|
|
|
6751
|
-
// src/components/heading.ts
|
|
6752
|
-
function renderHeadingComponent(component, theme, themeName) {
|
|
6753
|
-
if (!isHeadingComponent(component)) return [];
|
|
6754
|
-
const config = component.props;
|
|
6755
|
-
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6756
|
-
const header = createHeading(
|
|
6757
|
-
config.text,
|
|
6758
|
-
config.level || 1,
|
|
6759
|
-
theme,
|
|
6760
|
-
themeName,
|
|
6761
|
-
{
|
|
6762
|
-
alignment: config.alignment,
|
|
6763
|
-
spacing: config.spacing,
|
|
6764
|
-
lineSpacing: config.lineSpacing,
|
|
6765
|
-
columnBreak: config.columnBreak,
|
|
6766
|
-
// Local font overrides
|
|
6767
|
-
fontFamily: config.font?.family,
|
|
6768
|
-
fontSize: config.font?.size,
|
|
6769
|
-
fontColor: config.font?.color,
|
|
6770
|
-
bold: config.font?.bold,
|
|
6771
|
-
fontWeight: config.font?.fontWeight,
|
|
6772
|
-
italic: config.font?.italic,
|
|
6773
|
-
underline: config.font?.underline,
|
|
6774
|
-
scale: config.font?.scale,
|
|
6775
|
-
characterSpacing: config.font?.characterSpacing,
|
|
6776
|
-
// Proofing: local language override + no-proof toggle + known-words list
|
|
6777
|
-
language: config.language,
|
|
6778
|
-
noProof: config.noProof,
|
|
6779
|
-
noProofWords: config.noProofWords,
|
|
6780
|
-
// Pagination control
|
|
6781
|
-
keepNext: config.keepNext,
|
|
6782
|
-
keepLines: config.keepLines,
|
|
6783
|
-
// Paragraph indentation (w:ind) in twips
|
|
6784
|
-
indent: config.indent,
|
|
6785
|
-
// Bookmark ID for internal linking
|
|
6786
|
-
bookmarkId,
|
|
6787
|
-
// Tracked-change segments (rendered as native Word revisions)
|
|
6788
|
-
revision: config.revision,
|
|
6789
|
-
// Review comment anchored to this heading's text
|
|
6790
|
-
comment: config.comment
|
|
6791
|
-
}
|
|
6792
|
-
);
|
|
6793
|
-
return [header];
|
|
6794
|
-
}
|
|
6795
|
-
|
|
6796
6916
|
// src/utils/numberingConfig.ts
|
|
6797
|
-
import {
|
|
6798
|
-
|
|
6917
|
+
import {
|
|
6918
|
+
AlignmentType as AlignmentType3,
|
|
6919
|
+
convertInchesToTwip,
|
|
6920
|
+
LevelFormat,
|
|
6921
|
+
LevelSuffix
|
|
6922
|
+
} from "docx";
|
|
6923
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "async_hooks";
|
|
6799
6924
|
var LEVEL_FORMAT_MAP = {
|
|
6800
6925
|
decimal: LevelFormat.DECIMAL,
|
|
6801
6926
|
upperRoman: LevelFormat.UPPER_ROMAN,
|
|
@@ -6923,12 +7048,37 @@ function createNumberingConfig(config) {
|
|
|
6923
7048
|
levels
|
|
6924
7049
|
};
|
|
6925
7050
|
}
|
|
7051
|
+
var HEADING_NUMBERING_REFERENCE = "jto-heading-numbering";
|
|
7052
|
+
function createHeadingNumberingConfig() {
|
|
7053
|
+
const levels = [];
|
|
7054
|
+
for (let level = 0; level < 6; level++) {
|
|
7055
|
+
const text = Array.from({ length: level + 1 }, (_, i) => `%${i + 1}`).join(".") + ".";
|
|
7056
|
+
levels.push({
|
|
7057
|
+
level,
|
|
7058
|
+
format: LevelFormat.DECIMAL,
|
|
7059
|
+
text,
|
|
7060
|
+
alignment: AlignmentType3.LEFT,
|
|
7061
|
+
start: 1,
|
|
7062
|
+
// A space, not the default tab: a tab would push the heading text to the
|
|
7063
|
+
// next tab stop and misalign it against unnumbered headings.
|
|
7064
|
+
suffix: LevelSuffix.SPACE,
|
|
7065
|
+
style: {
|
|
7066
|
+
paragraph: { indent: { left: 0, hanging: 0 } },
|
|
7067
|
+
style: `Heading${level + 1}`
|
|
7068
|
+
}
|
|
7069
|
+
});
|
|
7070
|
+
}
|
|
7071
|
+
return { reference: HEADING_NUMBERING_REFERENCE, levels };
|
|
7072
|
+
}
|
|
7073
|
+
function headingNumberLabel(number) {
|
|
7074
|
+
return `${number}.`;
|
|
7075
|
+
}
|
|
6926
7076
|
var NumberingRegistry = class {
|
|
6927
7077
|
fallback = {
|
|
6928
7078
|
configs: /* @__PURE__ */ new Map(),
|
|
6929
7079
|
counter: 0
|
|
6930
7080
|
};
|
|
6931
|
-
scopes = new
|
|
7081
|
+
scopes = new AsyncLocalStorage7();
|
|
6932
7082
|
get state() {
|
|
6933
7083
|
return this.scopes.getStore() ?? this.fallback;
|
|
6934
7084
|
}
|
|
@@ -6978,6 +7128,63 @@ var NumberingRegistry = class {
|
|
|
6978
7128
|
};
|
|
6979
7129
|
var globalNumberingRegistry = new NumberingRegistry();
|
|
6980
7130
|
|
|
7131
|
+
// src/components/heading.ts
|
|
7132
|
+
var MAX_HEADING_LEVEL = 6;
|
|
7133
|
+
function headingNumbering(numbering, level) {
|
|
7134
|
+
if (numbering === false) return false;
|
|
7135
|
+
if (numbering !== true) return void 0;
|
|
7136
|
+
if (!globalNumberingRegistry.has(HEADING_NUMBERING_REFERENCE)) {
|
|
7137
|
+
globalNumberingRegistry.register(createHeadingNumberingConfig());
|
|
7138
|
+
}
|
|
7139
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;
|
|
7140
|
+
return { reference: HEADING_NUMBERING_REFERENCE, level: styleLevel - 1 };
|
|
7141
|
+
}
|
|
7142
|
+
function renderHeadingComponent(component, theme, themeName) {
|
|
7143
|
+
if (!isHeadingComponent(component)) return [];
|
|
7144
|
+
const config = component.props;
|
|
7145
|
+
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
7146
|
+
const header = createHeading(
|
|
7147
|
+
config.text,
|
|
7148
|
+
config.level || 1,
|
|
7149
|
+
theme,
|
|
7150
|
+
themeName,
|
|
7151
|
+
{
|
|
7152
|
+
alignment: config.alignment,
|
|
7153
|
+
spacing: config.spacing,
|
|
7154
|
+
lineSpacing: config.lineSpacing,
|
|
7155
|
+
columnBreak: config.columnBreak,
|
|
7156
|
+
// Local font overrides
|
|
7157
|
+
fontFamily: config.font?.family,
|
|
7158
|
+
fontSize: config.font?.size,
|
|
7159
|
+
fontColor: config.font?.color,
|
|
7160
|
+
bold: config.font?.bold,
|
|
7161
|
+
fontWeight: config.font?.fontWeight,
|
|
7162
|
+
italic: config.font?.italic,
|
|
7163
|
+
underline: config.font?.underline,
|
|
7164
|
+
scale: config.font?.scale,
|
|
7165
|
+
characterSpacing: config.font?.characterSpacing,
|
|
7166
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
7167
|
+
language: config.language,
|
|
7168
|
+
noProof: config.noProof,
|
|
7169
|
+
noProofWords: config.noProofWords,
|
|
7170
|
+
// Pagination control
|
|
7171
|
+
keepNext: config.keepNext,
|
|
7172
|
+
keepLines: config.keepLines,
|
|
7173
|
+
// Paragraph indentation (w:ind) in twips
|
|
7174
|
+
indent: config.indent,
|
|
7175
|
+
// Bookmark ID for internal linking
|
|
7176
|
+
bookmarkId,
|
|
7177
|
+
// Auto-numbering (1., 1.1., …) through the shared heading definition
|
|
7178
|
+
numbering: headingNumbering(config.numbering, config.level || 1),
|
|
7179
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
7180
|
+
revision: config.revision,
|
|
7181
|
+
// Review comment anchored to this heading's text
|
|
7182
|
+
comment: config.comment
|
|
7183
|
+
}
|
|
7184
|
+
);
|
|
7185
|
+
return [header];
|
|
7186
|
+
}
|
|
7187
|
+
|
|
6981
7188
|
// src/components/paragraph.ts
|
|
6982
7189
|
function parseMarkdownList(text) {
|
|
6983
7190
|
const lines = text.split("\n");
|
|
@@ -7117,8 +7324,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
7117
7324
|
return [text];
|
|
7118
7325
|
}
|
|
7119
7326
|
|
|
7120
|
-
// src/
|
|
7121
|
-
init_colorUtils();
|
|
7327
|
+
// src/utils/listLevels.ts
|
|
7122
7328
|
function createLevelsFromSimplifiedProps(props) {
|
|
7123
7329
|
const levels = [];
|
|
7124
7330
|
let format2;
|
|
@@ -7165,18 +7371,8 @@ function createLevelsFromSimplifiedProps(props) {
|
|
|
7165
7371
|
}
|
|
7166
7372
|
return levels;
|
|
7167
7373
|
}
|
|
7168
|
-
function resolveMarkerFonts(levels, theme) {
|
|
7169
|
-
return levels.map((level) => {
|
|
7170
|
-
const font = level.font;
|
|
7171
|
-
if (!font?.color) return level;
|
|
7172
|
-
return {
|
|
7173
|
-
...level,
|
|
7174
|
-
font: { ...font, color: resolveColor(font.color, theme) }
|
|
7175
|
-
};
|
|
7176
|
-
});
|
|
7177
|
-
}
|
|
7178
7374
|
function applyListStart(levels, start) {
|
|
7179
|
-
if (start === void 0) return levels;
|
|
7375
|
+
if (start === void 0) return [...levels];
|
|
7180
7376
|
return levels.map(
|
|
7181
7377
|
(level) => level.level === 0 && level.start === void 0 ? { ...level, start } : level
|
|
7182
7378
|
);
|
|
@@ -7234,28 +7430,37 @@ function fillMissingLevels(levels, maxLevel) {
|
|
|
7234
7430
|
}
|
|
7235
7431
|
return result;
|
|
7236
7432
|
}
|
|
7433
|
+
function resolveListLevels(props) {
|
|
7434
|
+
const maxLevel = getMaxLevelFromItems(props.items);
|
|
7435
|
+
if (props.levels && props.levels.length > 0) {
|
|
7436
|
+
return fillMissingLevels(
|
|
7437
|
+
applyListStart(props.levels, props.start),
|
|
7438
|
+
maxLevel
|
|
7439
|
+
);
|
|
7440
|
+
}
|
|
7441
|
+
return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);
|
|
7442
|
+
}
|
|
7443
|
+
|
|
7444
|
+
// src/components/list.ts
|
|
7445
|
+
init_colorUtils();
|
|
7446
|
+
function resolveMarkerFonts(levels, theme) {
|
|
7447
|
+
return levels.map((level) => {
|
|
7448
|
+
const font = level.font;
|
|
7449
|
+
if (!font?.color) return level;
|
|
7450
|
+
return {
|
|
7451
|
+
...level,
|
|
7452
|
+
font: { ...font, color: resolveColor(font.color, theme) }
|
|
7453
|
+
};
|
|
7454
|
+
});
|
|
7455
|
+
}
|
|
7237
7456
|
function renderListComponent(component, theme, themeName) {
|
|
7238
7457
|
if (!isListComponent(component)) return [];
|
|
7239
7458
|
const resolvedConfig = component.props;
|
|
7240
|
-
const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
|
|
7241
7459
|
const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
|
|
7242
7460
|
if (!globalNumberingRegistry.has(reference)) {
|
|
7243
|
-
let levels;
|
|
7244
|
-
if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {
|
|
7245
|
-
levels = fillMissingLevels(
|
|
7246
|
-
applyListStart(
|
|
7247
|
-
resolvedConfig.levels,
|
|
7248
|
-
resolvedConfig.start
|
|
7249
|
-
),
|
|
7250
|
-
maxLevel
|
|
7251
|
-
);
|
|
7252
|
-
} else {
|
|
7253
|
-
const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);
|
|
7254
|
-
levels = fillMissingLevels(baseLevels, maxLevel);
|
|
7255
|
-
}
|
|
7256
7461
|
const config = {
|
|
7257
7462
|
reference,
|
|
7258
|
-
levels: resolveMarkerFonts(
|
|
7463
|
+
levels: resolveMarkerFonts(resolveListLevels(resolvedConfig), theme)
|
|
7259
7464
|
};
|
|
7260
7465
|
const numberingConfig = createNumberingConfig(config);
|
|
7261
7466
|
globalNumberingRegistry.register(numberingConfig);
|
|
@@ -7295,6 +7500,7 @@ async function renderImageComponent(component, theme, themeName) {
|
|
|
7295
7500
|
|
|
7296
7501
|
// src/components/text-box.ts
|
|
7297
7502
|
import {
|
|
7503
|
+
Paragraph as Paragraph5,
|
|
7298
7504
|
Table as Table3,
|
|
7299
7505
|
TableRow as TableRow2,
|
|
7300
7506
|
TableCell as TableCell2,
|
|
@@ -7303,7 +7509,8 @@ import {
|
|
|
7303
7509
|
RelativeHorizontalPosition,
|
|
7304
7510
|
RelativeVerticalPosition,
|
|
7305
7511
|
OverlapType,
|
|
7306
|
-
TableLayoutType as TableLayoutType2
|
|
7512
|
+
TableLayoutType as TableLayoutType2,
|
|
7513
|
+
WpsShapeRun
|
|
7307
7514
|
} from "docx";
|
|
7308
7515
|
|
|
7309
7516
|
// src/styles/utils/borderUtils.ts
|
|
@@ -7380,6 +7587,8 @@ function buildCellOptions(children, styleCfg, theme) {
|
|
|
7380
7587
|
}
|
|
7381
7588
|
|
|
7382
7589
|
// src/components/text-box.ts
|
|
7590
|
+
init_colorUtils();
|
|
7591
|
+
init_docxImagePositioning();
|
|
7383
7592
|
init_widthUtils();
|
|
7384
7593
|
function mapTableFloatOptions(floating, theme, themeName) {
|
|
7385
7594
|
if (!floating) return void 0;
|
|
@@ -7435,26 +7644,23 @@ function mapTableFloatOptions(floating, theme, themeName) {
|
|
|
7435
7644
|
opt.overlap = OverlapType.OVERLAP;
|
|
7436
7645
|
return opt;
|
|
7437
7646
|
}
|
|
7438
|
-
async function
|
|
7439
|
-
|
|
7440
|
-
|
|
7647
|
+
async function renderTextBoxChildren(tb, theme, themeName, context) {
|
|
7648
|
+
const childContext = {
|
|
7649
|
+
...context,
|
|
7650
|
+
parent: tb
|
|
7651
|
+
};
|
|
7652
|
+
const rendered = [];
|
|
7653
|
+
for (const child of tb.children || []) {
|
|
7654
|
+
rendered.push(
|
|
7655
|
+
...await renderComponent(child, theme, themeName, childContext)
|
|
7656
|
+
);
|
|
7657
|
+
}
|
|
7658
|
+
return rendered;
|
|
7659
|
+
}
|
|
7660
|
+
async function renderTextBoxAsTable(tb, theme, themeName, _context, prerendered) {
|
|
7441
7661
|
const isInline = !tb.props.floating;
|
|
7442
|
-
const childComponents = tb.children || [];
|
|
7443
7662
|
if (isInline) {
|
|
7444
|
-
const cellChildren2 =
|
|
7445
|
-
const childContext2 = {
|
|
7446
|
-
..._context,
|
|
7447
|
-
parent: tb
|
|
7448
|
-
};
|
|
7449
|
-
for (const child of childComponents) {
|
|
7450
|
-
const rendered = await renderComponent(
|
|
7451
|
-
child,
|
|
7452
|
-
theme,
|
|
7453
|
-
themeName,
|
|
7454
|
-
childContext2
|
|
7455
|
-
);
|
|
7456
|
-
cellChildren2.push(...rendered);
|
|
7457
|
-
}
|
|
7663
|
+
const cellChildren2 = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
7458
7664
|
const styleCfg2 = tb.props.style;
|
|
7459
7665
|
const cellOpts2 = buildCellOptions(cellChildren2, styleCfg2, theme);
|
|
7460
7666
|
const row2 = new TableRow2({ children: [new TableCell2(cellOpts2)] });
|
|
@@ -7467,20 +7673,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
7467
7673
|
});
|
|
7468
7674
|
return [table2];
|
|
7469
7675
|
}
|
|
7470
|
-
const cellChildren =
|
|
7471
|
-
const childContext = {
|
|
7472
|
-
..._context,
|
|
7473
|
-
parent: tb
|
|
7474
|
-
};
|
|
7475
|
-
for (const child of childComponents) {
|
|
7476
|
-
const rendered = await renderComponent(
|
|
7477
|
-
child,
|
|
7478
|
-
theme,
|
|
7479
|
-
themeName,
|
|
7480
|
-
childContext
|
|
7481
|
-
);
|
|
7482
|
-
cellChildren.push(...rendered);
|
|
7483
|
-
}
|
|
7676
|
+
const cellChildren = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
7484
7677
|
const styleCfg = tb.props.style;
|
|
7485
7678
|
const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);
|
|
7486
7679
|
const row = new TableRow2({
|
|
@@ -7512,6 +7705,162 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
7512
7705
|
});
|
|
7513
7706
|
return [table];
|
|
7514
7707
|
}
|
|
7708
|
+
var PIXELS_TO_EMU = 9525;
|
|
7709
|
+
var TWIPS_PER_PIXEL = 15;
|
|
7710
|
+
function resolveShapeSize(value, axis, theme, themeName) {
|
|
7711
|
+
if (typeof value === "number") {
|
|
7712
|
+
return { pixels: Math.round(value), resolvedPercentage: false };
|
|
7713
|
+
}
|
|
7714
|
+
if (typeof value !== "string") return { resolvedPercentage: false };
|
|
7715
|
+
const fraction = parseFloat(value) / 100;
|
|
7716
|
+
if (!Number.isFinite(fraction) || fraction <= 0) {
|
|
7717
|
+
return { resolvedPercentage: false };
|
|
7718
|
+
}
|
|
7719
|
+
const availableTwips = axis === "width" ? getAvailableWidthTwips(theme, themeName) : getAvailableHeightTwips(theme, themeName);
|
|
7720
|
+
return {
|
|
7721
|
+
pixels: Math.round(availableTwips * fraction / TWIPS_PER_PIXEL),
|
|
7722
|
+
resolvedPercentage: true
|
|
7723
|
+
};
|
|
7724
|
+
}
|
|
7725
|
+
function shapeColor(value, theme) {
|
|
7726
|
+
return resolveColor(value, theme).replace(/^#/, "");
|
|
7727
|
+
}
|
|
7728
|
+
function shapeOutline(style, theme) {
|
|
7729
|
+
const border = style?.border;
|
|
7730
|
+
if (!border) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7731
|
+
const order = [
|
|
7732
|
+
"top",
|
|
7733
|
+
"left",
|
|
7734
|
+
"bottom",
|
|
7735
|
+
"right"
|
|
7736
|
+
];
|
|
7737
|
+
const declared = order.map((side) => [side, border[side]]).filter(
|
|
7738
|
+
(entry) => Boolean(entry[1])
|
|
7739
|
+
);
|
|
7740
|
+
if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7741
|
+
const unsupportedStyles = [
|
|
7742
|
+
...new Set(
|
|
7743
|
+
declared.map(([, config]) => config.style).filter(
|
|
7744
|
+
(value) => value === "dashed" || value === "dotted" || value === "double"
|
|
7745
|
+
)
|
|
7746
|
+
)
|
|
7747
|
+
];
|
|
7748
|
+
if (unsupportedStyles.length > 0) {
|
|
7749
|
+
return { ignoredSides: [], unsupportedStyles };
|
|
7750
|
+
}
|
|
7751
|
+
const [, used] = declared[0];
|
|
7752
|
+
const differs = ({ style: s, width, color }) => s !== used.style || width !== used.width || color !== used.color;
|
|
7753
|
+
const ignoredSides = declared.slice(1).filter(([, config]) => differs(config)).map(([side]) => side);
|
|
7754
|
+
if (used.style === "none") return { ignoredSides, unsupportedStyles };
|
|
7755
|
+
return {
|
|
7756
|
+
outline: {
|
|
7757
|
+
type: "solidFill",
|
|
7758
|
+
solidFillType: "rgb",
|
|
7759
|
+
value: used.color ? shapeColor(used.color, theme) : "000000",
|
|
7760
|
+
...used.width !== void 0 && {
|
|
7761
|
+
width: Math.round(used.width * PIXELS_TO_EMU)
|
|
7762
|
+
}
|
|
7763
|
+
},
|
|
7764
|
+
ignoredSides,
|
|
7765
|
+
unsupportedStyles
|
|
7766
|
+
};
|
|
7767
|
+
}
|
|
7768
|
+
function shapeBodyProperties(style) {
|
|
7769
|
+
const padding = style?.padding;
|
|
7770
|
+
if (!padding) return void 0;
|
|
7771
|
+
const toEmu = (value) => value === void 0 ? void 0 : Math.round(value * PIXELS_TO_EMU);
|
|
7772
|
+
return {
|
|
7773
|
+
margins: {
|
|
7774
|
+
...padding.top !== void 0 && { top: toEmu(padding.top) },
|
|
7775
|
+
...padding.bottom !== void 0 && { bottom: toEmu(padding.bottom) },
|
|
7776
|
+
...padding.left !== void 0 && { left: toEmu(padding.left) },
|
|
7777
|
+
...padding.right !== void 0 && { right: toEmu(padding.right) }
|
|
7778
|
+
}
|
|
7779
|
+
};
|
|
7780
|
+
}
|
|
7781
|
+
async function renderTextBoxAsShape(tb, theme, themeName, context) {
|
|
7782
|
+
const width = resolveShapeSize(tb.props.width, "width", theme, themeName);
|
|
7783
|
+
const height = resolveShapeSize(tb.props.height, "height", theme, themeName);
|
|
7784
|
+
if (width.pixels === void 0 || height.pixels === void 0) {
|
|
7785
|
+
console.warn(
|
|
7786
|
+
'[core-docx] text-box renderAs "shape" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'
|
|
7787
|
+
);
|
|
7788
|
+
return { kind: "fallback" };
|
|
7789
|
+
}
|
|
7790
|
+
const style = tb.props.style;
|
|
7791
|
+
const { outline, ignoredSides, unsupportedStyles } = shapeOutline(
|
|
7792
|
+
style,
|
|
7793
|
+
theme
|
|
7794
|
+
);
|
|
7795
|
+
if (unsupportedStyles.length > 0) {
|
|
7796
|
+
console.warn(
|
|
7797
|
+
`[core-docx] text-box renderAs "shape" cannot draw a ${unsupportedStyles.join("/")} border (a shape outline has no dash pattern); falling back to table rendering, which draws it.`
|
|
7798
|
+
);
|
|
7799
|
+
return { kind: "fallback" };
|
|
7800
|
+
}
|
|
7801
|
+
const rendered = await renderTextBoxChildren(tb, theme, themeName, context);
|
|
7802
|
+
if (rendered.some((element) => !(element instanceof Paragraph5))) {
|
|
7803
|
+
console.warn(
|
|
7804
|
+
'[core-docx] text-box renderAs "shape" requires paragraph-only content; falling back to table rendering.'
|
|
7805
|
+
);
|
|
7806
|
+
return { kind: "fallback", rendered };
|
|
7807
|
+
}
|
|
7808
|
+
const children = rendered;
|
|
7809
|
+
if (width.resolvedPercentage || height.resolvedPercentage) {
|
|
7810
|
+
console.warn(
|
|
7811
|
+
'[core-docx] text-box renderAs "shape" resolves percentage sizes at generation time, against the current page content box; the shape will not reflow if the page size changes.'
|
|
7812
|
+
);
|
|
7813
|
+
}
|
|
7814
|
+
const fill = style?.shading?.fill;
|
|
7815
|
+
if (ignoredSides.length > 0) {
|
|
7816
|
+
console.warn(
|
|
7817
|
+
`[core-docx] text-box renderAs "shape" has one uniform outline; using the first declared border side and ignoring ${ignoredSides.join(", ")}.`
|
|
7818
|
+
);
|
|
7819
|
+
}
|
|
7820
|
+
const dropOutline = Boolean(fill) && Boolean(outline);
|
|
7821
|
+
if (dropOutline) {
|
|
7822
|
+
console.warn(
|
|
7823
|
+
'[core-docx] text-box renderAs "shape" cannot carry a fill and a border at once (docx emits invalid shape properties); keeping the fill and dropping the border.'
|
|
7824
|
+
);
|
|
7825
|
+
}
|
|
7826
|
+
const bodyProperties = shapeBodyProperties(style);
|
|
7827
|
+
const run = new WpsShapeRun({
|
|
7828
|
+
type: "wps",
|
|
7829
|
+
children,
|
|
7830
|
+
transformation: { width: width.pixels, height: height.pixels },
|
|
7831
|
+
...fill && {
|
|
7832
|
+
solidFill: { type: "rgb", value: shapeColor(fill, theme) }
|
|
7833
|
+
},
|
|
7834
|
+
...outline && !dropOutline && { outline },
|
|
7835
|
+
...bodyProperties && { bodyProperties },
|
|
7836
|
+
// Absent `floating` makes it a `wp:inline` drawing.
|
|
7837
|
+
...tb.props.floating && {
|
|
7838
|
+
floating: mapFloatingOptions(tb.props.floating, theme, themeName)
|
|
7839
|
+
}
|
|
7840
|
+
});
|
|
7841
|
+
return {
|
|
7842
|
+
kind: "shape",
|
|
7843
|
+
paragraphs: [
|
|
7844
|
+
new Paragraph5({ children: [run], spacing: { before: 0, after: 0 } })
|
|
7845
|
+
]
|
|
7846
|
+
};
|
|
7847
|
+
}
|
|
7848
|
+
async function renderTextBoxComponent(component, theme, themeName, context) {
|
|
7849
|
+
if (!isTextBoxComponent(component)) return [];
|
|
7850
|
+
const tb = component;
|
|
7851
|
+
if (tb.props.renderAs === "shape") {
|
|
7852
|
+
const attempt = await renderTextBoxAsShape(tb, theme, themeName, context);
|
|
7853
|
+
if (attempt.kind === "shape") return attempt.paragraphs;
|
|
7854
|
+
return renderTextBoxAsTable(
|
|
7855
|
+
tb,
|
|
7856
|
+
theme,
|
|
7857
|
+
themeName,
|
|
7858
|
+
context,
|
|
7859
|
+
attempt.rendered
|
|
7860
|
+
);
|
|
7861
|
+
}
|
|
7862
|
+
return renderTextBoxAsTable(tb, theme, themeName, context);
|
|
7863
|
+
}
|
|
7515
7864
|
|
|
7516
7865
|
// src/components/table.ts
|
|
7517
7866
|
async function renderTableComponent(component, theme, themeName) {
|
|
@@ -7565,14 +7914,14 @@ async function renderTableComponent(component, theme, themeName) {
|
|
|
7565
7914
|
import { Paragraph as Paragraph6, BookmarkStart, BookmarkEnd } from "docx";
|
|
7566
7915
|
|
|
7567
7916
|
// src/core/sectionBookmarks.ts
|
|
7568
|
-
import { AsyncLocalStorage as
|
|
7917
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
|
|
7569
7918
|
var NESTED_LINK_ID_BASE = 1e6;
|
|
7570
7919
|
function createState3() {
|
|
7571
7920
|
return { nextNested: 1, resolved: /* @__PURE__ */ new WeakMap() };
|
|
7572
7921
|
}
|
|
7573
7922
|
var SectionBookmarkRegistry = class {
|
|
7574
7923
|
fallback = createState3();
|
|
7575
|
-
scopes = new
|
|
7924
|
+
scopes = new AsyncLocalStorage8();
|
|
7576
7925
|
get state() {
|
|
7577
7926
|
return this.scopes.getStore() ?? this.fallback;
|
|
7578
7927
|
}
|
|
@@ -7830,7 +8179,10 @@ function selectCachedEntries(collected, options) {
|
|
|
7830
8179
|
continue;
|
|
7831
8180
|
}
|
|
7832
8181
|
if (entry.level < depthStart || entry.level > depthEnd) continue;
|
|
7833
|
-
entries.push({
|
|
8182
|
+
entries.push({
|
|
8183
|
+
title: entry.number ? `${headingNumberLabel(entry.number)} ${entry.title}` : entry.title,
|
|
8184
|
+
level: entry.level
|
|
8185
|
+
});
|
|
7834
8186
|
}
|
|
7835
8187
|
return entries;
|
|
7836
8188
|
}
|
|
@@ -8138,6 +8490,61 @@ function computeSectionOrdinals(sections) {
|
|
|
8138
8490
|
|
|
8139
8491
|
// src/core/collectTocHeadings.ts
|
|
8140
8492
|
import { getStandardComponent } from "@json-to-office/shared-docx";
|
|
8493
|
+
|
|
8494
|
+
// src/utils/numberFormatting.ts
|
|
8495
|
+
var ROMAN_NUMERALS = [
|
|
8496
|
+
[1e3, "m"],
|
|
8497
|
+
[900, "cm"],
|
|
8498
|
+
[500, "d"],
|
|
8499
|
+
[400, "cd"],
|
|
8500
|
+
[100, "c"],
|
|
8501
|
+
[90, "xc"],
|
|
8502
|
+
[50, "l"],
|
|
8503
|
+
[40, "xl"],
|
|
8504
|
+
[10, "x"],
|
|
8505
|
+
[9, "ix"],
|
|
8506
|
+
[5, "v"],
|
|
8507
|
+
[4, "iv"],
|
|
8508
|
+
[1, "i"]
|
|
8509
|
+
];
|
|
8510
|
+
function toRoman(value) {
|
|
8511
|
+
let remaining = value;
|
|
8512
|
+
let out = "";
|
|
8513
|
+
for (const [amount, glyph] of ROMAN_NUMERALS) {
|
|
8514
|
+
while (remaining >= amount) {
|
|
8515
|
+
out += glyph;
|
|
8516
|
+
remaining -= amount;
|
|
8517
|
+
}
|
|
8518
|
+
}
|
|
8519
|
+
return out;
|
|
8520
|
+
}
|
|
8521
|
+
function toLetters(value) {
|
|
8522
|
+
const index = (value - 1) % 26;
|
|
8523
|
+
const repeats = Math.floor((value - 1) / 26) + 1;
|
|
8524
|
+
return String.fromCharCode(97 + index).repeat(repeats);
|
|
8525
|
+
}
|
|
8526
|
+
function formatNumberForLevel(value, format2) {
|
|
8527
|
+
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
8528
|
+
const n = Math.floor(value);
|
|
8529
|
+
switch (format2) {
|
|
8530
|
+
case "decimal":
|
|
8531
|
+
return String(n);
|
|
8532
|
+
case "lowerLetter":
|
|
8533
|
+
return toLetters(n);
|
|
8534
|
+
case "upperLetter":
|
|
8535
|
+
return toLetters(n).toUpperCase();
|
|
8536
|
+
case "lowerRoman":
|
|
8537
|
+
return toRoman(n);
|
|
8538
|
+
case "upperRoman":
|
|
8539
|
+
return toRoman(n).toUpperCase();
|
|
8540
|
+
default:
|
|
8541
|
+
return void 0;
|
|
8542
|
+
}
|
|
8543
|
+
}
|
|
8544
|
+
|
|
8545
|
+
// src/core/collectTocHeadings.ts
|
|
8546
|
+
var MAX_HEADING_LEVEL2 = 6;
|
|
8547
|
+
var MAX_LIST_LEVEL = 9;
|
|
8141
8548
|
function normalizeEntryTitle(text) {
|
|
8142
8549
|
return normalizeUnicodeText(text).replace(/(\*\*\*|___)([\s\S]*?)\1/g, "$2").replace(/(\*\*|__)([\s\S]*?)\1/g, "$2").replace(/(\*|_)([\s\S]*?)\1/g, "$2").trim();
|
|
8143
8550
|
}
|
|
@@ -8156,9 +8563,97 @@ function styleEntryKey(props) {
|
|
|
8156
8563
|
}
|
|
8157
8564
|
return themeStyle;
|
|
8158
8565
|
}
|
|
8159
|
-
function
|
|
8566
|
+
function levelStart(levels, level) {
|
|
8567
|
+
return levels[level]?.start ?? 1;
|
|
8568
|
+
}
|
|
8569
|
+
function collectDocumentOutline(sections) {
|
|
8160
8570
|
const entries = [];
|
|
8571
|
+
const numberedItems = /* @__PURE__ */ new Map();
|
|
8161
8572
|
const ordinals = computeSectionOrdinals(sections);
|
|
8573
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
8574
|
+
const headingCounters = new Array(MAX_HEADING_LEVEL2).fill(0);
|
|
8575
|
+
const listCounters = /* @__PURE__ */ new Map();
|
|
8576
|
+
const visitHeading = (component, props, sectionBookmarkId) => {
|
|
8577
|
+
const text = typeof props.text === "string" ? props.text : "";
|
|
8578
|
+
const title = normalizeEntryTitle(text);
|
|
8579
|
+
const level = typeof props.level === "number" ? props.level : 1;
|
|
8580
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL2 ? level : 1;
|
|
8581
|
+
let full;
|
|
8582
|
+
let own;
|
|
8583
|
+
if (props.numbering === true) {
|
|
8584
|
+
headingCounters[styleLevel - 1] += 1;
|
|
8585
|
+
for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL2; deeper++) {
|
|
8586
|
+
headingCounters[deeper] = 0;
|
|
8587
|
+
}
|
|
8588
|
+
full = headingCounters.slice(0, styleLevel).join(".");
|
|
8589
|
+
own = String(headingCounters[styleLevel - 1]);
|
|
8590
|
+
}
|
|
8591
|
+
const explicitId = component.id;
|
|
8592
|
+
const bookmarkId = typeof explicitId === "string" && explicitId ? explicitId : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));
|
|
8593
|
+
takenIds.add(bookmarkId);
|
|
8594
|
+
numberedItems.set(bookmarkId, {
|
|
8595
|
+
kind: "heading",
|
|
8596
|
+
text: title,
|
|
8597
|
+
...full !== void 0 && { full, own }
|
|
8598
|
+
});
|
|
8599
|
+
if (title) {
|
|
8600
|
+
entries.push({
|
|
8601
|
+
title,
|
|
8602
|
+
level,
|
|
8603
|
+
sectionBookmarkId,
|
|
8604
|
+
...full !== void 0 && { number: full }
|
|
8605
|
+
});
|
|
8606
|
+
}
|
|
8607
|
+
};
|
|
8608
|
+
const visitList = (props) => {
|
|
8609
|
+
const items = Array.isArray(props.items) ? props.items : [];
|
|
8610
|
+
if (items.length === 0) return;
|
|
8611
|
+
const reference = typeof props.reference === "string" && props.reference ? props.reference : void 0;
|
|
8612
|
+
const freshState = () => {
|
|
8613
|
+
const levels = resolveListLevels(
|
|
8614
|
+
props
|
|
8615
|
+
);
|
|
8616
|
+
return {
|
|
8617
|
+
levels,
|
|
8618
|
+
counters: Array.from(
|
|
8619
|
+
{ length: MAX_LIST_LEVEL },
|
|
8620
|
+
(_, level) => levelStart(levels, level) - 1
|
|
8621
|
+
)
|
|
8622
|
+
};
|
|
8623
|
+
};
|
|
8624
|
+
let state;
|
|
8625
|
+
if (reference === void 0) {
|
|
8626
|
+
state = freshState();
|
|
8627
|
+
} else {
|
|
8628
|
+
state = listCounters.get(reference) ?? freshState();
|
|
8629
|
+
listCounters.set(reference, state);
|
|
8630
|
+
}
|
|
8631
|
+
for (const item of items) {
|
|
8632
|
+
const isObject = typeof item === "object" && item !== null;
|
|
8633
|
+
const raw = isObject ? item.text : item;
|
|
8634
|
+
const text = typeof raw === "string" ? raw : "";
|
|
8635
|
+
if (!text.trim() && !(isObject && item.revision)) continue;
|
|
8636
|
+
const rawLevel = isObject ? item.level : void 0;
|
|
8637
|
+
const level = typeof rawLevel === "number" && rawLevel >= 0 ? rawLevel : 0;
|
|
8638
|
+
if (level >= MAX_LIST_LEVEL) continue;
|
|
8639
|
+
state.counters[level] += 1;
|
|
8640
|
+
for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {
|
|
8641
|
+
state.counters[deeper] = levelStart(state.levels, deeper) - 1;
|
|
8642
|
+
}
|
|
8643
|
+
const id = isObject ? item.id : void 0;
|
|
8644
|
+
if (typeof id !== "string" || !id) continue;
|
|
8645
|
+
takenIds.add(id);
|
|
8646
|
+
const number = formatNumberForLevel(
|
|
8647
|
+
state.counters[level],
|
|
8648
|
+
state.levels[level]?.format
|
|
8649
|
+
);
|
|
8650
|
+
numberedItems.set(id, {
|
|
8651
|
+
kind: "list-item",
|
|
8652
|
+
text: normalizeUnicodeText(text).trim(),
|
|
8653
|
+
...number !== void 0 && { full: number, own: number }
|
|
8654
|
+
});
|
|
8655
|
+
}
|
|
8656
|
+
};
|
|
8162
8657
|
sections.forEach((section, index) => {
|
|
8163
8658
|
const ordinal = ordinals[index]?.ordinal;
|
|
8164
8659
|
const sectionBookmarkId = ordinal ? globalSectionBookmarkRegistry.forLayoutSection(ordinal).id : void 0;
|
|
@@ -8166,15 +8661,11 @@ function collectTocHeadings(sections) {
|
|
|
8166
8661
|
if (!isEnabled(component)) return;
|
|
8167
8662
|
const props = component.props ?? {};
|
|
8168
8663
|
if (component.name === "heading") {
|
|
8169
|
-
|
|
8170
|
-
const title = normalizeEntryTitle(text);
|
|
8171
|
-
if (title) {
|
|
8172
|
-
const level = typeof props.level === "number" ? props.level : 1;
|
|
8173
|
-
entries.push({ title, level, sectionBookmarkId });
|
|
8174
|
-
}
|
|
8664
|
+
visitHeading(component, props, sectionBookmarkId);
|
|
8175
8665
|
return;
|
|
8176
8666
|
}
|
|
8177
8667
|
if (component.name === "paragraph") {
|
|
8668
|
+
if (typeof props.id === "string" && props.id) takenIds.add(props.id);
|
|
8178
8669
|
const styleId = styleEntryKey(props);
|
|
8179
8670
|
const text = typeof props.text === "string" ? props.text : "";
|
|
8180
8671
|
const title = normalizeEntryTitle(text);
|
|
@@ -8183,13 +8674,17 @@ function collectTocHeadings(sections) {
|
|
|
8183
8674
|
}
|
|
8184
8675
|
return;
|
|
8185
8676
|
}
|
|
8677
|
+
if (component.name === "list") {
|
|
8678
|
+
visitList(props);
|
|
8679
|
+
return;
|
|
8680
|
+
}
|
|
8186
8681
|
if (!isContainer(component.name)) return;
|
|
8187
8682
|
const children = component.children;
|
|
8188
8683
|
if (Array.isArray(children)) children.forEach(visit);
|
|
8189
8684
|
};
|
|
8190
8685
|
section.components.forEach(visit);
|
|
8191
8686
|
});
|
|
8192
|
-
return entries;
|
|
8687
|
+
return { entries, numberedItems };
|
|
8193
8688
|
}
|
|
8194
8689
|
|
|
8195
8690
|
// src/core/render.ts
|
|
@@ -8224,23 +8719,32 @@ function coreProperties(metadata) {
|
|
|
8224
8719
|
async function renderDocument(structure, layout, options) {
|
|
8225
8720
|
return runWithGenerationDate(
|
|
8226
8721
|
structure.metadata.date,
|
|
8227
|
-
() =>
|
|
8228
|
-
options?.
|
|
8229
|
-
() =>
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8722
|
+
() => runWithWarnings(
|
|
8723
|
+
options?.warnings,
|
|
8724
|
+
() => runWithBaseDir(
|
|
8725
|
+
options?.baseDir,
|
|
8726
|
+
() => globalBookmarkRegistry.runScoped(
|
|
8727
|
+
() => globalRevisionIdRegistry.runScoped(
|
|
8728
|
+
() => globalNumberingRegistry.runScoped(
|
|
8729
|
+
() => globalSectionBookmarkRegistry.runScoped(
|
|
8730
|
+
() => (
|
|
8731
|
+
// Comment ids are a separate OOXML namespace from w:ins/w:del,
|
|
8732
|
+
// but they need the same per-render isolation: outside this nest
|
|
8733
|
+
// concurrent generations would interleave counters and an anchor
|
|
8734
|
+
// would point at another document's comment body.
|
|
8735
|
+
globalCommentRegistry.runScoped(
|
|
8736
|
+
() => (
|
|
8737
|
+
// Footnote ids are document-scoped too: a reference resolved
|
|
8738
|
+
// against another render's counter points at the wrong body.
|
|
8739
|
+
globalNoteRegistry.runScoped(
|
|
8740
|
+
() => (
|
|
8741
|
+
// Cross-reference targets are keyed by bookmark id, which
|
|
8742
|
+
// is only unique within one document.
|
|
8743
|
+
globalNumberedItemsRegistry.runScoped(
|
|
8744
|
+
() => renderDocumentScoped(structure, layout, options)
|
|
8745
|
+
)
|
|
8746
|
+
)
|
|
8747
|
+
)
|
|
8244
8748
|
)
|
|
8245
8749
|
)
|
|
8246
8750
|
)
|
|
@@ -8282,13 +8786,14 @@ async function renderDocumentScoped(structure, layout, options) {
|
|
|
8282
8786
|
);
|
|
8283
8787
|
}
|
|
8284
8788
|
try {
|
|
8285
|
-
const
|
|
8286
|
-
if (
|
|
8287
|
-
context.tocHeadings =
|
|
8789
|
+
const outline = collectDocumentOutline(layout.sections);
|
|
8790
|
+
if (outline.entries.length > 0) {
|
|
8791
|
+
context.tocHeadings = outline.entries;
|
|
8288
8792
|
}
|
|
8793
|
+
globalNumberedItemsRegistry.seed(outline.numberedItems);
|
|
8289
8794
|
} catch (error) {
|
|
8290
8795
|
console.warn(
|
|
8291
|
-
"[core-docx]
|
|
8796
|
+
"[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it:",
|
|
8292
8797
|
error instanceof Error ? error.message : error
|
|
8293
8798
|
);
|
|
8294
8799
|
}
|
|
@@ -8460,7 +8965,7 @@ async function renderHeaderFooterComponents(components, theme, themeName, contex
|
|
|
8460
8965
|
themeName
|
|
8461
8966
|
);
|
|
8462
8967
|
const imageType = detectImageType(imageSource, responseContentType);
|
|
8463
|
-
const imageRun = createTypedImageRun({
|
|
8968
|
+
const imageRun = await createTypedImageRun({
|
|
8464
8969
|
type: imageType,
|
|
8465
8970
|
data: imageBuffer,
|
|
8466
8971
|
transformation: {
|
|
@@ -9098,6 +9603,7 @@ function createBuilderImpl(state) {
|
|
|
9098
9603
|
services: state.services,
|
|
9099
9604
|
bypassCache: !state.enableCache,
|
|
9100
9605
|
baseDir: options?.baseDir ?? state.baseDir,
|
|
9606
|
+
warnings,
|
|
9101
9607
|
...visualFonts.length > 0 && { visualFonts }
|
|
9102
9608
|
});
|
|
9103
9609
|
const preservedDefinition = preserveSet ? {
|