@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
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
|
};
|
|
@@ -2635,8 +2623,8 @@ import {
|
|
|
2635
2623
|
Paragraph as Paragraph9,
|
|
2636
2624
|
TextRun as TextRun9,
|
|
2637
2625
|
AlignmentType as AlignmentType5,
|
|
2638
|
-
BookmarkStart as
|
|
2639
|
-
BookmarkEnd as
|
|
2626
|
+
BookmarkStart as BookmarkStart3,
|
|
2627
|
+
BookmarkEnd as BookmarkEnd3
|
|
2640
2628
|
} from "docx";
|
|
2641
2629
|
|
|
2642
2630
|
// src/utils/imageUtils.ts
|
|
@@ -3752,8 +3740,51 @@ import {
|
|
|
3752
3740
|
InternalHyperlink,
|
|
3753
3741
|
FootnoteReferenceRun,
|
|
3754
3742
|
EndnoteReferenceRun,
|
|
3743
|
+
NumberedItemReference,
|
|
3744
|
+
NumberedItemReferenceFormat,
|
|
3755
3745
|
Tab
|
|
3756
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
|
|
3757
3788
|
var FOOTNOTE_MARKER_REGEX = /\[\^([^\]\s]+)\]/;
|
|
3758
3789
|
function escapeRegExp(s) {
|
|
3759
3790
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3969,13 +4000,59 @@ function splitNoteMarkers(text, noteRef, runs) {
|
|
|
3969
4000
|
if (trailing) out.push(...runs(trailing));
|
|
3970
4001
|
return out;
|
|
3971
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
|
+
}
|
|
3972
4049
|
function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
3973
4050
|
const normalizedText = normalizeUnicodeText(text);
|
|
3974
4051
|
const runs = [];
|
|
3975
|
-
const
|
|
4052
|
+
const tokenRegex = new RegExp(INLINE_TOKEN_REGEX, "g");
|
|
3976
4053
|
let lastIndex = 0;
|
|
3977
4054
|
let match;
|
|
3978
|
-
while ((match =
|
|
4055
|
+
while ((match = tokenRegex.exec(normalizedText)) !== null) {
|
|
3979
4056
|
if (match.index > lastIndex) {
|
|
3980
4057
|
const plainText = normalizedText.substring(lastIndex, match.index);
|
|
3981
4058
|
if (plainText) {
|
|
@@ -3987,6 +4064,19 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
3987
4064
|
runs.push(...plainRuns);
|
|
3988
4065
|
}
|
|
3989
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
|
+
}
|
|
3990
4080
|
const linkText = match[1];
|
|
3991
4081
|
const linkUrl = match[2];
|
|
3992
4082
|
const isInternal = linkUrl.startsWith("#");
|
|
@@ -4013,7 +4103,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
4013
4103
|
})
|
|
4014
4104
|
);
|
|
4015
4105
|
}
|
|
4016
|
-
lastIndex = match.index + match[0].length;
|
|
4017
4106
|
}
|
|
4018
4107
|
if (lastIndex < normalizedText.length) {
|
|
4019
4108
|
const remainingText = normalizedText.substring(lastIndex);
|
|
@@ -4222,7 +4311,7 @@ function initializeBuiltinPlaceholders() {
|
|
|
4222
4311
|
initializeBuiltinPlaceholders();
|
|
4223
4312
|
|
|
4224
4313
|
// src/utils/revisionUtils.ts
|
|
4225
|
-
import { AsyncLocalStorage as
|
|
4314
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
4226
4315
|
|
|
4227
4316
|
// src/utils/componentAnnotations.ts
|
|
4228
4317
|
function isRecord(value) {
|
|
@@ -4273,7 +4362,7 @@ var DEFAULT_REVISION_AUTHOR = "json-to-office";
|
|
|
4273
4362
|
var DEFAULT_REVISION_DATE = "1970-01-01T00:00:00Z";
|
|
4274
4363
|
var RevisionIdRegistry = class {
|
|
4275
4364
|
fallbackCounter = 0;
|
|
4276
|
-
scopes = new
|
|
4365
|
+
scopes = new AsyncLocalStorage3();
|
|
4277
4366
|
runScoped(callback) {
|
|
4278
4367
|
return this.scopes.run({ counter: 0 }, callback);
|
|
4279
4368
|
}
|
|
@@ -4548,23 +4637,38 @@ import {
|
|
|
4548
4637
|
PageNumber as PageNumber2,
|
|
4549
4638
|
ColumnBreak,
|
|
4550
4639
|
TableLayoutType,
|
|
4551
|
-
VerticalAlign
|
|
4552
|
-
Bookmark
|
|
4640
|
+
VerticalAlign
|
|
4553
4641
|
} from "docx";
|
|
4554
4642
|
init_styles();
|
|
4555
4643
|
init_defaults();
|
|
4556
4644
|
|
|
4557
4645
|
// src/utils/bookmarkRegistry.ts
|
|
4558
|
-
import { AsyncLocalStorage as
|
|
4646
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
4647
|
+
import { BookmarkStart, BookmarkEnd } from "docx";
|
|
4648
|
+
var CONTENT_LINK_ID_BASE = 2e6;
|
|
4649
|
+
function createState() {
|
|
4650
|
+
return { bookmarks: /* @__PURE__ */ new Map(), nextLinkId: CONTENT_LINK_ID_BASE + 1 };
|
|
4651
|
+
}
|
|
4652
|
+
function slugifyBookmarkText(text) {
|
|
4653
|
+
return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 40);
|
|
4654
|
+
}
|
|
4655
|
+
function dedupeBookmarkId(base, taken) {
|
|
4656
|
+
let id = base;
|
|
4657
|
+
let attempt = 0;
|
|
4658
|
+
while (taken(id) && attempt < 100) {
|
|
4659
|
+
id = `${base}-${++attempt}`;
|
|
4660
|
+
}
|
|
4661
|
+
return id;
|
|
4662
|
+
}
|
|
4559
4663
|
var BookmarkRegistry = class {
|
|
4560
|
-
fallback =
|
|
4561
|
-
scopes = new
|
|
4664
|
+
fallback = createState();
|
|
4665
|
+
scopes = new AsyncLocalStorage4();
|
|
4562
4666
|
get state() {
|
|
4563
4667
|
return this.scopes.getStore() ?? this.fallback;
|
|
4564
4668
|
}
|
|
4565
4669
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
4566
4670
|
runScoped(callback) {
|
|
4567
|
-
return this.scopes.run(
|
|
4671
|
+
return this.scopes.run(createState(), callback);
|
|
4568
4672
|
}
|
|
4569
4673
|
/**
|
|
4570
4674
|
* Register a bookmark
|
|
@@ -4577,18 +4681,28 @@ var BookmarkRegistry = class {
|
|
|
4577
4681
|
}
|
|
4578
4682
|
this.state.bookmarks.set(id, { id, title, type });
|
|
4579
4683
|
}
|
|
4684
|
+
/**
|
|
4685
|
+
* A `w:id` no other bookmark in this document will use.
|
|
4686
|
+
*
|
|
4687
|
+
* docx's own `Bookmark` cannot supply one: its constructor builds a fresh
|
|
4688
|
+
* id generator per instance (`bookmarkUniqueNumericIdGen()`), so every
|
|
4689
|
+
* bookmark it emits carries `w:id="1"`. Reported upstream as dolanmiu/docx
|
|
4690
|
+
* #3478, still unreleased as of 9.7.1. Duplicated ids leave the start/end
|
|
4691
|
+
* pairing ambiguous, which is why a `REF` field could not read a target's
|
|
4692
|
+
* text even though navigating to it by name worked.
|
|
4693
|
+
*/
|
|
4694
|
+
allocateLinkId() {
|
|
4695
|
+
return this.state.nextLinkId++;
|
|
4696
|
+
}
|
|
4580
4697
|
/**
|
|
4581
4698
|
* Generate a unique bookmark ID from text
|
|
4582
4699
|
* Converts text to a URL-friendly format
|
|
4583
4700
|
*/
|
|
4584
4701
|
generateId(text, _type = "bookmark") {
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
id = `${baseId}-${++attempt}`;
|
|
4590
|
-
}
|
|
4591
|
-
return id;
|
|
4702
|
+
return dedupeBookmarkId(
|
|
4703
|
+
slugifyBookmarkText(text),
|
|
4704
|
+
(id) => this.state.bookmarks.has(id)
|
|
4705
|
+
);
|
|
4592
4706
|
}
|
|
4593
4707
|
/**
|
|
4594
4708
|
* Check if a bookmark exists
|
|
@@ -4629,6 +4743,14 @@ var BookmarkRegistry = class {
|
|
|
4629
4743
|
}
|
|
4630
4744
|
};
|
|
4631
4745
|
var globalBookmarkRegistry = new BookmarkRegistry();
|
|
4746
|
+
function createBookmarkedContent(name, children) {
|
|
4747
|
+
const linkId = globalBookmarkRegistry.allocateLinkId();
|
|
4748
|
+
return [
|
|
4749
|
+
new BookmarkStart(name, linkId),
|
|
4750
|
+
...children,
|
|
4751
|
+
new BookmarkEnd(linkId)
|
|
4752
|
+
];
|
|
4753
|
+
}
|
|
4632
4754
|
|
|
4633
4755
|
// src/utils/commentAnchors.ts
|
|
4634
4756
|
import {
|
|
@@ -4640,10 +4762,10 @@ import {
|
|
|
4640
4762
|
|
|
4641
4763
|
// src/utils/commentRegistry.ts
|
|
4642
4764
|
import { Paragraph, TextRun as TextRun4 } from "docx";
|
|
4643
|
-
import { AsyncLocalStorage as
|
|
4765
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
|
|
4644
4766
|
var DEFAULT_COMMENT_AUTHOR = "json-to-office";
|
|
4645
4767
|
var DEFAULT_COMMENT_DATE = "1970-01-01T00:00:00Z";
|
|
4646
|
-
function
|
|
4768
|
+
function createState2() {
|
|
4647
4769
|
return { counter: 0, comments: [], hasResolved: false };
|
|
4648
4770
|
}
|
|
4649
4771
|
function deriveInitials(author) {
|
|
@@ -4654,14 +4776,14 @@ function bodyParagraphs(text) {
|
|
|
4654
4776
|
return normalizeUnicodeText(text).split("\n").map((line) => new Paragraph({ children: [new TextRun4({ text: line })] }));
|
|
4655
4777
|
}
|
|
4656
4778
|
var CommentRegistry = class {
|
|
4657
|
-
fallback =
|
|
4658
|
-
scopes = new
|
|
4779
|
+
fallback = createState2();
|
|
4780
|
+
scopes = new AsyncLocalStorage5();
|
|
4659
4781
|
get state() {
|
|
4660
4782
|
return this.scopes.getStore() ?? this.fallback;
|
|
4661
4783
|
}
|
|
4662
4784
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
4663
4785
|
runScoped(callback) {
|
|
4664
|
-
return this.scopes.run(
|
|
4786
|
+
return this.scopes.run(createState2(), callback);
|
|
4665
4787
|
}
|
|
4666
4788
|
/**
|
|
4667
4789
|
* Register a comment thread and return every id its anchors must carry — the
|
|
@@ -4729,7 +4851,7 @@ var CommentRegistry = class {
|
|
|
4729
4851
|
state.comments.length = 0;
|
|
4730
4852
|
state.hasResolved = false;
|
|
4731
4853
|
} else {
|
|
4732
|
-
this.fallback =
|
|
4854
|
+
this.fallback = createState2();
|
|
4733
4855
|
}
|
|
4734
4856
|
}
|
|
4735
4857
|
};
|
|
@@ -4750,8 +4872,8 @@ function closeCommentRange(ids) {
|
|
|
4750
4872
|
|
|
4751
4873
|
// src/utils/noteRegistry.ts
|
|
4752
4874
|
import { Paragraph as Paragraph2, TextRun as TextRun6 } from "docx";
|
|
4753
|
-
import { AsyncLocalStorage as
|
|
4754
|
-
function
|
|
4875
|
+
import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
|
|
4876
|
+
function createState3() {
|
|
4755
4877
|
return {
|
|
4756
4878
|
footnoteCounter: 0,
|
|
4757
4879
|
endnoteCounter: 0,
|
|
@@ -4768,14 +4890,14 @@ function bodyParagraphs2(text, style) {
|
|
|
4768
4890
|
);
|
|
4769
4891
|
}
|
|
4770
4892
|
var NoteRegistry = class {
|
|
4771
|
-
fallback =
|
|
4772
|
-
scopes = new
|
|
4893
|
+
fallback = createState3();
|
|
4894
|
+
scopes = new AsyncLocalStorage6();
|
|
4773
4895
|
get state() {
|
|
4774
4896
|
return this.scopes.getStore() ?? this.fallback;
|
|
4775
4897
|
}
|
|
4776
4898
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
4777
4899
|
runScoped(callback) {
|
|
4778
|
-
return this.scopes.run(
|
|
4900
|
+
return this.scopes.run(createState3(), callback);
|
|
4779
4901
|
}
|
|
4780
4902
|
/**
|
|
4781
4903
|
* Register a footnote body and return the id its reference must use. Ids are
|
|
@@ -4819,7 +4941,7 @@ var NoteRegistry = class {
|
|
|
4819
4941
|
delete state.endnotes[key];
|
|
4820
4942
|
}
|
|
4821
4943
|
} else {
|
|
4822
|
-
this.fallback =
|
|
4944
|
+
this.fallback = createState3();
|
|
4823
4945
|
}
|
|
4824
4946
|
}
|
|
4825
4947
|
};
|
|
@@ -4985,10 +5107,7 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4985
5107
|
"paragraph"
|
|
4986
5108
|
);
|
|
4987
5109
|
children.push(
|
|
4988
|
-
|
|
4989
|
-
id: options.bookmarkId,
|
|
4990
|
-
children: revisionRuns
|
|
4991
|
-
})
|
|
5110
|
+
...createBookmarkedContent(options.bookmarkId, revisionRuns)
|
|
4992
5111
|
);
|
|
4993
5112
|
} else {
|
|
4994
5113
|
children.push(...revisionRuns);
|
|
@@ -5011,12 +5130,7 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
5011
5130
|
normalizedContent,
|
|
5012
5131
|
"paragraph"
|
|
5013
5132
|
);
|
|
5014
|
-
children.push(
|
|
5015
|
-
new Bookmark({
|
|
5016
|
-
id: options.bookmarkId,
|
|
5017
|
-
children: textRuns
|
|
5018
|
-
})
|
|
5019
|
-
);
|
|
5133
|
+
children.push(...createBookmarkedContent(options.bookmarkId, textRuns));
|
|
5020
5134
|
} else {
|
|
5021
5135
|
children.push(...textRuns);
|
|
5022
5136
|
}
|
|
@@ -5125,7 +5239,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5125
5239
|
if (commentAnchor) {
|
|
5126
5240
|
children.push(...commentAnchor.start);
|
|
5127
5241
|
}
|
|
5128
|
-
const
|
|
5242
|
+
const hasInlineSyntax = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText) || hasCrossReference(normalizedText);
|
|
5129
5243
|
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
5130
5244
|
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
5131
5245
|
const headingWeighted = applyFontWeightAlias({
|
|
@@ -5177,10 +5291,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5177
5291
|
"heading"
|
|
5178
5292
|
);
|
|
5179
5293
|
children.push(
|
|
5180
|
-
|
|
5181
|
-
id: options.bookmarkId,
|
|
5182
|
-
children: revisionRuns
|
|
5183
|
-
})
|
|
5294
|
+
...createBookmarkedContent(options.bookmarkId, revisionRuns)
|
|
5184
5295
|
);
|
|
5185
5296
|
} else {
|
|
5186
5297
|
children.push(...revisionRuns);
|
|
@@ -5192,7 +5303,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5192
5303
|
"heading"
|
|
5193
5304
|
);
|
|
5194
5305
|
const headingTextChildren = [];
|
|
5195
|
-
if (
|
|
5306
|
+
if (hasInlineSyntax) {
|
|
5196
5307
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
5197
5308
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
5198
5309
|
enableHyperlinks: true,
|
|
@@ -5203,13 +5314,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5203
5314
|
headingTextChildren.push(...makeHeadingRuns(normalizedText));
|
|
5204
5315
|
}
|
|
5205
5316
|
children.push(
|
|
5206
|
-
|
|
5207
|
-
id: options.bookmarkId,
|
|
5208
|
-
children: headingTextChildren
|
|
5209
|
-
})
|
|
5317
|
+
...createBookmarkedContent(options.bookmarkId, headingTextChildren)
|
|
5210
5318
|
);
|
|
5211
5319
|
} else {
|
|
5212
|
-
if (
|
|
5320
|
+
if (hasInlineSyntax) {
|
|
5213
5321
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
5214
5322
|
boldColor: options.boldColor ? resolveColor(options.boldColor, theme) : void 0,
|
|
5215
5323
|
enableHyperlinks: true,
|
|
@@ -5231,7 +5339,10 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
5231
5339
|
spacing: hasExplicitSpacing ? spacing : void 0,
|
|
5232
5340
|
...options.keepNext !== void 0 && { keepNext: options.keepNext },
|
|
5233
5341
|
...options.keepLines !== void 0 && { keepLines: options.keepLines },
|
|
5234
|
-
...options.indent && { indent: options.indent }
|
|
5342
|
+
...options.indent && { indent: options.indent },
|
|
5343
|
+
// docx creates the concrete numbering instance for the reference itself,
|
|
5344
|
+
// in ParagraphProperties.prepForXml.
|
|
5345
|
+
...options.numbering !== void 0 && { numbering: options.numbering }
|
|
5235
5346
|
});
|
|
5236
5347
|
}
|
|
5237
5348
|
async function createImage(path4, theme, themeName, options = {}) {
|
|
@@ -5391,9 +5502,15 @@ function createList(items, _theme, _themeName, options = {}) {
|
|
|
5391
5502
|
} else if (options.spacing?.item) {
|
|
5392
5503
|
spacing.after = pointsToTwips(options.spacing.item);
|
|
5393
5504
|
}
|
|
5505
|
+
const itemId = typeof item === "object" ? item.id : void 0;
|
|
5506
|
+
let itemContent = textRuns;
|
|
5507
|
+
if (itemId) {
|
|
5508
|
+
globalBookmarkRegistry.register(itemId, itemText, "list-item");
|
|
5509
|
+
itemContent = createBookmarkedContent(itemId, textRuns);
|
|
5510
|
+
}
|
|
5394
5511
|
const paragraphChildren = [
|
|
5395
5512
|
...commentAnchor && index === firstRendered ? commentAnchor.start : [],
|
|
5396
|
-
...
|
|
5513
|
+
...itemContent,
|
|
5397
5514
|
...commentAnchor && index === lastRendered ? closeCommentRange(commentAnchor.ids) : []
|
|
5398
5515
|
];
|
|
5399
5516
|
const paragraph = new Paragraph3({
|
|
@@ -6236,54 +6353,14 @@ function createFooterElement(children, _options) {
|
|
|
6236
6353
|
});
|
|
6237
6354
|
}
|
|
6238
6355
|
|
|
6239
|
-
// src/components/heading.ts
|
|
6240
|
-
function renderHeadingComponent(component, theme, themeName) {
|
|
6241
|
-
if (!isHeadingComponent(component)) return [];
|
|
6242
|
-
const config = component.props;
|
|
6243
|
-
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6244
|
-
const header = createHeading(
|
|
6245
|
-
config.text,
|
|
6246
|
-
config.level || 1,
|
|
6247
|
-
theme,
|
|
6248
|
-
themeName,
|
|
6249
|
-
{
|
|
6250
|
-
alignment: config.alignment,
|
|
6251
|
-
spacing: config.spacing,
|
|
6252
|
-
lineSpacing: config.lineSpacing,
|
|
6253
|
-
columnBreak: config.columnBreak,
|
|
6254
|
-
// Local font overrides
|
|
6255
|
-
fontFamily: config.font?.family,
|
|
6256
|
-
fontSize: config.font?.size,
|
|
6257
|
-
fontColor: config.font?.color,
|
|
6258
|
-
bold: config.font?.bold,
|
|
6259
|
-
fontWeight: config.font?.fontWeight,
|
|
6260
|
-
italic: config.font?.italic,
|
|
6261
|
-
underline: config.font?.underline,
|
|
6262
|
-
scale: config.font?.scale,
|
|
6263
|
-
characterSpacing: config.font?.characterSpacing,
|
|
6264
|
-
// Proofing: local language override + no-proof toggle + known-words list
|
|
6265
|
-
language: config.language,
|
|
6266
|
-
noProof: config.noProof,
|
|
6267
|
-
noProofWords: config.noProofWords,
|
|
6268
|
-
// Pagination control
|
|
6269
|
-
keepNext: config.keepNext,
|
|
6270
|
-
keepLines: config.keepLines,
|
|
6271
|
-
// Paragraph indentation (w:ind) in twips
|
|
6272
|
-
indent: config.indent,
|
|
6273
|
-
// Bookmark ID for internal linking
|
|
6274
|
-
bookmarkId,
|
|
6275
|
-
// Tracked-change segments (rendered as native Word revisions)
|
|
6276
|
-
revision: config.revision,
|
|
6277
|
-
// Review comment anchored to this heading's text
|
|
6278
|
-
comment: config.comment
|
|
6279
|
-
}
|
|
6280
|
-
);
|
|
6281
|
-
return [header];
|
|
6282
|
-
}
|
|
6283
|
-
|
|
6284
6356
|
// src/utils/numberingConfig.ts
|
|
6285
|
-
import {
|
|
6286
|
-
|
|
6357
|
+
import {
|
|
6358
|
+
AlignmentType as AlignmentType3,
|
|
6359
|
+
convertInchesToTwip,
|
|
6360
|
+
LevelFormat,
|
|
6361
|
+
LevelSuffix
|
|
6362
|
+
} from "docx";
|
|
6363
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "async_hooks";
|
|
6287
6364
|
var LEVEL_FORMAT_MAP = {
|
|
6288
6365
|
decimal: LevelFormat.DECIMAL,
|
|
6289
6366
|
upperRoman: LevelFormat.UPPER_ROMAN,
|
|
@@ -6411,12 +6488,37 @@ function createNumberingConfig(config) {
|
|
|
6411
6488
|
levels
|
|
6412
6489
|
};
|
|
6413
6490
|
}
|
|
6491
|
+
var HEADING_NUMBERING_REFERENCE = "jto-heading-numbering";
|
|
6492
|
+
function createHeadingNumberingConfig() {
|
|
6493
|
+
const levels = [];
|
|
6494
|
+
for (let level = 0; level < 6; level++) {
|
|
6495
|
+
const text = Array.from({ length: level + 1 }, (_, i) => `%${i + 1}`).join(".") + ".";
|
|
6496
|
+
levels.push({
|
|
6497
|
+
level,
|
|
6498
|
+
format: LevelFormat.DECIMAL,
|
|
6499
|
+
text,
|
|
6500
|
+
alignment: AlignmentType3.LEFT,
|
|
6501
|
+
start: 1,
|
|
6502
|
+
// A space, not the default tab: a tab would push the heading text to the
|
|
6503
|
+
// next tab stop and misalign it against unnumbered headings.
|
|
6504
|
+
suffix: LevelSuffix.SPACE,
|
|
6505
|
+
style: {
|
|
6506
|
+
paragraph: { indent: { left: 0, hanging: 0 } },
|
|
6507
|
+
style: `Heading${level + 1}`
|
|
6508
|
+
}
|
|
6509
|
+
});
|
|
6510
|
+
}
|
|
6511
|
+
return { reference: HEADING_NUMBERING_REFERENCE, levels };
|
|
6512
|
+
}
|
|
6513
|
+
function headingNumberLabel(number) {
|
|
6514
|
+
return `${number}.`;
|
|
6515
|
+
}
|
|
6414
6516
|
var NumberingRegistry = class {
|
|
6415
6517
|
fallback = {
|
|
6416
6518
|
configs: /* @__PURE__ */ new Map(),
|
|
6417
6519
|
counter: 0
|
|
6418
6520
|
};
|
|
6419
|
-
scopes = new
|
|
6521
|
+
scopes = new AsyncLocalStorage7();
|
|
6420
6522
|
get state() {
|
|
6421
6523
|
return this.scopes.getStore() ?? this.fallback;
|
|
6422
6524
|
}
|
|
@@ -6466,6 +6568,63 @@ var NumberingRegistry = class {
|
|
|
6466
6568
|
};
|
|
6467
6569
|
var globalNumberingRegistry = new NumberingRegistry();
|
|
6468
6570
|
|
|
6571
|
+
// src/components/heading.ts
|
|
6572
|
+
var MAX_HEADING_LEVEL = 6;
|
|
6573
|
+
function headingNumbering(numbering, level) {
|
|
6574
|
+
if (numbering === false) return false;
|
|
6575
|
+
if (numbering !== true) return void 0;
|
|
6576
|
+
if (!globalNumberingRegistry.has(HEADING_NUMBERING_REFERENCE)) {
|
|
6577
|
+
globalNumberingRegistry.register(createHeadingNumberingConfig());
|
|
6578
|
+
}
|
|
6579
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;
|
|
6580
|
+
return { reference: HEADING_NUMBERING_REFERENCE, level: styleLevel - 1 };
|
|
6581
|
+
}
|
|
6582
|
+
function renderHeadingComponent(component, theme, themeName) {
|
|
6583
|
+
if (!isHeadingComponent(component)) return [];
|
|
6584
|
+
const config = component.props;
|
|
6585
|
+
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
6586
|
+
const header = createHeading(
|
|
6587
|
+
config.text,
|
|
6588
|
+
config.level || 1,
|
|
6589
|
+
theme,
|
|
6590
|
+
themeName,
|
|
6591
|
+
{
|
|
6592
|
+
alignment: config.alignment,
|
|
6593
|
+
spacing: config.spacing,
|
|
6594
|
+
lineSpacing: config.lineSpacing,
|
|
6595
|
+
columnBreak: config.columnBreak,
|
|
6596
|
+
// Local font overrides
|
|
6597
|
+
fontFamily: config.font?.family,
|
|
6598
|
+
fontSize: config.font?.size,
|
|
6599
|
+
fontColor: config.font?.color,
|
|
6600
|
+
bold: config.font?.bold,
|
|
6601
|
+
fontWeight: config.font?.fontWeight,
|
|
6602
|
+
italic: config.font?.italic,
|
|
6603
|
+
underline: config.font?.underline,
|
|
6604
|
+
scale: config.font?.scale,
|
|
6605
|
+
characterSpacing: config.font?.characterSpacing,
|
|
6606
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
6607
|
+
language: config.language,
|
|
6608
|
+
noProof: config.noProof,
|
|
6609
|
+
noProofWords: config.noProofWords,
|
|
6610
|
+
// Pagination control
|
|
6611
|
+
keepNext: config.keepNext,
|
|
6612
|
+
keepLines: config.keepLines,
|
|
6613
|
+
// Paragraph indentation (w:ind) in twips
|
|
6614
|
+
indent: config.indent,
|
|
6615
|
+
// Bookmark ID for internal linking
|
|
6616
|
+
bookmarkId,
|
|
6617
|
+
// Auto-numbering (1., 1.1., …) through the shared heading definition
|
|
6618
|
+
numbering: headingNumbering(config.numbering, config.level || 1),
|
|
6619
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
6620
|
+
revision: config.revision,
|
|
6621
|
+
// Review comment anchored to this heading's text
|
|
6622
|
+
comment: config.comment
|
|
6623
|
+
}
|
|
6624
|
+
);
|
|
6625
|
+
return [header];
|
|
6626
|
+
}
|
|
6627
|
+
|
|
6469
6628
|
// src/components/paragraph.ts
|
|
6470
6629
|
function parseMarkdownList(text) {
|
|
6471
6630
|
const lines = text.split("\n");
|
|
@@ -6605,8 +6764,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
6605
6764
|
return [text];
|
|
6606
6765
|
}
|
|
6607
6766
|
|
|
6608
|
-
// src/
|
|
6609
|
-
init_colorUtils();
|
|
6767
|
+
// src/utils/listLevels.ts
|
|
6610
6768
|
function createLevelsFromSimplifiedProps(props) {
|
|
6611
6769
|
const levels = [];
|
|
6612
6770
|
let format2;
|
|
@@ -6653,18 +6811,8 @@ function createLevelsFromSimplifiedProps(props) {
|
|
|
6653
6811
|
}
|
|
6654
6812
|
return levels;
|
|
6655
6813
|
}
|
|
6656
|
-
function resolveMarkerFonts(levels, theme) {
|
|
6657
|
-
return levels.map((level) => {
|
|
6658
|
-
const font = level.font;
|
|
6659
|
-
if (!font?.color) return level;
|
|
6660
|
-
return {
|
|
6661
|
-
...level,
|
|
6662
|
-
font: { ...font, color: resolveColor(font.color, theme) }
|
|
6663
|
-
};
|
|
6664
|
-
});
|
|
6665
|
-
}
|
|
6666
6814
|
function applyListStart(levels, start) {
|
|
6667
|
-
if (start === void 0) return levels;
|
|
6815
|
+
if (start === void 0) return [...levels];
|
|
6668
6816
|
return levels.map(
|
|
6669
6817
|
(level) => level.level === 0 && level.start === void 0 ? { ...level, start } : level
|
|
6670
6818
|
);
|
|
@@ -6722,28 +6870,37 @@ function fillMissingLevels(levels, maxLevel) {
|
|
|
6722
6870
|
}
|
|
6723
6871
|
return result;
|
|
6724
6872
|
}
|
|
6873
|
+
function resolveListLevels(props) {
|
|
6874
|
+
const maxLevel = getMaxLevelFromItems(props.items);
|
|
6875
|
+
if (props.levels && props.levels.length > 0) {
|
|
6876
|
+
return fillMissingLevels(
|
|
6877
|
+
applyListStart(props.levels, props.start),
|
|
6878
|
+
maxLevel
|
|
6879
|
+
);
|
|
6880
|
+
}
|
|
6881
|
+
return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);
|
|
6882
|
+
}
|
|
6883
|
+
|
|
6884
|
+
// src/components/list.ts
|
|
6885
|
+
init_colorUtils();
|
|
6886
|
+
function resolveMarkerFonts(levels, theme) {
|
|
6887
|
+
return levels.map((level) => {
|
|
6888
|
+
const font = level.font;
|
|
6889
|
+
if (!font?.color) return level;
|
|
6890
|
+
return {
|
|
6891
|
+
...level,
|
|
6892
|
+
font: { ...font, color: resolveColor(font.color, theme) }
|
|
6893
|
+
};
|
|
6894
|
+
});
|
|
6895
|
+
}
|
|
6725
6896
|
function renderListComponent(component, theme, themeName) {
|
|
6726
6897
|
if (!isListComponent(component)) return [];
|
|
6727
6898
|
const resolvedConfig = component.props;
|
|
6728
|
-
const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
|
|
6729
6899
|
const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
|
|
6730
6900
|
if (!globalNumberingRegistry.has(reference)) {
|
|
6731
|
-
let levels;
|
|
6732
|
-
if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {
|
|
6733
|
-
levels = fillMissingLevels(
|
|
6734
|
-
applyListStart(
|
|
6735
|
-
resolvedConfig.levels,
|
|
6736
|
-
resolvedConfig.start
|
|
6737
|
-
),
|
|
6738
|
-
maxLevel
|
|
6739
|
-
);
|
|
6740
|
-
} else {
|
|
6741
|
-
const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);
|
|
6742
|
-
levels = fillMissingLevels(baseLevels, maxLevel);
|
|
6743
|
-
}
|
|
6744
6901
|
const config = {
|
|
6745
6902
|
reference,
|
|
6746
|
-
levels: resolveMarkerFonts(
|
|
6903
|
+
levels: resolveMarkerFonts(resolveListLevels(resolvedConfig), theme)
|
|
6747
6904
|
};
|
|
6748
6905
|
const numberingConfig = createNumberingConfig(config);
|
|
6749
6906
|
globalNumberingRegistry.register(numberingConfig);
|
|
@@ -6783,6 +6940,7 @@ async function renderImageComponent(component, theme, themeName) {
|
|
|
6783
6940
|
|
|
6784
6941
|
// src/components/text-box.ts
|
|
6785
6942
|
import {
|
|
6943
|
+
Paragraph as Paragraph5,
|
|
6786
6944
|
Table as Table3,
|
|
6787
6945
|
TableRow as TableRow2,
|
|
6788
6946
|
TableCell as TableCell2,
|
|
@@ -6791,7 +6949,8 @@ import {
|
|
|
6791
6949
|
RelativeHorizontalPosition,
|
|
6792
6950
|
RelativeVerticalPosition,
|
|
6793
6951
|
OverlapType,
|
|
6794
|
-
TableLayoutType as TableLayoutType2
|
|
6952
|
+
TableLayoutType as TableLayoutType2,
|
|
6953
|
+
WpsShapeRun
|
|
6795
6954
|
} from "docx";
|
|
6796
6955
|
|
|
6797
6956
|
// src/styles/utils/borderUtils.ts
|
|
@@ -6868,6 +7027,8 @@ function buildCellOptions(children, styleCfg, theme) {
|
|
|
6868
7027
|
}
|
|
6869
7028
|
|
|
6870
7029
|
// src/components/text-box.ts
|
|
7030
|
+
init_colorUtils();
|
|
7031
|
+
init_docxImagePositioning();
|
|
6871
7032
|
init_widthUtils();
|
|
6872
7033
|
function mapTableFloatOptions(floating, theme, themeName) {
|
|
6873
7034
|
if (!floating) return void 0;
|
|
@@ -6923,26 +7084,23 @@ function mapTableFloatOptions(floating, theme, themeName) {
|
|
|
6923
7084
|
opt.overlap = OverlapType.OVERLAP;
|
|
6924
7085
|
return opt;
|
|
6925
7086
|
}
|
|
6926
|
-
async function
|
|
6927
|
-
|
|
6928
|
-
|
|
7087
|
+
async function renderTextBoxChildren(tb, theme, themeName, context) {
|
|
7088
|
+
const childContext = {
|
|
7089
|
+
...context,
|
|
7090
|
+
parent: tb
|
|
7091
|
+
};
|
|
7092
|
+
const rendered = [];
|
|
7093
|
+
for (const child of tb.children || []) {
|
|
7094
|
+
rendered.push(
|
|
7095
|
+
...await renderComponent(child, theme, themeName, childContext)
|
|
7096
|
+
);
|
|
7097
|
+
}
|
|
7098
|
+
return rendered;
|
|
7099
|
+
}
|
|
7100
|
+
async function renderTextBoxAsTable(tb, theme, themeName, _context, prerendered) {
|
|
6929
7101
|
const isInline = !tb.props.floating;
|
|
6930
|
-
const childComponents = tb.children || [];
|
|
6931
7102
|
if (isInline) {
|
|
6932
|
-
const cellChildren2 =
|
|
6933
|
-
const childContext2 = {
|
|
6934
|
-
..._context,
|
|
6935
|
-
parent: tb
|
|
6936
|
-
};
|
|
6937
|
-
for (const child of childComponents) {
|
|
6938
|
-
const rendered = await renderComponent(
|
|
6939
|
-
child,
|
|
6940
|
-
theme,
|
|
6941
|
-
themeName,
|
|
6942
|
-
childContext2
|
|
6943
|
-
);
|
|
6944
|
-
cellChildren2.push(...rendered);
|
|
6945
|
-
}
|
|
7103
|
+
const cellChildren2 = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
6946
7104
|
const styleCfg2 = tb.props.style;
|
|
6947
7105
|
const cellOpts2 = buildCellOptions(cellChildren2, styleCfg2, theme);
|
|
6948
7106
|
const row2 = new TableRow2({ children: [new TableCell2(cellOpts2)] });
|
|
@@ -6955,20 +7113,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
6955
7113
|
});
|
|
6956
7114
|
return [table2];
|
|
6957
7115
|
}
|
|
6958
|
-
const cellChildren =
|
|
6959
|
-
const childContext = {
|
|
6960
|
-
..._context,
|
|
6961
|
-
parent: tb
|
|
6962
|
-
};
|
|
6963
|
-
for (const child of childComponents) {
|
|
6964
|
-
const rendered = await renderComponent(
|
|
6965
|
-
child,
|
|
6966
|
-
theme,
|
|
6967
|
-
themeName,
|
|
6968
|
-
childContext
|
|
6969
|
-
);
|
|
6970
|
-
cellChildren.push(...rendered);
|
|
6971
|
-
}
|
|
7116
|
+
const cellChildren = prerendered ?? await renderTextBoxChildren(tb, theme, themeName, _context);
|
|
6972
7117
|
const styleCfg = tb.props.style;
|
|
6973
7118
|
const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);
|
|
6974
7119
|
const row = new TableRow2({
|
|
@@ -7000,6 +7145,162 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
7000
7145
|
});
|
|
7001
7146
|
return [table];
|
|
7002
7147
|
}
|
|
7148
|
+
var PIXELS_TO_EMU = 9525;
|
|
7149
|
+
var TWIPS_PER_PIXEL = 15;
|
|
7150
|
+
function resolveShapeSize(value, axis, theme, themeName) {
|
|
7151
|
+
if (typeof value === "number") {
|
|
7152
|
+
return { pixels: Math.round(value), resolvedPercentage: false };
|
|
7153
|
+
}
|
|
7154
|
+
if (typeof value !== "string") return { resolvedPercentage: false };
|
|
7155
|
+
const fraction = parseFloat(value) / 100;
|
|
7156
|
+
if (!Number.isFinite(fraction) || fraction <= 0) {
|
|
7157
|
+
return { resolvedPercentage: false };
|
|
7158
|
+
}
|
|
7159
|
+
const availableTwips = axis === "width" ? getAvailableWidthTwips(theme, themeName) : getAvailableHeightTwips(theme, themeName);
|
|
7160
|
+
return {
|
|
7161
|
+
pixels: Math.round(availableTwips * fraction / TWIPS_PER_PIXEL),
|
|
7162
|
+
resolvedPercentage: true
|
|
7163
|
+
};
|
|
7164
|
+
}
|
|
7165
|
+
function shapeColor(value, theme) {
|
|
7166
|
+
return resolveColor(value, theme).replace(/^#/, "");
|
|
7167
|
+
}
|
|
7168
|
+
function shapeOutline(style, theme) {
|
|
7169
|
+
const border = style?.border;
|
|
7170
|
+
if (!border) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7171
|
+
const order = [
|
|
7172
|
+
"top",
|
|
7173
|
+
"left",
|
|
7174
|
+
"bottom",
|
|
7175
|
+
"right"
|
|
7176
|
+
];
|
|
7177
|
+
const declared = order.map((side) => [side, border[side]]).filter(
|
|
7178
|
+
(entry) => Boolean(entry[1])
|
|
7179
|
+
);
|
|
7180
|
+
if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };
|
|
7181
|
+
const unsupportedStyles = [
|
|
7182
|
+
...new Set(
|
|
7183
|
+
declared.map(([, config]) => config.style).filter(
|
|
7184
|
+
(value) => value === "dashed" || value === "dotted" || value === "double"
|
|
7185
|
+
)
|
|
7186
|
+
)
|
|
7187
|
+
];
|
|
7188
|
+
if (unsupportedStyles.length > 0) {
|
|
7189
|
+
return { ignoredSides: [], unsupportedStyles };
|
|
7190
|
+
}
|
|
7191
|
+
const [, used] = declared[0];
|
|
7192
|
+
const differs = ({ style: s, width, color }) => s !== used.style || width !== used.width || color !== used.color;
|
|
7193
|
+
const ignoredSides = declared.slice(1).filter(([, config]) => differs(config)).map(([side]) => side);
|
|
7194
|
+
if (used.style === "none") return { ignoredSides, unsupportedStyles };
|
|
7195
|
+
return {
|
|
7196
|
+
outline: {
|
|
7197
|
+
type: "solidFill",
|
|
7198
|
+
solidFillType: "rgb",
|
|
7199
|
+
value: used.color ? shapeColor(used.color, theme) : "000000",
|
|
7200
|
+
...used.width !== void 0 && {
|
|
7201
|
+
width: Math.round(used.width * PIXELS_TO_EMU)
|
|
7202
|
+
}
|
|
7203
|
+
},
|
|
7204
|
+
ignoredSides,
|
|
7205
|
+
unsupportedStyles
|
|
7206
|
+
};
|
|
7207
|
+
}
|
|
7208
|
+
function shapeBodyProperties(style) {
|
|
7209
|
+
const padding = style?.padding;
|
|
7210
|
+
if (!padding) return void 0;
|
|
7211
|
+
const toEmu = (value) => value === void 0 ? void 0 : Math.round(value * PIXELS_TO_EMU);
|
|
7212
|
+
return {
|
|
7213
|
+
margins: {
|
|
7214
|
+
...padding.top !== void 0 && { top: toEmu(padding.top) },
|
|
7215
|
+
...padding.bottom !== void 0 && { bottom: toEmu(padding.bottom) },
|
|
7216
|
+
...padding.left !== void 0 && { left: toEmu(padding.left) },
|
|
7217
|
+
...padding.right !== void 0 && { right: toEmu(padding.right) }
|
|
7218
|
+
}
|
|
7219
|
+
};
|
|
7220
|
+
}
|
|
7221
|
+
async function renderTextBoxAsShape(tb, theme, themeName, context) {
|
|
7222
|
+
const width = resolveShapeSize(tb.props.width, "width", theme, themeName);
|
|
7223
|
+
const height = resolveShapeSize(tb.props.height, "height", theme, themeName);
|
|
7224
|
+
if (width.pixels === void 0 || height.pixels === void 0) {
|
|
7225
|
+
console.warn(
|
|
7226
|
+
'[core-docx] text-box renderAs "shape" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'
|
|
7227
|
+
);
|
|
7228
|
+
return { kind: "fallback" };
|
|
7229
|
+
}
|
|
7230
|
+
const style = tb.props.style;
|
|
7231
|
+
const { outline, ignoredSides, unsupportedStyles } = shapeOutline(
|
|
7232
|
+
style,
|
|
7233
|
+
theme
|
|
7234
|
+
);
|
|
7235
|
+
if (unsupportedStyles.length > 0) {
|
|
7236
|
+
console.warn(
|
|
7237
|
+
`[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.`
|
|
7238
|
+
);
|
|
7239
|
+
return { kind: "fallback" };
|
|
7240
|
+
}
|
|
7241
|
+
const rendered = await renderTextBoxChildren(tb, theme, themeName, context);
|
|
7242
|
+
if (rendered.some((element) => !(element instanceof Paragraph5))) {
|
|
7243
|
+
console.warn(
|
|
7244
|
+
'[core-docx] text-box renderAs "shape" requires paragraph-only content; falling back to table rendering.'
|
|
7245
|
+
);
|
|
7246
|
+
return { kind: "fallback", rendered };
|
|
7247
|
+
}
|
|
7248
|
+
const children = rendered;
|
|
7249
|
+
if (width.resolvedPercentage || height.resolvedPercentage) {
|
|
7250
|
+
console.warn(
|
|
7251
|
+
'[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.'
|
|
7252
|
+
);
|
|
7253
|
+
}
|
|
7254
|
+
const fill = style?.shading?.fill;
|
|
7255
|
+
if (ignoredSides.length > 0) {
|
|
7256
|
+
console.warn(
|
|
7257
|
+
`[core-docx] text-box renderAs "shape" has one uniform outline; using the first declared border side and ignoring ${ignoredSides.join(", ")}.`
|
|
7258
|
+
);
|
|
7259
|
+
}
|
|
7260
|
+
const dropOutline = Boolean(fill) && Boolean(outline);
|
|
7261
|
+
if (dropOutline) {
|
|
7262
|
+
console.warn(
|
|
7263
|
+
'[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.'
|
|
7264
|
+
);
|
|
7265
|
+
}
|
|
7266
|
+
const bodyProperties = shapeBodyProperties(style);
|
|
7267
|
+
const run = new WpsShapeRun({
|
|
7268
|
+
type: "wps",
|
|
7269
|
+
children,
|
|
7270
|
+
transformation: { width: width.pixels, height: height.pixels },
|
|
7271
|
+
...fill && {
|
|
7272
|
+
solidFill: { type: "rgb", value: shapeColor(fill, theme) }
|
|
7273
|
+
},
|
|
7274
|
+
...outline && !dropOutline && { outline },
|
|
7275
|
+
...bodyProperties && { bodyProperties },
|
|
7276
|
+
// Absent `floating` makes it a `wp:inline` drawing.
|
|
7277
|
+
...tb.props.floating && {
|
|
7278
|
+
floating: mapFloatingOptions(tb.props.floating, theme, themeName)
|
|
7279
|
+
}
|
|
7280
|
+
});
|
|
7281
|
+
return {
|
|
7282
|
+
kind: "shape",
|
|
7283
|
+
paragraphs: [
|
|
7284
|
+
new Paragraph5({ children: [run], spacing: { before: 0, after: 0 } })
|
|
7285
|
+
]
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
async function renderTextBoxComponent(component, theme, themeName, context) {
|
|
7289
|
+
if (!isTextBoxComponent(component)) return [];
|
|
7290
|
+
const tb = component;
|
|
7291
|
+
if (tb.props.renderAs === "shape") {
|
|
7292
|
+
const attempt = await renderTextBoxAsShape(tb, theme, themeName, context);
|
|
7293
|
+
if (attempt.kind === "shape") return attempt.paragraphs;
|
|
7294
|
+
return renderTextBoxAsTable(
|
|
7295
|
+
tb,
|
|
7296
|
+
theme,
|
|
7297
|
+
themeName,
|
|
7298
|
+
context,
|
|
7299
|
+
attempt.rendered
|
|
7300
|
+
);
|
|
7301
|
+
}
|
|
7302
|
+
return renderTextBoxAsTable(tb, theme, themeName, context);
|
|
7303
|
+
}
|
|
7003
7304
|
|
|
7004
7305
|
// src/components/table.ts
|
|
7005
7306
|
async function renderTableComponent(component, theme, themeName) {
|
|
@@ -7050,23 +7351,23 @@ async function renderTableComponent(component, theme, themeName) {
|
|
|
7050
7351
|
}
|
|
7051
7352
|
|
|
7052
7353
|
// src/components/section.ts
|
|
7053
|
-
import { Paragraph as Paragraph6, BookmarkStart, BookmarkEnd } from "docx";
|
|
7354
|
+
import { Paragraph as Paragraph6, BookmarkStart as BookmarkStart2, BookmarkEnd as BookmarkEnd2 } from "docx";
|
|
7054
7355
|
|
|
7055
7356
|
// src/core/sectionBookmarks.ts
|
|
7056
|
-
import { AsyncLocalStorage as
|
|
7357
|
+
import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
|
|
7057
7358
|
var NESTED_LINK_ID_BASE = 1e6;
|
|
7058
|
-
function
|
|
7359
|
+
function createState4() {
|
|
7059
7360
|
return { nextNested: 1, resolved: /* @__PURE__ */ new WeakMap() };
|
|
7060
7361
|
}
|
|
7061
7362
|
var SectionBookmarkRegistry = class {
|
|
7062
|
-
fallback =
|
|
7063
|
-
scopes = new
|
|
7363
|
+
fallback = createState4();
|
|
7364
|
+
scopes = new AsyncLocalStorage8();
|
|
7064
7365
|
get state() {
|
|
7065
7366
|
return this.scopes.getStore() ?? this.fallback;
|
|
7066
7367
|
}
|
|
7067
7368
|
/** Run work with an isolated registry that follows its async call chain. */
|
|
7068
7369
|
runScoped(callback) {
|
|
7069
|
-
return this.scopes.run(
|
|
7370
|
+
return this.scopes.run(createState4(), callback);
|
|
7070
7371
|
}
|
|
7071
7372
|
/**
|
|
7072
7373
|
* The bookmark for a layout section, derived from its ordinal.
|
|
@@ -7097,7 +7398,7 @@ var SectionBookmarkRegistry = class {
|
|
|
7097
7398
|
/** Test-only: reset the unscoped fallback counters. */
|
|
7098
7399
|
clear() {
|
|
7099
7400
|
if (!this.scopes.getStore()) {
|
|
7100
|
-
this.fallback =
|
|
7401
|
+
this.fallback = createState4();
|
|
7101
7402
|
}
|
|
7102
7403
|
}
|
|
7103
7404
|
};
|
|
@@ -7110,7 +7411,7 @@ async function renderSectionComponent(component, theme, themeName, context) {
|
|
|
7110
7411
|
const { id: sectionBookmarkId, linkId: bookmarkLinkId } = globalSectionBookmarkRegistry.forSectionComponent(component);
|
|
7111
7412
|
elements.push(
|
|
7112
7413
|
new Paragraph6({
|
|
7113
|
-
children: [new
|
|
7414
|
+
children: [new BookmarkStart2(sectionBookmarkId, bookmarkLinkId)],
|
|
7114
7415
|
spacing: {
|
|
7115
7416
|
before: 0,
|
|
7116
7417
|
after: 0,
|
|
@@ -7138,7 +7439,7 @@ async function renderSectionComponent(component, theme, themeName, context) {
|
|
|
7138
7439
|
}
|
|
7139
7440
|
elements.push(
|
|
7140
7441
|
new Paragraph6({
|
|
7141
|
-
children: [new
|
|
7442
|
+
children: [new BookmarkEnd2(bookmarkLinkId)],
|
|
7142
7443
|
spacing: {
|
|
7143
7444
|
before: 0,
|
|
7144
7445
|
after: 0,
|
|
@@ -7318,7 +7619,10 @@ function selectCachedEntries(collected, options) {
|
|
|
7318
7619
|
continue;
|
|
7319
7620
|
}
|
|
7320
7621
|
if (entry.level < depthStart || entry.level > depthEnd) continue;
|
|
7321
|
-
entries.push({
|
|
7622
|
+
entries.push({
|
|
7623
|
+
title: entry.number ? `${headingNumberLabel(entry.number)} ${entry.title}` : entry.title,
|
|
7624
|
+
level: entry.level
|
|
7625
|
+
});
|
|
7322
7626
|
}
|
|
7323
7627
|
return entries;
|
|
7324
7628
|
}
|
|
@@ -8077,6 +8381,61 @@ function computeSectionOrdinals(sections) {
|
|
|
8077
8381
|
|
|
8078
8382
|
// src/core/collectTocHeadings.ts
|
|
8079
8383
|
import { getStandardComponent } from "@json-to-office/shared-docx";
|
|
8384
|
+
|
|
8385
|
+
// src/utils/numberFormatting.ts
|
|
8386
|
+
var ROMAN_NUMERALS = [
|
|
8387
|
+
[1e3, "m"],
|
|
8388
|
+
[900, "cm"],
|
|
8389
|
+
[500, "d"],
|
|
8390
|
+
[400, "cd"],
|
|
8391
|
+
[100, "c"],
|
|
8392
|
+
[90, "xc"],
|
|
8393
|
+
[50, "l"],
|
|
8394
|
+
[40, "xl"],
|
|
8395
|
+
[10, "x"],
|
|
8396
|
+
[9, "ix"],
|
|
8397
|
+
[5, "v"],
|
|
8398
|
+
[4, "iv"],
|
|
8399
|
+
[1, "i"]
|
|
8400
|
+
];
|
|
8401
|
+
function toRoman(value) {
|
|
8402
|
+
let remaining = value;
|
|
8403
|
+
let out = "";
|
|
8404
|
+
for (const [amount, glyph] of ROMAN_NUMERALS) {
|
|
8405
|
+
while (remaining >= amount) {
|
|
8406
|
+
out += glyph;
|
|
8407
|
+
remaining -= amount;
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
return out;
|
|
8411
|
+
}
|
|
8412
|
+
function toLetters(value) {
|
|
8413
|
+
const index = (value - 1) % 26;
|
|
8414
|
+
const repeats = Math.floor((value - 1) / 26) + 1;
|
|
8415
|
+
return String.fromCharCode(97 + index).repeat(repeats);
|
|
8416
|
+
}
|
|
8417
|
+
function formatNumberForLevel(value, format2) {
|
|
8418
|
+
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
8419
|
+
const n = Math.floor(value);
|
|
8420
|
+
switch (format2) {
|
|
8421
|
+
case "decimal":
|
|
8422
|
+
return String(n);
|
|
8423
|
+
case "lowerLetter":
|
|
8424
|
+
return toLetters(n);
|
|
8425
|
+
case "upperLetter":
|
|
8426
|
+
return toLetters(n).toUpperCase();
|
|
8427
|
+
case "lowerRoman":
|
|
8428
|
+
return toRoman(n);
|
|
8429
|
+
case "upperRoman":
|
|
8430
|
+
return toRoman(n).toUpperCase();
|
|
8431
|
+
default:
|
|
8432
|
+
return void 0;
|
|
8433
|
+
}
|
|
8434
|
+
}
|
|
8435
|
+
|
|
8436
|
+
// src/core/collectTocHeadings.ts
|
|
8437
|
+
var MAX_HEADING_LEVEL2 = 6;
|
|
8438
|
+
var MAX_LIST_LEVEL = 9;
|
|
8080
8439
|
function normalizeEntryTitle(text) {
|
|
8081
8440
|
return normalizeUnicodeText(text).replace(/(\*\*\*|___)([\s\S]*?)\1/g, "$2").replace(/(\*\*|__)([\s\S]*?)\1/g, "$2").replace(/(\*|_)([\s\S]*?)\1/g, "$2").trim();
|
|
8082
8441
|
}
|
|
@@ -8095,9 +8454,97 @@ function styleEntryKey(props) {
|
|
|
8095
8454
|
}
|
|
8096
8455
|
return themeStyle;
|
|
8097
8456
|
}
|
|
8098
|
-
function
|
|
8457
|
+
function levelStart(levels, level) {
|
|
8458
|
+
return levels[level]?.start ?? 1;
|
|
8459
|
+
}
|
|
8460
|
+
function collectDocumentOutline(sections) {
|
|
8099
8461
|
const entries = [];
|
|
8462
|
+
const numberedItems = /* @__PURE__ */ new Map();
|
|
8100
8463
|
const ordinals = computeSectionOrdinals(sections);
|
|
8464
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
8465
|
+
const headingCounters = new Array(MAX_HEADING_LEVEL2).fill(0);
|
|
8466
|
+
const listCounters = /* @__PURE__ */ new Map();
|
|
8467
|
+
const visitHeading = (component, props, sectionBookmarkId) => {
|
|
8468
|
+
const text = typeof props.text === "string" ? props.text : "";
|
|
8469
|
+
const title = normalizeEntryTitle(text);
|
|
8470
|
+
const level = typeof props.level === "number" ? props.level : 1;
|
|
8471
|
+
const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL2 ? level : 1;
|
|
8472
|
+
let full;
|
|
8473
|
+
let own;
|
|
8474
|
+
if (props.numbering === true) {
|
|
8475
|
+
headingCounters[styleLevel - 1] += 1;
|
|
8476
|
+
for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL2; deeper++) {
|
|
8477
|
+
headingCounters[deeper] = 0;
|
|
8478
|
+
}
|
|
8479
|
+
full = headingCounters.slice(0, styleLevel).join(".");
|
|
8480
|
+
own = String(headingCounters[styleLevel - 1]);
|
|
8481
|
+
}
|
|
8482
|
+
const explicitId = component.id;
|
|
8483
|
+
const bookmarkId = typeof explicitId === "string" && explicitId ? explicitId : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));
|
|
8484
|
+
takenIds.add(bookmarkId);
|
|
8485
|
+
numberedItems.set(bookmarkId, {
|
|
8486
|
+
kind: "heading",
|
|
8487
|
+
text: title,
|
|
8488
|
+
...full !== void 0 && { full, own }
|
|
8489
|
+
});
|
|
8490
|
+
if (title) {
|
|
8491
|
+
entries.push({
|
|
8492
|
+
title,
|
|
8493
|
+
level,
|
|
8494
|
+
sectionBookmarkId,
|
|
8495
|
+
...full !== void 0 && { number: full }
|
|
8496
|
+
});
|
|
8497
|
+
}
|
|
8498
|
+
};
|
|
8499
|
+
const visitList = (props) => {
|
|
8500
|
+
const items = Array.isArray(props.items) ? props.items : [];
|
|
8501
|
+
if (items.length === 0) return;
|
|
8502
|
+
const reference = typeof props.reference === "string" && props.reference ? props.reference : void 0;
|
|
8503
|
+
const freshState = () => {
|
|
8504
|
+
const levels = resolveListLevels(
|
|
8505
|
+
props
|
|
8506
|
+
);
|
|
8507
|
+
return {
|
|
8508
|
+
levels,
|
|
8509
|
+
counters: Array.from(
|
|
8510
|
+
{ length: MAX_LIST_LEVEL },
|
|
8511
|
+
(_, level) => levelStart(levels, level) - 1
|
|
8512
|
+
)
|
|
8513
|
+
};
|
|
8514
|
+
};
|
|
8515
|
+
let state;
|
|
8516
|
+
if (reference === void 0) {
|
|
8517
|
+
state = freshState();
|
|
8518
|
+
} else {
|
|
8519
|
+
state = listCounters.get(reference) ?? freshState();
|
|
8520
|
+
listCounters.set(reference, state);
|
|
8521
|
+
}
|
|
8522
|
+
for (const item of items) {
|
|
8523
|
+
const isObject = typeof item === "object" && item !== null;
|
|
8524
|
+
const raw = isObject ? item.text : item;
|
|
8525
|
+
const text = typeof raw === "string" ? raw : "";
|
|
8526
|
+
if (!text.trim() && !(isObject && item.revision)) continue;
|
|
8527
|
+
const rawLevel = isObject ? item.level : void 0;
|
|
8528
|
+
const level = typeof rawLevel === "number" && rawLevel >= 0 ? rawLevel : 0;
|
|
8529
|
+
if (level >= MAX_LIST_LEVEL) continue;
|
|
8530
|
+
state.counters[level] += 1;
|
|
8531
|
+
for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {
|
|
8532
|
+
state.counters[deeper] = levelStart(state.levels, deeper) - 1;
|
|
8533
|
+
}
|
|
8534
|
+
const id = isObject ? item.id : void 0;
|
|
8535
|
+
if (typeof id !== "string" || !id) continue;
|
|
8536
|
+
takenIds.add(id);
|
|
8537
|
+
const number = formatNumberForLevel(
|
|
8538
|
+
state.counters[level],
|
|
8539
|
+
state.levels[level]?.format
|
|
8540
|
+
);
|
|
8541
|
+
numberedItems.set(id, {
|
|
8542
|
+
kind: "list-item",
|
|
8543
|
+
text: normalizeUnicodeText(text).trim(),
|
|
8544
|
+
...number !== void 0 && { full: number, own: number }
|
|
8545
|
+
});
|
|
8546
|
+
}
|
|
8547
|
+
};
|
|
8101
8548
|
sections.forEach((section, index) => {
|
|
8102
8549
|
const ordinal = ordinals[index]?.ordinal;
|
|
8103
8550
|
const sectionBookmarkId = ordinal ? globalSectionBookmarkRegistry.forLayoutSection(ordinal).id : void 0;
|
|
@@ -8105,15 +8552,11 @@ function collectTocHeadings(sections) {
|
|
|
8105
8552
|
if (!isEnabled(component)) return;
|
|
8106
8553
|
const props = component.props ?? {};
|
|
8107
8554
|
if (component.name === "heading") {
|
|
8108
|
-
|
|
8109
|
-
const title = normalizeEntryTitle(text);
|
|
8110
|
-
if (title) {
|
|
8111
|
-
const level = typeof props.level === "number" ? props.level : 1;
|
|
8112
|
-
entries.push({ title, level, sectionBookmarkId });
|
|
8113
|
-
}
|
|
8555
|
+
visitHeading(component, props, sectionBookmarkId);
|
|
8114
8556
|
return;
|
|
8115
8557
|
}
|
|
8116
8558
|
if (component.name === "paragraph") {
|
|
8559
|
+
if (typeof props.id === "string" && props.id) takenIds.add(props.id);
|
|
8117
8560
|
const styleId = styleEntryKey(props);
|
|
8118
8561
|
const text = typeof props.text === "string" ? props.text : "";
|
|
8119
8562
|
const title = normalizeEntryTitle(text);
|
|
@@ -8122,13 +8565,17 @@ function collectTocHeadings(sections) {
|
|
|
8122
8565
|
}
|
|
8123
8566
|
return;
|
|
8124
8567
|
}
|
|
8568
|
+
if (component.name === "list") {
|
|
8569
|
+
visitList(props);
|
|
8570
|
+
return;
|
|
8571
|
+
}
|
|
8125
8572
|
if (!isContainer(component.name)) return;
|
|
8126
8573
|
const children = component.children;
|
|
8127
8574
|
if (Array.isArray(children)) children.forEach(visit);
|
|
8128
8575
|
};
|
|
8129
8576
|
section.components.forEach(visit);
|
|
8130
8577
|
});
|
|
8131
|
-
return entries;
|
|
8578
|
+
return { entries, numberedItems };
|
|
8132
8579
|
}
|
|
8133
8580
|
|
|
8134
8581
|
// src/core/render.ts
|
|
@@ -8181,7 +8628,13 @@ async function renderDocument(structure, layout, options) {
|
|
|
8181
8628
|
// Footnote ids are document-scoped too: a reference resolved
|
|
8182
8629
|
// against another render's counter points at the wrong body.
|
|
8183
8630
|
globalNoteRegistry.runScoped(
|
|
8184
|
-
() =>
|
|
8631
|
+
() => (
|
|
8632
|
+
// Cross-reference targets are keyed by bookmark id, which
|
|
8633
|
+
// is only unique within one document.
|
|
8634
|
+
globalNumberedItemsRegistry.runScoped(
|
|
8635
|
+
() => renderDocumentScoped(structure, layout, options)
|
|
8636
|
+
)
|
|
8637
|
+
)
|
|
8185
8638
|
)
|
|
8186
8639
|
)
|
|
8187
8640
|
)
|
|
@@ -8224,13 +8677,14 @@ async function renderDocumentScoped(structure, layout, options) {
|
|
|
8224
8677
|
);
|
|
8225
8678
|
}
|
|
8226
8679
|
try {
|
|
8227
|
-
const
|
|
8228
|
-
if (
|
|
8229
|
-
context.tocHeadings =
|
|
8680
|
+
const outline = collectDocumentOutline(layout.sections);
|
|
8681
|
+
if (outline.entries.length > 0) {
|
|
8682
|
+
context.tocHeadings = outline.entries;
|
|
8230
8683
|
}
|
|
8684
|
+
globalNumberedItemsRegistry.seed(outline.numberedItems);
|
|
8231
8685
|
} catch (error) {
|
|
8232
8686
|
console.warn(
|
|
8233
|
-
"[core-docx]
|
|
8687
|
+
"[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it:",
|
|
8234
8688
|
error instanceof Error ? error.message : error
|
|
8235
8689
|
);
|
|
8236
8690
|
}
|
|
@@ -8473,7 +8927,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
8473
8927
|
if (sectionBookmarkId && isFirstLayoutOfUserSection && sharedLinkId !== void 0) {
|
|
8474
8928
|
elements.push(
|
|
8475
8929
|
new Paragraph9({
|
|
8476
|
-
children: [new
|
|
8930
|
+
children: [new BookmarkStart3(sectionBookmarkId, sharedLinkId)],
|
|
8477
8931
|
spacing: {
|
|
8478
8932
|
before: 0,
|
|
8479
8933
|
after: 0,
|
|
@@ -8498,7 +8952,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
8498
8952
|
if (closeBookmark && sharedLinkId !== void 0) {
|
|
8499
8953
|
elements.push(
|
|
8500
8954
|
new Paragraph9({
|
|
8501
|
-
children: [new
|
|
8955
|
+
children: [new BookmarkEnd3(sharedLinkId)]
|
|
8502
8956
|
})
|
|
8503
8957
|
);
|
|
8504
8958
|
}
|