docxmlater 10.0.3 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +3 -2
  2. package/dist/core/Document.d.ts +22 -0
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +170 -26
  5. package/dist/core/Document.js.map +1 -1
  6. package/dist/core/DocumentParser.d.ts.map +1 -1
  7. package/dist/core/DocumentParser.js +90 -2
  8. package/dist/core/DocumentParser.js.map +1 -1
  9. package/dist/elements/Hyperlink.d.ts +6 -0
  10. package/dist/elements/Hyperlink.d.ts.map +1 -1
  11. package/dist/elements/Hyperlink.js +23 -0
  12. package/dist/elements/Hyperlink.js.map +1 -1
  13. package/dist/elements/Paragraph.d.ts +8 -0
  14. package/dist/elements/Paragraph.d.ts.map +1 -1
  15. package/dist/elements/Paragraph.js +25 -1
  16. package/dist/elements/Paragraph.js.map +1 -1
  17. package/dist/elements/StructuredDocumentTag.d.ts +23 -1
  18. package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
  19. package/dist/elements/StructuredDocumentTag.js +97 -0
  20. package/dist/elements/StructuredDocumentTag.js.map +1 -1
  21. package/dist/elements/TableCell.d.ts +5 -0
  22. package/dist/elements/TableCell.d.ts.map +1 -1
  23. package/dist/elements/TableCell.js +13 -0
  24. package/dist/elements/TableCell.js.map +1 -1
  25. package/dist/elements/TableRow.d.ts +3 -0
  26. package/dist/elements/TableRow.d.ts.map +1 -1
  27. package/dist/elements/TableRow.js +10 -0
  28. package/dist/elements/TableRow.js.map +1 -1
  29. package/dist/formatting/AbstractNumbering.d.ts +4 -0
  30. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  31. package/dist/formatting/AbstractNumbering.js +15 -0
  32. package/dist/formatting/AbstractNumbering.js.map +1 -1
  33. package/dist/formatting/NumberingInstance.d.ts +6 -0
  34. package/dist/formatting/NumberingInstance.d.ts.map +1 -1
  35. package/dist/formatting/NumberingInstance.js +55 -1
  36. package/dist/formatting/NumberingInstance.js.map +1 -1
  37. package/dist/formatting/NumberingLevel.d.ts +4 -1
  38. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  39. package/dist/formatting/NumberingLevel.js +17 -0
  40. package/dist/formatting/NumberingLevel.js.map +1 -1
  41. package/dist/formatting/Style.d.ts +6 -0
  42. package/dist/formatting/Style.d.ts.map +1 -1
  43. package/dist/formatting/Style.js +20 -0
  44. package/dist/formatting/Style.js.map +1 -1
  45. package/dist/formatting/StylesManager.d.ts +23 -0
  46. package/dist/formatting/StylesManager.d.ts.map +1 -1
  47. package/dist/formatting/StylesManager.js +65 -0
  48. package/dist/formatting/StylesManager.js.map +1 -1
  49. package/dist/index.d.ts +2 -2
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
  53. package/dist/tracking/DocumentTrackingContext.js +30 -7
  54. package/dist/tracking/DocumentTrackingContext.js.map +1 -1
  55. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  56. package/dist/utils/InMemoryRevisionAcceptor.js +22 -1
  57. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  58. package/dist/utils/SelectiveRevisionAcceptor.d.ts +1 -0
  59. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  60. package/dist/utils/SelectiveRevisionAcceptor.js +46 -0
  61. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/core/Document.ts +287 -31
  64. package/src/core/DocumentParser.ts +110 -2
  65. package/src/elements/Hyperlink.ts +47 -0
  66. package/src/elements/Paragraph.ts +61 -1
  67. package/src/elements/StructuredDocumentTag.ts +230 -1
  68. package/src/elements/TableCell.ts +36 -1
  69. package/src/elements/TableRow.ts +24 -1
  70. package/src/formatting/AbstractNumbering.ts +31 -0
  71. package/src/formatting/NumberingInstance.ts +88 -1
  72. package/src/formatting/NumberingLevel.ts +37 -3
  73. package/src/formatting/Style.ts +46 -0
  74. package/src/formatting/StylesManager.ts +125 -0
  75. package/src/index.ts +2 -2
  76. package/src/tracking/DocumentTrackingContext.ts +38 -7
  77. package/src/utils/InMemoryRevisionAcceptor.ts +29 -1
  78. package/src/utils/SelectiveRevisionAcceptor.ts +70 -0
@@ -343,16 +343,47 @@ export class DocumentTrackingContext implements TrackingContext {
343
343
  }
344
344
 
345
345
  // Apply tblPrChange to each Table
346
+ // Per ECMA-376 §17.13.5.36, tblPrChange must contain FULL previous tblPr,
347
+ // not just the delta of changed properties.
346
348
  for (const [table, changes] of tableChanges) {
347
- this.applyElementPrChange(changes, (prevProps, getNextId, date) => {
348
- const existing = table.getTblPrChange();
349
- if (existing) {
350
- const merged = { ...(existing.previousProperties || {}), ...prevProps };
351
- table.setTblPrChange({ ...existing, previousProperties: merged });
349
+ // Build full snapshot: start from current formatting, roll back changed properties
350
+ const currentFormatting = table.getFormatting();
351
+ const fullPrevProps: Record<string, unknown> = {};
352
+
353
+ for (const [key, value] of Object.entries(currentFormatting)) {
354
+ if (value !== undefined) {
355
+ fullPrevProps[key] = value;
356
+ }
357
+ }
358
+
359
+ // Roll back changed properties to their previous values
360
+ let latestTimestamp = 0;
361
+ for (const change of changes) {
362
+ if (change.previousValue !== undefined) {
363
+ fullPrevProps[change.property] = change.previousValue;
352
364
  } else {
353
- table.setTblPrChange({ author: this.author, date, id: String(getNextId()), previousProperties: prevProps });
365
+ delete fullPrevProps[change.property];
354
366
  }
355
- });
367
+ if (change.timestamp > latestTimestamp) {
368
+ latestTimestamp = change.timestamp;
369
+ }
370
+ }
371
+
372
+ const date = formatDateForXml(new Date(latestTimestamp));
373
+
374
+ const existing = table.getTblPrChange();
375
+ if (existing) {
376
+ // Merge: existing previous state takes precedence (it's the ORIGINAL baseline)
377
+ const merged = { ...fullPrevProps, ...(existing.previousProperties || {}) };
378
+ table.setTblPrChange({ ...existing, previousProperties: merged });
379
+ } else {
380
+ table.setTblPrChange({
381
+ author: this.author,
382
+ date,
383
+ id: String(this.revisionManager.consumeNextId()),
384
+ previousProperties: fullPrevProps,
385
+ });
386
+ }
356
387
  }
357
388
 
358
389
  // Apply trPrChange to each TableRow
@@ -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
- return content.some((item) => item instanceof Revision);
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
  /**