@docx4j/core-ts 0.5.0 → 0.7.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 (207) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +92 -4
  3. package/dist/html/convert.mjs +2 -1
  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 +145 -23
  24. package/dist/model/content/Body.mjs +507 -150
  25. package/dist/model/content/Comment.d.mts +23 -5
  26. package/dist/model/content/Comment.mjs +207 -26
  27. package/dist/model/content/ContentControl.d.mts +198 -19
  28. package/dist/model/content/ContentControl.mjs +672 -99
  29. package/dist/model/content/Font.d.mts +70 -17
  30. package/dist/model/content/Font.mjs +119 -36
  31. package/dist/model/content/InlinePicture.d.mts +11 -0
  32. package/dist/model/content/InlinePicture.mjs +21 -1
  33. package/dist/model/content/List.d.mts +6 -3
  34. package/dist/model/content/List.mjs +18 -8
  35. package/dist/model/content/Paragraph.d.mts +200 -14
  36. package/dist/model/content/Paragraph.mjs +898 -82
  37. package/dist/model/content/Range.d.mts +227 -12
  38. package/dist/model/content/Range.mjs +785 -59
  39. package/dist/model/content/ResolvedView.d.mts +104 -0
  40. package/dist/model/content/ResolvedView.mjs +596 -0
  41. package/dist/model/content/Table.d.mts +29 -3
  42. package/dist/model/content/Table.mjs +135 -49
  43. package/dist/model/content/TrackedChange.d.mts +174 -15
  44. package/dist/model/content/TrackedChange.mjs +734 -170
  45. package/dist/model/content/comments.d.mts +20 -6
  46. package/dist/model/content/comments.mjs +67 -57
  47. package/dist/model/content/generalException.d.mts +18 -0
  48. package/dist/model/content/generalException.mjs +24 -0
  49. package/dist/model/content/index.d.mts +10 -3
  50. package/dist/model/content/index.mjs +10 -2
  51. package/dist/model/content/mathText.d.mts +21 -0
  52. package/dist/model/content/mathText.mjs +267 -0
  53. package/dist/model/content/officeText.d.mts +27 -0
  54. package/dist/model/content/officeText.mjs +74 -0
  55. package/dist/model/content/ooxml.mjs +12 -1
  56. package/dist/model/content/outline.d.mts +5 -0
  57. package/dist/model/content/outline.mjs +13 -0
  58. package/dist/model/content/paraIds.d.mts +5 -0
  59. package/dist/model/content/paraIds.mjs +54 -0
  60. package/dist/model/content/placeholders.d.mts +110 -0
  61. package/dist/model/content/placeholders.mjs +253 -0
  62. package/dist/model/content/search.d.mts +74 -0
  63. package/dist/model/content/search.mjs +255 -9
  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 +47 -0
  67. package/dist/model/content/story.mjs +95 -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 +102 -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 +63 -6
  79. package/dist/model/content/tracking.mjs +242 -22
  80. package/dist/model/content/tree.d.mts +172 -24
  81. package/dist/model/content/tree.mjs +328 -54
  82. package/dist/model/content/wordRange.d.mts +48 -0
  83. package/dist/model/content/wordRange.mjs +97 -0
  84. package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
  85. package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
  86. package/dist/model/customxml/XmlMapping.d.mts +32 -8
  87. package/dist/model/customxml/XmlMapping.mjs +64 -10
  88. package/dist/model/customxml/bindings.d.mts +33 -4
  89. package/dist/model/customxml/bindings.mjs +171 -45
  90. package/dist/model/customxml/index.d.mts +1 -0
  91. package/dist/model/customxml/index.mjs +1 -0
  92. package/dist/model/customxml/kinds.d.mts +8 -3
  93. package/dist/model/customxml/kinds.mjs +26 -5
  94. package/dist/model/customxml/opendope.d.mts +4 -1
  95. package/dist/model/customxml/opendope.mjs +9 -6
  96. package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
  97. package/dist/model/customxml/picturePlaceholder.mjs +32 -0
  98. package/dist/model/customxml/pictures.d.mts +4 -3
  99. package/dist/model/customxml/pictures.mjs +22 -8
  100. package/dist/model/customxml/storeItems.d.mts +57 -0
  101. package/dist/model/customxml/storeItems.mjs +122 -0
  102. package/dist/model/customxml/xhtml.mjs +23 -22
  103. package/dist/model/dateZone.d.mts +25 -0
  104. package/dist/model/dateZone.mjs +57 -0
  105. package/dist/model/index.d.mts +3 -0
  106. package/dist/model/index.mjs +5 -0
  107. package/dist/model/listnumbering/Emulator.d.mts +37 -5
  108. package/dist/model/listnumbering/Emulator.mjs +63 -9
  109. package/dist/model/properties/PropertyResolver.d.mts +74 -2
  110. package/dist/model/properties/PropertyResolver.mjs +133 -5
  111. package/dist/model/properties/catalogue.d.mts +19 -5
  112. package/dist/model/properties/catalogue.mjs +41 -15
  113. package/dist/model/properties/index.d.mts +1 -1
  114. package/dist/model/properties/log.d.mts +1 -1
  115. package/dist/model/properties/log.mjs +5 -5
  116. package/dist/model/properties/styleUtil.d.mts +3 -1
  117. package/dist/model/properties/styleUtil.mjs +20 -24
  118. package/dist/model/properties/table.mjs +4 -2
  119. package/dist/model/text/CaseMapping.d.mts +38 -0
  120. package/dist/model/text/CaseMapping.mjs +86 -0
  121. package/dist/model/text/Extractor.d.mts +349 -0
  122. package/dist/model/text/Extractor.mjs +2406 -0
  123. package/dist/model/text/LinkTargets.d.mts +45 -0
  124. package/dist/model/text/LinkTargets.mjs +170 -0
  125. package/dist/model/text/MarkdownExporter.d.mts +140 -0
  126. package/dist/model/text/MarkdownExporter.mjs +255 -0
  127. package/dist/model/text/PlainText.d.mts +29 -0
  128. package/dist/model/text/PlainText.mjs +542 -0
  129. package/dist/model/text/TextContext.d.mts +256 -0
  130. package/dist/model/text/TextContext.mjs +600 -0
  131. package/dist/model/text/TextOptions.d.mts +233 -0
  132. package/dist/model/text/TextOptions.mjs +419 -0
  133. package/dist/model/text/TextResult.d.mts +621 -0
  134. package/dist/model/text/TextResult.mjs +629 -0
  135. package/dist/model/text/Texts.d.mts +99 -0
  136. package/dist/model/text/Texts.mjs +187 -0
  137. package/dist/model/text/WmlToMarkdown.d.mts +120 -0
  138. package/dist/model/text/WmlToMarkdown.mjs +936 -0
  139. package/dist/model/text/caseMapping.generated.d.mts +7 -0
  140. package/dist/model/text/caseMapping.generated.mjs +214 -0
  141. package/dist/model/text/commonmark.d.mts +121 -0
  142. package/dist/model/text/commonmark.mjs +655 -0
  143. package/dist/model/text/index.d.mts +8 -0
  144. package/dist/model/text/index.mjs +9 -0
  145. package/dist/model/text/normalize.d.mts +8 -0
  146. package/dist/model/text/normalize.mjs +13 -0
  147. package/dist/model/text/outline.d.mts +4 -0
  148. package/dist/model/text/outline.mjs +71 -0
  149. package/dist/model/wordIntegers.d.mts +29 -0
  150. package/dist/model/wordIntegers.mjs +78 -0
  151. package/dist/office-js/document.mjs +15 -1
  152. package/dist/office-js/fragment.d.mts +7 -5
  153. package/dist/office-js/fragment.mjs +63 -14
  154. package/dist/office-js/proxy.d.mts +8 -0
  155. package/dist/office-js/proxy.mjs +29 -0
  156. package/dist/office-js/run.mjs +2 -0
  157. package/dist/office-js/supported.generated.mjs +16 -0
  158. package/dist/office-js/toApiScript.mjs +29 -12
  159. package/dist/opc/DirectoryPartStore.d.mts +6 -2
  160. package/dist/opc/DirectoryPartStore.mjs +11 -4
  161. package/dist/opc/FlatOpcPartStore.d.mts +4 -2
  162. package/dist/opc/FlatOpcPartStore.mjs +11 -8
  163. package/dist/opc/Load.d.mts +32 -0
  164. package/dist/opc/Load.mjs +115 -5
  165. package/dist/opc/PartStore.d.mts +34 -1
  166. package/dist/opc/PartStore.mjs +71 -8
  167. package/dist/opc/Save.d.mts +32 -0
  168. package/dist/opc/Save.mjs +110 -4
  169. package/dist/opc/ZipPartStore.d.mts +4 -2
  170. package/dist/opc/ZipPartStore.mjs +12 -7
  171. package/dist/opc/exceptions.d.mts +140 -0
  172. package/dist/opc/exceptions.mjs +108 -0
  173. package/dist/opc/index.d.mts +8 -5
  174. package/dist/opc/index.mjs +5 -3
  175. package/dist/opc/mce/preprocessor.d.mts +141 -5
  176. package/dist/opc/mce/preprocessor.mjs +119 -18
  177. package/dist/opc/mce/understood.d.mts +3 -11
  178. package/dist/opc/mce/understood.mjs +27 -23
  179. package/dist/opc/repair/breaks.d.mts +23 -0
  180. package/dist/opc/repair/breaks.mjs +288 -0
  181. package/dist/opc/repair/hosts.d.mts +12 -0
  182. package/dist/opc/repair/hosts.mjs +33 -0
  183. package/dist/opc/repair/mainRoot.d.mts +19 -0
  184. package/dist/opc/repair/mainRoot.mjs +168 -0
  185. package/dist/opc/repair/unknownElements.d.mts +8 -0
  186. package/dist/opc/repair/unknownElements.mjs +180 -0
  187. package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
  188. package/dist/opc/repair/wmlNames.generated.mjs +80 -0
  189. package/dist/opc/skipped.d.mts +50 -0
  190. package/dist/opc/skipped.mjs +140 -0
  191. package/dist/packages/OpcPackage.d.mts +110 -4
  192. package/dist/packages/OpcPackage.mjs +123 -7
  193. package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
  194. package/dist/packages/WordprocessingMLPackage.mjs +158 -21
  195. package/dist/packages/index.d.mts +1 -1
  196. package/dist/parts/DefaultXmlPart.mjs +2 -2
  197. package/dist/parts/Part.d.mts +14 -2
  198. package/dist/parts/RelationshipsPart.d.mts +15 -0
  199. package/dist/parts/RelationshipsPart.mjs +66 -1
  200. package/dist/parts/XmlPart.d.mts +63 -32
  201. package/dist/parts/XmlPart.mjs +240 -96
  202. package/dist/parts/wml/comments.mjs +30 -0
  203. package/dist/parts/wml/index.d.mts +12 -1
  204. package/dist/parts/wml/index.mjs +37 -1
  205. package/dist/xml/dom.d.mts +7 -0
  206. package/dist/xml/dom.mjs +18 -0
  207. package/package.json +2 -2
@@ -0,0 +1,32 @@
1
+ import { ImagePart } from '../../parts/BinaryPart.mjs';
2
+ import { addImagePart, imageRunOf } from '../content/InlinePicture.mjs';
3
+ /** docx4j's placeholder picture, a PNG, as base64. */
4
+ export const PICTURE_PLACEHOLDER_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAACXBIWXMAABYlAAAWJQFJUiTwAAACVklEQVR42u3cwU3jYBCGYRtx50gDNOUOckwDOaWBHNOBm6IAuEEBSByQIkv5B1njgGLP8xx3vasVeuVh82m3f/v46uDWHnwJEBbCQlggLISFsEBYCAthgbAQFsICYSEshAXCQlgU87jkF59Px+indvuDx9b+2PTH/y+sX/6gXdd9vr/O+U08ds+PnU/HdFtOIX+iT/8rncsbaxgGX8eNGcdx4TX0xsLfChEWwgJhISwq65f8pyAzP39jpZ6eX7yxcAoRFuTcYIQ26WyPSQenEGGBsBAWwgJhISxqMEITMkLjFCIsSDNC02CExilEWCAshIWwQFgIixqM0ISM0DiFCAvSjNA0GKFxChEWCAthISwQFsKiBiM0ISM0TiHCgjQjNA1GaJxChAXCQlgIC4SFsKjBCE3ICI1TiLAgzQhNgxEapxBhgbAQFsICYSEsajBCEzJC4xQiLEgzQtNghMYpRFggLISFsEBYCIsajNCEjNA4hQgL0ozQNBihcQoRFggLYSEsEBbCogYjNCEjNE4hwoI0IzQNRmicQoQFwkJYCAuEhbCowQhNyAiNU4iwIM0ITYMRGqcQYYGwEBbCAmEhLGowQhMyQuMUIixIM0LTYITGKURYICyEhbBAWAiLGozQhIzQOIUIC9KM0DQYoXEKERYIC2EhLBAWwqIGIzQhIzROIcKCNCM0DUZoNvfGuq57avoaaz7gsdU95o3Fmt9Yu/3h8m3WtZkfgXjsnh9Lf4PVLfyAFJxChIWwQFgIC2GBsBAWwgJhISyEBcJCWAgLhIWwEBb8+AbsaRgh6xNNrAAAAABJRU5ErkJggg==';
5
+ /** The drawing's extent, Word's: 1270000 EMU (100 points) square. */
6
+ export const PICTURE_PLACEHOLDER_EMU = 1270000;
7
+ /** The relationship each source part's placeholder image was added under, so that every control shares one part. */
8
+ const added = new WeakMap();
9
+ /** The run holding the placeholder drawing in `source` (`scope` its drawing ids'), the image part added once per part. */
10
+ export function picturePlaceholderRun(source, scope) {
11
+ var _a;
12
+ let relId = added.get(source);
13
+ if (relId === undefined || !(((_a = source.relationshipsPart) === null || _a === void 0 ? void 0 : _a.getPart(relId)) instanceof ImagePart)) {
14
+ relId = addImagePart(source, PICTURE_PLACEHOLDER_BASE64).relId;
15
+ added.set(source, relId);
16
+ }
17
+ return imageRunOf(relId, scope, PICTURE_PLACEHOLDER_EMU, PICTURE_PLACEHOLDER_EMU);
18
+ }
19
+ /**
20
+ * Word's form for a picture control (`w:picture`): the flag, and its content one run holding the placeholder drawing, in
21
+ * a paragraph where the control is block-level. What a mapped control whose node is empty shows (CR-005 section 10, D1
22
+ * (a2)) and what `insertContentControl('Picture')` makes (D2), as Word's do. False, and nothing changed, where the
23
+ * control's body has no part to hold the image.
24
+ */
25
+ export function showPicturePlaceholder(control) {
26
+ const source = control.parentBody.part;
27
+ if (!source)
28
+ return false;
29
+ control.setBoundContent([picturePlaceholderRun(source, control.parentBody.container)]);
30
+ control.isShowingPlaceholder = true;
31
+ return true;
32
+ }
@@ -33,9 +33,10 @@ export declare function pictureWidthOf(params: Map<string, string>): PictureWidt
33
33
  * fallback), a tag-bound control holding none is left and noted. Otherwise the control's content
34
34
  * becomes one run holding a new inline picture, sized as `PictureWidth` says, in the first
35
35
  * paragraph of a block-level control (its properties kept) or as a run-level control's content.
36
- * An empty value, a value that is not an image this package reads (PNG, JPEG, GIF, BMP; SVG where
37
- * the drawing is kept, since it has no pixel size to place a new picture at), and a body with no
38
- * part each leave the control as it was, with a note. The image part the control showed before
36
+ * An empty value gives a picture control Word's form, the flag and a placeholder picture (`picturePlaceholderRun`;
37
+ * CR-005 section 10, D1 (a2)), unless it shows one already; a tag-bound control it leaves, with a note. A value that is
38
+ * not an image this package reads (PNG, JPEG, GIF, BMP; SVG where the drawing is kept, since it has no pixel size to
39
+ * place a new picture at), and a body with no part each leave the control as it was, with a note. The image part the control showed before
39
40
  * stays in the package, as docx4j leaves it.
40
41
  */
41
42
  export declare function bindPicture(control: ContentControl, value: string, width: PictureWidth, label: string): PictureOutcome;
@@ -5,6 +5,7 @@ import { ImagePart } from '../../parts/BinaryPart.mjs';
5
5
  import { base64Decode, base64Encode } from '../../xml/dom.mjs';
6
6
  import { enclosingCellOf } from '../properties/table.mjs';
7
7
  import { tagParamsOf, selectEntryNode, PICTURE_HANDLER } from './opendope.mjs';
8
+ import { showPicturePlaceholder } from './picturePlaceholder.mjs';
8
9
  const EMU_PER_TWIP = 635;
9
10
  const BLIP = 'org_docx4j_dml.CTBlip';
10
11
  /** Whether a control is bound to a picture through its tag (`od:Handler=picture` with an `od:xpath`). */
@@ -81,16 +82,26 @@ function maxWidthEmu(control, width) {
81
82
  * fallback), a tag-bound control holding none is left and noted. Otherwise the control's content
82
83
  * becomes one run holding a new inline picture, sized as `PictureWidth` says, in the first
83
84
  * paragraph of a block-level control (its properties kept) or as a run-level control's content.
84
- * An empty value, a value that is not an image this package reads (PNG, JPEG, GIF, BMP; SVG where
85
- * the drawing is kept, since it has no pixel size to place a new picture at), and a body with no
86
- * part each leave the control as it was, with a note. The image part the control showed before
85
+ * An empty value gives a picture control Word's form, the flag and a placeholder picture (`picturePlaceholderRun`;
86
+ * CR-005 section 10, D1 (a2)), unless it shows one already; a tag-bound control it leaves, with a note. A value that is
87
+ * not an image this package reads (PNG, JPEG, GIF, BMP; SVG where the drawing is kept, since it has no pixel size to
88
+ * place a new picture at), and a body with no part each leave the control as it was, with a note. The image part the control showed before
87
89
  * stays in the package, as docx4j leaves it.
88
90
  */
89
91
  export function bindPicture(control, value, width, label) {
90
92
  const base64 = base64Of(value);
91
- if (base64 === '')
92
- return { done: false, note: `${label}: the node is empty; the control is left as it is` };
93
93
  const source = control.parentBody.part;
94
+ if (base64 === '') {
95
+ // a picture control's empty node: Word's form, the flag and a placeholder picture (CR-005 section 10, D1 (a2));
96
+ // one already showing a placeholder picture is left as it is, a tag-bound control left as before
97
+ if (control.type !== 'Picture')
98
+ return { done: false, note: `${label}: the node is empty; the control is left as it is` };
99
+ if (control.isShowingPlaceholder && firstBlipOf(control))
100
+ return { done: false };
101
+ if (!showPicturePlaceholder(control))
102
+ return { done: false, note: `${label}: the control's body has no part to hold an image` };
103
+ return { done: true };
104
+ }
94
105
  if (!source)
95
106
  return { done: false, note: `${label}: the control's body has no part to hold an image` };
96
107
  if (width.kind === 'keep') {
@@ -128,7 +139,9 @@ export function applyPictureHandlerTo(control, parts) {
128
139
  const selected = selectEntryNode(entryId, parts);
129
140
  if ('note' in selected)
130
141
  return { done: false, note: selected.note };
131
- return bindPicture(control, selected.node.text, pictureWidthOf(params), `od:xpath=${entryId}`);
142
+ const outcome = bindPicture(control, selected.node.text, pictureWidthOf(params), `od:xpath=${entryId}`);
143
+ // a stale storeItemID resolved as Word would (CR-020): said where the outcome has nothing else to say
144
+ return selected.repair && outcome.done && !outcome.note ? { ...outcome, note: selected.repair } : outcome;
132
145
  }
133
146
  /** The picture pass over the tag-bound controls, after the text bindings: counted into the result, what was left said in its notes. */
134
147
  export function applyPictureHandlersTo(controls, parts, result) {
@@ -158,7 +171,8 @@ export function applyPictureHandlersTo(controls, parts, result) {
158
171
  export async function updateFromPictureControl(control) {
159
172
  var _a, _b;
160
173
  const mapping = control.xmlMapping;
161
- if (!mapping.isMapped || control.type !== 'Picture')
174
+ // a control showing its placeholder picture holds no picture of its node's (CR-005 section 10)
175
+ if (!mapping.dataBinding || control.type !== 'Picture' || control.isShowingPlaceholder)
162
176
  return false;
163
177
  const node = mapping.customXmlNode;
164
178
  if (!node)
@@ -181,7 +195,7 @@ export async function updateFromPictureControl(control) {
181
195
  /** `updateFromContentControls`' picture pass: the mapped picture controls, counted into the result. */
182
196
  export async function updateFromPictureControls(controls, result) {
183
197
  for (const control of controls) {
184
- if (control.type !== 'Picture' || !control.xmlMapping.isMapped)
198
+ if (control.type !== 'Picture' || !control.xmlMapping.dataBinding)
185
199
  continue;
186
200
  result.bound++;
187
201
  if (await updateFromPictureControl(control))
@@ -0,0 +1,57 @@
1
+ /** The `w:storeItemID`s of the core and application properties (docx4j `BindingHandler`): not custom XML parts, never repaired. */
2
+ export declare const CORE_PROPERTIES_STOREITEMID = "{6C3C8BC8-F283-45AE-878A-BAB7291924A1}";
3
+ export declare const EXTENDED_PROPERTIES_STOREITEMID = "{6668398D-A668-4E3E-A5EB-62B293D839F1}";
4
+ /** An itemID without braces, lower-cased: how `getItem` compares ids, and so how a binding's names its part. */
5
+ export declare function normaliseStoreItemId(id: string): string;
6
+ /** Whether an ID is the core or the application properties'. */
7
+ export declare function isPropertiesStoreItem(id: string): boolean;
8
+ /** One custom XML part as the resolver sees it. */
9
+ export interface StoreItemCandidate<P> {
10
+ readonly part: P;
11
+ /** Its itemID, as its properties part spells it. */
12
+ readonly id: string;
13
+ /** Its part name: the order among several that fit. */
14
+ readonly partName: string;
15
+ /** Its document element; none where the part can't be read, which then fits nothing. */
16
+ readonly root: Element | null | undefined;
17
+ /** Whether the XPath, with these prefix mappings, selects a node in it. */
18
+ selects(xpath: string, prefixMappings: string | undefined): boolean;
19
+ }
20
+ /** The part a binding is evaluated against. */
21
+ export interface StoreItemResolution<P> {
22
+ readonly part: P;
23
+ /** True where the binding's ID names no part and this one fits its XPath: Word's repair. */
24
+ readonly repaired: boolean;
25
+ /** Where repaired, how many parts fit the XPath's first step; this one is the first, in part-name order, that selects a node. */
26
+ readonly fitting: number;
27
+ }
28
+ /**
29
+ * docx4j's `StoreItemResolver.resolve` rule over a package's custom XML parts:
30
+ * - the part the ID names, the comparison `getItem`'s (case and braces ignored); the core and application properties'
31
+ * IDs are left to the caller, and never repaired;
32
+ * - else the parts whose document element's namespace and local name match the XPath's first step, its prefix read with
33
+ * the binding's `w:prefixMappings`, else the objects package's `NAMESPACE_PREFIXES` (docx4j reads its own table); an
34
+ * XPath with no named first step (`//`, `*`, an axis, an attribute) fits every part. In part-name order: one fitting part
35
+ * is taken; of several, the first whose XPath selects a node, else the first (Word's choice in every fresh session,
36
+ * check 73b; CR-020 D7); none, and the binding is unresolved.
37
+ *
38
+ * What a stale ID resolves to is remembered per (ID, XPath, prefix mappings), since one stale ID fits different parts for
39
+ * different XPaths (the two-parts probe: B7 part 1, B11 part 2), and forgotten when the parts change (an add, a delete).
40
+ */
41
+ export declare class StoreItemResolver<P> {
42
+ private readonly candidates;
43
+ private readonly memo;
44
+ private signature;
45
+ constructor(candidates: () => readonly StoreItemCandidate<P>[]);
46
+ /** The part for a binding: named by its ID, else the one its XPath fits; undefined where none is named and none fits. */
47
+ resolve(storeItemId: string | undefined, xpath: string | undefined, prefixMappings: string | undefined): StoreItemResolution<P> | undefined;
48
+ }
49
+ /**
50
+ * The XPath's first step as its namespace and local name, with the binding's prefix mappings (`/p:root[1]/p:b7[1]` with
51
+ * `xmlns:p='urn:x'` is `urn:x` and `root`); undefined where the XPath does not start with a named step, when every part
52
+ * fits. docx4j's `StoreItemResolver.firstStep`.
53
+ */
54
+ export declare function firstStep(xpath: string | undefined, prefixMappings: string | undefined): {
55
+ namespaceURI: string;
56
+ localName: string;
57
+ } | undefined;
@@ -0,0 +1,122 @@
1
+ // CR-020: docx4j's StoreItemResolver (its CR-058 D4, `35cdeaee6`, released in 17.3.5): the custom XML part a binding is
2
+ // evaluated against. The part its `w:storeItemID` names, or, where that names no part, the one its XPath fits, as Word
3
+ // repairs such a binding on open (Word 365, 22 and 23 October 2026, and checks 73 and 73b: the control shows the part's
4
+ // value, Office JS's `customXmlPart` is that part, and the save writes its ID into `w:storeItemID`). Shared by every
5
+ // reader and the bind (CR-020 D1): the text model's bound values, `XmlMapping.customXmlPart` and `customXmlNode`,
6
+ // `applyBindings`, `updateFromContentControls` and the `od:xpath` passes, so they all name the part Word binds.
7
+ import { NAMESPACE_PREFIXES } from '@docx4j/generated-objects-ts';
8
+ import { parsePrefixMappings } from './xpath.mjs';
9
+ /** The `w:storeItemID`s of the core and application properties (docx4j `BindingHandler`): not custom XML parts, never repaired. */
10
+ export const CORE_PROPERTIES_STOREITEMID = '{6C3C8BC8-F283-45AE-878A-BAB7291924A1}';
11
+ export const EXTENDED_PROPERTIES_STOREITEMID = '{6668398D-A668-4E3E-A5EB-62B293D839F1}';
12
+ /** An itemID without braces, lower-cased: how `getItem` compares ids, and so how a binding's names its part. */
13
+ export function normaliseStoreItemId(id) {
14
+ return id.trim().replace(/[{}]/g, '').toLowerCase();
15
+ }
16
+ /** Whether an ID is the core or the application properties'. */
17
+ export function isPropertiesStoreItem(id) {
18
+ const key = normaliseStoreItemId(id);
19
+ return key === normaliseStoreItemId(CORE_PROPERTIES_STOREITEMID) || key === normaliseStoreItemId(EXTENDED_PROPERTIES_STOREITEMID);
20
+ }
21
+ /**
22
+ * docx4j's `StoreItemResolver.resolve` rule over a package's custom XML parts:
23
+ * - the part the ID names, the comparison `getItem`'s (case and braces ignored); the core and application properties'
24
+ * IDs are left to the caller, and never repaired;
25
+ * - else the parts whose document element's namespace and local name match the XPath's first step, its prefix read with
26
+ * the binding's `w:prefixMappings`, else the objects package's `NAMESPACE_PREFIXES` (docx4j reads its own table); an
27
+ * XPath with no named first step (`//`, `*`, an axis, an attribute) fits every part. In part-name order: one fitting part
28
+ * is taken; of several, the first whose XPath selects a node, else the first (Word's choice in every fresh session,
29
+ * check 73b; CR-020 D7); none, and the binding is unresolved.
30
+ *
31
+ * What a stale ID resolves to is remembered per (ID, XPath, prefix mappings), since one stale ID fits different parts for
32
+ * different XPaths (the two-parts probe: B7 part 1, B11 part 2), and forgotten when the parts change (an add, a delete).
33
+ */
34
+ export class StoreItemResolver {
35
+ constructor(candidates) {
36
+ this.candidates = candidates;
37
+ this.memo = new Map();
38
+ this.signature = '';
39
+ }
40
+ /** The part for a binding: named by its ID, else the one its XPath fits; undefined where none is named and none fits. */
41
+ resolve(storeItemId, xpath, prefixMappings) {
42
+ var _a;
43
+ if (!storeItemId)
44
+ return undefined;
45
+ const all = this.candidates();
46
+ const key = normaliseStoreItemId(storeItemId);
47
+ const named = all.find((candidate) => normaliseStoreItemId(candidate.id) === key);
48
+ if (named)
49
+ return { part: named.part, repaired: false, fitting: 0 };
50
+ if (isPropertiesStoreItem(storeItemId))
51
+ return undefined;
52
+ const signature = all.map((candidate) => `${normaliseStoreItemId(candidate.id)} ${candidate.partName}`).join('|');
53
+ if (signature !== this.signature) {
54
+ this.memo.clear();
55
+ this.signature = signature;
56
+ }
57
+ const memoKey = `${key}|${xpath !== null && xpath !== void 0 ? xpath : ''}|${prefixMappings !== null && prefixMappings !== void 0 ? prefixMappings : ''}`;
58
+ let resolved = this.memo.get(memoKey);
59
+ if (resolved === undefined) {
60
+ resolved = (_a = repair(all, xpath !== null && xpath !== void 0 ? xpath : '', prefixMappings)) !== null && _a !== void 0 ? _a : null;
61
+ this.memo.set(memoKey, resolved);
62
+ }
63
+ return resolved !== null && resolved !== void 0 ? resolved : undefined;
64
+ }
65
+ }
66
+ function repair(all, xpath, prefixMappings) {
67
+ const step = firstStep(xpath, prefixMappings);
68
+ const fitting = all.filter((candidate) => {
69
+ var _a, _b;
70
+ const root = candidate.root;
71
+ if (!root)
72
+ return false;
73
+ return step === undefined || (((_a = root.namespaceURI) !== null && _a !== void 0 ? _a : '') === step.namespaceURI && ((_b = root.localName) !== null && _b !== void 0 ? _b : root.nodeName) === step.localName);
74
+ }).sort((a, b) => (a.partName < b.partName ? -1 : a.partName > b.partName ? 1 : 0));
75
+ if (fitting.length === 0)
76
+ return undefined;
77
+ if (fitting.length === 1)
78
+ return { part: fitting[0].part, repaired: true, fitting: 1 };
79
+ const selecting = fitting.find((candidate) => {
80
+ try {
81
+ return candidate.selects(xpath, prefixMappings);
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ });
87
+ return { part: (selecting !== null && selecting !== void 0 ? selecting : fitting[0]).part, repaired: true, fitting: fitting.length };
88
+ }
89
+ /** The objects package's prefixes, prefix to namespace: what a prefix the binding doesn't map reads as. */
90
+ const NAMESPACES_BY_PREFIX = (() => {
91
+ const out = {};
92
+ for (const [uri, prefix] of Object.entries(NAMESPACE_PREFIXES))
93
+ if (prefix !== '' && !(prefix in out))
94
+ out[prefix] = uri;
95
+ return out;
96
+ })();
97
+ /**
98
+ * The XPath's first step as its namespace and local name, with the binding's prefix mappings (`/p:root[1]/p:b7[1]` with
99
+ * `xmlns:p='urn:x'` is `urn:x` and `root`); undefined where the XPath does not start with a named step, when every part
100
+ * fits. docx4j's `StoreItemResolver.firstStep`.
101
+ */
102
+ export function firstStep(xpath, prefixMappings) {
103
+ var _a, _b;
104
+ if (xpath === undefined)
105
+ return undefined;
106
+ let s = xpath.trim();
107
+ if (s.startsWith('//'))
108
+ return undefined;
109
+ if (s.startsWith('/'))
110
+ s = s.slice(1);
111
+ const end = s.search(/[/[(\s]/);
112
+ const step = end < 0 ? s : s.slice(0, end);
113
+ if (step === '' || step === '*' || step === '.' || step === '..' || step.includes('::') || step.startsWith('@'))
114
+ return undefined;
115
+ const colon = step.indexOf(':');
116
+ const prefix = colon < 0 ? '' : step.slice(0, colon);
117
+ const localName = colon < 0 ? step : step.slice(colon + 1);
118
+ if (localName === '' || localName === '*')
119
+ return undefined;
120
+ const namespaceURI = prefix === '' ? '' : ((_b = (_a = parsePrefixMappings(prefixMappings)[prefix]) !== null && _a !== void 0 ? _a : NAMESPACES_BY_PREFIX[prefix]) !== null && _b !== void 0 ? _b : '');
121
+ return { namespaceURI, localName };
122
+ }
@@ -1,10 +1,11 @@
1
1
  import { deepCopy } from '@docx4j/generated-objects-ts';
2
2
  import { Namespaces } from '../../parts/Namespaces.mjs';
3
- import { typeNameOf, linkParents, childrenOf } from '../content/tree.mjs';
3
+ import { typeNameOf, linkParents, childrenOf, writingEveryBranch } from '../content/tree.mjs';
4
4
  import { contentOf } from '../content/ooxml.mjs';
5
+ import { wrappingCellOf, endWithParagraph } from '../content/tableRules.mjs';
5
6
  import { convertHtml, styleLookupOf } from '../../html/convert.mjs';
6
7
  import { blocksToXml, needsOf, HYPERLINK_STYLE } from '../../html/elements.mjs';
7
- import { tagParamsOf, xpathsEntriesOf, XHTML_CONTENT_TYPE } from './opendope.mjs';
8
+ import { tagParamsOf, selectEntryNode, XHTML_CONTENT_TYPE } from './opendope.mjs';
8
9
  /** Whether a control is bound to XHTML through its tag. */
9
10
  export function isXhtmlBound(control) {
10
11
  const params = tagParamsOf(control.tag);
@@ -67,20 +68,15 @@ function inlineContentOf(paragraph) {
67
68
  * `dropped` (a run-level control's blocks after the first, and what the converter dropped).
68
69
  */
69
70
  export async function applyXhtmlBindingTo(control, parts, host, options = {}) {
70
- var _a, _b, _c, _d, _e, _f, _g, _h;
71
- var _j;
71
+ var _a, _b, _c, _d, _e, _f, _g;
72
+ var _h;
72
73
  const params = tagParamsOf(control.tag);
73
74
  const entryId = params.get('od:xpath');
74
- const entry = xpathsEntriesOf(parts).get(entryId);
75
- if (!entry)
76
- return { done: false, note: `od:xpath=${entryId}: no such entry in the XPaths part` };
77
- const part = (_a = parts.getItem(entry.storeItemID)) !== null && _a !== void 0 ? _a : parts.items.find((p) => p.id.replace(/[{}]/g, '').toLowerCase() === entry.storeItemID.replace(/[{}]/g, '').toLowerCase());
78
- if (!part)
79
- return { done: false, note: `od:xpath=${entryId}: no custom XML part ${entry.storeItemID}` };
80
- const node = part.selectSingleNode(entry.xpath, entry.prefixMappings);
81
- if (!node)
82
- return { done: false, note: `od:xpath=${entryId}: ${entry.xpath} selects nothing` };
83
- const parser = (_b = options.parser) !== null && _b !== void 0 ? _b : (typeof DOMParser === 'function' ? (h) => new DOMParser().parseFromString(h, 'text/html') : undefined);
75
+ const selected = selectEntryNode(entryId, parts);
76
+ if ('note' in selected)
77
+ return { done: false, note: selected.note };
78
+ const { node, repair } = selected;
79
+ const parser = (_a = options.parser) !== null && _a !== void 0 ? _a : (typeof DOMParser === 'function' ? (h) => new DOMParser().parseFromString(h, 'text/html') : undefined);
84
80
  if (!parser)
85
81
  return { done: false, note: `od:xpath=${entryId}: XHTML needs an HTML parser (applyBindings({ html: { parser } }))` };
86
82
  const converted = convertHtml(node.text, await lookupFor(host), { parser });
@@ -92,7 +88,7 @@ export async function applyXhtmlBindingTo(control, parts, host, options = {}) {
92
88
  await host.styles.ensure(converted.report.stylesWanted);
93
89
  }
94
90
  catch {
95
- dropped['styles the defaults lack'] = ((_c = dropped['styles the defaults lack']) !== null && _c !== void 0 ? _c : 0) + converted.report.stylesWanted.length;
91
+ dropped['styles the defaults lack'] = ((_b = dropped['styles the defaults lack']) !== null && _b !== void 0 ? _b : 0) + converted.report.stylesWanted.length;
96
92
  }
97
93
  }
98
94
  const needs = needsOf(blocks);
@@ -109,26 +105,26 @@ export async function applyXhtmlBindingTo(control, parts, host, options = {}) {
109
105
  lists.set(key, host.numbering.restart(firstNumbered));
110
106
  }
111
107
  const links = new Map();
112
- const rels = needs.links.length > 0 ? (_d = control.parentBody.part) === null || _d === void 0 ? void 0 : _d.getRelationshipsPart(true) : undefined;
108
+ const rels = needs.links.length > 0 ? (_c = control.parentBody.part) === null || _c === void 0 ? void 0 : _c.getRelationshipsPart(true) : undefined;
113
109
  if (rels) {
114
110
  for (const address of needs.links)
115
111
  links.set(address, rels.addExternalRelationship(Namespaces.HYPERLINK, address).id);
116
112
  host.requireStyles([HYPERLINK_STYLE]);
117
113
  }
118
114
  else if (needs.links.length > 0)
119
- dropped['links'] = ((_e = dropped['links']) !== null && _e !== void 0 ? _e : 0) + needs.links.length;
115
+ dropped['links'] = ((_d = dropped['links']) !== null && _d !== void 0 ? _d : 0) + needs.links.length;
120
116
  const elements = await contentOf(blocksToXml(blocks, { numId: (key) => lists.get(key), relId: (address) => links.get(address) }));
121
117
  applyRunProperties(elements, control.runProperties);
122
118
  const sdt = control.sdt;
123
- (_f = sdt.sdtContent) !== null && _f !== void 0 ? _f : (sdt.sdtContent = {});
124
- const content = ((_g = (_j = sdt.sdtContent).content) !== null && _g !== void 0 ? _g : (_j.content = []));
119
+ (_e = sdt.sdtContent) !== null && _e !== void 0 ? _e : (sdt.sdtContent = {});
120
+ const content = ((_f = (_h = sdt.sdtContent).content) !== null && _f !== void 0 ? _f : (_h.content = []));
125
121
  if (control.form === 'Run') {
126
122
  // A run-level control holds inline content: the first paragraph's, the rest reported.
127
123
  const first = elements.find((e) => typeNameOf(e) === 'org_docx4j_wml.P');
128
124
  const inlines = first ? inlineContentOf(first) : [];
129
125
  const rest = elements.length - (first ? 1 : 0);
130
126
  if (rest > 0)
131
- dropped['blocks after the first, in a run-level control'] = ((_h = dropped['blocks after the first, in a run-level control']) !== null && _h !== void 0 ? _h : 0) + rest;
127
+ dropped['blocks after the first, in a run-level control'] = ((_g = dropped['blocks after the first, in a run-level control']) !== null && _g !== void 0 ? _g : 0) + rest;
132
128
  content.length = 0;
133
129
  content.push(...inlines);
134
130
  linkParents(content, sdt.sdtContent);
@@ -137,9 +133,14 @@ export async function applyXhtmlBindingTo(control, parts, host, options = {}) {
137
133
  content.length = 0;
138
134
  content.push(...elements);
139
135
  linkParents(content, sdt.sdtContent);
136
+ // markup ending in a table, in a cell's control: the cell ends with a paragraph after it, docx4j's repair (CR-002 section 55)
137
+ const cell = wrappingCellOf(sdt.PARENT);
138
+ if (cell)
139
+ endWithParagraph(cell);
140
140
  }
141
- control.isShowingPlaceholder = false;
142
- return Object.keys(dropped).length > 0 ? { done: true, dropped } : { done: true };
141
+ // a control in a branch of a kept mc:AlternateContent too: the pass reaches every branch (CR-013 phase 3)
142
+ writingEveryBranch(() => { control.isShowingPlaceholder = false; });
143
+ return { done: true, ...(repair ? { note: repair } : {}), ...(Object.keys(dropped).length > 0 ? { dropped } : {}) };
143
144
  }
144
145
  /** The XHTML pass over the controls, after the text bindings: counted into the result, what was left said in its notes. */
145
146
  export async function applyXhtmlBindingsTo(controls, parts, host, result, options = {}) {
@@ -0,0 +1,25 @@
1
+ /** The fields a wall clock shows: `month` 1 to 12, `hour` 0 to 23. */
2
+ export interface WallClock {
3
+ readonly year: number;
4
+ readonly month: number;
5
+ readonly day: number;
6
+ readonly hour: number;
7
+ readonly minute: number;
8
+ readonly second: number;
9
+ }
10
+ /** The runtime's zone, an IANA id (`Australia/Sydney`; `UTC` where the runtime has no better answer). */
11
+ export declare function runtimeTimeZone(): string;
12
+ /**
13
+ * `id` when the runtime's `Intl` knows it as a zone, else a `RangeError` naming it: a package's
14
+ * `dateTimeZone` is refused at the set, never ignored, since a wrong zone shifts every stamp.
15
+ */
16
+ export declare function assertTimeZone(id: string): string;
17
+ /** The wall clock `date` shows in `zone`; the runtime's zone where `zone` is undefined. */
18
+ export declare function wallClockIn(date: Date, zone: string | undefined): WallClock;
19
+ /**
20
+ * The instant at which a wall clock in `zone` shows `clock`; the runtime's zone where `zone` is
21
+ * undefined. Found by offset: the clock taken as UTC, corrected by what the zone shows for that
22
+ * guess, twice, which settles across a daylight-saving step; a clock time that does not exist on a
23
+ * spring-forward day gives the instant an hour on, as `Date` does for the runtime's zone.
24
+ */
25
+ export declare function instantOf(clock: WallClock, zone: string | undefined): Date;
@@ -0,0 +1,57 @@
1
+ // The package's time zone (CR-018; the portfolio's date rule of 2026-10-28, docx4j CR-067 D12): an instant a document
2
+ // holds (a revision's or a comment's stamp, a date field) is shown, and a `w:date` without `dateUtc` read, in the zone
3
+ // the caller sets on the package it is working on, else the runtime's. Word writes such a `w:date` as the author's local
4
+ // wall-clock time labelled `Z` (CR-002 section 29, check 23), so the zone is what turns it into an instant and back.
5
+ // Under Office JS the runtime's zone is the client's; under Node on a server it is the server's, hence the option.
6
+ // Nothing here reaches a saved file as such: the zone decides which wall-clock fields are written for an instant.
7
+ /** The runtime's zone, an IANA id (`Australia/Sydney`; `UTC` where the runtime has no better answer). */
8
+ export function runtimeTimeZone() {
9
+ return new Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
10
+ }
11
+ /**
12
+ * `id` when the runtime's `Intl` knows it as a zone, else a `RangeError` naming it: a package's
13
+ * `dateTimeZone` is refused at the set, never ignored, since a wrong zone shifts every stamp.
14
+ */
15
+ export function assertTimeZone(id) {
16
+ try {
17
+ new Intl.DateTimeFormat('en-US', { timeZone: id });
18
+ }
19
+ catch {
20
+ throw new RangeError(`Not a time zone this runtime knows: ${JSON.stringify(id)} (an IANA id, such as "Australia/Sydney")`);
21
+ }
22
+ return id;
23
+ }
24
+ /** The wall clock `date` shows in `zone`; the runtime's zone where `zone` is undefined. */
25
+ export function wallClockIn(date, zone) {
26
+ if (zone === undefined) {
27
+ return {
28
+ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate(),
29
+ hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(),
30
+ };
31
+ }
32
+ const parts = new Intl.DateTimeFormat('en-US', {
33
+ timeZone: zone, hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit',
34
+ }).formatToParts(date);
35
+ const field = (type) => { var _a, _b; return Number((_b = (_a = parts.find((p) => p.type === type)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : NaN); };
36
+ return {
37
+ year: field('year'), month: field('month'), day: field('day'),
38
+ hour: field('hour') % 24, minute: field('minute'), second: field('second'), // hour12: false gives 24 at midnight on some engines
39
+ };
40
+ }
41
+ /**
42
+ * The instant at which a wall clock in `zone` shows `clock`; the runtime's zone where `zone` is
43
+ * undefined. Found by offset: the clock taken as UTC, corrected by what the zone shows for that
44
+ * guess, twice, which settles across a daylight-saving step; a clock time that does not exist on a
45
+ * spring-forward day gives the instant an hour on, as `Date` does for the runtime's zone.
46
+ */
47
+ export function instantOf(clock, zone) {
48
+ if (zone === undefined)
49
+ return new Date(clock.year, clock.month - 1, clock.day, clock.hour, clock.minute, clock.second);
50
+ const asUtc = Date.UTC(clock.year, clock.month - 1, clock.day, clock.hour, clock.minute, clock.second);
51
+ let guess = asUtc;
52
+ for (let i = 0; i < 2; i++) {
53
+ const shown = wallClockIn(new Date(guess), zone);
54
+ guess -= Date.UTC(shown.year, shown.month - 1, shown.day, shown.hour, shown.minute, shown.second) - asUtc;
55
+ }
56
+ return new Date(guess);
57
+ }
@@ -2,5 +2,8 @@ export * from './content/index.mjs';
2
2
  export * from './properties/index.mjs';
3
3
  export * from './listnumbering/index.mjs';
4
4
  export * from './fonts/index.mjs';
5
+ export * from './color/index.mjs';
5
6
  export * from './customxml/index.mjs';
7
+ export * from './text/index.mjs';
6
8
  export { toApiScript, type ApiScriptOptions, type ApiScriptTarget } from '../office-js/toApiScript.mjs';
9
+ export { keptRange, rangeOf, describeReading, isUnmeasured, UNMEASURED_RANGE, type KeptRange } from './wordIntegers.mjs';
@@ -7,8 +7,13 @@ export * from './properties/index.mjs';
7
7
  export * from './listnumbering/index.mjs';
8
8
  // CR-001 Phase B step 4: RunFontSelector, the Mapper and the default theme.
9
9
  export * from './fonts/index.mjs';
10
+ // CR-008 phase 2: colours as Office draws them (ThemeColors, WordColors, DrawingMLColors, SpreadsheetColors).
11
+ export * from './color/index.mjs';
10
12
  // CR-002 phase E: custom XML parts, XML mapping, the XPath engine, the typed content controls.
11
13
  export * from './customxml/index.mjs';
14
+ // CR-012: the text model (Texts, the block model, plain text).
15
+ export * from './text/index.mjs';
12
16
  // The source generator of CR-002 phase I: the content-API calls that reproduce a paragraph, a
13
17
  // range or a table. The `Word` shim it lives next to stays on the ./office-js subpath.
14
18
  export { toApiScript } from '../office-js/toApiScript.mjs';
19
+ export { keptRange, rangeOf, describeReading, isUnmeasured, UNMEASURED_RANGE } from './wordIntegers.mjs';
@@ -64,7 +64,8 @@ export interface NumberingResult {
64
64
  ilvl: string | undefined;
65
65
  /** The level definition, merged. Not docx4j's: a port convenience for CR-002 phase H. */
66
66
  level: LevelDefinition | undefined;
67
- /** The counter's value at this level, before formatting. Not docx4j's. */
67
+ /** The count this paragraph's level shows (the 3 of "1.3."), its counter once this paragraph is
68
+ * counted. docx4j `getValue()` (17.3.4), which this preceded. */
68
69
  count: number | undefined;
69
70
  /** No label was produced. docx4j returns an *empty* `ResultTriple` where a `w:num` or its
70
71
  * level has no definition; this flags that case rather than leaving every member undefined
@@ -117,8 +118,32 @@ export declare class Emulator {
117
118
  * to. The style itself, or any style it is based on, counts as the level's own. Direct
118
119
  * formatting is never suppressed: a paragraph whose *own* `w:numPr` names such a level is
119
120
  * numbered.
121
+ *
122
+ * A level which names no style belongs to one all the same: the first paragraph style in
123
+ * styles.xml whose own `w:numPr` names it ({@link levelStyleId}, docx4j 17.3.4, measured in
124
+ * Word 365 on the three documents of docx4j's `LevelOwnerTest`). Of two styles carrying such
125
+ * a level Word numbers the first in styles.xml - whatever their names, whichever the document
126
+ * uses first, whether or not it uses that style at all - and gives the other style's paragraphs
127
+ * no label and no count. They keep the level's indent, which the effective indent already
128
+ * gives them. A paragraph naming no style is the default paragraph style's in this check.
120
129
  */
121
130
  styleLinkedElsewhere(numId: string, ilvl: string, pStyleVal: string | undefined): boolean;
131
+ /**
132
+ * The paragraph style a numbering level belongs to: the one its `w:lvl/w:pStyle` names (the
133
+ * `w:num`'s override level's first, as {@link NumberingDefinitions.getLinkedStyleId} reads it),
134
+ * else the first paragraph style in styles.xml whose own `w:numPr` names a `w:num` on the same
135
+ * `w:abstractNum` at that level (its `w:ilvl`, 0 where it states none). Undefined where neither:
136
+ * no style carries the level, so a paragraph reaches it only through its own `w:numPr`.
137
+ *
138
+ * The level is the `w:abstractNum`'s, not a `w:num`'s: a style reaching it through a second
139
+ * `w:num` is on the same level, even where that `w:num` overrides it with a `w:lvl` of its own.
140
+ * A style's level is its `w:numPr`'s `w:ilvl`, not the level whose `w:pStyle` names it, as Word
141
+ * reads it (ECMA-376 17.9.24 has the naming level). docx4j `Emulator.levelStyleId` (17.3.4).
142
+ *
143
+ * @param numId a `w:numId` (not 0)
144
+ * @param ilvl a `w:ilvl`; undefined or empty for 0
145
+ */
146
+ levelStyleId(numId: string, ilvl: string | undefined): string | undefined;
122
147
  /**
123
148
  * The one resolution of numId and ilvl for a paragraph. docx4j `Emulator.resolve`
124
149
  * (CR-014 phase 3, which collapsed `getNumber`'s and `getInd`'s two copies onto it).
@@ -135,13 +160,18 @@ export declare class Emulator {
135
160
  resolve(pStyleVal: string | undefined, numId: string | undefined, ilvl: string | undefined, directNumPr: boolean): NumRef;
136
161
  /**
137
162
  * The numbering reference a paragraph resolves to, without taking a number and without
138
- * touching any state. docx4j `Emulator.numRefFor` (17.1.1); never undefined.
163
+ * touching any state. docx4j `Emulator.numRefFor` (17.1.1); never undefined. A paragraph with
164
+ * no `w:pPr` resolves as an empty one, against the default paragraph style, as
165
+ * {@link getNumber} resolves it (docx4j `c283dffdb`, 17.3.4).
139
166
  */
140
167
  numRefFor(pPr: wml.PPr | undefined): NumRef;
141
168
  /**
142
169
  * The next number for a paragraph, from its `w:pPr` (its own `w:numPr`, else its style's),
143
170
  * counted in `state` or in this emulator's default state.
144
171
  *
172
+ * A paragraph with no `w:pPr` resolves as one with an empty `w:pPr` does, against the default
173
+ * paragraph style, which may be numbered (docx4j 17.3.4; before, it was not numbered).
174
+ *
145
175
  * @returns undefined where the paragraph is not numbered
146
176
  */
147
177
  getNumber(pPr: wml.PPr | undefined, state?: NumberingState): NumberingResult | undefined;
@@ -176,11 +206,13 @@ export declare class Emulator {
176
206
  static peek(pkg: NumberedPackageLike, pPr: wml.PPr | undefined, state?: NumberingState): NumberingResult | undefined;
177
207
  /**
178
208
  * docx4j `Emulator.numRefFor(wmlPackage, pPr)`: where this paragraph's numbering resolves to,
179
- * before any counting. Never undefined; a package with no numbering part, a null `w:pPr` or
180
- * a package whose `PropertyResolver` has not been built each answer {@link NumRef.notNumbered}
181
- * with the reason.
209
+ * before any counting. Never undefined; a package with no numbering part or a package whose
210
+ * `PropertyResolver` has not been built each answer {@link NumRef.notNumbered} with the reason.
211
+ * A null `w:pPr` resolves as an empty one (docx4j `c283dffdb`, 17.3.4).
182
212
  */
183
213
  static numRefFor(pkg: NumberedPackageLike | undefined, pPr: wml.PPr | undefined): NumRef;
214
+ /** docx4j `Emulator.levelStyleId(numberingPart, numId, levelId)`: the paragraph style a level belongs to. */
215
+ static levelStyleId(part: NumberingPartLike, numId: string, ilvl: string | undefined): string | undefined;
184
216
  /** docx4j `Emulator.getInd(wmlPackage, pStyleVal, numId, levelId)`. */
185
217
  static getInd(pkg: NumberedPackageLike, pStyleVal: string | undefined, numId: string | undefined, ilvl: string | undefined): wml.PPrBase.Ind | undefined;
186
218
  toString(): string;