@docx4j/core-ts 0.1.0 → 0.1.1

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.
Files changed (168) hide show
  1. package/README.md +410 -10
  2. package/dist/model/content/Body.d.mts +109 -4
  3. package/dist/model/content/Body.mjs +300 -29
  4. package/dist/model/content/Comment.d.mts +78 -0
  5. package/dist/model/content/Comment.mjs +429 -0
  6. package/dist/model/content/ContentControl.d.mts +173 -0
  7. package/dist/model/content/ContentControl.mjs +638 -0
  8. package/dist/model/content/Font.d.mts +48 -8
  9. package/dist/model/content/Font.mjs +55 -13
  10. package/dist/model/content/InlinePicture.d.mts +103 -0
  11. package/dist/model/content/InlinePicture.mjs +361 -0
  12. package/dist/model/content/List.d.mts +253 -0
  13. package/dist/model/content/List.mjs +778 -0
  14. package/dist/model/content/Paragraph.d.mts +213 -16
  15. package/dist/model/content/Paragraph.mjs +611 -57
  16. package/dist/model/content/Range.d.mts +48 -4
  17. package/dist/model/content/Range.mjs +161 -4
  18. package/dist/model/content/Table.d.mts +130 -0
  19. package/dist/model/content/Table.mjs +429 -0
  20. package/dist/model/content/TrackedChange.d.mts +96 -0
  21. package/dist/model/content/TrackedChange.mjs +352 -0
  22. package/dist/model/content/comments.d.mts +122 -0
  23. package/dist/model/content/comments.mjs +248 -0
  24. package/dist/model/content/index.d.mts +13 -3
  25. package/dist/model/content/index.mjs +15 -3
  26. package/dist/model/content/ooxml.d.mts +17 -0
  27. package/dist/model/content/ooxml.mjs +214 -0
  28. package/dist/model/content/styles.d.mts +21 -0
  29. package/dist/model/content/styles.mjs +86 -0
  30. package/dist/model/content/tracking.d.mts +104 -0
  31. package/dist/model/content/tracking.mjs +313 -0
  32. package/dist/model/content/tree.d.mts +56 -9
  33. package/dist/model/content/tree.mjs +104 -31
  34. package/dist/model/customxml/CustomXmlPart.d.mts +158 -0
  35. package/dist/model/customxml/CustomXmlPart.mjs +415 -0
  36. package/dist/model/customxml/CustomXmlPartCollection.d.mts +68 -0
  37. package/dist/model/customxml/CustomXmlPartCollection.mjs +183 -0
  38. package/dist/model/customxml/XmlMapping.d.mts +46 -0
  39. package/dist/model/customxml/XmlMapping.mjs +98 -0
  40. package/dist/model/customxml/bindings.d.mts +41 -0
  41. package/dist/model/customxml/bindings.mjs +230 -0
  42. package/dist/model/customxml/index.d.mts +7 -0
  43. package/dist/model/customxml/index.mjs +9 -0
  44. package/dist/model/customxml/insert.d.mts +20 -0
  45. package/dist/model/customxml/insert.mjs +22 -0
  46. package/dist/model/customxml/kinds.d.mts +103 -0
  47. package/dist/model/customxml/kinds.mjs +267 -0
  48. package/dist/model/customxml/xpath.d.mts +52 -0
  49. package/dist/model/customxml/xpath.mjs +205 -0
  50. package/dist/model/fonts/CJKToEnglish.d.mts +2 -0
  51. package/dist/model/fonts/CJKToEnglish.mjs +16 -0
  52. package/dist/model/fonts/FontFallback.d.mts +58 -0
  53. package/dist/model/fonts/FontFallback.mjs +219 -0
  54. package/dist/model/fonts/IdentityPlusMapper.d.mts +7 -0
  55. package/dist/model/fonts/IdentityPlusMapper.mjs +19 -0
  56. package/dist/model/fonts/LanguageTagToScriptMapping.d.mts +7 -0
  57. package/dist/model/fonts/LanguageTagToScriptMapping.mjs +67 -0
  58. package/dist/model/fonts/Mapper.d.mts +190 -0
  59. package/dist/model/fonts/Mapper.mjs +481 -0
  60. package/dist/model/fonts/PhysicalFont.d.mts +34 -0
  61. package/dist/model/fonts/PhysicalFont.mjs +62 -0
  62. package/dist/model/fonts/RunFontSelector.d.mts +194 -0
  63. package/dist/model/fonts/RunFontSelector.mjs +441 -0
  64. package/dist/model/fonts/ThemeFonts.d.mts +17 -0
  65. package/dist/model/fonts/ThemeFonts.mjs +76 -0
  66. package/dist/model/fonts/defaultTheme.d.mts +37 -0
  67. package/dist/model/fonts/defaultTheme.mjs +57 -0
  68. package/dist/model/fonts/families.generated.d.mts +11 -0
  69. package/dist/model/fonts/families.generated.mjs +17 -0
  70. package/dist/model/fonts/fontsInUse.d.mts +39 -0
  71. package/dist/model/fonts/fontsInUse.mjs +183 -0
  72. package/dist/model/fonts/index.d.mts +14 -0
  73. package/dist/model/fonts/index.mjs +29 -0
  74. package/dist/model/fonts/lookup.d.mts +5 -0
  75. package/dist/model/fonts/lookup.mjs +12 -0
  76. package/dist/model/fonts/registry.d.mts +31 -0
  77. package/dist/model/fonts/registry.mjs +103 -0
  78. package/dist/model/fonts/scripts.d.mts +2 -0
  79. package/dist/model/fonts/scripts.mjs +78 -0
  80. package/dist/model/fonts/substitutions.generated.d.mts +30 -0
  81. package/dist/model/fonts/substitutions.generated.mjs +12 -0
  82. package/dist/model/fonts/themes.generated.d.mts +6 -0
  83. package/dist/model/fonts/themes.generated.mjs +11 -0
  84. package/dist/model/index.d.mts +5 -0
  85. package/dist/model/index.mjs +13 -1
  86. package/dist/model/listnumbering/Emulator.d.mts +187 -0
  87. package/dist/model/listnumbering/Emulator.mjs +332 -0
  88. package/dist/model/listnumbering/definitions.d.mts +251 -0
  89. package/dist/model/listnumbering/definitions.mjs +571 -0
  90. package/dist/model/listnumbering/formats.d.mts +25 -0
  91. package/dist/model/listnumbering/formats.mjs +320 -0
  92. package/dist/model/listnumbering/index.d.mts +4 -0
  93. package/dist/model/listnumbering/index.mjs +15 -0
  94. package/dist/model/listnumbering/state.d.mts +97 -0
  95. package/dist/model/listnumbering/state.mjs +179 -0
  96. package/dist/model/properties/PropertyResolver.d.mts +216 -0
  97. package/dist/model/properties/PropertyResolver.mjs +524 -0
  98. package/dist/model/properties/catalogue.d.mts +179 -0
  99. package/dist/model/properties/catalogue.mjs +860 -0
  100. package/dist/model/properties/index.d.mts +4 -0
  101. package/dist/model/properties/index.mjs +9 -0
  102. package/dist/model/properties/log.d.mts +7 -0
  103. package/dist/model/properties/log.mjs +25 -0
  104. package/dist/model/properties/styleUtil.d.mts +112 -0
  105. package/dist/model/properties/styleUtil.mjs +359 -0
  106. package/dist/node/index.d.mts +1 -0
  107. package/dist/node/index.mjs +12 -0
  108. package/dist/office-js/document.d.mts +111 -0
  109. package/dist/office-js/document.mjs +267 -0
  110. package/dist/office-js/enums.d.mts +187 -0
  111. package/dist/office-js/enums.mjs +176 -0
  112. package/dist/office-js/errors.d.mts +29 -0
  113. package/dist/office-js/errors.mjs +39 -0
  114. package/dist/office-js/extras.d.mts +5 -0
  115. package/dist/office-js/extras.mjs +29 -0
  116. package/dist/office-js/fragment.d.mts +10 -0
  117. package/dist/office-js/fragment.mjs +23 -0
  118. package/dist/office-js/index.d.mts +183 -0
  119. package/dist/office-js/index.mjs +54 -0
  120. package/dist/office-js/proxy.d.mts +72 -0
  121. package/dist/office-js/proxy.mjs +279 -0
  122. package/dist/office-js/run.d.mts +32 -0
  123. package/dist/office-js/run.mjs +66 -0
  124. package/dist/office-js/supported.d.mts +7 -0
  125. package/dist/office-js/supported.generated.d.mts +1 -0
  126. package/dist/office-js/supported.generated.mjs +235 -0
  127. package/dist/office-js/supported.mjs +53 -0
  128. package/dist/office-js/toApiScript.d.mts +25 -0
  129. package/dist/office-js/toApiScript.mjs +394 -0
  130. package/dist/opc/ContentTypes.d.mts +1 -0
  131. package/dist/opc/ContentTypes.mjs +1 -0
  132. package/dist/opc/DirectoryPartStore.d.mts +47 -0
  133. package/dist/opc/DirectoryPartStore.mjs +123 -0
  134. package/dist/opc/exceptions.d.mts +30 -0
  135. package/dist/opc/exceptions.mjs +38 -0
  136. package/dist/opc/index.d.mts +1 -1
  137. package/dist/opc/index.mjs +1 -1
  138. package/dist/packages/OpcPackage.d.mts +19 -1
  139. package/dist/packages/OpcPackage.mjs +29 -0
  140. package/dist/packages/PresentationMLPackage.d.mts +71 -1
  141. package/dist/packages/PresentationMLPackage.mjs +179 -0
  142. package/dist/packages/SpreadsheetMLPackage.d.mts +30 -1
  143. package/dist/packages/SpreadsheetMLPackage.mjs +78 -0
  144. package/dist/packages/WordprocessingMLPackage.d.mts +124 -2
  145. package/dist/packages/WordprocessingMLPackage.mjs +309 -2
  146. package/dist/packages/index.d.mts +1 -1
  147. package/dist/packages/index.mjs +1 -1
  148. package/dist/parts/DefaultXmlPart.d.mts +18 -0
  149. package/dist/parts/DefaultXmlPart.mjs +34 -5
  150. package/dist/parts/PartRegistry.mjs +1 -0
  151. package/dist/parts/XmlPart.d.mts +33 -0
  152. package/dist/parts/XmlPart.mjs +105 -2
  153. package/dist/parts/pml/defaults.d.mts +6 -0
  154. package/dist/parts/pml/defaults.mjs +53 -0
  155. package/dist/parts/pml/index.d.mts +66 -3
  156. package/dist/parts/pml/index.mjs +206 -7
  157. package/dist/parts/pml/placeholders.d.mts +71 -0
  158. package/dist/parts/pml/placeholders.mjs +141 -0
  159. package/dist/parts/sml/index.d.mts +19 -1
  160. package/dist/parts/sml/index.mjs +60 -1
  161. package/dist/parts/wml/comments.d.mts +1 -0
  162. package/dist/parts/wml/comments.mjs +179 -0
  163. package/dist/parts/wml/defaultNumbering.d.mts +1 -0
  164. package/dist/parts/wml/defaultNumbering.mjs +216 -0
  165. package/dist/parts/wml/index.d.mts +121 -0
  166. package/dist/parts/wml/index.mjs +291 -0
  167. package/dist/xml/dom.mjs +1 -2
  168. package/package.json +25 -4
@@ -0,0 +1,778 @@
1
+ import { deepCopy, unmarshalNode } from '@docx4j/generated-objects-ts';
2
+ import * as f from '@docx4j/generated-objects-ts/factory/org_docx4j_wml';
3
+ import { parseXml } from '../../xml/dom.mjs';
4
+ import { Docx4JException } from '../../opc/exceptions.mjs';
5
+ import { DEFAULT_NUMBERING_XML } from '../../parts/wml/defaultNumbering.mjs';
6
+ import { NumberingState, storyKindOf } from '../listnumbering/state.mjs';
7
+ import { LEVELS } from '../listnumbering/definitions.mjs';
8
+ import { isElement, linkParents } from './tree.mjs';
9
+ import { Font } from './Font.mjs';
10
+ function packageOf(body) {
11
+ const pkg = body.package_;
12
+ return typeof (pkg === null || pkg === void 0 ? void 0 : pkg.getMainDocumentPart) === 'function' ? pkg : undefined;
13
+ }
14
+ function mainOf(body) {
15
+ var _a;
16
+ try {
17
+ return (_a = packageOf(body)) === null || _a === void 0 ? void 0 : _a.getMainDocumentPart();
18
+ }
19
+ catch {
20
+ return undefined; // no main document part
21
+ }
22
+ }
23
+ /** The numbering part, or undefined where the document has none. */
24
+ function numberingPartOf(body) {
25
+ var _a;
26
+ return (_a = mainOf(body)) === null || _a === void 0 ? void 0 : _a.numberingDefinitionsPart;
27
+ }
28
+ /** The definitions, or undefined where there is no numbering part or nothing has read it. */
29
+ function definitionsOf(body) {
30
+ var _a;
31
+ try {
32
+ return (_a = numberingPartOf(body)) === null || _a === void 0 ? void 0 : _a.definitions;
33
+ }
34
+ catch {
35
+ return undefined; // the part has not been read (await pkg.getPropertyResolver())
36
+ }
37
+ }
38
+ /**
39
+ * The package's numbering emulator, or undefined where the document has no lists (or nothing
40
+ * has read the numbering part: `await pkg.getBody()` builds the resolver, which reads it).
41
+ */
42
+ export function numberingEmulatorOf(body) {
43
+ var _a;
44
+ try {
45
+ return (_a = numberingPartOf(body)) === null || _a === void 0 ? void 0 : _a.getEmulator();
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ }
51
+ /** Where a paragraph's numbering resolves to (docx4j `Emulator.numRefFor`), or undefined. */
52
+ function numRefOf(paragraph) {
53
+ var _a;
54
+ const ref = (_a = numberingEmulatorOf(paragraph.parentBody)) === null || _a === void 0 ? void 0 : _a.numRefFor(paragraph.p.pPr);
55
+ return ref === undefined || ref.notNumbered ? undefined : ref;
56
+ }
57
+ // --------------------------------------------------------------------------- the story walk
58
+ /**
59
+ * Every paragraph under `root` in document order, each with the {@link NumberingState} it
60
+ * counts in. `test/parity.test.mjs`'s `walkNumbering`, which is the harness's own walk: a text
61
+ * box's paragraphs stay in this story's list (they are in the part, in document order) but
62
+ * count in a story of their own, which is docx4j's rule (CR-014 probe P7).
63
+ */
64
+ function walkStory(root, state, emit) {
65
+ const walk = (value, current) => {
66
+ if (Array.isArray(value)) {
67
+ for (const item of value)
68
+ walk(item, current);
69
+ return;
70
+ }
71
+ if (typeof value !== 'object' || value === null)
72
+ return;
73
+ if (isElement(value)) {
74
+ walk(value.value, current);
75
+ return;
76
+ }
77
+ const node = value;
78
+ let inner = current;
79
+ if (node.TYPE_NAME === 'org_docx4j_wml.P')
80
+ emit(node, current);
81
+ else if (node.TYPE_NAME === 'org_docx4j_wml.CTTxbxContent')
82
+ inner = new NumberingState();
83
+ for (const key of Object.keys(node)) {
84
+ if (key === 'PARENT' || key === 'TYPE_NAME')
85
+ continue;
86
+ walk(node[key], inner);
87
+ }
88
+ };
89
+ walk(root, state);
90
+ }
91
+ /**
92
+ * The parts whose paragraphs share one story with this one, in docx4j's order: every header
93
+ * then every footer for a header or a footer, and the part alone otherwise (CR-001 section
94
+ * 15.2, `NumberingStates.forPart`).
95
+ */
96
+ function storyPartsOf(body, part) {
97
+ if (storyKindOf(part) !== 'headersFooters')
98
+ return [part];
99
+ const main = mainOf(body);
100
+ return main === undefined ? [part] : [...main.headerParts, ...main.footerParts];
101
+ }
102
+ /**
103
+ * Every numbered paragraph of this body's **story**, with the label and the counters, in one
104
+ * walk. A header or footer that has not been unmarshalled contributes nothing to the count,
105
+ * since it cannot be read synchronously: `await part.getBody()` on each first where a footer's
106
+ * numbers must continue the headers' (the story rule).
107
+ */
108
+ export function listLabelsOf(body) {
109
+ const out = new Map();
110
+ const emulator = numberingEmulatorOf(body);
111
+ const part = body.part;
112
+ if (emulator === undefined || part === undefined)
113
+ return out;
114
+ const state = new NumberingState();
115
+ for (const story of storyPartsOf(body, part)) {
116
+ if (!story.isUnmarshalled)
117
+ continue;
118
+ walkStory(story.contents, state, (p, counters) => {
119
+ var _a, _b, _c, _d, _e;
120
+ const result = emulator.getNumber(p.pPr, counters);
121
+ if (result === undefined || result.numString === undefined)
122
+ return;
123
+ out.set(p, {
124
+ listString: result.numString,
125
+ level: Number((_a = result.ilvl) !== null && _a !== void 0 ? _a : '0'),
126
+ numId: (_b = result.numId) !== null && _b !== void 0 ? _b : '',
127
+ siblingIndex: ((_c = result.count) !== null && _c !== void 0 ? _c : 1) - ((_e = (_d = result.level) === null || _d === void 0 ? void 0 : _d.start) !== null && _e !== void 0 ? _e : 1),
128
+ isBullet: result.isBullet,
129
+ });
130
+ });
131
+ }
132
+ return out;
133
+ }
134
+ /** The label of one paragraph, from a walk of its story. */
135
+ function labelOf(paragraph) {
136
+ return listLabelsOf(paragraph.parentBody).get(paragraph.p);
137
+ }
138
+ // ------------------------------------------------------------------------- the null objects
139
+ /**
140
+ * Office JS's `*OrNullObject` result: `isNullObject` is true and every other member throws.
141
+ * `src/office-js/proxy.mts` has the same shape for collections; it is repeated here rather
142
+ * than imported so that the content API does not pull the shim's proxies into a bundle.
143
+ */
144
+ function nullObject(className) {
145
+ const fail = (member) => {
146
+ throw new ItemNotFound(`Word.${className} is a null object (this paragraph is not a list item); check isNullObject before using ${member}`);
147
+ };
148
+ const proxy = new Proxy({ isNullObject: true }, {
149
+ get(target, prop) {
150
+ if (typeof prop === 'symbol')
151
+ return Reflect.get(target, prop);
152
+ if (prop === 'isNullObject')
153
+ return true;
154
+ if (prop === 'toJSON')
155
+ return () => ({ isNullObject: true });
156
+ if (prop === 'then')
157
+ return undefined;
158
+ return fail(prop);
159
+ },
160
+ set(_target, prop) {
161
+ return fail(String(prop));
162
+ },
163
+ });
164
+ return proxy;
165
+ }
166
+ /**
167
+ * Nothing matched, as Office JS's `ItemNotFound` says it: the same `code` as the shim's
168
+ * `ItemNotFoundError`, so add-in code branching on `error.code` behaves the same.
169
+ */
170
+ class ItemNotFound extends Error {
171
+ constructor(message) {
172
+ super(message);
173
+ this.code = 'ItemNotFound';
174
+ this.name = 'ItemNotFoundError';
175
+ }
176
+ }
177
+ export { ItemNotFound as ListItemNotFoundError };
178
+ // -------------------------------------------------------------------------------- the views
179
+ /**
180
+ * A subset of Office JS `Word.List` over one `w:num` and the `w:abstractNum` it names. A light
181
+ * view: it holds the `w:numId` and the body it was found through, and resolves both elements
182
+ * through the numbering part's definitions on every call.
183
+ *
184
+ * Every `setLevel*` method writes on the **abstract** definition, copying it first where
185
+ * another `w:num` shares it ({@link separate}), so that the change stays local to this list;
186
+ * each then refreshes the package's resolver, which rebuilds the numbering definitions.
187
+ */
188
+ export class List {
189
+ constructor(
190
+ /** `w:numId`, as a string (docx4j's key; {@link id} is Office JS's number). */
191
+ numId,
192
+ /** The body this list was found through: where {@link paragraphs} looks. */
193
+ body) {
194
+ this.numId = numId;
195
+ this.body = body;
196
+ }
197
+ /** Office JS `list.id`: the `w:numId`. */
198
+ get id() {
199
+ return Number(this.numId);
200
+ }
201
+ /** The definitions this list is read from; throws where the numbering part has not been read. */
202
+ get definitions() {
203
+ const definitions = definitionsOf(this.body);
204
+ if (definitions === undefined) {
205
+ throw new Docx4JException('This document has no numbering definitions; await pkg.getBody() (or getPropertyResolver()) first');
206
+ }
207
+ return definitions;
208
+ }
209
+ /** The `w:num`'s definition (docx4j `ListNumberingDefinition`). */
210
+ get definition() {
211
+ const definition = this.definitions.list(this.numId);
212
+ if (definition === undefined)
213
+ throw new ItemNotFound(`No w:num for numId ${this.numId}`);
214
+ return definition;
215
+ }
216
+ /** The `w:num` (extension: the tree). */
217
+ get element() {
218
+ return this.definition.num;
219
+ }
220
+ /** The `w:abstractNum` this list resolves to (extension: the tree). */
221
+ get abstractElement() {
222
+ var _a;
223
+ return (_a = this.definition.abstractDefinition) === null || _a === void 0 ? void 0 : _a.abstractNum;
224
+ }
225
+ /** The level definition (the abstract level with this `w:num`'s override over it), or undefined. */
226
+ level(level) {
227
+ return this.definition.level(level);
228
+ }
229
+ /** Office JS `list.levelExistences`: whether each of the nine levels is defined. */
230
+ get levelExistences() {
231
+ return Array.from({ length: LEVELS }, (_, i) => this.definition.levelExists(i));
232
+ }
233
+ /** Whether the level is defined (extension; Office JS has {@link levelExistences}). */
234
+ levelExists(level) {
235
+ return this.definition.levelExists(level);
236
+ }
237
+ /**
238
+ * Office JS `list.levelTypes`: `Bullet`, `Number` or `Picture` for each of the nine levels,
239
+ * from the level's `w:numFmt` and its `w:lvlPicBulletId`. A level that is not defined reads
240
+ * `Number`, as Office JS reports for a level with no format of its own.
241
+ */
242
+ get levelTypes() {
243
+ return Array.from({ length: LEVELS }, (_, i) => {
244
+ const level = this.level(i);
245
+ if (level === undefined)
246
+ return 'Number';
247
+ if (level.lvlPicBulletId !== undefined)
248
+ return 'Picture';
249
+ return level.isBullet ? 'Bullet' : 'Number';
250
+ });
251
+ }
252
+ /** Office JS `list.getLevelString(level)`: the level's `w:lvlText` ('%1.', '(%2)', a bullet). */
253
+ getLevelString(level) {
254
+ var _a, _b;
255
+ return (_b = (_a = this.level(level)) === null || _a === void 0 ? void 0 : _a.lvlText) !== null && _b !== void 0 ? _b : '';
256
+ }
257
+ /**
258
+ * Office JS `list.getLevelFont(level)`: the `Font` the level's label is drawn with, over the
259
+ * level's `w:rPr`.
260
+ *
261
+ * **It is a writable view**, and Office JS pairs it with `resetLevelFont`, so it
262
+ * {@link separate}s first: the numbering part becomes live and a shared abstract definition
263
+ * is copied, exactly as the `setLevel*` methods do. A read that must not cost the part its
264
+ * byte-for-byte round trip is `list.level(n).labelRPr` (CR-002 section 17).
265
+ */
266
+ getLevelFont(level) {
267
+ this.separate();
268
+ const holder = this.writableLvl(level);
269
+ return new Font(() => [holder]);
270
+ }
271
+ /** Office JS `list.getLevelParagraphs(level)`: this body's paragraphs at that level of this list. */
272
+ getLevelParagraphs(level) {
273
+ return this.paragraphs.filter((p) => levelOf(p) === level);
274
+ }
275
+ /**
276
+ * Office JS `list.paragraphs`: every paragraph of this body whose effective `w:numPr` names
277
+ * this list, in document order (a style-contributed `w:numPr` counts).
278
+ */
279
+ get paragraphs() {
280
+ return this.body.paragraphs.filter((p) => { var _a; return ((_a = numRefOf(p)) === null || _a === void 0 ? void 0 : _a.numId) === this.numId; });
281
+ }
282
+ /**
283
+ * Office JS `list.insertParagraph(text, location)`: a new paragraph of this list before its
284
+ * first item or after its last, at that item's level.
285
+ */
286
+ insertParagraph(text, location) {
287
+ var _a;
288
+ const items = this.paragraphs;
289
+ if (items.length === 0) {
290
+ throw new ItemNotFound(`List ${this.id} has no paragraphs in this body to insert relative to`);
291
+ }
292
+ const anchor = location === 'Start' ? items[0] : items[items.length - 1];
293
+ const paragraph = anchor.insertParagraph(text, location === 'Start' ? 'Before' : 'After');
294
+ paragraph.attachToList(this.id, (_a = levelOf(anchor)) !== null && _a !== void 0 ? _a : 0);
295
+ return paragraph;
296
+ }
297
+ // --- the level writers ------------------------------------------------------------------
298
+ /**
299
+ * Office JS `list.setLevelNumbering(level, listNumbering, formatString)`: the level's
300
+ * `w:numFmt` and, from `formatString`, its `w:lvlText` - each number in the array is a
301
+ * 0-based level whose counter goes there (`[0, '.', 1]` is `'%1.%2'`), each string a literal.
302
+ * Without one the level numbers itself and takes a trailing full stop (`'%<n>.'`).
303
+ */
304
+ setLevelNumbering(level, listNumbering, formatString) {
305
+ const lvl = this.writableLvl(level);
306
+ lvl.numFmt = f.createNumFmt({ val: NUMBERING_FORMATS[listNumbering] });
307
+ linkParents(lvl.numFmt, lvl);
308
+ lvl.lvlText = f.createLvlLvlText({ val: lvlTextOf(level, formatString) });
309
+ linkParents(lvl.lvlText, lvl);
310
+ this.written();
311
+ }
312
+ /**
313
+ * Office JS `list.setLevelBullet(level, listBullet, charCode, fontName)`: the level's
314
+ * `w:numFmt` becomes `bullet` and its `w:lvlText` the bullet character, with the font in the
315
+ * level's `w:rPr/w:rFonts`. `Custom` takes `charCode` and `fontName`; the other six are the
316
+ * characters and faces Word's bullet library uses.
317
+ */
318
+ setLevelBullet(level, listBullet, charCode, fontName) {
319
+ var _a, _b;
320
+ const preset = BULLETS[listBullet];
321
+ const code = listBullet === 'Custom' ? charCode : preset === null || preset === void 0 ? void 0 : preset.charCode;
322
+ if (code === undefined)
323
+ throw new Docx4JException("setLevelBullet('Custom') needs a charCode");
324
+ const font = fontName !== null && fontName !== void 0 ? fontName : preset === null || preset === void 0 ? void 0 : preset.fontName;
325
+ const lvl = this.writableLvl(level);
326
+ lvl.numFmt = f.createNumFmt({ val: 'bullet' });
327
+ linkParents(lvl.numFmt, lvl);
328
+ lvl.lvlText = f.createLvlLvlText({ val: String.fromCharCode(code) });
329
+ linkParents(lvl.lvlText, lvl);
330
+ if (font !== undefined && font !== '') {
331
+ const rPr = ((_a = lvl.rPr) !== null && _a !== void 0 ? _a : (lvl.rPr = { TYPE_NAME: 'org_docx4j_wml.RPr' }));
332
+ const rFonts = ((_b = rPr.rFonts) !== null && _b !== void 0 ? _b : (rPr.rFonts = { TYPE_NAME: 'org_docx4j_wml.RFonts' }));
333
+ rFonts.ascii = font;
334
+ rFonts.hAnsi = font;
335
+ rFonts.hint = 'default';
336
+ linkParents(rPr, lvl);
337
+ }
338
+ this.written();
339
+ }
340
+ /**
341
+ * Office JS `list.setLevelIndents(level, textIndent, bulletNumberPictureIndent)`, both in
342
+ * points: the level's `w:ind/@w:left` is where the text sits and the label's position is the
343
+ * hanging indent from it (or `w:firstLine` where the label sits to the right of the text).
344
+ */
345
+ setLevelIndents(level, textIndent, bulletNumberPictureIndent) {
346
+ var _a, _b;
347
+ const lvl = this.writableLvl(level);
348
+ const pPr = ((_a = lvl.pPr) !== null && _a !== void 0 ? _a : (lvl.pPr = { TYPE_NAME: 'org_docx4j_wml.PPr' }));
349
+ const ind = ((_b = pPr.ind) !== null && _b !== void 0 ? _b : (pPr.ind = f.createPPrBaseInd({})));
350
+ const left = Math.round(textIndent * TWIPS_PER_POINT);
351
+ const label = Math.round(bulletNumberPictureIndent * TWIPS_PER_POINT);
352
+ ind.left = left;
353
+ if (label <= left) {
354
+ ind.hanging = left - label;
355
+ delete ind.firstLine;
356
+ }
357
+ else {
358
+ ind.firstLine = label - left;
359
+ delete ind.hanging;
360
+ }
361
+ linkParents(pPr, lvl);
362
+ this.written();
363
+ }
364
+ /** Office JS `list.setLevelAlignment(level, alignment)`: the level's `w:lvlJc`. */
365
+ setLevelAlignment(level, alignment) {
366
+ const lvl = this.writableLvl(level);
367
+ const val = LVL_JC[alignment];
368
+ if (val === undefined)
369
+ delete lvl.lvlJc;
370
+ else {
371
+ lvl.lvlJc = f.createJc({ val });
372
+ linkParents(lvl.lvlJc, lvl);
373
+ }
374
+ this.written();
375
+ }
376
+ /**
377
+ * Office JS `list.setLevelStartingNumber(level, startingNumber)`: the level's `w:start`. A
378
+ * `w:startOverride` this `w:num` carries for the level would still win the first use, so it
379
+ * is removed with it.
380
+ */
381
+ setLevelStartingNumber(level, startingNumber) {
382
+ var _a;
383
+ const lvl = this.writableLvl(level);
384
+ lvl.start = f.createLvlStart({ val: startingNumber });
385
+ linkParents(lvl.start, lvl);
386
+ for (const override of (_a = this.element.lvlOverride) !== null && _a !== void 0 ? _a : []) {
387
+ if (Number(override.ilvl) === level)
388
+ delete override.startOverride;
389
+ }
390
+ this.written();
391
+ }
392
+ /**
393
+ * A new `w:num` over this list's `w:abstractNum` with a `w:startOverride` on level 0, which
394
+ * is how Word restarts a list: the counters are shared by abstract definition, and the
395
+ * override is spent on the new `w:num`'s first use in a story (CR-001 section 15.2). Attach
396
+ * the paragraphs that are to start again to the list it returns.
397
+ *
398
+ * Extension name (Office JS has no restart verb); `Paragraph.restartList()` is the sugar.
399
+ */
400
+ restart() {
401
+ var _a, _b, _c;
402
+ const numbering = this.live();
403
+ const num = this.element;
404
+ const start = (_b = (_a = this.level(0)) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 1;
405
+ const created = f.createNumberingNum({
406
+ numId: nextNumId(numbering),
407
+ abstractNumId: f.createNumberingNumAbstractNumId({ val: num.abstractNumId.val }),
408
+ lvlOverride: [f.createNumberingNumLvlOverride({
409
+ ilvl: 0,
410
+ startOverride: f.createNumberingNumLvlOverrideStartOverride({ val: start }),
411
+ })],
412
+ });
413
+ ((_c = numbering.num) !== null && _c !== void 0 ? _c : (numbering.num = [])).push(created);
414
+ linkParents(created, numbering);
415
+ this.written();
416
+ return new List(String(created.numId), this.body);
417
+ }
418
+ /**
419
+ * Gives this list a `w:abstractNum` of its own where another `w:num` shares the one it names
420
+ * (CR-002 section 3.9), so that a change to its levels stays local to it. The numbering part
421
+ * becomes live either way; the `setLevel*` methods call it for you.
422
+ */
423
+ separate() {
424
+ var _a, _b, _c;
425
+ const numbering = this.live();
426
+ const num = this.element;
427
+ const abstractId = num.abstractNumId.val;
428
+ const shared = ((_a = numbering.num) !== null && _a !== void 0 ? _a : []).some((other) => { var _a; return other !== num && ((_a = other.abstractNumId) === null || _a === void 0 ? void 0 : _a.val) === abstractId; });
429
+ if (!shared)
430
+ return;
431
+ const source = ((_b = numbering.abstractNum) !== null && _b !== void 0 ? _b : []).find((a) => a.abstractNumId === abstractId);
432
+ if (source === undefined)
433
+ return;
434
+ const copy = deepCopy(source);
435
+ copy.abstractNumId = nextAbstractNumId(numbering);
436
+ copy.nsid = f.createCTLongHexNumber({ val: hexId() });
437
+ // w:styleLink maps a numbering style to one definition; the copy must not claim it too
438
+ delete copy.styleLink;
439
+ ((_c = numbering.abstractNum) !== null && _c !== void 0 ? _c : (numbering.abstractNum = [])).push(copy);
440
+ linkParents(copy, numbering);
441
+ num.abstractNumId = f.createNumberingNumAbstractNumId({ val: copy.abstractNumId });
442
+ linkParents(num.abstractNumId, num);
443
+ this.written();
444
+ }
445
+ // --- internals --------------------------------------------------------------------------
446
+ /** The numbering part's live tree; the first write promotes the tree the definitions hold. */
447
+ live() {
448
+ const part = numberingPartOf(this.body);
449
+ if (part === undefined)
450
+ throw new Docx4JException('This document has no numbering part');
451
+ return part.makeLive();
452
+ }
453
+ /**
454
+ * The `w:lvl` a write goes to: this list's own abstract definition's, created where the
455
+ * definition has no level for it. A `w:lvlOverride/w:lvl` this `w:num` carries for the level
456
+ * would mask the abstract one, so it goes (the `w:startOverride` beside it stays).
457
+ */
458
+ writableLvl(level) {
459
+ var _a, _b;
460
+ this.separate();
461
+ const abstract = this.abstractElement;
462
+ if (abstract === undefined) {
463
+ throw new ItemNotFound(`w:num ${this.numId} names no w:abstractNum that this document defines`);
464
+ }
465
+ for (const override of (_a = this.element.lvlOverride) !== null && _a !== void 0 ? _a : []) {
466
+ if (Number(override.ilvl) === level)
467
+ delete override.lvl;
468
+ }
469
+ const levels = ((_b = abstract.lvl) !== null && _b !== void 0 ? _b : (abstract.lvl = []));
470
+ let lvl = levels.find((l) => Number(l.ilvl) === level);
471
+ if (lvl === undefined) {
472
+ lvl = f.createLvl({ ilvl: level });
473
+ levels.push(lvl);
474
+ levels.sort((a, b) => Number(a.ilvl) - Number(b.ilvl));
475
+ linkParents(lvl, abstract);
476
+ }
477
+ return lvl;
478
+ }
479
+ /** The numbering tree changed: the resolver (and with it the definitions) is rebuilt. */
480
+ written() {
481
+ var _a;
482
+ (_a = packageOf(this.body)) === null || _a === void 0 ? void 0 : _a.refreshPropertyResolver();
483
+ }
484
+ }
485
+ /**
486
+ * A subset of Office JS `Word.ListItem` over one paragraph's place in its list. A view: the
487
+ * paragraph is the state.
488
+ */
489
+ export class ListItem {
490
+ constructor(
491
+ /** The paragraph this is the list item of (Office JS: `paragraph.listItem`). */
492
+ paragraph) {
493
+ this.paragraph = paragraph;
494
+ }
495
+ /** Where this paragraph's numbering resolves to; throws when it is not a list item any more. */
496
+ get ref() {
497
+ const ref = numRefOf(this.paragraph);
498
+ if (ref === undefined)
499
+ throw new ItemNotFound('This paragraph is not a list item');
500
+ return ref;
501
+ }
502
+ /** The list this item is in. */
503
+ get list() {
504
+ return new List(this.ref.numId, this.paragraph.parentBody);
505
+ }
506
+ /**
507
+ * Office JS `listItem.level`: the `w:ilvl` the paragraph counts at, a style-contributed level
508
+ * included. Setting it writes the paragraph's own `w:numPr/w:ilvl` (with the `w:numId` beside
509
+ * it where the list came from the style), through the accessor that records `w:pPrChange`
510
+ * while the package tracks changes.
511
+ */
512
+ get level() {
513
+ var _a;
514
+ return Number((_a = this.ref.ilvl) !== null && _a !== void 0 ? _a : '0');
515
+ }
516
+ set level(value) {
517
+ var _a;
518
+ const ref = this.ref;
519
+ const numPr = this.paragraph.numPr();
520
+ if (((_a = numPr.numId) === null || _a === void 0 ? void 0 : _a.val) === undefined && ref.numId !== undefined) {
521
+ numPr.numId = f.createPPrBaseNumPrNumId({ val: Number(ref.numId) });
522
+ linkParents(numPr.numId, numPr);
523
+ }
524
+ numPr.ilvl = f.createPPrBaseNumPrIlvl({ val: value });
525
+ linkParents(numPr.ilvl, numPr);
526
+ }
527
+ /**
528
+ * Office JS `listItem.listString`: the label Word paints in front of the paragraph.
529
+ *
530
+ * It is counted by walking the paragraph's **story** from its start in document order
531
+ * (CR-001 section 15.2), so it costs one walk of the story per read; `Body.listLabels()`
532
+ * answers for every paragraph of the story in one walk.
533
+ */
534
+ get listString() {
535
+ var _a, _b;
536
+ return (_b = (_a = labelOf(this.paragraph)) === null || _a === void 0 ? void 0 : _a.listString) !== null && _b !== void 0 ? _b : '';
537
+ }
538
+ /**
539
+ * Office JS `listItem.siblingIndex`: the 0-based index of this item among the items of the
540
+ * same list and level, counted from where the level last restarted. The same walk as
541
+ * {@link listString}.
542
+ */
543
+ get siblingIndex() {
544
+ var _a, _b;
545
+ return (_b = (_a = labelOf(this.paragraph)) === null || _a === void 0 ? void 0 : _a.siblingIndex) !== null && _b !== void 0 ? _b : 0;
546
+ }
547
+ /**
548
+ * Office JS `listItem.getAncestor(parentOnly)`: the nearest preceding paragraph of this list
549
+ * at a shallower level - the parent when `parentOnly` is true, which throws when the nearest
550
+ * one is not exactly one level up. Throws `ItemNotFound` when there is no ancestor.
551
+ */
552
+ getAncestor(parentOnly = false) {
553
+ const level = this.level;
554
+ const items = this.list.paragraphs;
555
+ const at = items.findIndex((p) => p.p === this.paragraph.p);
556
+ for (let i = at - 1; i >= 0; i--) {
557
+ const other = levelOf(items[i]);
558
+ if (other === undefined || other >= level)
559
+ continue;
560
+ if (parentOnly && other !== level - 1)
561
+ break;
562
+ return items[i];
563
+ }
564
+ throw new ItemNotFound(`This list item (level ${level}) has no ${parentOnly ? 'parent' : 'ancestor'} in list ${this.list.id}`);
565
+ }
566
+ /**
567
+ * Office JS `listItem.getDescendants(directChildrenOnly)`: the paragraphs of this list which
568
+ * follow this one at a deeper level, up to the next one at this level or shallower; only the
569
+ * ones one level down when `directChildrenOnly` is true.
570
+ */
571
+ getDescendants(directChildrenOnly = false) {
572
+ const level = this.level;
573
+ const items = this.list.paragraphs;
574
+ const at = items.findIndex((p) => p.p === this.paragraph.p);
575
+ const out = [];
576
+ for (let i = at + 1; i < items.length; i++) {
577
+ const other = levelOf(items[i]);
578
+ if (other === undefined || other <= level)
579
+ break;
580
+ if (!directChildrenOnly || other === level + 1)
581
+ out.push(items[i]);
582
+ }
583
+ return out;
584
+ }
585
+ }
586
+ // ------------------------------------------------------------- what Paragraph and Body call
587
+ /** The effective `w:ilvl` of a paragraph, or undefined when it is not a list item. */
588
+ export function levelOf(paragraph) {
589
+ var _a;
590
+ const ref = numRefOf(paragraph);
591
+ return ref === undefined ? undefined : Number((_a = ref.ilvl) !== null && _a !== void 0 ? _a : '0');
592
+ }
593
+ /** Office JS `paragraph.isListItem`: docx4j's `Emulator.numRefFor` answers it. */
594
+ export function isListItem(paragraph) {
595
+ return numRefOf(paragraph) !== undefined;
596
+ }
597
+ /** Office JS `paragraph.listItem`; throws `ItemNotFound` when the paragraph is not one. */
598
+ export function listItemOf(paragraph) {
599
+ if (!isListItem(paragraph)) {
600
+ throw new ItemNotFound('This paragraph is not a list item (listItemOrNullObject does not throw)');
601
+ }
602
+ return new ListItem(paragraph);
603
+ }
604
+ /** Office JS `paragraph.listItemOrNullObject`. */
605
+ export function listItemOrNullObjectOf(paragraph) {
606
+ return isListItem(paragraph) ? new ListItem(paragraph) : nullObject('ListItem');
607
+ }
608
+ /** Office JS `paragraph.list`; throws `ItemNotFound` when the paragraph is not a list item. */
609
+ export function listOf(paragraph) {
610
+ const ref = numRefOf(paragraph);
611
+ if (ref === undefined) {
612
+ throw new ItemNotFound('This paragraph is not a list item (listOrNullObject does not throw)');
613
+ }
614
+ return new List(ref.numId, paragraph.parentBody);
615
+ }
616
+ /** Office JS `paragraph.listOrNullObject`. */
617
+ export function listOrNullObjectOf(paragraph) {
618
+ const ref = numRefOf(paragraph);
619
+ return ref === undefined ? nullObject('List') : new List(ref.numId, paragraph.parentBody);
620
+ }
621
+ /** Office JS `body.lists`: every `w:num` a paragraph of this body names, in order of first use. */
622
+ export function listsOf(body) {
623
+ const emulator = numberingEmulatorOf(body);
624
+ if (emulator === undefined)
625
+ return [];
626
+ const seen = new Set();
627
+ const out = [];
628
+ for (const paragraph of body.paragraphs) {
629
+ const ref = emulator.numRefFor(paragraph.p.pPr);
630
+ if (ref.notNumbered || ref.numId === undefined || seen.has(ref.numId))
631
+ continue;
632
+ seen.add(ref.numId);
633
+ out.push(new List(ref.numId, body));
634
+ }
635
+ return out;
636
+ }
637
+ /** Office JS `paragraph.attachToList(listId, level)`: the paragraph's own `w:numPr`. */
638
+ export function attachToList(paragraph, listId, level = 0) {
639
+ const numPr = paragraph.numPr();
640
+ numPr.numId = f.createPPrBaseNumPrNumId({ val: Number(listId) });
641
+ numPr.ilvl = f.createPPrBaseNumPrIlvl({ val: level });
642
+ linkParents(numPr, paragraph.p.pPr);
643
+ return new List(String(listId), paragraph.parentBody);
644
+ }
645
+ /**
646
+ * Office JS `paragraph.detachFromList()`: the paragraph's own `w:numPr` goes. Where its style
647
+ * still numbers it, a `w:numPr` with `w:numId` 0 takes its place, which is how Word switches an
648
+ * inherited list off (ECMA-376 17.9.18, and what `Emulator.resolve` reads).
649
+ */
650
+ export function detachFromList(paragraph) {
651
+ var _a;
652
+ if (((_a = paragraph.p.pPr) === null || _a === void 0 ? void 0 : _a.numPr) !== undefined) {
653
+ delete paragraph.pPr().numPr;
654
+ }
655
+ if (!isListItem(paragraph))
656
+ return;
657
+ const numPr = paragraph.numPr();
658
+ numPr.numId = f.createPPrBaseNumPrNumId({ val: 0 });
659
+ linkParents(numPr.numId, numPr);
660
+ delete numPr.ilvl;
661
+ }
662
+ /**
663
+ * Office JS `paragraph.startNewList()`: a `w:abstractNum` copied from docx4j's default
664
+ * definitions (its `numbering.xml` resource: `w:abstractNum` 1 is Word's decimal set and 0 its
665
+ * bullet set), a `w:num` for it, and the paragraph attached to that list.
666
+ *
667
+ * Asynchronous where Office JS's is synchronous: the default definitions are XML which has to
668
+ * be unmarshalled, and a document with no numbering part gets one here (CR-002 section 17).
669
+ */
670
+ export async function startNewList(paragraph, options) {
671
+ var _a, _b, _c, _d, _e;
672
+ const body = paragraph.parentBody;
673
+ const part = await ensureNumberingPart(body);
674
+ const numbering = await part.getContents();
675
+ const defaults = await defaultNumbering();
676
+ const template = ((_a = defaults.abstractNum) !== null && _a !== void 0 ? _a : [])[(options === null || options === void 0 ? void 0 : options.bullet) === true ? 0 : 1];
677
+ if (template === undefined)
678
+ throw new Docx4JException('The default numbering definitions are missing an abstractNum');
679
+ const abstract = deepCopy(template);
680
+ abstract.abstractNumId = nextAbstractNumId(numbering);
681
+ abstract.nsid = f.createCTLongHexNumber({ val: hexId() });
682
+ delete abstract.styleLink;
683
+ delete abstract.numStyleLink;
684
+ ((_b = numbering.abstractNum) !== null && _b !== void 0 ? _b : (numbering.abstractNum = [])).push(abstract);
685
+ linkParents(abstract, numbering);
686
+ const num = f.createNumberingNum({
687
+ numId: nextNumId(numbering),
688
+ abstractNumId: f.createNumberingNumAbstractNumId({ val: abstract.abstractNumId }),
689
+ });
690
+ ((_c = numbering.num) !== null && _c !== void 0 ? _c : (numbering.num = [])).push(num);
691
+ linkParents(num, numbering);
692
+ (_d = packageOf(body)) === null || _d === void 0 ? void 0 : _d.refreshPropertyResolver();
693
+ return attachToList(paragraph, num.numId, (_e = options === null || options === void 0 ? void 0 : options.level) !== null && _e !== void 0 ? _e : 0);
694
+ }
695
+ /**
696
+ * The numbering part, created with docx4j's default numbering where the document has none
697
+ * (docx4j's own `createNumbering` idiom), and unmarshalled either way so that what is written
698
+ * to it is saved.
699
+ */
700
+ async function ensureNumberingPart(body) {
701
+ const pkg = packageOf(body);
702
+ const main = mainOf(body);
703
+ if (pkg === undefined || main === undefined) {
704
+ throw new Docx4JException('This body has no package, so a list cannot be added to it');
705
+ }
706
+ const existing = main.numberingDefinitionsPart;
707
+ if (existing !== undefined) {
708
+ // the resolver read the part privately; unmarshalling it gives a second tree, so the
709
+ // definitions (and the `getInd` the resolver folds into every layer) are rebuilt over the
710
+ // live one
711
+ const before = existing.isUnmarshalled;
712
+ await existing.getContents();
713
+ if (!before)
714
+ pkg.refreshPropertyResolver();
715
+ return existing;
716
+ }
717
+ // Imported here so that the content API does not import the parts statically: parts/wml
718
+ // builds the Body views, so a static import would be a runtime cycle (as `ooxml.mts` does).
719
+ const { NumberingDefinitionsPart } = await import('../../parts/wml/index.mjs');
720
+ const created = new NumberingDefinitionsPart();
721
+ main.addTargetPart(created);
722
+ await created.unmarshalDefaultNumbering();
723
+ // the resolver was built before the part existed, and refreshPropertyResolver() cannot find
724
+ // a part added since (CR-001 section 15.2 departure 6)
725
+ await pkg.refresh();
726
+ return created;
727
+ }
728
+ // ----------------------------------------------------------------------------- the mechanics
729
+ const TWIPS_PER_POINT = 20;
730
+ /** Office JS `Word.ListNumbering` as `w:numFmt`. */
731
+ const NUMBERING_FORMATS = {
732
+ None: 'none',
733
+ Arabic: 'decimal',
734
+ UpperRoman: 'upperRoman',
735
+ LowerRoman: 'lowerRoman',
736
+ UpperLetter: 'upperLetter',
737
+ LowerLetter: 'lowerLetter',
738
+ };
739
+ /** Office JS `Word.ListBullet` as the character and face Word's bullet library uses. */
740
+ const BULLETS = {
741
+ Custom: undefined,
742
+ Solid: { charCode: 0xf0b7, fontName: 'Symbol' }, // a filled round bullet
743
+ Hollow: { charCode: 0x006f, fontName: 'Courier New' }, // a lower-case o
744
+ Square: { charCode: 0xf0a7, fontName: 'Wingdings' }, // a filled square
745
+ Diamonds: { charCode: 0xf076, fontName: 'Wingdings' }, // a four-diamond bullet
746
+ Arrow: { charCode: 0xf0d8, fontName: 'Wingdings' }, // a solid right-pointing arrowhead
747
+ Checkmark: { charCode: 0xf0fc, fontName: 'Wingdings' }, // a tick
748
+ };
749
+ /** `w:lvlJc`, which takes the same values as a paragraph's `w:jc`. */
750
+ const LVL_JC = {
751
+ Left: 'left', Centered: 'center', Right: 'right', Justified: 'both', Unknown: undefined,
752
+ };
753
+ /** Office JS's `formatString` as a `w:lvlText`: a number is a 0-based level, a string a literal. */
754
+ function lvlTextOf(level, formatString) {
755
+ if (formatString === undefined || formatString.length === 0)
756
+ return `%${level + 1}.`;
757
+ return formatString.map((part) => (typeof part === 'number' ? `%${part + 1}` : part)).join('');
758
+ }
759
+ /** A free `w:numId`: one past the highest the document uses (Word numbers from 1). */
760
+ function nextNumId(numbering) {
761
+ var _a;
762
+ return ((_a = numbering.num) !== null && _a !== void 0 ? _a : []).reduce((max, num) => Math.max(max, Number(num.numId)), 0) + 1;
763
+ }
764
+ /** A free `w:abstractNumId`. */
765
+ function nextAbstractNumId(numbering) {
766
+ var _a;
767
+ return ((_a = numbering.abstractNum) !== null && _a !== void 0 ? _a : []).reduce((max, a) => Math.max(max, Number(a.abstractNumId)), -1) + 1;
768
+ }
769
+ /** An eight-digit `w:nsid`, which is how Word tells two list families apart. */
770
+ function hexId() {
771
+ return Math.floor(Math.random() * 0x7fffffff).toString(16).toUpperCase().padStart(8, '0');
772
+ }
773
+ /** docx4j's default numbering definitions, unmarshalled once. */
774
+ let defaults;
775
+ function defaultNumbering() {
776
+ defaults !== null && defaults !== void 0 ? defaults : (defaults = (async () => (await unmarshalNode(parseXml(DEFAULT_NUMBERING_XML))).value)());
777
+ return defaults;
778
+ }