@json-to-office/core-docx 0.36.1 → 0.38.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/render.d.ts +2 -2
- package/dist/core/render.d.ts.map +1 -1
- package/dist/index.js +655 -201
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +653 -201
- 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 +34 -0
- package/dist/utils/bookmarkRegistry.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 +2 -2
|
@@ -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
|
};
|
|
@@ -2116,8 +2104,7 @@ import {
|
|
|
2116
2104
|
PageNumber as PageNumber2,
|
|
2117
2105
|
ColumnBreak,
|
|
2118
2106
|
TableLayoutType,
|
|
2119
|
-
VerticalAlign
|
|
2120
|
-
Bookmark
|
|
2107
|
+
VerticalAlign
|
|
2121
2108
|
} from "docx";
|
|
2122
2109
|
|
|
2123
2110
|
// src/utils/imageUtils.ts
|
|
@@ -2458,6 +2445,8 @@ import {
|
|
|
2458
2445
|
InternalHyperlink as InternalHyperlink2,
|
|
2459
2446
|
FootnoteReferenceRun as FootnoteReferenceRun2,
|
|
2460
2447
|
EndnoteReferenceRun as EndnoteReferenceRun2,
|
|
2448
|
+
NumberedItemReference,
|
|
2449
|
+
NumberedItemReferenceFormat,
|
|
2461
2450
|
Tab
|
|
2462
2451
|
} from "docx";
|
|
2463
2452
|
|
|
@@ -2658,6 +2647,45 @@ function initializeBuiltinPlaceholders() {
|
|
|
2658
2647
|
}
|
|
2659
2648
|
initializeBuiltinPlaceholders();
|
|
2660
2649
|
|
|
2650
|
+
// src/utils/numberedItemsRegistry.ts
|
|
2651
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
2652
|
+
var NumberedItemsRegistry = class {
|
|
2653
|
+
fallback = {
|
|
2654
|
+
items: /* @__PURE__ */ new Map(),
|
|
2655
|
+
seeded: false
|
|
2656
|
+
};
|
|
2657
|
+
scopes = new AsyncLocalStorage2();
|
|
2658
|
+
get state() {
|
|
2659
|
+
return this.scopes.getStore() ?? this.fallback;
|
|
2660
|
+
}
|
|
2661
|
+
/** Run work with an isolated registry that follows its async call chain. */
|
|
2662
|
+
runScoped(callback) {
|
|
2663
|
+
return this.scopes.run({ items: /* @__PURE__ */ new Map(), seeded: false }, callback);
|
|
2664
|
+
}
|
|
2665
|
+
/** Replace the contents with the pre-pass result. */
|
|
2666
|
+
seed(items) {
|
|
2667
|
+
const state = this.state;
|
|
2668
|
+
state.items = new Map(items);
|
|
2669
|
+
state.seeded = true;
|
|
2670
|
+
}
|
|
2671
|
+
/**
|
|
2672
|
+
* False outside a render (a unit test calling `createText` directly). An
|
|
2673
|
+
* unresolved reference is then expected rather than an authoring mistake, so
|
|
2674
|
+
* the caller stays quiet about it.
|
|
2675
|
+
*/
|
|
2676
|
+
isSeeded() {
|
|
2677
|
+
return this.state.seeded;
|
|
2678
|
+
}
|
|
2679
|
+
get(id) {
|
|
2680
|
+
return this.state.items.get(id);
|
|
2681
|
+
}
|
|
2682
|
+
clear() {
|
|
2683
|
+
this.state.items.clear();
|
|
2684
|
+
this.state.seeded = false;
|
|
2685
|
+
}
|
|
2686
|
+
};
|
|
2687
|
+
var globalNumberedItemsRegistry = new NumberedItemsRegistry();
|
|
2688
|
+
|
|
2661
2689
|
// src/utils/textParser.ts
|
|
2662
2690
|
var FOOTNOTE_MARKER_REGEX = /\[\^([^\]\s]+)\]/;
|
|
2663
2691
|
function escapeRegExp(s) {
|
|
@@ -2874,13 +2902,59 @@ function splitNoteMarkers(text, noteRef, runs) {
|
|
|
2874
2902
|
if (trailing) out.push(...runs(trailing));
|
|
2875
2903
|
return out;
|
|
2876
2904
|
}
|
|
2905
|
+
var CROSS_REFERENCE_PATTERN = "\\[@([^\\]\\s:]+)(?::(relative|no_context|full_context|none))?\\]";
|
|
2906
|
+
var INLINE_TOKEN_REGEX = `\\[([^\\]]+)\\]\\(([^)]+)\\)|${CROSS_REFERENCE_PATTERN}`;
|
|
2907
|
+
function hasCrossReference(text) {
|
|
2908
|
+
return new RegExp(CROSS_REFERENCE_PATTERN).test(text);
|
|
2909
|
+
}
|
|
2910
|
+
var REFERENCE_FORMATS = {
|
|
2911
|
+
relative: NumberedItemReferenceFormat.RELATIVE,
|
|
2912
|
+
no_context: NumberedItemReferenceFormat.NO_CONTEXT,
|
|
2913
|
+
full_context: NumberedItemReferenceFormat.FULL_CONTEXT,
|
|
2914
|
+
none: NumberedItemReferenceFormat.NONE
|
|
2915
|
+
};
|
|
2916
|
+
function createCrossReference(id, format2, token, baseStyle, options) {
|
|
2917
|
+
const info = globalNumberedItemsRegistry.get(id);
|
|
2918
|
+
if (!info) {
|
|
2919
|
+
if (globalNumberedItemsRegistry.isSeeded()) {
|
|
2920
|
+
console.warn(
|
|
2921
|
+
`[core-docx] Cross-reference ${token} has no target: no heading or list item declares the id "${id}". Rendering the token as literal text.`
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
return buildTextRuns(
|
|
2925
|
+
token,
|
|
2926
|
+
buildRunCommonProps(baseStyle, { boldColor: options.boldColor }),
|
|
2927
|
+
{ noProof: baseStyle.noProof, noProofWords: options.noProofWords }
|
|
2928
|
+
);
|
|
2929
|
+
}
|
|
2930
|
+
if (format2 === "none") {
|
|
2931
|
+
return [
|
|
2932
|
+
new NumberedItemReference(id, info.text, {
|
|
2933
|
+
hyperlink: true,
|
|
2934
|
+
referenceFormat: REFERENCE_FORMATS.none
|
|
2935
|
+
})
|
|
2936
|
+
];
|
|
2937
|
+
}
|
|
2938
|
+
const cachedValue = format2 === "no_context" ? info.own : info.full;
|
|
2939
|
+
if (cachedValue === void 0) {
|
|
2940
|
+
console.warn(
|
|
2941
|
+
`[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.`
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
return [
|
|
2945
|
+
new NumberedItemReference(id, cachedValue, {
|
|
2946
|
+
hyperlink: true,
|
|
2947
|
+
referenceFormat: REFERENCE_FORMATS[format2]
|
|
2948
|
+
})
|
|
2949
|
+
];
|
|
2950
|
+
}
|
|
2877
2951
|
function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
2878
2952
|
const normalizedText = normalizeUnicodeText(text);
|
|
2879
2953
|
const runs = [];
|
|
2880
|
-
const
|
|
2954
|
+
const tokenRegex = new RegExp(INLINE_TOKEN_REGEX, "g");
|
|
2881
2955
|
let lastIndex = 0;
|
|
2882
2956
|
let match;
|
|
2883
|
-
while ((match =
|
|
2957
|
+
while ((match = tokenRegex.exec(normalizedText)) !== null) {
|
|
2884
2958
|
if (match.index > lastIndex) {
|
|
2885
2959
|
const plainText = normalizedText.substring(lastIndex, match.index);
|
|
2886
2960
|
if (plainText) {
|
|
@@ -2892,6 +2966,19 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
2892
2966
|
runs.push(...plainRuns);
|
|
2893
2967
|
}
|
|
2894
2968
|
}
|
|
2969
|
+
lastIndex = match.index + match[0].length;
|
|
2970
|
+
if (match[1] === void 0) {
|
|
2971
|
+
runs.push(
|
|
2972
|
+
...createCrossReference(
|
|
2973
|
+
match[3],
|
|
2974
|
+
match[4] ?? "relative",
|
|
2975
|
+
match[0],
|
|
2976
|
+
baseStyle,
|
|
2977
|
+
options
|
|
2978
|
+
)
|
|
2979
|
+
);
|
|
2980
|
+
continue;
|
|
2981
|
+
}
|
|
2895
2982
|
const linkText = match[1];
|
|
2896
2983
|
const linkUrl = match[2];
|
|
2897
2984
|
const isInternal = linkUrl.startsWith("#");
|
|
@@ -2918,7 +3005,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
2918
3005
|
})
|
|
2919
3006
|
);
|
|
2920
3007
|
}
|
|
2921
|
-
lastIndex = match.index + match[0].length;
|
|
2922
3008
|
}
|
|
2923
3009
|
if (lastIndex < normalizedText.length) {
|
|
2924
3010
|
const remainingText = normalizedText.substring(lastIndex);
|
|
@@ -3612,16 +3698,32 @@ function getStyleIdForLevel(level) {
|
|
|
3612
3698
|
}
|
|
3613
3699
|
|
|
3614
3700
|
// src/utils/bookmarkRegistry.ts
|
|
3615
|
-
import { AsyncLocalStorage as
|
|
3701
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
3702
|
+
import { BookmarkStart, BookmarkEnd } from "docx";
|
|
3703
|
+
var CONTENT_LINK_ID_BASE = 2e6;
|
|
3704
|
+
function createState() {
|
|
3705
|
+
return { bookmarks: /* @__PURE__ */ new Map(), nextLinkId: CONTENT_LINK_ID_BASE + 1 };
|
|
3706
|
+
}
|
|
3707
|
+
function slugifyBookmarkText(text) {
|
|
3708
|
+
return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 40);
|
|
3709
|
+
}
|
|
3710
|
+
function dedupeBookmarkId(base, taken) {
|
|
3711
|
+
let id = base;
|
|
3712
|
+
let attempt = 0;
|
|
3713
|
+
while (taken(id) && attempt < 100) {
|
|
3714
|
+
id = `${base}-${++attempt}`;
|
|
3715
|
+
}
|
|
3716
|
+
return id;
|
|
3717
|
+
}
|
|
3616
3718
|
var BookmarkRegistry = class {
|
|
3617
|
-
fallback =
|
|
3618
|
-
scopes = new
|
|
3719
|
+
fallback = createState();
|
|
3720
|
+
scopes = new AsyncLocalStorage3();
|
|
3619
3721
|
get state() {
|
|
3620
3722
|
return this.scopes.getStore() ?? this.fallback;
|
|
3621
3723
|
}
|
|
3622
3724
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
3623
3725
|
runScoped(callback) {
|
|
3624
|
-
return this.scopes.run(
|
|
3726
|
+
return this.scopes.run(createState(), callback);
|
|
3625
3727
|
}
|
|
3626
3728
|
/**
|
|
3627
3729
|
* Register a bookmark
|
|
@@ -3634,18 +3736,28 @@ var BookmarkRegistry = class {
|
|
|
3634
3736
|
}
|
|
3635
3737
|
this.state.bookmarks.set(id, { id, title, type });
|
|
3636
3738
|
}
|
|
3739
|
+
/**
|
|
3740
|
+
* A `w:id` no other bookmark in this document will use.
|
|
3741
|
+
*
|
|
3742
|
+
* docx's own `Bookmark` cannot supply one: its constructor builds a fresh
|
|
3743
|
+
* id generator per instance (`bookmarkUniqueNumericIdGen()`), so every
|
|
3744
|
+
* bookmark it emits carries `w:id="1"`. Reported upstream as dolanmiu/docx
|
|
3745
|
+
* #3478, still unreleased as of 9.7.1. Duplicated ids leave the start/end
|
|
3746
|
+
* pairing ambiguous, which is why a `REF` field could not read a target's
|
|
3747
|
+
* text even though navigating to it by name worked.
|
|
3748
|
+
*/
|
|
3749
|
+
allocateLinkId() {
|
|
3750
|
+
return this.state.nextLinkId++;
|
|
3751
|
+
}
|
|
3637
3752
|
/**
|
|
3638
3753
|
* Generate a unique bookmark ID from text
|
|
3639
3754
|
* Converts text to a URL-friendly format
|
|
3640
3755
|
*/
|
|
3641
3756
|
generateId(text, _type = "bookmark") {
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
id = `${baseId}-${++attempt}`;
|
|
3647
|
-
}
|
|
3648
|
-
return id;
|
|
3757
|
+
return dedupeBookmarkId(
|
|
3758
|
+
slugifyBookmarkText(text),
|
|
3759
|
+
(id) => this.state.bookmarks.has(id)
|
|
3760
|
+
);
|
|
3649
3761
|
}
|
|
3650
3762
|
/**
|
|
3651
3763
|
* Check if a bookmark exists
|
|
@@ -3686,10 +3798,18 @@ var BookmarkRegistry = class {
|
|
|
3686
3798
|
}
|
|
3687
3799
|
};
|
|
3688
3800
|
var globalBookmarkRegistry = new BookmarkRegistry();
|
|
3801
|
+
function createBookmarkedContent(name, children) {
|
|
3802
|
+
const linkId = globalBookmarkRegistry.allocateLinkId();
|
|
3803
|
+
return [
|
|
3804
|
+
new BookmarkStart(name, linkId),
|
|
3805
|
+
...children,
|
|
3806
|
+
new BookmarkEnd(linkId)
|
|
3807
|
+
];
|
|
3808
|
+
}
|
|
3689
3809
|
|
|
3690
3810
|
// src/utils/revisionUtils.ts
|
|
3691
3811
|
import { TextRun as TextRun3, InsertedTextRun, DeletedTextRun } from "docx";
|
|
3692
|
-
import { AsyncLocalStorage as
|
|
3812
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
3693
3813
|
|
|
3694
3814
|
// src/utils/componentAnnotations.ts
|
|
3695
3815
|
function isRecord(value) {
|
|
@@ -3740,7 +3860,7 @@ var DEFAULT_REVISION_AUTHOR = "json-to-office";
|
|
|
3740
3860
|
var DEFAULT_REVISION_DATE = "1970-01-01T00:00:00Z";
|
|
3741
3861
|
var RevisionIdRegistry = class {
|
|
3742
3862
|
fallbackCounter = 0;
|
|
3743
|
-
scopes = new
|
|
3863
|
+
scopes = new AsyncLocalStorage4();
|
|
3744
3864
|
runScoped(callback) {
|
|
3745
3865
|
return this.scopes.run({ counter: 0 }, callback);
|
|
3746
3866
|
}
|
|
@@ -3851,10 +3971,10 @@ import {
|
|
|
3851
3971
|
|
|
3852
3972
|
// src/utils/commentRegistry.ts
|
|
3853
3973
|
import { Paragraph, TextRun as TextRun4 } from "docx";
|
|
3854
|
-
import { AsyncLocalStorage as
|
|
3974
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
|
|
3855
3975
|
var DEFAULT_COMMENT_AUTHOR = "json-to-office";
|
|
3856
3976
|
var DEFAULT_COMMENT_DATE = "1970-01-01T00:00:00Z";
|
|
3857
|
-
function
|
|
3977
|
+
function createState2() {
|
|
3858
3978
|
return { counter: 0, comments: [], hasResolved: false };
|
|
3859
3979
|
}
|
|
3860
3980
|
function deriveInitials(author) {
|
|
@@ -3865,14 +3985,14 @@ function bodyParagraphs(text) {
|
|
|
3865
3985
|
return normalizeUnicodeText(text).split("\n").map((line) => new Paragraph({ children: [new TextRun4({ text: line })] }));
|
|
3866
3986
|
}
|
|
3867
3987
|
var CommentRegistry = class {
|
|
3868
|
-
fallback =
|
|
3869
|
-
scopes = new
|
|
3988
|
+
fallback = createState2();
|
|
3989
|
+
scopes = new AsyncLocalStorage5();
|
|
3870
3990
|
get state() {
|
|
3871
3991
|
return this.scopes.getStore() ?? this.fallback;
|
|
3872
3992
|
}
|
|
3873
3993
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
3874
3994
|
runScoped(callback) {
|
|
3875
|
-
return this.scopes.run(
|
|
3995
|
+
return this.scopes.run(createState2(), callback);
|
|
3876
3996
|
}
|
|
3877
3997
|
/**
|
|
3878
3998
|
* Register a comment thread and return every id its anchors must carry — the
|
|
@@ -3940,7 +4060,7 @@ var CommentRegistry = class {
|
|
|
3940
4060
|
state.comments.length = 0;
|
|
3941
4061
|
state.hasResolved = false;
|
|
3942
4062
|
} else {
|
|
3943
|
-
this.fallback =
|
|
4063
|
+
this.fallback = createState2();
|
|
3944
4064
|
}
|
|
3945
4065
|
}
|
|
3946
4066
|
};
|
|
@@ -3961,8 +4081,8 @@ function closeCommentRange(ids) {
|
|
|
3961
4081
|
|
|
3962
4082
|
// src/utils/noteRegistry.ts
|
|
3963
4083
|
import { Paragraph as Paragraph2, TextRun as TextRun6 } from "docx";
|
|
3964
|
-
import { AsyncLocalStorage as
|
|
3965
|
-
function
|
|
4084
|
+
import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
|
|
4085
|
+
function createState3() {
|
|
3966
4086
|
return {
|
|
3967
4087
|
footnoteCounter: 0,
|
|
3968
4088
|
endnoteCounter: 0,
|
|
@@ -3979,14 +4099,14 @@ function bodyParagraphs2(text, style) {
|
|
|
3979
4099
|
);
|
|
3980
4100
|
}
|
|
3981
4101
|
var NoteRegistry = class {
|
|
3982
|
-
fallback =
|
|
3983
|
-
scopes = new
|
|
4102
|
+
fallback = createState3();
|
|
4103
|
+
scopes = new AsyncLocalStorage6();
|
|
3984
4104
|
get state() {
|
|
3985
4105
|
return this.scopes.getStore() ?? this.fallback;
|
|
3986
4106
|
}
|
|
3987
4107
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
3988
4108
|
runScoped(callback) {
|
|
3989
|
-
return this.scopes.run(
|
|
4109
|
+
return this.scopes.run(createState3(), callback);
|
|
3990
4110
|
}
|
|
3991
4111
|
/**
|
|
3992
4112
|
* Register a footnote body and return the id its reference must use. Ids are
|
|
@@ -4030,7 +4150,7 @@ var NoteRegistry = class {
|
|
|
4030
4150
|
delete state.endnotes[key];
|
|
4031
4151
|
}
|
|
4032
4152
|
} else {
|
|
4033
|
-
this.fallback =
|
|
4153
|
+
this.fallback = createState3();
|
|
4034
4154
|
}
|
|
4035
4155
|
}
|
|
4036
4156
|
};
|
|
@@ -4196,10 +4316,7 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4196
4316
|
"paragraph"
|
|
4197
4317
|
);
|
|
4198
4318
|
children.push(
|
|
4199
|
-
|
|
4200
|
-
id: options.bookmarkId,
|
|
4201
|
-
children: revisionRuns
|
|
4202
|
-
})
|
|
4319
|
+
...createBookmarkedContent(options.bookmarkId, revisionRuns)
|
|
4203
4320
|
);
|
|
4204
4321
|
} else {
|
|
4205
4322
|
children.push(...revisionRuns);
|
|
@@ -4222,12 +4339,7 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4222
4339
|
normalizedContent,
|
|
4223
4340
|
"paragraph"
|
|
4224
4341
|
);
|
|
4225
|
-
children.push(
|
|
4226
|
-
new Bookmark({
|
|
4227
|
-
id: options.bookmarkId,
|
|
4228
|
-
children: textRuns
|
|
4229
|
-
})
|
|
4230
|
-
);
|
|
4342
|
+
children.push(...createBookmarkedContent(options.bookmarkId, textRuns));
|
|
4231
4343
|
} else {
|
|
4232
4344
|
children.push(...textRuns);
|
|
4233
4345
|
}
|
|
@@ -4336,7 +4448,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4336
4448
|
if (commentAnchor) {
|
|
4337
4449
|
children.push(...commentAnchor.start);
|
|
4338
4450
|
}
|
|
4339
|
-
const
|
|
4451
|
+
const hasInlineSyntax = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText) || hasCrossReference(normalizedText);
|
|
4340
4452
|
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4341
4453
|
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
4342
4454
|
const headingWeighted = applyFontWeightAlias({
|
|
@@ -4388,10 +4500,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4388
4500
|
"heading"
|
|
4389
4501
|
);
|
|
4390
4502
|
children.push(
|
|
4391
|
-
|
|
4392
|
-
id: options.bookmarkId,
|
|
4393
|
-
children: revisionRuns
|
|
4394
|
-
})
|
|
4503
|
+
...createBookmarkedContent(options.bookmarkId, revisionRuns)
|
|
4395
4504
|
);
|
|
4396
4505
|
} else {
|
|
4397
4506
|
children.push(...revisionRuns);
|
|
@@ -4403,7 +4512,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4403
4512
|
"heading"
|
|
4404
4513
|
);
|
|
4405
4514
|
const headingTextChildren = [];
|
|
4406
|
-
if (
|
|
4515
|
+
if (hasInlineSyntax) {
|
|
4407
4516
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4408
4517
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
4409
4518
|
enableHyperlinks: true,
|
|
@@ -4414,13 +4523,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4414
4523
|
headingTextChildren.push(...makeHeadingRuns(normalizedText));
|
|
4415
4524
|
}
|
|
4416
4525
|
children.push(
|
|
4417
|
-
|
|
4418
|
-
id: options.bookmarkId,
|
|
4419
|
-
children: headingTextChildren
|
|
4420
|
-
})
|
|
4526
|
+
...createBookmarkedContent(options.bookmarkId, headingTextChildren)
|
|
4421
4527
|
);
|
|
4422
4528
|
} else {
|
|
4423
|
-
if (
|
|
4529
|
+
if (hasInlineSyntax) {
|
|
4424
4530
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4425
4531
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
4426
4532
|
enableHyperlinks: true,
|
|
@@ -4442,7 +4548,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4442
4548
|
spacing: hasExplicitSpacing ? spacing : void 0,
|
|
4443
4549
|
...options.keepNext !== void 0 && { keepNext: options.keepNext },
|
|
4444
4550
|
...options.keepLines !== void 0 && { keepLines: options.keepLines },
|
|
4445
|
-
...options.indent && { indent: options.indent }
|
|
4551
|
+
...options.indent && { indent: options.indent },
|
|
4552
|
+
// docx creates the concrete numbering instance for the reference itself,
|
|
4553
|
+
// in ParagraphProperties.prepForXml.
|
|
4554
|
+
...options.numbering !== void 0 && { numbering: options.numbering }
|
|
4446
4555
|
});
|
|
4447
4556
|
}
|
|
4448
4557
|
async function createImage(path3, theme, themeName, options = {}) {
|
|
@@ -4602,9 +4711,15 @@ function createList(items, _theme, _themeName, options = {}) {
|
|
|
4602
4711
|
} else if (options.spacing?.item) {
|
|
4603
4712
|
spacing.after = pointsToTwips(options.spacing.item);
|
|
4604
4713
|
}
|
|
4714
|
+
const itemId = typeof item === "object" ? item.id : void 0;
|
|
4715
|
+
let itemContent = textRuns;
|
|
4716
|
+
if (itemId) {
|
|
4717
|
+
globalBookmarkRegistry.register(itemId, itemText, "list-item");
|
|
4718
|
+
itemContent = createBookmarkedContent(itemId, textRuns);
|
|
4719
|
+
}
|
|
4605
4720
|
const paragraphChildren = [
|
|
4606
4721
|
...commentAnchor && index === firstRendered ? commentAnchor.start : [],
|
|
4607
|
-
...
|
|
4722
|
+
...itemContent,
|
|
4608
4723
|
...commentAnchor && index === lastRendered ? closeCommentRange(commentAnchor.ids) : []
|
|
4609
4724
|
];
|
|
4610
4725
|
const paragraph = new Paragraph3({
|
|
@@ -6595,8 +6710,8 @@ import {
|
|
|
6595
6710
|
Paragraph as Paragraph9,
|
|
6596
6711
|
TextRun as TextRun9,
|
|
6597
6712
|
AlignmentType as AlignmentType5,
|
|
6598
|
-
BookmarkStart as
|
|
6599
|
-
BookmarkEnd as
|
|
6713
|
+
BookmarkStart as BookmarkStart3,
|
|
6714
|
+
BookmarkEnd as BookmarkEnd3
|
|
6600
6715
|
} from "docx";
|
|
6601
6716
|
init_defaults();
|
|
6602
6717
|
init_styleHelpers();
|
|
@@ -6807,54 +6922,14 @@ async function renderComponentWithCache(component, theme, themeName, context, by
|
|
|
6807
6922
|
return rendered;
|
|
6808
6923
|
}
|
|
6809
6924
|
|
|
6810
|
-
// src/components/heading.ts
|
|
6811
|
-
function renderHeadingComponent(component, theme, themeName) {
|
|
6812
|
-
if (!isHeadingComponent(component)) return [];
|
|
6813
|
-
const config = component.props;
|
|
6814
|
-
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6815
|
-
const header = createHeading(
|
|
6816
|
-
config.text,
|
|
6817
|
-
config.level || 1,
|
|
6818
|
-
theme,
|
|
6819
|
-
themeName,
|
|
6820
|
-
{
|
|
6821
|
-
alignment: config.alignment,
|
|
6822
|
-
spacing: config.spacing,
|
|
6823
|
-
lineSpacing: config.lineSpacing,
|
|
6824
|
-
columnBreak: config.columnBreak,
|
|
6825
|
-
// Local font overrides
|
|
6826
|
-
fontFamily: config.font?.family,
|
|
6827
|
-
fontSize: config.font?.size,
|
|
6828
|
-
fontColor: config.font?.color,
|
|
6829
|
-
bold: config.font?.bold,
|
|
6830
|
-
fontWeight: config.font?.fontWeight,
|
|
6831
|
-
italic: config.font?.italic,
|
|
6832
|
-
underline: config.font?.underline,
|
|
6833
|
-
scale: config.font?.scale,
|
|
6834
|
-
characterSpacing: config.font?.characterSpacing,
|
|
6835
|
-
// Proofing: local language override + no-proof toggle + known-words list
|
|
6836
|
-
language: config.language,
|
|
6837
|
-
noProof: config.noProof,
|
|
6838
|
-
noProofWords: config.noProofWords,
|
|
6839
|
-
// Pagination control
|
|
6840
|
-
keepNext: config.keepNext,
|
|
6841
|
-
keepLines: config.keepLines,
|
|
6842
|
-
// Paragraph indentation (w:ind) in twips
|
|
6843
|
-
indent: config.indent,
|
|
6844
|
-
// Bookmark ID for internal linking
|
|
6845
|
-
bookmarkId,
|
|
6846
|
-
// Tracked-change segments (rendered as native Word revisions)
|
|
6847
|
-
revision: config.revision,
|
|
6848
|
-
// Review comment anchored to this heading's text
|
|
6849
|
-
comment: config.comment
|
|
6850
|
-
}
|
|
6851
|
-
);
|
|
6852
|
-
return [header];
|
|
6853
|
-
}
|
|
6854
|
-
|
|
6855
6925
|
// src/utils/numberingConfig.ts
|
|
6856
|
-
import {
|
|
6857
|
-
|
|
6926
|
+
import {
|
|
6927
|
+
AlignmentType as AlignmentType3,
|
|
6928
|
+
convertInchesToTwip,
|
|
6929
|
+
LevelFormat,
|
|
6930
|
+
LevelSuffix
|
|
6931
|
+
} from "docx";
|
|
6932
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "async_hooks";
|
|
6858
6933
|
var LEVEL_FORMAT_MAP = {
|
|
6859
6934
|
decimal: LevelFormat.DECIMAL,
|
|
6860
6935
|
upperRoman: LevelFormat.UPPER_ROMAN,
|
|
@@ -6982,12 +7057,37 @@ function createNumberingConfig(config) {
|
|
|
6982
7057
|
levels
|
|
6983
7058
|
};
|
|
6984
7059
|
}
|
|
7060
|
+
var HEADING_NUMBERING_REFERENCE = "jto-heading-numbering";
|
|
7061
|
+
function createHeadingNumberingConfig() {
|
|
7062
|
+
const levels = [];
|
|
7063
|
+
for (let level = 0; level < 6; level++) {
|
|
7064
|
+
const text = Array.from({ length: level + 1 }, (_, i) => `%${i + 1}`).join(".") + ".";
|
|
7065
|
+
levels.push({
|
|
7066
|
+
level,
|
|
7067
|
+
format: LevelFormat.DECIMAL,
|
|
7068
|
+
text,
|
|
7069
|
+
alignment: AlignmentType3.LEFT,
|
|
7070
|
+
start: 1,
|
|
7071
|
+
// A space, not the default tab: a tab would push the heading text to the
|
|
7072
|
+
// next tab stop and misalign it against unnumbered headings.
|
|
7073
|
+
suffix: LevelSuffix.SPACE,
|
|
7074
|
+
style: {
|
|
7075
|
+
paragraph: { indent: { left: 0, hanging: 0 } },
|
|
7076
|
+
style: `Heading${level + 1}`
|
|
7077
|
+
}
|
|
7078
|
+
});
|
|
7079
|
+
}
|
|
7080
|
+
return { reference: HEADING_NUMBERING_REFERENCE, levels };
|
|
7081
|
+
}
|
|
7082
|
+
function headingNumberLabel(number) {
|
|
7083
|
+
return `${number}.`;
|
|
7084
|
+
}
|
|
6985
7085
|
var NumberingRegistry = class {
|
|
6986
7086
|
fallback = {
|
|
6987
7087
|
configs: /* @__PURE__ */ new Map(),
|
|
6988
7088
|
counter: 0
|
|
6989
7089
|
};
|
|
6990
|
-
scopes = new
|
|
7090
|
+
scopes = new AsyncLocalStorage7();
|
|
6991
7091
|
get state() {
|
|
6992
7092
|
return this.scopes.getStore() ?? this.fallback;
|
|
6993
7093
|
}
|
|
@@ -7037,6 +7137,63 @@ var NumberingRegistry = class {
|
|
|
7037
7137
|
};
|
|
7038
7138
|
var globalNumberingRegistry = new NumberingRegistry();
|
|
7039
7139
|
|
|
7140
|
+
// src/components/heading.ts
|
|
7141
|
+
var MAX_HEADING_LEVEL = 6;
|
|
7142
|
+
function headingNumbering(numbering, level) {
|
|
7143
|
+
if (numbering === false) return false;
|
|
7144
|
+
if (numbering !== true) return void 0;
|
|
7145
|
+
if (!globalNumberingRegistry.has(HEADING_NUMBERING_REFERENCE)) {
|
|
7146
|
+
globalNumberingRegistry.register(createHeadingNumberingConfig());
|
|
7147
|
+
}
|
|
7148
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;
|
|
7149
|
+
return { reference: HEADING_NUMBERING_REFERENCE, level: styleLevel - 1 };
|
|
7150
|
+
}
|
|
7151
|
+
function renderHeadingComponent(component, theme, themeName) {
|
|
7152
|
+
if (!isHeadingComponent(component)) return [];
|
|
7153
|
+
const config = component.props;
|
|
7154
|
+
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
7155
|
+
const header = createHeading(
|
|
7156
|
+
config.text,
|
|
7157
|
+
config.level || 1,
|
|
7158
|
+
theme,
|
|
7159
|
+
themeName,
|
|
7160
|
+
{
|
|
7161
|
+
alignment: config.alignment,
|
|
7162
|
+
spacing: config.spacing,
|
|
7163
|
+
lineSpacing: config.lineSpacing,
|
|
7164
|
+
columnBreak: config.columnBreak,
|
|
7165
|
+
// Local font overrides
|
|
7166
|
+
fontFamily: config.font?.family,
|
|
7167
|
+
fontSize: config.font?.size,
|
|
7168
|
+
fontColor: config.font?.color,
|
|
7169
|
+
bold: config.font?.bold,
|
|
7170
|
+
fontWeight: config.font?.fontWeight,
|
|
7171
|
+
italic: config.font?.italic,
|
|
7172
|
+
underline: config.font?.underline,
|
|
7173
|
+
scale: config.font?.scale,
|
|
7174
|
+
characterSpacing: config.font?.characterSpacing,
|
|
7175
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
7176
|
+
language: config.language,
|
|
7177
|
+
noProof: config.noProof,
|
|
7178
|
+
noProofWords: config.noProofWords,
|
|
7179
|
+
// Pagination control
|
|
7180
|
+
keepNext: config.keepNext,
|
|
7181
|
+
keepLines: config.keepLines,
|
|
7182
|
+
// Paragraph indentation (w:ind) in twips
|
|
7183
|
+
indent: config.indent,
|
|
7184
|
+
// Bookmark ID for internal linking
|
|
7185
|
+
bookmarkId,
|
|
7186
|
+
// Auto-numbering (1., 1.1., …) through the shared heading definition
|
|
7187
|
+
numbering: headingNumbering(config.numbering, config.level || 1),
|
|
7188
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
7189
|
+
revision: config.revision,
|
|
7190
|
+
// Review comment anchored to this heading's text
|
|
7191
|
+
comment: config.comment
|
|
7192
|
+
}
|
|
7193
|
+
);
|
|
7194
|
+
return [header];
|
|
7195
|
+
}
|
|
7196
|
+
|
|
7040
7197
|
// src/components/paragraph.ts
|
|
7041
7198
|
function parseMarkdownList(text) {
|
|
7042
7199
|
const lines = text.split("\n");
|
|
@@ -7176,8 +7333,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
7176
7333
|
return [text];
|
|
7177
7334
|
}
|
|
7178
7335
|
|
|
7179
|
-
// src/
|
|
7180
|
-
init_colorUtils();
|
|
7336
|
+
// src/utils/listLevels.ts
|
|
7181
7337
|
function createLevelsFromSimplifiedProps(props) {
|
|
7182
7338
|
const levels = [];
|
|
7183
7339
|
let format2;
|
|
@@ -7224,18 +7380,8 @@ function createLevelsFromSimplifiedProps(props) {
|
|
|
7224
7380
|
}
|
|
7225
7381
|
return levels;
|
|
7226
7382
|
}
|
|
7227
|
-
function resolveMarkerFonts(levels, theme) {
|
|
7228
|
-
return levels.map((level) => {
|
|
7229
|
-
const font = level.font;
|
|
7230
|
-
if (!font?.color) return level;
|
|
7231
|
-
return {
|
|
7232
|
-
...level,
|
|
7233
|
-
font: { ...font, color: resolveColor(font.color, theme) }
|
|
7234
|
-
};
|
|
7235
|
-
});
|
|
7236
|
-
}
|
|
7237
7383
|
function applyListStart(levels, start) {
|
|
7238
|
-
if (start === void 0) return levels;
|
|
7384
|
+
if (start === void 0) return [...levels];
|
|
7239
7385
|
return levels.map(
|
|
7240
7386
|
(level) => level.level === 0 && level.start === void 0 ? { ...level, start } : level
|
|
7241
7387
|
);
|
|
@@ -7293,28 +7439,37 @@ function fillMissingLevels(levels, maxLevel) {
|
|
|
7293
7439
|
}
|
|
7294
7440
|
return result;
|
|
7295
7441
|
}
|
|
7442
|
+
function resolveListLevels(props) {
|
|
7443
|
+
const maxLevel = getMaxLevelFromItems(props.items);
|
|
7444
|
+
if (props.levels && props.levels.length > 0) {
|
|
7445
|
+
return fillMissingLevels(
|
|
7446
|
+
applyListStart(props.levels, props.start),
|
|
7447
|
+
maxLevel
|
|
7448
|
+
);
|
|
7449
|
+
}
|
|
7450
|
+
return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);
|
|
7451
|
+
}
|
|
7452
|
+
|
|
7453
|
+
// src/components/list.ts
|
|
7454
|
+
init_colorUtils();
|
|
7455
|
+
function resolveMarkerFonts(levels, theme) {
|
|
7456
|
+
return levels.map((level) => {
|
|
7457
|
+
const font = level.font;
|
|
7458
|
+
if (!font?.color) return level;
|
|
7459
|
+
return {
|
|
7460
|
+
...level,
|
|
7461
|
+
font: { ...font, color: resolveColor(font.color, theme) }
|
|
7462
|
+
};
|
|
7463
|
+
});
|
|
7464
|
+
}
|
|
7296
7465
|
function renderListComponent(component, theme, themeName) {
|
|
7297
7466
|
if (!isListComponent(component)) return [];
|
|
7298
7467
|
const resolvedConfig = component.props;
|
|
7299
|
-
const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
|
|
7300
7468
|
const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
|
|
7301
7469
|
if (!globalNumberingRegistry.has(reference)) {
|
|
7302
|
-
let levels;
|
|
7303
|
-
if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {
|
|
7304
|
-
levels = fillMissingLevels(
|
|
7305
|
-
applyListStart(
|
|
7306
|
-
resolvedConfig.levels,
|
|
7307
|
-
resolvedConfig.start
|
|
7308
|
-
),
|
|
7309
|
-
maxLevel
|
|
7310
|
-
);
|
|
7311
|
-
} else {
|
|
7312
|
-
const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);
|
|
7313
|
-
levels = fillMissingLevels(baseLevels, maxLevel);
|
|
7314
|
-
}
|
|
7315
7470
|
const config = {
|
|
7316
7471
|
reference,
|
|
7317
|
-
levels: resolveMarkerFonts(
|
|
7472
|
+
levels: resolveMarkerFonts(resolveListLevels(resolvedConfig), theme)
|
|
7318
7473
|
};
|
|
7319
7474
|
const numberingConfig = createNumberingConfig(config);
|
|
7320
7475
|
globalNumberingRegistry.register(numberingConfig);
|
|
@@ -7354,6 +7509,7 @@ async function renderImageComponent(component, theme, themeName) {
|
|
|
7354
7509
|
|
|
7355
7510
|
// src/components/text-box.ts
|
|
7356
7511
|
import {
|
|
7512
|
+
Paragraph as Paragraph5,
|
|
7357
7513
|
Table as Table3,
|
|
7358
7514
|
TableRow as TableRow2,
|
|
7359
7515
|
TableCell as TableCell2,
|
|
@@ -7362,7 +7518,8 @@ import {
|
|
|
7362
7518
|
RelativeHorizontalPosition,
|
|
7363
7519
|
RelativeVerticalPosition,
|
|
7364
7520
|
OverlapType,
|
|
7365
|
-
TableLayoutType as TableLayoutType2
|
|
7521
|
+
TableLayoutType as TableLayoutType2,
|
|
7522
|
+
WpsShapeRun
|
|
7366
7523
|
} from "docx";
|
|
7367
7524
|
|
|
7368
7525
|
// src/styles/utils/borderUtils.ts
|
|
@@ -7439,6 +7596,8 @@ function buildCellOptions(children, styleCfg, theme) {
|
|
|
7439
7596
|
}
|
|
7440
7597
|
|
|
7441
7598
|
// src/components/text-box.ts
|
|
7599
|
+
init_colorUtils();
|
|
7600
|
+
init_docxImagePositioning();
|
|
7442
7601
|
init_widthUtils();
|
|
7443
7602
|
function mapTableFloatOptions(floating, theme, themeName) {
|
|
7444
7603
|
if (!floating) return void 0;
|
|
@@ -7494,26 +7653,23 @@ function mapTableFloatOptions(floating, theme, themeName) {
|
|
|
7494
7653
|
opt.overlap = OverlapType.OVERLAP;
|
|
7495
7654
|
return opt;
|
|
7496
7655
|
}
|
|
7497
|
-
async function
|
|
7498
|
-
|
|
7499
|
-
|
|
7656
|
+
async function renderTextBoxChildren(tb, theme, themeName, context) {
|
|
7657
|
+
const childContext = {
|
|
7658
|
+
...context,
|
|
7659
|
+
parent: tb
|
|
7660
|
+
};
|
|
7661
|
+
const rendered = [];
|
|
7662
|
+
for (const child of tb.children || []) {
|
|
7663
|
+
rendered.push(
|
|
7664
|
+
...await renderComponent(child, theme, themeName, childContext)
|
|
7665
|
+
);
|
|
7666
|
+
}
|
|
7667
|
+
return rendered;
|
|
7668
|
+
}
|
|
7669
|
+
async function renderTextBoxAsTable(tb, theme, themeName, _context, prerendered) {
|
|
7500
7670
|
const isInline = !tb.props.floating;
|
|
7501
|
-
const childComponents = tb.children || [];
|
|
7502
7671
|
if (isInline) {
|
|
7503
|
-
const cellChildren2 =
|
|
7504
|
-
const childContext2 = {
|
|
7505
|
-
..._context,
|
|
7506
|
-
parent: tb
|
|
7507
|
-
};
|
|
7508
|
-
for (const child of childComponents) {
|
|
7509
|
-
const rendered = await renderComponent(
|
|
7510
|
-
child,
|
|
7511
|
-
theme,
|
|
7512
|
-
themeName,
|
|
7513
|
-
childContext2
|
|
7514
|
-
);
|
|
7515
|
-
cellChildren2.push(...rendered);
|
|
7516
|
-
}
|
|
7672
|
+
const cellChildren2 = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
7517
7673
|
const styleCfg2 = tb.props.style;
|
|
7518
7674
|
const cellOpts2 = buildCellOptions(cellChildren2, styleCfg2, theme);
|
|
7519
7675
|
const row2 = new TableRow2({ children: [new TableCell2(cellOpts2)] });
|
|
@@ -7526,20 +7682,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
7526
7682
|
});
|
|
7527
7683
|
return [table2];
|
|
7528
7684
|
}
|
|
7529
|
-
const cellChildren =
|
|
7530
|
-
const childContext = {
|
|
7531
|
-
..._context,
|
|
7532
|
-
parent: tb
|
|
7533
|
-
};
|
|
7534
|
-
for (const child of childComponents) {
|
|
7535
|
-
const rendered = await renderComponent(
|
|
7536
|
-
child,
|
|
7537
|
-
theme,
|
|
7538
|
-
themeName,
|
|
7539
|
-
childContext
|
|
7540
|
-
);
|
|
7541
|
-
cellChildren.push(...rendered);
|
|
7542
|
-
}
|
|
7685
|
+
const cellChildren = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
7543
7686
|
const styleCfg = tb.props.style;
|
|
7544
7687
|
const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);
|
|
7545
7688
|
const row = new TableRow2({
|
|
@@ -7571,6 +7714,162 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
7571
7714
|
});
|
|
7572
7715
|
return [table];
|
|
7573
7716
|
}
|
|
7717
|
+
var PIXELS_TO_EMU = 9525;
|
|
7718
|
+
var TWIPS_PER_PIXEL = 15;
|
|
7719
|
+
function resolveShapeSize(value, axis, theme, themeName) {
|
|
7720
|
+
if (typeof value === "number") {
|
|
7721
|
+
return { pixels: Math.round(value), resolvedPercentage: false };
|
|
7722
|
+
}
|
|
7723
|
+
if (typeof value !== "string") return { resolvedPercentage: false };
|
|
7724
|
+
const fraction = parseFloat(value) / 100;
|
|
7725
|
+
if (!Number.isFinite(fraction) || fraction <= 0) {
|
|
7726
|
+
return { resolvedPercentage: false };
|
|
7727
|
+
}
|
|
7728
|
+
const availableTwips = axis === "width" ? getAvailableWidthTwips(theme, themeName) : getAvailableHeightTwips(theme, themeName);
|
|
7729
|
+
return {
|
|
7730
|
+
pixels: Math.round(availableTwips * fraction / TWIPS_PER_PIXEL),
|
|
7731
|
+
resolvedPercentage: true
|
|
7732
|
+
};
|
|
7733
|
+
}
|
|
7734
|
+
function shapeColor(value, theme) {
|
|
7735
|
+
return resolveColor(value, theme).replace(/^#/, "");
|
|
7736
|
+
}
|
|
7737
|
+
function shapeOutline(style, theme) {
|
|
7738
|
+
const border = style?.border;
|
|
7739
|
+
if (!border) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7740
|
+
const order = [
|
|
7741
|
+
"top",
|
|
7742
|
+
"left",
|
|
7743
|
+
"bottom",
|
|
7744
|
+
"right"
|
|
7745
|
+
];
|
|
7746
|
+
const declared = order.map((side) => [side, border[side]]).filter(
|
|
7747
|
+
(entry) => Boolean(entry[1])
|
|
7748
|
+
);
|
|
7749
|
+
if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7750
|
+
const unsupportedStyles = [
|
|
7751
|
+
...new Set(
|
|
7752
|
+
declared.map(([, config]) => config.style).filter(
|
|
7753
|
+
(value) => value === "dashed" || value === "dotted" || value === "double"
|
|
7754
|
+
)
|
|
7755
|
+
)
|
|
7756
|
+
];
|
|
7757
|
+
if (unsupportedStyles.length > 0) {
|
|
7758
|
+
return { ignoredSides: [], unsupportedStyles };
|
|
7759
|
+
}
|
|
7760
|
+
const [, used] = declared[0];
|
|
7761
|
+
const differs = ({ style: s, width, color }) => s !== used.style || width !== used.width || color !== used.color;
|
|
7762
|
+
const ignoredSides = declared.slice(1).filter(([, config]) => differs(config)).map(([side]) => side);
|
|
7763
|
+
if (used.style === "none") return { ignoredSides, unsupportedStyles };
|
|
7764
|
+
return {
|
|
7765
|
+
outline: {
|
|
7766
|
+
type: "solidFill",
|
|
7767
|
+
solidFillType: "rgb",
|
|
7768
|
+
value: used.color ? shapeColor(used.color, theme) : "000000",
|
|
7769
|
+
...used.width !== void 0 && {
|
|
7770
|
+
width: Math.round(used.width * PIXELS_TO_EMU)
|
|
7771
|
+
}
|
|
7772
|
+
},
|
|
7773
|
+
ignoredSides,
|
|
7774
|
+
unsupportedStyles
|
|
7775
|
+
};
|
|
7776
|
+
}
|
|
7777
|
+
function shapeBodyProperties(style) {
|
|
7778
|
+
const padding = style?.padding;
|
|
7779
|
+
if (!padding) return void 0;
|
|
7780
|
+
const toEmu = (value) => value === void 0 ? void 0 : Math.round(value * PIXELS_TO_EMU);
|
|
7781
|
+
return {
|
|
7782
|
+
margins: {
|
|
7783
|
+
...padding.top !== void 0 && { top: toEmu(padding.top) },
|
|
7784
|
+
...padding.bottom !== void 0 && { bottom: toEmu(padding.bottom) },
|
|
7785
|
+
...padding.left !== void 0 && { left: toEmu(padding.left) },
|
|
7786
|
+
...padding.right !== void 0 && { right: toEmu(padding.right) }
|
|
7787
|
+
}
|
|
7788
|
+
};
|
|
7789
|
+
}
|
|
7790
|
+
async function renderTextBoxAsShape(tb, theme, themeName, context) {
|
|
7791
|
+
const width = resolveShapeSize(tb.props.width, "width", theme, themeName);
|
|
7792
|
+
const height = resolveShapeSize(tb.props.height, "height", theme, themeName);
|
|
7793
|
+
if (width.pixels === void 0 || height.pixels === void 0) {
|
|
7794
|
+
console.warn(
|
|
7795
|
+
'[core-docx] text-box renderAs "shape" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'
|
|
7796
|
+
);
|
|
7797
|
+
return { kind: "fallback" };
|
|
7798
|
+
}
|
|
7799
|
+
const style = tb.props.style;
|
|
7800
|
+
const { outline, ignoredSides, unsupportedStyles } = shapeOutline(
|
|
7801
|
+
style,
|
|
7802
|
+
theme
|
|
7803
|
+
);
|
|
7804
|
+
if (unsupportedStyles.length > 0) {
|
|
7805
|
+
console.warn(
|
|
7806
|
+
`[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.`
|
|
7807
|
+
);
|
|
7808
|
+
return { kind: "fallback" };
|
|
7809
|
+
}
|
|
7810
|
+
const rendered = await renderTextBoxChildren(tb, theme, themeName, context);
|
|
7811
|
+
if (rendered.some((element) => !(element instanceof Paragraph5))) {
|
|
7812
|
+
console.warn(
|
|
7813
|
+
'[core-docx] text-box renderAs "shape" requires paragraph-only content; falling back to table rendering.'
|
|
7814
|
+
);
|
|
7815
|
+
return { kind: "fallback", rendered };
|
|
7816
|
+
}
|
|
7817
|
+
const children = rendered;
|
|
7818
|
+
if (width.resolvedPercentage || height.resolvedPercentage) {
|
|
7819
|
+
console.warn(
|
|
7820
|
+
'[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.'
|
|
7821
|
+
);
|
|
7822
|
+
}
|
|
7823
|
+
const fill = style?.shading?.fill;
|
|
7824
|
+
if (ignoredSides.length > 0) {
|
|
7825
|
+
console.warn(
|
|
7826
|
+
`[core-docx] text-box renderAs "shape" has one uniform outline; using the first declared border side and ignoring ${ignoredSides.join(", ")}.`
|
|
7827
|
+
);
|
|
7828
|
+
}
|
|
7829
|
+
const dropOutline = Boolean(fill) && Boolean(outline);
|
|
7830
|
+
if (dropOutline) {
|
|
7831
|
+
console.warn(
|
|
7832
|
+
'[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.'
|
|
7833
|
+
);
|
|
7834
|
+
}
|
|
7835
|
+
const bodyProperties = shapeBodyProperties(style);
|
|
7836
|
+
const run = new WpsShapeRun({
|
|
7837
|
+
type: "wps",
|
|
7838
|
+
children,
|
|
7839
|
+
transformation: { width: width.pixels, height: height.pixels },
|
|
7840
|
+
...fill && {
|
|
7841
|
+
solidFill: { type: "rgb", value: shapeColor(fill, theme) }
|
|
7842
|
+
},
|
|
7843
|
+
...outline && !dropOutline && { outline },
|
|
7844
|
+
...bodyProperties && { bodyProperties },
|
|
7845
|
+
// Absent `floating` makes it a `wp:inline` drawing.
|
|
7846
|
+
...tb.props.floating && {
|
|
7847
|
+
floating: mapFloatingOptions(tb.props.floating, theme, themeName)
|
|
7848
|
+
}
|
|
7849
|
+
});
|
|
7850
|
+
return {
|
|
7851
|
+
kind: "shape",
|
|
7852
|
+
paragraphs: [
|
|
7853
|
+
new Paragraph5({ children: [run], spacing: { before: 0, after: 0 } })
|
|
7854
|
+
]
|
|
7855
|
+
};
|
|
7856
|
+
}
|
|
7857
|
+
async function renderTextBoxComponent(component, theme, themeName, context) {
|
|
7858
|
+
if (!isTextBoxComponent(component)) return [];
|
|
7859
|
+
const tb = component;
|
|
7860
|
+
if (tb.props.renderAs === "shape") {
|
|
7861
|
+
const attempt = await renderTextBoxAsShape(tb, theme, themeName, context);
|
|
7862
|
+
if (attempt.kind === "shape") return attempt.paragraphs;
|
|
7863
|
+
return renderTextBoxAsTable(
|
|
7864
|
+
tb,
|
|
7865
|
+
theme,
|
|
7866
|
+
themeName,
|
|
7867
|
+
context,
|
|
7868
|
+
attempt.rendered
|
|
7869
|
+
);
|
|
7870
|
+
}
|
|
7871
|
+
return renderTextBoxAsTable(tb, theme, themeName, context);
|
|
7872
|
+
}
|
|
7574
7873
|
|
|
7575
7874
|
// src/components/table.ts
|
|
7576
7875
|
async function renderTableComponent(component, theme, themeName) {
|
|
@@ -7621,23 +7920,23 @@ async function renderTableComponent(component, theme, themeName) {
|
|
|
7621
7920
|
}
|
|
7622
7921
|
|
|
7623
7922
|
// src/components/section.ts
|
|
7624
|
-
import { Paragraph as Paragraph6, BookmarkStart, BookmarkEnd } from "docx";
|
|
7923
|
+
import { Paragraph as Paragraph6, BookmarkStart as BookmarkStart2, BookmarkEnd as BookmarkEnd2 } from "docx";
|
|
7625
7924
|
|
|
7626
7925
|
// src/core/sectionBookmarks.ts
|
|
7627
|
-
import { AsyncLocalStorage as
|
|
7926
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
|
|
7628
7927
|
var NESTED_LINK_ID_BASE = 1e6;
|
|
7629
|
-
function
|
|
7928
|
+
function createState4() {
|
|
7630
7929
|
return { nextNested: 1, resolved: /* @__PURE__ */ new WeakMap() };
|
|
7631
7930
|
}
|
|
7632
7931
|
var SectionBookmarkRegistry = class {
|
|
7633
|
-
fallback =
|
|
7634
|
-
scopes = new
|
|
7932
|
+
fallback = createState4();
|
|
7933
|
+
scopes = new AsyncLocalStorage8();
|
|
7635
7934
|
get state() {
|
|
7636
7935
|
return this.scopes.getStore() ?? this.fallback;
|
|
7637
7936
|
}
|
|
7638
7937
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
7639
7938
|
runScoped(callback) {
|
|
7640
|
-
return this.scopes.run(
|
|
7939
|
+
return this.scopes.run(createState4(), callback);
|
|
7641
7940
|
}
|
|
7642
7941
|
/**
|
|
7643
7942
|
* The bookmark for a layout section, derived from its ordinal.
|
|
@@ -7668,7 +7967,7 @@ var SectionBookmarkRegistry = class {
|
|
|
7668
7967
|
/** Test-only: reset the unscoped fallback counters. */
|
|
7669
7968
|
clear() {
|
|
7670
7969
|
if (!this.scopes.getStore()) {
|
|
7671
|
-
this.fallback =
|
|
7970
|
+
this.fallback = createState4();
|
|
7672
7971
|
}
|
|
7673
7972
|
}
|
|
7674
7973
|
};
|
|
@@ -7681,7 +7980,7 @@ async function renderSectionComponent(component, theme, themeName, context) {
|
|
|
7681
7980
|
const { id: sectionBookmarkId, linkId: bookmarkLinkId } = globalSectionBookmarkRegistry.forSectionComponent(component);
|
|
7682
7981
|
elements.push(
|
|
7683
7982
|
new Paragraph6({
|
|
7684
|
-
children: [new
|
|
7983
|
+
children: [new BookmarkStart2(sectionBookmarkId, bookmarkLinkId)],
|
|
7685
7984
|
spacing: {
|
|
7686
7985
|
before: 0,
|
|
7687
7986
|
after: 0,
|
|
@@ -7709,7 +8008,7 @@ async function renderSectionComponent(component, theme, themeName, context) {
|
|
|
7709
8008
|
}
|
|
7710
8009
|
elements.push(
|
|
7711
8010
|
new Paragraph6({
|
|
7712
|
-
children: [new
|
|
8011
|
+
children: [new BookmarkEnd2(bookmarkLinkId)],
|
|
7713
8012
|
spacing: {
|
|
7714
8013
|
before: 0,
|
|
7715
8014
|
after: 0,
|
|
@@ -7889,7 +8188,10 @@ function selectCachedEntries(collected, options) {
|
|
|
7889
8188
|
continue;
|
|
7890
8189
|
}
|
|
7891
8190
|
if (entry.level < depthStart || entry.level > depthEnd) continue;
|
|
7892
|
-
entries.push({
|
|
8191
|
+
entries.push({
|
|
8192
|
+
title: entry.number ? `${headingNumberLabel(entry.number)} ${entry.title}` : entry.title,
|
|
8193
|
+
level: entry.level
|
|
8194
|
+
});
|
|
7893
8195
|
}
|
|
7894
8196
|
return entries;
|
|
7895
8197
|
}
|
|
@@ -8197,6 +8499,61 @@ function computeSectionOrdinals(sections) {
|
|
|
8197
8499
|
|
|
8198
8500
|
// src/core/collectTocHeadings.ts
|
|
8199
8501
|
import { getStandardComponent } from "@json-to-office/shared-docx";
|
|
8502
|
+
|
|
8503
|
+
// src/utils/numberFormatting.ts
|
|
8504
|
+
var ROMAN_NUMERALS = [
|
|
8505
|
+
[1e3, "m"],
|
|
8506
|
+
[900, "cm"],
|
|
8507
|
+
[500, "d"],
|
|
8508
|
+
[400, "cd"],
|
|
8509
|
+
[100, "c"],
|
|
8510
|
+
[90, "xc"],
|
|
8511
|
+
[50, "l"],
|
|
8512
|
+
[40, "xl"],
|
|
8513
|
+
[10, "x"],
|
|
8514
|
+
[9, "ix"],
|
|
8515
|
+
[5, "v"],
|
|
8516
|
+
[4, "iv"],
|
|
8517
|
+
[1, "i"]
|
|
8518
|
+
];
|
|
8519
|
+
function toRoman(value) {
|
|
8520
|
+
let remaining = value;
|
|
8521
|
+
let out = "";
|
|
8522
|
+
for (const [amount, glyph] of ROMAN_NUMERALS) {
|
|
8523
|
+
while (remaining >= amount) {
|
|
8524
|
+
out += glyph;
|
|
8525
|
+
remaining -= amount;
|
|
8526
|
+
}
|
|
8527
|
+
}
|
|
8528
|
+
return out;
|
|
8529
|
+
}
|
|
8530
|
+
function toLetters(value) {
|
|
8531
|
+
const index = (value - 1) % 26;
|
|
8532
|
+
const repeats = Math.floor((value - 1) / 26) + 1;
|
|
8533
|
+
return String.fromCharCode(97 + index).repeat(repeats);
|
|
8534
|
+
}
|
|
8535
|
+
function formatNumberForLevel(value, format2) {
|
|
8536
|
+
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
8537
|
+
const n = Math.floor(value);
|
|
8538
|
+
switch (format2) {
|
|
8539
|
+
case "decimal":
|
|
8540
|
+
return String(n);
|
|
8541
|
+
case "lowerLetter":
|
|
8542
|
+
return toLetters(n);
|
|
8543
|
+
case "upperLetter":
|
|
8544
|
+
return toLetters(n).toUpperCase();
|
|
8545
|
+
case "lowerRoman":
|
|
8546
|
+
return toRoman(n);
|
|
8547
|
+
case "upperRoman":
|
|
8548
|
+
return toRoman(n).toUpperCase();
|
|
8549
|
+
default:
|
|
8550
|
+
return void 0;
|
|
8551
|
+
}
|
|
8552
|
+
}
|
|
8553
|
+
|
|
8554
|
+
// src/core/collectTocHeadings.ts
|
|
8555
|
+
var MAX_HEADING_LEVEL2 = 6;
|
|
8556
|
+
var MAX_LIST_LEVEL = 9;
|
|
8200
8557
|
function normalizeEntryTitle(text) {
|
|
8201
8558
|
return normalizeUnicodeText(text).replace(/(\*\*\*|___)([\s\S]*?)\1/g, "$2").replace(/(\*\*|__)([\s\S]*?)\1/g, "$2").replace(/(\*|_)([\s\S]*?)\1/g, "$2").trim();
|
|
8202
8559
|
}
|
|
@@ -8215,9 +8572,97 @@ function styleEntryKey(props) {
|
|
|
8215
8572
|
}
|
|
8216
8573
|
return themeStyle;
|
|
8217
8574
|
}
|
|
8218
|
-
function
|
|
8575
|
+
function levelStart(levels, level) {
|
|
8576
|
+
return levels[level]?.start ?? 1;
|
|
8577
|
+
}
|
|
8578
|
+
function collectDocumentOutline(sections) {
|
|
8219
8579
|
const entries = [];
|
|
8580
|
+
const numberedItems = /* @__PURE__ */ new Map();
|
|
8220
8581
|
const ordinals = computeSectionOrdinals(sections);
|
|
8582
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
8583
|
+
const headingCounters = new Array(MAX_HEADING_LEVEL2).fill(0);
|
|
8584
|
+
const listCounters = /* @__PURE__ */ new Map();
|
|
8585
|
+
const visitHeading = (component, props, sectionBookmarkId) => {
|
|
8586
|
+
const text = typeof props.text === "string" ? props.text : "";
|
|
8587
|
+
const title = normalizeEntryTitle(text);
|
|
8588
|
+
const level = typeof props.level === "number" ? props.level : 1;
|
|
8589
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL2 ? level : 1;
|
|
8590
|
+
let full;
|
|
8591
|
+
let own;
|
|
8592
|
+
if (props.numbering === true) {
|
|
8593
|
+
headingCounters[styleLevel - 1] += 1;
|
|
8594
|
+
for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL2; deeper++) {
|
|
8595
|
+
headingCounters[deeper] = 0;
|
|
8596
|
+
}
|
|
8597
|
+
full = headingCounters.slice(0, styleLevel).join(".");
|
|
8598
|
+
own = String(headingCounters[styleLevel - 1]);
|
|
8599
|
+
}
|
|
8600
|
+
const explicitId = component.id;
|
|
8601
|
+
const bookmarkId = typeof explicitId === "string" && explicitId ? explicitId : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));
|
|
8602
|
+
takenIds.add(bookmarkId);
|
|
8603
|
+
numberedItems.set(bookmarkId, {
|
|
8604
|
+
kind: "heading",
|
|
8605
|
+
text: title,
|
|
8606
|
+
...full !== void 0 && { full, own }
|
|
8607
|
+
});
|
|
8608
|
+
if (title) {
|
|
8609
|
+
entries.push({
|
|
8610
|
+
title,
|
|
8611
|
+
level,
|
|
8612
|
+
sectionBookmarkId,
|
|
8613
|
+
...full !== void 0 && { number: full }
|
|
8614
|
+
});
|
|
8615
|
+
}
|
|
8616
|
+
};
|
|
8617
|
+
const visitList = (props) => {
|
|
8618
|
+
const items = Array.isArray(props.items) ? props.items : [];
|
|
8619
|
+
if (items.length === 0) return;
|
|
8620
|
+
const reference = typeof props.reference === "string" && props.reference ? props.reference : void 0;
|
|
8621
|
+
const freshState = () => {
|
|
8622
|
+
const levels = resolveListLevels(
|
|
8623
|
+
props
|
|
8624
|
+
);
|
|
8625
|
+
return {
|
|
8626
|
+
levels,
|
|
8627
|
+
counters: Array.from(
|
|
8628
|
+
{ length: MAX_LIST_LEVEL },
|
|
8629
|
+
(_, level) => levelStart(levels, level) - 1
|
|
8630
|
+
)
|
|
8631
|
+
};
|
|
8632
|
+
};
|
|
8633
|
+
let state;
|
|
8634
|
+
if (reference === void 0) {
|
|
8635
|
+
state = freshState();
|
|
8636
|
+
} else {
|
|
8637
|
+
state = listCounters.get(reference) ?? freshState();
|
|
8638
|
+
listCounters.set(reference, state);
|
|
8639
|
+
}
|
|
8640
|
+
for (const item of items) {
|
|
8641
|
+
const isObject = typeof item === "object" && item !== null;
|
|
8642
|
+
const raw = isObject ? item.text : item;
|
|
8643
|
+
const text = typeof raw === "string" ? raw : "";
|
|
8644
|
+
if (!text.trim() && !(isObject && item.revision)) continue;
|
|
8645
|
+
const rawLevel = isObject ? item.level : void 0;
|
|
8646
|
+
const level = typeof rawLevel === "number" && rawLevel >= 0 ? rawLevel : 0;
|
|
8647
|
+
if (level >= MAX_LIST_LEVEL) continue;
|
|
8648
|
+
state.counters[level] += 1;
|
|
8649
|
+
for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {
|
|
8650
|
+
state.counters[deeper] = levelStart(state.levels, deeper) - 1;
|
|
8651
|
+
}
|
|
8652
|
+
const id = isObject ? item.id : void 0;
|
|
8653
|
+
if (typeof id !== "string" || !id) continue;
|
|
8654
|
+
takenIds.add(id);
|
|
8655
|
+
const number = formatNumberForLevel(
|
|
8656
|
+
state.counters[level],
|
|
8657
|
+
state.levels[level]?.format
|
|
8658
|
+
);
|
|
8659
|
+
numberedItems.set(id, {
|
|
8660
|
+
kind: "list-item",
|
|
8661
|
+
text: normalizeUnicodeText(text).trim(),
|
|
8662
|
+
...number !== void 0 && { full: number, own: number }
|
|
8663
|
+
});
|
|
8664
|
+
}
|
|
8665
|
+
};
|
|
8221
8666
|
sections.forEach((section, index) => {
|
|
8222
8667
|
const ordinal = ordinals[index]?.ordinal;
|
|
8223
8668
|
const sectionBookmarkId = ordinal ? globalSectionBookmarkRegistry.forLayoutSection(ordinal).id : void 0;
|
|
@@ -8225,15 +8670,11 @@ function collectTocHeadings(sections) {
|
|
|
8225
8670
|
if (!isEnabled(component)) return;
|
|
8226
8671
|
const props = component.props ?? {};
|
|
8227
8672
|
if (component.name === "heading") {
|
|
8228
|
-
|
|
8229
|
-
const title = normalizeEntryTitle(text);
|
|
8230
|
-
if (title) {
|
|
8231
|
-
const level = typeof props.level === "number" ? props.level : 1;
|
|
8232
|
-
entries.push({ title, level, sectionBookmarkId });
|
|
8233
|
-
}
|
|
8673
|
+
visitHeading(component, props, sectionBookmarkId);
|
|
8234
8674
|
return;
|
|
8235
8675
|
}
|
|
8236
8676
|
if (component.name === "paragraph") {
|
|
8677
|
+
if (typeof props.id === "string" && props.id) takenIds.add(props.id);
|
|
8237
8678
|
const styleId = styleEntryKey(props);
|
|
8238
8679
|
const text = typeof props.text === "string" ? props.text : "";
|
|
8239
8680
|
const title = normalizeEntryTitle(text);
|
|
@@ -8242,13 +8683,17 @@ function collectTocHeadings(sections) {
|
|
|
8242
8683
|
}
|
|
8243
8684
|
return;
|
|
8244
8685
|
}
|
|
8686
|
+
if (component.name === "list") {
|
|
8687
|
+
visitList(props);
|
|
8688
|
+
return;
|
|
8689
|
+
}
|
|
8245
8690
|
if (!isContainer(component.name)) return;
|
|
8246
8691
|
const children = component.children;
|
|
8247
8692
|
if (Array.isArray(children)) children.forEach(visit);
|
|
8248
8693
|
};
|
|
8249
8694
|
section.components.forEach(visit);
|
|
8250
8695
|
});
|
|
8251
|
-
return entries;
|
|
8696
|
+
return { entries, numberedItems };
|
|
8252
8697
|
}
|
|
8253
8698
|
|
|
8254
8699
|
// src/core/render.ts
|
|
@@ -8301,7 +8746,13 @@ async function renderDocument(structure, layout, options) {
|
|
|
8301
8746
|
// Footnote ids are document-scoped too: a reference resolved
|
|
8302
8747
|
// against another render's counter points at the wrong body.
|
|
8303
8748
|
globalNoteRegistry.runScoped(
|
|
8304
|
-
() =>
|
|
8749
|
+
() => (
|
|
8750
|
+
// Cross-reference targets are keyed by bookmark id, which
|
|
8751
|
+
// is only unique within one document.
|
|
8752
|
+
globalNumberedItemsRegistry.runScoped(
|
|
8753
|
+
() => renderDocumentScoped(structure, layout, options)
|
|
8754
|
+
)
|
|
8755
|
+
)
|
|
8305
8756
|
)
|
|
8306
8757
|
)
|
|
8307
8758
|
)
|
|
@@ -8344,13 +8795,14 @@ async function renderDocumentScoped(structure, layout, options) {
|
|
|
8344
8795
|
);
|
|
8345
8796
|
}
|
|
8346
8797
|
try {
|
|
8347
|
-
const
|
|
8348
|
-
if (
|
|
8349
|
-
context.tocHeadings =
|
|
8798
|
+
const outline = collectDocumentOutline(layout.sections);
|
|
8799
|
+
if (outline.entries.length > 0) {
|
|
8800
|
+
context.tocHeadings = outline.entries;
|
|
8350
8801
|
}
|
|
8802
|
+
globalNumberedItemsRegistry.seed(outline.numberedItems);
|
|
8351
8803
|
} catch (error) {
|
|
8352
8804
|
console.warn(
|
|
8353
|
-
"[core-docx]
|
|
8805
|
+
"[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it:",
|
|
8354
8806
|
error instanceof Error ? error.message : error
|
|
8355
8807
|
);
|
|
8356
8808
|
}
|
|
@@ -8593,7 +9045,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
8593
9045
|
if (sectionBookmarkId && isFirstLayoutOfUserSection && sharedLinkId !== void 0) {
|
|
8594
9046
|
elements.push(
|
|
8595
9047
|
new Paragraph9({
|
|
8596
|
-
children: [new
|
|
9048
|
+
children: [new BookmarkStart3(sectionBookmarkId, sharedLinkId)],
|
|
8597
9049
|
spacing: {
|
|
8598
9050
|
before: 0,
|
|
8599
9051
|
after: 0,
|
|
@@ -8618,7 +9070,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
8618
9070
|
if (closeBookmark && sharedLinkId !== void 0) {
|
|
8619
9071
|
elements.push(
|
|
8620
9072
|
new Paragraph9({
|
|
8621
|
-
children: [new
|
|
9073
|
+
children: [new BookmarkEnd3(sharedLinkId)]
|
|
8622
9074
|
})
|
|
8623
9075
|
);
|
|
8624
9076
|
}
|