@docx4j/core-ts 0.2.2 → 0.3.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.
@@ -3,11 +3,12 @@ import { runFontSelectorOf } from '../fonts/lookup.mjs';
3
3
  import { typeNameOf, linkParents, runItemsOf, runsOf } from './tree.mjs';
4
4
  import { Docx4JException } from '../../opc/exceptions.mjs';
5
5
  import { ContentControl } from './ContentControl.mjs';
6
- import { sdt as sdtOf, nextSdtId, applyRunOptions } from '@docx4j/generated-objects-ts/builders/wml';
6
+ import { sdt as sdtOf, nextSdtId, applyRunOptions, t as textElement } from '@docx4j/generated-objects-ts/builders/wml';
7
7
  import { hyperlink as hyperlinkOf } from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
8
8
  import { Namespaces } from '../../parts/Namespaces.mjs';
9
9
  import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
10
10
  import { contentOf } from './ooxml.mjs';
11
+ import { markHolderInserted } from './tracking.mjs';
11
12
  import { searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
12
13
  import { commentApi } from './comments.mjs';
13
14
  /**
@@ -93,8 +94,10 @@ export class Range {
93
94
  let r;
94
95
  if (location === 'Replace')
95
96
  r = this.paragraph.splice(this.start, this.end, text);
97
+ // text put before the range joins the run the range starts in - inside the link the range is on,
98
+ // as Office JS (check 32: insertText('Before') on a link's text went into the link, as 'After' did)
96
99
  else if (location === 'Before' || location === 'Start')
97
- r = this.paragraph.splice(this.start, this.start, text);
100
+ r = this.paragraph.splice(this.start, this.start, text, 'after');
98
101
  else
99
102
  r = this.paragraph.splice(this.end, this.end, text);
100
103
  // this range keeps covering the same text: a replacement resizes it, text before it shifts it, text after it leaves it
@@ -206,7 +209,7 @@ export class Range {
206
209
  * span gets an empty control at its position. Returns the control.
207
210
  */
208
211
  insertContentControl(kind) {
209
- var _a;
212
+ var _a, _b;
210
213
  const paragraph = this.paragraph;
211
214
  const body = paragraph.parentBody;
212
215
  // The control is built empty first: `sdt` refuses a kind that cannot be run-level (a repeating
@@ -232,9 +235,49 @@ export class Range {
232
235
  items.push(element);
233
236
  }
234
237
  const at = owner.indexOf(items[0]);
238
+ const tracker = paragraph.changeTracker;
239
+ const revision = segments[0].revision;
240
+ if (tracker && revision) {
241
+ // The runs are in a revision: the control goes between its halves, not in it, and the runs go
242
+ // into the control in a revision of the same kind and attributes with a new id - Word's form for
243
+ // inserted text wrapped in a new control (check 30, inserted-text-wrapped: the w:ins inside the
244
+ // control, the control's own markers outside it).
245
+ const index = revision.items.indexOf(items[0]);
246
+ revision.items.splice(index, items.length);
247
+ const value = revision.value;
248
+ const itemsKey = Object.keys(value).find((key) => value[key] === revision.items);
249
+ const inner = {};
250
+ for (const [key, v] of Object.entries(value))
251
+ if (key !== itemsKey && key !== 'PARENT')
252
+ inner[key] = v;
253
+ inner.id = tracker.nextId();
254
+ inner[itemsKey] = items;
255
+ const wrapped = { name: revision.element.name, value: inner };
256
+ linkParents(items, inner);
257
+ sdt.value.sdtContent.content = [wrapped];
258
+ linkParents(wrapped, sdt.value.sdtContent);
259
+ const holderOwner = revision.owner;
260
+ const parent = (_a = revision.value.PARENT) !== null && _a !== void 0 ? _a : paragraph.p;
261
+ if (revision.items.length === 0) {
262
+ holderOwner.splice(holderOwner.indexOf(revision.element), 1, sdt); // the whole revision wrapped
263
+ linkParents(sdt, parent);
264
+ }
265
+ else if (index === 0) {
266
+ holderOwner.splice(holderOwner.indexOf(revision.element), 0, sdt); // its start wrapped
267
+ linkParents(sdt, parent);
268
+ }
269
+ else if (!paragraph.splitHolderAround(revision, index, sdt, () => tracker.nextId())) {
270
+ throw new Docx4JException('This range is in a revision that cannot be split around a content control');
271
+ }
272
+ markHolderInserted(tracker, sdt, holderOwner, () => { });
273
+ return new ContentControl(sdt, holderOwner, body);
274
+ }
235
275
  sdt.value.sdtContent.content = items;
236
276
  owner.splice(at, items.length, sdt);
237
- linkParents(sdt, (_a = segments[0].run.PARENT) !== null && _a !== void 0 ? _a : paragraph.p);
277
+ linkParents(sdt, (_b = segments[0].run.PARENT) !== null && _b !== void 0 ? _b : paragraph.p);
278
+ // under tracking the control itself is the insertion, the runs in it what they were (check 30)
279
+ if (tracker)
280
+ markHolderInserted(tracker, sdt, owner, () => { });
238
281
  return new ContentControl(sdt, owner, body);
239
282
  }
240
283
  /**
@@ -248,7 +291,9 @@ export class Range {
248
291
  * `w:hyperlink`, splitting runs at the boundaries as `font` and `insertContentControl` do;
249
292
  * setting `""` removes them and wraps nothing. An external address becomes a relationship of
250
293
  * this range's part, which is why the part must exist (CR-002 section 20). Only the hyperlinks
251
- * the range touches are removed; before 0.2.1 every one in the paragraph was (section 25).
294
+ * the range touches are removed; before 0.2.1 every one in the paragraph was (section 25). An
295
+ * empty range is refused with a `GeneralException`, as Office JS refuses it (section 25, check 19):
296
+ * to change a link under a caret, set it on the link's whole range.
252
297
  *
253
298
  * The runs are styled as Word styles them, measured through Office JS (`test/README.md` check
254
299
  * 15, CR-002 section 25): each run a link wraps takes the `Hyperlink` character style, over any
@@ -270,6 +315,13 @@ export class Range {
270
315
  }
271
316
  set hyperlink(value) {
272
317
  var _a, _b, _c;
318
+ // Office JS refuses a hyperlink set on an empty range - inside a link, in plain text, just after a
319
+ // link, and "" alike - with GeneralException, and changes nothing (test/README.md check 19, Word
320
+ // 16.0.20326.20158; CR-002 section 25). Before, the setter removed the link under a caret and
321
+ // left an empty w:hyperlink there.
322
+ if (this.start === this.end) {
323
+ throw new GeneralException('A hyperlink cannot be set on an empty range, as in Office JS: select the text to link, or the whole of a link to change it');
324
+ }
273
325
  const paragraph = this.paragraph;
274
326
  // A range that crosses the edge of a link takes the whole of that link into the new one; a range
275
327
  // inside a link replaces it with a link over the range alone. Measured in Word through Office JS
@@ -303,10 +355,6 @@ export class Range {
303
355
  holder.value.anchor = location;
304
356
  if (address !== '')
305
357
  holder.value.id = this.addHyperlinkRelationship(address);
306
- if (start === end) {
307
- paragraph.insertItemsAt(start, [holder]);
308
- return;
309
- }
310
358
  paragraph.splitAt(start);
311
359
  paragraph.splitAt(end);
312
360
  const segments = paragraph.segments().filter((seg) => seg.start >= start && seg.end <= end);
@@ -327,6 +375,7 @@ export class Range {
327
375
  owner.splice(at, items.length, holder);
328
376
  linkParents(holder, (_a = segments[0].run.PARENT) !== null && _a !== void 0 ? _a : paragraph.p);
329
377
  this.restyle(holder.value, true);
378
+ mergeTextRuns(holder.value.content, holder.value);
330
379
  (_c = (_b = paragraph.parentBody.package_) === null || _b === void 0 ? void 0 : _b.requireStyles) === null || _c === void 0 ? void 0 : _c.call(_b, [HYPERLINK_STYLE]);
331
380
  }
332
381
  /** The first `w:hyperlink` this range touches, if any. */
@@ -353,16 +402,16 @@ export class Range {
353
402
  }
354
403
  }
355
404
  /**
356
- * Whether this range touches a hyperlink's text: overlaps it, or for an empty range lies in it
357
- * (from its first character up to, not including, its end). A hyperlink holding no text touches
358
- * nothing.
405
+ * Whether this range touches a hyperlink's text: overlaps it, or for an empty range lies in it or
406
+ * at either end of it - Office JS reads a caret just after a link as in that link (check 19, case
407
+ * K; the start edge was not measured). A hyperlink holding no text touches nothing.
359
408
  */
360
409
  touches(holder) {
361
410
  const span = this.spanOf(holder);
362
411
  return span !== undefined && this.touchesSpan(span);
363
412
  }
364
413
  touchesSpan([start, end]) {
365
- return this.start === this.end ? start <= this.start && this.start < end : start < this.end && end > this.start;
414
+ return this.start === this.end ? start <= this.start && this.start <= end : start < this.end && end > this.start;
366
415
  }
367
416
  /** The text a hyperlink holds, as [start, end) in the paragraph, or undefined when it holds none. */
368
417
  spanOf(holder) {
@@ -393,6 +442,10 @@ export class Range {
393
442
  if (tracking && !tracking.ownInsertions.has(run))
394
443
  tracking.tracker.recordRPrChange(run.rPr);
395
444
  applyRunOptions(run.rPr, linked ? { style: HYPERLINK_STYLE, color: '' } : { style: '' });
445
+ if (tracking)
446
+ tracking.tracker.settleRPrChange(run);
447
+ if (!run.rPr)
448
+ continue;
396
449
  if (Object.keys(run.rPr).every((key) => key === 'TYPE_NAME'))
397
450
  delete run.rPr;
398
451
  else
@@ -413,8 +466,56 @@ export class Range {
413
466
  return part.getRelationshipsPart(true).addExternalRelationship(Namespaces.HYPERLINK, address).id;
414
467
  }
415
468
  }
469
+ /**
470
+ * What Office JS throws where the host refuses an operation it has no answer for: its `code`, so that
471
+ * add-in code branching on `error.code` behaves the same here (check 19).
472
+ */
473
+ class GeneralException extends Docx4JException {
474
+ constructor(message) {
475
+ super(message);
476
+ this.code = 'GeneralException';
477
+ this.name = 'GeneralException';
478
+ }
479
+ }
416
480
  /** The character style Word gives the runs of a hyperlink it makes. */
417
481
  const HYPERLINK_STYLE = 'Hyperlink';
482
+ /**
483
+ * Adjacent runs holding nothing but text and the same properties become one, as Word writes a link
484
+ * it makes: linking "beta gamma" over the end of a link on "alpha beta" gives Word one run
485
+ * "alpha beta gamma" (`test/README.md` check 16, case F), where splitting and restyling left two.
486
+ * Runs whose properties differ at all - a `w:rPrChange` under tracking among them - stay apart.
487
+ */
488
+ function mergeTextRuns(items, parent) {
489
+ var _a, _b;
490
+ for (let i = items.length - 1; i > 0; i--) {
491
+ const [a, b] = [items[i - 1], items[i]];
492
+ if (!isTextRun(a) || !isTextRun(b))
493
+ continue;
494
+ const [ra, rb] = [a.value, b.value];
495
+ if (canonical(ra.rPr) !== canonical(rb.rPr))
496
+ continue;
497
+ const text = [...((_a = ra.content) !== null && _a !== void 0 ? _a : []), ...((_b = rb.content) !== null && _b !== void 0 ? _b : [])].map((item) => { var _a; return (_a = item.value.value) !== null && _a !== void 0 ? _a : ''; }).join('');
498
+ ra.content = [textElement(text)];
499
+ linkParents(ra.content, ra);
500
+ items.splice(i, 1);
501
+ }
502
+ linkParents(items, parent);
503
+ }
504
+ function isTextRun(item) {
505
+ var _a;
506
+ return typeNameOf(item) === 'org_docx4j_wml.R'
507
+ && ((_a = item.value.content) !== null && _a !== void 0 ? _a : []).every((c) => { var _a; return ((_a = c.name) === null || _a === void 0 ? void 0 : _a.localPart) === 't'; });
508
+ }
509
+ /** A value as text with its keys in order and `PARENT` left out, to compare run properties by content. */
510
+ function canonical(value) {
511
+ return JSON.stringify(value, (key, v) => {
512
+ if (key === 'PARENT')
513
+ return undefined;
514
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
515
+ return v;
516
+ return Object.fromEntries(Object.keys(v).sort().map((k) => [k, v[k]]));
517
+ });
518
+ }
418
519
  /** Whether `object` is `ancestor` or below it, following `PARENT` no further than `stop`. */
419
520
  function within(object, ancestor, stop) {
420
521
  for (let o = object; o !== undefined && o !== stop; o = o.PARENT) {
@@ -3,7 +3,7 @@ import { tr as rowOf } from '@docx4j/generated-objects-ts/builders/wml';
3
3
  import { Docx4JException } from '../../opc/exceptions.mjs';
4
4
  import { typeNameOf, childrenOf, linkParents, textOf, rowsOf, cellsOf } from './tree.mjs';
5
5
  import { builtInOf, idOfBuiltIn, styleNameOf, styleIdOf } from './styles.mjs';
6
- import { trackInsertedParagraph } from './tracking.mjs';
6
+ import { trackInsertedBlocks } from './tracking.mjs';
7
7
  /** The default table width in twips (A4 with 2.54 cm margins), as the objects package's `tbl` builder uses. */
8
8
  const DEFAULT_WIDTH = 9026;
9
9
  const TWIPS_PER_POINT = 20;
@@ -418,12 +418,10 @@ function markRowsInserted(tracker, rows) {
418
418
  if (!tracker)
419
419
  return;
420
420
  for (const row of rows) {
421
- tracker.markRowInserted(row.value);
422
- for (const cell of cellsOf(row.value)) {
423
- for (const block of (_a = childrenOf(cell.element.value)) !== null && _a !== void 0 ? _a : []) {
424
- if (typeNameOf(block) === 'org_docx4j_wml.P')
425
- trackInsertedParagraph(tracker, block.value);
426
- }
427
- }
421
+ if (!((_a = row.value.trPr) === null || _a === void 0 ? void 0 : _a.ins))
422
+ tracker.markRowInserted(row.value);
423
+ // nested tables and block controls in a new row's cells too (CR-002 section 37)
424
+ for (const cell of cellsOf(row.value))
425
+ trackInsertedBlocks(tracker, childrenOf(cell.element.value));
428
426
  }
429
427
  }
@@ -1,5 +1,5 @@
1
1
  import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
- import { type Element, type RevisionKind } from './tree.mjs';
2
+ import { type Element, type Located, type RevisionKind } from './tree.mjs';
3
3
  import { Range } from './Range.mjs';
4
4
  import type { Paragraph } from './Paragraph.mjs';
5
5
  /** Office JS `Word.ChangeTrackingState` (`Unknown` is not produced here). */
@@ -35,7 +35,8 @@ export type TrackedChangeTarget =
35
35
  * `w:trPr/w:ins` or `w:trPr/w:del`: a table row. `inner` is the revision markup the row's own
36
36
  * cells carry (the `w:ins` or `w:del` around their runs and on their paragraph marks), which
37
37
  * `Body.getTrackedChanges` reports through the row rather than separately, as Office JS does:
38
- * one change per row. Accepting or rejecting the row applies them too.
38
+ * one change per row. Accepting or rejecting the row applies them too. `table` is the table the
39
+ * row is in, which goes with its last row.
39
40
  */
40
41
  | {
41
42
  kind: 'row';
@@ -44,6 +45,73 @@ export type TrackedChangeTarget =
44
45
  owner: Element[];
45
46
  value: wml.CTTrackChange;
46
47
  inner: TrackedChange[];
48
+ table?: Located<wml.Tbl>;
49
+ }
50
+ /**
51
+ * Touching insertions, deletions or formatting changes by one author - `w:ins` or `w:del` around
52
+ * runs and inserted or deleted paragraph marks, or runs' `w:rPrChange`, with nothing unrevised
53
+ * between them - which Office JS lists as one change (CR-002 section 29, checks 22, 23 and 28): a
54
+ * deleted paragraph's text and mark, a deletion across a mark, bold put on two runs of different
55
+ * formatting. `pieces` are the single changes, in document order; `value` is the first's.
56
+ */
57
+ | {
58
+ kind: 'group';
59
+ revision: 'ins' | 'del' | 'format';
60
+ pieces: TrackedChange[];
61
+ value: wml.CTTrackChange;
62
+ }
63
+ /**
64
+ * A table's property records - `w:tblPrChange`, `w:tblGridChange`, `w:tblPrExChange`, and every
65
+ * `w:trPrChange` and `w:tcPrChange` in it - which Word writes as one set for one change and Office
66
+ * JS lists as one `Formatted` change (CR-002 section 35, checks 27 and 28). `value` is the table's
67
+ * record, else the first row's or cell's.
68
+ */
69
+ | {
70
+ kind: 'tableProperties';
71
+ tbl: Element<wml.Tbl>;
72
+ value: wml.CTTrackChange;
73
+ }
74
+ /** `w:tcPr/w:cellIns` or `w:tcPr/w:cellDel`: an inserted or deleted cell (section 35, check 27). */
75
+ | {
76
+ kind: 'cell';
77
+ cell: 'ins' | 'del';
78
+ tc: Element<wml.Tc>;
79
+ owner: Element[];
80
+ tr: wml.Tr;
81
+ value: wml.CTTrackChange;
82
+ }
83
+ /** `w:pPr/w:rPr/w:rPrChange`: a paragraph mark's formatting, which groups with its runs' (check 27). */
84
+ | {
85
+ kind: 'markProperties';
86
+ value: wml.ParaRPrChange;
87
+ }
88
+ /**
89
+ * `w:sectPr/w:sectPrChange`: a section's properties, at a paragraph's section break or the body's
90
+ * last section. `text` is the section's, as Office JS reports it (check 27: the text, then `\f`).
91
+ */
92
+ | {
93
+ kind: 'sectionProperties';
94
+ sectPr: wml.SectPr;
95
+ value: wml.CTSectPrChange;
96
+ text: string;
97
+ }
98
+ /**
99
+ * A content control or custom XML element that is itself an insertion: `w:customXmlInsRangeStart`
100
+ * and `w:customXmlInsRangeEnd` around it, the end first inside its content, and a second pair the
101
+ * other way round at its end - Word's form for a control put in under tracking (check 30, CR-002
102
+ * section 37 item 7), which groups with the insertions around and inside it. `holder` is the
103
+ * `w:sdt` or `w:customXml`, `owner` the list holding it, `outer` the pair in that list and `inner`
104
+ * the pair in its content. Rejecting takes the element away and leaves its content where it
105
+ * stood; accepting takes the markers away. Its text is its content's, which the pieces inside
106
+ * report.
107
+ */
108
+ | {
109
+ kind: 'holder';
110
+ holder: Element;
111
+ owner: Element[];
112
+ outer: [Element, Element];
113
+ inner: [Element, Element];
114
+ value: wml.CTTrackChange;
47
115
  };
48
116
  /**
49
117
  * A subset of Office JS `Word.TrackedChange`: `type`, `author`, `date`, `text`, `accept()`,
@@ -60,13 +128,17 @@ export declare class TrackedChange {
60
128
  /** Office JS `Word.ChangeTrackingState`. */
61
129
  get type(): TrackedChangeType;
62
130
  get author(): string;
63
- /** `w:date`, when the markup carries one. */
131
+ /**
132
+ * When the change was made: `w16du:dateUtc` if the markup has it, else `w:date` read as Word writes
133
+ * it, local wall-clock time (`revisionDateOf`, CR-002 section 29); a group's is its first piece's,
134
+ * as Office JS reports it.
135
+ */
64
136
  get date(): Date | undefined;
65
137
  /** The annotation id (`w:id`; an extension). */
66
138
  get id(): number;
67
139
  /** The markup this change is over (an extension): the `w:ins` element, the `w:rPrChange`, ... */
68
140
  get element(): object;
69
- /** The text the change covers; '' for a paragraph mark, whose range is the paragraph. */
141
+ /** The text the change covers; `\r` for a paragraph mark, as Office JS gives it (check 22). */
70
142
  get text(): string;
71
143
  /** The range the change covers; a deletion is a collapsed range where it sits in the accepted text. */
72
144
  getRange(): Range | undefined;
@@ -82,6 +154,13 @@ export declare class TrackedChange {
82
154
  reject(): void;
83
155
  private requireParagraph;
84
156
  }
157
+ /**
158
+ * The insertion of a content control or custom XML element, when `items[i]` is a
159
+ * `w:customXmlInsRangeStart` and what follows is Word's form for one (check 30): the element, whose
160
+ * content starts with that marker's `w:customXmlInsRangeEnd` and ends with a second start, and that
161
+ * one's end right after the element. Anything else is not one (a marker on its own is left alone).
162
+ */
163
+ export declare function holderInsertionAt(items: Element[], i: number, paragraph: Paragraph | undefined): TrackedChange | undefined;
85
164
  /**
86
165
  * docx4j AcceptTrackedChanges: the paragraph takes the next one's content and properties, so the
87
166
  * mark that survives is the next one's. Called when a deleted mark is accepted and when an
@@ -93,10 +172,50 @@ export declare class TrackedChange {
93
172
  * mark is simply dropped.
94
173
  */
95
174
  export declare function joinWithNext(paragraph: Pick<Paragraph, 'container' | 'element' | 'p'>, fallbackToPrevious?: boolean): void;
96
- /** The tracked changes of one paragraph, in document order. */
175
+ /**
176
+ * The tracked changes of one paragraph, in document order, touching pieces grouped as Office JS
177
+ * groups them (`groupTouching`). Office JS lists the changes that start in the paragraph (check 22):
178
+ * pieces that carry on a change from the paragraph before - its inserted or deleted mark - are left
179
+ * to that paragraph, and a change running on into the next is cut at this paragraph's end.
180
+ */
97
181
  export declare function trackedChangesOfParagraph(paragraph: Paragraph): TrackedChange[];
182
+ /** Between two tracked changes: something unrevised - text, a paragraph mark, a table - that keeps them apart. */
183
+ export declare const BREAK: "break";
184
+ export type TrackedChangeToken = TrackedChange | typeof BREAK;
185
+ /**
186
+ * A paragraph's single changes in document order, its mark last, with a `BREAK` wherever unrevised
187
+ * content stands between two of them: `groupTouching` makes the groups from these.
188
+ */
189
+ export declare function trackedChangeTokensOfParagraph(paragraph: Paragraph): TrackedChangeToken[];
190
+ /**
191
+ * Tokens made into the changes Office JS lists: consecutive pieces of one kind (inserted, deleted, or
192
+ * a run's formatting) by one author, nothing unrevised between them, are one change (checks 22, 23
193
+ * and 28: text and marks alike, dates regardless, formatting whatever it recorded; another author, or
194
+ * one kind against another, starts a new one). A change that does not group - a paragraph's
195
+ * properties, a move - is listed where it stands and does not break a group. A group of one piece is
196
+ * that piece.
197
+ */
198
+ export declare function groupTouching(tokens: TrackedChangeToken[]): TrackedChange[];
98
199
  /**
99
200
  * The `w:trPr/w:ins` and `w:trPr/w:del` revisions of a table row. `inner` is the revision markup
100
201
  * of the row's own cells, which the row's change owns rather than reporting separately.
101
202
  */
102
- export declare function trackedChangesOfRow(tr: Element<wml.Tr>, owner: Element[], inner?: TrackedChange[]): TrackedChange[];
203
+ export declare function trackedChangesOfRow(tr: Element<wml.Tr>, owner: Element[], inner?: TrackedChange[], table?: Located<wml.Tbl>): TrackedChange[];
204
+ /** The change a table's property records make, one per table, or undefined when they make none. */
205
+ export declare function tablePropertiesChangeOf(tbl: Element<wml.Tbl>): TrackedChange | undefined;
206
+ /** A cell's own revision, `w:cellIns` or `w:cellDel`, or undefined. */
207
+ export declare function cellChangeOf(tc: Element<wml.Tc>, owner: Element[], tr: wml.Tr): TrackedChange | undefined;
208
+ /** The change to the body's last section (`w:body/w:sectPr/w:sectPrChange`), its text the section's paragraphs'. */
209
+ export declare function bodySectionChangeOf(container: {
210
+ content?: Element[];
211
+ sectPr?: wml.SectPr;
212
+ }): TrackedChange | undefined;
213
+ /**
214
+ * What `acceptAll` and `rejectAll` resolve that is never listed: a `w:cellMerge`, which Office JS
215
+ * cannot list (check 27: `getTrackedChanges` throws); a `w:numberingChange`, which Word no longer
216
+ * writes and drops when one is put in, and whose record is the old number's text, so that a reject
217
+ * too can only drop it; and a table's records that change nothing. A merge rejected gets the merge it
218
+ * recorded back (docx4j's reading; unmeasured). A `w:customXmlInsRangeStart` or `End` left without
219
+ * the form `holderInsertionAt` lists marks nothing that can be found, and goes either way.
220
+ */
221
+ export declare function resolveUnlisted(items: Element[], what: 'accept' | 'reject'): void;