docxmlater 11.0.10 → 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 +427 -81
- 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 +427 -81
- 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 +681 -114
- 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
package/src/elements/Revision.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { Run } from './Run.js';
|
|
9
9
|
import type { RunFormatting } from './Run.js';
|
|
10
|
-
import { XMLElement } from '../xml/XMLBuilder.js';
|
|
10
|
+
import { XMLBuilder, XMLElement } from '../xml/XMLBuilder.js';
|
|
11
11
|
import type { RevisionLocation } from './PropertyChangeTypes.js';
|
|
12
12
|
import type { RevisionContent } from './RevisionContent.js';
|
|
13
13
|
import { isRunContent, isHyperlinkContent } from './RevisionContent.js';
|
|
@@ -477,16 +477,22 @@ export class Revision {
|
|
|
477
477
|
* - w:date: When the change was made (ST_DateTime, ISO 8601) - OPTIONAL
|
|
478
478
|
*
|
|
479
479
|
* **Move Operations:**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
* ```
|
|
480
|
+
* w:moveFrom/w:moveTo are CT_RunTrackChange and carry only w:id/w:author/w:date.
|
|
481
|
+
* The moveId field stays in-memory pairing metadata (getMovePair/validateMovePairs);
|
|
482
|
+
* on disk, source/destination linkage is expressed solely via the w:name attribute
|
|
483
|
+
* on w:moveFromRangeStart/w:moveToRangeStart (see RangeMarker.toXML()).
|
|
485
484
|
*
|
|
486
485
|
* **Content vs Property Changes:**
|
|
487
486
|
* - Content revisions (insert/delete/move): Contain w:r elements with text runs
|
|
488
487
|
* - Property revisions (rPrChange/pPrChange): Contain previous property elements (w:rPr, w:pPr)
|
|
489
488
|
*
|
|
489
|
+
* **Hyperlink Content:**
|
|
490
|
+
* w:hyperlink is not a valid child of CT_RunTrackChange, so hyperlink content is
|
|
491
|
+
* serialized with inverted nesting (<w:hyperlink><w:ins>...</w:ins></w:hyperlink>).
|
|
492
|
+
* Mixed Run + Hyperlink content produces sibling elements (one revision element per
|
|
493
|
+
* run group, one hyperlink-wrapped revision element per link), returned as a single
|
|
494
|
+
* raw-XML fragment element that XMLBuilder emits verbatim.
|
|
495
|
+
*
|
|
490
496
|
* @returns XMLElement representing the revision in OOXML format, or null for internal-only types
|
|
491
497
|
* @see ECMA-376 Part 1 §17.13.5 (Revision Identifiers for Paragraph Content)
|
|
492
498
|
* @see ECMA-376 Part 1 §17.13.5.15 (Inserted Paragraph)
|
|
@@ -515,10 +521,9 @@ export class Revision {
|
|
|
515
521
|
'w:date': this.formatDate(this.date),
|
|
516
522
|
};
|
|
517
523
|
|
|
518
|
-
//
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
524
|
+
// moveId is intentionally NOT serialized: ECMA-376 CT_RunTrackChange declares no
|
|
525
|
+
// such attribute, and an undeclared w: attribute fails Open XML schema validation.
|
|
526
|
+
// On-disk move pairing is carried by w:name on the move range start markers.
|
|
522
527
|
|
|
523
528
|
const elementName = this.getElementName();
|
|
524
529
|
const children: XMLElement[] = [];
|
|
@@ -531,43 +536,84 @@ export class Revision {
|
|
|
531
536
|
}
|
|
532
537
|
}
|
|
533
538
|
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
+
// Per ECMA-376, w:hyperlink is NOT a valid child of w:ins/w:del (CT_RunTrackChange);
|
|
540
|
+
// the nesting must be inverted so w:ins/w:del sits inside w:hyperlink. Content is
|
|
541
|
+
// therefore split into sibling segments: each consecutive run group gets its own
|
|
542
|
+
// revision element and each hyperlink wraps its own revision element, preserving
|
|
543
|
+
// the link target (r:id/w:anchor) instead of downgrading it to plain runs.
|
|
544
|
+
if (!this.isPropertyChangeType()) {
|
|
545
|
+
const segments: XMLElement[] = [];
|
|
546
|
+
// CT_TrackChange requires a document-unique w:id, so sibling segments
|
|
547
|
+
// cannot share the revision's id. Extra segments derive ids from a high
|
|
548
|
+
// base (deterministic, stable across saves) that cannot collide with the
|
|
549
|
+
// small sequential ids RevisionManager issues.
|
|
550
|
+
const segmentAttributes = (segmentIndex: number): Record<string, string> =>
|
|
551
|
+
segmentIndex === 0
|
|
552
|
+
? attributes
|
|
553
|
+
: {
|
|
554
|
+
...attributes,
|
|
555
|
+
'w:id': String(500000000 + (this.id % 1000000) * 1000 + segmentIndex),
|
|
556
|
+
};
|
|
557
|
+
let pendingRuns: XMLElement[] = [];
|
|
558
|
+
const flushRuns = (): void => {
|
|
559
|
+
if (pendingRuns.length > 0) {
|
|
560
|
+
segments.push({
|
|
561
|
+
name: elementName,
|
|
562
|
+
attributes: segmentAttributes(segments.length),
|
|
563
|
+
children: pendingRuns,
|
|
564
|
+
});
|
|
565
|
+
pendingRuns = [];
|
|
566
|
+
}
|
|
567
|
+
};
|
|
539
568
|
|
|
540
|
-
|
|
541
|
-
|
|
569
|
+
for (const item of this.content) {
|
|
570
|
+
if (isHyperlinkContent(item)) {
|
|
571
|
+
flushRuns();
|
|
572
|
+
segments.push(
|
|
573
|
+
this.createHyperlinkWrappedRevisionXml(
|
|
574
|
+
item,
|
|
575
|
+
elementName,
|
|
576
|
+
segmentAttributes(segments.length)
|
|
577
|
+
)
|
|
578
|
+
);
|
|
579
|
+
} else if (isRunContent(item)) {
|
|
580
|
+
if (this.type === 'delete' || this.type === 'moveFrom') {
|
|
581
|
+
pendingRuns.push(this.createDeletedRunXml(item));
|
|
582
|
+
} else {
|
|
583
|
+
pendingRuns.push(item.toXML());
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
flushRuns();
|
|
588
|
+
|
|
589
|
+
if (segments.length === 0) {
|
|
590
|
+
return { name: elementName, attributes, children: [] };
|
|
591
|
+
}
|
|
592
|
+
if (segments.length === 1) {
|
|
593
|
+
return segments[0]!;
|
|
594
|
+
}
|
|
595
|
+
// Multiple sibling elements cannot share one XML root; emit them as a
|
|
596
|
+
// pre-serialized fragment that XMLBuilder passes through verbatim.
|
|
597
|
+
return {
|
|
598
|
+
name: '__rawXml',
|
|
599
|
+
rawXml: segments.map((segment) => XMLBuilder.elementToString(segment)).join(''),
|
|
600
|
+
};
|
|
542
601
|
}
|
|
543
602
|
|
|
544
|
-
//
|
|
603
|
+
// Property change revisions keep their content runs alongside the
|
|
604
|
+
// previous-properties element
|
|
545
605
|
for (const item of this.content) {
|
|
546
606
|
if (isHyperlinkContent(item)) {
|
|
547
|
-
// For multiple-item revisions containing hyperlinks, extract the runs
|
|
548
|
-
// and add them directly (hyperlink wrapper omitted to maintain validity)
|
|
549
607
|
const hyperlinkXml = item.toXML();
|
|
550
608
|
if (hyperlinkXml.children) {
|
|
551
609
|
for (const child of hyperlinkXml.children) {
|
|
552
610
|
if (typeof child === 'object' && child.name === 'w:r') {
|
|
553
|
-
|
|
554
|
-
children.push(this.convertRunXmlToDeleted(child));
|
|
555
|
-
} else {
|
|
556
|
-
children.push(child);
|
|
557
|
-
}
|
|
611
|
+
children.push(child);
|
|
558
612
|
}
|
|
559
613
|
}
|
|
560
614
|
}
|
|
561
615
|
} else if (isRunContent(item)) {
|
|
562
|
-
|
|
563
|
-
if (this.type === 'delete' || this.type === 'moveFrom') {
|
|
564
|
-
// For deletions and moveFrom, we need to modify the run XML to use w:delText instead of w:t
|
|
565
|
-
const runXml = this.createDeletedRunXml(item);
|
|
566
|
-
children.push(runXml);
|
|
567
|
-
} else {
|
|
568
|
-
// For other types, use normal run XML
|
|
569
|
-
children.push(item.toXML());
|
|
570
|
-
}
|
|
616
|
+
children.push(item.toXML());
|
|
571
617
|
}
|
|
572
618
|
}
|
|
573
619
|
|
|
@@ -647,8 +693,11 @@ export class Revision {
|
|
|
647
693
|
*
|
|
648
694
|
* **Implementation:**
|
|
649
695
|
* This method converts the previousProperties object into OOXML elements.
|
|
650
|
-
* -
|
|
651
|
-
* -
|
|
696
|
+
* - runPropertiesChange delegates to Run.generateRunPropertiesXML
|
|
697
|
+
* - Other types translate API-style keys to their schema local names
|
|
698
|
+
* (e.g., alignment → w:jc), serialize known object values (spacing,
|
|
699
|
+
* indentation, borders, shading, table widths), and order children
|
|
700
|
+
* per the schema sequence of the containing property element
|
|
652
701
|
*
|
|
653
702
|
* @returns XMLElement containing previous properties (w:rPr, w:pPr, etc.)
|
|
654
703
|
* @see ECMA-376 Part 1 §17.13.5.31 (Run Properties Change)
|
|
@@ -692,24 +741,31 @@ export class Revision {
|
|
|
692
741
|
break;
|
|
693
742
|
}
|
|
694
743
|
|
|
695
|
-
// Build property children from previousProperties
|
|
744
|
+
// Build property children from previousProperties, translating API-style
|
|
745
|
+
// keys to their OOXML local names (keys already given as local names pass
|
|
746
|
+
// through unchanged)
|
|
747
|
+
const keyMap = Revision.PROPERTY_KEY_TO_ELEMENT[this.type] ?? {};
|
|
696
748
|
const propChildren: XMLElement[] = [];
|
|
697
749
|
if (this.previousProperties) {
|
|
698
750
|
for (const [key, value] of Object.entries(this.previousProperties)) {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
propChildren.push(
|
|
702
|
-
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
703
|
-
// Value properties (e.g., font size, color)
|
|
704
|
-
propChildren.push({
|
|
705
|
-
name: `w:${key}`,
|
|
706
|
-
attributes: { 'w:val': value.toString() },
|
|
707
|
-
children: [],
|
|
708
|
-
});
|
|
751
|
+
const child = this.createPreviousPropertyXml(`w:${keyMap[key] ?? key}`, value);
|
|
752
|
+
if (child) {
|
|
753
|
+
propChildren.push(child);
|
|
709
754
|
}
|
|
710
755
|
}
|
|
711
756
|
}
|
|
712
757
|
|
|
758
|
+
// CT_PPrBase, CT_TblPrBase, CT_TrPr, CT_TcPr and CT_SectPr are xsd:sequence
|
|
759
|
+
// types, so children must follow the declared order to stay schema-valid
|
|
760
|
+
const order = Revision.PROPERTY_CHILD_ORDER[propElementName];
|
|
761
|
+
if (order) {
|
|
762
|
+
const rank = (name: string): number => {
|
|
763
|
+
const index = order.indexOf(name);
|
|
764
|
+
return index === -1 ? order.length : index;
|
|
765
|
+
};
|
|
766
|
+
propChildren.sort((a, b) => rank(a.name) - rank(b.name));
|
|
767
|
+
}
|
|
768
|
+
|
|
713
769
|
return {
|
|
714
770
|
name: propElementName,
|
|
715
771
|
attributes: {},
|
|
@@ -717,6 +773,349 @@ export class Revision {
|
|
|
717
773
|
};
|
|
718
774
|
}
|
|
719
775
|
|
|
776
|
+
/**
|
|
777
|
+
* API-key → OOXML local-name translations for property-change snapshots.
|
|
778
|
+
* previousProperties accepts the same key names as the element formatting
|
|
779
|
+
* APIs (e.g. ParagraphFormatting.alignment); the schema requires the local
|
|
780
|
+
* element names (w:jc), so keys are translated before serialization.
|
|
781
|
+
*/
|
|
782
|
+
private static readonly PROPERTY_KEY_TO_ELEMENT: Partial<
|
|
783
|
+
Record<RevisionType, Record<string, string>>
|
|
784
|
+
> = {
|
|
785
|
+
paragraphPropertiesChange: {
|
|
786
|
+
alignment: 'jc',
|
|
787
|
+
style: 'pStyle',
|
|
788
|
+
styleId: 'pStyle',
|
|
789
|
+
indentation: 'ind',
|
|
790
|
+
numbering: 'numPr',
|
|
791
|
+
outlineLevel: 'outlineLvl',
|
|
792
|
+
shading: 'shd',
|
|
793
|
+
borders: 'pBdr',
|
|
794
|
+
},
|
|
795
|
+
tablePropertiesChange: {
|
|
796
|
+
alignment: 'jc',
|
|
797
|
+
style: 'tblStyle',
|
|
798
|
+
styleId: 'tblStyle',
|
|
799
|
+
width: 'tblW',
|
|
800
|
+
indent: 'tblInd',
|
|
801
|
+
borders: 'tblBorders',
|
|
802
|
+
shading: 'shd',
|
|
803
|
+
layout: 'tblLayout',
|
|
804
|
+
cellMargins: 'tblCellMar',
|
|
805
|
+
cellSpacing: 'tblCellSpacing',
|
|
806
|
+
},
|
|
807
|
+
tableExceptionPropertiesChange: {
|
|
808
|
+
alignment: 'jc',
|
|
809
|
+
width: 'tblW',
|
|
810
|
+
indent: 'tblInd',
|
|
811
|
+
borders: 'tblBorders',
|
|
812
|
+
shading: 'shd',
|
|
813
|
+
layout: 'tblLayout',
|
|
814
|
+
cellMargins: 'tblCellMar',
|
|
815
|
+
cellSpacing: 'tblCellSpacing',
|
|
816
|
+
},
|
|
817
|
+
tableRowPropertiesChange: {
|
|
818
|
+
alignment: 'jc',
|
|
819
|
+
height: 'trHeight',
|
|
820
|
+
isHeader: 'tblHeader',
|
|
821
|
+
cellSpacing: 'tblCellSpacing',
|
|
822
|
+
},
|
|
823
|
+
tableCellPropertiesChange: {
|
|
824
|
+
width: 'tcW',
|
|
825
|
+
borders: 'tcBorders',
|
|
826
|
+
shading: 'shd',
|
|
827
|
+
verticalAlignment: 'vAlign',
|
|
828
|
+
margins: 'tcMar',
|
|
829
|
+
},
|
|
830
|
+
sectionPropertiesChange: {
|
|
831
|
+
pageSize: 'pgSz',
|
|
832
|
+
margins: 'pgMar',
|
|
833
|
+
columns: 'cols',
|
|
834
|
+
pageNumbering: 'pgNumType',
|
|
835
|
+
},
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Schema child order for property snapshot containers (xsd:sequence order
|
|
840
|
+
* from the corresponding CT_* types). Unknown children sort after known ones.
|
|
841
|
+
*/
|
|
842
|
+
private static readonly PROPERTY_CHILD_ORDER: Record<string, readonly string[]> = {
|
|
843
|
+
'w:pPr': [
|
|
844
|
+
'w:pStyle',
|
|
845
|
+
'w:keepNext',
|
|
846
|
+
'w:keepLines',
|
|
847
|
+
'w:pageBreakBefore',
|
|
848
|
+
'w:framePr',
|
|
849
|
+
'w:widowControl',
|
|
850
|
+
'w:numPr',
|
|
851
|
+
'w:suppressLineNumbers',
|
|
852
|
+
'w:pBdr',
|
|
853
|
+
'w:shd',
|
|
854
|
+
'w:tabs',
|
|
855
|
+
'w:suppressAutoHyphens',
|
|
856
|
+
'w:kinsoku',
|
|
857
|
+
'w:wordWrap',
|
|
858
|
+
'w:overflowPunct',
|
|
859
|
+
'w:topLinePunct',
|
|
860
|
+
'w:autoSpaceDE',
|
|
861
|
+
'w:autoSpaceDN',
|
|
862
|
+
'w:bidi',
|
|
863
|
+
'w:adjustRightInd',
|
|
864
|
+
'w:snapToGrid',
|
|
865
|
+
'w:spacing',
|
|
866
|
+
'w:ind',
|
|
867
|
+
'w:contextualSpacing',
|
|
868
|
+
'w:mirrorIndents',
|
|
869
|
+
'w:suppressOverlap',
|
|
870
|
+
'w:jc',
|
|
871
|
+
'w:textDirection',
|
|
872
|
+
'w:textAlignment',
|
|
873
|
+
'w:textboxTightWrap',
|
|
874
|
+
'w:outlineLvl',
|
|
875
|
+
],
|
|
876
|
+
'w:tblPr': [
|
|
877
|
+
'w:tblStyle',
|
|
878
|
+
'w:tblpPr',
|
|
879
|
+
'w:tblOverlap',
|
|
880
|
+
'w:bidiVisual',
|
|
881
|
+
'w:tblStyleRowBandSize',
|
|
882
|
+
'w:tblStyleColBandSize',
|
|
883
|
+
'w:tblW',
|
|
884
|
+
'w:jc',
|
|
885
|
+
'w:tblCellSpacing',
|
|
886
|
+
'w:tblInd',
|
|
887
|
+
'w:tblBorders',
|
|
888
|
+
'w:shd',
|
|
889
|
+
'w:tblLayout',
|
|
890
|
+
'w:tblCellMar',
|
|
891
|
+
'w:tblLook',
|
|
892
|
+
'w:tblCaption',
|
|
893
|
+
'w:tblDescription',
|
|
894
|
+
],
|
|
895
|
+
'w:tblPrEx': [
|
|
896
|
+
'w:tblW',
|
|
897
|
+
'w:jc',
|
|
898
|
+
'w:tblCellSpacing',
|
|
899
|
+
'w:tblInd',
|
|
900
|
+
'w:tblBorders',
|
|
901
|
+
'w:shd',
|
|
902
|
+
'w:tblLayout',
|
|
903
|
+
'w:tblCellMar',
|
|
904
|
+
'w:tblLook',
|
|
905
|
+
],
|
|
906
|
+
'w:trPr': [
|
|
907
|
+
'w:cnfStyle',
|
|
908
|
+
'w:divId',
|
|
909
|
+
'w:gridBefore',
|
|
910
|
+
'w:gridAfter',
|
|
911
|
+
'w:wBefore',
|
|
912
|
+
'w:wAfter',
|
|
913
|
+
'w:cantSplit',
|
|
914
|
+
'w:trHeight',
|
|
915
|
+
'w:tblHeader',
|
|
916
|
+
'w:tblCellSpacing',
|
|
917
|
+
'w:jc',
|
|
918
|
+
'w:hidden',
|
|
919
|
+
],
|
|
920
|
+
'w:tcPr': [
|
|
921
|
+
'w:cnfStyle',
|
|
922
|
+
'w:tcW',
|
|
923
|
+
'w:gridSpan',
|
|
924
|
+
'w:hMerge',
|
|
925
|
+
'w:vMerge',
|
|
926
|
+
'w:tcBorders',
|
|
927
|
+
'w:shd',
|
|
928
|
+
'w:noWrap',
|
|
929
|
+
'w:tcMar',
|
|
930
|
+
'w:textDirection',
|
|
931
|
+
'w:tcFitText',
|
|
932
|
+
'w:vAlign',
|
|
933
|
+
'w:hideMark',
|
|
934
|
+
],
|
|
935
|
+
'w:sectPr': [
|
|
936
|
+
'w:headerReference',
|
|
937
|
+
'w:footerReference',
|
|
938
|
+
'w:footnotePr',
|
|
939
|
+
'w:endnotePr',
|
|
940
|
+
'w:type',
|
|
941
|
+
'w:pgSz',
|
|
942
|
+
'w:pgMar',
|
|
943
|
+
'w:paperSrc',
|
|
944
|
+
'w:pgBorders',
|
|
945
|
+
'w:lnNumType',
|
|
946
|
+
'w:pgNumType',
|
|
947
|
+
'w:cols',
|
|
948
|
+
'w:formProt',
|
|
949
|
+
'w:vAlign',
|
|
950
|
+
'w:noEndnote',
|
|
951
|
+
'w:titlePg',
|
|
952
|
+
'w:textDirection',
|
|
953
|
+
'w:bidi',
|
|
954
|
+
'w:rtlGutter',
|
|
955
|
+
'w:docGrid',
|
|
956
|
+
],
|
|
957
|
+
'w:numPr': ['w:ilvl', 'w:numId', 'w:numberingChange', 'w:ins'],
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Serializes one previous-property entry to its OOXML element.
|
|
962
|
+
* Booleans follow the CT_OnOff convention (true = on, false = explicit off
|
|
963
|
+
* via w:val="0") so the snapshot keeps the same tri-state information the
|
|
964
|
+
* main property serializers emit.
|
|
965
|
+
*/
|
|
966
|
+
private createPreviousPropertyXml(name: string, value: unknown): XMLElement | null {
|
|
967
|
+
if (typeof value === 'boolean') {
|
|
968
|
+
return { name, attributes: value ? {} : { 'w:val': '0' }, children: [] };
|
|
969
|
+
}
|
|
970
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
971
|
+
return { name, attributes: { 'w:val': value.toString() }, children: [] };
|
|
972
|
+
}
|
|
973
|
+
if (value && typeof value === 'object') {
|
|
974
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- previousProperties is Record<string, any>
|
|
975
|
+
return this.createObjectPropertyXml(name, value as Record<string, any>);
|
|
976
|
+
}
|
|
977
|
+
return null;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Serializes object-valued previous properties (complex OOXML structures).
|
|
982
|
+
* Only shapes with a known schema mapping are emitted; unknown objects are
|
|
983
|
+
* skipped because their attribute layout cannot be inferred safely.
|
|
984
|
+
*/
|
|
985
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- previousProperties is Record<string, any>
|
|
986
|
+
private createObjectPropertyXml(name: string, value: Record<string, any>): XMLElement | null {
|
|
987
|
+
switch (name) {
|
|
988
|
+
case 'w:spacing':
|
|
989
|
+
return {
|
|
990
|
+
name,
|
|
991
|
+
attributes: XMLBuilder.buildAttributes({
|
|
992
|
+
'w:before': value.before,
|
|
993
|
+
'w:beforeLines': value.beforeLines,
|
|
994
|
+
'w:beforeAutospacing':
|
|
995
|
+
value.beforeAutospacing === undefined
|
|
996
|
+
? undefined
|
|
997
|
+
: value.beforeAutospacing
|
|
998
|
+
? '1'
|
|
999
|
+
: '0',
|
|
1000
|
+
'w:after': value.after,
|
|
1001
|
+
'w:afterLines': value.afterLines,
|
|
1002
|
+
'w:afterAutospacing':
|
|
1003
|
+
value.afterAutospacing === undefined ? undefined : value.afterAutospacing ? '1' : '0',
|
|
1004
|
+
'w:line': value.line,
|
|
1005
|
+
'w:lineRule': value.lineRule,
|
|
1006
|
+
}),
|
|
1007
|
+
children: [],
|
|
1008
|
+
};
|
|
1009
|
+
case 'w:ind':
|
|
1010
|
+
return {
|
|
1011
|
+
name,
|
|
1012
|
+
attributes: XMLBuilder.buildAttributes({
|
|
1013
|
+
'w:start': value.start,
|
|
1014
|
+
'w:end': value.end,
|
|
1015
|
+
'w:left': value.left,
|
|
1016
|
+
'w:leftChars': value.leftChars,
|
|
1017
|
+
'w:right': value.right,
|
|
1018
|
+
'w:rightChars': value.rightChars,
|
|
1019
|
+
'w:firstLine': value.firstLine,
|
|
1020
|
+
'w:firstLineChars': value.firstLineChars,
|
|
1021
|
+
'w:hanging': value.hanging,
|
|
1022
|
+
'w:hangingChars': value.hangingChars,
|
|
1023
|
+
}),
|
|
1024
|
+
children: [],
|
|
1025
|
+
};
|
|
1026
|
+
case 'w:numPr': {
|
|
1027
|
+
const numPrChildren: XMLElement[] = [];
|
|
1028
|
+
const level = value.level ?? value.ilvl;
|
|
1029
|
+
const numId = value.numId ?? value.id;
|
|
1030
|
+
if (level !== undefined) {
|
|
1031
|
+
numPrChildren.push({
|
|
1032
|
+
name: 'w:ilvl',
|
|
1033
|
+
attributes: { 'w:val': String(level) },
|
|
1034
|
+
children: [],
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
if (numId !== undefined) {
|
|
1038
|
+
numPrChildren.push({
|
|
1039
|
+
name: 'w:numId',
|
|
1040
|
+
attributes: { 'w:val': String(numId) },
|
|
1041
|
+
children: [],
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
return numPrChildren.length > 0 ? { name, attributes: {}, children: numPrChildren } : null;
|
|
1045
|
+
}
|
|
1046
|
+
case 'w:shd':
|
|
1047
|
+
return XMLBuilder.createShading(value);
|
|
1048
|
+
case 'w:pBdr':
|
|
1049
|
+
case 'w:tblBorders':
|
|
1050
|
+
case 'w:tcBorders': {
|
|
1051
|
+
const sides =
|
|
1052
|
+
name === 'w:pBdr'
|
|
1053
|
+
? ['top', 'left', 'bottom', 'right', 'between', 'bar']
|
|
1054
|
+
: ['top', 'left', 'bottom', 'right', 'insideH', 'insideV'];
|
|
1055
|
+
const borderChildren: XMLElement[] = [];
|
|
1056
|
+
for (const side of sides) {
|
|
1057
|
+
if (value[side]) {
|
|
1058
|
+
borderChildren.push(XMLBuilder.createBorder(side, value[side]));
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
return borderChildren.length > 0
|
|
1062
|
+
? { name, attributes: {}, children: borderChildren }
|
|
1063
|
+
: null;
|
|
1064
|
+
}
|
|
1065
|
+
case 'w:tblW':
|
|
1066
|
+
case 'w:tcW':
|
|
1067
|
+
case 'w:tblInd':
|
|
1068
|
+
case 'w:tblCellSpacing':
|
|
1069
|
+
return {
|
|
1070
|
+
name,
|
|
1071
|
+
attributes: XMLBuilder.buildAttributes({
|
|
1072
|
+
'w:w': value.w ?? value.width ?? value.value,
|
|
1073
|
+
'w:type': value.type ?? 'dxa',
|
|
1074
|
+
}),
|
|
1075
|
+
children: [],
|
|
1076
|
+
};
|
|
1077
|
+
case 'w:trHeight':
|
|
1078
|
+
return {
|
|
1079
|
+
name,
|
|
1080
|
+
attributes: XMLBuilder.buildAttributes({
|
|
1081
|
+
'w:val': value.value ?? value.val ?? value.height,
|
|
1082
|
+
'w:hRule': value.rule ?? value.hRule,
|
|
1083
|
+
}),
|
|
1084
|
+
children: [],
|
|
1085
|
+
};
|
|
1086
|
+
case 'w:tcMar':
|
|
1087
|
+
case 'w:tblCellMar':
|
|
1088
|
+
return XMLBuilder.createMargins(name.slice(2), value);
|
|
1089
|
+
case 'w:pgSz':
|
|
1090
|
+
return {
|
|
1091
|
+
name,
|
|
1092
|
+
attributes: XMLBuilder.buildAttributes({
|
|
1093
|
+
'w:w': value.width ?? value.w,
|
|
1094
|
+
'w:h': value.height ?? value.h,
|
|
1095
|
+
'w:orient': value.orientation ?? value.orient,
|
|
1096
|
+
}),
|
|
1097
|
+
children: [],
|
|
1098
|
+
};
|
|
1099
|
+
case 'w:pgMar':
|
|
1100
|
+
return {
|
|
1101
|
+
name,
|
|
1102
|
+
attributes: XMLBuilder.buildAttributes({
|
|
1103
|
+
'w:top': value.top,
|
|
1104
|
+
'w:right': value.right,
|
|
1105
|
+
'w:bottom': value.bottom,
|
|
1106
|
+
'w:left': value.left,
|
|
1107
|
+
'w:header': value.header,
|
|
1108
|
+
'w:footer': value.footer,
|
|
1109
|
+
'w:gutter': value.gutter,
|
|
1110
|
+
}),
|
|
1111
|
+
children: [],
|
|
1112
|
+
};
|
|
1113
|
+
default:
|
|
1114
|
+
// Unknown object shape — no schema mapping to apply
|
|
1115
|
+
return null;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
720
1119
|
/**
|
|
721
1120
|
* Creates XML for a deleted run (uses w:delText or w:delInstrText instead of w:t)
|
|
722
1121
|
*
|
package/src/elements/Run.ts
CHANGED
|
@@ -506,8 +506,10 @@ export class Run {
|
|
|
506
506
|
warnToConsole: true, // Enable warnings to help catch data quality issues
|
|
507
507
|
});
|
|
508
508
|
|
|
509
|
-
// Use cleaned text if available and cleaning was requested
|
|
510
|
-
|
|
509
|
+
// Use cleaned text if available and cleaning was requested.
|
|
510
|
+
// `??` (not `||`) so a cleaned result of '' (input that was entirely XML
|
|
511
|
+
// markup) is kept rather than falling back to the original markup-laden text.
|
|
512
|
+
const cleanedText = validation.cleanedText ?? text;
|
|
511
513
|
|
|
512
514
|
// Convert undefined/null to empty string for consistent XML generation
|
|
513
515
|
const normalizedText = cleanedText ?? '';
|
|
@@ -774,8 +776,10 @@ export class Run {
|
|
|
774
776
|
warnToConsole: true, // Enable warnings to help catch data quality issues
|
|
775
777
|
});
|
|
776
778
|
|
|
777
|
-
// Use cleaned text if available and cleaning was requested
|
|
778
|
-
|
|
779
|
+
// Use cleaned text if available and cleaning was requested.
|
|
780
|
+
// `??` (not `||`) so a cleaned result of '' (input that was entirely XML
|
|
781
|
+
// markup) is kept rather than falling back to the original markup-laden text.
|
|
782
|
+
const cleanedText = validation.cleanedText ?? text;
|
|
779
783
|
|
|
780
784
|
// Convert undefined/null to empty string for consistent XML generation
|
|
781
785
|
const normalizedText = cleanedText ?? '';
|
|
@@ -1627,8 +1631,14 @@ export class Run {
|
|
|
1627
1631
|
*/
|
|
1628
1632
|
setFont(font: string, size?: number): this {
|
|
1629
1633
|
const previousFont = this.formatting.font;
|
|
1634
|
+
const previousHAnsi = this.formatting.fontHAnsi;
|
|
1635
|
+
const previousCs = this.formatting.fontCs;
|
|
1630
1636
|
const previousSize = this.formatting.size;
|
|
1631
1637
|
this.formatting.font = font;
|
|
1638
|
+
// Mirror into hAnsi/cs so an explicit font choice covers all character
|
|
1639
|
+
// ranges; the serializer no longer back-fills these slots from ascii.
|
|
1640
|
+
this.formatting.fontHAnsi = font;
|
|
1641
|
+
this.formatting.fontCs = font;
|
|
1632
1642
|
if (size !== undefined) {
|
|
1633
1643
|
this.formatting.size = size;
|
|
1634
1644
|
}
|
|
@@ -1636,6 +1646,12 @@ export class Run {
|
|
|
1636
1646
|
if (previousFont !== font) {
|
|
1637
1647
|
this.trackingContext.trackRunPropertyChange(this, 'font', previousFont, font);
|
|
1638
1648
|
}
|
|
1649
|
+
if (previousHAnsi !== font) {
|
|
1650
|
+
this.trackingContext.trackRunPropertyChange(this, 'fontHAnsi', previousHAnsi, font);
|
|
1651
|
+
}
|
|
1652
|
+
if (previousCs !== font) {
|
|
1653
|
+
this.trackingContext.trackRunPropertyChange(this, 'fontCs', previousCs, font);
|
|
1654
|
+
}
|
|
1639
1655
|
if (size !== undefined && previousSize !== size) {
|
|
1640
1656
|
this.trackingContext.trackRunPropertyChange(this, 'size', previousSize, size);
|
|
1641
1657
|
}
|
|
@@ -2019,6 +2035,24 @@ export class Run {
|
|
|
2019
2035
|
return this;
|
|
2020
2036
|
}
|
|
2021
2037
|
|
|
2038
|
+
/**
|
|
2039
|
+
* Sets only the ASCII font slot (w:rFonts w:ascii) without mirroring into
|
|
2040
|
+
* hAnsi/cs. Use this when reconstructing a run from source XML so the parsed
|
|
2041
|
+
* model carries exactly the rFonts slots the document declared — unlike
|
|
2042
|
+
* setFont(), which intentionally fills hAnsi/cs for programmatic convenience
|
|
2043
|
+
* and would otherwise override style/theme-inherited fonts on round-trip.
|
|
2044
|
+
* @param font - Font name for the ASCII slot
|
|
2045
|
+
* @returns This run for method chaining
|
|
2046
|
+
*/
|
|
2047
|
+
setFontAscii(font: string): this {
|
|
2048
|
+
const previousValue = this.formatting.font;
|
|
2049
|
+
this.formatting.font = font;
|
|
2050
|
+
if (this.trackingContext?.isEnabled() && previousValue !== font) {
|
|
2051
|
+
this.trackingContext.trackRunPropertyChange(this, 'font', previousValue, font);
|
|
2052
|
+
}
|
|
2053
|
+
return this;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2022
2056
|
/**
|
|
2023
2057
|
* Sets the High ANSI font (w:rFonts w:hAnsi)
|
|
2024
2058
|
* @param font - Font name for high ANSI characters
|
|
@@ -2822,9 +2856,13 @@ export class Run {
|
|
|
2822
2856
|
) {
|
|
2823
2857
|
const rFontsAttrs: Record<string, string> = {};
|
|
2824
2858
|
if (formatting.font) rFontsAttrs['w:ascii'] = formatting.font;
|
|
2825
|
-
|
|
2859
|
+
// Only emit w:hAnsi/w:cs when explicitly set — per ECMA-376 §17.3.2.26
|
|
2860
|
+
// each rFonts slot inherits independently from the style/theme chain, so
|
|
2861
|
+
// back-filling them from the ascii font would override style- or
|
|
2862
|
+
// theme-resolved hAnsi/cs fonts and break round-trip fidelity.
|
|
2863
|
+
if (formatting.fontHAnsi !== undefined) rFontsAttrs['w:hAnsi'] = formatting.fontHAnsi;
|
|
2826
2864
|
if (formatting.fontEastAsia) rFontsAttrs['w:eastAsia'] = formatting.fontEastAsia;
|
|
2827
|
-
rFontsAttrs['w:cs'] = formatting.fontCs
|
|
2865
|
+
if (formatting.fontCs !== undefined) rFontsAttrs['w:cs'] = formatting.fontCs;
|
|
2828
2866
|
if (formatting.fontHint) rFontsAttrs['w:hint'] = formatting.fontHint;
|
|
2829
2867
|
// Theme font references per ECMA-376 Part 1 §17.3.2.26
|
|
2830
2868
|
if (formatting.fontAsciiTheme) rFontsAttrs['w:asciiTheme'] = formatting.fontAsciiTheme;
|