docxmlater 10.0.3 → 10.0.4
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/README.md +3 -2
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +26 -1
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +8 -0
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +25 -1
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js +22 -1
- package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.d.ts +1 -0
- package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/SelectiveRevisionAcceptor.js +46 -0
- package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
- package/package.json +1 -1
- package/src/core/DocumentParser.ts +34 -1
- package/src/elements/Paragraph.ts +61 -1
- package/src/utils/InMemoryRevisionAcceptor.ts +29 -1
- package/src/utils/SelectiveRevisionAcceptor.ts +70 -0
|
@@ -279,6 +279,15 @@ export interface ParagraphFormatting {
|
|
|
279
279
|
/** Date when the paragraph mark was deleted */
|
|
280
280
|
date: Date;
|
|
281
281
|
};
|
|
282
|
+
/** Paragraph mark insertion tracking (for inserted ¶ symbols) */
|
|
283
|
+
paragraphMarkInsertion?: {
|
|
284
|
+
/** Unique revision ID */
|
|
285
|
+
id: number;
|
|
286
|
+
/** Author who inserted the paragraph mark */
|
|
287
|
+
author: string;
|
|
288
|
+
/** Date when the paragraph mark was inserted */
|
|
289
|
+
date: Date;
|
|
290
|
+
};
|
|
282
291
|
/** True when the original XML had numId=0 (explicitly suppressed numbering) */
|
|
283
292
|
numberingSuppressed?: boolean;
|
|
284
293
|
}
|
|
@@ -2800,6 +2809,42 @@ export class Paragraph {
|
|
|
2800
2809
|
return !!this.formatting.paragraphMarkDeletion;
|
|
2801
2810
|
}
|
|
2802
2811
|
|
|
2812
|
+
/**
|
|
2813
|
+
* Marks the paragraph mark (¶ symbol) as inserted via tracked changes.
|
|
2814
|
+
* This adds a `w:ins` element inside `w:pPr/w:rPr` indicating the insertion
|
|
2815
|
+
* of the ¶ symbol.
|
|
2816
|
+
*
|
|
2817
|
+
* @param id - Unique revision ID
|
|
2818
|
+
* @param author - Author who inserted the paragraph mark
|
|
2819
|
+
* @param date - Date when the insertion occurred (defaults to now)
|
|
2820
|
+
* @returns This paragraph for chaining
|
|
2821
|
+
*/
|
|
2822
|
+
markParagraphMarkAsInserted(id: number, author: string, date?: Date): this {
|
|
2823
|
+
this.formatting.paragraphMarkInsertion = {
|
|
2824
|
+
id,
|
|
2825
|
+
author,
|
|
2826
|
+
date: date || new Date(),
|
|
2827
|
+
};
|
|
2828
|
+
return this;
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
/**
|
|
2832
|
+
* Clears the paragraph mark insertion marker
|
|
2833
|
+
* @returns This paragraph for chaining
|
|
2834
|
+
*/
|
|
2835
|
+
clearParagraphMarkInsertion(): this {
|
|
2836
|
+
delete this.formatting.paragraphMarkInsertion;
|
|
2837
|
+
return this;
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
/**
|
|
2841
|
+
* Checks if the paragraph mark is marked as inserted
|
|
2842
|
+
* @returns True if the paragraph mark is inserted
|
|
2843
|
+
*/
|
|
2844
|
+
isParagraphMarkInserted(): boolean {
|
|
2845
|
+
return !!this.formatting.paragraphMarkInsertion;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2803
2848
|
/**
|
|
2804
2849
|
* Converts the paragraph to WordprocessingML XML element
|
|
2805
2850
|
*
|
|
@@ -3137,7 +3182,8 @@ export class Paragraph {
|
|
|
3137
3182
|
// Per CT_PPr, w:rPr comes after all CT_PPrBase elements and before w:sectPr/w:pPrChange
|
|
3138
3183
|
if (
|
|
3139
3184
|
this.formatting.paragraphMarkRunProperties ||
|
|
3140
|
-
this.formatting.paragraphMarkDeletion
|
|
3185
|
+
this.formatting.paragraphMarkDeletion ||
|
|
3186
|
+
this.formatting.paragraphMarkInsertion
|
|
3141
3187
|
) {
|
|
3142
3188
|
const rPrChildren: XMLElement[] = [];
|
|
3143
3189
|
|
|
@@ -3156,6 +3202,20 @@ export class Paragraph {
|
|
|
3156
3202
|
}
|
|
3157
3203
|
}
|
|
3158
3204
|
|
|
3205
|
+
// Per CT_ParaRPr schema, w:ins precedes w:del in the sequence
|
|
3206
|
+
// Add insertion marker if the paragraph mark is inserted (w:ins)
|
|
3207
|
+
// Per ECMA-376 Part 1 §17.13.5.18 - tracks insertion of paragraph mark
|
|
3208
|
+
if (this.formatting.paragraphMarkInsertion) {
|
|
3209
|
+
const ins = this.formatting.paragraphMarkInsertion;
|
|
3210
|
+
rPrChildren.push(
|
|
3211
|
+
XMLBuilder.wSelf("ins", {
|
|
3212
|
+
"w:id": ins.id.toString(),
|
|
3213
|
+
"w:author": ins.author,
|
|
3214
|
+
"w:date": formatDateForXml(ins.date),
|
|
3215
|
+
})
|
|
3216
|
+
);
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3159
3219
|
// Add deletion marker if the paragraph mark is deleted (w:del)
|
|
3160
3220
|
// Per ECMA-376 Part 1 §17.13.5.14 - tracks deletion of paragraph mark
|
|
3161
3221
|
if (this.formatting.paragraphMarkDeletion) {
|
|
@@ -568,6 +568,26 @@ function acceptRevisionsInParagraph(
|
|
|
568
568
|
}
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
+
// Clear paragraph mark deletion tracking if accepting deletions
|
|
572
|
+
// This removes the w:del element from w:pPr/w:rPr
|
|
573
|
+
if (options.acceptDeletions) {
|
|
574
|
+
const formatting = paragraph.getFormatting();
|
|
575
|
+
if (formatting.paragraphMarkDeletion) {
|
|
576
|
+
paragraph.clearParagraphMarkDeletion();
|
|
577
|
+
result.deletionsAccepted++;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Clear paragraph mark insertion tracking if accepting insertions
|
|
582
|
+
// This removes the w:ins element from w:pPr/w:rPr
|
|
583
|
+
if (options.acceptInsertions) {
|
|
584
|
+
const formatting = paragraph.getFormatting();
|
|
585
|
+
if (formatting.paragraphMarkInsertion) {
|
|
586
|
+
paragraph.clearParagraphMarkInsertion();
|
|
587
|
+
result.insertionsAccepted++;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
571
591
|
return result;
|
|
572
592
|
}
|
|
573
593
|
|
|
@@ -576,7 +596,15 @@ function acceptRevisionsInParagraph(
|
|
|
576
596
|
*/
|
|
577
597
|
export function paragraphHasRevisions(paragraph: Paragraph): boolean {
|
|
578
598
|
const content = paragraph.getContent();
|
|
579
|
-
|
|
599
|
+
if (content.some((item) => item instanceof Revision)) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
// Also check paragraph mark revision markers in w:pPr/w:rPr
|
|
603
|
+
const formatting = paragraph.getFormatting();
|
|
604
|
+
if (formatting.paragraphMarkDeletion || formatting.paragraphMarkInsertion) {
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
return false;
|
|
580
608
|
}
|
|
581
609
|
|
|
582
610
|
/**
|
|
@@ -238,6 +238,76 @@ export class SelectiveRevisionAcceptor {
|
|
|
238
238
|
|
|
239
239
|
// Replace paragraph content with the transformed content
|
|
240
240
|
paragraph.setContent(newContent);
|
|
241
|
+
|
|
242
|
+
// Handle paragraph mark revision markers (w:del/w:ins in w:pPr/w:rPr)
|
|
243
|
+
// Both accept and reject clear the marker — these are metadata-only markers (no content),
|
|
244
|
+
// so there is no content to add or remove, only the marker itself to clear.
|
|
245
|
+
const formatting = paragraph.getFormatting();
|
|
246
|
+
if (formatting.paragraphMarkDeletion) {
|
|
247
|
+
const del = formatting.paragraphMarkDeletion;
|
|
248
|
+
if (this.matchesMarkerCriteria(del, criteria)) {
|
|
249
|
+
paragraph.clearParagraphMarkDeletion();
|
|
250
|
+
processedIds.push(del.id.toString());
|
|
251
|
+
} else {
|
|
252
|
+
remainingIds.push(del.id.toString());
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (formatting.paragraphMarkInsertion) {
|
|
256
|
+
const ins = formatting.paragraphMarkInsertion;
|
|
257
|
+
if (this.matchesMarkerCriteria(ins, criteria)) {
|
|
258
|
+
paragraph.clearParagraphMarkInsertion();
|
|
259
|
+
processedIds.push(ins.id.toString());
|
|
260
|
+
} else {
|
|
261
|
+
remainingIds.push(ins.id.toString());
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Check if a paragraph mark revision marker matches the given criteria.
|
|
268
|
+
* Simplified version of matchesCriteria for non-Revision marker objects.
|
|
269
|
+
*/
|
|
270
|
+
private static matchesMarkerCriteria(
|
|
271
|
+
marker: { id: number; author: string; date: Date },
|
|
272
|
+
criteria: SelectionCriteria
|
|
273
|
+
): boolean {
|
|
274
|
+
// If no criteria specified, match nothing
|
|
275
|
+
if (
|
|
276
|
+
!criteria.ids &&
|
|
277
|
+
!criteria.types &&
|
|
278
|
+
!criteria.authors &&
|
|
279
|
+
!criteria.dateRange &&
|
|
280
|
+
!criteria.categories &&
|
|
281
|
+
!criteria.custom
|
|
282
|
+
) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Filter by IDs
|
|
287
|
+
if (criteria.ids && !criteria.ids.includes(marker.id)) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Filter by authors
|
|
292
|
+
if (criteria.authors && !criteria.authors.includes(marker.author)) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Filter by date range
|
|
297
|
+
if (criteria.dateRange) {
|
|
298
|
+
if (marker.date < criteria.dateRange.start || marker.date > criteria.dateRange.end) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// types, categories, and custom filters don't apply to paragraph mark markers
|
|
304
|
+
// (they are not Revision objects with a type/category)
|
|
305
|
+
// If criteria only specifies types/categories/custom, markers won't match
|
|
306
|
+
if (criteria.types || criteria.categories || criteria.custom) {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return true;
|
|
241
311
|
}
|
|
242
312
|
|
|
243
313
|
/**
|