docxmlater 10.3.6 → 10.4.0

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.
Files changed (184) hide show
  1. package/README.md +158 -7
  2. package/dist/core/Document.d.ts +97 -3
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +727 -50
  5. package/dist/core/Document.js.map +1 -1
  6. package/dist/core/DocumentContent.d.ts.map +1 -1
  7. package/dist/core/DocumentContent.js +0 -8
  8. package/dist/core/DocumentContent.js.map +1 -1
  9. package/dist/core/DocumentGenerator.d.ts.map +1 -1
  10. package/dist/core/DocumentGenerator.js +9 -5
  11. package/dist/core/DocumentGenerator.js.map +1 -1
  12. package/dist/core/DocumentParser.d.ts.map +1 -1
  13. package/dist/core/DocumentParser.js +573 -101
  14. package/dist/core/DocumentParser.js.map +1 -1
  15. package/dist/core/RelationshipManager.d.ts.map +1 -1
  16. package/dist/core/RelationshipManager.js +4 -3
  17. package/dist/core/RelationshipManager.js.map +1 -1
  18. package/dist/elements/Bookmark.d.ts +7 -0
  19. package/dist/elements/Bookmark.d.ts.map +1 -1
  20. package/dist/elements/Bookmark.js +24 -4
  21. package/dist/elements/Bookmark.js.map +1 -1
  22. package/dist/elements/BookmarkManager.d.ts.map +1 -1
  23. package/dist/elements/BookmarkManager.js +4 -3
  24. package/dist/elements/BookmarkManager.js.map +1 -1
  25. package/dist/elements/CommonTypes.d.ts +2 -2
  26. package/dist/elements/CommonTypes.d.ts.map +1 -1
  27. package/dist/elements/CommonTypes.js +14 -1
  28. package/dist/elements/CommonTypes.js.map +1 -1
  29. package/dist/elements/Field.d.ts +1 -1
  30. package/dist/elements/Field.d.ts.map +1 -1
  31. package/dist/elements/Field.js +1 -1
  32. package/dist/elements/Field.js.map +1 -1
  33. package/dist/elements/Footer.d.ts +2 -0
  34. package/dist/elements/Footer.d.ts.map +1 -1
  35. package/dist/elements/Footer.js +6 -0
  36. package/dist/elements/Footer.js.map +1 -1
  37. package/dist/elements/Header.d.ts +2 -0
  38. package/dist/elements/Header.d.ts.map +1 -1
  39. package/dist/elements/Header.js +6 -0
  40. package/dist/elements/Header.js.map +1 -1
  41. package/dist/elements/Image.d.ts.map +1 -1
  42. package/dist/elements/Image.js +3 -0
  43. package/dist/elements/Image.js.map +1 -1
  44. package/dist/elements/Paragraph.d.ts +81 -1
  45. package/dist/elements/Paragraph.d.ts.map +1 -1
  46. package/dist/elements/Paragraph.js +515 -21
  47. package/dist/elements/Paragraph.js.map +1 -1
  48. package/dist/elements/Revision.d.ts +0 -1
  49. package/dist/elements/Revision.d.ts.map +1 -1
  50. package/dist/elements/Revision.js +0 -12
  51. package/dist/elements/Revision.js.map +1 -1
  52. package/dist/elements/RevisionManager.d.ts +0 -1
  53. package/dist/elements/RevisionManager.d.ts.map +1 -1
  54. package/dist/elements/RevisionManager.js +0 -2
  55. package/dist/elements/RevisionManager.js.map +1 -1
  56. package/dist/elements/Run.d.ts +16 -4
  57. package/dist/elements/Run.d.ts.map +1 -1
  58. package/dist/elements/Run.js +114 -22
  59. package/dist/elements/Run.js.map +1 -1
  60. package/dist/elements/Section.d.ts +7 -1
  61. package/dist/elements/Section.d.ts.map +1 -1
  62. package/dist/elements/Section.js +185 -4
  63. package/dist/elements/Section.js.map +1 -1
  64. package/dist/elements/Shape.js.map +1 -1
  65. package/dist/elements/Table.d.ts +30 -1
  66. package/dist/elements/Table.d.ts.map +1 -1
  67. package/dist/elements/Table.js +357 -40
  68. package/dist/elements/Table.js.map +1 -1
  69. package/dist/elements/TableCell.d.ts +3 -0
  70. package/dist/elements/TableCell.d.ts.map +1 -1
  71. package/dist/elements/TableCell.js +30 -3
  72. package/dist/elements/TableCell.js.map +1 -1
  73. package/dist/elements/TableGridChange.d.ts +0 -1
  74. package/dist/elements/TableGridChange.d.ts.map +1 -1
  75. package/dist/elements/TableGridChange.js +0 -10
  76. package/dist/elements/TableGridChange.js.map +1 -1
  77. package/dist/elements/TableRow.d.ts +4 -0
  78. package/dist/elements/TableRow.d.ts.map +1 -1
  79. package/dist/elements/TableRow.js +31 -3
  80. package/dist/elements/TableRow.js.map +1 -1
  81. package/dist/formatting/AbstractNumbering.d.ts +5 -0
  82. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  83. package/dist/formatting/AbstractNumbering.js +22 -0
  84. package/dist/formatting/AbstractNumbering.js.map +1 -1
  85. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  86. package/dist/formatting/NumberingLevel.js +3 -3
  87. package/dist/formatting/NumberingLevel.js.map +1 -1
  88. package/dist/formatting/Style.d.ts +1 -0
  89. package/dist/formatting/Style.d.ts.map +1 -1
  90. package/dist/formatting/Style.js +25 -59
  91. package/dist/formatting/Style.js.map +1 -1
  92. package/dist/formatting/StylesManager.d.ts +1 -0
  93. package/dist/formatting/StylesManager.d.ts.map +1 -1
  94. package/dist/formatting/StylesManager.js +12 -0
  95. package/dist/formatting/StylesManager.js.map +1 -1
  96. package/dist/helpers/CleanupHelper.js.map +1 -1
  97. package/dist/images/ImageOptimizer.d.ts.map +1 -1
  98. package/dist/images/ImageOptimizer.js +0 -1
  99. package/dist/images/ImageOptimizer.js.map +1 -1
  100. package/dist/index.d.ts +1 -1
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/managers/DrawingManager.d.ts.map +1 -1
  104. package/dist/managers/DrawingManager.js +4 -2
  105. package/dist/managers/DrawingManager.js.map +1 -1
  106. package/dist/types/formatting.d.ts +2 -2
  107. package/dist/types/formatting.d.ts.map +1 -1
  108. package/dist/types/formatting.js.map +1 -1
  109. package/dist/utils/ChangelogGenerator.d.ts +2 -2
  110. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  111. package/dist/utils/ChangelogGenerator.js +4 -5
  112. package/dist/utils/ChangelogGenerator.js.map +1 -1
  113. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  114. package/dist/utils/InMemoryRevisionAcceptor.js +0 -1
  115. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  116. package/dist/utils/RevisionAwareProcessor.d.ts +2 -2
  117. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  118. package/dist/utils/RevisionAwareProcessor.js +2 -2
  119. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  120. package/dist/utils/SelectiveRevisionAcceptor.d.ts +0 -2
  121. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  122. package/dist/utils/SelectiveRevisionAcceptor.js +0 -26
  123. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  124. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  125. package/dist/utils/ShadingResolver.js.map +1 -1
  126. package/dist/utils/acceptRevisions.js +1 -1
  127. package/dist/utils/acceptRevisions.js.map +1 -1
  128. package/dist/utils/stripTrackedChanges.js +1 -1
  129. package/dist/utils/stripTrackedChanges.js.map +1 -1
  130. package/dist/utils/units.d.ts.map +1 -1
  131. package/dist/utils/units.js +1 -1
  132. package/dist/utils/units.js.map +1 -1
  133. package/dist/validation/RevisionAutoFixer.d.ts +2 -1
  134. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  135. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  136. package/package.json +10 -1
  137. package/src/constants/CLAUDE.md +28 -0
  138. package/src/core/CLAUDE.md +4 -0
  139. package/src/core/Document.ts +1755 -85
  140. package/src/core/DocumentContent.ts +0 -11
  141. package/src/core/DocumentGenerator.ts +11 -12
  142. package/src/core/DocumentParser.ts +599 -138
  143. package/src/core/RelationshipManager.ts +6 -3
  144. package/src/elements/Bookmark.ts +39 -4
  145. package/src/elements/BookmarkManager.ts +4 -3
  146. package/src/elements/CLAUDE.md +18 -2
  147. package/src/elements/CommonTypes.ts +35 -8
  148. package/src/elements/Field.ts +1 -1
  149. package/src/elements/Footer.ts +23 -0
  150. package/src/elements/Header.ts +25 -0
  151. package/src/elements/Image.ts +5 -0
  152. package/src/elements/Paragraph.ts +1069 -41
  153. package/src/elements/Revision.ts +0 -19
  154. package/src/elements/RevisionManager.ts +1 -3
  155. package/src/elements/Run.ts +265 -35
  156. package/src/elements/Section.ts +214 -8
  157. package/src/elements/Shape.ts +1 -1
  158. package/src/elements/Table.ts +850 -61
  159. package/src/elements/TableCell.ts +84 -10
  160. package/src/elements/TableGridChange.ts +2 -16
  161. package/src/elements/TableRow.ts +94 -9
  162. package/src/formatting/AbstractNumbering.ts +42 -1
  163. package/src/formatting/CLAUDE.md +4 -0
  164. package/src/formatting/NumberingLevel.ts +11 -7
  165. package/src/formatting/Style.ts +39 -71
  166. package/src/formatting/StylesManager.ts +36 -0
  167. package/src/helpers/CleanupHelper.ts +1 -1
  168. package/src/images/ImageOptimizer.ts +0 -3
  169. package/src/index.ts +1 -1
  170. package/src/managers/DrawingManager.ts +5 -3
  171. package/src/tracking/CLAUDE.md +30 -0
  172. package/src/types/CLAUDE.md +39 -0
  173. package/src/types/formatting.ts +2 -2
  174. package/src/utils/CLAUDE.md +15 -0
  175. package/src/utils/ChangelogGenerator.ts +4 -5
  176. package/src/utils/InMemoryRevisionAcceptor.ts +0 -9
  177. package/src/utils/RevisionAwareProcessor.ts +2 -3
  178. package/src/utils/SelectiveRevisionAcceptor.ts +0 -39
  179. package/src/utils/ShadingResolver.ts +0 -1
  180. package/src/utils/acceptRevisions.ts +1 -1
  181. package/src/utils/stripTrackedChanges.ts +1 -1
  182. package/src/utils/units.ts +2 -1
  183. package/src/validation/CLAUDE.md +40 -0
  184. package/src/validation/RevisionAutoFixer.ts +2 -1
@@ -8,6 +8,7 @@
8
8
  import { Relationship, RelationshipType } from './Relationship';
9
9
  import { XMLParser } from '../xml/XMLParser';
10
10
  import { sanitizeHyperlinkUrl } from '../utils/validation';
11
+ import { InvalidDocxError, CorruptedArchiveError } from '../zip/errors';
11
12
 
12
13
  /**
13
14
  * Manages relationships for a document or document part
@@ -221,7 +222,7 @@ export class RelationshipManager {
221
222
 
222
223
  // Verify this is a hyperlink relationship
223
224
  if (relationship.getType() !== RelationshipType.HYPERLINK) {
224
- throw new Error(
225
+ throw new InvalidDocxError(
225
226
  `Relationship ${relationshipId} is not a hyperlink relationship. ` +
226
227
  `Type is ${relationship.getType()}, expected ${RelationshipType.HYPERLINK}`
227
228
  );
@@ -384,7 +385,7 @@ export class RelationshipManager {
384
385
 
385
386
  // Prevent ReDoS: validate input size (typical .rels files are < 10KB, max 10MB)
386
387
  if (xml.length > 10000000) {
387
- throw new Error(
388
+ throw new CorruptedArchiveError(
388
389
  'Relationships XML file too large (>10MB). Possible malicious input or corrupted file.'
389
390
  );
390
391
  }
@@ -394,7 +395,9 @@ export class RelationshipManager {
394
395
 
395
396
  // Prevent infinite loops: check relationship count
396
397
  if (relationshipElements.length > 1000) {
397
- throw new Error('Too many relationships in XML file (>1000). Possible malicious input.');
398
+ throw new CorruptedArchiveError(
399
+ 'Too many relationships in XML file (>1000). Possible malicious input.'
400
+ );
398
401
  }
399
402
 
400
403
  // Process each relationship element
@@ -17,6 +17,10 @@ export interface BookmarkProperties {
17
17
  name: string;
18
18
  /** Skip name normalization (used when loading from existing documents) */
19
19
  skipNormalization?: boolean;
20
+ /** First column in table bookmark range (ECMA-376 §17.16.5) */
21
+ colFirst?: number;
22
+ /** Last column in table bookmark range (ECMA-376 §17.16.5) */
23
+ colLast?: number;
20
24
  }
21
25
 
22
26
  /**
@@ -25,6 +29,8 @@ export interface BookmarkProperties {
25
29
  export class Bookmark {
26
30
  private id: number;
27
31
  private name: string;
32
+ private colFirst?: number;
33
+ private colLast?: number;
28
34
 
29
35
  /**
30
36
  * Creates a new Bookmark
@@ -37,6 +43,8 @@ export class Bookmark {
37
43
  this.name = properties.skipNormalization
38
44
  ? properties.name
39
45
  : this.normalizeName(properties.name);
46
+ this.colFirst = properties.colFirst;
47
+ this.colLast = properties.colLast;
40
48
  }
41
49
 
42
50
  /**
@@ -136,17 +144,44 @@ export class Bookmark {
136
144
  return this;
137
145
  }
138
146
 
147
+ /**
148
+ * Gets the first column in a table bookmark range
149
+ */
150
+ getColFirst(): number | undefined {
151
+ return this.colFirst;
152
+ }
153
+
154
+ /**
155
+ * Gets the last column in a table bookmark range
156
+ */
157
+ getColLast(): number | undefined {
158
+ return this.colLast;
159
+ }
160
+
161
+ /**
162
+ * Sets the column range for a table bookmark (ECMA-376 §17.16.5)
163
+ */
164
+ setColumnRange(colFirst: number, colLast: number): this {
165
+ this.colFirst = colFirst;
166
+ this.colLast = colLast;
167
+ return this;
168
+ }
169
+
139
170
  /**
140
171
  * Generates XML for the bookmark start marker
141
172
  * @returns XMLElement for bookmarkStart
142
173
  */
143
174
  toStartXML(): XMLElement {
175
+ const attrs: Record<string, string | number> = {
176
+ 'w:id': this.id.toString(),
177
+ 'w:name': this.name,
178
+ };
179
+ // Table bookmark column range per ECMA-376 §17.16.5
180
+ if (this.colFirst !== undefined) attrs['w:colFirst'] = this.colFirst.toString();
181
+ if (this.colLast !== undefined) attrs['w:colLast'] = this.colLast.toString();
144
182
  return {
145
183
  name: 'w:bookmarkStart',
146
- attributes: {
147
- 'w:id': this.id.toString(),
148
- 'w:name': this.name,
149
- },
184
+ attributes: attrs,
150
185
  selfClosing: true,
151
186
  };
152
187
  }
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { Bookmark } from './Bookmark';
11
+ import { InvalidDocxError } from '../zip/errors';
11
12
 
12
13
  /**
13
14
  * Type for the centralized ID provider callback.
@@ -55,7 +56,7 @@ export class BookmarkManager {
55
56
 
56
57
  // Check for duplicate names
57
58
  if (this.bookmarks.has(name)) {
58
- throw new Error(
59
+ throw new InvalidDocxError(
59
60
  `Bookmark with name "${name}" already exists. Bookmark names must be unique within a document.`
60
61
  );
61
62
  }
@@ -83,7 +84,7 @@ export class BookmarkManager {
83
84
 
84
85
  // Check for duplicate names
85
86
  if (this.bookmarks.has(name)) {
86
- throw new Error(
87
+ throw new InvalidDocxError(
87
88
  `Bookmark with name "${name}" already exists. Bookmark names must be unique within a document.`
88
89
  );
89
90
  }
@@ -194,7 +195,7 @@ export class BookmarkManager {
194
195
  counter++;
195
196
  }
196
197
 
197
- throw new Error(`Could not generate unique bookmark name from base "${baseName}"`);
198
+ throw new InvalidDocxError(`Could not generate unique bookmark name from base "${baseName}"`);
198
199
  }
199
200
 
200
201
  /**
@@ -38,19 +38,31 @@ Header/Footer Elements
38
38
 
39
39
  Container for text and inline content. Key formatting: `alignment`, `spacing`, `indentation`, `pPrChange` (revision tracking), `keepNext`/`keepLines`/`pageBreakBefore` (pagination).
40
40
 
41
- **Rule:** `setKeepNext(true)` / `setKeepLines(true)` auto-clears `pageBreakBefore`.
41
+ **CT_OnOff properties:** `keepNext`, `keepLines`, `pageBreakBefore`, `suppressLineNumbers`, `suppressAutoHyphens`, `contextualSpacing`, `mirrorIndents`, `suppressOverlap` all use `!== undefined` semantics with `w:val` attribute, supporting explicit `false` to override style inheritance.
42
+
43
+ **Rule:** `setKeepNext(true)` / `setKeepLines(true)` auto-clears `pageBreakBefore` to `undefined` (absent, not explicit false).
44
+
45
+ **Alignment:** `ParagraphAlignment` includes bidi-aware values (`start`, `end`), CJK (`distribute`), Arabic kashida (`mediumKashida`, `highKashida`, `lowKashida`), and Thai (`thaiDistribute`).
46
+
47
+ **w14 attributes:** `paraId` and `textId` (Word 2010+) are auto-generated for new paragraphs during `prepareSave()`. Values are 8-char hex, must be < `0x80000000`.
42
48
 
43
49
  CJK methods: `setKinsoku()`, `setWordWrap()`, `setOverflowPunct()`, `setTopLinePunct()`, `setAutoSpaceDE()`, `setAutoSpaceDN()`.
44
50
 
45
51
  ### Run (`Run.ts`)
46
52
 
47
- Formatted text span. Character formatting (bold, italic, underline, strikethrough), font properties, color (normalized to uppercase 6-char hex), highlight, special chars (tabs, breaks, symbols), complex script support.
53
+ Formatted text span. Character formatting (bold, italic, underline, strikethrough), font properties, color (hex or `'auto'`), highlight, special chars (tabs, breaks, symbols), complex script support.
54
+
55
+ **CT_OnOff properties:** Boolean properties use `!== undefined` semantics: `undefined` = inherit from style, `true` = on, `false` = explicitly off (`w:val="0"`). This applies to: bold, bCs, italic, iCs, caps, smallCaps, strike, dstrike, snapToGrid.
56
+
57
+ **Vertical alignment:** `setSubscript()`, `setSuperscript()`, and `vertAlignBaseline` field for explicit baseline reset per ST_VerticalAlignRun.
48
58
 
49
59
  Theme fonts: `setFontAsciiTheme()`, `setFontHAnsiTheme()`, `setFontEastAsiaTheme()`, `setFontCsTheme()`.
50
60
  Underline: `setUnderlineColor()`, `setUnderlineThemeColor()`.
51
61
  w14 effects: `addRawW14Property(xml)` for Word 2010+ ligatures, numForm, textOutline.
52
62
  Form fields: `FormFieldData`, `FormFieldTextInput`, `FormFieldCheckBox`, `FormFieldDropDownList` interfaces.
53
63
 
64
+ **Static helper:** `Run.generateRunPropertiesXML(formatting)` — generates `w:rPr` with all 38+ CT_RPr elements in strict ECMA-376 order. Used by both Run and Style serialization.
65
+
54
66
  ### Table (`Table.ts`, `TableRow.ts`, `TableCell.ts`)
55
67
 
56
68
  Row/column management, cell merging (horizontal + vertical), border styling, property change tracking (`w:tblPrChange`), inter-row content preservation (bookmarks, comments between rows).
@@ -59,6 +71,10 @@ Navigation: `getFirstParagraph()`, `getLastParagraph()`.
59
71
  Layout: `getLayout()` returns `'fixed'` or `'auto'`.
60
72
  Legacy merge: `setHorizontalMerge()` / `getHorizontalMerge()` (hMerge).
61
73
 
74
+ **Constraints:** `removeRow()` prevents removing the last row (ECMA-376 requires >= 1 row). `insertRow()`/`insertRows()` use grid span count for correct column count with merged cells. `tblPrEx` is serialized before `trPr` in `w:tr` per CT_Row.
75
+
76
+ **TableRow:** `setHeightRule(rule)` sets height rule independently. When `w:hRule` is absent, the spec default is `"auto"` (not `"atLeast"`).
77
+
62
78
  **Nested Tables:** Raw XML passthrough via `TableCell.rawNestedContent[]`.
63
79
  ```typescript
64
80
  cell.addRawNestedContent(position, xml, "table")
@@ -223,19 +223,33 @@ export type PageVerticalAlignment = 'top' | 'center' | 'bottom' | 'both';
223
223
  export type CellVerticalAlignment = 'top' | 'center' | 'bottom';
224
224
 
225
225
  /**
226
- * Paragraph text alignment
226
+ * Paragraph text alignment per ECMA-376 §17.18.44 (ST_Jc)
227
227
  *
228
228
  * From: Paragraph.ts (ParagraphAlignment)
229
- * Note: 'both' is an alias for 'justify' in some contexts
229
+ * Note: 'both' is the OOXML name for justified text; 'justify' is accepted as an alias.
230
+ * 'start'/'end' are bidi-aware alternatives to 'left'/'right'.
230
231
  */
231
- export type ParagraphAlignment = 'left' | 'center' | 'right' | 'justify' | 'both';
232
-
233
- /**
234
- * Table alignment (horizontal positioning)
232
+ export type ParagraphAlignment =
233
+ | 'left'
234
+ | 'center'
235
+ | 'right'
236
+ | 'justify'
237
+ | 'both'
238
+ | 'start'
239
+ | 'end'
240
+ | 'distribute'
241
+ | 'mediumKashida'
242
+ | 'highKashida'
243
+ | 'lowKashida'
244
+ | 'thaiDistribute';
245
+
246
+ /**
247
+ * Table alignment (horizontal positioning) per ECMA-376 §17.18.45 (ST_JcTable)
235
248
  *
236
249
  * From: Table.ts (TableAlignment)
250
+ * 'start'/'end' are bidi-aware alternatives to 'left'/'right'.
237
251
  */
238
- export type TableAlignment = 'left' | 'center' | 'right';
252
+ export type TableAlignment = 'left' | 'center' | 'right' | 'start' | 'end';
239
253
 
240
254
  /**
241
255
  * Row justification/alignment options
@@ -466,7 +480,20 @@ export function isVerticalAlignment(value: string): value is VerticalAlignment {
466
480
  * Check if a value is a valid ParagraphAlignment
467
481
  */
468
482
  export function isParagraphAlignment(value: string): value is ParagraphAlignment {
469
- return ['left', 'center', 'right', 'justify', 'both'].includes(value);
483
+ return [
484
+ 'left',
485
+ 'center',
486
+ 'right',
487
+ 'justify',
488
+ 'both',
489
+ 'start',
490
+ 'end',
491
+ 'distribute',
492
+ 'mediumKashida',
493
+ 'highKashida',
494
+ 'lowKashida',
495
+ 'thaiDistribute',
496
+ ].includes(value);
470
497
  }
471
498
 
472
499
  /**
@@ -447,7 +447,7 @@ export class Field {
447
447
  */
448
448
  static createHyperlink(
449
449
  url: string,
450
- displayText: string = url,
450
+ _displayText: string = url,
451
451
  tooltip?: string,
452
452
  formatting?: RunFormatting
453
453
  ): Field {
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { XMLElement } from '../xml/XMLBuilder';
9
9
  import { Paragraph } from './Paragraph';
10
+ import { RunFormatting } from './Run';
10
11
  import { Table } from './Table';
11
12
 
12
13
  /**
@@ -105,6 +106,28 @@ export class Footer {
105
106
  return para;
106
107
  }
107
108
 
109
+ /**
110
+ * Adds formatted text to the footer as a new paragraph
111
+ *
112
+ * Convenience method that creates a paragraph with a single formatted run.
113
+ *
114
+ * @param text - Text content
115
+ * @param formatting - Optional run formatting (bold, font, size, etc.)
116
+ * @returns The created Paragraph for further customization
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * footer.addText('Page ', { size: 8 });
121
+ * footer.addText('Confidential', { italic: true, color: '888888' });
122
+ * ```
123
+ */
124
+ addText(text: string, formatting?: RunFormatting): Paragraph {
125
+ const para = new Paragraph();
126
+ para.addText(text, formatting);
127
+ this.elements.push(para);
128
+ return para;
129
+ }
130
+
108
131
  /**
109
132
  * Adds a table to the footer
110
133
  * @param table Table to add
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { XMLElement } from '../xml/XMLBuilder';
9
9
  import { Paragraph } from './Paragraph';
10
+ import { RunFormatting } from './Run';
10
11
  import { Table } from './Table';
11
12
 
12
13
  /**
@@ -105,6 +106,30 @@ export class Header {
105
106
  return para;
106
107
  }
107
108
 
109
+ /**
110
+ * Adds formatted text to the header as a new paragraph
111
+ *
112
+ * Convenience method that creates a paragraph with a single formatted run.
113
+ * For headers with multiple runs or complex content, use `createParagraph()`
114
+ * and build content manually.
115
+ *
116
+ * @param text - Text content
117
+ * @param formatting - Optional run formatting (bold, font, size, etc.)
118
+ * @returns The created Paragraph for further customization
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * header.addText('Company Name', { bold: true, font: 'Arial', size: 10 });
123
+ * header.addText('Confidential', { italic: true, color: 'FF0000' });
124
+ * ```
125
+ */
126
+ addText(text: string, formatting?: RunFormatting): Paragraph {
127
+ const para = new Paragraph();
128
+ para.addText(text, formatting);
129
+ this.elements.push(para);
130
+ return para;
131
+ }
132
+
108
133
  /**
109
134
  * Adds a table to the header
110
135
  * @param table Table to add
@@ -1492,6 +1492,10 @@ export class Image {
1492
1492
  delete this.border._fromParsed;
1493
1493
  }
1494
1494
 
1495
+ // Clear passthrough slots that conflict with explicit border
1496
+ this._rawPassthrough.delete('zero-width-ln');
1497
+ this._rawPassthrough.delete('spPr-noFill');
1498
+
1495
1499
  // Calculate space needed for border (half-width on each side)
1496
1500
  // Border is drawn centered on the edge
1497
1501
  const borderEmu = this.border.width * UNITS.EMUS_PER_POINT;
@@ -1515,6 +1519,7 @@ export class Image {
1515
1519
  */
1516
1520
  removeBorder(): this {
1517
1521
  this.border = undefined;
1522
+ this._rawPassthrough.delete('zero-width-ln');
1518
1523
  return this;
1519
1524
  }
1520
1525