@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
@@ -1,4 +1,4 @@
1
- export type PreviewFileType = 'markdown' | 'text' | 'html' | 'image' | 'unsupported';
1
+ export type PreviewFileType = 'markdown' | 'text' | 'html' | 'image' | 'directory' | 'unsupported';
2
2
  export declare const MARKDOWN_PREVIEW_EXTENSIONS: Set<string>;
3
3
  export declare const HTML_PREVIEW_EXTENSIONS: Set<string>;
4
4
  export declare const TEXT_PREVIEW_EXTENSIONS: Set<string>;
@@ -31,7 +31,9 @@ export const TEXT_PREVIEW_EXTENSIONS = new Set([
31
31
  '.java',
32
32
  '.go',
33
33
  '.rs',
34
- '.sql'
34
+ '.sql',
35
+ '.srt',
36
+ '.vtt'
35
37
  ]);
36
38
  const TEXT_PREVIEW_BASENAMES = new Set([
37
39
  '.env',
@@ -0,0 +1,4 @@
1
+ import type { RenderPayload } from './model.js';
2
+ import type { HtmlPreviewMode } from './types.js';
3
+ export declare function renderApp(container: HTMLElement, payload?: RenderPayload, htmlMode?: HtmlPreviewMode, expandedState?: boolean): void;
4
+ export declare function bootstrapApp(): void;
@@ -0,0 +1,564 @@
1
+ /**
2
+ * Composition root for the File Preview app. It wires host services, file-type handlers, and specialized controllers together without owning feature logic inline.
3
+ */
4
+ import { App } from '@modelcontextprotocol/ext-apps';
5
+ import { createCompactRowShellController } from '../../shared/tool-shell.js';
6
+ import { createWidgetStateStorage } from '../../shared/widget-state.js';
7
+ import { renderCompactRow } from '../../shared/compact-row.js';
8
+ import { connectWithSharedHostContext } from '../../shared/host-context.js';
9
+ import { createUiEventTracker } from '../../shared/ui-event-tracker.js';
10
+ import { attachDirectoryHandlers } from './directory-controller.js';
11
+ import { buildDocumentLayout } from './document-layout.js';
12
+ import { getDocumentFullscreenAvailability, parseReadRange, stripReadStatusLine } from './document-workspace.js';
13
+ import { getFileTypeCapabilities, renderPayloadBody } from './file-type-handlers.js';
14
+ import { buildOpenInEditorCommand, buildOpenInFolderCommand, detectDefaultMarkdownEditor, renderMarkdownEditorAppIcon } from './host/external-actions.js';
15
+ import { attachSelectionContext } from './host/selection-context.js';
16
+ import { createMarkdownController } from './markdown/controller.js';
17
+ import { createConflictDialogController, renderConflictDialogMarkup, } from './markdown/conflict-dialog.js';
18
+ import { attachPanelActions } from './panel-actions.js';
19
+ import { extractRenderPayload, extractToolText, getFileExtensionForAnalytics, isLikelyUrl, isPreviewStructuredContent } from './payload-utils.js';
20
+ let isExpanded = false;
21
+ let hideSummaryRow = false;
22
+ let previewShownFired = false;
23
+ let onRender;
24
+ let trackUiEvent;
25
+ let conflictDialogController;
26
+ let rpcCallTool;
27
+ let rpcUpdateContext;
28
+ let openExternalLink;
29
+ let requestDisplayMode;
30
+ let shellController;
31
+ let currentPayload;
32
+ let currentHtmlMode = 'rendered';
33
+ let currentHostContext;
34
+ let rerenderCurrent;
35
+ let syncPayload;
36
+ let persistPayload;
37
+ let localPayloadOverride;
38
+ let hostPayload;
39
+ let inlinePayloadBeforeFullscreen;
40
+ let directoryBackPayload;
41
+ let selectionAbortController = null;
42
+ const markdownEditorAppCache = new Map();
43
+ const markdownEditorAppPending = new Set();
44
+ async function callToolIfReady(name, args) {
45
+ return rpcCallTool ? rpcCallTool(name, args) : undefined;
46
+ }
47
+ function getAvailableDisplayModes() {
48
+ const rawModes = currentHostContext?.availableDisplayModes;
49
+ if (!Array.isArray(rawModes)) {
50
+ return [];
51
+ }
52
+ return rawModes.filter((mode) => typeof mode === 'string');
53
+ }
54
+ function getCurrentDisplayMode() {
55
+ return typeof currentHostContext?.displayMode === 'string'
56
+ ? currentHostContext.displayMode
57
+ : null;
58
+ }
59
+ function storePayloadOverride(payload) {
60
+ localPayloadOverride = payload;
61
+ currentPayload = payload;
62
+ persistPayload?.(payload);
63
+ }
64
+ function getEffectiveIncomingPayload(payload) {
65
+ if (!localPayloadOverride) {
66
+ return payload;
67
+ }
68
+ if (localPayloadOverride.filePath !== payload.filePath) {
69
+ localPayloadOverride = undefined;
70
+ return payload;
71
+ }
72
+ const incomingContent = stripReadStatusLine(payload.content);
73
+ const overriddenContent = stripReadStatusLine(localPayloadOverride.content);
74
+ if (incomingContent === overriddenContent) {
75
+ return payload;
76
+ }
77
+ return localPayloadOverride;
78
+ }
79
+ function updateSaveStatusDOM(label, statusClass) {
80
+ const existing = document.querySelector('.panel-save-status');
81
+ if (label) {
82
+ if (existing) {
83
+ existing.textContent = label;
84
+ existing.className = `panel-save-status panel-save-status--${statusClass}`;
85
+ }
86
+ else {
87
+ const actions = document.querySelector('.panel-topbar-actions');
88
+ if (actions) {
89
+ const span = document.createElement('span');
90
+ span.className = `panel-save-status panel-save-status--${statusClass}`;
91
+ span.textContent = label;
92
+ actions.prepend(span);
93
+ }
94
+ }
95
+ }
96
+ else if (existing) {
97
+ existing.remove();
98
+ }
99
+ }
100
+ const markdownController = createMarkdownController({
101
+ callTool: callToolIfReady,
102
+ openExternalLink: async (url) => (openExternalLink ? openExternalLink(url) : undefined),
103
+ requestDisplayMode: async (mode) => (requestDisplayMode ? requestDisplayMode(mode) : undefined),
104
+ getAvailableDisplayModes,
105
+ getCurrentDisplayMode,
106
+ getCurrentPayload: () => currentPayload,
107
+ setExpanded: (expanded) => {
108
+ isExpanded = expanded;
109
+ },
110
+ syncPayload: (payload) => syncPayload?.(payload),
111
+ storePayloadOverride,
112
+ rerender: () => {
113
+ rerenderCurrent?.();
114
+ },
115
+ updateSaveStatus: updateSaveStatusDOM,
116
+ trackUiEvent: (event, params) => trackUiEvent?.(event, params),
117
+ showConflictDialog: (options) => {
118
+ if (conflictDialogController) {
119
+ conflictDialogController.open(options);
120
+ return;
121
+ }
122
+ // Dialog not yet initialized (would only happen if the save failure
123
+ // somehow fires before bootstrapApp). Fall back to the cancel callback
124
+ // so the editor still shows its inline note instead of silently no-op'ing.
125
+ console.warn('[file-preview] conflictDialogController not ready; firing onCancel fallback');
126
+ options.onCancel?.();
127
+ },
128
+ });
129
+ /**
130
+ * Check if a payload needs its file content to be read.
131
+ * Tool results from edit_block/write_file include structuredContent but
132
+ * their text is a success message, not file content. Detect this by
133
+ * checking for the absence of the read status line that read_file always includes.
134
+ * URL payloads are fetched remotely by read_file(isUrl:true); we can't
135
+ * re-fetch them from here (no isUrl flag on the refresh path), so skip.
136
+ */
137
+ function needsContentRead(payload) {
138
+ if (payload.fileType === 'directory' || payload.fileType === 'image' || payload.fileType === 'unsupported') {
139
+ return false;
140
+ }
141
+ if (/^https?:\/\//i.test(payload.filePath)) {
142
+ return false;
143
+ }
144
+ return !parseReadRange(payload.content);
145
+ }
146
+ async function readAndResolvePayload(payload, onReady) {
147
+ try {
148
+ const freshPayload = await markdownController.readPayload(payload.filePath);
149
+ if (freshPayload) {
150
+ onReady(freshPayload);
151
+ if (freshPayload.fileType === 'markdown') {
152
+ void markdownController.refreshFromDisk(freshPayload);
153
+ }
154
+ return;
155
+ }
156
+ }
157
+ catch {
158
+ // Fall through to original payload.
159
+ }
160
+ onReady(payload);
161
+ }
162
+ function renderStatusState(container, message) {
163
+ container.innerHTML = `
164
+ <main class="shell">
165
+ ${renderCompactRow({ label: message, variant: 'status', interactive: false })}
166
+ </main>
167
+ `;
168
+ document.body.classList.add('dc-ready');
169
+ }
170
+ function renderLoadingState(container) {
171
+ container.innerHTML = `
172
+ <main class="shell">
173
+ ${renderCompactRow({ label: 'Preparing preview…', variant: 'loading', interactive: false })}
174
+ </main>
175
+ `;
176
+ document.body.classList.add('dc-ready');
177
+ }
178
+ export function renderApp(container, payload, htmlMode = 'rendered', expandedState = false) {
179
+ isExpanded = expandedState;
180
+ currentHtmlMode = htmlMode;
181
+ shellController?.dispose();
182
+ shellController = undefined;
183
+ if (!payload || payload.fileType !== 'markdown') {
184
+ markdownController.clear();
185
+ }
186
+ else {
187
+ markdownController.disposeHandles();
188
+ }
189
+ if (!payload) {
190
+ selectionAbortController?.abort();
191
+ selectionAbortController = null;
192
+ currentPayload = undefined;
193
+ renderStatusState(container, 'No preview available for this response.');
194
+ onRender?.();
195
+ return;
196
+ }
197
+ currentPayload = payload;
198
+ const capabilities = getFileTypeCapabilities(payload);
199
+ if (!capabilities.supportsPreview && hideSummaryRow) {
200
+ isExpanded = false;
201
+ }
202
+ const range = parseReadRange(payload.content);
203
+ const body = renderPayloadBody({
204
+ payload,
205
+ htmlMode,
206
+ startLine: range?.fromLine ?? 1,
207
+ markdownController,
208
+ });
209
+ const markdownWorkspace = payload.fileType === 'markdown' ? markdownController.getState(payload) : undefined;
210
+ const fileExtension = getFileExtensionForAnalytics(payload.filePath);
211
+ const isFullscreen = getCurrentDisplayMode() === 'fullscreen';
212
+ const canGoFullscreen = !isFullscreen && getDocumentFullscreenAvailability({
213
+ availableDisplayModes: getAvailableDisplayModes(),
214
+ }).canFullscreen;
215
+ const defaultMarkdownEditor = payload.fileType === 'markdown'
216
+ ? markdownEditorAppCache.get(payload.filePath)
217
+ : undefined;
218
+ if (payload.fileType === 'markdown' && !defaultMarkdownEditor) {
219
+ void detectDefaultMarkdownEditor({
220
+ filePath: payload.filePath,
221
+ editorAppCache: markdownEditorAppCache,
222
+ editorAppPending: markdownEditorAppPending,
223
+ callTool: callToolIfReady,
224
+ extractToolText,
225
+ onDetected: () => {
226
+ rerenderCurrent?.();
227
+ },
228
+ });
229
+ }
230
+ const layout = buildDocumentLayout({
231
+ payload,
232
+ body,
233
+ capabilities,
234
+ fileExtension,
235
+ htmlMode,
236
+ currentDisplayMode: getCurrentDisplayMode(),
237
+ isExpanded,
238
+ hideSummaryRow,
239
+ markdownWorkspace,
240
+ canGoFullscreen,
241
+ isMarkdownUndoAvailable: markdownWorkspace ? markdownController.isUndoAvailable(markdownWorkspace) : false,
242
+ defaultMarkdownEditorName: defaultMarkdownEditor?.appName,
243
+ markdownEditorAppIcon: renderMarkdownEditorAppIcon(),
244
+ hasDirectoryBackButton: Boolean(directoryBackPayload),
245
+ });
246
+ container.innerHTML = layout.html;
247
+ document.body.classList.add('dc-ready');
248
+ attachPanelActions({
249
+ container,
250
+ payload,
251
+ htmlMode,
252
+ getIsExpanded: () => isExpanded,
253
+ callTool: callToolIfReady,
254
+ trackUiEvent,
255
+ getFileExtensionForAnalytics,
256
+ buildOpenInFolderCommand: (filePath) => buildOpenInFolderCommand(filePath, isLikelyUrl),
257
+ buildOpenInEditorCommand: (filePath) => buildOpenInEditorCommand(filePath, isLikelyUrl, markdownEditorAppCache),
258
+ render: (nextPayload, nextHtmlMode = 'rendered', nextExpanded = isExpanded) => {
259
+ renderApp(container, nextPayload, nextHtmlMode, nextExpanded);
260
+ },
261
+ updateSaveStatus: updateSaveStatusDOM,
262
+ markdownController,
263
+ });
264
+ if (payload.fileType === 'markdown') {
265
+ markdownController.attachHandlers(payload);
266
+ }
267
+ selectionAbortController = attachSelectionContext({
268
+ payload,
269
+ isMarkdownEditing: payload.fileType === 'markdown' && !!markdownWorkspace,
270
+ updateContext: rpcUpdateContext,
271
+ trackUiEvent,
272
+ getFileExtensionForAnalytics,
273
+ previousAbortController: selectionAbortController,
274
+ });
275
+ if (payload.fileType === 'directory') {
276
+ attachDirectoryHandlers({
277
+ container,
278
+ callTool: callToolIfReady,
279
+ buildOpenInFolderCommand: (filePath) => buildOpenInFolderCommand(filePath, isLikelyUrl),
280
+ onOpenPayload: (nextPayload) => {
281
+ directoryBackPayload = payload;
282
+ renderApp(container, nextPayload, 'rendered', true);
283
+ },
284
+ });
285
+ }
286
+ const backBtn = document.getElementById('dir-back');
287
+ if (backBtn && directoryBackPayload) {
288
+ const savedPayload = directoryBackPayload;
289
+ backBtn.addEventListener('click', () => {
290
+ directoryBackPayload = undefined;
291
+ renderApp(container, savedPayload, 'rendered', true);
292
+ });
293
+ }
294
+ if (payload.fileType === 'directory') {
295
+ directoryBackPayload = undefined;
296
+ }
297
+ const compactRow = document.getElementById('compact-toggle');
298
+ shellController = createCompactRowShellController({
299
+ shell: document.getElementById('tool-shell'),
300
+ compactRow,
301
+ initialExpanded: layout.effectiveExpanded,
302
+ onToggle: (expanded) => {
303
+ isExpanded = expanded;
304
+ trackUiEvent?.(expanded ? 'expand' : 'collapse', {
305
+ file_type: payload.fileType,
306
+ file_extension: fileExtension,
307
+ });
308
+ },
309
+ onScrollAfterExpand: () => {
310
+ trackUiEvent?.('scroll_after_expand', {
311
+ file_type: payload.fileType,
312
+ file_extension: fileExtension,
313
+ });
314
+ },
315
+ onRender,
316
+ });
317
+ onRender?.();
318
+ if (!previewShownFired) {
319
+ previewShownFired = true;
320
+ trackUiEvent?.('preview_shown', {
321
+ file_type: payload.fileType,
322
+ file_extension: fileExtension,
323
+ });
324
+ }
325
+ }
326
+ export function bootstrapApp() {
327
+ const container = document.getElementById('app');
328
+ if (!container) {
329
+ return;
330
+ }
331
+ renderLoadingState(container);
332
+ // Mount the conflict dialog once at body level. It's position: fixed and
333
+ // must live outside the app container so that re-renders of the document
334
+ // body never wipe it while it's open.
335
+ if (!document.getElementById('md-conflict-modal')) {
336
+ const dialogHost = document.createElement('div');
337
+ dialogHost.innerHTML = renderConflictDialogMarkup();
338
+ const dialogRoot = dialogHost.firstElementChild;
339
+ if (dialogRoot) {
340
+ document.body.appendChild(dialogRoot);
341
+ }
342
+ }
343
+ conflictDialogController = createConflictDialogController({ container: document });
344
+ const app = new App({ name: 'Desktop Commander File Preview', version: '1.0.0' }, { updateModelContext: { text: {} } }, { autoResize: true });
345
+ const chrome = {
346
+ expanded: isExpanded,
347
+ hideSummaryRow,
348
+ };
349
+ const syncChromeState = () => {
350
+ isExpanded = chrome.expanded;
351
+ hideSummaryRow = chrome.hideSummaryRow;
352
+ };
353
+ const widgetState = createWidgetStateStorage((value) => isPreviewStructuredContent(value) && typeof value.content === 'string');
354
+ const renderAndSync = (payload) => {
355
+ if (payload) {
356
+ widgetState.write(payload);
357
+ }
358
+ renderApp(container, payload, 'rendered', isExpanded);
359
+ };
360
+ const syncFromPersistedWidgetState = () => {
361
+ const persistedPayload = widgetState.read();
362
+ if (!persistedPayload) {
363
+ return;
364
+ }
365
+ if (currentPayload
366
+ && currentPayload.filePath === persistedPayload.filePath
367
+ && stripReadStatusLine(currentPayload.content) === stripReadStatusLine(persistedPayload.content)) {
368
+ return;
369
+ }
370
+ renderAndSync(persistedPayload);
371
+ };
372
+ syncPayload = renderAndSync;
373
+ persistPayload = (payload) => {
374
+ widgetState.write(payload);
375
+ };
376
+ rerenderCurrent = () => {
377
+ renderApp(container, currentPayload, currentHtmlMode, isExpanded);
378
+ };
379
+ let pendingCachedPayload;
380
+ let initialStateResolved = false;
381
+ const resolveInitialState = (payload, message) => {
382
+ if (initialStateResolved) {
383
+ return;
384
+ }
385
+ initialStateResolved = true;
386
+ if (payload) {
387
+ hostPayload = payload;
388
+ renderAndSync(payload);
389
+ if (payload.fileType === 'markdown' && getCurrentDisplayMode() === 'fullscreen') {
390
+ void markdownController.requestEditMode(payload);
391
+ }
392
+ if (payload.fileType === 'markdown') {
393
+ void markdownController.refreshFromDisk(payload);
394
+ }
395
+ return;
396
+ }
397
+ renderStatusState(container, message ?? 'No preview available for this response.');
398
+ onRender?.();
399
+ };
400
+ onRender = () => { };
401
+ rpcCallTool = (name, args) => (app.callServerTool({ name, arguments: args }));
402
+ rpcUpdateContext = (text) => {
403
+ const params = text
404
+ ? { content: [{ type: 'text', text }] }
405
+ : { content: [] };
406
+ app.updateModelContext(params).catch(() => {
407
+ // Host may not support updateModelContext.
408
+ });
409
+ };
410
+ openExternalLink = async (url) => {
411
+ const result = await app.openLink({ url });
412
+ return result.isError !== true;
413
+ };
414
+ requestDisplayMode = async (mode) => {
415
+ const result = await app.requestDisplayMode({ mode });
416
+ return typeof result.mode === 'string' ? result.mode : null;
417
+ };
418
+ trackUiEvent = createUiEventTracker((name, args) => app.callServerTool({ name, arguments: args }), {
419
+ component: 'file_preview',
420
+ baseParams: { tool_name: 'read_file' },
421
+ });
422
+ app.ontoolinput = (params) => {
423
+ const requestedPath = typeof params.arguments?.path === 'string' ? params.arguments.path : undefined;
424
+ if (!initialStateResolved
425
+ && pendingCachedPayload
426
+ && requestedPath
427
+ && pendingCachedPayload.filePath === requestedPath) {
428
+ const cached = pendingCachedPayload;
429
+ pendingCachedPayload = undefined;
430
+ resolveInitialState(cached);
431
+ return;
432
+ }
433
+ renderLoadingState(container);
434
+ onRender?.();
435
+ };
436
+ app.ontoolresult = (result) => {
437
+ pendingCachedPayload = undefined;
438
+ const payload = extractRenderPayload(result);
439
+ const message = extractToolText(result);
440
+ if (!initialStateResolved) {
441
+ if (payload) {
442
+ if (needsContentRead(payload)) {
443
+ void readAndResolvePayload(payload, (p) => resolveInitialState(getEffectiveIncomingPayload(p)));
444
+ return;
445
+ }
446
+ resolveInitialState(getEffectiveIncomingPayload(payload));
447
+ return;
448
+ }
449
+ if (message) {
450
+ resolveInitialState(undefined, message);
451
+ }
452
+ return;
453
+ }
454
+ if (payload) {
455
+ if (needsContentRead(payload)) {
456
+ renderLoadingState(container);
457
+ void readAndResolvePayload(payload, (p) => renderAndSync(getEffectiveIncomingPayload(p)));
458
+ }
459
+ else {
460
+ renderAndSync(getEffectiveIncomingPayload(payload));
461
+ }
462
+ }
463
+ else if (message) {
464
+ renderStatusState(container, message);
465
+ onRender?.();
466
+ }
467
+ };
468
+ app.ontoolcancelled = (params) => {
469
+ resolveInitialState(undefined, params.reason ?? 'Tool was cancelled.');
470
+ };
471
+ const handleVisibilitySync = () => {
472
+ if (document.visibilityState === 'visible') {
473
+ syncFromPersistedWidgetState();
474
+ }
475
+ };
476
+ const handleFocusSync = () => {
477
+ // Only sync cross-tab state if the page was hidden (tab switch).
478
+ // Simple focus changes within the same page should not trigger a re-render
479
+ // as it destroys the active editor.
480
+ if (document.visibilityState !== 'visible') {
481
+ syncFromPersistedWidgetState();
482
+ }
483
+ };
484
+ const teardown = () => {
485
+ shellController?.dispose();
486
+ shellController = undefined;
487
+ markdownController.disposeHandles();
488
+ selectionAbortController?.abort();
489
+ selectionAbortController = null;
490
+ document.removeEventListener('visibilitychange', handleVisibilitySync);
491
+ window.removeEventListener('focus', handleFocusSync);
492
+ };
493
+ document.addEventListener('visibilitychange', handleVisibilitySync);
494
+ window.addEventListener('focus', handleFocusSync);
495
+ app.onteardown = async () => {
496
+ teardown();
497
+ return {};
498
+ };
499
+ void connectWithSharedHostContext({
500
+ app,
501
+ chrome,
502
+ onContextApplied: () => {
503
+ const previousDisplayMode = getCurrentDisplayMode();
504
+ syncChromeState();
505
+ currentHostContext = app.getHostContext();
506
+ const nextDisplayMode = getCurrentDisplayMode();
507
+ const displayModeChanged = previousDisplayMode !== nextDisplayMode;
508
+ // Clicking a display-mode button blurs the editor first, and the
509
+ // editor's onBlur handler already persists dirty drafts, so there
510
+ // is nothing additional to save here.
511
+ if (previousDisplayMode === 'fullscreen'
512
+ && nextDisplayMode === 'inline'
513
+ && currentPayload?.fileType === 'markdown') {
514
+ isExpanded = true;
515
+ chrome.expanded = true;
516
+ const restorePayload = inlinePayloadBeforeFullscreen ?? hostPayload;
517
+ const restoreWasPartial = restorePayload ? parseReadRange(restorePayload.content)?.isPartial === true : false;
518
+ if (restoreWasPartial && restorePayload) {
519
+ localPayloadOverride = restorePayload;
520
+ currentPayload = restorePayload;
521
+ widgetState.write(restorePayload);
522
+ void markdownController.handleInlineExitFromFullscreen(restorePayload).then((freshPayload) => {
523
+ if (freshPayload) {
524
+ currentPayload = freshPayload;
525
+ localPayloadOverride = freshPayload;
526
+ widgetState.write(freshPayload);
527
+ rerenderCurrent?.();
528
+ }
529
+ });
530
+ }
531
+ else {
532
+ void markdownController.handleInlineExitFromFullscreen();
533
+ }
534
+ inlinePayloadBeforeFullscreen = undefined;
535
+ }
536
+ if (previousDisplayMode !== 'fullscreen'
537
+ && nextDisplayMode === 'fullscreen'
538
+ && currentPayload?.fileType === 'markdown') {
539
+ inlinePayloadBeforeFullscreen = currentPayload;
540
+ if (parseReadRange(currentPayload.content)?.isPartial) {
541
+ void markdownController.requestEditMode(currentPayload);
542
+ }
543
+ }
544
+ if (initialStateResolved && displayModeChanged) {
545
+ rerenderCurrent?.();
546
+ }
547
+ },
548
+ onConnected: () => {
549
+ currentHostContext = app.getHostContext();
550
+ pendingCachedPayload = widgetState.read() ?? undefined;
551
+ window.setTimeout(() => {
552
+ if (!initialStateResolved) {
553
+ resolveInitialState(undefined, 'Preview unavailable after page refresh. Switch threads or re-run the tool.');
554
+ }
555
+ }, 8000);
556
+ },
557
+ }).catch(() => {
558
+ renderStatusState(container, 'Failed to connect to host.');
559
+ onRender?.();
560
+ });
561
+ window.addEventListener('beforeunload', () => {
562
+ teardown();
563
+ }, { once: true });
564
+ }
@@ -0,0 +1,6 @@
1
+ export declare function inferLanguageFromPath(filePath: string): string;
2
+ export declare function formatJsonIfPossible(content: string, filePath: string): {
3
+ content: string;
4
+ notice?: string;
5
+ };
6
+ export declare function renderCodeViewer(code: string, language?: string): string;
@@ -0,0 +1,60 @@
1
+ import { highlightSource } from './highlighting.js';
2
+ const EXTENSION_LANGUAGE_MAP = {
3
+ js: 'javascript',
4
+ cjs: 'javascript',
5
+ mjs: 'javascript',
6
+ ts: 'typescript',
7
+ jsx: 'javascript',
8
+ tsx: 'typescript',
9
+ json: 'json',
10
+ yaml: 'yaml',
11
+ yml: 'yaml',
12
+ toml: 'toml',
13
+ ini: 'ini',
14
+ xml: 'xml',
15
+ html: 'html',
16
+ htm: 'html',
17
+ css: 'css',
18
+ scss: 'css',
19
+ less: 'css',
20
+ sh: 'bash',
21
+ bash: 'bash',
22
+ zsh: 'bash',
23
+ py: 'python',
24
+ rb: 'ruby',
25
+ java: 'java',
26
+ go: 'go',
27
+ rs: 'rust',
28
+ sql: 'sql',
29
+ md: 'markdown',
30
+ markdown: 'markdown'
31
+ };
32
+ function getFileExtension(filePath) {
33
+ const match = filePath.toLowerCase().match(/\.([a-z0-9]+)$/);
34
+ return match ? match[1] : '';
35
+ }
36
+ export function inferLanguageFromPath(filePath) {
37
+ const extension = getFileExtension(filePath);
38
+ return EXTENSION_LANGUAGE_MAP[extension] ?? 'text';
39
+ }
40
+ export function formatJsonIfPossible(content, filePath) {
41
+ if (inferLanguageFromPath(filePath) !== 'json') {
42
+ return { content };
43
+ }
44
+ try {
45
+ return {
46
+ content: `${JSON.stringify(JSON.parse(content), null, 2)}\n`
47
+ };
48
+ }
49
+ catch {
50
+ return {
51
+ content,
52
+ notice: 'Invalid JSON. Showing raw source.'
53
+ };
54
+ }
55
+ }
56
+ export function renderCodeViewer(code, language = 'text') {
57
+ const normalizedLanguage = language || 'text';
58
+ const highlighted = highlightSource(code, normalizedLanguage);
59
+ return `<pre class="code-viewer"><code class="hljs language-${normalizedLanguage}">${highlighted}</code></pre>`;
60
+ }
@@ -0,0 +1,8 @@
1
+ export type HtmlPreviewMode = 'rendered' | 'source';
2
+ export interface HtmlRenderOptions {
3
+ allowUnsafeScripts?: boolean;
4
+ }
5
+ export declare function renderHtmlPreview(content: string, mode: HtmlPreviewMode, options?: HtmlRenderOptions): {
6
+ html: string;
7
+ notice?: string;
8
+ };