@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
@@ -1,5 +1,5 @@
1
1
  import { deepCopy } from '@docx4j/generated-objects-ts';
2
- import { typeNameOf, rowsOf, cellsOf, childrenOf, linkParents, textOfView } from './tree.mjs';
2
+ import { typeNameOf, rowsOf, cellsOf, cellLayoutsOf, childrenOf, linkParents, textOfView } from './tree.mjs';
3
3
  import { canonical } from './tracking.mjs';
4
4
  /** The marker members of a `w:tcPr` that are revisions of their own, kept whatever a reject restores. */
5
5
  const CELL_MARKERS = ['cellIns', 'cellDel', 'cellMerge'];
@@ -16,11 +16,23 @@ function without(value, keys) {
16
16
  function differs(current, recorded) {
17
17
  return canonical(current !== null && current !== void 0 ? current : {}) !== canonical(recorded !== null && recorded !== void 0 ? recorded : {});
18
18
  }
19
+ /**
20
+ * A table's rows and a row's cells in every branch of a kept row- or cell-level `mc:AlternateContent`:
21
+ * the table's property records are one change whichever branch holds them, and resolving it reaches
22
+ * every branch (CR-013 phase 3; docx4j's `Lister.allRowsOf` and `allCellsOf`, its CR-051 phase 2, from
23
+ * docx4j-python's finding). The change's text reads the selected branch (`tableChangeText`).
24
+ */
25
+ function allRows(tbl) {
26
+ return rowsOf(tbl, 'every').map((row) => row.element.value);
27
+ }
28
+ function allCells(tr) {
29
+ return cellsOf(tr, 'every').map((cell) => cell.element.value);
30
+ }
19
31
  /** The rows a change takes in: a row with a `w:trPrChange` or a `w:tblPrExChange`, or a cell with a `w:tcPrChange`. */
20
32
  function inChange(tr) {
21
33
  var _a, _b;
22
34
  return ((_a = tr.trPr) === null || _a === void 0 ? void 0 : _a.trPrChange) !== undefined || ((_b = tr.tblPrEx) === null || _b === void 0 ? void 0 : _b.tblPrExChange) !== undefined
23
- || cellsOf(tr).some((cell) => { var _a; return ((_a = cell.element.value.tcPr) === null || _a === void 0 ? void 0 : _a.tcPrChange) !== undefined; });
35
+ || allCells(tr).some((tc) => { var _a; return ((_a = tc.tcPr) === null || _a === void 0 ? void 0 : _a.tcPrChange) !== undefined; });
24
36
  }
25
37
  /**
26
38
  * True when a row in the change is not as its records have it: its properties (a row without a
@@ -32,8 +44,8 @@ function rowDiffers(tr) {
32
44
  return true;
33
45
  if (((_c = tr.tblPrEx) === null || _c === void 0 ? void 0 : _c.tblPrExChange) && differs(without(tr.tblPrEx, ['tblPrExChange']), tr.tblPrEx.tblPrExChange.tblPrEx))
34
46
  return true;
35
- return cellsOf(tr).some(({ element }) => {
36
- const tcPr = element.value.tcPr;
47
+ return allCells(tr).some((tc) => {
48
+ const tcPr = tc.tcPr;
37
49
  return (tcPr === null || tcPr === void 0 ? void 0 : tcPr.tcPrChange) !== undefined && differs(without(tcPr, [...CELL_MARKERS, 'tcPrChange']), tcPr.tcPrChange.tcPr);
38
50
  });
39
51
  }
@@ -48,48 +60,50 @@ function tableDiffers(tbl) {
48
60
  }
49
61
  export function tableRecordsOf(tbl) {
50
62
  var _a, _b, _c, _d;
51
- const rows = rowsOf(tbl).map((row) => row.element.value);
52
- const changed = rows.filter(inChange);
63
+ const changed = allRows(tbl).filter(inChange);
53
64
  if (!((_a = tbl.tblPr) === null || _a === void 0 ? void 0 : _a.tblPrChange) && !((_b = tbl.tblGrid) === null || _b === void 0 ? void 0 : _b.tblGridChange) && changed.length === 0)
54
65
  return undefined;
55
66
  // a set of records that holds no difference is no change (checks 24 and 26's rule)
56
67
  if (!tableDiffers(tbl) && !changed.some(rowDiffers))
57
68
  return undefined;
58
- const value = (_d = (_c = tbl.tblPr) === null || _c === void 0 ? void 0 : _c.tblPrChange) !== null && _d !== void 0 ? _d : changed.map((tr) => { var _a, _b, _c, _d; return (_d = (_b = (_a = tr.trPr) === null || _a === void 0 ? void 0 : _a.trPrChange) !== null && _b !== void 0 ? _b : (_c = tr.tblPrEx) === null || _c === void 0 ? void 0 : _c.tblPrExChange) !== null && _d !== void 0 ? _d : cellsOf(tr).map((c) => { var _a; return (_a = c.element.value.tcPr) === null || _a === void 0 ? void 0 : _a.tcPrChange; }).find(Boolean); }).find(Boolean);
69
+ const value = (_d = (_c = tbl.tblPr) === null || _c === void 0 ? void 0 : _c.tblPrChange) !== null && _d !== void 0 ? _d : changed.map((tr) => { var _a, _b, _c, _d; return (_d = (_b = (_a = tr.trPr) === null || _a === void 0 ? void 0 : _a.trPrChange) !== null && _b !== void 0 ? _b : (_c = tr.tblPrEx) === null || _c === void 0 ? void 0 : _c.tblPrExChange) !== null && _d !== void 0 ? _d : allCells(tr).map((tc) => { var _a; return (_a = tc.tcPr) === null || _a === void 0 ? void 0 : _a.tcPrChange; }).find(Boolean); }).find(Boolean);
59
70
  return value ? { value } : undefined;
60
71
  }
61
72
  /** True when the table has any property record at all, changing anything or not. */
62
73
  export function hasTableRecords(tbl) {
63
74
  var _a, _b;
64
- return ((_a = tbl.tblPr) === null || _a === void 0 ? void 0 : _a.tblPrChange) !== undefined || ((_b = tbl.tblGrid) === null || _b === void 0 ? void 0 : _b.tblGridChange) !== undefined || rowsOf(tbl).some((row) => inChange(row.element.value));
75
+ return ((_a = tbl.tblPr) === null || _a === void 0 ? void 0 : _a.tblPrChange) !== undefined || ((_b = tbl.tblGrid) === null || _b === void 0 ? void 0 : _b.tblGridChange) !== undefined || allRows(tbl).some(inChange);
65
76
  }
66
77
  /** A cell's text as Office JS reports it in a table's change: its paragraphs, a `\r` between them. */
67
78
  function cellText(tc) {
68
79
  var _a;
69
- return ((_a = childrenOf(tc)) !== null && _a !== void 0 ? _a : []).filter((el) => typeNameOf(el) === 'org_docx4j_wml.P').map((el) => textOfView(el.value, { view: 'accepted' })).join('\r');
80
+ return ((_a = childrenOf(tc)) !== null && _a !== void 0 ? _a : []).filter((el) => typeNameOf(el) === 'org_docx4j_wml.P').map((el) => textOfView(el.value, { view: 'accepted', characters: 'textOf' })).join('\r');
70
81
  }
71
82
  /** A row's text as Office JS reports it: its cells with a tab between them, then `\r\n` (checks 27 and 28). */
72
83
  export function rowText(tr) {
73
- return cellsOf(tr).map((cell) => cellText(cell.element.value)).join('\t') + '\r\n';
84
+ return cellsOf(tr, 'read').map((cell) => cellText(cell.element.value)).join('\t') + '\r\n';
74
85
  }
75
- /** The text of a table's change: the table's where its own properties or grid changed, else the changed rows'. */
86
+ /**
87
+ * The text of a table's change: the table's where its own properties or grid changed, else the changed
88
+ * rows', read in the selected branch, what Word shows: so a change whose records are all in other
89
+ * branches has no text (docx4j's `Tables.changeText`, its `aTableChangesTextReadsTheBranchWordReads`).
90
+ */
76
91
  export function tableChangeText(tbl) {
77
- const rows = rowsOf(tbl).map((row) => row.element.value);
92
+ const rows = rowsOf(tbl, 'read').map((row) => row.element.value);
78
93
  const shown = tableDiffers(tbl) ? rows : rows.filter((tr) => inChange(tr) && rowDiffers(tr));
79
94
  return shown.map(rowText).join('');
80
95
  }
81
- /** Accepting keeps the properties as they are and drops every record; a row's `w:trPr` left empty goes. */
96
+ /** Accepting keeps the properties as they are and drops every record, in every branch; a row's `w:trPr` left empty goes. */
82
97
  export function acceptTable(tbl) {
83
98
  var _a, _b, _c, _d, _e;
84
99
  (_a = tbl.tblPr) === null || _a === void 0 ? true : delete _a.tblPrChange;
85
100
  (_b = tbl.tblGrid) === null || _b === void 0 ? true : delete _b.tblGridChange;
86
- for (const { element } of rowsOf(tbl)) {
87
- const tr = element.value;
101
+ for (const tr of allRows(tbl)) {
88
102
  (_c = tr.trPr) === null || _c === void 0 ? true : delete _c.trPrChange;
89
103
  (_d = tr.tblPrEx) === null || _d === void 0 ? true : delete _d.tblPrExChange;
90
104
  pruneRow(tr);
91
- for (const cell of cellsOf(tr))
92
- (_e = cell.element.value.tcPr) === null || _e === void 0 ? true : delete _e.tcPrChange;
105
+ for (const tc of allCells(tr))
106
+ (_e = tc.tcPr) === null || _e === void 0 ? true : delete _e.tcPrChange;
93
107
  }
94
108
  }
95
109
  /**
@@ -97,6 +111,7 @@ export function acceptTable(tbl) {
97
111
  * change as recorded - a row in the change without a `w:trPrChange` cleared, having had no properties
98
112
  * (check 28, from a saved file) - then collapses a merged grid (check 27: a width change records the
99
113
  * old cells over a grid of the old and new column edges together). Rows outside the change are left.
114
+ * Every branch of a kept row- or cell-level `mc:AlternateContent` is restored (CR-013 phase 3).
100
115
  */
101
116
  export function rejectTable(tbl) {
102
117
  var _a, _b, _c, _d;
@@ -106,8 +121,7 @@ export function rejectTable(tbl) {
106
121
  const gridChange = (_b = tbl.tblGrid) === null || _b === void 0 ? void 0 : _b.tblGridChange;
107
122
  if (gridChange && tbl.tblGrid)
108
123
  replaceProperties(tbl.tblGrid, gridChange.tblGrid, [], tbl);
109
- for (const { element } of rowsOf(tbl)) {
110
- const tr = element.value;
124
+ for (const tr of allRows(tbl)) {
111
125
  if (!inChange(tr))
112
126
  continue;
113
127
  const exChange = (_c = tr.tblPrEx) === null || _c === void 0 ? void 0 : _c.tblPrExChange;
@@ -116,10 +130,10 @@ export function rejectTable(tbl) {
116
130
  if (tr.trPr)
117
131
  replaceProperties(tr.trPr, (_d = tr.trPr.trPrChange) === null || _d === void 0 ? void 0 : _d.trPr, ROW_MARKERS, tr);
118
132
  pruneRow(tr);
119
- for (const cell of cellsOf(tr)) {
120
- const tcPr = cell.element.value.tcPr;
133
+ for (const tc of allCells(tr)) {
134
+ const tcPr = tc.tcPr;
121
135
  if (tcPr === null || tcPr === void 0 ? void 0 : tcPr.tcPrChange)
122
- replaceProperties(tcPr, tcPr.tcPrChange.tcPr, CELL_MARKERS, cell.element.value);
136
+ replaceProperties(tcPr, tcPr.tcPrChange.tcPr, CELL_MARKERS, tc);
123
137
  }
124
138
  }
125
139
  if (gridChange)
@@ -159,21 +173,27 @@ function span(tc) {
159
173
  /**
160
174
  * Grid columns that no row keeps apart become one: the edges any row's cells (or its `w:gridBefore`
161
175
  * and `w:gridAfter`) fall on are kept, the others merged, and each cell's `w:gridSpan` and each row's
162
- * skipped columns counted again over the kept columns.
176
+ * skipped columns counted again over the kept columns. The grid is every branch's: every row-level
177
+ * branch's rows are counted, and a row's cells along each of its layouts (`cellLayoutsOf`, one per
178
+ * reading of a cell-level `mc:AlternateContent`), every branch spanning the same columns (CR-013 phase 3,
179
+ * docx4j's `Lister.cellLayoutsOf`; phase 2 counted every branch's cells along one row).
163
180
  */
164
181
  export function collapseGrid(tbl) {
165
182
  var _a, _b, _c, _d, _e, _f;
166
183
  const cols = (_b = (_a = tbl.tblGrid) === null || _a === void 0 ? void 0 : _a.gridCol) !== null && _b !== void 0 ? _b : [];
167
184
  if (cols.length < 2)
168
185
  return;
169
- const rows = rowsOf(tbl).map((row) => row.element.value);
186
+ const rows = allRows(tbl);
187
+ const layouts = new Map(rows.map((tr) => [tr, cellLayoutsOf(tr).map((layout) => layout.map((cell) => cell.element.value))]));
170
188
  const edges = new Set([0, cols.length]);
171
189
  for (const tr of rows) {
172
- let at = Number((_d = (_c = rowMember(tr, 'gridBefore')) === null || _c === void 0 ? void 0 : _c.value.val) !== null && _d !== void 0 ? _d : 0);
173
- edges.add(at);
174
- for (const cell of cellsOf(tr)) {
175
- at += span(cell.element.value);
190
+ for (const layout of layouts.get(tr)) {
191
+ let at = Number((_d = (_c = rowMember(tr, 'gridBefore')) === null || _c === void 0 ? void 0 : _c.value.val) !== null && _d !== void 0 ? _d : 0);
176
192
  edges.add(at);
193
+ for (const tc of layout) {
194
+ at += span(tc);
195
+ edges.add(at);
196
+ }
177
197
  }
178
198
  }
179
199
  const kept = [...edges].filter((edge) => edge >= 0 && edge <= cols.length).sort((a, b) => a - b);
@@ -185,23 +205,33 @@ export function collapseGrid(tbl) {
185
205
  linkParents(tbl.tblGrid, tbl);
186
206
  for (const tr of rows) {
187
207
  const before = rowMember(tr, 'gridBefore');
188
- let at = Number((_e = before === null || before === void 0 ? void 0 : before.value.val) !== null && _e !== void 0 ? _e : 0);
189
- if (before)
190
- before.value.val = index(at);
191
- for (const cell of cellsOf(tr)) {
192
- const tc = cell.element.value;
193
- const next = at + span(tc);
194
- const count = index(next) - index(at);
195
- if (tc.tcPr) {
196
- if (count > 1)
197
- tc.tcPr.gridSpan = { ...((_f = tc.tcPr.gridSpan) !== null && _f !== void 0 ? _f : {}), val: count };
198
- else
199
- delete tc.tcPr.gridSpan;
208
+ const start = Number((_e = before === null || before === void 0 ? void 0 : before.value.val) !== null && _e !== void 0 ? _e : 0);
209
+ // the new spans counted along each layout, last first, a cell outside the elements once; the row's
210
+ // skipped columns after from the selected branches' layout (the first)
211
+ const spans = new Map();
212
+ let end = start;
213
+ const all = layouts.get(tr);
214
+ for (let l = all.length - 1; l >= 0; l--) {
215
+ let at = start;
216
+ for (const tc of all[l]) {
217
+ const next = at + span(tc);
218
+ spans.set(tc, index(next) - index(at));
219
+ at = next;
200
220
  }
201
- at = next;
221
+ end = at;
202
222
  }
223
+ for (const [tc, count] of spans) {
224
+ if (!tc.tcPr)
225
+ continue;
226
+ if (count > 1)
227
+ tc.tcPr.gridSpan = { ...((_f = tc.tcPr.gridSpan) !== null && _f !== void 0 ? _f : {}), val: count };
228
+ else
229
+ delete tc.tcPr.gridSpan;
230
+ }
231
+ if (before)
232
+ before.value.val = index(start);
203
233
  const after = rowMember(tr, 'gridAfter');
204
234
  if (after)
205
- after.value.val = kept.length - 1 - index(at);
235
+ after.value.val = kept.length - 1 - index(end);
206
236
  }
207
237
  }
@@ -0,0 +1,30 @@
1
+ import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
+ import { type Element } from './tree.mjs';
3
+ /** The paragraph a cell ends with, as Word reads it, and the list it is in. */
4
+ export interface CellEnd {
5
+ element: Element<wml.P>;
6
+ container: Element[];
7
+ }
8
+ /**
9
+ * The paragraph these cell contents end with, as Word reads them: the last block, past range markup, through
10
+ * block-level controls and custom XML, and through the branch of a kept `mc:AlternateContent` a reader takes
11
+ * (`selectedBranchOf`; the others aren't checked). Undefined where the last block, so read, is a table or there is
12
+ * no block at all.
13
+ */
14
+ export declare function paragraphEndOf(items: Element[] | undefined): CellEnd | undefined;
15
+ /** docx4j's `endsWithParagraph`: whether the last block among these cell contents, as Word reads it, is a paragraph. */
16
+ export declare function endsWithParagraph(items: Element[] | undefined): boolean;
17
+ /**
18
+ * docx4j's `endWithParagraph`, Word's repair: an empty paragraph appended to the cell, after any wrapper, where its
19
+ * last block as Word reads it isn't one. Returns the paragraph appended, undefined where the rule held.
20
+ */
21
+ export declare function endWithParagraph(tc: wml.Tc): wml.P | undefined;
22
+ /** The cell whose content holds this container (a `w:tc`, a control's content, a branch, ...): up `PARENT` past the wrappers. */
23
+ export declare function wrappingCellOf(owner: object | undefined): wml.Tc | undefined;
24
+ /** The cell a paragraph is in, through the wrappers, and whether it is the paragraph that cell ends with as Word reads it. */
25
+ export declare function endsCell(p: wml.P): boolean;
26
+ /**
27
+ * D3: every cell of the tables in these blocks, at any depth, ends with a paragraph (docx4j's repair). For content
28
+ * that comes from a caller (`insertXml`, `insertOoxml`) before it goes in.
29
+ */
30
+ export declare function endCellsWithParagraphs(blocks: readonly Element[]): void;
@@ -0,0 +1,102 @@
1
+ import { typeNameOf, childrenOf, linkParents, selectedBranchOf, paragraphOf, rowsOf, cellsOf, ALTERNATE_CONTENT, BRANCH_TYPES } from './tree.mjs';
2
+ import { assignParaIds } from './paraIds.mjs';
3
+ const P = 'org_docx4j_wml.P';
4
+ const TBL = 'org_docx4j_wml.Tbl';
5
+ const TC = 'org_docx4j_wml.Tc';
6
+ /** What counts as a block among a cell's contents; anything else (bookmarks, comment and move ranges, permissions) is range markup. */
7
+ const BLOCKS = new Set([P, TBL, 'org_docx4j_wml.SdtBlock', 'org_docx4j_wml.CTCustomXmlBlock', ALTERNATE_CONTENT]);
8
+ /** What stands between a cell and the blocks Word reads through: block-level controls, their content, custom XML, a kept branch. */
9
+ const WRAPPERS = new Set([
10
+ 'org_docx4j_wml.SdtBlock', 'org_docx4j_wml.SdtContentBlock', 'org_docx4j_wml.CTSdtContentBlock', 'org_docx4j_wml.CTCustomXmlBlock',
11
+ ALTERNATE_CONTENT, ...BRANCH_TYPES,
12
+ ]);
13
+ /** The last block-level item, unwrapped from its element pair; undefined where there is none. */
14
+ function lastBlock(items) {
15
+ var _a, _b;
16
+ for (let i = ((_a = items === null || items === void 0 ? void 0 : items.length) !== null && _a !== void 0 ? _a : 0) - 1; i >= 0; i--)
17
+ if (BLOCKS.has((_b = typeNameOf(items[i])) !== null && _b !== void 0 ? _b : ''))
18
+ return items[i];
19
+ return undefined;
20
+ }
21
+ /**
22
+ * The paragraph these cell contents end with, as Word reads them: the last block, past range markup, through
23
+ * block-level controls and custom XML, and through the branch of a kept `mc:AlternateContent` a reader takes
24
+ * (`selectedBranchOf`; the others aren't checked). Undefined where the last block, so read, is a table or there is
25
+ * no block at all.
26
+ */
27
+ export function paragraphEndOf(items) {
28
+ const last = lastBlock(items);
29
+ if (!last)
30
+ return undefined;
31
+ const tn = typeNameOf(last);
32
+ if (tn === P)
33
+ return { element: last, container: items };
34
+ if (tn === TBL)
35
+ return undefined;
36
+ const inner = tn === ALTERNATE_CONTENT ? selectedBranchOf(last.value) : childrenOf(last.value);
37
+ return paragraphEndOf(inner);
38
+ }
39
+ /** docx4j's `endsWithParagraph`: whether the last block among these cell contents, as Word reads it, is a paragraph. */
40
+ export function endsWithParagraph(items) {
41
+ return paragraphEndOf(items) !== undefined;
42
+ }
43
+ /**
44
+ * docx4j's `endWithParagraph`, Word's repair: an empty paragraph appended to the cell, after any wrapper, where its
45
+ * last block as Word reads it isn't one. Returns the paragraph appended, undefined where the rule held.
46
+ */
47
+ export function endWithParagraph(tc) {
48
+ var _a;
49
+ const content = ((_a = tc.content) !== null && _a !== void 0 ? _a : (tc.content = []));
50
+ if (endsWithParagraph(content))
51
+ return undefined;
52
+ const p = paragraphOf([]);
53
+ content.push(p);
54
+ linkParents(p, tc);
55
+ assignParaIds(tc, [p]);
56
+ return p.value;
57
+ }
58
+ /** The cell whose content holds this container (a `w:tc`, a control's content, a branch, ...): up `PARENT` past the wrappers. */
59
+ export function wrappingCellOf(owner) {
60
+ var _a;
61
+ let o = owner;
62
+ for (let guard = 0; o && guard < 32 && WRAPPERS.has((_a = o.TYPE_NAME) !== null && _a !== void 0 ? _a : ''); guard++)
63
+ o = o.PARENT;
64
+ return (o === null || o === void 0 ? void 0 : o.TYPE_NAME) === TC ? o : undefined;
65
+ }
66
+ /** The cell a paragraph is in, through the wrappers, and whether it is the paragraph that cell ends with as Word reads it. */
67
+ export function endsCell(p) {
68
+ var _a;
69
+ const cell = wrappingCellOf(p.PARENT);
70
+ return cell !== undefined && ((_a = paragraphEndOf(cell.content)) === null || _a === void 0 ? void 0 : _a.element.value) === p;
71
+ }
72
+ /**
73
+ * D3: every cell of the tables in these blocks, at any depth, ends with a paragraph (docx4j's repair). For content
74
+ * that comes from a caller (`insertXml`, `insertOoxml`) before it goes in.
75
+ */
76
+ export function endCellsWithParagraphs(blocks) {
77
+ const visit = (items) => {
78
+ var _a, _b;
79
+ for (const el of items !== null && items !== void 0 ? items : []) {
80
+ const v = el.value;
81
+ if (typeof v !== 'object' || v === null)
82
+ continue;
83
+ if (typeNameOf(el) === TBL) {
84
+ for (const row of rowsOf(v, 'every')) {
85
+ for (const cell of cellsOf(row.element.value, 'every')) {
86
+ const tc = cell.element.value;
87
+ visit(tc.content);
88
+ endWithParagraph(tc);
89
+ }
90
+ }
91
+ }
92
+ else if (typeNameOf(el) === ALTERNATE_CONTENT) {
93
+ for (const choice of (_a = v.choice) !== null && _a !== void 0 ? _a : [])
94
+ visit(choice.any);
95
+ visit((_b = v.fallback) === null || _b === void 0 ? void 0 : _b.any);
96
+ }
97
+ else if (typeNameOf(el) !== P)
98
+ visit(childrenOf(v));
99
+ }
100
+ };
101
+ visit(blocks);
102
+ }
@@ -0,0 +1,18 @@
1
+ import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
+ import { type HiddenRuns } from './tree.mjs';
3
+ /** A text box a paragraph anchors: its `w:txbxContent`, or legacy WordArt's string, which has no paragraphs. */
4
+ export interface AnchoredBox {
5
+ content?: wml.CTTxbxContent;
6
+ wordArt?: string;
7
+ }
8
+ /**
9
+ * The text boxes a paragraph anchors, in the order the text model numbers them (`textbox:0`, `textbox:1`):
10
+ * the drawings, VML pictures and kept `mc:AlternateContent` its runs hold in the accepted view, a hidden
11
+ * run's and a field code's left out, each walked as the text model's `anchored` walks it. In a drawing or a
12
+ * shape every `w:txbxContent` (the selected branch of an element, not entered further), and legacy WordArt
13
+ * (a `v:shape` with a `v:textpath` string); nothing in a chart, SmartArt, a picture or an embedded object.
14
+ *
15
+ * A paragraph the accepted view joins to the next (its mark deleted) is one block in the text model, whose
16
+ * boxes are numbered on from the first paragraph's; here each paragraph numbers its own.
17
+ */
18
+ export declare function textBoxesOf(p: wml.P, hidden?: HiddenRuns): AnchoredBox[];
@@ -0,0 +1,105 @@
1
+ import { segmentsOf, selectedBranchOf, isElement, ALTERNATE_CONTENT } from './tree.mjs';
2
+ /**
3
+ * The text boxes a paragraph anchors, in the order the text model numbers them (`textbox:0`, `textbox:1`):
4
+ * the drawings, VML pictures and kept `mc:AlternateContent` its runs hold in the accepted view, a hidden
5
+ * run's and a field code's left out, each walked as the text model's `anchored` walks it. In a drawing or a
6
+ * shape every `w:txbxContent` (the selected branch of an element, not entered further), and legacy WordArt
7
+ * (a `v:shape` with a `v:textpath` string); nothing in a chart, SmartArt, a picture or an embedded object.
8
+ *
9
+ * A paragraph the accepted view joins to the next (its mark deleted) is one block in the text model, whose
10
+ * boxes are numbered on from the first paragraph's; here each paragraph numbers its own.
11
+ */
12
+ export function textBoxesOf(p, hidden) {
13
+ const out = [];
14
+ // the fields open where the walk is, each true while in its code (from its begin to its separate)
15
+ const fields = [];
16
+ segmentsOf(p, {
17
+ hidden,
18
+ visit: (item, _at, _owner, run) => {
19
+ if (run === undefined)
20
+ return;
21
+ const name = item.name.localPart;
22
+ if (name === 'fldChar') {
23
+ const type = item.value.fldCharType;
24
+ if (type === 'begin')
25
+ fields.push(true);
26
+ else if (type === 'separate') {
27
+ if (fields.length > 0)
28
+ fields[fields.length - 1] = false;
29
+ }
30
+ else if (type === 'end')
31
+ fields.pop();
32
+ return;
33
+ }
34
+ const drawn = name === 'drawing' || name === 'pict' || name === 'object' || item.value.TYPE_NAME === ALTERNATE_CONTENT;
35
+ if (!drawn || fields.includes(true) || (hidden === null || hidden === void 0 ? void 0 : hidden(run.element.value)) === true)
36
+ return;
37
+ boxesIn(item.value, out, 0);
38
+ },
39
+ });
40
+ return out;
41
+ }
42
+ const CHART = 'http://schemas.openxmlformats.org/drawingml/2006/chart';
43
+ const CHARTEX = 'http://schemas.microsoft.com/office/drawing/2014/chartex';
44
+ /** What a graphic holds that the text model doesn't enter for text boxes: a chart, SmartArt, a picture. */
45
+ const LEAVES = new Set(['org_docx4j_dml_chart.CTRelId', 'org_docx4j_com_microsoft_schemas_office_drawing_x2014_chartex.CTRelId', 'org_docx4j_dml_diagram.CTRelIds', 'org_docx4j_dml_picture.Pic']);
46
+ /** The text model's `anchored` walk, text boxes only: typed objects in property and list order, DOM not entered. */
47
+ function boxesIn(value, out, depth) {
48
+ var _a, _b, _c, _d, _e;
49
+ if (typeof value !== 'object' || value === null || depth > 200)
50
+ return;
51
+ const tn = value.TYPE_NAME;
52
+ if (tn === undefined)
53
+ return;
54
+ switch (tn) {
55
+ case 'org_docx4j_wml.CTTxbxContent':
56
+ out.push({ content: value });
57
+ return;
58
+ case ALTERNATE_CONTENT:
59
+ for (const o of (_a = selectedBranchOf(value)) !== null && _a !== void 0 ? _a : [])
60
+ boxesIn(unwrap(o), out, depth + 1);
61
+ return;
62
+ case 'org_docx4j_wml.CTObject':
63
+ case 'org_docx4j_wml.CTControl':
64
+ case 'org_docx4j_dml_picture.Pic':
65
+ return;
66
+ case 'org_docx4j_dml_wordprocessingDrawing.Inline':
67
+ case 'org_docx4j_dml_wordprocessingDrawing.Anchor': {
68
+ const data = (_b = value.graphic) === null || _b === void 0 ? void 0 : _b.graphicData;
69
+ if (!data)
70
+ return;
71
+ const uri = (_c = data.uri) !== null && _c !== void 0 ? _c : '';
72
+ if (uri === CHART || uri.startsWith(CHARTEX))
73
+ return;
74
+ if (((_d = data.any) !== null && _d !== void 0 ? _d : []).some((o) => { var _a, _b; return LEAVES.has((_b = (_a = unwrap(o)) === null || _a === void 0 ? void 0 : _a.TYPE_NAME) !== null && _b !== void 0 ? _b : ''); }))
75
+ return;
76
+ break;
77
+ }
78
+ case 'org_docx4j_vml.CTShape': {
79
+ for (const e of ((_e = value.pathOrFormulasOrHandles) !== null && _e !== void 0 ? _e : [])) {
80
+ const v = unwrap(e);
81
+ if ((v === null || v === void 0 ? void 0 : v.TYPE_NAME) === 'org_docx4j_vml.CTTextPath' && v.string !== undefined && v.string !== '') {
82
+ out.push({ wordArt: v.string });
83
+ return;
84
+ }
85
+ }
86
+ break;
87
+ }
88
+ default:
89
+ }
90
+ for (const key of Object.keys(value)) {
91
+ if (key === 'PARENT' || key === 'TYPE_NAME')
92
+ continue;
93
+ const fv = value[key];
94
+ if (Array.isArray(fv)) {
95
+ for (const o of [...fv])
96
+ if (typeof o === 'object' && o !== null)
97
+ boxesIn(unwrap(o), out, depth + 1);
98
+ }
99
+ else if (typeof fv === 'object' && fv !== null)
100
+ boxesIn(unwrap(fv), out, depth + 1);
101
+ }
102
+ }
103
+ function unwrap(o) {
104
+ return isElement(o) ? o.value : o;
105
+ }
@@ -0,0 +1,39 @@
1
+ import type { Part } from '../../parts/Part.mjs';
2
+ import type { TrackedChange, TrackedChangeKind } from './TrackedChange.mjs';
3
+ /**
4
+ * The conditions of docx4j's `TrackedChangeFilter` (CR-011 section 3.2). Every condition given must
5
+ * hold, and one not given holds for all. They apply to the single changes a group is made of
6
+ * (`TrackedChange.pieces`):
7
+ * - a listing returns a change, whole, when any of its pieces matches;
8
+ * - a resolve-all resolves only the pieces that match, so a `kinds` filter can take a deleted
9
+ * paragraph's text and leave its mark (docx4j CR-043's U19).
10
+ *
11
+ * The range conditions of docx4j's (`within`, `withinBookmark`) are not here (CR-011 D2), and a key
12
+ * this does not know is refused rather than ignored: a misspelt condition would otherwise resolve
13
+ * every change.
14
+ */
15
+ export interface TrackedChangeFilter {
16
+ /** Changes by these authors (`w:author`), compared exactly. */
17
+ authors?: readonly string[];
18
+ /** Changes of these types: Office JS's `Word.ChangeTrackingState` names or docx4j's `Type` names (CR-011 D3). */
19
+ types?: readonly ('Added' | 'Deleted' | 'Formatted' | 'ADDED' | 'DELETED' | 'FORMATTED')[];
20
+ /**
21
+ * Changes made at or after this (`TrackedChange.date`). A string is read by `Date`, so an ISO date
22
+ * travels as JSON. A change with no date matches no date range.
23
+ */
24
+ from?: Date | string;
25
+ /** Changes made before this; as `from`. */
26
+ to?: Date | string;
27
+ /** Changes of these kinds (`TrackedChange.kind`: a single change's, as `RUN_INSERTION`). */
28
+ kinds?: readonly TrackedChangeKind[];
29
+ /** Changes in these parts (`TrackedChange.part`); a string is a part name, as `'/word/footnotes.xml'`. */
30
+ parts?: readonly (Part | string)[];
31
+ }
32
+ /** A filter object, or a function over a single change (a piece) that returns whether it is taken. */
33
+ export type TrackedChangeSelection = TrackedChangeFilter | ((change: TrackedChange) => boolean);
34
+ /**
35
+ * Whether a single change meets a selection, as a function: the function form as it is, the object form
36
+ * checked once here (a `TypeError` for a key or value it does not know), so that nothing is resolved on a
37
+ * filter that was misread.
38
+ */
39
+ export declare function pieceMatcher(selection: TrackedChangeSelection): (piece: TrackedChange) => boolean;
@@ -0,0 +1,81 @@
1
+ // Which tracked changes a listing returns and a resolve-all resolves (CR-011 section 3.2): docx4j's
2
+ // TrackedChangeFilter (its CR-043, org.docx4j.model.revisions) by author, type, kind, date and part,
3
+ // as an object that travels as JSON, or a function over a single change.
4
+ import { PartName } from '../../opc/PartName.mjs';
5
+ const KEYS = new Set(['authors', 'types', 'from', 'to', 'kinds', 'parts']);
6
+ const TYPES = {
7
+ Added: 'Added', Deleted: 'Deleted', Formatted: 'Formatted',
8
+ ADDED: 'Added', DELETED: 'Deleted', FORMATTED: 'Formatted',
9
+ };
10
+ const KINDS = new Set([
11
+ 'RUN_INSERTION', 'RUN_DELETION', 'MOVE', 'PARAGRAPH_MARK_INSERTION', 'PARAGRAPH_MARK_DELETION',
12
+ 'RUN_PROPERTIES', 'PARAGRAPH_MARK_PROPERTIES', 'PARAGRAPH_PROPERTIES', 'ROW_INSERTION', 'ROW_DELETION',
13
+ 'FIELD_INSERTION', 'CONTENT_CONTROL_INSERTION', 'CONTENT_CONTROL_DELETION', 'MATH_STRUCTURE_INSERTION', 'MATH_STRUCTURE_DELETION',
14
+ 'INSERTION', 'DELETION', 'FORMATTING', 'TABLE_PROPERTIES', 'SECTION_PROPERTIES', 'CELL_INSERTION', 'CELL_DELETION',
15
+ ]);
16
+ /**
17
+ * Whether a single change meets a selection, as a function: the function form as it is, the object form
18
+ * checked once here (a `TypeError` for a key or value it does not know), so that nothing is resolved on a
19
+ * filter that was misread.
20
+ */
21
+ export function pieceMatcher(selection) {
22
+ var _a;
23
+ if (typeof selection === 'function')
24
+ return selection;
25
+ if (typeof selection !== 'object' || selection === null)
26
+ throw new TypeError('A tracked-change filter is an object or a function');
27
+ for (const key of Object.keys(selection)) {
28
+ if (!KEYS.has(key))
29
+ throw new TypeError(`Unknown tracked-change filter condition '${key}' (known: ${[...KEYS].join(', ')})`);
30
+ }
31
+ const authors = listOf(selection.authors, 'authors', (a) => typeof a === 'string');
32
+ const types = (_a = listOf(selection.types, 'types', (t) => typeof t === 'string' && t in TYPES)) === null || _a === void 0 ? void 0 : _a.map((t) => TYPES[t]);
33
+ const kinds = listOf(selection.kinds, 'kinds', (k) => typeof k === 'string' && KINDS.has(k));
34
+ const parts = listOf(selection.parts, 'parts', (p) => typeof p === 'string' || (typeof p === 'object' && p !== null && 'partName' in p));
35
+ const names = parts === null || parts === void 0 ? void 0 : parts.map((p) => (typeof p === 'string' ? PartName.of(p) : undefined));
36
+ const from = dateOf(selection.from, 'from');
37
+ const to = dateOf(selection.to, 'to');
38
+ return (piece) => {
39
+ var _a;
40
+ if (authors && !authors.includes(piece.author))
41
+ return false;
42
+ if (types && !types.includes(piece.type))
43
+ return false;
44
+ if (kinds && !kinds.includes(piece.kind))
45
+ return false;
46
+ if (from !== undefined || to !== undefined) {
47
+ const date = (_a = piece.date) === null || _a === void 0 ? void 0 : _a.getTime();
48
+ if (date === undefined)
49
+ return false;
50
+ if (from !== undefined && date < from)
51
+ return false;
52
+ if (to !== undefined && date >= to)
53
+ return false;
54
+ }
55
+ if (parts) {
56
+ const part = piece.part;
57
+ if (!part || !parts.some((p, i) => (typeof p === 'string' ? names[i].equals(part.partName) : p === part)))
58
+ return false;
59
+ }
60
+ return true;
61
+ };
62
+ }
63
+ function listOf(value, key, valid) {
64
+ if (value === undefined)
65
+ return undefined;
66
+ if (!Array.isArray(value))
67
+ throw new TypeError(`The tracked-change filter's '${key}' is an array`);
68
+ for (const item of value)
69
+ if (!valid(item))
70
+ throw new TypeError(`The tracked-change filter's '${key}' has ${JSON.stringify(String(item))}, which it does not know`);
71
+ return value;
72
+ }
73
+ function dateOf(value, key) {
74
+ var _a;
75
+ if (value === undefined)
76
+ return undefined;
77
+ const time = (_a = (value instanceof Date ? value : typeof value === 'string' ? new Date(value) : undefined)) === null || _a === void 0 ? void 0 : _a.getTime();
78
+ if (time === undefined || Number.isNaN(time))
79
+ throw new TypeError(`The tracked-change filter's '${key}' is not a date: ${String(value)}`);
80
+ return time;
81
+ }