@docx4j/core-ts 0.1.0 → 0.1.1

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 (168) hide show
  1. package/README.md +410 -10
  2. package/dist/model/content/Body.d.mts +109 -4
  3. package/dist/model/content/Body.mjs +300 -29
  4. package/dist/model/content/Comment.d.mts +78 -0
  5. package/dist/model/content/Comment.mjs +429 -0
  6. package/dist/model/content/ContentControl.d.mts +173 -0
  7. package/dist/model/content/ContentControl.mjs +638 -0
  8. package/dist/model/content/Font.d.mts +48 -8
  9. package/dist/model/content/Font.mjs +55 -13
  10. package/dist/model/content/InlinePicture.d.mts +103 -0
  11. package/dist/model/content/InlinePicture.mjs +361 -0
  12. package/dist/model/content/List.d.mts +253 -0
  13. package/dist/model/content/List.mjs +778 -0
  14. package/dist/model/content/Paragraph.d.mts +213 -16
  15. package/dist/model/content/Paragraph.mjs +611 -57
  16. package/dist/model/content/Range.d.mts +48 -4
  17. package/dist/model/content/Range.mjs +161 -4
  18. package/dist/model/content/Table.d.mts +130 -0
  19. package/dist/model/content/Table.mjs +429 -0
  20. package/dist/model/content/TrackedChange.d.mts +96 -0
  21. package/dist/model/content/TrackedChange.mjs +352 -0
  22. package/dist/model/content/comments.d.mts +122 -0
  23. package/dist/model/content/comments.mjs +248 -0
  24. package/dist/model/content/index.d.mts +13 -3
  25. package/dist/model/content/index.mjs +15 -3
  26. package/dist/model/content/ooxml.d.mts +17 -0
  27. package/dist/model/content/ooxml.mjs +214 -0
  28. package/dist/model/content/styles.d.mts +21 -0
  29. package/dist/model/content/styles.mjs +86 -0
  30. package/dist/model/content/tracking.d.mts +104 -0
  31. package/dist/model/content/tracking.mjs +313 -0
  32. package/dist/model/content/tree.d.mts +56 -9
  33. package/dist/model/content/tree.mjs +104 -31
  34. package/dist/model/customxml/CustomXmlPart.d.mts +158 -0
  35. package/dist/model/customxml/CustomXmlPart.mjs +415 -0
  36. package/dist/model/customxml/CustomXmlPartCollection.d.mts +68 -0
  37. package/dist/model/customxml/CustomXmlPartCollection.mjs +183 -0
  38. package/dist/model/customxml/XmlMapping.d.mts +46 -0
  39. package/dist/model/customxml/XmlMapping.mjs +98 -0
  40. package/dist/model/customxml/bindings.d.mts +41 -0
  41. package/dist/model/customxml/bindings.mjs +230 -0
  42. package/dist/model/customxml/index.d.mts +7 -0
  43. package/dist/model/customxml/index.mjs +9 -0
  44. package/dist/model/customxml/insert.d.mts +20 -0
  45. package/dist/model/customxml/insert.mjs +22 -0
  46. package/dist/model/customxml/kinds.d.mts +103 -0
  47. package/dist/model/customxml/kinds.mjs +267 -0
  48. package/dist/model/customxml/xpath.d.mts +52 -0
  49. package/dist/model/customxml/xpath.mjs +205 -0
  50. package/dist/model/fonts/CJKToEnglish.d.mts +2 -0
  51. package/dist/model/fonts/CJKToEnglish.mjs +16 -0
  52. package/dist/model/fonts/FontFallback.d.mts +58 -0
  53. package/dist/model/fonts/FontFallback.mjs +219 -0
  54. package/dist/model/fonts/IdentityPlusMapper.d.mts +7 -0
  55. package/dist/model/fonts/IdentityPlusMapper.mjs +19 -0
  56. package/dist/model/fonts/LanguageTagToScriptMapping.d.mts +7 -0
  57. package/dist/model/fonts/LanguageTagToScriptMapping.mjs +67 -0
  58. package/dist/model/fonts/Mapper.d.mts +190 -0
  59. package/dist/model/fonts/Mapper.mjs +481 -0
  60. package/dist/model/fonts/PhysicalFont.d.mts +34 -0
  61. package/dist/model/fonts/PhysicalFont.mjs +62 -0
  62. package/dist/model/fonts/RunFontSelector.d.mts +194 -0
  63. package/dist/model/fonts/RunFontSelector.mjs +441 -0
  64. package/dist/model/fonts/ThemeFonts.d.mts +17 -0
  65. package/dist/model/fonts/ThemeFonts.mjs +76 -0
  66. package/dist/model/fonts/defaultTheme.d.mts +37 -0
  67. package/dist/model/fonts/defaultTheme.mjs +57 -0
  68. package/dist/model/fonts/families.generated.d.mts +11 -0
  69. package/dist/model/fonts/families.generated.mjs +17 -0
  70. package/dist/model/fonts/fontsInUse.d.mts +39 -0
  71. package/dist/model/fonts/fontsInUse.mjs +183 -0
  72. package/dist/model/fonts/index.d.mts +14 -0
  73. package/dist/model/fonts/index.mjs +29 -0
  74. package/dist/model/fonts/lookup.d.mts +5 -0
  75. package/dist/model/fonts/lookup.mjs +12 -0
  76. package/dist/model/fonts/registry.d.mts +31 -0
  77. package/dist/model/fonts/registry.mjs +103 -0
  78. package/dist/model/fonts/scripts.d.mts +2 -0
  79. package/dist/model/fonts/scripts.mjs +78 -0
  80. package/dist/model/fonts/substitutions.generated.d.mts +30 -0
  81. package/dist/model/fonts/substitutions.generated.mjs +12 -0
  82. package/dist/model/fonts/themes.generated.d.mts +6 -0
  83. package/dist/model/fonts/themes.generated.mjs +11 -0
  84. package/dist/model/index.d.mts +5 -0
  85. package/dist/model/index.mjs +13 -1
  86. package/dist/model/listnumbering/Emulator.d.mts +187 -0
  87. package/dist/model/listnumbering/Emulator.mjs +332 -0
  88. package/dist/model/listnumbering/definitions.d.mts +251 -0
  89. package/dist/model/listnumbering/definitions.mjs +571 -0
  90. package/dist/model/listnumbering/formats.d.mts +25 -0
  91. package/dist/model/listnumbering/formats.mjs +320 -0
  92. package/dist/model/listnumbering/index.d.mts +4 -0
  93. package/dist/model/listnumbering/index.mjs +15 -0
  94. package/dist/model/listnumbering/state.d.mts +97 -0
  95. package/dist/model/listnumbering/state.mjs +179 -0
  96. package/dist/model/properties/PropertyResolver.d.mts +216 -0
  97. package/dist/model/properties/PropertyResolver.mjs +524 -0
  98. package/dist/model/properties/catalogue.d.mts +179 -0
  99. package/dist/model/properties/catalogue.mjs +860 -0
  100. package/dist/model/properties/index.d.mts +4 -0
  101. package/dist/model/properties/index.mjs +9 -0
  102. package/dist/model/properties/log.d.mts +7 -0
  103. package/dist/model/properties/log.mjs +25 -0
  104. package/dist/model/properties/styleUtil.d.mts +112 -0
  105. package/dist/model/properties/styleUtil.mjs +359 -0
  106. package/dist/node/index.d.mts +1 -0
  107. package/dist/node/index.mjs +12 -0
  108. package/dist/office-js/document.d.mts +111 -0
  109. package/dist/office-js/document.mjs +267 -0
  110. package/dist/office-js/enums.d.mts +187 -0
  111. package/dist/office-js/enums.mjs +176 -0
  112. package/dist/office-js/errors.d.mts +29 -0
  113. package/dist/office-js/errors.mjs +39 -0
  114. package/dist/office-js/extras.d.mts +5 -0
  115. package/dist/office-js/extras.mjs +29 -0
  116. package/dist/office-js/fragment.d.mts +10 -0
  117. package/dist/office-js/fragment.mjs +23 -0
  118. package/dist/office-js/index.d.mts +183 -0
  119. package/dist/office-js/index.mjs +54 -0
  120. package/dist/office-js/proxy.d.mts +72 -0
  121. package/dist/office-js/proxy.mjs +279 -0
  122. package/dist/office-js/run.d.mts +32 -0
  123. package/dist/office-js/run.mjs +66 -0
  124. package/dist/office-js/supported.d.mts +7 -0
  125. package/dist/office-js/supported.generated.d.mts +1 -0
  126. package/dist/office-js/supported.generated.mjs +235 -0
  127. package/dist/office-js/supported.mjs +53 -0
  128. package/dist/office-js/toApiScript.d.mts +25 -0
  129. package/dist/office-js/toApiScript.mjs +394 -0
  130. package/dist/opc/ContentTypes.d.mts +1 -0
  131. package/dist/opc/ContentTypes.mjs +1 -0
  132. package/dist/opc/DirectoryPartStore.d.mts +47 -0
  133. package/dist/opc/DirectoryPartStore.mjs +123 -0
  134. package/dist/opc/exceptions.d.mts +30 -0
  135. package/dist/opc/exceptions.mjs +38 -0
  136. package/dist/opc/index.d.mts +1 -1
  137. package/dist/opc/index.mjs +1 -1
  138. package/dist/packages/OpcPackage.d.mts +19 -1
  139. package/dist/packages/OpcPackage.mjs +29 -0
  140. package/dist/packages/PresentationMLPackage.d.mts +71 -1
  141. package/dist/packages/PresentationMLPackage.mjs +179 -0
  142. package/dist/packages/SpreadsheetMLPackage.d.mts +30 -1
  143. package/dist/packages/SpreadsheetMLPackage.mjs +78 -0
  144. package/dist/packages/WordprocessingMLPackage.d.mts +124 -2
  145. package/dist/packages/WordprocessingMLPackage.mjs +309 -2
  146. package/dist/packages/index.d.mts +1 -1
  147. package/dist/packages/index.mjs +1 -1
  148. package/dist/parts/DefaultXmlPart.d.mts +18 -0
  149. package/dist/parts/DefaultXmlPart.mjs +34 -5
  150. package/dist/parts/PartRegistry.mjs +1 -0
  151. package/dist/parts/XmlPart.d.mts +33 -0
  152. package/dist/parts/XmlPart.mjs +105 -2
  153. package/dist/parts/pml/defaults.d.mts +6 -0
  154. package/dist/parts/pml/defaults.mjs +53 -0
  155. package/dist/parts/pml/index.d.mts +66 -3
  156. package/dist/parts/pml/index.mjs +206 -7
  157. package/dist/parts/pml/placeholders.d.mts +71 -0
  158. package/dist/parts/pml/placeholders.mjs +141 -0
  159. package/dist/parts/sml/index.d.mts +19 -1
  160. package/dist/parts/sml/index.mjs +60 -1
  161. package/dist/parts/wml/comments.d.mts +1 -0
  162. package/dist/parts/wml/comments.mjs +179 -0
  163. package/dist/parts/wml/defaultNumbering.d.mts +1 -0
  164. package/dist/parts/wml/defaultNumbering.mjs +216 -0
  165. package/dist/parts/wml/index.d.mts +121 -0
  166. package/dist/parts/wml/index.mjs +291 -0
  167. package/dist/xml/dom.mjs +1 -2
  168. package/package.json +25 -4
@@ -1,14 +1,27 @@
1
1
  import { deepCopy, marshalString } from '@docx4j/generated-objects-ts';
2
+ import { Docx4JException } from '../../opc/exceptions.mjs';
2
3
  import { r as textRun, t as textItem, br as breakItem } from '@docx4j/generated-objects-ts/builders/wml';
3
- import { segmentsOf, runsOf, runItemsOf, linkParents, textOf, W_NS, runOf, paragraphOf } from './tree.mjs';
4
+ import { segmentsOf, runsOf, runItemsOf, linkParents, textOf, textOfView, typeNameOf, W_NS, runOf, paragraphOf, revisionKindOf } from './tree.mjs';
4
5
  function withRPr(run, rPr) {
5
6
  if (rPr)
6
7
  run.value.rPr = rPr;
7
8
  return run;
8
9
  }
9
10
  import { Font } from './Font.mjs';
11
+ import { runFontSelectorOf } from '../fonts/lookup.mjs';
10
12
  import { Range } from './Range.mjs';
11
13
  import { searchPattern, findAll } from './search.mjs';
14
+ import { builtInOf, idOfBuiltIn, styleNameOf, styleIdOf } from './styles.mjs';
15
+ import { cellOf } from './Table.mjs';
16
+ import { ContentControl, collectRunControls } from './ContentControl.mjs';
17
+ import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/wml';
18
+ import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
19
+ import { InlinePicture, addImage, writableWidthEmu } from './InlinePicture.mjs';
20
+ import { contentOf } from './ooxml.mjs';
21
+ import { commentApi } from './comments.mjs';
22
+ import { copyRPr, markDeleted, toDeletedText } from './tracking.mjs';
23
+ import { trackedChangesOfParagraph } from './TrackedChange.mjs';
24
+ import { isListItem, listOf, listOrNullObjectOf, listItemOf, listItemOrNullObjectOf, startNewList, attachToList, detachFromList, } from './List.mjs';
12
25
  const TWIPS_PER_POINT = 20;
13
26
  /**
14
27
  * A subset of Office JS `Word.Paragraph` over a `w:p` in a body, cell, header, footer or
@@ -42,64 +55,111 @@ export class Paragraph {
42
55
  /** Replaces the content with one run of the text, keeping the first run's formatting. */
43
56
  set text(value) {
44
57
  var _a;
58
+ if (this.changeTracker) {
59
+ this.splice(0, this.text.length, value);
60
+ return;
61
+ }
45
62
  const rPr = (_a = runsOf(this.p)[0]) === null || _a === void 0 ? void 0 : _a.value.rPr;
46
63
  this.p.content = [withRPr(textRun(value), rPr ? deepCopy(rPr) : undefined)];
47
64
  linkParents(this.p.content, this.p);
48
65
  }
49
- /** The style id (w:pStyle); 'Normal' when none is set. */
50
- get style() {
66
+ /**
67
+ * The text in one of the two views (extension; `text` is the accepted one). `{ view: 'original' }`
68
+ * reads the document as it was before the tracked changes: `w:del` included, `w:ins` excluded.
69
+ */
70
+ getText(options) {
71
+ return (options === null || options === void 0 ? void 0 : options.view) === 'original' ? textOfView(this.p, options) : this.text;
72
+ }
73
+ /** The style id (w:pStyle; docx4j's name for it); 'Normal' when none is set. Extension: Office JS has `style` and `styleBuiltIn` only. */
74
+ get styleId() {
51
75
  var _a, _b, _c;
52
76
  return (_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val) !== null && _c !== void 0 ? _c : 'Normal';
53
77
  }
54
- set style(id) {
78
+ set styleId(id) {
79
+ // through pPr(), so that a tracked write records w:pPrChange first (CR-002 phase F)
80
+ const pPr = this.pPr();
55
81
  if (id === '' || id === 'Normal') {
56
- if (this.p.pPr)
57
- delete this.p.pPr.pStyle;
82
+ delete pPr.pStyle;
58
83
  return;
59
84
  }
60
- this.pPr().pStyle = { val: id };
85
+ pPr.pStyle = { val: id };
86
+ }
87
+ /**
88
+ * The style's display name ('Heading 1', 'My Style'), as Office JS: from the styles part's
89
+ * `w:name` when that part is unmarshalled, else derived from the id. Setting accepts a display
90
+ * name, a stored name, or an id.
91
+ */
92
+ get style() {
93
+ return styleNameOf(this.parentBody.package_, this.styleId);
94
+ }
95
+ set style(name) {
96
+ this.styleId = styleIdOf(this.parentBody.package_, name);
61
97
  }
62
- /** Word's display name of the style ('Heading 1'); mapped to and from ids by removing spaces. */
98
+ /** The `Word.Style` value ('Heading1'), or 'Other' when the style is not a built-in one, as Office JS. */
63
99
  get styleBuiltIn() {
64
- return this.style.replace(/(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Za-z])(?=[0-9])/g, ' ');
100
+ return builtInOf(this.styleId);
101
+ }
102
+ set styleBuiltIn(value) {
103
+ this.styleId = idOfBuiltIn(value);
65
104
  }
66
- set styleBuiltIn(name) {
67
- this.style = name.replace(/\s+/g, '');
105
+ /**
106
+ * The paragraph properties which actually apply: the document defaults, the style chain and
107
+ * the numbering level, then this paragraph's own `w:pPr` (docx4j
108
+ * `PropertyResolver.getEffectivePPr`). A live, possibly cached object: copy it before
109
+ * changing it. Needs the package's resolver; see `Body.propertyResolver`.
110
+ */
111
+ get effectivePPr() {
112
+ return this.parentBody.propertyResolver.getEffectivePPr(this.p.pPr);
113
+ }
114
+ /** The paragraph mark's effective run properties (docx4j `getEffectiveParagraphMarkRPr`). */
115
+ get effectiveParagraphMarkRPr() {
116
+ return this.parentBody.propertyResolver.getEffectiveParagraphMarkRPr(this.p.pPr);
117
+ }
118
+ /** The `w:pPr` a formatting read works from: the resolved one, or this paragraph's own. */
119
+ readPPr(options) {
120
+ return (options === null || options === void 0 ? void 0 : options.direct) === true ? this.p.pPr : this.effectivePPr;
121
+ }
122
+ /**
123
+ * Office JS's paragraph formatting in one call, and the way to ask for direct formatting:
124
+ * `formatting({ direct: true })` is what the individual getters reported before CR-001
125
+ * Phase B step 2 (an absent property reads 0, 10 or `'Unknown'`).
126
+ */
127
+ formatting(options) {
128
+ var _a, _b, _c, _d, _e, _f, _g, _h;
129
+ const pPr = this.readPPr(options);
130
+ const effective = (options === null || options === void 0 ? void 0 : options.direct) !== true;
131
+ return {
132
+ alignment: alignmentOf(pPr, effective),
133
+ leftIndent: ((_b = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.ind) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT,
134
+ rightIndent: ((_d = (_c = pPr === null || pPr === void 0 ? void 0 : pPr.ind) === null || _c === void 0 ? void 0 : _c.right) !== null && _d !== void 0 ? _d : 0) / TWIPS_PER_POINT,
135
+ firstLineIndent: firstLineIndentOf(pPr),
136
+ spaceBefore: ((_f = (_e = pPr === null || pPr === void 0 ? void 0 : pPr.spacing) === null || _e === void 0 ? void 0 : _e.before) !== null && _f !== void 0 ? _f : 0) / TWIPS_PER_POINT,
137
+ spaceAfter: ((_h = (_g = pPr === null || pPr === void 0 ? void 0 : pPr.spacing) === null || _g === void 0 ? void 0 : _g.after) !== null && _h !== void 0 ? _h : 0) / TWIPS_PER_POINT,
138
+ lineSpacing: lineSpacingOf(pPr),
139
+ outlineLevel: outlineLevelOf(pPr),
140
+ };
68
141
  }
142
+ /** The effective alignment; an absent `w:jc` after resolution is `'Left'`, as Office JS. */
69
143
  get alignment() {
70
- var _a, _b;
71
- switch ((_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.jc) === null || _b === void 0 ? void 0 : _b.val) {
72
- case 'left':
73
- case 'start': return 'Left';
74
- case 'center': return 'Centered';
75
- case 'right':
76
- case 'end': return 'Right';
77
- case 'both':
78
- case 'distribute': return 'Justified';
79
- default: return 'Unknown';
80
- }
144
+ return alignmentOf(this.effectivePPr, true);
81
145
  }
82
146
  set alignment(v) {
147
+ const pPr = this.pPr();
83
148
  const val = v === 'Left' ? 'left' : v === 'Centered' ? 'center' : v === 'Right' ? 'right' : v === 'Justified' ? 'both' : undefined;
84
149
  if (val === undefined) {
85
- if (this.p.pPr)
86
- delete this.p.pPr.jc;
150
+ delete pPr.jc;
87
151
  return;
88
152
  }
89
- this.pPr().jc = { val };
153
+ pPr.jc = { val };
90
154
  }
91
- /** Indents and spacing in points, as Office JS; 0 when not set directly. */
92
- get leftIndent() { var _a, _b, _c; return ((_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.ind) === null || _b === void 0 ? void 0 : _b.left) !== null && _c !== void 0 ? _c : 0) / TWIPS_PER_POINT; }
155
+ /** Indents and spacing in points, as Office JS; the effective values (CR-001 Phase B step 2). */
156
+ get leftIndent() { var _a, _b; return ((_b = (_a = this.effectivePPr.ind) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
93
157
  set leftIndent(pt) { this.ind().left = Math.round(pt * TWIPS_PER_POINT); }
94
- get rightIndent() { var _a, _b, _c; return ((_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.ind) === null || _b === void 0 ? void 0 : _b.right) !== null && _c !== void 0 ? _c : 0) / TWIPS_PER_POINT; }
158
+ get rightIndent() { var _a, _b; return ((_b = (_a = this.effectivePPr.ind) === null || _a === void 0 ? void 0 : _a.right) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
95
159
  set rightIndent(pt) { this.ind().right = Math.round(pt * TWIPS_PER_POINT); }
96
160
  /** First-line indent; negative for a hanging indent, as Office JS. */
97
161
  get firstLineIndent() {
98
- var _a, _b;
99
- const ind = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.ind;
100
- if ((ind === null || ind === void 0 ? void 0 : ind.hanging) !== undefined)
101
- return -ind.hanging / TWIPS_PER_POINT;
102
- return ((_b = ind === null || ind === void 0 ? void 0 : ind.firstLine) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT;
162
+ return firstLineIndentOf(this.effectivePPr);
103
163
  }
104
164
  set firstLineIndent(pt) {
105
165
  const ind = this.ind();
@@ -112,30 +172,34 @@ export class Paragraph {
112
172
  delete ind.hanging;
113
173
  }
114
174
  }
115
- get spaceBefore() { var _a, _b, _c; return ((_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.spacing) === null || _b === void 0 ? void 0 : _b.before) !== null && _c !== void 0 ? _c : 0) / TWIPS_PER_POINT; }
175
+ get spaceBefore() { var _a, _b; return ((_b = (_a = this.effectivePPr.spacing) === null || _a === void 0 ? void 0 : _a.before) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
116
176
  set spaceBefore(pt) { this.spacing().before = Math.round(pt * TWIPS_PER_POINT); }
117
- get spaceAfter() { var _a, _b, _c; return ((_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.spacing) === null || _b === void 0 ? void 0 : _b.after) !== null && _c !== void 0 ? _c : 0) / TWIPS_PER_POINT; }
177
+ get spaceAfter() { var _a, _b; return ((_b = (_a = this.effectivePPr.spacing) === null || _a === void 0 ? void 0 : _a.after) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
118
178
  set spaceAfter(pt) { this.spacing().after = Math.round(pt * TWIPS_PER_POINT); }
119
179
  /** Line spacing in points: w:line/240 lines of 12pt when the rule is auto, else w:line twips; 0 when not set. */
120
180
  get lineSpacing() {
121
- var _a;
122
- const s = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.spacing;
123
- if ((s === null || s === void 0 ? void 0 : s.line) === undefined)
124
- return 0;
125
- return s.lineRule === undefined || s.lineRule === 'auto' ? (s.line / 240) * 12 : s.line / TWIPS_PER_POINT;
181
+ return lineSpacingOf(this.effectivePPr);
126
182
  }
127
183
  set lineSpacing(pt) { const s = this.spacing(); s.line = Math.round(pt * TWIPS_PER_POINT); s.lineRule = 'exact'; }
128
- /** w:outlineLvl + 1 (1 to 9); 10 for body text, as Office JS. */
129
- get outlineLevel() { var _a, _b; const l = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.outlineLvl) === null || _b === void 0 ? void 0 : _b.val; return l === undefined ? 10 : l + 1; }
130
- set outlineLevel(level) { if (level >= 10 || level < 1) {
131
- if (this.p.pPr)
132
- delete this.p.pPr.outlineLvl;
133
- }
184
+ /** w:outlineLvl + 1 (1 to 9); 10 for body text, as Office JS. A heading style supplies it. */
185
+ get outlineLevel() { return outlineLevelOf(this.effectivePPr); }
186
+ set outlineLevel(level) { const pPr = this.pPr(); if (level >= 10 || level < 1)
187
+ delete pPr.outlineLvl;
134
188
  else
135
- this.pPr().outlineLvl = { val: level - 1 }; }
136
- /** Direct formatting of the runs: reads the first run, writes all (extension: `Font` is over runs, not the paragraph mark). */
189
+ pPr.outlineLvl = { val: level - 1 }; }
190
+ /**
191
+ * The runs' formatting: reads the first run's *effective* properties, writes direct
192
+ * formatting to all (extension: `Font` is over runs, not the paragraph mark).
193
+ */
137
194
  get font() {
138
- return new Font(() => runsOf(this.p).map((r) => r.value));
195
+ return this.getFont();
196
+ }
197
+ /** `font`, with `{ direct: true }` for the direct formatting of the first run (extension). */
198
+ getFont(options) {
199
+ const holders = () => runsOf(this.p).map((r) => r.value);
200
+ if ((options === null || options === void 0 ? void 0 : options.direct) === true)
201
+ return new Font(holders, () => this.fontTracking());
202
+ return new Font(holders, () => this.fontTracking(), (rPr) => this.parentBody.propertyResolver.getEffectiveRPr(rPr, this.p.pPr), (rPr) => { var _a; return (_a = runFontSelectorOf(this.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
139
203
  }
140
204
  /** w14:paraId, the stable address Word gives paragraphs. */
141
205
  get paraId() {
@@ -151,6 +215,32 @@ export class Paragraph {
151
215
  get runs() {
152
216
  return runsOf(this.p);
153
217
  }
218
+ /** The cell this paragraph is in, or undefined when it is not in a table (Office JS). */
219
+ get parentTableCell() {
220
+ return cellOf(this.p, this.parentBody);
221
+ }
222
+ /** The run-level content controls in this paragraph, in order, nested ones included. */
223
+ get contentControls() {
224
+ const out = [];
225
+ collectRunControls(this.p, this.parentBody, out);
226
+ return out;
227
+ }
228
+ /** The inline pictures in this paragraph, in order (Office JS Paragraph.inlinePictures). */
229
+ get inlinePictures() {
230
+ var _a, _b;
231
+ const out = [];
232
+ for (const run of runsOf(this.p)) {
233
+ for (const item of ((_a = run.value.content) !== null && _a !== void 0 ? _a : [])) {
234
+ if (item.name.localPart !== 'drawing')
235
+ continue;
236
+ const inline = (_b = item.value.anchorOrInline) === null || _b === void 0 ? void 0 : _b[0];
237
+ if (inline && inline.TYPE_NAME === 'org_docx4j_dml_wordprocessingDrawing.Inline') {
238
+ out.push(new InlinePicture(item, run, this));
239
+ }
240
+ }
241
+ }
242
+ return out;
243
+ }
154
244
  /** Text inserted at the start, the end, or replacing the whole paragraph's text. */
155
245
  insertText(text, location) {
156
246
  const length = this.text.length;
@@ -166,6 +256,7 @@ export class Paragraph {
166
256
  if (pPr) {
167
257
  delete pPr.rPr;
168
258
  delete pPr.sectPr;
259
+ delete pPr.pPrChange;
169
260
  }
170
261
  const el = paragraphOf(text === '' ? [] : [textRun(text)], pPr);
171
262
  return this.parentBody.insertElement(el, location, this);
@@ -176,22 +267,92 @@ export class Paragraph {
176
267
  const brk = breakItem(type === 'Page' ? 'page' : undefined);
177
268
  if (location === 'Before' || location === 'After') {
178
269
  const p = this.insertParagraph('', location);
179
- p.p.content.push(runOf([brk]));
180
- linkParents(p.p.content, p.p);
270
+ const run = runOf([brk]);
271
+ const tracker = p.changeTracker;
272
+ const item = tracker ? tracker.ins([run]) : run;
273
+ p.p.content.push(item);
274
+ linkParents(item, p.p);
181
275
  return;
182
276
  }
183
277
  const run = runOf([brk]);
278
+ const tracker = this.changeTracker;
279
+ const item = tracker ? tracker.ins([run]) : run;
184
280
  const content = ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
281
+ if (location === 'Start')
282
+ content.unshift(item);
283
+ else
284
+ content.push(item);
285
+ linkParents(item, this.p);
286
+ }
287
+ /**
288
+ * Adds the image as a part of this paragraph's part, with a relationship, and shows it at the
289
+ * start or the end of this paragraph, or in place of its content (Office JS).
290
+ */
291
+ insertInlinePictureFromBase64(base64, location, options) {
292
+ var _a;
293
+ var _b;
294
+ const part = this.parentBody.part;
295
+ if (!part)
296
+ throw new Docx4JException('This body has no part, so an image cannot be related to it');
297
+ const { run, drawing } = addImage(part, base64, this.parentBody.container, writableWidthEmu(this.parentBody.container), options);
298
+ const content = ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
299
+ if (location === 'Replace')
300
+ content.length = 0;
185
301
  if (location === 'Start')
186
302
  content.unshift(run);
187
303
  else
188
304
  content.push(run);
189
305
  linkParents(run, this.p);
306
+ return new InlinePicture(drawing, run, this);
307
+ }
308
+ /**
309
+ * Word's `insertOoxml` at paragraph level: a flat OPC `pkg:package` (or a bare fragment). One
310
+ * incoming paragraph is merged into this one at 'Start' and 'End', as Word's paste does;
311
+ * anything else is inserted as blocks before or after. 'Replace' puts the content where this
312
+ * paragraph was and removes it.
313
+ */
314
+ async insertOoxml(ooxml, location) {
315
+ var _a, _b;
316
+ const preprocess = (_a = this.parentBody.package_) === null || _a === void 0 ? void 0 : _a.loadOptions.preprocessor;
317
+ const elements = await contentOf(ooxml, { preprocess: preprocess ? (doc) => preprocess(doc) : undefined, target: this.parentBody.part });
318
+ if (elements.length === 0)
319
+ return [];
320
+ const only = elements.length === 1 && typeNameOf(elements[0]) === 'org_docx4j_wml.P' ? elements[0].value : undefined;
321
+ if (only && (location === 'Start' || location === 'End')) {
322
+ this.insertItemsAt(location === 'Start' ? 0 : this.text.length, ((_b = only.content) !== null && _b !== void 0 ? _b : []));
323
+ return [this];
324
+ }
325
+ if (location === 'Replace') {
326
+ const inserted = this.parentBody.insertElement(elements, 'Before', this);
327
+ void inserted;
328
+ this.delete();
329
+ }
330
+ else {
331
+ this.parentBody.insertElement(elements, location === 'Start' ? 'Before' : location === 'End' ? 'After' : location, this);
332
+ }
333
+ return elements.map((el) => typeNameOf(el) === 'org_docx4j_wml.P'
334
+ ? new Paragraph(el, this.container, this.parentBody)
335
+ : { element: el, container: this.container });
190
336
  }
191
337
  /** Matches within this paragraph. */
192
338
  search(text, options) {
193
339
  return findAll(this.text, searchPattern(text, options)).map(([s, e]) => new Range(this, s, e));
194
340
  }
341
+ /**
342
+ * Replaces every match of `find` with `replace`, last match first so that the offsets of the
343
+ * ones still to do stay valid (CR-002 section 3.7). Returns the number replaced; tracked when
344
+ * the package's `changeTrackingMode` is on.
345
+ */
346
+ replaceText(find, replace, options) {
347
+ const matches = this.search(find, options);
348
+ for (let i = matches.length - 1; i >= 0; i--)
349
+ matches[i].insertText(replace, 'Replace');
350
+ return matches.length;
351
+ }
352
+ /** The tracked changes in this paragraph, in document order (CR-002 phase F). */
353
+ getTrackedChanges() {
354
+ return trackedChangesOfParagraph(this);
355
+ }
195
356
  getRange(location = 'Whole') {
196
357
  const length = this.text.length;
197
358
  if (location === 'Start')
@@ -200,12 +361,53 @@ export class Paragraph {
200
361
  return new Range(this, length, length);
201
362
  return new Range(this, 0, length);
202
363
  }
203
- /** Removes the paragraph from its container. */
364
+ /**
365
+ * Removes the paragraph from its container. While the package tracks changes, the content
366
+ * becomes a `w:del` and the mark is marked deleted (`w:pPr/w:rPr/w:del`) instead, unless the
367
+ * whole paragraph was this author's own insertion, which Word simply takes back.
368
+ */
204
369
  delete() {
370
+ const tracker = this.changeTracker;
371
+ if (tracker) {
372
+ this.trackedDelete(tracker);
373
+ return;
374
+ }
205
375
  const i = this.index;
206
376
  if (i >= 0)
207
377
  this.container.splice(i, 1);
208
378
  }
379
+ trackedDelete(tracker) {
380
+ var _a, _b;
381
+ if (markDeleted(this.p))
382
+ throw new Docx4JException('This paragraph is already marked deleted');
383
+ const length = this.text.length;
384
+ if (length > 0)
385
+ this.deleteText(tracker, 0, length);
386
+ const rPr = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.rPr;
387
+ const ownMark = (rPr === null || rPr === void 0 ? void 0 : rPr.ins) !== undefined && rPr.ins.author === tracker.author;
388
+ if (ownMark && ((_b = this.p.content) !== null && _b !== void 0 ? _b : []).length === 0) {
389
+ const i = this.index;
390
+ if (i >= 0)
391
+ this.container.splice(i, 1);
392
+ return;
393
+ }
394
+ tracker.markParagraphDeleted(this.p);
395
+ }
396
+ /**
397
+ * The paragraph's content and its mark marked deleted, the paragraph element itself kept:
398
+ * what the cells of a deleted table row need (a `w:tc` must keep a block-level child, and Word
399
+ * writes `w:del` around every run and `w:pPr/w:rPr/w:del` on every mark inside a deleted row).
400
+ * The same primitives `delete()` uses, without its "take back my own insertion" step.
401
+ * Does nothing when the mark is already deleted.
402
+ */
403
+ markDeletedInPlace(tracker) {
404
+ if (markDeleted(this.p))
405
+ return;
406
+ const length = this.text.length;
407
+ if (length > 0)
408
+ this.deleteText(tracker, 0, length);
409
+ tracker.markParagraphDeleted(this.p);
410
+ }
209
411
  /** The paragraph as XML (extension; Office JS getOoxml wraps it in a package). */
210
412
  getXml() {
211
413
  return marshalString(this.element);
@@ -218,10 +420,33 @@ export class Paragraph {
218
420
  return ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
219
421
  }
220
422
  // --- editing primitives, shared with Range ---
423
+ /**
424
+ * The paragraph's properties, created when absent. Every property setter goes through this
425
+ * one accessor, so this is where a tracked write records `w:pPrChange` with the properties as
426
+ * they stand before it.
427
+ *
428
+ * @internal public so that the list views (CR-002 phase H) write `w:numPr` the same way.
429
+ */
221
430
  pPr() {
431
+ var _a, _b;
432
+ var _c;
433
+ const pPr = ((_a = (_c = this.p).pPr) !== null && _a !== void 0 ? _a : (_c.pPr = { TYPE_NAME: 'org_docx4j_wml.PPr' }));
434
+ linkParents(pPr, this.p);
435
+ (_b = this.changeTracker) === null || _b === void 0 ? void 0 : _b.recordPPrChange(pPr);
436
+ return pPr;
437
+ }
438
+ /**
439
+ * The paragraph's `w:numPr`, created when absent, through {@link pPr} so that a tracked
440
+ * write records `w:pPrChange` first.
441
+ *
442
+ * @internal what the list views write through (CR-002 phase H).
443
+ */
444
+ numPr() {
222
445
  var _a;
223
- var _b;
224
- return ((_a = (_b = this.p).pPr) !== null && _a !== void 0 ? _a : (_b.pPr = { TYPE_NAME: 'org_docx4j_wml.PPr' }));
446
+ const pPr = this.pPr();
447
+ const numPr = ((_a = pPr.numPr) !== null && _a !== void 0 ? _a : (pPr.numPr = { TYPE_NAME: 'org_docx4j_wml.PPrBase.NumPr' }));
448
+ linkParents(numPr, pPr);
449
+ return numPr;
225
450
  }
226
451
  ind() {
227
452
  var _a;
@@ -233,9 +458,24 @@ export class Paragraph {
233
458
  var _b;
234
459
  return ((_a = (_b = this.pPr()).spacing) !== null && _a !== void 0 ? _a : (_b.spacing = {}));
235
460
  }
461
+ /** The package's change tracker while `changeTrackingMode` is on; undefined when it is off. */
462
+ get changeTracker() {
463
+ return this.parentBody.changeTracker;
464
+ }
465
+ /** What `Font` needs to write `w:rPrChange`: the tracker, and the runs that are our own insertion (`Range` shares it). */
466
+ fontTracking() {
467
+ const tracker = this.changeTracker;
468
+ if (!tracker)
469
+ return undefined;
470
+ const ownInsertions = new Set();
471
+ for (const seg of this.segments())
472
+ if (tracker.ownInsertion(seg.revision))
473
+ ownInsertions.add(seg.run);
474
+ return { tracker, ownInsertions };
475
+ }
236
476
  /** The text segments (w:t, w:tab, ...) with their offsets. */
237
- segments() {
238
- return segmentsOf(this.p);
477
+ segments(options) {
478
+ return segmentsOf(this.p, options);
239
479
  }
240
480
  /**
241
481
  * Replaces the text in [start, end) with `text` and returns the range of the inserted text.
@@ -249,6 +489,14 @@ export class Paragraph {
249
489
  const length = this.text.length;
250
490
  start = Math.max(0, Math.min(start, length));
251
491
  end = Math.max(start, Math.min(end, length));
492
+ const tracker = this.changeTracker;
493
+ if (tracker) {
494
+ // a replacement is the w:del first and the w:ins after it, as Word writes one
495
+ const deletions = end > start ? this.deleteText(tracker, start, end) : [];
496
+ if (text.length > 0)
497
+ this.insertTracked(tracker, start, text, deletions[deletions.length - 1]);
498
+ return new Range(this, start, start + text.length);
499
+ }
252
500
  let segs = this.segments();
253
501
  let inserted = false;
254
502
  if (end > start) {
@@ -323,6 +571,27 @@ export class Paragraph {
323
571
  }
324
572
  return new Range(this, start, start + text.length);
325
573
  }
574
+ /**
575
+ * Inserts run-level items (runs, hyperlinks, content controls) at a text offset, splitting the
576
+ * run there when the offset falls inside one. PARENT is linked on what is inserted.
577
+ */
578
+ insertItemsAt(offset, items) {
579
+ var _a, _b, _c;
580
+ var _d;
581
+ if (items.length === 0)
582
+ return;
583
+ this.splitAt(offset);
584
+ const segs = this.segments();
585
+ const after = segs.find((s) => s.start >= offset);
586
+ const before = [...segs].reverse().find((s) => s.end <= offset);
587
+ const neighbour = after !== null && after !== void 0 ? after : before;
588
+ const list = neighbour ? neighbour.runOwner : ((_a = (_d = this.p).content) !== null && _a !== void 0 ? _a : (_d.content = []));
589
+ const at = neighbour ? (after ? neighbour.runIndex : neighbour.runIndex + 1) : (offset === 0 ? 0 : list.length);
590
+ list.splice(at, 0, ...items);
591
+ const owner = (_c = (_b = neighbour === null || neighbour === void 0 ? void 0 : neighbour.run) === null || _b === void 0 ? void 0 : _b.PARENT) !== null && _c !== void 0 ? _c : this.p;
592
+ for (const item of items)
593
+ linkParents(item, owner);
594
+ }
326
595
  /** Splits the run at a text offset so that [offset, ...) begins a run; returns nothing when the offset is already a boundary. */
327
596
  splitAt(offset) {
328
597
  var _a;
@@ -341,6 +610,87 @@ export class Paragraph {
341
610
  seg.runOwner.splice(seg.runIndex + 1, 0, second);
342
611
  linkParents(second, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
343
612
  }
613
+ // --- lists (CR-002 phase H) ---
614
+ /**
615
+ * Office JS `paragraph.isListItem`: whether Word paints a label in front of this paragraph.
616
+ * The effective `w:numPr` decides it (docx4j `Emulator.numRefFor`), so a "List Number" style
617
+ * counts; a `w:numId` of 0, a `w:numId` naming no `w:num`, and a level linked to another
618
+ * paragraph style do not.
619
+ */
620
+ get isListItem() {
621
+ return isListItem(this);
622
+ }
623
+ /** Office JS `paragraph.list`: the list this paragraph is in; throws when it is not in one. */
624
+ get list() {
625
+ return listOf(this);
626
+ }
627
+ /** Office JS `paragraph.listOrNullObject`: the list, or a null object (`isNullObject` true). */
628
+ get listOrNullObject() {
629
+ return listOrNullObjectOf(this);
630
+ }
631
+ /** Office JS `paragraph.listItem`: this paragraph's place in its list; throws when it has none. */
632
+ get listItem() {
633
+ return listItemOf(this);
634
+ }
635
+ /** Office JS `paragraph.listItemOrNullObject`. */
636
+ get listItemOrNullObject() {
637
+ return listItemOrNullObjectOf(this);
638
+ }
639
+ /**
640
+ * Office JS `paragraph.startNewList()`: a new list definition (docx4j's default decimal set,
641
+ * or its bullet set with `{ bullet: true }`) with this paragraph as its first item, adding
642
+ * the numbering part and its relationship when the document has none.
643
+ *
644
+ * Asynchronous where Office JS's is synchronous, since the default definitions are XML to be
645
+ * unmarshalled (CR-002 section 17).
646
+ */
647
+ startNewList(options) {
648
+ return startNewList(this, options);
649
+ }
650
+ /** Office JS `paragraph.attachToList(listId, level)`: this paragraph joins that list. */
651
+ attachToList(listId, level = 0) {
652
+ return attachToList(this, listId, level);
653
+ }
654
+ /** Office JS `paragraph.detachFromList()`: this paragraph leaves its list. */
655
+ detachFromList() {
656
+ detachFromList(this);
657
+ }
658
+ /**
659
+ * The same list, starting again at this paragraph: a new `w:num` over the same
660
+ * `w:abstractNum` with a `w:startOverride` (extension; `List.restart()` is the verb).
661
+ */
662
+ restartList() {
663
+ const list = this.list;
664
+ const level = this.listItem.level;
665
+ const restarted = list.restart();
666
+ this.attachToList(restarted.id, level);
667
+ return restarted;
668
+ }
669
+ // --- comments (CR-002 phase G) ---
670
+ /** The comments anchored in this paragraph, replies nested under their parent. */
671
+ async getComments() {
672
+ return commentApi().commentsOf(this);
673
+ }
674
+ /** Comments the whole paragraph (sugar over `getRange().insertComment`). */
675
+ async insertComment(text) {
676
+ return commentApi().insertComment(this.getRange(), text);
677
+ }
678
+ // --- content controls (CR-002 phase E) ---
679
+ /**
680
+ * Wraps this paragraph in a new block-level content control (Office JS
681
+ * `Paragraph.insertContentControl`), typed for the kind when one is given. The `w:id` is free in
682
+ * the body. Returns the control.
683
+ */
684
+ insertContentControl(kind) {
685
+ var _a;
686
+ const at = this.index;
687
+ if (at < 0)
688
+ throw new Docx4JException('This paragraph is not in its container any more');
689
+ const sdt = sdtOf([this.element], { kind: sdtKindFor(kind), id: nextSdtId(controlIdScope(this.parentBody)), form: 'block' });
690
+ this.container.splice(at, 1, sdt);
691
+ linkParents(sdt, (_a = this.p.PARENT) !== null && _a !== void 0 ? _a : this.parentBody.container);
692
+ return new ContentControl(sdt, this.container, this.parentBody);
693
+ }
344
694
  removeEmptyRuns() {
345
695
  var _a;
346
696
  const prune = (items) => {
@@ -353,12 +703,216 @@ export class Paragraph {
353
703
  }
354
704
  else if (v.TYPE_NAME !== 'org_docx4j_wml.P') {
355
705
  const nested = runItemsOf(v);
356
- if (nested)
706
+ if (nested) {
357
707
  prune(nested);
708
+ // a revision left with nothing in it goes too
709
+ if (nested.length === 0 && revisionKindOf(el) !== undefined)
710
+ items.splice(i, 1);
711
+ }
358
712
  }
359
713
  }
360
714
  };
361
715
  prune((_a = this.p.content) !== null && _a !== void 0 ? _a : []);
362
716
  }
717
+ // --- tracked editing (CR-002 phase F) ---------------------------------------------------
718
+ /**
719
+ * The text in [start, end) becomes a deletion: the runs holding it are isolated, their `w:t`
720
+ * turned into `w:delText`, and each run of consecutive ones moved into one `w:del`. Text this
721
+ * author had inserted is simply removed, as Word does, rather than nested in a `w:del`.
722
+ * Returns the `w:del` elements it made, in document order.
723
+ */
724
+ deleteText(tracker, start, end) {
725
+ var _a, _b, _c, _d, _e, _f;
726
+ const targets = this.isolate(start, end);
727
+ for (const seg of targets)
728
+ tracker.assertEditable(seg.revision);
729
+ const list = [];
730
+ for (const seg of targets) {
731
+ const run = seg.runOwner[seg.runIndex];
732
+ if (list.length > 0 && list[list.length - 1].run === run)
733
+ continue;
734
+ const target = { run, owner: seg.runOwner, own: tracker.ownInsertion(seg.revision) };
735
+ if (seg.revision)
736
+ target.revision = seg.revision;
737
+ list.push(target);
738
+ }
739
+ // groups of consecutive runs in the same array, so that one w:del holds them all
740
+ const groups = [];
741
+ for (const t of list) {
742
+ const last = groups[groups.length - 1];
743
+ const previous = last === null || last === void 0 ? void 0 : last[last.length - 1];
744
+ if (last && previous && previous.own === t.own && previous.owner === t.owner
745
+ && t.owner.indexOf(t.run) === t.owner.indexOf(previous.run) + 1)
746
+ last.push(t);
747
+ else
748
+ groups.push([t]);
749
+ }
750
+ const made = [];
751
+ for (let g = groups.length - 1; g >= 0; g--) {
752
+ const group = groups[g];
753
+ const owner = group[0].owner;
754
+ const at = owner.indexOf(group[0].run);
755
+ const runs = owner.splice(at, group.length);
756
+ if (group[0].own) {
757
+ // taking back our own insertion: the runs go, and an emptied w:ins with them
758
+ const revision = group[0].revision;
759
+ if (revision && revision.items.length === 0) {
760
+ const i = revision.owner.indexOf(revision.element);
761
+ if (i >= 0)
762
+ revision.owner.splice(i, 1);
763
+ }
764
+ continue;
765
+ }
766
+ for (const run of runs)
767
+ toDeletedText(run.value);
768
+ const del = tracker.del(runs);
769
+ owner.splice(at, 0, del);
770
+ linkParents(del, ((_c = (_b = (_a = group[0].revision) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : group[0].run.value.PARENT) !== null && _c !== void 0 ? _c : this.p));
771
+ made.unshift({ owner, element: del, parent: ((_f = (_e = (_d = group[0].revision) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : del.value.PARENT) !== null && _f !== void 0 ? _f : this.p) });
772
+ }
773
+ return made;
774
+ }
775
+ /**
776
+ * Text inserted at `at` as a `w:ins`. A run of this author's own that is already inside a
777
+ * `w:ins` is extended rather than nested in another one, as Word does. `anchor` is the `w:del`
778
+ * of a replacement, which the insertion must follow.
779
+ */
780
+ insertTracked(tracker, at, text, anchor) {
781
+ var _a, _b, _c, _d, _e;
782
+ var _f;
783
+ if (anchor) {
784
+ const rPr = copyRPr((_a = runsOf(anchor.element.value, { view: 'original' })[0]) === null || _a === void 0 ? void 0 : _a.value.rPr);
785
+ const ins = tracker.ins([runOf([textItem(text)], rPr)]);
786
+ anchor.owner.splice(anchor.owner.indexOf(anchor.element) + 1, 0, ins);
787
+ linkParents(ins, anchor.parent);
788
+ return;
789
+ }
790
+ this.splitAt(at);
791
+ const segs = this.segments();
792
+ const before = [...segs].reverse().find((s) => s.end <= at);
793
+ const after = segs.find((s) => s.start >= at);
794
+ for (const [seg, side] of [[before, 'after'], [after, 'before']]) {
795
+ if (!seg || !tracker.ownInsertion(seg.revision))
796
+ continue;
797
+ if (seg.editable) {
798
+ const t = seg.item.value;
799
+ t.value = side === 'after' ? seg.text + text : text + seg.text;
800
+ if (/^\s|\s$|\s\s/.test(t.value))
801
+ t.space = 'preserve';
802
+ }
803
+ else {
804
+ const run = runOf([textItem(text)], copyRPr(seg.run.rPr));
805
+ seg.runOwner.splice(side === 'after' ? seg.runIndex + 1 : seg.runIndex, 0, run);
806
+ linkParents(run, seg.revision.value);
807
+ }
808
+ return;
809
+ }
810
+ const neighbour = before !== null && before !== void 0 ? before : after;
811
+ tracker.assertEditable(neighbour === null || neighbour === void 0 ? void 0 : neighbour.revision);
812
+ const rPr = copyRPr((_b = neighbour === null || neighbour === void 0 ? void 0 : neighbour.run.rPr) !== null && _b !== void 0 ? _b : (_c = runsOf(this.p)[0]) === null || _c === void 0 ? void 0 : _c.value.rPr);
813
+ const ins = tracker.ins([runOf([textItem(text)], rPr)]);
814
+ if (neighbour) {
815
+ const owner = neighbour.revision ? neighbour.revision.owner : neighbour.runOwner;
816
+ const item = neighbour.revision ? neighbour.revision.element : neighbour.runOwner[neighbour.runIndex];
817
+ const parent = (neighbour.revision ? neighbour.revision.value : neighbour.run);
818
+ owner.splice(owner.indexOf(item) + (neighbour === before ? 1 : 0), 0, ins);
819
+ linkParents(ins, (_d = parent.PARENT) !== null && _d !== void 0 ? _d : this.p);
820
+ }
821
+ else {
822
+ const content = ((_e = (_f = this.p).content) !== null && _e !== void 0 ? _e : (_f.content = []));
823
+ if (at === 0)
824
+ content.unshift(ins);
825
+ else
826
+ content.push(ins);
827
+ linkParents(ins, this.p);
828
+ }
829
+ }
830
+ /**
831
+ * Splits runs so that every run holding text in [start, end) holds nothing else, and returns
832
+ * the segments inside the span. `splitAt` does the `w:t` boundaries; this also moves the items
833
+ * of a run that straddles a boundary (a tab, a break, a drawing) out into runs of their own.
834
+ */
835
+ isolate(start, end) {
836
+ this.splitAt(start);
837
+ this.splitAt(end);
838
+ for (let guard = 0; guard < 10000; guard++) {
839
+ const inside = this.segments().filter((s) => s.start >= start && s.end <= end && s.text.length > 0);
840
+ let split = false;
841
+ const seen = new Set();
842
+ for (const seg of inside) {
843
+ if (seen.has(seg.run))
844
+ continue;
845
+ seen.add(seg.run);
846
+ const ofRun = inside.filter((s) => s.run === seg.run);
847
+ const first = ofRun[0];
848
+ const last = ofRun[ofRun.length - 1];
849
+ if (first.index > 0) {
850
+ this.splitRunBefore(first);
851
+ split = true;
852
+ break;
853
+ }
854
+ if (last.index < last.owner.length - 1) {
855
+ this.splitRunAfter(last);
856
+ split = true;
857
+ break;
858
+ }
859
+ }
860
+ if (!split)
861
+ return inside;
862
+ }
863
+ return this.segments().filter((s) => s.start >= start && s.end <= end && s.text.length > 0);
864
+ }
865
+ /** Moves the items before `seg` into a run of their own, in front of `seg`'s run. */
866
+ splitRunBefore(seg) {
867
+ var _a;
868
+ const head = seg.owner.splice(0, seg.index);
869
+ const first = runOf(head, copyRPr(seg.run.rPr));
870
+ seg.runOwner.splice(seg.runIndex, 0, first);
871
+ linkParents(first, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
872
+ }
873
+ /** Moves the items after `seg` into a run of their own, behind `seg`'s run. */
874
+ splitRunAfter(seg) {
875
+ var _a;
876
+ const tail = seg.owner.splice(seg.index + 1);
877
+ if (tail.length === 0)
878
+ return;
879
+ const rest = runOf(tail, copyRPr(seg.run.rPr));
880
+ seg.runOwner.splice(seg.runIndex + 1, 0, rest);
881
+ linkParents(rest, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
882
+ }
363
883
  }
364
884
  export { W_NS };
885
+ // --- reading one w:pPr, direct or resolved -----------------------------------------------
886
+ function alignmentOf(pPr, effective) {
887
+ var _a;
888
+ switch ((_a = pPr === null || pPr === void 0 ? void 0 : pPr.jc) === null || _a === void 0 ? void 0 : _a.val) {
889
+ case 'left':
890
+ case 'start': return 'Left';
891
+ case 'center': return 'Centered';
892
+ case 'right':
893
+ case 'end': return 'Right';
894
+ case 'both':
895
+ case 'distribute': return 'Justified';
896
+ // Word lays a paragraph with no w:jc out left-aligned, so that is the effective value
897
+ default: return effective ? 'Left' : 'Unknown';
898
+ }
899
+ }
900
+ function firstLineIndentOf(pPr) {
901
+ var _a;
902
+ const ind = pPr === null || pPr === void 0 ? void 0 : pPr.ind;
903
+ if ((ind === null || ind === void 0 ? void 0 : ind.hanging) !== undefined)
904
+ return -ind.hanging / TWIPS_PER_POINT;
905
+ return ((_a = ind === null || ind === void 0 ? void 0 : ind.firstLine) !== null && _a !== void 0 ? _a : 0) / TWIPS_PER_POINT;
906
+ }
907
+ function lineSpacingOf(pPr) {
908
+ const spacing = pPr === null || pPr === void 0 ? void 0 : pPr.spacing;
909
+ if ((spacing === null || spacing === void 0 ? void 0 : spacing.line) === undefined)
910
+ return 0;
911
+ return spacing.lineRule === undefined || spacing.lineRule === 'auto'
912
+ ? (spacing.line / 240) * 12 : spacing.line / TWIPS_PER_POINT;
913
+ }
914
+ function outlineLevelOf(pPr) {
915
+ var _a;
916
+ const level = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.outlineLvl) === null || _a === void 0 ? void 0 : _a.val;
917
+ return level === undefined ? 10 : level + 1;
918
+ }