@wonderwhy-er/desktop-commander 0.2.37 → 0.2.39

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 (383) hide show
  1. package/README.md +290 -100
  2. package/dist/command-manager.js +6 -3
  3. package/dist/config-field-definitions.d.ts +41 -0
  4. package/dist/config-field-definitions.js +37 -0
  5. package/dist/config-manager.d.ts +2 -0
  6. package/dist/config-manager.js +22 -2
  7. package/dist/handlers/filesystem-handlers.d.ts +5 -0
  8. package/dist/handlers/filesystem-handlers.js +19 -12
  9. package/dist/remote-device/desktop-commander-integration.js +1 -1
  10. package/dist/remote-device/remote-channel.js +1 -1
  11. package/dist/search-manager.js +31 -38
  12. package/dist/server.js +11 -4
  13. package/dist/terminal-manager.js +4 -2
  14. package/dist/tools/config.d.ts +71 -0
  15. package/dist/tools/config.js +117 -2
  16. package/dist/tools/edit.js +34 -1
  17. package/dist/tools/filesystem.js +91 -3
  18. package/dist/tools/improved-process-tools.js +2 -1
  19. package/dist/tools/schemas.d.ts +3 -0
  20. package/dist/tools/schemas.js +1 -0
  21. package/dist/types.d.ts +0 -1
  22. package/dist/ui/config-editor/app.d.ts +43 -0
  23. package/dist/ui/config-editor/app.js +840 -0
  24. package/dist/ui/config-editor/array-modal.d.ts +19 -0
  25. package/dist/ui/config-editor/array-modal.js +185 -0
  26. package/dist/ui/config-editor/config-editor-runtime.js +150 -0
  27. package/dist/ui/config-editor/index.html +13 -0
  28. package/dist/ui/config-editor/main.js +2 -0
  29. package/dist/ui/config-editor/src/App.d.ts +43 -0
  30. package/dist/ui/config-editor/src/App.js +840 -0
  31. package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
  32. package/dist/ui/config-editor/src/array-modal.js +185 -0
  33. package/dist/ui/config-editor/src/components/layout.d.ts +4 -0
  34. package/dist/ui/config-editor/src/components/layout.js +83 -0
  35. package/dist/ui/config-editor/src/components/toolbar.d.ts +1 -0
  36. package/dist/ui/config-editor/src/components/toolbar.js +21 -0
  37. package/dist/ui/config-editor/src/config-values.d.ts +6 -0
  38. package/dist/ui/config-editor/src/config-values.js +61 -0
  39. package/dist/ui/config-editor/src/contracts.d.ts +14 -0
  40. package/dist/ui/config-editor/src/contracts.js +3 -0
  41. package/dist/ui/config-editor/src/directory-browser.d.ts +6 -0
  42. package/dist/ui/config-editor/src/directory-browser.js +71 -0
  43. package/dist/ui/config-editor/src/layout.d.ts +5 -0
  44. package/dist/ui/config-editor/src/layout.js +90 -0
  45. package/dist/ui/config-editor/src/main.js +2 -0
  46. package/dist/ui/config-editor/src/parsing.d.ts +5 -0
  47. package/dist/ui/config-editor/src/parsing.js +50 -0
  48. package/dist/ui/config-editor/src/toolbar.d.ts +1 -0
  49. package/dist/ui/config-editor/src/toolbar.js +18 -0
  50. package/dist/ui/config-editor/src/types.d.ts +17 -0
  51. package/dist/ui/config-editor/src/types.js +3 -0
  52. package/dist/ui/config-editor/src/utils/config-values.d.ts +9 -0
  53. package/dist/ui/config-editor/src/utils/config-values.js +61 -0
  54. package/dist/ui/config-editor/src/utils/directory-browser.d.ts +31 -0
  55. package/dist/ui/config-editor/src/utils/directory-browser.js +201 -0
  56. package/dist/ui/config-editor/src/utils/parsing.d.ts +8 -0
  57. package/dist/ui/config-editor/src/utils/parsing.js +50 -0
  58. package/dist/ui/config-editor/styles.css +587 -0
  59. package/dist/ui/file-preview/app.d.ts +8 -0
  60. package/dist/ui/file-preview/app.js +2020 -0
  61. package/dist/ui/file-preview/components/code-viewer.d.ts +6 -0
  62. package/dist/ui/file-preview/components/code-viewer.js +73 -0
  63. package/dist/ui/file-preview/components/highlighting.d.ts +2 -0
  64. package/dist/ui/file-preview/components/highlighting.js +54 -0
  65. package/dist/ui/file-preview/components/html-renderer.d.ts +5 -0
  66. package/dist/ui/file-preview/components/html-renderer.js +47 -0
  67. package/dist/ui/file-preview/components/markdown-renderer.d.ts +1 -0
  68. package/dist/ui/file-preview/components/markdown-renderer.js +67 -0
  69. package/dist/ui/file-preview/components/toolbar.d.ts +6 -0
  70. package/dist/ui/file-preview/components/toolbar.js +75 -0
  71. package/dist/ui/file-preview/image-preview.d.ts +3 -0
  72. package/dist/ui/file-preview/image-preview.js +21 -0
  73. package/dist/ui/file-preview/main.js +5 -0
  74. package/dist/ui/file-preview/markdown/editor.d.ts +36 -0
  75. package/dist/ui/file-preview/markdown/editor.js +643 -0
  76. package/dist/ui/file-preview/markdown/linking.d.ts +9 -0
  77. package/dist/ui/file-preview/markdown/linking.js +210 -0
  78. package/dist/ui/file-preview/markdown/outline.d.ts +7 -0
  79. package/dist/ui/file-preview/markdown/outline.js +40 -0
  80. package/dist/ui/file-preview/markdown/preview.d.ts +8 -0
  81. package/dist/ui/file-preview/markdown/preview.js +33 -0
  82. package/dist/ui/file-preview/markdown/slugify.d.ts +3 -0
  83. package/dist/ui/file-preview/markdown/slugify.js +31 -0
  84. package/dist/ui/file-preview/markdown/toc.d.ts +11 -0
  85. package/dist/ui/file-preview/markdown/toc.js +75 -0
  86. package/dist/ui/file-preview/markdown/utils.d.ts +1 -0
  87. package/dist/ui/file-preview/markdown/utils.js +15 -0
  88. package/dist/ui/file-preview/markdown/workspace-controller.d.ts +25 -0
  89. package/dist/ui/file-preview/markdown/workspace-controller.js +40 -0
  90. package/dist/ui/file-preview/preview-runtime.js +399 -13969
  91. package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
  92. package/dist/ui/file-preview/shared/preview-file-types.js +3 -1
  93. package/dist/ui/file-preview/src/App.d.ts +4 -0
  94. package/dist/ui/file-preview/src/App.js +564 -0
  95. package/dist/ui/file-preview/src/components/CodeViewer.d.ts +6 -0
  96. package/dist/ui/file-preview/src/components/CodeViewer.js +60 -0
  97. package/dist/ui/file-preview/src/components/HtmlRenderer.d.ts +8 -0
  98. package/dist/ui/file-preview/src/components/HtmlRenderer.js +45 -0
  99. package/dist/ui/file-preview/src/components/MarkdownRenderer.d.ts +1 -0
  100. package/dist/ui/file-preview/src/components/MarkdownRenderer.js +15 -0
  101. package/dist/ui/file-preview/src/components/editor-toolbar.d.ts +15 -0
  102. package/dist/ui/file-preview/src/components/editor-toolbar.js +384 -0
  103. package/dist/ui/file-preview/src/components/html-renderer.d.ts +1 -5
  104. package/dist/ui/file-preview/src/components/html-renderer.js +11 -27
  105. package/dist/ui/file-preview/src/components/markdown-editor.d.ts +29 -0
  106. package/dist/ui/file-preview/src/components/markdown-editor.js +535 -0
  107. package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
  108. package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
  109. package/dist/ui/file-preview/src/directory-controller.js +233 -0
  110. package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
  111. package/dist/ui/file-preview/src/document-layout.js +109 -0
  112. package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
  113. package/dist/ui/file-preview/src/document-outline.js +97 -0
  114. package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
  115. package/dist/ui/file-preview/src/document-workspace.js +33 -0
  116. package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
  117. package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
  118. package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
  119. package/dist/ui/file-preview/src/host/external-actions.js +94 -0
  120. package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
  121. package/dist/ui/file-preview/src/host/selection-context.js +106 -0
  122. package/dist/ui/file-preview/src/markdown/block-merge.d.ts +25 -0
  123. package/dist/ui/file-preview/src/markdown/block-merge.js +86 -0
  124. package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
  125. package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
  126. package/dist/ui/file-preview/src/markdown/controller.d.ts +38 -0
  127. package/dist/ui/file-preview/src/markdown/controller.js +921 -0
  128. package/dist/ui/file-preview/src/markdown/editor.d.ts +35 -0
  129. package/dist/ui/file-preview/src/markdown/editor.js +691 -0
  130. package/dist/ui/file-preview/src/markdown/link-modal.d.ts +13 -0
  131. package/dist/ui/file-preview/src/markdown/link-modal.js +213 -0
  132. package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
  133. package/dist/ui/file-preview/src/markdown/linking.js +228 -0
  134. package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
  135. package/dist/ui/file-preview/src/markdown/outline.js +16 -0
  136. package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
  137. package/dist/ui/file-preview/src/markdown/parser.js +38 -0
  138. package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
  139. package/dist/ui/file-preview/src/markdown/preview.js +20 -0
  140. package/dist/ui/file-preview/src/markdown/raw-editor.d.ts +8 -0
  141. package/dist/ui/file-preview/src/markdown/raw-editor.js +61 -0
  142. package/dist/ui/file-preview/src/markdown/selection-toolbar.d.ts +14 -0
  143. package/dist/ui/file-preview/src/markdown/selection-toolbar.js +128 -0
  144. package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
  145. package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
  146. package/dist/ui/file-preview/src/markdown/toc.d.ts +11 -0
  147. package/dist/ui/file-preview/src/markdown/toc.js +75 -0
  148. package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
  149. package/dist/ui/file-preview/src/markdown/utils.js +15 -0
  150. package/dist/ui/file-preview/src/markdown-workspace/editor.d.ts +36 -0
  151. package/dist/ui/file-preview/src/markdown-workspace/editor.js +643 -0
  152. package/dist/ui/file-preview/src/markdown-workspace/linking.d.ts +9 -0
  153. package/dist/ui/file-preview/src/markdown-workspace/linking.js +210 -0
  154. package/dist/ui/file-preview/src/markdown-workspace/outline.d.ts +7 -0
  155. package/dist/ui/file-preview/src/markdown-workspace/outline.js +40 -0
  156. package/dist/ui/file-preview/src/markdown-workspace/preview.d.ts +8 -0
  157. package/dist/ui/file-preview/src/markdown-workspace/preview.js +33 -0
  158. package/dist/ui/file-preview/src/markdown-workspace/slugify.d.ts +3 -0
  159. package/dist/ui/file-preview/src/markdown-workspace/slugify.js +31 -0
  160. package/dist/ui/file-preview/src/markdown-workspace/toc.d.ts +11 -0
  161. package/dist/ui/file-preview/src/markdown-workspace/toc.js +75 -0
  162. package/dist/ui/file-preview/src/markdown-workspace/utils.d.ts +1 -0
  163. package/dist/ui/file-preview/src/markdown-workspace/utils.js +15 -0
  164. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.d.ts +25 -0
  165. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.js +40 -0
  166. package/dist/ui/file-preview/src/model.d.ts +34 -0
  167. package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
  168. package/dist/ui/file-preview/src/panel-actions.js +182 -0
  169. package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
  170. package/dist/ui/file-preview/src/path-utils.js +64 -0
  171. package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
  172. package/dist/ui/file-preview/src/payload-utils.js +94 -0
  173. package/dist/ui/file-preview/styles.css +1144 -277
  174. package/dist/ui/file-preview/types.d.ts +1 -0
  175. package/dist/ui/file-preview/types.js +1 -0
  176. package/dist/ui/resources.d.ts +7 -0
  177. package/dist/ui/resources.js +16 -2
  178. package/dist/ui/server-integration.d.ts +13 -0
  179. package/dist/ui/server-integration.js +31 -0
  180. package/dist/ui/shared/ToolHeader.d.ts +9 -0
  181. package/dist/ui/shared/ToolHeader.js +29 -0
  182. package/dist/ui/shared/app-bootstrap.d.ts +9 -0
  183. package/dist/ui/shared/app-bootstrap.js +15 -0
  184. package/dist/ui/shared/compact-row.d.ts +11 -0
  185. package/dist/ui/shared/compact-row.js +18 -0
  186. package/dist/ui/shared/guards.d.ts +1 -0
  187. package/dist/ui/shared/guards.js +3 -0
  188. package/dist/ui/shared/host-context.d.ts +15 -0
  189. package/dist/ui/shared/host-context.js +51 -0
  190. package/dist/ui/shared/host-lifecycle.d.ts +1 -0
  191. package/dist/ui/shared/host-lifecycle.js +8 -2
  192. package/dist/ui/shared/tool-bridge.d.ts +30 -0
  193. package/dist/ui/shared/tool-bridge.js +137 -0
  194. package/dist/ui/shared/tool-shell.d.ts +9 -0
  195. package/dist/ui/shared/tool-shell.js +46 -4
  196. package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
  197. package/dist/ui/shared/ui-event-tracker.js +27 -0
  198. package/dist/ui/shared/widget-state.d.ts +6 -1
  199. package/dist/ui/shared/widget-state.js +102 -4
  200. package/dist/utils/capture.js +3 -3
  201. package/dist/utils/files/base.d.ts +2 -0
  202. package/dist/utils/open-browser.js +1 -1
  203. package/dist/utils/ui-call-context.d.ts +8 -0
  204. package/dist/utils/ui-call-context.js +72 -0
  205. package/dist/version.d.ts +1 -1
  206. package/dist/version.js +1 -1
  207. package/package.json +13 -4
  208. package/dist/data/spec-kit-prompts.json +0 -123
  209. package/dist/handlers/node-handlers.d.ts +0 -6
  210. package/dist/handlers/node-handlers.js +0 -73
  211. package/dist/handlers/test-crash-handler.d.ts +0 -11
  212. package/dist/handlers/test-crash-handler.js +0 -26
  213. package/dist/http-index.d.ts +0 -45
  214. package/dist/http-index.js +0 -51
  215. package/dist/http-server-auto-tunnel.js +0 -667
  216. package/dist/http-server-named-tunnel.d.ts +0 -2
  217. package/dist/http-server-named-tunnel.js +0 -167
  218. package/dist/http-server-tunnel.d.ts +0 -2
  219. package/dist/http-server-tunnel.js +0 -111
  220. package/dist/http-server.d.ts +0 -2
  221. package/dist/http-server.js +0 -270
  222. package/dist/index-oauth.d.ts +0 -2
  223. package/dist/index-oauth.js +0 -201
  224. package/dist/oauth/auth-middleware.d.ts +0 -20
  225. package/dist/oauth/auth-middleware.js +0 -62
  226. package/dist/oauth/index.d.ts +0 -3
  227. package/dist/oauth/index.js +0 -3
  228. package/dist/oauth/oauth-manager.d.ts +0 -80
  229. package/dist/oauth/oauth-manager.js +0 -179
  230. package/dist/oauth/oauth-routes.d.ts +0 -3
  231. package/dist/oauth/oauth-routes.js +0 -377
  232. package/dist/oauth/provider.d.ts +0 -22
  233. package/dist/oauth/provider.js +0 -124
  234. package/dist/oauth/server.d.ts +0 -18
  235. package/dist/oauth/server.js +0 -160
  236. package/dist/oauth/types.d.ts +0 -54
  237. package/dist/oauth/types.js +0 -2
  238. package/dist/remote-device/templates/auth-success.d.ts +0 -1
  239. package/dist/remote-device/templates/auth-success.js +0 -30
  240. package/dist/setup.log +0 -275
  241. package/dist/test-setup.js +0 -14
  242. package/dist/tools/docx/builders/html-builder.d.ts +0 -17
  243. package/dist/tools/docx/builders/html-builder.js +0 -92
  244. package/dist/tools/docx/builders/image.d.ts +0 -14
  245. package/dist/tools/docx/builders/image.js +0 -84
  246. package/dist/tools/docx/builders/index.d.ts +0 -11
  247. package/dist/tools/docx/builders/index.js +0 -11
  248. package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
  249. package/dist/tools/docx/builders/markdown-builder.js +0 -260
  250. package/dist/tools/docx/builders/paragraph.d.ts +0 -12
  251. package/dist/tools/docx/builders/paragraph.js +0 -29
  252. package/dist/tools/docx/builders/table.d.ts +0 -10
  253. package/dist/tools/docx/builders/table.js +0 -138
  254. package/dist/tools/docx/builders/utils.d.ts +0 -5
  255. package/dist/tools/docx/builders/utils.js +0 -18
  256. package/dist/tools/docx/constants.d.ts +0 -32
  257. package/dist/tools/docx/constants.js +0 -61
  258. package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
  259. package/dist/tools/docx/converters/markdown-to-html.js +0 -111
  260. package/dist/tools/docx/create.d.ts +0 -21
  261. package/dist/tools/docx/create.js +0 -386
  262. package/dist/tools/docx/dom.d.ts +0 -139
  263. package/dist/tools/docx/dom.js +0 -448
  264. package/dist/tools/docx/errors.d.ts +0 -28
  265. package/dist/tools/docx/errors.js +0 -48
  266. package/dist/tools/docx/extractors/images.d.ts +0 -14
  267. package/dist/tools/docx/extractors/images.js +0 -40
  268. package/dist/tools/docx/extractors/metadata.d.ts +0 -14
  269. package/dist/tools/docx/extractors/metadata.js +0 -64
  270. package/dist/tools/docx/extractors/sections.d.ts +0 -14
  271. package/dist/tools/docx/extractors/sections.js +0 -61
  272. package/dist/tools/docx/html.d.ts +0 -17
  273. package/dist/tools/docx/html.js +0 -111
  274. package/dist/tools/docx/index.d.ts +0 -10
  275. package/dist/tools/docx/index.js +0 -10
  276. package/dist/tools/docx/markdown.d.ts +0 -84
  277. package/dist/tools/docx/markdown.js +0 -507
  278. package/dist/tools/docx/modify.d.ts +0 -28
  279. package/dist/tools/docx/modify.js +0 -271
  280. package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
  281. package/dist/tools/docx/operations/handlers/index.js +0 -152
  282. package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
  283. package/dist/tools/docx/operations/html-manipulator.js +0 -352
  284. package/dist/tools/docx/operations/index.d.ts +0 -14
  285. package/dist/tools/docx/operations/index.js +0 -61
  286. package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
  287. package/dist/tools/docx/operations/operation-handlers.js +0 -67
  288. package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
  289. package/dist/tools/docx/operations/preprocessor.js +0 -44
  290. package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
  291. package/dist/tools/docx/operations/xml-replacer.js +0 -35
  292. package/dist/tools/docx/operations.d.ts +0 -13
  293. package/dist/tools/docx/operations.js +0 -13
  294. package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
  295. package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
  296. package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
  297. package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
  298. package/dist/tools/docx/ops/index.d.ts +0 -17
  299. package/dist/tools/docx/ops/index.js +0 -70
  300. package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
  301. package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
  302. package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
  303. package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
  304. package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
  305. package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
  306. package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
  307. package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
  308. package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
  309. package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
  310. package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
  311. package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
  312. package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
  313. package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
  314. package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
  315. package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
  316. package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
  317. package/dist/tools/docx/ops/set-color-for-style.js +0 -31
  318. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
  319. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
  320. package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
  321. package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
  322. package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
  323. package/dist/tools/docx/parsers/image-extractor.js +0 -61
  324. package/dist/tools/docx/parsers/index.d.ts +0 -9
  325. package/dist/tools/docx/parsers/index.js +0 -9
  326. package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
  327. package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
  328. package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
  329. package/dist/tools/docx/parsers/table-parser.js +0 -72
  330. package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
  331. package/dist/tools/docx/parsers/xml-parser.js +0 -71
  332. package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
  333. package/dist/tools/docx/parsers/zip-reader.js +0 -52
  334. package/dist/tools/docx/read.d.ts +0 -27
  335. package/dist/tools/docx/read.js +0 -308
  336. package/dist/tools/docx/relationships.d.ts +0 -22
  337. package/dist/tools/docx/relationships.js +0 -76
  338. package/dist/tools/docx/structure.d.ts +0 -25
  339. package/dist/tools/docx/structure.js +0 -102
  340. package/dist/tools/docx/styled-html-parser.d.ts +0 -23
  341. package/dist/tools/docx/styled-html-parser.js +0 -1262
  342. package/dist/tools/docx/types.d.ts +0 -213
  343. package/dist/tools/docx/types.js +0 -5
  344. package/dist/tools/docx/utils/escaping.d.ts +0 -13
  345. package/dist/tools/docx/utils/escaping.js +0 -26
  346. package/dist/tools/docx/utils/images.d.ts +0 -9
  347. package/dist/tools/docx/utils/images.js +0 -26
  348. package/dist/tools/docx/utils/index.d.ts +0 -12
  349. package/dist/tools/docx/utils/index.js +0 -17
  350. package/dist/tools/docx/utils/markdown.d.ts +0 -13
  351. package/dist/tools/docx/utils/markdown.js +0 -32
  352. package/dist/tools/docx/utils/paths.d.ts +0 -15
  353. package/dist/tools/docx/utils/paths.js +0 -27
  354. package/dist/tools/docx/utils/versioning.d.ts +0 -25
  355. package/dist/tools/docx/utils/versioning.js +0 -55
  356. package/dist/tools/docx/utils.d.ts +0 -101
  357. package/dist/tools/docx/utils.js +0 -299
  358. package/dist/tools/docx/validate.d.ts +0 -33
  359. package/dist/tools/docx/validate.js +0 -49
  360. package/dist/tools/docx/validators.d.ts +0 -13
  361. package/dist/tools/docx/validators.js +0 -40
  362. package/dist/tools/docx/write.d.ts +0 -17
  363. package/dist/tools/docx/write.js +0 -88
  364. package/dist/tools/docx/xml-view-test.js +0 -63
  365. package/dist/tools/docx/xml-view.d.ts +0 -56
  366. package/dist/tools/docx/xml-view.js +0 -169
  367. package/dist/tools/docx/zip.d.ts +0 -21
  368. package/dist/tools/docx/zip.js +0 -35
  369. package/dist/tools/pdf-processor.js +0 -3
  370. package/dist/tools/search.d.ts +0 -32
  371. package/dist/tools/search.js +0 -202
  372. package/dist/ui/file-preview/src/app.d.ts +0 -4
  373. package/dist/ui/file-preview/src/app.js +0 -800
  374. package/dist/utils/crash-logger.d.ts +0 -18
  375. package/dist/utils/crash-logger.js +0 -44
  376. package/dist/utils/dedent.d.ts +0 -8
  377. package/dist/utils/dedent.js +0 -38
  378. /package/dist/{http-server-auto-tunnel.d.ts → ui/config-editor/main.d.ts} +0 -0
  379. /package/dist/{test-docx.d.ts → ui/config-editor/src/main.d.ts} +0 -0
  380. /package/dist/{tools/docx/xml-view-test.d.ts → ui/file-preview/main.d.ts} +0 -0
  381. /package/dist/ui/file-preview/src/components/{toolbar.d.ts → Toolbar.d.ts} +0 -0
  382. /package/dist/ui/file-preview/src/components/{toolbar.js → Toolbar.js} +0 -0
  383. /package/dist/{tools/pdf-processor.d.ts → ui/file-preview/src/model.js} +0 -0
@@ -0,0 +1,691 @@
1
+ import { Editor } from '@tiptap/core';
2
+ import StarterKit from '@tiptap/starter-kit';
3
+ import Image from '@tiptap/extension-image';
4
+ import { Markdown } from 'tiptap-markdown';
5
+ import { restoreWikiLinks, rewriteWikiLinks } from './linking.js';
6
+ import { createSlugTracker } from './slugify.js';
7
+ function shouldIgnoreBlur(shell, event) {
8
+ const nextTarget = event.relatedTarget;
9
+ const widgetShell = shell?.closest('.tool-shell');
10
+ return Boolean(nextTarget && (shell?.contains(nextTarget) || widgetShell?.contains(nextTarget)));
11
+ }
12
+ function renderFormattingButtons() {
13
+ return `
14
+ <button class="markdown-format-button" type="button" data-format="bold"><strong>B</strong></button>
15
+ <button class="markdown-format-button" type="button" data-format="italic"><em>I</em></button>
16
+ <button class="markdown-format-button" type="button" data-format="strike"><span style="text-decoration:line-through">S</span></button>
17
+ <span class="markdown-format-sep" aria-hidden="true"></span>
18
+ <label class="markdown-format-size" title="Block style" aria-label="Block style">
19
+ <select id="markdown-block-style">
20
+ <option value="p" selected>Normal</option>
21
+ <option value="h1">H1</option>
22
+ <option value="h2">H2</option>
23
+ <option value="h3">H3</option>
24
+ </select>
25
+ </label>
26
+ <span class="markdown-format-sep" aria-hidden="true"></span>
27
+ <button class="markdown-format-button" type="button" data-format="quote" title="Quote" aria-label="Quote">&#10077;</button>
28
+ <button class="markdown-format-button" type="button" data-format="list" title="List" aria-label="List">&#8226;</button>
29
+ <button class="markdown-format-button" type="button" data-format="link" title="Link" aria-label="Link">&#128279;</button>
30
+ <button class="markdown-format-button" type="button" data-format="code" title="Code" aria-label="Code">&lsaquo;&rsaquo;</button>
31
+ `;
32
+ }
33
+ function renderModeToggleIcon(view) {
34
+ if (view === 'raw') {
35
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
36
+ }
37
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16"></path><path d="M4 12h10"></path><path d="M4 17h7"></path></svg>';
38
+ }
39
+ function renderHeadingOptionLabel(headings, heading) {
40
+ const duplicateCount = headings.filter((candidate) => candidate.text === heading.text).length;
41
+ if (duplicateCount <= 1) {
42
+ return heading.text;
43
+ }
44
+ return `${heading.text} (#${heading.id})`;
45
+ }
46
+ export function renderMarkdownCopyButton() {
47
+ return `<button class="markdown-editor-copy-button" type="button" id="copy-active-markdown" title="Copy" aria-label="Copy"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg><span>Copy</span></button>`;
48
+ }
49
+ export function renderMarkdownModeToggle(view) {
50
+ return `
51
+ <div class="markdown-editor-mode-toggle" role="tablist" aria-label="Editor mode">
52
+ <div class="markdown-editor-mode-toggle-indicator markdown-editor-mode-toggle-indicator--${view}" aria-hidden="true"></div>
53
+ <button class="markdown-editor-mode-option${view === 'raw' ? ' is-active' : ''}" type="button" id="markdown-mode-raw" role="tab" aria-selected="${view === 'raw' ? 'true' : 'false'}" title="Raw" aria-label="Raw">${renderModeToggleIcon('raw')}<span>Raw</span></button>
54
+ <button class="markdown-editor-mode-option${view === 'markdown' ? ' is-active' : ''}" type="button" id="markdown-mode-markdown" role="tab" aria-selected="${view === 'markdown' ? 'true' : 'false'}" title="Preview" aria-label="Preview">${renderModeToggleIcon('markdown')}<span>Preview</span></button>
55
+ </div>
56
+ `;
57
+ }
58
+ export function renderMarkdownEditorShell(options) {
59
+ const isMarkdownView = options.view === 'markdown';
60
+ return `
61
+ <div class="markdown-editor-shell markdown-editor-shell--${options.view}">
62
+ <section class="markdown-editor-pane markdown-editor-pane--${options.view}" aria-label="Markdown editor">
63
+ ${isMarkdownView ? `<div id="markdown-editor-context-menu" class="markdown-editor-context-menu" hidden>${renderFormattingButtons()}</div><div id="markdown-link-modal" class="markdown-link-modal" hidden><div class="markdown-link-modal-card"><div class="markdown-link-mode-tabs"><button type="button" id="markdown-link-mode-file" class="markdown-link-mode-tab is-active">File</button><button type="button" id="markdown-link-mode-url" class="markdown-link-mode-tab">URL</button></div><div id="markdown-link-file-fields"><label class="markdown-link-modal-label" for="markdown-link-search">Find note</label><input id="markdown-link-search" class="markdown-link-modal-input" type="text" placeholder="Search files..." /><div id="markdown-link-results" class="markdown-link-results"></div><label class="markdown-link-modal-label" for="markdown-link-heading">Heading</label><select id="markdown-link-heading" class="markdown-link-modal-input markdown-link-modal-select"><option value="">None</option></select><label class="markdown-link-modal-label" for="markdown-link-alias">Alias</label><input id="markdown-link-alias" class="markdown-link-modal-input" type="text" placeholder="Optional label" /></div><div id="markdown-link-url-fields" hidden><label class="markdown-link-modal-label" for="markdown-link-input">URL</label><input id="markdown-link-input" class="markdown-link-modal-input" type="url" placeholder="https://example.com" /><label class="markdown-link-modal-label" for="markdown-link-label">Label</label><input id="markdown-link-label" class="markdown-link-modal-input" type="text" placeholder="Optional label" /></div><div class="markdown-link-modal-actions"><button type="button" id="markdown-link-cancel" class="markdown-link-modal-button">Cancel</button><button type="button" id="markdown-link-apply" class="markdown-link-modal-button markdown-link-modal-button--primary">Insert</button></div></div></div>` : ''}
64
+ <div id="markdown-editor-root" class="markdown-editor-root"></div>
65
+ </section>
66
+ </div>
67
+ `;
68
+ }
69
+ function applyRawTab(textarea) {
70
+ const start = textarea.selectionStart;
71
+ const end = textarea.selectionEnd;
72
+ const nextValue = `${textarea.value.slice(0, start)}\t${textarea.value.slice(end)}`;
73
+ textarea.value = nextValue;
74
+ textarea.selectionStart = start + 1;
75
+ textarea.selectionEnd = start + 1;
76
+ }
77
+ /**
78
+ * Walk the prose-mirror DOM and assign slug-based id attributes to headings
79
+ * so the outline's revealLine can scroll to them. Re-run after every update;
80
+ * no-op writes are skipped so identical ids don't dirty the style engine.
81
+ */
82
+ function syncHeadingIds(root) {
83
+ const nextSlug = createSlugTracker();
84
+ const headings = Array.from(root.querySelectorAll('h1, h2, h3, h4, h5, h6'));
85
+ for (const heading of headings) {
86
+ const text = heading.textContent?.trim() ?? '';
87
+ if (!text) {
88
+ if (heading.hasAttribute('id')) {
89
+ heading.removeAttribute('id');
90
+ }
91
+ if (heading.hasAttribute('data-heading-id')) {
92
+ heading.removeAttribute('data-heading-id');
93
+ }
94
+ continue;
95
+ }
96
+ const headingId = nextSlug(text);
97
+ if (heading.id !== headingId) {
98
+ heading.id = headingId;
99
+ }
100
+ if (heading.getAttribute('data-heading-id') !== headingId) {
101
+ heading.setAttribute('data-heading-id', headingId);
102
+ }
103
+ }
104
+ }
105
+ export function mountMarkdownEditor(options) {
106
+ const shell = options.target.closest('.markdown-editor-shell');
107
+ const contextMenu = shell?.querySelector('#markdown-editor-context-menu');
108
+ const formatButtons = shell ? Array.from(shell.querySelectorAll('[data-format]')) : [];
109
+ const blockStyleSelect = shell?.querySelector('#markdown-block-style');
110
+ const linkModal = shell?.querySelector('#markdown-link-modal');
111
+ const linkModeFile = shell?.querySelector('#markdown-link-mode-file');
112
+ const linkModeUrl = shell?.querySelector('#markdown-link-mode-url');
113
+ const linkFileFields = shell?.querySelector('#markdown-link-file-fields');
114
+ const linkUrlFields = shell?.querySelector('#markdown-link-url-fields');
115
+ const linkSearchInput = shell?.querySelector('#markdown-link-search');
116
+ const linkResults = shell?.querySelector('#markdown-link-results');
117
+ const linkHeadingSelect = shell?.querySelector('#markdown-link-heading');
118
+ const linkAliasInput = shell?.querySelector('#markdown-link-alias');
119
+ const linkInput = shell?.querySelector('#markdown-link-input');
120
+ const linkLabelInput = shell?.querySelector('#markdown-link-label');
121
+ const linkApply = shell?.querySelector('#markdown-link-apply');
122
+ const linkCancel = shell?.querySelector('#markdown-link-cancel');
123
+ let linkMode = 'file';
124
+ let linkSearchResults = [];
125
+ let selectedLinkItem = null;
126
+ let linkResultsMessage = 'Search for a file to link';
127
+ let linkSearchRequestId = 0;
128
+ let linkHeadingRequestId = 0;
129
+ if (options.view === 'markdown') {
130
+ options.target.replaceChildren();
131
+ const getTiptapMarkdown = () => {
132
+ const storage = tiptap.storage;
133
+ return restoreWikiLinks(storage.markdown?.getMarkdown() ?? '');
134
+ };
135
+ const tiptap = new Editor({
136
+ element: options.target,
137
+ extensions: [
138
+ StarterKit.configure({
139
+ heading: { levels: [1, 2, 3, 4, 5, 6] },
140
+ codeBlock: { HTMLAttributes: { class: 'code-viewer' } },
141
+ link: {
142
+ openOnClick: false,
143
+ autolink: true,
144
+ HTMLAttributes: { 'data-markdown-link': 'true' },
145
+ },
146
+ }),
147
+ Image.configure({ allowBase64: true, inline: true }),
148
+ Markdown.configure({
149
+ html: true,
150
+ tightLists: true,
151
+ bulletListMarker: '-',
152
+ linkify: true,
153
+ breaks: false,
154
+ transformPastedText: true,
155
+ transformCopiedText: false,
156
+ }),
157
+ ],
158
+ content: rewriteWikiLinks(options.value),
159
+ editorProps: {
160
+ attributes: {
161
+ class: 'markdown-editor-surface markdown-editor-surface--markdown markdown markdown-doc',
162
+ role: 'textbox',
163
+ 'aria-multiline': 'true',
164
+ },
165
+ },
166
+ onUpdate: ({ editor }) => {
167
+ syncHeadingIds(editor.view.dom);
168
+ options.onChange(getTiptapMarkdown());
169
+ },
170
+ onSelectionUpdate: () => {
171
+ updateContextMenu();
172
+ },
173
+ onBlur: ({ event }) => {
174
+ if (shouldIgnoreBlur(shell, event)) {
175
+ return;
176
+ }
177
+ if (contextMenu) {
178
+ contextMenu.hidden = true;
179
+ }
180
+ options.onBlur?.();
181
+ },
182
+ });
183
+ const editorDom = tiptap.view.dom;
184
+ syncHeadingIds(editorDom);
185
+ const updateContextMenu = () => {
186
+ if (!contextMenu) {
187
+ return;
188
+ }
189
+ const { from, to, empty } = tiptap.state.selection;
190
+ if (empty || !tiptap.isFocused) {
191
+ contextMenu.hidden = true;
192
+ return;
193
+ }
194
+ const start = tiptap.view.coordsAtPos(from);
195
+ const end = tiptap.view.coordsAtPos(to);
196
+ const shellEl = shell;
197
+ if (!shellEl) {
198
+ return;
199
+ }
200
+ const shellRect = shellEl.getBoundingClientRect();
201
+ const midX = (start.left + end.right) / 2;
202
+ contextMenu.hidden = false;
203
+ const left = Math.max(12, midX - shellRect.left - contextMenu.offsetWidth / 2);
204
+ const top = Math.max(12, start.top - shellRect.top - contextMenu.offsetHeight - 10);
205
+ contextMenu.style.left = `${left}px`;
206
+ contextMenu.style.top = `${top}px`;
207
+ };
208
+ const setLinkHeadingOptions = (headings = [], placeholder = 'None') => {
209
+ if (!linkHeadingSelect) {
210
+ return;
211
+ }
212
+ linkHeadingSelect.replaceChildren();
213
+ const noneOption = document.createElement('option');
214
+ noneOption.value = '';
215
+ noneOption.textContent = placeholder;
216
+ linkHeadingSelect.appendChild(noneOption);
217
+ for (const heading of headings) {
218
+ const option = document.createElement('option');
219
+ option.value = heading.id;
220
+ option.textContent = renderHeadingOptionLabel(headings, heading);
221
+ option.dataset.headingText = heading.text;
222
+ linkHeadingSelect.appendChild(option);
223
+ }
224
+ };
225
+ const loadHeadingsForItem = async (item) => {
226
+ if (!linkHeadingSelect) {
227
+ return;
228
+ }
229
+ const requestId = ++linkHeadingRequestId;
230
+ setLinkHeadingOptions([], 'Loading…');
231
+ try {
232
+ const headings = await options.loadHeadings?.(item.path) ?? [];
233
+ if (requestId !== linkHeadingRequestId || selectedLinkItem?.path !== item.path) {
234
+ return;
235
+ }
236
+ setLinkHeadingOptions(headings);
237
+ }
238
+ catch {
239
+ if (requestId !== linkHeadingRequestId || selectedLinkItem?.path !== item.path) {
240
+ return;
241
+ }
242
+ setLinkHeadingOptions([], 'Failed to load headings');
243
+ }
244
+ };
245
+ const renderLinkResults = () => {
246
+ if (!linkResults) {
247
+ return;
248
+ }
249
+ if (linkSearchResults.length === 0) {
250
+ const empty = document.createElement('div');
251
+ empty.className = 'markdown-link-results-empty';
252
+ empty.textContent = linkResultsMessage;
253
+ linkResults.replaceChildren(empty);
254
+ return;
255
+ }
256
+ const fragment = document.createDocumentFragment();
257
+ for (const item of linkSearchResults) {
258
+ const button = document.createElement('button');
259
+ button.type = 'button';
260
+ button.className = `markdown-link-result${selectedLinkItem?.path === item.path ? ' is-active' : ''}`;
261
+ button.dataset.linkPath = item.path;
262
+ const title = document.createElement('span');
263
+ title.className = 'markdown-link-result-title';
264
+ title.textContent = item.title;
265
+ const path = document.createElement('span');
266
+ path.className = 'markdown-link-result-path';
267
+ path.textContent = item.relativePath;
268
+ button.append(title, path);
269
+ button.addEventListener('click', () => {
270
+ selectedLinkItem = item;
271
+ renderLinkResults();
272
+ void loadHeadingsForItem(item);
273
+ });
274
+ fragment.appendChild(button);
275
+ }
276
+ linkResults.replaceChildren(fragment);
277
+ };
278
+ const updateLinkMode = (mode) => {
279
+ linkMode = mode;
280
+ linkModeFile?.classList.toggle('is-active', mode === 'file');
281
+ linkModeUrl?.classList.toggle('is-active', mode === 'url');
282
+ if (linkFileFields) {
283
+ linkFileFields.hidden = mode !== 'file';
284
+ }
285
+ if (linkUrlFields) {
286
+ linkUrlFields.hidden = mode !== 'url';
287
+ }
288
+ };
289
+ const runLinkSearch = async () => {
290
+ if (!linkSearchInput || !options.searchLinks) {
291
+ return;
292
+ }
293
+ const query = linkSearchInput.value.trim();
294
+ if (query.length === 0) {
295
+ linkSearchRequestId += 1;
296
+ linkSearchResults = [];
297
+ selectedLinkItem = null;
298
+ linkResultsMessage = 'Search for a file to link';
299
+ setLinkHeadingOptions();
300
+ renderLinkResults();
301
+ return;
302
+ }
303
+ const requestId = ++linkSearchRequestId;
304
+ try {
305
+ const results = await options.searchLinks(query);
306
+ if (requestId !== linkSearchRequestId || query !== linkSearchInput.value.trim()) {
307
+ return;
308
+ }
309
+ linkSearchResults = results;
310
+ selectedLinkItem = results[0] ?? null;
311
+ linkResultsMessage = results.length === 0 ? 'No matching files found' : 'Search for a file to link';
312
+ renderLinkResults();
313
+ if (selectedLinkItem) {
314
+ void loadHeadingsForItem(selectedLinkItem);
315
+ }
316
+ else {
317
+ setLinkHeadingOptions();
318
+ }
319
+ }
320
+ catch {
321
+ if (requestId !== linkSearchRequestId) {
322
+ return;
323
+ }
324
+ linkSearchResults = [];
325
+ selectedLinkItem = null;
326
+ linkResultsMessage = 'Search failed. Try again.';
327
+ setLinkHeadingOptions();
328
+ renderLinkResults();
329
+ }
330
+ };
331
+ const closeLinkModal = () => {
332
+ linkModal?.setAttribute('hidden', '');
333
+ if (linkInput) {
334
+ linkInput.value = '';
335
+ }
336
+ if (linkLabelInput) {
337
+ linkLabelInput.value = '';
338
+ }
339
+ if (linkAliasInput) {
340
+ linkAliasInput.value = '';
341
+ }
342
+ if (linkSearchInput) {
343
+ linkSearchInput.value = '';
344
+ }
345
+ setLinkHeadingOptions();
346
+ linkSearchResults = [];
347
+ selectedLinkItem = null;
348
+ linkResultsMessage = 'Search for a file to link';
349
+ renderLinkResults();
350
+ };
351
+ const openLinkModalForSelection = () => {
352
+ if (!linkModal) {
353
+ return;
354
+ }
355
+ const selectedText = tiptap.state.doc.textBetween(tiptap.state.selection.from, tiptap.state.selection.to, ' ').trim();
356
+ linkModal.removeAttribute('hidden');
357
+ updateLinkMode('url');
358
+ if (linkLabelInput) {
359
+ linkLabelInput.value = selectedText;
360
+ }
361
+ if (linkInput) {
362
+ linkInput.value = '';
363
+ linkInput.focus();
364
+ }
365
+ linkSearchResults = [];
366
+ selectedLinkItem = null;
367
+ linkResultsMessage = 'Search for a file to link';
368
+ setLinkHeadingOptions();
369
+ renderLinkResults();
370
+ };
371
+ const handleLinkApply = () => {
372
+ if (linkMode === 'url') {
373
+ const href = linkInput?.value?.trim();
374
+ if (!href) {
375
+ closeLinkModal();
376
+ return;
377
+ }
378
+ const label = linkLabelInput?.value?.trim() || href;
379
+ const { from, to, empty } = tiptap.state.selection;
380
+ if (empty) {
381
+ tiptap.chain().focus().insertContent({
382
+ type: 'text',
383
+ text: label,
384
+ marks: [{ type: 'link', attrs: { href } }],
385
+ }).run();
386
+ }
387
+ else {
388
+ tiptap.chain()
389
+ .focus()
390
+ .deleteRange({ from, to })
391
+ .insertContent({
392
+ type: 'text',
393
+ text: label,
394
+ marks: [{ type: 'link', attrs: { href } }],
395
+ })
396
+ .run();
397
+ }
398
+ }
399
+ else if (selectedLinkItem) {
400
+ const selectedHeadingId = linkHeadingSelect?.value?.trim();
401
+ const selectedHeadingText = linkHeadingSelect?.selectedOptions[0]?.dataset.headingText?.trim();
402
+ const alias = linkAliasInput?.value?.trim();
403
+ const pathPart = selectedLinkItem.path === options.currentFilePath ? '' : selectedLinkItem.wikiPath;
404
+ const wikiLink = `[[${pathPart}${selectedHeadingId ? `#${selectedHeadingId}` : ''}${alias ? `|${alias}` : ''}]]`;
405
+ const href = `${selectedLinkItem.relativePath}${selectedHeadingId ? `#${selectedHeadingId}` : ''}`;
406
+ const label = alias || selectedHeadingText || selectedLinkItem.title;
407
+ const { from, to, empty } = tiptap.state.selection;
408
+ const insertChain = tiptap.chain().focus();
409
+ if (!empty) {
410
+ insertChain.deleteRange({ from, to });
411
+ }
412
+ insertChain.insertContent({
413
+ type: 'text',
414
+ text: label,
415
+ marks: [{
416
+ type: 'link',
417
+ attrs: {
418
+ href,
419
+ title: `mcp-wiki:${encodeURIComponent(wikiLink)}`,
420
+ },
421
+ }],
422
+ }).run();
423
+ }
424
+ closeLinkModal();
425
+ };
426
+ const handleFormatClick = (event) => {
427
+ const target = event.currentTarget;
428
+ const format = target.dataset.format;
429
+ if (!format) {
430
+ return;
431
+ }
432
+ switch (format) {
433
+ case 'bold':
434
+ tiptap.chain().focus().toggleBold().run();
435
+ break;
436
+ case 'italic':
437
+ tiptap.chain().focus().toggleItalic().run();
438
+ break;
439
+ case 'strike':
440
+ tiptap.chain().focus().toggleStrike().run();
441
+ break;
442
+ case 'quote':
443
+ tiptap.chain().focus().toggleBlockquote().run();
444
+ break;
445
+ case 'list':
446
+ tiptap.chain().focus().toggleBulletList().run();
447
+ break;
448
+ case 'code':
449
+ tiptap.chain().focus().toggleCode().run();
450
+ break;
451
+ case 'link':
452
+ openLinkModalForSelection();
453
+ break;
454
+ }
455
+ };
456
+ const handleBlockStyleChange = () => {
457
+ const value = blockStyleSelect?.value;
458
+ if (!value) {
459
+ return;
460
+ }
461
+ if (value === 'p') {
462
+ tiptap.chain().focus().setParagraph().run();
463
+ return;
464
+ }
465
+ const match = /^h([1-6])$/.exec(value);
466
+ if (match) {
467
+ const level = Number.parseInt(match[1], 10);
468
+ tiptap.chain().focus().toggleHeading({ level }).run();
469
+ }
470
+ };
471
+ const linkPopover = document.createElement('div');
472
+ linkPopover.className = 'markdown-link-popover';
473
+ linkPopover.hidden = true;
474
+ editorDom.parentElement?.appendChild(linkPopover);
475
+ let popoverHideTimer = null;
476
+ const showLinkPopover = (anchor) => {
477
+ if (popoverHideTimer) {
478
+ clearTimeout(popoverHideTimer);
479
+ popoverHideTimer = null;
480
+ }
481
+ const href = anchor.getAttribute('href') ?? '';
482
+ linkPopover.innerHTML = `<button class="markdown-link-popover-btn" id="link-popover-edit" type="button" title="Edit link"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg></button><button class="markdown-link-popover-btn" id="link-popover-open" type="button" title="Open link"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg></button>`;
483
+ linkPopover.hidden = false;
484
+ linkPopover.querySelector('#link-popover-open')?.addEventListener('click', (e) => {
485
+ e.preventDefault();
486
+ e.stopPropagation();
487
+ linkPopover.hidden = true;
488
+ anchor.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
489
+ }, { once: true });
490
+ linkPopover.querySelector('#link-popover-edit')?.addEventListener('click', (e) => {
491
+ e.preventDefault();
492
+ e.stopPropagation();
493
+ linkPopover.hidden = true;
494
+ if (!linkModal) {
495
+ return;
496
+ }
497
+ const pos = tiptap.view.posAtDOM(anchor, 0);
498
+ if (pos >= 0) {
499
+ const endPos = pos + (anchor.textContent?.length ?? 0);
500
+ tiptap.chain().focus().setTextSelection({ from: pos, to: endPos }).run();
501
+ }
502
+ const label = anchor.textContent?.trim() ?? '';
503
+ linkModal.removeAttribute('hidden');
504
+ updateLinkMode('url');
505
+ if (linkInput) {
506
+ linkInput.value = href;
507
+ }
508
+ if (linkLabelInput) {
509
+ linkLabelInput.value = label;
510
+ }
511
+ }, { once: true });
512
+ const rect = anchor.getBoundingClientRect();
513
+ const parent = editorDom.parentElement;
514
+ if (!parent) {
515
+ return;
516
+ }
517
+ const parentRect = parent.getBoundingClientRect();
518
+ linkPopover.style.left = `${Math.max(4, rect.left - parentRect.left)}px`;
519
+ linkPopover.style.top = `${rect.bottom - parentRect.top + 4}px`;
520
+ };
521
+ const hideLinkPopover = () => {
522
+ popoverHideTimer = setTimeout(() => {
523
+ linkPopover.hidden = true;
524
+ }, 200);
525
+ };
526
+ const handleMouseOver = (e) => {
527
+ const target = e.target?.closest?.('a[href]');
528
+ if (target && editorDom.contains(target)) {
529
+ showLinkPopover(target);
530
+ }
531
+ };
532
+ const handleMouseOut = (e) => {
533
+ const target = e.target?.closest?.('a[href]');
534
+ if (target) {
535
+ hideLinkPopover();
536
+ }
537
+ };
538
+ const handlePopoverEnter = () => {
539
+ if (popoverHideTimer) {
540
+ clearTimeout(popoverHideTimer);
541
+ popoverHideTimer = null;
542
+ }
543
+ };
544
+ const handlePopoverLeave = () => {
545
+ hideLinkPopover();
546
+ };
547
+ const handleLinkModeFileClick = () => updateLinkMode('file');
548
+ const handleLinkModeUrlClick = () => {
549
+ updateLinkMode('url');
550
+ linkInput?.focus();
551
+ };
552
+ const handleSearchInput = () => { void runLinkSearch(); };
553
+ const handleModalBackdropClick = (e) => {
554
+ if (e.target === linkModal) {
555
+ closeLinkModal();
556
+ }
557
+ };
558
+ editorDom.addEventListener('mouseover', handleMouseOver);
559
+ editorDom.addEventListener('mouseout', handleMouseOut);
560
+ linkPopover.addEventListener('mouseenter', handlePopoverEnter);
561
+ linkPopover.addEventListener('mouseleave', handlePopoverLeave);
562
+ formatButtons.forEach((button) => button.addEventListener('click', handleFormatClick));
563
+ blockStyleSelect?.addEventListener('change', handleBlockStyleChange);
564
+ linkModeFile?.addEventListener('click', handleLinkModeFileClick);
565
+ linkModeUrl?.addEventListener('click', handleLinkModeUrlClick);
566
+ linkSearchInput?.addEventListener('input', handleSearchInput);
567
+ linkApply?.addEventListener('click', handleLinkApply);
568
+ linkCancel?.addEventListener('click', closeLinkModal);
569
+ linkModal?.addEventListener('click', handleModalBackdropClick);
570
+ if (typeof options.initialScrollTop === 'number') {
571
+ editorDom.scrollTop = options.initialScrollTop;
572
+ }
573
+ renderLinkResults();
574
+ return {
575
+ destroy: () => {
576
+ editorDom.removeEventListener('mouseover', handleMouseOver);
577
+ editorDom.removeEventListener('mouseout', handleMouseOut);
578
+ linkPopover.removeEventListener('mouseenter', handlePopoverEnter);
579
+ linkPopover.removeEventListener('mouseleave', handlePopoverLeave);
580
+ formatButtons.forEach((button) => button.removeEventListener('click', handleFormatClick));
581
+ blockStyleSelect?.removeEventListener('change', handleBlockStyleChange);
582
+ linkModeFile?.removeEventListener('click', handleLinkModeFileClick);
583
+ linkModeUrl?.removeEventListener('click', handleLinkModeUrlClick);
584
+ linkSearchInput?.removeEventListener('input', handleSearchInput);
585
+ linkApply?.removeEventListener('click', handleLinkApply);
586
+ linkCancel?.removeEventListener('click', closeLinkModal);
587
+ linkModal?.removeEventListener('click', handleModalBackdropClick);
588
+ linkPopover.remove();
589
+ if (popoverHideTimer) {
590
+ clearTimeout(popoverHideTimer);
591
+ }
592
+ tiptap.destroy();
593
+ options.target.replaceChildren();
594
+ },
595
+ focus: () => {
596
+ tiptap.commands.focus();
597
+ },
598
+ getValue: () => getTiptapMarkdown(),
599
+ setValue: (value) => {
600
+ tiptap.commands.setContent(rewriteWikiLinks(value), { emitUpdate: false });
601
+ syncHeadingIds(editorDom);
602
+ },
603
+ revealLine: (_lineNumber, headingId) => {
604
+ if (headingId) {
605
+ const heading = editorDom.querySelector(`#${CSS.escape(headingId)}`);
606
+ if (heading) {
607
+ heading.scrollIntoView({ block: 'start', inline: 'nearest' });
608
+ editorDom.scrollTop = Math.max(editorDom.scrollTop - 24, 0);
609
+ heading.setAttribute('tabindex', '-1');
610
+ heading.focus({ preventScroll: true });
611
+ return;
612
+ }
613
+ }
614
+ tiptap.commands.focus();
615
+ },
616
+ setScrollTop: (scrollTop) => {
617
+ editorDom.scrollTop = Math.max(0, scrollTop);
618
+ },
619
+ };
620
+ }
621
+ const textarea = document.createElement('textarea');
622
+ textarea.className = 'markdown-editor-textarea markdown-editor-textarea--raw';
623
+ textarea.spellcheck = false;
624
+ textarea.setAttribute('autocomplete', 'off');
625
+ textarea.setAttribute('autocorrect', 'off');
626
+ textarea.setAttribute('autocapitalize', 'off');
627
+ textarea.placeholder = 'Edit raw markdown...';
628
+ textarea.value = options.value;
629
+ options.target.replaceChildren(textarea);
630
+ const autosize = () => {
631
+ textarea.style.height = 'auto';
632
+ textarea.style.height = `${Math.max(textarea.scrollHeight, 640)}px`;
633
+ };
634
+ const handleInput = () => {
635
+ autosize();
636
+ options.onChange(textarea.value);
637
+ };
638
+ const handleFocusOut = (event) => {
639
+ if (shouldIgnoreBlur(shell, event)) {
640
+ return;
641
+ }
642
+ options.onBlur?.();
643
+ };
644
+ const handleKeyDown = (event) => {
645
+ if (event.key !== 'Tab') {
646
+ return;
647
+ }
648
+ event.preventDefault();
649
+ applyRawTab(textarea);
650
+ autosize();
651
+ options.onChange(textarea.value);
652
+ };
653
+ textarea.addEventListener('input', handleInput);
654
+ textarea.addEventListener('keydown', handleKeyDown);
655
+ textarea.addEventListener('focusout', handleFocusOut);
656
+ autosize();
657
+ if (typeof options.initialScrollTop === 'number') {
658
+ textarea.scrollTop = options.initialScrollTop;
659
+ }
660
+ return {
661
+ destroy: () => {
662
+ textarea.removeEventListener('input', handleInput);
663
+ textarea.removeEventListener('keydown', handleKeyDown);
664
+ textarea.removeEventListener('focusout', handleFocusOut);
665
+ options.target.replaceChildren();
666
+ },
667
+ focus: () => {
668
+ textarea.focus();
669
+ },
670
+ getValue: () => textarea.value,
671
+ setValue: (value) => {
672
+ textarea.value = value;
673
+ autosize();
674
+ },
675
+ revealLine: (lineNumber) => {
676
+ const targetLine = Math.max(1, Math.floor(lineNumber));
677
+ const lines = textarea.value.split('\n');
678
+ let index = 0;
679
+ for (let currentLine = 1; currentLine < targetLine && currentLine <= lines.length; currentLine += 1) {
680
+ index += lines[currentLine - 1].length + 1;
681
+ }
682
+ textarea.focus();
683
+ textarea.setSelectionRange(index, index);
684
+ const lineHeight = Number.parseFloat(window.getComputedStyle(textarea).lineHeight || '20') || 20;
685
+ textarea.scrollTop = Math.max(0, (targetLine - 1) * lineHeight - lineHeight * 2);
686
+ },
687
+ setScrollTop: (scrollTop) => {
688
+ textarea.scrollTop = Math.max(0, scrollTop);
689
+ },
690
+ };
691
+ }