docxmlater 10.2.5 → 10.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,7 @@
1
1
  import type { Run } from './Run';
2
2
  import type { Hyperlink } from './Hyperlink';
3
3
  import type { ImageRun } from './ImageRun';
4
- import type { ComplexField } from './Field';
5
- export type RevisionContent = Run | ImageRun | Hyperlink | ComplexField;
4
+ export type RevisionContent = Run | ImageRun | Hyperlink;
6
5
  export declare function isRunContent(content: RevisionContent): content is Run;
7
6
  export declare function isHyperlinkContent(content: RevisionContent): content is Hyperlink;
8
7
  export declare function isImageRunContent(content: RevisionContent): content is ImageRun;
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionContent.d.ts","sourceRoot":"","sources":["../../src/elements/RevisionContent.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAW5C,MAAM,MAAM,eAAe,GAAG,GAAG,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAUxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,GAAG,CAQrE;AAUD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,SAAS,CAKjF;AAWD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,QAAQ,CAK/E"}
1
+ {"version":3,"file":"RevisionContent.d.ts","sourceRoot":"","sources":["../../src/elements/RevisionContent.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAU3C,MAAM,MAAM,eAAe,GAAG,GAAG,GAAG,QAAQ,GAAG,SAAS,CAAC;AAUzD,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,GAAG,CAQrE;AAUD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,SAAS,CAKjF;AAWD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,IAAI,QAAQ,CAK/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionContent.js","sourceRoot":"","sources":["../../src/elements/RevisionContent.ts"],"names":[],"mappings":";;AAmCA,oCAQC;AAUD,gDAKC;AAWD,8CAKC;AAvCD,SAAgB,YAAY,CAAC,OAAwB;IACnD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,MAAM,UAAU,GAAG,OAAQ,OAAe,CAAC,OAAO,KAAK,UAAU,CAAC;IAClE,MAAM,SAAS,GAAG,OAAQ,OAAe,CAAC,MAAM,KAAK,UAAU,CAAC;IAEhE,OAAO,UAAU,IAAI,CAAC,SAAS,CAAC;AAClC,CAAC;AAUD,SAAgB,kBAAkB,CAAC,OAAwB;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,OAAO,OAAQ,OAAe,CAAC,MAAM,KAAK,UAAU,CAAC;AACvD,CAAC;AAWD,SAAgB,iBAAiB,CAAC,OAAwB;IACxD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,OAAO,OAAQ,OAAe,CAAC,eAAe,KAAK,UAAU,CAAC;AAChE,CAAC","sourcesContent":["/**\n * RevisionContent - Defines valid content types for tracked changes (revisions)\n *\n * Per ECMA-376, w:ins and w:del elements can contain:\n * - w:r (runs) - Text with formatting\n * - w:r with w:drawing (image runs) - Images embedded in runs\n * - w:hyperlink - Hyperlinks with nested runs\n *\n * This module provides the type definitions and type guards for revision content.\n */\n\nimport type { Run } from './Run';\nimport type { Hyperlink } from './Hyperlink';\nimport type { ImageRun } from './ImageRun';\nimport type { ComplexField } from './Field';\n\n/**\n * Content types valid within a revision (tracked change)\n *\n * Per ECMA-376 Part 1 section 17.13.5, revision elements can contain:\n * - Run elements (w:r) - the most common case\n * - ImageRun elements (w:r with w:drawing) - for tracked image changes\n * - Hyperlink elements (w:hyperlink) - for tracked hyperlink changes\n * - ComplexField elements (w:fldChar sequences) - for tracked field code changes\n */\nexport type RevisionContent = Run | ImageRun | Hyperlink | ComplexField;\n\n/**\n * Type guard to check if content is a Run\n * @param content - The content to check\n * @returns true if content is a Run instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * Run objects have getText() but NOT getUrl() or getAnchor() methods.\n */\nexport function isRunContent(content: RevisionContent): content is Run {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: Runs have getText but no getUrl\n const hasGetText = typeof (content as any).getText === 'function';\n const hasGetUrl = typeof (content as any).getUrl === 'function';\n\n return hasGetText && !hasGetUrl;\n}\n\n/**\n * Type guard to check if content is a Hyperlink\n * @param content - The content to check\n * @returns true if content is a Hyperlink instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * Hyperlink objects have getUrl() method which Runs don't have.\n */\nexport function isHyperlinkContent(content: RevisionContent): content is Hyperlink {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: Hyperlinks have getUrl method\n return typeof (content as any).getUrl === 'function';\n}\n\n/**\n * Type guard to check if content is an ImageRun\n * @param content - The content to check\n * @returns true if content is an ImageRun instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * ImageRun objects have getImageElement() method which regular Runs don't have.\n * This check should be performed BEFORE isRunContent() since ImageRun extends Run.\n */\nexport function isImageRunContent(content: RevisionContent): content is ImageRun {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: ImageRun has getImageElement method which regular Run doesn't have\n return typeof (content as any).getImageElement === 'function';\n}\n"]}
1
+ {"version":3,"file":"RevisionContent.js","sourceRoot":"","sources":["../../src/elements/RevisionContent.ts"],"names":[],"mappings":";;AAiCA,oCAQC;AAUD,gDAKC;AAWD,8CAKC;AAvCD,SAAgB,YAAY,CAAC,OAAwB;IACnD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,MAAM,UAAU,GAAG,OAAQ,OAAe,CAAC,OAAO,KAAK,UAAU,CAAC;IAClE,MAAM,SAAS,GAAG,OAAQ,OAAe,CAAC,MAAM,KAAK,UAAU,CAAC;IAEhE,OAAO,UAAU,IAAI,CAAC,SAAS,CAAC;AAClC,CAAC;AAUD,SAAgB,kBAAkB,CAAC,OAAwB;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,OAAO,OAAQ,OAAe,CAAC,MAAM,KAAK,UAAU,CAAC;AACvD,CAAC;AAWD,SAAgB,iBAAiB,CAAC,OAAwB;IACxD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAG1D,OAAO,OAAQ,OAAe,CAAC,eAAe,KAAK,UAAU,CAAC;AAChE,CAAC","sourcesContent":["/**\n * RevisionContent - Defines valid content types for tracked changes (revisions)\n *\n * Per ECMA-376, w:ins and w:del elements can contain:\n * - w:r (runs) Text with formatting\n * - w:r with w:drawing (image runs) Images embedded in runs\n * - w:hyperlink Hyperlinks with nested runs\n *\n * This module provides the type definitions and type guards for revision content.\n */\n\nimport type { Run } from './Run';\nimport type { Hyperlink } from './Hyperlink';\nimport type { ImageRun } from './ImageRun';\n\n/**\n * Content types valid within a revision (tracked change)\n *\n * Per ECMA-376 Part 1 section 17.13.5, revision elements can contain:\n * - Run elements (w:r) - the most common case\n * - ImageRun elements (w:r with w:drawing) - for tracked image changes\n * - Hyperlink elements (w:hyperlink) - for tracked hyperlink changes\n */\nexport type RevisionContent = Run | ImageRun | Hyperlink;\n\n/**\n * Type guard to check if content is a Run\n * @param content - The content to check\n * @returns true if content is a Run instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * Run objects have getText() but NOT getUrl() or getAnchor() methods.\n */\nexport function isRunContent(content: RevisionContent): content is Run {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: Runs have getText but no getUrl\n const hasGetText = typeof (content as any).getText === 'function';\n const hasGetUrl = typeof (content as any).getUrl === 'function';\n\n return hasGetText && !hasGetUrl;\n}\n\n/**\n * Type guard to check if content is a Hyperlink\n * @param content - The content to check\n * @returns true if content is a Hyperlink instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * Hyperlink objects have getUrl() method which Runs don't have.\n */\nexport function isHyperlinkContent(content: RevisionContent): content is Hyperlink {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: Hyperlinks have getUrl method\n return typeof (content as any).getUrl === 'function';\n}\n\n/**\n * Type guard to check if content is an ImageRun\n * @param content - The content to check\n * @returns true if content is an ImageRun instance\n *\n * Note: Uses duck typing instead of constructor.name to handle minified builds.\n * ImageRun objects have getImageElement() method which regular Runs don't have.\n * This check should be performed BEFORE isRunContent() since ImageRun extends Run.\n */\nexport function isImageRunContent(content: RevisionContent): content is ImageRun {\n if (!content || typeof content !== 'object') return false;\n\n // Duck typing: ImageRun has getImageElement method which regular Run doesn't have\n return typeof (content as any).getImageElement === 'function';\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docxmlater",
3
- "version": "10.2.5",
3
+ "version": "10.2.7",
4
4
  "description": "A comprehensive DOCX editing framework for creating, reading, and manipulating Microsoft Word documents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -3089,8 +3089,17 @@ export class DocumentParser {
3089
3089
  fieldState = null;
3090
3090
  groupedContent.push(item);
3091
3091
  } else {
3092
- // Normal revision outside of any field
3093
- groupedContent.push(item);
3092
+ // Normal revision outside of any field — check if it contains a complete
3093
+ // field code sequence (Scenario A: entire HYPERLINK fldChar sequence inside w:ins).
3094
+ // parseRevisionFromXml() creates individual Runs from the fldChar/instrText/result
3095
+ // elements, but assembleComplexFields() only sees the Revision wrapper.
3096
+ // Promote complete field code sequences to ComplexField at the paragraph level.
3097
+ const promoted = this.tryPromoteRevisionFieldCode(item);
3098
+ if (promoted) {
3099
+ groupedContent.push(promoted);
3100
+ } else {
3101
+ groupedContent.push(item);
3102
+ }
3094
3103
  }
3095
3104
  } else {
3096
3105
  // Non-run content (hyperlinks, images, etc.)
@@ -3547,6 +3556,49 @@ export class DocumentParser {
3547
3556
  );
3548
3557
  }
3549
3558
 
3559
+ /**
3560
+ * Checks if a Revision contains a complete field code sequence (fldChar begin → instrText →
3561
+ * fldChar separate → result text → fldChar end) and promotes it to a ComplexField.
3562
+ *
3563
+ * This handles the case where an entire HYPERLINK field code is inside a tracked change
3564
+ * (w:ins), producing Runs with fldChar tokens inside the Revision. Since assembleComplexFields()
3565
+ * only sees the Revision wrapper (not the Runs inside), the field code is never assembled.
3566
+ *
3567
+ * @returns ComplexField if promotion succeeded, null otherwise
3568
+ */
3569
+ private tryPromoteRevisionFieldCode(revision: Revision): ComplexField | null {
3570
+ const content = revision.getContent();
3571
+
3572
+ // Quick check: need at least 3 runs (begin, instr/separate, end)
3573
+ const runs = content.filter((c): c is Run => c instanceof Run);
3574
+ if (runs.length < 3) return null;
3575
+
3576
+ // Check if the runs contain a complete field code sequence
3577
+ let hasBegin = false;
3578
+ let hasEnd = false;
3579
+ for (const run of runs) {
3580
+ const rc = run.getContent();
3581
+ const fc = rc.find((c) => c.type === 'fieldChar');
3582
+ if (fc?.fieldCharType === 'begin') hasBegin = true;
3583
+ if (fc?.fieldCharType === 'end') hasEnd = true;
3584
+ }
3585
+ if (!hasBegin || !hasEnd) return null;
3586
+
3587
+ // Assemble the field from the revision's runs
3588
+ const complexField = this.createComplexFieldFromRuns(runs);
3589
+ if (!complexField) return null;
3590
+
3591
+ // Only promote HYPERLINK fields — other field types inside revisions
3592
+ // are uncommon and preserving the revision wrapper is safer
3593
+ if (!complexField.isHyperlinkField()) return null;
3594
+
3595
+ defaultLogger.debug(
3596
+ `Promoted HYPERLINK field code from inside ${revision.getType()} revision (id=${revision.getId()}) to ComplexField`
3597
+ );
3598
+
3599
+ return complexField;
3600
+ }
3601
+
3550
3602
  /**
3551
3603
  * NEW: Create ComplexField from sequence of field runs
3552
3604
  * Extracts instruction from instrText runs and result from text runs
@@ -2,9 +2,9 @@
2
2
  * RevisionContent - Defines valid content types for tracked changes (revisions)
3
3
  *
4
4
  * Per ECMA-376, w:ins and w:del elements can contain:
5
- * - w:r (runs) - Text with formatting
6
- * - w:r with w:drawing (image runs) - Images embedded in runs
7
- * - w:hyperlink - Hyperlinks with nested runs
5
+ * - w:r (runs) Text with formatting
6
+ * - w:r with w:drawing (image runs) Images embedded in runs
7
+ * - w:hyperlink Hyperlinks with nested runs
8
8
  *
9
9
  * This module provides the type definitions and type guards for revision content.
10
10
  */
@@ -12,7 +12,6 @@
12
12
  import type { Run } from './Run';
13
13
  import type { Hyperlink } from './Hyperlink';
14
14
  import type { ImageRun } from './ImageRun';
15
- import type { ComplexField } from './Field';
16
15
 
17
16
  /**
18
17
  * Content types valid within a revision (tracked change)
@@ -21,9 +20,8 @@ import type { ComplexField } from './Field';
21
20
  * - Run elements (w:r) - the most common case
22
21
  * - ImageRun elements (w:r with w:drawing) - for tracked image changes
23
22
  * - Hyperlink elements (w:hyperlink) - for tracked hyperlink changes
24
- * - ComplexField elements (w:fldChar sequences) - for tracked field code changes
25
23
  */
26
- export type RevisionContent = Run | ImageRun | Hyperlink | ComplexField;
24
+ export type RevisionContent = Run | ImageRun | Hyperlink;
27
25
 
28
26
  /**
29
27
  * Type guard to check if content is a Run