docxmlater 10.2.2 → 10.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +9 -0
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +44 -0
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/elements/Field.d.ts +9 -0
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +117 -4
- package/dist/elements/Field.js.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/utils/InMemoryRevisionAcceptor.js +24 -4
- package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
- package/package.json +1 -1
- package/src/core/Document.ts +13 -0
- package/src/core/DocumentParser.ts +50 -1
- package/src/elements/Field.ts +165 -7
- package/src/utils/InMemoryRevisionAcceptor.ts +31 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * InMemoryRevisionAcceptor - Accept revisions by transforming the in-memory object model\n *\n * This approach follows the industry standard (OpenXML PowerTools, Aspose.Words):\n * - Transforms Revision objects in paragraph.content[] to their \"accepted\" state\n * - For insertions: Unwrap - extract child Runs/Hyperlinks into parent paragraph\n * - For deletions: Remove - delete the revision and its content from the model\n * - For property changes: Remove the change metadata, keep the current formatting\n *\n * Unlike the raw XML approach (acceptRevisions.ts), this allows subsequent modifications\n * to the in-memory model to be correctly serialized on save().\n *\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\n * @see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/ee836138(v=office.12)\n */\n\nimport type { Document } from '../core/Document';\nimport { Paragraph } from '../elements/Paragraph';\nimport type { ParagraphContent } from '../elements/Paragraph';\nimport { Revision, RevisionType } from '../elements/Revision';\nimport type { Run } from '../elements/Run';\nimport type { Hyperlink } from '../elements/Hyperlink';\nimport { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';\nimport type { ImageRun } from '../elements/ImageRun';\nimport { ComplexField } from '../elements/Field';\nimport { Table } from '../elements/Table';\nimport { Section } from '../elements/Section';\nimport { getGlobalLogger, createScopedLogger, ILogger } from './logger';\n\n/**\n * Get scoped logger for this module\n */\nfunction getLogger(): ILogger {\n return createScopedLogger(getGlobalLogger(), 'InMemoryRevisionAcceptor');\n}\n\n/**\n * Options for accepting revisions\n */\nexport interface AcceptRevisionsOptions {\n /** Accept insertion revisions (w:ins) - default: true */\n acceptInsertions?: boolean;\n /** Accept deletion revisions (w:del) - default: true */\n acceptDeletions?: boolean;\n /** Accept move operations (w:moveFrom, w:moveTo) - default: true */\n acceptMoves?: boolean;\n /** Accept property change revisions (rPrChange, pPrChange, etc.) - default: true */\n acceptPropertyChanges?: boolean;\n /** Remove empty tables after revision acceptance - default: true */\n cleanupEmptyTables?: boolean;\n}\n\n/**\n * Result of accepting revisions\n */\nexport interface AcceptRevisionsResult {\n /** Number of insertions accepted */\n insertionsAccepted: number;\n /** Number of deletions accepted */\n deletionsAccepted: number;\n /** Number of move operations accepted */\n movesAccepted: number;\n /** Number of property changes accepted */\n propertyChangesAccepted: number;\n /** Total revisions processed */\n totalAccepted: number;\n /** Number of empty tables removed during cleanup */\n emptyTablesRemoved: number;\n}\n\n/**\n * Revision types that represent content changes (contain actual text/runs)\n */\nconst CONTENT_REVISION_TYPES: RevisionType[] = ['insert', 'delete', 'moveFrom', 'moveTo'];\n\n/**\n * Revision types that represent property/formatting changes\n */\nconst PROPERTY_REVISION_TYPES: RevisionType[] = [\n 'runPropertiesChange',\n 'paragraphPropertiesChange',\n 'tablePropertiesChange',\n 'tableExceptionPropertiesChange',\n 'tableRowPropertiesChange',\n 'tableCellPropertiesChange',\n 'sectionPropertiesChange',\n 'numberingChange',\n];\n\n/**\n * Strip revision markup from raw XML string.\n * Used for nested tables stored as raw XML that cannot be processed via the in-memory model.\n *\n * Follows the same rules as the main revision acceptor:\n * - Insertions: Keep content, remove wrapper tags\n * - Deletions: Remove entirely (content and tags)\n * - MoveFrom: Remove entirely (source of move)\n * - MoveTo: Keep content, remove wrapper\n * - Property changes: Remove change tracking elements\n * - Range markers: Remove boundary markers\n *\n * @param xml - Raw XML string containing revision markup\n * @returns Cleaned XML with revisions accepted\n */\nexport function stripRevisionsFromXml(xml: string): string {\n let result = xml;\n\n // Step 1: Remove range markers (must be done first)\n const rangePatterns = [\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\n ];\n for (const pattern of rangePatterns) {\n result = result.replace(pattern, '');\n }\n\n // Step 2: Remove property change elements\n const propChangePatterns = [\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\n ];\n for (const pattern of propChangePatterns) {\n result = result.replace(pattern, '');\n }\n\n // Step 3: Remove deletions entirely (including content)\n // Iterate until no more deletions (handles nested cases)\n let prevLen = 0;\n while (result.length !== prevLen) {\n prevLen = result.length;\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\n }\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n\n // Step 4: Remove moveFrom entirely (source of moved content)\n prevLen = 0;\n while (result.length !== prevLen) {\n prevLen = result.length;\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\n }\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n\n // Step 5: Unwrap moveTo (keep content, remove wrapper)\n result = result.replace(/<\\/w:moveTo>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\n\n // Step 6: Unwrap insertions (keep content, remove wrapper)\n result = result.replace(/<\\/w:ins>/g, '');\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\n\n // Step 7: Clean up orphaned tags\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\n\n return result;\n}\n\n/**\n * Accept all revisions in the document by transforming the in-memory model.\n *\n * This is the industry-standard approach used by OpenXML PowerTools, Aspose.Words,\n * and other production DOCX libraries. It allows subsequent modifications to the\n * document to work correctly.\n *\n * @param doc - Document to process\n * @param options - Options for which revision types to accept\n * @returns Result with counts of accepted revisions\n */\nexport function acceptRevisionsInMemory(\n doc: Document,\n options: AcceptRevisionsOptions = {}\n): AcceptRevisionsResult {\n const logger = getLogger();\n const opts: Required<AcceptRevisionsOptions> = {\n acceptInsertions: options.acceptInsertions ?? true,\n acceptDeletions: options.acceptDeletions ?? true,\n acceptMoves: options.acceptMoves ?? true,\n acceptPropertyChanges: options.acceptPropertyChanges ?? true,\n cleanupEmptyTables: options.cleanupEmptyTables ?? true,\n };\n\n const result: AcceptRevisionsResult = {\n insertionsAccepted: 0,\n deletionsAccepted: 0,\n movesAccepted: 0,\n propertyChangesAccepted: 0,\n totalAccepted: 0,\n emptyTablesRemoved: 0,\n };\n\n logger.info('Accepting revisions in-memory', { options: opts });\n\n // Validate move pairs before accepting if moves are being accepted\n // Orphaned moves could result in content loss (moveFrom without moveTo = content deleted)\n if (opts.acceptMoves) {\n const revisionManager = doc.getRevisionManager();\n if (revisionManager) {\n const movePairValidation = revisionManager.validateMovePairs();\n if (!movePairValidation.valid) {\n if (movePairValidation.orphanedMoveFrom.length > 0) {\n logger.warn(\n 'Orphaned moveFrom revisions detected - accepting these will DELETE content permanently ' +\n '(content was moved from here but no moveTo destination exists)',\n { orphanedMoveIds: movePairValidation.orphanedMoveFrom }\n );\n }\n if (movePairValidation.orphanedMoveTo.length > 0) {\n logger.warn(\n 'Orphaned moveTo revisions detected - content may be duplicated ' +\n '(content moved to here but no moveFrom source exists)',\n { orphanedMoveIds: movePairValidation.orphanedMoveTo }\n );\n }\n }\n }\n }\n\n // Process all paragraphs in the document body\n const paragraphs = doc.getAllParagraphs();\n for (const paragraph of paragraphs) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n\n // Process paragraphs in tables and clear table/row/cell property changes\n const tables = doc.getTables();\n for (const table of tables) {\n // Clear tblPrChange on table\n if (opts.acceptPropertyChanges && table.getTblPrChange()) {\n table.clearTblPrChange();\n result.propertyChangesAccepted++;\n }\n\n for (const row of table.getRows()) {\n // Clear trPrChange on row\n if (opts.acceptPropertyChanges && row.getTrPrChange()) {\n row.clearTrPrChange();\n result.propertyChangesAccepted++;\n }\n\n for (const cell of row.getCells()) {\n // Clear tcPrChange on cell\n if (opts.acceptPropertyChanges && cell.getTcPrChange()) {\n cell.clearTcPrChange();\n result.propertyChangesAccepted++;\n }\n\n // Clear cell structural revision markers (cellIns/cellDel/cellMerge)\n if (opts.acceptPropertyChanges && cell.getCellRevision()) {\n cell.clearCellRevision();\n result.propertyChangesAccepted++;\n }\n\n // Process paragraphs in the cell\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n\n // Process raw nested content (nested tables stored as XML)\n // These cannot be processed via the in-memory model, so we use XML-based stripping\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n // Count revisions stripped from nested content\n // We can't distinguish types in raw XML, so count as property changes\n result.propertyChangesAccepted++;\n logger.debug('Stripped revisions from nested content', {\n type: item.type,\n position: item.position,\n originalLength: item.xml.length,\n cleanedLength: cleanedXml.length,\n });\n }\n }\n }\n }\n }\n }\n }\n\n // Process paragraphs in headers\n const headerFooterManager = doc.getHeaderFooterManager();\n if (headerFooterManager) {\n const headers = headerFooterManager.getAllHeaders();\n for (const headerEntry of headers) {\n const elements = headerEntry.header.getElements();\n for (const element of elements) {\n // Element can be Paragraph or Table - use instanceof for type safety\n if (element instanceof Paragraph) {\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n } else if (element instanceof Table) {\n // It's a Table - process its cells\n for (const row of element.getRows()) {\n for (const cell of row.getCells()) {\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n // Process raw nested content in header tables\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n result.propertyChangesAccepted++;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Process paragraphs in footers\n const footers = headerFooterManager.getAllFooters();\n for (const footerEntry of footers) {\n const elements = footerEntry.footer.getElements();\n for (const element of elements) {\n // Element can be Paragraph or Table - use instanceof for type safety\n if (element instanceof Paragraph) {\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n } else if (element instanceof Table) {\n // It's a Table - process its cells\n for (const row of element.getRows()) {\n for (const cell of row.getCells()) {\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n // Process raw nested content in footer tables\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n result.propertyChangesAccepted++;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Clear sectPrChange on document section\n if (opts.acceptPropertyChanges) {\n const section = doc.getSection();\n if (section?.getSectPrChange()) {\n section.clearSectPrChange();\n result.propertyChangesAccepted++;\n }\n }\n\n // Clear revision manager\n const revisionManager = doc.getRevisionManager();\n if (revisionManager) {\n revisionManager.clear();\n }\n\n // Disable track changes setting\n doc.disableTrackChanges();\n\n // Cleanup empty tables if enabled\n // This removes tables that have no visible content after revision acceptance\n // (e.g., tables where all content was deleted via tracked changes)\n if (opts.cleanupEmptyTables) {\n result.emptyTablesRemoved = cleanupEmptyTables(doc, logger);\n }\n\n result.totalAccepted =\n result.insertionsAccepted +\n result.deletionsAccepted +\n result.movesAccepted +\n result.propertyChangesAccepted;\n\n logger.info('Revisions accepted in-memory', {\n insertions: result.insertionsAccepted,\n deletions: result.deletionsAccepted,\n moves: result.movesAccepted,\n propertyChanges: result.propertyChangesAccepted,\n total: result.totalAccepted,\n emptyTablesRemoved: result.emptyTablesRemoved,\n });\n\n return result;\n}\n\n/**\n * Accept revisions in a single paragraph by transforming its content array.\n *\n * The transformation follows these rules:\n * - Insertions (w:ins): Unwrap - extract child content into parent position\n * - Deletions (w:del): Remove - delete revision and its content\n * - MoveFrom (w:moveFrom): Remove - content exists at moveTo destination\n * - MoveTo (w:moveTo): Unwrap - keep content, remove wrapper\n * - Property changes: Remove from model (current formatting is kept)\n *\n * @param paragraph - Paragraph to process\n * @param options - Options for which revision types to accept\n * @returns Result with counts of accepted revisions\n */\nfunction acceptRevisionsInParagraph(\n paragraph: Paragraph,\n options: Required<AcceptRevisionsOptions>\n): AcceptRevisionsResult {\n const result: AcceptRevisionsResult = {\n insertionsAccepted: 0,\n deletionsAccepted: 0,\n movesAccepted: 0,\n propertyChangesAccepted: 0,\n totalAccepted: 0,\n emptyTablesRemoved: 0,\n };\n\n const content = paragraph.getContent();\n const newContent: ParagraphContent[] = [];\n\n for (const item of content) {\n if (item instanceof Revision) {\n const revisionType = item.getType();\n\n // Handle insertion revisions (w:ins)\n if (revisionType === 'insert' && options.acceptInsertions) {\n // Unwrap: Extract child content into parent position\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.insertionsAccepted++;\n continue;\n }\n\n // Handle deletion revisions (w:del)\n if (revisionType === 'delete' && options.acceptDeletions) {\n // Remove: Don't add to newContent - content is deleted\n result.deletionsAccepted++;\n continue;\n }\n\n // Handle moveFrom revisions (source of moved content)\n if (revisionType === 'moveFrom' && options.acceptMoves) {\n // Remove: Content exists at moveTo destination\n result.movesAccepted++;\n continue;\n }\n\n // Handle moveTo revisions (destination of moved content)\n if (revisionType === 'moveTo' && options.acceptMoves) {\n // Unwrap: Keep content, remove wrapper\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.movesAccepted++;\n continue;\n }\n\n // Handle property change revisions\n if (PROPERTY_REVISION_TYPES.includes(revisionType) && options.acceptPropertyChanges) {\n // For property changes, the revision is metadata attached to runs\n // The current formatting (newProperties) is already applied to the run\n // We just need to remove the change tracking metadata\n // The content inside should be preserved\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.propertyChangesAccepted++;\n continue;\n }\n\n // If we reach here, this revision type is not being accepted\n // Keep it in the content\n newContent.push(item);\n } else if (item instanceof ComplexField && item.hasResultRevisions()) {\n // Accept revisions nested inside ComplexField result sections\n const fieldRevisions = item.getResultRevisions();\n for (const rev of fieldRevisions) {\n const revType = rev.getType();\n if (revType === 'insert' && options.acceptInsertions) result.insertionsAccepted++;\n else if (revType === 'delete' && options.acceptDeletions) result.deletionsAccepted++;\n else if ((revType === 'moveFrom' || revType === 'moveTo') && options.acceptMoves)\n result.movesAccepted++;\n }\n item.setResultRevisions([]); // Clear after acceptance\n newContent.push(item);\n } else {\n // Non-revision content - keep as-is\n newContent.push(item);\n }\n }\n\n // Replace paragraph content with the transformed content\n paragraph.setContent(newContent);\n\n // Clear paragraph property change tracking (pPrChange) if accepting property changes\n // This removes the w:pPrChange element from the paragraph's formatting\n if (options.acceptPropertyChanges) {\n const formatting = paragraph.getFormatting();\n if (formatting.pPrChange) {\n paragraph.clearParagraphPropertiesChange();\n result.propertyChangesAccepted++;\n }\n }\n\n // Clear paragraph mark deletion tracking if accepting deletions\n // This removes the w:del element from w:pPr/w:rPr\n if (options.acceptDeletions) {\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkDeletion) {\n paragraph.clearParagraphMarkDeletion();\n result.deletionsAccepted++;\n }\n }\n\n // Clear paragraph mark insertion tracking if accepting insertions\n // This removes the w:ins element from w:pPr/w:rPr\n if (options.acceptInsertions) {\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkInsertion) {\n paragraph.clearParagraphMarkInsertion();\n result.insertionsAccepted++;\n }\n }\n\n return result;\n}\n\n/**\n * Check if a paragraph has any revisions\n */\nexport function paragraphHasRevisions(paragraph: Paragraph): boolean {\n const content = paragraph.getContent();\n if (content.some((item) => item instanceof Revision)) {\n return true;\n }\n // Also check paragraph mark revision markers in w:pPr/w:rPr\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkDeletion || formatting.paragraphMarkInsertion) {\n return true;\n }\n return false;\n}\n\n/**\n * Get all revisions from a paragraph\n */\nexport function getRevisionsFromParagraph(paragraph: Paragraph): Revision[] {\n const content = paragraph.getContent();\n return content.filter((item): item is Revision => item instanceof Revision);\n}\n\n/**\n * Count revisions by type in a document\n */\nexport function countRevisionsByType(doc: Document): Map<RevisionType, number> {\n const counts = new Map<RevisionType, number>();\n\n const paragraphs = doc.getAllParagraphs();\n for (const paragraph of paragraphs) {\n const revisions = getRevisionsFromParagraph(paragraph);\n for (const revision of revisions) {\n const type = revision.getType();\n counts.set(type, (counts.get(type) || 0) + 1);\n }\n }\n\n return counts;\n}\n\n/**\n * Remove tables that have no visible content after revision acceptance.\n *\n * A table is considered empty if ALL cells in ALL rows have no text content.\n * This handles cases where all table content was deleted via tracked changes -\n * the deletion markers are stripped but the empty table structure remains.\n *\n * @param doc - Document to clean up\n * @param logger - Logger instance for debug output\n * @returns Number of empty tables removed\n */\nfunction cleanupEmptyTables(doc: Document, logger: ILogger): number {\n const tables = doc.getTables();\n let removedCount = 0;\n const tablesToRemove: number[] = [];\n\n for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {\n const table = tables[tableIndex];\n if (!table) continue;\n\n let hasContent = false;\n const rows = table.getRows();\n\n for (const row of rows) {\n const cells = row.getCells();\n for (const cell of cells) {\n const paragraphs = cell.getParagraphs();\n for (const para of paragraphs) {\n const text = para.getText().trim();\n if (text.length > 0) {\n hasContent = true;\n break;\n }\n }\n if (hasContent) break;\n }\n if (hasContent) break;\n }\n\n if (!hasContent) {\n // Mark this table for removal (store index)\n tablesToRemove.push(tableIndex);\n logger.debug('Found empty table for removal', { tableIndex });\n }\n }\n\n // Remove tables in reverse order to preserve indices\n for (let i = tablesToRemove.length - 1; i >= 0; i--) {\n const tableIndex = tablesToRemove[i];\n if (tableIndex !== undefined && doc.removeTable(tableIndex)) {\n removedCount++;\n logger.debug('Removed empty table', { tableIndex });\n }\n }\n\n if (removedCount > 0) {\n logger.info('Empty table cleanup complete', { tablesRemoved: removedCount });\n }\n\n return removedCount;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InMemoryRevisionAcceptor.js","sourceRoot":"","sources":["../../src/utils/InMemoryRevisionAcceptor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * InMemoryRevisionAcceptor - Accept revisions by transforming the in-memory object model\n *\n * This approach follows the industry standard (OpenXML PowerTools, Aspose.Words):\n * - Transforms Revision objects in paragraph.content[] to their \"accepted\" state\n * - For insertions: Unwrap - extract child Runs/Hyperlinks into parent paragraph\n * - For deletions: Remove - delete the revision and its content from the model\n * - For property changes: Remove the change metadata, keep the current formatting\n *\n * Unlike the raw XML approach (acceptRevisions.ts), this allows subsequent modifications\n * to the in-memory model to be correctly serialized on save().\n *\n * @see https://github.com/OfficeDev/Open-Xml-PowerTools - RevisionAccepter.cs\n * @see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/ee836138(v=office.12)\n */\n\nimport type { Document } from '../core/Document';\nimport { Paragraph } from '../elements/Paragraph';\nimport type { ParagraphContent } from '../elements/Paragraph';\nimport { Revision, RevisionType } from '../elements/Revision';\nimport type { Run } from '../elements/Run';\nimport type { Hyperlink } from '../elements/Hyperlink';\nimport { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';\nimport type { ImageRun } from '../elements/ImageRun';\nimport { ComplexField } from '../elements/Field';\nimport { Table } from '../elements/Table';\nimport { Section } from '../elements/Section';\nimport { getGlobalLogger, createScopedLogger, ILogger } from './logger';\n\n/**\n * Get scoped logger for this module\n */\nfunction getLogger(): ILogger {\n return createScopedLogger(getGlobalLogger(), 'InMemoryRevisionAcceptor');\n}\n\n/**\n * Options for accepting revisions\n */\nexport interface AcceptRevisionsOptions {\n /** Accept insertion revisions (w:ins) - default: true */\n acceptInsertions?: boolean;\n /** Accept deletion revisions (w:del) - default: true */\n acceptDeletions?: boolean;\n /** Accept move operations (w:moveFrom, w:moveTo) - default: true */\n acceptMoves?: boolean;\n /** Accept property change revisions (rPrChange, pPrChange, etc.) - default: true */\n acceptPropertyChanges?: boolean;\n /** Remove empty tables after revision acceptance - default: true */\n cleanupEmptyTables?: boolean;\n}\n\n/**\n * Result of accepting revisions\n */\nexport interface AcceptRevisionsResult {\n /** Number of insertions accepted */\n insertionsAccepted: number;\n /** Number of deletions accepted */\n deletionsAccepted: number;\n /** Number of move operations accepted */\n movesAccepted: number;\n /** Number of property changes accepted */\n propertyChangesAccepted: number;\n /** Total revisions processed */\n totalAccepted: number;\n /** Number of empty tables removed during cleanup */\n emptyTablesRemoved: number;\n}\n\n/**\n * Revision types that represent content changes (contain actual text/runs)\n */\nconst CONTENT_REVISION_TYPES: RevisionType[] = ['insert', 'delete', 'moveFrom', 'moveTo'];\n\n/**\n * Revision types that represent property/formatting changes\n */\nconst PROPERTY_REVISION_TYPES: RevisionType[] = [\n 'runPropertiesChange',\n 'paragraphPropertiesChange',\n 'tablePropertiesChange',\n 'tableExceptionPropertiesChange',\n 'tableRowPropertiesChange',\n 'tableCellPropertiesChange',\n 'sectionPropertiesChange',\n 'numberingChange',\n];\n\n/**\n * Strip revision markup from raw XML string.\n * Used for nested tables stored as raw XML that cannot be processed via the in-memory model.\n *\n * Follows the same rules as the main revision acceptor:\n * - Insertions: Keep content, remove wrapper tags\n * - Deletions: Remove entirely (content and tags)\n * - MoveFrom: Remove entirely (source of move)\n * - MoveTo: Keep content, remove wrapper\n * - Property changes: Remove change tracking elements\n * - Range markers: Remove boundary markers\n *\n * @param xml - Raw XML string containing revision markup\n * @returns Cleaned XML with revisions accepted\n */\nexport function stripRevisionsFromXml(xml: string): string {\n let result = xml;\n\n // Step 1: Remove range markers (must be done first)\n const rangePatterns = [\n /<w:moveFromRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeStart>)/gs,\n /<w:moveFromRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveFromRangeEnd>)/gs,\n /<w:moveToRangeStart[^>]*(?:\\/>|>.*?<\\/w:moveToRangeStart>)/gs,\n /<w:moveToRangeEnd[^>]*(?:\\/>|>.*?<\\/w:moveToRangeEnd>)/gs,\n /<w:customXmlInsRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeStart>)/gs,\n /<w:customXmlInsRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlInsRangeEnd>)/gs,\n /<w:customXmlDelRangeStart[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeStart>)/gs,\n /<w:customXmlDelRangeEnd[^>]*(?:\\/>|>.*?<\\/w:customXmlDelRangeEnd>)/gs,\n ];\n for (const pattern of rangePatterns) {\n result = result.replace(pattern, '');\n }\n\n // Step 2: Remove property change elements\n const propChangePatterns = [\n /<w:rPrChange[^>]*>[\\s\\S]*?<\\/w:rPrChange>/g,\n /<w:pPrChange[^>]*>[\\s\\S]*?<\\/w:pPrChange>/g,\n /<w:tblPrChange[^>]*>[\\s\\S]*?<\\/w:tblPrChange>/g,\n /<w:tblPrExChange[^>]*>[\\s\\S]*?<\\/w:tblPrExChange>/g,\n /<w:tcPrChange[^>]*>[\\s\\S]*?<\\/w:tcPrChange>/g,\n /<w:trPrChange[^>]*>[\\s\\S]*?<\\/w:trPrChange>/g,\n /<w:sectPrChange[^>]*>[\\s\\S]*?<\\/w:sectPrChange>/g,\n /<w:tblGridChange[^>]*>[\\s\\S]*?<\\/w:tblGridChange>/g,\n /<w:numberingChange[^>]*>[\\s\\S]*?<\\/w:numberingChange>/g,\n ];\n for (const pattern of propChangePatterns) {\n result = result.replace(pattern, '');\n }\n\n // Step 3: Remove deletions entirely (including content)\n // Iterate until no more deletions (handles nested cases)\n let prevLen = 0;\n while (result.length !== prevLen) {\n prevLen = result.length;\n result = result.replace(/<w:del\\b[^>]*>[\\s\\S]*?<\\/w:del>/g, '');\n }\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n\n // Step 4: Remove moveFrom entirely (source of moved content)\n prevLen = 0;\n while (result.length !== prevLen) {\n prevLen = result.length;\n result = result.replace(/<w:moveFrom\\b[^>]*>[\\s\\S]*?<\\/w:moveFrom>/g, '');\n }\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n\n // Step 5: Unwrap moveTo (keep content, remove wrapper)\n result = result.replace(/<\\/w:moveTo>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*>/g, '');\n\n // Step 6: Unwrap insertions (keep content, remove wrapper)\n result = result.replace(/<\\/w:ins>/g, '');\n result = result.replace(/<w:ins\\b[^>]*>/g, '');\n\n // Step 7: Clean up orphaned tags\n result = result.replace(/<w:ins\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:del\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveFrom\\b[^>]*\\/>/g, '');\n result = result.replace(/<w:moveTo\\b[^>]*\\/>/g, '');\n\n return result;\n}\n\n/**\n * Accept all revisions in the document by transforming the in-memory model.\n *\n * This is the industry-standard approach used by OpenXML PowerTools, Aspose.Words,\n * and other production DOCX libraries. It allows subsequent modifications to the\n * document to work correctly.\n *\n * @param doc - Document to process\n * @param options - Options for which revision types to accept\n * @returns Result with counts of accepted revisions\n */\nexport function acceptRevisionsInMemory(\n doc: Document,\n options: AcceptRevisionsOptions = {}\n): AcceptRevisionsResult {\n const logger = getLogger();\n const opts: Required<AcceptRevisionsOptions> = {\n acceptInsertions: options.acceptInsertions ?? true,\n acceptDeletions: options.acceptDeletions ?? true,\n acceptMoves: options.acceptMoves ?? true,\n acceptPropertyChanges: options.acceptPropertyChanges ?? true,\n cleanupEmptyTables: options.cleanupEmptyTables ?? true,\n };\n\n const result: AcceptRevisionsResult = {\n insertionsAccepted: 0,\n deletionsAccepted: 0,\n movesAccepted: 0,\n propertyChangesAccepted: 0,\n totalAccepted: 0,\n emptyTablesRemoved: 0,\n };\n\n logger.info('Accepting revisions in-memory', { options: opts });\n\n // Validate move pairs before accepting if moves are being accepted\n // Orphaned moves could result in content loss (moveFrom without moveTo = content deleted)\n if (opts.acceptMoves) {\n const revisionManager = doc.getRevisionManager();\n if (revisionManager) {\n const movePairValidation = revisionManager.validateMovePairs();\n if (!movePairValidation.valid) {\n if (movePairValidation.orphanedMoveFrom.length > 0) {\n logger.warn(\n 'Orphaned moveFrom revisions detected - accepting these will DELETE content permanently ' +\n '(content was moved from here but no moveTo destination exists)',\n { orphanedMoveIds: movePairValidation.orphanedMoveFrom }\n );\n }\n if (movePairValidation.orphanedMoveTo.length > 0) {\n logger.warn(\n 'Orphaned moveTo revisions detected - content may be duplicated ' +\n '(content moved to here but no moveFrom source exists)',\n { orphanedMoveIds: movePairValidation.orphanedMoveTo }\n );\n }\n }\n }\n }\n\n // Process all paragraphs in the document body\n const paragraphs = doc.getAllParagraphs();\n for (const paragraph of paragraphs) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n\n // Process paragraphs in tables and clear table/row/cell property changes\n const tables = doc.getTables();\n for (const table of tables) {\n // Clear tblPrChange on table\n if (opts.acceptPropertyChanges && table.getTblPrChange()) {\n table.clearTblPrChange();\n result.propertyChangesAccepted++;\n }\n\n for (const row of table.getRows()) {\n // Clear trPrChange on row\n if (opts.acceptPropertyChanges && row.getTrPrChange()) {\n row.clearTrPrChange();\n result.propertyChangesAccepted++;\n }\n\n for (const cell of row.getCells()) {\n // Clear tcPrChange on cell\n if (opts.acceptPropertyChanges && cell.getTcPrChange()) {\n cell.clearTcPrChange();\n result.propertyChangesAccepted++;\n }\n\n // Clear cell structural revision markers (cellIns/cellDel/cellMerge)\n if (opts.acceptPropertyChanges && cell.getCellRevision()) {\n cell.clearCellRevision();\n result.propertyChangesAccepted++;\n }\n\n // Process paragraphs in the cell\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n\n // Process raw nested content (nested tables stored as XML)\n // These cannot be processed via the in-memory model, so we use XML-based stripping\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n // Count revisions stripped from nested content\n // We can't distinguish types in raw XML, so count as property changes\n result.propertyChangesAccepted++;\n logger.debug('Stripped revisions from nested content', {\n type: item.type,\n position: item.position,\n originalLength: item.xml.length,\n cleanedLength: cleanedXml.length,\n });\n }\n }\n }\n }\n }\n }\n }\n\n // Process paragraphs in headers\n const headerFooterManager = doc.getHeaderFooterManager();\n if (headerFooterManager) {\n const headers = headerFooterManager.getAllHeaders();\n for (const headerEntry of headers) {\n const elements = headerEntry.header.getElements();\n for (const element of elements) {\n // Element can be Paragraph or Table - use instanceof for type safety\n if (element instanceof Paragraph) {\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n } else if (element instanceof Table) {\n // It's a Table - process its cells\n for (const row of element.getRows()) {\n for (const cell of row.getCells()) {\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n // Process raw nested content in header tables\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n result.propertyChangesAccepted++;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Process paragraphs in footers\n const footers = headerFooterManager.getAllFooters();\n for (const footerEntry of footers) {\n const elements = footerEntry.footer.getElements();\n for (const element of elements) {\n // Element can be Paragraph or Table - use instanceof for type safety\n if (element instanceof Paragraph) {\n const paragraphResult = acceptRevisionsInParagraph(element, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n } else if (element instanceof Table) {\n // It's a Table - process its cells\n for (const row of element.getRows()) {\n for (const cell of row.getCells()) {\n for (const paragraph of cell.getParagraphs()) {\n const paragraphResult = acceptRevisionsInParagraph(paragraph, opts);\n result.insertionsAccepted += paragraphResult.insertionsAccepted;\n result.deletionsAccepted += paragraphResult.deletionsAccepted;\n result.movesAccepted += paragraphResult.movesAccepted;\n result.propertyChangesAccepted += paragraphResult.propertyChangesAccepted;\n }\n // Process raw nested content in footer tables\n if (cell.hasRawNestedContent()) {\n const rawContent = cell.getRawNestedContent();\n for (let i = 0; i < rawContent.length; i++) {\n const item = rawContent[i];\n if (item) {\n const cleanedXml = stripRevisionsFromXml(item.xml);\n if (cleanedXml !== item.xml) {\n cell.updateRawNestedContent(i, cleanedXml);\n result.propertyChangesAccepted++;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Clear sectPrChange on document section\n if (opts.acceptPropertyChanges) {\n const section = doc.getSection();\n if (section?.getSectPrChange()) {\n section.clearSectPrChange();\n result.propertyChangesAccepted++;\n }\n }\n\n // Clear revision manager\n const revisionManager = doc.getRevisionManager();\n if (revisionManager) {\n revisionManager.clear();\n }\n\n // Disable track changes setting\n doc.disableTrackChanges();\n\n // Cleanup empty tables if enabled\n // This removes tables that have no visible content after revision acceptance\n // (e.g., tables where all content was deleted via tracked changes)\n if (opts.cleanupEmptyTables) {\n result.emptyTablesRemoved = cleanupEmptyTables(doc, logger);\n }\n\n result.totalAccepted =\n result.insertionsAccepted +\n result.deletionsAccepted +\n result.movesAccepted +\n result.propertyChangesAccepted;\n\n logger.info('Revisions accepted in-memory', {\n insertions: result.insertionsAccepted,\n deletions: result.deletionsAccepted,\n moves: result.movesAccepted,\n propertyChanges: result.propertyChangesAccepted,\n total: result.totalAccepted,\n emptyTablesRemoved: result.emptyTablesRemoved,\n });\n\n return result;\n}\n\n/**\n * Accept revisions in a single paragraph by transforming its content array.\n *\n * The transformation follows these rules:\n * - Insertions (w:ins): Unwrap - extract child content into parent position\n * - Deletions (w:del): Remove - delete revision and its content\n * - MoveFrom (w:moveFrom): Remove - content exists at moveTo destination\n * - MoveTo (w:moveTo): Unwrap - keep content, remove wrapper\n * - Property changes: Remove from model (current formatting is kept)\n *\n * @param paragraph - Paragraph to process\n * @param options - Options for which revision types to accept\n * @returns Result with counts of accepted revisions\n */\nfunction acceptRevisionsInParagraph(\n paragraph: Paragraph,\n options: Required<AcceptRevisionsOptions>\n): AcceptRevisionsResult {\n const result: AcceptRevisionsResult = {\n insertionsAccepted: 0,\n deletionsAccepted: 0,\n movesAccepted: 0,\n propertyChangesAccepted: 0,\n totalAccepted: 0,\n emptyTablesRemoved: 0,\n };\n\n const content = paragraph.getContent();\n const newContent: ParagraphContent[] = [];\n\n for (const item of content) {\n if (item instanceof Revision) {\n const revisionType = item.getType();\n\n // Handle insertion revisions (w:ins)\n if (revisionType === 'insert' && options.acceptInsertions) {\n // Unwrap: Extract child content into parent position\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.insertionsAccepted++;\n continue;\n }\n\n // Handle deletion revisions (w:del)\n if (revisionType === 'delete' && options.acceptDeletions) {\n // Remove: Don't add to newContent - content is deleted\n result.deletionsAccepted++;\n continue;\n }\n\n // Handle moveFrom revisions (source of moved content)\n if (revisionType === 'moveFrom' && options.acceptMoves) {\n // Remove: Content exists at moveTo destination\n result.movesAccepted++;\n continue;\n }\n\n // Handle moveTo revisions (destination of moved content)\n if (revisionType === 'moveTo' && options.acceptMoves) {\n // Unwrap: Keep content, remove wrapper\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.movesAccepted++;\n continue;\n }\n\n // Handle property change revisions\n if (PROPERTY_REVISION_TYPES.includes(revisionType) && options.acceptPropertyChanges) {\n // For property changes, the revision is metadata attached to runs\n // The current formatting (newProperties) is already applied to the run\n // We just need to remove the change tracking metadata\n // The content inside should be preserved\n const childContent = item.getContent();\n for (const child of childContent) {\n // Check ImageRun FIRST since ImageRun extends Run\n if (isImageRunContent(child)) {\n newContent.push(child);\n } else if (isRunContent(child)) {\n newContent.push(child);\n } else if (isHyperlinkContent(child)) {\n newContent.push(child);\n }\n }\n result.propertyChangesAccepted++;\n continue;\n }\n\n // If we reach here, this revision type is not being accepted\n // Keep it in the content\n newContent.push(item);\n } else if (item instanceof ComplexField && item.hasResultRevisions()) {\n // Accept revisions nested inside ComplexField result sections\n // Merge insertion/moveTo text into the result before clearing\n const fieldRevisions = item.getResultRevisions();\n let mergedResult = item.getResult() || '';\n const revisionsToKeep: Revision[] = [];\n\n for (const rev of fieldRevisions) {\n const revType = rev.getType();\n if (revType === 'insert' && options.acceptInsertions) {\n // Merge insertion text into result\n for (const child of rev.getRuns()) {\n mergedResult += child.getText() || '';\n }\n result.insertionsAccepted++;\n } else if (revType === 'delete' && options.acceptDeletions) {\n // Deleted text was never in result — just count it\n result.deletionsAccepted++;\n } else if (revType === 'moveTo' && options.acceptMoves) {\n // Merge moveTo text into result\n for (const child of rev.getRuns()) {\n mergedResult += child.getText() || '';\n }\n result.movesAccepted++;\n } else if (revType === 'moveFrom' && options.acceptMoves) {\n result.movesAccepted++;\n } else {\n // Revision type not being accepted — keep it\n revisionsToKeep.push(rev);\n }\n }\n\n // setResult() clears both resultRevisions and resultContent\n item.setResult(mergedResult);\n // Restore any unaccepted revisions\n if (revisionsToKeep.length > 0) {\n item.setResultRevisions(revisionsToKeep);\n }\n newContent.push(item);\n } else {\n // Non-revision content - keep as-is\n newContent.push(item);\n }\n }\n\n // Replace paragraph content with the transformed content\n paragraph.setContent(newContent);\n\n // Clear paragraph property change tracking (pPrChange) if accepting property changes\n // This removes the w:pPrChange element from the paragraph's formatting\n if (options.acceptPropertyChanges) {\n const formatting = paragraph.getFormatting();\n if (formatting.pPrChange) {\n paragraph.clearParagraphPropertiesChange();\n result.propertyChangesAccepted++;\n }\n }\n\n // Clear paragraph mark deletion tracking if accepting deletions\n // This removes the w:del element from w:pPr/w:rPr\n if (options.acceptDeletions) {\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkDeletion) {\n paragraph.clearParagraphMarkDeletion();\n result.deletionsAccepted++;\n }\n }\n\n // Clear paragraph mark insertion tracking if accepting insertions\n // This removes the w:ins element from w:pPr/w:rPr\n if (options.acceptInsertions) {\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkInsertion) {\n paragraph.clearParagraphMarkInsertion();\n result.insertionsAccepted++;\n }\n }\n\n return result;\n}\n\n/**\n * Check if a paragraph has any revisions\n */\nexport function paragraphHasRevisions(paragraph: Paragraph): boolean {\n const content = paragraph.getContent();\n if (content.some((item) => item instanceof Revision)) {\n return true;\n }\n // Also check paragraph mark revision markers in w:pPr/w:rPr\n const formatting = paragraph.getFormatting();\n if (formatting.paragraphMarkDeletion || formatting.paragraphMarkInsertion) {\n return true;\n }\n return false;\n}\n\n/**\n * Get all revisions from a paragraph\n */\nexport function getRevisionsFromParagraph(paragraph: Paragraph): Revision[] {\n const content = paragraph.getContent();\n return content.filter((item): item is Revision => item instanceof Revision);\n}\n\n/**\n * Count revisions by type in a document\n */\nexport function countRevisionsByType(doc: Document): Map<RevisionType, number> {\n const counts = new Map<RevisionType, number>();\n\n const paragraphs = doc.getAllParagraphs();\n for (const paragraph of paragraphs) {\n const revisions = getRevisionsFromParagraph(paragraph);\n for (const revision of revisions) {\n const type = revision.getType();\n counts.set(type, (counts.get(type) || 0) + 1);\n }\n }\n\n return counts;\n}\n\n/**\n * Remove tables that have no visible content after revision acceptance.\n *\n * A table is considered empty if ALL cells in ALL rows have no text content.\n * This handles cases where all table content was deleted via tracked changes -\n * the deletion markers are stripped but the empty table structure remains.\n *\n * @param doc - Document to clean up\n * @param logger - Logger instance for debug output\n * @returns Number of empty tables removed\n */\nfunction cleanupEmptyTables(doc: Document, logger: ILogger): number {\n const tables = doc.getTables();\n let removedCount = 0;\n const tablesToRemove: number[] = [];\n\n for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {\n const table = tables[tableIndex];\n if (!table) continue;\n\n let hasContent = false;\n const rows = table.getRows();\n\n for (const row of rows) {\n const cells = row.getCells();\n for (const cell of cells) {\n const paragraphs = cell.getParagraphs();\n for (const para of paragraphs) {\n const text = para.getText().trim();\n if (text.length > 0) {\n hasContent = true;\n break;\n }\n }\n if (hasContent) break;\n }\n if (hasContent) break;\n }\n\n if (!hasContent) {\n // Mark this table for removal (store index)\n tablesToRemove.push(tableIndex);\n logger.debug('Found empty table for removal', { tableIndex });\n }\n }\n\n // Remove tables in reverse order to preserve indices\n for (let i = tablesToRemove.length - 1; i >= 0; i--) {\n const tableIndex = tablesToRemove[i];\n if (tableIndex !== undefined && doc.removeTable(tableIndex)) {\n removedCount++;\n logger.debug('Removed empty table', { tableIndex });\n }\n }\n\n if (removedCount > 0) {\n logger.info('Empty table cleanup complete', { tablesRemoved: removedCount });\n }\n\n return removedCount;\n}\n"]}
|
package/package.json
CHANGED
package/src/core/Document.ts
CHANGED
|
@@ -10751,6 +10751,19 @@ export class Document {
|
|
|
10751
10751
|
}
|
|
10752
10752
|
}
|
|
10753
10753
|
|
|
10754
|
+
// Bind to ComplexField instances in paragraph content
|
|
10755
|
+
if (element && typeof element.getContent === 'function') {
|
|
10756
|
+
for (const item of element.getContent()) {
|
|
10757
|
+
if (
|
|
10758
|
+
item &&
|
|
10759
|
+
typeof item._setTrackingContext === 'function' &&
|
|
10760
|
+
typeof item.getInstruction === 'function'
|
|
10761
|
+
) {
|
|
10762
|
+
item._setTrackingContext(this.trackingContext);
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
10765
|
+
}
|
|
10766
|
+
|
|
10754
10767
|
// Recursively bind to table rows and cells
|
|
10755
10768
|
if (element && typeof element.getRows === 'function') {
|
|
10756
10769
|
for (const row of element.getRows()) {
|
|
@@ -2689,6 +2689,7 @@ export class DocumentParser {
|
|
|
2689
2689
|
let fieldRuns: Run[] = [];
|
|
2690
2690
|
let fieldRevisions: Revision[] = []; // Track revisions inside field result section
|
|
2691
2691
|
let instructionRevisions: Revision[] = []; // Track revisions in instruction area
|
|
2692
|
+
let orderedResultItems: Array<Run | Revision> = []; // Track interleaved order of result runs + revisions
|
|
2692
2693
|
let fieldState: 'begin' | 'instruction' | 'separate' | 'result' | 'end' | null = null;
|
|
2693
2694
|
let nestingDepth = 0;
|
|
2694
2695
|
let hasNestedFields = false;
|
|
@@ -2749,6 +2750,7 @@ export class DocumentParser {
|
|
|
2749
2750
|
fieldRuns = [];
|
|
2750
2751
|
instructionRevisions = [];
|
|
2751
2752
|
fieldRevisions = [];
|
|
2753
|
+
orderedResultItems = [];
|
|
2752
2754
|
fieldState = null;
|
|
2753
2755
|
hasNestedFields = false;
|
|
2754
2756
|
fieldStartIndex = -1;
|
|
@@ -2801,6 +2803,7 @@ export class DocumentParser {
|
|
|
2801
2803
|
fieldRuns = [];
|
|
2802
2804
|
instructionRevisions = [];
|
|
2803
2805
|
fieldRevisions = [];
|
|
2806
|
+
orderedResultItems = [];
|
|
2804
2807
|
fieldState = null;
|
|
2805
2808
|
break;
|
|
2806
2809
|
}
|
|
@@ -2840,6 +2843,39 @@ export class DocumentParser {
|
|
|
2840
2843
|
if (fieldRevisions.length > 0) {
|
|
2841
2844
|
const complexField = this.createComplexFieldFromRuns(fieldRuns);
|
|
2842
2845
|
if (complexField) {
|
|
2846
|
+
// Build ordered resultContent for correct round-trip serialization
|
|
2847
|
+
if (orderedResultItems.length > 0) {
|
|
2848
|
+
const orderedContent: XMLElement[] = [];
|
|
2849
|
+
for (const resultItem of orderedResultItems) {
|
|
2850
|
+
if (resultItem instanceof Run) {
|
|
2851
|
+
orderedContent.push(resultItem.toXML());
|
|
2852
|
+
} else if (resultItem instanceof Revision) {
|
|
2853
|
+
const xml = resultItem.toXML();
|
|
2854
|
+
if (xml) orderedContent.push(xml);
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
// Compute accepted text (non-revision runs + insertion text)
|
|
2858
|
+
let acceptedText = '';
|
|
2859
|
+
for (const resultItem of orderedResultItems) {
|
|
2860
|
+
if (resultItem instanceof Run) {
|
|
2861
|
+
acceptedText += resultItem.getText() || '';
|
|
2862
|
+
} else if (
|
|
2863
|
+
resultItem instanceof Revision &&
|
|
2864
|
+
resultItem.getType() === 'insert'
|
|
2865
|
+
) {
|
|
2866
|
+
for (const child of resultItem.getRuns()) {
|
|
2867
|
+
acceptedText += child.getText() || '';
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
// Set accepted text as the result (for getResult() API)
|
|
2872
|
+
complexField.setResult(acceptedText || complexField.getResult() || '');
|
|
2873
|
+
// Add ordered content for serialization (overrides the text-based path)
|
|
2874
|
+
for (const xmlEl of orderedContent) {
|
|
2875
|
+
complexField.addResultContent(xmlEl);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
// Attach revisions for tracking/acceptance
|
|
2843
2879
|
for (const rev of fieldRevisions) {
|
|
2844
2880
|
rev.setFieldContext({
|
|
2845
2881
|
field: complexField,
|
|
@@ -2858,6 +2894,7 @@ export class DocumentParser {
|
|
|
2858
2894
|
fieldRuns = [];
|
|
2859
2895
|
instructionRevisions = [];
|
|
2860
2896
|
fieldRevisions = [];
|
|
2897
|
+
orderedResultItems = [];
|
|
2861
2898
|
fieldState = null;
|
|
2862
2899
|
break;
|
|
2863
2900
|
}
|
|
@@ -2905,6 +2942,7 @@ export class DocumentParser {
|
|
|
2905
2942
|
fieldRuns = [];
|
|
2906
2943
|
instructionRevisions = [];
|
|
2907
2944
|
fieldRevisions = [];
|
|
2945
|
+
orderedResultItems = [];
|
|
2908
2946
|
fieldState = null;
|
|
2909
2947
|
break;
|
|
2910
2948
|
}
|
|
@@ -2924,6 +2962,7 @@ export class DocumentParser {
|
|
|
2924
2962
|
fieldRuns = [];
|
|
2925
2963
|
instructionRevisions = [];
|
|
2926
2964
|
fieldRevisions = [];
|
|
2965
|
+
orderedResultItems = [];
|
|
2927
2966
|
fieldState = null;
|
|
2928
2967
|
break;
|
|
2929
2968
|
}
|
|
@@ -2958,6 +2997,7 @@ export class DocumentParser {
|
|
|
2958
2997
|
fieldRuns = [];
|
|
2959
2998
|
instructionRevisions = [];
|
|
2960
2999
|
fieldRevisions = [];
|
|
3000
|
+
orderedResultItems = [];
|
|
2961
3001
|
fieldState = null;
|
|
2962
3002
|
}
|
|
2963
3003
|
break;
|
|
@@ -2971,11 +3011,16 @@ export class DocumentParser {
|
|
|
2971
3011
|
} else {
|
|
2972
3012
|
// Regular run - check if we're inside a field result section
|
|
2973
3013
|
if (nestingDepth > 0) {
|
|
2974
|
-
// Inside a
|
|
3014
|
+
// Inside a field - collect all runs to preserve raw structure
|
|
2975
3015
|
fieldRuns.push(item);
|
|
3016
|
+
// Track result runs for interleaved ordering (only outer field level)
|
|
3017
|
+
if (nestingDepth === 1 && (fieldState === 'separate' || fieldState === 'result')) {
|
|
3018
|
+
orderedResultItems.push(item);
|
|
3019
|
+
}
|
|
2976
3020
|
} else if (fieldState === 'separate' || fieldState === 'result') {
|
|
2977
3021
|
// This run is part of the field result - collect it
|
|
2978
3022
|
fieldRuns.push(item);
|
|
3023
|
+
orderedResultItems.push(item);
|
|
2979
3024
|
fieldState = 'result';
|
|
2980
3025
|
} else if (fieldState === 'begin' || fieldState === 'instruction') {
|
|
2981
3026
|
// We're in the middle of parsing field instruction
|
|
@@ -2994,6 +3039,7 @@ export class DocumentParser {
|
|
|
2994
3039
|
fieldRuns = [];
|
|
2995
3040
|
instructionRevisions = [];
|
|
2996
3041
|
fieldRevisions = [];
|
|
3042
|
+
orderedResultItems = [];
|
|
2997
3043
|
fieldState = null;
|
|
2998
3044
|
groupedContent.push(item);
|
|
2999
3045
|
} else {
|
|
@@ -3010,6 +3056,7 @@ export class DocumentParser {
|
|
|
3010
3056
|
// Set preliminary field context (field reference will be set when ComplexField is created)
|
|
3011
3057
|
item.setFieldContext({ position: 'result' });
|
|
3012
3058
|
fieldRevisions.push(item);
|
|
3059
|
+
orderedResultItems.push(item);
|
|
3013
3060
|
fieldState = 'result';
|
|
3014
3061
|
defaultLogger.debug(
|
|
3015
3062
|
`Found revision inside complex field result: type=${item.getType()}, id=${item.getId()}`
|
|
@@ -3038,6 +3085,7 @@ export class DocumentParser {
|
|
|
3038
3085
|
fieldRuns = [];
|
|
3039
3086
|
instructionRevisions = [];
|
|
3040
3087
|
fieldRevisions = [];
|
|
3088
|
+
orderedResultItems = [];
|
|
3041
3089
|
fieldState = null;
|
|
3042
3090
|
groupedContent.push(item);
|
|
3043
3091
|
} else {
|
|
@@ -3061,6 +3109,7 @@ export class DocumentParser {
|
|
|
3061
3109
|
fieldRuns = [];
|
|
3062
3110
|
instructionRevisions = [];
|
|
3063
3111
|
fieldRevisions = [];
|
|
3112
|
+
orderedResultItems = [];
|
|
3064
3113
|
fieldState = null;
|
|
3065
3114
|
}
|
|
3066
3115
|
groupedContent.push(item);
|
package/src/elements/Field.ts
CHANGED
|
@@ -627,6 +627,7 @@ export class ComplexField {
|
|
|
627
627
|
*/
|
|
628
628
|
private _hasResultSection = false;
|
|
629
629
|
private _formFieldData?: FormFieldData;
|
|
630
|
+
private trackingContext?: import('../tracking/TrackingContext').TrackingContext;
|
|
630
631
|
|
|
631
632
|
/**
|
|
632
633
|
* Creates a new complex field
|
|
@@ -843,6 +844,160 @@ export class ComplexField {
|
|
|
843
844
|
return [...this.resultContent];
|
|
844
845
|
}
|
|
845
846
|
|
|
847
|
+
/**
|
|
848
|
+
* Sets the tracking context for automatic change tracking
|
|
849
|
+
* @internal
|
|
850
|
+
*/
|
|
851
|
+
_setTrackingContext(context: import('../tracking/TrackingContext').TrackingContext): void {
|
|
852
|
+
this.trackingContext = context;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Gets the accepted (visible) text from resultContent XMLElements.
|
|
857
|
+
* Processes w:r (plain runs), w:ins (accepted insertions), skips w:del/w:moveFrom.
|
|
858
|
+
* Falls back to this.result if resultContent is empty.
|
|
859
|
+
*/
|
|
860
|
+
getAcceptedResultText(): string {
|
|
861
|
+
if (this.resultContent.length === 0) {
|
|
862
|
+
return this.result || '';
|
|
863
|
+
}
|
|
864
|
+
let text = '';
|
|
865
|
+
for (const element of this.resultContent) {
|
|
866
|
+
if (element.name === 'w:r') {
|
|
867
|
+
text += this.extractTextFromRunXml(element);
|
|
868
|
+
} else if (element.name === 'w:ins') {
|
|
869
|
+
for (const child of element.children || []) {
|
|
870
|
+
if (typeof child !== 'string' && child.name === 'w:r') {
|
|
871
|
+
text += this.extractTextFromRunXml(child);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
// Skip w:del, w:moveFrom (deleted/moved text not visible)
|
|
876
|
+
}
|
|
877
|
+
return text || this.result || '';
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Extracts text content from a w:r (run) XMLElement
|
|
882
|
+
*/
|
|
883
|
+
private extractTextFromRunXml(run: XMLElement): string {
|
|
884
|
+
let text = '';
|
|
885
|
+
for (const child of run.children || []) {
|
|
886
|
+
if (typeof child !== 'string' && (child.name === 'w:t' || child.name === 'w:delText')) {
|
|
887
|
+
for (const t of child.children || []) {
|
|
888
|
+
if (typeof t === 'string') text += t;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return text;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Sets the field result with tracked changes (del/ins pair).
|
|
897
|
+
* Creates a w:del wrapping the old text and a w:ins wrapping the new text,
|
|
898
|
+
* preserving formatting from the original result runs.
|
|
899
|
+
*
|
|
900
|
+
* @param newText - New result text to display
|
|
901
|
+
* @param author - Author name for the revision
|
|
902
|
+
* @param options - Optional formatting control
|
|
903
|
+
*/
|
|
904
|
+
setTrackedResult(
|
|
905
|
+
newText: string,
|
|
906
|
+
author: string,
|
|
907
|
+
options?: {
|
|
908
|
+
formatting?: RunFormatting;
|
|
909
|
+
preserveFormatting?: boolean;
|
|
910
|
+
}
|
|
911
|
+
): this {
|
|
912
|
+
const currentText = this.getAcceptedResultText();
|
|
913
|
+
if (currentText === newText) return this; // No-op if unchanged
|
|
914
|
+
|
|
915
|
+
const date = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
916
|
+
|
|
917
|
+
// Get revision IDs from TrackingContext if available, else Date.now()-based
|
|
918
|
+
let delId: number, insId: number;
|
|
919
|
+
if (this.trackingContext) {
|
|
920
|
+
const rm = this.trackingContext.getRevisionManager();
|
|
921
|
+
delId = rm.consumeNextId();
|
|
922
|
+
insId = rm.consumeNextId();
|
|
923
|
+
} else {
|
|
924
|
+
const base = Date.now() % 100000000;
|
|
925
|
+
delId = base;
|
|
926
|
+
insId = base + 1;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Resolve formatting: explicit > preserve > resultFormatting
|
|
930
|
+
let rPr: XMLElement | null = null;
|
|
931
|
+
if (options?.formatting) {
|
|
932
|
+
rPr = this.createRunProperties(options.formatting);
|
|
933
|
+
} else if (options?.preserveFormatting) {
|
|
934
|
+
rPr = this.extractFirstVisibleRunProperties();
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Build <w:del> with old text
|
|
938
|
+
const delRunChildren: (string | XMLElement)[] = [];
|
|
939
|
+
if (rPr) delRunChildren.push(rPr);
|
|
940
|
+
delRunChildren.push({
|
|
941
|
+
name: 'w:delText',
|
|
942
|
+
attributes: { 'xml:space': 'preserve' },
|
|
943
|
+
children: [currentText],
|
|
944
|
+
});
|
|
945
|
+
const delElement: XMLElement = {
|
|
946
|
+
name: 'w:del',
|
|
947
|
+
attributes: { 'w:id': String(delId), 'w:author': author, 'w:date': date },
|
|
948
|
+
children: [{ name: 'w:r', children: delRunChildren }],
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
// Build <w:ins> with new text
|
|
952
|
+
const insRunChildren: (string | XMLElement)[] = [];
|
|
953
|
+
if (rPr) insRunChildren.push(rPr);
|
|
954
|
+
insRunChildren.push({
|
|
955
|
+
name: 'w:t',
|
|
956
|
+
attributes: { 'xml:space': 'preserve' },
|
|
957
|
+
children: [newText],
|
|
958
|
+
});
|
|
959
|
+
const insElement: XMLElement = {
|
|
960
|
+
name: 'w:ins',
|
|
961
|
+
attributes: { 'w:id': String(insId), 'w:author': author, 'w:date': date },
|
|
962
|
+
children: [{ name: 'w:r', children: insRunChildren }],
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
// Replace content: resultContent takes priority in toXML()
|
|
966
|
+
this.resultContent = [delElement, insElement];
|
|
967
|
+
this.result = newText;
|
|
968
|
+
this.resultRevisions = [];
|
|
969
|
+
|
|
970
|
+
return this;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Extracts w:rPr from the first visible run in resultContent
|
|
975
|
+
*/
|
|
976
|
+
private extractFirstVisibleRunProperties(): XMLElement | null {
|
|
977
|
+
for (const element of this.resultContent) {
|
|
978
|
+
if (element.name === 'w:r') {
|
|
979
|
+
const rPr = (element.children || []).find(
|
|
980
|
+
(c): c is XMLElement => typeof c !== 'string' && c.name === 'w:rPr'
|
|
981
|
+
);
|
|
982
|
+
if (rPr) return rPr;
|
|
983
|
+
} else if (element.name === 'w:ins') {
|
|
984
|
+
for (const child of element.children || []) {
|
|
985
|
+
if (typeof child !== 'string' && child.name === 'w:r') {
|
|
986
|
+
const rPr = (child.children || []).find(
|
|
987
|
+
(c): c is XMLElement => typeof c !== 'string' && c.name === 'w:rPr'
|
|
988
|
+
);
|
|
989
|
+
if (rPr) return rPr;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
// Fall back to resultFormatting
|
|
995
|
+
if (this.resultFormatting) {
|
|
996
|
+
return this.createRunProperties(this.resultFormatting);
|
|
997
|
+
}
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
|
|
846
1001
|
/**
|
|
847
1002
|
* Sets whether this field spans multiple paragraphs
|
|
848
1003
|
*/
|
|
@@ -970,13 +1125,16 @@ export class ComplexField {
|
|
|
970
1125
|
});
|
|
971
1126
|
}
|
|
972
1127
|
|
|
973
|
-
// 4a. Result revisions
|
|
974
|
-
//
|
|
975
|
-
//
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1128
|
+
// 4a. Result revisions — only when NOT using resultContent
|
|
1129
|
+
// When resultContent is populated (e.g., by DocumentParser with interleaved revision XML),
|
|
1130
|
+
// it already includes revision elements in the correct interleaved position.
|
|
1131
|
+
// Emitting them again here would cause duplication.
|
|
1132
|
+
if (this.resultContent.length === 0) {
|
|
1133
|
+
for (const revision of this.resultRevisions) {
|
|
1134
|
+
const revisionXml = revision.toXML();
|
|
1135
|
+
if (revisionXml) {
|
|
1136
|
+
runs.push(revisionXml);
|
|
1137
|
+
}
|
|
980
1138
|
}
|
|
981
1139
|
}
|
|
982
1140
|
|
|
@@ -547,15 +547,42 @@ function acceptRevisionsInParagraph(
|
|
|
547
547
|
newContent.push(item);
|
|
548
548
|
} else if (item instanceof ComplexField && item.hasResultRevisions()) {
|
|
549
549
|
// Accept revisions nested inside ComplexField result sections
|
|
550
|
+
// Merge insertion/moveTo text into the result before clearing
|
|
550
551
|
const fieldRevisions = item.getResultRevisions();
|
|
552
|
+
let mergedResult = item.getResult() || '';
|
|
553
|
+
const revisionsToKeep: Revision[] = [];
|
|
554
|
+
|
|
551
555
|
for (const rev of fieldRevisions) {
|
|
552
556
|
const revType = rev.getType();
|
|
553
|
-
if (revType === 'insert' && options.acceptInsertions)
|
|
554
|
-
|
|
555
|
-
|
|
557
|
+
if (revType === 'insert' && options.acceptInsertions) {
|
|
558
|
+
// Merge insertion text into result
|
|
559
|
+
for (const child of rev.getRuns()) {
|
|
560
|
+
mergedResult += child.getText() || '';
|
|
561
|
+
}
|
|
562
|
+
result.insertionsAccepted++;
|
|
563
|
+
} else if (revType === 'delete' && options.acceptDeletions) {
|
|
564
|
+
// Deleted text was never in result — just count it
|
|
565
|
+
result.deletionsAccepted++;
|
|
566
|
+
} else if (revType === 'moveTo' && options.acceptMoves) {
|
|
567
|
+
// Merge moveTo text into result
|
|
568
|
+
for (const child of rev.getRuns()) {
|
|
569
|
+
mergedResult += child.getText() || '';
|
|
570
|
+
}
|
|
571
|
+
result.movesAccepted++;
|
|
572
|
+
} else if (revType === 'moveFrom' && options.acceptMoves) {
|
|
556
573
|
result.movesAccepted++;
|
|
574
|
+
} else {
|
|
575
|
+
// Revision type not being accepted — keep it
|
|
576
|
+
revisionsToKeep.push(rev);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// setResult() clears both resultRevisions and resultContent
|
|
581
|
+
item.setResult(mergedResult);
|
|
582
|
+
// Restore any unaccepted revisions
|
|
583
|
+
if (revisionsToKeep.length > 0) {
|
|
584
|
+
item.setResultRevisions(revisionsToKeep);
|
|
557
585
|
}
|
|
558
|
-
item.setResultRevisions([]); // Clear after acceptance
|
|
559
586
|
newContent.push(item);
|
|
560
587
|
} else {
|
|
561
588
|
// Non-revision content - keep as-is
|