@eigenpal/docx-js-editor 0.0.20 → 0.0.21

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 (200) hide show
  1. package/dist/{ClipboardManager-EZ0C6Onq.d.cts → ClipboardManager-B1jZrC6h.d.cts} +1 -1
  2. package/dist/{ClipboardManager-D6dkOFg6.d.ts → ClipboardManager-jqJVxB6g.d.ts} +1 -1
  3. package/dist/{DocumentAgent-BcCDg7i2.d.ts → DocumentAgent-CnJ9AEl_.d.cts} +31 -3
  4. package/dist/{DocumentAgent-B0EC8lPC.d.cts → DocumentAgent-CrbsDniO.d.ts} +31 -3
  5. package/dist/{FindReplaceDialog-AWQXKEUQ.js → FindReplaceDialog-AQFR4OCT.js} +1 -2
  6. package/dist/FindReplaceDialog-J3DI3U5I.cjs +1 -0
  7. package/dist/{FootnotePropertiesDialog-73VT2ZVZ.cjs → FootnotePropertiesDialog-DO5DCAW6.cjs} +1 -2
  8. package/dist/{FootnotePropertiesDialog-ZM3EF3EF.js → FootnotePropertiesDialog-YYIZU5U6.js} +1 -2
  9. package/dist/{HyperlinkDialog-BA25XUT5.js → HyperlinkDialog-HGZ2S37Z.js} +1 -2
  10. package/dist/HyperlinkDialog-PEPS3C2G.cjs +1 -0
  11. package/dist/{ImagePositionDialog-AIAMKPFK.js → ImagePositionDialog-DQ4JWS4F.js} +1 -2
  12. package/dist/{ImagePositionDialog-KMK7ROV2.cjs → ImagePositionDialog-UYXYHSP4.cjs} +1 -2
  13. package/dist/{ImagePropertiesDialog-ERFCUVCW.js → ImagePropertiesDialog-GJMGLM6G.js} +1 -2
  14. package/dist/{ImagePropertiesDialog-USMMRK6X.cjs → ImagePropertiesDialog-V6SVKINO.cjs} +1 -2
  15. package/dist/{TablePropertiesDialog-72CIUAZT.cjs → TablePropertiesDialog-A36OXG3A.cjs} +1 -2
  16. package/dist/{TablePropertiesDialog-EMUEVYB3.js → TablePropertiesDialog-STZOGHJB.js} +1 -2
  17. package/dist/{agentApi-BFVyKagE.d.cts → agentApi-DfsWRyrP.d.cts} +1 -1
  18. package/dist/{agentApi-BFVyKagE.d.ts → agentApi-DfsWRyrP.d.ts} +1 -1
  19. package/dist/{chunk-FDANI5P4.cjs → chunk-2VHQ7YOQ.cjs} +1 -2
  20. package/dist/chunk-2Y6FLZ5Q.js +3 -0
  21. package/dist/chunk-32HMU2UV.js +111 -0
  22. package/dist/chunk-4CUGBNL2.cjs +1 -0
  23. package/dist/chunk-5GFXHUMP.js +1 -0
  24. package/dist/chunk-6NDMKJIE.js +9 -0
  25. package/dist/chunk-6NYA53QC.cjs +258 -0
  26. package/dist/chunk-7KJ3YVDQ.js +10 -0
  27. package/dist/{chunk-JOYPFQW2.js → chunk-AARNCPWR.js} +1 -2
  28. package/dist/{chunk-4QT5LPBA.cjs → chunk-B7TICMXD.cjs} +16 -17
  29. package/dist/{chunk-2QOEHCBX.js → chunk-BUEMG4NW.js} +1 -2
  30. package/dist/{chunk-CV5WFE7K.js → chunk-CLDB6TL7.js} +2 -3
  31. package/dist/{chunk-M2T6XKT5.js → chunk-CTYOM6BE.js} +1 -2
  32. package/dist/chunk-EH3NY2DQ.cjs +26 -0
  33. package/dist/{chunk-FGVGZLBL.js → chunk-FVUGBRDD.js} +1 -2
  34. package/dist/chunk-FXJAIFPR.js +59 -0
  35. package/dist/chunk-GICVJSFJ.cjs +9 -0
  36. package/dist/{chunk-Y6VCTLCJ.js → chunk-H5NTJZO4.js} +1 -2
  37. package/dist/chunk-HT2Z33YM.cjs +111 -0
  38. package/dist/chunk-JRRTZZ72.cjs +1 -0
  39. package/dist/{chunk-T2HQYRA7.cjs → chunk-NVAQQYBJ.cjs} +1 -2
  40. package/dist/chunk-P3AEZKQO.cjs +3 -0
  41. package/dist/{chunk-GWBTKVFD.cjs → chunk-P7ZF45KZ.cjs} +1 -2
  42. package/dist/{chunk-QEBO3EQP.cjs → chunk-PCJ5ACUV.cjs} +1 -2
  43. package/dist/{chunk-Q6HUGWO6.js → chunk-PJVI53AH.js} +1 -2
  44. package/dist/chunk-Q7YYC75E.js +258 -0
  45. package/dist/{chunk-7JSPKVOW.js → chunk-QVPR2W5S.js} +1 -2
  46. package/dist/{chunk-XZNOV52K.cjs → chunk-TAF6KYDM.cjs} +4 -5
  47. package/dist/chunk-USRMBYI6.js +3 -0
  48. package/dist/chunk-UTWPV2I4.js +26 -0
  49. package/dist/{chunk-DJAEBZ33.cjs → chunk-VTAS7VZ6.cjs} +1 -2
  50. package/dist/chunk-XQNCLN4T.cjs +3 -0
  51. package/dist/{chunk-S26DZVRQ.cjs → chunk-XS2AQFMF.cjs} +1 -2
  52. package/dist/chunk-Y6QBJGMO.cjs +59 -0
  53. package/dist/{chunk-WD2HTKRR.cjs → chunk-YS7FDEZ4.cjs} +1 -2
  54. package/dist/chunk-ZTVQA46Q.js +1 -0
  55. package/dist/{clipboard-beGtyabO.d.ts → clipboard-BE8E-szx.d.ts} +1 -1
  56. package/dist/{clipboard-CqE-UZ2d.d.cts → clipboard-DkfAv07F.d.cts} +1 -1
  57. package/dist/{colorResolver-B5YbO_a4.d.ts → colorResolver-CYttioMe.d.ts} +46 -3
  58. package/dist/{colorResolver-Cu46bSKr.d.cts → colorResolver-Dr8kQZAQ.d.cts} +46 -3
  59. package/dist/core-plugins-reexport.cjs +1 -2
  60. package/dist/core-plugins-reexport.d.cts +4 -4
  61. package/dist/core-plugins-reexport.d.ts +4 -4
  62. package/dist/core-plugins-reexport.js +1 -2
  63. package/dist/core-reexport.cjs +1 -2
  64. package/dist/core-reexport.d.cts +10 -10
  65. package/dist/core-reexport.d.ts +10 -10
  66. package/dist/core-reexport.js +1 -2
  67. package/dist/executor-JGWZ7S6Z.cjs +1 -0
  68. package/dist/executor-L2MVKMXO.js +1 -0
  69. package/dist/{fontLoader-CFKpg0Ri.d.ts → fontLoader-BsqQnB4v.d.ts} +1 -1
  70. package/dist/{fontLoader-HZYfILUm.d.cts → fontLoader-DECXIoMr.d.cts} +1 -1
  71. package/dist/headless-reexport.cjs +4 -5
  72. package/dist/headless-reexport.d.cts +7 -7
  73. package/dist/headless-reexport.d.ts +7 -7
  74. package/dist/headless-reexport.js +4 -5
  75. package/dist/index.cjs +6 -7
  76. package/dist/index.css +0 -1
  77. package/dist/index.d.cts +12 -12
  78. package/dist/index.d.ts +12 -12
  79. package/dist/index.js +6 -7
  80. package/dist/lib-GD2QD2JK.js +1 -0
  81. package/dist/lib-HOLGQI5K.cjs +1 -0
  82. package/dist/mcp-reexport.cjs +9 -10
  83. package/dist/mcp-reexport.d.cts +2 -2
  84. package/dist/mcp-reexport.d.ts +2 -2
  85. package/dist/mcp-reexport.js +4 -5
  86. package/dist/{processTemplate-G37IM66O.js → processTemplate-3HN7Q3KT.js} +1 -2
  87. package/dist/processTemplate-BXZKWRQD.cjs +1 -0
  88. package/dist/{react-BjOCdeTs.d.ts → react-C6bgHDFl.d.ts} +8 -6
  89. package/dist/{react-UzAn4o7l.d.cts → react-CAlVCYa4.d.cts} +8 -6
  90. package/dist/react.cjs +1 -2
  91. package/dist/react.css +0 -1
  92. package/dist/react.d.cts +5 -5
  93. package/dist/react.d.ts +5 -5
  94. package/dist/react.js +1 -2
  95. package/dist/{registry-DjacfR6Q.d.cts → registry-BU-FbHh-.d.cts} +1 -1
  96. package/dist/{registry-CV6nYWqP.d.ts → registry-gRbkCooh.d.ts} +1 -1
  97. package/dist/selectionRects-7QU337P5.cjs +1 -0
  98. package/dist/selectionRects-V5RC2BYX.js +1 -0
  99. package/dist/styles.css +1 -1
  100. package/dist/{types-DwZ3xysp.d.ts → types-7wjInVMW.d.ts} +1 -1
  101. package/dist/{types-Bnp8rvJn.d.cts → types-DEEpBL9H.d.cts} +1 -1
  102. package/dist/ui.cjs +1 -2
  103. package/dist/ui.d.cts +32 -85
  104. package/dist/ui.d.ts +32 -85
  105. package/dist/ui.js +1 -2
  106. package/dist/{variableDetector-CMhJtM96.d.cts → variableDetector-B4oQJa2e.d.cts} +33 -2
  107. package/dist/{variableDetector-BaDeXz7D.d.ts → variableDetector-BXJaTkiB.d.ts} +33 -2
  108. package/package.json +1 -1
  109. package/dist/FindReplaceDialog-AWQXKEUQ.js.map +0 -1
  110. package/dist/FindReplaceDialog-I4SZDSVP.cjs +0 -2
  111. package/dist/FindReplaceDialog-I4SZDSVP.cjs.map +0 -1
  112. package/dist/FootnotePropertiesDialog-73VT2ZVZ.cjs.map +0 -1
  113. package/dist/FootnotePropertiesDialog-ZM3EF3EF.js.map +0 -1
  114. package/dist/HyperlinkDialog-BA25XUT5.js.map +0 -1
  115. package/dist/HyperlinkDialog-V63LPOT2.cjs +0 -2
  116. package/dist/HyperlinkDialog-V63LPOT2.cjs.map +0 -1
  117. package/dist/ImagePositionDialog-AIAMKPFK.js.map +0 -1
  118. package/dist/ImagePositionDialog-KMK7ROV2.cjs.map +0 -1
  119. package/dist/ImagePropertiesDialog-ERFCUVCW.js.map +0 -1
  120. package/dist/ImagePropertiesDialog-USMMRK6X.cjs.map +0 -1
  121. package/dist/TablePropertiesDialog-72CIUAZT.cjs.map +0 -1
  122. package/dist/TablePropertiesDialog-EMUEVYB3.js.map +0 -1
  123. package/dist/chunk-2CHPKB5A.cjs +0 -112
  124. package/dist/chunk-2CHPKB5A.cjs.map +0 -1
  125. package/dist/chunk-2QOEHCBX.js.map +0 -1
  126. package/dist/chunk-4QT5LPBA.cjs.map +0 -1
  127. package/dist/chunk-5DYSI4O4.cjs +0 -60
  128. package/dist/chunk-5DYSI4O4.cjs.map +0 -1
  129. package/dist/chunk-5FJXHXFV.cjs +0 -2
  130. package/dist/chunk-5FJXHXFV.cjs.map +0 -1
  131. package/dist/chunk-6FEWNF6B.js +0 -4
  132. package/dist/chunk-6FEWNF6B.js.map +0 -1
  133. package/dist/chunk-6LF5HZCV.js +0 -10
  134. package/dist/chunk-6LF5HZCV.js.map +0 -1
  135. package/dist/chunk-7JSPKVOW.js.map +0 -1
  136. package/dist/chunk-C33XDRDJ.cjs +0 -28
  137. package/dist/chunk-C33XDRDJ.cjs.map +0 -1
  138. package/dist/chunk-CV5WFE7K.js.map +0 -1
  139. package/dist/chunk-CXJRNISO.js +0 -2
  140. package/dist/chunk-CXJRNISO.js.map +0 -1
  141. package/dist/chunk-DJAEBZ33.cjs.map +0 -1
  142. package/dist/chunk-DP6Q75ZD.js +0 -28
  143. package/dist/chunk-DP6Q75ZD.js.map +0 -1
  144. package/dist/chunk-FDANI5P4.cjs.map +0 -1
  145. package/dist/chunk-FGVGZLBL.js.map +0 -1
  146. package/dist/chunk-GJ4GKSDU.cjs +0 -2
  147. package/dist/chunk-GJ4GKSDU.cjs.map +0 -1
  148. package/dist/chunk-GWBTKVFD.cjs.map +0 -1
  149. package/dist/chunk-JOYPFQW2.js.map +0 -1
  150. package/dist/chunk-L54YNLSE.js +0 -2
  151. package/dist/chunk-L54YNLSE.js.map +0 -1
  152. package/dist/chunk-LPGMLJMO.js +0 -259
  153. package/dist/chunk-LPGMLJMO.js.map +0 -1
  154. package/dist/chunk-M2T6XKT5.js.map +0 -1
  155. package/dist/chunk-OHG7ROFC.js +0 -11
  156. package/dist/chunk-OHG7ROFC.js.map +0 -1
  157. package/dist/chunk-PANKMCFX.cjs +0 -4
  158. package/dist/chunk-PANKMCFX.cjs.map +0 -1
  159. package/dist/chunk-Q6HUGWO6.js.map +0 -1
  160. package/dist/chunk-QDV75OJ4.js +0 -112
  161. package/dist/chunk-QDV75OJ4.js.map +0 -1
  162. package/dist/chunk-QEBO3EQP.cjs.map +0 -1
  163. package/dist/chunk-QVIZ775M.cjs +0 -259
  164. package/dist/chunk-QVIZ775M.cjs.map +0 -1
  165. package/dist/chunk-RMUMR42R.cjs +0 -10
  166. package/dist/chunk-RMUMR42R.cjs.map +0 -1
  167. package/dist/chunk-S26DZVRQ.cjs.map +0 -1
  168. package/dist/chunk-T2HQYRA7.cjs.map +0 -1
  169. package/dist/chunk-ULXNEG66.js +0 -60
  170. package/dist/chunk-ULXNEG66.js.map +0 -1
  171. package/dist/chunk-WD2HTKRR.cjs.map +0 -1
  172. package/dist/chunk-XZNOV52K.cjs.map +0 -1
  173. package/dist/chunk-Y6VCTLCJ.js.map +0 -1
  174. package/dist/core-plugins-reexport.cjs.map +0 -1
  175. package/dist/core-plugins-reexport.js.map +0 -1
  176. package/dist/core-reexport.cjs.map +0 -1
  177. package/dist/core-reexport.js.map +0 -1
  178. package/dist/executor-K5RXUTTR.js +0 -2
  179. package/dist/executor-K5RXUTTR.js.map +0 -1
  180. package/dist/executor-XIPIU3H4.cjs +0 -2
  181. package/dist/executor-XIPIU3H4.cjs.map +0 -1
  182. package/dist/headless-reexport.cjs.map +0 -1
  183. package/dist/headless-reexport.js.map +0 -1
  184. package/dist/index.cjs.map +0 -1
  185. package/dist/index.css.map +0 -1
  186. package/dist/index.js.map +0 -1
  187. package/dist/mcp-reexport.cjs.map +0 -1
  188. package/dist/mcp-reexport.js.map +0 -1
  189. package/dist/processTemplate-G37IM66O.js.map +0 -1
  190. package/dist/processTemplate-RFBGVH7T.cjs +0 -2
  191. package/dist/processTemplate-RFBGVH7T.cjs.map +0 -1
  192. package/dist/react.cjs.map +0 -1
  193. package/dist/react.css.map +0 -1
  194. package/dist/react.js.map +0 -1
  195. package/dist/selectionRects-6DU7HN7E.js +0 -2
  196. package/dist/selectionRects-6DU7HN7E.js.map +0 -1
  197. package/dist/selectionRects-YZSC24ZP.cjs +0 -2
  198. package/dist/selectionRects-YZSC24ZP.cjs.map +0 -1
  199. package/dist/ui.cjs.map +0 -1
  200. package/dist/ui.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/dialogs/findReplaceUtils.ts","../src/components/dialogs/useFindReplace.ts","../src/components/dialogs/FindReplaceDialog.tsx"],"names":["createDefaultFindOptions","escapeRegexString","str","createSearchPattern","searchText","options","pattern","flags","findAllMatches","content","matches","searchFor","escapeRegex","regex","match","replaceAllInContent","replaceText","replaceFirstInContent","startIndex","m","getMatchCountText","result","isEmptySearch","getDefaultHighlightOptions","getRunText","run","text","item","getParagraphPlainText","paragraph","child","findInDocument","document","body","paragraphIndex","block","paragraphMatches","findInParagraph","row","cell","cellContent","paragraphText","textMatches","contentInfo","findContentAtOffset","offset","currentOffset","contentIndex","itemText","itemLength","scrollToMatch","containerElement","paragraphElement","useFindReplace","hookOptions","state","setState","useState","openFind","useCallback","selectedText","prev","openReplace","close","toggle","setSearchText","setReplaceText","setOptions","setMatches","currentIndex","newIndex","goToNextMatch","goToPreviousMatch","goToMatch","index","getCurrentMatch","hasMatches","DIALOG_OVERLAY_STYLE","DIALOG_CONTENT_STYLE","DIALOG_HEADER_STYLE","DIALOG_TITLE_STYLE","CLOSE_BUTTON_STYLE","DIALOG_BODY_STYLE","ROW_STYLE","LABEL_STYLE","INPUT_STYLE","INPUT_FOCUS_STYLE","BUTTON_CONTAINER_STYLE","BUTTON_BASE_STYLE","BUTTON_DISABLED_STYLE","NAV_BUTTON_STYLE","NAV_BUTTON_DISABLED_STYLE","OPTIONS_CONTAINER_STYLE","CHECKBOX_LABEL_STYLE","CHECKBOX_STYLE","STATUS_STYLE","NO_RESULTS_STYLE","ChevronUpIcon","style","jsx","ChevronDownIcon","FindReplaceDialog","isOpen","onClose","onFind","onFindNext","onFindPrevious","onReplace","onReplaceAll","onHighlightMatches","onClearHighlights","initialSearchText","replaceMode","currentResult","className","showReplace","setShowReplace","matchCase","setMatchCase","matchWholeWord","setMatchWholeWord","setResult","searchFocused","setSearchFocused","replaceFocused","setReplaceFocused","searchInputRef","useRef","replaceInputRef","useEffect","searchResult","performSearch","handleSearchChange","e","handleSearchKeyDown","handleFindPrevious","handleFindNext","handleReplaceKeyDown","handleReplace","newResult","handleReplaceAll","toggleReplaceMode","newValue","handleOverlayClick","handleDialogKeyDown","noMatches","jsxs","Fragment","FindReplaceDialog_default"],"mappings":"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","file":"chunk-M2T6XKT5.js","sourcesContent":["/**\n * Find & Replace Utility Functions\n *\n * Pure utility functions for text search, pattern matching, and document search.\n * Extracted from FindReplaceDialog.tsx.\n */\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * A single match result in the document\n */\nexport interface FindMatch {\n /** Index of the paragraph containing the match */\n paragraphIndex: number;\n /** Index of the run/content within the paragraph */\n contentIndex: number;\n /** Character offset within the content */\n startOffset: number;\n /** Character offset for end of match */\n endOffset: number;\n /** The matched text */\n text: string;\n}\n\n/**\n * Find options for controlling search behavior\n */\nexport interface FindOptions {\n /** Whether to match case */\n matchCase: boolean;\n /** Whether to match whole words only */\n matchWholeWord: boolean;\n /** Whether to use regular expressions (future) */\n useRegex?: boolean;\n}\n\n/**\n * Find result with all matches\n */\nexport interface FindResult {\n /** All matches found */\n matches: FindMatch[];\n /** Total match count */\n totalCount: number;\n /** Current match index (0-based) */\n currentIndex: number;\n}\n\n/**\n * Highlight options for document rendering\n */\nexport interface HighlightOptions {\n /** Background color for current match */\n currentMatchColor: string;\n /** Background color for other matches */\n otherMatchColor: string;\n}\n\n// ============================================================================\n// TEXT SEARCH UTILITIES\n// ============================================================================\n\n/**\n * Create default find options\n */\nexport function createDefaultFindOptions(): FindOptions {\n return {\n matchCase: false,\n matchWholeWord: false,\n useRegex: false,\n };\n}\n\n/**\n * Escape string for use in regex pattern\n */\nexport function escapeRegexString(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Create a regex pattern from search text and options\n */\nexport function createSearchPattern(searchText: string, options: FindOptions): RegExp | null {\n if (!searchText) return null;\n\n try {\n let pattern: string;\n\n if (options.useRegex) {\n pattern = searchText;\n } else {\n pattern = escapeRegexString(searchText);\n }\n\n if (options.matchWholeWord) {\n pattern = `\\\\b${pattern}\\\\b`;\n }\n\n const flags = options.matchCase ? 'g' : 'gi';\n return new RegExp(pattern, flags);\n } catch {\n return null;\n }\n}\n\n/**\n * Find all matches of search text in content\n */\nexport function findAllMatches(\n content: string,\n searchText: string,\n options: FindOptions\n): Array<{ start: number; end: number }> {\n if (!content || !searchText) {\n return [];\n }\n\n const matches: Array<{ start: number; end: number }> = [];\n\n let searchFor = searchText;\n if (!options.matchCase) {\n searchFor = searchText.toLowerCase();\n }\n\n const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n let pattern: string;\n if (options.matchWholeWord) {\n pattern = `\\\\b${escapeRegex(searchFor)}\\\\b`;\n } else {\n pattern = escapeRegex(searchFor);\n }\n\n const flags = options.matchCase ? 'g' : 'gi';\n const regex = new RegExp(pattern, flags);\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n matches.push({\n start: match.index,\n end: match.index + match[0].length,\n });\n if (match[0].length === 0) {\n regex.lastIndex++;\n }\n }\n\n return matches;\n}\n\n/**\n * Replace text in content\n */\nexport function replaceAllInContent(\n content: string,\n searchText: string,\n replaceText: string,\n options: FindOptions\n): string {\n const pattern = createSearchPattern(searchText, options);\n if (!pattern) return content;\n\n return content.replace(pattern, replaceText);\n}\n\n/**\n * Replace first match in content\n */\nexport function replaceFirstInContent(\n content: string,\n searchText: string,\n replaceText: string,\n options: FindOptions,\n startIndex: number = 0\n): { content: string; replaced: boolean; matchStart: number; matchEnd: number } {\n const matches = findAllMatches(content, searchText, options);\n\n const match = matches.find((m) => m.start >= startIndex) || matches[0];\n\n if (!match) {\n return { content, replaced: false, matchStart: -1, matchEnd: -1 };\n }\n\n const newContent = content.substring(0, match.start) + replaceText + content.substring(match.end);\n\n return {\n content: newContent,\n replaced: true,\n matchStart: match.start,\n matchEnd: match.start + replaceText.length,\n };\n}\n\n/**\n * Get match count for status display\n */\nexport function getMatchCountText(result: FindResult | null): string {\n if (!result) return '';\n if (result.totalCount === 0) return 'No results';\n if (result.totalCount === 1) return '1 match';\n return `${result.currentIndex + 1} of ${result.totalCount} matches`;\n}\n\n/**\n * Check if search text is empty or whitespace-only\n */\nexport function isEmptySearch(searchText: string): boolean {\n return !searchText || searchText.trim() === '';\n}\n\n/**\n * Get default highlight options\n */\nexport function getDefaultHighlightOptions(): HighlightOptions {\n return {\n currentMatchColor: '#FFFF00',\n otherMatchColor: '#FFFFAA',\n };\n}\n\n// ============================================================================\n// DOCUMENT SEARCH UTILITIES\n// ============================================================================\n\n/**\n * Get plain text from a run\n */\nfunction getRunText(run: any): string {\n if (!run || !run.content) return '';\n let text = '';\n for (const item of run.content) {\n if (item.type === 'text') {\n text += item.text || '';\n } else if (item.type === 'tab') {\n text += '\\t';\n } else if (item.type === 'break' && item.breakType === 'textWrapping') {\n text += '\\n';\n }\n }\n return text;\n}\n\n/**\n * Get plain text from a paragraph\n */\nfunction getParagraphPlainText(paragraph: any): string {\n if (!paragraph || !paragraph.content) return '';\n let text = '';\n for (const item of paragraph.content) {\n if (item.type === 'run') {\n text += getRunText(item);\n } else if (item.type === 'hyperlink') {\n for (const child of item.children || []) {\n if (child.type === 'run') {\n text += getRunText(child);\n }\n }\n }\n }\n return text;\n}\n\n/**\n * Find all matches in a document\n */\nexport function findInDocument(\n document: any,\n searchText: string,\n options: FindOptions\n): FindMatch[] {\n if (!document || !searchText) return [];\n\n const matches: FindMatch[] = [];\n const body = document.package?.document || document.package?.document;\n if (!body || !body.content) return matches;\n\n let paragraphIndex = 0;\n for (const block of body.content) {\n if (block.type === 'paragraph') {\n const paragraphMatches = findInParagraph(block, searchText, options, paragraphIndex);\n matches.push(...paragraphMatches);\n paragraphIndex++;\n } else if (block.type === 'table') {\n for (const row of block.rows || []) {\n for (const cell of row.cells || []) {\n for (const cellContent of cell.content || []) {\n if (cellContent.type === 'paragraph') {\n // Table paragraphs tracked separately - skip for now\n }\n }\n }\n }\n }\n }\n\n return matches;\n}\n\n/**\n * Find matches in a single paragraph\n */\nexport function findInParagraph(\n paragraph: any,\n searchText: string,\n options: FindOptions,\n paragraphIndex: number\n): FindMatch[] {\n const matches: FindMatch[] = [];\n const paragraphText = getParagraphPlainText(paragraph);\n\n if (!paragraphText) return matches;\n\n const textMatches = findAllMatches(paragraphText, searchText, options);\n\n for (const match of textMatches) {\n const contentInfo = findContentAtOffset(paragraph, match.start);\n\n matches.push({\n paragraphIndex,\n contentIndex: contentInfo.contentIndex,\n startOffset: contentInfo.offsetInContent,\n endOffset: contentInfo.offsetInContent + (match.end - match.start),\n text: paragraphText.substring(match.start, match.end),\n });\n }\n\n return matches;\n}\n\n/**\n * Find the content (run) at a specific character offset in a paragraph\n */\nfunction findContentAtOffset(\n paragraph: any,\n offset: number\n): { contentIndex: number; runIndex: number; offsetInContent: number } {\n if (!paragraph || !paragraph.content) {\n return { contentIndex: 0, runIndex: 0, offsetInContent: offset };\n }\n\n let currentOffset = 0;\n let contentIndex = 0;\n\n for (const item of paragraph.content) {\n let itemText = '';\n\n if (item.type === 'run') {\n itemText = getRunText(item);\n } else if (item.type === 'hyperlink') {\n for (const child of item.children || []) {\n if (child.type === 'run') {\n itemText += getRunText(child);\n }\n }\n }\n\n const itemLength = itemText.length;\n\n if (currentOffset + itemLength > offset) {\n return {\n contentIndex,\n runIndex: contentIndex,\n offsetInContent: offset - currentOffset,\n };\n }\n\n currentOffset += itemLength;\n contentIndex++;\n }\n\n return {\n contentIndex: Math.max(0, paragraph.content.length - 1),\n runIndex: Math.max(0, paragraph.content.length - 1),\n offsetInContent: 0,\n };\n}\n\n/**\n * Scroll to a match in the document\n */\nexport function scrollToMatch(containerElement: HTMLElement | null, match: FindMatch): void {\n if (!containerElement || !match) return;\n\n const paragraphElement = containerElement.querySelector(\n `[data-paragraph-index=\"${match.paragraphIndex}\"]`\n );\n\n if (paragraphElement) {\n paragraphElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n}\n","/**\n * useFindReplace Hook\n *\n * React hook for managing find/replace dialog state.\n * Extracted from FindReplaceDialog.tsx.\n */\n\nimport { useState, useCallback } from 'react';\nimport type { FindMatch, FindOptions } from './findReplaceUtils';\nimport { createDefaultFindOptions } from './findReplaceUtils';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Options for the useFindReplace hook\n */\nexport interface FindReplaceOptions {\n /** Whether to show replace functionality initially */\n initialReplaceMode?: boolean;\n /** Callback when matches change */\n onMatchesChange?: (matches: FindMatch[]) => void;\n /** Callback when current match changes */\n onCurrentMatchChange?: (match: FindMatch | null, index: number) => void;\n}\n\n/**\n * State for the find/replace hook\n */\nexport interface FindReplaceState {\n /** Whether the dialog is open */\n isOpen: boolean;\n /** Current search text */\n searchText: string;\n /** Current replace text */\n replaceText: string;\n /** Find options */\n options: FindOptions;\n /** All matches found */\n matches: FindMatch[];\n /** Current match index */\n currentIndex: number;\n /** Whether in replace mode */\n replaceMode: boolean;\n}\n\n/**\n * Return type for the useFindReplace hook\n */\nexport interface UseFindReplaceReturn {\n /** Current state */\n state: FindReplaceState;\n /** Open the find dialog */\n openFind: (selectedText?: string) => void;\n /** Open the replace dialog */\n openReplace: (selectedText?: string) => void;\n /** Close the dialog */\n close: () => void;\n /** Toggle dialog visibility */\n toggle: () => void;\n /** Update search text */\n setSearchText: (text: string) => void;\n /** Update replace text */\n setReplaceText: (text: string) => void;\n /** Update find options */\n setOptions: (options: Partial<FindOptions>) => void;\n /** Set search results */\n setMatches: (matches: FindMatch[], currentIndex?: number) => void;\n /** Go to next match */\n goToNextMatch: () => number;\n /** Go to previous match */\n goToPreviousMatch: () => number;\n /** Go to a specific match by index */\n goToMatch: (index: number) => void;\n /** Get current match */\n getCurrentMatch: () => FindMatch | null;\n /** Check if has matches */\n hasMatches: () => boolean;\n}\n\n// ============================================================================\n// HOOK\n// ============================================================================\n\n/**\n * Hook for managing find/replace dialog state\n */\nexport function useFindReplace(hookOptions?: FindReplaceOptions): UseFindReplaceReturn {\n const [state, setState] = useState<FindReplaceState>({\n isOpen: false,\n searchText: '',\n replaceText: '',\n options: createDefaultFindOptions(),\n matches: [],\n currentIndex: 0,\n replaceMode: hookOptions?.initialReplaceMode ?? false,\n });\n\n const openFind = useCallback((selectedText?: string) => {\n setState((prev) => ({\n ...prev,\n isOpen: true,\n replaceMode: false,\n searchText: selectedText || prev.searchText,\n matches: [],\n currentIndex: 0,\n }));\n }, []);\n\n const openReplace = useCallback((selectedText?: string) => {\n setState((prev) => ({\n ...prev,\n isOpen: true,\n replaceMode: true,\n searchText: selectedText || prev.searchText,\n matches: [],\n currentIndex: 0,\n }));\n }, []);\n\n const close = useCallback(() => {\n setState((prev) => ({\n ...prev,\n isOpen: false,\n }));\n }, []);\n\n const toggle = useCallback(() => {\n setState((prev) => ({\n ...prev,\n isOpen: !prev.isOpen,\n }));\n }, []);\n\n const setSearchText = useCallback((text: string) => {\n setState((prev) => ({\n ...prev,\n searchText: text,\n }));\n }, []);\n\n const setReplaceText = useCallback((text: string) => {\n setState((prev) => ({\n ...prev,\n replaceText: text,\n }));\n }, []);\n\n const setOptions = useCallback((options: Partial<FindOptions>) => {\n setState((prev) => ({\n ...prev,\n options: { ...prev.options, ...options },\n }));\n }, []);\n\n const setMatches = useCallback(\n (matches: FindMatch[], currentIndex: number = 0) => {\n const newIndex = Math.max(0, Math.min(currentIndex, matches.length - 1));\n setState((prev) => ({\n ...prev,\n matches,\n currentIndex: matches.length > 0 ? newIndex : 0,\n }));\n hookOptions?.onMatchesChange?.(matches);\n if (matches.length > 0) {\n hookOptions?.onCurrentMatchChange?.(matches[newIndex], newIndex);\n } else {\n hookOptions?.onCurrentMatchChange?.(null, -1);\n }\n },\n [hookOptions]\n );\n\n const goToNextMatch = useCallback(() => {\n let newIndex = 0;\n setState((prev) => {\n if (prev.matches.length === 0) return prev;\n newIndex = (prev.currentIndex + 1) % prev.matches.length;\n return { ...prev, currentIndex: newIndex };\n });\n return newIndex;\n }, []);\n\n const goToPreviousMatch = useCallback(() => {\n let newIndex = 0;\n setState((prev) => {\n if (prev.matches.length === 0) return prev;\n newIndex = prev.currentIndex === 0 ? prev.matches.length - 1 : prev.currentIndex - 1;\n return { ...prev, currentIndex: newIndex };\n });\n return newIndex;\n }, []);\n\n const goToMatch = useCallback((index: number) => {\n setState((prev) => {\n if (prev.matches.length === 0 || index < 0 || index >= prev.matches.length) {\n return prev;\n }\n return { ...prev, currentIndex: index };\n });\n }, []);\n\n const getCurrentMatch = useCallback((): FindMatch | null => {\n if (state.matches.length === 0) return null;\n return state.matches[state.currentIndex] || null;\n }, [state.matches, state.currentIndex]);\n\n const hasMatches = useCallback(() => state.matches.length > 0, [state.matches.length]);\n\n return {\n state,\n openFind,\n openReplace,\n close,\n toggle,\n setSearchText,\n setReplaceText,\n setOptions,\n setMatches,\n goToNextMatch,\n goToPreviousMatch,\n goToMatch,\n getCurrentMatch,\n hasMatches,\n };\n}\n","/**\n * Find and Replace Dialog Component\n *\n * Modal dialog for searching and replacing text in the document.\n * Supports find, find next/previous, replace, and replace all operations.\n *\n * Logic and utilities are in separate files:\n * - findReplaceUtils.ts — Pure search/replace functions and types\n * - useFindReplace.ts — React hook for dialog state management\n */\n\nimport React, { useState, useEffect, useCallback, useRef } from 'react';\nimport type { CSSProperties, KeyboardEvent, ChangeEvent } from 'react';\n\n// Re-export types and utilities so existing imports still work\nexport type { FindMatch, FindOptions, FindResult, HighlightOptions } from './findReplaceUtils';\nexport {\n createDefaultFindOptions,\n findAllMatches,\n escapeRegexString,\n createSearchPattern,\n replaceAllInContent,\n replaceFirstInContent,\n getMatchCountText,\n isEmptySearch,\n getDefaultHighlightOptions,\n findInDocument,\n findInParagraph,\n scrollToMatch,\n} from './findReplaceUtils';\n\nexport type { FindReplaceOptions, FindReplaceState, UseFindReplaceReturn } from './useFindReplace';\nexport { useFindReplace } from './useFindReplace';\n\nimport type { FindOptions, FindResult, FindMatch } from './findReplaceUtils';\n\n// ============================================================================\n// PROPS\n// ============================================================================\n\n/**\n * Props for the FindReplaceDialog component\n */\nexport interface FindReplaceDialogProps {\n /** Whether the dialog is open */\n isOpen: boolean;\n /** Callback when dialog is closed */\n onClose: () => void;\n /** Callback when searching for text */\n onFind: (searchText: string, options: FindOptions) => FindResult | null;\n /** Callback when navigating to next match */\n onFindNext: () => FindMatch | null;\n /** Callback when navigating to previous match */\n onFindPrevious: () => FindMatch | null;\n /** Callback when replacing current match */\n onReplace: (replaceText: string) => boolean;\n /** Callback when replacing all matches */\n onReplaceAll: (searchText: string, replaceText: string, options: FindOptions) => number;\n /** Callback to highlight matches in document */\n onHighlightMatches?: (matches: FindMatch[]) => void;\n /** Callback to clear highlights */\n onClearHighlights?: () => void;\n /** Initial search text (e.g., from selected text) */\n initialSearchText?: string;\n /** Whether to start in replace mode */\n replaceMode?: boolean;\n /** Current match result (from external state) */\n currentResult?: FindResult | null;\n /** Additional CSS class */\n className?: string;\n /** Additional inline styles */\n style?: CSSProperties;\n}\n\n// ============================================================================\n// STYLES\n// ============================================================================\n\nconst DIALOG_OVERLAY_STYLE: CSSProperties = {\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'transparent',\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'flex-end',\n zIndex: 10000,\n pointerEvents: 'none',\n};\n\nconst DIALOG_CONTENT_STYLE: CSSProperties = {\n backgroundColor: 'white',\n borderRadius: '4px',\n boxShadow: '0 4px 20px rgba(0, 0, 0, 0.2)',\n minWidth: '360px',\n maxWidth: '440px',\n width: '100%',\n margin: '60px 20px 20px 20px',\n pointerEvents: 'auto',\n};\n\nconst DIALOG_HEADER_STYLE: CSSProperties = {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n borderBottom: '1px solid var(--doc-border)',\n backgroundColor: 'var(--doc-bg-subtle)',\n borderTopLeftRadius: '4px',\n borderTopRightRadius: '4px',\n};\n\nconst DIALOG_TITLE_STYLE: CSSProperties = {\n margin: 0,\n fontSize: '14px',\n fontWeight: 600,\n color: 'var(--doc-text)',\n};\n\nconst CLOSE_BUTTON_STYLE: CSSProperties = {\n background: 'none',\n border: 'none',\n fontSize: '18px',\n cursor: 'pointer',\n color: 'var(--doc-text-muted)',\n padding: '2px 6px',\n lineHeight: 1,\n};\n\nconst DIALOG_BODY_STYLE: CSSProperties = {\n padding: '16px',\n};\n\nconst ROW_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '12px',\n};\n\nconst LABEL_STYLE: CSSProperties = {\n width: '60px',\n fontSize: '13px',\n color: 'var(--doc-text)',\n flexShrink: 0,\n};\n\nconst INPUT_STYLE: CSSProperties = {\n flex: 1,\n padding: '8px 10px',\n border: '1px solid var(--doc-border-input)',\n borderRadius: '3px',\n fontSize: '13px',\n boxSizing: 'border-box',\n outline: 'none',\n};\n\nconst INPUT_FOCUS_STYLE: CSSProperties = {\n ...INPUT_STYLE,\n borderColor: 'var(--doc-link)',\n boxShadow: '0 0 0 2px rgba(5, 99, 193, 0.1)',\n};\n\nconst BUTTON_CONTAINER_STYLE: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: '6px',\n marginLeft: '8px',\n};\n\nconst BUTTON_BASE_STYLE: CSSProperties = {\n padding: '6px 12px',\n borderRadius: '3px',\n fontSize: '12px',\n fontWeight: 500,\n cursor: 'pointer',\n border: '1px solid var(--doc-border-input)',\n backgroundColor: 'var(--doc-bg-input)',\n color: 'var(--doc-text)',\n minWidth: '80px',\n textAlign: 'center',\n};\n\nconst BUTTON_DISABLED_STYLE: CSSProperties = {\n ...BUTTON_BASE_STYLE,\n backgroundColor: 'var(--doc-bg-hover)',\n color: 'var(--doc-text-placeholder)',\n cursor: 'not-allowed',\n};\n\nconst NAV_BUTTON_STYLE: CSSProperties = {\n padding: '6px 10px',\n borderRadius: '3px',\n fontSize: '14px',\n cursor: 'pointer',\n border: '1px solid var(--doc-border-input)',\n backgroundColor: 'var(--doc-bg-input)',\n color: 'var(--doc-text)',\n};\n\nconst NAV_BUTTON_DISABLED_STYLE: CSSProperties = {\n ...NAV_BUTTON_STYLE,\n color: 'var(--doc-border-input)',\n cursor: 'not-allowed',\n};\n\nconst OPTIONS_CONTAINER_STYLE: CSSProperties = {\n display: 'flex',\n gap: '16px',\n marginTop: '4px',\n marginLeft: '68px',\n};\n\nconst CHECKBOX_LABEL_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n fontSize: '12px',\n color: 'var(--doc-text-muted)',\n cursor: 'pointer',\n};\n\nconst CHECKBOX_STYLE: CSSProperties = {\n width: '14px',\n height: '14px',\n cursor: 'pointer',\n};\n\nconst STATUS_STYLE: CSSProperties = {\n marginLeft: '68px',\n fontSize: '12px',\n color: 'var(--doc-text-muted)',\n marginBottom: '8px',\n};\n\nconst NO_RESULTS_STYLE: CSSProperties = {\n ...STATUS_STYLE,\n color: 'var(--doc-error)',\n};\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst ChevronUpIcon: React.FC<{ style?: CSSProperties }> = ({ style }) => (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={style}\n >\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n);\n\nconst ChevronDownIcon: React.FC<{ style?: CSSProperties }> = ({ style }) => (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={style}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n);\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\n/**\n * FindReplaceDialog component - Modal for finding and replacing text\n */\nexport function FindReplaceDialog({\n isOpen,\n onClose,\n onFind,\n onFindNext,\n onFindPrevious,\n onReplace,\n onReplaceAll,\n onHighlightMatches,\n onClearHighlights,\n initialSearchText = '',\n replaceMode = false,\n currentResult,\n className,\n style,\n}: FindReplaceDialogProps): React.ReactElement | null {\n // State\n const [searchText, setSearchText] = useState('');\n const [replaceText, setReplaceText] = useState('');\n const [showReplace, setShowReplace] = useState(replaceMode);\n const [matchCase, setMatchCase] = useState(false);\n const [matchWholeWord, setMatchWholeWord] = useState(false);\n const [result, setResult] = useState<FindResult | null>(null);\n const [searchFocused, setSearchFocused] = useState(false);\n const [replaceFocused, setReplaceFocused] = useState(false);\n\n // Refs\n const searchInputRef = useRef<HTMLInputElement>(null);\n const replaceInputRef = useRef<HTMLInputElement>(null);\n\n // Sync with external result if provided\n useEffect(() => {\n if (currentResult !== undefined) {\n setResult(currentResult);\n }\n }, [currentResult]);\n\n // Initialize when dialog opens\n useEffect(() => {\n if (isOpen) {\n setSearchText(initialSearchText);\n setReplaceText('');\n setShowReplace(replaceMode);\n setResult(null);\n\n setTimeout(() => {\n searchInputRef.current?.focus();\n searchInputRef.current?.select();\n }, 100);\n\n if (initialSearchText) {\n const searchResult = onFind(initialSearchText, { matchCase, matchWholeWord });\n setResult(searchResult);\n if (searchResult?.matches && onHighlightMatches) {\n onHighlightMatches(searchResult.matches);\n }\n }\n } else {\n if (onClearHighlights) {\n onClearHighlights();\n }\n }\n }, [isOpen, initialSearchText, replaceMode]);\n\n const performSearch = useCallback(() => {\n if (!searchText.trim()) {\n setResult(null);\n if (onClearHighlights) {\n onClearHighlights();\n }\n return;\n }\n\n const searchResult = onFind(searchText, { matchCase, matchWholeWord });\n setResult(searchResult);\n\n if (searchResult?.matches && onHighlightMatches) {\n onHighlightMatches(searchResult.matches);\n } else if (onClearHighlights) {\n onClearHighlights();\n }\n }, [searchText, matchCase, matchWholeWord, onFind, onHighlightMatches, onClearHighlights]);\n\n useEffect(() => {\n if (isOpen && searchText.trim()) {\n performSearch();\n }\n }, [matchCase, matchWholeWord]);\n\n const handleSearchChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setSearchText(e.target.value);\n }, []);\n\n const handleSearchKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n if (e.shiftKey) {\n handleFindPrevious();\n } else {\n if (!result) {\n performSearch();\n } else {\n handleFindNext();\n }\n }\n } else if (e.key === 'Escape') {\n onClose();\n }\n },\n [result, performSearch, onClose]\n );\n\n const handleReplaceKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleReplace();\n } else if (e.key === 'Escape') {\n onClose();\n }\n },\n [onClose]\n );\n\n const handleFindNext = useCallback(() => {\n if (!searchText.trim()) {\n performSearch();\n return;\n }\n\n if (!result) {\n performSearch();\n return;\n }\n\n const match = onFindNext();\n if (match && result) {\n const newIndex = (result.currentIndex + 1) % result.totalCount;\n setResult({\n ...result,\n currentIndex: newIndex,\n });\n }\n }, [searchText, result, performSearch, onFindNext]);\n\n const handleFindPrevious = useCallback(() => {\n if (!searchText.trim()) {\n performSearch();\n return;\n }\n\n if (!result) {\n performSearch();\n return;\n }\n\n const match = onFindPrevious();\n if (match && result) {\n const newIndex = result.currentIndex === 0 ? result.totalCount - 1 : result.currentIndex - 1;\n setResult({\n ...result,\n currentIndex: newIndex,\n });\n }\n }, [searchText, result, performSearch, onFindPrevious]);\n\n const handleReplace = useCallback(() => {\n if (!result || result.totalCount === 0) return;\n\n const success = onReplace(replaceText);\n if (success) {\n const newResult = onFind(searchText, { matchCase, matchWholeWord });\n setResult(newResult);\n if (newResult?.matches && onHighlightMatches) {\n onHighlightMatches(newResult.matches);\n }\n }\n }, [\n result,\n replaceText,\n searchText,\n matchCase,\n matchWholeWord,\n onReplace,\n onFind,\n onHighlightMatches,\n ]);\n\n const handleReplaceAll = useCallback(() => {\n if (!searchText.trim()) return;\n\n const count = onReplaceAll(searchText, replaceText, { matchCase, matchWholeWord });\n if (count > 0) {\n setResult({\n matches: [],\n totalCount: 0,\n currentIndex: -1,\n });\n if (onClearHighlights) {\n onClearHighlights();\n }\n }\n }, [searchText, replaceText, matchCase, matchWholeWord, onReplaceAll, onClearHighlights]);\n\n const toggleReplaceMode = useCallback(() => {\n setShowReplace((prev) => {\n const newValue = !prev;\n if (newValue) {\n setTimeout(() => replaceInputRef.current?.focus(), 100);\n }\n return newValue;\n });\n }, []);\n\n const handleOverlayClick = useCallback((e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n // Don't close on overlay click - this is a non-modal dialog\n }\n }, []);\n\n const handleDialogKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Escape') {\n onClose();\n }\n },\n [onClose]\n );\n\n if (!isOpen) {\n return null;\n }\n\n const hasMatches = result && result.totalCount > 0;\n const noMatches = result && result.totalCount === 0 && searchText.trim();\n\n return (\n <div\n className={`docx-find-replace-dialog-overlay ${className || ''}`}\n style={{ ...DIALOG_OVERLAY_STYLE, ...style }}\n onClick={handleOverlayClick}\n onKeyDown={handleDialogKeyDown}\n >\n <div\n className=\"docx-find-replace-dialog\"\n data-testid=\"find-replace-dialog\"\n style={DIALOG_CONTENT_STYLE}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-labelledby=\"find-replace-dialog-title\"\n >\n {/* Header */}\n <div className=\"docx-find-replace-dialog-header\" style={DIALOG_HEADER_STYLE}>\n <h2 id=\"find-replace-dialog-title\" style={DIALOG_TITLE_STYLE}>\n {showReplace ? 'Find and Replace' : 'Find'}\n </h2>\n <button\n type=\"button\"\n className=\"docx-find-replace-dialog-close\"\n style={CLOSE_BUTTON_STYLE}\n onClick={onClose}\n aria-label=\"Close dialog\"\n >\n &times;\n </button>\n </div>\n\n {/* Body */}\n <div className=\"docx-find-replace-dialog-body\" style={DIALOG_BODY_STYLE}>\n {/* Find row */}\n <div className=\"docx-find-replace-dialog-row\" style={ROW_STYLE}>\n <label htmlFor=\"find-text\" style={LABEL_STYLE}>\n Find:\n </label>\n <input\n ref={searchInputRef}\n id=\"find-text\"\n type=\"text\"\n className=\"docx-find-replace-dialog-input\"\n style={searchFocused ? INPUT_FOCUS_STYLE : INPUT_STYLE}\n value={searchText}\n onChange={handleSearchChange}\n onKeyDown={handleSearchKeyDown}\n onFocus={() => setSearchFocused(true)}\n onBlur={() => {\n setSearchFocused(false);\n if (searchText.trim() && !result) {\n performSearch();\n }\n }}\n placeholder=\"Enter text to find...\"\n aria-label=\"Find text\"\n />\n <div style={{ display: 'flex', gap: '4px' }}>\n <button\n type=\"button\"\n className=\"docx-find-replace-dialog-nav\"\n style={hasMatches ? NAV_BUTTON_STYLE : NAV_BUTTON_DISABLED_STYLE}\n onClick={handleFindPrevious}\n disabled={!hasMatches}\n aria-label=\"Find previous\"\n title=\"Find Previous (Shift+Enter)\"\n >\n <ChevronUpIcon />\n </button>\n <button\n type=\"button\"\n className=\"docx-find-replace-dialog-nav\"\n style={hasMatches ? NAV_BUTTON_STYLE : NAV_BUTTON_DISABLED_STYLE}\n onClick={handleFindNext}\n disabled={!hasMatches}\n aria-label=\"Find next\"\n title=\"Find Next (Enter)\"\n >\n <ChevronDownIcon />\n </button>\n </div>\n </div>\n\n {/* Status line */}\n {hasMatches && (\n <div className=\"docx-find-replace-dialog-status\" style={STATUS_STYLE}>\n {result.currentIndex + 1} of {result.totalCount} matches\n </div>\n )}\n {noMatches && (\n <div className=\"docx-find-replace-dialog-status\" style={NO_RESULTS_STYLE}>\n No results found\n </div>\n )}\n\n {/* Replace row (togglable) */}\n {showReplace && (\n <>\n <div className=\"docx-find-replace-dialog-row\" style={ROW_STYLE}>\n <label htmlFor=\"replace-text\" style={LABEL_STYLE}>\n Replace:\n </label>\n <input\n ref={replaceInputRef}\n id=\"replace-text\"\n type=\"text\"\n className=\"docx-find-replace-dialog-input\"\n style={replaceFocused ? INPUT_FOCUS_STYLE : INPUT_STYLE}\n value={replaceText}\n onChange={(e) => setReplaceText(e.target.value)}\n onKeyDown={handleReplaceKeyDown}\n onFocus={() => setReplaceFocused(true)}\n onBlur={() => setReplaceFocused(false)}\n placeholder=\"Enter replacement text...\"\n aria-label=\"Replace text\"\n />\n <div style={BUTTON_CONTAINER_STYLE}>\n <button\n type=\"button\"\n className=\"docx-find-replace-dialog-button\"\n style={hasMatches ? BUTTON_BASE_STYLE : BUTTON_DISABLED_STYLE}\n onClick={handleReplace}\n disabled={!hasMatches}\n title=\"Replace current match\"\n >\n Replace\n </button>\n <button\n type=\"button\"\n className=\"docx-find-replace-dialog-button\"\n style={hasMatches ? BUTTON_BASE_STYLE : BUTTON_DISABLED_STYLE}\n onClick={handleReplaceAll}\n disabled={!hasMatches}\n title=\"Replace all matches\"\n >\n Replace All\n </button>\n </div>\n </div>\n </>\n )}\n\n {/* Options */}\n <div className=\"docx-find-replace-dialog-options\" style={OPTIONS_CONTAINER_STYLE}>\n <label className=\"docx-find-replace-dialog-option\" style={CHECKBOX_LABEL_STYLE}>\n <input\n type=\"checkbox\"\n style={CHECKBOX_STYLE}\n checked={matchCase}\n onChange={(e) => setMatchCase(e.target.checked)}\n />\n Match case\n </label>\n <label className=\"docx-find-replace-dialog-option\" style={CHECKBOX_LABEL_STYLE}>\n <input\n type=\"checkbox\"\n style={CHECKBOX_STYLE}\n checked={matchWholeWord}\n onChange={(e) => setMatchWholeWord(e.target.checked)}\n />\n Whole words\n </label>\n {!showReplace && (\n <button\n type=\"button\"\n style={{\n ...CHECKBOX_LABEL_STYLE,\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n color: 'var(--doc-link)',\n padding: 0,\n }}\n onClick={toggleReplaceMode}\n >\n + Replace\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport default FindReplaceDialog;\n"]}
@@ -1,11 +0,0 @@
1
- import {q as q$1}from'./chunk-DP6Q75ZD.js';import {b as b$1,f as f$1}from'./chunk-CV5WFE7K.js';function H(e){return g(e).variables}function g(e){let t=[],n={body:[],headers:[],footers:[],footnotes:[],endnotes:[],textBoxes:[]};if(e.package?.document){let r=$(e.package.document);r.forEach(o=>{t.push({name:o,location:"body"});}),n.body=Array.from(new Set(r)).sort();}if(e.package?.document?.sections&&e.package.document.sections.forEach((r,o)=>{r.properties.headerReferences&&r.properties.headerReferences.forEach(i=>{});}),e.package?.footnotes){let r=D(e.package.footnotes);r.forEach(o=>{t.push({name:o,location:"footnote"});}),n.footnotes=Array.from(new Set(r)).sort();}if(e.package?.endnotes){let r=D(e.package.endnotes);r.forEach(o=>{t.push({name:o,location:"endnote"});}),n.endnotes=Array.from(new Set(r)).sort();}e.templateVariables&&e.templateVariables.forEach(r=>{t.some(o=>o.name===r)||t.push({name:r,location:"body"});});let a=new Set;return t.forEach(r=>a.add(r.name)),{variables:Array.from(a).sort(),totalOccurrences:t.length,byLocation:n,occurrences:t}}function $(e){let t=[];if(e.content&&t.push(...R(e.content)),e.sections)for(let n of e.sections)n.content&&t.push(...R(n.content));return t}function R(e){let t=[];for(let n of e)n.type==="paragraph"?t.push(...b(n)):n.type==="table"&&t.push(...P(n));return t}function b(e){let t=[];if(!e.content)return t;for(let n of e.content)n.type==="run"?t.push(...d(n)):n.type==="hyperlink"?t.push(...J(n)):n.type==="simpleField"?t.push(...L(n)):n.type==="complexField"&&t.push(...F(n));return t}function d(e){let t=[];if(!e.content)return t;for(let n of e.content)n.type==="text"&&n.text&&t.push(...E(n.text));return t}function J(e){let t=[];if(!e.children)return t;for(let n of e.children)n.type==="run"&&t.push(...d(n));return t}function L(e){let t=[];if(e.instruction&&t.push(...E(e.instruction)),e.content)for(let n of e.content)n.type==="run"&&t.push(...d(n));return t}function F(e){let t=[];if(e.fieldCode)for(let n of e.fieldCode)n.type==="run"&&t.push(...d(n));if(e.fieldResult)for(let n of e.fieldResult)n.type==="run"&&t.push(...d(n));return t}function P(e){let t=[];if(!e.rows)return t;for(let n of e.rows)if(n.cells)for(let a of n.cells)t.push(...B(a));return t}function B(e){let t=[];if(!e.content)return t;for(let n of e.content)n.type==="paragraph"?t.push(...b(n)):n.type==="table"&&t.push(...P(n));return t}function D(e){let t=[];for(let n of e)if(n.content)for(let a of n.content)t.push(...b(a));return t}var k=/\{([a-zA-Z_][a-zA-Z0-9_\-\.]*)\}/g,M=/\{(.+?)\}/g;function E(e){if(!e)return [];let t=[],n=new RegExp(k),a;for(;(a=n.exec(e))!==null;)t.push(a[1]);return t}function q(e){return k.test(e)}function U(e){return !(!e||typeof e!="string"||e.length===0||e.length>100||!/^[a-zA-Z_]/.test(e)||!/^[a-zA-Z_][a-zA-Z0-9_\-\.]*$/.test(e))}function X(e){if(!e)return "";let t=e.replace(/\s+/g,"_");return t=t.replace(/[^a-zA-Z0-9_\-\.]/g,""),t&&!/^[a-zA-Z_]/.test(t)&&(t="_"+t),t.substring(0,100)}function G(e){return `{${e}}`}function K(e){let t=e.match(/^\{(.+?)\}$/);return t?t[1]:null}function Q(e,t){return e&&e.replace(M,(n,a)=>{let r=a.trim();return r in t?t[r]:n})}function Y(e,t=""){return e&&e.replace(M,t)}function ee(e){return H(e).length>0}function Z(e){return typeof e=="object"&&e!==null&&("_def"in e||"parse"in e||"safeParse"in e)}function h(e,t){let n=t,{position:a,variableName:r}=n,o=JSON.parse(JSON.stringify(e)),s=o.package.document.content.filter(u=>u.type==="paragraph");if(a.paragraphIndex>=s.length)throw new Error(`Paragraph index ${a.paragraphIndex} out of bounds`);let c=s[a.paragraphIndex],l=`{${r}}`;return S(c,a.offset,l),o.templateVariables||(o.templateVariables=[]),o.templateVariables.includes(r)||o.templateVariables.push(r),o}function y(e,t){let n=t,{range:a,variableName:r}=n,o=JSON.parse(JSON.stringify(e)),s=o.package.document.content.filter(u=>u.type==="paragraph");if(a.start.paragraphIndex!==a.end.paragraphIndex)throw new Error("Template variable replacement cannot span multiple paragraphs");if(a.start.paragraphIndex>=s.length)throw new Error(`Paragraph index ${a.start.paragraphIndex} out of bounds`);let c=s[a.start.paragraphIndex];z(c,a.start.offset,a.end.offset);let l=`{${r}}`;return S(c,a.start.offset,l),o.templateVariables||(o.templateVariables=[]),o.templateVariables.includes(r)||o.templateVariables.push(r),o}function S(e,t,n){let a=0,r=false;for(let o=0;o<e.content.length;o++){let i=e.content[o];if(i.type==="run"){let s=x(i),c=a,l=a+s.length;if(!r&&t>=c&&t<=l){let u=t-c,v=s.slice(0,u),V=s.slice(u),m=[];for(let p=0;p<o;p++)m.push(e.content[p]);v&&m.push({type:"run",formatting:i.formatting,content:[{type:"text",text:v}]}),m.push({type:"run",formatting:i.formatting,content:[{type:"text",text:n}]}),V&&m.push({type:"run",formatting:i.formatting,content:[{type:"text",text:V}]});for(let p=o+1;p<e.content.length;p++)m.push(e.content[p]);e.content=m,r=true;break}a=l;}else if(i.type==="hyperlink")for(let s of i.children)s.type==="run"&&(a+=x(s).length);}r||e.content.push({type:"run",content:[{type:"text",text:n}]});}function z(e,t,n){let a=[],r=0;for(let o of e.content)if(o.type==="run"){let i=x(o),s=r,c=r+i.length;if(c<=t||s>=n)a.push(o);else {let l="";s<t&&(l+=i.slice(0,t-s)),c>n&&(l+=i.slice(n-s)),l.length>0&&a.push({type:"run",formatting:o.formatting,content:[{type:"text",text:l}]});}r=c;}else a.push(o);e.content=a;}function x(e){return e.content.filter(t=>t.type==="text").map(t=>t.text).join("")}var f={type:"string",description:"Document ID from a previous docx_load call"},j={type:"object",properties:{paragraphIndex:{type:"number",description:"Index of the paragraph (0-indexed)"},offset:{type:"number",description:"Character offset within the paragraph"}},required:["paragraphIndex","offset"]},_={name:"docx_get_variables",description:`List all template variables ({name} format) found in the document.
2
- Returns variable names without braces, along with their locations (body, headers, footers, etc.).
3
- Use this to discover what data fields a template document expects.`,inputSchema:{type:"object",properties:{documentId:f},required:["documentId"]},handler:async(e,t)=>{let{documentId:n}=e,a=t.session.documents.get(n);if(!a)return {isError:true,content:[{type:"text",text:`Document not found: ${n}`}]};try{let r=g(a.document);return {content:[{type:"text",text:JSON.stringify({variables:r.variables,count:r.variables.length,totalOccurrences:r.totalOccurrences,byLocation:r.byLocation},null,2)}]}}catch(r){return {isError:true,content:[{type:"text",text:`Failed to detect variables: ${r.message}`}]}}},annotations:{category:"template",readOnly:true,complexity:"low",examples:[{description:"Get all variables from a loaded document",input:{documentId:"doc_123"},output:'{"variables": ["customer_name", "invoice_date"], "count": 2}'}]}},A={name:"docx_insert_variable",description:`Insert a template variable placeholder ({name}) at a specific position in the document.
4
- The variable can later be substituted with actual values using docx_apply_template.
5
- Variable names should follow the pattern: letters, numbers, underscores, starting with a letter.`,inputSchema:{type:"object",properties:{documentId:f,position:j,variableName:{type:"string",description:'Variable name without braces (e.g., "customer_name"). Will be inserted as {customer_name}',pattern:"^[a-zA-Z_][a-zA-Z0-9_]*$"}},required:["documentId","position","variableName"]},handler:async(e,t)=>{let{documentId:n,position:a,variableName:r}=e,o=t.session.documents.get(n);if(!o)return {isError:true,content:[{type:"text",text:`Document not found: ${n}`}]};if(!/^[a-zA-Z_][a-zA-Z0-9_\-.]*$/.test(r))return {isError:true,content:[{type:"text",text:`Invalid variable name: ${r}. Must start with letter/underscore and contain only alphanumeric, underscore, hyphen, or dot.`}]};try{let{executeCommand:i}=await import('./executor-K5RXUTTR.js'),s=i(o.document,{type:"insertText",position:a,text:`{${r}}`});return o.document=s,o.lastModified=Date.now(),s.templateVariables||(s.templateVariables=[]),s.templateVariables.includes(r)||s.templateVariables.push(r),{content:[{type:"text",text:JSON.stringify({success:!0,variable:r,insertedAs:`{${r}}`,position:a})}]}}catch(i){return {isError:true,content:[{type:"text",text:`Failed to insert variable: ${i.message}`}]}}},annotations:{category:"template",readOnly:false,complexity:"low",examples:[{description:"Insert customer name variable at start of first paragraph",input:{documentId:"doc_123",position:{paragraphIndex:0,offset:0},variableName:"customer_name"}}]}},O={name:"docx_apply_template",description:`Substitute template variables with actual values in the document.
6
- Replaces all {variable} placeholders with the corresponding values provided.
7
- Preserves all formatting (fonts, styles, colors, tables).
8
- Use docx_get_variables first to discover what variables exist in the document.`,inputSchema:{type:"object",properties:{documentId:f,variables:{type:"object",description:'Map of variable names to values (e.g., {"customer_name": "John Doe", "date": "2024-01-15"})',additionalProperties:{type:"string"}},keepUnmatchedVariables:{type:"boolean",description:"If true, keep {variable} placeholders for variables not in the map. If false, replace with empty string. Default: true",default:true}},required:["documentId","variables"]},handler:async(e,t)=>{let{documentId:n,variables:a,keepUnmatchedVariables:r=true}=e,o=t.session.documents.get(n);if(!o)return {isError:true,content:[{type:"text",text:`Document not found: ${n}`}]};if(!o.buffer)return {isError:true,content:[{type:"text",text:"Cannot apply template: document was not loaded from a DOCX buffer"}]};try{let i=b$1(o.buffer,a,{nullGetter:r?"keep":"empty"}),s=await q$1(i.buffer);return o.document=s,o.buffer=i.buffer,o.lastModified=Date.now(),{content:[{type:"text",text:JSON.stringify({success:!0,replacedVariables:i.replacedVariables,unreplacedVariables:i.unreplacedVariables,warnings:i.warnings})}]}}catch(i){return {isError:true,content:[{type:"text",text:`Failed to apply template: ${i.message}`}]}}},annotations:{category:"template",readOnly:false,complexity:"medium",examples:[{description:"Fill in customer and date values",input:{documentId:"doc_123",variables:{customer_name:"Jane Smith",invoice_date:"2024-02-15",amount:"$1,234.56"}}}]}},N={name:"docx_validate_template",description:`Validate that a document is a valid docxtemplater template.
9
- Checks for syntax errors like unclosed braces, invalid tag names, etc.
10
- Returns validation result with any errors found and list of valid tags.`,inputSchema:{type:"object",properties:{documentId:f},required:["documentId"]},handler:async(e,t)=>{let{documentId:n}=e,a=t.session.documents.get(n);if(!a)return {isError:true,content:[{type:"text",text:`Document not found: ${n}`}]};if(!a.buffer)return {isError:true,content:[{type:"text",text:"Cannot validate template: document was not loaded from a DOCX buffer"}]};try{let r=f$1(a.buffer);return {content:[{type:"text",text:JSON.stringify({valid:r.valid,tags:r.tags,errors:r.errors.map(o=>({message:o.message,variable:o.variable,type:o.type}))},null,2)}]}}catch(r){return {isError:true,content:[{type:"text",text:`Failed to validate template: ${r.message}`}]}}},annotations:{category:"template",readOnly:true,complexity:"low"}},T=[_,A,O,N];var W={id:"docxtemplater",name:"Docxtemplater",version:"1.0.0",description:"Template variable support using standard docxtemplater syntax ({variable})",commandHandlers:{insertTemplateVariable:h,replaceWithTemplateVariable:y},mcpTools:T};export{H as a,g as b,$ as c,b as d,E as e,q as f,U as g,X as h,G as i,K as j,Q as k,Y as l,ee as m,Z as n,W as o};//# sourceMappingURL=chunk-OHG7ROFC.js.map
11
- //# sourceMappingURL=chunk-OHG7ROFC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../core/src/utils/variableDetector.ts","../../core/src/core-plugins/types.ts","../../core/src/core-plugins/docxtemplater/handlers.ts","../../core/src/core-plugins/docxtemplater/mcp-tools.ts","../../core/src/core-plugins/docxtemplater/index.ts"],"names":["detectVariables","doc","detectVariablesDetailed","occurrences","byLocation","bodyVars","detectVariablesInBody","v","section","_sectionIndex","_headerRef","footnoteVars","detectVariablesInNotes","endnoteVars","allVariables","o","body","variables","detectVariablesInBlockContent","content","block","detectVariablesInParagraph","detectVariablesInTable","paragraph","item","detectVariablesInRun","detectVariablesInHyperlink","detectVariablesInSimpleField","detectVariablesInComplexField","run","extractVariablesFromText","hyperlink","child","field","table","row","cell","detectVariablesInCell","notes","note","VARIABLE_PATTERN","VARIABLE_PATTERN_RELAXED","text","pattern","match","hasTemplateVariables","isValidVariableName","name","sanitizeVariableName","sanitized","formatVariable","parseVariable","variable","replaceVariables","values","varName","removeVariables","placeholder","documentHasVariables","isZodSchema","schema","handleInsertTemplateVariable","command","cmd","position","variableName","newDoc","paragraphs","variableText","insertTextAtOffset","handleReplaceWithTemplateVariable","range","deleteTextInRange","offset","currentOffset","inserted","i","runText","getRunText","runStart","runEnd","insertPos","beforeText","afterText","newContent","j","startOffset","endOffset","newText","c","documentIdSchema","positionSchema","getVariablesTool","input","context","documentId","loaded","result","error","insertVariableTool","executeCommand","applyTemplateTool","keepUnmatchedVariables","processTemplateDetailed","parseDocx","validateTemplateTool","validateTemplate","e","docxtemplaterMcpTools","docxtemplaterPlugin"],"mappings":"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","file":"chunk-OHG7ROFC.js","sourcesContent":["/**\n * Variable Detector Utility\n *\n * Scans a DOCX document for template variables in the format {variable_name}\n * (standard docxtemplater syntax).\n * Returns a unique, sorted list of variable names found in the document.\n */\n\nimport type {\n Document,\n DocumentBody,\n Paragraph,\n Table,\n TableCell,\n Run,\n Hyperlink,\n SimpleField,\n ComplexField,\n BlockContent,\n HeaderFooter,\n Footnote,\n Endnote,\n TextBox,\n} from '../types/document';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Result of variable detection\n */\nexport interface VariableDetectionResult {\n /** Unique variable names sorted alphabetically */\n variables: string[];\n /** Total count of variable occurrences */\n totalOccurrences: number;\n /** Variables by location */\n byLocation: {\n body: string[];\n headers: string[];\n footers: string[];\n footnotes: string[];\n endnotes: string[];\n textBoxes: string[];\n };\n /** Variable occurrences with positions */\n occurrences: VariableOccurrence[];\n}\n\n/**\n * A single variable occurrence with location info\n */\nexport interface VariableOccurrence {\n /** Variable name (without braces) */\n name: string;\n /** Location type */\n location: 'body' | 'header' | 'footer' | 'footnote' | 'endnote' | 'textBox';\n /** Paragraph index within location */\n paragraphIndex?: number;\n /** Section index (for headers/footers) */\n sectionIndex?: number;\n}\n\n// ============================================================================\n// MAIN FUNCTIONS\n// ============================================================================\n\n/**\n * Detect all template variables in a document\n *\n * @param doc - The parsed document\n * @returns Array of unique variable names sorted alphabetically\n */\nexport function detectVariables(doc: Document): string[] {\n const result = detectVariablesDetailed(doc);\n return result.variables;\n}\n\n/**\n * Detect variables with detailed information\n *\n * @param doc - The parsed document\n * @returns Detailed detection result\n */\nexport function detectVariablesDetailed(doc: Document): VariableDetectionResult {\n const occurrences: VariableOccurrence[] = [];\n const byLocation: VariableDetectionResult['byLocation'] = {\n body: [],\n headers: [],\n footers: [],\n footnotes: [],\n endnotes: [],\n textBoxes: [],\n };\n\n // Scan main body\n if (doc.package?.document) {\n const bodyVars = detectVariablesInBody(doc.package.document);\n bodyVars.forEach((v) => {\n occurrences.push({ name: v, location: 'body' });\n });\n byLocation.body = Array.from(new Set(bodyVars)).sort();\n }\n\n // Scan headers and footers\n if (doc.package?.document?.sections) {\n doc.package.document.sections.forEach((section, _sectionIndex) => {\n // Headers\n if (section.properties.headerReferences) {\n section.properties.headerReferences.forEach((_headerRef) => {\n // If we have actual header content, scan it\n // Note: Headers are stored separately in the package\n });\n }\n });\n }\n\n // Scan footers from package\n // (Actual footer content would be accessed from pkg.headers/pkg.footers if available)\n\n // Scan footnotes\n if (doc.package?.footnotes) {\n const footnoteVars = detectVariablesInNotes(doc.package.footnotes);\n footnoteVars.forEach((v) => {\n occurrences.push({ name: v, location: 'footnote' });\n });\n byLocation.footnotes = Array.from(new Set(footnoteVars)).sort();\n }\n\n // Scan endnotes\n if (doc.package?.endnotes) {\n const endnoteVars = detectVariablesInNotes(doc.package.endnotes);\n endnoteVars.forEach((v) => {\n occurrences.push({ name: v, location: 'endnote' });\n });\n byLocation.endnotes = Array.from(new Set(endnoteVars)).sort();\n }\n\n // Also check templateVariables from document if already detected\n if (doc.templateVariables) {\n doc.templateVariables.forEach((v) => {\n if (!occurrences.some((o) => o.name === v)) {\n occurrences.push({ name: v, location: 'body' });\n }\n });\n }\n\n // Collect all unique variables\n const allVariables = new Set<string>();\n occurrences.forEach((o) => allVariables.add(o.name));\n\n return {\n variables: Array.from(allVariables).sort(),\n totalOccurrences: occurrences.length,\n byLocation,\n occurrences,\n };\n}\n\n/**\n * Detect variables in document body\n */\nexport function detectVariablesInBody(body: DocumentBody): string[] {\n const variables: string[] = [];\n\n // Scan content array\n if (body.content) {\n variables.push(...detectVariablesInBlockContent(body.content));\n }\n\n // Scan sections\n if (body.sections) {\n for (const section of body.sections) {\n if (section.content) {\n variables.push(...detectVariablesInBlockContent(section.content));\n }\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in block content (paragraphs and tables)\n */\nexport function detectVariablesInBlockContent(content: BlockContent[]): string[] {\n const variables: string[] = [];\n\n for (const block of content) {\n if (block.type === 'paragraph') {\n variables.push(...detectVariablesInParagraph(block));\n } else if (block.type === 'table') {\n variables.push(...detectVariablesInTable(block));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a paragraph\n */\nexport function detectVariablesInParagraph(paragraph: Paragraph): string[] {\n const variables: string[] = [];\n\n if (!paragraph.content) return variables;\n\n for (const item of paragraph.content) {\n if (item.type === 'run') {\n variables.push(...detectVariablesInRun(item));\n } else if (item.type === 'hyperlink') {\n variables.push(...detectVariablesInHyperlink(item));\n } else if (item.type === 'simpleField') {\n variables.push(...detectVariablesInSimpleField(item));\n } else if (item.type === 'complexField') {\n variables.push(...detectVariablesInComplexField(item));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a text run\n */\nexport function detectVariablesInRun(run: Run): string[] {\n const variables: string[] = [];\n\n if (!run.content) return variables;\n\n for (const item of run.content) {\n if (item.type === 'text' && item.text) {\n variables.push(...extractVariablesFromText(item.text));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a hyperlink\n */\nexport function detectVariablesInHyperlink(hyperlink: Hyperlink): string[] {\n const variables: string[] = [];\n\n if (!hyperlink.children) return variables;\n\n for (const child of hyperlink.children) {\n if (child.type === 'run') {\n variables.push(...detectVariablesInRun(child));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a simple field\n */\nexport function detectVariablesInSimpleField(field: SimpleField): string[] {\n const variables: string[] = [];\n\n // Check field instruction\n if (field.instruction) {\n variables.push(...extractVariablesFromText(field.instruction));\n }\n\n // Check field content runs\n if (field.content) {\n for (const run of field.content) {\n if (run.type === 'run') {\n variables.push(...detectVariablesInRun(run));\n }\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a complex field\n */\nexport function detectVariablesInComplexField(field: ComplexField): string[] {\n const variables: string[] = [];\n\n // Check field code runs\n if (field.fieldCode) {\n for (const run of field.fieldCode) {\n if (run.type === 'run') {\n variables.push(...detectVariablesInRun(run));\n }\n }\n }\n\n // Check field result runs\n if (field.fieldResult) {\n for (const run of field.fieldResult) {\n if (run.type === 'run') {\n variables.push(...detectVariablesInRun(run));\n }\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a table\n */\nexport function detectVariablesInTable(table: Table): string[] {\n const variables: string[] = [];\n\n if (!table.rows) return variables;\n\n for (const row of table.rows) {\n if (!row.cells) continue;\n\n for (const cell of row.cells) {\n variables.push(...detectVariablesInCell(cell));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a table cell\n */\nexport function detectVariablesInCell(cell: TableCell): string[] {\n const variables: string[] = [];\n\n if (!cell.content) return variables;\n\n for (const block of cell.content) {\n if (block.type === 'paragraph') {\n variables.push(...detectVariablesInParagraph(block));\n } else if (block.type === 'table') {\n // Nested tables\n variables.push(...detectVariablesInTable(block));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in footnotes/endnotes\n */\nexport function detectVariablesInNotes(notes: (Footnote | Endnote)[]): string[] {\n const variables: string[] = [];\n\n for (const note of notes) {\n if (!note.content) continue;\n\n for (const paragraph of note.content) {\n variables.push(...detectVariablesInParagraph(paragraph));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in headers/footers\n */\nexport function detectVariablesInHeaderFooter(hf: HeaderFooter): string[] {\n const variables: string[] = [];\n\n if (!hf.content) return variables;\n\n for (const block of hf.content) {\n if (block.type === 'paragraph') {\n variables.push(...detectVariablesInParagraph(block));\n } else if (block.type === 'table') {\n variables.push(...detectVariablesInTable(block));\n }\n }\n\n return variables;\n}\n\n/**\n * Detect variables in a text box\n */\nexport function detectVariablesInTextBox(textBox: TextBox): string[] {\n const variables: string[] = [];\n\n if (!textBox.content) return variables;\n\n // TextBox.content is Paragraph[]\n for (const paragraph of textBox.content) {\n variables.push(...detectVariablesInParagraph(paragraph));\n }\n\n return variables;\n}\n\n// ============================================================================\n// TEXT EXTRACTION\n// ============================================================================\n\n/**\n * Regular expression for matching template variables\n * Matches {variable_name} (standard docxtemplater syntax) where variable_name can contain:\n * - Letters (a-z, A-Z)\n * - Numbers (0-9)\n * - Underscores (_)\n * - Hyphens (-)\n * - Dots (.)\n */\nconst VARIABLE_PATTERN = /\\{([a-zA-Z_][a-zA-Z0-9_\\-\\.]*)\\}/g;\n\n/**\n * Alternative pattern allowing any content between braces\n */\nconst VARIABLE_PATTERN_RELAXED = /\\{(.+?)\\}/g;\n\n/**\n * Extract variable names from text\n *\n * @param text - The text to search\n * @returns Array of variable names (without braces)\n */\nexport function extractVariablesFromText(text: string): string[] {\n if (!text) return [];\n\n const variables: string[] = [];\n const pattern = new RegExp(VARIABLE_PATTERN);\n let match: RegExpExecArray | null;\n\n while ((match = pattern.exec(text)) !== null) {\n variables.push(match[1]);\n }\n\n return variables;\n}\n\n/**\n * Extract all variables from text (relaxed matching)\n * Allows any content between { and }\n */\nexport function extractVariablesFromTextRelaxed(text: string): string[] {\n if (!text) return [];\n\n const variables: string[] = [];\n const pattern = new RegExp(VARIABLE_PATTERN_RELAXED);\n let match: RegExpExecArray | null;\n\n while ((match = pattern.exec(text)) !== null) {\n const varName = match[1].trim();\n if (varName) {\n variables.push(varName);\n }\n }\n\n return variables;\n}\n\n/**\n * Check if text contains template variables\n */\nexport function hasTemplateVariables(text: string): boolean {\n return VARIABLE_PATTERN.test(text);\n}\n\n/**\n * Count template variables in text\n */\nexport function countVariables(text: string): number {\n const matches = text.match(VARIABLE_PATTERN);\n return matches ? matches.length : 0;\n}\n\n/**\n * Get unique variable names from text\n */\nexport function getUniqueVariables(text: string): string[] {\n const variables = extractVariablesFromText(text);\n return Array.from(new Set(variables)).sort();\n}\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n/**\n * Check if a variable name is valid\n */\nexport function isValidVariableName(name: string): boolean {\n if (!name || typeof name !== 'string') return false;\n if (name.length === 0 || name.length > 100) return false;\n\n // Must start with letter or underscore\n if (!/^[a-zA-Z_]/.test(name)) return false;\n\n // Can contain letters, numbers, underscores, hyphens, dots\n if (!/^[a-zA-Z_][a-zA-Z0-9_\\-\\.]*$/.test(name)) return false;\n\n return true;\n}\n\n/**\n * Sanitize a variable name\n */\nexport function sanitizeVariableName(name: string): string {\n if (!name) return '';\n\n // Replace spaces with underscores\n let sanitized = name.replace(/\\s+/g, '_');\n\n // Remove invalid characters\n sanitized = sanitized.replace(/[^a-zA-Z0-9_\\-\\.]/g, '');\n\n // Ensure starts with letter or underscore\n if (sanitized && !/^[a-zA-Z_]/.test(sanitized)) {\n sanitized = '_' + sanitized;\n }\n\n // Limit length\n return sanitized.substring(0, 100);\n}\n\n/**\n * Format a variable name with braces (standard docxtemplater syntax)\n */\nexport function formatVariable(name: string): string {\n return `{${name}}`;\n}\n\n/**\n * Parse a variable string to get the name\n */\nexport function parseVariable(variable: string): string | null {\n const match = variable.match(/^\\{(.+?)\\}$/);\n return match ? match[1] : null;\n}\n\n// ============================================================================\n// REPLACEMENT\n// ============================================================================\n\n/**\n * Replace variables in text with values\n *\n * @param text - The text containing variables\n * @param values - Map of variable name to replacement value\n * @returns Text with variables replaced\n */\nexport function replaceVariables(text: string, values: Record<string, string>): string {\n if (!text) return text;\n\n return text.replace(VARIABLE_PATTERN_RELAXED, (match, varName) => {\n const name = varName.trim();\n if (name in values) {\n return values[name];\n }\n return match; // Keep original if not in values\n });\n}\n\n/**\n * Replace all variables in text with a placeholder\n *\n * @param text - The text containing variables\n * @param placeholder - Placeholder to use (default: empty string)\n * @returns Text with variables replaced\n */\nexport function removeVariables(text: string, placeholder = ''): string {\n if (!text) return text;\n return text.replace(VARIABLE_PATTERN_RELAXED, placeholder);\n}\n\n/**\n * Highlight variables in text for display\n *\n * @param text - The text containing variables\n * @param wrapper - Function to wrap variable text\n * @returns Array of text segments\n */\nexport function highlightVariables(\n text: string,\n wrapper: (varName: string) => string = (v) => `[${v}]`\n): string {\n if (!text) return text;\n\n return text.replace(VARIABLE_PATTERN_RELAXED, (_match, varName) => {\n return wrapper(varName.trim());\n });\n}\n\n// ============================================================================\n// DOCUMENT-LEVEL HELPERS\n// ============================================================================\n\n/**\n * Get total variable count in document (including duplicates)\n */\nexport function getVariableCount(doc: Document): number {\n const result = detectVariablesDetailed(doc);\n return result.totalOccurrences;\n}\n\n/**\n * Get unique variable count in document\n */\nexport function getUniqueVariableCount(doc: Document): number {\n return detectVariables(doc).length;\n}\n\n/**\n * Check if document has any template variables\n */\nexport function documentHasVariables(doc: Document): boolean {\n return detectVariables(doc).length > 0;\n}\n\n/**\n * Get variables grouped by first letter for large lists\n */\nexport function groupVariablesByLetter(variables: string[]): Record<string, string[]> {\n const groups: Record<string, string[]> = {};\n\n for (const variable of variables) {\n const letter = variable.charAt(0).toUpperCase();\n if (!groups[letter]) {\n groups[letter] = [];\n }\n groups[letter].push(variable);\n }\n\n return groups;\n}\n\nexport default detectVariables;\n","/**\n * Core Plugin System Types\n *\n * Defines the interfaces for headless plugins that work in Node.js\n * without React/DOM dependencies. These plugins extend DocumentAgent\n * with additional commands and expose MCP tools for AI integration.\n */\n\nimport type { Document } from '../types/document';\nimport type { AgentCommand, Position, Range } from '../types/agentApi';\n\n// ============================================================================\n// PLUGIN INTERFACE\n// ============================================================================\n\n/**\n * Core plugin interface - headless, works in Node.js\n *\n * Plugins can:\n * - Register command handlers that DocumentAgent dispatches to\n * - Declare MCP tools that the MCP server exposes to AI clients\n * - Have optional initialization logic\n * - Declare dependencies on other plugins\n */\nexport interface CorePlugin {\n /** Unique plugin identifier */\n id: string;\n\n /** Human-readable plugin name */\n name: string;\n\n /** Plugin version (semver) */\n version?: string;\n\n /** Plugin description */\n description?: string;\n\n /**\n * Command handlers this plugin provides.\n * DocumentAgent dispatches commands to these handlers.\n *\n * @example\n * ```ts\n * commandHandlers: {\n * 'insertTemplateVariable': (doc, cmd) => {\n * // Transform document\n * return modifiedDoc;\n * },\n * }\n * ```\n */\n commandHandlers?: Record<string, CommandHandler>;\n\n /**\n * MCP tools this plugin exposes.\n * MCP server collects these from all plugins.\n */\n mcpTools?: McpToolDefinition[];\n\n /**\n * Optional setup when plugin is registered.\n * Called once during plugin registration.\n */\n initialize?: () => void | Promise<void>;\n\n /**\n * Optional cleanup when plugin is unregistered.\n */\n destroy?: () => void | Promise<void>;\n\n /**\n * Dependencies on other plugins (by ID).\n * The registry ensures dependencies are loaded first.\n */\n dependencies?: string[];\n}\n\n// ============================================================================\n// COMMAND TYPES\n// ============================================================================\n\n/**\n * Command handler function type\n *\n * Receives a document and a command, returns a modified document.\n * Must be pure/immutable - always return a new document.\n */\nexport type CommandHandler = (doc: Document, command: PluginCommand) => Document;\n\n/**\n * Extended command type for plugins\n *\n * Plugins can define custom command types beyond the built-in AgentCommand types.\n */\nexport interface PluginCommand {\n /** Command type identifier */\n type: string;\n\n /** Unique command ID (for undo tracking) */\n id?: string;\n\n /** Position for positional commands */\n position?: Position;\n\n /** Range for range-based commands */\n range?: Range;\n\n /** Additional command-specific data */\n [key: string]: unknown;\n}\n\n/**\n * Result of command execution\n */\nexport interface CommandResult {\n /** The modified document */\n document: Document;\n\n /** Whether the command succeeded */\n success: boolean;\n\n /** Error message if failed */\n error?: string;\n\n /** Metadata about the operation */\n metadata?: Record<string, unknown>;\n}\n\n// ============================================================================\n// MCP TOOL TYPES\n// ============================================================================\n\n/**\n * MCP tool definition\n *\n * Describes a tool that can be called by AI clients through the MCP server.\n */\nexport interface McpToolDefinition {\n /** Tool name (used in MCP protocol) */\n name: string;\n\n /** Human-readable description for AI */\n description: string;\n\n /**\n * JSON Schema for tool input validation.\n * Can be a Zod schema or plain JSON Schema object.\n */\n inputSchema: JsonSchema | ZodSchemaLike;\n\n /**\n * Handler function for the tool.\n * Receives validated input and returns a result.\n */\n handler: McpToolHandler;\n\n /**\n * Optional annotations for the tool\n */\n annotations?: McpToolAnnotations;\n}\n\n/**\n * MCP tool handler function\n */\nexport type McpToolHandler = (\n input: unknown,\n context: McpToolContext\n) => Promise<McpToolResult> | McpToolResult;\n\n/**\n * Context passed to MCP tool handlers\n */\nexport interface McpToolContext {\n /** Current document (if loaded) */\n document?: Document;\n\n /** Document buffer (if loaded) */\n documentBuffer?: ArrayBuffer;\n\n /** Session state */\n session: McpSession;\n\n /** Logger for debugging */\n log: (message: string, data?: unknown) => void;\n}\n\n/**\n * MCP session state\n *\n * Maintains state across tool calls within a session.\n */\nexport interface McpSession {\n /** Session ID */\n id: string;\n\n /** Loaded documents by ID */\n documents: Map<string, LoadedDocument>;\n\n /** Custom session data */\n data: Map<string, unknown>;\n}\n\n/**\n * A loaded document in the session\n */\nexport interface LoadedDocument {\n /** Document ID */\n id: string;\n\n /** Parsed document */\n document: Document;\n\n /** Original buffer (for repacking) */\n buffer?: ArrayBuffer;\n\n /** Source filename or path */\n source?: string;\n\n /** Last modified timestamp */\n lastModified: number;\n}\n\n/**\n * MCP tool result\n */\nexport interface McpToolResult {\n /** Result content */\n content: McpToolContent[];\n\n /** Whether this is an error result */\n isError?: boolean;\n}\n\n/**\n * MCP tool content types\n */\nexport type McpToolContent =\n | { type: 'text'; text: string }\n | { type: 'image'; data: string; mimeType: string }\n | { type: 'resource'; uri: string; mimeType?: string; text?: string };\n\n/**\n * MCP tool annotations\n */\nexport interface McpToolAnnotations {\n /** Tool category for organization */\n category?: string;\n\n /** Whether this tool modifies the document */\n readOnly?: boolean;\n\n /** Estimated cost/complexity */\n complexity?: 'low' | 'medium' | 'high';\n\n /** Example usage */\n examples?: McpToolExample[];\n}\n\n/**\n * MCP tool example\n */\nexport interface McpToolExample {\n /** Example description */\n description: string;\n\n /** Example input */\n input: unknown;\n\n /** Expected output description */\n output?: string;\n}\n\n// ============================================================================\n// JSON SCHEMA TYPES\n// ============================================================================\n\n/**\n * JSON Schema definition (subset)\n */\nexport interface JsonSchema {\n type?: string | string[];\n properties?: Record<string, JsonSchema>;\n items?: JsonSchema;\n required?: string[];\n description?: string;\n enum?: unknown[];\n default?: unknown;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n format?: string;\n additionalProperties?: boolean | JsonSchema;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n $ref?: string;\n}\n\n/**\n * Zod-like schema interface for compatibility\n */\nexport interface ZodSchemaLike {\n _def?: unknown;\n parse?: (data: unknown) => unknown;\n safeParse?: (data: unknown) => { success: boolean; data?: unknown; error?: unknown };\n}\n\n/**\n * Check if a schema is Zod-like\n */\nexport function isZodSchema(schema: unknown): schema is ZodSchemaLike {\n return (\n typeof schema === 'object' &&\n schema !== null &&\n ('_def' in schema || 'parse' in schema || 'safeParse' in schema)\n );\n}\n\n// ============================================================================\n// PLUGIN EVENTS\n// ============================================================================\n\n/**\n * Plugin lifecycle events\n */\nexport type PluginEvent =\n | { type: 'registered'; plugin: CorePlugin }\n | { type: 'unregistered'; pluginId: string }\n | { type: 'error'; pluginId: string; error: Error };\n\n/**\n * Plugin event listener\n */\nexport type PluginEventListener = (event: PluginEvent) => void;\n\n// ============================================================================\n// UTILITY TYPES\n// ============================================================================\n\n/**\n * Extract command type from a union\n */\nexport type ExtractCommand<T extends AgentCommand, Type extends string> = T extends { type: Type }\n ? T\n : never;\n\n/**\n * Create a typed command handler\n */\nexport type TypedCommandHandler<T extends PluginCommand> = (doc: Document, command: T) => Document;\n\n/**\n * Plugin configuration options\n */\nexport interface PluginOptions {\n /** Enable debug logging */\n debug?: boolean;\n\n /** Custom configuration */\n config?: Record<string, unknown>;\n}\n\n/**\n * Result of plugin registration\n */\nexport interface PluginRegistrationResult {\n /** Whether registration succeeded */\n success: boolean;\n\n /** Registered plugin (if successful) */\n plugin?: CorePlugin;\n\n /** Error message (if failed) */\n error?: string;\n\n /** Warning messages */\n warnings?: string[];\n}\n\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\nexport type {\n CorePlugin as Plugin,\n CommandHandler as PluginCommandHandler,\n McpToolDefinition as ToolDefinition,\n McpToolHandler as ToolHandler,\n McpToolResult as ToolResult,\n};\n","/**\n * Docxtemplater Plugin Command Handlers\n *\n * Handles template-related commands for DocumentAgent.\n */\n\nimport type { Document, Paragraph, Run, TextContent } from '../../types/document';\nimport type { PluginCommand } from '../types';\n\n// ============================================================================\n// COMMAND TYPES\n// ============================================================================\n\n/**\n * Insert a template variable at a position\n */\nexport interface InsertTemplateVariableCommand extends PluginCommand {\n type: 'insertTemplateVariable';\n position: {\n paragraphIndex: number;\n offset: number;\n };\n variableName: string;\n}\n\n/**\n * Replace text with a template variable\n */\nexport interface ReplaceWithTemplateVariableCommand extends PluginCommand {\n type: 'replaceWithTemplateVariable';\n range: {\n start: { paragraphIndex: number; offset: number };\n end: { paragraphIndex: number; offset: number };\n };\n variableName: string;\n}\n\n// ============================================================================\n// HANDLERS\n// ============================================================================\n\n/**\n * Handle insertTemplateVariable command\n *\n * Inserts {variableName} at the specified position.\n */\nexport function handleInsertTemplateVariable(doc: Document, command: PluginCommand): Document {\n const cmd = command as InsertTemplateVariableCommand;\n const { position, variableName } = cmd;\n\n // Clone document for immutability\n const newDoc: Document = JSON.parse(JSON.stringify(doc));\n const body = newDoc.package.document;\n\n // Find the paragraph\n const paragraphs = body.content.filter((block): block is Paragraph => block.type === 'paragraph');\n\n if (position.paragraphIndex >= paragraphs.length) {\n throw new Error(`Paragraph index ${position.paragraphIndex} out of bounds`);\n }\n\n const paragraph = paragraphs[position.paragraphIndex];\n\n // Create the variable text\n const variableText = `{${variableName}}`;\n\n // Insert the variable at the offset\n insertTextAtOffset(paragraph, position.offset, variableText);\n\n // Track the variable in document metadata\n if (!newDoc.templateVariables) {\n newDoc.templateVariables = [];\n }\n if (!newDoc.templateVariables.includes(variableName)) {\n newDoc.templateVariables.push(variableName);\n }\n\n return newDoc;\n}\n\n/**\n * Handle replaceWithTemplateVariable command\n *\n * Replaces the text in the range with {variableName}.\n */\nexport function handleReplaceWithTemplateVariable(doc: Document, command: PluginCommand): Document {\n const cmd = command as ReplaceWithTemplateVariableCommand;\n const { range, variableName } = cmd;\n\n // Clone document for immutability\n const newDoc: Document = JSON.parse(JSON.stringify(doc));\n const body = newDoc.package.document;\n\n // Find the paragraphs\n const paragraphs = body.content.filter((block): block is Paragraph => block.type === 'paragraph');\n\n if (range.start.paragraphIndex !== range.end.paragraphIndex) {\n throw new Error('Template variable replacement cannot span multiple paragraphs');\n }\n\n if (range.start.paragraphIndex >= paragraphs.length) {\n throw new Error(`Paragraph index ${range.start.paragraphIndex} out of bounds`);\n }\n\n const paragraph = paragraphs[range.start.paragraphIndex];\n\n // Delete the range first\n deleteTextInRange(paragraph, range.start.offset, range.end.offset);\n\n // Insert the variable at the start position\n const variableText = `{${variableName}}`;\n insertTextAtOffset(paragraph, range.start.offset, variableText);\n\n // Track the variable\n if (!newDoc.templateVariables) {\n newDoc.templateVariables = [];\n }\n if (!newDoc.templateVariables.includes(variableName)) {\n newDoc.templateVariables.push(variableName);\n }\n\n return newDoc;\n}\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Insert text at a specific offset in a paragraph\n */\nfunction insertTextAtOffset(paragraph: Paragraph, offset: number, text: string): void {\n let currentOffset = 0;\n let inserted = false;\n\n for (let i = 0; i < paragraph.content.length; i++) {\n const item = paragraph.content[i];\n\n if (item.type === 'run') {\n const runText = getRunText(item);\n const runStart = currentOffset;\n const runEnd = currentOffset + runText.length;\n\n if (!inserted && offset >= runStart && offset <= runEnd) {\n const insertPos = offset - runStart;\n\n // Split the run at the insertion point\n const beforeText = runText.slice(0, insertPos);\n const afterText = runText.slice(insertPos);\n\n const newContent: Paragraph['content'] = [];\n\n // Add items before this run\n for (let j = 0; j < i; j++) {\n newContent.push(paragraph.content[j]);\n }\n\n // Add text before insertion point (if any)\n if (beforeText) {\n newContent.push({\n type: 'run',\n formatting: item.formatting,\n content: [{ type: 'text', text: beforeText }],\n });\n }\n\n // Add the new text\n newContent.push({\n type: 'run',\n formatting: item.formatting,\n content: [{ type: 'text', text }],\n });\n\n // Add text after insertion point (if any)\n if (afterText) {\n newContent.push({\n type: 'run',\n formatting: item.formatting,\n content: [{ type: 'text', text: afterText }],\n });\n }\n\n // Add remaining items\n for (let j = i + 1; j < paragraph.content.length; j++) {\n newContent.push(paragraph.content[j]);\n }\n\n paragraph.content = newContent;\n inserted = true;\n break;\n }\n\n currentOffset = runEnd;\n } else if (item.type === 'hyperlink') {\n // Handle hyperlink text\n for (const child of item.children) {\n if (child.type === 'run') {\n currentOffset += getRunText(child).length;\n }\n }\n }\n }\n\n // If not inserted (empty paragraph or offset at end), append\n if (!inserted) {\n paragraph.content.push({\n type: 'run',\n content: [{ type: 'text', text }],\n });\n }\n}\n\n/**\n * Delete text in a range within a paragraph\n */\nfunction deleteTextInRange(paragraph: Paragraph, startOffset: number, endOffset: number): void {\n const newContent: Paragraph['content'] = [];\n let currentOffset = 0;\n\n for (const item of paragraph.content) {\n if (item.type === 'run') {\n const runText = getRunText(item);\n const runStart = currentOffset;\n const runEnd = currentOffset + runText.length;\n\n // Check overlap with deletion range\n if (runEnd <= startOffset || runStart >= endOffset) {\n // No overlap, keep entire run\n newContent.push(item);\n } else {\n // Partial overlap\n let newText = '';\n\n if (runStart < startOffset) {\n // Keep text before start\n newText += runText.slice(0, startOffset - runStart);\n }\n\n if (runEnd > endOffset) {\n // Keep text after end\n newText += runText.slice(endOffset - runStart);\n }\n\n if (newText.length > 0) {\n newContent.push({\n type: 'run',\n formatting: item.formatting,\n content: [{ type: 'text', text: newText }],\n });\n }\n }\n\n currentOffset = runEnd;\n } else {\n newContent.push(item);\n }\n }\n\n paragraph.content = newContent;\n}\n\n/**\n * Get plain text from a run\n */\nfunction getRunText(run: Run): string {\n return run.content\n .filter((c): c is TextContent => c.type === 'text')\n .map((c) => c.text)\n .join('');\n}\n","/**\n * Docxtemplater Plugin MCP Tools\n *\n * MCP tool definitions for template operations that can be called by AI clients.\n */\n\nimport type { McpToolDefinition, McpToolContext, McpToolResult, JsonSchema } from '../types';\n\nimport { detectVariablesDetailed } from '../../utils/variableDetector';\nimport { processTemplateDetailed, validateTemplate } from '../../utils/processTemplate';\nimport { parseDocx } from '../../docx/parser';\n\n// ============================================================================\n// SCHEMAS\n// ============================================================================\n\nconst documentIdSchema: JsonSchema = {\n type: 'string',\n description: 'Document ID from a previous docx_load call',\n};\n\nconst positionSchema: JsonSchema = {\n type: 'object',\n properties: {\n paragraphIndex: {\n type: 'number',\n description: 'Index of the paragraph (0-indexed)',\n },\n offset: {\n type: 'number',\n description: 'Character offset within the paragraph',\n },\n },\n required: ['paragraphIndex', 'offset'],\n};\n\n// ============================================================================\n// TOOL DEFINITIONS\n// ============================================================================\n\n/**\n * Get template variables from a document\n */\nexport const getVariablesTool: McpToolDefinition = {\n name: 'docx_get_variables',\n description: `List all template variables ({name} format) found in the document.\nReturns variable names without braces, along with their locations (body, headers, footers, etc.).\nUse this to discover what data fields a template document expects.`,\n\n inputSchema: {\n type: 'object',\n properties: {\n documentId: documentIdSchema,\n },\n required: ['documentId'],\n },\n\n handler: async (input: unknown, context: McpToolContext): Promise<McpToolResult> => {\n const { documentId } = input as { documentId: string };\n\n const loaded = context.session.documents.get(documentId);\n if (!loaded) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Document not found: ${documentId}` }],\n };\n }\n\n try {\n const result = detectVariablesDetailed(loaded.document);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n variables: result.variables,\n count: result.variables.length,\n totalOccurrences: result.totalOccurrences,\n byLocation: result.byLocation,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (error) {\n return {\n isError: true,\n content: [\n { type: 'text', text: `Failed to detect variables: ${(error as Error).message}` },\n ],\n };\n }\n },\n\n annotations: {\n category: 'template',\n readOnly: true,\n complexity: 'low',\n examples: [\n {\n description: 'Get all variables from a loaded document',\n input: { documentId: 'doc_123' },\n output: '{\"variables\": [\"customer_name\", \"invoice_date\"], \"count\": 2}',\n },\n ],\n },\n};\n\n/**\n * Insert a template variable at a position\n */\nexport const insertVariableTool: McpToolDefinition = {\n name: 'docx_insert_variable',\n description: `Insert a template variable placeholder ({name}) at a specific position in the document.\nThe variable can later be substituted with actual values using docx_apply_template.\nVariable names should follow the pattern: letters, numbers, underscores, starting with a letter.`,\n\n inputSchema: {\n type: 'object',\n properties: {\n documentId: documentIdSchema,\n position: positionSchema,\n variableName: {\n type: 'string',\n description:\n 'Variable name without braces (e.g., \"customer_name\"). Will be inserted as {customer_name}',\n pattern: '^[a-zA-Z_][a-zA-Z0-9_]*$',\n },\n },\n required: ['documentId', 'position', 'variableName'],\n },\n\n handler: async (input: unknown, context: McpToolContext): Promise<McpToolResult> => {\n const { documentId, position, variableName } = input as {\n documentId: string;\n position: { paragraphIndex: number; offset: number };\n variableName: string;\n };\n\n const loaded = context.session.documents.get(documentId);\n if (!loaded) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Document not found: ${documentId}` }],\n };\n }\n\n // Validate variable name\n if (!/^[a-zA-Z_][a-zA-Z0-9_\\-.]*$/.test(variableName)) {\n return {\n isError: true,\n content: [\n {\n type: 'text',\n text: `Invalid variable name: ${variableName}. Must start with letter/underscore and contain only alphanumeric, underscore, hyphen, or dot.`,\n },\n ],\n };\n }\n\n try {\n // Import the executor to run the command\n const { executeCommand } = await import('../../agent/executor');\n\n // Execute the insert command\n const newDoc = executeCommand(loaded.document, {\n type: 'insertText',\n position,\n text: `{${variableName}}`,\n });\n\n // Update the document in the session\n loaded.document = newDoc;\n loaded.lastModified = Date.now();\n\n // Track the variable\n if (!newDoc.templateVariables) {\n newDoc.templateVariables = [];\n }\n if (!newDoc.templateVariables.includes(variableName)) {\n newDoc.templateVariables.push(variableName);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n success: true,\n variable: variableName,\n insertedAs: `{${variableName}}`,\n position,\n }),\n },\n ],\n };\n } catch (error) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Failed to insert variable: ${(error as Error).message}` }],\n };\n }\n },\n\n annotations: {\n category: 'template',\n readOnly: false,\n complexity: 'low',\n examples: [\n {\n description: 'Insert customer name variable at start of first paragraph',\n input: {\n documentId: 'doc_123',\n position: { paragraphIndex: 0, offset: 0 },\n variableName: 'customer_name',\n },\n },\n ],\n },\n};\n\n/**\n * Apply template substitution\n */\nexport const applyTemplateTool: McpToolDefinition = {\n name: 'docx_apply_template',\n description: `Substitute template variables with actual values in the document.\nReplaces all {variable} placeholders with the corresponding values provided.\nPreserves all formatting (fonts, styles, colors, tables).\nUse docx_get_variables first to discover what variables exist in the document.`,\n\n inputSchema: {\n type: 'object',\n properties: {\n documentId: documentIdSchema,\n variables: {\n type: 'object',\n description:\n 'Map of variable names to values (e.g., {\"customer_name\": \"John Doe\", \"date\": \"2024-01-15\"})',\n additionalProperties: {\n type: 'string',\n },\n },\n keepUnmatchedVariables: {\n type: 'boolean',\n description:\n 'If true, keep {variable} placeholders for variables not in the map. If false, replace with empty string. Default: true',\n default: true,\n },\n },\n required: ['documentId', 'variables'],\n },\n\n handler: async (input: unknown, context: McpToolContext): Promise<McpToolResult> => {\n const {\n documentId,\n variables,\n keepUnmatchedVariables = true,\n } = input as {\n documentId: string;\n variables: Record<string, string>;\n keepUnmatchedVariables?: boolean;\n };\n\n const loaded = context.session.documents.get(documentId);\n if (!loaded) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Document not found: ${documentId}` }],\n };\n }\n\n if (!loaded.buffer) {\n return {\n isError: true,\n content: [\n {\n type: 'text',\n text: 'Cannot apply template: document was not loaded from a DOCX buffer',\n },\n ],\n };\n }\n\n try {\n // Process the template\n const result = processTemplateDetailed(loaded.buffer, variables, {\n nullGetter: keepUnmatchedVariables ? 'keep' : 'empty',\n });\n\n // Re-parse the processed document\n const newDoc = await parseDocx(result.buffer);\n\n // Update session\n loaded.document = newDoc;\n loaded.buffer = result.buffer;\n loaded.lastModified = Date.now();\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n success: true,\n replacedVariables: result.replacedVariables,\n unreplacedVariables: result.unreplacedVariables,\n warnings: result.warnings,\n }),\n },\n ],\n };\n } catch (error) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Failed to apply template: ${(error as Error).message}` }],\n };\n }\n },\n\n annotations: {\n category: 'template',\n readOnly: false,\n complexity: 'medium',\n examples: [\n {\n description: 'Fill in customer and date values',\n input: {\n documentId: 'doc_123',\n variables: {\n customer_name: 'Jane Smith',\n invoice_date: '2024-02-15',\n amount: '$1,234.56',\n },\n },\n },\n ],\n },\n};\n\n/**\n * Validate a template document\n */\nexport const validateTemplateTool: McpToolDefinition = {\n name: 'docx_validate_template',\n description: `Validate that a document is a valid docxtemplater template.\nChecks for syntax errors like unclosed braces, invalid tag names, etc.\nReturns validation result with any errors found and list of valid tags.`,\n\n inputSchema: {\n type: 'object',\n properties: {\n documentId: documentIdSchema,\n },\n required: ['documentId'],\n },\n\n handler: async (input: unknown, context: McpToolContext): Promise<McpToolResult> => {\n const { documentId } = input as { documentId: string };\n\n const loaded = context.session.documents.get(documentId);\n if (!loaded) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Document not found: ${documentId}` }],\n };\n }\n\n if (!loaded.buffer) {\n return {\n isError: true,\n content: [\n {\n type: 'text',\n text: 'Cannot validate template: document was not loaded from a DOCX buffer',\n },\n ],\n };\n }\n\n try {\n const result = validateTemplate(loaded.buffer);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n valid: result.valid,\n tags: result.tags,\n errors: result.errors.map((e) => ({\n message: e.message,\n variable: e.variable,\n type: e.type,\n })),\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (error) {\n return {\n isError: true,\n content: [\n { type: 'text', text: `Failed to validate template: ${(error as Error).message}` },\n ],\n };\n }\n },\n\n annotations: {\n category: 'template',\n readOnly: true,\n complexity: 'low',\n },\n};\n\n// ============================================================================\n// EXPORT ALL TOOLS\n// ============================================================================\n\nexport const docxtemplaterMcpTools: McpToolDefinition[] = [\n getVariablesTool,\n insertVariableTool,\n applyTemplateTool,\n validateTemplateTool,\n];\n","/**\n * Docxtemplater Plugin\n *\n * Core plugin for template variable functionality using docxtemplater.\n *\n * **Command handlers** — `insertTemplateVariable` and `replaceWithTemplateVariable`\n * allow DocumentAgent to programmatically insert `{variable}` placeholders.\n *\n * @example\n * ```ts\n * import { pluginRegistry } from '@eigenpal/docx-editor/core-plugins';\n * import { docxtemplaterPlugin } from '@eigenpal/docx-editor/core-plugins/docxtemplater';\n *\n * pluginRegistry.register(docxtemplaterPlugin);\n * ```\n */\n\nimport type { CorePlugin } from '../types';\nimport { handleInsertTemplateVariable, handleReplaceWithTemplateVariable } from './handlers';\nimport { docxtemplaterMcpTools } from './mcp-tools';\n\n// ============================================================================\n// PLUGIN DEFINITION\n// ============================================================================\n\n/**\n * Docxtemplater plugin for template variable functionality.\n *\n * Dependency validation is handled lazily by `processTemplate` at call time,\n * so no eager `initialize()` is needed.\n */\nexport const docxtemplaterPlugin: CorePlugin = {\n id: 'docxtemplater',\n name: 'Docxtemplater',\n version: '1.0.0',\n description: 'Template variable support using standard docxtemplater syntax ({variable})',\n\n /**\n * Command handlers for template operations.\n * DocumentAgent dispatches `insertTemplateVariable` and\n * `replaceWithTemplateVariable` commands to these handlers.\n */\n commandHandlers: {\n insertTemplateVariable: handleInsertTemplateVariable,\n replaceWithTemplateVariable: handleReplaceWithTemplateVariable,\n },\n\n /** MCP tools for AI integration (optional, used by the MCP server if running) */\n mcpTools: docxtemplaterMcpTools,\n};\n\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\n// Export handlers for direct use\nexport {\n handleInsertTemplateVariable,\n handleReplaceWithTemplateVariable,\n type InsertTemplateVariableCommand,\n type ReplaceWithTemplateVariableCommand,\n} from './handlers';\n\n// Export MCP tools for customization\nexport {\n docxtemplaterMcpTools,\n getVariablesTool,\n insertVariableTool,\n applyTemplateTool,\n validateTemplateTool,\n} from './mcp-tools';\n"]}