@docx4j/core-ts 0.4.0 → 0.6.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.
Files changed (166) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +34 -3
  3. package/dist/html/convert.mjs +40 -15
  4. package/dist/html/elements.mjs +2 -1
  5. package/dist/model/color/ColorMath.d.mts +29 -0
  6. package/dist/model/color/ColorMath.mjs +146 -0
  7. package/dist/model/color/ColorTables.d.mts +6 -0
  8. package/dist/model/color/ColorTables.mjs +83 -0
  9. package/dist/model/color/DrawingMLColors.d.mts +52 -0
  10. package/dist/model/color/DrawingMLColors.mjs +374 -0
  11. package/dist/model/color/ResolvedColor.d.mts +36 -0
  12. package/dist/model/color/ResolvedColor.mjs +65 -0
  13. package/dist/model/color/SpreadsheetColors.d.mts +36 -0
  14. package/dist/model/color/SpreadsheetColors.mjs +84 -0
  15. package/dist/model/color/StyleFill.d.mts +28 -0
  16. package/dist/model/color/StyleFill.mjs +21 -0
  17. package/dist/model/color/ThemeColors.d.mts +86 -0
  18. package/dist/model/color/ThemeColors.mjs +304 -0
  19. package/dist/model/color/WordColors.d.mts +71 -0
  20. package/dist/model/color/WordColors.mjs +121 -0
  21. package/dist/model/color/index.d.mts +6 -0
  22. package/dist/model/color/index.mjs +30 -0
  23. package/dist/model/content/Body.d.mts +153 -19
  24. package/dist/model/content/Body.mjs +570 -131
  25. package/dist/model/content/Comment.d.mts +21 -3
  26. package/dist/model/content/Comment.mjs +202 -19
  27. package/dist/model/content/ContentControl.d.mts +197 -18
  28. package/dist/model/content/ContentControl.mjs +664 -95
  29. package/dist/model/content/Font.d.mts +67 -17
  30. package/dist/model/content/Font.mjs +114 -35
  31. package/dist/model/content/InlinePicture.d.mts +82 -7
  32. package/dist/model/content/InlinePicture.mjs +221 -28
  33. package/dist/model/content/List.mjs +13 -1
  34. package/dist/model/content/Paragraph.d.mts +213 -14
  35. package/dist/model/content/Paragraph.mjs +936 -100
  36. package/dist/model/content/Range.d.mts +242 -11
  37. package/dist/model/content/Range.mjs +975 -119
  38. package/dist/model/content/ResolvedView.d.mts +104 -0
  39. package/dist/model/content/ResolvedView.mjs +596 -0
  40. package/dist/model/content/Table.d.mts +29 -3
  41. package/dist/model/content/Table.mjs +109 -33
  42. package/dist/model/content/TrackedChange.d.mts +301 -16
  43. package/dist/model/content/TrackedChange.mjs +1284 -158
  44. package/dist/model/content/binder.d.mts +2 -1
  45. package/dist/model/content/binder.mjs +48 -1
  46. package/dist/model/content/comments.d.mts +20 -6
  47. package/dist/model/content/comments.mjs +67 -57
  48. package/dist/model/content/generalException.d.mts +18 -0
  49. package/dist/model/content/generalException.mjs +24 -0
  50. package/dist/model/content/index.d.mts +8 -3
  51. package/dist/model/content/index.mjs +7 -2
  52. package/dist/model/content/mathText.d.mts +21 -0
  53. package/dist/model/content/mathText.mjs +267 -0
  54. package/dist/model/content/officeText.d.mts +27 -0
  55. package/dist/model/content/officeText.mjs +74 -0
  56. package/dist/model/content/outline.d.mts +5 -0
  57. package/dist/model/content/outline.mjs +13 -0
  58. package/dist/model/content/placeholders.d.mts +110 -0
  59. package/dist/model/content/placeholders.mjs +253 -0
  60. package/dist/model/content/relationships.d.mts +30 -0
  61. package/dist/model/content/relationships.mjs +133 -0
  62. package/dist/model/content/search.d.mts +72 -0
  63. package/dist/model/content/search.mjs +204 -2
  64. package/dist/model/content/spanEdits.d.mts +159 -0
  65. package/dist/model/content/spanEdits.mjs +728 -0
  66. package/dist/model/content/story.d.mts +44 -0
  67. package/dist/model/content/story.mjs +92 -0
  68. package/dist/model/content/tableColumns.d.mts +1 -1
  69. package/dist/model/content/tableColumns.mjs +108 -80
  70. package/dist/model/content/tableRevisions.d.mts +11 -3
  71. package/dist/model/content/tableRevisions.mjs +72 -42
  72. package/dist/model/content/tableRules.d.mts +30 -0
  73. package/dist/model/content/tableRules.mjs +100 -0
  74. package/dist/model/content/textBoxes.d.mts +18 -0
  75. package/dist/model/content/textBoxes.mjs +105 -0
  76. package/dist/model/content/trackedChangeFilter.d.mts +39 -0
  77. package/dist/model/content/trackedChangeFilter.mjs +81 -0
  78. package/dist/model/content/tracking.d.mts +28 -0
  79. package/dist/model/content/tracking.mjs +149 -10
  80. package/dist/model/content/tree.d.mts +212 -13
  81. package/dist/model/content/tree.mjs +356 -35
  82. package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
  83. package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
  84. package/dist/model/customxml/XmlMapping.d.mts +1 -1
  85. package/dist/model/customxml/XmlMapping.mjs +11 -0
  86. package/dist/model/customxml/bindings.d.mts +21 -2
  87. package/dist/model/customxml/bindings.mjs +76 -32
  88. package/dist/model/customxml/kinds.d.mts +8 -3
  89. package/dist/model/customxml/kinds.mjs +26 -5
  90. package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
  91. package/dist/model/customxml/picturePlaceholder.mjs +32 -0
  92. package/dist/model/customxml/pictures.d.mts +9 -5
  93. package/dist/model/customxml/pictures.mjs +31 -13
  94. package/dist/model/customxml/xhtml.mjs +8 -2
  95. package/dist/model/fonts/families.generated.mjs +2 -2
  96. package/dist/model/fonts/registry.mjs +7 -1
  97. package/dist/model/fonts/substitutions.generated.mjs +2 -2
  98. package/dist/model/fonts/themes.generated.mjs +1 -1
  99. package/dist/model/index.d.mts +2 -0
  100. package/dist/model/index.mjs +4 -0
  101. package/dist/model/listnumbering/Emulator.d.mts +37 -5
  102. package/dist/model/listnumbering/Emulator.mjs +63 -9
  103. package/dist/model/listnumbering/definitions.mjs +18 -0
  104. package/dist/model/properties/PropertyResolver.d.mts +87 -7
  105. package/dist/model/properties/PropertyResolver.mjs +197 -17
  106. package/dist/model/properties/catalogue.d.mts +32 -4
  107. package/dist/model/properties/catalogue.mjs +115 -36
  108. package/dist/model/properties/log.d.mts +1 -1
  109. package/dist/model/properties/log.mjs +5 -5
  110. package/dist/model/properties/table.d.mts +16 -2
  111. package/dist/model/properties/table.mjs +17 -5
  112. package/dist/model/text/Extractor.d.mts +289 -0
  113. package/dist/model/text/Extractor.mjs +2162 -0
  114. package/dist/model/text/LinkTargets.d.mts +45 -0
  115. package/dist/model/text/LinkTargets.mjs +170 -0
  116. package/dist/model/text/MarkdownExporter.d.mts +140 -0
  117. package/dist/model/text/MarkdownExporter.mjs +255 -0
  118. package/dist/model/text/PlainText.d.mts +29 -0
  119. package/dist/model/text/PlainText.mjs +539 -0
  120. package/dist/model/text/TextContext.d.mts +161 -0
  121. package/dist/model/text/TextContext.mjs +425 -0
  122. package/dist/model/text/TextOptions.d.mts +150 -0
  123. package/dist/model/text/TextOptions.mjs +278 -0
  124. package/dist/model/text/TextResult.d.mts +504 -0
  125. package/dist/model/text/TextResult.mjs +526 -0
  126. package/dist/model/text/Texts.d.mts +99 -0
  127. package/dist/model/text/Texts.mjs +187 -0
  128. package/dist/model/text/WmlToMarkdown.d.mts +120 -0
  129. package/dist/model/text/WmlToMarkdown.mjs +911 -0
  130. package/dist/model/text/commonmark.d.mts +121 -0
  131. package/dist/model/text/commonmark.mjs +655 -0
  132. package/dist/model/text/index.d.mts +7 -0
  133. package/dist/model/text/index.mjs +8 -0
  134. package/dist/model/text/normalize.d.mts +8 -0
  135. package/dist/model/text/normalize.mjs +13 -0
  136. package/dist/model/text/outline.d.mts +4 -0
  137. package/dist/model/text/outline.mjs +71 -0
  138. package/dist/office-js/fragment.d.mts +7 -5
  139. package/dist/office-js/fragment.mjs +63 -14
  140. package/dist/office-js/proxy.d.mts +8 -0
  141. package/dist/office-js/proxy.mjs +29 -0
  142. package/dist/office-js/run.mjs +2 -0
  143. package/dist/office-js/supported.generated.mjs +16 -0
  144. package/dist/office-js/toApiScript.mjs +21 -5
  145. package/dist/opc/Load.d.mts +9 -2
  146. package/dist/opc/Save.d.mts +17 -0
  147. package/dist/opc/Save.mjs +12 -2
  148. package/dist/opc/index.d.mts +3 -3
  149. package/dist/opc/index.mjs +2 -2
  150. package/dist/opc/mce/preprocessor.d.mts +88 -7
  151. package/dist/opc/mce/preprocessor.mjs +144 -37
  152. package/dist/opc/mce/understood.d.mts +34 -0
  153. package/dist/opc/mce/understood.mjs +55 -3
  154. package/dist/packages/OpcPackage.d.mts +20 -0
  155. package/dist/packages/OpcPackage.mjs +16 -3
  156. package/dist/packages/WordprocessingMLPackage.d.mts +77 -7
  157. package/dist/packages/WordprocessingMLPackage.mjs +242 -11
  158. package/dist/parts/DefaultXmlPart.mjs +2 -2
  159. package/dist/parts/Part.d.mts +10 -2
  160. package/dist/parts/XmlPart.d.mts +35 -32
  161. package/dist/parts/XmlPart.mjs +107 -107
  162. package/dist/parts/wml/comments.mjs +30 -0
  163. package/dist/parts/wml/index.mjs +12 -0
  164. package/dist/xml/dom.d.mts +7 -0
  165. package/dist/xml/dom.mjs +18 -0
  166. package/package.json +2 -2
@@ -1,5 +1,40 @@
1
- import { isElement, typeNameOf, runItemsOf } from '@docx4j/generated-objects-ts/builders/wml';
1
+ import { isElement, typeNameOf, runItemsOf, mcBranchOf, sdtProperty } from '@docx4j/generated-objects-ts/builders/wml';
2
+ import { READ_UNDERSTOOD_PREFIXES } from '../../opc/mce/understood.mjs';
3
+ import { isMath, mathTextOf } from './mathText.mjs';
4
+ import { NotSupportedError } from '../../office-js/errors.mjs';
2
5
  export { isElement, typeNameOf, walk, find, linkParents, textOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
6
+ /**
7
+ * Run content that stands in the text and has no text of its own: a `w:drawing` (a picture, a chart, a
8
+ * text box), a VML `w:pict` and an embedded `w:object`. Office JS counts an inline picture as in a
9
+ * range, so a span's deletion takes the objects in it (CR-002 section 48). A kept `mc:AlternateContent`
10
+ * in a run is one such object too, whatever its branches hold (`ALTERNATE_CONTENT`, CR-010 phase 3).
11
+ */
12
+ export const OBJECT_ITEMS = new Set(['drawing', 'pict', 'object']);
13
+ /** The TYPE_NAME of a kept `mc:AlternateContent` (the default load since CR-010 phase 4; under `KEPT_HOSTS` with `mcePreprocess: true`). */
14
+ export const ALTERNATE_CONTENT = 'org_docx4j_mce.AlternateContent';
15
+ /**
16
+ * The branch of a kept `mc:AlternateContent` the content API reads (docx4j's `McMode.READ`, CR-010
17
+ * phase 3): the objects package's `mcBranchOf` over `READ_UNDERSTOOD_PREFIXES`, the prefixes load
18
+ * understands and the four Word 365 understands that load leaves alone (CR-010 section 15). So a reader
19
+ * takes the branch the preprocessor would have resolved the element to, unless a Choice requires one of
20
+ * those four: then it takes that Choice, as Word does, where a resolved load takes the next one or the
21
+ * Fallback. A mutator walks every branch instead (docx4j's `McMode.ALL`). Undefined for an element with
22
+ * no branches.
23
+ */
24
+ export function selectedBranchOf(value) {
25
+ return mcBranchOf(value, { understood: READ_UNDERSTOOD_PREFIXES });
26
+ }
27
+ /** True for a kept `mc:AlternateContent`: its element pair, or its value. */
28
+ export function isAlternateContent(value) {
29
+ const v = isElement(value) ? value.value : value;
30
+ return typeof v === 'object' && v !== null && v.TYPE_NAME === ALTERNATE_CONTENT;
31
+ }
32
+ /** Both edges: the objects at a span's start and at its end are in it. */
33
+ export const WHOLE = Object.freeze({ start: true, end: true });
34
+ /** True when an object at offset `at` is in the span [start, end) with these edges. */
35
+ export function objectInSpan(at, start, end, edges) {
36
+ return (start < at && at < end) || (at === start && (edges === null || edges === void 0 ? void 0 : edges.start) === true) || (at === end && (edges === null || edges === void 0 ? void 0 : edges.end) === true);
37
+ }
3
38
  /** Types whose value holds runs (directly or through sdtContent); the revision holders are separate. */
4
39
  const RUN_HOLDERS = new Set([
5
40
  'org_docx4j_wml.P.Hyperlink', 'org_docx4j_wml.SdtRun', 'org_docx4j_wml.CTSmartTagRun',
@@ -21,6 +56,46 @@ function shows(view, kind) {
21
56
  return view === 'accepted' ? kind === 'ins' || kind === 'moveTo' : kind === 'del' || kind === 'moveFrom';
22
57
  }
23
58
  export { runItemsOf };
59
+ /**
60
+ * An item's text in Office JS's text, Word's own character stream (CR-012 phase 4; check 48, Word 365):
61
+ * a `w:br` U+000B, of type page U+000C and column U+000E; a `w:cr` U+000D; a `w:ptab` `0`; the
62
+ * non-breaking and optional hyphens U+001E and U+001F; any `w:sym` `(`, whatever its font or code
63
+ * (check 48b); a footnote or endnote reference U+0002, and so the note's own mark (`w:footnoteRef`,
64
+ * `w:endnoteRef`, not measured). Undefined for an item that adds no text: a comment reference, a
65
+ * field's characters and code, a drawing.
66
+ */
67
+ export function officeItemText(item) {
68
+ var _a;
69
+ const v = item.value;
70
+ switch (item.name.localPart) {
71
+ case 't':
72
+ case 'delText': return String((_a = v.value) !== null && _a !== void 0 ? _a : '');
73
+ case 'tab': return '\t';
74
+ case 'br': return v.type === 'page' ? '\f' : v.type === 'column' ? '\u000E' : '\u000B';
75
+ case 'cr': return '\r';
76
+ case 'ptab': return '0';
77
+ case 'noBreakHyphen': return '\u001E';
78
+ case 'softHyphen': return '\u001F';
79
+ case 'sym': return '(';
80
+ case 'footnoteReference':
81
+ case 'endnoteReference':
82
+ case 'footnoteRef':
83
+ case 'endnoteRef': return '\u0002';
84
+ default: return undefined;
85
+ }
86
+ }
87
+ /** An item a run-level element's selected branch may hold that makes the element one object (CR-012 section 12.2 item 5). */
88
+ function isDrawn(item) {
89
+ return OBJECT_ITEMS.has(item.name.localPart);
90
+ }
91
+ /** The `run` of an equation's segment: it is in no run, and nothing may be written to this one. */
92
+ function standIn(math) {
93
+ return Object.freeze({ TYPE_NAME: 'org_docx4j_wml.R', PARENT: math.value.PARENT });
94
+ }
95
+ /**
96
+ * The item text the revision listings and the text model's plan count (`itemTextOf`): whether a run
97
+ * holds text, in the characters `textOf` gives. Not Office JS's (`officeItemText`).
98
+ */
24
99
  function itemText(item) {
25
100
  var _a, _b;
26
101
  const t = item.name.localPart;
@@ -41,39 +116,103 @@ function itemText(item) {
41
116
  }
42
117
  }
43
118
  /**
44
- * The text segments of a paragraph (or any run holder) in order. The default view is the
45
- * accepted one: the runs of a `w:ins` or `w:moveTo` count, those of a `w:del` or `w:moveFrom`
46
- * do not. `{ view: 'original' }` is the other way round (CR-002 phase F).
119
+ * The text segments of a paragraph (or any run holder) in order, in Office JS's characters
120
+ * (`officeItemText`). The default view is the accepted one: the runs of a `w:ins` or `w:moveTo`
121
+ * count, those of a `w:del` or `w:moveFrom` do not. `{ view: 'original' }` is the other way round
122
+ * (CR-002 phase F). `{ objects: true }` lists the drawn objects too, each a segment of no text where
123
+ * it stands (CR-002 section 48), and the items of hidden runs (`hidden`).
124
+ *
125
+ * A kept `mc:AlternateContent` reads as its selected branch (CR-012 section 12.2, ED-009): in a run,
126
+ * a branch holding run items reads as those items, at the run's offsets, and one holding a drawing,
127
+ * a picture or an object is one object segment, as a drawing is (CR-010 phase 3); among a paragraph's
128
+ * runs, it reads as the runs its branch holds. Either way the segments carry `alternate`, so that an
129
+ * edit lands in that branch. An equation is one segment of its drawn text (`math`).
47
130
  */
48
131
  export function segmentsOf(container, options) {
49
132
  var _a;
50
133
  const view = (_a = options === null || options === void 0 ? void 0 : options.view) !== null && _a !== void 0 ? _a : 'accepted';
134
+ const objects = (options === null || options === void 0 ? void 0 : options.objects) === true;
135
+ const hiddenRun = options === null || options === void 0 ? void 0 : options.hidden;
136
+ const visit = options === null || options === void 0 ? void 0 : options.visit;
137
+ const office = (options === null || options === void 0 ? void 0 : options.characters) !== 'textOf';
138
+ const charactersOf = office ? officeItemText : itemText;
51
139
  const out = [];
52
140
  let pos = 0;
53
- const visitRuns = (items, revision) => {
141
+ const runContent = (run, runEl, content, runOwner, runIndex, revision, alternate, hidden) => {
142
+ for (let j = 0; j < content.length; j++) {
143
+ const item = content[j];
144
+ const where = { owner: content, index: j, run, runOwner, runIndex };
145
+ if (office && isAlternateContent(item)) {
146
+ const branch = selectedBranchOf(item.value);
147
+ // a branch holding content the model doesn't bind (DOM) is one object, as a drawing is
148
+ if (branch && branch.every(isElement) && !branch.some(isDrawn)) {
149
+ runContent(run, runEl, branch, runOwner, runIndex, revision, { element: item, owner: content, branch, level: 'run' }, hidden);
150
+ continue;
151
+ }
152
+ }
153
+ const text = charactersOf(item);
154
+ if (text === undefined || (hidden && text !== '')) {
155
+ const drawn = OBJECT_ITEMS.has(item.name.localPart) || isAlternateContent(item);
156
+ if (objects && (drawn || (hidden && text !== undefined))) {
157
+ const seg = { item, ...where, text: '', start: pos, end: pos, editable: false, object: true };
158
+ if (hidden)
159
+ seg.hidden = true;
160
+ if (revision)
161
+ seg.revision = revision;
162
+ if (alternate)
163
+ seg.alternate = alternate;
164
+ out.push(seg);
165
+ }
166
+ visit === null || visit === void 0 ? void 0 : visit(item, pos, content, { element: runEl, owner: runOwner });
167
+ continue;
168
+ }
169
+ const seg = { item, ...where, text, start: pos, end: pos + text.length, editable: item.name.localPart === 't' };
170
+ if (revision)
171
+ seg.revision = revision;
172
+ if (alternate)
173
+ seg.alternate = alternate;
174
+ out.push(seg);
175
+ pos += text.length;
176
+ }
177
+ };
178
+ const visitRuns = (items, revision, alternate) => {
54
179
  var _a;
55
180
  if (!items)
56
181
  return;
57
182
  for (let i = 0; i < items.length; i++) {
58
183
  const el = items[i];
184
+ if (!isElement(el))
185
+ continue; // a kept branch's unbound content (DOM)
186
+ visit === null || visit === void 0 ? void 0 : visit(el, pos, items, undefined);
59
187
  const tn = typeNameOf(el);
60
188
  if (tn === 'org_docx4j_wml.R') {
61
189
  const run = el.value;
62
- const content = (_a = run.content) !== null && _a !== void 0 ? _a : [];
63
- for (let j = 0; j < content.length; j++) {
64
- const item = content[j];
65
- const text = itemText(item);
66
- if (text === undefined)
67
- continue;
68
- const seg = {
69
- item, owner: content, index: j, run, runOwner: items, runIndex: i, text,
70
- start: pos, end: pos + text.length, editable: item.name.localPart === 't',
71
- };
72
- if (revision)
73
- seg.revision = revision;
74
- out.push(seg);
75
- pos += text.length;
76
- }
190
+ runContent(run, el, (_a = run.content) !== null && _a !== void 0 ? _a : [], items, i, revision, alternate, (hiddenRun === null || hiddenRun === void 0 ? void 0 : hiddenRun(run)) === true);
191
+ continue;
192
+ }
193
+ if (!office) {
194
+ // textOf's reader: no branch among the runs, no equation
195
+ }
196
+ else if (isAlternateContent(el)) {
197
+ const branch = selectedBranchOf(el.value);
198
+ if (branch)
199
+ visitRuns(branch, revision, { element: el, owner: items, branch, level: 'paragraph' });
200
+ continue;
201
+ }
202
+ else if (isMath(el)) {
203
+ const text = mathTextOf(el.value, view);
204
+ if (text === '')
205
+ continue;
206
+ const seg = {
207
+ item: el, owner: items, index: i, run: standIn(el), runOwner: items, runIndex: i, text,
208
+ start: pos, end: pos + text.length, editable: false, math: true,
209
+ };
210
+ if (revision)
211
+ seg.revision = revision;
212
+ if (alternate)
213
+ seg.alternate = alternate;
214
+ out.push(seg);
215
+ pos += text.length;
77
216
  continue;
78
217
  }
79
218
  const kind = revisionKindOf(el);
@@ -82,21 +221,60 @@ export function segmentsOf(container, options) {
82
221
  continue;
83
222
  const nested = runItemsOf(el.value);
84
223
  if (nested)
85
- visitRuns(nested, { kind, element: el, value: el.value, items: nested, owner: items });
224
+ visitRuns(nested, { kind, element: el, value: el.value, items: nested, owner: items }, alternate);
86
225
  }
87
226
  else if (tn !== undefined && RUN_HOLDERS.has(tn)) {
88
- visitRuns(runItemsOf(el.value), revision);
227
+ visitRuns(runItemsOf(el.value), revision, alternate);
89
228
  }
90
229
  }
91
230
  };
92
- visitRuns(runItemsOf(container), undefined);
231
+ visitRuns(runItemsOf(container), undefined, undefined);
93
232
  return out;
94
233
  }
95
- /** The text of a paragraph or container in one of the two views (`textOf` is the accepted one). */
234
+ /**
235
+ * Which of a paragraph's runs are hidden, as the text model's rule has it (REQ-507) and Office JS's text
236
+ * leaves them out (check 48b): a run's own `w:vanish`, else its paragraph style's and character style's.
237
+ * Without a resolver only a run's own counts.
238
+ */
239
+ export function hiddenRunsOf(resolver, p) {
240
+ var _a, _b;
241
+ const pStyle = (_b = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val;
242
+ return (run) => {
243
+ var _a, _b, _c, _d;
244
+ if (inShowingPlaceholder(run))
245
+ return true;
246
+ const own = (_a = run.rPr) === null || _a === void 0 ? void 0 : _a.vanish;
247
+ if (own !== undefined && own !== null)
248
+ return own.val !== false;
249
+ return (_d = resolver === null || resolver === void 0 ? void 0 : resolver.isVanishedByStyles(pStyle, (_c = (_b = run.rPr) === null || _b === void 0 ? void 0 : _b.rStyle) === null || _c === void 0 ? void 0 : _c.val)) !== null && _d !== void 0 ? _d : false;
250
+ };
251
+ }
252
+ /**
253
+ * Whether a run is in a content control showing its placeholder (`w:showingPlcHdr`), run-level or block-level, up its
254
+ * `PARENT`s. Office JS reads a placeholder as no text, and finds no text there to keep (check 53 cases 34 and 35, check 58
255
+ * cases 11 and 12; CR-012 section 18), so the readers take its runs as they take hidden ones.
256
+ */
257
+ export function inShowingPlaceholder(run) {
258
+ var _a;
259
+ let o = run.PARENT;
260
+ for (let guard = 0; o && guard < 32; guard++, o = o.PARENT) {
261
+ const v = o;
262
+ if (v.sdtPr === undefined || v.sdtContent === undefined)
263
+ continue;
264
+ const item = sdtProperty(v.sdtPr, 'showingPlcHdr');
265
+ if (item !== undefined && ((_a = item.value) === null || _a === void 0 ? void 0 : _a.val) !== false)
266
+ return true;
267
+ }
268
+ return false;
269
+ }
270
+ /** The text of a paragraph or container in one of the two views, in Office JS's characters (`segmentsOf`). */
96
271
  export function textOfView(container, options) {
97
272
  return segmentsOf(container, options).map((s) => s.text).join('');
98
273
  }
99
- /** The runs of a paragraph, direct and nested in hyperlinks, content controls and insertions, in order. */
274
+ /**
275
+ * The runs of a paragraph, direct and nested in hyperlinks, content controls and insertions, in order,
276
+ * and in the selected branch of a kept `mc:AlternateContent` among them (CR-012 section 12.2).
277
+ */
100
278
  export function runsOf(container, options) {
101
279
  var _a;
102
280
  const view = (_a = options === null || options === void 0 ? void 0 : options.view) !== null && _a !== void 0 ? _a : 'accepted';
@@ -110,6 +288,10 @@ export function runsOf(container, options) {
110
288
  out.push(el);
111
289
  continue;
112
290
  }
291
+ if (isAlternateContent(el)) {
292
+ visit(selectedBranchOf(el.value));
293
+ continue;
294
+ }
113
295
  const kind = revisionKindOf(el);
114
296
  if (kind !== undefined) {
115
297
  if (shows(view, kind))
@@ -122,30 +304,129 @@ export function runsOf(container, options) {
122
304
  visit(runItemsOf(container));
123
305
  return out;
124
306
  }
307
+ /** The TYPE_NAMEs of a kept `mc:AlternateContent`'s branches, whose items are their `any`. */
308
+ export const BRANCH_TYPES = new Set(['org_docx4j_mce.AlternateContent.Choice', 'org_docx4j_mce.AlternateContent.Fallback']);
125
309
  /**
126
310
  * The block-level children of a container: body, header, footer, cell, sdt content, table (rows),
127
311
  * row (cells). A content control of any kind (block, row, cell, run) answers with its
128
- * `sdtContent`'s content, so that a traversal does not have to know the four types.
312
+ * `sdtContent`'s content, so that a traversal does not have to know the four types. A branch of a kept
313
+ * `mc:AlternateContent` (a Choice or the Fallback) answers with its items, so that a locator climbing
314
+ * `PARENT` from a branch's paragraph, row or cell finds the list it is in; the element itself answers
315
+ * in a reader's walk (`'read'`) with its selected branch (CR-013 phase 2), and otherwise not at all.
129
316
  */
130
- export function childrenOf(value) {
317
+ export function childrenOf(value, mode) {
131
318
  const v = value;
132
319
  if (v.sdtContent)
133
320
  return v.sdtContent.content;
134
- return Array.isArray(v.content) ? v.content : undefined;
321
+ if (Array.isArray(v.content))
322
+ return v.content;
323
+ const tn = v.TYPE_NAME;
324
+ if (tn === undefined)
325
+ return undefined;
326
+ if (BRANCH_TYPES.has(tn))
327
+ return v.any;
328
+ if (mode === 'read' && tn === ALTERNATE_CONTENT)
329
+ return selectedBranchOf(v);
330
+ return undefined;
331
+ }
332
+ /** Every branch of a kept `mc:AlternateContent`, the Choices in order, then the Fallback. */
333
+ export function branchesOf(value) {
334
+ var _a, _b;
335
+ const out = [];
336
+ for (const choice of (_a = value.choice) !== null && _a !== void 0 ? _a : [])
337
+ if (choice.any)
338
+ out.push(choice.any);
339
+ if ((_b = value.fallback) === null || _b === void 0 ? void 0 : _b.any)
340
+ out.push(value.fallback.any);
341
+ return out;
342
+ }
343
+ /** How many bulk edits are writing in every branch now (`writingEveryBranch`). */
344
+ let everyBranch = 0;
345
+ /**
346
+ * Runs a bulk edit that reaches every branch of a kept `mc:AlternateContent` (CR-013 phase 3): a
347
+ * `replaceText`, a tracked clear or row deletion, the binding passes. Inside it the views it makes of
348
+ * what is in a branch write, where a caller's view refuses (D4): the edit itself reaches every branch,
349
+ * the selected one and the others alike, as CR-010's rule has mutators do.
350
+ */
351
+ export function writingEveryBranch(edit) {
352
+ everyBranch++;
353
+ try {
354
+ return edit();
355
+ }
356
+ finally {
357
+ everyBranch--;
358
+ }
359
+ }
360
+ /**
361
+ * Refuses a write through a view in a branch of a kept `mc:AlternateContent` at block, row or cell level
362
+ * (CR-013 D4): the view reads the selected branch, and a write would have to reach the element's other
363
+ * branches too, which nothing maps. A bulk edit reaching every branch writes there (`writingEveryBranch`).
364
+ * `className` is Office JS's ('Paragraph', 'Body').
365
+ */
366
+ export function assertOutsideBranch(value, className, what = `this ${className.toLowerCase()}`) {
367
+ if (everyBranch === 0 && inBranch(value)) {
368
+ throw new NotSupportedError(className, 'edit', `${what} is in a branch of an mc:AlternateContent, which is read-only (CR-013 D4): `
369
+ + "a write would have to reach the element's other branches too, which nothing maps yet");
370
+ }
371
+ }
372
+ /**
373
+ * True for a value inside a branch of a kept `mc:AlternateContent` at block, row or cell level: a
374
+ * paragraph, table, row, cell or content control a reader sees in the selected branch (CR-013 phase 2).
375
+ * A view of one is read-only (D4). From `PARENT` links; a run-level element's content is not reached
376
+ * from a paragraph, which is outside it.
377
+ */
378
+ export function inBranch(value) {
379
+ let o = value === null || value === void 0 ? void 0 : value.PARENT;
380
+ for (let guard = 0; o && guard < 256; guard++, o = o.PARENT) {
381
+ const tn = o.TYPE_NAME;
382
+ if (tn !== undefined && BRANCH_TYPES.has(tn))
383
+ return true;
384
+ }
385
+ return false;
386
+ }
387
+ /**
388
+ * True for a value no reader sees: inside a branch of a kept `mc:AlternateContent` other than the one
389
+ * `selectedBranchOf` takes, at any depth (CR-013 phase 3). What a bulk edit writes there it does not
390
+ * count, as resolve-all counts the listed changes: the count is of what a reader sees.
391
+ */
392
+ export function inUnreadBranch(value) {
393
+ let o = value === null || value === void 0 ? void 0 : value.PARENT;
394
+ for (let guard = 0; o && guard < 256; guard++, o = o.PARENT) {
395
+ const tn = o.TYPE_NAME;
396
+ if (tn === undefined || !BRANCH_TYPES.has(tn))
397
+ continue;
398
+ const ac = o.PARENT;
399
+ if (ac && selectedBranchOf(ac) !== o.any)
400
+ return true;
401
+ }
402
+ return false;
403
+ }
404
+ /**
405
+ * The lists a walk takes for a kept `mc:AlternateContent` among blocks, rows or cells: a reader's
406
+ * (`'read'`) its selected branch, a mutator's (`'every'`) every branch, the Choices first.
407
+ */
408
+ export function branchListsOf(value, mode) {
409
+ if (mode === 'every')
410
+ return branchesOf(value);
411
+ const read = selectedBranchOf(value);
412
+ return read ? [read] : [];
135
413
  }
136
414
  /** w:sdt and w:customXml at row level: they hold the rows of a table (docx4j CTSdtRow, CTCustomXmlRow). */
137
415
  const ROW_HOLDERS = new Set(['org_docx4j_wml.CTSdtRow', 'org_docx4j_wml.CTCustomXmlRow']);
138
416
  /** The same at cell level. */
139
417
  const CELL_HOLDERS = new Set(['org_docx4j_wml.CTSdtCell', 'org_docx4j_wml.CTCustomXmlCell']);
140
- /** The rows of a table, in order, descending into row-level content controls (an OpenDoPE repeat). */
141
- export function rowsOf(tbl) {
142
- return located(childrenOf(tbl), 'org_docx4j_wml.Tr', ROW_HOLDERS);
418
+ /**
419
+ * The rows of a table, in order, descending into row-level content controls (an OpenDoPE repeat), and,
420
+ * with a mode, into a row-level `mc:AlternateContent` (`BranchMode`; CR-013 phase 2).
421
+ */
422
+ export function rowsOf(tbl, mode) {
423
+ return located(childrenOf(tbl), 'org_docx4j_wml.Tr', ROW_HOLDERS, mode);
143
424
  }
144
- /** The cells of a row, in order, descending into cell-level content controls. */
145
- export function cellsOf(tr) {
146
- return located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS);
425
+ /** The cells of a row, in order, descending into cell-level content controls, and with a mode into a cell-level `mc:AlternateContent`. */
426
+ export function cellsOf(tr, mode) {
427
+ return located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS, mode);
147
428
  }
148
- function located(items, typeName, holders) {
429
+ function located(items, typeName, holders, mode, reading) {
149
430
  const out = [];
150
431
  const visit = (list) => {
151
432
  if (!list)
@@ -156,11 +437,51 @@ function located(items, typeName, holders) {
156
437
  out.push({ element, container: list });
157
438
  else if (tn !== undefined && holders.has(tn) && typeof element.value === 'object' && element.value !== null)
158
439
  visit(childrenOf(element.value));
440
+ else if (tn === ALTERNATE_CONTENT && mode !== undefined) {
441
+ if (reading && element.value === reading.ac)
442
+ visit(reading.branch);
443
+ else
444
+ for (const branch of branchListsOf(element.value, mode))
445
+ visit(branch);
446
+ }
159
447
  }
160
448
  };
161
449
  visit(items);
162
450
  return out;
163
451
  }
452
+ /**
453
+ * A row's cells as laid along the grid, one list per reading of the row (docx4j's `Lister.cellLayoutsOf`,
454
+ * its CR-051 phase 2): the selected branches' first (`cellsOf(tr, 'read')`), then, for each cell-level
455
+ * `mc:AlternateContent` and each of its other branches, the row read with that branch in the element's
456
+ * place. Every branch spans the same grid columns, so every cell is in some list at its grid position:
457
+ * what a pass over the grid's columns walks (`collapseGrid`, the column passes; CR-013 phase 3).
458
+ */
459
+ export function cellLayoutsOf(tr) {
460
+ const out = [cellsOf(tr, 'read')];
461
+ const elements = [];
462
+ const collect = (list) => {
463
+ for (const element of list !== null && list !== void 0 ? list : []) {
464
+ const tn = typeNameOf(element);
465
+ if (tn === ALTERNATE_CONTENT) {
466
+ elements.push(element.value);
467
+ for (const branch of branchesOf(element.value))
468
+ collect(branch);
469
+ }
470
+ else if (tn !== undefined && CELL_HOLDERS.has(tn) && typeof element.value === 'object' && element.value !== null) {
471
+ collect(childrenOf(element.value));
472
+ }
473
+ }
474
+ };
475
+ collect(childrenOf(tr));
476
+ for (const ac of elements) {
477
+ const read = selectedBranchOf(ac);
478
+ for (const branch of branchesOf(ac)) {
479
+ if (branch !== read)
480
+ out.push(located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS, 'read', { ac, branch }));
481
+ }
482
+ }
483
+ return out;
484
+ }
164
485
  /** Content controls: `w:sdt` at block, row, cell and run level, by TYPE_NAME. */
165
486
  export const SDT_TYPES = new Set([
166
487
  'org_docx4j_wml.SdtBlock', 'org_docx4j_wml.SdtRun', 'org_docx4j_wml.CTSdtRow', 'org_docx4j_wml.CTSdtCell',
@@ -68,13 +68,21 @@ export declare class CustomXmlPartCollection implements CustomXmlPartOwner, Cust
68
68
  applyBindings(options?: {
69
69
  html?: XhtmlBindingOptions;
70
70
  }): Promise<BindingResult>;
71
+ /** The three passes over some controls: the text bindings, the pictures, the XHTML. */
72
+ private bind;
71
73
  /**
72
74
  * docx4j `UpdateXmlFromDocumentSurface.updateCustomXmlParts`: writes what the controls now show
73
75
  * back into the custom XML. The reverse of `applyBindings`, and what makes an edit to a bound
74
76
  * control show in Word (CR-002 section 12).
75
77
  */
76
78
  updateFromContentControls(): Promise<BindingResult>;
79
+ /**
80
+ * The controls the binding passes take, in every branch of a kept `mc:AlternateContent` (CR-013 phase 3):
81
+ * those a reader sees (`read`: outside the elements and in their selected branches) and the others.
82
+ */
77
83
  private controlsOf;
78
84
  /** The view of a part: its itemID and schema references, read from the properties part's DOM. */
79
85
  private viewFor;
80
86
  }
87
+ /** A version 4 UUID, as docx4j's `UUID.randomUUID()` gives (crypto when the runtime has it). */
88
+ export declare function uuid(): string;
@@ -16,6 +16,7 @@ import { CustomXmlPart } from './CustomXmlPart.mjs';
16
16
  import { applyBindingsTo, updateFromControls } from './bindings.mjs';
17
17
  import { applyXhtmlBindingsTo, isXhtmlBound } from './xhtml.mjs';
18
18
  import { applyPictureHandlersTo, updateFromPictureControls } from './pictures.mjs';
19
+ import { inUnreadBranch, writingEveryBranch } from '../content/tree.mjs';
19
20
  /** A subset of Office JS `Word.CustomXmlPartCollection`. */
20
21
  export class CustomXmlPartCollection {
21
22
  constructor(host) {
@@ -125,10 +126,14 @@ export class CustomXmlPartCollection {
125
126
  if (part.itemId)
126
127
  this.host.customXmlDataStorageParts.delete(part.itemId);
127
128
  this.views.delete(part);
128
- for (const control of this.controlsOf(this.host.boundBodies())) {
129
- if (normaliseId(control.xmlMapping.storeItemID) === normaliseId(view.id))
130
- control.xmlMapping.delete();
131
- }
129
+ // every branch's controls (CR-013 phase 3)
130
+ const { read, unread } = this.controlsOf(this.host.boundBodies());
131
+ writingEveryBranch(() => {
132
+ for (const control of [...read, ...unread]) {
133
+ if (normaliseId(control.xmlMapping.storeItemID) === normaliseId(view.id))
134
+ control.xmlMapping.delete();
135
+ }
136
+ });
132
137
  }
133
138
  /**
134
139
  * docx4j `BindingHandler.applyBindings`: pushes the custom XML values into the bound controls,
@@ -136,12 +141,21 @@ export class CustomXmlPartCollection {
136
141
  * headers and footers it has) and parses the custom XML parts.
137
142
  */
138
143
  async applyBindings(options = {}) {
139
- var _a, _b;
140
144
  await this.load();
141
- const controls = this.controlsOf(await this.host.getBoundBodies());
142
- const result = applyBindingsTo(controls);
145
+ // every branch of a kept mc:AlternateContent is bound, as Word binds what it reads; the result counts
146
+ // what a reader sees, the other branches' controls bound after them and not counted (CR-013 phase 3)
147
+ const { read, unread } = this.controlsOf(await this.host.getBoundBodies());
148
+ const result = await this.bind(read, options);
149
+ if (unread.length > 0)
150
+ await this.bind(unread, options);
151
+ return result;
152
+ }
153
+ /** The three passes over some controls: the text bindings, the pictures, the XHTML. */
154
+ async bind(controls, options) {
155
+ var _a, _b;
156
+ const result = writingEveryBranch(() => applyBindingsTo(controls));
143
157
  // od:Handler=picture through the tag's od:xpath entry (CR-005 section 9): after the text bindings, which took the picture controls.
144
- applyPictureHandlersTo(controls, this, result);
158
+ writingEveryBranch(() => applyPictureHandlersTo(controls, this, result));
145
159
  // Escaped XHTML through the tag's od:xpath entry (CR-005 section 8.2): after the text bindings, asynchronous.
146
160
  if (this.host.xhtmlHost)
147
161
  await applyXhtmlBindingsTo(controls, this, this.host.xhtmlHost, result, (_a = options.html) !== null && _a !== void 0 ? _a : {});
@@ -156,14 +170,23 @@ export class CustomXmlPartCollection {
156
170
  */
157
171
  async updateFromContentControls() {
158
172
  await this.load();
159
- const controls = this.controlsOf(await this.host.getBoundBodies());
173
+ // what a reader sees of the controls: the selected branch's, as Word writes back what it shows (CR-013 phase 3)
174
+ const controls = this.controlsOf(await this.host.getBoundBodies()).read;
160
175
  const result = updateFromControls(controls);
161
176
  // a mapped picture control's image back to its node, as Word 15 writes it (CR-005 section 9, check 38)
162
177
  await updateFromPictureControls(controls, result);
163
178
  return result;
164
179
  }
180
+ /**
181
+ * The controls the binding passes take, in every branch of a kept `mc:AlternateContent` (CR-013 phase 3):
182
+ * those a reader sees (`read`: outside the elements and in their selected branches) and the others.
183
+ */
165
184
  controlsOf(bodies) {
166
- return bodies.flatMap((body) => body.contentControls);
185
+ const read = [];
186
+ const unread = [];
187
+ for (const control of bodies.flatMap((body) => body.contentControlsIn('every')))
188
+ (inUnreadBranch(control.sdt) ? unread : read).push(control);
189
+ return { read, unread };
167
190
  }
168
191
  /** The view of a part: its itemID and schema references, read from the properties part's DOM. */
169
192
  async viewFor(part) {
@@ -212,7 +235,7 @@ function suffixOf(partName) {
212
235
  return (_a = m === null || m === void 0 ? void 0 : m[1]) !== null && _a !== void 0 ? _a : '';
213
236
  }
214
237
  /** A version 4 UUID, as docx4j's `UUID.randomUUID()` gives (crypto when the runtime has it). */
215
- function uuid() {
238
+ export function uuid() {
216
239
  const c = globalThis.crypto;
217
240
  if (c === null || c === void 0 ? void 0 : c.randomUUID)
218
241
  return c.randomUUID();
@@ -1,5 +1,5 @@
1
1
  import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
- import type { ContentControl } from '../content/ContentControl.mjs';
2
+ import { type ContentControl } from '../content/ContentControl.mjs';
3
3
  import type { CustomXmlPart, CustomXmlNode } from './CustomXmlPart.mjs';
4
4
  /** What `XmlMapping` needs of `pkg.customXmlParts`, so that this module does not import the package. */
5
5
  export interface CustomXmlPartLookup {
@@ -1,6 +1,8 @@
1
1
  import * as el from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
2
2
  import * as w15el from '@docx4j/generated-objects-ts/el/org_docx4j_w15';
3
3
  import { sdtProperty } from '@docx4j/generated-objects-ts/builders/wml';
4
+ import { holdsOneParagraph } from '../content/ContentControl.mjs';
5
+ import { NotSupportedError } from '../../office-js/errors.mjs';
4
6
  import { canonicalXPathOf } from './xpath.mjs';
5
7
  import { applyBindingTo } from './bindings.mjs';
6
8
  /** The Word 2012 (w15) namespace; not imported from `ContentControl`, which imports this module. */
@@ -112,6 +114,15 @@ export class XmlMapping {
112
114
  if (prefixMappings !== '')
113
115
  binding.prefixMappings = prefixMappings;
114
116
  const w15 = this.usesW15;
117
+ // w:dataBinding makes a block control plain text to Word, which holds it to one paragraph: binding one that holds
118
+ // more is refused before anything changes, since Word couldn't open the file (CR-002 section 61.6, check 56;
119
+ // docx4j-python's review). w15:dataBinding, Word's rich-text binding, may hold blocks.
120
+ const control = this.contentControl;
121
+ if (!w15 && control.form === 'Block' && (control.type === 'PlainText' || control.type === 'RichText') && !holdsOneParagraph(control)) {
122
+ throw new NotSupportedError('XmlMapping', 'setMapping', 'this block content control holds more than one paragraph, and a control '
123
+ + "bound by w:dataBinding is plain text to Word, which can't open a file where one holds more (CR-002 section 61, check 56); "
124
+ + 'leave it one paragraph first');
125
+ }
115
126
  const element = (w15 ? w15el.dataBinding(binding) : el.dataBinding(binding));
116
127
  const items = (_a = this.contentControl.sdt.sdtPr) === null || _a === void 0 ? void 0 : _a.rPrOrAliasOrLock;
117
128
  const other = w15 ? W_NS : W15_NS;