docxmlater 11.0.9 → 12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -13
- package/dist/core/Document.d.ts +28 -2
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +725 -170
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts +1 -0
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +77 -25
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentParser.d.ts +7 -3
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +431 -85
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +2 -2
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/elements/Comment.d.ts +15 -1
- package/dist/elements/Comment.d.ts.map +1 -1
- package/dist/elements/Comment.js +67 -12
- package/dist/elements/Comment.js.map +1 -1
- package/dist/elements/CommentManager.d.ts +4 -0
- package/dist/elements/CommentManager.d.ts.map +1 -1
- package/dist/elements/CommentManager.js +74 -16
- package/dist/elements/CommentManager.js.map +1 -1
- package/dist/elements/EndnoteManager.d.ts.map +1 -1
- package/dist/elements/EndnoteManager.js.map +1 -1
- package/dist/elements/Field.d.ts +10 -1
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +76 -34
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/FieldHelpers.d.ts +1 -0
- package/dist/elements/FieldHelpers.d.ts.map +1 -1
- package/dist/elements/FieldHelpers.js +8 -4
- package/dist/elements/FieldHelpers.js.map +1 -1
- package/dist/elements/Footer.d.ts +3 -1
- package/dist/elements/Footer.d.ts.map +1 -1
- package/dist/elements/Footer.js +39 -53
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/FootnoteManager.d.ts.map +1 -1
- package/dist/elements/FootnoteManager.js.map +1 -1
- package/dist/elements/Header.d.ts +3 -1
- package/dist/elements/Header.d.ts.map +1 -1
- package/dist/elements/Header.js +39 -53
- package/dist/elements/Header.js.map +1 -1
- package/dist/elements/HeaderFooterManager.d.ts +4 -2
- package/dist/elements/HeaderFooterManager.d.ts.map +1 -1
- package/dist/elements/HeaderFooterManager.js +36 -6
- package/dist/elements/HeaderFooterManager.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts +6 -1
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +69 -44
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +33 -6
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/ImageManager.d.ts +1 -0
- package/dist/elements/ImageManager.d.ts.map +1 -1
- package/dist/elements/ImageManager.js +11 -0
- package/dist/elements/ImageManager.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +3 -0
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +91 -26
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/Revision.d.ts +4 -0
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +369 -29
- package/dist/elements/Revision.js.map +1 -1
- package/dist/elements/Run.d.ts +1 -0
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +24 -4
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +17 -7
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.d.ts.map +1 -1
- package/dist/elements/Shape.js +50 -42
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts +9 -1
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +46 -6
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/Table.d.ts +2 -0
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +90 -42
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +1 -0
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +32 -13
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableOfContents.d.ts.map +1 -1
- package/dist/elements/TableOfContents.js +5 -7
- package/dist/elements/TableOfContents.js.map +1 -1
- package/dist/elements/TableRow.d.ts +1 -0
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +16 -1
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/elements/TextBox.d.ts.map +1 -1
- package/dist/elements/TextBox.js +55 -42
- package/dist/elements/TextBox.js.map +1 -1
- package/dist/esm/core/Document.js +726 -171
- package/dist/esm/core/Document.js.map +1 -1
- package/dist/esm/core/DocumentGenerator.js +77 -25
- package/dist/esm/core/DocumentGenerator.js.map +1 -1
- package/dist/esm/core/DocumentParser.js +431 -85
- package/dist/esm/core/DocumentParser.js.map +1 -1
- package/dist/esm/core/RelationshipManager.js +2 -2
- package/dist/esm/core/RelationshipManager.js.map +1 -1
- package/dist/esm/elements/Comment.js +67 -12
- package/dist/esm/elements/Comment.js.map +1 -1
- package/dist/esm/elements/CommentManager.js +74 -16
- package/dist/esm/elements/CommentManager.js.map +1 -1
- package/dist/esm/elements/EndnoteManager.js.map +1 -1
- package/dist/esm/elements/Field.js +77 -35
- package/dist/esm/elements/Field.js.map +1 -1
- package/dist/esm/elements/FieldHelpers.js +7 -4
- package/dist/esm/elements/FieldHelpers.js.map +1 -1
- package/dist/esm/elements/Footer.js +39 -53
- package/dist/esm/elements/Footer.js.map +1 -1
- package/dist/esm/elements/FootnoteManager.js.map +1 -1
- package/dist/esm/elements/Header.js +39 -53
- package/dist/esm/elements/Header.js.map +1 -1
- package/dist/esm/elements/HeaderFooterManager.js +36 -6
- package/dist/esm/elements/HeaderFooterManager.js.map +1 -1
- package/dist/esm/elements/Hyperlink.js +69 -44
- package/dist/esm/elements/Hyperlink.js.map +1 -1
- package/dist/esm/elements/Image.js +33 -6
- package/dist/esm/elements/Image.js.map +1 -1
- package/dist/esm/elements/ImageManager.js +11 -0
- package/dist/esm/elements/ImageManager.js.map +1 -1
- package/dist/esm/elements/Paragraph.js +91 -26
- package/dist/esm/elements/Paragraph.js.map +1 -1
- package/dist/esm/elements/Revision.js +369 -29
- package/dist/esm/elements/Revision.js.map +1 -1
- package/dist/esm/elements/Run.js +24 -4
- package/dist/esm/elements/Run.js.map +1 -1
- package/dist/esm/elements/Section.js +17 -7
- package/dist/esm/elements/Section.js.map +1 -1
- package/dist/esm/elements/Shape.js +50 -42
- package/dist/esm/elements/Shape.js.map +1 -1
- package/dist/esm/elements/StructuredDocumentTag.js +46 -6
- package/dist/esm/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/esm/elements/Table.js +90 -42
- package/dist/esm/elements/Table.js.map +1 -1
- package/dist/esm/elements/TableCell.js +32 -13
- package/dist/esm/elements/TableCell.js.map +1 -1
- package/dist/esm/elements/TableOfContents.js +5 -7
- package/dist/esm/elements/TableOfContents.js.map +1 -1
- package/dist/esm/elements/TableRow.js +16 -1
- package/dist/esm/elements/TableRow.js.map +1 -1
- package/dist/esm/elements/TextBox.js +55 -42
- package/dist/esm/elements/TextBox.js.map +1 -1
- package/dist/esm/formatting/AbstractNumbering.js +1 -1
- package/dist/esm/formatting/AbstractNumbering.js.map +1 -1
- package/dist/esm/formatting/NumberingLevel.js +8 -6
- package/dist/esm/formatting/NumberingLevel.js.map +1 -1
- package/dist/esm/formatting/NumberingManager.js +16 -1
- package/dist/esm/formatting/NumberingManager.js.map +1 -1
- package/dist/esm/formatting/Style.js +14 -0
- package/dist/esm/formatting/Style.js.map +1 -1
- package/dist/esm/formatting/StylesManager.js +14 -2
- package/dist/esm/formatting/StylesManager.js.map +1 -1
- package/dist/esm/helpers/CleanupHelper.js +103 -26
- package/dist/esm/helpers/CleanupHelper.js.map +1 -1
- package/dist/esm/images/ImageOptimizer.js +52 -4
- package/dist/esm/images/ImageOptimizer.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal.js +1 -1
- package/dist/esm/internal.js.map +1 -1
- package/dist/esm/processors/CompatibilityUpgrader.js +7 -1
- package/dist/esm/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/esm/processors/InMemoryRevisionAcceptor.js +134 -13
- package/dist/esm/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/RevisionWalker.js +58 -8
- package/dist/esm/processors/RevisionWalker.js.map +1 -1
- package/dist/esm/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/esm/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/cnfStyleDecoder.js +7 -7
- package/dist/esm/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/esm/processors/stripTrackedChanges.js +16 -5
- package/dist/esm/processors/stripTrackedChanges.js.map +1 -1
- package/dist/esm/utils/deepClone.js +24 -11
- package/dist/esm/utils/deepClone.js.map +1 -1
- package/dist/esm/utils/units.js +1 -1
- package/dist/esm/utils/units.js.map +1 -1
- package/dist/esm/utils/validation.js +11 -23
- package/dist/esm/utils/validation.js.map +1 -1
- package/dist/esm/utils/xmlSanitization.js +131 -7
- package/dist/esm/utils/xmlSanitization.js.map +1 -1
- package/dist/esm/validation/RevisionAutoFixer.js +69 -55
- package/dist/esm/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/esm/validation/RevisionValidator.js +24 -20
- package/dist/esm/validation/RevisionValidator.js.map +1 -1
- package/dist/esm/xml/XMLBuilder.js +52 -20
- package/dist/esm/xml/XMLBuilder.js.map +1 -1
- package/dist/esm/xml/XMLParser.js +55 -13
- package/dist/esm/xml/XMLParser.js.map +1 -1
- package/dist/esm/zip/ZipHandler.js +37 -13
- package/dist/esm/zip/ZipHandler.js.map +1 -1
- package/dist/esm/zip/ZipReader.js +53 -6
- package/dist/esm/zip/ZipReader.js.map +1 -1
- package/dist/esm/zip/errors.js +7 -0
- package/dist/esm/zip/errors.js.map +1 -1
- package/dist/esm/zip/types.js +4 -0
- package/dist/esm/zip/types.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +1 -1
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts +1 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +8 -6
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/NumberingManager.d.ts.map +1 -1
- package/dist/formatting/NumberingManager.js +16 -1
- package/dist/formatting/NumberingManager.js.map +1 -1
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +14 -0
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +2 -0
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +14 -2
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.d.ts.map +1 -1
- package/dist/helpers/CleanupHelper.js +103 -26
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.d.ts.map +1 -1
- package/dist/images/ImageOptimizer.js +52 -4
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -1
- package/dist/internal.js.map +1 -1
- package/dist/processors/CompatibilityUpgrader.d.ts.map +1 -1
- package/dist/processors/CompatibilityUpgrader.js +7 -1
- package/dist/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.d.ts +1 -0
- package/dist/processors/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.js +135 -13
- package/dist/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/processors/RevisionWalker.d.ts +2 -0
- package/dist/processors/RevisionWalker.d.ts.map +1 -1
- package/dist/processors/RevisionWalker.js +58 -8
- package/dist/processors/RevisionWalker.js.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/processors/cnfStyleDecoder.d.ts.map +1 -1
- package/dist/processors/cnfStyleDecoder.js +7 -7
- package/dist/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/processors/stripTrackedChanges.d.ts.map +1 -1
- package/dist/processors/stripTrackedChanges.js +16 -5
- package/dist/processors/stripTrackedChanges.js.map +1 -1
- package/dist/utils/deepClone.d.ts.map +1 -1
- package/dist/utils/deepClone.js +24 -11
- package/dist/utils/deepClone.js.map +1 -1
- package/dist/utils/units.d.ts.map +1 -1
- package/dist/utils/units.js +1 -1
- package/dist/utils/units.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +11 -23
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/xmlSanitization.d.ts +2 -0
- package/dist/utils/xmlSanitization.d.ts.map +1 -1
- package/dist/utils/xmlSanitization.js +133 -7
- package/dist/utils/xmlSanitization.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.d.ts +6 -2
- package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
- package/dist/validation/RevisionAutoFixer.js +68 -54
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/validation/RevisionValidator.d.ts +2 -0
- package/dist/validation/RevisionValidator.d.ts.map +1 -1
- package/dist/validation/RevisionValidator.js +26 -21
- package/dist/validation/RevisionValidator.js.map +1 -1
- package/dist/xml/XMLBuilder.d.ts +1 -0
- package/dist/xml/XMLBuilder.d.ts.map +1 -1
- package/dist/xml/XMLBuilder.js +52 -20
- package/dist/xml/XMLBuilder.js.map +1 -1
- package/dist/xml/XMLParser.d.ts +1 -0
- package/dist/xml/XMLParser.d.ts.map +1 -1
- package/dist/xml/XMLParser.js +55 -13
- package/dist/xml/XMLParser.js.map +1 -1
- package/dist/zip/ZipHandler.d.ts.map +1 -1
- package/dist/zip/ZipHandler.js +37 -13
- package/dist/zip/ZipHandler.js.map +1 -1
- package/dist/zip/ZipReader.d.ts.map +1 -1
- package/dist/zip/ZipReader.js +52 -5
- package/dist/zip/ZipReader.js.map +1 -1
- package/dist/zip/errors.d.ts +3 -0
- package/dist/zip/errors.d.ts.map +1 -1
- package/dist/zip/errors.js +9 -1
- package/dist/zip/errors.js.map +1 -1
- package/dist/zip/types.d.ts +4 -0
- package/dist/zip/types.d.ts.map +1 -1
- package/dist/zip/types.js +4 -0
- package/dist/zip/types.js.map +1 -1
- package/package.json +2 -2
- package/src/core/Document.ts +1159 -240
- package/src/core/DocumentGenerator.ts +106 -26
- package/src/core/DocumentParser.ts +692 -120
- package/src/core/RelationshipManager.ts +446 -442
- package/src/elements/Comment.ts +123 -18
- package/src/elements/CommentManager.ts +121 -22
- package/src/elements/EndnoteManager.ts +4 -1
- package/src/elements/Field.ts +134 -43
- package/src/elements/FieldHelpers.ts +20 -4
- package/src/elements/Footer.ts +62 -67
- package/src/elements/FootnoteManager.ts +4 -1
- package/src/elements/Header.ts +62 -67
- package/src/elements/HeaderFooterManager.ts +56 -8
- package/src/elements/Hyperlink.ts +150 -55
- package/src/elements/Image.ts +51 -7
- package/src/elements/ImageManager.ts +24 -0
- package/src/elements/Paragraph.ts +161 -40
- package/src/elements/Revision.ts +446 -47
- package/src/elements/Run.ts +44 -6
- package/src/elements/Section.ts +25 -9
- package/src/elements/Shape.ts +52 -44
- package/src/elements/StructuredDocumentTag.ts +83 -8
- package/src/elements/Table.ts +151 -50
- package/src/elements/TableCell.ts +57 -17
- package/src/elements/TableOfContents.ts +10 -9
- package/src/elements/TableRow.ts +35 -3
- package/src/elements/TextBox.ts +58 -43
- package/src/formatting/AbstractNumbering.ts +4 -2
- package/src/formatting/NumberingLevel.ts +50 -12
- package/src/formatting/NumberingManager.ts +32 -3
- package/src/formatting/Style.ts +14 -0
- package/src/formatting/StylesManager.ts +29 -2
- package/src/helpers/CleanupHelper.ts +122 -30
- package/src/images/ImageOptimizer.ts +64 -5
- package/src/index.ts +7 -0
- package/src/internal.ts +1 -0
- package/src/processors/CompatibilityUpgrader.ts +15 -2
- package/src/processors/InMemoryRevisionAcceptor.ts +276 -17
- package/src/processors/RevisionWalker.ts +83 -7
- package/src/processors/SelectiveRevisionAcceptor.ts +164 -28
- package/src/processors/cnfStyleDecoder.ts +18 -12
- package/src/processors/stripTrackedChanges.ts +47 -10
- package/src/utils/deepClone.ts +48 -14
- package/src/utils/units.ts +3 -1
- package/src/utils/validation.ts +30 -32
- package/src/utils/xmlSanitization.ts +218 -22
- package/src/validation/RevisionAutoFixer.ts +109 -65
- package/src/validation/RevisionValidator.ts +48 -23
- package/src/xml/XMLBuilder.ts +82 -22
- package/src/xml/XMLParser.ts +87 -20
- package/src/zip/ZipHandler.ts +61 -21
- package/src/zip/ZipReader.ts +135 -13
- package/src/zip/errors.ts +15 -0
- package/src/zip/types.ts +44 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stripTrackedChanges.js","sourceRoot":"","sources":["../../src/processors/stripTrackedChanges.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler.js';\n\n/**\n * Strips all tracked changes markup from a Word document\n * This includes insertions, deletions, move operations, and property changes\n * Also cleans up related metadata in people.xml, settings.xml, and core.xml\n */\nclass TrackedChangesStripper {\n private zipHandler: ZipHandler;\n\n constructor(zipHandler: ZipHandler) {\n this.zipHandler = zipHandler;\n }\n\n /**\n * Main method to strip all tracked changes from the document.\n *\n * Per ECMA-376 Part 1, tracked-change markup can appear in any\n * part that carries block-level content: the body (§17.2 w:body),\n * headers / footers (§17.10.3-4 CT_HdrFtr), footnotes (§17.11.15),\n * endnotes (§17.11.4), and comments (§17.13.4). All of these\n * must be walked — stripping document.xml alone would leave\n * tracked changes visible in Word for every header / footer /\n * note / comment revision.\n */\n public async stripTrackedChanges(): Promise<void> {\n // Always process the body.\n await this.stripPartRevisions('word/document.xml');\n\n // Process every header and footer part present in the ZIP.\n for (const file of this.zipHandler.getFilePaths()) {\n if (/^word\\/header\\d+\\.xml$/.exec(file) || /^word\\/footer\\d+\\.xml$/.exec(file)) {\n await this.stripPartRevisions(file);\n }\n }\n\n // Process singleton notes / comments parts when present.\n for (const path of ['word/footnotes.xml', 'word/endnotes.xml', 'word/comments.xml']) {\n if (this.zipHandler.getFileAsString(path)) {\n await this.stripPartRevisions(path);\n }\n }\n\n // Clean up metadata files\n await this.cleanupPeopleXml();\n await this.cleanupSettingsXml();\n await this.cleanupCorePropsXml();\n }\n\n /**\n * Strip ALL revision elements from a single document part.\n * The per-step pipeline is identical to the historical\n * document.xml implementation; the only difference is the\n * configurable source path.\n */\n private async stripPartRevisions(partPath: string): Promise<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 (boundary markers for tracked changes)\n content = this.removeRangeMarkers(content);\n\n // STEP 2: Process insertions - keep content, remove wrapper\n content = this.processInsertions(content);\n\n // STEP 3: Process deletions - remove entirely\n content = this.processDeletions(content);\n\n // STEP 4: Process move operations\n content = this.processMoveFrom(content);\n content = this.processMoveTo(content);\n\n // STEP 5: Remove all property change tracking elements\n content = this.removePropertyChanges(content);\n\n // STEP 6: Remove any remaining self-closing revision tags\n content = this.removeSelfClosingRevisionTags(content);\n\n // Update the file in the zip\n this.zipHandler.updateFile(partPath, content);\n }\n\n /**\n * Remove all range marker elements\n */\n private removeRangeMarkers(xml: string): string {\n const patterns = [\n /<w:moveFromRangeStart[^>]*\\/>/g,\n /<w:moveFromRangeEnd[^>]*\\/>/g,\n /<w:moveToRangeStart[^>]*\\/>/g,\n /<w:moveToRangeEnd[^>]*\\/>/g,\n /<w:customXmlInsRangeStart[^>]*\\/>/g,\n /<w:customXmlInsRangeEnd[^>]*\\/>/g,\n /<w:customXmlDelRangeStart[^>]*\\/>/g,\n /<w:customXmlDelRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveToRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveToRangeEnd[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:ins> elements - keep inner content, remove wrapper\n * Handles orphaned tags by removing opening and closing tags separately\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 processInsertions(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 // First, remove all closing tags\n result = result.replace(/<\\/w:ins>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:ins[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Process <w:del> elements - remove entire element\n * Uses iterative replacement to handle nested deletions\n */\n private processDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes (handles nested revisions)\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Match entire deletion element and remove it\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:del[\\s>][^>]*>.*?<\\/w:del>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveFrom> elements - remove entire element (source of move)\n * Uses iterative replacement to handle nested moves\n */\n private processMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:moveFrom[\\s>][^>]*>.*?<\\/w:moveFrom>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveTo> elements - keep inner content (destination of move)\n * Handles orphaned tags by removing opening and closing tags separately\n */\n private processMoveTo(xml: string): string {\n let result = xml;\n\n // First, remove all closing tags\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:moveTo[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n */\n private removePropertyChanges(xml: string): string {\n const patterns = [\n /<w:rPrChange[^>]*>.*?<\\/w:rPrChange>/gs, // Run property changes\n /<w:pPrChange[^>]*>.*?<\\/w:pPrChange>/gs, // Paragraph property changes\n /<w:tblPrChange[^>]*>.*?<\\/w:tblPrChange>/gs, // Table property changes\n /<w:tblPrExChange[^>]*>.*?<\\/w:tblPrExChange>/gs, // Table property exception changes\n /<w:tcPrChange[^>]*>.*?<\\/w:tcPrChange>/gs, // Table cell property changes\n /<w:trPrChange[^>]*>.*?<\\/w:trPrChange>/gs, // Table row property changes\n /<w:sectPrChange[^>]*>.*?<\\/w:sectPrChange>/gs, // Section property changes\n /<w:tblGridChange[^>]*>.*?<\\/w:tblGridChange>/gs, // Table grid changes\n /<w:numberingChange[^>]*>.*?<\\/w:numberingChange>/gs, // Numbering changes\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Remove self-closing revision tags\n */\n private removeSelfClosingRevisionTags(xml: string): string {\n const patterns = [\n /<w:ins\\s+[^>]*\\/>/g,\n /<w:del\\s+[^>]*\\/>/g,\n /<w:moveFrom\\s+[^>]*\\/>/g,\n /<w:moveTo\\s+[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\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 word/people.xml - remove revision authors\n */\n private async cleanupPeopleXml(): Promise<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 <w:person> elements (standard namespace)\n content = content.replace(/<w:person[^>]*>.*?<\\/w:person>/gs, '');\n\n // Remove all <w15:person> elements (Word 2013+ namespace)\n content = content.replace(/<w15:person[^>]*>.*?<\\/w15:person>/gs, '');\n\n // Remove any other namespace variants of person elements\n content = content.replace(/<w\\d*:person[^>]*>.*?<\\/w\\d*:person>/gs, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private async cleanupSettingsXml(): Promise<void> {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove track changes settings\n content = content.replace(/<w:trackRevisions[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions[^>]*>.*?<\\/w:trackRevisions>/gs, '');\n\n // Remove revision view settings\n content = content.replace(/<w:revisionView[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView[^>]*>.*?<\\/w:revisionView>/gs, '');\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private async cleanupCorePropsXml(): Promise<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/**\n * Convenience function to strip tracked changes from a ZipHandler\n */\nexport async function stripTrackedChanges(zipHandler: ZipHandler): Promise<void> {\n const stripper = new TrackedChangesStripper(zipHandler);\n await stripper.stripTrackedChanges();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stripTrackedChanges.js","sourceRoot":"","sources":["../../src/processors/stripTrackedChanges.ts"],"names":[],"mappings":"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","sourcesContent":["import { ZipHandler } from '../zip/ZipHandler.js';\n\n/**\n * Strips all tracked changes markup from a Word document\n * This includes insertions, deletions, move operations, and property changes\n * Also cleans up related metadata in people.xml, settings.xml, and core.xml\n */\nclass TrackedChangesStripper {\n private zipHandler: ZipHandler;\n\n constructor(zipHandler: ZipHandler) {\n this.zipHandler = zipHandler;\n }\n\n /**\n * Main method to strip all tracked changes from the document.\n *\n * Per ECMA-376 Part 1, tracked-change markup can appear in any\n * part that carries block-level content: the body (§17.2 w:body),\n * headers / footers (§17.10.3-4 CT_HdrFtr), footnotes (§17.11.15),\n * endnotes (§17.11.4), and comments (§17.13.4). All of these\n * must be walked — stripping document.xml alone would leave\n * tracked changes visible in Word for every header / footer /\n * note / comment revision.\n */\n public async stripTrackedChanges(): Promise<void> {\n // Always process the body.\n await this.stripPartRevisions('word/document.xml');\n\n // Process every header and footer part present in the ZIP.\n for (const file of this.zipHandler.getFilePaths()) {\n if (/^word\\/header\\d+\\.xml$/.exec(file) || /^word\\/footer\\d+\\.xml$/.exec(file)) {\n await this.stripPartRevisions(file);\n }\n }\n\n // Process singleton notes / comments parts when present.\n for (const path of ['word/footnotes.xml', 'word/endnotes.xml', 'word/comments.xml']) {\n if (this.zipHandler.getFileAsString(path)) {\n await this.stripPartRevisions(path);\n }\n }\n\n // Clean up metadata files\n await this.cleanupPeopleXml();\n await this.cleanupSettingsXml();\n await this.cleanupCorePropsXml();\n }\n\n /**\n * Strip ALL revision elements from a single document part.\n * The per-step pipeline is identical to the historical\n * document.xml implementation; the only difference is the\n * configurable source path.\n */\n private async stripPartRevisions(partPath: string): Promise<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 (boundary markers for tracked changes)\n content = this.removeRangeMarkers(content);\n\n // STEP 2: Process insertions - keep content, remove wrapper\n content = this.processInsertions(content);\n\n // STEP 3: Remove rows whose w:trPr carries a row-deletion marker\n // (self-closing <w:del/> per ECMA-376 §17.13.5.14 marks the ENTIRE\n // row as deleted). Must run before the marker itself is stripped in\n // STEP 4, otherwise the row would silently survive as un-deleted.\n content = this.removeDeletedRows(content);\n\n // STEP 4: Remove self-closing revision markers (paragraph-mark\n // deletions in w:pPr/w:rPr per ECMA-376 §17.13.5.15, etc.). Must run\n // BEFORE the block-removal steps: their [^>]* also matches the\n // trailing '/' of `<w:del .../>`, which would turn the marker into an\n // opening tag and swallow everything up to the next closing tag,\n // corrupting the part.\n content = this.removeSelfClosingRevisionTags(content);\n\n // STEP 5: Process deletions - remove entirely\n content = this.processDeletions(content);\n\n // STEP 6: Process move operations\n content = this.processMoveFrom(content);\n content = this.processMoveTo(content);\n\n // STEP 7: Remove all property change tracking elements\n content = this.removePropertyChanges(content);\n\n // Update the file in the zip\n this.zipHandler.updateFile(partPath, content);\n }\n\n /**\n * Remove all range marker elements\n */\n private removeRangeMarkers(xml: string): string {\n const patterns = [\n /<w:moveFromRangeStart[^>]*\\/>/g,\n /<w:moveFromRangeEnd[^>]*\\/>/g,\n /<w:moveToRangeStart[^>]*\\/>/g,\n /<w:moveToRangeEnd[^>]*\\/>/g,\n /<w:customXmlInsRangeStart[^>]*\\/>/g,\n /<w:customXmlInsRangeEnd[^>]*\\/>/g,\n /<w:customXmlDelRangeStart[^>]*\\/>/g,\n /<w:customXmlDelRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveFromRangeEnd[^>]*\\/>/g,\n /<w:customXmlMoveToRangeStart[^>]*\\/>/g,\n /<w:customXmlMoveToRangeEnd[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:ins> elements - keep inner content, remove wrapper\n * Handles orphaned tags by removing opening and closing tags separately\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 processInsertions(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 // First, remove all closing tags\n result = result.replace(/<\\/w:ins>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:ins[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Remove entire <w:tr> rows marked as tracked deletions.\n *\n * Per ECMA-376 Part 1 §17.13.5.14, a self-closing `<w:del/>` inside\n * `<w:trPr>` marks the whole row as deleted — stripping just the marker\n * would resurrect the row instead of removing it. Mirrors the row-level\n * pass in acceptRevisions.ts: the negative lookaheads keep the match\n * anchored to a single row (it cannot slip past a cell boundary or a\n * nested-table row and latch onto a later row's trPr-with-del).\n */\n private removeDeletedRows(xml: string): string {\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\n let result = xml;\n let previousLength = 0;\n while (result.length !== previousLength) {\n previousLength = result.length;\n result = result.replace(rowDelPattern, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:del> elements - remove entire element\n * Uses iterative replacement to handle nested deletions\n */\n private processDeletions(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes (handles nested revisions)\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Match entire deletion element and remove it\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:del[\\s>][^>]*>.*?<\\/w:del>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveFrom> elements - remove entire element (source of move)\n * Uses iterative replacement to handle nested moves\n */\n private processMoveFrom(xml: string): string {\n let result = xml;\n let previousLength = 0;\n\n // Keep replacing until no more changes\n while (result.length !== previousLength) {\n previousLength = result.length;\n\n // Use [\\s>] to match either space or closing bracket\n result = result.replace(/<w:moveFrom[\\s>][^>]*>.*?<\\/w:moveFrom>/gs, '');\n }\n\n return result;\n }\n\n /**\n * Process <w:moveTo> elements - keep inner content (destination of move)\n * Handles orphaned tags by removing opening and closing tags separately\n */\n private processMoveTo(xml: string): string {\n let result = xml;\n\n // First, remove all closing tags\n result = result.replace(/<\\/w:moveTo>/g, '');\n\n // Then, remove all opening tags (keeping any content that follows)\n result = result.replace(/<w:moveTo[\\s>][^>]*>/g, '');\n\n return result;\n }\n\n /**\n * Remove all property change tracking elements\n */\n private removePropertyChanges(xml: string): string {\n const patterns = [\n /<w:rPrChange[^>]*>.*?<\\/w:rPrChange>/gs, // Run property changes\n /<w:pPrChange[^>]*>.*?<\\/w:pPrChange>/gs, // Paragraph property changes\n /<w:tblPrChange[^>]*>.*?<\\/w:tblPrChange>/gs, // Table property changes\n /<w:tblPrExChange[^>]*>.*?<\\/w:tblPrExChange>/gs, // Table property exception changes\n /<w:tcPrChange[^>]*>.*?<\\/w:tcPrChange>/gs, // Table cell property changes\n /<w:trPrChange[^>]*>.*?<\\/w:trPrChange>/gs, // Table row property changes\n /<w:sectPrChange[^>]*>.*?<\\/w:sectPrChange>/gs, // Section property changes\n /<w:tblGridChange[^>]*>.*?<\\/w:tblGridChange>/gs, // Table grid changes\n /<w:numberingChange[^>]*>.*?<\\/w:numberingChange>/gs, // Numbering changes\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\n\n return result;\n }\n\n /**\n * Remove self-closing revision tags\n * `\\b` (not `\\s+`) so attribute-less markers like `<w:del/>` are also\n * caught while `<w:delText>` is not.\n */\n private removeSelfClosingRevisionTags(xml: string): string {\n const patterns = [\n /<w:ins\\b[^>]*\\/>/g,\n /<w:del\\b[^>]*\\/>/g,\n /<w:moveFrom\\b[^>]*\\/>/g,\n /<w:moveTo\\b[^>]*\\/>/g,\n ];\n\n let result = xml;\n for (const pattern of patterns) {\n result = result.replace(pattern, '');\n }\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 word/people.xml - remove revision authors\n */\n private async cleanupPeopleXml(): Promise<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 <w:person> elements (standard namespace)\n content = content.replace(/<w:person[^>]*>.*?<\\/w:person>/gs, '');\n\n // Remove all <w15:person> elements (Word 2013+ namespace)\n content = content.replace(/<w15:person[^>]*>.*?<\\/w15:person>/gs, '');\n\n // Remove any other namespace variants of person elements\n content = content.replace(/<w\\d*:person[^>]*>.*?<\\/w\\d*:person>/gs, '');\n\n this.zipHandler.updateFile('word/people.xml', content);\n }\n\n /**\n * Clean up word/settings.xml - disable track changes\n */\n private async cleanupSettingsXml(): Promise<void> {\n const settingsXml = this.zipHandler.getFileAsString('word/settings.xml');\n if (!settingsXml) {\n return;\n }\n\n let content = settingsXml;\n\n // Remove track changes settings\n content = content.replace(/<w:trackRevisions[^>]*\\/>/g, '');\n content = content.replace(/<w:trackRevisions[^>]*>.*?<\\/w:trackRevisions>/gs, '');\n\n // Remove revision view settings\n content = content.replace(/<w:revisionView[^>]*\\/>/g, '');\n content = content.replace(/<w:revisionView[^>]*>.*?<\\/w:revisionView>/gs, '');\n\n this.zipHandler.updateFile('word/settings.xml', content);\n }\n\n /**\n * Clean up docProps/core.xml - reset revision count\n */\n private async cleanupCorePropsXml(): Promise<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/**\n * Convenience function to strip tracked changes from a ZipHandler\n */\nexport async function stripTrackedChanges(zipHandler: ZipHandler): Promise<void> {\n const stripper = new TrackedChangesStripper(zipHandler);\n await stripper.stripTrackedChanges();\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deepClone.d.ts","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deepClone.d.ts","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":"AA8BA,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAKtC"}
|
package/dist/utils/deepClone.js
CHANGED
|
@@ -2,41 +2,54 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deepClone = deepClone;
|
|
4
4
|
function deepClone(obj) {
|
|
5
|
+
return cloneInternal(obj, new WeakMap());
|
|
6
|
+
}
|
|
7
|
+
function cloneInternal(obj, seen) {
|
|
5
8
|
if (obj === null || typeof obj !== 'object') {
|
|
6
9
|
return obj;
|
|
7
10
|
}
|
|
11
|
+
const existing = seen.get(obj);
|
|
12
|
+
if (existing !== undefined) {
|
|
13
|
+
return existing;
|
|
14
|
+
}
|
|
8
15
|
if (obj instanceof Date) {
|
|
9
|
-
|
|
16
|
+
const dateCopy = new Date(obj.getTime());
|
|
17
|
+
seen.set(obj, dateCopy);
|
|
18
|
+
return dateCopy;
|
|
19
|
+
}
|
|
20
|
+
if (obj instanceof RegExp) {
|
|
21
|
+
const regexpCopy = new RegExp(obj.source, obj.flags);
|
|
22
|
+
seen.set(obj, regexpCopy);
|
|
23
|
+
return regexpCopy;
|
|
10
24
|
}
|
|
11
25
|
if (Array.isArray(obj)) {
|
|
12
26
|
const arrCopy = [];
|
|
27
|
+
seen.set(obj, arrCopy);
|
|
13
28
|
for (let i = 0; i < obj.length; i++) {
|
|
14
|
-
arrCopy[i] =
|
|
29
|
+
arrCopy[i] = cloneInternal(obj[i], seen);
|
|
15
30
|
}
|
|
16
31
|
return arrCopy;
|
|
17
32
|
}
|
|
18
33
|
if (obj instanceof Map) {
|
|
19
34
|
const mapCopy = new Map();
|
|
35
|
+
seen.set(obj, mapCopy);
|
|
20
36
|
obj.forEach((value, key) => {
|
|
21
|
-
mapCopy.set(
|
|
37
|
+
mapCopy.set(cloneInternal(key, seen), cloneInternal(value, seen));
|
|
22
38
|
});
|
|
23
39
|
return mapCopy;
|
|
24
40
|
}
|
|
25
41
|
if (obj instanceof Set) {
|
|
26
42
|
const setCopy = new Set();
|
|
43
|
+
seen.set(obj, setCopy);
|
|
27
44
|
obj.forEach((value) => {
|
|
28
|
-
setCopy.add(
|
|
45
|
+
setCopy.add(cloneInternal(value, seen));
|
|
29
46
|
});
|
|
30
47
|
return setCopy;
|
|
31
48
|
}
|
|
32
|
-
if (obj instanceof RegExp) {
|
|
33
|
-
return new RegExp(obj.source, obj.flags);
|
|
34
|
-
}
|
|
35
49
|
const objCopy = Object.create(Object.getPrototypeOf(obj));
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
50
|
+
seen.set(obj, objCopy);
|
|
51
|
+
for (const key of Object.keys(obj)) {
|
|
52
|
+
objCopy[key] = cloneInternal(obj[key], seen);
|
|
40
53
|
}
|
|
41
54
|
return objCopy;
|
|
42
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deepClone.js","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"deepClone.js","sourceRoot":"","sources":["../../src/utils/deepClone.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Deep clone utility for safely cloning objects\n * More efficient and type-safe than JSON.parse(JSON.stringify())\n */\n\n/**\n * Deep clone an object using structured cloning\n * Preserves most object types including Date, RegExp, Map, Set, etc.\n *\n * For simple objects (like formatting options), this is more efficient\n * than JSON.parse(JSON.stringify()) and doesn't lose non-serializable values.\n *\n * Cyclic and shared references are handled via an internal seen-cache: an\n * object encountered more than once during a single clone is cloned exactly\n * once, so circular graphs cannot overflow the stack and shared sub-objects\n * (including shared Date and RegExp instances) retain a single shared identity\n * in the result.\n *\n * @param obj - Object to clone\n * @returns Deep cloned copy of the object\n *\n * @example\n * ```typescript\n * const original = { bold: true, color: \"FF0000\", date: new Date() };\n * const cloned = deepClone(original);\n * cloned.bold = false;\n * console.log(original.bold); // true (unchanged)\n * console.log(cloned.date instanceof Date); // true (preserved)\n * ```\n */\nexport function deepClone<T>(obj: T): T {\n // Map of already-cloned source objects to their clones, scoped to this call.\n // Guards against infinite recursion on cyclic input and preserves the\n // identity of references shared by multiple parents within the same graph.\n return cloneInternal(obj, new WeakMap<object, unknown>());\n}\n\nfunction cloneInternal<T>(obj: T, seen: WeakMap<object, unknown>): T {\n // Handle primitive types and null\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Return the existing clone for any object already seen in this call. Placed\n // before the Date/RegExp branches so a single Date/RegExp instance shared by\n // multiple nodes resolves to one shared clone (the JSDoc shared-identity\n // guarantee), not a fresh copy per reference.\n const existing = seen.get(obj as object);\n if (existing !== undefined) {\n return existing as T;\n }\n\n // Handle Date (immutable value copy; cannot form a cycle). Registered in\n // `seen` so repeat references to the same instance share this clone.\n if (obj instanceof Date) {\n const dateCopy = new Date(obj.getTime());\n seen.set(obj as object, dateCopy);\n return dateCopy as T;\n }\n\n // Handle RegExp (immutable value copy; cannot form a cycle). Registered in\n // `seen` so repeat references to the same instance share this clone.\n if (obj instanceof RegExp) {\n const regexpCopy = new RegExp(obj.source, obj.flags);\n seen.set(obj as object, regexpCopy);\n return regexpCopy as T;\n }\n\n // Handle Array\n if (Array.isArray(obj)) {\n const arrCopy: unknown[] = [];\n // Register before recursing so self/back references resolve to this clone.\n seen.set(obj as object, arrCopy);\n for (let i = 0; i < obj.length; i++) {\n arrCopy[i] = cloneInternal(obj[i], seen);\n }\n return arrCopy as T;\n }\n\n // Handle Map\n if (obj instanceof Map) {\n const mapCopy = new Map();\n seen.set(obj, mapCopy);\n obj.forEach((value, key) => {\n mapCopy.set(cloneInternal(key, seen), cloneInternal(value, seen));\n });\n return mapCopy as T;\n }\n\n // Handle Set\n if (obj instanceof Set) {\n const setCopy = new Set();\n seen.set(obj, setCopy);\n obj.forEach((value) => {\n setCopy.add(cloneInternal(value, seen));\n });\n return setCopy as T;\n }\n\n // Handle plain objects\n const objCopy = Object.create(Object.getPrototypeOf(obj)) as Record<string, unknown>;\n seen.set(obj as object, objCopy);\n // Object.keys avoids the prototype-builtins shadowing risk of\n // obj.hasOwnProperty(key) (matches sibling deepEqual.ts) and yields the same\n // own-enumerable string keys the previous for..in + hasOwnProperty loop did.\n for (const key of Object.keys(obj as object)) {\n objCopy[key] = cloneInternal((obj as Record<string, unknown>)[key], seen);\n }\n\n return objCopy as T;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY,KAAK,CAAC;AAK/B,eAAO,MAAM,KAAK;;;;;;;;;;;CAqBR,CAAC;AAWX,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAOD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAWD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAOD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAQD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAE7E;AAWD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY,KAAK,CAAC;AAK/B,eAAO,MAAM,KAAK;;;;;;;;;;;CAqBR,CAAC;AAWX,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAOD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAWD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAOD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAOD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAQD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAE7E;AAWD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIpD;AAOD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAOD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAWD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGzD;AAOD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAWD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD;AAOD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAOD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAQD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAEjF;AAWD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5C;AAOD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAOD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAOD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAQD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAEzE;AAYD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAE/E;AAQD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAEjF;AAQD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAEhF;AAQD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAE7E;AAQD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAqB,GAAG,MAAM,CAEjF;AASD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CA0Bb,CAAC;AAKX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC"}
|
package/dist/utils/units.js
CHANGED
|
@@ -72,7 +72,7 @@ function emusToPixels(emus, dpi = exports.STANDARD_DPI) {
|
|
|
72
72
|
return Math.round((emus / exports.UNITS.EMUS_PER_INCH) * dpi);
|
|
73
73
|
}
|
|
74
74
|
function pointsToTwips(points) {
|
|
75
|
-
return points * exports.UNITS.TWIPS_PER_POINT;
|
|
75
|
+
return Math.round(points * exports.UNITS.TWIPS_PER_POINT);
|
|
76
76
|
}
|
|
77
77
|
function pointsToEmus(points) {
|
|
78
78
|
return Math.round(points * exports.UNITS.EMUS_PER_POINT);
|
package/dist/utils/units.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unit Conversion Utilities\n *\n * Word documents use multiple measurement units:\n * - Twips: 1/20th of a point (used for most measurements like margins, indents)\n * - EMUs: English Metric Units (used for DrawingML, images)\n * - Points: Typography unit (72 points = 1 inch)\n * - Pixels: Screen measurement (depends on DPI)\n * - Inches/Centimeters: Human-readable units\n *\n * Conversion factors:\n * - 1 inch = 72 points = 1440 twips = 914,400 EMUs\n * - 1 cm = 0.393701 inches = 360,000 EMUs\n * - 1 point = 20 twips = 12,700 EMUs\n */\n\n/**\n * Standard DPI (dots per inch) for screen displays\n */\nexport const STANDARD_DPI = 96;\n\n/**\n * Conversion constants\n */\nexport const UNITS = {\n /** EMUs per inch */\n EMUS_PER_INCH: 914400,\n /** Twips per inch */\n TWIPS_PER_INCH: 1440,\n /** Points per inch */\n POINTS_PER_INCH: 72,\n /** Twips per point */\n TWIPS_PER_POINT: 20,\n /** EMUs per twip */\n EMUS_PER_TWIP: 635,\n /** EMUs per point */\n EMUS_PER_POINT: 12700,\n /** EMUs per centimeter */\n EMUS_PER_CM: 360000,\n /** Inches per centimeter */\n INCHES_PER_CM: 0.393701,\n /** Centimeters per inch */\n CM_PER_INCH: 2.54,\n /** Half-points per point (Word uses half-points for font sizes) */\n HALF_POINTS_PER_POINT: 2,\n} as const;\n\n// ============================================================================\n// Twips Conversions\n// ============================================================================\n\n/**\n * Converts twips to points\n * @param twips Value in twips\n * @returns Value in points\n */\nexport function twipsToPoints(twips: number): number {\n return twips / UNITS.TWIPS_PER_POINT;\n}\n\n/**\n * Converts twips to inches\n * @param twips Value in twips\n * @returns Value in inches\n */\nexport function twipsToInches(twips: number): number {\n return twips / UNITS.TWIPS_PER_INCH;\n}\n\n/**\n * Converts twips to centimeters\n * @param twips Value in twips\n * @returns Value in centimeters\n */\nexport function twipsToCm(twips: number): number {\n return twipsToInches(twips) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts twips to EMUs\n * @param twips Value in twips\n * @returns Value in EMUs\n */\nexport function twipsToEmus(twips: number): number {\n return Math.round(twips * UNITS.EMUS_PER_TWIP);\n}\n\n// ============================================================================\n// EMUs Conversions\n// ============================================================================\n\n/**\n * Converts EMUs to twips\n * @param emus Value in EMUs\n * @returns Value in twips\n */\nexport function emusToTwips(emus: number): number {\n return Math.round(emus / UNITS.EMUS_PER_TWIP);\n}\n\n/**\n * Converts EMUs to inches\n * @param emus Value in EMUs\n * @returns Value in inches\n */\nexport function emusToInches(emus: number): number {\n return emus / UNITS.EMUS_PER_INCH;\n}\n\n/**\n * Converts EMUs to centimeters\n * @param emus Value in EMUs\n * @returns Value in centimeters\n */\nexport function emusToCm(emus: number): number {\n return emus / UNITS.EMUS_PER_CM;\n}\n\n/**\n * Converts EMUs to points\n * @param emus Value in EMUs\n * @returns Value in points\n */\nexport function emusToPoints(emus: number): number {\n return emus / UNITS.EMUS_PER_POINT;\n}\n\n/**\n * Converts EMUs to pixels\n * @param emus Value in EMUs\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function emusToPixels(emus: number, dpi: number = STANDARD_DPI): number {\n return Math.round((emus / UNITS.EMUS_PER_INCH) * dpi);\n}\n\n// ============================================================================\n// Points Conversions\n// ============================================================================\n\n/**\n * Converts points to twips\n * @param points Value in points\n * @returns Value in twips\n */\nexport function pointsToTwips(points: number): number {\n return points * UNITS.TWIPS_PER_POINT;\n}\n\n/**\n * Converts points to EMUs\n * @param points Value in points\n * @returns Value in EMUs\n */\nexport function pointsToEmus(points: number): number {\n return Math.round(points * UNITS.EMUS_PER_POINT);\n}\n\n/**\n * Converts points to inches\n * @param points Value in points\n * @returns Value in inches\n */\nexport function pointsToInches(points: number): number {\n return points / UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts points to centimeters\n * @param points Value in points\n * @returns Value in centimeters\n */\nexport function pointsToCm(points: number): number {\n return pointsToInches(points) * UNITS.CM_PER_INCH;\n}\n\n// ============================================================================\n// Half-Points Conversions (Word uses half-points for font sizes)\n// ============================================================================\n\n/**\n * Converts points to half-points (for Word font size storage)\n * @param points Value in points\n * @returns Value in half-points\n */\nexport function pointsToHalfPoints(points: number): number {\n // Round to nearest integer — w:sz/w:szCs require ST_HpsMeasure (unsigned integer)\n return Math.round(points * UNITS.HALF_POINTS_PER_POINT);\n}\n\n/**\n * Converts half-points to points (from Word font size storage)\n * @param halfPoints Value in half-points\n * @returns Value in points\n */\nexport function halfPointsToPoints(halfPoints: number): number {\n return halfPoints / UNITS.HALF_POINTS_PER_POINT;\n}\n\n// ============================================================================\n// Inches Conversions\n// ============================================================================\n\n/**\n * Converts inches to twips\n * @param inches Value in inches\n * @returns Value in twips\n */\nexport function inchesToTwips(inches: number): number {\n return Math.round(inches * UNITS.TWIPS_PER_INCH);\n}\n\n/**\n * Converts inches to EMUs\n * @param inches Value in inches\n * @returns Value in EMUs\n */\nexport function inchesToEmus(inches: number): number {\n return Math.round(inches * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts inches to points\n * @param inches Value in inches\n * @returns Value in points\n */\nexport function inchesToPoints(inches: number): number {\n return inches * UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts inches to centimeters\n * @param inches Value in inches\n * @returns Value in centimeters\n */\nexport function inchesToCm(inches: number): number {\n return inches * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts inches to pixels\n * @param inches Value in inches\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function inchesToPixels(inches: number, dpi: number = STANDARD_DPI): number {\n return Math.round(inches * dpi);\n}\n\n// ============================================================================\n// Centimeters Conversions\n// ============================================================================\n\n/**\n * Converts centimeters to twips\n * @param cm Value in centimeters\n * @returns Value in twips\n */\nexport function cmToTwips(cm: number): number {\n return inchesToTwips(cm * UNITS.INCHES_PER_CM);\n}\n\n/**\n * Converts centimeters to EMUs\n * @param cm Value in centimeters\n * @returns Value in EMUs\n */\nexport function cmToEmus(cm: number): number {\n return Math.round(cm * UNITS.EMUS_PER_CM);\n}\n\n/**\n * Converts centimeters to inches\n * @param cm Value in centimeters\n * @returns Value in inches\n */\nexport function cmToInches(cm: number): number {\n return cm * UNITS.INCHES_PER_CM;\n}\n\n/**\n * Converts centimeters to points\n * @param cm Value in centimeters\n * @returns Value in points\n */\nexport function cmToPoints(cm: number): number {\n return inchesToPoints(cmToInches(cm));\n}\n\n/**\n * Converts centimeters to pixels\n * @param cm Value in centimeters\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function cmToPixels(cm: number, dpi: number = STANDARD_DPI): number {\n return inchesToPixels(cmToInches(cm), dpi);\n}\n\n// ============================================================================\n// Pixels Conversions\n// ============================================================================\n\n/**\n * Converts pixels to EMUs\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in EMUs\n */\nexport function pixelsToEmus(pixels: number, dpi: number = STANDARD_DPI): number {\n return Math.round((pixels / dpi) * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts pixels to inches\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in inches\n */\nexport function pixelsToInches(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixels / dpi;\n}\n\n/**\n * Converts pixels to twips\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in twips\n */\nexport function pixelsToTwips(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToTwips(pixelsToInches(pixels, dpi));\n}\n\n/**\n * Converts pixels to centimeters\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in centimeters\n */\nexport function pixelsToCm(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixelsToInches(pixels, dpi) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts pixels to points\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in points\n */\nexport function pixelsToPoints(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToPoints(pixelsToInches(pixels, dpi));\n}\n\n// ============================================================================\n// Common Document Sizes (in twips)\n// ============================================================================\n\n/**\n * Common page sizes in twips\n */\nexport const PAGE_SIZES = {\n /** Letter (8.5\" x 11\") */\n LETTER: {\n width: 12240, // 8.5 inches\n height: 15840, // 11 inches\n },\n /** A4 (21cm x 29.7cm) */\n A4: {\n width: 11906, // 21cm\n height: 16838, // 29.7cm\n },\n /** Legal (8.5\" x 14\") */\n LEGAL: {\n width: 12240, // 8.5 inches\n height: 20160, // 14 inches\n },\n /** Tabloid (11\" x 17\") */\n TABLOID: {\n width: 15840, // 11 inches\n height: 24480, // 17 inches\n },\n /** A3 (29.7cm x 42cm) */\n A3: {\n width: 16838, // 29.7cm\n height: 23811, // 42cm\n },\n} as const;\n\n/**\n * Common margin sizes in twips\n */\nexport const COMMON_MARGINS = {\n /** Normal margins (1 inch all around) */\n NORMAL: {\n top: 1440,\n bottom: 1440,\n left: 1440,\n right: 1440,\n },\n /** Narrow margins (0.5 inch all around) */\n NARROW: {\n top: 720,\n bottom: 720,\n left: 720,\n right: 720,\n },\n /** Wide margins (2 inches left/right, 1 inch top/bottom) */\n WIDE: {\n top: 1440,\n bottom: 1440,\n left: 2880,\n right: 2880,\n },\n /** Moderate margins (1 inch top/bottom, 0.75 inch left/right) */\n MODERATE: {\n top: 1440,\n bottom: 1440,\n left: 1080,\n right: 1080,\n },\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unit Conversion Utilities\n *\n * Word documents use multiple measurement units:\n * - Twips: 1/20th of a point (used for most measurements like margins, indents)\n * - EMUs: English Metric Units (used for DrawingML, images)\n * - Points: Typography unit (72 points = 1 inch)\n * - Pixels: Screen measurement (depends on DPI)\n * - Inches/Centimeters: Human-readable units\n *\n * Conversion factors:\n * - 1 inch = 72 points = 1440 twips = 914,400 EMUs\n * - 1 cm = 0.393701 inches = 360,000 EMUs\n * - 1 point = 20 twips = 12,700 EMUs\n */\n\n/**\n * Standard DPI (dots per inch) for screen displays\n */\nexport const STANDARD_DPI = 96;\n\n/**\n * Conversion constants\n */\nexport const UNITS = {\n /** EMUs per inch */\n EMUS_PER_INCH: 914400,\n /** Twips per inch */\n TWIPS_PER_INCH: 1440,\n /** Points per inch */\n POINTS_PER_INCH: 72,\n /** Twips per point */\n TWIPS_PER_POINT: 20,\n /** EMUs per twip */\n EMUS_PER_TWIP: 635,\n /** EMUs per point */\n EMUS_PER_POINT: 12700,\n /** EMUs per centimeter */\n EMUS_PER_CM: 360000,\n /** Inches per centimeter */\n INCHES_PER_CM: 0.393701,\n /** Centimeters per inch */\n CM_PER_INCH: 2.54,\n /** Half-points per point (Word uses half-points for font sizes) */\n HALF_POINTS_PER_POINT: 2,\n} as const;\n\n// ============================================================================\n// Twips Conversions\n// ============================================================================\n\n/**\n * Converts twips to points\n * @param twips Value in twips\n * @returns Value in points\n */\nexport function twipsToPoints(twips: number): number {\n return twips / UNITS.TWIPS_PER_POINT;\n}\n\n/**\n * Converts twips to inches\n * @param twips Value in twips\n * @returns Value in inches\n */\nexport function twipsToInches(twips: number): number {\n return twips / UNITS.TWIPS_PER_INCH;\n}\n\n/**\n * Converts twips to centimeters\n * @param twips Value in twips\n * @returns Value in centimeters\n */\nexport function twipsToCm(twips: number): number {\n return twipsToInches(twips) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts twips to EMUs\n * @param twips Value in twips\n * @returns Value in EMUs\n */\nexport function twipsToEmus(twips: number): number {\n return Math.round(twips * UNITS.EMUS_PER_TWIP);\n}\n\n// ============================================================================\n// EMUs Conversions\n// ============================================================================\n\n/**\n * Converts EMUs to twips\n * @param emus Value in EMUs\n * @returns Value in twips\n */\nexport function emusToTwips(emus: number): number {\n return Math.round(emus / UNITS.EMUS_PER_TWIP);\n}\n\n/**\n * Converts EMUs to inches\n * @param emus Value in EMUs\n * @returns Value in inches\n */\nexport function emusToInches(emus: number): number {\n return emus / UNITS.EMUS_PER_INCH;\n}\n\n/**\n * Converts EMUs to centimeters\n * @param emus Value in EMUs\n * @returns Value in centimeters\n */\nexport function emusToCm(emus: number): number {\n return emus / UNITS.EMUS_PER_CM;\n}\n\n/**\n * Converts EMUs to points\n * @param emus Value in EMUs\n * @returns Value in points\n */\nexport function emusToPoints(emus: number): number {\n return emus / UNITS.EMUS_PER_POINT;\n}\n\n/**\n * Converts EMUs to pixels\n * @param emus Value in EMUs\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function emusToPixels(emus: number, dpi: number = STANDARD_DPI): number {\n return Math.round((emus / UNITS.EMUS_PER_INCH) * dpi);\n}\n\n// ============================================================================\n// Points Conversions\n// ============================================================================\n\n/**\n * Converts points to twips\n * @param points Value in points\n * @returns Value in twips\n */\nexport function pointsToTwips(points: number): number {\n // Round to nearest integer — twips attributes (w:spacing, w:ind) require\n // ST_DecimalNumber-based integer values\n return Math.round(points * UNITS.TWIPS_PER_POINT);\n}\n\n/**\n * Converts points to EMUs\n * @param points Value in points\n * @returns Value in EMUs\n */\nexport function pointsToEmus(points: number): number {\n return Math.round(points * UNITS.EMUS_PER_POINT);\n}\n\n/**\n * Converts points to inches\n * @param points Value in points\n * @returns Value in inches\n */\nexport function pointsToInches(points: number): number {\n return points / UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts points to centimeters\n * @param points Value in points\n * @returns Value in centimeters\n */\nexport function pointsToCm(points: number): number {\n return pointsToInches(points) * UNITS.CM_PER_INCH;\n}\n\n// ============================================================================\n// Half-Points Conversions (Word uses half-points for font sizes)\n// ============================================================================\n\n/**\n * Converts points to half-points (for Word font size storage)\n * @param points Value in points\n * @returns Value in half-points\n */\nexport function pointsToHalfPoints(points: number): number {\n // Round to nearest integer — w:sz/w:szCs require ST_HpsMeasure (unsigned integer)\n return Math.round(points * UNITS.HALF_POINTS_PER_POINT);\n}\n\n/**\n * Converts half-points to points (from Word font size storage)\n * @param halfPoints Value in half-points\n * @returns Value in points\n */\nexport function halfPointsToPoints(halfPoints: number): number {\n return halfPoints / UNITS.HALF_POINTS_PER_POINT;\n}\n\n// ============================================================================\n// Inches Conversions\n// ============================================================================\n\n/**\n * Converts inches to twips\n * @param inches Value in inches\n * @returns Value in twips\n */\nexport function inchesToTwips(inches: number): number {\n return Math.round(inches * UNITS.TWIPS_PER_INCH);\n}\n\n/**\n * Converts inches to EMUs\n * @param inches Value in inches\n * @returns Value in EMUs\n */\nexport function inchesToEmus(inches: number): number {\n return Math.round(inches * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts inches to points\n * @param inches Value in inches\n * @returns Value in points\n */\nexport function inchesToPoints(inches: number): number {\n return inches * UNITS.POINTS_PER_INCH;\n}\n\n/**\n * Converts inches to centimeters\n * @param inches Value in inches\n * @returns Value in centimeters\n */\nexport function inchesToCm(inches: number): number {\n return inches * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts inches to pixels\n * @param inches Value in inches\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function inchesToPixels(inches: number, dpi: number = STANDARD_DPI): number {\n return Math.round(inches * dpi);\n}\n\n// ============================================================================\n// Centimeters Conversions\n// ============================================================================\n\n/**\n * Converts centimeters to twips\n * @param cm Value in centimeters\n * @returns Value in twips\n */\nexport function cmToTwips(cm: number): number {\n return inchesToTwips(cm * UNITS.INCHES_PER_CM);\n}\n\n/**\n * Converts centimeters to EMUs\n * @param cm Value in centimeters\n * @returns Value in EMUs\n */\nexport function cmToEmus(cm: number): number {\n return Math.round(cm * UNITS.EMUS_PER_CM);\n}\n\n/**\n * Converts centimeters to inches\n * @param cm Value in centimeters\n * @returns Value in inches\n */\nexport function cmToInches(cm: number): number {\n return cm * UNITS.INCHES_PER_CM;\n}\n\n/**\n * Converts centimeters to points\n * @param cm Value in centimeters\n * @returns Value in points\n */\nexport function cmToPoints(cm: number): number {\n return inchesToPoints(cmToInches(cm));\n}\n\n/**\n * Converts centimeters to pixels\n * @param cm Value in centimeters\n * @param dpi Dots per inch (default: 96)\n * @returns Value in pixels\n */\nexport function cmToPixels(cm: number, dpi: number = STANDARD_DPI): number {\n return inchesToPixels(cmToInches(cm), dpi);\n}\n\n// ============================================================================\n// Pixels Conversions\n// ============================================================================\n\n/**\n * Converts pixels to EMUs\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in EMUs\n */\nexport function pixelsToEmus(pixels: number, dpi: number = STANDARD_DPI): number {\n return Math.round((pixels / dpi) * UNITS.EMUS_PER_INCH);\n}\n\n/**\n * Converts pixels to inches\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in inches\n */\nexport function pixelsToInches(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixels / dpi;\n}\n\n/**\n * Converts pixels to twips\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in twips\n */\nexport function pixelsToTwips(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToTwips(pixelsToInches(pixels, dpi));\n}\n\n/**\n * Converts pixels to centimeters\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in centimeters\n */\nexport function pixelsToCm(pixels: number, dpi: number = STANDARD_DPI): number {\n return pixelsToInches(pixels, dpi) * UNITS.CM_PER_INCH;\n}\n\n/**\n * Converts pixels to points\n * @param pixels Value in pixels\n * @param dpi Dots per inch (default: 96)\n * @returns Value in points\n */\nexport function pixelsToPoints(pixels: number, dpi: number = STANDARD_DPI): number {\n return inchesToPoints(pixelsToInches(pixels, dpi));\n}\n\n// ============================================================================\n// Common Document Sizes (in twips)\n// ============================================================================\n\n/**\n * Common page sizes in twips\n */\nexport const PAGE_SIZES = {\n /** Letter (8.5\" x 11\") */\n LETTER: {\n width: 12240, // 8.5 inches\n height: 15840, // 11 inches\n },\n /** A4 (21cm x 29.7cm) */\n A4: {\n width: 11906, // 21cm\n height: 16838, // 29.7cm\n },\n /** Legal (8.5\" x 14\") */\n LEGAL: {\n width: 12240, // 8.5 inches\n height: 20160, // 14 inches\n },\n /** Tabloid (11\" x 17\") */\n TABLOID: {\n width: 15840, // 11 inches\n height: 24480, // 17 inches\n },\n /** A3 (29.7cm x 42cm) */\n A3: {\n width: 16838, // 29.7cm\n height: 23811, // 42cm\n },\n} as const;\n\n/**\n * Common margin sizes in twips\n */\nexport const COMMON_MARGINS = {\n /** Normal margins (1 inch all around) */\n NORMAL: {\n top: 1440,\n bottom: 1440,\n left: 1440,\n right: 1440,\n },\n /** Narrow margins (0.5 inch all around) */\n NARROW: {\n top: 720,\n bottom: 720,\n left: 720,\n right: 720,\n },\n /** Wide margins (2 inches left/right, 1 inch top/bottom) */\n WIDE: {\n top: 1440,\n bottom: 1440,\n left: 2880,\n right: 2880,\n },\n /** Moderate margins (1 inch top/bottom, 0.75 inch left/right) */\n MODERATE: {\n top: 1440,\n bottom: 1440,\n left: 1080,\n right: 1080,\n },\n} as const;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ/D;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ/D;AAgBD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUtD;AAmBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoClD;AAQD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAWxD;AAOD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAa/D;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAmBtE;AAmBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBpD;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAatE;AAKD,eAAO,MAAM,gBAAgB,sBAAgB,CAAC;AAQ9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAiB,GAAG,IAAI,CAcnF;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,EAAE,QAAQ,SAAI,GAAG,IAAI,CAQpF;AASD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,SAAc,GACtB,IAAI,CAQN;AASD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAc,GAAG,IAAI,CAkB5E;AAQD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAU,GAAG,IAAI,CAQ/E;AAQD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAe,GAAG,IAAI,CAQhF;AAUD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,IAAI,CAkBpE;AAKD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAaD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAuDpF;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAyBzE;AAaD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,oBAAoB,CA0BtB;AAKD,MAAM,WAAW,0BAA0B;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAeD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,0BAA0B,GAAG,IAAI,CAoCnF"}
|
package/dist/utils/validation.js
CHANGED
|
@@ -32,24 +32,13 @@ function validateDocxStructure(filePaths) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
function isBinaryFile(filePath) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
'.ico',
|
|
43
|
-
'.emf',
|
|
44
|
-
'.wmf',
|
|
45
|
-
'.bin',
|
|
46
|
-
'.dat',
|
|
47
|
-
'.ttf',
|
|
48
|
-
'.otf',
|
|
49
|
-
'.woff',
|
|
50
|
-
];
|
|
51
|
-
const extension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
|
|
52
|
-
return binaryExtensions.includes(extension);
|
|
35
|
+
const textExtensions = ['.xml', '.rels', '.svg', '.txt', '.html', '.css', '.js'];
|
|
36
|
+
const dotIndex = filePath.lastIndexOf('.');
|
|
37
|
+
if (dotIndex === -1) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const extension = filePath.substring(dotIndex).toLowerCase();
|
|
41
|
+
return !textExtensions.includes(extension);
|
|
53
42
|
}
|
|
54
43
|
function normalizePath(path) {
|
|
55
44
|
const normalized = path.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
@@ -68,10 +57,6 @@ function normalizePath(path) {
|
|
|
68
57
|
`Absolute paths are not allowed in DOCX archives. ` +
|
|
69
58
|
`Only relative paths within the archive are permitted.`);
|
|
70
59
|
}
|
|
71
|
-
if (path.startsWith('/') && normalized.startsWith('/')) {
|
|
72
|
-
throw new Error(`Invalid file path: "${path}" appears to be an absolute Unix path. ` +
|
|
73
|
-
`Only relative paths are allowed in DOCX archives.`);
|
|
74
|
-
}
|
|
75
60
|
return normalized;
|
|
76
61
|
}
|
|
77
62
|
function isValidZipBuffer(buffer) {
|
|
@@ -98,6 +83,9 @@ function validateTwips(value, fieldName = 'value') {
|
|
|
98
83
|
if (!Number.isFinite(value)) {
|
|
99
84
|
throw new Error(`${fieldName} must be a finite number, got ${value}`);
|
|
100
85
|
}
|
|
86
|
+
if (!Number.isInteger(value)) {
|
|
87
|
+
throw new Error(`${fieldName} must be an integer (in twips), got ${value}`);
|
|
88
|
+
}
|
|
101
89
|
const MIN_TWIPS = -31680;
|
|
102
90
|
const MAX_TWIPS = 31680;
|
|
103
91
|
if (value < MIN_TWIPS || value > MAX_TWIPS) {
|
|
@@ -166,7 +154,7 @@ function validateFontSize(size, fieldName = 'font size') {
|
|
|
166
154
|
throw new Error(`${fieldName} must be an integer (in half-points), got ${size}`);
|
|
167
155
|
}
|
|
168
156
|
const MIN_SIZE = 2;
|
|
169
|
-
const MAX_SIZE =
|
|
157
|
+
const MAX_SIZE = 3276;
|
|
170
158
|
if (size < MIN_SIZE || size > MAX_SIZE) {
|
|
171
159
|
throw new Error(`${fieldName} out of range: ${size} half-points (allowed: ${MIN_SIZE}-${MAX_SIZE}, or ${MIN_SIZE / 2}-${MAX_SIZE / 2} points)`);
|
|
172
160
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validation utilities for DOCX files\n */\n\nimport { REQUIRED_DOCX_FILES } from '../zip/types.js';\nimport { MissingRequiredFileError } from '../zip/errors.js';\nimport { defaultLogger } from './logger.js';\n\n/**\n * Validates that all required DOCX files are present\n * @param filePaths - Array of file paths in the archive\n * @throws {MissingRequiredFileError} If a required file is missing\n */\nexport function validateDocxStructure(filePaths: string[]): void {\n const fileSet = new Set(filePaths);\n\n for (const requiredFile of REQUIRED_DOCX_FILES) {\n if (!fileSet.has(requiredFile)) {\n throw new MissingRequiredFileError(requiredFile);\n }\n }\n}\n\n/**\n * Checks if a file path represents a binary file based on extension\n * @param filePath - The file path to check\n * @returns True if the file is likely binary\n */\nexport function isBinaryFile(filePath: string): boolean {\n const binaryExtensions = [\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.tiff',\n '.ico',\n '.emf',\n '.wmf',\n '.bin',\n '.dat',\n '.ttf',\n '.otf',\n '.woff',\n ];\n\n const extension = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();\n return binaryExtensions.includes(extension);\n}\n\n/**\n * Normalizes a file path for consistent comparisons\n * Converts backslashes to forward slashes and removes leading slashes\n * Also validates against path traversal attacks\n *\n * **Security:** This function validates paths to prevent:\n * - Path traversal attacks (../, ..\\, URL-encoded variants)\n * - Absolute paths (C:\\, /etc/, etc.)\n * - Malicious DOCX files attempting directory escape\n *\n * @param path - The path to normalize\n * @returns Normalized path\n * @throws {Error} If path contains path traversal sequences, absolute paths, or URL-encoded attacks\n */\nexport function normalizePath(path: string): string {\n // First convert all backslashes to forward slashes for consistent checking\n const normalized = path.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n\n // Security: Reject URL-encoded path traversal attempts\n // Attackers might try: %2e%2e%2f (%2e = . and %2f = /)\n if (/%2[eE]|%2[fF]|%5[cC]/.test(path)) {\n throw new Error(\n `Invalid file path: \"${path}\" contains URL-encoded characters (%2E, %2F, %5C). ` +\n `This could be an attempt to bypass path validation. ` +\n `Only plain characters are allowed in DOCX file paths.`\n );\n }\n\n // Security: Prevent path traversal attacks\n // Check AFTER normalization when all paths use forward slashes\n // This catches: ../, /.., or standalone \"..\"\n if (normalized.includes('../') || normalized.includes('/..') || normalized === '..') {\n throw new Error(\n `Invalid file path: \"${path}\" contains path traversal sequence (..). ` +\n `This could be a malicious DOCX file attempting directory traversal. ` +\n `DOCX archives must only contain relative paths within the archive.`\n );\n }\n\n // Security: Prevent absolute paths (Windows drive letters)\n // Examples: C:/, C:\\, D:, etc.\n if (/^[a-zA-Z]:/.test(normalized)) {\n throw new Error(\n `Invalid file path: \"${path}\" appears to be an absolute Windows path. ` +\n `Absolute paths are not allowed in DOCX archives. ` +\n `Only relative paths within the archive are permitted.`\n );\n }\n\n // Security: Prevent Unix absolute paths\n // After removing leading slashes, if it starts with / it's suspicious\n if (path.startsWith('/') && normalized.startsWith('/')) {\n throw new Error(\n `Invalid file path: \"${path}\" appears to be an absolute Unix path. ` +\n `Only relative paths are allowed in DOCX archives.`\n );\n }\n\n return normalized;\n}\n\n/**\n * Validates that a buffer contains a valid ZIP file signature\n * ZIP files start with the signature 'PK' (0x50 0x4B)\n * @param buffer - The buffer to validate\n * @returns True if the buffer appears to be a ZIP file\n */\nexport function isValidZipBuffer(buffer: Buffer): boolean {\n if (buffer.length < 4) {\n return false;\n }\n\n // Check for ZIP signature: PK\\x03\\x04 or PK\\x05\\x06 (for empty archives)\n return (\n buffer[0] === 0x50 &&\n buffer[1] === 0x4b &&\n ((buffer[2] === 0x03 && buffer[3] === 0x04) || (buffer[2] === 0x05 && buffer[3] === 0x06))\n );\n}\n\n/**\n * Checks if a string is valid UTF-8 text\n * @param content - The content to check\n * @returns True if the content is valid text\n */\nexport function isTextContent(content: Buffer | string): boolean {\n if (typeof content === 'string') {\n return true;\n }\n\n // Try to decode as UTF-8 and check for null bytes\n try {\n const text = content.toString('utf8');\n // Binary files often contain null bytes\n return !text.includes('\\0');\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a twips value (used for spacing, indentation, margins)\n * Twips: 1/20th of a point, 1440 twips = 1 inch\n * Reasonable range: -31680 to 31680 (±22 inches)\n * @param value - The twips value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateTwips(value: number, fieldName = 'value'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n // Reasonable range: ±22 inches (31680 twips)\n const MIN_TWIPS = -31680;\n const MAX_TWIPS = 31680;\n\n if (value < MIN_TWIPS || value > MAX_TWIPS) {\n throw new Error(\n `${fieldName} out of range: ${value} twips (allowed: ${MIN_TWIPS} to ${MAX_TWIPS}, ±22 inches)`\n );\n }\n}\n\n/**\n * Normalizes a color to uppercase 6-character hex format\n * Accepts 3-character or 6-character hex colors with or without '#' prefix\n * Follows Microsoft Word convention of uppercase hex colors\n *\n * @param color - Color to normalize (e.g., '#F00', 'FF0000', '#FF0000', 'f00')\n * @returns Normalized color (e.g., 'FF0000')\n * @throws Error if color format is invalid\n *\n * @example\n * ```typescript\n * normalizeColor('#F00') // Returns: 'FF0000'\n * normalizeColor('FF0000') // Returns: 'FF0000'\n * normalizeColor('#ff0000') // Returns: 'FF0000'\n * normalizeColor('f00') // Returns: 'FF0000'\n * ```\n */\nexport function normalizeColor(color: string): string {\n const hex = color.replace(/^#/, '');\n\n // Validate hex format\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(hex)) {\n throw new Error(\n `Invalid color format: \"${color}\". Expected 3 or 6-character hex ` +\n `(e.g., \"FF0000\", \"#FF0000\", \"F00\", or \"#F00\")`\n );\n }\n\n // Expand 3-character to 6-character\n if (hex.length === 3) {\n return (\n hex.charAt(0) +\n hex.charAt(0) +\n hex.charAt(1) +\n hex.charAt(1) +\n hex.charAt(2) +\n hex.charAt(2)\n ).toUpperCase();\n }\n\n return hex.toUpperCase();\n}\n\n/**\n * Validates a hexadecimal color value\n * Must be 6 characters (RRGGBB format)\n * @param color - The color hex string to validate (without #)\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the color is invalid\n */\nexport function validateColor(color: string, fieldName = 'color'): void {\n if (typeof color !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof color}`);\n }\n\n // Allow both with and without # prefix\n const cleanColor = color.startsWith('#') ? color.substring(1) : color;\n\n if (!/^[0-9A-Fa-f]{6}$/.test(cleanColor)) {\n throw new Error(\n `${fieldName} must be a 6-digit hex color (e.g., 'FF0000' or '#FF0000'), got '${color}'`\n );\n }\n}\n\n/**\n * Alias for validateColor for backwards compatibility\n */\nexport const validateHexColor = validateColor;\n\n/**\n * Validates a numbering ID (must be non-negative integer)\n * @param numId - The numbering ID to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the ID is invalid\n */\nexport function validateNumberingId(numId: number, fieldName = 'numbering ID'): void {\n if (!Number.isInteger(numId)) {\n throw new Error(`${fieldName} must be an integer, got ${numId}`);\n }\n\n if (numId < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${numId}`);\n }\n\n // Word supports numbering IDs up to 2147483647\n const MAX_NUM_ID = 2147483647;\n if (numId > MAX_NUM_ID) {\n throw new Error(`${fieldName} exceeds maximum value ${MAX_NUM_ID}, got ${numId}`);\n }\n}\n\n/**\n * Validates a numbering level (0-8 for Word)\n * @param level - The level to validate\n * @param fieldName - Name of the field (for error messages)\n * @param maxLevel - Maximum allowed level (default 8)\n * @throws {Error} If the level is invalid\n */\nexport function validateLevel(level: number, fieldName = 'level', maxLevel = 8): void {\n if (!Number.isInteger(level)) {\n throw new Error(`${fieldName} must be an integer, got ${level}`);\n }\n\n if (level < 0 || level > maxLevel) {\n throw new Error(`${fieldName} must be between 0 and ${maxLevel}, got ${level}`);\n }\n}\n\n/**\n * Validates an alignment value against allowed values\n * @param alignment - The alignment value to validate\n * @param allowed - Array of allowed alignment values\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the alignment is invalid\n */\nexport function validateAlignment(\n alignment: string,\n allowed: readonly string[],\n fieldName = 'alignment'\n): void {\n if (typeof alignment !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof alignment}`);\n }\n\n if (!allowed.includes(alignment)) {\n throw new Error(`Invalid ${fieldName}: '${alignment}' (allowed: ${allowed.join(', ')})`);\n }\n}\n\n/**\n * Validates a font size (in half-points for Word)\n * Reasonable range: 2-1638 (1-819 points)\n * @param size - The font size in half-points to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the size is invalid\n */\nexport function validateFontSize(size: number, fieldName = 'font size'): void {\n if (!Number.isFinite(size)) {\n throw new Error(`${fieldName} must be a finite number, got ${size}`);\n }\n\n if (!Number.isInteger(size)) {\n throw new Error(`${fieldName} must be an integer (in half-points), got ${size}`);\n }\n\n // Reasonable range: 2-1638 half-points (1-819 points)\n const MIN_SIZE = 2;\n const MAX_SIZE = 1638;\n\n if (size < MIN_SIZE || size > MAX_SIZE) {\n throw new Error(\n `${fieldName} out of range: ${size} half-points (allowed: ${MIN_SIZE}-${MAX_SIZE}, or ${MIN_SIZE / 2}-${MAX_SIZE / 2} points)`\n );\n }\n}\n\n/**\n * Validates that a string is not empty\n * @param value - The string to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the string is empty or not a string\n */\nexport function validateNonEmptyString(value: string, fieldName = 'value'): void {\n if (typeof value !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof value}`);\n }\n\n if (value.trim().length === 0) {\n throw new Error(`${fieldName} cannot be empty`);\n }\n}\n\n/**\n * Validates a percentage value (0-100)\n * @param value - The percentage to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the percentage is invalid\n */\nexport function validatePercentage(value: number, fieldName = 'percentage'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (value < 0 || value > 100) {\n throw new Error(`${fieldName} must be between 0 and 100, got ${value}`);\n }\n}\n\n/**\n * Validates EMUs (English Metric Units) value\n * Used for image dimensions: 914400 EMUs = 1 inch\n * Reasonable range: 0 to 50 million (about 55 inches)\n * @param value - The EMUs value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateEmus(value: number, fieldName = 'EMUs'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (!Number.isInteger(value)) {\n throw new Error(`${fieldName} must be an integer, got ${value}`);\n }\n\n if (value < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${value}`);\n }\n\n // Reasonable maximum: 50 million EMUs (about 55 inches)\n const MAX_EMUS = 50000000;\n if (value > MAX_EMUS) {\n throw new Error(`${fieldName} exceeds maximum ${MAX_EMUS} (about 55 inches), got ${value}`);\n }\n}\n\n/**\n * Result of text validation for XML-like content\n */\nexport interface TextValidationResult {\n isValid: boolean;\n hasXmlPatterns: boolean;\n warnings: string[];\n cleanedText?: string;\n}\n\n/**\n * Detects XML-like patterns in text that might cause display issues\n *\n * This function checks for patterns that look like XML markup which,\n * when properly escaped in XML output, will display as literal text\n * in Word documents rather than being interpreted as markup.\n *\n * @param text - The text to validate\n * @param context - Optional context for better warning messages (e.g., \"hyperlink text\")\n * @returns Validation result with warnings and optional cleaned text\n */\nexport function detectXmlInText(text: string, context?: string): TextValidationResult {\n const warnings: string[] = [];\n let hasXmlPatterns = false;\n\n // Check for common XML element patterns\n const xmlElementPattern = /<\\/?w:[^>]+>|<w:[^>]+\\/>/g;\n const escapedXmlPattern = /<.*?>|"|'/g;\n\n // Check for specific problematic patterns we've seen\n const problematicPatterns = [\n /<w:t\\s+xml:space=\"preserve\">/,\n /<w:t\\s+xml:space=[\"']preserve[\"']>/,\n /<\\/w:t>/,\n /<w:t\\s+xml:space="preserve">/,\n ];\n\n // Check for any XML-like tags\n if (xmlElementPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains XML-like markup: \"${text.substring(0, 100)}${text.length > 100 ? '...' : ''}\". ` +\n `This will be displayed as literal text in the document. ` +\n `If you intended to add formatting, use the appropriate API methods instead.`\n );\n }\n\n // Check for already-escaped XML entities\n if (escapedXmlPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains escaped XML entities (e.g., <, >, "). ` +\n `These will appear as literal characters in the document.`\n );\n }\n\n // Check for specific known problematic patterns\n for (const pattern of problematicPatterns) {\n if (pattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains a known problematic XML pattern that suggests ` +\n `the text may have been corrupted by previous processing.`\n );\n break;\n }\n }\n\n return {\n isValid: true, // Text is always \"valid\" - we just warn about potential issues\n hasXmlPatterns,\n warnings,\n };\n}\n\n/**\n * Cleans XML-like patterns from text\n *\n * This function removes or cleans various XML patterns that might\n * appear in text content, typically from corrupted or improperly\n * processed documents.\n *\n * @param text - The text to clean\n * @param aggressive - If true, removes all angle brackets; if false, only removes clear XML tags\n * @returns Cleaned text with XML patterns removed\n */\nexport function cleanXmlFromText(text: string, aggressive = false): string {\n let cleaned = text;\n\n // First, unescape any HTML/XML entities\n cleaned = cleaned\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/&/g, '&');\n\n // Remove specific Word XML patterns\n // This targets patterns like <w:t xml:space=\"preserve\">\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\n\n // Remove any remaining XML-like tags if aggressive mode\n if (aggressive) {\n cleaned = cleaned.replace(/<[^>]+>/g, '');\n }\n\n // Clean up any double spaces left behind\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n return cleaned;\n}\n\n/**\n * Validates text for use in Run or Hyperlink elements\n *\n * This is the main validation function that should be called when\n * setting text content in Run or Hyperlink elements. It provides\n * warnings about problematic content and optionally cleans the text.\n *\n * @param text - The text to validate\n * @param options - Validation options\n * @returns Validation result with warnings and optionally cleaned text\n */\nexport function validateRunText(\n text: string,\n options: {\n context?: string;\n autoClean?: boolean;\n aggressive?: boolean;\n warnToConsole?: boolean;\n } = {}\n): TextValidationResult {\n const { context, autoClean = false, aggressive = false, warnToConsole = true } = options;\n\n // Detect XML patterns\n const result = detectXmlInText(text, context);\n\n // If auto-cleaning is enabled and XML patterns were found\n if (autoClean && result.hasXmlPatterns) {\n result.cleanedText = cleanXmlFromText(text, aggressive);\n\n // Add a note about cleaning\n result.warnings.push(\n `Text has been automatically cleaned. ` +\n `Original: \"${text.substring(0, 50)}${text.length > 50 ? '...' : ''}\" ` +\n `Cleaned: \"${result.cleanedText.substring(0, 50)}${result.cleanedText.length > 50 ? '...' : ''}\"`\n );\n }\n\n // Log warnings to console in development if requested\n if (warnToConsole && result.warnings.length > 0 && typeof console !== 'undefined') {\n const contextStr = context ? ` [${context}]` : '';\n defaultLogger.warn(`DocXML Text Validation Warning${contextStr}:`);\n result.warnings.forEach((warning) => defaultLogger.warn(` - ${warning}`));\n }\n\n return result;\n}\n\n/**\n * Result of URL sanitization\n */\nexport interface SanitizeHyperlinkUrlResult {\n /** The sanitized URL */\n url: string;\n /** List of fixes that were applied */\n fixes: string[];\n}\n\n/**\n * Sanitizes hyperlink URLs by removing browser extension prefixes and fixing\n * broken protocols that result from the stripping.\n *\n * Known corruptions:\n * - Chrome extensions (e.g. Adobe Acrobat) wrap URLs with `chrome-extension://[id]/`\n * - Firefox extensions wrap URLs with `moz-extension://[uuid]/`\n * - Edge extensions wrap URLs with `extension://[id]/`\n * - After stripping, protocol may be broken (`https:/` instead of `https://`)\n *\n * @param url - The URL to sanitize\n * @returns Object with sanitized URL and list of fixes, or null if no changes needed\n */\nexport function sanitizeHyperlinkUrl(url: string): SanitizeHyperlinkUrlResult | null {\n if (!url) return null;\n\n const fixes: string[] = [];\n let sanitized = url;\n\n // Strip known browser extension URL prefixes\n const extensionPrefixes = [\n { pattern: /^chrome-extension:\\/\\/[a-z]{32}\\//i, name: 'Chrome extension' },\n {\n pattern: /^moz-extension:\\/\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\//i,\n name: 'Firefox extension',\n },\n { pattern: /^extension:\\/\\/[a-z0-9]{32}\\//i, name: 'Edge extension' },\n ];\n\n for (const { pattern, name } of extensionPrefixes) {\n const match = pattern.exec(sanitized);\n if (match) {\n sanitized = sanitized.substring(match[0].length);\n fixes.push(`Stripped ${name} URL prefix`);\n break;\n }\n }\n\n // Fix broken protocol after stripping (https:/ -> https://, http:/ -> http://)\n const brokenProtocol = /^(https?:\\/)([^/])/i.exec(sanitized);\n if (brokenProtocol) {\n sanitized =\n brokenProtocol[1] + '/' + brokenProtocol[2] + sanitized.substring(brokenProtocol[0].length);\n fixes.push('Fixed broken protocol (added missing slash)');\n }\n\n if (fixes.length === 0) return null;\n\n return { url: sanitized, fixes };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validation utilities for DOCX files\n */\n\nimport { REQUIRED_DOCX_FILES } from '../zip/types.js';\nimport { MissingRequiredFileError } from '../zip/errors.js';\nimport { defaultLogger } from './logger.js';\n\n/**\n * Validates that all required DOCX files are present\n * @param filePaths - Array of file paths in the archive\n * @throws {MissingRequiredFileError} If a required file is missing\n */\nexport function validateDocxStructure(filePaths: string[]): void {\n const fileSet = new Set(filePaths);\n\n for (const requiredFile of REQUIRED_DOCX_FILES) {\n if (!fileSet.has(requiredFile)) {\n throw new MissingRequiredFileError(requiredFile);\n }\n }\n}\n\n/**\n * Checks if a file path represents a binary file based on extension\n *\n * Uses a text-extension whitelist rather than a binary-extension whitelist:\n * misclassifying text as binary only changes its in-memory representation\n * (Buffer instead of string), but misclassifying binary as text corrupts the\n * bytes through a lossy UTF-8 decode. OOXML packages can embed arbitrary\n * binary parts (.xlsx/.pdf OLE packages, .odttf obfuscated fonts, .emz/.wmz\n * compressed metafiles, extensionless parts), so anything not known to be\n * text must be preserved byte-for-byte.\n *\n * @param filePath - The file path to check\n * @returns True if the file is likely binary\n */\nexport function isBinaryFile(filePath: string): boolean {\n const textExtensions = ['.xml', '.rels', '.svg', '.txt', '.html', '.css', '.js'];\n\n const dotIndex = filePath.lastIndexOf('.');\n if (dotIndex === -1) {\n return true;\n }\n\n const extension = filePath.substring(dotIndex).toLowerCase();\n return !textExtensions.includes(extension);\n}\n\n/**\n * Normalizes a file path for consistent comparisons\n * Converts backslashes to forward slashes and removes leading slashes\n * Also validates against path traversal attacks\n *\n * **Security:** This function validates paths to prevent:\n * - Path traversal attacks (../, ..\\, URL-encoded variants)\n * - Absolute Windows paths (C:\\, D:, etc.) — rejected\n * - Malicious DOCX files attempting directory escape\n *\n * Unix absolute paths (/etc/...) are sanitized to archive-relative paths\n * by stripping leading slashes, not rejected.\n *\n * @param path - The path to normalize\n * @returns Normalized path\n * @throws {Error} If path contains path traversal sequences, absolute Windows paths, or URL-encoded attacks\n */\nexport function normalizePath(path: string): string {\n // First convert all backslashes to forward slashes for consistent checking\n const normalized = path.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n\n // Security: Reject URL-encoded path traversal attempts\n // Attackers might try: %2e%2e%2f (%2e = . and %2f = /)\n if (/%2[eE]|%2[fF]|%5[cC]/.test(path)) {\n throw new Error(\n `Invalid file path: \"${path}\" contains URL-encoded characters (%2E, %2F, %5C). ` +\n `This could be an attempt to bypass path validation. ` +\n `Only plain characters are allowed in DOCX file paths.`\n );\n }\n\n // Security: Prevent path traversal attacks\n // Check AFTER normalization when all paths use forward slashes\n // This catches: ../, /.., or standalone \"..\"\n if (normalized.includes('../') || normalized.includes('/..') || normalized === '..') {\n throw new Error(\n `Invalid file path: \"${path}\" contains path traversal sequence (..). ` +\n `This could be a malicious DOCX file attempting directory traversal. ` +\n `DOCX archives must only contain relative paths within the archive.`\n );\n }\n\n // Security: Prevent absolute paths (Windows drive letters)\n // Examples: C:/, C:\\, D:, etc.\n if (/^[a-zA-Z]:/.test(normalized)) {\n throw new Error(\n `Invalid file path: \"${path}\" appears to be an absolute Windows path. ` +\n `Absolute paths are not allowed in DOCX archives. ` +\n `Only relative paths within the archive are permitted.`\n );\n }\n\n return normalized;\n}\n\n/**\n * Validates that a buffer contains a valid ZIP file signature\n * ZIP files start with the signature 'PK' (0x50 0x4B)\n * @param buffer - The buffer to validate\n * @returns True if the buffer appears to be a ZIP file\n */\nexport function isValidZipBuffer(buffer: Buffer): boolean {\n if (buffer.length < 4) {\n return false;\n }\n\n // Check for ZIP signature: PK\\x03\\x04 or PK\\x05\\x06 (for empty archives)\n return (\n buffer[0] === 0x50 &&\n buffer[1] === 0x4b &&\n ((buffer[2] === 0x03 && buffer[3] === 0x04) || (buffer[2] === 0x05 && buffer[3] === 0x06))\n );\n}\n\n/**\n * Checks if a string is valid UTF-8 text\n * @param content - The content to check\n * @returns True if the content is valid text\n */\nexport function isTextContent(content: Buffer | string): boolean {\n if (typeof content === 'string') {\n return true;\n }\n\n // Try to decode as UTF-8 and check for null bytes\n try {\n const text = content.toString('utf8');\n // Binary files often contain null bytes\n return !text.includes('\\0');\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a twips value (used for spacing, indentation, margins)\n * Twips: 1/20th of a point, 1440 twips = 1 inch\n * Reasonable range: -31680 to 31680 (±22 inches)\n * @param value - The twips value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateTwips(value: number, fieldName = 'value'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n // ST_TwipsMeasure/ST_SignedTwipsMeasure are ST_DecimalNumber-based — integers only\n if (!Number.isInteger(value)) {\n throw new Error(`${fieldName} must be an integer (in twips), got ${value}`);\n }\n\n // Reasonable range: ±22 inches (31680 twips)\n const MIN_TWIPS = -31680;\n const MAX_TWIPS = 31680;\n\n if (value < MIN_TWIPS || value > MAX_TWIPS) {\n throw new Error(\n `${fieldName} out of range: ${value} twips (allowed: ${MIN_TWIPS} to ${MAX_TWIPS}, ±22 inches)`\n );\n }\n}\n\n/**\n * Normalizes a color to uppercase 6-character hex format\n * Accepts 3-character or 6-character hex colors with or without '#' prefix\n * Follows Microsoft Word convention of uppercase hex colors\n *\n * @param color - Color to normalize (e.g., '#F00', 'FF0000', '#FF0000', 'f00')\n * @returns Normalized color (e.g., 'FF0000')\n * @throws Error if color format is invalid\n *\n * @example\n * ```typescript\n * normalizeColor('#F00') // Returns: 'FF0000'\n * normalizeColor('FF0000') // Returns: 'FF0000'\n * normalizeColor('#ff0000') // Returns: 'FF0000'\n * normalizeColor('f00') // Returns: 'FF0000'\n * ```\n */\nexport function normalizeColor(color: string): string {\n const hex = color.replace(/^#/, '');\n\n // Validate hex format\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(hex)) {\n throw new Error(\n `Invalid color format: \"${color}\". Expected 3 or 6-character hex ` +\n `(e.g., \"FF0000\", \"#FF0000\", \"F00\", or \"#F00\")`\n );\n }\n\n // Expand 3-character to 6-character\n if (hex.length === 3) {\n return (\n hex.charAt(0) +\n hex.charAt(0) +\n hex.charAt(1) +\n hex.charAt(1) +\n hex.charAt(2) +\n hex.charAt(2)\n ).toUpperCase();\n }\n\n return hex.toUpperCase();\n}\n\n/**\n * Validates a hexadecimal color value\n * Must be 6 characters (RRGGBB format)\n * @param color - The color hex string to validate (without #)\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the color is invalid\n */\nexport function validateColor(color: string, fieldName = 'color'): void {\n if (typeof color !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof color}`);\n }\n\n // Allow both with and without # prefix\n const cleanColor = color.startsWith('#') ? color.substring(1) : color;\n\n if (!/^[0-9A-Fa-f]{6}$/.test(cleanColor)) {\n throw new Error(\n `${fieldName} must be a 6-digit hex color (e.g., 'FF0000' or '#FF0000'), got '${color}'`\n );\n }\n}\n\n/**\n * Alias for validateColor for backwards compatibility\n */\nexport const validateHexColor = validateColor;\n\n/**\n * Validates a numbering ID (must be non-negative integer)\n * @param numId - The numbering ID to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the ID is invalid\n */\nexport function validateNumberingId(numId: number, fieldName = 'numbering ID'): void {\n if (!Number.isInteger(numId)) {\n throw new Error(`${fieldName} must be an integer, got ${numId}`);\n }\n\n if (numId < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${numId}`);\n }\n\n // Word supports numbering IDs up to 2147483647\n const MAX_NUM_ID = 2147483647;\n if (numId > MAX_NUM_ID) {\n throw new Error(`${fieldName} exceeds maximum value ${MAX_NUM_ID}, got ${numId}`);\n }\n}\n\n/**\n * Validates a numbering level (0-8 for Word)\n * @param level - The level to validate\n * @param fieldName - Name of the field (for error messages)\n * @param maxLevel - Maximum allowed level (default 8)\n * @throws {Error} If the level is invalid\n */\nexport function validateLevel(level: number, fieldName = 'level', maxLevel = 8): void {\n if (!Number.isInteger(level)) {\n throw new Error(`${fieldName} must be an integer, got ${level}`);\n }\n\n if (level < 0 || level > maxLevel) {\n throw new Error(`${fieldName} must be between 0 and ${maxLevel}, got ${level}`);\n }\n}\n\n/**\n * Validates an alignment value against allowed values\n * @param alignment - The alignment value to validate\n * @param allowed - Array of allowed alignment values\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the alignment is invalid\n */\nexport function validateAlignment(\n alignment: string,\n allowed: readonly string[],\n fieldName = 'alignment'\n): void {\n if (typeof alignment !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof alignment}`);\n }\n\n if (!allowed.includes(alignment)) {\n throw new Error(`Invalid ${fieldName}: '${alignment}' (allowed: ${allowed.join(', ')})`);\n }\n}\n\n/**\n * Validates a font size (in half-points for Word)\n * Reasonable range: 2-3276 (1-1638 points)\n * @param size - The font size in half-points to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the size is invalid\n */\nexport function validateFontSize(size: number, fieldName = 'font size'): void {\n if (!Number.isFinite(size)) {\n throw new Error(`${fieldName} must be a finite number, got ${size}`);\n }\n\n if (!Number.isInteger(size)) {\n throw new Error(`${fieldName} must be an integer (in half-points), got ${size}`);\n }\n\n // Word's limit is 1-1638 points, i.e. 2-3276 half-points for w:sz (ST_HpsMeasure)\n const MIN_SIZE = 2;\n const MAX_SIZE = 3276;\n\n if (size < MIN_SIZE || size > MAX_SIZE) {\n throw new Error(\n `${fieldName} out of range: ${size} half-points (allowed: ${MIN_SIZE}-${MAX_SIZE}, or ${MIN_SIZE / 2}-${MAX_SIZE / 2} points)`\n );\n }\n}\n\n/**\n * Validates that a string is not empty\n * @param value - The string to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the string is empty or not a string\n */\nexport function validateNonEmptyString(value: string, fieldName = 'value'): void {\n if (typeof value !== 'string') {\n throw new Error(`${fieldName} must be a string, got ${typeof value}`);\n }\n\n if (value.trim().length === 0) {\n throw new Error(`${fieldName} cannot be empty`);\n }\n}\n\n/**\n * Validates a percentage value (0-100)\n * @param value - The percentage to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the percentage is invalid\n */\nexport function validatePercentage(value: number, fieldName = 'percentage'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (value < 0 || value > 100) {\n throw new Error(`${fieldName} must be between 0 and 100, got ${value}`);\n }\n}\n\n/**\n * Validates EMUs (English Metric Units) value\n * Used for image dimensions: 914400 EMUs = 1 inch\n * Reasonable range: 0 to 50 million (about 55 inches)\n * @param value - The EMUs value to validate\n * @param fieldName - Name of the field (for error messages)\n * @throws {Error} If the value is invalid\n */\nexport function validateEmus(value: number, fieldName = 'EMUs'): void {\n if (!Number.isFinite(value)) {\n throw new Error(`${fieldName} must be a finite number, got ${value}`);\n }\n\n if (!Number.isInteger(value)) {\n throw new Error(`${fieldName} must be an integer, got ${value}`);\n }\n\n if (value < 0) {\n throw new Error(`${fieldName} must be non-negative, got ${value}`);\n }\n\n // Reasonable maximum: 50 million EMUs (about 55 inches)\n const MAX_EMUS = 50000000;\n if (value > MAX_EMUS) {\n throw new Error(`${fieldName} exceeds maximum ${MAX_EMUS} (about 55 inches), got ${value}`);\n }\n}\n\n/**\n * Result of text validation for XML-like content\n */\nexport interface TextValidationResult {\n isValid: boolean;\n hasXmlPatterns: boolean;\n warnings: string[];\n cleanedText?: string;\n}\n\n/**\n * Detects XML-like patterns in text that might cause display issues\n *\n * This function checks for patterns that look like XML markup which,\n * when properly escaped in XML output, will display as literal text\n * in Word documents rather than being interpreted as markup.\n *\n * @param text - The text to validate\n * @param context - Optional context for better warning messages (e.g., \"hyperlink text\")\n * @returns Validation result with warnings and optional cleaned text\n */\nexport function detectXmlInText(text: string, context?: string): TextValidationResult {\n const warnings: string[] = [];\n let hasXmlPatterns = false;\n\n // Check for common XML element patterns\n const xmlElementPattern = /<\\/?w:[^>]+>|<w:[^>]+\\/>/g;\n const escapedXmlPattern = /<.*?>|"|'/g;\n\n // Check for specific problematic patterns we've seen\n const problematicPatterns = [\n /<w:t\\s+xml:space=\"preserve\">/,\n /<w:t\\s+xml:space=[\"']preserve[\"']>/,\n /<\\/w:t>/,\n /<w:t\\s+xml:space="preserve">/,\n ];\n\n // Check for any XML-like tags\n if (xmlElementPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains XML-like markup: \"${text.substring(0, 100)}${text.length > 100 ? '...' : ''}\". ` +\n `This will be displayed as literal text in the document. ` +\n `If you intended to add formatting, use the appropriate API methods instead.`\n );\n }\n\n // Check for already-escaped XML entities\n if (escapedXmlPattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains escaped XML entities (e.g., <, >, "). ` +\n `These will appear as literal characters in the document.`\n );\n }\n\n // Check for specific known problematic patterns\n for (const pattern of problematicPatterns) {\n if (pattern.test(text)) {\n hasXmlPatterns = true;\n const contextStr = context ? ` in ${context}` : '';\n warnings.push(\n `Text${contextStr} contains a known problematic XML pattern that suggests ` +\n `the text may have been corrupted by previous processing.`\n );\n break;\n }\n }\n\n return {\n isValid: true, // Text is always \"valid\" - we just warn about potential issues\n hasXmlPatterns,\n warnings,\n };\n}\n\n/**\n * Cleans XML-like patterns from text\n *\n * This function removes or cleans various XML patterns that might\n * appear in text content, typically from corrupted or improperly\n * processed documents.\n *\n * @param text - The text to clean\n * @param aggressive - If true, removes all angle brackets; if false, only removes clear XML tags\n * @returns Cleaned text with XML patterns removed\n */\nexport function cleanXmlFromText(text: string, aggressive = false): string {\n let cleaned = text;\n\n // First, unescape any HTML/XML entities\n cleaned = cleaned\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/&/g, '&');\n\n // Remove specific Word XML patterns\n // This targets patterns like <w:t xml:space=\"preserve\">\n cleaned = cleaned.replace(/<w:[^>]+>/g, '');\n cleaned = cleaned.replace(/<\\/w:[^>]+>/g, '');\n\n // Remove any remaining XML-like tags if aggressive mode\n if (aggressive) {\n cleaned = cleaned.replace(/<[^>]+>/g, '');\n }\n\n // Clean up any double spaces left behind\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n return cleaned;\n}\n\n/**\n * Validates text for use in Run or Hyperlink elements\n *\n * This is the main validation function that should be called when\n * setting text content in Run or Hyperlink elements. It provides\n * warnings about problematic content and optionally cleans the text.\n *\n * @param text - The text to validate\n * @param options - Validation options\n * @returns Validation result with warnings and optionally cleaned text\n */\nexport function validateRunText(\n text: string,\n options: {\n context?: string;\n autoClean?: boolean;\n aggressive?: boolean;\n warnToConsole?: boolean;\n } = {}\n): TextValidationResult {\n const { context, autoClean = false, aggressive = false, warnToConsole = true } = options;\n\n // Detect XML patterns\n const result = detectXmlInText(text, context);\n\n // If auto-cleaning is enabled and XML patterns were found\n if (autoClean && result.hasXmlPatterns) {\n result.cleanedText = cleanXmlFromText(text, aggressive);\n\n // Add a note about cleaning\n result.warnings.push(\n `Text has been automatically cleaned. ` +\n `Original: \"${text.substring(0, 50)}${text.length > 50 ? '...' : ''}\" ` +\n `Cleaned: \"${result.cleanedText.substring(0, 50)}${result.cleanedText.length > 50 ? '...' : ''}\"`\n );\n }\n\n // Log warnings to console in development if requested\n if (warnToConsole && result.warnings.length > 0 && typeof console !== 'undefined') {\n const contextStr = context ? ` [${context}]` : '';\n defaultLogger.warn(`DocXML Text Validation Warning${contextStr}:`);\n result.warnings.forEach((warning) => defaultLogger.warn(` - ${warning}`));\n }\n\n return result;\n}\n\n/**\n * Result of URL sanitization\n */\nexport interface SanitizeHyperlinkUrlResult {\n /** The sanitized URL */\n url: string;\n /** List of fixes that were applied */\n fixes: string[];\n}\n\n/**\n * Sanitizes hyperlink URLs by removing browser extension prefixes and fixing\n * broken protocols that result from the stripping.\n *\n * Known corruptions:\n * - Chrome extensions (e.g. Adobe Acrobat) wrap URLs with `chrome-extension://[id]/`\n * - Firefox extensions wrap URLs with `moz-extension://[uuid]/`\n * - Edge extensions wrap URLs with `extension://[id]/`\n * - After stripping, protocol may be broken (`https:/` instead of `https://`)\n *\n * @param url - The URL to sanitize\n * @returns Object with sanitized URL and list of fixes, or null if no changes needed\n */\nexport function sanitizeHyperlinkUrl(url: string): SanitizeHyperlinkUrlResult | null {\n if (!url) return null;\n\n const fixes: string[] = [];\n let sanitized = url;\n\n // Strip known browser extension URL prefixes\n const extensionPrefixes = [\n { pattern: /^chrome-extension:\\/\\/[a-z]{32}\\//i, name: 'Chrome extension' },\n {\n pattern: /^moz-extension:\\/\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\//i,\n name: 'Firefox extension',\n },\n { pattern: /^extension:\\/\\/[a-z0-9]{32}\\//i, name: 'Edge extension' },\n ];\n\n for (const { pattern, name } of extensionPrefixes) {\n const match = pattern.exec(sanitized);\n if (match) {\n sanitized = sanitized.substring(match[0].length);\n fixes.push(`Stripped ${name} URL prefix`);\n break;\n }\n }\n\n // Fix broken protocol after stripping (https:/ -> https://, http:/ -> http://)\n const brokenProtocol = /^(https?:\\/)([^/])/i.exec(sanitized);\n if (brokenProtocol) {\n sanitized =\n brokenProtocol[1] + '/' + brokenProtocol[2] + sanitized.substring(brokenProtocol[0].length);\n fixes.push('Fixed broken protocol (added missing slash)');\n }\n\n if (fixes.length === 0) return null;\n\n return { url: sanitized, fixes };\n}\n"]}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare function removeInvalidXmlChars(text: string, logWarning?: boolean): string;
|
|
2
2
|
export declare function findInvalidXmlChars(text: string): number[];
|
|
3
3
|
export declare function hasInvalidXmlChars(text: string): boolean;
|
|
4
|
+
export declare function reorderRunPropertyChildren(xml: string): string;
|
|
5
|
+
export declare function normalizeAnchorSizeRel(xml: string): string;
|
|
4
6
|
export declare const XML_CONTROL_CHARS: {
|
|
5
7
|
readonly NULL: 0;
|
|
6
8
|
readonly SOH: 1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xmlSanitization.d.ts","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"xmlSanitization.d.ts","sourceRoot":"","sources":["../../src/utils/xmlSanitization.ts"],"names":[],"mappings":"AAuEA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,MAAM,CAqB7E;AAqBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAkC1D;AAkBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAyGD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA2B9D;AAeD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB1D;AAKD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAmCpB,CAAC"}
|