docxmlater 12.0.1 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionWalker.js","sourceRoot":"","sources":["../../src/processors/RevisionWalker.ts"],"names":[],"mappings":";;;AAqCA,MAAM,iBAAiB,GAAG;IAExB,MAAM,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC;IAG7B,MAAM,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;IAG/B,gBAAgB,EAAE;QAChB,aAAa;QACb,aAAa;QACb,eAAe;QACf,cAAc;QACd,cAAc;QACd,gBAAgB;QAChB,iBAAiB;QACjB,mBAAmB;QACnB,iBAAiB;KAClB;IAGD,aAAa,EAAE;QACb,sBAAsB;QACtB,oBAAoB;QACpB,oBAAoB;QACpB,kBAAkB;QAClB,0BAA0B;QAC1B,wBAAwB;QACxB,0BAA0B;QAC1B,wBAAwB;QACxB,+BAA+B;QAC/B,6BAA6B;QAC7B,6BAA6B;QAC7B,2BAA2B;KAC5B;CACF,CAAC;AAcF,MAAa,cAAc;IAczB,MAAM,CAAC,WAAW,CAAC,GAAoB,EAAE,OAA+B;QACtE,MAAM,IAAI,GAAoC;YAC5C,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,IAAI,IAAI;YACnD,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,IAAI;YACjD,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;YACzC,qBAAqB,EAAE,OAAO,EAAE,qBAAqB,IAAI,IAAI;SAC9D,CAAC;QAGF,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAG5C,cAAc,CAAC,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAE7C,OAAO,KAAK,CAAC;IACf,CAAC;IAKO,MAAM,CAAC,SAAS,CAAC,GAAQ;QAC/B,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO,GAAG,CAAC;QACb,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,KAAK,GAAQ,EAAE,CAAC;QACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAMO,MAAM,CAAC,gBAAgB,CAAC,GAAQ,EAAE,OAAwC;QAChF,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QAYD,IAAI,OAAO,CAAC,eAAe,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,cAAc,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,OAAO,CAAC,eAAe,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,cAAc,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACxC,CAAC;QAGD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,kBAAkB,CACxE,CAAC;QAGF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACvD,cAAc,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAID,cAAc,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAOO,MAAM,CAAC,iBAAiB,CAAC,GAAQ;QACvC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAW,EAAE;YACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAClD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAIpD,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACrB,CAAC;YACD,cAAc,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;QACtE,CAAC;aAAM,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC;YACnB,cAAc,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAYO,MAAM,CAAC,wBAAwB,CAAC,MAAW;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAW,EAAE;YAG3C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC;YAC/E,cAAc,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACtC,OAAO,CACL,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS;gBACzB,CAAC,GAAG,CAAC,OAAO,CAAC;gBACb,CAAC,GAAG,CAAC,UAAU,CAAC;gBAChB,CAAC,GAAG,CAAC,OAAO,CAAC;gBACb,CAAC,GAAG,CAAC,aAAa,CAAC,CACpB,CAAC;QACJ,CAAC,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;YACzB,CAAC;YACD,cAAc,CAAC,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAC1E,CAAC;aAAM,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;YACvB,cAAc,CAAC,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IASO,MAAM,CAAC,uBAAuB,CACpC,MAAW,EACX,IAAY,EACZ,cAA2B;QAE3B,IAAI,CAAC,MAAM,CAAC,gBAAgB;YAAE,OAAO;QACrC,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CACtD,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CACzE,CAAC;QACF,cAAc,CAAC,sBAAsB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjE,CAAC;IAKO,MAAM,CAAC,gBAAgB,CAAC,MAAW,EAAE,OAAwC;QACnF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,kBAAkB,CACxE,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;YAEhC,IAAI,cAAc,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC9C,cAAc,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAChD,CAAC;iBAAM,IAAI,cAAc,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;gBACrD,cAAc,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAKO,MAAM,CAAC,YAAY,CAAC,GAAW,EAAE,OAAwC;QAC/E,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,IAAI,GAAG,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB;gBAAE,OAAO,KAAK,CAAC;YAC/D,IAAI,GAAG,KAAK,UAAU,IAAI,CAAC,OAAO,CAAC,WAAW;gBAAE,OAAO,KAAK,CAAC;YAC7D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAKO,MAAM,CAAC,YAAY,CAAC,GAAW,EAAE,OAAwC;QAC/E,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,IAAI,GAAG,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe;gBAAE,OAAO,KAAK,CAAC;YAC9D,IAAI,GAAG,KAAK,YAAY,IAAI,CAAC,OAAO,CAAC,WAAW;gBAAE,OAAO,KAAK,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,OAAO,OAAO,CAAC,qBAAqB,CAAC;QACvC,CAAC;QACD,IAAI,iBAAiB,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAeO,MAAM,CAAC,iBAAiB,CAAC,MAAW,EAAE,GAAW;QACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAIrE,MAAM,eAAe,GAAqC,EAAE,CAAC;QAE7D,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAE5B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC/C,IAAI,cAAc,GAAG,CAAC,CAAC;YAEvB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;gBAEvB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBAEjB,MAAM,UAAU,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;oBAChD,cAAc,EAAE,CAAC;oBAEjB,IAAI,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;wBACjD,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;4BAEhC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;4BAChD,KAAK,MAAM,UAAU,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;gCACrD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC;gCAClC,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gCACnD,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;gCAE3C,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;gCAC5C,IAAI,aAAa,EAAE,CAAC;oCAClB,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;oCAClF,IAAI,QAAQ,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;wCACjC,eAAe,CAAC,IAAI,CAAC;4CACnB,IAAI,EAAE,SAAS;4CACf,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC;yCAC9B,CAAC,CAAC;oCACL,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;6BAAM,CAAC;4BAEN,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,kBAAkB,CACxE,CAAC;4BACF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gCACjC,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gCACxC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gCACzE,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;oCAC/B,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gCAC3D,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBAEN,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;oBAEhC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;oBACpC,IAAI,cAAc,EAAE,CAAC;wBACnB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;wBACtF,IAAI,GAAG,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;4BAC7B,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBAC5D,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAGD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QAGnB,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAE/B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAiB,CAAC;YAE/C,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,eAAe,EAAE,CAAC;gBAChD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7B,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC9B,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,CAAC;YAGD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC;gBAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;gBAC1B,CAAC;YACH,CAAC;YAGD,MAAM,kBAAkB,GAAuB,EAAE,CAAC;YAClD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;YAE/C,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,eAAe,EAAE,CAAC;gBACvC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;gBAChC,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAChD,CAAC;YAED,MAAM,CAAC,gBAAgB,GAAG,kBAAkB,CAAC;QAC/C,CAAC;aAAM,CAAC;YAEN,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;gBACnC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;oBAAE,SAAS;gBAEtD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,kBAAkB,CACxE,CAAC;gBAEF,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;oBACnC,cAAc,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAKO,MAAM,CAAC,iBAAiB,CAAC,MAAW,EAAE,GAAW;QACvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO;QAGzB,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC5B,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CACtD,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CACxC,CAAC;YAEF,cAAc,CAAC,sBAAsB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACjE,CAAC;QAGD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAKO,MAAM,CAAC,eAAe,CAAC,MAAW,EAAE,QAAgB,EAAE,UAAe;QAC3E,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;YAEnC,MAAM,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;QAChC,CAAC;aAAM,CAAC;YAEN,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAEvE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAKO,MAAM,CAAC,sBAAsB,CAAC,eAAmC;QACvE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE/C,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvD,KAAK,CAAC,KAAK,GAAG,YAAY,CAAC;YAC3B,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAKD,MAAM,CAAC,iBAAiB,CAAC,GAAW;QAClC,OAAO,CACL,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACtC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACtC,iBAAiB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC;YAChD,iBAAiB,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAC9C,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,4BAA4B;QACjC,OAAO,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClC,CAAC;CACF;AAzcD,wCAycC","sourcesContent":["/**\n * RevisionWalker - DOM-based tree walker for accepting tracked changes\n *\n * Replaces the fragile RegEx-based revision acceptance with a robust\n * DOM-based approach that properly handles nested elements and preserves\n * element ordering.\n *\n * @module RevisionWalker\n */\n\nimport { ParsedXMLObject } from '../xml/XMLParser.js';\n\n/**\n * Options for controlling which revision types to accept\n */\nexport interface RevisionWalkerOptions {\n /** Keep content, remove w:ins wrapper (default: true) */\n acceptInsertions?: boolean;\n /** Remove w:del and content entirely (default: true) */\n acceptDeletions?: boolean;\n /** Handle w:moveFrom/w:moveTo (default: true) */\n acceptMoves?: boolean;\n /** Remove *Change elements (default: true) */\n acceptPropertyChanges?: boolean;\n}\n\n/**\n * Structure for tracking element order\n */\ninterface OrderedChildInfo {\n type: string;\n index: number;\n}\n\n/**\n * Revision element categories\n */\nconst REVISION_ELEMENTS = {\n /** Elements to unwrap (keep content, remove wrapper) */\n UNWRAP: ['w:ins', 'w:moveTo'],\n\n /** Elements to remove entirely (with content) */\n REMOVE: ['w:del', 'w:moveFrom'],\n\n /** Property change tracking elements */\n PROPERTY_CHANGES: [\n 'w:rPrChange',\n 'w:pPrChange',\n 'w:tblPrChange',\n 'w:tcPrChange',\n 'w:trPrChange',\n 'w:sectPrChange',\n 'w:tblGridChange',\n 'w:numberingChange',\n 'w:tblPrExChange',\n ],\n\n /** Range marker elements */\n RANGE_MARKERS: [\n 'w:moveFromRangeStart',\n 'w:moveFromRangeEnd',\n 'w:moveToRangeStart',\n 'w:moveToRangeEnd',\n 'w:customXmlInsRangeStart',\n 'w:customXmlInsRangeEnd',\n 'w:customXmlDelRangeStart',\n 'w:customXmlDelRangeEnd',\n 'w:customXmlMoveFromRangeStart',\n 'w:customXmlMoveFromRangeEnd',\n 'w:customXmlMoveToRangeStart',\n 'w:customXmlMoveToRangeEnd',\n ],\n};\n\n/**\n * DOM-based tree walker for accepting Word document revisions\n *\n * This class processes a parsed XML object tree (from XMLParser.parseToObject())\n * and accepts all tracked changes by:\n * - Unwrapping insertions (w:ins, w:moveTo) - keeping content\n * - Removing deletions (w:del, w:moveFrom) - discarding content\n * - Removing property changes (*Change elements)\n * - Removing range markers\n *\n * Element order is preserved using the _orderedChildren metadata.\n */\nexport class RevisionWalker {\n /**\n * Process a parsed XML object tree and accept all revisions\n *\n * @param obj - Parsed XML object from XMLParser.parseToObject()\n * @param options - Options controlling which revisions to accept\n * @returns New object tree with revisions accepted\n *\n * @example\n * ```typescript\n * const parsed = XMLParser.parseToObject(documentXml);\n * const clean = RevisionWalker.processTree(parsed);\n * ```\n */\n static processTree(obj: ParsedXMLObject, options?: RevisionWalkerOptions): ParsedXMLObject {\n const opts: Required<RevisionWalkerOptions> = {\n acceptInsertions: options?.acceptInsertions ?? true,\n acceptDeletions: options?.acceptDeletions ?? true,\n acceptMoves: options?.acceptMoves ?? true,\n acceptPropertyChanges: options?.acceptPropertyChanges ?? true,\n };\n\n // Deep clone the object to avoid mutating the original\n const clone = RevisionWalker.deepClone(obj);\n\n // Walk and transform the tree\n RevisionWalker.walkAndTransform(clone, opts);\n\n return clone;\n }\n\n /**\n * Deep clone an object\n */\n private static deepClone(obj: any): any {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => RevisionWalker.deepClone(item));\n }\n\n const clone: any = {};\n for (const key of Object.keys(obj)) {\n clone[key] = RevisionWalker.deepClone(obj[key]);\n }\n return clone;\n }\n\n /**\n * Recursively walk and transform the object tree\n * Processes children first (depth-first) to handle nested revisions\n */\n private static walkAndTransform(obj: any, options: Required<RevisionWalkerOptions>): void {\n if (obj === null || typeof obj !== 'object') {\n return;\n }\n\n // Pre-recursion: row-level tracked deletions (CT_TrPr > w:del per\n // §17.13.5.14). Must run BEFORE the depth-first recursion — otherwise\n // processRevisions in trPr would strip the w:del marker before we can\n // detect it at the table level. The default `w:del` removal in\n // processRevisions only strips the marker itself, leaving a zombie\n // empty row; per spec, accepting the deletion removes the entire row.\n // Tables are checked from the parent first: a table whose rows are ALL\n // tracked-deleted must be removed entirely (a row-less w:tbl violates\n // §17.4.38's at-least-one-row requirement and Word's Accept All drops\n // the whole table), and only the parent can remove the w:tbl itself.\n if (options.acceptDeletions && obj['w:tbl']) {\n RevisionWalker.removeFullyDeletedTables(obj);\n }\n if (options.acceptDeletions && obj['w:tr']) {\n RevisionWalker.filterDeletedRows(obj);\n }\n\n // Get keys to process (excluding metadata keys)\n const keys = Object.keys(obj).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n // First pass: recurse into children (depth-first)\n for (const key of keys) {\n const value = obj[key];\n if (Array.isArray(value)) {\n for (const item of value) {\n RevisionWalker.walkAndTransform(item, options);\n }\n } else if (typeof value === 'object' && value !== null) {\n RevisionWalker.walkAndTransform(value, options);\n }\n }\n\n // Second pass: process revision elements at this level\n // We need to iterate carefully because we're modifying the object\n RevisionWalker.processRevisions(obj, options);\n }\n\n /**\n * Remove `<w:tr>` entries whose `<w:trPr>` contains a self-closing\n * `<w:del/>` row-level deletion marker. Operates on the parsed-object\n * representation (arrays when multiple, single object otherwise).\n */\n private static filterDeletedRows(tbl: any): void {\n const rows = tbl['w:tr'];\n const isRowDeleted = (row: any): boolean => {\n if (!row || typeof row !== 'object') return false;\n const trPr = row['w:trPr'];\n if (!trPr || typeof trPr !== 'object') return false;\n // w:del at row level is a CT_TrackChange (no children). When absent\n // the parser leaves no key; when present it's a self-closing tag\n // parsed as an object with only @_w:id/@_w:author/@_w:date keys.\n return !!trPr['w:del'];\n };\n\n if (Array.isArray(rows)) {\n const removedIndices = new Set<number>();\n for (let i = 0; i < rows.length; i++) {\n if (isRowDeleted(rows[i])) removedIndices.add(i);\n }\n if (removedIndices.size === 0) return;\n const kept = rows.filter((_, i) => !removedIndices.has(i));\n if (kept.length === 0) {\n delete tbl['w:tr'];\n } else {\n tbl['w:tr'] = kept;\n }\n RevisionWalker.dropOrderedChildEntries(tbl, 'w:tr', removedIndices);\n } else if (isRowDeleted(rows)) {\n delete tbl['w:tr'];\n RevisionWalker.dropOrderedChildEntries(tbl, 'w:tr', new Set([0]));\n }\n }\n\n /**\n * Remove `<w:tbl>` children whose rows are ALL tracked-deleted.\n *\n * Runs at the table's parent because filterDeletedRows (invoked on the\n * table itself) has no reference back to the container holding the\n * `w:tbl` key. Skips tables that still carry potential row containers\n * (w:ins / w:moveTo wrappers, w:sdt, w:customXml) — their surviving rows\n * are only materialized as direct `w:tr` children later, when the\n * wrappers are unwrapped during recursion.\n */\n private static removeFullyDeletedTables(parent: any): void {\n const tables = parent['w:tbl'];\n const becomesRowless = (tbl: any): boolean => {\n // Tables with no rows at all are pre-existing structures, not the\n // result of accepting a deletion — leave them untouched.\n if (!tbl || typeof tbl !== 'object' || tbl['w:tr'] === undefined) return false;\n RevisionWalker.filterDeletedRows(tbl);\n return (\n tbl['w:tr'] === undefined &&\n !tbl['w:ins'] &&\n !tbl['w:moveTo'] &&\n !tbl['w:sdt'] &&\n !tbl['w:customXml']\n );\n };\n\n if (Array.isArray(tables)) {\n const removedIndices = new Set<number>();\n for (let i = 0; i < tables.length; i++) {\n if (becomesRowless(tables[i])) removedIndices.add(i);\n }\n if (removedIndices.size === 0) return;\n const kept = tables.filter((_: any, i: number) => !removedIndices.has(i));\n if (kept.length === 0) {\n delete parent['w:tbl'];\n } else {\n parent['w:tbl'] = kept;\n }\n RevisionWalker.dropOrderedChildEntries(parent, 'w:tbl', removedIndices);\n } else if (becomesRowless(tables)) {\n delete parent['w:tbl'];\n RevisionWalker.dropOrderedChildEntries(parent, 'w:tbl', new Set([0]));\n }\n }\n\n /**\n * Drop specific {type, index} entries from `_orderedChildren` and\n * re-index the survivors. The serializer maps each entry onto the\n * element array by index, so stale entries left after filtering would\n * shift surviving elements relative to inter-element siblings (e.g. a\n * w:bookmarkEnd between table rows) or silently drop the tail.\n */\n private static dropOrderedChildEntries(\n parent: any,\n type: string,\n removedIndices: Set<number>\n ): void {\n if (!parent._orderedChildren) return;\n parent._orderedChildren = parent._orderedChildren.filter(\n (c: OrderedChildInfo) => c.type !== type || !removedIndices.has(c.index)\n );\n RevisionWalker.reindexOrderedChildren(parent._orderedChildren);\n }\n\n /**\n * Process revision elements at the current level\n */\n private static processRevisions(parent: any, options: Required<RevisionWalkerOptions>): void {\n if (!parent || typeof parent !== 'object') {\n return;\n }\n\n const keysToProcess = Object.keys(parent).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n for (const key of keysToProcess) {\n // Check if this is a revision element\n if (RevisionWalker.shouldUnwrap(key, options)) {\n RevisionWalker.unwrapAllElements(parent, key);\n } else if (RevisionWalker.shouldRemove(key, options)) {\n RevisionWalker.removeAllElements(parent, key);\n }\n }\n }\n\n /**\n * Check if an element should be unwrapped (content kept)\n */\n private static shouldUnwrap(key: string, options: Required<RevisionWalkerOptions>): boolean {\n if (REVISION_ELEMENTS.UNWRAP.includes(key)) {\n if (key === 'w:ins' && !options.acceptInsertions) return false;\n if (key === 'w:moveTo' && !options.acceptMoves) return false;\n return true;\n }\n return false;\n }\n\n /**\n * Check if an element should be removed (content discarded)\n */\n private static shouldRemove(key: string, options: Required<RevisionWalkerOptions>): boolean {\n if (REVISION_ELEMENTS.REMOVE.includes(key)) {\n if (key === 'w:del' && !options.acceptDeletions) return false;\n if (key === 'w:moveFrom' && !options.acceptMoves) return false;\n return true;\n }\n if (REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key)) {\n return options.acceptPropertyChanges;\n }\n if (REVISION_ELEMENTS.RANGE_MARKERS.includes(key)) {\n return true; // Always remove range markers\n }\n return false;\n }\n\n /**\n * Unwrap all elements of a given type, promoting their children to parent\n *\n * This is the most complex operation in RevisionWalker. When we unwrap a\n * revision element like w:ins, we need to:\n * 1. Extract the children from inside w:ins\n * 2. Insert them at the correct position in the parent's element arrays\n * 3. Update _orderedChildren to reflect the new structure\n *\n * The key challenge is maintaining correct element order. For example:\n * Before: <w:tbl><w:tr>Row1</w:tr><w:ins><w:tr>Row2</w:tr></w:ins><w:tr>Row3</w:tr></w:tbl>\n * After: <w:tbl><w:tr>Row1</w:tr><w:tr>Row2</w:tr><w:tr>Row3</w:tr></w:tbl>\n */\n private static unwrapAllElements(parent: any, key: string): void {\n const elements = parent[key];\n if (!elements) return;\n\n const elementArray = Array.isArray(elements) ? elements : [elements];\n\n // Build a complete ordered list of child elements by walking _orderedChildren\n // This captures the intended order before we modify anything\n const orderedElements: { type: string; element: any }[] = [];\n\n if (parent._orderedChildren) {\n // Track how many of each type we've seen to get correct array index\n const typeCounters = new Map<string, number>();\n let unwrappedIndex = 0;\n\n for (const entry of parent._orderedChildren) {\n const { type } = entry;\n\n if (type === key) {\n // This is a revision element - extract its children in order\n const revElement = elementArray[unwrappedIndex];\n unwrappedIndex++;\n\n if (revElement && typeof revElement === 'object') {\n if (revElement._orderedChildren) {\n // Use the revision element's _orderedChildren for correct order\n const childCounters = new Map<string, number>();\n for (const childEntry of revElement._orderedChildren) {\n const childType = childEntry.type;\n const childIdx = childCounters.get(childType) || 0;\n childCounters.set(childType, childIdx + 1);\n\n const childElements = revElement[childType];\n if (childElements) {\n const childArray = Array.isArray(childElements) ? childElements : [childElements];\n if (childIdx < childArray.length) {\n orderedElements.push({\n type: childType,\n element: childArray[childIdx],\n });\n }\n }\n }\n } else {\n // No _orderedChildren, extract children in object key order\n const childKeys = Object.keys(revElement).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n for (const childKey of childKeys) {\n const childValue = revElement[childKey];\n const childArray = Array.isArray(childValue) ? childValue : [childValue];\n for (const child of childArray) {\n orderedElements.push({ type: childKey, element: child });\n }\n }\n }\n }\n } else {\n // Regular element - get it from the parent\n const idx = typeCounters.get(type) || 0;\n typeCounters.set(type, idx + 1);\n\n const parentElements = parent[type];\n if (parentElements) {\n const parentArray = Array.isArray(parentElements) ? parentElements : [parentElements];\n if (idx < parentArray.length) {\n orderedElements.push({ type, element: parentArray[idx] });\n }\n }\n }\n }\n }\n\n // Remove the revision wrapper\n delete parent[key];\n\n // If we have ordered elements, rebuild the arrays in correct order\n if (orderedElements.length > 0) {\n // Group elements by type\n const rebuiltArrays = new Map<string, any[]>();\n\n for (const { type, element } of orderedElements) {\n if (!rebuiltArrays.has(type)) {\n rebuiltArrays.set(type, []);\n }\n rebuiltArrays.get(type)!.push(element);\n }\n\n // Update parent with rebuilt arrays\n for (const [type, elements] of rebuiltArrays) {\n if (elements.length === 1) {\n parent[type] = elements[0];\n } else {\n parent[type] = elements;\n }\n }\n\n // Rebuild _orderedChildren\n const newOrderedChildren: OrderedChildInfo[] = [];\n const typeCounters = new Map<string, number>();\n\n for (const { type } of orderedElements) {\n const idx = typeCounters.get(type) || 0;\n typeCounters.set(type, idx + 1);\n newOrderedChildren.push({ type, index: idx });\n }\n\n parent._orderedChildren = newOrderedChildren;\n } else {\n // Fallback for when there's no _orderedChildren - just merge\n for (const element of elementArray) {\n if (!element || typeof element !== 'object') continue;\n\n const elementKeys = Object.keys(element).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n for (const childKey of elementKeys) {\n RevisionWalker.mergeIntoParent(parent, childKey, element[childKey]);\n }\n }\n }\n }\n\n /**\n * Remove all elements of a given type (including their content)\n */\n private static removeAllElements(parent: any, key: string): void {\n if (!parent[key]) return;\n\n // Update _orderedChildren before removing\n if (parent._orderedChildren) {\n parent._orderedChildren = parent._orderedChildren.filter(\n (c: OrderedChildInfo) => c.type !== key\n );\n // Re-index remaining elements of same types\n RevisionWalker.reindexOrderedChildren(parent._orderedChildren);\n }\n\n // Remove the element\n delete parent[key];\n }\n\n /**\n * Merge a child value into the parent, handling arrays properly\n */\n private static mergeIntoParent(parent: any, childKey: string, childValue: any): void {\n if (parent[childKey] === undefined) {\n // No existing value, just assign\n parent[childKey] = childValue;\n } else {\n // Existing value, need to merge\n const existing = parent[childKey];\n const incoming = Array.isArray(childValue) ? childValue : [childValue];\n\n if (Array.isArray(existing)) {\n parent[childKey] = [...existing, ...incoming];\n } else {\n parent[childKey] = [existing, ...incoming];\n }\n }\n }\n\n /**\n * Re-index _orderedChildren to ensure indices are sequential per type\n */\n private static reindexOrderedChildren(orderedChildren: OrderedChildInfo[]): void {\n const typeCounters = new Map<string, number>();\n\n for (const entry of orderedChildren) {\n const currentIndex = typeCounters.get(entry.type) || 0;\n entry.index = currentIndex;\n typeCounters.set(entry.type, currentIndex + 1);\n }\n }\n\n /**\n * Check if an element is a revision-related element (any type)\n */\n static isRevisionElement(key: string): boolean {\n return (\n REVISION_ELEMENTS.UNWRAP.includes(key) ||\n REVISION_ELEMENTS.REMOVE.includes(key) ||\n REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key) ||\n REVISION_ELEMENTS.RANGE_MARKERS.includes(key)\n );\n }\n\n /**\n * Get revision element categories (for external use/testing)\n */\n static getRevisionElementCategories(): typeof REVISION_ELEMENTS {\n return { ...REVISION_ELEMENTS };\n }\n}\n"]}
1
+ {"version":3,"file":"RevisionWalker.js","sourceRoot":"","sources":["../../src/processors/RevisionWalker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RevisionWalker - DOM-based tree walker for accepting tracked changes\n *\n * Replaces the fragile RegEx-based revision acceptance with a robust\n * DOM-based approach that properly handles nested elements and preserves\n * element ordering.\n *\n * @module RevisionWalker\n */\n\nimport { ParsedXMLObject } from '../xml/XMLParser.js';\n\n/**\n * Options for controlling which revision types to process\n */\nexport interface RevisionWalkerOptions {\n /**\n * Direction of processing (default: 'accept').\n *\n * - 'accept': keep inserted content, discard deleted content (the post-edit\n * document).\n * - 'reject': discard inserted content, restore deleted content and previous\n * formatting (the original pre-edit document — the exact inverse of accept).\n */\n mode?: 'accept' | 'reject';\n /**\n * Process insertions. In 'accept' mode w:ins is unwrapped (content kept); in\n * 'reject' mode w:ins is removed (content discarded). Inserted rows/tables are\n * removed under 'reject'. (default: true)\n */\n acceptInsertions?: boolean;\n /**\n * Process deletions. In 'accept' mode w:del is removed (content discarded); in\n * 'reject' mode w:del is unwrapped and w:delText restored to w:t. Deleted\n * rows/tables are removed under 'accept'. (default: true)\n */\n acceptDeletions?: boolean;\n /** Handle w:moveFrom/w:moveTo (default: true) */\n acceptMoves?: boolean;\n /**\n * Process *Change elements. In 'accept' mode they are removed (current\n * formatting kept); in 'reject' mode the previous formatting stored inside the\n * change is restored. (default: true)\n */\n acceptPropertyChanges?: boolean;\n}\n\n/** Action to take on a revision element at a given level. */\ntype RevisionAction = 'unwrap' | 'remove' | 'restore' | 'none';\n\n/**\n * Structure for tracking element order\n */\ninterface OrderedChildInfo {\n type: string;\n index: number;\n}\n\n/**\n * Revision element categories\n */\nconst REVISION_ELEMENTS = {\n /** Elements to unwrap (keep content, remove wrapper) */\n UNWRAP: ['w:ins', 'w:moveTo'],\n\n /** Elements to remove entirely (with content) */\n REMOVE: ['w:del', 'w:moveFrom'],\n\n /** Property change tracking elements */\n PROPERTY_CHANGES: [\n 'w:rPrChange',\n 'w:pPrChange',\n 'w:tblPrChange',\n 'w:tcPrChange',\n 'w:trPrChange',\n 'w:sectPrChange',\n 'w:tblGridChange',\n 'w:numberingChange',\n 'w:tblPrExChange',\n ],\n\n /** Range marker elements */\n RANGE_MARKERS: [\n 'w:moveFromRangeStart',\n 'w:moveFromRangeEnd',\n 'w:moveToRangeStart',\n 'w:moveToRangeEnd',\n 'w:customXmlInsRangeStart',\n 'w:customXmlInsRangeEnd',\n 'w:customXmlDelRangeStart',\n 'w:customXmlDelRangeEnd',\n 'w:customXmlMoveFromRangeStart',\n 'w:customXmlMoveFromRangeEnd',\n 'w:customXmlMoveToRangeStart',\n 'w:customXmlMoveToRangeEnd',\n ],\n};\n\n/**\n * Children that are tracked independently of a property-change snapshot and\n * must be carried over (not wiped) when rejecting that change restores the\n * previous properties. Keyed by the wrapper element; `position` is where they\n * sit in the wrapper's ECMA-376 child order relative to the restored snapshot:\n *\n * - CT_PPr (§17.3.1.26): the paragraph-mark run properties (`w:rPr`) and the\n * section properties (`w:sectPr`) follow the base paragraph properties, and a\n * `w:pPrChange` snapshot is a CT_PPrBase that contains neither.\n * - CT_SectPr (§17.6.17): the header/footer references PRECEDE the section base\n * contents, and a `w:sectPrChange` snapshot is a CT_SectPrBase that contains\n * neither — so they must be prepended or the section loses its headers/footers.\n */\nconst PRESERVED_ON_RESTORE: Record<string, { keys: string[]; position: 'before' | 'after' }> = {\n 'w:pPr': { keys: ['w:rPr', 'w:sectPr'], position: 'after' },\n 'w:sectPr': { keys: ['w:headerReference', 'w:footerReference'], position: 'before' },\n};\n\n/**\n * Deleted run-content elements and the live elements they restore to when a\n * deletion is rejected (§17.3.3.7 w:delText is structurally CT_Text, identical\n * to w:t; w:delInstrText likewise mirrors w:instrText).\n */\nconst DELETED_TEXT_RENAMES: Record<string, string> = {\n 'w:delText': 'w:t',\n 'w:delInstrText': 'w:instrText',\n};\n\n/**\n * DOM-based tree walker for accepting Word document revisions\n *\n * This class processes a parsed XML object tree (from XMLParser.parseToObject())\n * and accepts all tracked changes by:\n * - Unwrapping insertions (w:ins, w:moveTo) - keeping content\n * - Removing deletions (w:del, w:moveFrom) - discarding content\n * - Removing property changes (*Change elements)\n * - Removing range markers\n *\n * Element order is preserved using the _orderedChildren metadata.\n */\nexport class RevisionWalker {\n /**\n * Process a parsed XML object tree and accept all revisions\n *\n * @param obj - Parsed XML object from XMLParser.parseToObject()\n * @param options - Options controlling which revisions to accept\n * @returns New object tree with revisions accepted\n *\n * @example\n * ```typescript\n * const parsed = XMLParser.parseToObject(documentXml);\n * const clean = RevisionWalker.processTree(parsed);\n * ```\n */\n static processTree(obj: ParsedXMLObject, options?: RevisionWalkerOptions): ParsedXMLObject {\n const opts: Required<RevisionWalkerOptions> = {\n mode: options?.mode ?? 'accept',\n acceptInsertions: options?.acceptInsertions ?? true,\n acceptDeletions: options?.acceptDeletions ?? true,\n acceptMoves: options?.acceptMoves ?? true,\n acceptPropertyChanges: options?.acceptPropertyChanges ?? true,\n };\n\n // Deep clone the object to avoid mutating the original\n const clone = RevisionWalker.deepClone(obj);\n\n // Walk and transform the tree\n RevisionWalker.walkAndTransform(clone, opts);\n\n // Reject restores deleted content by unwrapping w:del; the runs inside a\n // deletion carry their text in w:delText (and field codes in\n // w:delInstrText). Once unwrapped they are live content again, so convert\n // those back to the normal w:t / w:instrText elements. (§17.3.3.7)\n if (opts.mode === 'reject' && opts.acceptDeletions) {\n RevisionWalker.convertDeletedTextToNormal(clone);\n }\n\n return clone;\n }\n\n /**\n * Deep clone an object\n */\n private static deepClone(obj: any): any {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => RevisionWalker.deepClone(item));\n }\n\n const clone: any = {};\n for (const key of Object.keys(obj)) {\n clone[key] = RevisionWalker.deepClone(obj[key]);\n }\n return clone;\n }\n\n /**\n * Recursively walk and transform the object tree\n * Processes children first (depth-first) to handle nested revisions\n */\n private static walkAndTransform(obj: any, options: Required<RevisionWalkerOptions>): void {\n if (obj === null || typeof obj !== 'object') {\n return;\n }\n\n // Pre-recursion: row-level tracked deletions (CT_TrPr > w:del per\n // §17.13.5.14). Must run BEFORE the depth-first recursion — otherwise\n // processRevisions in trPr would strip the w:del marker before we can\n // detect it at the table level. The default `w:del` removal in\n // processRevisions only strips the marker itself, leaving a zombie\n // empty row; per spec, accepting the deletion removes the entire row.\n // Tables are checked from the parent first: a table whose rows are ALL\n // tracked-deleted must be removed entirely (a row-less w:tbl violates\n // §17.4.38's at-least-one-row requirement and Word's Accept All drops\n // the whole table), and only the parent can remove the w:tbl itself.\n // Reject is the mirror image: a row whose w:trPr carries a self-closing\n // w:ins marker was added by the edit and must be removed to revert to the\n // original (gated on acceptInsertions, since this undoes an insertion). A\n // table whose rows are ALL insert-marked is removed entirely, mirroring the\n // accept-side at-least-one-row handling.\n if (options.mode === 'reject') {\n if (options.acceptInsertions && obj['w:tbl']) {\n RevisionWalker.removeFullyMarkedTables(obj, 'w:ins');\n }\n if (options.acceptInsertions && obj['w:tr']) {\n RevisionWalker.filterMarkedRows(obj, 'w:ins');\n }\n } else {\n if (options.acceptDeletions && obj['w:tbl']) {\n RevisionWalker.removeFullyMarkedTables(obj, 'w:del');\n }\n if (options.acceptDeletions && obj['w:tr']) {\n RevisionWalker.filterMarkedRows(obj, 'w:del');\n }\n }\n\n // Get keys to process (excluding metadata keys)\n const keys = Object.keys(obj).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n // First pass: recurse into children (depth-first)\n for (const key of keys) {\n const value = obj[key];\n if (Array.isArray(value)) {\n for (const item of value) {\n RevisionWalker.walkAndTransform(item, options);\n }\n } else if (typeof value === 'object' && value !== null) {\n RevisionWalker.walkAndTransform(value, options);\n }\n }\n\n // Second pass: process revision elements at this level\n // We need to iterate carefully because we're modifying the object\n RevisionWalker.processRevisions(obj, options);\n }\n\n /**\n * Remove `<w:tr>` entries whose `<w:trPr>` contains a self-closing row-level\n * tracking marker. `marker` is `w:del` when accepting (drop deleted rows) or\n * `w:ins` when rejecting (drop inserted rows). Operates on the parsed-object\n * representation (arrays when multiple, single object otherwise).\n */\n private static filterMarkedRows(tbl: any, marker: 'w:del' | 'w:ins'): void {\n const rows = tbl['w:tr'];\n const isRowMarked = (row: any): boolean => {\n if (!row || typeof row !== 'object') return false;\n const trPr = row['w:trPr'];\n if (!trPr || typeof trPr !== 'object') return false;\n // The row-level marker is a CT_TrackChange (no children). When absent\n // the parser leaves no key; when present it's a self-closing tag\n // parsed as an object with only @_w:id/@_w:author/@_w:date keys.\n return !!trPr[marker];\n };\n\n if (Array.isArray(rows)) {\n const removedIndices = new Set<number>();\n for (let i = 0; i < rows.length; i++) {\n if (isRowMarked(rows[i])) removedIndices.add(i);\n }\n if (removedIndices.size === 0) return;\n const kept = rows.filter((_, i) => !removedIndices.has(i));\n if (kept.length === 0) {\n delete tbl['w:tr'];\n } else {\n tbl['w:tr'] = kept;\n }\n RevisionWalker.dropOrderedChildEntries(tbl, 'w:tr', removedIndices);\n } else if (isRowMarked(rows)) {\n delete tbl['w:tr'];\n RevisionWalker.dropOrderedChildEntries(tbl, 'w:tr', new Set([0]));\n }\n }\n\n /**\n * Remove `<w:tbl>` children whose rows are ALL marked with the given\n * row-level tracking marker (`w:del` when accepting, `w:ins` when rejecting).\n *\n * Runs at the table's parent because filterMarkedRows (invoked on the table\n * itself) has no reference back to the container holding the `w:tbl` key.\n * Skips tables that still carry potential row containers — the wrappers that\n * SURVIVE this direction (w:ins/w:moveTo when accepting deletions,\n * w:del/w:moveFrom when rejecting insertions), plus w:sdt / w:customXml —\n * since their rows only materialize as direct `w:tr` children later, when the\n * wrappers are unwrapped during recursion.\n */\n private static removeFullyMarkedTables(parent: any, marker: 'w:del' | 'w:ins'): void {\n const tables = parent['w:tbl'];\n // Wrappers whose rows survive in this direction must not be treated as\n // \"rowless\": accept keeps w:ins/w:moveTo content, reject keeps w:del/\n // w:moveFrom content.\n const survivingWrappers: string[] =\n marker === 'w:del' ? ['w:ins', 'w:moveTo'] : ['w:del', 'w:moveFrom'];\n const becomesRowless = (tbl: any): boolean => {\n // Tables with no rows at all are pre-existing structures, not the\n // result of a tracked change — leave them untouched.\n if (!tbl || typeof tbl !== 'object' || tbl['w:tr'] === undefined) return false;\n RevisionWalker.filterMarkedRows(tbl, marker);\n return (\n tbl['w:tr'] === undefined &&\n !survivingWrappers.some((w) => tbl[w]) &&\n !tbl['w:sdt'] &&\n !tbl['w:customXml']\n );\n };\n\n if (Array.isArray(tables)) {\n const removedIndices = new Set<number>();\n for (let i = 0; i < tables.length; i++) {\n if (becomesRowless(tables[i])) removedIndices.add(i);\n }\n if (removedIndices.size === 0) return;\n const kept = tables.filter((_: any, i: number) => !removedIndices.has(i));\n if (kept.length === 0) {\n delete parent['w:tbl'];\n } else {\n parent['w:tbl'] = kept;\n }\n RevisionWalker.dropOrderedChildEntries(parent, 'w:tbl', removedIndices);\n } else if (becomesRowless(tables)) {\n delete parent['w:tbl'];\n RevisionWalker.dropOrderedChildEntries(parent, 'w:tbl', new Set([0]));\n }\n }\n\n /**\n * Drop specific {type, index} entries from `_orderedChildren` and\n * re-index the survivors. The serializer maps each entry onto the\n * element array by index, so stale entries left after filtering would\n * shift surviving elements relative to inter-element siblings (e.g. a\n * w:bookmarkEnd between table rows) or silently drop the tail.\n */\n private static dropOrderedChildEntries(\n parent: any,\n type: string,\n removedIndices: Set<number>\n ): void {\n if (!parent._orderedChildren) return;\n parent._orderedChildren = parent._orderedChildren.filter(\n (c: OrderedChildInfo) => c.type !== type || !removedIndices.has(c.index)\n );\n RevisionWalker.reindexOrderedChildren(parent._orderedChildren);\n }\n\n /**\n * Process revision elements at the current level\n */\n private static processRevisions(parent: any, options: Required<RevisionWalkerOptions>): void {\n if (!parent || typeof parent !== 'object') {\n return;\n }\n\n const keysToProcess = Object.keys(parent).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n for (const key of keysToProcess) {\n switch (RevisionWalker.getActionForKey(key, options)) {\n case 'unwrap':\n RevisionWalker.unwrapAllElements(parent, key);\n break;\n case 'remove':\n RevisionWalker.removeAllElements(parent, key);\n break;\n case 'restore':\n RevisionWalker.restorePropertyChange(parent, key);\n break;\n case 'none':\n break;\n }\n }\n }\n\n /**\n * Resolve what to do with a revision element of the given key, honouring the\n * processing direction. Accept and reject are exact inverses for content\n * revisions; property changes are removed on accept and restored on reject.\n */\n private static getActionForKey(\n key: string,\n options: Required<RevisionWalkerOptions>\n ): RevisionAction {\n const reject = options.mode === 'reject';\n\n // Content revisions are driven off REVISION_ELEMENTS so membership stays a\n // single source of truth (shared with isRevisionElement). On accept, UNWRAP\n // keeps content and REMOVE discards it; reject is the exact inverse.\n const isUnwrap = REVISION_ELEMENTS.UNWRAP.includes(key);\n const isRemove = REVISION_ELEMENTS.REMOVE.includes(key);\n if (isUnwrap || isRemove) {\n // Per-key gating: w:ins ↔ insertions, w:del ↔ deletions, w:moveTo/\n // w:moveFrom ↔ moves.\n const gate =\n key === 'w:ins'\n ? options.acceptInsertions\n : key === 'w:del'\n ? options.acceptDeletions\n : options.acceptMoves;\n if (!gate) return 'none';\n const keepContent = reject ? isRemove : isUnwrap;\n return keepContent ? 'unwrap' : 'remove';\n }\n if (REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key)) {\n if (!options.acceptPropertyChanges) return 'none';\n // w:numberingChange (CT_TrackChangeNumbering) is a legacy attribute-only\n // marker with no embedded previous-properties element, so there is\n // nothing to restore — drop it in both directions.\n if (reject && key !== 'w:numberingChange') return 'restore';\n return 'remove';\n }\n if (REVISION_ELEMENTS.RANGE_MARKERS.includes(key)) {\n return 'remove'; // Always remove range markers\n }\n return 'none';\n }\n\n /**\n * Unwrap all elements of a given type, promoting their children to parent\n *\n * This is the most complex operation in RevisionWalker. When we unwrap a\n * revision element like w:ins, we need to:\n * 1. Extract the children from inside w:ins\n * 2. Insert them at the correct position in the parent's element arrays\n * 3. Update _orderedChildren to reflect the new structure\n *\n * The key challenge is maintaining correct element order. For example:\n * Before: <w:tbl><w:tr>Row1</w:tr><w:ins><w:tr>Row2</w:tr></w:ins><w:tr>Row3</w:tr></w:tbl>\n * After: <w:tbl><w:tr>Row1</w:tr><w:tr>Row2</w:tr><w:tr>Row3</w:tr></w:tbl>\n */\n private static unwrapAllElements(parent: any, key: string): void {\n const elements = parent[key];\n if (!elements) return;\n\n const elementArray = Array.isArray(elements) ? elements : [elements];\n\n // Build a complete ordered list of child elements by walking _orderedChildren\n // This captures the intended order before we modify anything\n const orderedElements: { type: string; element: any }[] = [];\n\n if (parent._orderedChildren) {\n // Track how many of each type we've seen to get correct array index\n const typeCounters = new Map<string, number>();\n let unwrappedIndex = 0;\n\n for (const entry of parent._orderedChildren) {\n const { type } = entry;\n\n if (type === key) {\n // This is a revision element - extract its children in order\n const revElement = elementArray[unwrappedIndex];\n unwrappedIndex++;\n\n if (revElement && typeof revElement === 'object') {\n if (revElement._orderedChildren) {\n // Use the revision element's _orderedChildren for correct order\n const childCounters = new Map<string, number>();\n for (const childEntry of revElement._orderedChildren) {\n const childType = childEntry.type;\n const childIdx = childCounters.get(childType) || 0;\n childCounters.set(childType, childIdx + 1);\n\n const childElements = revElement[childType];\n if (childElements) {\n const childArray = Array.isArray(childElements) ? childElements : [childElements];\n if (childIdx < childArray.length) {\n orderedElements.push({\n type: childType,\n element: childArray[childIdx],\n });\n }\n }\n }\n } else {\n // No _orderedChildren, extract children in object key order\n const childKeys = Object.keys(revElement).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n for (const childKey of childKeys) {\n const childValue = revElement[childKey];\n const childArray = Array.isArray(childValue) ? childValue : [childValue];\n for (const child of childArray) {\n orderedElements.push({ type: childKey, element: child });\n }\n }\n }\n }\n } else {\n // Regular element - get it from the parent\n const idx = typeCounters.get(type) || 0;\n typeCounters.set(type, idx + 1);\n\n const parentElements = parent[type];\n if (parentElements) {\n const parentArray = Array.isArray(parentElements) ? parentElements : [parentElements];\n if (idx < parentArray.length) {\n orderedElements.push({ type, element: parentArray[idx] });\n }\n }\n }\n }\n }\n\n // Remove the revision wrapper\n delete parent[key];\n\n // If we have ordered elements, rebuild the arrays in correct order\n if (orderedElements.length > 0) {\n // Group elements by type\n const rebuiltArrays = new Map<string, any[]>();\n\n for (const { type, element } of orderedElements) {\n if (!rebuiltArrays.has(type)) {\n rebuiltArrays.set(type, []);\n }\n rebuiltArrays.get(type)!.push(element);\n }\n\n // Update parent with rebuilt arrays\n for (const [type, elements] of rebuiltArrays) {\n if (elements.length === 1) {\n parent[type] = elements[0];\n } else {\n parent[type] = elements;\n }\n }\n\n // Rebuild _orderedChildren\n const newOrderedChildren: OrderedChildInfo[] = [];\n const typeCounters = new Map<string, number>();\n\n for (const { type } of orderedElements) {\n const idx = typeCounters.get(type) || 0;\n typeCounters.set(type, idx + 1);\n newOrderedChildren.push({ type, index: idx });\n }\n\n parent._orderedChildren = newOrderedChildren;\n } else {\n // Fallback for when there's no _orderedChildren - just merge\n for (const element of elementArray) {\n if (!element || typeof element !== 'object') continue;\n\n const elementKeys = Object.keys(element).filter(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n for (const childKey of elementKeys) {\n RevisionWalker.mergeIntoParent(parent, childKey, element[childKey]);\n }\n }\n }\n }\n\n /**\n * Remove all elements of a given type (including their content)\n */\n private static removeAllElements(parent: any, key: string): void {\n if (!parent[key]) return;\n\n // Update _orderedChildren before removing\n if (parent._orderedChildren) {\n parent._orderedChildren = parent._orderedChildren.filter(\n (c: OrderedChildInfo) => c.type !== key\n );\n // Re-index remaining elements of same types\n RevisionWalker.reindexOrderedChildren(parent._orderedChildren);\n }\n\n // Remove the element\n delete parent[key];\n }\n\n /**\n * Restore the previous formatting recorded by a property-change element\n * (reject direction). A change such as `w:rPrChange` lives inside the\n * properties wrapper it tracks (`w:rPr`) and embeds the complete previous\n * wrapper as a child:\n *\n * <w:rPr><w:b/><w:rPrChange><w:rPr><w:i/></w:rPr></w:rPrChange></w:rPr>\n *\n * Rejecting it replaces the current direct formatting (`w:b`) with the\n * embedded previous formatting (`w:i`) and drops the change marker. Children\n * that are tracked independently of the snapshot — e.g. a paragraph's mark\n * run properties / section properties, or a section's header/footer\n * references (see {@link PRESERVED_ON_RESTORE}) — are carried over from the\n * current wrapper in their correct schema position rather than discarded.\n *\n * @param parent - the properties wrapper containing the change element\n * @param changeKey - the change element key, e.g. 'w:rPrChange'\n */\n private static restorePropertyChange(parent: any, changeKey: string): void {\n const changeRaw = parent[changeKey];\n if (!changeRaw) return;\n const changeEl = Array.isArray(changeRaw) ? changeRaw[0] : changeRaw;\n\n // 'w:rPrChange' -> 'w:rPr', 'w:tblGridChange' -> 'w:tblGrid', etc.\n const previousKey = changeKey.replace(/Change$/, '');\n const previousRaw =\n changeEl && typeof changeEl === 'object' ? changeEl[previousKey] : undefined;\n\n // Malformed change with no embedded previous-properties snapshot: there is\n // nothing to restore, so drop just the marker and leave the current\n // formatting intact rather than emptying the wrapper.\n if (previousRaw === undefined) {\n RevisionWalker.removeAllElements(parent, changeKey);\n return;\n }\n const previousEl = Array.isArray(previousRaw) ? previousRaw[0] : previousRaw;\n\n const preserve = PRESERVED_ON_RESTORE[previousKey];\n const preserveKeys = preserve?.keys ?? [];\n\n // Snapshot children become the restored formatting (minus any preserved\n // keys it might redundantly carry).\n const snapshotChildren =\n previousEl && typeof previousEl === 'object'\n ? RevisionWalker.getOrderedChildList(previousEl).filter(\n (c) => !preserveKeys.includes(c.type)\n )\n : [];\n\n // Preserved children are read from the CURRENT wrapper in their existing\n // document order (captured before the wrapper is cleared below).\n const preservedChildren = preserveKeys.length\n ? RevisionWalker.getOrderedChildList(parent).filter(\n (c) => preserveKeys.includes(c.type) && c.type !== changeKey\n )\n : [];\n\n const newChildren =\n preserve?.position === 'before'\n ? [...preservedChildren, ...snapshotChildren]\n : [...snapshotChildren, ...preservedChildren];\n\n RevisionWalker.rebuildChildren(parent, newChildren);\n }\n\n /**\n * Replace all non-metadata children of `parent` with the supplied ordered\n * `{type, element}` list, regrouping per-type arrays and rebuilding\n * `_orderedChildren` so the serializer emits them in the given order.\n * Attributes (`@_*`) and `#text` are left untouched.\n */\n private static rebuildChildren(parent: any, ordered: { type: string; element: any }[]): void {\n for (const k of Object.keys(parent)) {\n if (!k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren') {\n delete parent[k];\n }\n }\n\n const grouped = new Map<string, any[]>();\n for (const { type, element } of ordered) {\n if (!grouped.has(type)) grouped.set(type, []);\n grouped.get(type)!.push(element);\n }\n for (const [type, elements] of grouped) {\n parent[type] = elements.length === 1 ? elements[0] : elements;\n }\n\n const orderedChildren: OrderedChildInfo[] = [];\n const counters = new Map<string, number>();\n for (const { type } of ordered) {\n const idx = counters.get(type) || 0;\n counters.set(type, idx + 1);\n orderedChildren.push({ type, index: idx });\n }\n if (orderedChildren.length > 0) {\n parent._orderedChildren = orderedChildren;\n } else {\n delete parent._orderedChildren;\n }\n }\n\n /**\n * Flatten an element's children into an ordered `{type, element}` list,\n * honouring `_orderedChildren` when present and falling back to key order.\n */\n private static getOrderedChildList(el: any): { type: string; element: any }[] {\n const result: { type: string; element: any }[] = [];\n const ordered = el._orderedChildren as OrderedChildInfo[] | undefined;\n\n if (Array.isArray(ordered) && ordered.length > 0) {\n const counters = new Map<string, number>();\n for (const entry of ordered) {\n const { type } = entry;\n const idx = counters.get(type) || 0;\n counters.set(type, idx + 1);\n const value = el[type];\n if (value === undefined) continue;\n const arr = Array.isArray(value) ? value : [value];\n if (idx < arr.length) result.push({ type, element: arr[idx] });\n }\n return result;\n }\n\n for (const key of Object.keys(el)) {\n if (key.startsWith('@_') || key === '#text' || key === '_orderedChildren') continue;\n const value = el[key];\n const arr = Array.isArray(value) ? value : [value];\n for (const element of arr) result.push({ type: key, element });\n }\n return result;\n }\n\n /**\n * Convert restored deleted text back to live text throughout the tree\n * (reject direction). After w:del unwrapping, the runs that were deleted\n * still hold their text in w:delText / w:delInstrText; rename those to the\n * normal w:t / w:instrText so the content is real again, fixing any\n * `_orderedChildren` type references as we go.\n */\n private static convertDeletedTextToNormal(obj: any): void {\n if (obj === null || typeof obj !== 'object') return;\n\n if (Array.isArray(obj)) {\n for (const item of obj) RevisionWalker.convertDeletedTextToNormal(item);\n return;\n }\n\n // When this node carries any deleted-text element, rebuild its children\n // from the document-ordered list with the deleted-text keys renamed. Going\n // through the ordered list keeps text in its original position even if a\n // run holds both a w:delText and a live w:t (CT_R permits interleaving).\n const hasDeletedText = Object.keys(obj).some((k) => k in DELETED_TEXT_RENAMES);\n if (hasDeletedText) {\n const ordered = RevisionWalker.getOrderedChildList(obj).map((child) => ({\n type: DELETED_TEXT_RENAMES[child.type] ?? child.type,\n element: child.element,\n }));\n RevisionWalker.rebuildChildren(obj, ordered);\n }\n\n for (const key of Object.keys(obj)) {\n if (key.startsWith('@_') || key === '#text' || key === '_orderedChildren') continue;\n RevisionWalker.convertDeletedTextToNormal(obj[key]);\n }\n }\n\n /**\n * Merge a child value into the parent, handling arrays properly\n */\n private static mergeIntoParent(parent: any, childKey: string, childValue: any): void {\n if (parent[childKey] === undefined) {\n // No existing value, just assign\n parent[childKey] = childValue;\n } else {\n // Existing value, need to merge\n const existing = parent[childKey];\n const incoming = Array.isArray(childValue) ? childValue : [childValue];\n\n if (Array.isArray(existing)) {\n parent[childKey] = [...existing, ...incoming];\n } else {\n parent[childKey] = [existing, ...incoming];\n }\n }\n }\n\n /**\n * Re-index _orderedChildren to ensure indices are sequential per type\n */\n private static reindexOrderedChildren(orderedChildren: OrderedChildInfo[]): void {\n const typeCounters = new Map<string, number>();\n\n for (const entry of orderedChildren) {\n const currentIndex = typeCounters.get(entry.type) || 0;\n entry.index = currentIndex;\n typeCounters.set(entry.type, currentIndex + 1);\n }\n }\n\n /**\n * Check if an element is a revision-related element (any type)\n */\n static isRevisionElement(key: string): boolean {\n return (\n REVISION_ELEMENTS.UNWRAP.includes(key) ||\n REVISION_ELEMENTS.REMOVE.includes(key) ||\n REVISION_ELEMENTS.PROPERTY_CHANGES.includes(key) ||\n REVISION_ELEMENTS.RANGE_MARKERS.includes(key)\n );\n }\n\n /**\n * Get revision element categories (for external use/testing)\n */\n static getRevisionElementCategories(): typeof REVISION_ELEMENTS {\n return { ...REVISION_ELEMENTS };\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { ZipHandler } from '../zip/ZipHandler.js';
2
2
  export declare function acceptAllRevisions(zipHandler: ZipHandler): Promise<void>;
3
+ export declare function rejectAllRevisions(zipHandler: ZipHandler): Promise<void>;
3
4
  export declare function cleanupRevisionMetadata(zipHandler: ZipHandler): void;
4
5
  //# sourceMappingURL=acceptRevisions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"acceptRevisions.d.ts","sourceRoot":"","sources":["../../src/processors/acceptRevisions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAiwBlD,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAeD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAGpE"}
1
+ {"version":3,"file":"acceptRevisions.d.ts","sourceRoot":"","sources":["../../src/processors/acceptRevisions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAyxBlD,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAuBD,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAeD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAGpE"}
@@ -1,20 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.acceptAllRevisions = acceptAllRevisions;
4
+ exports.rejectAllRevisions = rejectAllRevisions;
4
5
  exports.cleanupRevisionMetadata = cleanupRevisionMetadata;
5
6
  const XMLParser_js_1 = require("../xml/XMLParser.js");
6
7
  const RevisionWalker_js_1 = require("./RevisionWalker.js");
7
- const REVISION_MARKER_PATTERN = /<w:(?:ins|del|moveFrom|moveTo|rPrChange|pPrChange|tblPrChange|tblPrExChange|trPrChange|tcPrChange|sectPrChange|numberingChange|cellIns|cellDel|cellMerge|moveFromRangeStart|moveFromRangeEnd|moveToRangeStart|moveToRangeEnd|customXmlInsRangeStart|customXmlInsRangeEnd|customXmlDelRangeStart|customXmlDelRangeEnd|customXmlMoveFromRangeStart|customXmlMoveFromRangeEnd|customXmlMoveToRangeStart|customXmlMoveToRangeEnd)\b/;
8
- class RevisionAcceptor {
8
+ const REVISION_MARKER_PATTERN = /<w:(?:ins|del|moveFrom|moveTo|rPrChange|pPrChange|tblPrChange|tblPrExChange|trPrChange|tcPrChange|sectPrChange|tblGridChange|numberingChange|cellIns|cellDel|cellMerge|moveFromRangeStart|moveFromRangeEnd|moveToRangeStart|moveToRangeEnd|customXmlInsRangeStart|customXmlInsRangeEnd|customXmlDelRangeStart|customXmlDelRangeEnd|customXmlMoveFromRangeStart|customXmlMoveFromRangeEnd|customXmlMoveToRangeStart|customXmlMoveToRangeEnd)\b/;
9
+ class RevisionProcessor {
9
10
  zipHandler;
10
11
  useDomBasedProcessing = true;
11
- constructor(zipHandler) {
12
+ mode;
13
+ constructor(zipHandler, mode = 'accept') {
12
14
  this.zipHandler = zipHandler;
15
+ this.mode = mode;
13
16
  }
14
17
  setUseDomBasedProcessing(enabled) {
15
18
  this.useDomBasedProcessing = enabled;
16
19
  }
17
- async acceptAllRevisions() {
20
+ async process() {
18
21
  await this.processDocumentPart('word/document.xml');
19
22
  const files = this.zipHandler.getFilePaths();
20
23
  for (const file of files) {
@@ -36,10 +39,10 @@ class RevisionAcceptor {
36
39
  }
37
40
  async processDocumentPart(partPath) {
38
41
  const xml = this.zipHandler.getFileAsString(partPath);
39
- if (!xml || !RevisionAcceptor.containsRevisionMarkup(xml)) {
42
+ if (!xml || !RevisionProcessor.containsRevisionMarkup(xml)) {
40
43
  return;
41
44
  }
42
- if (this.useDomBasedProcessing) {
45
+ if (this.useDomBasedProcessing || this.mode === 'reject') {
43
46
  return this.processDocumentPartDOM(partPath);
44
47
  }
45
48
  return this.processDocumentPartRegex(partPath);
@@ -54,12 +57,15 @@ class RevisionAcceptor {
54
57
  }
55
58
  const parsed = XMLParser_js_1.XMLParser.parseToObject(xml, { trimValues: false });
56
59
  const processed = RevisionWalker_js_1.RevisionWalker.processTree(parsed, {
60
+ mode: this.mode,
57
61
  acceptInsertions: true,
58
62
  acceptDeletions: true,
59
63
  acceptMoves: true,
60
64
  acceptPropertyChanges: true,
61
65
  });
62
- this.remapImageRelationshipsInTree(processed);
66
+ if (this.mode === 'accept') {
67
+ this.remapImageRelationshipsInTree(processed);
68
+ }
63
69
  const outputXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n' + this.objectToXml(processed);
64
70
  this.zipHandler.updateFile(partPath, outputXml);
65
71
  }
@@ -410,11 +416,15 @@ class RevisionAcceptor {
410
416
  }
411
417
  }
412
418
  async function acceptAllRevisions(zipHandler) {
413
- const acceptor = new RevisionAcceptor(zipHandler);
414
- await acceptor.acceptAllRevisions();
419
+ const acceptor = new RevisionProcessor(zipHandler);
420
+ await acceptor.process();
421
+ }
422
+ async function rejectAllRevisions(zipHandler) {
423
+ const rejector = new RevisionProcessor(zipHandler, 'reject');
424
+ await rejector.process();
415
425
  }
416
426
  function cleanupRevisionMetadata(zipHandler) {
417
- const acceptor = new RevisionAcceptor(zipHandler);
418
- acceptor.cleanupMetadata();
427
+ const processor = new RevisionProcessor(zipHandler);
428
+ processor.cleanupMetadata();
419
429
  }
420
430
  //# sourceMappingURL=acceptRevisions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"acceptRevisions.js","sourceRoot":"","sources":["../../src/processors/acceptRevisions.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler.js';\nimport { XMLParser } from '../xml/XMLParser.js';\nimport { RevisionWalker } from './RevisionWalker.js';\n\n/**\n * Markers covered: w:ins, w:del, w:moveFrom, w:moveTo,\n * w:rPrChange, w:pPrChange, w:tblPrChange, w:tblPrExChange,\n * w:trPrChange, w:tcPrChange, w:sectPrChange, w:numberingChange,\n * w:cellIns, w:cellDel, w:cellMerge, and any *RangeStart/End markers.\n */\nconst REVISION_MARKER_PATTERN =\n /<w:(?:ins|del|moveFrom|moveTo|rPrChange|pPrChange|tblPrChange|tblPrExChange|trPrChange|tcPrChange|sectPrChange|numberingChange|cellIns|cellDel|cellMerge|moveFromRangeStart|moveFromRangeEnd|moveToRangeStart|moveToRangeEnd|customXmlInsRangeStart|customXmlInsRangeEnd|customXmlDelRangeStart|customXmlDelRangeEnd|customXmlMoveFromRangeStart|customXmlMoveFromRangeEnd|customXmlMoveToRangeStart|customXmlMoveToRangeEnd)\\b/;\n\n/**\n * Accepts all tracked changes in a Word document per Microsoft's OpenXML SDK pattern\n *\n * This implementation uses DOM-based tree walking for reliability:\n * 1. Insertions (<w:ins>): Keep content, remove wrapper tags\n * 2. Deletions (<w:del>): Remove entirely (content and tags)\n * 3. Move From (<w:moveFrom>): Remove entirely (source of move)\n * 4. Move To (<w:moveTo>): Keep content, remove wrapper (destination of move)\n * 5. Property changes: Remove all *Change elements\n * 6. Range markers: Remove all boundary markers\n *\n * Also cleans up metadata in people.xml, settings.xml, and core.xml\n *\n * @see https://learn.microsoft.com/en-us/office/open-xml/how-to-accept-all-revisions\n */\nclass RevisionAcceptor {\n private zipHandler: ZipHandler;\n /** Feature flag for DOM-based processing (default: true) */\n private useDomBasedProcessing = true;\n\n constructor(zipHandler: ZipHandler) {\n this.zipHandler = zipHandler;\n }\n\n /**\n * Enable or disable DOM-based processing (for testing/migration)\n */\n setUseDomBasedProcessing(enabled: boolean): void {\n this.useDomBasedProcessing = enabled;\n }\n\n /**\n * Main method to accept all revisions in the document\n */\n public async acceptAllRevisions(): Promise<void> {\n // Process document.xml\n await this.processDocumentPart('word/document.xml');\n\n // Process headers / footers / footnotes / endnotes / comments.\n // Footnotes (§17.11.15), endnotes (§17.11.4), and comments (§17.13.4)\n // can all carry block-level content including tracked changes\n // (w:ins / w:del / pPrChange / rPrChange / moveFrom / moveTo).\n // Previously only document.xml + headers + footers were walked,\n // leaving footnote / endnote / comment revisions unaccepted so\n // Word still showed the document as having pending tracked\n // changes after `acceptAllRevisions()` returned.\n const files = this.zipHandler.getFilePaths();\n for (const file of files) {\n if (/^word\\/header\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n if (/^word\\/footer\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n }\n // Singleton notes / comments parts. Check presence explicitly\n // (not all documents have them) — processDocumentPart is a no-op\n // on missing files.\n for (const notesPath of ['word/footnotes.xml', 'word/endnotes.xml', 'word/comments.xml']) {\n if (this.zipHandler.getFileAsString(notesPath)) {\n await this.processDocumentPart(notesPath);\n }\n }\n\n // Clean up metadata files\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Process a document part (document.xml, header, footer) to accept revisions\n */\n private async processDocumentPart(partPath: string): Promise<void> {\n // Fast path: parts with no revision markup do not need to be re-serialised.\n // Re-serialising a part destroys the original whitespace / formatting\n // (XMLBuilder emits a different layout than the source), which can break\n // byte-for-byte passthrough preservation in downstream consumers\n // (e.g., comments.xml round-trip with no tracked changes inside).\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml || !RevisionAcceptor.containsRevisionMarkup(xml)) {\n return;\n }\n\n if (this.useDomBasedProcessing) {\n return this.processDocumentPartDOM(partPath);\n }\n return this.processDocumentPartRegex(partPath);\n }\n\n /**\n * Quick scan for any tracked-change marker. Returns false when the part\n * carries none, allowing the acceptor to skip an unnecessary parse +\n * re-serialise round-trip.\n */\n private static containsRevisionMarkup(xml: string): boolean {\n return REVISION_MARKER_PATTERN.test(xml);\n }\n\n /**\n * DOM-based implementation of revision acceptance\n * Uses XMLParser and RevisionWalker for reliable processing\n */\n private processDocumentPartDOM(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n // Step 1: Parse XML to object tree\n // IMPORTANT: trimValues: false preserves whitespace from xml:space=\"preserve\" attributes\n const parsed = XMLParser.parseToObject(xml, { trimValues: false });\n\n // Step 2: Process revisions using DOM walker\n const processed = RevisionWalker.processTree(parsed, {\n acceptInsertions: true,\n acceptDeletions: true,\n acceptMoves: true,\n acceptPropertyChanges: true,\n });\n\n // Step 3: Handle image relationship ID remapping\n this.remapImageRelationshipsInTree(processed);\n\n // Step 4: Convert back to XML\n const outputXml =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' + this.objectToXml(processed);\n\n // Step 5: Update file\n this.zipHandler.updateFile(partPath, outputXml);\n }\n\n /**\n * Legacy RegEx-based implementation (kept as fallback)\n */\n private processDocumentPartRegex(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n let content = xml;\n\n // Step 1: Remove all range markers FIRST (before processing revisions)\n // This prevents orphaned references when revision content is modified\n content = this.removeAllRangeMarkers(content);\n\n // Step 2: Remove all property change elements\n // These track formatting changes and must be removed before other processing\n content = this.removeAllPropertyChanges(content);\n\n // Step 3: Process deletions - remove entire element INCLUDING content\n // Must be done before insertions to handle nested scenarios\n content = this.acceptDeletions(content);\n\n // Step 4: Process move operations\n // Remove moveFrom entirely (source), unwrap moveTo (destination)\n content = this.acceptMoveFrom(content);\n content = this.acceptMoveTo(content);\n\n // Step 5: Process insertions - keep content, remove wrapper\n content = this.acceptInsertions(content);\n\n // Step 6: Final cleanup - remove any remaining orphaned tags\n content = this.cleanupOrphanedTags(content);\n\n // Update the file\n this.zipHandler.updateFile(partPath, content);\n }\n\n /**\n * Remove all range marker elements\n * These are boundary markers for tracked changes and moves\n */\n private removeAllRangeMarkers(xml: string): string {\n const patterns = [\n // Move range markers\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\n // Custom XML range markers\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\n /<w:customXmlMoveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeStart>)/gs,\n /<w:customXmlMoveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeEnd>)/gs,\n /<w:customXmlMoveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeStart>)/gs,\n /<w:customXmlMoveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeEnd>)/gs,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n * Per ECMA-376, these track previous state of formatting\n */\n private removeAllPropertyChanges(xml: string): string {\n const patterns = [\n // Run property changes\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\n // Paragraph property changes\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\n // Table property changes\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\n // Table cell property changes\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\n // Table row property changes\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\n // Section property changes\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\n // Table grid changes\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\n // Numbering changes\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Accept deletions - remove the entire <w:del> element including its content.\n *\n * Per Microsoft SDK: \"DeletedRun elements should be removed along with\n * their content\". Additionally, per ECMA-376 Part 1 §17.13.5.14, a\n * self-closing `<w:del/>` inside `<w:trPr>` marks the entire row as a\n * tracked deletion — accepting it must remove the entire `<w:tr>` block,\n * not just the marker. Without that, zombie rows (the row wrapper with\n * empty cells) persist in the document after revision acceptance.\n */\n private acceptDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Pass A — row-level deletion: remove entire <w:tr> whose <w:trPr>\n // contains a self-closing row-deletion marker. Constraints:\n // - `<w:trPr\\b(?:\\s[^>]*)?>` only matches the OPEN form of trPr (i.e.\n // rejects self-closing `<w:trPr/>`, which by definition contains\n // no del markers), so the match anchors on the correct row.\n // - negative lookahead `(?!<w:tc\\b|<w:tr\\b|<\\/w:tr>)` between the\n // `<w:tr>` opening and the `<w:trPr>` prevents the match from\n // slipping past a cell boundary or nested-table row and latching\n // onto a later row's trPr-with-del.\n const rowDelPattern =\n /<w:tr\\b[^>]*>(?:(?!<w:tc\\b|<w:tr\\b|<\\/w:tr>)[\\s\\S])*?<w:trPr\\b(?:\\s[^>]*)?>(?:(?!<\\/w:trPr>)[\\s\\S])*?<w:del\\b[^>]*\\/>(?:(?!<\\/w:trPr>)[\\s\\S])*?<\\/w:trPr>(?:(?!<w:tr\\b|<\\/w:tr>)[\\s\\S])*?<\\/w:tr>/g;\n previousLength = 0;\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(rowDelPattern, '');\n }\n\n // Pass B — wrapper deletions: iterate until no more <w:del>..</w:del>\n // elements (handles nested cases).\n previousLength = 0;\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\n }\n\n // Pass C — remove any remaining self-closing deletion markers (paragraph\n // mark deletions inside pPr/rPr, orphans, etc.). By this point, any\n // row-level markers have already triggered full-row removal in Pass A,\n // so this pass only cleans up non-structural markers.\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveFrom - remove the entire element (source of moved content)\n *\n * The content exists at the moveTo destination, so we discard the source\n */\n private acceptMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\n }\n\n // Also remove self-closing tags\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveTo - keep the content, remove the wrapper tags\n *\n * The moveTo location is where the content should remain\n */\n private acceptMoveTo(xml: string): string {\n let result = xml;\n\n // Remove closing tags first (prevents issues with regex matching)\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Remove opening tags (keeps content that was inside)\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Accept insertions - keep the content, remove the wrapper tags\n *\n * Per Microsoft SDK: \"InsertedRun elements should be unwrapped, keeping their content\"\n *\n * IMPORTANT: This method now handles relationship ID remapping for images inside insertions.\n * When Word tracks changes with images, it can reuse relationship IDs (like rId5) because\n * they're in separate tracked change contexts. But when we unwrap them, duplicate IDs\n * cause corruption. This method assigns new unique IDs to images inside insertions.\n */\n private acceptInsertions(xml: string): string {\n let result = xml;\n\n // Parse existing relationships\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n\n // Process each w:ins element and remap images one by one\n const insRegex = /<w:ins\\b[^>]*>[\\s\\S]*?<\\/w:ins>/g;\n\n result = result.replace(insRegex, (insMatch) => {\n // For each image reference inside this insertion, generate a unique new ID\n return insMatch.replace(/r:embed=\"(rId\\d+)\"/g, (_embedMatch, oldId) => {\n // Generate new unique ID for THIS occurrence\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n\n // Add relationship with same target as original\n const target = relationships.get(oldId);\n if (target) {\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n }\n\n return `r:embed=\"${newId}\"`;\n });\n });\n\n // Now unwrap the w:ins tags (content has unique remapped IDs)\n result = result.replace(/<\\/w:ins>/g, '');\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Final cleanup to remove any orphaned or malformed revision-related tags\n */\n private cleanupOrphanedTags(xml: string): string {\n let result = xml;\n\n // Remove any remaining self-closing revision tags\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\n\n // Remove empty w:r elements that might be left after removing deletions\n result = result.replace(/<w:r\\b[^>]*>\\s*<\\/w:r>/g, '');\n\n // Remove empty w:p elements (but preserve those with properties)\n // We keep <w:p><w:pPr>...</w:pPr></w:p> as those are intentional empty paragraphs with styling\n result = result.replace(/<w:p>\\s*<\\/w:p>/g, '');\n\n return result;\n }\n\n /**\n * Parse relationship IDs from word/_rels/document.xml.rels\n * Returns a map of relationship ID to target path\n */\n private parseRelationships(): Map<string, string> {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return new Map();\n\n const map = new Map<string, string>();\n const relationshipRegex = /<Relationship[^>]*Id=\"([^\"]+)\"[^>]*Target=\"([^\"]+)\"[^>]*\\/>/g;\n let match;\n\n while ((match = relationshipRegex.exec(relsXml)) !== null) {\n if (match[1] && match[2]) {\n map.set(match[1], match[2]); // rId -> target path\n }\n }\n\n return map;\n }\n\n /**\n * Get the next available relationship ID\n * Finds the highest numeric ID and increments it\n */\n private getNextRelationshipId(existingIds: Set<string>): string {\n let maxId = 0;\n for (const id of existingIds) {\n const num = parseInt(id.replace('rId', ''));\n if (!isNaN(num) && num > maxId) {\n maxId = num;\n }\n }\n return `rId${maxId + 1}`;\n }\n\n /**\n * Add a new relationship to word/_rels/document.xml.rels\n */\n private addRelationship(rId: string, target: string, type: string): void {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return;\n\n // Insert new relationship before closing tag\n const newRel = `<Relationship Id=\"${rId}\" Type=\"${type}\" Target=\"${target}\"/>`;\n const updated = relsXml.replace('</Relationships>', `${newRel}\\n</Relationships>`);\n\n this.zipHandler.updateFile('word/_rels/document.xml.rels', updated);\n }\n\n /**\n * Clean up all revision metadata files (people.xml, settings.xml, core.xml).\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Called as part of acceptAllRevisions() but can also be called separately\n * when using in-memory revision acceptance.\n */\n public cleanupMetadata(): void {\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Clean up word/people.xml - remove all revision authors\n *\n * Handles both w: and w15: namespace variants\n */\n private cleanupPeopleXml(): void {\n const peopleXml = this.zipHandler.getFileAsString('word/people.xml');\n if (!peopleXml) {\n return;\n }\n\n let content = peopleXml;\n\n // Remove all person elements in any namespace variant\n content = content.replace(/<w:person\\b[^>]*>[\\s\\S]*?<\\/w:person>/g, '');\n content = content.replace(/<w15:person\\b[^>]*>[\\s\\S]*?<\\/w15:person>/g, '');\n\n // Handle any namespace-prefixed variants (w1:, w2:, etc.)\n content = content.replace(/<w\\d+:person\\b[^>]*>[\\s\\S]*?<\\/w\\d+:person>/g, '');\n\n // Also remove self-closing person elements\n content = content.replace(/<w:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w15:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w\\d+:person\\b[^>]*\\/>/g, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private cleanupSettingsXml(): void {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove trackRevisions element (enables tracking)\n content = content.replace(/<w:trackRevisions\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions\\b[^>]*>[\\s\\S]*?<\\/w:trackRevisions>/g, '');\n\n // Remove revisionView element (controls which revisions are visible)\n content = content.replace(/<w:revisionView\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView\\b[^>]*>[\\s\\S]*?<\\/w:revisionView>/g, '');\n\n // Remove doNotTrackMoves (prevents move tracking)\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackMoves>/g, '');\n\n // Remove doNotTrackFormatting\n content = content.replace(/<w:doNotTrackFormatting\\b[^>]*\\/>/g, '');\n content = content.replace(\n /<w:doNotTrackFormatting\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackFormatting>/g,\n ''\n );\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private cleanupCorePropsXml(): void {\n const coreXml = this.zipHandler.getFileAsString('docProps/core.xml');\n if (!coreXml) {\n return;\n }\n\n // Reset revision count to 1\n const content = coreXml.replace(\n /<cp:revision>\\d+<\\/cp:revision>/g,\n '<cp:revision>1</cp:revision>'\n );\n\n this.zipHandler.updateFile('docProps/core.xml', content);\n }\n\n // =========================================================================\n // DOM-based processing helper methods\n // =========================================================================\n\n /**\n * Convert parsed XML object back to XML string\n * Preserves element order using _orderedChildren metadata\n *\n * Based on DocumentParser.objectToXml() implementation\n */\n private objectToXml(obj: any): string {\n const buildXml = (o: any, name?: string): string => {\n // Handle simple string/number with a tag name: <tagName>value</tagName>\n if (name && (typeof o === 'string' || typeof o === 'number')) {\n return `<${name}>${this.escapeXml(String(o))}</${name}>`;\n }\n if (typeof o === 'string') return this.escapeXml(o);\n if (typeof o !== 'object' || o === null) return String(o ?? '');\n\n const keys = Object.keys(o);\n\n // If a name is provided, we're building a specific element\n // Don't return empty string for empty objects with a name - they become self-closing tags\n if (keys.length === 0 && !name) return '';\n\n const tagName = name || keys[0]!;\n const element = name ? o : o[tagName];\n\n let xml = `<${tagName}`;\n\n // Add attributes (keys starting with @_)\n if (element && typeof element === 'object') {\n for (const key of Object.keys(element)) {\n if (key.startsWith('@_')) {\n const attrName = key.substring(2);\n xml += ` ${attrName}=\"${this.escapeXml(String(element[key]))}\"`;\n }\n }\n }\n\n // Check for children (non-attribute, non-text, non-metadata keys)\n const hasChildren =\n element &&\n typeof element === 'object' &&\n Object.keys(element).some(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n // Per ECMA-376, certain elements MUST NOT be self-closing (e.g., <w:p/> is invalid).\n // This mirrors the CANNOT_SELF_CLOSE list in XMLBuilder.ts.\n const CANNOT_SELF_CLOSE = [\n 'w:t',\n 'w:r',\n 'w:p',\n 'w:tbl',\n 'w:tr',\n 'w:tc',\n 'w:body',\n 'w:document',\n 'w:hyperlink',\n 'w:sdt',\n 'w:sdtContent',\n 'w:sdtPr',\n 'w:pPr',\n 'w:rPr',\n 'w:sectPr',\n 'w:del',\n 'w:ins',\n 'w:moveFrom',\n 'w:moveTo',\n ];\n\n if (!hasChildren && !element?.['#text']) {\n if (CANNOT_SELF_CLOSE.includes(tagName)) {\n xml += `></${tagName}>`;\n } else {\n xml += '/>';\n }\n } else {\n xml += '>';\n\n // Add text content\n if (element?.['#text']) {\n xml += this.escapeXml(String(element['#text']));\n }\n\n // Add child elements using _orderedChildren if available\n if (element && typeof element === 'object') {\n const orderedChildren = element._orderedChildren as\n | { type: string; index: number }[]\n | undefined;\n\n if (orderedChildren && orderedChildren.length > 0) {\n // Use _orderedChildren to preserve element order\n for (const childInfo of orderedChildren) {\n const childType = childInfo.type;\n const childIndex = childInfo.index;\n\n if (element[childType] !== undefined) {\n const children = element[childType];\n\n if (Array.isArray(children)) {\n if (childIndex < children.length) {\n const childXml = buildXml(children[childIndex], childType);\n xml += childXml;\n }\n } else {\n // Single child element\n if (childIndex === 0) {\n const childXml = buildXml(children, childType);\n xml += childXml;\n }\n }\n }\n }\n } else {\n // Fallback: iterate through keys if no _orderedChildren\n for (const key of Object.keys(element)) {\n if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const children = element[key];\n if (Array.isArray(children)) {\n for (const child of children) {\n xml += buildXml(child, key);\n }\n } else {\n xml += buildXml(children, key);\n }\n }\n }\n }\n }\n\n xml += `</${tagName}>`;\n }\n\n return xml;\n };\n\n return buildXml(obj);\n }\n\n /**\n * Escape special XML characters\n */\n private escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n /**\n * Remap image relationship IDs in the parsed tree to prevent duplicates\n * Walks the tree looking for r:embed attributes and assigns unique IDs\n */\n private remapImageRelationshipsInTree(obj: any): void {\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n const remappedIds = new Map<string, string>();\n\n // Walk the tree and find all r:embed attributes\n this.walkTreeForEmbeds(obj, (embedId: string, parent: any, key: string) => {\n // Check if this ID has already been remapped\n if (remappedIds.has(embedId)) {\n parent[key] = remappedIds.get(embedId);\n return;\n }\n\n // Check if this ID needs remapping (duplicate)\n // For DOM-based processing, we check if we've seen this ID before in this pass\n const target = relationships.get(embedId);\n if (target) {\n // Generate new unique ID\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n remappedIds.set(embedId, newId);\n\n // Add relationship with same target\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n\n // Update the attribute\n parent[key] = newId;\n }\n });\n }\n\n /**\n * Walk the tree looking for r:embed attributes\n */\n private walkTreeForEmbeds(\n obj: any,\n callback: (embedId: string, parent: any, key: string) => void\n ): void {\n if (!obj || typeof obj !== 'object') {\n return;\n }\n\n for (const key of Object.keys(obj)) {\n // Check for r:embed attribute\n if (key === '@_r:embed') {\n callback(obj[key], obj, key);\n } else if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const value = obj[key];\n if (Array.isArray(value)) {\n for (const item of value) {\n this.walkTreeForEmbeds(item, callback);\n }\n } else if (typeof value === 'object') {\n this.walkTreeForEmbeds(value, callback);\n }\n }\n }\n }\n}\n\n/**\n * Convenience function to accept all revisions in a document\n */\nexport async function acceptAllRevisions(zipHandler: ZipHandler): Promise<void> {\n const acceptor = new RevisionAcceptor(zipHandler);\n await acceptor.acceptAllRevisions();\n}\n\n/**\n * Convenience function to clean up revision metadata files.\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Use this after in-memory revision acceptance to ensure metadata is also cleaned.\n * The raw XML acceptAllRevisions() function calls this automatically.\n *\n * @param zipHandler - The ZipHandler containing the DOCX package\n */\nexport function cleanupRevisionMetadata(zipHandler: ZipHandler): void {\n const acceptor = new RevisionAcceptor(zipHandler);\n acceptor.cleanupMetadata();\n}\n"]}
1
+ {"version":3,"file":"acceptRevisions.js","sourceRoot":"","sources":["../../src/processors/acceptRevisions.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler.js';\nimport { XMLParser } from '../xml/XMLParser.js';\nimport { RevisionWalker } from './RevisionWalker.js';\n\n/**\n * Markers covered: w:ins, w:del, w:moveFrom, w:moveTo,\n * w:rPrChange, w:pPrChange, w:tblPrChange, w:tblPrExChange,\n * w:trPrChange, w:tcPrChange, w:sectPrChange, w:tblGridChange,\n * w:numberingChange, w:cellIns, w:cellDel, w:cellMerge, and any\n * *RangeStart/End markers.\n */\nconst REVISION_MARKER_PATTERN =\n /<w:(?:ins|del|moveFrom|moveTo|rPrChange|pPrChange|tblPrChange|tblPrExChange|trPrChange|tcPrChange|sectPrChange|tblGridChange|numberingChange|cellIns|cellDel|cellMerge|moveFromRangeStart|moveFromRangeEnd|moveToRangeStart|moveToRangeEnd|customXmlInsRangeStart|customXmlInsRangeEnd|customXmlDelRangeStart|customXmlDelRangeEnd|customXmlMoveFromRangeStart|customXmlMoveFromRangeEnd|customXmlMoveToRangeStart|customXmlMoveToRangeEnd)\\b/;\n\n/**\n * Applies tracked changes in a Word document per Microsoft's OpenXML SDK\n * pattern, in either direction (see `mode`).\n *\n * This implementation uses DOM-based tree walking for reliability. In 'accept'\n * mode (the post-edit document):\n * 1. Insertions (<w:ins>): Keep content, remove wrapper tags\n * 2. Deletions (<w:del>): Remove entirely (content and tags)\n * 3. Move From (<w:moveFrom>): Remove entirely (source of move)\n * 4. Move To (<w:moveTo>): Keep content, remove wrapper (destination of move)\n * 5. Property changes: Remove all *Change elements\n * 6. Range markers: Remove all boundary markers\n *\n * In 'reject' mode every content decision is inverted and property changes\n * restore the previous formatting (see RevisionWalker).\n *\n * Also cleans up metadata in people.xml, settings.xml, and core.xml\n *\n * @see https://learn.microsoft.com/en-us/office/open-xml/how-to-accept-all-revisions\n */\nclass RevisionProcessor {\n private zipHandler: ZipHandler;\n /** Feature flag for DOM-based processing (default: true) */\n private useDomBasedProcessing = true;\n /**\n * Processing direction. 'accept' yields the post-edit document; 'reject'\n * reverts to the original pre-edit document (the exact inverse). Reject is\n * DOM-only — the regex fallback cannot restore previous formatting.\n */\n private mode: 'accept' | 'reject';\n\n constructor(zipHandler: ZipHandler, mode: 'accept' | 'reject' = 'accept') {\n this.zipHandler = zipHandler;\n this.mode = mode;\n }\n\n /**\n * Enable or disable DOM-based processing (for testing/migration)\n */\n setUseDomBasedProcessing(enabled: boolean): void {\n this.useDomBasedProcessing = enabled;\n }\n\n /**\n * Main entry point: apply every tracked change in the document in the\n * configured direction (accept or reject).\n */\n public async process(): Promise<void> {\n // Process document.xml\n await this.processDocumentPart('word/document.xml');\n\n // Process headers / footers / footnotes / endnotes / comments.\n // Footnotes (§17.11.15), endnotes (§17.11.4), and comments (§17.13.4)\n // can all carry block-level content including tracked changes\n // (w:ins / w:del / pPrChange / rPrChange / moveFrom / moveTo).\n // Previously only document.xml + headers + footers were walked,\n // leaving footnote / endnote / comment revisions unaccepted so\n // Word still showed the document as having pending tracked\n // changes after `acceptAllRevisions()` returned.\n const files = this.zipHandler.getFilePaths();\n for (const file of files) {\n if (/^word\\/header\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n if (/^word\\/footer\\d+\\.xml$/.exec(file)) {\n await this.processDocumentPart(file);\n }\n }\n // Singleton notes / comments parts. Check presence explicitly\n // (not all documents have them) — processDocumentPart is a no-op\n // on missing files.\n for (const notesPath of ['word/footnotes.xml', 'word/endnotes.xml', 'word/comments.xml']) {\n if (this.zipHandler.getFileAsString(notesPath)) {\n await this.processDocumentPart(notesPath);\n }\n }\n\n // Clean up metadata files\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Process a document part (document.xml, header, footer) to accept revisions\n */\n private async processDocumentPart(partPath: string): Promise<void> {\n // Fast path: parts with no revision markup do not need to be re-serialised.\n // Re-serialising a part destroys the original whitespace / formatting\n // (XMLBuilder emits a different layout than the source), which can break\n // byte-for-byte passthrough preservation in downstream consumers\n // (e.g., comments.xml round-trip with no tracked changes inside).\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml || !RevisionProcessor.containsRevisionMarkup(xml)) {\n return;\n }\n\n // Reject must restore previous formatting from *Change snapshots, which the\n // regex fallback cannot do — always take the DOM path when rejecting.\n if (this.useDomBasedProcessing || this.mode === 'reject') {\n return this.processDocumentPartDOM(partPath);\n }\n return this.processDocumentPartRegex(partPath);\n }\n\n /**\n * Quick scan for any tracked-change marker. Returns false when the part\n * carries none, allowing the acceptor to skip an unnecessary parse +\n * re-serialise round-trip.\n */\n private static containsRevisionMarkup(xml: string): boolean {\n return REVISION_MARKER_PATTERN.test(xml);\n }\n\n /**\n * DOM-based implementation of revision acceptance\n * Uses XMLParser and RevisionWalker for reliable processing\n */\n private processDocumentPartDOM(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n // Step 1: Parse XML to object tree\n // IMPORTANT: trimValues: false preserves whitespace from xml:space=\"preserve\" attributes\n const parsed = XMLParser.parseToObject(xml, { trimValues: false });\n\n // Step 2: Process revisions using DOM walker\n const processed = RevisionWalker.processTree(parsed, {\n mode: this.mode,\n acceptInsertions: true,\n acceptDeletions: true,\n acceptMoves: true,\n acceptPropertyChanges: true,\n });\n\n // Step 3: Handle image relationship ID remapping.\n // Only relevant when accepting: unwrapping an inserted image can surface a\n // relationship ID that Word reused across tracked-change contexts, so a\n // fresh unique ID is assigned. Rejecting discards insertions and restores\n // the original content, whose relationship IDs are already unique, so\n // remapping would needlessly rewrite valid references.\n if (this.mode === 'accept') {\n this.remapImageRelationshipsInTree(processed);\n }\n\n // Step 4: Convert back to XML\n const outputXml =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' + this.objectToXml(processed);\n\n // Step 5: Update file\n this.zipHandler.updateFile(partPath, outputXml);\n }\n\n /**\n * Legacy RegEx-based implementation (kept as fallback)\n */\n private processDocumentPartRegex(partPath: string): void {\n const xml = this.zipHandler.getFileAsString(partPath);\n if (!xml) {\n return;\n }\n\n let content = xml;\n\n // Step 1: Remove all range markers FIRST (before processing revisions)\n // This prevents orphaned references when revision content is modified\n content = this.removeAllRangeMarkers(content);\n\n // Step 2: Remove all property change elements\n // These track formatting changes and must be removed before other processing\n content = this.removeAllPropertyChanges(content);\n\n // Step 3: Process deletions - remove entire element INCLUDING content\n // Must be done before insertions to handle nested scenarios\n content = this.acceptDeletions(content);\n\n // Step 4: Process move operations\n // Remove moveFrom entirely (source), unwrap moveTo (destination)\n content = this.acceptMoveFrom(content);\n content = this.acceptMoveTo(content);\n\n // Step 5: Process insertions - keep content, remove wrapper\n content = this.acceptInsertions(content);\n\n // Step 6: Final cleanup - remove any remaining orphaned tags\n content = this.cleanupOrphanedTags(content);\n\n // Update the file\n this.zipHandler.updateFile(partPath, content);\n }\n\n /**\n * Remove all range marker elements\n * These are boundary markers for tracked changes and moves\n */\n private removeAllRangeMarkers(xml: string): string {\n const patterns = [\n // Move range markers\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\n // Custom XML range markers\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\n /<w:customXmlMoveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeStart>)/gs,\n /<w:customXmlMoveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveFromRangeEnd>)/gs,\n /<w:customXmlMoveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeStart>)/gs,\n /<w:customXmlMoveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlMoveToRangeEnd>)/gs,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n * Per ECMA-376, these track previous state of formatting\n */\n private removeAllPropertyChanges(xml: string): string {\n const patterns = [\n // Run property changes\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\n // Paragraph property changes\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\n // Table property changes\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\n // Table cell property changes\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\n // Table row property changes\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\n // Section property changes\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\n // Table grid changes\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\n // Numbering changes\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n return result;\n }\n\n /**\n * Accept deletions - remove the entire <w:del> element including its content.\n *\n * Per Microsoft SDK: \"DeletedRun elements should be removed along with\n * their content\". Additionally, per ECMA-376 Part 1 §17.13.5.14, a\n * self-closing `<w:del/>` inside `<w:trPr>` marks the entire row as a\n * tracked deletion — accepting it must remove the entire `<w:tr>` block,\n * not just the marker. Without that, zombie rows (the row wrapper with\n * empty cells) persist in the document after revision acceptance.\n */\n private acceptDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Pass A — row-level deletion: remove entire <w:tr> whose <w:trPr>\n // contains a self-closing row-deletion marker. Constraints:\n // - `<w:trPr\\b(?:\\s[^>]*)?>` only matches the OPEN form of trPr (i.e.\n // rejects self-closing `<w:trPr/>`, which by definition contains\n // no del markers), so the match anchors on the correct row.\n // - negative lookahead `(?!<w:tc\\b|<w:tr\\b|<\\/w:tr>)` between the\n // `<w:tr>` opening and the `<w:trPr>` prevents the match from\n // slipping past a cell boundary or nested-table row and latching\n // onto a later row's trPr-with-del.\n const rowDelPattern =\n /<w:tr\\b[^>]*>(?:(?!<w:tc\\b|<w:tr\\b|<\\/w:tr>)[\\s\\S])*?<w:trPr\\b(?:\\s[^>]*)?>(?:(?!<\\/w:trPr>)[\\s\\S])*?<w:del\\b[^>]*\\/>(?:(?!<\\/w:trPr>)[\\s\\S])*?<\\/w:trPr>(?:(?!<w:tr\\b|<\\/w:tr>)[\\s\\S])*?<\\/w:tr>/g;\n previousLength = 0;\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(rowDelPattern, '');\n }\n\n // Pass B — wrapper deletions: iterate until no more <w:del>..</w:del>\n // elements (handles nested cases).\n previousLength = 0;\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\n }\n\n // Pass C — remove any remaining self-closing deletion markers (paragraph\n // mark deletions inside pPr/rPr, orphans, etc.). By this point, any\n // row-level markers have already triggered full-row removal in Pass A,\n // so this pass only cleans up non-structural markers.\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveFrom - remove the entire element (source of moved content)\n *\n * The content exists at the moveTo destination, so we discard the source\n */\n private acceptMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\n }\n\n // Also remove self-closing tags\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n\n return result;\n }\n\n /**\n * Accept moveTo - keep the content, remove the wrapper tags\n *\n * The moveTo location is where the content should remain\n */\n private acceptMoveTo(xml: string): string {\n let result = xml;\n\n // Remove closing tags first (prevents issues with regex matching)\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Remove opening tags (keeps content that was inside)\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Accept insertions - keep the content, remove the wrapper tags\n *\n * Per Microsoft SDK: \"InsertedRun elements should be unwrapped, keeping their content\"\n *\n * IMPORTANT: This method now handles relationship ID remapping for images inside insertions.\n * When Word tracks changes with images, it can reuse relationship IDs (like rId5) because\n * they're in separate tracked change contexts. But when we unwrap them, duplicate IDs\n * cause corruption. This method assigns new unique IDs to images inside insertions.\n */\n private acceptInsertions(xml: string): string {\n let result = xml;\n\n // Parse existing relationships\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n\n // Process each w:ins element and remap images one by one\n const insRegex = /<w:ins\\b[^>]*>[\\s\\S]*?<\\/w:ins>/g;\n\n result = result.replace(insRegex, (insMatch) => {\n // For each image reference inside this insertion, generate a unique new ID\n return insMatch.replace(/r:embed=\"(rId\\d+)\"/g, (_embedMatch, oldId) => {\n // Generate new unique ID for THIS occurrence\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n\n // Add relationship with same target as original\n const target = relationships.get(oldId);\n if (target) {\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n }\n\n return `r:embed=\"${newId}\"`;\n });\n });\n\n // Now unwrap the w:ins tags (content has unique remapped IDs)\n result = result.replace(/<\\/w:ins>/g, '');\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Final cleanup to remove any orphaned or malformed revision-related tags\n */\n private cleanupOrphanedTags(xml: string): string {\n let result = xml;\n\n // Remove any remaining self-closing revision tags\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\n\n // Remove empty w:r elements that might be left after removing deletions\n result = result.replace(/<w:r\\b[^>]*>\\s*<\\/w:r>/g, '');\n\n // Remove empty w:p elements (but preserve those with properties)\n // We keep <w:p><w:pPr>...</w:pPr></w:p> as those are intentional empty paragraphs with styling\n result = result.replace(/<w:p>\\s*<\\/w:p>/g, '');\n\n return result;\n }\n\n /**\n * Parse relationship IDs from word/_rels/document.xml.rels\n * Returns a map of relationship ID to target path\n */\n private parseRelationships(): Map<string, string> {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return new Map();\n\n const map = new Map<string, string>();\n const relationshipRegex = /<Relationship[^>]*Id=\"([^\"]+)\"[^>]*Target=\"([^\"]+)\"[^>]*\\/>/g;\n let match;\n\n while ((match = relationshipRegex.exec(relsXml)) !== null) {\n if (match[1] && match[2]) {\n map.set(match[1], match[2]); // rId -> target path\n }\n }\n\n return map;\n }\n\n /**\n * Get the next available relationship ID\n * Finds the highest numeric ID and increments it\n */\n private getNextRelationshipId(existingIds: Set<string>): string {\n let maxId = 0;\n for (const id of existingIds) {\n const num = parseInt(id.replace('rId', ''));\n if (!isNaN(num) && num > maxId) {\n maxId = num;\n }\n }\n return `rId${maxId + 1}`;\n }\n\n /**\n * Add a new relationship to word/_rels/document.xml.rels\n */\n private addRelationship(rId: string, target: string, type: string): void {\n const relsXml = this.zipHandler.getFileAsString('word/_rels/document.xml.rels');\n if (!relsXml) return;\n\n // Insert new relationship before closing tag\n const newRel = `<Relationship Id=\"${rId}\" Type=\"${type}\" Target=\"${target}\"/>`;\n const updated = relsXml.replace('</Relationships>', `${newRel}\\n</Relationships>`);\n\n this.zipHandler.updateFile('word/_rels/document.xml.rels', updated);\n }\n\n /**\n * Clean up all revision metadata files (people.xml, settings.xml, core.xml).\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Called as part of acceptAllRevisions() but can also be called separately\n * when using in-memory revision acceptance.\n */\n public cleanupMetadata(): void {\n this.cleanupPeopleXml();\n this.cleanupSettingsXml();\n this.cleanupCorePropsXml();\n }\n\n /**\n * Clean up word/people.xml - remove all revision authors\n *\n * Handles both w: and w15: namespace variants\n */\n private cleanupPeopleXml(): void {\n const peopleXml = this.zipHandler.getFileAsString('word/people.xml');\n if (!peopleXml) {\n return;\n }\n\n let content = peopleXml;\n\n // Remove all person elements in any namespace variant\n content = content.replace(/<w:person\\b[^>]*>[\\s\\S]*?<\\/w:person>/g, '');\n content = content.replace(/<w15:person\\b[^>]*>[\\s\\S]*?<\\/w15:person>/g, '');\n\n // Handle any namespace-prefixed variants (w1:, w2:, etc.)\n content = content.replace(/<w\\d+:person\\b[^>]*>[\\s\\S]*?<\\/w\\d+:person>/g, '');\n\n // Also remove self-closing person elements\n content = content.replace(/<w:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w15:person\\b[^>]*\\/>/g, '');\n content = content.replace(/<w\\d+:person\\b[^>]*\\/>/g, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private cleanupSettingsXml(): void {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove trackRevisions element (enables tracking)\n content = content.replace(/<w:trackRevisions\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions\\b[^>]*>[\\s\\S]*?<\\/w:trackRevisions>/g, '');\n\n // Remove revisionView element (controls which revisions are visible)\n content = content.replace(/<w:revisionView\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView\\b[^>]*>[\\s\\S]*?<\\/w:revisionView>/g, '');\n\n // Remove doNotTrackMoves (prevents move tracking)\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*\\/>/g, '');\n content = content.replace(/<w:doNotTrackMoves\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackMoves>/g, '');\n\n // Remove doNotTrackFormatting\n content = content.replace(/<w:doNotTrackFormatting\\b[^>]*\\/>/g, '');\n content = content.replace(\n /<w:doNotTrackFormatting\\b[^>]*>[\\s\\S]*?<\\/w:doNotTrackFormatting>/g,\n ''\n );\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private cleanupCorePropsXml(): void {\n const coreXml = this.zipHandler.getFileAsString('docProps/core.xml');\n if (!coreXml) {\n return;\n }\n\n // Reset revision count to 1\n const content = coreXml.replace(\n /<cp:revision>\\d+<\\/cp:revision>/g,\n '<cp:revision>1</cp:revision>'\n );\n\n this.zipHandler.updateFile('docProps/core.xml', content);\n }\n\n // =========================================================================\n // DOM-based processing helper methods\n // =========================================================================\n\n /**\n * Convert parsed XML object back to XML string\n * Preserves element order using _orderedChildren metadata\n *\n * Based on DocumentParser.objectToXml() implementation\n */\n private objectToXml(obj: any): string {\n const buildXml = (o: any, name?: string): string => {\n // Handle simple string/number with a tag name: <tagName>value</tagName>\n if (name && (typeof o === 'string' || typeof o === 'number')) {\n return `<${name}>${this.escapeXml(String(o))}</${name}>`;\n }\n if (typeof o === 'string') return this.escapeXml(o);\n if (typeof o !== 'object' || o === null) return String(o ?? '');\n\n const keys = Object.keys(o);\n\n // If a name is provided, we're building a specific element\n // Don't return empty string for empty objects with a name - they become self-closing tags\n if (keys.length === 0 && !name) return '';\n\n const tagName = name || keys[0]!;\n const element = name ? o : o[tagName];\n\n let xml = `<${tagName}`;\n\n // Add attributes (keys starting with @_)\n if (element && typeof element === 'object') {\n for (const key of Object.keys(element)) {\n if (key.startsWith('@_')) {\n const attrName = key.substring(2);\n xml += ` ${attrName}=\"${this.escapeXml(String(element[key]))}\"`;\n }\n }\n }\n\n // Check for children (non-attribute, non-text, non-metadata keys)\n const hasChildren =\n element &&\n typeof element === 'object' &&\n Object.keys(element).some(\n (k) => !k.startsWith('@_') && k !== '#text' && k !== '_orderedChildren'\n );\n\n // Per ECMA-376, certain elements MUST NOT be self-closing (e.g., <w:p/> is invalid).\n // This mirrors the CANNOT_SELF_CLOSE list in XMLBuilder.ts.\n const CANNOT_SELF_CLOSE = [\n 'w:t',\n 'w:r',\n 'w:p',\n 'w:tbl',\n 'w:tr',\n 'w:tc',\n 'w:body',\n 'w:document',\n 'w:hyperlink',\n 'w:sdt',\n 'w:sdtContent',\n 'w:sdtPr',\n 'w:pPr',\n 'w:rPr',\n 'w:sectPr',\n 'w:del',\n 'w:ins',\n 'w:moveFrom',\n 'w:moveTo',\n ];\n\n if (!hasChildren && !element?.['#text']) {\n if (CANNOT_SELF_CLOSE.includes(tagName)) {\n xml += `></${tagName}>`;\n } else {\n xml += '/>';\n }\n } else {\n xml += '>';\n\n // Add text content\n if (element?.['#text']) {\n xml += this.escapeXml(String(element['#text']));\n }\n\n // Add child elements using _orderedChildren if available\n if (element && typeof element === 'object') {\n const orderedChildren = element._orderedChildren as\n | { type: string; index: number }[]\n | undefined;\n\n if (orderedChildren && orderedChildren.length > 0) {\n // Use _orderedChildren to preserve element order\n for (const childInfo of orderedChildren) {\n const childType = childInfo.type;\n const childIndex = childInfo.index;\n\n if (element[childType] !== undefined) {\n const children = element[childType];\n\n if (Array.isArray(children)) {\n if (childIndex < children.length) {\n const childXml = buildXml(children[childIndex], childType);\n xml += childXml;\n }\n } else {\n // Single child element\n if (childIndex === 0) {\n const childXml = buildXml(children, childType);\n xml += childXml;\n }\n }\n }\n }\n } else {\n // Fallback: iterate through keys if no _orderedChildren\n for (const key of Object.keys(element)) {\n if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const children = element[key];\n if (Array.isArray(children)) {\n for (const child of children) {\n xml += buildXml(child, key);\n }\n } else {\n xml += buildXml(children, key);\n }\n }\n }\n }\n }\n\n xml += `</${tagName}>`;\n }\n\n return xml;\n };\n\n return buildXml(obj);\n }\n\n /**\n * Escape special XML characters\n */\n private escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n\n /**\n * Remap image relationship IDs in the parsed tree to prevent duplicates\n * Walks the tree looking for r:embed attributes and assigns unique IDs\n */\n private remapImageRelationshipsInTree(obj: any): void {\n const relationships = this.parseRelationships();\n const existingIds = new Set(relationships.keys());\n const remappedIds = new Map<string, string>();\n\n // Walk the tree and find all r:embed attributes\n this.walkTreeForEmbeds(obj, (embedId: string, parent: any, key: string) => {\n // Check if this ID has already been remapped\n if (remappedIds.has(embedId)) {\n parent[key] = remappedIds.get(embedId);\n return;\n }\n\n // Check if this ID needs remapping (duplicate)\n // For DOM-based processing, we check if we've seen this ID before in this pass\n const target = relationships.get(embedId);\n if (target) {\n // Generate new unique ID\n const newId = this.getNextRelationshipId(existingIds);\n existingIds.add(newId);\n remappedIds.set(embedId, newId);\n\n // Add relationship with same target\n this.addRelationship(\n newId,\n target,\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'\n );\n\n // Update the attribute\n parent[key] = newId;\n }\n });\n }\n\n /**\n * Walk the tree looking for r:embed attributes\n */\n private walkTreeForEmbeds(\n obj: any,\n callback: (embedId: string, parent: any, key: string) => void\n ): void {\n if (!obj || typeof obj !== 'object') {\n return;\n }\n\n for (const key of Object.keys(obj)) {\n // Check for r:embed attribute\n if (key === '@_r:embed') {\n callback(obj[key], obj, key);\n } else if (!key.startsWith('@_') && key !== '#text' && key !== '_orderedChildren') {\n const value = obj[key];\n if (Array.isArray(value)) {\n for (const item of value) {\n this.walkTreeForEmbeds(item, callback);\n }\n } else if (typeof value === 'object') {\n this.walkTreeForEmbeds(value, callback);\n }\n }\n }\n }\n}\n\n/**\n * Convenience function to accept all revisions in a document\n */\nexport async function acceptAllRevisions(zipHandler: ZipHandler): Promise<void> {\n const acceptor = new RevisionProcessor(zipHandler);\n await acceptor.process();\n}\n\n/**\n * Convenience function to reject all revisions in a document, reverting it to\n * its original pre-edit state (the exact inverse of {@link acceptAllRevisions}):\n *\n * 1. Insertions (`w:ins`): removed — inserted content is discarded\n * 2. Deletions (`w:del`): unwrapped and `w:delText` restored to `w:t` — deleted\n * content reappears\n * 3. MoveFrom (`w:moveFrom`): unwrapped — the original source content is restored\n * 4. MoveTo (`w:moveTo`): removed — the moved-to destination is discarded\n * 5. Property changes (`w:rPrChange`, `w:pPrChange`, ...): previous formatting\n * stored inside the change is restored, then the marker is removed\n * 6. Inserted rows/tables are removed; deleted rows/tables are kept\n * 7. Range markers are removed and revision metadata is cleaned up\n *\n * Limitations (shared with {@link acceptAllRevisions}): cell-level markers\n * (`w:cellIns`/`w:cellDel`/`w:cellMerge`) are left in place, and the legacy\n * `w:numberingChange` is dropped rather than reverted (it embeds no recoverable\n * previous value).\n *\n * @param zipHandler - The ZipHandler containing the DOCX package\n */\nexport async function rejectAllRevisions(zipHandler: ZipHandler): Promise<void> {\n const rejector = new RevisionProcessor(zipHandler, 'reject');\n await rejector.process();\n}\n\n/**\n * Convenience function to clean up revision metadata files.\n *\n * This removes:\n * - All revision authors from people.xml\n * - Track changes settings from settings.xml\n * - Resets revision count in core.xml\n *\n * Use this after in-memory revision acceptance to ensure metadata is also cleaned.\n * The raw XML acceptAllRevisions() function calls this automatically.\n *\n * @param zipHandler - The ZipHandler containing the DOCX package\n */\nexport function cleanupRevisionMetadata(zipHandler: ZipHandler): void {\n const processor = new RevisionProcessor(zipHandler);\n processor.cleanupMetadata();\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docxmlater",
3
- "version": "12.0.1",
3
+ "version": "12.1.0",
4
4
  "description": "TypeScript library for editing existing Word documents with full tracked-changes, comment, and bookmark fidelity. Round-trip safe DOCX modification.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -81,7 +81,11 @@ function getLogger(): ILogger {
81
81
  }
82
82
  // Raw XML revision acceptance - used at load time BEFORE parsing
83
83
  // cleanupRevisionMetadata - cleanup metadata files after in-memory acceptance
84
- import { acceptAllRevisions, cleanupRevisionMetadata } from '../processors/acceptRevisions.js';
84
+ import {
85
+ acceptAllRevisions,
86
+ rejectAllRevisions,
87
+ cleanupRevisionMetadata,
88
+ } from '../processors/acceptRevisions.js';
85
89
  // In-memory revision acceptance - used AFTER parsing, allows subsequent modifications
86
90
  import { acceptRevisionsInMemory } from '../processors/InMemoryRevisionAcceptor.js';
87
91
  import { stripTrackedChanges } from '../processors/stripTrackedChanges.js';
@@ -157,6 +161,7 @@ export interface DocumentLoadOptions extends DocumentOptions {
157
161
  *
158
162
  * - 'preserve': Keep tracked changes as-is (may cause corruption if IDs conflict)
159
163
  * - 'accept': Accept all changes - removes revision markup, keeps inserted content, removes deleted content (default)
164
+ * - 'reject': Reject all changes - reverts to the original pre-edit document: removes inserted content, restores deleted content, undoes moves, and restores previous formatting from property-change markers (the exact inverse of 'accept')
160
165
  * - 'strip': Remove all revision markup, keeping inserted content and removing deleted content (same resulting text as 'accept')
161
166
  *
162
167
  * Default: 'accept' (prevents corruption from revision ID conflicts)
@@ -171,6 +176,9 @@ export interface DocumentLoadOptions extends DocumentOptions {
171
176
  * // Explicit accept
172
177
  * const doc = await Document.load('file.docx', { revisionHandling: 'accept' });
173
178
  *
179
+ * // Reject all changes - revert to the original pre-edit document
180
+ * const doc = await Document.load('file.docx', { revisionHandling: 'reject' });
181
+ *
174
182
  * // Strip all tracked changes
175
183
  * const doc = await Document.load('file.docx', { revisionHandling: 'strip' });
176
184
  *
@@ -178,7 +186,7 @@ export interface DocumentLoadOptions extends DocumentOptions {
178
186
  * const doc = await Document.load('file.docx', { revisionHandling: 'preserve' });
179
187
  * ```
180
188
  */
181
- revisionHandling?: 'preserve' | 'accept' | 'strip';
189
+ revisionHandling?: 'preserve' | 'accept' | 'reject' | 'strip';
182
190
 
183
191
  /**
184
192
  * Accept all tracked changes after parsing using in-memory transformation.
@@ -919,6 +927,17 @@ export class Document {
919
927
  // If acceptRevisions is true, we need to preserve revisions during parsing
920
928
  // so they can be accepted using in-memory transformation after parsing
921
929
  const useInMemoryAccept = options?.acceptRevisions === true;
930
+ // `acceptRevisions: true` performs an in-memory ACCEPT, which is the exact
931
+ // opposite of `revisionHandling: 'reject'`. Honoring the in-memory accept
932
+ // gate would silently produce the accepted document when the caller asked
933
+ // to revert — surface the conflict instead of doing the opposite.
934
+ if (useInMemoryAccept && options?.revisionHandling === 'reject') {
935
+ throw new Error(
936
+ "Conflicting load options: 'acceptRevisions: true' (in-memory accept) cannot be combined " +
937
+ 'with \'revisionHandling: "reject"\'. Use \'revisionHandling: "reject"\' on its own to ' +
938
+ 'revert the document to its original pre-edit state.'
939
+ );
940
+ }
922
941
  const revisionHandling = useInMemoryAccept
923
942
  ? 'preserve' // Force preserve so revisions are parsed into model
924
943
  : (options?.revisionHandling ?? 'accept'); // Default to accept
@@ -927,6 +946,10 @@ export class Document {
927
946
  if (revisionHandling === 'accept') {
928
947
  // Accept all tracked changes to prevent corruption (raw XML approach)
929
948
  await acceptAllRevisions(zipHandler);
949
+ } else if (revisionHandling === 'reject') {
950
+ // Reject all tracked changes - revert to the original pre-edit document
951
+ // (inverse of accept: drop insertions, restore deletions/moves/formatting)
952
+ await rejectAllRevisions(zipHandler);
930
953
  } else if (revisionHandling === 'strip') {
931
954
  // Strip all tracked changes completely
932
955
  await stripTrackedChanges(zipHandler);