@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.
- package/dist/model/content/Body.d.mts +15 -3
- package/dist/model/content/Body.mjs +93 -31
- package/dist/model/content/Comment.d.mts +27 -2
- package/dist/model/content/Comment.mjs +180 -41
- package/dist/model/content/ContentControl.d.mts +6 -0
- package/dist/model/content/ContentControl.mjs +51 -5
- package/dist/model/content/Font.mjs +2 -0
- package/dist/model/content/List.mjs +9 -6
- package/dist/model/content/Paragraph.d.mts +72 -2
- package/dist/model/content/Paragraph.mjs +308 -55
- package/dist/model/content/Range.d.mts +6 -4
- package/dist/model/content/Range.mjs +114 -13
- package/dist/model/content/Table.mjs +6 -8
- package/dist/model/content/TrackedChange.d.mts +125 -6
- package/dist/model/content/TrackedChange.mjs +847 -50
- package/dist/model/content/comments.d.mts +20 -3
- package/dist/model/content/comments.mjs +1 -9
- package/dist/model/content/index.d.mts +3 -3
- package/dist/model/content/index.mjs +2 -2
- package/dist/model/content/stylesFacade.mjs +5 -2
- package/dist/model/content/tableRevisions.d.mts +30 -0
- package/dist/model/content/tableRevisions.mjs +207 -0
- package/dist/model/content/tracking.d.mts +109 -13
- package/dist/model/content/tracking.mjs +267 -43
- package/dist/packages/WordprocessingMLPackage.d.mts +6 -0
- package/dist/packages/WordprocessingMLPackage.mjs +11 -0
- package/dist/parts/wml/commentStyles.d.mts +3 -0
- package/dist/parts/wml/commentStyles.mjs +25 -0
- package/dist/parts/wml/comments.mjs +51 -22
- package/package.json +1 -1
|
@@ -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, (
|
|
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
|
-
*
|
|
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
|
|
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 {
|
|
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
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
/**
|
|
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;
|
|
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
|
-
/**
|
|
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;
|