@docx4j/core-ts 0.1.0 → 0.1.2

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 (172) 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 +11 -0
  131. package/dist/opc/ContentTypes.mjs +14 -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/Namespaces.d.mts +18 -0
  151. package/dist/parts/Namespaces.mjs +20 -0
  152. package/dist/parts/Part.d.mts +6 -0
  153. package/dist/parts/Part.mjs +13 -0
  154. package/dist/parts/PartRegistry.mjs +13 -1
  155. package/dist/parts/XmlPart.d.mts +33 -0
  156. package/dist/parts/XmlPart.mjs +105 -2
  157. package/dist/parts/pml/defaults.d.mts +6 -0
  158. package/dist/parts/pml/defaults.mjs +53 -0
  159. package/dist/parts/pml/index.d.mts +66 -3
  160. package/dist/parts/pml/index.mjs +206 -7
  161. package/dist/parts/pml/placeholders.d.mts +71 -0
  162. package/dist/parts/pml/placeholders.mjs +141 -0
  163. package/dist/parts/sml/index.d.mts +80 -1
  164. package/dist/parts/sml/index.mjs +154 -1
  165. package/dist/parts/wml/comments.d.mts +1 -0
  166. package/dist/parts/wml/comments.mjs +179 -0
  167. package/dist/parts/wml/defaultNumbering.d.mts +1 -0
  168. package/dist/parts/wml/defaultNumbering.mjs +216 -0
  169. package/dist/parts/wml/index.d.mts +121 -0
  170. package/dist/parts/wml/index.mjs +291 -0
  171. package/dist/xml/dom.mjs +1 -2
  172. package/package.json +25 -4
@@ -0,0 +1,267 @@
1
+ import { deepCopy } from '@docx4j/generated-objects-ts';
2
+ import * as el from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
3
+ import { Docx4JException } from '../../opc/exceptions.mjs';
4
+ /** Word's default checkbox glyphs (docx4j BindingTraverserXSLT uses the same two). */
5
+ export const CHECKED_SYMBOL = '☒';
6
+ export const UNCHECKED_SYMBOL = '☐';
7
+ /** The font Word writes with them. */
8
+ export const CHECKBOX_FONT = 'MS Gothic';
9
+ /** `w14:CTOnOff/@val` is a boolean since objects 0.1.3 (docx4j CR-018); documents holding `w14:val="1"` unmarshal to true. */
10
+ function isOn(value) {
11
+ return value === true;
12
+ }
13
+ /** A hex character code ('2612') as its character; the string itself when it is not one. */
14
+ function symbolOf(state, fallback) {
15
+ const val = state === null || state === void 0 ? void 0 : state.val;
16
+ if (!val)
17
+ return fallback;
18
+ return /^[0-9A-Fa-f]{4,5}$/.test(val) ? String.fromCodePoint(parseInt(val, 16)) : val;
19
+ }
20
+ function codeOf(symbol) {
21
+ const point = symbol.codePointAt(0);
22
+ return point === undefined ? '2610' : point.toString(16).toUpperCase().padStart(4, '0');
23
+ }
24
+ /** Office JS `Word.CheckboxContentControl` over `w14:checkbox`. */
25
+ export class CheckboxContentControl {
26
+ constructor(control, checkbox) {
27
+ this.control = control;
28
+ this.checkbox = checkbox;
29
+ }
30
+ get isChecked() {
31
+ var _a;
32
+ return isOn((_a = this.checkbox.checked) === null || _a === void 0 ? void 0 : _a.val);
33
+ }
34
+ set isChecked(value) {
35
+ var _a;
36
+ var _b;
37
+ ((_a = (_b = this.checkbox).checked) !== null && _a !== void 0 ? _a : (_b.checked = {})).val = value;
38
+ this.control.setCheckboxGlyph(value ? this.checkedSymbol : this.uncheckedSymbol);
39
+ }
40
+ /** The glyph shown when checked (`w14:checkedState/@w14:val`, a hex character code). */
41
+ get checkedSymbol() {
42
+ return symbolOf(this.checkbox.checkedState, CHECKED_SYMBOL);
43
+ }
44
+ set checkedSymbol(symbol) {
45
+ var _a, _b;
46
+ var _c, _d;
47
+ ((_a = (_c = this.checkbox).checkedState) !== null && _a !== void 0 ? _a : (_c.checkedState = {})).val = codeOf(symbol);
48
+ (_b = (_d = this.checkbox.checkedState).font) !== null && _b !== void 0 ? _b : (_d.font = CHECKBOX_FONT);
49
+ }
50
+ get uncheckedSymbol() {
51
+ return symbolOf(this.checkbox.uncheckedState, UNCHECKED_SYMBOL);
52
+ }
53
+ set uncheckedSymbol(symbol) {
54
+ var _a, _b;
55
+ var _c, _d;
56
+ ((_a = (_c = this.checkbox).uncheckedState) !== null && _a !== void 0 ? _a : (_c.uncheckedState = {})).val = codeOf(symbol);
57
+ (_b = (_d = this.checkbox.uncheckedState).font) !== null && _b !== void 0 ? _b : (_d.font = CHECKBOX_FONT);
58
+ }
59
+ /** The font of the two glyphs (extension; Word writes MS Gothic). */
60
+ get font() {
61
+ var _a, _b, _c, _d;
62
+ return (_d = (_b = (_a = this.checkbox.checkedState) === null || _a === void 0 ? void 0 : _a.font) !== null && _b !== void 0 ? _b : (_c = this.checkbox.uncheckedState) === null || _c === void 0 ? void 0 : _c.font) !== null && _d !== void 0 ? _d : CHECKBOX_FONT;
63
+ }
64
+ }
65
+ /** Office JS `Word.DatePickerContentControl` over `w:date`. */
66
+ export class DatePickerContentControl {
67
+ constructor(date) {
68
+ this.date = date;
69
+ }
70
+ /** `w:dateFormat`, Word's .NET date pattern ('d MMMM yyyy'). Office JS calls it dateDisplayFormat. */
71
+ get dateFormat() {
72
+ var _a, _b;
73
+ return (_b = (_a = this.date.dateFormat) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : '';
74
+ }
75
+ set dateFormat(format) {
76
+ if (format === '') {
77
+ delete this.date.dateFormat;
78
+ return;
79
+ }
80
+ this.date.dateFormat = { val: format };
81
+ }
82
+ /** Office JS's name for the same property. */
83
+ get dateDisplayFormat() {
84
+ return this.dateFormat;
85
+ }
86
+ set dateDisplayFormat(format) {
87
+ this.dateFormat = format;
88
+ }
89
+ /** `w:lid`, the language the date is shown in ('en-AU'). */
90
+ get dateDisplayLocale() {
91
+ var _a, _b;
92
+ return (_b = (_a = this.date.lid) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : '';
93
+ }
94
+ set dateDisplayLocale(locale) {
95
+ if (locale === '') {
96
+ delete this.date.lid;
97
+ return;
98
+ }
99
+ this.date.lid = { val: locale };
100
+ }
101
+ /** `w:calendar` ('gregorian', 'hijri', ...). */
102
+ get dateCalendarType() {
103
+ var _a, _b;
104
+ return (_b = (_a = this.date.calendar) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : 'gregorian';
105
+ }
106
+ set dateCalendarType(calendar) {
107
+ this.date.calendar = { val: calendar };
108
+ }
109
+ /** `w:storeMappedDataAs`: how a bound date is written into the custom XML ('dateTime', 'date', 'text'). */
110
+ get dateStorageFormat() {
111
+ var _a, _b;
112
+ return (_b = (_a = this.date.storeMappedDataAs) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : 'text';
113
+ }
114
+ set dateStorageFormat(format) {
115
+ this.date.storeMappedDataAs = { val: format };
116
+ }
117
+ /** `w:fullDate`, the date itself when Word has one (extension). */
118
+ get fullDate() {
119
+ var _a, _b, _c, _d, _e;
120
+ const c = this.date.fullDate;
121
+ if (!c || c.year === undefined || Number.isNaN(c.year))
122
+ return undefined;
123
+ return new Date(Date.UTC(c.year, ((_a = c.month) !== null && _a !== void 0 ? _a : 1) - 1, (_b = c.day) !== null && _b !== void 0 ? _b : 1, (_c = c.hour) !== null && _c !== void 0 ? _c : 0, (_d = c.minute) !== null && _d !== void 0 ? _d : 0, Math.floor((_e = c.second) !== null && _e !== void 0 ? _e : 0)));
124
+ }
125
+ set fullDate(value) {
126
+ if (!value) {
127
+ delete this.date.fullDate;
128
+ return;
129
+ }
130
+ this.date.fullDate = {
131
+ year: value.getUTCFullYear(), month: value.getUTCMonth() + 1, day: value.getUTCDate(),
132
+ hour: value.getUTCHours(), minute: value.getUTCMinutes(), second: value.getUTCSeconds(), timezone: 0,
133
+ };
134
+ }
135
+ }
136
+ /** One entry of a drop-down list or combo box (Office JS `Word.ContentControlListItem`). */
137
+ export class ContentControlListItem {
138
+ constructor(items, item) {
139
+ this.items = items;
140
+ this.item = item;
141
+ }
142
+ get displayText() {
143
+ var _a;
144
+ return (_a = this.item.displayText) !== null && _a !== void 0 ? _a : '';
145
+ }
146
+ set displayText(text) {
147
+ this.item.displayText = text;
148
+ }
149
+ get value() {
150
+ var _a;
151
+ return (_a = this.item.value) !== null && _a !== void 0 ? _a : '';
152
+ }
153
+ set value(value) {
154
+ this.item.value = value;
155
+ }
156
+ get index() {
157
+ return this.items.indexOf(this.item);
158
+ }
159
+ delete() {
160
+ const at = this.index;
161
+ if (at >= 0)
162
+ this.items.splice(at, 1);
163
+ }
164
+ }
165
+ /** Office JS `Word.DropDownListContentControl` / `Word.ComboBoxContentControl`: the same shape. */
166
+ export class ListContentControl {
167
+ constructor(list) {
168
+ this.list = list;
169
+ }
170
+ get listItems() {
171
+ var _a;
172
+ var _b;
173
+ const items = ((_a = (_b = this.list).listItem) !== null && _a !== void 0 ? _a : (_b.listItem = []));
174
+ return items.map((item) => new ContentControlListItem(items, item));
175
+ }
176
+ /** Adds an entry; `value` defaults to the display text, `index` appends when omitted. */
177
+ addListItem(displayText, value, index) {
178
+ var _a;
179
+ var _b;
180
+ const items = ((_a = (_b = this.list).listItem) !== null && _a !== void 0 ? _a : (_b.listItem = []));
181
+ const item = { TYPE_NAME: 'org_docx4j_wml.CTSdtListItem', displayText, value: value !== null && value !== void 0 ? value : displayText };
182
+ if (index === undefined || index >= items.length)
183
+ items.push(item);
184
+ else
185
+ items.splice(Math.max(0, index), 0, item);
186
+ return new ContentControlListItem(items, item);
187
+ }
188
+ deleteAllListItems() {
189
+ this.list.listItem = [];
190
+ }
191
+ /** `w:lastValue`, what Word last showed (extension). */
192
+ get lastValue() {
193
+ var _a;
194
+ return (_a = this.list.lastValue) !== null && _a !== void 0 ? _a : '';
195
+ }
196
+ set lastValue(value) {
197
+ this.list.lastValue = value;
198
+ }
199
+ }
200
+ /** Office JS `Word.PictureContentControl`. */
201
+ export class PictureContentControl {
202
+ constructor(control) {
203
+ this.control = control;
204
+ }
205
+ /** The picture the control holds, if any. */
206
+ get inlinePicture() {
207
+ for (const paragraph of this.control.paragraphs) {
208
+ const picture = paragraph.inlinePictures[0];
209
+ if (picture)
210
+ return picture;
211
+ }
212
+ return undefined;
213
+ }
214
+ }
215
+ /** Office JS `Word.RepeatingSectionContentControl` over `w15:repeatingSection`. */
216
+ export class RepeatingSectionContentControl {
217
+ constructor(control, section) {
218
+ this.control = control;
219
+ this.section = section;
220
+ }
221
+ /** The repeated items: the `w15:repeatingSectionItem` controls directly inside. */
222
+ get items() {
223
+ return this.control.contentControls.filter((c) => c.type === 'RepeatingSectionItem');
224
+ }
225
+ get sectionTitle() {
226
+ var _a, _b;
227
+ return (_b = (_a = this.section.sectionTitle) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : '';
228
+ }
229
+ set sectionTitle(title) {
230
+ if (title === '') {
231
+ delete this.section.sectionTitle;
232
+ return;
233
+ }
234
+ this.section.sectionTitle = { val: title };
235
+ }
236
+ /** Whether Word offers the + and x buttons (`w15:doNotAllowInsertDeleteSection`, inverted). */
237
+ get allowInsertDeleteSection() {
238
+ const flag = this.section.doNotAllowInsertDeleteSection;
239
+ return !(flag !== undefined && flag.val !== false);
240
+ }
241
+ set allowInsertDeleteSection(allow) {
242
+ if (allow)
243
+ delete this.section.doNotAllowInsertDeleteSection;
244
+ else
245
+ this.section.doNotAllowInsertDeleteSection = { val: true };
246
+ }
247
+ /**
248
+ * Adds a copy of the item at `index` after it, as Word's + button does, and returns the new
249
+ * item's control. The copy is a deep copy with its PARENT links rebuilt by the container.
250
+ */
251
+ insertItemAfter(index) {
252
+ const items = this.items;
253
+ const item = items[index];
254
+ if (!item)
255
+ throw new Docx4JException(`This repeating section has ${items.length} item(s); there is none at ${index}`);
256
+ return item.insertCopyAfter();
257
+ }
258
+ }
259
+ /** Office JS `Word.GroupContentControl`: no members of its own. */
260
+ export class GroupContentControl {
261
+ }
262
+ /** The `w:sdtContent` glyph run of a checkbox, as Word writes it (docx4j's binding does the same). */
263
+ export function checkboxRun(symbol, font, rPr) {
264
+ const properties = rPr ? deepCopy(rPr) : {};
265
+ properties.rFonts = { ascii: font, hAnsi: font, eastAsia: font, hint: 'eastAsia' };
266
+ return el.r({ rPr: properties, content: [el.t({ value: symbol })] });
267
+ }
@@ -0,0 +1,52 @@
1
+ /** The XPath result kinds `selectValue` can report. */
2
+ export type XPathValue = string | number | boolean | undefined;
3
+ /**
4
+ * XPath 1.0 over a DOM (CR-002 section 3.6). `select` answers a node set; `selectValue` answers a
5
+ * string, number or boolean result. `namespaces` maps prefixes used in the expression to URIs.
6
+ */
7
+ export interface XPathEngine {
8
+ /** Prepares the engine (loads the `xpath` package in Node); idempotent, and cheap once done. */
9
+ ready(): Promise<void>;
10
+ /** True when `select` and `selectValue` can be called synchronously. */
11
+ readonly isReady: boolean;
12
+ select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
13
+ selectValue(expression: string, context: Node, namespaces?: Record<string, string>): XPathValue;
14
+ }
15
+ /**
16
+ * The default engine: `document.evaluate` where the runtime has it, else the `xpath` package,
17
+ * imported on `ready()`. The import specifier is a variable so that a bundler does not follow it
18
+ * and a consumer without the optional peer still type-checks.
19
+ */
20
+ export declare class DefaultXPathEngine implements XPathEngine {
21
+ private module;
22
+ private loading;
23
+ /** True when the runtime has a native `document.evaluate` (a browser, a Word add-in). */
24
+ private native;
25
+ get isReady(): boolean;
26
+ ready(): Promise<void>;
27
+ select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
28
+ selectValue(expression: string, context: Node, namespaces?: Record<string, string>): XPathValue;
29
+ private call;
30
+ }
31
+ /**
32
+ * Word's prefix mapping string, `xmlns:ns0='http://x' xmlns:ns1="http://y"`, as a map. The default
33
+ * declaration (`xmlns='...'`) is read under the empty prefix, though XPath 1.0 never uses it.
34
+ */
35
+ export declare function parsePrefixMappings(mappings: string | undefined): Record<string, string>;
36
+ /** The inverse: the `xmlns:ns0='...'` form Word writes into `w:prefixMappings`. */
37
+ export declare function formatPrefixMappings(namespaces: Record<string, string>): string;
38
+ /** A node's canonical XPath and the prefixes it uses. */
39
+ export interface CanonicalXPath {
40
+ xpath: string;
41
+ prefixMappings: string;
42
+ }
43
+ /**
44
+ * The canonical `/ns0:a[1]/ns0:b[2]` form Word writes for a node (`setMappingByNode`,
45
+ * `CustomXmlNode.xpath`): a location path from the document element down, every step with its
46
+ * position among the siblings of the same name, prefixes allocated ns0, ns1, ... in the order the
47
+ * namespaces are met. A node in no namespace gets no prefix, which is what Word writes too
48
+ * (`/invoice[1]/customer[1]/name[1]` in the OpenDoPE invoice).
49
+ */
50
+ export declare function canonicalXPathOf(node: Node): CanonicalXPath;
51
+ /** The XML of a node, without an XML declaration (`CustomXmlNode.xml`). */
52
+ export declare function xmlOf(node: Node): string;
@@ -0,0 +1,205 @@
1
+ // CR-002 phase E, section 3.6: XPath 1.0 over the custom XML DOM.
2
+ //
3
+ // Two runtimes, one interface. In a browser or an Office add-in `document.evaluate` is native and
4
+ // complete; in Node the `xpath` package (goto100, MIT) is the companion of the @xmldom/xmldom DOM
5
+ // the runtime brings, and is an **optional peer dependency** so that an add-in bundle never carries
6
+ // it (CR-002 open question 7). `pkg.xpathEngine` is settable, so a consumer with another DOM, or
7
+ // one who wants no dynamic import at all, plugs in its own.
8
+ //
9
+ // Readiness: loading the `xpath` package is asynchronous, and section 3's rule is that only what
10
+ // marshals or unmarshals is asynchronous. So the engine is **warmed once** — `await
11
+ // pkg.xpathEngine.ready()`, which `pkg.customXmlParts.load()` does for you — and every node call
12
+ // afterwards is synchronous. A call before the engine is ready throws, naming the fix.
13
+ import { Docx4JException } from '../../opc/exceptions.mjs';
14
+ import { serializeXml } from '../../xml/dom.mjs';
15
+ // XPathResult constants, spelled out because `XPathResult` is not a global in Node.
16
+ const ANY_TYPE = 0;
17
+ const NUMBER_TYPE = 1;
18
+ const STRING_TYPE = 2;
19
+ const BOOLEAN_TYPE = 3;
20
+ const ORDERED_NODE_SNAPSHOT_TYPE = 7;
21
+ function documentOf(context) {
22
+ var _a;
23
+ return (_a = (context.nodeType === 9 ? context : context.ownerDocument)) !== null && _a !== void 0 ? _a : undefined;
24
+ }
25
+ function nativeEvaluatorFor(context) {
26
+ const doc = documentOf(context);
27
+ return doc && typeof doc.evaluate === 'function' ? doc : undefined;
28
+ }
29
+ /**
30
+ * The default engine: `document.evaluate` where the runtime has it, else the `xpath` package,
31
+ * imported on `ready()`. The import specifier is a variable so that a bundler does not follow it
32
+ * and a consumer without the optional peer still type-checks.
33
+ */
34
+ export class DefaultXPathEngine {
35
+ constructor() {
36
+ /** True when the runtime has a native `document.evaluate` (a browser, a Word add-in). */
37
+ this.native = typeof document !== 'undefined' && typeof document.evaluate === 'function';
38
+ }
39
+ get isReady() {
40
+ return this.native || this.module !== undefined;
41
+ }
42
+ async ready() {
43
+ var _a;
44
+ if (this.isReady)
45
+ return;
46
+ (_a = this.loading) !== null && _a !== void 0 ? _a : (this.loading = (async () => {
47
+ const specifier = 'xpath';
48
+ try {
49
+ this.module = (await import(/* @vite-ignore */ specifier));
50
+ }
51
+ catch (e) {
52
+ throw new Docx4JException("XPath needs either a DOM with document.evaluate or the optional peer dependency 'xpath' (npm install xpath); "
53
+ + 'set pkg.xpathEngine to your own engine to avoid both', { cause: e });
54
+ }
55
+ })());
56
+ await this.loading;
57
+ }
58
+ select(expression, context, namespaces = {}) {
59
+ const doc = nativeEvaluatorFor(context);
60
+ if (doc) {
61
+ const result = doc.evaluate(expression, context, resolverFor(namespaces), ORDERED_NODE_SNAPSHOT_TYPE, null);
62
+ const out = [];
63
+ for (let i = 0; i < result.snapshotLength; i++) {
64
+ const node = result.snapshotItem(i);
65
+ if (node)
66
+ out.push(node);
67
+ }
68
+ return out;
69
+ }
70
+ const value = this.call(expression, context, namespaces);
71
+ return Array.isArray(value) ? value : isNode(value) ? [value] : [];
72
+ }
73
+ selectValue(expression, context, namespaces = {}) {
74
+ var _a, _b, _c;
75
+ const doc = nativeEvaluatorFor(context);
76
+ if (doc) {
77
+ const result = doc.evaluate(expression, context, resolverFor(namespaces), ANY_TYPE, null);
78
+ switch (result.resultType) {
79
+ case NUMBER_TYPE: return result.numberValue;
80
+ case STRING_TYPE: return result.stringValue;
81
+ case BOOLEAN_TYPE: return result.booleanValue;
82
+ default: {
83
+ const node = result.iterateNext();
84
+ return node ? ((_a = node.textContent) !== null && _a !== void 0 ? _a : '') : undefined;
85
+ }
86
+ }
87
+ }
88
+ const value = this.call(expression, context, namespaces);
89
+ if (Array.isArray(value)) {
90
+ const node = value[0];
91
+ return node ? ((_b = node.textContent) !== null && _b !== void 0 ? _b : '') : undefined;
92
+ }
93
+ if (isNode(value))
94
+ return (_c = value.textContent) !== null && _c !== void 0 ? _c : '';
95
+ return value === null || value === undefined ? undefined : value;
96
+ }
97
+ call(expression, context, namespaces) {
98
+ if (!this.module) {
99
+ throw new Docx4JException('The XPath engine is not ready yet: await pkg.customXmlParts.load() (or pkg.xpathEngine.ready()) once before selecting nodes');
100
+ }
101
+ const select = Object.keys(namespaces).length > 0 ? this.module.useNamespaces(namespaces) : this.module.select;
102
+ return select(expression, context);
103
+ }
104
+ }
105
+ function isNode(value) {
106
+ return typeof value === 'object' && value !== null && typeof value.nodeType === 'number';
107
+ }
108
+ function resolverFor(namespaces) {
109
+ return { lookupNamespaceURI: (prefix) => { var _a; return (prefix ? (_a = namespaces[prefix]) !== null && _a !== void 0 ? _a : null : null); } };
110
+ }
111
+ /**
112
+ * Word's prefix mapping string, `xmlns:ns0='http://x' xmlns:ns1="http://y"`, as a map. The default
113
+ * declaration (`xmlns='...'`) is read under the empty prefix, though XPath 1.0 never uses it.
114
+ */
115
+ export function parsePrefixMappings(mappings) {
116
+ var _a;
117
+ const out = {};
118
+ if (!mappings)
119
+ return out;
120
+ const re = /xmlns(?::([\w.\-]+))?\s*=\s*(['"])(.*?)\2/g;
121
+ let m;
122
+ while ((m = re.exec(mappings)) !== null)
123
+ out[(_a = m[1]) !== null && _a !== void 0 ? _a : ''] = m[3];
124
+ return out;
125
+ }
126
+ /** The inverse: the `xmlns:ns0='...'` form Word writes into `w:prefixMappings`. */
127
+ export function formatPrefixMappings(namespaces) {
128
+ return Object.entries(namespaces)
129
+ .map(([prefix, uri]) => (prefix === '' ? `xmlns='${uri}'` : `xmlns:${prefix}='${uri}'`))
130
+ .join(' ');
131
+ }
132
+ /**
133
+ * The canonical `/ns0:a[1]/ns0:b[2]` form Word writes for a node (`setMappingByNode`,
134
+ * `CustomXmlNode.xpath`): a location path from the document element down, every step with its
135
+ * position among the siblings of the same name, prefixes allocated ns0, ns1, ... in the order the
136
+ * namespaces are met. A node in no namespace gets no prefix, which is what Word writes too
137
+ * (`/invoice[1]/customer[1]/name[1]` in the OpenDoPE invoice).
138
+ */
139
+ export function canonicalXPathOf(node) {
140
+ var _a, _b;
141
+ const chain = [];
142
+ let current = node;
143
+ while (current && current.nodeType !== 9) {
144
+ chain.unshift(current);
145
+ current = current.nodeType === 2 ? current.ownerElement : current.parentNode;
146
+ }
147
+ const prefixes = new Map();
148
+ const qname = (namespaceURI, localName) => {
149
+ if (!namespaceURI)
150
+ return localName;
151
+ let prefix = prefixes.get(namespaceURI);
152
+ if (prefix === undefined) {
153
+ prefix = `ns${prefixes.size}`;
154
+ prefixes.set(namespaceURI, prefix);
155
+ }
156
+ return `${prefix}:${localName}`;
157
+ };
158
+ const steps = [];
159
+ for (const item of chain) {
160
+ if (item.nodeType === 2) {
161
+ const attr = item;
162
+ steps.push(`@${qname(attr.namespaceURI, (_a = attr.localName) !== null && _a !== void 0 ? _a : attr.name)}`);
163
+ continue;
164
+ }
165
+ if (item.nodeType === 3 || item.nodeType === 4) {
166
+ steps.push(`text()[${positionOf(item, (n) => n.nodeType === 3 || n.nodeType === 4)}]`);
167
+ continue;
168
+ }
169
+ if (item.nodeType === 8) {
170
+ steps.push(`comment()[${positionOf(item, (n) => n.nodeType === 8)}]`);
171
+ continue;
172
+ }
173
+ const element = item;
174
+ const local = (_b = element.localName) !== null && _b !== void 0 ? _b : element.nodeName;
175
+ const ns = element.namespaceURI;
176
+ const position = positionOf(element, (n) => { var _a, _b; return n.nodeType === 1 && ((_a = n.localName) !== null && _a !== void 0 ? _a : n.nodeName) === local && ((_b = n.namespaceURI) !== null && _b !== void 0 ? _b : null) === (ns !== null && ns !== void 0 ? ns : null); });
177
+ steps.push(`${qname(ns, local)}[${position}]`);
178
+ }
179
+ const namespaces = {};
180
+ for (const [uri, prefix] of prefixes)
181
+ namespaces[prefix] = uri;
182
+ return { xpath: `/${steps.join('/')}`, prefixMappings: formatPrefixMappings(namespaces) };
183
+ }
184
+ function positionOf(node, matches) {
185
+ const parent = node.parentNode;
186
+ if (!parent)
187
+ return 1;
188
+ let position = 0;
189
+ for (let child = parent.firstChild; child; child = child.nextSibling) {
190
+ if (!matches(child))
191
+ continue;
192
+ position++;
193
+ if (child === node)
194
+ return position;
195
+ }
196
+ return position || 1;
197
+ }
198
+ /** The XML of a node, without an XML declaration (`CustomXmlNode.xml`). */
199
+ export function xmlOf(node) {
200
+ if (node.nodeType === 2) {
201
+ const attr = node;
202
+ return `${attr.name}="${attr.value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;')}"`;
203
+ }
204
+ return serializeXml(node);
205
+ }
@@ -0,0 +1,2 @@
1
+ /** The English name of a CJK font name, or undefined where this is not one of the names we know. */
2
+ export declare function toEnglish(fontName: string): string | undefined;
@@ -0,0 +1,16 @@
1
+ // docx4j `org.docx4j.fonts.CJKToEnglish`.
2
+ //
3
+ // Certain fonts have CJK names in a docx; on Windows (English locale at least) the font names
4
+ // are in English. Font discovery collects the English name where there is one, so that the
5
+ // mapper is populated with the name the machine would have.
6
+ const TO_ENGLISH = new Map([
7
+ ['MS ゴシック', 'MS Gothic'], // <a:font script="Jpan" typeface="MS ゴシック"/>
8
+ ['MS 明朝', 'MS Mincho'],
9
+ ['맑은 고딕', 'Malgun Gothic'], // <a:font script="Hang" typeface="맑은 고딕"/>
10
+ ['宋体', 'SimSun'], // <a:font script="Hans" typeface="宋体"/>
11
+ ['新細明體', 'PMingLiU'],
12
+ ]);
13
+ /** The English name of a CJK font name, or undefined where this is not one of the names we know. */
14
+ export function toEnglish(fontName) {
15
+ return TO_ENGLISH.get(fontName);
16
+ }
@@ -0,0 +1,58 @@
1
+ import type { FontRegistry } from './registry.mjs';
2
+ import type { PhysicalFont } from './PhysicalFont.mjs';
3
+ import { type VclEntry } from './substitutions.generated.mjs';
4
+ export type FontClass = 'SERIF' | 'SANS' | 'MONO' | 'UNKNOWN';
5
+ /** The key convention `FontSubstitutions.xml` uses: the name lower-cased, everything but
6
+ * letters and digits removed. */
7
+ export declare function shortKey(fontName: string): string;
8
+ /**
9
+ * The `FontSubstitutions.xml` entry for this name, or undefined. The table knows families,
10
+ * not the foundry and weight suffixes a document adds to them ("Calisto MT", "Segoe UI
11
+ * Light"), so trailing words are dropped one at a time until one matches.
12
+ */
13
+ export declare function vclEntryFor(documentFontName: string | undefined): VclEntry | undefined;
14
+ /** Whether `FontSubstitutions.xml` calls this font condensed (Arial Narrow and the like): no
15
+ * ordinary stand-in has its widths, and docx4j's corpus showed the document default is the
16
+ * lesser evil, so these are deliberately left unmapped. */
17
+ export declare function isCondensed(documentFontName: string | undefined): boolean;
18
+ /** Whether this family is one docx4j deliberately leaves to the document default rather than
19
+ * standing in for it: a condensed face, or one of the measured exceptions. */
20
+ export declare function leftToTheDocumentDefault(documentFontName: string | undefined): boolean;
21
+ /**
22
+ * The class a name says, sans before serif so that "HelveticaNeue LT 55 Roman" is a sans.
23
+ *
24
+ * @param generic whether a name which only ends in "Sans" or "Serif" counts. It does when the
25
+ * question is what class an installed font is (Liberation Sans, DejaVu Serif), but not when
26
+ * it is whether to stand in for a document font: measured, that guess was worth less than the
27
+ * document default.
28
+ */
29
+ export declare function classFromName(documentFontName: string | undefined, generic?: boolean): FontClass;
30
+ /** The font's class, from `FontSubstitutions.xml` where it knows the font, else from its name. */
31
+ export declare function classOf(documentFontName: string | undefined): FontClass;
32
+ /** The class to stand in for: the table's word, else what the name says for certain. */
33
+ export declare function substitutionClass(documentFontName: string | undefined): FontClass;
34
+ /**
35
+ * A physical font of this document font's class, without regard to what it can render. Used
36
+ * where the characters are Latin (or Greek/Cyrillic), which any of these covers.
37
+ *
38
+ * `FontSubstitutions.xml`'s own list first - it is ordered by closeness - then the class
39
+ * defaults. Undefined where the font's class is unknown, or it is condensed or one of the
40
+ * measured exceptions, or the registry has nothing of that class.
41
+ */
42
+ export declare function selectByClass(registry: FontRegistry, documentFontName: string | undefined): PhysicalFont | undefined;
43
+ /** U+2190-U+2BFF, the symbol blocks: Arrows, Mathematical Operators, Miscellaneous Technical,
44
+ * Box Drawing, Block Elements, Geometric Shapes, Miscellaneous Symbols, Dingbats, Braille and
45
+ * the supplemental arrow and maths blocks. Every one of them is `COMMON`, so they are their
46
+ * own group rather than shared: the space and the digits beside an arrow are not dragged into
47
+ * the symbol font with it. */
48
+ export declare function isSymbol(cp: number): boolean;
49
+ /** U+1F000-U+1FAFF, the emoji blocks (`COMMON`, and like the symbols a group of their own). */
50
+ export declare function isEmoji(cp: number): boolean;
51
+ /** The East Asian punctuation and form blocks, which are `COMMON` - a fullwidth comma U+FF0C,
52
+ * an ideographic comma U+3001 - and which a Latin face does not have. */
53
+ export declare function isEastAsianForm(cp: number): boolean;
54
+ export declare const SYMBOL_GROUP = "SYMBOL";
55
+ export declare const EMOJI_GROUP = "EMOJI";
56
+ /** The key a code point groups under: its Unicode script, except that the symbol and emoji
57
+ * blocks are their own groups. */
58
+ export declare function coverageGroupOf(cp: number): string;