@docx4j/core-ts 0.6.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 (119) hide show
  1. package/README.md +60 -0
  2. package/dist/model/content/Body.mjs +6 -17
  3. package/dist/model/content/Comment.d.mts +2 -2
  4. package/dist/model/content/Comment.mjs +12 -7
  5. package/dist/model/content/ContentControl.d.mts +1 -1
  6. package/dist/model/content/ContentControl.mjs +8 -4
  7. package/dist/model/content/Font.d.mts +4 -1
  8. package/dist/model/content/Font.mjs +6 -2
  9. package/dist/model/content/List.d.mts +6 -3
  10. package/dist/model/content/List.mjs +15 -8
  11. package/dist/model/content/Paragraph.d.mts +12 -2
  12. package/dist/model/content/Paragraph.mjs +31 -11
  13. package/dist/model/content/Table.mjs +26 -16
  14. package/dist/model/content/TrackedChange.d.mts +2 -2
  15. package/dist/model/content/TrackedChange.mjs +6 -3
  16. package/dist/model/content/index.d.mts +3 -1
  17. package/dist/model/content/index.mjs +4 -1
  18. package/dist/model/content/ooxml.mjs +12 -1
  19. package/dist/model/content/paraIds.d.mts +5 -0
  20. package/dist/model/content/paraIds.mjs +54 -0
  21. package/dist/model/content/search.d.mts +2 -0
  22. package/dist/model/content/search.mjs +51 -7
  23. package/dist/model/content/story.d.mts +5 -2
  24. package/dist/model/content/story.mjs +6 -3
  25. package/dist/model/content/tableRules.mjs +2 -0
  26. package/dist/model/content/tracking.d.mts +35 -6
  27. package/dist/model/content/tracking.mjs +93 -12
  28. package/dist/model/content/tree.d.mts +7 -8
  29. package/dist/model/content/tree.mjs +7 -9
  30. package/dist/model/content/wordRange.d.mts +48 -0
  31. package/dist/model/content/wordRange.mjs +97 -0
  32. package/dist/model/customxml/CustomXmlPartCollection.d.mts +22 -1
  33. package/dist/model/customxml/CustomXmlPartCollection.mjs +48 -2
  34. package/dist/model/customxml/XmlMapping.d.mts +31 -7
  35. package/dist/model/customxml/XmlMapping.mjs +53 -10
  36. package/dist/model/customxml/bindings.d.mts +12 -2
  37. package/dist/model/customxml/bindings.mjs +98 -16
  38. package/dist/model/customxml/index.d.mts +1 -0
  39. package/dist/model/customxml/index.mjs +1 -0
  40. package/dist/model/customxml/opendope.d.mts +4 -1
  41. package/dist/model/customxml/opendope.mjs +9 -6
  42. package/dist/model/customxml/pictures.mjs +5 -3
  43. package/dist/model/customxml/storeItems.d.mts +57 -0
  44. package/dist/model/customxml/storeItems.mjs +122 -0
  45. package/dist/model/customxml/xhtml.mjs +15 -20
  46. package/dist/model/dateZone.d.mts +25 -0
  47. package/dist/model/dateZone.mjs +57 -0
  48. package/dist/model/index.d.mts +1 -0
  49. package/dist/model/index.mjs +1 -0
  50. package/dist/model/properties/PropertyResolver.d.mts +14 -1
  51. package/dist/model/properties/PropertyResolver.mjs +18 -3
  52. package/dist/model/properties/index.d.mts +1 -1
  53. package/dist/model/properties/log.mjs +2 -2
  54. package/dist/model/properties/styleUtil.d.mts +3 -1
  55. package/dist/model/properties/styleUtil.mjs +20 -24
  56. package/dist/model/text/CaseMapping.d.mts +38 -0
  57. package/dist/model/text/CaseMapping.mjs +86 -0
  58. package/dist/model/text/Extractor.d.mts +66 -6
  59. package/dist/model/text/Extractor.mjs +300 -56
  60. package/dist/model/text/PlainText.mjs +7 -4
  61. package/dist/model/text/TextContext.d.mts +103 -8
  62. package/dist/model/text/TextContext.mjs +228 -53
  63. package/dist/model/text/TextOptions.d.mts +88 -5
  64. package/dist/model/text/TextOptions.mjs +158 -17
  65. package/dist/model/text/TextResult.d.mts +126 -9
  66. package/dist/model/text/TextResult.mjs +115 -12
  67. package/dist/model/text/WmlToMarkdown.mjs +32 -7
  68. package/dist/model/text/caseMapping.generated.d.mts +7 -0
  69. package/dist/model/text/caseMapping.generated.mjs +214 -0
  70. package/dist/model/text/index.d.mts +3 -2
  71. package/dist/model/text/index.mjs +1 -0
  72. package/dist/model/wordIntegers.d.mts +29 -0
  73. package/dist/model/wordIntegers.mjs +78 -0
  74. package/dist/office-js/document.mjs +15 -1
  75. package/dist/office-js/toApiScript.mjs +8 -7
  76. package/dist/opc/DirectoryPartStore.d.mts +6 -2
  77. package/dist/opc/DirectoryPartStore.mjs +11 -4
  78. package/dist/opc/FlatOpcPartStore.d.mts +4 -2
  79. package/dist/opc/FlatOpcPartStore.mjs +11 -8
  80. package/dist/opc/Load.d.mts +32 -0
  81. package/dist/opc/Load.mjs +115 -5
  82. package/dist/opc/PartStore.d.mts +34 -1
  83. package/dist/opc/PartStore.mjs +71 -8
  84. package/dist/opc/Save.d.mts +17 -2
  85. package/dist/opc/Save.mjs +100 -4
  86. package/dist/opc/ZipPartStore.d.mts +4 -2
  87. package/dist/opc/ZipPartStore.mjs +12 -7
  88. package/dist/opc/exceptions.d.mts +140 -0
  89. package/dist/opc/exceptions.mjs +108 -0
  90. package/dist/opc/index.d.mts +7 -4
  91. package/dist/opc/index.mjs +5 -3
  92. package/dist/opc/mce/preprocessor.d.mts +121 -10
  93. package/dist/opc/mce/preprocessor.mjs +122 -21
  94. package/dist/opc/mce/understood.d.mts +3 -35
  95. package/dist/opc/mce/understood.mjs +27 -53
  96. package/dist/opc/repair/breaks.d.mts +23 -0
  97. package/dist/opc/repair/breaks.mjs +288 -0
  98. package/dist/opc/repair/hosts.d.mts +12 -0
  99. package/dist/opc/repair/hosts.mjs +33 -0
  100. package/dist/opc/repair/mainRoot.d.mts +19 -0
  101. package/dist/opc/repair/mainRoot.mjs +168 -0
  102. package/dist/opc/repair/unknownElements.d.mts +8 -0
  103. package/dist/opc/repair/unknownElements.mjs +180 -0
  104. package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
  105. package/dist/opc/repair/wmlNames.generated.mjs +80 -0
  106. package/dist/opc/skipped.d.mts +50 -0
  107. package/dist/opc/skipped.mjs +140 -0
  108. package/dist/packages/OpcPackage.d.mts +98 -5
  109. package/dist/packages/OpcPackage.mjs +122 -7
  110. package/dist/packages/WordprocessingMLPackage.mjs +3 -1
  111. package/dist/packages/index.d.mts +1 -1
  112. package/dist/parts/Part.d.mts +5 -1
  113. package/dist/parts/RelationshipsPart.d.mts +15 -0
  114. package/dist/parts/RelationshipsPart.mjs +66 -1
  115. package/dist/parts/XmlPart.d.mts +54 -5
  116. package/dist/parts/XmlPart.mjs +203 -10
  117. package/dist/parts/wml/index.d.mts +12 -1
  118. package/dist/parts/wml/index.mjs +25 -1
  119. package/package.json +2 -2
@@ -1,5 +1,6 @@
1
- import { READ_UNDERSTOOD_NAMESPACES } from './understood.mjs';
1
+ import { UNDERSTOOD_NAMESPACES } from './understood.mjs';
2
2
  export const MCE_NS = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
3
+ const W = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
3
4
  /**
4
5
  * The hosts whose mc:AlternateContent is kept whole on load, as `{namespace}localName`
5
6
  * (CR-010 phase 1): a chart's `c:chartSpace` and SpreadsheetML's `workbook`.
@@ -13,21 +14,25 @@ export const KEPT_HOSTS = new Set([
13
14
  * warnings are what resolving would report. Returns them.
14
15
  */
15
16
  export function mceKeep(doc, part) {
16
- return preprocessAlternateContent(doc, { resolve: false, partName: part === null || part === void 0 ? void 0 : part.partName.name }).warnings;
17
+ return preprocessAlternateContent(doc, { resolve: false, partName: part === null || part === void 0 ? void 0 : part.partName.name, wordProcessing: isWordProcessing(part) }).warnings;
17
18
  }
18
- /** The resolving preprocessor (`mcePreprocess: true`), over `READ_UNDERSTOOD_NAMESPACES`. Returns the part's warnings. */
19
+ /** The resolving preprocessor (`mcePreprocess: true`), over `UNDERSTOOD_NAMESPACES`. Returns the part's warnings. */
19
20
  export function mcePreprocess(doc, part) {
20
- return preprocessAlternateContent(doc, { partName: part === null || part === void 0 ? void 0 : part.partName.name }).warnings;
21
+ return preprocessAlternateContent(doc, { partName: part === null || part === void 0 ? void 0 : part.partName.name, wordProcessing: isWordProcessing(part) }).warnings;
21
22
  }
22
23
  /** A preprocessor over a namespace set (or kept hosts) of your own. */
23
24
  export function createMcePreprocessor(options) {
24
- return (doc, part) => preprocessAlternateContent(doc, { ...options, partName: part === null || part === void 0 ? void 0 : part.partName.name }).warnings;
25
+ return (doc, part) => preprocessAlternateContent(doc, { wordProcessing: isWordProcessing(part), ...options, partName: part === null || part === void 0 ? void 0 : part.partName.name }).warnings;
26
+ }
27
+ /** Whether a part is WordprocessingML's, by its content type (the transitional and macro-enabled forms); a bare node is taken as one. */
28
+ function isWordProcessing(part) {
29
+ return part === undefined || /wordprocessingml|vnd\.ms-word/.test(part.contentType);
25
30
  }
26
31
  /**
27
- * Resolves every mc:AlternateContent under a node, outermost first, but those `KEPT_HOSTS` and the
28
- * nothing-selectable rule keep (see the file comment). Returns the number resolved.
32
+ * Resolves every mc:AlternateContent under a node, outermost first, but those the file comment keeps. Returns the number
33
+ * resolved, one nothing was selected from among them.
29
34
  */
30
- export function resolveAlternateContent(root, understood = READ_UNDERSTOOD_NAMESPACES) {
35
+ export function resolveAlternateContent(root, understood = UNDERSTOOD_NAMESPACES) {
31
36
  return preprocessAlternateContent(root, { understood }).resolved;
32
37
  }
33
38
  /**
@@ -36,19 +41,28 @@ export function resolveAlternateContent(root, understood = READ_UNDERSTOOD_NAMES
36
41
  * and leaves the DOM as it was.
37
42
  */
38
43
  export function preprocessAlternateContent(root, options = {}) {
39
- var _a, _b, _c;
40
- const understood = (_a = options.understood) !== null && _a !== void 0 ? _a : READ_UNDERSTOOD_NAMESPACES;
44
+ var _a, _b, _c, _d;
45
+ const understood = (_a = options.understood) !== null && _a !== void 0 ? _a : UNDERSTOOD_NAMESPACES;
41
46
  const keptHosts = (_b = options.keptHosts) !== null && _b !== void 0 ? _b : KEPT_HOSTS;
42
47
  const resolve = (_c = options.resolve) !== null && _c !== void 0 ? _c : true;
48
+ const wordProcessing = (_d = options.wordProcessing) !== null && _d !== void 0 ? _d : true;
43
49
  const result = { resolved: 0, kept: 0, warnings: [] };
50
+ const undeclared = new Set();
51
+ // a list read where its element stood in the source: resolving moves a branch's content out of the mc:Choice that may declare
52
+ // its prefixes, as Excel's drawings declare a14 there and list it on an a:srgbClr inside
53
+ const asRead = new Map();
44
54
  const visit = (node) => {
45
- var _a;
46
- const hostKept = node.nodeType === 1 && keptHosts.has(`{${(_a = node.namespaceURI) !== null && _a !== void 0 ? _a : ''}}${node.localName}`);
55
+ var _a, _b, _c;
56
+ if (node.nodeType === 1)
57
+ for (const p of (_a = asRead.get(node)) !== null && _a !== void 0 ? _a : undeclaredIgnorable(node))
58
+ undeclared.add(p);
59
+ const hostKept = node.nodeType === 1 && keptHosts.has(`{${(_b = node.namespaceURI) !== null && _b !== void 0 ? _b : ''}}${node.localName}`);
47
60
  // A work list, not the live child list: resolving replaces a child with the branch's content,
48
61
  // which is visited in its turn (it may hold, or be, another mc:AlternateContent).
49
62
  const queue = [];
50
63
  for (let c = node.firstChild; c; c = c.nextSibling)
51
64
  queue.push(c);
65
+ let removed = false;
52
66
  for (let i = 0; i < queue.length; i++) {
53
67
  if (queue[i].nodeType !== 1)
54
68
  continue;
@@ -60,33 +74,98 @@ export function preprocessAlternateContent(root, options = {}) {
60
74
  const { choices, fallback } = branchesOf(el);
61
75
  const chosen = choices.find((c) => choiceUnderstood(c, understood));
62
76
  const branch = chosen !== null && chosen !== void 0 ? chosen : fallback;
63
- if (hostKept || (branch === undefined && choices.length > 0)) {
77
+ const nothing = branch === undefined && choices.length > 0;
78
+ if (hostKept || (nothing && !wordProcessing)) {
64
79
  result.kept++;
65
80
  continue;
66
81
  }
67
- const warning = branchesDiffer(el, choices, fallback, branch, understood, options.partName);
82
+ const atRoot = ((_c = el.parentNode) === null || _c === void 0 ? void 0 : _c.nodeType) === 9;
83
+ const warning = nothing ? nothingSelected(el, choices, resolve && !atRoot, atRoot, options.partName) : branchesDiffer(el, choices, fallback, branch, understood, options.partName);
68
84
  if (warning)
69
85
  result.warnings.push(warning);
70
- if (!resolve) {
86
+ // a part's root is left whole, as a resolving load can't put a branch's content where the root stood beside it, and
87
+ // reading the branch as the part is WD REQ-317's, not built (CR-028 D10)
88
+ if (!resolve || atRoot) {
71
89
  result.kept++;
72
90
  if (branch)
73
91
  visit(branch);
74
92
  continue;
75
93
  }
76
94
  const moved = [];
95
+ if (branch)
96
+ readInPlace(branch, asRead);
77
97
  if (branch)
78
98
  for (let c = branch.firstChild; c; c = c.nextSibling)
79
99
  moved.push(c);
80
100
  for (const n of moved)
81
101
  node.insertBefore(n, el);
82
102
  node.removeChild(el);
103
+ removed = true;
83
104
  queue.splice(i + 1, 0, ...moved);
84
105
  result.resolved++;
85
106
  }
107
+ if (removed)
108
+ keepACellsParagraph(node);
86
109
  };
87
110
  visit(root);
111
+ if (undeclared.size > 0)
112
+ result.warnings.push(undeclaredPrefix([...undeclared], options.partName));
88
113
  return result;
89
114
  }
115
+ /** The prefixes an element's `mc:Ignorable` lists that have no declaration in scope on it, where it stands now (WD REQ-323). */
116
+ function undeclaredIgnorable(el) {
117
+ const listed = el.getAttributeNS(MCE_NS, 'Ignorable');
118
+ if (!listed)
119
+ return [];
120
+ return listed.trim().split(/\s+/).filter((prefix) => prefix !== '' && !el.lookupNamespaceURI(prefix));
121
+ }
122
+ /**
123
+ * Before a branch's content is moved out, each list in it read where it stands, unless an outer branch's move already read it
124
+ * there. A list in a nested branch not taken is read too, and never visited, so never said.
125
+ */
126
+ function readInPlace(branch, into) {
127
+ const all = branch.getElementsByTagName('*');
128
+ for (let i = 0; i < all.length; i++) {
129
+ const el = all.item(i);
130
+ if (!into.has(el) && el.hasAttributeNS(MCE_NS, 'Ignorable'))
131
+ into.set(el, undeclaredIgnorable(el));
132
+ }
133
+ }
134
+ function undeclaredPrefix(prefixes, partName) {
135
+ return {
136
+ code: 'mce.undeclared_prefix',
137
+ partName,
138
+ prefixes,
139
+ message: `${partName !== null && partName !== void 0 ? partName : 'a part'}: mc:Ignorable lists ${prefixes.join(' ')}, which no declaration in scope binds, so it names nothing and is read as though the list didn't hold it (WD REQ-323)`,
140
+ };
141
+ }
142
+ /**
143
+ * A `w:tc` left with no block gets the paragraph Word's repair gives a cell with none (CR-029 D4 and D9): single-spaced with no
144
+ * space after, `w:spacing w:after="0" w:line="240" w:lineRule="auto"`, whatever the document's defaults, its Normal style or a
145
+ * table style say (the `cell-paragraph` round). Word writes no spacing where the paragraph already reads so (`cp-02`); there the
146
+ * element changes nothing drawn. Word repairs such a cell on open (`te-01` to `te-03`), and opens this silently.
147
+ */
148
+ function keepACellsParagraph(node) {
149
+ if (node.nodeType !== 1)
150
+ return;
151
+ const cell = node;
152
+ if (cell.namespaceURI !== W || cell.localName !== 'tc')
153
+ return;
154
+ for (let c = cell.firstChild; c; c = c.nextSibling) {
155
+ if (c.nodeType === 1 && c.localName !== 'tcPr')
156
+ return;
157
+ }
158
+ const doc = cell.ownerDocument;
159
+ const name = (local) => (cell.prefix ? `${cell.prefix}:${local}` : local);
160
+ const spacing = doc.createElementNS(W, name('spacing'));
161
+ for (const [attribute, value] of [['after', '0'], ['line', '240'], ['lineRule', 'auto']])
162
+ spacing.setAttributeNS(W, name(attribute), value);
163
+ const pPr = doc.createElementNS(W, name('pPr'));
164
+ pPr.appendChild(spacing);
165
+ const p = doc.createElementNS(W, name('p'));
166
+ p.appendChild(pPr);
167
+ cell.appendChild(p);
168
+ }
90
169
  function isAlternateContent(el) {
91
170
  return el.namespaceURI === MCE_NS && el.localName === 'AlternateContent';
92
171
  }
@@ -126,25 +205,24 @@ const TEXT_NAMESPACES = new Set([
126
205
  ]);
127
206
  /**
128
207
  * The text a branch holds: its w:t, a:t and m:t, whitespace collapsed. A nested
129
- * mc:AlternateContent contributes the branch the same rule selects, or its first Choice when
130
- * nothing is selectable (the reading rule).
208
+ * mc:AlternateContent contributes the branch the same rule selects, and nothing where it selects nothing.
131
209
  */
132
210
  function textOfBranch(node, understood) {
133
211
  const out = [];
134
212
  const walk = (n) => {
135
- var _a, _b, _c, _d;
213
+ var _a, _b, _c;
136
214
  for (let c = n.firstChild; c; c = c.nextSibling) {
137
215
  if (c.nodeType !== 1)
138
216
  continue;
139
217
  const el = c;
140
218
  if (isAlternateContent(el)) {
141
219
  const { choices, fallback } = branchesOf(el);
142
- const branch = (_b = (_a = choices.find((x) => choiceUnderstood(x, understood))) !== null && _a !== void 0 ? _a : fallback) !== null && _b !== void 0 ? _b : choices[0];
220
+ const branch = (_a = choices.find((x) => choiceUnderstood(x, understood))) !== null && _a !== void 0 ? _a : fallback;
143
221
  if (branch)
144
222
  walk(branch);
145
223
  }
146
- else if (el.localName === 't' && TEXT_NAMESPACES.has((_c = el.namespaceURI) !== null && _c !== void 0 ? _c : ''))
147
- out.push((_d = el.textContent) !== null && _d !== void 0 ? _d : '');
224
+ else if (el.localName === 't' && TEXT_NAMESPACES.has((_b = el.namespaceURI) !== null && _b !== void 0 ? _b : ''))
225
+ out.push((_c = el.textContent) !== null && _c !== void 0 ? _c : '');
148
226
  else
149
227
  walk(el);
150
228
  }
@@ -156,6 +234,29 @@ function branchName(branch) {
156
234
  var _a;
157
235
  return branch.localName === 'Choice' ? `Choice(${((_a = branch.getAttribute('Requires')) !== null && _a !== void 0 ? _a : '').trim()})` : 'Fallback';
158
236
  }
237
+ /** `mce.nothing_selected`'s record: the namespaces the Choices require, each once, in order (the objects package's `NothingSelected`). */
238
+ function nothingSelected(ac, choices, removed, root, partName) {
239
+ var _a;
240
+ const namespaces = new Set();
241
+ for (const choice of choices) {
242
+ for (const prefix of ((_a = choice.getAttribute('Requires')) !== null && _a !== void 0 ? _a : '').trim().split(/\s+/)) {
243
+ const ns = prefix === '' ? null : choice.lookupNamespaceURI(prefix);
244
+ if (ns)
245
+ namespaces.add(ns);
246
+ }
247
+ }
248
+ const located = ac;
249
+ const where = typeof located.lineNumber === 'number' ? ` (line ${located.lineNumber}, column ${located.columnNumber})` : '';
250
+ return {
251
+ code: 'mce.nothing_selected',
252
+ partName,
253
+ ...(typeof located.lineNumber === 'number' ? { line: located.lineNumber, column: located.columnNumber } : {}),
254
+ namespaces: [...namespaces],
255
+ removed,
256
+ root,
257
+ message: `${partName !== null && partName !== void 0 ? partName : 'a part'}${where}: mc:AlternateContent selects nothing: no Choice is understood (${[...namespaces].join(', ') || 'no namespace bound'}) and it has no Fallback, so it reads as absent (REQ-305)`,
258
+ };
259
+ }
159
260
  function branchesDiffer(ac, choices, fallback, selected, understood, partName) {
160
261
  const all = fallback ? [...choices, fallback] : choices;
161
262
  if (all.length < 2 || selected === undefined)
@@ -1,35 +1,3 @@
1
- export declare const UNDERSTOOD_NAMESPACES: ReadonlySet<string>;
2
- /**
3
- * The conventional prefixes of `UNDERSTOOD_NAMESPACES` (`NAMESPACE_PREFIXES`), the object model's namespaces
4
- * expressed as prefixes (CR-010 section 11.5): the unmarshalled model does not keep the declarations in
5
- * force at the element, so the objects package's `mcBranchOf` compares prefixes, and its default set,
6
- * every prefix `NAMESPACE_PREFIXES` knows, is wider than what load understands. The readers match
7
- * against `READ_UNDERSTOOD_PREFIXES`, this and four more. An understood namespace with no conventional
8
- * prefix has no entry.
9
- */
10
- export declare const UNDERSTOOD_PREFIXES: ReadonlySet<string>;
11
- /**
12
- * The namespaces a reader of a kept mc:AlternateContent counts as understood beyond `UNDERSTOOD_NAMESPACES`
13
- * (CR-010 section 15): Word 365 takes a Choice requiring any of them (measured 2026-10-20), and docx4j's
14
- * published understood list (`understood-namespaces.txt`) has all four, among the 11 its JAXB contexts
15
- * bind and no generated module here does. The name is CR-010's, when only the readers counted them;
16
- * since CR-013 (D3) resolving does too (`READ_UNDERSTOOD_NAMESPACES`). Resolving turns the Choice it takes
17
- * into typed content, which no module types here, but what Word writes in these namespaces survives a
18
- * re-marshal: in every file seen it is attributes only (`w16du:dateUtc`, `w16sdtdh:storeItemChecksum`,
19
- * `x14ac:dyDescent` and `x14ac:knownFonts`; `w16sdtfl` is only declared), measured 2026-10-21.
20
- */
21
- export declare const READ_ONLY_UNDERSTOOD_NAMESPACES: ReadonlySet<string>;
22
- /**
23
- * What a reader of a kept mc:AlternateContent matches `mc:Choice/@Requires` against (`selectedBranchOf`,
24
- * docx4j's `McMode.READ`): `UNDERSTOOD_PREFIXES` and the conventional prefixes of
25
- * `READ_ONLY_UNDERSTOOD_NAMESPACES`. A Choice requiring only these is taken by the gate alone, as REQ-302
26
- * of the text extraction specification reads, whatever its content (CR-010 section 15).
27
- */
28
- export declare const READ_UNDERSTOOD_PREFIXES: ReadonlySet<string>;
29
- /**
30
- * What load selects by, as namespaces: `UNDERSTOOD_NAMESPACES` and `READ_ONLY_UNDERSTOOD_NAMESPACES`, the
31
- * readers' set (`READ_UNDERSTOOD_PREFIXES`) by URI. Resolving (`mcePreprocess: true`) takes the Choice it
32
- * names, and the default load's `mce.branches_differ` reports it as the selected branch, so a resolved load
33
- * takes the branch the readers of a kept load take, as Word 365 does (CR-013 D3).
34
- */
35
- export declare const READ_UNDERSTOOD_NAMESPACES: ReadonlySet<string>;
1
+ import { UNDERSTOOD_NAMESPACES } from '@docx4j/generated-objects-ts/builders/wml';
2
+ export { UNDERSTOOD_NAMESPACES };
3
+ export declare const TRAVERSAL_NAMESPACES: ReadonlySet<string>;
@@ -1,16 +1,18 @@
1
- // What "understanding" an mc:Choice means here: the namespaces whose content survives a load and
2
- // a save. Word takes the first mc:Choice whose Requires prefixes it all understands (ECMA-376
3
- // Part 3, 10.2.1), and so does this preprocessor.
1
+ // The two sets WD REQ-306 has an extractor publish (CR-029).
4
2
  //
5
- // It is the defaultElementNamespaceURI of every generated module of @docx4j/generated-objects-ts
6
- // (0.3.0), which `mce.test.mjs` asserts so that the next regeneration announces an addition, plus
7
- // three groups of hand-kept entries, each marked below: namespaces no module *defaults* to but which
8
- // the model binds anyway (attributes, or elements a module of another namespace declares), the
9
- // slicer namespaces of CR-004 phase B, whose content the model does not bind at all but carries
10
- // through as DOM, and the chartex namespaces Office gates a chart's frame with, which nothing in the
11
- // Choice uses (CR-009 section 8).
12
- import { NAMESPACE_PREFIXES } from '@docx4j/generated-objects-ts';
13
- export const UNDERSTOOD_NAMESPACES = new Set([
3
+ // `UNDERSTOOD_NAMESPACES` decides every markup compatibility question in a word-processing package: which `mc:Choice`
4
+ // a reader takes (REQ-302), whether an element selects nothing (REQ-305), and which namespace Word doesn't know
5
+ // (`repairBreaksOutsideRuns`, `readThroughUnknownElements`). It is what Word 365 was measured to understand, docx4j's
6
+ // published `understood-namespaces.txt` (114 URIs at `824565363`), and it comes from the objects package, whose
7
+ // `mcBranchOf` reads it. It is silent on spreadsheets and presentations, where a namespace not measured counts as not understood.
8
+ //
9
+ // `TRAVERSAL_NAMESPACES` is what this package's readers can traverse, docx4j's `traversal-namespaces.txt`, and it decides
10
+ // nothing about selection. Its first 107 are the namespaces whose content survives a load and a save: the
11
+ // defaultElementNamespaceURI of every generated module of @docx4j/generated-objects-ts, which `mce.test.mjs` asserts so
12
+ // that the next regeneration announces an addition, plus the hand-kept groups marked below. The last 11 are docx4j's.
13
+ import { UNDERSTOOD_NAMESPACES } from '@docx4j/generated-objects-ts/builders/wml';
14
+ export { UNDERSTOOD_NAMESPACES };
15
+ export const TRAVERSAL_NAMESPACES = new Set([
14
16
  'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
15
17
  'http://schemas.openxmlformats.org/package/2006/relationships',
16
18
  'http://schemas.openxmlformats.org/markup-compatibility/2006',
@@ -122,7 +124,7 @@ export const UNDERSTOOD_NAMESPACES = new Set([
122
124
  // holds the one unbound element, and that wildcard is lax (docx4j 8e8f6ea83), so it loads as DOM
123
125
  // and re-marshals unchanged. Taking the Choice therefore keeps the slicer or timeline; leaving
124
126
  // it would take the Fallback, an "Excel 2010 or higher" placeholder box, and lose the slicer for
125
- // good. A Choice is only worth taking when everything in it round-trips (docx4j CR-021 8.9).
127
+ // good.
126
128
  'http://schemas.microsoft.com/office/drawing/2010/slicer',
127
129
  'http://schemas.microsoft.com/office/drawing/2012/slicer',
128
130
  'http://schemas.microsoft.com/office/drawing/2012/timeslicer',
@@ -136,44 +138,16 @@ export const UNDERSTOOD_NAMESPACES = new Set([
136
138
  // here: no file seen gates a Choice with one.
137
139
  'http://schemas.microsoft.com/office/drawing/2015/9/8/chartex',
138
140
  'http://schemas.microsoft.com/office/drawing/2015/10/21/chartex',
141
+ // The 11 docx4j's JAXB contexts bind and no generated module here does, in its published order.
142
+ 'http://schemas.microsoft.com/office/drawing/2016/11/diagram',
143
+ 'http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash',
144
+ 'http://schemas.microsoft.com/office/word/2023/wordml/word16du',
145
+ 'http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock',
146
+ 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac',
147
+ 'http://schemas.microsoft.com/office/spreadsheetml/2015/revision2',
148
+ 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision3',
149
+ 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision6',
150
+ 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision9',
151
+ 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision10',
152
+ 'http://schemas.microsoft.com/office/spreadsheetml/2017/revision16',
139
153
  ]);
140
- const prefixesOf = (namespaces) => [...namespaces].map((uri) => NAMESPACE_PREFIXES[uri]).filter((prefix) => prefix !== undefined && prefix !== '');
141
- /**
142
- * The conventional prefixes of `UNDERSTOOD_NAMESPACES` (`NAMESPACE_PREFIXES`), the object model's namespaces
143
- * expressed as prefixes (CR-010 section 11.5): the unmarshalled model does not keep the declarations in
144
- * force at the element, so the objects package's `mcBranchOf` compares prefixes, and its default set,
145
- * every prefix `NAMESPACE_PREFIXES` knows, is wider than what load understands. The readers match
146
- * against `READ_UNDERSTOOD_PREFIXES`, this and four more. An understood namespace with no conventional
147
- * prefix has no entry.
148
- */
149
- export const UNDERSTOOD_PREFIXES = new Set(prefixesOf(UNDERSTOOD_NAMESPACES));
150
- /**
151
- * The namespaces a reader of a kept mc:AlternateContent counts as understood beyond `UNDERSTOOD_NAMESPACES`
152
- * (CR-010 section 15): Word 365 takes a Choice requiring any of them (measured 2026-10-20), and docx4j's
153
- * published understood list (`understood-namespaces.txt`) has all four, among the 11 its JAXB contexts
154
- * bind and no generated module here does. The name is CR-010's, when only the readers counted them;
155
- * since CR-013 (D3) resolving does too (`READ_UNDERSTOOD_NAMESPACES`). Resolving turns the Choice it takes
156
- * into typed content, which no module types here, but what Word writes in these namespaces survives a
157
- * re-marshal: in every file seen it is attributes only (`w16du:dateUtc`, `w16sdtdh:storeItemChecksum`,
158
- * `x14ac:dyDescent` and `x14ac:knownFonts`; `w16sdtfl` is only declared), measured 2026-10-21.
159
- */
160
- export const READ_ONLY_UNDERSTOOD_NAMESPACES = new Set([
161
- 'http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash', // w16sdtdh
162
- 'http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock', // w16sdtfl
163
- 'http://schemas.microsoft.com/office/word/2023/wordml/word16du', // w16du
164
- 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac', // x14ac
165
- ]);
166
- /**
167
- * What a reader of a kept mc:AlternateContent matches `mc:Choice/@Requires` against (`selectedBranchOf`,
168
- * docx4j's `McMode.READ`): `UNDERSTOOD_PREFIXES` and the conventional prefixes of
169
- * `READ_ONLY_UNDERSTOOD_NAMESPACES`. A Choice requiring only these is taken by the gate alone, as REQ-302
170
- * of the text extraction specification reads, whatever its content (CR-010 section 15).
171
- */
172
- export const READ_UNDERSTOOD_PREFIXES = new Set([...UNDERSTOOD_PREFIXES, ...prefixesOf(READ_ONLY_UNDERSTOOD_NAMESPACES)]);
173
- /**
174
- * What load selects by, as namespaces: `UNDERSTOOD_NAMESPACES` and `READ_ONLY_UNDERSTOOD_NAMESPACES`, the
175
- * readers' set (`READ_UNDERSTOOD_PREFIXES`) by URI. Resolving (`mcePreprocess: true`) takes the Choice it
176
- * names, and the default load's `mce.branches_differ` reports it as the selected branch, so a resolved load
177
- * takes the branch the readers of a kept load take, as Word 365 does (CR-013 D3).
178
- */
179
- export const READ_UNDERSTOOD_NAMESPACES = new Set([...UNDERSTOOD_NAMESPACES, ...READ_ONLY_UNDERSTOOD_NAMESPACES]);
@@ -0,0 +1,23 @@
1
+ import { type ContentSkippedWarning } from '../skipped.mjs';
2
+ /**
3
+ * A part holding a w:br outside a w:r, or a text element holding elements, read as Word reads them (CR-021 D2): one per
4
+ * part, as docx4j's one WARN a part. The code and the fields are docx4j-python's (`part_name`, `breaks`,
5
+ * `text_elements` there), settled through the portfolio session on 2026-11-03. The counts are the stylesheet's: every
6
+ * w:br whose parent is a run container or w:body, and every text element holding an element, at any depth.
7
+ */
8
+ export interface BrOutsideRunWarning {
9
+ code: 'br.outside_run';
10
+ partName: string | undefined;
11
+ /** The w:brs found directly in a run container or in w:body. */
12
+ breaks: number;
13
+ /** The w:t, w:instrText, w:delText and w:delInstrText found holding elements. */
14
+ textElements: number;
15
+ /** docx4j's WARN, after the part: "w:br outside a w:r: 2 outside a run, 1 text elements holding elements; read as Word reads them". */
16
+ message: string;
17
+ }
18
+ /**
19
+ * Puts each w:br found outside a w:r in a run, as Word reads it, over a part's DOM (CR-021; docx4j CR-073's three
20
+ * rules, above). A part whose root is not WordprocessingML's is left alone. Returns the part's warning, or nothing
21
+ * where the part holds none.
22
+ */
23
+ export declare function repairBreaksOutsideRuns(doc: Document, partName?: string): (BrOutsideRunWarning | ContentSkippedWarning)[];