@docx4j/core-ts 0.3.0 → 0.3.2
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.mjs +40 -19
- package/dist/model/content/Comment.d.mts +6 -0
- package/dist/model/content/Comment.mjs +76 -22
- package/dist/model/content/ContentControl.d.mts +11 -1
- package/dist/model/content/ContentControl.mjs +69 -10
- package/dist/model/content/Paragraph.d.mts +37 -2
- package/dist/model/content/Paragraph.mjs +140 -38
- package/dist/model/content/Range.mjs +49 -5
- package/dist/model/content/Table.mjs +6 -8
- package/dist/model/content/TrackedChange.d.mts +32 -4
- package/dist/model/content/TrackedChange.mjs +271 -34
- package/dist/model/content/index.d.mts +1 -1
- package/dist/model/content/index.mjs +1 -1
- package/dist/model/content/stylesFacade.mjs +9 -3
- package/dist/model/content/tracking.d.mts +65 -5
- package/dist/model/content/tracking.mjs +170 -43
- package/dist/model/customxml/XmlMapping.d.mts +20 -4
- package/dist/model/customxml/XmlMapping.mjs +44 -6
- package/dist/model/customxml/bindings.d.mts +9 -2
- package/dist/model/customxml/bindings.mjs +18 -2
- package/dist/model/customxml/index.d.mts +1 -1
- package/dist/model/customxml/index.mjs +1 -1
- package/dist/model/customxml/insert.d.mts +10 -0
- package/dist/model/customxml/insert.mjs +13 -0
- package/dist/model/fonts/RunFontSelector.d.mts +8 -1
- package/dist/model/fonts/RunFontSelector.mjs +6 -5
- package/dist/model/properties/PropertyResolver.d.mts +110 -10
- package/dist/model/properties/PropertyResolver.mjs +300 -31
- package/dist/model/properties/index.d.mts +3 -0
- package/dist/model/properties/index.mjs +2 -0
- package/dist/model/properties/table.d.mts +155 -0
- package/dist/model/properties/table.mjs +315 -0
- package/dist/model/properties/tableStyleConditions.d.mts +101 -0
- package/dist/model/properties/tableStyleConditions.mjs +296 -0
- 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 +4 -22
- package/dist/parts/wml/placeholderStyle.d.mts +3 -0
- package/dist/parts/wml/placeholderStyle.mjs +13 -0
- package/package.json +2 -2
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { textOf } from '@docx4j/generated-objects-ts/builders/wml';
|
|
2
2
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
3
|
-
import { typeNameOf, runItemsOf, revisionKindOf, linkParents, segmentsOf, textOfView, cellsOf, rowsOf, childrenOf, W_NS } from './tree.mjs';
|
|
3
|
+
import { typeNameOf, runItemsOf, revisionKindOf, linkParents, segmentsOf, textOfView, cellsOf, rowsOf, childrenOf, W_NS, itemTextOf } from './tree.mjs';
|
|
4
|
+
import { removeMarkers } from './comments.mjs';
|
|
4
5
|
import { Range } from './Range.mjs';
|
|
5
6
|
import { rPrFromElements } from '@docx4j/generated-objects-ts/builders/wml';
|
|
6
|
-
import { revisionDateOf, toRestoredText, toDeletedText, restoreRPr, restorePPr, pruneParagraphProperties } from './tracking.mjs';
|
|
7
|
+
import { revisionDateOf, toRestoredText, toDeletedText, restoreRPr, restorePPr, pruneParagraphProperties, HOLDER_TYPES, holderItemsOf } from './tracking.mjs';
|
|
7
8
|
import { tableRecordsOf, hasTableRecords, tableChangeText, rowText as tableRowText, acceptTable, rejectTable } from './tableRevisions.mjs';
|
|
8
9
|
import { deepCopy } from '@docx4j/generated-objects-ts';
|
|
9
10
|
/**
|
|
@@ -27,6 +28,7 @@ export class TrackedChange {
|
|
|
27
28
|
case 'row': return t.row === 'ins' ? 'Added' : 'Deleted';
|
|
28
29
|
case 'group': return t.revision === 'ins' ? 'Added' : t.revision === 'del' ? 'Deleted' : 'Formatted';
|
|
29
30
|
case 'cell': return t.cell === 'ins' ? 'Added' : 'Deleted';
|
|
31
|
+
case 'holder': return 'Added';
|
|
30
32
|
default: return 'Formatted';
|
|
31
33
|
}
|
|
32
34
|
}
|
|
@@ -55,6 +57,7 @@ export class TrackedChange {
|
|
|
55
57
|
case 'tableProperties': return t.tbl;
|
|
56
58
|
case 'cell': return t.tc;
|
|
57
59
|
case 'sectionProperties': return t.sectPr;
|
|
60
|
+
case 'holder': return t.holder;
|
|
58
61
|
default: return t.value;
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -117,7 +120,7 @@ export class TrackedChange {
|
|
|
117
120
|
if (t.revision === 'ins' || t.revision === 'moveTo')
|
|
118
121
|
unwrap(t);
|
|
119
122
|
else
|
|
120
|
-
|
|
123
|
+
removeRevision(t, this.paragraph);
|
|
121
124
|
return;
|
|
122
125
|
case 'mark':
|
|
123
126
|
if (t.mark === 'ins')
|
|
@@ -143,7 +146,7 @@ export class TrackedChange {
|
|
|
143
146
|
applyInner(t.inner, 'accept');
|
|
144
147
|
}
|
|
145
148
|
else
|
|
146
|
-
|
|
149
|
+
removeRow(t);
|
|
147
150
|
return;
|
|
148
151
|
case 'group':
|
|
149
152
|
resolvePieces(t.pieces, 'accept');
|
|
@@ -167,6 +170,10 @@ export class TrackedChange {
|
|
|
167
170
|
case 'sectionProperties':
|
|
168
171
|
delete t.sectPr.sectPrChange;
|
|
169
172
|
return;
|
|
173
|
+
case 'holder':
|
|
174
|
+
// the element stays, the markers go (check 30: accept all leaves the control, no marker)
|
|
175
|
+
removeHolderMarkers(t);
|
|
176
|
+
return;
|
|
170
177
|
}
|
|
171
178
|
}
|
|
172
179
|
/**
|
|
@@ -181,7 +188,7 @@ export class TrackedChange {
|
|
|
181
188
|
if ((t.revision === 'moveFrom' || t.revision === 'moveTo') && (resolveMove(this, 'reject') || resolveRangelessHalf(this, 'reject')))
|
|
182
189
|
return;
|
|
183
190
|
if (t.revision === 'ins' || t.revision === 'moveTo')
|
|
184
|
-
|
|
191
|
+
removeRevision(t, this.paragraph);
|
|
185
192
|
else
|
|
186
193
|
restoreDeleted(t);
|
|
187
194
|
return;
|
|
@@ -210,7 +217,7 @@ export class TrackedChange {
|
|
|
210
217
|
applyInner(t.inner, 'reject');
|
|
211
218
|
}
|
|
212
219
|
else
|
|
213
|
-
|
|
220
|
+
removeRow(t);
|
|
214
221
|
return;
|
|
215
222
|
case 'group':
|
|
216
223
|
resolvePieces(t.pieces, 'reject');
|
|
@@ -230,6 +237,12 @@ export class TrackedChange {
|
|
|
230
237
|
case 'sectionProperties':
|
|
231
238
|
restoreSection(t.sectPr, t.value);
|
|
232
239
|
return;
|
|
240
|
+
case 'holder':
|
|
241
|
+
// the element goes, its content stays where it stood: what is left of it after the pieces
|
|
242
|
+
// inside were rejected (nothing, for content inserted with it; check 30: reject all removes the
|
|
243
|
+
// control, and an existing control, which has no markers, stays)
|
|
244
|
+
unwrapHolder(t);
|
|
245
|
+
return;
|
|
233
246
|
}
|
|
234
247
|
}
|
|
235
248
|
requireParagraph() {
|
|
@@ -245,21 +258,37 @@ export class TrackedChange {
|
|
|
245
258
|
* is all `w:delText`).
|
|
246
259
|
*/
|
|
247
260
|
function rowText(tr, view) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
261
|
+
// Office JS's text for a row: its cells with a tab between them, then `\r\n`; a cell's paragraphs
|
|
262
|
+
// with `\r` between them, a nested table's rows each with their own `\r\n` and no separator of their
|
|
263
|
+
// own (checks 30 and 31: "row one\r\n", "nested\r\nouter cell\r\n")
|
|
264
|
+
const cellText = (tc) => {
|
|
265
|
+
var _a, _b;
|
|
266
|
+
let out = '';
|
|
267
|
+
let afterParagraph = false;
|
|
268
|
+
for (const el of (_a = childrenOf(tc)) !== null && _a !== void 0 ? _a : []) {
|
|
269
|
+
const tn = typeNameOf(el);
|
|
270
|
+
if (tn === 'org_docx4j_wml.P') {
|
|
271
|
+
out += (afterParagraph ? '\r' : '') + textOfView(el.value, { view });
|
|
272
|
+
afterParagraph = true;
|
|
273
|
+
}
|
|
274
|
+
else if (tn === 'org_docx4j_wml.Tbl') {
|
|
275
|
+
for (const row of rowsOf(el.value))
|
|
276
|
+
out += rowText(row.element.value, view);
|
|
277
|
+
afterParagraph = false;
|
|
278
|
+
}
|
|
279
|
+
else if (typeof el.value === 'object' && el.value !== null) {
|
|
280
|
+
// a block control or custom XML element: what it holds, as if it were not there
|
|
281
|
+
for (const inner of (_b = childrenOf(el.value)) !== null && _b !== void 0 ? _b : []) {
|
|
282
|
+
if (typeNameOf(inner) === 'org_docx4j_wml.P') {
|
|
283
|
+
out += (afterParagraph ? '\r' : '') + textOfView(inner.value, { view });
|
|
284
|
+
afterParagraph = true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
254
287
|
}
|
|
255
|
-
const v = el.value;
|
|
256
|
-
if (typeof v === 'object' && v !== null)
|
|
257
|
-
visit(childrenOf(v));
|
|
258
288
|
}
|
|
289
|
+
return out;
|
|
259
290
|
};
|
|
260
|
-
|
|
261
|
-
visit(childrenOf(cell.element.value));
|
|
262
|
-
return lines.join('\n');
|
|
291
|
+
return cellsOf(tr).map((cell) => cellText(cell.element.value)).join('\t') + '\r\n';
|
|
263
292
|
}
|
|
264
293
|
/** The changes inside a row, last first, so that a paragraph join never disturbs one still to do. */
|
|
265
294
|
function applyInner(inner, what) {
|
|
@@ -330,10 +359,167 @@ function resolvePieces(pieces, what) {
|
|
|
330
359
|
for (let i = marks.length - 1; i >= 0; i--)
|
|
331
360
|
marks[i][what]();
|
|
332
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* The list an element is in now: `owner` as the change was listed, else the list its `PARENT` keeps -
|
|
364
|
+
* a piece listed inside a holder that was unwrapped since (its content moved out into the owner,
|
|
365
|
+
* check 30) is still found.
|
|
366
|
+
*/
|
|
367
|
+
function currentOwner(owner, element) {
|
|
368
|
+
var _a, _b;
|
|
369
|
+
if (owner.includes(element))
|
|
370
|
+
return owner;
|
|
371
|
+
const parent = (_a = element.value) === null || _a === void 0 ? void 0 : _a.PARENT;
|
|
372
|
+
const actual = parent ? (_b = runItemsOf(parent)) !== null && _b !== void 0 ? _b : childrenOf(parent) : undefined;
|
|
373
|
+
return (actual === null || actual === void 0 ? void 0 : actual.includes(element)) ? actual : owner;
|
|
374
|
+
}
|
|
333
375
|
function remove(owner, element) {
|
|
334
|
-
const
|
|
376
|
+
const list = currentOwner(owner, element);
|
|
377
|
+
const i = list.indexOf(element);
|
|
335
378
|
if (i >= 0)
|
|
336
|
-
|
|
379
|
+
list.splice(i, 1);
|
|
380
|
+
}
|
|
381
|
+
/** A holder's four insertion markers taken away; the element stays. */
|
|
382
|
+
function removeHolderMarkers(t) {
|
|
383
|
+
var _a;
|
|
384
|
+
remove(t.owner, t.outer[0]);
|
|
385
|
+
remove(t.owner, t.outer[1]);
|
|
386
|
+
const items = (_a = holderItemsOf(t.holder.value)) !== null && _a !== void 0 ? _a : [];
|
|
387
|
+
remove(items, t.inner[0]);
|
|
388
|
+
remove(items, t.inner[1]);
|
|
389
|
+
}
|
|
390
|
+
/** A holder's insertion rejected: the markers go, and its content takes its place in the owner. */
|
|
391
|
+
function unwrapHolder(t) {
|
|
392
|
+
var _a;
|
|
393
|
+
removeHolderMarkers(t);
|
|
394
|
+
const owner = currentOwner(t.owner, t.holder);
|
|
395
|
+
const i = owner.indexOf(t.holder);
|
|
396
|
+
if (i < 0)
|
|
397
|
+
return;
|
|
398
|
+
const items = (_a = holderItemsOf(t.holder.value)) !== null && _a !== void 0 ? _a : [];
|
|
399
|
+
const moved = items.splice(0); // the holder keeps nothing
|
|
400
|
+
owner.splice(i, 1, ...moved);
|
|
401
|
+
linkParents(moved, t.holder.value.PARENT);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* The insertion of a content control or custom XML element, when `items[i]` is a
|
|
405
|
+
* `w:customXmlInsRangeStart` and what follows is Word's form for one (check 30): the element, whose
|
|
406
|
+
* content starts with that marker's `w:customXmlInsRangeEnd` and ends with a second start, and that
|
|
407
|
+
* one's end right after the element. Anything else is not one (a marker on its own is left alone).
|
|
408
|
+
*/
|
|
409
|
+
export function holderInsertionAt(items, i, paragraph) {
|
|
410
|
+
var _a, _b, _c, _d, _e, _f;
|
|
411
|
+
const start = items[i];
|
|
412
|
+
if (((_a = start.name) === null || _a === void 0 ? void 0 : _a.localPart) !== 'customXmlInsRangeStart')
|
|
413
|
+
return undefined;
|
|
414
|
+
const holder = items[i + 1];
|
|
415
|
+
const outerEnd = items[i + 2];
|
|
416
|
+
if (!holder || !outerEnd || !HOLDER_TYPES.has((_b = typeNameOf(holder)) !== null && _b !== void 0 ? _b : '') || ((_c = outerEnd.name) === null || _c === void 0 ? void 0 : _c.localPart) !== 'customXmlInsRangeEnd')
|
|
417
|
+
return undefined;
|
|
418
|
+
const inner = (_d = childrenOf(holder.value)) !== null && _d !== void 0 ? _d : [];
|
|
419
|
+
const innerEnd = inner[0];
|
|
420
|
+
const innerStart = inner[inner.length - 1];
|
|
421
|
+
if (inner.length < 2 || !innerEnd || !innerStart || ((_e = innerEnd.name) === null || _e === void 0 ? void 0 : _e.localPart) !== 'customXmlInsRangeEnd' || ((_f = innerStart.name) === null || _f === void 0 ? void 0 : _f.localPart) !== 'customXmlInsRangeStart')
|
|
422
|
+
return undefined;
|
|
423
|
+
const idOf = (marker) => marker.value.id;
|
|
424
|
+
if (idOf(innerEnd) !== idOf(start) || idOf(outerEnd) !== idOf(innerStart))
|
|
425
|
+
return undefined;
|
|
426
|
+
return new TrackedChange({ kind: 'holder', holder, owner: items, outer: [start, outerEnd], inner: [innerEnd, innerStart], value: start.value }, paragraph);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* A row taken away, and its table with it when it was the last: a table has no revision of its own,
|
|
430
|
+
* so one whose rows were all inserted was inserted, and one whose rows were all deleted was deleted.
|
|
431
|
+
* A `w:tbl` left with no rows is not a table any more (CR-002 section 37).
|
|
432
|
+
*/
|
|
433
|
+
function removeRow(t) {
|
|
434
|
+
remove(t.owner, t.tr);
|
|
435
|
+
if (t.table && rowsOf(t.table.element.value).length === 0)
|
|
436
|
+
remove(t.table.container, t.table.element);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* A revision taken away with its runs - a rejected insertion, an accepted deletion - and the comments
|
|
440
|
+
* on it, by where their markers were (CR-002 section 38 item 1):
|
|
441
|
+
* - Word writes a comment's range start inside the `w:ins` of the text it is on; when that text goes,
|
|
442
|
+
* current Word removes the comment with it - markers, reference run and entry (check 32, run
|
|
443
|
+
* 2026-10-02: rejecting the insertion, rejecting all, and accepting the deletion in the same shape,
|
|
444
|
+
* each left no comment). A comment whose start comes out of the revision with no text left in its
|
|
445
|
+
* range is removed here: the markers and the reference now, the entries in the comment parts when
|
|
446
|
+
* the comments are next read or the package saved (`pendingCommentRemovals`).
|
|
447
|
+
* - A comment whose markers lie outside the revision (this package's own form before 0.3.1, and any
|
|
448
|
+
* file's) is kept when its text goes: Word 2010 and Word 15, rejecting all in the editor's
|
|
449
|
+
* `review-for-word.docx`, left its reference run alone, the range markers dropped and the entry kept
|
|
450
|
+
* (the editor's finding of 2026-10-02). The range markers go here, the reference and the entry stay.
|
|
451
|
+
* A comment with text left in its range keeps its markers where the text was (not measured), and
|
|
452
|
+
* current Word's answer for the outside form, and the older Words' for the inside one, are not measured.
|
|
453
|
+
*/
|
|
454
|
+
function removeRevision(t, paragraph) {
|
|
455
|
+
var _a, _b, _c;
|
|
456
|
+
const owner = currentOwner(t.owner, t.element);
|
|
457
|
+
const i = owner.indexOf(t.element);
|
|
458
|
+
if (i < 0)
|
|
459
|
+
return;
|
|
460
|
+
const kept = ((_a = runItemsOf(t.element.value)) !== null && _a !== void 0 ? _a : []).filter((item) => { var _a, _b; return ((_a = item.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeStart' || ((_b = item.name) === null || _b === void 0 ? void 0 : _b.localPart) === 'commentRangeEnd'; });
|
|
461
|
+
// the comments whose range held the revision: a start inside it (Word's form), or one before it
|
|
462
|
+
// with its end after it (the engine's own, the markers beside the runs)
|
|
463
|
+
const idOf = (el) => el.value.id;
|
|
464
|
+
const inside = new Set(kept.filter((m) => { var _a; return ((_a = m.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeStart'; }).map(idOf));
|
|
465
|
+
const outside = new Set();
|
|
466
|
+
for (let s = 0; s < i; s++) {
|
|
467
|
+
const el = owner[s];
|
|
468
|
+
if (((_b = el.name) === null || _b === void 0 ? void 0 : _b.localPart) !== 'commentRangeStart')
|
|
469
|
+
continue;
|
|
470
|
+
const id = idOf(el);
|
|
471
|
+
if (owner.some((other, e) => { var _a; return e > i && ((_a = other.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeEnd' && idOf(other) === id; }))
|
|
472
|
+
outside.add(id);
|
|
473
|
+
}
|
|
474
|
+
owner.splice(i, 1, ...kept);
|
|
475
|
+
linkParents(kept, t.element.value.PARENT);
|
|
476
|
+
const body = paragraph === null || paragraph === void 0 ? void 0 : paragraph.parentBody;
|
|
477
|
+
if (!body)
|
|
478
|
+
return;
|
|
479
|
+
for (const id of [...inside, ...outside]) {
|
|
480
|
+
const start = owner.find((el) => { var _a; return ((_a = el.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeStart' && idOf(el) === id; });
|
|
481
|
+
if (!start || !rangeIsEmpty(owner, start, id))
|
|
482
|
+
continue;
|
|
483
|
+
if (inside.has(id)) {
|
|
484
|
+
removeMarkers(body.container, id);
|
|
485
|
+
const pkg = body.package_;
|
|
486
|
+
(_c = pkg === null || pkg === void 0 ? void 0 : pkg.pendingCommentRemovals) === null || _c === void 0 ? void 0 : _c.add(id);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
// the range markers only: the reference run and the entry stay (Word 2010 and 15)
|
|
490
|
+
const end = owner.find((el) => { var _a; return ((_a = el.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeEnd' && idOf(el) === id; });
|
|
491
|
+
for (const marker of [end, start])
|
|
492
|
+
if (marker)
|
|
493
|
+
owner.splice(owner.indexOf(marker), 1);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/** True when nothing with text stands between a comment's range start and its end in the same list. */
|
|
498
|
+
function rangeIsEmpty(owner, start, id) {
|
|
499
|
+
var _a;
|
|
500
|
+
const from = owner.indexOf(start);
|
|
501
|
+
if (from < 0)
|
|
502
|
+
return false;
|
|
503
|
+
for (let i = from + 1; i < owner.length; i++) {
|
|
504
|
+
const el = owner[i];
|
|
505
|
+
if (((_a = el.name) === null || _a === void 0 ? void 0 : _a.localPart) === 'commentRangeEnd' && el.value.id === id)
|
|
506
|
+
return true;
|
|
507
|
+
if (hasText(el))
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
return false; // the end is elsewhere: text may be
|
|
511
|
+
}
|
|
512
|
+
function hasText(el) {
|
|
513
|
+
var _a, _b;
|
|
514
|
+
const v = el.value;
|
|
515
|
+
if (typeof v !== 'object' || v === null)
|
|
516
|
+
return false;
|
|
517
|
+
if (typeNameOf(el) === 'org_docx4j_wml.R')
|
|
518
|
+
return ((_a = v.content) !== null && _a !== void 0 ? _a : []).some((item) => itemTextOf(item) !== undefined);
|
|
519
|
+
const kind = revisionKindOf(el);
|
|
520
|
+
if (kind === 'del' || kind === 'moveFrom')
|
|
521
|
+
return false; // deleted text is no text in the accepted view
|
|
522
|
+
return ((_b = runItemsOf(v)) !== null && _b !== void 0 ? _b : []).some(hasText);
|
|
337
523
|
}
|
|
338
524
|
/** A `w:ins` or `w:moveTo` accepted: its runs take its place. */
|
|
339
525
|
function unwrap(t) {
|
|
@@ -377,7 +563,7 @@ function dropMark(paragraph, which) {
|
|
|
377
563
|
*/
|
|
378
564
|
export function joinWithNext(paragraph, fallbackToPrevious = false) {
|
|
379
565
|
var _a, _b, _c, _d, _e;
|
|
380
|
-
const container = paragraph.container;
|
|
566
|
+
const container = currentOwner(paragraph.container, paragraph.element);
|
|
381
567
|
const i = container.indexOf(paragraph.element);
|
|
382
568
|
const next = i >= 0 ? container[i + 1] : undefined;
|
|
383
569
|
const p = paragraph.p;
|
|
@@ -800,8 +986,17 @@ function sectionText(items, end) {
|
|
|
800
986
|
.map((el) => textOfView(el.value, { view: 'accepted' })).join('\r');
|
|
801
987
|
}
|
|
802
988
|
function tokensOfRunLevel(paragraph, items, out) {
|
|
803
|
-
var _a, _b;
|
|
804
|
-
for (
|
|
989
|
+
var _a, _b, _c;
|
|
990
|
+
for (let i = 0; i < items.length; i++) {
|
|
991
|
+
const el = items[i];
|
|
992
|
+
// an inline control or custom XML element that is itself an insertion: a piece, then what is in it
|
|
993
|
+
const inserted = holderInsertionAt(items, i, paragraph);
|
|
994
|
+
if (inserted) {
|
|
995
|
+
out.push(inserted);
|
|
996
|
+
tokensOfRunLevel(paragraph, (_a = childrenOf(items[i + 1].value)) !== null && _a !== void 0 ? _a : [], out);
|
|
997
|
+
i += 2;
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
805
1000
|
const kind = revisionKindOf(el);
|
|
806
1001
|
if (kind !== undefined) {
|
|
807
1002
|
// moved text is content Office JS cannot list (checks 16, 17), and is kept apart
|
|
@@ -824,17 +1019,27 @@ function tokensOfRunLevel(paragraph, items, out) {
|
|
|
824
1019
|
continue;
|
|
825
1020
|
}
|
|
826
1021
|
if (typeNameOf(el) === 'org_docx4j_wml.R') {
|
|
827
|
-
// a run whose formatting changed is a piece of its own; one that did not keeps pieces apart
|
|
1022
|
+
// a run whose formatting changed is a piece of its own; one that did not keeps pieces apart -
|
|
1023
|
+
// if it has text: a run holding only a comment reference does not (check 32: one author's two
|
|
1024
|
+
// w:ins with the reference run between them listed as one change)
|
|
828
1025
|
const run = el.value;
|
|
829
|
-
if ((
|
|
1026
|
+
if ((_b = run.rPr) === null || _b === void 0 ? void 0 : _b.rPrChange)
|
|
830
1027
|
out.push(new TrackedChange({ kind: 'runProperties', run, value: run.rPr.rPrChange }, paragraph));
|
|
831
|
-
else if (((
|
|
1028
|
+
else if (((_c = run.content) !== null && _c !== void 0 ? _c : []).some((item) => itemTextOf(item) !== undefined))
|
|
832
1029
|
out.push(BREAK);
|
|
833
1030
|
continue;
|
|
834
1031
|
}
|
|
1032
|
+
// a run holder that is not itself an insertion - a hyperlink, a field, a control or custom XML
|
|
1033
|
+
// element that was there - keeps the insertions inside it apart from those outside: Office JS
|
|
1034
|
+
// listed "before ", "link" and " after" as three changes over a w:ins in a w:hyperlink, and the same
|
|
1035
|
+
// over a w:fldSimple and an unmarked inline w:sdt (check 30, part C), against one change over an
|
|
1036
|
+
// inserted control (above) and over Word's own one-w:ins forms
|
|
835
1037
|
const nested = runItemsOf(el.value);
|
|
836
|
-
if (nested)
|
|
1038
|
+
if (nested) {
|
|
1039
|
+
out.push(BREAK);
|
|
837
1040
|
tokensOfRunLevel(paragraph, nested, out);
|
|
1041
|
+
out.push(BREAK);
|
|
1042
|
+
}
|
|
838
1043
|
}
|
|
839
1044
|
}
|
|
840
1045
|
/**
|
|
@@ -850,6 +1055,13 @@ function groupable(change) {
|
|
|
850
1055
|
return t.revision;
|
|
851
1056
|
if (t.kind === 'runProperties' || t.kind === 'markProperties')
|
|
852
1057
|
return 'format';
|
|
1058
|
+
if (t.kind === 'holder')
|
|
1059
|
+
return 'ins';
|
|
1060
|
+
// an inserted or deleted row groups with rows and text touching it: Office JS lists an inserted
|
|
1061
|
+
// table of three rows, with the inserted paragraphs before and after it, as one change, and rows
|
|
1062
|
+
// added to a table that was there as one change per touching run of them (check 31)
|
|
1063
|
+
if (t.kind === 'row')
|
|
1064
|
+
return t.row;
|
|
853
1065
|
return undefined;
|
|
854
1066
|
}
|
|
855
1067
|
/**
|
|
@@ -894,13 +1106,13 @@ export function groupTouching(tokens) {
|
|
|
894
1106
|
* The `w:trPr/w:ins` and `w:trPr/w:del` revisions of a table row. `inner` is the revision markup
|
|
895
1107
|
* of the row's own cells, which the row's change owns rather than reporting separately.
|
|
896
1108
|
*/
|
|
897
|
-
export function trackedChangesOfRow(tr, owner, inner = []) {
|
|
1109
|
+
export function trackedChangesOfRow(tr, owner, inner = [], table) {
|
|
898
1110
|
const trPr = tr.value.trPr;
|
|
899
1111
|
const out = [];
|
|
900
1112
|
if (trPr === null || trPr === void 0 ? void 0 : trPr.ins)
|
|
901
|
-
out.push(new TrackedChange({ kind: 'row', row: 'ins', tr, owner, value: trPr.ins, inner }, undefined));
|
|
1113
|
+
out.push(new TrackedChange({ kind: 'row', row: 'ins', tr, owner, value: trPr.ins, inner, table }, undefined));
|
|
902
1114
|
if (trPr === null || trPr === void 0 ? void 0 : trPr.del)
|
|
903
|
-
out.push(new TrackedChange({ kind: 'row', row: 'del', tr, owner, value: trPr.del, inner }, undefined));
|
|
1115
|
+
out.push(new TrackedChange({ kind: 'row', row: 'del', tr, owner, value: trPr.del, inner, table }, undefined));
|
|
904
1116
|
return out;
|
|
905
1117
|
}
|
|
906
1118
|
// --- CR-002 section 35: tables, cells, marks and sections --------------------------------------------
|
|
@@ -996,17 +1208,26 @@ function restoreSection(sectPr, change) {
|
|
|
996
1208
|
* cannot list (check 27: `getTrackedChanges` throws); a `w:numberingChange`, which Word no longer
|
|
997
1209
|
* writes and drops when one is put in, and whose record is the old number's text, so that a reject
|
|
998
1210
|
* too can only drop it; and a table's records that change nothing. A merge rejected gets the merge it
|
|
999
|
-
* recorded back (docx4j's reading; unmeasured).
|
|
1211
|
+
* recorded back (docx4j's reading; unmeasured). A `w:customXmlInsRangeStart` or `End` left without
|
|
1212
|
+
* the form `holderInsertionAt` lists marks nothing that can be found, and goes either way.
|
|
1000
1213
|
*/
|
|
1001
1214
|
export function resolveUnlisted(items, what) {
|
|
1002
1215
|
const visit = (list) => {
|
|
1003
|
-
var _a;
|
|
1004
|
-
|
|
1216
|
+
var _a, _b;
|
|
1217
|
+
if (!list)
|
|
1218
|
+
return;
|
|
1219
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
1220
|
+
const name = (_a = list[i].name) === null || _a === void 0 ? void 0 : _a.localPart;
|
|
1221
|
+
if (name === 'customXmlInsRangeStart' || name === 'customXmlInsRangeEnd')
|
|
1222
|
+
list.splice(i, 1);
|
|
1223
|
+
}
|
|
1224
|
+
for (const el of list) {
|
|
1005
1225
|
const tn = typeNameOf(el);
|
|
1006
1226
|
if (tn === 'org_docx4j_wml.P') {
|
|
1007
|
-
const numPr = (
|
|
1227
|
+
const numPr = (_b = el.value.pPr) === null || _b === void 0 ? void 0 : _b.numPr;
|
|
1008
1228
|
if (numPr === null || numPr === void 0 ? void 0 : numPr.numberingChange)
|
|
1009
1229
|
delete numPr.numberingChange;
|
|
1230
|
+
sweepMarkers(el.value.content);
|
|
1010
1231
|
continue;
|
|
1011
1232
|
}
|
|
1012
1233
|
if (tn === 'org_docx4j_wml.Tbl') {
|
|
@@ -1030,6 +1251,22 @@ export function resolveUnlisted(items, what) {
|
|
|
1030
1251
|
};
|
|
1031
1252
|
visit(items);
|
|
1032
1253
|
}
|
|
1254
|
+
/** Stray `w:customXmlInsRangeStart` / `End` markers taken out of run-level content, through its holders and revisions. */
|
|
1255
|
+
function sweepMarkers(items) {
|
|
1256
|
+
var _a;
|
|
1257
|
+
if (!items)
|
|
1258
|
+
return;
|
|
1259
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
1260
|
+
const name = (_a = items[i].name) === null || _a === void 0 ? void 0 : _a.localPart;
|
|
1261
|
+
if (name === 'customXmlInsRangeStart' || name === 'customXmlInsRangeEnd') {
|
|
1262
|
+
items.splice(i, 1);
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
const v = items[i].value;
|
|
1266
|
+
if (typeof v === 'object' && v !== null)
|
|
1267
|
+
sweepMarkers(runItemsOf(v));
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1033
1270
|
function resolveCellMerge(tcPr, what) {
|
|
1034
1271
|
const change = tcPr.cellMerge;
|
|
1035
1272
|
delete tcPr.cellMerge;
|
|
@@ -13,7 +13,7 @@ export { contentOf, isFlatOpc, rewriteRelationshipIds, type OoxmlOptions } from
|
|
|
13
13
|
export { type SearchOptions, searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
|
|
14
14
|
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf, type TextSegment, type Located, type TextView, type TextViewOptions, type RevisionKind, type RevisionHolder } from './tree.mjs';
|
|
15
15
|
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext, type TrackedChangeType, type TrackedChangeTarget } from './TrackedChange.mjs';
|
|
16
|
-
export { ChangeTracker, trackerOf, calendarOf, dateOf, wordCalendarOf, revisionDateOf, copyRPr, markDeleted, markInserted, highestAnnotationId, MARKUP_TYPES, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, type ChangeTrackingMode, type TrackingHost, type TrackingScope, type TrackedPart, } from './tracking.mjs';
|
|
16
|
+
export { ChangeTracker, trackerOf, calendarOf, dateOf, wordCalendarOf, revisionDateOf, copyRPr, markDeleted, markInserted, highestAnnotationId, MARKUP_TYPES, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, trackInsertedBlocks, wrapNewRuns, wrapInsertedRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, type ChangeTrackingMode, type TrackingHost, type TrackingScope, type TrackedPart, } from './tracking.mjs';
|
|
17
17
|
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS, type Element, type Wrapper, type WmlOptions, type Raw, type Interpolated, type RunOptions, type RunFormatting, type ParagraphOptions, type TableOptions, type CellOptions, type SdtKind, type SdtForm, type SdtOptions } from '@docx4j/generated-objects-ts/builders/wml';
|
|
18
18
|
export { StylesFacade, type StylePackageLike } from './stylesFacade.mjs';
|
|
19
19
|
export { bindSnapshot, boundsOf, pathOf, type Bound, type BoundSnapshot } from './binder.mjs';
|
|
@@ -16,7 +16,7 @@ export { searchPattern, findAll, matchesOf, expandReplacement } from './search.m
|
|
|
16
16
|
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf } from './tree.mjs';
|
|
17
17
|
// change tracking (CR-002 phase F)
|
|
18
18
|
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext } from './TrackedChange.mjs';
|
|
19
|
-
export { ChangeTracker, trackerOf, calendarOf, dateOf, wordCalendarOf, revisionDateOf, copyRPr, markDeleted, markInserted, highestAnnotationId, MARKUP_TYPES, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, } from './tracking.mjs';
|
|
19
|
+
export { ChangeTracker, trackerOf, calendarOf, dateOf, wordCalendarOf, revisionDateOf, copyRPr, markDeleted, markInserted, highestAnnotationId, MARKUP_TYPES, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, trackInsertedBlocks, wrapNewRuns, wrapInsertedRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, } from './tracking.mjs';
|
|
20
20
|
// The objects package's builders, re-exported so that one import serves the content API and the tree it works on.
|
|
21
21
|
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
|
|
22
22
|
export { StylesFacade } from './stylesFacade.mjs';
|
|
@@ -3,19 +3,25 @@ import { linkParents } from './tree.mjs';
|
|
|
3
3
|
import { parseXml } from '../../xml/dom.mjs';
|
|
4
4
|
import { DEFAULT_STYLES_XML } from '../../parts/wml/defaultStyles.mjs';
|
|
5
5
|
import { SPLICEABLE_STYLES_XML } from '../../parts/wml/spliceableStyles.mjs';
|
|
6
|
+
import { commentStyles } from '../../parts/wml/commentStyles.mjs';
|
|
7
|
+
import { placeholderStyle } from '../../parts/wml/placeholderStyle.mjs';
|
|
6
8
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
7
9
|
/**
|
|
8
10
|
* Where a definition is looked up, unmarshalled once and never handed out (a copy is spliced in):
|
|
9
11
|
* the defaults `createPackage()` writes, and then the nine styles docx4j's own `styles.xml` carries
|
|
10
12
|
* **commented out** - which is why a created document has no `FootnoteText` although the file
|
|
11
|
-
* appears to contain one, and why this facade exists (CR-002 section 22.2)
|
|
13
|
+
* appears to contain one, and why this facade exists (CR-002 section 22.2) - with Word's two comment
|
|
14
|
+
* styles and its `PlaceholderText` after them.
|
|
12
15
|
*/
|
|
13
16
|
let sources;
|
|
14
17
|
function styleSources() {
|
|
15
18
|
return (sources !== null && sources !== void 0 ? sources : (sources = (async () => {
|
|
16
19
|
const read = async (xml) => { var _a; return (_a = (await unmarshalNode(parseXml(xml))).value.style) !== null && _a !== void 0 ? _a : []; };
|
|
17
20
|
const defaults = await read(DEFAULT_STYLES_XML);
|
|
18
|
-
|
|
21
|
+
// and Word's two comment styles, which the comment parts add when they are made, for a caller
|
|
22
|
+
// that makes the comment itself (CR-002 section 37), and Word's PlaceholderText, which a
|
|
23
|
+
// placeholder run names (CR-002 section 40)
|
|
24
|
+
return { defaults, all: [...defaults, ...(await read(SPLICEABLE_STYLES_XML)), ...commentStyles(), placeholderStyle()] };
|
|
19
25
|
})()));
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
@@ -99,7 +105,7 @@ function closureOf(wanted, present, source) {
|
|
|
99
105
|
seen.add(id);
|
|
100
106
|
const template = source.find((s) => s.styleId === id);
|
|
101
107
|
if (template === undefined) {
|
|
102
|
-
throw new Docx4JException(`No definition to splice for the style ${id}: neither docx4j's default styles
|
|
108
|
+
throw new Docx4JException(`No definition to splice for the style ${id}: neither docx4j's default styles, the nine it comments out, the two comment styles nor PlaceholderText carry one. Define it yourself on the styles part.`);
|
|
103
109
|
}
|
|
104
110
|
// what it is based on and linked to must be there too, and before it reads better in the part
|
|
105
111
|
for (const dependency of [(_a = template.basedOn) === null || _a === void 0 ? void 0 : _a.val, (_b = template.link) === null || _b === void 0 ? void 0 : _b.val]) {
|
|
@@ -92,6 +92,20 @@ export declare function canonical(value: unknown): string;
|
|
|
92
92
|
export interface TrackedPart {
|
|
93
93
|
readonly contents?: unknown;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Makes sure the part's root lists a prefix in `mc:Ignorable`, appending it when absent, so that
|
|
97
|
+
* content in that prefix's namespace may be written in it; the facade then declares the prefix.
|
|
98
|
+
* This is docx4j's pattern - the writer of the content adds its prefix
|
|
99
|
+
* (`Paginate.declareW14Ignorable`) - and Jason's decision (CR-002 section 29). Since objects 0.3.1
|
|
100
|
+
* (its CR-008) the marshaller does it for every writer as well; these calls stay as the writer's
|
|
101
|
+
* own statement. False when there is no unmarshalled root to put it on. Every part a
|
|
102
|
+
* `Body` is over (document, header, footer, notes, comments) has a root that binds `mc:Ignorable`.
|
|
103
|
+
*
|
|
104
|
+
* The prefix must be the facade's conventional one for its namespace (`w15`, `w16du`): an
|
|
105
|
+
* application that does not know the namespace (Word 2010 and `w15`) opens the part only when the
|
|
106
|
+
* prefix is ignorable, as Word's own files declare it (CR-002 section 40).
|
|
107
|
+
*/
|
|
108
|
+
export declare function declareIgnorable(part: TrackedPart | undefined, prefix: string): boolean;
|
|
95
109
|
/**
|
|
96
110
|
* The per-package writer of revision markup. Created by the package while
|
|
97
111
|
* `changeTrackingMode` is not `Off`; every content-API mutation asks its `Body` for one and,
|
|
@@ -174,16 +188,62 @@ export declare class ChangeTracker {
|
|
|
174
188
|
markRowDeleted(tr: wml.Tr): void;
|
|
175
189
|
}
|
|
176
190
|
/**
|
|
177
|
-
* A whole paragraph inserted: the mark is marked inserted and every run of it
|
|
178
|
-
* `w:ins
|
|
179
|
-
*
|
|
191
|
+
* A whole paragraph inserted: the mark is marked inserted (unless it already is) and every run of it
|
|
192
|
+
* goes into a `w:ins` - the runs in its hyperlinks, inline content controls, fields and smart tags as
|
|
193
|
+
* well (`wrapNewRuns`). Word, splitting a paragraph, marks the *first* paragraph's mark instead and
|
|
194
|
+
* leaves the new one the original mark; marking the new paragraph's own mark is the same document once
|
|
180
195
|
* accepted or rejected and keeps the edit to the element that was added (CR-002 section 13).
|
|
181
196
|
*/
|
|
182
197
|
export declare function trackInsertedParagraph(tracker: ChangeTracker, p: wml.P): void;
|
|
183
|
-
/**
|
|
198
|
+
/**
|
|
199
|
+
* Every run of the paragraph not already in a revision, wrapped in one `w:ins` per group of touching
|
|
200
|
+
* runs - at the top level and inside the run-level holders, where Word's form decides (`test/README.md`
|
|
201
|
+
* check 30, CR-002 section 37 item 7): in a hyperlink or a simple field the `w:ins` goes inside, since
|
|
202
|
+
* neither can be in one (`CT_RunTrackChange` holds `EG_ContentRunContent` only); a smart tag goes
|
|
203
|
+
* *into* the `w:ins` with the runs beside it, its own runs plain; an inline content control or custom
|
|
204
|
+
* XML element keeps the `w:ins` inside and is itself marked inserted (`markHolderInserted`). Before,
|
|
205
|
+
* only the top level was wrapped, so that rejecting an inserted paragraph left a link's text behind
|
|
206
|
+
* (the editor's finding on 0.3.0, CR-002 section 37 item 4).
|
|
207
|
+
*/
|
|
184
208
|
export declare function wrapNewRuns(tracker: ChangeTracker, p: wml.P): void;
|
|
185
|
-
/**
|
|
209
|
+
/**
|
|
210
|
+
* `wrapNewRuns` over run-level items that are about to go into a paragraph (`Paragraph.insertItemsAt`):
|
|
211
|
+
* the runs among them, and those in their holders, wrapped in `w:ins`; a content control or custom
|
|
212
|
+
* XML element among them marked inserted. `parent` is what the items' array belongs to.
|
|
213
|
+
*/
|
|
214
|
+
export declare function wrapInsertedRuns(tracker: ChangeTracker, items: Element[] | undefined, parent: object): void;
|
|
215
|
+
/** A whole table inserted: every row is marked inserted and everything in its cells is an insertion (`trackInsertedBlocks`). */
|
|
186
216
|
export declare function trackInsertedTable(tracker: ChangeTracker, tbl: wml.Tbl): void;
|
|
217
|
+
/**
|
|
218
|
+
* Block content inserted, whatever it holds: a paragraph (`trackInsertedParagraph`), a table
|
|
219
|
+
* (`trackInsertedTable`: rows inside row-level content controls, nested tables in its cells), and a
|
|
220
|
+
* block-level content control's or custom XML element's content, recursively, the element itself
|
|
221
|
+
* marked inserted (`markHolderInserted`; `owner` is the array holding `block`, which takes the
|
|
222
|
+
* markers). What `Body.insertElement` and `Table.addRows` track new content by (CR-002 section 37).
|
|
223
|
+
*/
|
|
224
|
+
export declare function trackInsertedBlock(tracker: ChangeTracker, block: Element, owner: Element[]): void;
|
|
225
|
+
/** `trackInsertedBlock` over every item of a list, which is their owner. */
|
|
226
|
+
export declare function trackInsertedBlocks(tracker: ChangeTracker, items: Element[] | undefined): void;
|
|
227
|
+
/**
|
|
228
|
+
* The elements Word marks inserted as a whole with `w:customXmlInsRangeStart` / `End`: a content
|
|
229
|
+
* control or a custom XML element (check 30 measured the control at run and block level; a smart tag
|
|
230
|
+
* goes into the `w:ins` instead, and a hyperlink or field has no form of its own). Row- and cell-level
|
|
231
|
+
* ones are listed for the reader: `trackInsertedTable` walks through them to the rows and cells, and
|
|
232
|
+
* does not mark them.
|
|
233
|
+
*/
|
|
234
|
+
export declare const HOLDER_TYPES: ReadonlySet<string>;
|
|
235
|
+
/** The list a holder's content is in (`w:sdtContent`'s for a control, its own for custom XML), created when absent. */
|
|
236
|
+
export declare function holderItemsOf(value: object): Element[] | undefined;
|
|
237
|
+
/**
|
|
238
|
+
* A content control or custom XML element inserted under tracking, as Word writes it (check 30): a
|
|
239
|
+
* `w:customXmlInsRangeStart` before the element with its `w:customXmlInsRangeEnd` first inside its
|
|
240
|
+
* content, and a second start last inside with its end after the element. Rejecting takes the element
|
|
241
|
+
* away and leaves its content where it stood (`TrackedChange`'s `holder` target); without the markers
|
|
242
|
+
* an element holding only an insertion reads as one that was there before and was typed into, which
|
|
243
|
+
* rejecting keeps (check 30, existing-control-typed). `inside` tracks the content between the two
|
|
244
|
+
* pairs, so that the ids run in document order as Word's do.
|
|
245
|
+
*/
|
|
246
|
+
export declare function markHolderInserted(tracker: ChangeTracker, holder: Element, owner: Element[], inside: () => void): void;
|
|
187
247
|
/** The paragraph mark's run properties (`w:pPr/w:rPr`), created when absent. */
|
|
188
248
|
export declare function paraRPrOf(p: wml.P): wml.ParaRPr;
|
|
189
249
|
/** The row's properties (`w:trPr`), created when absent. */
|