docxmlater 11.0.9 → 12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -13
- package/dist/core/Document.d.ts +28 -2
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +725 -170
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentGenerator.d.ts +1 -0
- package/dist/core/DocumentGenerator.d.ts.map +1 -1
- package/dist/core/DocumentGenerator.js +77 -25
- package/dist/core/DocumentGenerator.js.map +1 -1
- package/dist/core/DocumentParser.d.ts +7 -3
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +431 -85
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +2 -2
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/elements/Comment.d.ts +15 -1
- package/dist/elements/Comment.d.ts.map +1 -1
- package/dist/elements/Comment.js +67 -12
- package/dist/elements/Comment.js.map +1 -1
- package/dist/elements/CommentManager.d.ts +4 -0
- package/dist/elements/CommentManager.d.ts.map +1 -1
- package/dist/elements/CommentManager.js +74 -16
- package/dist/elements/CommentManager.js.map +1 -1
- package/dist/elements/EndnoteManager.d.ts.map +1 -1
- package/dist/elements/EndnoteManager.js.map +1 -1
- package/dist/elements/Field.d.ts +10 -1
- package/dist/elements/Field.d.ts.map +1 -1
- package/dist/elements/Field.js +76 -34
- package/dist/elements/Field.js.map +1 -1
- package/dist/elements/FieldHelpers.d.ts +1 -0
- package/dist/elements/FieldHelpers.d.ts.map +1 -1
- package/dist/elements/FieldHelpers.js +8 -4
- package/dist/elements/FieldHelpers.js.map +1 -1
- package/dist/elements/Footer.d.ts +3 -1
- package/dist/elements/Footer.d.ts.map +1 -1
- package/dist/elements/Footer.js +39 -53
- package/dist/elements/Footer.js.map +1 -1
- package/dist/elements/FootnoteManager.d.ts.map +1 -1
- package/dist/elements/FootnoteManager.js.map +1 -1
- package/dist/elements/Header.d.ts +3 -1
- package/dist/elements/Header.d.ts.map +1 -1
- package/dist/elements/Header.js +39 -53
- package/dist/elements/Header.js.map +1 -1
- package/dist/elements/HeaderFooterManager.d.ts +4 -2
- package/dist/elements/HeaderFooterManager.d.ts.map +1 -1
- package/dist/elements/HeaderFooterManager.js +36 -6
- package/dist/elements/HeaderFooterManager.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts +6 -1
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +69 -44
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/Image.d.ts.map +1 -1
- package/dist/elements/Image.js +33 -6
- package/dist/elements/Image.js.map +1 -1
- package/dist/elements/ImageManager.d.ts +1 -0
- package/dist/elements/ImageManager.d.ts.map +1 -1
- package/dist/elements/ImageManager.js +11 -0
- package/dist/elements/ImageManager.js.map +1 -1
- package/dist/elements/Paragraph.d.ts +3 -0
- package/dist/elements/Paragraph.d.ts.map +1 -1
- package/dist/elements/Paragraph.js +91 -26
- package/dist/elements/Paragraph.js.map +1 -1
- package/dist/elements/Revision.d.ts +4 -0
- package/dist/elements/Revision.d.ts.map +1 -1
- package/dist/elements/Revision.js +369 -29
- package/dist/elements/Revision.js.map +1 -1
- package/dist/elements/Run.d.ts +1 -0
- package/dist/elements/Run.d.ts.map +1 -1
- package/dist/elements/Run.js +24 -4
- package/dist/elements/Run.js.map +1 -1
- package/dist/elements/Section.d.ts.map +1 -1
- package/dist/elements/Section.js +17 -7
- package/dist/elements/Section.js.map +1 -1
- package/dist/elements/Shape.d.ts.map +1 -1
- package/dist/elements/Shape.js +50 -42
- package/dist/elements/Shape.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts +9 -1
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +46 -6
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/Table.d.ts +2 -0
- package/dist/elements/Table.d.ts.map +1 -1
- package/dist/elements/Table.js +90 -42
- package/dist/elements/Table.js.map +1 -1
- package/dist/elements/TableCell.d.ts +1 -0
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +32 -13
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableOfContents.d.ts.map +1 -1
- package/dist/elements/TableOfContents.js +5 -7
- package/dist/elements/TableOfContents.js.map +1 -1
- package/dist/elements/TableRow.d.ts +1 -0
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +16 -1
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/elements/TextBox.d.ts.map +1 -1
- package/dist/elements/TextBox.js +55 -42
- package/dist/elements/TextBox.js.map +1 -1
- package/dist/esm/core/Document.js +726 -171
- package/dist/esm/core/Document.js.map +1 -1
- package/dist/esm/core/DocumentGenerator.js +77 -25
- package/dist/esm/core/DocumentGenerator.js.map +1 -1
- package/dist/esm/core/DocumentParser.js +431 -85
- package/dist/esm/core/DocumentParser.js.map +1 -1
- package/dist/esm/core/RelationshipManager.js +2 -2
- package/dist/esm/core/RelationshipManager.js.map +1 -1
- package/dist/esm/elements/Comment.js +67 -12
- package/dist/esm/elements/Comment.js.map +1 -1
- package/dist/esm/elements/CommentManager.js +74 -16
- package/dist/esm/elements/CommentManager.js.map +1 -1
- package/dist/esm/elements/EndnoteManager.js.map +1 -1
- package/dist/esm/elements/Field.js +77 -35
- package/dist/esm/elements/Field.js.map +1 -1
- package/dist/esm/elements/FieldHelpers.js +7 -4
- package/dist/esm/elements/FieldHelpers.js.map +1 -1
- package/dist/esm/elements/Footer.js +39 -53
- package/dist/esm/elements/Footer.js.map +1 -1
- package/dist/esm/elements/FootnoteManager.js.map +1 -1
- package/dist/esm/elements/Header.js +39 -53
- package/dist/esm/elements/Header.js.map +1 -1
- package/dist/esm/elements/HeaderFooterManager.js +36 -6
- package/dist/esm/elements/HeaderFooterManager.js.map +1 -1
- package/dist/esm/elements/Hyperlink.js +69 -44
- package/dist/esm/elements/Hyperlink.js.map +1 -1
- package/dist/esm/elements/Image.js +33 -6
- package/dist/esm/elements/Image.js.map +1 -1
- package/dist/esm/elements/ImageManager.js +11 -0
- package/dist/esm/elements/ImageManager.js.map +1 -1
- package/dist/esm/elements/Paragraph.js +91 -26
- package/dist/esm/elements/Paragraph.js.map +1 -1
- package/dist/esm/elements/Revision.js +369 -29
- package/dist/esm/elements/Revision.js.map +1 -1
- package/dist/esm/elements/Run.js +24 -4
- package/dist/esm/elements/Run.js.map +1 -1
- package/dist/esm/elements/Section.js +17 -7
- package/dist/esm/elements/Section.js.map +1 -1
- package/dist/esm/elements/Shape.js +50 -42
- package/dist/esm/elements/Shape.js.map +1 -1
- package/dist/esm/elements/StructuredDocumentTag.js +46 -6
- package/dist/esm/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/esm/elements/Table.js +90 -42
- package/dist/esm/elements/Table.js.map +1 -1
- package/dist/esm/elements/TableCell.js +32 -13
- package/dist/esm/elements/TableCell.js.map +1 -1
- package/dist/esm/elements/TableOfContents.js +5 -7
- package/dist/esm/elements/TableOfContents.js.map +1 -1
- package/dist/esm/elements/TableRow.js +16 -1
- package/dist/esm/elements/TableRow.js.map +1 -1
- package/dist/esm/elements/TextBox.js +55 -42
- package/dist/esm/elements/TextBox.js.map +1 -1
- package/dist/esm/formatting/AbstractNumbering.js +1 -1
- package/dist/esm/formatting/AbstractNumbering.js.map +1 -1
- package/dist/esm/formatting/NumberingLevel.js +8 -6
- package/dist/esm/formatting/NumberingLevel.js.map +1 -1
- package/dist/esm/formatting/NumberingManager.js +16 -1
- package/dist/esm/formatting/NumberingManager.js.map +1 -1
- package/dist/esm/formatting/Style.js +14 -0
- package/dist/esm/formatting/Style.js.map +1 -1
- package/dist/esm/formatting/StylesManager.js +14 -2
- package/dist/esm/formatting/StylesManager.js.map +1 -1
- package/dist/esm/helpers/CleanupHelper.js +103 -26
- package/dist/esm/helpers/CleanupHelper.js.map +1 -1
- package/dist/esm/images/ImageOptimizer.js +52 -4
- package/dist/esm/images/ImageOptimizer.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal.js +1 -1
- package/dist/esm/internal.js.map +1 -1
- package/dist/esm/processors/CompatibilityUpgrader.js +7 -1
- package/dist/esm/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/esm/processors/InMemoryRevisionAcceptor.js +134 -13
- package/dist/esm/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/RevisionWalker.js +58 -8
- package/dist/esm/processors/RevisionWalker.js.map +1 -1
- package/dist/esm/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/esm/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/esm/processors/cnfStyleDecoder.js +7 -7
- package/dist/esm/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/esm/processors/stripTrackedChanges.js +16 -5
- package/dist/esm/processors/stripTrackedChanges.js.map +1 -1
- package/dist/esm/utils/deepClone.js +24 -11
- package/dist/esm/utils/deepClone.js.map +1 -1
- package/dist/esm/utils/units.js +1 -1
- package/dist/esm/utils/units.js.map +1 -1
- package/dist/esm/utils/validation.js +11 -23
- package/dist/esm/utils/validation.js.map +1 -1
- package/dist/esm/utils/xmlSanitization.js +131 -7
- package/dist/esm/utils/xmlSanitization.js.map +1 -1
- package/dist/esm/validation/RevisionAutoFixer.js +69 -55
- package/dist/esm/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/esm/validation/RevisionValidator.js +24 -20
- package/dist/esm/validation/RevisionValidator.js.map +1 -1
- package/dist/esm/xml/XMLBuilder.js +52 -20
- package/dist/esm/xml/XMLBuilder.js.map +1 -1
- package/dist/esm/xml/XMLParser.js +55 -13
- package/dist/esm/xml/XMLParser.js.map +1 -1
- package/dist/esm/zip/ZipHandler.js +37 -13
- package/dist/esm/zip/ZipHandler.js.map +1 -1
- package/dist/esm/zip/ZipReader.js +53 -6
- package/dist/esm/zip/ZipReader.js.map +1 -1
- package/dist/esm/zip/errors.js +7 -0
- package/dist/esm/zip/errors.js.map +1 -1
- package/dist/esm/zip/types.js +4 -0
- package/dist/esm/zip/types.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +1 -1
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts +1 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +8 -6
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/NumberingManager.d.ts.map +1 -1
- package/dist/formatting/NumberingManager.js +16 -1
- package/dist/formatting/NumberingManager.js.map +1 -1
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +14 -0
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +2 -0
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +14 -2
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/helpers/CleanupHelper.d.ts.map +1 -1
- package/dist/helpers/CleanupHelper.js +103 -26
- package/dist/helpers/CleanupHelper.js.map +1 -1
- package/dist/images/ImageOptimizer.d.ts.map +1 -1
- package/dist/images/ImageOptimizer.js +52 -4
- package/dist/images/ImageOptimizer.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -1
- package/dist/internal.js.map +1 -1
- package/dist/processors/CompatibilityUpgrader.d.ts.map +1 -1
- package/dist/processors/CompatibilityUpgrader.js +7 -1
- package/dist/processors/CompatibilityUpgrader.js.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.d.ts +1 -0
- package/dist/processors/InMemoryRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/InMemoryRevisionAcceptor.js +135 -13
- package/dist/processors/InMemoryRevisionAcceptor.js.map +1 -1
- package/dist/processors/RevisionWalker.d.ts +2 -0
- package/dist/processors/RevisionWalker.d.ts.map +1 -1
- package/dist/processors/RevisionWalker.js +58 -8
- package/dist/processors/RevisionWalker.js.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.d.ts.map +1 -1
- package/dist/processors/SelectiveRevisionAcceptor.js +116 -17
- package/dist/processors/SelectiveRevisionAcceptor.js.map +1 -1
- package/dist/processors/cnfStyleDecoder.d.ts.map +1 -1
- package/dist/processors/cnfStyleDecoder.js +7 -7
- package/dist/processors/cnfStyleDecoder.js.map +1 -1
- package/dist/processors/stripTrackedChanges.d.ts.map +1 -1
- package/dist/processors/stripTrackedChanges.js +16 -5
- package/dist/processors/stripTrackedChanges.js.map +1 -1
- package/dist/utils/deepClone.d.ts.map +1 -1
- package/dist/utils/deepClone.js +24 -11
- package/dist/utils/deepClone.js.map +1 -1
- package/dist/utils/units.d.ts.map +1 -1
- package/dist/utils/units.js +1 -1
- package/dist/utils/units.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +11 -23
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/xmlSanitization.d.ts +2 -0
- package/dist/utils/xmlSanitization.d.ts.map +1 -1
- package/dist/utils/xmlSanitization.js +133 -7
- package/dist/utils/xmlSanitization.js.map +1 -1
- package/dist/validation/RevisionAutoFixer.d.ts +6 -2
- package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
- package/dist/validation/RevisionAutoFixer.js +68 -54
- package/dist/validation/RevisionAutoFixer.js.map +1 -1
- package/dist/validation/RevisionValidator.d.ts +2 -0
- package/dist/validation/RevisionValidator.d.ts.map +1 -1
- package/dist/validation/RevisionValidator.js +26 -21
- package/dist/validation/RevisionValidator.js.map +1 -1
- package/dist/xml/XMLBuilder.d.ts +1 -0
- package/dist/xml/XMLBuilder.d.ts.map +1 -1
- package/dist/xml/XMLBuilder.js +52 -20
- package/dist/xml/XMLBuilder.js.map +1 -1
- package/dist/xml/XMLParser.d.ts +1 -0
- package/dist/xml/XMLParser.d.ts.map +1 -1
- package/dist/xml/XMLParser.js +55 -13
- package/dist/xml/XMLParser.js.map +1 -1
- package/dist/zip/ZipHandler.d.ts.map +1 -1
- package/dist/zip/ZipHandler.js +37 -13
- package/dist/zip/ZipHandler.js.map +1 -1
- package/dist/zip/ZipReader.d.ts.map +1 -1
- package/dist/zip/ZipReader.js +52 -5
- package/dist/zip/ZipReader.js.map +1 -1
- package/dist/zip/errors.d.ts +3 -0
- package/dist/zip/errors.d.ts.map +1 -1
- package/dist/zip/errors.js +9 -1
- package/dist/zip/errors.js.map +1 -1
- package/dist/zip/types.d.ts +4 -0
- package/dist/zip/types.d.ts.map +1 -1
- package/dist/zip/types.js +4 -0
- package/dist/zip/types.js.map +1 -1
- package/package.json +2 -2
- package/src/core/Document.ts +1159 -240
- package/src/core/DocumentGenerator.ts +106 -26
- package/src/core/DocumentParser.ts +692 -120
- package/src/core/RelationshipManager.ts +446 -442
- package/src/elements/Comment.ts +123 -18
- package/src/elements/CommentManager.ts +121 -22
- package/src/elements/EndnoteManager.ts +4 -1
- package/src/elements/Field.ts +134 -43
- package/src/elements/FieldHelpers.ts +20 -4
- package/src/elements/Footer.ts +62 -67
- package/src/elements/FootnoteManager.ts +4 -1
- package/src/elements/Header.ts +62 -67
- package/src/elements/HeaderFooterManager.ts +56 -8
- package/src/elements/Hyperlink.ts +150 -55
- package/src/elements/Image.ts +51 -7
- package/src/elements/ImageManager.ts +24 -0
- package/src/elements/Paragraph.ts +161 -40
- package/src/elements/Revision.ts +446 -47
- package/src/elements/Run.ts +44 -6
- package/src/elements/Section.ts +25 -9
- package/src/elements/Shape.ts +52 -44
- package/src/elements/StructuredDocumentTag.ts +83 -8
- package/src/elements/Table.ts +151 -50
- package/src/elements/TableCell.ts +57 -17
- package/src/elements/TableOfContents.ts +10 -9
- package/src/elements/TableRow.ts +35 -3
- package/src/elements/TextBox.ts +58 -43
- package/src/formatting/AbstractNumbering.ts +4 -2
- package/src/formatting/NumberingLevel.ts +50 -12
- package/src/formatting/NumberingManager.ts +32 -3
- package/src/formatting/Style.ts +14 -0
- package/src/formatting/StylesManager.ts +29 -2
- package/src/helpers/CleanupHelper.ts +122 -30
- package/src/images/ImageOptimizer.ts +64 -5
- package/src/index.ts +7 -0
- package/src/internal.ts +1 -0
- package/src/processors/CompatibilityUpgrader.ts +15 -2
- package/src/processors/InMemoryRevisionAcceptor.ts +276 -17
- package/src/processors/RevisionWalker.ts +83 -7
- package/src/processors/SelectiveRevisionAcceptor.ts +164 -28
- package/src/processors/cnfStyleDecoder.ts +18 -12
- package/src/processors/stripTrackedChanges.ts +47 -10
- package/src/utils/deepClone.ts +48 -14
- package/src/utils/units.ts +3 -1
- package/src/utils/validation.ts +30 -32
- package/src/utils/xmlSanitization.ts +218 -22
- package/src/validation/RevisionAutoFixer.ts +109 -65
- package/src/validation/RevisionValidator.ts +48 -23
- package/src/xml/XMLBuilder.ts +82 -22
- package/src/xml/XMLParser.ts +87 -20
- package/src/zip/ZipHandler.ts +61 -21
- package/src/zip/ZipReader.ts +135 -13
- package/src/zip/errors.ts +15 -0
- package/src/zip/types.ts +44 -2
package/src/elements/Header.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Different headers can be defined for first page, odd pages, and even pages.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { XMLBuilder } from '../xml/XMLBuilder.js';
|
|
9
|
+
import { XMLParser } from '../xml/XMLParser.js';
|
|
9
10
|
import { Paragraph } from './Paragraph.js';
|
|
10
11
|
import { RunFormatting } from './Run.js';
|
|
11
12
|
import { Table } from './Table.js';
|
|
@@ -36,6 +37,12 @@ export class Header {
|
|
|
36
37
|
private type: HeaderType;
|
|
37
38
|
private headerId?: string;
|
|
38
39
|
private rawXML?: string; // Store original XML for preservation
|
|
40
|
+
// Top-level w:p/w:tbl count of the preserved raw XML. DocumentParser calls
|
|
41
|
+
// setRawXML() before repopulating elements from that same XML, so mutators
|
|
42
|
+
// can't simply clear rawXML — they would fire during parsing and lose the
|
|
43
|
+
// preserved bytes. Instead, growth beyond this count is the signal that
|
|
44
|
+
// content was added after load and the preserved XML is stale.
|
|
45
|
+
private rawXmlBlockCount = Number.MAX_SAFE_INTEGER;
|
|
39
46
|
|
|
40
47
|
/**
|
|
41
48
|
* Creates a new header
|
|
@@ -51,9 +58,43 @@ export class Header {
|
|
|
51
58
|
*/
|
|
52
59
|
setRawXML(xml: string): this {
|
|
53
60
|
this.rawXML = xml;
|
|
61
|
+
this.rawXmlBlockCount = Header.countTopLevelBlocks(xml);
|
|
54
62
|
return this;
|
|
55
63
|
}
|
|
56
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Counts the top-level w:p/w:tbl children of a raw header part.
|
|
67
|
+
* Parsing populates this.elements from exactly those blocks, so the count
|
|
68
|
+
* is the baseline against which mutators detect post-load additions.
|
|
69
|
+
*/
|
|
70
|
+
private static countTopLevelBlocks(xml: string): number {
|
|
71
|
+
try {
|
|
72
|
+
const parsed = XMLParser.parseToObject(xml) as Record<string, unknown>;
|
|
73
|
+
const root = parsed?.['w:hdr'];
|
|
74
|
+
if (!root || typeof root !== 'object') {
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
const count = (node: unknown): number =>
|
|
78
|
+
node === undefined ? 0 : Array.isArray(node) ? node.length : 1;
|
|
79
|
+
const rootObj = root as Record<string, unknown>;
|
|
80
|
+
return count(rootObj['w:p']) + count(rootObj['w:tbl']);
|
|
81
|
+
} catch {
|
|
82
|
+
// Unparseable part: never invalidate, keep the preserved bytes
|
|
83
|
+
return Number.MAX_SAFE_INTEGER;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Drops the preserved raw XML once content grows beyond what that XML
|
|
89
|
+
* already contains, so toXML() regenerates from elements and post-load
|
|
90
|
+
* edits are not silently discarded on save.
|
|
91
|
+
*/
|
|
92
|
+
private invalidateRawXmlOnGrowth(): void {
|
|
93
|
+
if (this.rawXML !== undefined && this.elements.length > this.rawXmlBlockCount) {
|
|
94
|
+
this.rawXML = undefined;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
57
98
|
/**
|
|
58
99
|
* Gets the raw XML content if available
|
|
59
100
|
*/
|
|
@@ -90,6 +131,7 @@ export class Header {
|
|
|
90
131
|
*/
|
|
91
132
|
addParagraph(paragraph: Paragraph): this {
|
|
92
133
|
this.elements.push(paragraph);
|
|
134
|
+
this.invalidateRawXmlOnGrowth();
|
|
93
135
|
return this;
|
|
94
136
|
}
|
|
95
137
|
|
|
@@ -103,6 +145,7 @@ export class Header {
|
|
|
103
145
|
para.addText(text);
|
|
104
146
|
}
|
|
105
147
|
this.elements.push(para);
|
|
148
|
+
this.invalidateRawXmlOnGrowth();
|
|
106
149
|
return para;
|
|
107
150
|
}
|
|
108
151
|
|
|
@@ -127,6 +170,7 @@ export class Header {
|
|
|
127
170
|
const para = new Paragraph();
|
|
128
171
|
para.addText(text, formatting);
|
|
129
172
|
this.elements.push(para);
|
|
173
|
+
this.invalidateRawXmlOnGrowth();
|
|
130
174
|
return para;
|
|
131
175
|
}
|
|
132
176
|
|
|
@@ -136,6 +180,7 @@ export class Header {
|
|
|
136
180
|
*/
|
|
137
181
|
addTable(table: Table): this {
|
|
138
182
|
this.elements.push(table);
|
|
183
|
+
this.invalidateRawXmlOnGrowth();
|
|
139
184
|
return this;
|
|
140
185
|
}
|
|
141
186
|
|
|
@@ -147,6 +192,7 @@ export class Header {
|
|
|
147
192
|
createTable(rows: number, columns: number): Table {
|
|
148
193
|
const table = new Table(rows, columns);
|
|
149
194
|
this.elements.push(table);
|
|
195
|
+
this.invalidateRawXmlOnGrowth();
|
|
150
196
|
return table;
|
|
151
197
|
}
|
|
152
198
|
|
|
@@ -183,76 +229,25 @@ export class Header {
|
|
|
183
229
|
return this.rawXML;
|
|
184
230
|
}
|
|
185
231
|
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
let xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
|
|
190
|
-
xml += '<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ';
|
|
191
|
-
xml += 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\n';
|
|
192
|
-
|
|
193
|
-
// Add elements
|
|
194
|
-
for (const element of elementXmls) {
|
|
195
|
-
xml += this.renderElement(element, 1);
|
|
196
|
-
}
|
|
232
|
+
// Serialize through XMLBuilder so text and attribute values are
|
|
233
|
+
// XML-escaped and rawXml passthrough children are honored
|
|
234
|
+
const children = this.elements.map((el) => el.toXML());
|
|
197
235
|
|
|
198
|
-
//
|
|
199
|
-
if (
|
|
200
|
-
|
|
236
|
+
// ECMA-376 requires block-level content in w:hdr
|
|
237
|
+
if (children.length === 0) {
|
|
238
|
+
children.push(XMLBuilder.w('p'));
|
|
201
239
|
}
|
|
202
240
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
* Renders an XML element to string with indentation
|
|
210
|
-
*/
|
|
211
|
-
private renderElement(element: XMLElement, indent: number): string {
|
|
212
|
-
const spaces = ' '.repeat(indent);
|
|
213
|
-
let xml = '';
|
|
214
|
-
|
|
215
|
-
if (element.selfClosing) {
|
|
216
|
-
xml += `${spaces}<${element.name}`;
|
|
217
|
-
if (element.attributes) {
|
|
218
|
-
for (const [key, value] of Object.entries(element.attributes)) {
|
|
219
|
-
xml += ` ${key}="${value}"`;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
xml += '/>\n';
|
|
223
|
-
} else {
|
|
224
|
-
xml += `${spaces}<${element.name}`;
|
|
225
|
-
if (element.attributes) {
|
|
226
|
-
for (const [key, value] of Object.entries(element.attributes)) {
|
|
227
|
-
xml += ` ${key}="${value}"`;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
xml += '>';
|
|
231
|
-
|
|
232
|
-
if (element.children && element.children.length > 0) {
|
|
233
|
-
const hasOnlyText = element.children.every((c) => typeof c === 'string');
|
|
234
|
-
|
|
235
|
-
if (hasOnlyText) {
|
|
236
|
-
// Inline text content
|
|
237
|
-
xml += element.children.join('');
|
|
238
|
-
} else {
|
|
239
|
-
// Block-level children
|
|
240
|
-
xml += '\n';
|
|
241
|
-
for (const child of element.children) {
|
|
242
|
-
if (typeof child === 'string') {
|
|
243
|
-
xml += spaces + ' ' + child + '\n';
|
|
244
|
-
} else {
|
|
245
|
-
xml += this.renderElement(child, indent + 1);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
xml += spaces;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
xml += `</${element.name}>\n`;
|
|
253
|
-
}
|
|
241
|
+
const namespaces: Record<string, string> = {
|
|
242
|
+
...XMLBuilder.createNamespaces(),
|
|
243
|
+
// Extension namespaces (w14:paraId etc. on regenerated paragraphs)
|
|
244
|
+
// must be declared ignorable or Word rejects the part
|
|
245
|
+
'mc:Ignorable': 'w14 w15 wp14 asvg',
|
|
246
|
+
};
|
|
254
247
|
|
|
255
|
-
|
|
248
|
+
const builder = new XMLBuilder();
|
|
249
|
+
builder.element('w:hdr', namespaces, children);
|
|
250
|
+
return builder.build(true);
|
|
256
251
|
}
|
|
257
252
|
|
|
258
253
|
/**
|
|
@@ -51,18 +51,31 @@ export class HeaderFooterManager {
|
|
|
51
51
|
* Registers a header with the manager
|
|
52
52
|
* @param header The header to register
|
|
53
53
|
* @param relationshipId The relationship ID for this header
|
|
54
|
+
* @param originalFilename Part name from the relationship target for loaded
|
|
55
|
+
* headers — kept as-is so saved content lands where the relationship points
|
|
54
56
|
* @returns The filename assigned to this header
|
|
55
57
|
*/
|
|
56
|
-
registerHeader(header: Header, relationshipId: string): string {
|
|
58
|
+
registerHeader(header: Header, relationshipId: string, originalFilename?: string): string {
|
|
57
59
|
// Check if already registered
|
|
58
60
|
const existing = this.headers.get(header);
|
|
59
61
|
if (existing) {
|
|
60
62
|
return existing.filename;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
let number: number;
|
|
66
|
+
let filename: string;
|
|
67
|
+
if (originalFilename) {
|
|
68
|
+
filename = originalFilename;
|
|
69
|
+
const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
|
|
70
|
+
number = digits ? parseInt(digits, 10) : this.nextHeaderNumber;
|
|
71
|
+
// Keep the counter ahead of parsed part names so generated names never collide
|
|
72
|
+
if (number >= this.nextHeaderNumber) {
|
|
73
|
+
this.nextHeaderNumber = number + 1;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
number = this.nextHeaderNumber++;
|
|
77
|
+
filename = header.getFilename(number);
|
|
78
|
+
}
|
|
66
79
|
|
|
67
80
|
// Set header ID
|
|
68
81
|
header.setHeaderId(relationshipId);
|
|
@@ -84,18 +97,31 @@ export class HeaderFooterManager {
|
|
|
84
97
|
* Registers a footer with the manager
|
|
85
98
|
* @param footer The footer to register
|
|
86
99
|
* @param relationshipId The relationship ID for this footer
|
|
100
|
+
* @param originalFilename Part name from the relationship target for loaded
|
|
101
|
+
* footers — kept as-is so saved content lands where the relationship points
|
|
87
102
|
* @returns The filename assigned to this footer
|
|
88
103
|
*/
|
|
89
|
-
registerFooter(footer: Footer, relationshipId: string): string {
|
|
104
|
+
registerFooter(footer: Footer, relationshipId: string, originalFilename?: string): string {
|
|
90
105
|
// Check if already registered
|
|
91
106
|
const existing = this.footers.get(footer);
|
|
92
107
|
if (existing) {
|
|
93
108
|
return existing.filename;
|
|
94
109
|
}
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
let number: number;
|
|
112
|
+
let filename: string;
|
|
113
|
+
if (originalFilename) {
|
|
114
|
+
filename = originalFilename;
|
|
115
|
+
const digits = /(\d+)\.xml$/i.exec(originalFilename)?.[1];
|
|
116
|
+
number = digits ? parseInt(digits, 10) : this.nextFooterNumber;
|
|
117
|
+
// Keep the counter ahead of parsed part names so generated names never collide
|
|
118
|
+
if (number >= this.nextFooterNumber) {
|
|
119
|
+
this.nextFooterNumber = number + 1;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
number = this.nextFooterNumber++;
|
|
123
|
+
filename = footer.getFilename(number);
|
|
124
|
+
}
|
|
99
125
|
|
|
100
126
|
// Set footer ID
|
|
101
127
|
footer.setFooterId(relationshipId);
|
|
@@ -113,6 +139,28 @@ export class HeaderFooterManager {
|
|
|
113
139
|
return filename;
|
|
114
140
|
}
|
|
115
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Returns the part filename this header has, or would receive when
|
|
144
|
+
* registered. Does not consume a sequence number — callers can create the
|
|
145
|
+
* relationship targeting the same part name registerHeader() will assign.
|
|
146
|
+
* @param header The header
|
|
147
|
+
* @returns The current or upcoming filename
|
|
148
|
+
*/
|
|
149
|
+
peekHeaderFilename(header: Header): string {
|
|
150
|
+
return this.headers.get(header)?.filename ?? header.getFilename(this.nextHeaderNumber);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns the part filename this footer has, or would receive when
|
|
155
|
+
* registered. Does not consume a sequence number — callers can create the
|
|
156
|
+
* relationship targeting the same part name registerFooter() will assign.
|
|
157
|
+
* @param footer The footer
|
|
158
|
+
* @returns The current or upcoming filename
|
|
159
|
+
*/
|
|
160
|
+
peekFooterFilename(footer: Footer): string {
|
|
161
|
+
return this.footers.get(footer)?.filename ?? footer.getFilename(this.nextFooterNumber);
|
|
162
|
+
}
|
|
163
|
+
|
|
116
164
|
/**
|
|
117
165
|
* Gets the filename for a header
|
|
118
166
|
* @param header The header
|