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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryRevisionAcceptor.d.ts","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAmB9D,MAAM,WAAW,sBAAsB;IAErC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAKD,MAAM,WAAW,qBAAqB;IAEpC,kBAAkB,EAAE,MAAM,CAAC;IAE3B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,CAAC;IAEtB,uBAAuB,EAAE,MAAM,CAAC;IAEhC,aAAa,EAAE,MAAM,CAAC;IAEtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAyCD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkEzD;AAaD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA2PvB;
|
|
1
|
+
{"version":3,"file":"InMemoryRevisionAcceptor.d.ts","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAmB9D,MAAM,WAAW,sBAAsB;IAErC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAKD,MAAM,WAAW,qBAAqB;IAEpC,kBAAkB,EAAE,MAAM,CAAC;IAE3B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,CAAC;IAEtB,uBAAuB,EAAE,MAAM,CAAC;IAEhC,aAAa,EAAE,MAAM,CAAC;IAEtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAyCD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkEzD;AAaD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA2PvB;AA2JD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAWnE;AAKD,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,EAAE,CAG1E;AAKD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAa7E"}
|
|
@@ -366,11 +366,32 @@ function acceptRevisionsInParagraph(paragraph, options) {
|
|
|
366
366
|
result.propertyChangesAccepted++;
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
+
if (options.acceptDeletions) {
|
|
370
|
+
const formatting = paragraph.getFormatting();
|
|
371
|
+
if (formatting.paragraphMarkDeletion) {
|
|
372
|
+
paragraph.clearParagraphMarkDeletion();
|
|
373
|
+
result.deletionsAccepted++;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (options.acceptInsertions) {
|
|
377
|
+
const formatting = paragraph.getFormatting();
|
|
378
|
+
if (formatting.paragraphMarkInsertion) {
|
|
379
|
+
paragraph.clearParagraphMarkInsertion();
|
|
380
|
+
result.insertionsAccepted++;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
369
383
|
return result;
|
|
370
384
|
}
|
|
371
385
|
function paragraphHasRevisions(paragraph) {
|
|
372
386
|
const content = paragraph.getContent();
|
|
373
|
-
|
|
387
|
+
if (content.some((item) => item instanceof Revision_1.Revision)) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
const formatting = paragraph.getFormatting();
|
|
391
|
+
if (formatting.paragraphMarkDeletion || formatting.paragraphMarkInsertion) {
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
return false;
|
|
374
395
|
}
|
|
375
396
|
function getRevisionsFromParagraph(paragraph) {
|
|
376
397
|
const content = paragraph.getContent();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":";;AA4GA,sDAkEC;AAaD,0DA8PC;AAuID,sDAGC;AAKD,8DAGC;AAKD,oDAaC;AA5kBD,qDAAkD;AAElD,mDAA8D;AAG9D,iEAAkG;AAElG,6CAA0C;AAE1C,qCAAwE;AAKxE,SAAS,SAAS;IAChB,OAAO,IAAA,2BAAkB,EAAC,IAAA,wBAAe,GAAE,EAAE,0BAA0B,CAAC,CAAC;AAC3E,CAAC;AAuCD,MAAM,sBAAsB,GAAmB;IAC7C,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,QAAQ;CACT,CAAC;AAKF,MAAM,uBAAuB,GAAmB;IAC9C,qBAAqB;IACrB,2BAA2B;IAC3B,uBAAuB;IACvB,gCAAgC;IAChC,0BAA0B;IAC1B,2BAA2B;IAC3B,yBAAyB;IACzB,iBAAiB;CAClB,CAAC;AAiBF,SAAgB,qBAAqB,CAAC,GAAW;IAC/C,IAAI,MAAM,GAAG,GAAG,CAAC;IAGjB,MAAM,aAAa,GAAG;QACpB,kEAAkE;QAClE,8DAA8D;QAC9D,8DAA8D;QAC9D,0DAA0D;QAC1D,0EAA0E;QAC1E,sEAAsE;QACtE,0EAA0E;QAC1E,sEAAsE;KACvE,CAAC;IACF,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAGD,MAAM,kBAAkB,GAAG;QACzB,4CAA4C;QAC5C,4CAA4C;QAC5C,gDAAgD;QAChD,oDAAoD;QACpD,8CAA8C;QAC9C,8CAA8C;QAC9C,kDAAkD;QAClD,oDAAoD;QACpD,wDAAwD;KACzD,CAAC;IACF,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAID,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAGjD,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4CAA4C,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;IAGtD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAGlD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC1C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IAG/C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;IAEpD,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD,SAAgB,uBAAuB,CACrC,GAAa,EACb,UAAkC,EAAE;IAEpC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAqC;QAC7C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,IAAI;QAClD,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,IAAI;QAChD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,IAAI,IAAI;QAC5D,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,IAAI;KACvD,CAAC;IAEF,MAAM,MAAM,GAA0B;QACpC,kBAAkB,EAAE,CAAC;QACrB,iBAAiB,EAAE,CAAC;QACpB,aAAa,EAAE,CAAC;QAChB,uBAAuB,EAAE,CAAC;QAC1B,aAAa,EAAE,CAAC;QAChB,kBAAkB,EAAE,CAAC;KACtB,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAIhE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,eAAe,GAAG,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACjD,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,kBAAkB,GAAG,eAAe,CAAC,iBAAiB,EAAE,CAAC;YAC/D,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,MAAM,CAAC,IAAI,CACT,yFAAyF;wBACzF,gEAAgE,EAChE,EAAE,eAAe,EAAE,kBAAkB,CAAC,gBAAgB,EAAE,CACzD,CAAC;gBACJ,CAAC;gBACD,IAAI,kBAAkB,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACjD,MAAM,CAAC,IAAI,CACT,iEAAiE;wBACjE,uDAAuD,EACvD,EAAE,eAAe,EAAE,kBAAkB,CAAC,cAAc,EAAE,CACvD,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAGD,MAAM,UAAU,GAAG,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;QAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;QAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;QACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;IAC5E,CAAC;IAGD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAE3B,IAAI,IAAI,CAAC,qBAAqB,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YACzD,KAAK,CAAC,gBAAgB,EAAE,CAAC;YACzB,MAAM,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAElC,IAAI,IAAI,CAAC,qBAAqB,IAAI,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC;gBACtD,GAAG,CAAC,eAAe,EAAE,CAAC;gBACtB,MAAM,CAAC,uBAAuB,EAAE,CAAC;YACnC,CAAC;YAED,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;gBAElC,IAAI,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;oBACvD,IAAI,CAAC,eAAe,EAAE,CAAC;oBACvB,MAAM,CAAC,uBAAuB,EAAE,CAAC;gBACnC,CAAC;gBAGD,IAAI,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;oBACzD,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACzB,MAAM,CAAC,uBAAuB,EAAE,CAAC;gBACnC,CAAC;gBAGD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;oBAC7C,MAAM,eAAe,GAAG,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;oBACpE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;oBAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;oBAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;oBACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;gBAC5E,CAAC;gBAID,IAAI,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;oBAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;wBAC3B,IAAI,IAAI,EAAE,CAAC;4BACT,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;4BACnD,IAAI,UAAU,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;gCAC5B,IAAI,CAAC,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;gCAG3C,MAAM,CAAC,uBAAuB,EAAE,CAAC;gCACjC,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE;oCACrD,IAAI,EAAE,IAAI,CAAC,IAAI;oCACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;oCACvB,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM;oCAC/B,aAAa,EAAE,UAAU,CAAC,MAAM;iCACjC,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAGD,MAAM,mBAAmB,GAAG,GAAG,CAAC,sBAAsB,EAAE,CAAC;IACzD,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,mBAAmB,CAAC,aAAa,EAAE,CAAC;QACpD,KAAK,MAAM,WAAW,IAAI,OAAO,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAClD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAE/B,IAAI,OAAO,YAAY,qBAAS,EAAE,CAAC;oBACjC,MAAM,eAAe,GAAG,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAClE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;oBAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;oBAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;oBACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;gBAC5E,CAAC;qBAAM,IAAI,OAAO,YAAY,aAAK,EAAE,CAAC;oBAEpC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;wBACpC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;4BAClC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;gCAC7C,MAAM,eAAe,GAAG,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gCACpE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;gCAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;gCAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;gCACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;4BAC5E,CAAC;4BAED,IAAI,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;gCAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;gCAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oCAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;oCAC3B,IAAI,IAAI,EAAE,CAAC;wCACT,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wCACnD,IAAI,UAAU,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;4CAC5B,IAAI,CAAC,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;4CAC3C,MAAM,CAAC,uBAAuB,EAAE,CAAC;wCACnC,CAAC;oCACH,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAGD,MAAM,OAAO,GAAG,mBAAmB,CAAC,aAAa,EAAE,CAAC;QACpD,KAAK,MAAM,WAAW,IAAI,OAAO,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAClD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAE/B,IAAI,OAAO,YAAY,qBAAS,EAAE,CAAC;oBACjC,MAAM,eAAe,GAAG,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAClE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;oBAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;oBAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;oBACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;gBAC5E,CAAC;qBAAM,IAAI,OAAO,YAAY,aAAK,EAAE,CAAC;oBAEpC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;wBACpC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;4BAClC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;gCAC7C,MAAM,eAAe,GAAG,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gCACpE,MAAM,CAAC,kBAAkB,IAAI,eAAe,CAAC,kBAAkB,CAAC;gCAChE,MAAM,CAAC,iBAAiB,IAAI,eAAe,CAAC,iBAAiB,CAAC;gCAC9D,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,aAAa,CAAC;gCACtD,MAAM,CAAC,uBAAuB,IAAI,eAAe,CAAC,uBAAuB,CAAC;4BAC5E,CAAC;4BAED,IAAI,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;gCAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;gCAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oCAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;oCAC3B,IAAI,IAAI,EAAE,CAAC;wCACT,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wCACnD,IAAI,UAAU,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;4CAC5B,IAAI,CAAC,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;4CAC3C,MAAM,CAAC,uBAAuB,EAAE,CAAC;wCACnC,CAAC;oCACH,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAGD,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;QACjC,IAAI,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;YAC/B,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC5B,MAAM,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAGD,MAAM,eAAe,GAAG,GAAG,CAAC,kBAAkB,EAAE,CAAC;IACjD,IAAI,eAAe,EAAE,CAAC;QACpB,eAAe,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAGD,GAAG,CAAC,mBAAmB,EAAE,CAAC;IAK1B,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,MAAM,CAAC,kBAAkB,GAAG,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,aAAa;QAClB,MAAM,CAAC,kBAAkB;YACzB,MAAM,CAAC,iBAAiB;YACxB,MAAM,CAAC,aAAa;YACpB,MAAM,CAAC,uBAAuB,CAAC;IAEjC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE;QAC1C,UAAU,EAAE,MAAM,CAAC,kBAAkB;QACrC,SAAS,EAAE,MAAM,CAAC,iBAAiB;QACnC,KAAK,EAAE,MAAM,CAAC,aAAa;QAC3B,eAAe,EAAE,MAAM,CAAC,uBAAuB;QAC/C,KAAK,EAAE,MAAM,CAAC,aAAa;QAC3B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;KAC9C,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAgBD,SAAS,0BAA0B,CACjC,SAAoB,EACpB,OAAyC;IAEzC,MAAM,MAAM,GAA0B;QACpC,kBAAkB,EAAE,CAAC;QACrB,iBAAiB,EAAE,CAAC;QACpB,aAAa,EAAE,CAAC;QAChB,uBAAuB,EAAE,CAAC;QAC1B,aAAa,EAAE,CAAC;QAChB,kBAAkB,EAAE,CAAC;KACtB,CAAC;IAEF,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;IACvC,MAAM,UAAU,GAAuB,EAAE,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,YAAY,mBAAQ,EAAE,CAAC;YAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAGpC,IAAI,YAAY,KAAK,QAAQ,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;gBAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBACvC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;oBAEjC,IAAI,IAAA,mCAAiB,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,8BAAY,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC/B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,oCAAkB,EAAC,KAAK,CAAC,EAAE,CAAC;wBACrC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAC5B,SAAS;YACX,CAAC;YAGD,IAAI,YAAY,KAAK,QAAQ,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;gBAEzD,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YAGD,IAAI,YAAY,KAAK,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBAEvD,MAAM,CAAC,aAAa,EAAE,CAAC;gBACvB,SAAS;YACX,CAAC;YAGD,IAAI,YAAY,KAAK,QAAQ,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBAErD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBACvC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;oBAEjC,IAAI,IAAA,mCAAiB,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,8BAAY,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC/B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,oCAAkB,EAAC,KAAK,CAAC,EAAE,CAAC;wBACrC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,aAAa,EAAE,CAAC;gBACvB,SAAS;YACX,CAAC;YAGD,IAAI,uBAAuB,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;gBAKpF,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBACvC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;oBAEjC,IAAI,IAAA,mCAAiB,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,8BAAY,EAAC,KAAK,CAAC,EAAE,CAAC;wBAC/B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,IAAI,IAAA,oCAAkB,EAAC,KAAK,CAAC,EAAE,CAAC;wBACrC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,uBAAuB,EAAE,CAAC;gBACjC,SAAS;YACX,CAAC;YAID,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YAEN,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAGD,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAIjC,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC;QAC7C,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACzB,SAAS,CAAC,8BAA8B,EAAE,CAAC;YAC3C,MAAM,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAKD,SAAgB,qBAAqB,CAAC,SAAoB;IACxD,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,YAAY,mBAAQ,CAAC,CAAC;AAC1D,CAAC;AAKD,SAAgB,yBAAyB,CAAC,SAAoB;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAoB,EAAE,CAAC,IAAI,YAAY,mBAAQ,CAAC,CAAC;AAC9E,CAAC;AAKD,SAAgB,oBAAoB,CAAC,GAAa;IAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE/C,MAAM,UAAU,GAAG,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAC;QACvD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD,SAAS,kBAAkB,CAAC,GAAa,EAAE,MAAe;IACxD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;IAC/B,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAE7B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;oBAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;oBACnC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACpB,UAAU,GAAG,IAAI,CAAC;wBAClB,MAAM;oBACR,CAAC;gBACH,CAAC;gBACD,IAAI,UAAU;oBAAE,MAAM;YACxB,CAAC;YACD,IAAI,UAAU;gBAAE,MAAM;QACxB,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAEhB,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAGD,KAAK,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,YAAY,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC","sourcesContent":["/**\r\n * InMemoryRevisionAcceptor - Accept revisions by transforming the in-memory object model\r\n *\r\n * This approach follows the industry standard (OpenXML PowerTools, Aspose.Words):\r\n * - Transforms Revision objects in paragraph.content[] to their \"accepted\" state\r\n * - For insertions: Unwrap - extract child Runs/Hyperlinks into parent paragraph\r\n * - For deletions: Remove - delete the revision and its content from the model\r\n * - For property changes: Remove the change metadata, keep the current formatting\r\n *\r\n * Unlike the raw XML approach (acceptRevisions.ts), this allows subsequent modifications\r\n * to the in-memory model to be correctly serialized on save().\r\n *\r\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\r\n * @see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/ee836138(v=office.12)\r\n */\r\n\r\nimport type { Document } from '../core/Document';\r\nimport { Paragraph } from '../elements/Paragraph';\r\nimport type { ParagraphContent } from '../elements/Paragraph';\r\nimport { Revision, RevisionType } from '../elements/Revision';\r\nimport type { Run } from '../elements/Run';\r\nimport type { Hyperlink } from '../elements/Hyperlink';\r\nimport { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';\r\nimport type { ImageRun } from '../elements/ImageRun';\r\nimport { Table } from '../elements/Table';\r\nimport { Section } from '../elements/Section';\r\nimport { getGlobalLogger, createScopedLogger, ILogger } from './logger';\r\n\r\n/**\r\n * Get scoped logger for this module\r\n */\r\nfunction getLogger(): ILogger {\r\n return createScopedLogger(getGlobalLogger(), 'InMemoryRevisionAcceptor');\r\n}\r\n\r\n/**\r\n * Options for accepting revisions\r\n */\r\nexport interface AcceptRevisionsOptions {\r\n /** Accept insertion revisions (w:ins) - default: true */\r\n acceptInsertions?: boolean;\r\n /** Accept deletion revisions (w:del) - default: true */\r\n acceptDeletions?: boolean;\r\n /** Accept move operations (w:moveFrom, w:moveTo) - default: true */\r\n acceptMoves?: boolean;\r\n /** Accept property change revisions (rPrChange, pPrChange, etc.) - default: true */\r\n acceptPropertyChanges?: boolean;\r\n /** Remove empty tables after revision acceptance - default: true */\r\n cleanupEmptyTables?: boolean;\r\n}\r\n\r\n/**\r\n * Result of accepting revisions\r\n */\r\nexport interface AcceptRevisionsResult {\r\n /** Number of insertions accepted */\r\n insertionsAccepted: number;\r\n /** Number of deletions accepted */\r\n deletionsAccepted: number;\r\n /** Number of move operations accepted */\r\n movesAccepted: number;\r\n /** Number of property changes accepted */\r\n propertyChangesAccepted: number;\r\n /** Total revisions processed */\r\n totalAccepted: number;\r\n /** Number of empty tables removed during cleanup */\r\n emptyTablesRemoved: number;\r\n}\r\n\r\n/**\r\n * Revision types that represent content changes (contain actual text/runs)\r\n */\r\nconst CONTENT_REVISION_TYPES: RevisionType[] = [\r\n 'insert',\r\n 'delete',\r\n 'moveFrom',\r\n 'moveTo',\r\n];\r\n\r\n/**\r\n * Revision types that represent property/formatting changes\r\n */\r\nconst PROPERTY_REVISION_TYPES: RevisionType[] = [\r\n 'runPropertiesChange',\r\n 'paragraphPropertiesChange',\r\n 'tablePropertiesChange',\r\n 'tableExceptionPropertiesChange',\r\n 'tableRowPropertiesChange',\r\n 'tableCellPropertiesChange',\r\n 'sectionPropertiesChange',\r\n 'numberingChange',\r\n];\r\n\r\n/**\r\n * Strip revision markup from raw XML string.\r\n * Used for nested tables stored as raw XML that cannot be processed via the in-memory model.\r\n *\r\n * Follows the same rules as the main revision acceptor:\r\n * - Insertions: Keep content, remove wrapper tags\r\n * - Deletions: Remove entirely (content and tags)\r\n * - MoveFrom: Remove entirely (source of move)\r\n * - MoveTo: Keep content, remove wrapper\r\n * - Property changes: Remove change tracking elements\r\n * - Range markers: Remove boundary markers\r\n *\r\n * @param xml - Raw XML string containing revision markup\r\n * @returns Cleaned XML with revisions accepted\r\n */\r\nexport function stripRevisionsFromXml(xml: string): string {\r\n let result = xml;\r\n\r\n // Step 1: Remove range markers (must be done first)\r\n const rangePatterns = [\r\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\r\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\r\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\r\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\r\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\r\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\r\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\r\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\r\n ];\r\n for (const pattern of rangePatterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n\r\n // Step 2: Remove property change elements\r\n const propChangePatterns = [\r\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\r\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\r\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\r\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\r\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\r\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\r\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\r\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\r\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\r\n ];\r\n for (const pattern of propChangePatterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n\r\n // Step 3: Remove deletions entirely (including content)\r\n // Iterate until no more deletions (handles nested cases)\r\n let prevLen = 0;\r\n while (result.length !== prevLen) {\r\n prevLen = result.length;\r\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\r\n }\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n\r\n // Step 4: Remove moveFrom entirely (source of moved content)\r\n prevLen = 0;\r\n while (result.length !== prevLen) {\r\n prevLen = result.length;\r\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\r\n }\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n\r\n // Step 5: Unwrap moveTo (keep content, remove wrapper)\r\n result = result.replace(/<\\/w:moveTo>/g, '');\r\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\r\n\r\n // Step 6: Unwrap insertions (keep content, remove wrapper)\r\n result = result.replace(/<\\/w:ins>/g, '');\r\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\r\n\r\n // Step 7: Clean up orphaned tags\r\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Accept all revisions in the document by transforming the in-memory model.\r\n *\r\n * This is the industry-standard approach used by OpenXML PowerTools, Aspose.Words,\r\n * and other production DOCX libraries. It allows subsequent modifications to the\r\n * document to work correctly.\r\n *\r\n * @param doc - Document to process\r\n * @param options - Options for which revision types to accept\r\n * @returns Result with counts of accepted revisions\r\n */\r\nexport function acceptRevisionsInMemory(\r\n doc: Document,\r\n options: AcceptRevisionsOptions = {}\r\n): AcceptRevisionsResult {\r\n const logger = getLogger();\r\n const opts: Required<AcceptRevisionsOptions> = {\r\n acceptInsertions: options.acceptInsertions ?? true,\r\n acceptDeletions: options.acceptDeletions ?? true,\r\n acceptMoves: options.acceptMoves ?? true,\r\n acceptPropertyChanges: options.acceptPropertyChanges ?? true,\r\n cleanupEmptyTables: options.cleanupEmptyTables ?? true,\r\n };\r\n\r\n const result: AcceptRevisionsResult = {\r\n insertionsAccepted: 0,\r\n deletionsAccepted: 0,\r\n movesAccepted: 0,\r\n propertyChangesAccepted: 0,\r\n totalAccepted: 0,\r\n emptyTablesRemoved: 0,\r\n };\r\n\r\n logger.info('Accepting revisions in-memory', { options: opts });\r\n\r\n // Validate move pairs before accepting if moves are being accepted\r\n // Orphaned moves could result in content loss (moveFrom without moveTo = content deleted)\r\n if (opts.acceptMoves) {\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const movePairValidation = revisionManager.validateMovePairs();\r\n if (!movePairValidation.valid) {\r\n if (movePairValidation.orphanedMoveFrom.length > 0) {\r\n logger.warn(\r\n 'Orphaned moveFrom revisions detected - accepting these will DELETE content permanently ' +\r\n '(content was moved from here but no moveTo destination exists)',\r\n { orphanedMoveIds: movePairValidation.orphanedMoveFrom }\r\n );\r\n }\r\n if (movePairValidation.orphanedMoveTo.length > 0) {\r\n logger.warn(\r\n 'Orphaned moveTo revisions detected - content may be duplicated ' +\r\n '(content moved to here but no moveFrom source exists)',\r\n { orphanedMoveIds: movePairValidation.orphanedMoveTo }\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process all paragraphs in the document body\r\n const paragraphs = doc.getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n\r\n // Process paragraphs in tables and clear table/row/cell property changes\r\n const tables = doc.getTables();\r\n for (const table of tables) {\r\n // Clear tblPrChange on table\r\n if (opts.acceptPropertyChanges && table.getTblPrChange()) {\r\n table.clearTblPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n for (const row of table.getRows()) {\r\n // Clear trPrChange on row\r\n if (opts.acceptPropertyChanges && row.getTrPrChange()) {\r\n row.clearTrPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n for (const cell of row.getCells()) {\r\n // Clear tcPrChange on cell\r\n if (opts.acceptPropertyChanges && cell.getTcPrChange()) {\r\n cell.clearTcPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n // Clear cell structural revision markers (cellIns/cellDel/cellMerge)\r\n if (opts.acceptPropertyChanges && cell.getCellRevision()) {\r\n cell.clearCellRevision();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n // Process paragraphs in the cell\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n\r\n // Process raw nested content (nested tables stored as XML)\r\n // These cannot be processed via the in-memory model, so we use XML-based stripping\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n // Count revisions stripped from nested content\r\n // We can't distinguish types in raw XML, so count as property changes\r\n result.propertyChangesAccepted++;\r\n logger.debug('Stripped revisions from nested content', {\r\n type: item.type,\r\n position: item.position,\r\n originalLength: item.xml.length,\r\n cleanedLength: cleanedXml.length,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process paragraphs in headers\r\n const headerFooterManager = doc.getHeaderFooterManager();\r\n if (headerFooterManager) {\r\n const headers = headerFooterManager.getAllHeaders();\r\n for (const headerEntry of headers) {\r\n const elements = headerEntry.header.getElements();\r\n for (const element of elements) {\r\n // Element can be Paragraph or Table - use instanceof for type safety\r\n if (element instanceof Paragraph) {\r\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n } else if (element instanceof Table) {\r\n // It's a Table - process its cells\r\n for (const row of element.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n // Process raw nested content in header tables\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process paragraphs in footers\r\n const footers = headerFooterManager.getAllFooters();\r\n for (const footerEntry of footers) {\r\n const elements = footerEntry.footer.getElements();\r\n for (const element of elements) {\r\n // Element can be Paragraph or Table - use instanceof for type safety\r\n if (element instanceof Paragraph) {\r\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n } else if (element instanceof Table) {\r\n // It's a Table - process its cells\r\n for (const row of element.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n // Process raw nested content in footer tables\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear sectPrChange on document section\r\n if (opts.acceptPropertyChanges) {\r\n const section = doc.getSection();\r\n if (section?.getSectPrChange()) {\r\n section.clearSectPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n\r\n // Clear revision manager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n revisionManager.clear();\r\n }\r\n\r\n // Disable track changes setting\r\n doc.disableTrackChanges();\r\n\r\n // Cleanup empty tables if enabled\r\n // This removes tables that have no visible content after revision acceptance\r\n // (e.g., tables where all content was deleted via tracked changes)\r\n if (opts.cleanupEmptyTables) {\r\n result.emptyTablesRemoved = cleanupEmptyTables(doc, logger);\r\n }\r\n\r\n result.totalAccepted =\r\n result.insertionsAccepted +\r\n result.deletionsAccepted +\r\n result.movesAccepted +\r\n result.propertyChangesAccepted;\r\n\r\n logger.info('Revisions accepted in-memory', {\r\n insertions: result.insertionsAccepted,\r\n deletions: result.deletionsAccepted,\r\n moves: result.movesAccepted,\r\n propertyChanges: result.propertyChangesAccepted,\r\n total: result.totalAccepted,\r\n emptyTablesRemoved: result.emptyTablesRemoved,\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Accept revisions in a single paragraph by transforming its content array.\r\n *\r\n * The transformation follows these rules:\r\n * - Insertions (w:ins): Unwrap - extract child content into parent position\r\n * - Deletions (w:del): Remove - delete revision and its content\r\n * - MoveFrom (w:moveFrom): Remove - content exists at moveTo destination\r\n * - MoveTo (w:moveTo): Unwrap - keep content, remove wrapper\r\n * - Property changes: Remove from model (current formatting is kept)\r\n *\r\n * @param paragraph - Paragraph to process\r\n * @param options - Options for which revision types to accept\r\n * @returns Result with counts of accepted revisions\r\n */\r\nfunction acceptRevisionsInParagraph(\r\n paragraph: Paragraph,\r\n options: Required<AcceptRevisionsOptions>\r\n): AcceptRevisionsResult {\r\n const result: AcceptRevisionsResult = {\r\n insertionsAccepted: 0,\r\n deletionsAccepted: 0,\r\n movesAccepted: 0,\r\n propertyChangesAccepted: 0,\r\n totalAccepted: 0,\r\n emptyTablesRemoved: 0,\r\n };\r\n\r\n const content = paragraph.getContent();\r\n const newContent: ParagraphContent[] = [];\r\n\r\n for (const item of content) {\r\n if (item instanceof Revision) {\r\n const revisionType = item.getType();\r\n\r\n // Handle insertion revisions (w:ins)\r\n if (revisionType === 'insert' && options.acceptInsertions) {\r\n // Unwrap: Extract child content into parent position\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.insertionsAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle deletion revisions (w:del)\r\n if (revisionType === 'delete' && options.acceptDeletions) {\r\n // Remove: Don't add to newContent - content is deleted\r\n result.deletionsAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle moveFrom revisions (source of moved content)\r\n if (revisionType === 'moveFrom' && options.acceptMoves) {\r\n // Remove: Content exists at moveTo destination\r\n result.movesAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle moveTo revisions (destination of moved content)\r\n if (revisionType === 'moveTo' && options.acceptMoves) {\r\n // Unwrap: Keep content, remove wrapper\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.movesAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle property change revisions\r\n if (PROPERTY_REVISION_TYPES.includes(revisionType) && options.acceptPropertyChanges) {\r\n // For property changes, the revision is metadata attached to runs\r\n // The current formatting (newProperties) is already applied to the run\r\n // We just need to remove the change tracking metadata\r\n // The content inside should be preserved\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.propertyChangesAccepted++;\r\n continue;\r\n }\r\n\r\n // If we reach here, this revision type is not being accepted\r\n // Keep it in the content\r\n newContent.push(item);\r\n } else {\r\n // Non-revision content - keep as-is\r\n newContent.push(item);\r\n }\r\n }\r\n\r\n // Replace paragraph content with the transformed content\r\n paragraph.setContent(newContent);\r\n\r\n // Clear paragraph property change tracking (pPrChange) if accepting property changes\r\n // This removes the w:pPrChange element from the paragraph's formatting\r\n if (options.acceptPropertyChanges) {\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.pPrChange) {\r\n paragraph.clearParagraphPropertiesChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if a paragraph has any revisions\r\n */\r\nexport function paragraphHasRevisions(paragraph: Paragraph): boolean {\r\n const content = paragraph.getContent();\r\n return content.some((item) => item instanceof Revision);\r\n}\r\n\r\n/**\r\n * Get all revisions from a paragraph\r\n */\r\nexport function getRevisionsFromParagraph(paragraph: Paragraph): Revision[] {\r\n const content = paragraph.getContent();\r\n return content.filter((item): item is Revision => item instanceof Revision);\r\n}\r\n\r\n/**\r\n * Count revisions by type in a document\r\n */\r\nexport function countRevisionsByType(doc: Document): Map<RevisionType, number> {\r\n const counts = new Map<RevisionType, number>();\r\n\r\n const paragraphs = doc.getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n const revisions = getRevisionsFromParagraph(paragraph);\r\n for (const revision of revisions) {\r\n const type = revision.getType();\r\n counts.set(type, (counts.get(type) || 0) + 1);\r\n }\r\n }\r\n\r\n return counts;\r\n}\r\n\r\n/**\r\n * Remove tables that have no visible content after revision acceptance.\r\n *\r\n * A table is considered empty if ALL cells in ALL rows have no text content.\r\n * This handles cases where all table content was deleted via tracked changes -\r\n * the deletion markers are stripped but the empty table structure remains.\r\n *\r\n * @param doc - Document to clean up\r\n * @param logger - Logger instance for debug output\r\n * @returns Number of empty tables removed\r\n */\r\nfunction cleanupEmptyTables(doc: Document, logger: ILogger): number {\r\n const tables = doc.getTables();\r\n let removedCount = 0;\r\n const tablesToRemove: number[] = [];\r\n\r\n for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {\r\n const table = tables[tableIndex];\r\n if (!table) continue;\r\n\r\n let hasContent = false;\r\n const rows = table.getRows();\r\n\r\n for (const row of rows) {\r\n const cells = row.getCells();\r\n for (const cell of cells) {\r\n const paragraphs = cell.getParagraphs();\r\n for (const para of paragraphs) {\r\n const text = para.getText().trim();\r\n if (text.length > 0) {\r\n hasContent = true;\r\n break;\r\n }\r\n }\r\n if (hasContent) break;\r\n }\r\n if (hasContent) break;\r\n }\r\n\r\n if (!hasContent) {\r\n // Mark this table for removal (store index)\r\n tablesToRemove.push(tableIndex);\r\n logger.debug('Found empty table for removal', { tableIndex });\r\n }\r\n }\r\n\r\n // Remove tables in reverse order to preserve indices\r\n for (let i = tablesToRemove.length - 1; i >= 0; i--) {\r\n const tableIndex = tablesToRemove[i];\r\n if (tableIndex !== undefined && doc.removeTable(tableIndex)) {\r\n removedCount++;\r\n logger.debug('Removed empty table', { tableIndex });\r\n }\r\n }\r\n\r\n if (removedCount > 0) {\r\n logger.info('Empty table cleanup complete', { tablesRemoved: removedCount });\r\n }\r\n\r\n return removedCount;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"InMemoryRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * InMemoryRevisionAcceptor - Accept revisions by transforming the in-memory object model\r\n *\r\n * This approach follows the industry standard (OpenXML PowerTools, Aspose.Words):\r\n * - Transforms Revision objects in paragraph.content[] to their \"accepted\" state\r\n * - For insertions: Unwrap - extract child Runs/Hyperlinks into parent paragraph\r\n * - For deletions: Remove - delete the revision and its content from the model\r\n * - For property changes: Remove the change metadata, keep the current formatting\r\n *\r\n * Unlike the raw XML approach (acceptRevisions.ts), this allows subsequent modifications\r\n * to the in-memory model to be correctly serialized on save().\r\n *\r\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\r\n * @see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/ee836138(v=office.12)\r\n */\r\n\r\nimport type { Document } from '../core/Document';\r\nimport { Paragraph } from '../elements/Paragraph';\r\nimport type { ParagraphContent } from '../elements/Paragraph';\r\nimport { Revision, RevisionType } from '../elements/Revision';\r\nimport type { Run } from '../elements/Run';\r\nimport type { Hyperlink } from '../elements/Hyperlink';\r\nimport { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';\r\nimport type { ImageRun } from '../elements/ImageRun';\r\nimport { Table } from '../elements/Table';\r\nimport { Section } from '../elements/Section';\r\nimport { getGlobalLogger, createScopedLogger, ILogger } from './logger';\r\n\r\n/**\r\n * Get scoped logger for this module\r\n */\r\nfunction getLogger(): ILogger {\r\n return createScopedLogger(getGlobalLogger(), 'InMemoryRevisionAcceptor');\r\n}\r\n\r\n/**\r\n * Options for accepting revisions\r\n */\r\nexport interface AcceptRevisionsOptions {\r\n /** Accept insertion revisions (w:ins) - default: true */\r\n acceptInsertions?: boolean;\r\n /** Accept deletion revisions (w:del) - default: true */\r\n acceptDeletions?: boolean;\r\n /** Accept move operations (w:moveFrom, w:moveTo) - default: true */\r\n acceptMoves?: boolean;\r\n /** Accept property change revisions (rPrChange, pPrChange, etc.) - default: true */\r\n acceptPropertyChanges?: boolean;\r\n /** Remove empty tables after revision acceptance - default: true */\r\n cleanupEmptyTables?: boolean;\r\n}\r\n\r\n/**\r\n * Result of accepting revisions\r\n */\r\nexport interface AcceptRevisionsResult {\r\n /** Number of insertions accepted */\r\n insertionsAccepted: number;\r\n /** Number of deletions accepted */\r\n deletionsAccepted: number;\r\n /** Number of move operations accepted */\r\n movesAccepted: number;\r\n /** Number of property changes accepted */\r\n propertyChangesAccepted: number;\r\n /** Total revisions processed */\r\n totalAccepted: number;\r\n /** Number of empty tables removed during cleanup */\r\n emptyTablesRemoved: number;\r\n}\r\n\r\n/**\r\n * Revision types that represent content changes (contain actual text/runs)\r\n */\r\nconst CONTENT_REVISION_TYPES: RevisionType[] = [\r\n 'insert',\r\n 'delete',\r\n 'moveFrom',\r\n 'moveTo',\r\n];\r\n\r\n/**\r\n * Revision types that represent property/formatting changes\r\n */\r\nconst PROPERTY_REVISION_TYPES: RevisionType[] = [\r\n 'runPropertiesChange',\r\n 'paragraphPropertiesChange',\r\n 'tablePropertiesChange',\r\n 'tableExceptionPropertiesChange',\r\n 'tableRowPropertiesChange',\r\n 'tableCellPropertiesChange',\r\n 'sectionPropertiesChange',\r\n 'numberingChange',\r\n];\r\n\r\n/**\r\n * Strip revision markup from raw XML string.\r\n * Used for nested tables stored as raw XML that cannot be processed via the in-memory model.\r\n *\r\n * Follows the same rules as the main revision acceptor:\r\n * - Insertions: Keep content, remove wrapper tags\r\n * - Deletions: Remove entirely (content and tags)\r\n * - MoveFrom: Remove entirely (source of move)\r\n * - MoveTo: Keep content, remove wrapper\r\n * - Property changes: Remove change tracking elements\r\n * - Range markers: Remove boundary markers\r\n *\r\n * @param xml - Raw XML string containing revision markup\r\n * @returns Cleaned XML with revisions accepted\r\n */\r\nexport function stripRevisionsFromXml(xml: string): string {\r\n let result = xml;\r\n\r\n // Step 1: Remove range markers (must be done first)\r\n const rangePatterns = [\r\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\r\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\r\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\r\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\r\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\r\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\r\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\r\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\r\n ];\r\n for (const pattern of rangePatterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n\r\n // Step 2: Remove property change elements\r\n const propChangePatterns = [\r\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\r\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\r\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\r\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\r\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\r\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\r\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\r\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\r\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\r\n ];\r\n for (const pattern of propChangePatterns) {\r\n result = result.replace(pattern, '');\r\n }\r\n\r\n // Step 3: Remove deletions entirely (including content)\r\n // Iterate until no more deletions (handles nested cases)\r\n let prevLen = 0;\r\n while (result.length !== prevLen) {\r\n prevLen = result.length;\r\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\r\n }\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n\r\n // Step 4: Remove moveFrom entirely (source of moved content)\r\n prevLen = 0;\r\n while (result.length !== prevLen) {\r\n prevLen = result.length;\r\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\r\n }\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n\r\n // Step 5: Unwrap moveTo (keep content, remove wrapper)\r\n result = result.replace(/<\\/w:moveTo>/g, '');\r\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\r\n\r\n // Step 6: Unwrap insertions (keep content, remove wrapper)\r\n result = result.replace(/<\\/w:ins>/g, '');\r\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\r\n\r\n // Step 7: Clean up orphaned tags\r\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\r\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Accept all revisions in the document by transforming the in-memory model.\r\n *\r\n * This is the industry-standard approach used by OpenXML PowerTools, Aspose.Words,\r\n * and other production DOCX libraries. It allows subsequent modifications to the\r\n * document to work correctly.\r\n *\r\n * @param doc - Document to process\r\n * @param options - Options for which revision types to accept\r\n * @returns Result with counts of accepted revisions\r\n */\r\nexport function acceptRevisionsInMemory(\r\n doc: Document,\r\n options: AcceptRevisionsOptions = {}\r\n): AcceptRevisionsResult {\r\n const logger = getLogger();\r\n const opts: Required<AcceptRevisionsOptions> = {\r\n acceptInsertions: options.acceptInsertions ?? true,\r\n acceptDeletions: options.acceptDeletions ?? true,\r\n acceptMoves: options.acceptMoves ?? true,\r\n acceptPropertyChanges: options.acceptPropertyChanges ?? true,\r\n cleanupEmptyTables: options.cleanupEmptyTables ?? true,\r\n };\r\n\r\n const result: AcceptRevisionsResult = {\r\n insertionsAccepted: 0,\r\n deletionsAccepted: 0,\r\n movesAccepted: 0,\r\n propertyChangesAccepted: 0,\r\n totalAccepted: 0,\r\n emptyTablesRemoved: 0,\r\n };\r\n\r\n logger.info('Accepting revisions in-memory', { options: opts });\r\n\r\n // Validate move pairs before accepting if moves are being accepted\r\n // Orphaned moves could result in content loss (moveFrom without moveTo = content deleted)\r\n if (opts.acceptMoves) {\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const movePairValidation = revisionManager.validateMovePairs();\r\n if (!movePairValidation.valid) {\r\n if (movePairValidation.orphanedMoveFrom.length > 0) {\r\n logger.warn(\r\n 'Orphaned moveFrom revisions detected - accepting these will DELETE content permanently ' +\r\n '(content was moved from here but no moveTo destination exists)',\r\n { orphanedMoveIds: movePairValidation.orphanedMoveFrom }\r\n );\r\n }\r\n if (movePairValidation.orphanedMoveTo.length > 0) {\r\n logger.warn(\r\n 'Orphaned moveTo revisions detected - content may be duplicated ' +\r\n '(content moved to here but no moveFrom source exists)',\r\n { orphanedMoveIds: movePairValidation.orphanedMoveTo }\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process all paragraphs in the document body\r\n const paragraphs = doc.getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n\r\n // Process paragraphs in tables and clear table/row/cell property changes\r\n const tables = doc.getTables();\r\n for (const table of tables) {\r\n // Clear tblPrChange on table\r\n if (opts.acceptPropertyChanges && table.getTblPrChange()) {\r\n table.clearTblPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n for (const row of table.getRows()) {\r\n // Clear trPrChange on row\r\n if (opts.acceptPropertyChanges && row.getTrPrChange()) {\r\n row.clearTrPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n for (const cell of row.getCells()) {\r\n // Clear tcPrChange on cell\r\n if (opts.acceptPropertyChanges && cell.getTcPrChange()) {\r\n cell.clearTcPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n // Clear cell structural revision markers (cellIns/cellDel/cellMerge)\r\n if (opts.acceptPropertyChanges && cell.getCellRevision()) {\r\n cell.clearCellRevision();\r\n result.propertyChangesAccepted++;\r\n }\r\n\r\n // Process paragraphs in the cell\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n\r\n // Process raw nested content (nested tables stored as XML)\r\n // These cannot be processed via the in-memory model, so we use XML-based stripping\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n // Count revisions stripped from nested content\r\n // We can't distinguish types in raw XML, so count as property changes\r\n result.propertyChangesAccepted++;\r\n logger.debug('Stripped revisions from nested content', {\r\n type: item.type,\r\n position: item.position,\r\n originalLength: item.xml.length,\r\n cleanedLength: cleanedXml.length,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process paragraphs in headers\r\n const headerFooterManager = doc.getHeaderFooterManager();\r\n if (headerFooterManager) {\r\n const headers = headerFooterManager.getAllHeaders();\r\n for (const headerEntry of headers) {\r\n const elements = headerEntry.header.getElements();\r\n for (const element of elements) {\r\n // Element can be Paragraph or Table - use instanceof for type safety\r\n if (element instanceof Paragraph) {\r\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n } else if (element instanceof Table) {\r\n // It's a Table - process its cells\r\n for (const row of element.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n // Process raw nested content in header tables\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Process paragraphs in footers\r\n const footers = headerFooterManager.getAllFooters();\r\n for (const footerEntry of footers) {\r\n const elements = footerEntry.footer.getElements();\r\n for (const element of elements) {\r\n // Element can be Paragraph or Table - use instanceof for type safety\r\n if (element instanceof Paragraph) {\r\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n } else if (element instanceof Table) {\r\n // It's a Table - process its cells\r\n for (const row of element.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\r\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\r\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\r\n result.movesAccepted += paragraphResult.movesAccepted;\r\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\r\n }\r\n // Process raw nested content in footer tables\r\n if (cell.hasRawNestedContent()) {\r\n const rawContent = cell.getRawNestedContent();\r\n for (let i = 0; i < rawContent.length; i++) {\r\n const item = rawContent[i];\r\n if (item) {\r\n const cleanedXml = stripRevisionsFromXml(item.xml);\r\n if (cleanedXml !== item.xml) {\r\n cell.updateRawNestedContent(i, cleanedXml);\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear sectPrChange on document section\r\n if (opts.acceptPropertyChanges) {\r\n const section = doc.getSection();\r\n if (section?.getSectPrChange()) {\r\n section.clearSectPrChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n\r\n // Clear revision manager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n revisionManager.clear();\r\n }\r\n\r\n // Disable track changes setting\r\n doc.disableTrackChanges();\r\n\r\n // Cleanup empty tables if enabled\r\n // This removes tables that have no visible content after revision acceptance\r\n // (e.g., tables where all content was deleted via tracked changes)\r\n if (opts.cleanupEmptyTables) {\r\n result.emptyTablesRemoved = cleanupEmptyTables(doc, logger);\r\n }\r\n\r\n result.totalAccepted =\r\n result.insertionsAccepted +\r\n result.deletionsAccepted +\r\n result.movesAccepted +\r\n result.propertyChangesAccepted;\r\n\r\n logger.info('Revisions accepted in-memory', {\r\n insertions: result.insertionsAccepted,\r\n deletions: result.deletionsAccepted,\r\n moves: result.movesAccepted,\r\n propertyChanges: result.propertyChangesAccepted,\r\n total: result.totalAccepted,\r\n emptyTablesRemoved: result.emptyTablesRemoved,\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Accept revisions in a single paragraph by transforming its content array.\r\n *\r\n * The transformation follows these rules:\r\n * - Insertions (w:ins): Unwrap - extract child content into parent position\r\n * - Deletions (w:del): Remove - delete revision and its content\r\n * - MoveFrom (w:moveFrom): Remove - content exists at moveTo destination\r\n * - MoveTo (w:moveTo): Unwrap - keep content, remove wrapper\r\n * - Property changes: Remove from model (current formatting is kept)\r\n *\r\n * @param paragraph - Paragraph to process\r\n * @param options - Options for which revision types to accept\r\n * @returns Result with counts of accepted revisions\r\n */\r\nfunction acceptRevisionsInParagraph(\r\n paragraph: Paragraph,\r\n options: Required<AcceptRevisionsOptions>\r\n): AcceptRevisionsResult {\r\n const result: AcceptRevisionsResult = {\r\n insertionsAccepted: 0,\r\n deletionsAccepted: 0,\r\n movesAccepted: 0,\r\n propertyChangesAccepted: 0,\r\n totalAccepted: 0,\r\n emptyTablesRemoved: 0,\r\n };\r\n\r\n const content = paragraph.getContent();\r\n const newContent: ParagraphContent[] = [];\r\n\r\n for (const item of content) {\r\n if (item instanceof Revision) {\r\n const revisionType = item.getType();\r\n\r\n // Handle insertion revisions (w:ins)\r\n if (revisionType === 'insert' && options.acceptInsertions) {\r\n // Unwrap: Extract child content into parent position\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.insertionsAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle deletion revisions (w:del)\r\n if (revisionType === 'delete' && options.acceptDeletions) {\r\n // Remove: Don't add to newContent - content is deleted\r\n result.deletionsAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle moveFrom revisions (source of moved content)\r\n if (revisionType === 'moveFrom' && options.acceptMoves) {\r\n // Remove: Content exists at moveTo destination\r\n result.movesAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle moveTo revisions (destination of moved content)\r\n if (revisionType === 'moveTo' && options.acceptMoves) {\r\n // Unwrap: Keep content, remove wrapper\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.movesAccepted++;\r\n continue;\r\n }\r\n\r\n // Handle property change revisions\r\n if (PROPERTY_REVISION_TYPES.includes(revisionType) && options.acceptPropertyChanges) {\r\n // For property changes, the revision is metadata attached to runs\r\n // The current formatting (newProperties) is already applied to the run\r\n // We just need to remove the change tracking metadata\r\n // The content inside should be preserved\r\n const childContent = item.getContent();\r\n for (const child of childContent) {\r\n // Check ImageRun FIRST since ImageRun extends Run\r\n if (isImageRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isRunContent(child)) {\r\n newContent.push(child);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n result.propertyChangesAccepted++;\r\n continue;\r\n }\r\n\r\n // If we reach here, this revision type is not being accepted\r\n // Keep it in the content\r\n newContent.push(item);\r\n } else {\r\n // Non-revision content - keep as-is\r\n newContent.push(item);\r\n }\r\n }\r\n\r\n // Replace paragraph content with the transformed content\r\n paragraph.setContent(newContent);\r\n\r\n // Clear paragraph property change tracking (pPrChange) if accepting property changes\r\n // This removes the w:pPrChange element from the paragraph's formatting\r\n if (options.acceptPropertyChanges) {\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.pPrChange) {\r\n paragraph.clearParagraphPropertiesChange();\r\n result.propertyChangesAccepted++;\r\n }\r\n }\r\n\r\n // Clear paragraph mark deletion tracking if accepting deletions\r\n // This removes the w:del element from w:pPr/w:rPr\r\n if (options.acceptDeletions) {\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.paragraphMarkDeletion) {\r\n paragraph.clearParagraphMarkDeletion();\r\n result.deletionsAccepted++;\r\n }\r\n }\r\n\r\n // Clear paragraph mark insertion tracking if accepting insertions\r\n // This removes the w:ins element from w:pPr/w:rPr\r\n if (options.acceptInsertions) {\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.paragraphMarkInsertion) {\r\n paragraph.clearParagraphMarkInsertion();\r\n result.insertionsAccepted++;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if a paragraph has any revisions\r\n */\r\nexport function paragraphHasRevisions(paragraph: Paragraph): boolean {\r\n const content = paragraph.getContent();\r\n if (content.some((item) => item instanceof Revision)) {\r\n return true;\r\n }\r\n // Also check paragraph mark revision markers in w:pPr/w:rPr\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.paragraphMarkDeletion || formatting.paragraphMarkInsertion) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Get all revisions from a paragraph\r\n */\r\nexport function getRevisionsFromParagraph(paragraph: Paragraph): Revision[] {\r\n const content = paragraph.getContent();\r\n return content.filter((item): item is Revision => item instanceof Revision);\r\n}\r\n\r\n/**\r\n * Count revisions by type in a document\r\n */\r\nexport function countRevisionsByType(doc: Document): Map<RevisionType, number> {\r\n const counts = new Map<RevisionType, number>();\r\n\r\n const paragraphs = doc.getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n const revisions = getRevisionsFromParagraph(paragraph);\r\n for (const revision of revisions) {\r\n const type = revision.getType();\r\n counts.set(type, (counts.get(type) || 0) + 1);\r\n }\r\n }\r\n\r\n return counts;\r\n}\r\n\r\n/**\r\n * Remove tables that have no visible content after revision acceptance.\r\n *\r\n * A table is considered empty if ALL cells in ALL rows have no text content.\r\n * This handles cases where all table content was deleted via tracked changes -\r\n * the deletion markers are stripped but the empty table structure remains.\r\n *\r\n * @param doc - Document to clean up\r\n * @param logger - Logger instance for debug output\r\n * @returns Number of empty tables removed\r\n */\r\nfunction cleanupEmptyTables(doc: Document, logger: ILogger): number {\r\n const tables = doc.getTables();\r\n let removedCount = 0;\r\n const tablesToRemove: number[] = [];\r\n\r\n for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {\r\n const table = tables[tableIndex];\r\n if (!table) continue;\r\n\r\n let hasContent = false;\r\n const rows = table.getRows();\r\n\r\n for (const row of rows) {\r\n const cells = row.getCells();\r\n for (const cell of cells) {\r\n const paragraphs = cell.getParagraphs();\r\n for (const para of paragraphs) {\r\n const text = para.getText().trim();\r\n if (text.length > 0) {\r\n hasContent = true;\r\n break;\r\n }\r\n }\r\n if (hasContent) break;\r\n }\r\n if (hasContent) break;\r\n }\r\n\r\n if (!hasContent) {\r\n // Mark this table for removal (store index)\r\n tablesToRemove.push(tableIndex);\r\n logger.debug('Found empty table for removal', { tableIndex });\r\n }\r\n }\r\n\r\n // Remove tables in reverse order to preserve indices\r\n for (let i = tablesToRemove.length - 1; i >= 0; i--) {\r\n const tableIndex = tablesToRemove[i];\r\n if (tableIndex !== undefined && doc.removeTable(tableIndex)) {\r\n removedCount++;\r\n logger.debug('Removed empty table', { tableIndex });\r\n }\r\n }\r\n\r\n if (removedCount > 0) {\r\n logger.info('Empty table cleanup complete', { tablesRemoved: removedCount });\r\n }\r\n\r\n return removedCount;\r\n}\r\n"]}
|
|
@@ -16,6 +16,7 @@ export declare class SelectiveRevisionAcceptor {
|
|
|
16
16
|
static accept(doc: Document, criteria: SelectionCriteria): SelectiveAcceptResult;
|
|
17
17
|
static reject(doc: Document, criteria: SelectionCriteria): SelectiveAcceptResult;
|
|
18
18
|
private static processSelectiveParagraph;
|
|
19
|
+
private static matchesMarkerCriteria;
|
|
19
20
|
private static acceptRevisionItem;
|
|
20
21
|
private static rejectRevisionItem;
|
|
21
22
|
static preview(doc: Document, criteria: SelectionCriteria, action: 'accept' | 'reject'): SelectiveAcceptResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectiveRevisionAcceptor.d.ts","sourceRoot":"","sources":["../../src/utils/SelectiveRevisionAcceptor.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAY,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAK9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAK7D,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAMD,qBAAa,yBAAyB;IAUpC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB;IA0ExB,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB;IAkExB,OAAO,CAAC,MAAM,CAAC,yBAAyB;
|
|
1
|
+
{"version":3,"file":"SelectiveRevisionAcceptor.d.ts","sourceRoot":"","sources":["../../src/utils/SelectiveRevisionAcceptor.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAY,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAK9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAK7D,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAMD,qBAAa,yBAAyB;IAUpC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB;IA0ExB,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB;IAkExB,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAmExC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA8CpC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAsDjC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA2DjC,MAAM,CAAC,OAAO,CACZ,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAC1B,qBAAqB;IAcxB,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,qBAAqB;IAW3E,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,qBAAqB;IAW3E,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,qBAAqB;IAWhF,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,qBAAqB;IAWhF,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,qBAAqB;IAazE,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,qBAAqB;IAYxE,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG,qBAAqB;IAUjE,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,QAAQ,GAAG,qBAAqB;IAUhE,MAAM,CAAC,uBAAuB,CAAC,GAAG,EAAE,QAAQ,GAAG,qBAAqB;IAUpE,MAAM,CAAC,wBAAwB,CAAC,GAAG,EAAE,QAAQ,GAAG,qBAAqB;IAOrE,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAqBjC,OAAO,CAAC,MAAM,CAAC,eAAe;IA0D9B,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsClC,OAAO,CAAC,MAAM,CAAC,WAAW;CAa3B"}
|
|
@@ -133,6 +133,52 @@ class SelectiveRevisionAcceptor {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
paragraph.setContent(newContent);
|
|
136
|
+
const formatting = paragraph.getFormatting();
|
|
137
|
+
if (formatting.paragraphMarkDeletion) {
|
|
138
|
+
const del = formatting.paragraphMarkDeletion;
|
|
139
|
+
if (this.matchesMarkerCriteria(del, criteria)) {
|
|
140
|
+
paragraph.clearParagraphMarkDeletion();
|
|
141
|
+
processedIds.push(del.id.toString());
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
remainingIds.push(del.id.toString());
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (formatting.paragraphMarkInsertion) {
|
|
148
|
+
const ins = formatting.paragraphMarkInsertion;
|
|
149
|
+
if (this.matchesMarkerCriteria(ins, criteria)) {
|
|
150
|
+
paragraph.clearParagraphMarkInsertion();
|
|
151
|
+
processedIds.push(ins.id.toString());
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
remainingIds.push(ins.id.toString());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
static matchesMarkerCriteria(marker, criteria) {
|
|
159
|
+
if (!criteria.ids &&
|
|
160
|
+
!criteria.types &&
|
|
161
|
+
!criteria.authors &&
|
|
162
|
+
!criteria.dateRange &&
|
|
163
|
+
!criteria.categories &&
|
|
164
|
+
!criteria.custom) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (criteria.ids && !criteria.ids.includes(marker.id)) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
if (criteria.authors && !criteria.authors.includes(marker.author)) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
if (criteria.dateRange) {
|
|
174
|
+
if (marker.date < criteria.dateRange.start || marker.date > criteria.dateRange.end) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (criteria.types || criteria.categories || criteria.custom) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
136
182
|
}
|
|
137
183
|
static acceptRevisionItem(revision, newContent) {
|
|
138
184
|
const revisionType = revision.getType();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectiveRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/SelectiveRevisionAcceptor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * SelectiveRevisionAcceptor - Accept or reject specific revisions based on criteria\r\n *\r\n * Provides granular control over revision acceptance using in-memory DOM transformation.\r\n * Extends the all-or-nothing approach with selective acceptance by author, type, date,\r\n * and custom criteria.\r\n *\r\n * Uses the industry-standard in-memory transformation approach (like OpenXML PowerTools),\r\n * allowing subsequent modifications to be saved correctly.\r\n *\r\n * @module SelectiveRevisionAcceptor\r\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\r\n */\r\n\r\nimport type { Document } from '../core/Document';\r\nimport type { Paragraph, ParagraphContent } from '../elements/Paragraph';\r\nimport { Revision, RevisionType } from '../elements/Revision';\r\nimport type { Run } from '../elements/Run';\r\nimport type { Hyperlink } from '../elements/Hyperlink';\r\nimport { isRunContent, isHyperlinkContent } from '../elements/RevisionContent';\r\nimport { ChangeCategory } from './ChangelogGenerator';\r\nimport { SelectionCriteria } from './RevisionAwareProcessor';\r\n\r\n/**\r\n * Result of selective revision acceptance.\r\n */\r\nexport interface SelectiveAcceptResult {\r\n /** IDs of accepted revisions */\r\n accepted: string[];\r\n /** IDs of rejected/removed revisions */\r\n rejected: string[];\r\n /** IDs of revisions that remain */\r\n remaining: string[];\r\n /** Summary of actions taken */\r\n summary: {\r\n totalProcessed: number;\r\n acceptedCount: number;\r\n rejectedCount: number;\r\n remainingCount: number;\r\n };\r\n}\r\n\r\n/**\r\n * Provides granular control over revision acceptance using in-memory DOM transformation.\r\n * Allows subsequent modifications to be saved correctly.\r\n */\r\nexport class SelectiveRevisionAcceptor {\r\n /**\r\n * Accept revisions matching criteria using in-memory DOM transformation.\r\n * Matching revisions: content kept, revision wrapper removed.\r\n * Non-matching revisions: preserved in the document.\r\n *\r\n * @param doc - Document to process\r\n * @param criteria - Selection criteria\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static accept(\r\n doc: Document,\r\n criteria: SelectionCriteria\r\n ): SelectiveAcceptResult {\r\n const accepted: string[] = [];\r\n const remaining: string[] = [];\r\n\r\n // Check if doc has full Document API (getAllParagraphs, getTables)\r\n // or if it's a minimal mock (only getRevisionManager)\r\n const hasFullApi = typeof (doc as any).getAllParagraphs === 'function';\r\n\r\n if (hasFullApi) {\r\n // Full in-memory DOM transformation\r\n const paragraphs = (doc as any).getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'accept', accepted, remaining);\r\n }\r\n\r\n // Process paragraphs in tables\r\n const tables = (doc as any).getTables();\r\n for (const table of tables) {\r\n for (const row of table.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'accept', accepted, remaining);\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: Filter revisions from RevisionManager only (for backward compatibility)\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const allRevisions = revisionManager.getAllRevisions();\r\n for (const rev of allRevisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n accepted.push(rev.getId().toString());\r\n } else {\r\n remaining.push(rev.getId().toString());\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear accepted revisions from RevisionManager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n for (const id of accepted) {\r\n revisionManager.removeById(parseInt(id, 10));\r\n }\r\n }\r\n\r\n return {\r\n accepted,\r\n rejected: [],\r\n remaining,\r\n summary: {\r\n totalProcessed: accepted.length + remaining.length,\r\n acceptedCount: accepted.length,\r\n rejectedCount: 0,\r\n remainingCount: remaining.length,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Reject revisions matching criteria using in-memory DOM transformation.\r\n * Matching revisions: content AND wrapper removed (opposite of accept).\r\n * Non-matching revisions: preserved in the document.\r\n *\r\n * For insertions: Rejecting removes the inserted content entirely.\r\n * For deletions: Rejecting keeps the deleted content (opposite of accepting).\r\n *\r\n * @param doc - Document to process\r\n * @param criteria - Selection criteria\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static reject(\r\n doc: Document,\r\n criteria: SelectionCriteria\r\n ): SelectiveAcceptResult {\r\n const rejected: string[] = [];\r\n const remaining: string[] = [];\r\n\r\n // Check if doc has full Document API (getAllParagraphs, getTables)\r\n // or if it's a minimal mock (only getRevisionManager)\r\n const hasFullApi = typeof (doc as any).getAllParagraphs === 'function';\r\n\r\n if (hasFullApi) {\r\n // Full in-memory DOM transformation\r\n const paragraphs = (doc as any).getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'reject', rejected, remaining);\r\n }\r\n\r\n // Process paragraphs in tables\r\n const tables = (doc as any).getTables();\r\n for (const table of tables) {\r\n for (const row of table.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'reject', rejected, remaining);\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: Filter revisions from RevisionManager only (for backward compatibility)\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const allRevisions = revisionManager.getAllRevisions();\r\n for (const rev of allRevisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n rejected.push(rev.getId().toString());\r\n } else {\r\n remaining.push(rev.getId().toString());\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear rejected revisions from RevisionManager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n for (const id of rejected) {\r\n revisionManager.removeById(parseInt(id, 10));\r\n }\r\n }\r\n\r\n return {\r\n accepted: [],\r\n rejected,\r\n remaining,\r\n summary: {\r\n totalProcessed: rejected.length + remaining.length,\r\n acceptedCount: 0,\r\n rejectedCount: rejected.length,\r\n remainingCount: remaining.length,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Process a paragraph for selective revision acceptance/rejection.\r\n * Transforms matching revisions in-place using DOM transformation.\r\n */\r\n private static processSelectiveParagraph(\r\n paragraph: Paragraph,\r\n criteria: SelectionCriteria,\r\n action: 'accept' | 'reject',\r\n processedIds: string[],\r\n remainingIds: string[]\r\n ): void {\r\n const content = paragraph.getContent();\r\n const newContent: ParagraphContent[] = [];\r\n\r\n for (const item of content) {\r\n if (item instanceof Revision) {\r\n const revisionId = item.getId().toString();\r\n\r\n if (this.matchesCriteria(item, criteria)) {\r\n // This revision matches the criteria - process it\r\n processedIds.push(revisionId);\r\n\r\n if (action === 'accept') {\r\n // Accept: Transform based on revision type\r\n this.acceptRevisionItem(item, newContent);\r\n } else {\r\n // Reject: Transform opposite of accept\r\n this.rejectRevisionItem(item, newContent);\r\n }\r\n } else {\r\n // This revision doesn't match - keep it\r\n remainingIds.push(revisionId);\r\n newContent.push(item);\r\n }\r\n } else {\r\n // Non-revision content - keep as-is\r\n newContent.push(item);\r\n }\r\n }\r\n\r\n // Replace paragraph content with the transformed content\r\n paragraph.setContent(newContent);\r\n }\r\n\r\n /**\r\n * Accept a single revision item (unwrap insertions, remove deletions).\r\n */\r\n private static acceptRevisionItem(\r\n revision: Revision,\r\n newContent: ParagraphContent[]\r\n ): void {\r\n const revisionType = revision.getType();\r\n const childContent = revision.getContent();\r\n\r\n switch (revisionType) {\r\n case 'insert':\r\n case 'moveTo':\r\n // Unwrap: Extract child content into parent position\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n case 'delete':\r\n case 'moveFrom':\r\n // Remove: Don't add to newContent - content is deleted\r\n break;\r\n\r\n case 'runPropertiesChange':\r\n case 'paragraphPropertiesChange':\r\n case 'tablePropertiesChange':\r\n case 'tableExceptionPropertiesChange':\r\n case 'tableRowPropertiesChange':\r\n case 'tableCellPropertiesChange':\r\n case 'sectionPropertiesChange':\r\n case 'numberingChange':\r\n // Property changes: Keep content, remove change metadata\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n default:\r\n // Unknown type - keep the revision as-is for safety\r\n newContent.push(revision);\r\n }\r\n }\r\n\r\n /**\r\n * Reject a single revision item (opposite of accept).\r\n * - Rejecting an insertion removes the content\r\n * - Rejecting a deletion keeps the content (unwraps it)\r\n */\r\n private static rejectRevisionItem(\r\n revision: Revision,\r\n newContent: ParagraphContent[]\r\n ): void {\r\n const revisionType = revision.getType();\r\n const childContent = revision.getContent();\r\n\r\n switch (revisionType) {\r\n case 'insert':\r\n case 'moveTo':\r\n // Reject insertion: Remove the inserted content entirely\r\n break;\r\n\r\n case 'delete':\r\n case 'moveFrom':\r\n // Reject deletion: Keep the deleted content (unwrap)\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n case 'runPropertiesChange':\r\n case 'paragraphPropertiesChange':\r\n case 'tablePropertiesChange':\r\n case 'tableExceptionPropertiesChange':\r\n case 'tableRowPropertiesChange':\r\n case 'tableCellPropertiesChange':\r\n case 'sectionPropertiesChange':\r\n case 'numberingChange':\r\n // Rejecting property changes: Would need to restore old properties\r\n // For now, just keep content without the change metadata\r\n // (Full implementation would restore previousProperties)\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n default:\r\n // Unknown type - keep the revision as-is for safety\r\n newContent.push(revision);\r\n }\r\n }\r\n\r\n /**\r\n * Preview what would happen without making changes.\r\n *\r\n * @param doc - Document to analyze\r\n * @param criteria - Selection criteria\r\n * @param action - Action to preview\r\n * @returns Preview of what would happen\r\n */\r\n static preview(\r\n doc: Document,\r\n criteria: SelectionCriteria,\r\n action: 'accept' | 'reject'\r\n ): SelectiveAcceptResult {\r\n // Preview is the same as the actual operation but without side effects\r\n return action === 'accept'\r\n ? this.accept(doc, criteria)\r\n : this.reject(doc, criteria);\r\n }\r\n\r\n /**\r\n * Accept all revisions by a specific author.\r\n *\r\n * @param doc - Document to process\r\n * @param author - Author name to accept\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptByAuthor(doc: Document, author: string): SelectiveAcceptResult {\r\n return this.accept(doc, { authors: [author] });\r\n }\r\n\r\n /**\r\n * Reject all revisions by a specific author.\r\n *\r\n * @param doc - Document to process\r\n * @param author - Author name to reject\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectByAuthor(doc: Document, author: string): SelectiveAcceptResult {\r\n return this.reject(doc, { authors: [author] });\r\n }\r\n\r\n /**\r\n * Accept all revisions of specific types.\r\n *\r\n * @param doc - Document to process\r\n * @param types - Revision types to accept\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptByType(doc: Document, types: RevisionType[]): SelectiveAcceptResult {\r\n return this.accept(doc, { types });\r\n }\r\n\r\n /**\r\n * Reject all revisions of specific types.\r\n *\r\n * @param doc - Document to process\r\n * @param types - Revision types to reject\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectByType(doc: Document, types: RevisionType[]): SelectiveAcceptResult {\r\n return this.reject(doc, { types });\r\n }\r\n\r\n /**\r\n * Accept all revisions before a specific date.\r\n *\r\n * @param doc - Document to process\r\n * @param date - Cutoff date (exclusive)\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptBeforeDate(doc: Document, date: Date): SelectiveAcceptResult {\r\n return this.accept(doc, {\r\n dateRange: { start: new Date(0), end: date },\r\n });\r\n }\r\n\r\n /**\r\n * Accept all revisions after a specific date.\r\n *\r\n * @param doc - Document to process\r\n * @param date - Start date (exclusive)\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptAfterDate(doc: Document, date: Date): SelectiveAcceptResult {\r\n return this.accept(doc, {\r\n dateRange: { start: date, end: new Date() },\r\n });\r\n }\r\n\r\n /**\r\n * Accept all insertions only.\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptInsertionsOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { types: ['insert'] });\r\n }\r\n\r\n /**\r\n * Accept all deletions only.\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptDeletionsOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { types: ['delete'] });\r\n }\r\n\r\n /**\r\n * Reject all formatting changes (keep content changes).\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectFormattingChanges(doc: Document): SelectiveAcceptResult {\r\n return this.reject(doc, { categories: ['formatting'] });\r\n }\r\n\r\n /**\r\n * Accept content changes only (reject formatting).\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptContentChangesOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { categories: ['content'] });\r\n }\r\n\r\n /**\r\n * Partition revisions into matching and non-matching based on criteria.\r\n */\r\n private static partitionRevisions(\r\n revisions: Revision[],\r\n criteria: SelectionCriteria\r\n ): { matching: Revision[]; nonMatching: Revision[] } {\r\n const matching: Revision[] = [];\r\n const nonMatching: Revision[] = [];\r\n\r\n for (const rev of revisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n matching.push(rev);\r\n } else {\r\n nonMatching.push(rev);\r\n }\r\n }\r\n\r\n return { matching, nonMatching };\r\n }\r\n\r\n /**\r\n * Check if a revision matches the given criteria.\r\n */\r\n private static matchesCriteria(\r\n revision: Revision,\r\n criteria: SelectionCriteria\r\n ): boolean {\r\n // If no criteria specified, match nothing\r\n if (\r\n !criteria.ids &&\r\n !criteria.types &&\r\n !criteria.authors &&\r\n !criteria.dateRange &&\r\n !criteria.categories &&\r\n !criteria.custom\r\n ) {\r\n return false;\r\n }\r\n\r\n // Filter by IDs\r\n if (criteria.ids && !criteria.ids.includes(revision.getId())) {\r\n return false;\r\n }\r\n\r\n // Filter by types\r\n if (criteria.types && !criteria.types.includes(revision.getType())) {\r\n return false;\r\n }\r\n\r\n // Filter by authors\r\n if (criteria.authors && !criteria.authors.includes(revision.getAuthor())) {\r\n return false;\r\n }\r\n\r\n // Filter by date range\r\n if (criteria.dateRange) {\r\n const date = revision.getDate();\r\n if (date < criteria.dateRange.start || date > criteria.dateRange.end) {\r\n return false;\r\n }\r\n }\r\n\r\n // Filter by categories\r\n if (criteria.categories) {\r\n const category = this.getRevisionCategory(revision);\r\n if (!criteria.categories.includes(category)) {\r\n return false;\r\n }\r\n }\r\n\r\n // Custom filter\r\n if (criteria.custom && !criteria.custom(revision)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the semantic category of a revision.\r\n */\r\n private static getRevisionCategory(revision: Revision): ChangeCategory {\r\n const type = revision.getType();\r\n\r\n if (type === 'insert' || type === 'delete') {\r\n return 'content';\r\n }\r\n if (\r\n type === 'runPropertiesChange' ||\r\n type === 'paragraphPropertiesChange' ||\r\n type === 'numberingChange'\r\n ) {\r\n return 'formatting';\r\n }\r\n if (\r\n type === 'moveFrom' ||\r\n type === 'moveTo' ||\r\n type === 'sectionPropertiesChange'\r\n ) {\r\n return 'structural';\r\n }\r\n if (\r\n type === 'tablePropertiesChange' ||\r\n type === 'tableExceptionPropertiesChange' ||\r\n type === 'tableRowPropertiesChange' ||\r\n type === 'tableCellPropertiesChange' ||\r\n type === 'tableCellInsert' ||\r\n type === 'tableCellDelete' ||\r\n type === 'tableCellMerge'\r\n ) {\r\n return 'table';\r\n }\r\n\r\n return 'content';\r\n }\r\n\r\n /**\r\n * Create an empty result.\r\n */\r\n private static emptyResult(): SelectiveAcceptResult {\r\n return {\r\n accepted: [],\r\n rejected: [],\r\n remaining: [],\r\n summary: {\r\n totalProcessed: 0,\r\n acceptedCount: 0,\r\n rejectedCount: 0,\r\n remainingCount: 0,\r\n },\r\n };\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"SelectiveRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/SelectiveRevisionAcceptor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * SelectiveRevisionAcceptor - Accept or reject specific revisions based on criteria\r\n *\r\n * Provides granular control over revision acceptance using in-memory DOM transformation.\r\n * Extends the all-or-nothing approach with selective acceptance by author, type, date,\r\n * and custom criteria.\r\n *\r\n * Uses the industry-standard in-memory transformation approach (like OpenXML PowerTools),\r\n * allowing subsequent modifications to be saved correctly.\r\n *\r\n * @module SelectiveRevisionAcceptor\r\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\r\n */\r\n\r\nimport type { Document } from '../core/Document';\r\nimport type { Paragraph, ParagraphContent } from '../elements/Paragraph';\r\nimport { Revision, RevisionType } from '../elements/Revision';\r\nimport type { Run } from '../elements/Run';\r\nimport type { Hyperlink } from '../elements/Hyperlink';\r\nimport { isRunContent, isHyperlinkContent } from '../elements/RevisionContent';\r\nimport { ChangeCategory } from './ChangelogGenerator';\r\nimport { SelectionCriteria } from './RevisionAwareProcessor';\r\n\r\n/**\r\n * Result of selective revision acceptance.\r\n */\r\nexport interface SelectiveAcceptResult {\r\n /** IDs of accepted revisions */\r\n accepted: string[];\r\n /** IDs of rejected/removed revisions */\r\n rejected: string[];\r\n /** IDs of revisions that remain */\r\n remaining: string[];\r\n /** Summary of actions taken */\r\n summary: {\r\n totalProcessed: number;\r\n acceptedCount: number;\r\n rejectedCount: number;\r\n remainingCount: number;\r\n };\r\n}\r\n\r\n/**\r\n * Provides granular control over revision acceptance using in-memory DOM transformation.\r\n * Allows subsequent modifications to be saved correctly.\r\n */\r\nexport class SelectiveRevisionAcceptor {\r\n /**\r\n * Accept revisions matching criteria using in-memory DOM transformation.\r\n * Matching revisions: content kept, revision wrapper removed.\r\n * Non-matching revisions: preserved in the document.\r\n *\r\n * @param doc - Document to process\r\n * @param criteria - Selection criteria\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static accept(\r\n doc: Document,\r\n criteria: SelectionCriteria\r\n ): SelectiveAcceptResult {\r\n const accepted: string[] = [];\r\n const remaining: string[] = [];\r\n\r\n // Check if doc has full Document API (getAllParagraphs, getTables)\r\n // or if it's a minimal mock (only getRevisionManager)\r\n const hasFullApi = typeof (doc as any).getAllParagraphs === 'function';\r\n\r\n if (hasFullApi) {\r\n // Full in-memory DOM transformation\r\n const paragraphs = (doc as any).getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'accept', accepted, remaining);\r\n }\r\n\r\n // Process paragraphs in tables\r\n const tables = (doc as any).getTables();\r\n for (const table of tables) {\r\n for (const row of table.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'accept', accepted, remaining);\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: Filter revisions from RevisionManager only (for backward compatibility)\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const allRevisions = revisionManager.getAllRevisions();\r\n for (const rev of allRevisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n accepted.push(rev.getId().toString());\r\n } else {\r\n remaining.push(rev.getId().toString());\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear accepted revisions from RevisionManager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n for (const id of accepted) {\r\n revisionManager.removeById(parseInt(id, 10));\r\n }\r\n }\r\n\r\n return {\r\n accepted,\r\n rejected: [],\r\n remaining,\r\n summary: {\r\n totalProcessed: accepted.length + remaining.length,\r\n acceptedCount: accepted.length,\r\n rejectedCount: 0,\r\n remainingCount: remaining.length,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Reject revisions matching criteria using in-memory DOM transformation.\r\n * Matching revisions: content AND wrapper removed (opposite of accept).\r\n * Non-matching revisions: preserved in the document.\r\n *\r\n * For insertions: Rejecting removes the inserted content entirely.\r\n * For deletions: Rejecting keeps the deleted content (opposite of accepting).\r\n *\r\n * @param doc - Document to process\r\n * @param criteria - Selection criteria\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static reject(\r\n doc: Document,\r\n criteria: SelectionCriteria\r\n ): SelectiveAcceptResult {\r\n const rejected: string[] = [];\r\n const remaining: string[] = [];\r\n\r\n // Check if doc has full Document API (getAllParagraphs, getTables)\r\n // or if it's a minimal mock (only getRevisionManager)\r\n const hasFullApi = typeof (doc as any).getAllParagraphs === 'function';\r\n\r\n if (hasFullApi) {\r\n // Full in-memory DOM transformation\r\n const paragraphs = (doc as any).getAllParagraphs();\r\n for (const paragraph of paragraphs) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'reject', rejected, remaining);\r\n }\r\n\r\n // Process paragraphs in tables\r\n const tables = (doc as any).getTables();\r\n for (const table of tables) {\r\n for (const row of table.getRows()) {\r\n for (const cell of row.getCells()) {\r\n for (const paragraph of cell.getParagraphs()) {\r\n this.processSelectiveParagraph(paragraph, criteria, 'reject', rejected, remaining);\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: Filter revisions from RevisionManager only (for backward compatibility)\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n const allRevisions = revisionManager.getAllRevisions();\r\n for (const rev of allRevisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n rejected.push(rev.getId().toString());\r\n } else {\r\n remaining.push(rev.getId().toString());\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Clear rejected revisions from RevisionManager\r\n const revisionManager = doc.getRevisionManager();\r\n if (revisionManager) {\r\n for (const id of rejected) {\r\n revisionManager.removeById(parseInt(id, 10));\r\n }\r\n }\r\n\r\n return {\r\n accepted: [],\r\n rejected,\r\n remaining,\r\n summary: {\r\n totalProcessed: rejected.length + remaining.length,\r\n acceptedCount: 0,\r\n rejectedCount: rejected.length,\r\n remainingCount: remaining.length,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Process a paragraph for selective revision acceptance/rejection.\r\n * Transforms matching revisions in-place using DOM transformation.\r\n */\r\n private static processSelectiveParagraph(\r\n paragraph: Paragraph,\r\n criteria: SelectionCriteria,\r\n action: 'accept' | 'reject',\r\n processedIds: string[],\r\n remainingIds: string[]\r\n ): void {\r\n const content = paragraph.getContent();\r\n const newContent: ParagraphContent[] = [];\r\n\r\n for (const item of content) {\r\n if (item instanceof Revision) {\r\n const revisionId = item.getId().toString();\r\n\r\n if (this.matchesCriteria(item, criteria)) {\r\n // This revision matches the criteria - process it\r\n processedIds.push(revisionId);\r\n\r\n if (action === 'accept') {\r\n // Accept: Transform based on revision type\r\n this.acceptRevisionItem(item, newContent);\r\n } else {\r\n // Reject: Transform opposite of accept\r\n this.rejectRevisionItem(item, newContent);\r\n }\r\n } else {\r\n // This revision doesn't match - keep it\r\n remainingIds.push(revisionId);\r\n newContent.push(item);\r\n }\r\n } else {\r\n // Non-revision content - keep as-is\r\n newContent.push(item);\r\n }\r\n }\r\n\r\n // Replace paragraph content with the transformed content\r\n paragraph.setContent(newContent);\r\n\r\n // Handle paragraph mark revision markers (w:del/w:ins in w:pPr/w:rPr)\r\n // Both accept and reject clear the marker — these are metadata-only markers (no content),\r\n // so there is no content to add or remove, only the marker itself to clear.\r\n const formatting = paragraph.getFormatting();\r\n if (formatting.paragraphMarkDeletion) {\r\n const del = formatting.paragraphMarkDeletion;\r\n if (this.matchesMarkerCriteria(del, criteria)) {\r\n paragraph.clearParagraphMarkDeletion();\r\n processedIds.push(del.id.toString());\r\n } else {\r\n remainingIds.push(del.id.toString());\r\n }\r\n }\r\n if (formatting.paragraphMarkInsertion) {\r\n const ins = formatting.paragraphMarkInsertion;\r\n if (this.matchesMarkerCriteria(ins, criteria)) {\r\n paragraph.clearParagraphMarkInsertion();\r\n processedIds.push(ins.id.toString());\r\n } else {\r\n remainingIds.push(ins.id.toString());\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Check if a paragraph mark revision marker matches the given criteria.\r\n * Simplified version of matchesCriteria for non-Revision marker objects.\r\n */\r\n private static matchesMarkerCriteria(\r\n marker: { id: number; author: string; date: Date },\r\n criteria: SelectionCriteria\r\n ): boolean {\r\n // If no criteria specified, match nothing\r\n if (\r\n !criteria.ids &&\r\n !criteria.types &&\r\n !criteria.authors &&\r\n !criteria.dateRange &&\r\n !criteria.categories &&\r\n !criteria.custom\r\n ) {\r\n return false;\r\n }\r\n\r\n // Filter by IDs\r\n if (criteria.ids && !criteria.ids.includes(marker.id)) {\r\n return false;\r\n }\r\n\r\n // Filter by authors\r\n if (criteria.authors && !criteria.authors.includes(marker.author)) {\r\n return false;\r\n }\r\n\r\n // Filter by date range\r\n if (criteria.dateRange) {\r\n if (marker.date < criteria.dateRange.start || marker.date > criteria.dateRange.end) {\r\n return false;\r\n }\r\n }\r\n\r\n // types, categories, and custom filters don't apply to paragraph mark markers\r\n // (they are not Revision objects with a type/category)\r\n // If criteria only specifies types/categories/custom, markers won't match\r\n if (criteria.types || criteria.categories || criteria.custom) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Accept a single revision item (unwrap insertions, remove deletions).\r\n */\r\n private static acceptRevisionItem(\r\n revision: Revision,\r\n newContent: ParagraphContent[]\r\n ): void {\r\n const revisionType = revision.getType();\r\n const childContent = revision.getContent();\r\n\r\n switch (revisionType) {\r\n case 'insert':\r\n case 'moveTo':\r\n // Unwrap: Extract child content into parent position\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n case 'delete':\r\n case 'moveFrom':\r\n // Remove: Don't add to newContent - content is deleted\r\n break;\r\n\r\n case 'runPropertiesChange':\r\n case 'paragraphPropertiesChange':\r\n case 'tablePropertiesChange':\r\n case 'tableExceptionPropertiesChange':\r\n case 'tableRowPropertiesChange':\r\n case 'tableCellPropertiesChange':\r\n case 'sectionPropertiesChange':\r\n case 'numberingChange':\r\n // Property changes: Keep content, remove change metadata\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n default:\r\n // Unknown type - keep the revision as-is for safety\r\n newContent.push(revision);\r\n }\r\n }\r\n\r\n /**\r\n * Reject a single revision item (opposite of accept).\r\n * - Rejecting an insertion removes the content\r\n * - Rejecting a deletion keeps the content (unwraps it)\r\n */\r\n private static rejectRevisionItem(\r\n revision: Revision,\r\n newContent: ParagraphContent[]\r\n ): void {\r\n const revisionType = revision.getType();\r\n const childContent = revision.getContent();\r\n\r\n switch (revisionType) {\r\n case 'insert':\r\n case 'moveTo':\r\n // Reject insertion: Remove the inserted content entirely\r\n break;\r\n\r\n case 'delete':\r\n case 'moveFrom':\r\n // Reject deletion: Keep the deleted content (unwrap)\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n case 'runPropertiesChange':\r\n case 'paragraphPropertiesChange':\r\n case 'tablePropertiesChange':\r\n case 'tableExceptionPropertiesChange':\r\n case 'tableRowPropertiesChange':\r\n case 'tableCellPropertiesChange':\r\n case 'sectionPropertiesChange':\r\n case 'numberingChange':\r\n // Rejecting property changes: Would need to restore old properties\r\n // For now, just keep content without the change metadata\r\n // (Full implementation would restore previousProperties)\r\n for (const child of childContent) {\r\n if (isRunContent(child)) {\r\n newContent.push(child as Run);\r\n } else if (isHyperlinkContent(child)) {\r\n newContent.push(child);\r\n }\r\n }\r\n break;\r\n\r\n default:\r\n // Unknown type - keep the revision as-is for safety\r\n newContent.push(revision);\r\n }\r\n }\r\n\r\n /**\r\n * Preview what would happen without making changes.\r\n *\r\n * @param doc - Document to analyze\r\n * @param criteria - Selection criteria\r\n * @param action - Action to preview\r\n * @returns Preview of what would happen\r\n */\r\n static preview(\r\n doc: Document,\r\n criteria: SelectionCriteria,\r\n action: 'accept' | 'reject'\r\n ): SelectiveAcceptResult {\r\n // Preview is the same as the actual operation but without side effects\r\n return action === 'accept'\r\n ? this.accept(doc, criteria)\r\n : this.reject(doc, criteria);\r\n }\r\n\r\n /**\r\n * Accept all revisions by a specific author.\r\n *\r\n * @param doc - Document to process\r\n * @param author - Author name to accept\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptByAuthor(doc: Document, author: string): SelectiveAcceptResult {\r\n return this.accept(doc, { authors: [author] });\r\n }\r\n\r\n /**\r\n * Reject all revisions by a specific author.\r\n *\r\n * @param doc - Document to process\r\n * @param author - Author name to reject\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectByAuthor(doc: Document, author: string): SelectiveAcceptResult {\r\n return this.reject(doc, { authors: [author] });\r\n }\r\n\r\n /**\r\n * Accept all revisions of specific types.\r\n *\r\n * @param doc - Document to process\r\n * @param types - Revision types to accept\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptByType(doc: Document, types: RevisionType[]): SelectiveAcceptResult {\r\n return this.accept(doc, { types });\r\n }\r\n\r\n /**\r\n * Reject all revisions of specific types.\r\n *\r\n * @param doc - Document to process\r\n * @param types - Revision types to reject\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectByType(doc: Document, types: RevisionType[]): SelectiveAcceptResult {\r\n return this.reject(doc, { types });\r\n }\r\n\r\n /**\r\n * Accept all revisions before a specific date.\r\n *\r\n * @param doc - Document to process\r\n * @param date - Cutoff date (exclusive)\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptBeforeDate(doc: Document, date: Date): SelectiveAcceptResult {\r\n return this.accept(doc, {\r\n dateRange: { start: new Date(0), end: date },\r\n });\r\n }\r\n\r\n /**\r\n * Accept all revisions after a specific date.\r\n *\r\n * @param doc - Document to process\r\n * @param date - Start date (exclusive)\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptAfterDate(doc: Document, date: Date): SelectiveAcceptResult {\r\n return this.accept(doc, {\r\n dateRange: { start: date, end: new Date() },\r\n });\r\n }\r\n\r\n /**\r\n * Accept all insertions only.\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptInsertionsOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { types: ['insert'] });\r\n }\r\n\r\n /**\r\n * Accept all deletions only.\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptDeletionsOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { types: ['delete'] });\r\n }\r\n\r\n /**\r\n * Reject all formatting changes (keep content changes).\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static rejectFormattingChanges(doc: Document): SelectiveAcceptResult {\r\n return this.reject(doc, { categories: ['formatting'] });\r\n }\r\n\r\n /**\r\n * Accept content changes only (reject formatting).\r\n *\r\n * @param doc - Document to process\r\n * @returns Result with accepted, rejected, and remaining revision IDs\r\n */\r\n static acceptContentChangesOnly(doc: Document): SelectiveAcceptResult {\r\n return this.accept(doc, { categories: ['content'] });\r\n }\r\n\r\n /**\r\n * Partition revisions into matching and non-matching based on criteria.\r\n */\r\n private static partitionRevisions(\r\n revisions: Revision[],\r\n criteria: SelectionCriteria\r\n ): { matching: Revision[]; nonMatching: Revision[] } {\r\n const matching: Revision[] = [];\r\n const nonMatching: Revision[] = [];\r\n\r\n for (const rev of revisions) {\r\n if (this.matchesCriteria(rev, criteria)) {\r\n matching.push(rev);\r\n } else {\r\n nonMatching.push(rev);\r\n }\r\n }\r\n\r\n return { matching, nonMatching };\r\n }\r\n\r\n /**\r\n * Check if a revision matches the given criteria.\r\n */\r\n private static matchesCriteria(\r\n revision: Revision,\r\n criteria: SelectionCriteria\r\n ): boolean {\r\n // If no criteria specified, match nothing\r\n if (\r\n !criteria.ids &&\r\n !criteria.types &&\r\n !criteria.authors &&\r\n !criteria.dateRange &&\r\n !criteria.categories &&\r\n !criteria.custom\r\n ) {\r\n return false;\r\n }\r\n\r\n // Filter by IDs\r\n if (criteria.ids && !criteria.ids.includes(revision.getId())) {\r\n return false;\r\n }\r\n\r\n // Filter by types\r\n if (criteria.types && !criteria.types.includes(revision.getType())) {\r\n return false;\r\n }\r\n\r\n // Filter by authors\r\n if (criteria.authors && !criteria.authors.includes(revision.getAuthor())) {\r\n return false;\r\n }\r\n\r\n // Filter by date range\r\n if (criteria.dateRange) {\r\n const date = revision.getDate();\r\n if (date < criteria.dateRange.start || date > criteria.dateRange.end) {\r\n return false;\r\n }\r\n }\r\n\r\n // Filter by categories\r\n if (criteria.categories) {\r\n const category = this.getRevisionCategory(revision);\r\n if (!criteria.categories.includes(category)) {\r\n return false;\r\n }\r\n }\r\n\r\n // Custom filter\r\n if (criteria.custom && !criteria.custom(revision)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the semantic category of a revision.\r\n */\r\n private static getRevisionCategory(revision: Revision): ChangeCategory {\r\n const type = revision.getType();\r\n\r\n if (type === 'insert' || type === 'delete') {\r\n return 'content';\r\n }\r\n if (\r\n type === 'runPropertiesChange' ||\r\n type === 'paragraphPropertiesChange' ||\r\n type === 'numberingChange'\r\n ) {\r\n return 'formatting';\r\n }\r\n if (\r\n type === 'moveFrom' ||\r\n type === 'moveTo' ||\r\n type === 'sectionPropertiesChange'\r\n ) {\r\n return 'structural';\r\n }\r\n if (\r\n type === 'tablePropertiesChange' ||\r\n type === 'tableExceptionPropertiesChange' ||\r\n type === 'tableRowPropertiesChange' ||\r\n type === 'tableCellPropertiesChange' ||\r\n type === 'tableCellInsert' ||\r\n type === 'tableCellDelete' ||\r\n type === 'tableCellMerge'\r\n ) {\r\n return 'table';\r\n }\r\n\r\n return 'content';\r\n }\r\n\r\n /**\r\n * Create an empty result.\r\n */\r\n private static emptyResult(): SelectiveAcceptResult {\r\n return {\r\n accepted: [],\r\n rejected: [],\r\n remaining: [],\r\n summary: {\r\n totalProcessed: 0,\r\n acceptedCount: 0,\r\n rejectedCount: 0,\r\n remainingCount: 0,\r\n },\r\n };\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -2170,11 +2170,44 @@ export class DocumentParser {
|
|
|
2170
2170
|
// Paragraph mark run properties (w:rPr within w:pPr) per ECMA-376 Part 1 §17.3.1.29
|
|
2171
2171
|
// This controls formatting of the paragraph mark (¶ symbol) itself
|
|
2172
2172
|
if (pPrObj["w:rPr"]) {
|
|
2173
|
+
const rPrObj = pPrObj["w:rPr"];
|
|
2173
2174
|
// Create a temporary Run to use the existing parseRunPropertiesFromObject method
|
|
2174
2175
|
const tempRun = new Run("");
|
|
2175
|
-
this.parseRunPropertiesFromObject(
|
|
2176
|
+
this.parseRunPropertiesFromObject(rPrObj, tempRun);
|
|
2176
2177
|
// Extract the formatting and set it as paragraph mark properties
|
|
2177
2178
|
paragraph.setParagraphMarkFormatting(tempRun.getFormatting());
|
|
2179
|
+
|
|
2180
|
+
// Parse paragraph mark deletion tracking (w:del in w:pPr/w:rPr)
|
|
2181
|
+
// Per ECMA-376 Part 1 §17.13.5.14 - indicates the paragraph mark was deleted
|
|
2182
|
+
if (rPrObj["w:del"]) {
|
|
2183
|
+
// Handle array case (malformed XML with duplicate w:del elements)
|
|
2184
|
+
const rawDel = rPrObj["w:del"];
|
|
2185
|
+
const delObj = Array.isArray(rawDel) ? rawDel[0] : rawDel;
|
|
2186
|
+
if (delObj && typeof delObj === "object") {
|
|
2187
|
+
const id = parseInt(delObj["@_w:id"] || "0", 10) || 0;
|
|
2188
|
+
const author = String(delObj["@_w:author"] ?? "");
|
|
2189
|
+
const dateStr = delObj["@_w:date"];
|
|
2190
|
+
const parsedDate = dateStr ? new Date(String(dateStr)) : new Date();
|
|
2191
|
+
const date = isNaN(parsedDate.getTime()) ? new Date() : parsedDate;
|
|
2192
|
+
paragraph.markParagraphMarkAsDeleted(id, author, date);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
// Parse paragraph mark insertion tracking (w:ins in w:pPr/w:rPr)
|
|
2197
|
+
// Per ECMA-376 Part 1 §17.13.5.18 - indicates the paragraph mark was inserted
|
|
2198
|
+
if (rPrObj["w:ins"]) {
|
|
2199
|
+
// Handle array case (malformed XML with duplicate w:ins elements)
|
|
2200
|
+
const rawIns = rPrObj["w:ins"];
|
|
2201
|
+
const insObj = Array.isArray(rawIns) ? rawIns[0] : rawIns;
|
|
2202
|
+
if (insObj && typeof insObj === "object") {
|
|
2203
|
+
const id = parseInt(insObj["@_w:id"] || "0", 10) || 0;
|
|
2204
|
+
const author = String(insObj["@_w:author"] ?? "");
|
|
2205
|
+
const dateStr = insObj["@_w:date"];
|
|
2206
|
+
const parsedDate = dateStr ? new Date(String(dateStr)) : new Date();
|
|
2207
|
+
const date = isNaN(parsedDate.getTime()) ? new Date() : parsedDate;
|
|
2208
|
+
paragraph.markParagraphMarkAsInserted(id, author, date);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2178
2211
|
}
|
|
2179
2212
|
|
|
2180
2213
|
// Alignment
|