documentation-hub 5.7.2

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 (271) hide show
  1. package/.eslintrc.json +43 -0
  2. package/.github/workflows/build.yml +64 -0
  3. package/.github/workflows/ci.yml +39 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/Current.md +97 -0
  6. package/DocHub_Image.png +0 -0
  7. package/README.md +666 -0
  8. package/USER_GUIDE.md +1173 -0
  9. package/Updater.md +311 -0
  10. package/build/256x256.png +0 -0
  11. package/build/512x512.png +0 -0
  12. package/build/app-update.yml +4 -0
  13. package/build/create-icon.js +208 -0
  14. package/build/icon.ico +0 -0
  15. package/build/icon.png +0 -0
  16. package/build/icon_1024x1024.png +0 -0
  17. package/dist/assets/Analytics-BpsG9895.js +1 -0
  18. package/dist/assets/Card-IAZin8kp.js +1 -0
  19. package/dist/assets/CurrentSession-B-rFkHvf.js +12 -0
  20. package/dist/assets/Dashboard-C_5gMb0q.js +1 -0
  21. package/dist/assets/Documents-CqZ25axS.js +1 -0
  22. package/dist/assets/Input-l89xwXBi.js +1 -0
  23. package/dist/assets/Reporting-DqdHJY_a.js +1 -0
  24. package/dist/assets/Search-XNbu5z_3.js +1 -0
  25. package/dist/assets/SessionManager-lH9hZfzH.js +1 -0
  26. package/dist/assets/Sessions-ClZOPYNc.js +1 -0
  27. package/dist/assets/Settings-DUEHGURa.js +11 -0
  28. package/dist/assets/index-8xUe8ptc.js +24 -0
  29. package/dist/assets/index-RYyJqF7O.css +1 -0
  30. package/dist/assets/path-BkOl0AGO.js +1 -0
  31. package/dist/assets/promises-ID_B9S-h.js +1 -0
  32. package/dist/assets/urlHelpers-TvgahX0r.js +1 -0
  33. package/dist/assets/useToast-yRSO1dkm.js +1 -0
  34. package/dist/assets/vendor-charts-RkGK5ROP.js +36 -0
  35. package/dist/assets/vendor-db-l0sNRNKZ.js +1 -0
  36. package/dist/assets/vendor-react-BVZ_anCF.js +4 -0
  37. package/dist/assets/vendor-search-Dw8P0qyA.js +1 -0
  38. package/dist/assets/vendor-ui-BU7NfluV.js +53 -0
  39. package/dist/electron/PowerAutomateApiService-LfW09ZGr.js +147 -0
  40. package/dist/electron/main-CXkNtyv-.js +19789 -0
  41. package/dist/electron/main.js +5 -0
  42. package/dist/electron/preload.js +1 -0
  43. package/dist/icon.png +0 -0
  44. package/dist/index.html +27 -0
  45. package/docs/CODEBASE_ANALYSIS_REPORT.md +309 -0
  46. package/docs/DEBUG_LOGGING_GUIDE.md +244 -0
  47. package/docs/README.md +115 -0
  48. package/docs/TOC_WIRING_GUIDE.md +344 -0
  49. package/docs/analysis/Bullet_Symbol_Bug_Analysis.md +136 -0
  50. package/docs/analysis/DOCXMLATER_ANALYSIS_SUMMARY.txt +169 -0
  51. package/docs/analysis/Document_Processing_Issues_Analysis.md +704 -0
  52. package/docs/analysis/FIELD_PRESERVATION_ANALYSIS.md +1200 -0
  53. package/docs/analysis/INDENTATION_PRESERVE_ANALYSIS.md +181 -0
  54. package/docs/analysis/INDENTATION_PRESERVE_IMPLEMENTATION.md +207 -0
  55. package/docs/analysis/List_Implementation.md +206 -0
  56. package/docs/analysis/List_Implementation_Accuracy_Report.md +366 -0
  57. package/docs/analysis/PROCESSING_OPTIONS_UI_UPDATES.md +220 -0
  58. package/docs/analysis/RefactorStyles.md +852 -0
  59. package/docs/analysis/STYLE_PARAMETER_ENHANCEMENT.md +143 -0
  60. package/docs/analysis/docxmlater-comparison-todo-2025-11-13.md +636 -0
  61. package/docs/analysis/docxmlater-implementation-analysis-2025-11-13.md +340 -0
  62. package/docs/analysis/docxmlater-template_ui-integration-analysis.md +263 -0
  63. package/docs/analysis/github-issues-to-create.md +237 -0
  64. package/docs/api/API_README.md +538 -0
  65. package/docs/api/API_REFERENCE.md +751 -0
  66. package/docs/api/TYPE_DEFINITIONS.md +869 -0
  67. package/docs/architecture/FONT_EMBEDDING_GUIDE.md +318 -0
  68. package/docs/architecture/docxmlater-functions-and-structure.md +726 -0
  69. package/docs/docxmlater-readme.md +1341 -0
  70. package/docs/fixes/EXECUTION_LOG_TEST_BASE.md +573 -0
  71. package/docs/fixes/HYPERLINK_TEXT_SANITIZATION.md +253 -0
  72. package/docs/fixes/README.md +37 -0
  73. package/docs/github-issues/issue-1-body.md +125 -0
  74. package/docs/github-issues/issue-10-body.md +850 -0
  75. package/docs/github-issues/issue-2-body.md +200 -0
  76. package/docs/github-issues/issue-3-body.md +270 -0
  77. package/docs/github-issues/issue-4-body.md +169 -0
  78. package/docs/github-issues/issue-5-body.md +173 -0
  79. package/docs/github-issues/issue-6-body.md +158 -0
  80. package/docs/github-issues/issue-7-body.md +171 -0
  81. package/docs/github-issues/issue-8-body.md +407 -0
  82. package/docs/github-issues/issue-9-body.md +515 -0
  83. package/docs/github-issues/issue-tracker.md +274 -0
  84. package/docs/github-issues/predictive-analysis-2025-10-18.md +2131 -0
  85. package/docs/implementation/List_Framework_Refactor_Plan.md +336 -0
  86. package/docs/implementation/PRIMARY_TEXT_COLOR_FEATURE.md +217 -0
  87. package/docs/implementation/RELEASE_PLAN_v2.1.0.md +362 -0
  88. package/docs/implementation/RefactorStyles.md +588 -0
  89. package/docs/implementation/implement-plan.md +489 -0
  90. package/docs/implementation/missing-helpers-implementation.md +391 -0
  91. package/docs/implementation/refactor-plan.md +520 -0
  92. package/docs/implementation/session-implementation-complete.md +233 -0
  93. package/docs/implementation/session-management-plan.md +250 -0
  94. package/docs/setup-checklist.md +77 -0
  95. package/docs/versions/changelog.md +345 -0
  96. package/electron/customUpdater.ts +656 -0
  97. package/electron/main.ts +2441 -0
  98. package/electron/memoryConfig.ts +187 -0
  99. package/electron/preload.ts +394 -0
  100. package/electron/proxyConfig.ts +340 -0
  101. package/electron/services/BackupService.ts +452 -0
  102. package/electron/services/DictionaryService.ts +402 -0
  103. package/electron/services/LocalDictionaryLookupService.ts +147 -0
  104. package/electron/services/PowerAutomateApiService.ts +231 -0
  105. package/electron/services/SharePointSyncService.ts +474 -0
  106. package/electron/windowsCertStore.ts +427 -0
  107. package/electron/zscalerConfig.ts +381 -0
  108. package/eslint.config.js +92 -0
  109. package/jest.config.js +52 -0
  110. package/package.json +214 -0
  111. package/postcss.config.mjs +6 -0
  112. package/public/icon.png +0 -0
  113. package/publish-release.ps1 +5 -0
  114. package/renovate.json +30 -0
  115. package/src/App.tsx +216 -0
  116. package/src/__mocks__/p-limit.js +12 -0
  117. package/src/__mocks__/styleMock.js +1 -0
  118. package/src/components/common/BugReportButton.tsx +44 -0
  119. package/src/components/common/BugReportDialog.tsx +193 -0
  120. package/src/components/common/Button.tsx +153 -0
  121. package/src/components/common/Card.tsx +86 -0
  122. package/src/components/common/ColorPickerDialog.tsx +177 -0
  123. package/src/components/common/ConfirmDialog.tsx +96 -0
  124. package/src/components/common/DebugConsole.tsx +275 -0
  125. package/src/components/common/EmptyState.tsx +183 -0
  126. package/src/components/common/ErrorBoundary.tsx +98 -0
  127. package/src/components/common/ErrorDetailsDialog.tsx +153 -0
  128. package/src/components/common/ErrorFallback.tsx +218 -0
  129. package/src/components/common/Input.tsx +109 -0
  130. package/src/components/common/Skeleton.tsx +184 -0
  131. package/src/components/common/SplashScreen.tsx +81 -0
  132. package/src/components/common/Toast.tsx +155 -0
  133. package/src/components/common/Tooltip.tsx +79 -0
  134. package/src/components/common/UpdateNotification.tsx +320 -0
  135. package/src/components/comparison/ComparisonWindow.tsx +374 -0
  136. package/src/components/comparison/SideBySideDiff.tsx +486 -0
  137. package/src/components/comparison/index.ts +8 -0
  138. package/src/components/document/DocumentUploader.tsx +288 -0
  139. package/src/components/document/HyperlinkPreview.tsx +430 -0
  140. package/src/components/document/HyperlinkService.md +1484 -0
  141. package/src/components/document/Hyperlink_Technical_Documentation.md +496 -0
  142. package/src/components/document/InlineChangesView.tsx +707 -0
  143. package/src/components/document/ProcessingProgress.tsx +303 -0
  144. package/src/components/document/ProcessingResults.tsx +256 -0
  145. package/src/components/document/TrackedChangesDetail.tsx +530 -0
  146. package/src/components/document/TrackedChangesPanel.tsx +546 -0
  147. package/src/components/document/VirtualDocumentList.tsx +240 -0
  148. package/src/components/editor/DocumentEditor.tsx +723 -0
  149. package/src/components/editor/DocumentEditorModal.tsx +640 -0
  150. package/src/components/editor/EditorQuickActions.tsx +502 -0
  151. package/src/components/editor/EditorToolbar.tsx +312 -0
  152. package/src/components/editor/TableEditor.tsx +926 -0
  153. package/src/components/editor/index.ts +18 -0
  154. package/src/components/layout/Header.tsx +190 -0
  155. package/src/components/layout/Sidebar.tsx +313 -0
  156. package/src/components/layout/TitleBar.tsx +190 -0
  157. package/src/components/navigation/CommandPalette.tsx +233 -0
  158. package/src/components/navigation/KeyboardShortcutsModal.tsx +173 -0
  159. package/src/components/sessions/ChangeItem.tsx +408 -0
  160. package/src/components/sessions/ChangeViewer.tsx +1155 -0
  161. package/src/components/sessions/DocumentComparisonModal.tsx +314 -0
  162. package/src/components/sessions/ProcessingOptions.tsx +297 -0
  163. package/src/components/sessions/ReplacementsTab.tsx +438 -0
  164. package/src/components/sessions/RevisionHandlingOptions.tsx +87 -0
  165. package/src/components/sessions/SessionManager.tsx +188 -0
  166. package/src/components/sessions/StylesEditor.tsx +1335 -0
  167. package/src/components/sessions/TabContainer.tsx +151 -0
  168. package/src/components/sessions/VirtualSessionList.tsx +157 -0
  169. package/src/components/sessions/sessionToProcessorManager.tsx +420 -0
  170. package/src/components/settings/CertificateManager.tsx +410 -0
  171. package/src/components/settings/SegmentedControl.tsx +88 -0
  172. package/src/components/settings/SettingRow.tsx +52 -0
  173. package/src/contexts/GlobalStatsContext.tsx +396 -0
  174. package/src/contexts/SessionContext.tsx +2129 -0
  175. package/src/contexts/ThemeContext.tsx +428 -0
  176. package/src/contexts/UserSettingsContext.tsx +290 -0
  177. package/src/contexts/__tests__/GlobalStatsContext.test.tsx +390 -0
  178. package/src/global.d.ts +273 -0
  179. package/src/hooks/useDocumentQueue.tsx +210 -0
  180. package/src/hooks/useToast.tsx +55 -0
  181. package/src/main.tsx +10 -0
  182. package/src/pages/Analytics.tsx +386 -0
  183. package/src/pages/CurrentSession.tsx +1174 -0
  184. package/src/pages/Dashboard.tsx +319 -0
  185. package/src/pages/Documents.tsx +317 -0
  186. package/src/pages/Projects.tsx +250 -0
  187. package/src/pages/Reporting.tsx +386 -0
  188. package/src/pages/Search.tsx +349 -0
  189. package/src/pages/Sessions.tsx +285 -0
  190. package/src/pages/Settings.tsx +2662 -0
  191. package/src/services/HyperlinkService.ts +1085 -0
  192. package/src/services/document/DocXMLaterProcessor.ts +617 -0
  193. package/src/services/document/DocumentProcessingComparison.ts +856 -0
  194. package/src/services/document/DocumentSnapshotService.ts +575 -0
  195. package/src/services/document/WordDocumentProcessor.ts +10509 -0
  196. package/src/services/document/__tests__/DocXMLaterProcessor.hyperlinks.test.md +311 -0
  197. package/src/services/document/__tests__/WordDocumentProcessor.integration.test.ts +515 -0
  198. package/src/services/document/__tests__/WordDocumentProcessor.test.ts +812 -0
  199. package/src/services/document/blanklines/BlankLineManager.ts +658 -0
  200. package/src/services/document/blanklines/__tests__/paragraphChecks.test.ts +281 -0
  201. package/src/services/document/blanklines/helpers/blankLineInsertion.ts +87 -0
  202. package/src/services/document/blanklines/helpers/blankLineSnapshot.ts +251 -0
  203. package/src/services/document/blanklines/helpers/clearCustom.ts +121 -0
  204. package/src/services/document/blanklines/helpers/contextChecks.ts +117 -0
  205. package/src/services/document/blanklines/helpers/imageChecks.ts +51 -0
  206. package/src/services/document/blanklines/helpers/paragraphChecks.ts +236 -0
  207. package/src/services/document/blanklines/helpers/removeBlanksBetweenListItems.ts +91 -0
  208. package/src/services/document/blanklines/helpers/removeTrailingBlanks.ts +35 -0
  209. package/src/services/document/blanklines/helpers/tableGuards.ts +21 -0
  210. package/src/services/document/blanklines/index.ts +67 -0
  211. package/src/services/document/blanklines/rules/additionRules.ts +337 -0
  212. package/src/services/document/blanklines/rules/indentationRules.ts +317 -0
  213. package/src/services/document/blanklines/rules/removalRules.ts +362 -0
  214. package/src/services/document/blanklines/rules/ruleTypes.ts +92 -0
  215. package/src/services/document/blanklines/types.ts +29 -0
  216. package/src/services/document/helpers/ImageBorderCropper.ts +377 -0
  217. package/src/services/document/helpers/__tests__/whitespace.test.ts +272 -0
  218. package/src/services/document/helpers/whitespace.ts +117 -0
  219. package/src/services/document/list/ListNormalizer.ts +947 -0
  220. package/src/services/document/list/index.ts +45 -0
  221. package/src/services/document/list/list-detection.ts +275 -0
  222. package/src/services/document/list/list-types.ts +162 -0
  223. package/src/services/document/processors/HyperlinkProcessor.ts +370 -0
  224. package/src/services/document/processors/ListProcessor.ts +257 -0
  225. package/src/services/document/processors/StructureProcessor.ts +176 -0
  226. package/src/services/document/processors/StyleProcessor.ts +389 -0
  227. package/src/services/document/processors/TableProcessor.ts +2238 -0
  228. package/src/services/document/processors/__tests__/HyperlinkProcessor.test.ts +314 -0
  229. package/src/services/document/processors/__tests__/ListProcessor.test.ts +291 -0
  230. package/src/services/document/processors/__tests__/StructureProcessor.test.ts +257 -0
  231. package/src/services/document/processors/__tests__/TableProcessor.hlp-tips-bullets.test.ts +459 -0
  232. package/src/services/document/processors/__tests__/TableProcessor.test.ts +1604 -0
  233. package/src/services/document/processors/index.ts +28 -0
  234. package/src/services/document/types/docx-processing.ts +310 -0
  235. package/src/services/editor/EditorActionHandlers.ts +901 -0
  236. package/src/services/editor/index.ts +13 -0
  237. package/src/setupTests.ts +47 -0
  238. package/src/styles/global.css +782 -0
  239. package/src/types/backup.ts +132 -0
  240. package/src/types/dictionary.ts +125 -0
  241. package/src/types/document-processing.ts +331 -0
  242. package/src/types/docxmlater-augments.d.ts +142 -0
  243. package/src/types/editor.ts +280 -0
  244. package/src/types/electron.ts +340 -0
  245. package/src/types/globalStats.ts +155 -0
  246. package/src/types/hyperlink.ts +471 -0
  247. package/src/types/operations.ts +354 -0
  248. package/src/types/session.ts +427 -0
  249. package/src/types/settings.ts +112 -0
  250. package/src/utils/MemoryMonitor.ts +248 -0
  251. package/src/utils/cn.ts +6 -0
  252. package/src/utils/colorConvert.ts +306 -0
  253. package/src/utils/diffUtils.ts +347 -0
  254. package/src/utils/documentUtils.ts +202 -0
  255. package/src/utils/electronGuard.ts +62 -0
  256. package/src/utils/indexedDB.ts +915 -0
  257. package/src/utils/logger.ts +717 -0
  258. package/src/utils/pathSecurity.ts +232 -0
  259. package/src/utils/pathValidator.ts +236 -0
  260. package/src/utils/processingTimeEstimator.ts +153 -0
  261. package/src/utils/safeJsonParse.ts +62 -0
  262. package/src/utils/textSanitizer.ts +162 -0
  263. package/src/utils/urlHelpers.ts +304 -0
  264. package/src/utils/urlPatterns.ts +198 -0
  265. package/src/utils/urlSanitizer.ts +152 -0
  266. package/src/vite-env.d.ts +11 -0
  267. package/tsconfig.electron.json +19 -0
  268. package/tsconfig.json +36 -0
  269. package/tsconfig.node.json +12 -0
  270. package/typedoc.json +45 -0
  271. package/vite.config.ts +152 -0
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Session to Processor Mapper
3
+ *
4
+ * Provides type-safe conversion between Session (UI format) and WordProcessingOptions (Processor format)
5
+ * Prevents style transposition by ensuring all properties are correctly mapped and validated
6
+ */
7
+
8
+ import type { WordProcessingOptions } from '../../services/document/WordDocumentProcessor';
9
+ import type { Session, SessionStyle, TableShadingSettings } from '../../types/session';
10
+
11
+ /**
12
+ * Normalize color from UI format (#RRGGBB) to OOXML format (RRGGBB)
13
+ *
14
+ * @param color - Color in hex format (with or without # prefix)
15
+ * @returns Color in OOXML format (6 hex digits, uppercase, no # prefix)
16
+ */
17
+ function normalizeColor(color: string): string {
18
+ return color.replace('#', '').toUpperCase();
19
+ }
20
+
21
+ /**
22
+ * Validates that a color is in correct format (6 hex digits without # prefix)
23
+ *
24
+ * @param color - Color to validate
25
+ * @returns True if valid OOXML color format
26
+ */
27
+ function isValidOOXMLColor(color: string): boolean {
28
+ return /^[0-9A-Fa-f]{6}$/.test(color);
29
+ }
30
+
31
+ /**
32
+ * Maps SessionStyle[] (UI format) to WordProcessingOptions.styles (Processor format)
33
+ *
34
+ * CRITICAL: Preserves ALL properties to prevent transposition
35
+ * - Includes preserve* flags for conditional formatting
36
+ * - Includes noSpaceBetweenSame for contextual spacing
37
+ * - Includes indentation for list paragraph positioning
38
+ * - Auto-normalizes colors from #RRGGBB to RRGGBB
39
+ *
40
+ * @param sessionStyles - Array of SessionStyle objects from UI
41
+ * @returns Array of style objects compatible with WordProcessingOptions
42
+ */
43
+ export function mapSessionStylesToProcessor(
44
+ sessionStyles: SessionStyle[]
45
+ ): NonNullable<WordProcessingOptions['styles']> {
46
+ return sessionStyles.map((style) => ({
47
+ // Identity
48
+ id: style.id,
49
+ name: style.name,
50
+
51
+ // Font properties
52
+ fontFamily: style.fontFamily,
53
+ fontSize: style.fontSize,
54
+
55
+ // Format properties
56
+ bold: style.bold,
57
+ italic: style.italic,
58
+ underline: style.underline,
59
+
60
+ // Preserve flags - CRITICAL for preventing transposition
61
+ preserveBold: style.preserveBold,
62
+ preserveItalic: style.preserveItalic,
63
+ preserveUnderline: style.preserveUnderline,
64
+
65
+ // Paragraph properties
66
+ alignment: style.alignment,
67
+ spaceBefore: style.spaceBefore,
68
+ spaceAfter: style.spaceAfter,
69
+ lineSpacing: style.lineSpacing,
70
+
71
+ // Advanced properties
72
+ color: normalizeColor(style.color), // Auto-normalize: #000000 → 000000
73
+ noSpaceBetweenSame: style.noSpaceBetweenSame,
74
+ indentation: style.indentation,
75
+ }));
76
+ }
77
+
78
+ /**
79
+ * Maps TableShadingSettings (UI format) to WordProcessingOptions.tableShadingSettings
80
+ *
81
+ * @param settings - Table shading settings from session
82
+ * @returns Normalized table shading settings for processor
83
+ */
84
+ function mapTableShadingSettings(
85
+ settings: TableShadingSettings | undefined
86
+ ): WordProcessingOptions['tableShadingSettings'] {
87
+ if (!settings) return undefined;
88
+
89
+ return {
90
+ header2Shading: normalizeColor(settings.header2Shading),
91
+ otherShading: normalizeColor(settings.otherShading),
92
+ imageBorderWidth: settings.imageBorderWidth ?? 1.0,
93
+ cellBorderThickness: settings.cellBorderThickness ?? 0.5,
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Maps Session.processingOptions.enabledOperations to WordProcessingOptions boolean flags
99
+ *
100
+ * This function provides the bridge between UI checkbox state and processor method execution:
101
+ * - UI stores array of enabled option IDs (e.g., ['remove-italics', 'smart-tables'])
102
+ * - Processor expects individual boolean flags and nested operations object
103
+ *
104
+ * @param enabledOperations - Array of enabled option IDs
105
+ * @returns Partial WordProcessingOptions with appropriate flags set
106
+ */
107
+ function mapEnabledOperationsToFlags(enabledOperations: string[]): Partial<WordProcessingOptions> {
108
+ const enabled = new Set(enabledOperations);
109
+ const flags: Partial<WordProcessingOptions> = {};
110
+
111
+ // ═══════════════════════════════════════════════════════════
112
+ // Text Formatting Group
113
+ // ═══════════════════════════════════════════════════════════
114
+ if (enabled.has('remove-italics')) flags.removeItalics = true;
115
+ if (enabled.has('normalize-dashes')) flags.normalizeDashes = true;
116
+ if (enabled.has('remove-whitespace')) flags.removeWhitespace = true;
117
+
118
+ // ═══════════════════════════════════════════════════════════
119
+ // Content Structure Group
120
+ // ═══════════════════════════════════════════════════════════
121
+ if (enabled.has('remove-paragraph-lines')) flags.removeParagraphLines = true;
122
+ if (enabled.has('remove-headers-footers')) flags.removeHeadersFooters = true;
123
+ if (enabled.has('add-document-warning')) flags.addDocumentWarning = true;
124
+ if (enabled.has('center-border-images')) flags.centerAndBorderImages = true;
125
+
126
+ // ═══════════════════════════════════════════════════════════
127
+ // Lists & Tables Group
128
+ // ═══════════════════════════════════════════════════════════
129
+ if (enabled.has('list-indentation')) {
130
+ // Special case: list-indentation sets listBulletSettings.enabled
131
+ // CRITICAL FIX: Do NOT create the object here - just set the enabled flag
132
+ // The actual indentationLevels will be populated from session.listBulletSettings
133
+ // to preserve UI-configured indentation values
134
+ if (!flags.listBulletSettings) {
135
+ flags.listBulletSettings = { enabled: true } as any;
136
+ } else {
137
+ flags.listBulletSettings.enabled = true;
138
+ }
139
+ }
140
+ if (enabled.has('bullet-uniformity')) flags.bulletUniformity = true;
141
+ if (enabled.has('smart-tables')) {
142
+ flags.smartTables = true;
143
+ flags.tableUniformity = true; // Auto-enable table uniformity with smart tables
144
+ }
145
+ if (enabled.has('standardize-table-borders')) {
146
+ flags.standardizeTableBorders = true;
147
+ }
148
+
149
+ // ═══════════════════════════════════════════════════════════
150
+ // Hyperlink Operations (nested under operations object)
151
+ // NOTE: operations property comes from HyperlinkProcessingOptions parent interface
152
+ // Using type assertion to work with inherited property
153
+ // ═══════════════════════════════════════════════════════════
154
+ const operations: any = {};
155
+ if (enabled.has('update-top-hyperlinks')) operations.updateTopHyperlinks = true;
156
+ if (enabled.has('update-toc-hyperlinks')) operations.updateTocHyperlinks = true;
157
+ if (enabled.has('force-remove-heading1-toc')) operations.forceRemoveHeading1FromTOC = true;
158
+ if (enabled.has('fix-internal-hyperlinks')) operations.fixInternalHyperlinks = true;
159
+ if (enabled.has('fix-content-ids')) operations.fixContentIds = true;
160
+ if (enabled.has('replace-outdated-titles')) operations.replaceOutdatedTitles = true;
161
+ if (enabled.has('validate-document-styles')) operations.validateDocumentStyles = true;
162
+ if (enabled.has('validate-header2-tables')) operations.validateHeader2Tables = true;
163
+
164
+ // Assign operations object using type assertion
165
+ (flags as any).operations = operations;
166
+
167
+ return flags;
168
+ }
169
+
170
+ /**
171
+ * MAIN CONVERTER: Session → WordProcessingOptions
172
+ *
173
+ * Converts complete Session object to WordProcessingOptions for document processing
174
+ * - Type-safe conversion with zero data loss
175
+ * - Auto-normalizes colors (#RRGGBB → RRGGBB)
176
+ * - Maps UI option IDs to processor boolean flags
177
+ * - Preserves all style properties including preserve* flags
178
+ *
179
+ * @param session - Complete Session object from SessionContext
180
+ * @returns WordProcessingOptions ready for WordDocumentProcessor.processDocument()
181
+ */
182
+ export function sessionToProcessorOptions(session: Session): WordProcessingOptions {
183
+ // Base options
184
+ const options: WordProcessingOptions = {
185
+ createBackup: session.processingOptions?.createBackup ?? true,
186
+ validateBeforeProcessing: session.processingOptions?.validateUrls ?? true,
187
+ // Enable change tracking for Document Changes UI - tracks hyperlink and other modifications
188
+ trackChanges: true,
189
+ };
190
+
191
+ // Map enabled operations to boolean flags
192
+ const enabledOps = session.processingOptions?.enabledOperations || [];
193
+ Object.assign(options, mapEnabledOperationsToFlags(enabledOps));
194
+
195
+ // Map styles with ALL properties (prevents transposition)
196
+ if (session.styles && session.styles.length > 0) {
197
+ options.styles = mapSessionStylesToProcessor(session.styles);
198
+ // Only apply styles if the 'validate-document-styles' option is checked
199
+ options.assignStyles = enabledOps.includes('validate-document-styles');
200
+ }
201
+
202
+ // Map list settings (direct copy - interfaces are compatible)
203
+ if (session.listBulletSettings?.enabled) {
204
+ options.listBulletSettings = {
205
+ enabled: true,
206
+ indentationLevels: session.listBulletSettings.indentationLevels,
207
+ spacingBetweenItems: 0, // Use List Paragraph style's spaceAfter instead
208
+ };
209
+ }
210
+
211
+ // Map table shading with color normalization
212
+ options.tableShadingSettings = mapTableShadingSettings(session.tableShadingSettings);
213
+
214
+ // Enable auto-operations based on configuration
215
+ if (options.smartTables) {
216
+ options.tableUniformity = true;
217
+ }
218
+
219
+ return options;
220
+ }
221
+
222
+ /**
223
+ * Validates WordProcessingOptions before processing
224
+ *
225
+ * Catches configuration errors that would cause document corruption:
226
+ * - Invalid color formats (must be 6 hex digits without #)
227
+ * - Invalid font sizes (range: 1-1638 pt)
228
+ * - Invalid spacing values (must be non-negative)
229
+ * - Missing required properties
230
+ *
231
+ * @param options - WordProcessingOptions to validate
232
+ * @returns Validation result with specific error messages
233
+ */
234
+ export function validateProcessingOptions(options: WordProcessingOptions): {
235
+ valid: boolean;
236
+ errors: string[];
237
+ } {
238
+ const errors: string[] = [];
239
+
240
+ // Validate styles if present
241
+ if (options.styles) {
242
+ for (const style of options.styles) {
243
+ // Required fields
244
+ if (!style.id || !style.name) {
245
+ errors.push(`Style missing required fields: id="${style.id}", name="${style.name}"`);
246
+ }
247
+
248
+ // Color format: must be 6 hex digits WITHOUT # prefix at this point
249
+ if (style.color && !isValidOOXMLColor(style.color)) {
250
+ errors.push(
251
+ `Invalid color for style "${style.id}": "${style.color}" ` +
252
+ `(expected 6 hex digits without # prefix, e.g., "000000")`
253
+ );
254
+ }
255
+
256
+ // Font size range (Word maximum is 1638 pt)
257
+ if (style.fontSize <= 0 || style.fontSize > 1638) {
258
+ errors.push(
259
+ `Invalid fontSize for style "${style.id}": ${style.fontSize} ` + `(valid range: 1-1638)`
260
+ );
261
+ }
262
+
263
+ // Spacing must be non-negative
264
+ if (style.spaceBefore < 0) {
265
+ errors.push(
266
+ `Invalid spaceBefore for style "${style.id}": ${style.spaceBefore} (must be >= 0)`
267
+ );
268
+ }
269
+ if (style.spaceAfter < 0) {
270
+ errors.push(
271
+ `Invalid spaceAfter for style "${style.id}": ${style.spaceAfter} (must be >= 0)`
272
+ );
273
+ }
274
+
275
+ // Line spacing multiplier (typical: 1.0, 1.15, 1.5, 2.0)
276
+ if (style.lineSpacing <= 0 || style.lineSpacing > 10) {
277
+ errors.push(
278
+ `Invalid lineSpacing for style "${style.id}": ${style.lineSpacing} ` +
279
+ `(valid range: 0.1-10)`
280
+ );
281
+ }
282
+
283
+ // Indentation validation (if present)
284
+ if (style.indentation) {
285
+ if (
286
+ style.indentation.left !== undefined &&
287
+ (style.indentation.left < 0 || style.indentation.left > 10)
288
+ ) {
289
+ errors.push(
290
+ `Invalid indentation.left for style "${style.id}": ${style.indentation.left} ` +
291
+ `(valid range: 0-10 inches)`
292
+ );
293
+ }
294
+ if (
295
+ style.indentation.firstLine !== undefined &&
296
+ (style.indentation.firstLine < 0 || style.indentation.firstLine > 10)
297
+ ) {
298
+ errors.push(
299
+ `Invalid indentation.firstLine for style "${style.id}": ${style.indentation.firstLine} ` +
300
+ `(valid range: 0-10 inches)`
301
+ );
302
+ }
303
+ }
304
+ }
305
+ }
306
+
307
+ // Validate table shading colors
308
+ if (options.tableShadingSettings) {
309
+ const { header2Shading, otherShading } = options.tableShadingSettings;
310
+
311
+ if (header2Shading && !isValidOOXMLColor(header2Shading)) {
312
+ errors.push(
313
+ `Invalid header2Shading color: "${header2Shading}" ` +
314
+ `(expected 6 hex digits without # prefix, e.g., "BFBFBF")`
315
+ );
316
+ }
317
+
318
+ if (otherShading && !isValidOOXMLColor(otherShading)) {
319
+ errors.push(
320
+ `Invalid otherShading color: "${otherShading}" ` +
321
+ `(expected 6 hex digits without # prefix, e.g., "DFDFDF")`
322
+ );
323
+ }
324
+ }
325
+
326
+ // Validate list settings if enabled
327
+ if (options.listBulletSettings?.enabled) {
328
+ if (
329
+ !options.listBulletSettings.indentationLevels ||
330
+ options.listBulletSettings.indentationLevels.length === 0
331
+ ) {
332
+ errors.push('List settings enabled but indentationLevels array is empty or undefined');
333
+ } else {
334
+ // Validate each indentation level
335
+ for (const level of options.listBulletSettings.indentationLevels) {
336
+ if (level.symbolIndent < 0 || level.symbolIndent > 10) {
337
+ errors.push(
338
+ `Invalid symbolIndent at level ${level.level}: ${level.symbolIndent} inches ` +
339
+ `(valid range: 0-10)`
340
+ );
341
+ }
342
+ if (level.textIndent < 0 || level.textIndent > 10) {
343
+ errors.push(
344
+ `Invalid textIndent at level ${level.level}: ${level.textIndent} inches ` +
345
+ `(valid range: 0-10)`
346
+ );
347
+ }
348
+ if (level.textIndent <= level.symbolIndent) {
349
+ errors.push(
350
+ `Invalid indentation at level ${level.level}: textIndent (${level.textIndent}) ` +
351
+ `must be greater than symbolIndent (${level.symbolIndent})`
352
+ );
353
+ }
354
+ }
355
+ }
356
+ }
357
+
358
+ return {
359
+ valid: errors.length === 0,
360
+ errors,
361
+ };
362
+ }
363
+
364
+ /**
365
+ * Quick validation check - returns true if options are valid
366
+ *
367
+ * @param options - WordProcessingOptions to check
368
+ * @returns True if valid, false otherwise
369
+ */
370
+ export function isValid(options: WordProcessingOptions): boolean {
371
+ return validateProcessingOptions(options).valid;
372
+ }
373
+
374
+ /**
375
+ * Development helper: Logs validation errors to console
376
+ *
377
+ * @param options - WordProcessingOptions to validate
378
+ * @returns True if valid, false with console errors if invalid
379
+ */
380
+ export function validateAndLog(options: WordProcessingOptions): boolean {
381
+ const result = validateProcessingOptions(options);
382
+
383
+ if (!result.valid) {
384
+ console.error('❌ WordProcessingOptions validation failed:');
385
+ result.errors.forEach((error, index) => {
386
+ console.error(` ${index + 1}. ${error}`);
387
+ });
388
+ } else {
389
+ console.log('✅ WordProcessingOptions validation passed');
390
+ }
391
+
392
+ return result.valid;
393
+ }
394
+
395
+ /**
396
+ * Helper: Get user-friendly description of which operations are enabled
397
+ * Useful for logging and debugging
398
+ *
399
+ * @param session - Session to describe
400
+ * @returns Human-readable string of enabled operations
401
+ */
402
+ export function describeEnabledOperations(session: Session): string {
403
+ const enabledOps = session.processingOptions?.enabledOperations || [];
404
+
405
+ if (enabledOps.length === 0) {
406
+ return 'No operations enabled';
407
+ }
408
+
409
+ const opNames = enabledOps.map((op) => {
410
+ // Convert kebab-case to Title Case
411
+ return op
412
+ .split('-')
413
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
414
+ .join(' ');
415
+ });
416
+
417
+ return `${enabledOps.length} operations: ${opNames.slice(0, 5).join(', ')}${
418
+ enabledOps.length > 5 ? '...' : ''
419
+ }`;
420
+ }