docxmlater 10.3.5 → 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 (185) hide show
  1. package/README.md +158 -7
  2. package/dist/core/Document.d.ts +102 -3
  3. package/dist/core/Document.d.ts.map +1 -1
  4. package/dist/core/Document.js +775 -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 +588 -102
  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 +1 -0
  42. package/dist/elements/Image.d.ts.map +1 -1
  43. package/dist/elements/Image.js +17 -2
  44. package/dist/elements/Image.js.map +1 -1
  45. package/dist/elements/Paragraph.d.ts +81 -1
  46. package/dist/elements/Paragraph.d.ts.map +1 -1
  47. package/dist/elements/Paragraph.js +515 -21
  48. package/dist/elements/Paragraph.js.map +1 -1
  49. package/dist/elements/Revision.d.ts +0 -1
  50. package/dist/elements/Revision.d.ts.map +1 -1
  51. package/dist/elements/Revision.js +0 -12
  52. package/dist/elements/Revision.js.map +1 -1
  53. package/dist/elements/RevisionManager.d.ts +0 -1
  54. package/dist/elements/RevisionManager.d.ts.map +1 -1
  55. package/dist/elements/RevisionManager.js +0 -2
  56. package/dist/elements/RevisionManager.js.map +1 -1
  57. package/dist/elements/Run.d.ts +16 -4
  58. package/dist/elements/Run.d.ts.map +1 -1
  59. package/dist/elements/Run.js +114 -22
  60. package/dist/elements/Run.js.map +1 -1
  61. package/dist/elements/Section.d.ts +7 -1
  62. package/dist/elements/Section.d.ts.map +1 -1
  63. package/dist/elements/Section.js +185 -4
  64. package/dist/elements/Section.js.map +1 -1
  65. package/dist/elements/Shape.js.map +1 -1
  66. package/dist/elements/Table.d.ts +30 -1
  67. package/dist/elements/Table.d.ts.map +1 -1
  68. package/dist/elements/Table.js +357 -40
  69. package/dist/elements/Table.js.map +1 -1
  70. package/dist/elements/TableCell.d.ts +3 -0
  71. package/dist/elements/TableCell.d.ts.map +1 -1
  72. package/dist/elements/TableCell.js +30 -3
  73. package/dist/elements/TableCell.js.map +1 -1
  74. package/dist/elements/TableGridChange.d.ts +0 -1
  75. package/dist/elements/TableGridChange.d.ts.map +1 -1
  76. package/dist/elements/TableGridChange.js +0 -10
  77. package/dist/elements/TableGridChange.js.map +1 -1
  78. package/dist/elements/TableRow.d.ts +4 -0
  79. package/dist/elements/TableRow.d.ts.map +1 -1
  80. package/dist/elements/TableRow.js +31 -3
  81. package/dist/elements/TableRow.js.map +1 -1
  82. package/dist/formatting/AbstractNumbering.d.ts +5 -0
  83. package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
  84. package/dist/formatting/AbstractNumbering.js +22 -0
  85. package/dist/formatting/AbstractNumbering.js.map +1 -1
  86. package/dist/formatting/NumberingLevel.d.ts.map +1 -1
  87. package/dist/formatting/NumberingLevel.js +3 -3
  88. package/dist/formatting/NumberingLevel.js.map +1 -1
  89. package/dist/formatting/Style.d.ts +1 -0
  90. package/dist/formatting/Style.d.ts.map +1 -1
  91. package/dist/formatting/Style.js +25 -59
  92. package/dist/formatting/Style.js.map +1 -1
  93. package/dist/formatting/StylesManager.d.ts +1 -0
  94. package/dist/formatting/StylesManager.d.ts.map +1 -1
  95. package/dist/formatting/StylesManager.js +12 -0
  96. package/dist/formatting/StylesManager.js.map +1 -1
  97. package/dist/helpers/CleanupHelper.js.map +1 -1
  98. package/dist/images/ImageOptimizer.d.ts.map +1 -1
  99. package/dist/images/ImageOptimizer.js +0 -1
  100. package/dist/images/ImageOptimizer.js.map +1 -1
  101. package/dist/index.d.ts +1 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/managers/DrawingManager.d.ts.map +1 -1
  105. package/dist/managers/DrawingManager.js +4 -2
  106. package/dist/managers/DrawingManager.js.map +1 -1
  107. package/dist/types/formatting.d.ts +2 -2
  108. package/dist/types/formatting.d.ts.map +1 -1
  109. package/dist/types/formatting.js.map +1 -1
  110. package/dist/utils/ChangelogGenerator.d.ts +2 -2
  111. package/dist/utils/ChangelogGenerator.d.ts.map +1 -1
  112. package/dist/utils/ChangelogGenerator.js +4 -5
  113. package/dist/utils/ChangelogGenerator.js.map +1 -1
  114. package/dist/utils/InMemoryRevisionAcceptor.d.ts.map +1 -1
  115. package/dist/utils/InMemoryRevisionAcceptor.js +0 -1
  116. package/dist/utils/InMemoryRevisionAcceptor.js.map +1 -1
  117. package/dist/utils/RevisionAwareProcessor.d.ts +2 -2
  118. package/dist/utils/RevisionAwareProcessor.d.ts.map +1 -1
  119. package/dist/utils/RevisionAwareProcessor.js +2 -2
  120. package/dist/utils/RevisionAwareProcessor.js.map +1 -1
  121. package/dist/utils/SelectiveRevisionAcceptor.d.ts +0 -2
  122. package/dist/utils/SelectiveRevisionAcceptor.d.ts.map +1 -1
  123. package/dist/utils/SelectiveRevisionAcceptor.js +0 -26
  124. package/dist/utils/SelectiveRevisionAcceptor.js.map +1 -1
  125. package/dist/utils/ShadingResolver.d.ts.map +1 -1
  126. package/dist/utils/ShadingResolver.js.map +1 -1
  127. package/dist/utils/acceptRevisions.js +1 -1
  128. package/dist/utils/acceptRevisions.js.map +1 -1
  129. package/dist/utils/stripTrackedChanges.js +1 -1
  130. package/dist/utils/stripTrackedChanges.js.map +1 -1
  131. package/dist/utils/units.d.ts.map +1 -1
  132. package/dist/utils/units.js +1 -1
  133. package/dist/utils/units.js.map +1 -1
  134. package/dist/validation/RevisionAutoFixer.d.ts +2 -1
  135. package/dist/validation/RevisionAutoFixer.d.ts.map +1 -1
  136. package/dist/validation/RevisionAutoFixer.js.map +1 -1
  137. package/package.json +10 -1
  138. package/src/constants/CLAUDE.md +28 -0
  139. package/src/core/CLAUDE.md +4 -0
  140. package/src/core/Document.ts +1888 -137
  141. package/src/core/DocumentContent.ts +0 -11
  142. package/src/core/DocumentGenerator.ts +11 -12
  143. package/src/core/DocumentParser.ts +620 -139
  144. package/src/core/RelationshipManager.ts +6 -3
  145. package/src/elements/Bookmark.ts +39 -4
  146. package/src/elements/BookmarkManager.ts +4 -3
  147. package/src/elements/CLAUDE.md +18 -2
  148. package/src/elements/CommonTypes.ts +35 -8
  149. package/src/elements/Field.ts +1 -1
  150. package/src/elements/Footer.ts +23 -0
  151. package/src/elements/Header.ts +25 -0
  152. package/src/elements/Image.ts +28 -5
  153. package/src/elements/Paragraph.ts +1069 -41
  154. package/src/elements/Revision.ts +0 -19
  155. package/src/elements/RevisionManager.ts +1 -3
  156. package/src/elements/Run.ts +265 -35
  157. package/src/elements/Section.ts +214 -8
  158. package/src/elements/Shape.ts +1 -1
  159. package/src/elements/Table.ts +850 -61
  160. package/src/elements/TableCell.ts +84 -10
  161. package/src/elements/TableGridChange.ts +2 -16
  162. package/src/elements/TableRow.ts +94 -9
  163. package/src/formatting/AbstractNumbering.ts +42 -1
  164. package/src/formatting/CLAUDE.md +4 -0
  165. package/src/formatting/NumberingLevel.ts +11 -7
  166. package/src/formatting/Style.ts +39 -71
  167. package/src/formatting/StylesManager.ts +36 -0
  168. package/src/helpers/CleanupHelper.ts +1 -1
  169. package/src/images/ImageOptimizer.ts +0 -3
  170. package/src/index.ts +1 -1
  171. package/src/managers/DrawingManager.ts +5 -3
  172. package/src/tracking/CLAUDE.md +30 -0
  173. package/src/types/CLAUDE.md +39 -0
  174. package/src/types/formatting.ts +2 -2
  175. package/src/utils/CLAUDE.md +15 -0
  176. package/src/utils/ChangelogGenerator.ts +4 -5
  177. package/src/utils/InMemoryRevisionAcceptor.ts +0 -9
  178. package/src/utils/RevisionAwareProcessor.ts +2 -3
  179. package/src/utils/SelectiveRevisionAcceptor.ts +0 -39
  180. package/src/utils/ShadingResolver.ts +0 -1
  181. package/src/utils/acceptRevisions.ts +1 -1
  182. package/src/utils/stripTrackedChanges.ts +1 -1
  183. package/src/utils/units.ts +2 -1
  184. package/src/validation/CLAUDE.md +40 -0
  185. package/src/validation/RevisionAutoFixer.ts +2 -1
@@ -192,6 +192,42 @@ export class StylesManager {
192
192
  return this.styles.get(styleId);
193
193
  }
194
194
 
195
+ /**
196
+ * Clones an existing style with a new ID and optional name
197
+ *
198
+ * Deep-copies the source style (including all run, paragraph, and table
199
+ * formatting) and registers the clone with the new ID. If `newName` is
200
+ * not provided, the clone's name is set to the new ID.
201
+ *
202
+ * @param sourceId - ID of the style to clone
203
+ * @param newId - ID for the cloned style (must be unique)
204
+ * @param newName - Display name for the clone (defaults to newId)
205
+ * @returns The cloned Style, or undefined if source not found
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * // Create a variant of Heading1
210
+ * const variant = stylesManager.cloneStyle('Heading1', 'Heading1Blue', 'Blue Heading 1');
211
+ * variant?.setRunFormatting({ ...variant.getRunFormatting(), color: '0000FF' });
212
+ *
213
+ * // Clone a custom style for a different section
214
+ * stylesManager.cloneStyle('CustomNote', 'CustomNoteAlt');
215
+ * ```
216
+ */
217
+ cloneStyle(sourceId: string, newId: string, newName?: string): Style | undefined {
218
+ const source = this.getStyle(sourceId);
219
+ if (!source) return undefined;
220
+
221
+ const props = source.getProperties();
222
+ props.styleId = newId;
223
+ props.name = newName ?? newId;
224
+ props.isDefault = false; // Clones should never be default
225
+
226
+ const cloned = new Style(props);
227
+ this.addStyle(cloned);
228
+ return cloned;
229
+ }
230
+
195
231
  /**
196
232
  * Checks if a style exists or can be loaded
197
233
  * @param styleId - Style ID to check
@@ -437,7 +437,7 @@ export class CleanupHelper {
437
437
  };
438
438
 
439
439
  // Helper to process paragraph content
440
- const processParagraph = (paragraph: any): void => {
440
+ const processParagraph = (paragraph: Paragraph): void => {
441
441
  for (const item of paragraph.getContent()) {
442
442
  // Process all Hyperlink instances (both internal AND external)
443
443
  if (item instanceof Hyperlink) {
@@ -69,9 +69,6 @@ function buildPngChunk(type: string, data: Buffer): Buffer {
69
69
  // PNG Re-compression
70
70
  // =============================================================================
71
71
 
72
- /** Chunks that must be preserved for correct PNG rendering */
73
- const ESSENTIAL_CHUNK_TYPES = new Set(['IHDR', 'PLTE', 'tRNS', 'IDAT', 'IEND']);
74
-
75
72
  /**
76
73
  * Re-compresses a PNG buffer at zlib level 9 and strips non-essential metadata chunks.
77
74
  * Returns the optimized buffer, or null if the PNG is invalid/cannot be optimized.
package/src/index.ts CHANGED
@@ -35,7 +35,7 @@ export {
35
35
  isShape,
36
36
  isTextBox,
37
37
  } from './elements/Paragraph';
38
- export { Run, RunFormatting, ThemeColorValue } from './elements/Run';
38
+ export { Run, RunFormatting, ThemeColorValue, LanguageConfig } from './elements/Run';
39
39
  export {
40
40
  Section,
41
41
  PageOrientation,
@@ -256,14 +256,16 @@ export class DrawingManager {
256
256
  * @param drawing Drawing to check
257
257
  * @returns True if PreservedDrawing
258
258
  */
259
- private isPreservedDrawing(drawing: any): drawing is PreservedDrawing {
259
+ private isPreservedDrawing(drawing: unknown): drawing is PreservedDrawing {
260
260
  return (
261
- drawing &&
261
+ !!drawing &&
262
262
  typeof drawing === 'object' &&
263
263
  'type' in drawing &&
264
264
  'xml' in drawing &&
265
265
  'relationshipIds' in drawing &&
266
- (drawing.type === 'smartart' || drawing.type === 'chart' || drawing.type === 'wordart')
266
+ ((drawing as PreservedDrawing).type === 'smartart' ||
267
+ (drawing as PreservedDrawing).type === 'chart' ||
268
+ (drawing as PreservedDrawing).type === 'wordart')
267
269
  );
268
270
  }
269
271
 
@@ -0,0 +1,30 @@
1
+ # Tracking Module
2
+
3
+ `src/tracking/` — Change tracking context for revision-aware document editing.
4
+
5
+ ## Interfaces & Classes
6
+
7
+ ### TrackingContext (interface)
8
+
9
+ Contract for tracking changes on document elements. Methods:
10
+
11
+ - `trackRunPropertyChange(run, previousProps)` — creates `w:rPrChange`
12
+ - `trackParagraphPropertyChange(para, previousProps)` — creates `w:pPrChange`
13
+ - `trackTableChange(table, previousProps)` — creates `w:tblPrChange`
14
+ - `trackInsertion(element)` / `trackDeletion(element)` — wraps in `w:ins`/`w:del`
15
+ - `flushPendingChanges()` — converts queued changes to Revision objects
16
+ - `isEnabled()` — check if tracking is active
17
+
18
+ ### DocumentTrackingContext (`DocumentTrackingContext.ts`)
19
+
20
+ Implementation of `TrackingContext`. Key behaviors:
21
+
22
+ - **State:** enabled flag, author name, `trackFormatting` toggle, pending changes map
23
+ - **Consolidation:** Groups changes by element with time-window keys to batch similar edits (prevents one revision per keystroke)
24
+ - **PrChange application:** Creates/merges `*PrChange` markers (`rPrChange`, `pPrChange`, `tblPrChange`, `tcPrChange`, `sectPrChange`) per ECMA-376
25
+ - **Full snapshot tracking:** Stores complete previous properties (not deltas) for table/cell/section changes
26
+ - **WeakMap for element IDs:** Prevents GC issues with stable element references
27
+
28
+ ## Key Pattern
29
+
30
+ Call `doc.flushPendingChanges()` before inspecting `pPrChange` or `rPrChange` in tests — pending changes are batched and only materialized on flush or save.
@@ -0,0 +1,39 @@
1
+ # Types Module
2
+
3
+ `src/types/` — TypeScript type definitions shared across modules.
4
+
5
+ ## Files
6
+
7
+ ### `formatting.ts`
8
+ Formatting-related types used by Document search/replace and paragraph formatting:
9
+ - `BorderStyleType`, `BorderStyle`, `ParagraphBorder` — border definitions
10
+ - `ShadingPattern`, `ParagraphShading` — re-exported from CommonTypes
11
+ - `TabAlignment`, `TabLeader`, `TabStop` — tab stop configuration
12
+ - `FindOptions`, `ReplaceOptions`, `SearchResult` — text search/replace options
13
+ - `EmphasisType`, `ListPrefix`, `FormatOptions`, `StyleApplyOptions` — style application
14
+
15
+ ### `styleConfig.ts`
16
+ Style configuration interfaces for Document's style application methods:
17
+ - `StyleRunFormatting` — character-level formatting (font, size, bold, etc.)
18
+ - `StyleParagraphFormatting` — paragraph-level formatting (alignment, spacing, indentation)
19
+ - `StyleConfig`, `Heading2Config`, `NormalConfig` — predefined style configurations
20
+ - `ApplyStylesOptions` — options for `doc.applyStyles()` / `doc.applyStylesFromObjects()`
21
+ - `ApplyCustomFormattingOptions` — deprecated alias for `ApplyStylesOptions`
22
+
23
+ ### `settings-types.ts`
24
+ Document settings interfaces:
25
+ - `DocumentProtection` — password protection settings
26
+ - `RevisionViewSettings` — revision display mode
27
+ - `TrackChangesSettings` — track changes configuration
28
+ - `WebSettingsInfo` — web settings (div cleanup, encoding)
29
+
30
+ ### `list-types.ts`
31
+ List detection and normalization:
32
+ - `ListCategory`, `NumberFormat`, `BulletFormat` — list type classification
33
+ - `ListDetectionResult`, `ListAnalysis` — detection output
34
+ - `ListNormalizationOptions`, `ListNormalizationReport` — normalization config/results
35
+
36
+ ### `compatibility-types.ts`
37
+ Word compatibility mode types:
38
+ - `CompatSetting` — individual compatibility setting (name, uri, val)
39
+ - `CompatibilityInfo` — full compatibility state (mode value, legacy flags, modern settings)
@@ -56,12 +56,12 @@ export type { ShadingConfig as ParagraphShading } from '../elements/CommonTypes'
56
56
  /**
57
57
  * Tab stop alignment
58
58
  */
59
- export type TabAlignment = 'left' | 'center' | 'right' | 'decimal' | 'bar' | 'clear';
59
+ export type TabAlignment = 'left' | 'center' | 'right' | 'decimal' | 'bar' | 'clear' | 'num';
60
60
 
61
61
  /**
62
62
  * Tab leader character
63
63
  */
64
- export type TabLeader = 'none' | 'dot' | 'dash' | 'underscore' | 'heavy' | 'middleDot';
64
+ export type TabLeader = 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot';
65
65
 
66
66
  /**
67
67
  * Tab stop configuration
@@ -2,6 +2,21 @@
2
2
 
3
3
  `src/utils/` — Standalone utilities (22 TypeScript files) for unit conversions, revision processing, validation, logging, and helpers.
4
4
 
5
+ ## Architecture Classification
6
+
7
+ **Pure utilities** (no element/core imports — safe to use anywhere):
8
+ - `units.ts`, `validation.ts`, `deepClone.ts`, `dateFormatting.ts`, `errorHandling.ts`
9
+ - `xmlSanitization.ts`, `formatting.ts`, `parsingHelpers.ts`, `logger.ts`, `diagnostics.ts`
10
+ - `textDiff.ts`, `list-detection.ts`, `corruptionDetection.ts`
11
+
12
+ **Domain-specific processors** (import from elements/core — should arguably be in `src/processors/`):
13
+ - `acceptRevisions.ts`, `RevisionWalker.ts`, `InMemoryRevisionAcceptor.ts`
14
+ - `SelectiveRevisionAcceptor.ts`, `RevisionAwareProcessor.ts`, `MoveOperationHelper.ts`
15
+ - `ChangelogGenerator.ts`, `ShadingResolver.ts`, `stripTrackedChanges.ts`
16
+ - `CompatibilityUpgrader.ts`, `cnfStyleDecoder.ts`
17
+
18
+ This split explains the 36+ dependency-cruiser warnings about utils importing elements — the domain-specific files are processors, not pure utilities.
19
+
5
20
  ## Unit Conversions (`units.ts`)
6
21
 
7
22
  40+ conversion functions between twips, EMUs, points, half-points, pixels, inches, centimeters.
@@ -198,7 +198,7 @@ export class ChangelogGenerator {
198
198
  static fromRevisions(
199
199
  revisions: Revision[],
200
200
  options?: ChangelogOptions,
201
- doc?: Document
201
+ _doc?: Document
202
202
  ): ChangeEntry[] {
203
203
  const logger = getLogger();
204
204
  const opts = {
@@ -619,7 +619,6 @@ export class ChangelogGenerator {
619
619
  */
620
620
  static describeRevision(revision: Revision, maxLength = 50): string {
621
621
  const type = revision.getType();
622
- const author = revision.getAuthor();
623
622
  const runs = revision.getRuns();
624
623
  const text = runs.map((r) => r.getText()).join('');
625
624
  const excerpt =
@@ -676,7 +675,7 @@ export class ChangelogGenerator {
676
675
  /**
677
676
  * Generate description for a hyperlink change revision.
678
677
  */
679
- private static describeHyperlinkChange(revision: Revision, maxLength: number): string {
678
+ private static describeHyperlinkChange(revision: Revision, _maxLength: number): string {
680
679
  const prevProps = revision.getPreviousProperties() || {};
681
680
  const newProps = revision.getNewProperties() || {};
682
681
  const changes: string[] = [];
@@ -883,7 +882,7 @@ export class ChangelogGenerator {
883
882
  // Truncate if too long
884
883
  return json.length > 100 ? json.substring(0, 97) + '...' : json;
885
884
  } catch (e) {
886
- getLogger().debug('Failed to stringify value', { error: String(e) });
885
+ getLogger().warn('Failed to stringify value for changelog', { error: String(e) });
887
886
  return '[complex value]';
888
887
  }
889
888
  }
@@ -1203,7 +1202,7 @@ export class ChangelogGenerator {
1203
1202
  * fs.writeFileSync('changelog.html', html);
1204
1203
  * ```
1205
1204
  */
1206
- static toHTML(entries: ChangeEntry[], options?: ChangelogOptions): string {
1205
+ static toHTML(entries: ChangeEntry[], _options?: ChangelogOptions): string {
1207
1206
  const summary = this.getSummary(entries);
1208
1207
 
1209
1208
  // Group entries by category
@@ -18,13 +18,9 @@ import type { Document } from '../core/Document';
18
18
  import { Paragraph } from '../elements/Paragraph';
19
19
  import type { ParagraphContent } from '../elements/Paragraph';
20
20
  import { Revision, RevisionType } from '../elements/Revision';
21
- import type { Run } from '../elements/Run';
22
- import type { Hyperlink } from '../elements/Hyperlink';
23
21
  import { isRunContent, isHyperlinkContent, isImageRunContent } from '../elements/RevisionContent';
24
- import type { ImageRun } from '../elements/ImageRun';
25
22
  import { ComplexField } from '../elements/Field';
26
23
  import { Table } from '../elements/Table';
27
- import { Section } from '../elements/Section';
28
24
  import { getGlobalLogger, createScopedLogger, ILogger } from './logger';
29
25
 
30
26
  /**
@@ -68,11 +64,6 @@ export interface AcceptRevisionsResult {
68
64
  emptyTablesRemoved: number;
69
65
  }
70
66
 
71
- /**
72
- * Revision types that represent content changes (contain actual text/runs)
73
- */
74
- const CONTENT_REVISION_TYPES: RevisionType[] = ['insert', 'delete', 'moveFrom', 'moveTo'];
75
-
76
67
  /**
77
68
  * Revision types that represent property/formatting changes
78
69
  */
@@ -13,7 +13,6 @@
13
13
 
14
14
  import type { Document } from '../core/Document';
15
15
  import { Revision, RevisionType } from '../elements/Revision';
16
- import { RevisionManager } from '../elements/RevisionManager';
17
16
  import { ChangeCategory, ChangeLocation } from './ChangelogGenerator';
18
17
 
19
18
  /**
@@ -382,7 +381,7 @@ export class RevisionAwareProcessor {
382
381
  * @param runIndex - Optional run index
383
382
  * @returns Conflicting revision or null
384
383
  */
385
- static checkConflict(doc: Document, paragraphIndex: number, runIndex?: number): Revision | null {
384
+ static checkConflict(doc: Document, paragraphIndex: number, _runIndex?: number): Revision | null {
386
385
  const revisionManager = doc.getRevisionManager();
387
386
  if (!revisionManager) {
388
387
  return null;
@@ -407,7 +406,7 @@ export class RevisionAwareProcessor {
407
406
  static getAffectedRevisions(
408
407
  doc: Document,
409
408
  paragraphIndex: number,
410
- runIndex?: number
409
+ _runIndex?: number
411
410
  ): Revision[] {
412
411
  const revisionManager = doc.getRevisionManager();
413
412
  if (!revisionManager) {
@@ -16,7 +16,6 @@ import type { Document } from '../core/Document';
16
16
  import type { Paragraph, ParagraphContent } from '../elements/Paragraph';
17
17
  import { Revision, RevisionType } from '../elements/Revision';
18
18
  import type { Run } from '../elements/Run';
19
- import type { Hyperlink } from '../elements/Hyperlink';
20
19
  import { isRunContent, isHyperlinkContent } from '../elements/RevisionContent';
21
20
  import { ChangeCategory } from './ChangelogGenerator';
22
21
  import { SelectionCriteria } from './RevisionAwareProcessor';
@@ -533,27 +532,6 @@ export class SelectiveRevisionAcceptor {
533
532
  return this.accept(doc, { categories: ['content'] });
534
533
  }
535
534
 
536
- /**
537
- * Partition revisions into matching and non-matching based on criteria.
538
- */
539
- private static partitionRevisions(
540
- revisions: Revision[],
541
- criteria: SelectionCriteria
542
- ): { matching: Revision[]; nonMatching: Revision[] } {
543
- const matching: Revision[] = [];
544
- const nonMatching: Revision[] = [];
545
-
546
- for (const rev of revisions) {
547
- if (this.matchesCriteria(rev, criteria)) {
548
- matching.push(rev);
549
- } else {
550
- nonMatching.push(rev);
551
- }
552
- }
553
-
554
- return { matching, nonMatching };
555
- }
556
-
557
535
  /**
558
536
  * Check if a revision matches the given criteria.
559
537
  */
@@ -642,21 +620,4 @@ export class SelectiveRevisionAcceptor {
642
620
 
643
621
  return 'content';
644
622
  }
645
-
646
- /**
647
- * Create an empty result.
648
- */
649
- private static emptyResult(): SelectiveAcceptResult {
650
- return {
651
- accepted: [],
652
- rejected: [],
653
- remaining: [],
654
- summary: {
655
- totalProcessed: 0,
656
- acceptedCount: 0,
657
- rejectedCount: 0,
658
- remainingCount: 0,
659
- },
660
- };
661
- }
662
623
  }
@@ -18,7 +18,6 @@ import type { Table } from '../elements/Table';
18
18
  import type { TableCell } from '../elements/TableCell';
19
19
  import type { StylesManager } from '../formatting/StylesManager';
20
20
  import { getActiveConditionalsInPriorityOrder } from './cnfStyleDecoder';
21
- import type { ConditionalFormattingType } from '../formatting/Style';
22
21
 
23
22
  /**
24
23
  * Resolves the effective shading for a table cell through the style hierarchy.
@@ -281,7 +281,7 @@ class RevisionAcceptor {
281
281
 
282
282
  result = result.replace(insRegex, (insMatch) => {
283
283
  // For each image reference inside this insertion, generate a unique new ID
284
- return insMatch.replace(/r:embed="(rId\d+)"/g, (embedMatch, oldId) => {
284
+ return insMatch.replace(/r:embed="(rId\d+)"/g, (_embedMatch, oldId) => {
285
285
  // Generate new unique ID for THIS occurrence
286
286
  const newId = this.getNextRelationshipId(existingIds);
287
287
  existingIds.add(newId);
@@ -107,7 +107,7 @@ class TrackedChangesStripper {
107
107
 
108
108
  result = result.replace(insRegex, (insMatch) => {
109
109
  // For each image reference inside this insertion, generate a unique new ID
110
- return insMatch.replace(/r:embed="(rId\d+)"/g, (embedMatch, oldId) => {
110
+ return insMatch.replace(/r:embed="(rId\d+)"/g, (_embedMatch, oldId) => {
111
111
  // Generate new unique ID for THIS occurrence
112
112
  const newId = this.getNextRelationshipId(existingIds);
113
113
  existingIds.add(newId);
@@ -185,7 +185,8 @@ export function pointsToCm(points: number): number {
185
185
  * @returns Value in half-points
186
186
  */
187
187
  export function pointsToHalfPoints(points: number): number {
188
- return points * UNITS.HALF_POINTS_PER_POINT;
188
+ // Round to nearest integer — w:sz/w:szCs require ST_HpsMeasure (unsigned integer)
189
+ return Math.round(points * UNITS.HALF_POINTS_PER_POINT);
189
190
  }
190
191
 
191
192
  /**
@@ -0,0 +1,40 @@
1
+ # Validation Module
2
+
3
+ `src/validation/` — Revision validation, rule definitions, and auto-fix.
4
+
5
+ ## Classes
6
+
7
+ ### RevisionValidator (`RevisionValidator.ts`)
8
+
9
+ Static validation class. Entry point: `validate(doc, options?)`.
10
+
11
+ Runs all rules with configurable strictness (`strict` / `normal` / `lenient`). Returns `ValidationResult` with categorized issues (errors, warnings, infos) and summary stats.
12
+
13
+ Individual validators: `validateRevisionIds()`, `validateMovePairs()`, `validateAuthors()`, `validateDates()`, `validateContent()`, `validateSequentialIds()`.
14
+
15
+ ### ValidationRules (`ValidationRules.ts`)
16
+
17
+ 10 rules organized by severity:
18
+
19
+ | Rule | Severity | Description | Auto-fixable |
20
+ |--------|----------|----------------------------|-------------|
21
+ | REV001 | Error | Duplicate revision IDs | Yes |
22
+ | REV002 | Error | Missing authors | Yes |
23
+ | REV003 | Error | Orphaned moveFrom | Yes |
24
+ | REV004 | Error | Orphaned moveTo | Yes |
25
+ | REV101 | Warning | Missing dates | Yes |
26
+ | REV102 | Warning | Invalid date format | Yes |
27
+ | REV103 | Warning | Empty revisions | Yes |
28
+ | REV104 | Warning | Non-sequential IDs | Yes |
29
+ | REV201 | Info | Large revision count | No |
30
+ | REV202 | Info | Old revision dates | No |
31
+
32
+ **Auto-fix dependency order:** REV001 -> REV002 -> REV003/004 -> REV103 -> REV104
33
+
34
+ ### RevisionAutoFixer (`RevisionAutoFixer.ts`)
35
+
36
+ Applies fixes in correct dependency order. Supports dry-run mode via `preview()`.
37
+
38
+ Entry point: `fix(doc, options?)`. Returns `AutoFixResult` with detailed actions taken.
39
+
40
+ Individual fixers: `fixDuplicateIds()`, `fixMissingAuthors()`, `fixOrphanedMoveMarkers()`, `fixEmptyRevisions()`, `fixNonSequentialIds()`.
@@ -9,6 +9,7 @@
9
9
 
10
10
  import type { Document } from '../core/Document';
11
11
  import type { Revision } from '../elements/Revision';
12
+ import type { RevisionManager } from '../elements/RevisionManager';
12
13
  import {
13
14
  REVISION_RULES,
14
15
  AutoFixOptions,
@@ -387,7 +388,7 @@ export class RevisionAutoFixer {
387
388
  * @returns Array of fix actions
388
389
  */
389
390
  static fixEmptyRevisions(
390
- revisionManager: any,
391
+ revisionManager: RevisionManager,
391
392
  revisions: Revision[],
392
393
  dryRun?: boolean
393
394
  ): FixAction[] {