@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
package/dist/index.js
CHANGED
|
@@ -383,9 +383,6 @@ var init_minimal_docx_theme = __esm({
|
|
|
383
383
|
},
|
|
384
384
|
section: {
|
|
385
385
|
pageBreak: false
|
|
386
|
-
},
|
|
387
|
-
heading: {
|
|
388
|
-
numbering: false
|
|
389
386
|
}
|
|
390
387
|
}
|
|
391
388
|
};
|
|
@@ -508,9 +505,6 @@ var init_corporate_docx_theme = __esm({
|
|
|
508
505
|
},
|
|
509
506
|
section: {
|
|
510
507
|
pageBreak: false
|
|
511
|
-
},
|
|
512
|
-
heading: {
|
|
513
|
-
numbering: false
|
|
514
508
|
}
|
|
515
509
|
}
|
|
516
510
|
};
|
|
@@ -753,9 +747,6 @@ var init_apex_docx_theme = __esm({
|
|
|
753
747
|
},
|
|
754
748
|
section: {
|
|
755
749
|
pageBreak: false
|
|
756
|
-
},
|
|
757
|
-
heading: {
|
|
758
|
-
numbering: false
|
|
759
750
|
}
|
|
760
751
|
}
|
|
761
752
|
};
|
|
@@ -889,9 +880,6 @@ var init_devportal_docx_theme = __esm({
|
|
|
889
880
|
},
|
|
890
881
|
section: {
|
|
891
882
|
pageBreak: false
|
|
892
|
-
},
|
|
893
|
-
heading: {
|
|
894
|
-
numbering: false
|
|
895
883
|
}
|
|
896
884
|
}
|
|
897
885
|
};
|
|
@@ -2665,10 +2653,68 @@ function resolveFromBaseDir(filePath) {
|
|
|
2665
2653
|
if (!base || isAbsolute(filePath)) return filePath;
|
|
2666
2654
|
return resolve(base, filePath);
|
|
2667
2655
|
}
|
|
2656
|
+
var warningsStorage = new AsyncLocalStorage();
|
|
2657
|
+
function runWithWarnings(warnings, callback) {
|
|
2658
|
+
return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
|
|
2659
|
+
}
|
|
2660
|
+
function reportWarning(component, code, message, context) {
|
|
2661
|
+
const warnings = warningsStorage.getStore();
|
|
2662
|
+
if (warnings) {
|
|
2663
|
+
warnings.push({
|
|
2664
|
+
component,
|
|
2665
|
+
message,
|
|
2666
|
+
severity: "warning",
|
|
2667
|
+
context: { code, ...context }
|
|
2668
|
+
});
|
|
2669
|
+
return;
|
|
2670
|
+
}
|
|
2671
|
+
console.warn(`[json-to-docx] [${code}] ${message}`);
|
|
2672
|
+
}
|
|
2668
2673
|
|
|
2669
2674
|
// src/utils/imageUtils.ts
|
|
2670
2675
|
init_widthUtils();
|
|
2671
2676
|
import { ImageRun } from "docx";
|
|
2677
|
+
var SVG_RASTER_SCALE = 3;
|
|
2678
|
+
var SVG_MAX_EDGE_PX = 4096;
|
|
2679
|
+
var SVG_MIN_EDGE_PX = 16;
|
|
2680
|
+
var resvgModule;
|
|
2681
|
+
function loadResvg() {
|
|
2682
|
+
resvgModule ??= import("@resvg/resvg-js");
|
|
2683
|
+
return resvgModule;
|
|
2684
|
+
}
|
|
2685
|
+
function toRasterPx(px) {
|
|
2686
|
+
return Math.min(
|
|
2687
|
+
SVG_MAX_EDGE_PX,
|
|
2688
|
+
Math.max(SVG_MIN_EDGE_PX, Math.round(px * SVG_RASTER_SCALE))
|
|
2689
|
+
);
|
|
2690
|
+
}
|
|
2691
|
+
async function rasterizeSvgFallback(svg, transformation) {
|
|
2692
|
+
let Resvg;
|
|
2693
|
+
try {
|
|
2694
|
+
({ Resvg } = await loadResvg());
|
|
2695
|
+
} catch (error) {
|
|
2696
|
+
reportWarning(
|
|
2697
|
+
"image",
|
|
2698
|
+
"IMAGE_SVG_RASTER_FAILED",
|
|
2699
|
+
`Could not load the SVG rasterizer, so inline SVG keeps a fallback that only Word 2016+ can draw: ${String(error)}`
|
|
2700
|
+
);
|
|
2701
|
+
return void 0;
|
|
2702
|
+
}
|
|
2703
|
+
try {
|
|
2704
|
+
const markup = svg.toString("utf-8");
|
|
2705
|
+
const probeImage = new Resvg(markup);
|
|
2706
|
+
const wide = probeImage.width / probeImage.height > transformation.width / transformation.height;
|
|
2707
|
+
const fitTo = wide ? { mode: "height", value: toRasterPx(transformation.height) } : { mode: "width", value: toRasterPx(transformation.width) };
|
|
2708
|
+
return Buffer.from(new Resvg(markup, { fitTo }).render().asPng());
|
|
2709
|
+
} catch (error) {
|
|
2710
|
+
reportWarning(
|
|
2711
|
+
"image",
|
|
2712
|
+
"IMAGE_SVG_RASTER_FAILED",
|
|
2713
|
+
`Could not rasterize inline SVG, so its fallback only renders in Word 2016+: ${String(error)}`
|
|
2714
|
+
);
|
|
2715
|
+
return void 0;
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2672
2718
|
function parseWidthValue(width, availableWidthPx) {
|
|
2673
2719
|
if (typeof width === "number") {
|
|
2674
2720
|
return width;
|
|
@@ -2778,17 +2824,18 @@ function detectImageType(imagePath, responseContentType) {
|
|
|
2778
2824
|
if (typeFromExtension) return typeFromExtension;
|
|
2779
2825
|
return "png";
|
|
2780
2826
|
}
|
|
2781
|
-
function createTypedImageRun(opts) {
|
|
2827
|
+
async function createTypedImageRun(opts) {
|
|
2782
2828
|
const base = {
|
|
2783
2829
|
data: opts.data,
|
|
2784
2830
|
transformation: opts.transformation,
|
|
2785
2831
|
...opts.floating && { floating: opts.floating }
|
|
2786
2832
|
};
|
|
2787
2833
|
if (opts.type === "svg") {
|
|
2834
|
+
const raster = await rasterizeSvgFallback(opts.data, opts.transformation);
|
|
2788
2835
|
return new ImageRun({
|
|
2789
2836
|
type: "svg",
|
|
2790
2837
|
...base,
|
|
2791
|
-
fallback: { type: "png", data: opts.data }
|
|
2838
|
+
fallback: { type: "png", data: raster ?? opts.data }
|
|
2792
2839
|
});
|
|
2793
2840
|
}
|
|
2794
2841
|
return new ImageRun({ type: opts.type, ...base });
|
|
@@ -3693,8 +3740,51 @@ import {
|
|
|
3693
3740
|
InternalHyperlink,
|
|
3694
3741
|
FootnoteReferenceRun,
|
|
3695
3742
|
EndnoteReferenceRun,
|
|
3743
|
+
NumberedItemReference,
|
|
3744
|
+
NumberedItemReferenceFormat,
|
|
3696
3745
|
Tab
|
|
3697
3746
|
} from "docx";
|
|
3747
|
+
|
|
3748
|
+
// src/utils/numberedItemsRegistry.ts
|
|
3749
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
3750
|
+
var NumberedItemsRegistry = class {
|
|
3751
|
+
fallback = {
|
|
3752
|
+
items: /* @__PURE__ */ new Map(),
|
|
3753
|
+
seeded: false
|
|
3754
|
+
};
|
|
3755
|
+
scopes = new AsyncLocalStorage2();
|
|
3756
|
+
get state() {
|
|
3757
|
+
return this.scopes.getStore() ?? this.fallback;
|
|
3758
|
+
}
|
|
3759
|
+
/** Run work with an isolated registry that follows its async call chain. */
|
|
3760
|
+
runScoped(callback) {
|
|
3761
|
+
return this.scopes.run({ items: /* @__PURE__ */ new Map(), seeded: false }, callback);
|
|
3762
|
+
}
|
|
3763
|
+
/** Replace the contents with the pre-pass result. */
|
|
3764
|
+
seed(items) {
|
|
3765
|
+
const state = this.state;
|
|
3766
|
+
state.items = new Map(items);
|
|
3767
|
+
state.seeded = true;
|
|
3768
|
+
}
|
|
3769
|
+
/**
|
|
3770
|
+
* False outside a render (a unit test calling `createText` directly). An
|
|
3771
|
+
* unresolved reference is then expected rather than an authoring mistake, so
|
|
3772
|
+
* the caller stays quiet about it.
|
|
3773
|
+
*/
|
|
3774
|
+
isSeeded() {
|
|
3775
|
+
return this.state.seeded;
|
|
3776
|
+
}
|
|
3777
|
+
get(id) {
|
|
3778
|
+
return this.state.items.get(id);
|
|
3779
|
+
}
|
|
3780
|
+
clear() {
|
|
3781
|
+
this.state.items.clear();
|
|
3782
|
+
this.state.seeded = false;
|
|
3783
|
+
}
|
|
3784
|
+
};
|
|
3785
|
+
var globalNumberedItemsRegistry = new NumberedItemsRegistry();
|
|
3786
|
+
|
|
3787
|
+
// src/utils/textParser.ts
|
|
3698
3788
|
var FOOTNOTE_MARKER_REGEX = /\[\^([^\]\s]+)\]/;
|
|
3699
3789
|
function escapeRegExp(s) {
|
|
3700
3790
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3910,13 +4000,59 @@ function splitNoteMarkers(text, noteRef, runs) {
|
|
|
3910
4000
|
if (trailing) out.push(...runs(trailing));
|
|
3911
4001
|
return out;
|
|
3912
4002
|
}
|
|
4003
|
+
var CROSS_REFERENCE_PATTERN = "\\[@([^\\]\\s:]+)(?::(relative|no_context|full_context|none))?\\]";
|
|
4004
|
+
var INLINE_TOKEN_REGEX = `\\[([^\\]]+)\\]\\(([^)]+)\\)|${CROSS_REFERENCE_PATTERN}`;
|
|
4005
|
+
function hasCrossReference(text) {
|
|
4006
|
+
return new RegExp(CROSS_REFERENCE_PATTERN).test(text);
|
|
4007
|
+
}
|
|
4008
|
+
var REFERENCE_FORMATS = {
|
|
4009
|
+
relative: NumberedItemReferenceFormat.RELATIVE,
|
|
4010
|
+
no_context: NumberedItemReferenceFormat.NO_CONTEXT,
|
|
4011
|
+
full_context: NumberedItemReferenceFormat.FULL_CONTEXT,
|
|
4012
|
+
none: NumberedItemReferenceFormat.NONE
|
|
4013
|
+
};
|
|
4014
|
+
function createCrossReference(id, format2, token, baseStyle, options) {
|
|
4015
|
+
const info = globalNumberedItemsRegistry.get(id);
|
|
4016
|
+
if (!info) {
|
|
4017
|
+
if (globalNumberedItemsRegistry.isSeeded()) {
|
|
4018
|
+
console.warn(
|
|
4019
|
+
`[core-docx] Cross-reference ${token} has no target: no heading or list item declares the id "${id}". Rendering the token as literal text.`
|
|
4020
|
+
);
|
|
4021
|
+
}
|
|
4022
|
+
return buildTextRuns(
|
|
4023
|
+
token,
|
|
4024
|
+
buildRunCommonProps(baseStyle, { boldColor: options.boldColor }),
|
|
4025
|
+
{ noProof: baseStyle.noProof, noProofWords: options.noProofWords }
|
|
4026
|
+
);
|
|
4027
|
+
}
|
|
4028
|
+
if (format2 === "none") {
|
|
4029
|
+
return [
|
|
4030
|
+
new NumberedItemReference(id, info.text, {
|
|
4031
|
+
hyperlink: true,
|
|
4032
|
+
referenceFormat: REFERENCE_FORMATS.none
|
|
4033
|
+
})
|
|
4034
|
+
];
|
|
4035
|
+
}
|
|
4036
|
+
const cachedValue = format2 === "no_context" ? info.own : info.full;
|
|
4037
|
+
if (cachedValue === void 0) {
|
|
4038
|
+
console.warn(
|
|
4039
|
+
`[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.`
|
|
4040
|
+
);
|
|
4041
|
+
}
|
|
4042
|
+
return [
|
|
4043
|
+
new NumberedItemReference(id, cachedValue, {
|
|
4044
|
+
hyperlink: true,
|
|
4045
|
+
referenceFormat: REFERENCE_FORMATS[format2]
|
|
4046
|
+
})
|
|
4047
|
+
];
|
|
4048
|
+
}
|
|
3913
4049
|
function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
3914
4050
|
const normalizedText = normalizeUnicodeText(text);
|
|
3915
4051
|
const runs = [];
|
|
3916
|
-
const
|
|
4052
|
+
const tokenRegex = new RegExp(INLINE_TOKEN_REGEX, "g");
|
|
3917
4053
|
let lastIndex = 0;
|
|
3918
4054
|
let match;
|
|
3919
|
-
while ((match =
|
|
4055
|
+
while ((match = tokenRegex.exec(normalizedText)) !== null) {
|
|
3920
4056
|
if (match.index > lastIndex) {
|
|
3921
4057
|
const plainText = normalizedText.substring(lastIndex, match.index);
|
|
3922
4058
|
if (plainText) {
|
|
@@ -3928,6 +4064,19 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
3928
4064
|
runs.push(...plainRuns);
|
|
3929
4065
|
}
|
|
3930
4066
|
}
|
|
4067
|
+
lastIndex = match.index + match[0].length;
|
|
4068
|
+
if (match[1] === void 0) {
|
|
4069
|
+
runs.push(
|
|
4070
|
+
...createCrossReference(
|
|
4071
|
+
match[3],
|
|
4072
|
+
match[4] ?? "relative",
|
|
4073
|
+
match[0],
|
|
4074
|
+
baseStyle,
|
|
4075
|
+
options
|
|
4076
|
+
)
|
|
4077
|
+
);
|
|
4078
|
+
continue;
|
|
4079
|
+
}
|
|
3931
4080
|
const linkText = match[1];
|
|
3932
4081
|
const linkUrl = match[2];
|
|
3933
4082
|
const isInternal = linkUrl.startsWith("#");
|
|
@@ -3954,7 +4103,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
3954
4103
|
})
|
|
3955
4104
|
);
|
|
3956
4105
|
}
|
|
3957
|
-
lastIndex = match.index + match[0].length;
|
|
3958
4106
|
}
|
|
3959
4107
|
if (lastIndex < normalizedText.length) {
|
|
3960
4108
|
const remainingText = normalizedText.substring(lastIndex);
|
|
@@ -4163,7 +4311,7 @@ function initializeBuiltinPlaceholders() {
|
|
|
4163
4311
|
initializeBuiltinPlaceholders();
|
|
4164
4312
|
|
|
4165
4313
|
// src/utils/revisionUtils.ts
|
|
4166
|
-
import { AsyncLocalStorage as
|
|
4314
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
4167
4315
|
|
|
4168
4316
|
// src/utils/componentAnnotations.ts
|
|
4169
4317
|
function isRecord(value) {
|
|
@@ -4214,7 +4362,7 @@ var DEFAULT_REVISION_AUTHOR = "json-to-office";
|
|
|
4214
4362
|
var DEFAULT_REVISION_DATE = "1970-01-01T00:00:00Z";
|
|
4215
4363
|
var RevisionIdRegistry = class {
|
|
4216
4364
|
fallbackCounter = 0;
|
|
4217
|
-
scopes = new
|
|
4365
|
+
scopes = new AsyncLocalStorage3();
|
|
4218
4366
|
runScoped(callback) {
|
|
4219
4367
|
return this.scopes.run({ counter: 0 }, callback);
|
|
4220
4368
|
}
|
|
@@ -4496,10 +4644,21 @@ init_styles();
|
|
|
4496
4644
|
init_defaults();
|
|
4497
4645
|
|
|
4498
4646
|
// src/utils/bookmarkRegistry.ts
|
|
4499
|
-
import { AsyncLocalStorage as
|
|
4647
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
4648
|
+
function slugifyBookmarkText(text) {
|
|
4649
|
+
return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 40);
|
|
4650
|
+
}
|
|
4651
|
+
function dedupeBookmarkId(base, taken) {
|
|
4652
|
+
let id = base;
|
|
4653
|
+
let attempt = 0;
|
|
4654
|
+
while (taken(id) && attempt < 100) {
|
|
4655
|
+
id = `${base}-${++attempt}`;
|
|
4656
|
+
}
|
|
4657
|
+
return id;
|
|
4658
|
+
}
|
|
4500
4659
|
var BookmarkRegistry = class {
|
|
4501
4660
|
fallback = { bookmarks: /* @__PURE__ */ new Map() };
|
|
4502
|
-
scopes = new
|
|
4661
|
+
scopes = new AsyncLocalStorage4();
|
|
4503
4662
|
get state() {
|
|
4504
4663
|
return this.scopes.getStore() ?? this.fallback;
|
|
4505
4664
|
}
|
|
@@ -4523,13 +4682,10 @@ var BookmarkRegistry = class {
|
|
|
4523
4682
|
* Converts text to a URL-friendly format
|
|
4524
4683
|
*/
|
|
4525
4684
|
generateId(text, _type = "bookmark") {
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
id = `${baseId}-${++attempt}`;
|
|
4531
|
-
}
|
|
4532
|
-
return id;
|
|
4685
|
+
return dedupeBookmarkId(
|
|
4686
|
+
slugifyBookmarkText(text),
|
|
4687
|
+
(id) => this.state.bookmarks.has(id)
|
|
4688
|
+
);
|
|
4533
4689
|
}
|
|
4534
4690
|
/**
|
|
4535
4691
|
* Check if a bookmark exists
|
|
@@ -4581,7 +4737,7 @@ import {
|
|
|
4581
4737
|
|
|
4582
4738
|
// src/utils/commentRegistry.ts
|
|
4583
4739
|
import { Paragraph, TextRun as TextRun4 } from "docx";
|
|
4584
|
-
import { AsyncLocalStorage as
|
|
4740
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
|
|
4585
4741
|
var DEFAULT_COMMENT_AUTHOR = "json-to-office";
|
|
4586
4742
|
var DEFAULT_COMMENT_DATE = "1970-01-01T00:00:00Z";
|
|
4587
4743
|
function createState() {
|
|
@@ -4596,7 +4752,7 @@ function bodyParagraphs(text) {
|
|
|
4596
4752
|
}
|
|
4597
4753
|
var CommentRegistry = class {
|
|
4598
4754
|
fallback = createState();
|
|
4599
|
-
scopes = new
|
|
4755
|
+
scopes = new AsyncLocalStorage5();
|
|
4600
4756
|
get state() {
|
|
4601
4757
|
return this.scopes.getStore() ?? this.fallback;
|
|
4602
4758
|
}
|
|
@@ -4691,7 +4847,7 @@ function closeCommentRange(ids) {
|
|
|
4691
4847
|
|
|
4692
4848
|
// src/utils/noteRegistry.ts
|
|
4693
4849
|
import { Paragraph as Paragraph2, TextRun as TextRun6 } from "docx";
|
|
4694
|
-
import { AsyncLocalStorage as
|
|
4850
|
+
import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
|
|
4695
4851
|
function createState2() {
|
|
4696
4852
|
return {
|
|
4697
4853
|
footnoteCounter: 0,
|
|
@@ -4710,7 +4866,7 @@ function bodyParagraphs2(text, style) {
|
|
|
4710
4866
|
}
|
|
4711
4867
|
var NoteRegistry = class {
|
|
4712
4868
|
fallback = createState2();
|
|
4713
|
-
scopes = new
|
|
4869
|
+
scopes = new AsyncLocalStorage6();
|
|
4714
4870
|
get state() {
|
|
4715
4871
|
return this.scopes.getStore() ?? this.fallback;
|
|
4716
4872
|
}
|
|
@@ -5066,7 +5222,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5066
5222
|
if (commentAnchor) {
|
|
5067
5223
|
children.push(...commentAnchor.start);
|
|
5068
5224
|
}
|
|
5069
|
-
const
|
|
5225
|
+
const hasInlineSyntax = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText) || hasCrossReference(normalizedText);
|
|
5070
5226
|
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
5071
5227
|
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
5072
5228
|
const headingWeighted = applyFontWeightAlias({
|
|
@@ -5133,7 +5289,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5133
5289
|
"heading"
|
|
5134
5290
|
);
|
|
5135
5291
|
const headingTextChildren = [];
|
|
5136
|
-
if (
|
|
5292
|
+
if (hasInlineSyntax) {
|
|
5137
5293
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
5138
5294
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
5139
5295
|
enableHyperlinks: true,
|
|
@@ -5150,7 +5306,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5150
5306
|
})
|
|
5151
5307
|
);
|
|
5152
5308
|
} else {
|
|
5153
|
-
if (
|
|
5309
|
+
if (hasInlineSyntax) {
|
|
5154
5310
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
5155
5311
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
5156
5312
|
enableHyperlinks: true,
|
|
@@ -5172,7 +5328,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5172
5328
|
spacing: hasExplicitSpacing ? spacing : void 0,
|
|
5173
5329
|
...options.keepNext !== void 0 && { keepNext: options.keepNext },
|
|
5174
5330
|
...options.keepLines !== void 0 && { keepLines: options.keepLines },
|
|
5175
|
-
...options.indent && { indent: options.indent }
|
|
5331
|
+
...options.indent && { indent: options.indent },
|
|
5332
|
+
// docx creates the concrete numbering instance for the reference itself,
|
|
5333
|
+
// in ParagraphProperties.prepForXml.
|
|
5334
|
+
...options.numbering !== void 0 && { numbering: options.numbering }
|
|
5176
5335
|
});
|
|
5177
5336
|
}
|
|
5178
5337
|
async function createImage(path4, theme, themeName, options = {}) {
|
|
@@ -5217,7 +5376,7 @@ async function createImage(path4, theme, themeName, options = {}) {
|
|
|
5217
5376
|
const { mapFloatingOptions: mapFloatingOptions2 } = await Promise.resolve().then(() => (init_docxImagePositioning(), docxImagePositioning_exports));
|
|
5218
5377
|
const floating = isFloating ? mapFloatingOptions2(options.floating, theme, themeName) : void 0;
|
|
5219
5378
|
const imageType = detectImageType(imagePath, responseContentType);
|
|
5220
|
-
const imageRun = createTypedImageRun({
|
|
5379
|
+
const imageRun = await createTypedImageRun({
|
|
5221
5380
|
type: imageType,
|
|
5222
5381
|
data: imageBuffer,
|
|
5223
5382
|
transformation: { width: dimensions.width, height: dimensions.height },
|
|
@@ -5332,9 +5491,17 @@ function createList(items, _theme, _themeName, options = {}) {
|
|
|
5332
5491
|
} else if (options.spacing?.item) {
|
|
5333
5492
|
spacing.after = pointsToTwips(options.spacing.item);
|
|
5334
5493
|
}
|
|
5494
|
+
const itemId = typeof item === "object" ? item.id : void 0;
|
|
5495
|
+
let itemContent = textRuns;
|
|
5496
|
+
if (itemId) {
|
|
5497
|
+
globalBookmarkRegistry.register(itemId, itemText, "list-item");
|
|
5498
|
+
itemContent = [
|
|
5499
|
+
new Bookmark({ id: itemId, children: textRuns })
|
|
5500
|
+
];
|
|
5501
|
+
}
|
|
5335
5502
|
const paragraphChildren = [
|
|
5336
5503
|
...commentAnchor && index === firstRendered ? commentAnchor.start : [],
|
|
5337
|
-
...
|
|
5504
|
+
...itemContent,
|
|
5338
5505
|
...commentAnchor && index === lastRendered ? closeCommentRange(commentAnchor.ids) : []
|
|
5339
5506
|
];
|
|
5340
5507
|
const paragraph = new Paragraph3({
|
|
@@ -5762,7 +5929,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5762
5929
|
// fallback height
|
|
5763
5930
|
);
|
|
5764
5931
|
const imgType = detectImageType(imageSource, imageResult.contentType);
|
|
5765
|
-
const imageRun = createTypedImageRun({
|
|
5932
|
+
const imageRun = await createTypedImageRun({
|
|
5766
5933
|
type: imgType,
|
|
5767
5934
|
data: imageResult.buffer,
|
|
5768
5935
|
transformation: {
|
|
@@ -6177,54 +6344,14 @@ function createFooterElement(children, _options) {
|
|
|
6177
6344
|
});
|
|
6178
6345
|
}
|
|
6179
6346
|
|
|
6180
|
-
// src/components/heading.ts
|
|
6181
|
-
function renderHeadingComponent(component, theme, themeName) {
|
|
6182
|
-
if (!isHeadingComponent(component)) return [];
|
|
6183
|
-
const config = component.props;
|
|
6184
|
-
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6185
|
-
const header = createHeading(
|
|
6186
|
-
config.text,
|
|
6187
|
-
config.level || 1,
|
|
6188
|
-
theme,
|
|
6189
|
-
themeName,
|
|
6190
|
-
{
|
|
6191
|
-
alignment: config.alignment,
|
|
6192
|
-
spacing: config.spacing,
|
|
6193
|
-
lineSpacing: config.lineSpacing,
|
|
6194
|
-
columnBreak: config.columnBreak,
|
|
6195
|
-
// Local font overrides
|
|
6196
|
-
fontFamily: config.font?.family,
|
|
6197
|
-
fontSize: config.font?.size,
|
|
6198
|
-
fontColor: config.font?.color,
|
|
6199
|
-
bold: config.font?.bold,
|
|
6200
|
-
fontWeight: config.font?.fontWeight,
|
|
6201
|
-
italic: config.font?.italic,
|
|
6202
|
-
underline: config.font?.underline,
|
|
6203
|
-
scale: config.font?.scale,
|
|
6204
|
-
characterSpacing: config.font?.characterSpacing,
|
|
6205
|
-
// Proofing: local language override + no-proof toggle + known-words list
|
|
6206
|
-
language: config.language,
|
|
6207
|
-
noProof: config.noProof,
|
|
6208
|
-
noProofWords: config.noProofWords,
|
|
6209
|
-
// Pagination control
|
|
6210
|
-
keepNext: config.keepNext,
|
|
6211
|
-
keepLines: config.keepLines,
|
|
6212
|
-
// Paragraph indentation (w:ind) in twips
|
|
6213
|
-
indent: config.indent,
|
|
6214
|
-
// Bookmark ID for internal linking
|
|
6215
|
-
bookmarkId,
|
|
6216
|
-
// Tracked-change segments (rendered as native Word revisions)
|
|
6217
|
-
revision: config.revision,
|
|
6218
|
-
// Review comment anchored to this heading's text
|
|
6219
|
-
comment: config.comment
|
|
6220
|
-
}
|
|
6221
|
-
);
|
|
6222
|
-
return [header];
|
|
6223
|
-
}
|
|
6224
|
-
|
|
6225
6347
|
// src/utils/numberingConfig.ts
|
|
6226
|
-
import {
|
|
6227
|
-
|
|
6348
|
+
import {
|
|
6349
|
+
AlignmentType as AlignmentType3,
|
|
6350
|
+
convertInchesToTwip,
|
|
6351
|
+
LevelFormat,
|
|
6352
|
+
LevelSuffix
|
|
6353
|
+
} from "docx";
|
|
6354
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "async_hooks";
|
|
6228
6355
|
var LEVEL_FORMAT_MAP = {
|
|
6229
6356
|
decimal: LevelFormat.DECIMAL,
|
|
6230
6357
|
upperRoman: LevelFormat.UPPER_ROMAN,
|
|
@@ -6352,12 +6479,37 @@ function createNumberingConfig(config) {
|
|
|
6352
6479
|
levels
|
|
6353
6480
|
};
|
|
6354
6481
|
}
|
|
6482
|
+
var HEADING_NUMBERING_REFERENCE = "jto-heading-numbering";
|
|
6483
|
+
function createHeadingNumberingConfig() {
|
|
6484
|
+
const levels = [];
|
|
6485
|
+
for (let level = 0; level < 6; level++) {
|
|
6486
|
+
const text = Array.from({ length: level + 1 }, (_, i) => `%${i + 1}`).join(".") + ".";
|
|
6487
|
+
levels.push({
|
|
6488
|
+
level,
|
|
6489
|
+
format: LevelFormat.DECIMAL,
|
|
6490
|
+
text,
|
|
6491
|
+
alignment: AlignmentType3.LEFT,
|
|
6492
|
+
start: 1,
|
|
6493
|
+
// A space, not the default tab: a tab would push the heading text to the
|
|
6494
|
+
// next tab stop and misalign it against unnumbered headings.
|
|
6495
|
+
suffix: LevelSuffix.SPACE,
|
|
6496
|
+
style: {
|
|
6497
|
+
paragraph: { indent: { left: 0, hanging: 0 } },
|
|
6498
|
+
style: `Heading${level + 1}`
|
|
6499
|
+
}
|
|
6500
|
+
});
|
|
6501
|
+
}
|
|
6502
|
+
return { reference: HEADING_NUMBERING_REFERENCE, levels };
|
|
6503
|
+
}
|
|
6504
|
+
function headingNumberLabel(number) {
|
|
6505
|
+
return `${number}.`;
|
|
6506
|
+
}
|
|
6355
6507
|
var NumberingRegistry = class {
|
|
6356
6508
|
fallback = {
|
|
6357
6509
|
configs: /* @__PURE__ */ new Map(),
|
|
6358
6510
|
counter: 0
|
|
6359
6511
|
};
|
|
6360
|
-
scopes = new
|
|
6512
|
+
scopes = new AsyncLocalStorage7();
|
|
6361
6513
|
get state() {
|
|
6362
6514
|
return this.scopes.getStore() ?? this.fallback;
|
|
6363
6515
|
}
|
|
@@ -6407,6 +6559,63 @@ var NumberingRegistry = class {
|
|
|
6407
6559
|
};
|
|
6408
6560
|
var globalNumberingRegistry = new NumberingRegistry();
|
|
6409
6561
|
|
|
6562
|
+
// src/components/heading.ts
|
|
6563
|
+
var MAX_HEADING_LEVEL = 6;
|
|
6564
|
+
function headingNumbering(numbering, level) {
|
|
6565
|
+
if (numbering === false) return false;
|
|
6566
|
+
if (numbering !== true) return void 0;
|
|
6567
|
+
if (!globalNumberingRegistry.has(HEADING_NUMBERING_REFERENCE)) {
|
|
6568
|
+
globalNumberingRegistry.register(createHeadingNumberingConfig());
|
|
6569
|
+
}
|
|
6570
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;
|
|
6571
|
+
return { reference: HEADING_NUMBERING_REFERENCE, level: styleLevel - 1 };
|
|
6572
|
+
}
|
|
6573
|
+
function renderHeadingComponent(component, theme, themeName) {
|
|
6574
|
+
if (!isHeadingComponent(component)) return [];
|
|
6575
|
+
const config = component.props;
|
|
6576
|
+
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6577
|
+
const header = createHeading(
|
|
6578
|
+
config.text,
|
|
6579
|
+
config.level || 1,
|
|
6580
|
+
theme,
|
|
6581
|
+
themeName,
|
|
6582
|
+
{
|
|
6583
|
+
alignment: config.alignment,
|
|
6584
|
+
spacing: config.spacing,
|
|
6585
|
+
lineSpacing: config.lineSpacing,
|
|
6586
|
+
columnBreak: config.columnBreak,
|
|
6587
|
+
// Local font overrides
|
|
6588
|
+
fontFamily: config.font?.family,
|
|
6589
|
+
fontSize: config.font?.size,
|
|
6590
|
+
fontColor: config.font?.color,
|
|
6591
|
+
bold: config.font?.bold,
|
|
6592
|
+
fontWeight: config.font?.fontWeight,
|
|
6593
|
+
italic: config.font?.italic,
|
|
6594
|
+
underline: config.font?.underline,
|
|
6595
|
+
scale: config.font?.scale,
|
|
6596
|
+
characterSpacing: config.font?.characterSpacing,
|
|
6597
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
6598
|
+
language: config.language,
|
|
6599
|
+
noProof: config.noProof,
|
|
6600
|
+
noProofWords: config.noProofWords,
|
|
6601
|
+
// Pagination control
|
|
6602
|
+
keepNext: config.keepNext,
|
|
6603
|
+
keepLines: config.keepLines,
|
|
6604
|
+
// Paragraph indentation (w:ind) in twips
|
|
6605
|
+
indent: config.indent,
|
|
6606
|
+
// Bookmark ID for internal linking
|
|
6607
|
+
bookmarkId,
|
|
6608
|
+
// Auto-numbering (1., 1.1., …) through the shared heading definition
|
|
6609
|
+
numbering: headingNumbering(config.numbering, config.level || 1),
|
|
6610
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
6611
|
+
revision: config.revision,
|
|
6612
|
+
// Review comment anchored to this heading's text
|
|
6613
|
+
comment: config.comment
|
|
6614
|
+
}
|
|
6615
|
+
);
|
|
6616
|
+
return [header];
|
|
6617
|
+
}
|
|
6618
|
+
|
|
6410
6619
|
// src/components/paragraph.ts
|
|
6411
6620
|
function parseMarkdownList(text) {
|
|
6412
6621
|
const lines = text.split("\n");
|
|
@@ -6546,8 +6755,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
6546
6755
|
return [text];
|
|
6547
6756
|
}
|
|
6548
6757
|
|
|
6549
|
-
// src/
|
|
6550
|
-
init_colorUtils();
|
|
6758
|
+
// src/utils/listLevels.ts
|
|
6551
6759
|
function createLevelsFromSimplifiedProps(props) {
|
|
6552
6760
|
const levels = [];
|
|
6553
6761
|
let format2;
|
|
@@ -6594,18 +6802,8 @@ function createLevelsFromSimplifiedProps(props) {
|
|
|
6594
6802
|
}
|
|
6595
6803
|
return levels;
|
|
6596
6804
|
}
|
|
6597
|
-
function resolveMarkerFonts(levels, theme) {
|
|
6598
|
-
return levels.map((level) => {
|
|
6599
|
-
const font = level.font;
|
|
6600
|
-
if (!font?.color) return level;
|
|
6601
|
-
return {
|
|
6602
|
-
...level,
|
|
6603
|
-
font: { ...font, color: resolveColor(font.color, theme) }
|
|
6604
|
-
};
|
|
6605
|
-
});
|
|
6606
|
-
}
|
|
6607
6805
|
function applyListStart(levels, start) {
|
|
6608
|
-
if (start === void 0) return levels;
|
|
6806
|
+
if (start === void 0) return [...levels];
|
|
6609
6807
|
return levels.map(
|
|
6610
6808
|
(level) => level.level === 0 && level.start === void 0 ? { ...level, start } : level
|
|
6611
6809
|
);
|
|
@@ -6663,28 +6861,37 @@ function fillMissingLevels(levels, maxLevel) {
|
|
|
6663
6861
|
}
|
|
6664
6862
|
return result;
|
|
6665
6863
|
}
|
|
6864
|
+
function resolveListLevels(props) {
|
|
6865
|
+
const maxLevel = getMaxLevelFromItems(props.items);
|
|
6866
|
+
if (props.levels && props.levels.length > 0) {
|
|
6867
|
+
return fillMissingLevels(
|
|
6868
|
+
applyListStart(props.levels, props.start),
|
|
6869
|
+
maxLevel
|
|
6870
|
+
);
|
|
6871
|
+
}
|
|
6872
|
+
return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);
|
|
6873
|
+
}
|
|
6874
|
+
|
|
6875
|
+
// src/components/list.ts
|
|
6876
|
+
init_colorUtils();
|
|
6877
|
+
function resolveMarkerFonts(levels, theme) {
|
|
6878
|
+
return levels.map((level) => {
|
|
6879
|
+
const font = level.font;
|
|
6880
|
+
if (!font?.color) return level;
|
|
6881
|
+
return {
|
|
6882
|
+
...level,
|
|
6883
|
+
font: { ...font, color: resolveColor(font.color, theme) }
|
|
6884
|
+
};
|
|
6885
|
+
});
|
|
6886
|
+
}
|
|
6666
6887
|
function renderListComponent(component, theme, themeName) {
|
|
6667
6888
|
if (!isListComponent(component)) return [];
|
|
6668
6889
|
const resolvedConfig = component.props;
|
|
6669
|
-
const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
|
|
6670
6890
|
const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
|
|
6671
6891
|
if (!globalNumberingRegistry.has(reference)) {
|
|
6672
|
-
let levels;
|
|
6673
|
-
if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {
|
|
6674
|
-
levels = fillMissingLevels(
|
|
6675
|
-
applyListStart(
|
|
6676
|
-
resolvedConfig.levels,
|
|
6677
|
-
resolvedConfig.start
|
|
6678
|
-
),
|
|
6679
|
-
maxLevel
|
|
6680
|
-
);
|
|
6681
|
-
} else {
|
|
6682
|
-
const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);
|
|
6683
|
-
levels = fillMissingLevels(baseLevels, maxLevel);
|
|
6684
|
-
}
|
|
6685
6892
|
const config = {
|
|
6686
6893
|
reference,
|
|
6687
|
-
levels: resolveMarkerFonts(
|
|
6894
|
+
levels: resolveMarkerFonts(resolveListLevels(resolvedConfig), theme)
|
|
6688
6895
|
};
|
|
6689
6896
|
const numberingConfig = createNumberingConfig(config);
|
|
6690
6897
|
globalNumberingRegistry.register(numberingConfig);
|
|
@@ -6724,6 +6931,7 @@ async function renderImageComponent(component, theme, themeName) {
|
|
|
6724
6931
|
|
|
6725
6932
|
// src/components/text-box.ts
|
|
6726
6933
|
import {
|
|
6934
|
+
Paragraph as Paragraph5,
|
|
6727
6935
|
Table as Table3,
|
|
6728
6936
|
TableRow as TableRow2,
|
|
6729
6937
|
TableCell as TableCell2,
|
|
@@ -6732,7 +6940,8 @@ import {
|
|
|
6732
6940
|
RelativeHorizontalPosition,
|
|
6733
6941
|
RelativeVerticalPosition,
|
|
6734
6942
|
OverlapType,
|
|
6735
|
-
TableLayoutType as TableLayoutType2
|
|
6943
|
+
TableLayoutType as TableLayoutType2,
|
|
6944
|
+
WpsShapeRun
|
|
6736
6945
|
} from "docx";
|
|
6737
6946
|
|
|
6738
6947
|
// src/styles/utils/borderUtils.ts
|
|
@@ -6809,6 +7018,8 @@ function buildCellOptions(children, styleCfg, theme) {
|
|
|
6809
7018
|
}
|
|
6810
7019
|
|
|
6811
7020
|
// src/components/text-box.ts
|
|
7021
|
+
init_colorUtils();
|
|
7022
|
+
init_docxImagePositioning();
|
|
6812
7023
|
init_widthUtils();
|
|
6813
7024
|
function mapTableFloatOptions(floating, theme, themeName) {
|
|
6814
7025
|
if (!floating) return void 0;
|
|
@@ -6864,26 +7075,23 @@ function mapTableFloatOptions(floating, theme, themeName) {
|
|
|
6864
7075
|
opt.overlap = OverlapType.OVERLAP;
|
|
6865
7076
|
return opt;
|
|
6866
7077
|
}
|
|
6867
|
-
async function
|
|
6868
|
-
|
|
6869
|
-
|
|
7078
|
+
async function renderTextBoxChildren(tb, theme, themeName, context) {
|
|
7079
|
+
const childContext = {
|
|
7080
|
+
...context,
|
|
7081
|
+
parent: tb
|
|
7082
|
+
};
|
|
7083
|
+
const rendered = [];
|
|
7084
|
+
for (const child of tb.children || []) {
|
|
7085
|
+
rendered.push(
|
|
7086
|
+
...await renderComponent(child, theme, themeName, childContext)
|
|
7087
|
+
);
|
|
7088
|
+
}
|
|
7089
|
+
return rendered;
|
|
7090
|
+
}
|
|
7091
|
+
async function renderTextBoxAsTable(tb, theme, themeName, _context, prerendered) {
|
|
6870
7092
|
const isInline = !tb.props.floating;
|
|
6871
|
-
const childComponents = tb.children || [];
|
|
6872
7093
|
if (isInline) {
|
|
6873
|
-
const cellChildren2 =
|
|
6874
|
-
const childContext2 = {
|
|
6875
|
-
..._context,
|
|
6876
|
-
parent: tb
|
|
6877
|
-
};
|
|
6878
|
-
for (const child of childComponents) {
|
|
6879
|
-
const rendered = await renderComponent(
|
|
6880
|
-
child,
|
|
6881
|
-
theme,
|
|
6882
|
-
themeName,
|
|
6883
|
-
childContext2
|
|
6884
|
-
);
|
|
6885
|
-
cellChildren2.push(...rendered);
|
|
6886
|
-
}
|
|
7094
|
+
const cellChildren2 = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
6887
7095
|
const styleCfg2 = tb.props.style;
|
|
6888
7096
|
const cellOpts2 = buildCellOptions(cellChildren2, styleCfg2, theme);
|
|
6889
7097
|
const row2 = new TableRow2({ children: [new TableCell2(cellOpts2)] });
|
|
@@ -6896,20 +7104,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
6896
7104
|
});
|
|
6897
7105
|
return [table2];
|
|
6898
7106
|
}
|
|
6899
|
-
const cellChildren =
|
|
6900
|
-
const childContext = {
|
|
6901
|
-
..._context,
|
|
6902
|
-
parent: tb
|
|
6903
|
-
};
|
|
6904
|
-
for (const child of childComponents) {
|
|
6905
|
-
const rendered = await renderComponent(
|
|
6906
|
-
child,
|
|
6907
|
-
theme,
|
|
6908
|
-
themeName,
|
|
6909
|
-
childContext
|
|
6910
|
-
);
|
|
6911
|
-
cellChildren.push(...rendered);
|
|
6912
|
-
}
|
|
7107
|
+
const cellChildren = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
6913
7108
|
const styleCfg = tb.props.style;
|
|
6914
7109
|
const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);
|
|
6915
7110
|
const row = new TableRow2({
|
|
@@ -6941,6 +7136,162 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
6941
7136
|
});
|
|
6942
7137
|
return [table];
|
|
6943
7138
|
}
|
|
7139
|
+
var PIXELS_TO_EMU = 9525;
|
|
7140
|
+
var TWIPS_PER_PIXEL = 15;
|
|
7141
|
+
function resolveShapeSize(value, axis, theme, themeName) {
|
|
7142
|
+
if (typeof value === "number") {
|
|
7143
|
+
return { pixels: Math.round(value), resolvedPercentage: false };
|
|
7144
|
+
}
|
|
7145
|
+
if (typeof value !== "string") return { resolvedPercentage: false };
|
|
7146
|
+
const fraction = parseFloat(value) / 100;
|
|
7147
|
+
if (!Number.isFinite(fraction) || fraction <= 0) {
|
|
7148
|
+
return { resolvedPercentage: false };
|
|
7149
|
+
}
|
|
7150
|
+
const availableTwips = axis === "width" ? getAvailableWidthTwips(theme, themeName) : getAvailableHeightTwips(theme, themeName);
|
|
7151
|
+
return {
|
|
7152
|
+
pixels: Math.round(availableTwips * fraction / TWIPS_PER_PIXEL),
|
|
7153
|
+
resolvedPercentage: true
|
|
7154
|
+
};
|
|
7155
|
+
}
|
|
7156
|
+
function shapeColor(value, theme) {
|
|
7157
|
+
return resolveColor(value, theme).replace(/^#/, "");
|
|
7158
|
+
}
|
|
7159
|
+
function shapeOutline(style, theme) {
|
|
7160
|
+
const border = style?.border;
|
|
7161
|
+
if (!border) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7162
|
+
const order = [
|
|
7163
|
+
"top",
|
|
7164
|
+
"left",
|
|
7165
|
+
"bottom",
|
|
7166
|
+
"right"
|
|
7167
|
+
];
|
|
7168
|
+
const declared = order.map((side) => [side, border[side]]).filter(
|
|
7169
|
+
(entry) => Boolean(entry[1])
|
|
7170
|
+
);
|
|
7171
|
+
if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7172
|
+
const unsupportedStyles = [
|
|
7173
|
+
...new Set(
|
|
7174
|
+
declared.map(([, config]) => config.style).filter(
|
|
7175
|
+
(value) => value === "dashed" || value === "dotted" || value === "double"
|
|
7176
|
+
)
|
|
7177
|
+
)
|
|
7178
|
+
];
|
|
7179
|
+
if (unsupportedStyles.length > 0) {
|
|
7180
|
+
return { ignoredSides: [], unsupportedStyles };
|
|
7181
|
+
}
|
|
7182
|
+
const [, used] = declared[0];
|
|
7183
|
+
const differs = ({ style: s, width, color }) => s !== used.style || width !== used.width || color !== used.color;
|
|
7184
|
+
const ignoredSides = declared.slice(1).filter(([, config]) => differs(config)).map(([side]) => side);
|
|
7185
|
+
if (used.style === "none") return { ignoredSides, unsupportedStyles };
|
|
7186
|
+
return {
|
|
7187
|
+
outline: {
|
|
7188
|
+
type: "solidFill",
|
|
7189
|
+
solidFillType: "rgb",
|
|
7190
|
+
value: used.color ? shapeColor(used.color, theme) : "000000",
|
|
7191
|
+
...used.width !== void 0 && {
|
|
7192
|
+
width: Math.round(used.width * PIXELS_TO_EMU)
|
|
7193
|
+
}
|
|
7194
|
+
},
|
|
7195
|
+
ignoredSides,
|
|
7196
|
+
unsupportedStyles
|
|
7197
|
+
};
|
|
7198
|
+
}
|
|
7199
|
+
function shapeBodyProperties(style) {
|
|
7200
|
+
const padding = style?.padding;
|
|
7201
|
+
if (!padding) return void 0;
|
|
7202
|
+
const toEmu = (value) => value === void 0 ? void 0 : Math.round(value * PIXELS_TO_EMU);
|
|
7203
|
+
return {
|
|
7204
|
+
margins: {
|
|
7205
|
+
...padding.top !== void 0 && { top: toEmu(padding.top) },
|
|
7206
|
+
...padding.bottom !== void 0 && { bottom: toEmu(padding.bottom) },
|
|
7207
|
+
...padding.left !== void 0 && { left: toEmu(padding.left) },
|
|
7208
|
+
...padding.right !== void 0 && { right: toEmu(padding.right) }
|
|
7209
|
+
}
|
|
7210
|
+
};
|
|
7211
|
+
}
|
|
7212
|
+
async function renderTextBoxAsShape(tb, theme, themeName, context) {
|
|
7213
|
+
const width = resolveShapeSize(tb.props.width, "width", theme, themeName);
|
|
7214
|
+
const height = resolveShapeSize(tb.props.height, "height", theme, themeName);
|
|
7215
|
+
if (width.pixels === void 0 || height.pixels === void 0) {
|
|
7216
|
+
console.warn(
|
|
7217
|
+
'[core-docx] text-box renderAs "shape" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'
|
|
7218
|
+
);
|
|
7219
|
+
return { kind: "fallback" };
|
|
7220
|
+
}
|
|
7221
|
+
const style = tb.props.style;
|
|
7222
|
+
const { outline, ignoredSides, unsupportedStyles } = shapeOutline(
|
|
7223
|
+
style,
|
|
7224
|
+
theme
|
|
7225
|
+
);
|
|
7226
|
+
if (unsupportedStyles.length > 0) {
|
|
7227
|
+
console.warn(
|
|
7228
|
+
`[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.`
|
|
7229
|
+
);
|
|
7230
|
+
return { kind: "fallback" };
|
|
7231
|
+
}
|
|
7232
|
+
const rendered = await renderTextBoxChildren(tb, theme, themeName, context);
|
|
7233
|
+
if (rendered.some((element) => !(element instanceof Paragraph5))) {
|
|
7234
|
+
console.warn(
|
|
7235
|
+
'[core-docx] text-box renderAs "shape" requires paragraph-only content; falling back to table rendering.'
|
|
7236
|
+
);
|
|
7237
|
+
return { kind: "fallback", rendered };
|
|
7238
|
+
}
|
|
7239
|
+
const children = rendered;
|
|
7240
|
+
if (width.resolvedPercentage || height.resolvedPercentage) {
|
|
7241
|
+
console.warn(
|
|
7242
|
+
'[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.'
|
|
7243
|
+
);
|
|
7244
|
+
}
|
|
7245
|
+
const fill = style?.shading?.fill;
|
|
7246
|
+
if (ignoredSides.length > 0) {
|
|
7247
|
+
console.warn(
|
|
7248
|
+
`[core-docx] text-box renderAs "shape" has one uniform outline; using the first declared border side and ignoring ${ignoredSides.join(", ")}.`
|
|
7249
|
+
);
|
|
7250
|
+
}
|
|
7251
|
+
const dropOutline = Boolean(fill) && Boolean(outline);
|
|
7252
|
+
if (dropOutline) {
|
|
7253
|
+
console.warn(
|
|
7254
|
+
'[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.'
|
|
7255
|
+
);
|
|
7256
|
+
}
|
|
7257
|
+
const bodyProperties = shapeBodyProperties(style);
|
|
7258
|
+
const run = new WpsShapeRun({
|
|
7259
|
+
type: "wps",
|
|
7260
|
+
children,
|
|
7261
|
+
transformation: { width: width.pixels, height: height.pixels },
|
|
7262
|
+
...fill && {
|
|
7263
|
+
solidFill: { type: "rgb", value: shapeColor(fill, theme) }
|
|
7264
|
+
},
|
|
7265
|
+
...outline && !dropOutline && { outline },
|
|
7266
|
+
...bodyProperties && { bodyProperties },
|
|
7267
|
+
// Absent `floating` makes it a `wp:inline` drawing.
|
|
7268
|
+
...tb.props.floating && {
|
|
7269
|
+
floating: mapFloatingOptions(tb.props.floating, theme, themeName)
|
|
7270
|
+
}
|
|
7271
|
+
});
|
|
7272
|
+
return {
|
|
7273
|
+
kind: "shape",
|
|
7274
|
+
paragraphs: [
|
|
7275
|
+
new Paragraph5({ children: [run], spacing: { before: 0, after: 0 } })
|
|
7276
|
+
]
|
|
7277
|
+
};
|
|
7278
|
+
}
|
|
7279
|
+
async function renderTextBoxComponent(component, theme, themeName, context) {
|
|
7280
|
+
if (!isTextBoxComponent(component)) return [];
|
|
7281
|
+
const tb = component;
|
|
7282
|
+
if (tb.props.renderAs === "shape") {
|
|
7283
|
+
const attempt = await renderTextBoxAsShape(tb, theme, themeName, context);
|
|
7284
|
+
if (attempt.kind === "shape") return attempt.paragraphs;
|
|
7285
|
+
return renderTextBoxAsTable(
|
|
7286
|
+
tb,
|
|
7287
|
+
theme,
|
|
7288
|
+
themeName,
|
|
7289
|
+
context,
|
|
7290
|
+
attempt.rendered
|
|
7291
|
+
);
|
|
7292
|
+
}
|
|
7293
|
+
return renderTextBoxAsTable(tb, theme, themeName, context);
|
|
7294
|
+
}
|
|
6944
7295
|
|
|
6945
7296
|
// src/components/table.ts
|
|
6946
7297
|
async function renderTableComponent(component, theme, themeName) {
|
|
@@ -6994,14 +7345,14 @@ async function renderTableComponent(component, theme, themeName) {
|
|
|
6994
7345
|
import { Paragraph as Paragraph6, BookmarkStart, BookmarkEnd } from "docx";
|
|
6995
7346
|
|
|
6996
7347
|
// src/core/sectionBookmarks.ts
|
|
6997
|
-
import { AsyncLocalStorage as
|
|
7348
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
|
|
6998
7349
|
var NESTED_LINK_ID_BASE = 1e6;
|
|
6999
7350
|
function createState3() {
|
|
7000
7351
|
return { nextNested: 1, resolved: /* @__PURE__ */ new WeakMap() };
|
|
7001
7352
|
}
|
|
7002
7353
|
var SectionBookmarkRegistry = class {
|
|
7003
7354
|
fallback = createState3();
|
|
7004
|
-
scopes = new
|
|
7355
|
+
scopes = new AsyncLocalStorage8();
|
|
7005
7356
|
get state() {
|
|
7006
7357
|
return this.scopes.getStore() ?? this.fallback;
|
|
7007
7358
|
}
|
|
@@ -7259,7 +7610,10 @@ function selectCachedEntries(collected, options) {
|
|
|
7259
7610
|
continue;
|
|
7260
7611
|
}
|
|
7261
7612
|
if (entry.level < depthStart || entry.level > depthEnd) continue;
|
|
7262
|
-
entries.push({
|
|
7613
|
+
entries.push({
|
|
7614
|
+
title: entry.number ? `${headingNumberLabel(entry.number)} ${entry.title}` : entry.title,
|
|
7615
|
+
level: entry.level
|
|
7616
|
+
});
|
|
7263
7617
|
}
|
|
7264
7618
|
return entries;
|
|
7265
7619
|
}
|
|
@@ -8018,6 +8372,61 @@ function computeSectionOrdinals(sections) {
|
|
|
8018
8372
|
|
|
8019
8373
|
// src/core/collectTocHeadings.ts
|
|
8020
8374
|
import { getStandardComponent } from "@json-to-office/shared-docx";
|
|
8375
|
+
|
|
8376
|
+
// src/utils/numberFormatting.ts
|
|
8377
|
+
var ROMAN_NUMERALS = [
|
|
8378
|
+
[1e3, "m"],
|
|
8379
|
+
[900, "cm"],
|
|
8380
|
+
[500, "d"],
|
|
8381
|
+
[400, "cd"],
|
|
8382
|
+
[100, "c"],
|
|
8383
|
+
[90, "xc"],
|
|
8384
|
+
[50, "l"],
|
|
8385
|
+
[40, "xl"],
|
|
8386
|
+
[10, "x"],
|
|
8387
|
+
[9, "ix"],
|
|
8388
|
+
[5, "v"],
|
|
8389
|
+
[4, "iv"],
|
|
8390
|
+
[1, "i"]
|
|
8391
|
+
];
|
|
8392
|
+
function toRoman(value) {
|
|
8393
|
+
let remaining = value;
|
|
8394
|
+
let out = "";
|
|
8395
|
+
for (const [amount, glyph] of ROMAN_NUMERALS) {
|
|
8396
|
+
while (remaining >= amount) {
|
|
8397
|
+
out += glyph;
|
|
8398
|
+
remaining -= amount;
|
|
8399
|
+
}
|
|
8400
|
+
}
|
|
8401
|
+
return out;
|
|
8402
|
+
}
|
|
8403
|
+
function toLetters(value) {
|
|
8404
|
+
const index = (value - 1) % 26;
|
|
8405
|
+
const repeats = Math.floor((value - 1) / 26) + 1;
|
|
8406
|
+
return String.fromCharCode(97 + index).repeat(repeats);
|
|
8407
|
+
}
|
|
8408
|
+
function formatNumberForLevel(value, format2) {
|
|
8409
|
+
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
8410
|
+
const n = Math.floor(value);
|
|
8411
|
+
switch (format2) {
|
|
8412
|
+
case "decimal":
|
|
8413
|
+
return String(n);
|
|
8414
|
+
case "lowerLetter":
|
|
8415
|
+
return toLetters(n);
|
|
8416
|
+
case "upperLetter":
|
|
8417
|
+
return toLetters(n).toUpperCase();
|
|
8418
|
+
case "lowerRoman":
|
|
8419
|
+
return toRoman(n);
|
|
8420
|
+
case "upperRoman":
|
|
8421
|
+
return toRoman(n).toUpperCase();
|
|
8422
|
+
default:
|
|
8423
|
+
return void 0;
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8426
|
+
|
|
8427
|
+
// src/core/collectTocHeadings.ts
|
|
8428
|
+
var MAX_HEADING_LEVEL2 = 6;
|
|
8429
|
+
var MAX_LIST_LEVEL = 9;
|
|
8021
8430
|
function normalizeEntryTitle(text) {
|
|
8022
8431
|
return normalizeUnicodeText(text).replace(/(\*\*\*|___)([\s\S]*?)\1/g, "$2").replace(/(\*\*|__)([\s\S]*?)\1/g, "$2").replace(/(\*|_)([\s\S]*?)\1/g, "$2").trim();
|
|
8023
8432
|
}
|
|
@@ -8036,9 +8445,97 @@ function styleEntryKey(props) {
|
|
|
8036
8445
|
}
|
|
8037
8446
|
return themeStyle;
|
|
8038
8447
|
}
|
|
8039
|
-
function
|
|
8448
|
+
function levelStart(levels, level) {
|
|
8449
|
+
return levels[level]?.start ?? 1;
|
|
8450
|
+
}
|
|
8451
|
+
function collectDocumentOutline(sections) {
|
|
8040
8452
|
const entries = [];
|
|
8453
|
+
const numberedItems = /* @__PURE__ */ new Map();
|
|
8041
8454
|
const ordinals = computeSectionOrdinals(sections);
|
|
8455
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
8456
|
+
const headingCounters = new Array(MAX_HEADING_LEVEL2).fill(0);
|
|
8457
|
+
const listCounters = /* @__PURE__ */ new Map();
|
|
8458
|
+
const visitHeading = (component, props, sectionBookmarkId) => {
|
|
8459
|
+
const text = typeof props.text === "string" ? props.text : "";
|
|
8460
|
+
const title = normalizeEntryTitle(text);
|
|
8461
|
+
const level = typeof props.level === "number" ? props.level : 1;
|
|
8462
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL2 ? level : 1;
|
|
8463
|
+
let full;
|
|
8464
|
+
let own;
|
|
8465
|
+
if (props.numbering === true) {
|
|
8466
|
+
headingCounters[styleLevel - 1] += 1;
|
|
8467
|
+
for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL2; deeper++) {
|
|
8468
|
+
headingCounters[deeper] = 0;
|
|
8469
|
+
}
|
|
8470
|
+
full = headingCounters.slice(0, styleLevel).join(".");
|
|
8471
|
+
own = String(headingCounters[styleLevel - 1]);
|
|
8472
|
+
}
|
|
8473
|
+
const explicitId = component.id;
|
|
8474
|
+
const bookmarkId = typeof explicitId === "string" && explicitId ? explicitId : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));
|
|
8475
|
+
takenIds.add(bookmarkId);
|
|
8476
|
+
numberedItems.set(bookmarkId, {
|
|
8477
|
+
kind: "heading",
|
|
8478
|
+
text: title,
|
|
8479
|
+
...full !== void 0 && { full, own }
|
|
8480
|
+
});
|
|
8481
|
+
if (title) {
|
|
8482
|
+
entries.push({
|
|
8483
|
+
title,
|
|
8484
|
+
level,
|
|
8485
|
+
sectionBookmarkId,
|
|
8486
|
+
...full !== void 0 && { number: full }
|
|
8487
|
+
});
|
|
8488
|
+
}
|
|
8489
|
+
};
|
|
8490
|
+
const visitList = (props) => {
|
|
8491
|
+
const items = Array.isArray(props.items) ? props.items : [];
|
|
8492
|
+
if (items.length === 0) return;
|
|
8493
|
+
const reference = typeof props.reference === "string" && props.reference ? props.reference : void 0;
|
|
8494
|
+
const freshState = () => {
|
|
8495
|
+
const levels = resolveListLevels(
|
|
8496
|
+
props
|
|
8497
|
+
);
|
|
8498
|
+
return {
|
|
8499
|
+
levels,
|
|
8500
|
+
counters: Array.from(
|
|
8501
|
+
{ length: MAX_LIST_LEVEL },
|
|
8502
|
+
(_, level) => levelStart(levels, level) - 1
|
|
8503
|
+
)
|
|
8504
|
+
};
|
|
8505
|
+
};
|
|
8506
|
+
let state;
|
|
8507
|
+
if (reference === void 0) {
|
|
8508
|
+
state = freshState();
|
|
8509
|
+
} else {
|
|
8510
|
+
state = listCounters.get(reference) ?? freshState();
|
|
8511
|
+
listCounters.set(reference, state);
|
|
8512
|
+
}
|
|
8513
|
+
for (const item of items) {
|
|
8514
|
+
const isObject = typeof item === "object" && item !== null;
|
|
8515
|
+
const raw = isObject ? item.text : item;
|
|
8516
|
+
const text = typeof raw === "string" ? raw : "";
|
|
8517
|
+
if (!text.trim() && !(isObject && item.revision)) continue;
|
|
8518
|
+
const rawLevel = isObject ? item.level : void 0;
|
|
8519
|
+
const level = typeof rawLevel === "number" && rawLevel >= 0 ? rawLevel : 0;
|
|
8520
|
+
if (level >= MAX_LIST_LEVEL) continue;
|
|
8521
|
+
state.counters[level] += 1;
|
|
8522
|
+
for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {
|
|
8523
|
+
state.counters[deeper] = levelStart(state.levels, deeper) - 1;
|
|
8524
|
+
}
|
|
8525
|
+
const id = isObject ? item.id : void 0;
|
|
8526
|
+
if (typeof id !== "string" || !id) continue;
|
|
8527
|
+
takenIds.add(id);
|
|
8528
|
+
const number = formatNumberForLevel(
|
|
8529
|
+
state.counters[level],
|
|
8530
|
+
state.levels[level]?.format
|
|
8531
|
+
);
|
|
8532
|
+
numberedItems.set(id, {
|
|
8533
|
+
kind: "list-item",
|
|
8534
|
+
text: normalizeUnicodeText(text).trim(),
|
|
8535
|
+
...number !== void 0 && { full: number, own: number }
|
|
8536
|
+
});
|
|
8537
|
+
}
|
|
8538
|
+
};
|
|
8042
8539
|
sections.forEach((section, index) => {
|
|
8043
8540
|
const ordinal = ordinals[index]?.ordinal;
|
|
8044
8541
|
const sectionBookmarkId = ordinal ? globalSectionBookmarkRegistry.forLayoutSection(ordinal).id : void 0;
|
|
@@ -8046,15 +8543,11 @@ function collectTocHeadings(sections) {
|
|
|
8046
8543
|
if (!isEnabled(component)) return;
|
|
8047
8544
|
const props = component.props ?? {};
|
|
8048
8545
|
if (component.name === "heading") {
|
|
8049
|
-
|
|
8050
|
-
const title = normalizeEntryTitle(text);
|
|
8051
|
-
if (title) {
|
|
8052
|
-
const level = typeof props.level === "number" ? props.level : 1;
|
|
8053
|
-
entries.push({ title, level, sectionBookmarkId });
|
|
8054
|
-
}
|
|
8546
|
+
visitHeading(component, props, sectionBookmarkId);
|
|
8055
8547
|
return;
|
|
8056
8548
|
}
|
|
8057
8549
|
if (component.name === "paragraph") {
|
|
8550
|
+
if (typeof props.id === "string" && props.id) takenIds.add(props.id);
|
|
8058
8551
|
const styleId = styleEntryKey(props);
|
|
8059
8552
|
const text = typeof props.text === "string" ? props.text : "";
|
|
8060
8553
|
const title = normalizeEntryTitle(text);
|
|
@@ -8063,13 +8556,17 @@ function collectTocHeadings(sections) {
|
|
|
8063
8556
|
}
|
|
8064
8557
|
return;
|
|
8065
8558
|
}
|
|
8559
|
+
if (component.name === "list") {
|
|
8560
|
+
visitList(props);
|
|
8561
|
+
return;
|
|
8562
|
+
}
|
|
8066
8563
|
if (!isContainer(component.name)) return;
|
|
8067
8564
|
const children = component.children;
|
|
8068
8565
|
if (Array.isArray(children)) children.forEach(visit);
|
|
8069
8566
|
};
|
|
8070
8567
|
section.components.forEach(visit);
|
|
8071
8568
|
});
|
|
8072
|
-
return entries;
|
|
8569
|
+
return { entries, numberedItems };
|
|
8073
8570
|
}
|
|
8074
8571
|
|
|
8075
8572
|
// src/core/render.ts
|
|
@@ -8104,23 +8601,32 @@ function coreProperties(metadata) {
|
|
|
8104
8601
|
async function renderDocument(structure, layout, options) {
|
|
8105
8602
|
return runWithGenerationDate(
|
|
8106
8603
|
structure.metadata.date,
|
|
8107
|
-
() =>
|
|
8108
|
-
options?.
|
|
8109
|
-
() =>
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8604
|
+
() => runWithWarnings(
|
|
8605
|
+
options?.warnings,
|
|
8606
|
+
() => runWithBaseDir(
|
|
8607
|
+
options?.baseDir,
|
|
8608
|
+
() => globalBookmarkRegistry.runScoped(
|
|
8609
|
+
() => globalRevisionIdRegistry.runScoped(
|
|
8610
|
+
() => globalNumberingRegistry.runScoped(
|
|
8611
|
+
() => globalSectionBookmarkRegistry.runScoped(
|
|
8612
|
+
() => (
|
|
8613
|
+
// Comment ids are a separate OOXML namespace from w:ins/w:del,
|
|
8614
|
+
// but they need the same per-render isolation: outside this nest
|
|
8615
|
+
// concurrent generations would interleave counters and an anchor
|
|
8616
|
+
// would point at another document's comment body.
|
|
8617
|
+
globalCommentRegistry.runScoped(
|
|
8618
|
+
() => (
|
|
8619
|
+
// Footnote ids are document-scoped too: a reference resolved
|
|
8620
|
+
// against another render's counter points at the wrong body.
|
|
8621
|
+
globalNoteRegistry.runScoped(
|
|
8622
|
+
() => (
|
|
8623
|
+
// Cross-reference targets are keyed by bookmark id, which
|
|
8624
|
+
// is only unique within one document.
|
|
8625
|
+
globalNumberedItemsRegistry.runScoped(
|
|
8626
|
+
() => renderDocumentScoped(structure, layout, options)
|
|
8627
|
+
)
|
|
8628
|
+
)
|
|
8629
|
+
)
|
|
8124
8630
|
)
|
|
8125
8631
|
)
|
|
8126
8632
|
)
|
|
@@ -8162,13 +8668,14 @@ async function renderDocumentScoped(structure, layout, options) {
|
|
|
8162
8668
|
);
|
|
8163
8669
|
}
|
|
8164
8670
|
try {
|
|
8165
|
-
const
|
|
8166
|
-
if (
|
|
8167
|
-
context.tocHeadings =
|
|
8671
|
+
const outline = collectDocumentOutline(layout.sections);
|
|
8672
|
+
if (outline.entries.length > 0) {
|
|
8673
|
+
context.tocHeadings = outline.entries;
|
|
8168
8674
|
}
|
|
8675
|
+
globalNumberedItemsRegistry.seed(outline.numberedItems);
|
|
8169
8676
|
} catch (error) {
|
|
8170
8677
|
console.warn(
|
|
8171
|
-
"[core-docx]
|
|
8678
|
+
"[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it:",
|
|
8172
8679
|
error instanceof Error ? error.message : error
|
|
8173
8680
|
);
|
|
8174
8681
|
}
|
|
@@ -8340,7 +8847,7 @@ async function renderHeaderFooterComponents(components, theme, themeName, contex
|
|
|
8340
8847
|
themeName
|
|
8341
8848
|
);
|
|
8342
8849
|
const imageType = detectImageType(imageSource, responseContentType);
|
|
8343
|
-
const imageRun = createTypedImageRun({
|
|
8850
|
+
const imageRun = await createTypedImageRun({
|
|
8344
8851
|
type: imageType,
|
|
8345
8852
|
data: imageBuffer,
|
|
8346
8853
|
transformation: {
|
|
@@ -8868,6 +9375,7 @@ async function generateDocumentWithCustomThemes(documentIn, customThemes, servic
|
|
|
8868
9375
|
bypassCache: false,
|
|
8869
9376
|
services,
|
|
8870
9377
|
baseDir,
|
|
9378
|
+
warnings,
|
|
8871
9379
|
...visualFonts.length > 0 && { visualFonts }
|
|
8872
9380
|
});
|
|
8873
9381
|
return renderedDocument;
|
|
@@ -9850,6 +10358,7 @@ function createBuilderImpl(state) {
|
|
|
9850
10358
|
services: state.services,
|
|
9851
10359
|
bypassCache: !state.enableCache,
|
|
9852
10360
|
baseDir: options?.baseDir ?? state.baseDir,
|
|
10361
|
+
warnings,
|
|
9853
10362
|
...visualFonts.length > 0 && { visualFonts }
|
|
9854
10363
|
});
|
|
9855
10364
|
const preservedDefinition = preserveSet ? {
|