@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,233 @@
1
+ import { escapeHtml } from './components/highlighting.js';
2
+ import { buildRenderPayload, extractToolText } from './payload-utils.js';
3
+ function parseDirectoryEntries(content) {
4
+ const lines = content.split('\n');
5
+ const hintLines = [];
6
+ const entryLines = [];
7
+ for (const line of lines) {
8
+ if (/^\[(DIR|FILE|DENIED|WARNING)\]/.test(line.trim())) {
9
+ entryLines.push(line.trim());
10
+ }
11
+ else if (entryLines.length === 0) {
12
+ hintLines.push(line);
13
+ }
14
+ }
15
+ const flat = [];
16
+ for (const line of entryLines) {
17
+ if (line.startsWith('[WARNING]')) {
18
+ const warnBody = line.replace(/^\[WARNING\]\s*/, '');
19
+ const colonIdx = warnBody.indexOf(':');
20
+ const dirName = colonIdx >= 0 ? warnBody.slice(0, colonIdx).trim() : '';
21
+ const msg = colonIdx >= 0 ? warnBody.slice(colonIdx + 1).trim() : warnBody;
22
+ const parts = dirName.replace(/\\/g, '/').split('/').filter(Boolean);
23
+ flat.push({
24
+ name: dirName,
25
+ fullPath: dirName,
26
+ isDir: false,
27
+ isDenied: false,
28
+ isWarning: true,
29
+ warningText: msg,
30
+ depth: parts.length,
31
+ });
32
+ continue;
33
+ }
34
+ const isDir = line.startsWith('[DIR]');
35
+ const isDenied = line.startsWith('[DENIED]');
36
+ const name = line.replace(/^\[(DIR|FILE|DENIED)\]\s*/, '');
37
+ const parts = name.replace(/\\/g, '/').split('/');
38
+ flat.push({
39
+ name,
40
+ fullPath: name,
41
+ isDir,
42
+ isDenied,
43
+ isWarning: false,
44
+ warningText: '',
45
+ depth: parts.length - 1,
46
+ });
47
+ }
48
+ const root = [];
49
+ const stack = [root];
50
+ for (const item of flat) {
51
+ const baseName = item.fullPath.replace(/\\/g, '/').split('/').pop() ?? item.fullPath;
52
+ const entry = {
53
+ name: baseName,
54
+ isDir: item.isDir,
55
+ isDenied: item.isDenied,
56
+ isWarning: item.isWarning,
57
+ warningText: item.warningText,
58
+ children: [],
59
+ relativePath: item.fullPath,
60
+ };
61
+ while (stack.length > item.depth + 1) {
62
+ stack.pop();
63
+ }
64
+ const parent = stack[stack.length - 1];
65
+ parent.push(entry);
66
+ if (item.isDir) {
67
+ stack.push(entry.children);
68
+ }
69
+ }
70
+ return { hint: hintLines.join('\n').trim(), entries: root };
71
+ }
72
+ let dirEntryIdCounter = 0;
73
+ function renderDirTree(entries, rootPath) {
74
+ if (entries.length === 0) {
75
+ return '<div class="dir-tree"><span class="dir-empty">Empty directory</span></div>';
76
+ }
77
+ function renderEntries(items) {
78
+ return items.map((item) => {
79
+ const id = `de-${dirEntryIdCounter++}`;
80
+ const fullPath = `${rootPath}/${item.relativePath.replace(/\\/g, '/')}`;
81
+ const escapedPath = escapeHtml(fullPath);
82
+ if (item.isWarning) {
83
+ return `<div class="dir-entry"><button class="dir-row dir-row-warning dir-load-more" data-loadpath="${escapedPath}"><span class="dir-warning-icon">⚠️</span> <span class="dir-warning-text">${escapeHtml(item.warningText)} — click to load all</span></button></div>`;
84
+ }
85
+ if (item.isDenied) {
86
+ return `<div class="dir-entry"><span class="dir-icon">🚫</span> <span class="dir-name-denied">${escapeHtml(item.name)}</span></div>`;
87
+ }
88
+ if (item.isDir) {
89
+ const hasChildren = item.children.length > 0;
90
+ const chevron = `<span class="dir-chevron${hasChildren ? ' expanded' : ''}">${hasChildren ? '▼' : '▶'}</span>`;
91
+ const openButton = `<button class="dir-open-btn" data-openpath="${escapedPath}" title="Open in Finder">📂</button>`;
92
+ const childrenHtml = hasChildren ? `<div class="dir-children" id="${id}-ch">${renderEntries(item.children)}</div>` : '';
93
+ return `<div class="dir-entry-group" id="${id}"><div class="dir-row dir-row-folder" data-path="${escapedPath}" data-eid="${id}" data-loaded="${hasChildren}">${chevron} <span class="dir-icon">📁</span> <span class="dir-name">${escapeHtml(item.name)}</span>${openButton}</div>${childrenHtml}</div>`;
94
+ }
95
+ return `<div class="dir-entry"><div class="dir-row dir-row-file" data-path="${escapedPath}"><span class="file-icon">📄</span> <span class="file-name">${escapeHtml(item.name)}</span></div></div>`;
96
+ }).join('');
97
+ }
98
+ return `<div class="dir-tree">${renderEntries(entries)}</div>`;
99
+ }
100
+ export function renderDirectoryBody(content, rootPath) {
101
+ dirEntryIdCounter = 0;
102
+ const { hint, entries } = parseDirectoryEntries(content);
103
+ return {
104
+ notice: hint || undefined,
105
+ html: `<div class="panel-content directory-content">${renderDirTree(entries, rootPath)}</div>`,
106
+ };
107
+ }
108
+ export function attachDirectoryHandlers(options) {
109
+ const tree = options.container.querySelector('.dir-tree');
110
+ if (!tree) {
111
+ return;
112
+ }
113
+ tree.addEventListener('click', async (event) => {
114
+ const openBtn = event.target.closest('.dir-open-btn');
115
+ if (openBtn) {
116
+ event.stopPropagation();
117
+ const openPath = openBtn.dataset.openpath;
118
+ if (!openPath) {
119
+ return;
120
+ }
121
+ const command = options.buildOpenInFolderCommand(openPath);
122
+ if (command) {
123
+ try {
124
+ await options.callTool?.('start_process', { command, timeout_ms: 12000 });
125
+ }
126
+ catch {
127
+ // Keep UI stable if opening folder fails.
128
+ }
129
+ }
130
+ return;
131
+ }
132
+ const loadMoreBtn = event.target.closest('.dir-load-more');
133
+ if (loadMoreBtn) {
134
+ event.stopPropagation();
135
+ const loadPath = loadMoreBtn.dataset.loadpath;
136
+ if (!loadPath) {
137
+ return;
138
+ }
139
+ loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Loading…';
140
+ loadMoreBtn.disabled = true;
141
+ try {
142
+ const result = await options.callTool?.('list_directory', { path: loadPath, depth: 1 });
143
+ const text = extractToolText(result) ?? '';
144
+ if (text) {
145
+ const parsed = parseDirectoryEntries(text);
146
+ const html = renderDirTree(parsed.entries, loadPath);
147
+ const parentChildren = loadMoreBtn.closest('.dir-children');
148
+ if (parentChildren) {
149
+ const temp = document.createElement('div');
150
+ temp.innerHTML = html;
151
+ const inner = temp.querySelector('.dir-tree');
152
+ parentChildren.innerHTML = inner ? inner.innerHTML : '';
153
+ }
154
+ }
155
+ }
156
+ catch {
157
+ loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Failed to load';
158
+ loadMoreBtn.disabled = false;
159
+ }
160
+ return;
161
+ }
162
+ const target = event.target.closest('.dir-row');
163
+ if (!target) {
164
+ return;
165
+ }
166
+ const fullPath = target.dataset.path;
167
+ if (!fullPath) {
168
+ return;
169
+ }
170
+ if (target.classList.contains('dir-row-folder')) {
171
+ const entryId = target.dataset.eid;
172
+ if (!entryId) {
173
+ return;
174
+ }
175
+ const childrenEl = document.getElementById(`${entryId}-ch`);
176
+ const chevron = target.querySelector('.dir-chevron');
177
+ if (childrenEl) {
178
+ const hidden = childrenEl.classList.toggle('dir-collapsed');
179
+ chevron?.classList.toggle('expanded', !hidden);
180
+ if (chevron)
181
+ chevron.textContent = hidden ? '▶' : '▼';
182
+ return;
183
+ }
184
+ if (target.dataset.loaded === 'true') {
185
+ return;
186
+ }
187
+ if (chevron)
188
+ chevron.textContent = '⏳';
189
+ try {
190
+ const result = await options.callTool?.('list_directory', { path: fullPath, depth: 2 });
191
+ const text = extractToolText(result) ?? '';
192
+ if (text) {
193
+ target.dataset.loaded = 'true';
194
+ const parsed = parseDirectoryEntries(text);
195
+ const html = renderDirTree(parsed.entries, fullPath);
196
+ const wrapper = document.createElement('div');
197
+ wrapper.className = 'dir-children';
198
+ wrapper.id = `${entryId}-ch`;
199
+ const temp = document.createElement('div');
200
+ temp.innerHTML = html;
201
+ const inner = temp.querySelector('.dir-tree');
202
+ wrapper.innerHTML = inner ? inner.innerHTML : '<span class="dir-empty">Empty</span>';
203
+ target.parentElement?.appendChild(wrapper);
204
+ chevron?.classList.add('expanded');
205
+ if (chevron)
206
+ chevron.textContent = '▼';
207
+ }
208
+ }
209
+ catch {
210
+ if (chevron)
211
+ chevron.textContent = '⚠';
212
+ }
213
+ return;
214
+ }
215
+ if (target.classList.contains('dir-row-file')) {
216
+ target.classList.add('dir-loading');
217
+ try {
218
+ const result = await options.callTool?.('read_file', { path: fullPath });
219
+ if (!result || typeof result !== 'object' || result === null) {
220
+ return;
221
+ }
222
+ const structuredContent = result.structuredContent;
223
+ if (structuredContent && typeof structuredContent === 'object') {
224
+ const text = extractToolText(result) ?? '';
225
+ options.onOpenPayload(buildRenderPayload(structuredContent, text));
226
+ }
227
+ }
228
+ catch {
229
+ target.classList.remove('dir-loading');
230
+ }
231
+ }
232
+ });
233
+ }
@@ -0,0 +1,20 @@
1
+ import type { FileTypeCapabilities, MarkdownWorkspaceState, RenderBodyResult, RenderPayload } from './model.js';
2
+ export declare function buildDocumentLayout(options: {
3
+ payload: RenderPayload;
4
+ body: RenderBodyResult;
5
+ capabilities: FileTypeCapabilities;
6
+ fileExtension: string;
7
+ htmlMode: 'rendered' | 'source';
8
+ currentDisplayMode: string | null;
9
+ isExpanded: boolean;
10
+ hideSummaryRow: boolean;
11
+ markdownWorkspace?: MarkdownWorkspaceState;
12
+ canGoFullscreen: boolean;
13
+ isMarkdownUndoAvailable: boolean;
14
+ defaultMarkdownEditorName?: string;
15
+ markdownEditorAppIcon: string;
16
+ hasDirectoryBackButton: boolean;
17
+ }): {
18
+ html: string;
19
+ effectiveExpanded: boolean;
20
+ };
@@ -0,0 +1,109 @@
1
+ import { renderCompactRow } from '../../shared/compact-row.js';
2
+ import { escapeHtml } from '../../shared/escape-html.js';
3
+ import { parseReadRange, stripReadStatusLine } from './document-workspace.js';
4
+ import { renderMarkdownCopyButton, renderMarkdownModeToggle } from './markdown/editor.js';
5
+ import { buildBreadcrumb, countContentLines } from './payload-utils.js';
6
+ function renderCopyIcon() {
7
+ return '<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>';
8
+ }
9
+ function renderFolderIcon() {
10
+ 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="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
11
+ }
12
+ function renderUndoIcon() {
13
+ 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="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 1 1 0 10h-1"/></svg>';
14
+ }
15
+ function renderExpandIcon() {
16
+ 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="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>';
17
+ }
18
+ function renderMarkdownSaveStatus(workspace) {
19
+ if (workspace.fileDeleted) {
20
+ return '<span class="panel-save-status panel-save-status--saved">File deleted</span>';
21
+ }
22
+ if (workspace.saveIndicator !== 'saved') {
23
+ return '';
24
+ }
25
+ const variant = workspace.saving ? 'saving' : 'saved';
26
+ return `<span class="panel-save-status panel-save-status--${variant}">Saved</span>`;
27
+ }
28
+ export function buildDocumentLayout(options) {
29
+ const range = parseReadRange(options.payload.content);
30
+ const notice = options.body.notice ? `<div class="notice">${options.body.notice}</div>` : '';
31
+ const breadcrumb = buildBreadcrumb(options.payload.filePath);
32
+ const lineCount = range ? range.toLine - range.fromLine + 1 : countContentLines(options.payload.content);
33
+ const fileTypeLabel = options.payload.fileType === 'markdown' ? 'MARKDOWN'
34
+ : options.payload.fileType === 'html' ? 'HTML'
35
+ : options.payload.fileType === 'image' ? 'IMAGE'
36
+ : options.payload.fileType === 'directory' ? 'DIRECTORY'
37
+ : options.fileExtension !== 'none' ? options.fileExtension.toUpperCase()
38
+ : 'TEXT';
39
+ const compactLabel = range?.isPartial
40
+ ? `View lines ${range.fromLine}–${range.toLine}`
41
+ : options.payload.fileType === 'directory' ? 'View directory'
42
+ : 'View file';
43
+ let footerLabel = range?.isPartial
44
+ ? `${fileTypeLabel} • LINES ${range.fromLine}–${range.toLine} OF ${range.totalLines}`
45
+ : `${fileTypeLabel} • ${lineCount} LINE${lineCount !== 1 ? 'S' : ''}`;
46
+ if (options.markdownWorkspace) {
47
+ const source = stripReadStatusLine(options.markdownWorkspace.draftContent);
48
+ const markdownWordCount = source.trim().split(/\s+/).filter(Boolean).length;
49
+ const markdownLineCount = countContentLines(source);
50
+ footerLabel = `${fileTypeLabel} • EDIT MODE • ${markdownLineCount} LINES • ${markdownWordCount} WORDS`;
51
+ }
52
+ const isFullscreen = options.currentDisplayMode === 'fullscreen';
53
+ const htmlToggle = options.payload.fileType === 'html'
54
+ ? `<button class="panel-action" id="toggle-html-mode">${options.htmlMode === 'rendered' ? 'Source' : 'Rendered'}</button>`
55
+ : '';
56
+ const backButton = options.hasDirectoryBackButton && options.payload.fileType !== 'directory'
57
+ ? '<button class="panel-action dir-back-btn" id="dir-back" title="Back to directory">← Back</button>'
58
+ : '';
59
+ const isMarkdown = options.payload.fileType === 'markdown';
60
+ const isMarkdownEdit = isMarkdown && !!options.markdownWorkspace;
61
+ const revertDisabled = isMarkdownEdit && (options.markdownWorkspace.fileDeleted || options.markdownWorkspace.loadingDocument || !options.isMarkdownUndoAvailable);
62
+ const fileDeleted = isMarkdownEdit && options.markdownWorkspace.fileDeleted;
63
+ const hasMissingBefore = range?.isPartial && range.fromLine > 1;
64
+ const hasMissingAfter = range?.isPartial && range.toLine < range.totalLines && (range.totalLines - range.toLine) > 1;
65
+ const loadBeforeBanner = hasMissingBefore
66
+ ? `<button class="load-lines-banner" id="load-before">↑ Load lines 1–${range.fromLine - 1}</button>`
67
+ : '';
68
+ const loadAfterBanner = hasMissingAfter
69
+ ? `<button class="load-lines-banner" id="load-after">↓ Load lines ${range.toLine + 1}–${range.totalLines}</button>`
70
+ : '';
71
+ const effectiveExpanded = options.isExpanded || isFullscreen;
72
+ const canOpenInFolder = options.capabilities.canOpenInFolder;
73
+ const canCopy = options.capabilities.canCopy;
74
+ return {
75
+ effectiveExpanded,
76
+ html: `
77
+ <main id="tool-shell" class="shell tool-shell ${effectiveExpanded ? 'expanded' : 'collapsed'}${options.hideSummaryRow ? ' host-framed' : ''}${isFullscreen ? ' fullscreen' : ''}">
78
+ ${isFullscreen ? '' : renderCompactRow({ id: 'compact-toggle', label: compactLabel, filename: options.payload.fileName, variant: 'ready', expandable: true, expanded: options.isExpanded, interactive: true })}
79
+ <section class="panel">
80
+ <div class="panel-topbar">
81
+ ${backButton}
82
+ ${options.hideSummaryRow ? '' : `<span class="panel-breadcrumb" title="${escapeHtml(options.payload.filePath)}">${breadcrumb}</span>`}
83
+ <span class="panel-topbar-actions">
84
+ ${isMarkdownEdit ? renderMarkdownSaveStatus(options.markdownWorkspace) : ''}
85
+ ${htmlToggle}
86
+ ${isMarkdownEdit && isFullscreen ? renderMarkdownModeToggle(options.markdownWorkspace.editorView) : ''}
87
+ ${isMarkdown && !isFullscreen && options.canGoFullscreen ? `<button class="panel-action" id="expand-fullscreen" title="Expand" aria-label="Expand">${renderExpandIcon()}</button>` : ''}
88
+ ${isMarkdownEdit ? `<button class="panel-action" id="revert-markdown" ${isFullscreen ? '' : 'title="Undo" aria-label="Undo" '}${revertDisabled ? 'disabled' : ''}>${renderUndoIcon()}${isFullscreen ? ' Undo' : ''}</button>` : ''}
89
+ ${isMarkdownEdit && isFullscreen ? renderMarkdownCopyButton() : ''}
90
+ ${isMarkdown && !isFullscreen ? `<button class="panel-action" id="copy-active-markdown" title="Copy" aria-label="Copy">${renderCopyIcon()}</button>` : ''}
91
+ ${canCopy && options.capabilities.supportsPreview && !isMarkdown ? `<button class="panel-action" id="copy-source" title="Copy source" aria-label="Copy source">${renderCopyIcon()}</button>` : ''}
92
+ ${canOpenInFolder && isMarkdownEdit && isFullscreen ? `<button class="panel-action" id="open-in-editor" ${fileDeleted ? 'disabled' : ''}>${options.markdownEditorAppIcon} Open in ${escapeHtml(options.defaultMarkdownEditorName ?? 'editor')}</button>` : ''}
93
+ ${canOpenInFolder && !(isMarkdownEdit && isFullscreen) ? `<button class="panel-action" id="open-in-folder" title="Open in folder" aria-label="Open in folder" ${isMarkdownEdit && fileDeleted ? 'disabled' : ''}>${renderFolderIcon()}</button>` : ''}
94
+ </span>
95
+ </div>
96
+ ${notice}
97
+ <div class="panel-content-wrapper">
98
+ ${loadBeforeBanner}
99
+ ${options.body.html}
100
+ ${loadAfterBanner}
101
+ </div>
102
+ <div class="panel-footer">
103
+ <span>${footerLabel}</span>
104
+ </div>
105
+ </section>
106
+ </main>
107
+ `,
108
+ };
109
+ }
@@ -0,0 +1,17 @@
1
+ export interface DocumentOutlineItem {
2
+ id: string;
3
+ text: string;
4
+ level: number;
5
+ line?: number;
6
+ }
7
+ export interface DocumentOutlineHandle {
8
+ dispose: () => void;
9
+ refresh: (outline: DocumentOutlineItem[], activeHeadingId?: string | null) => void;
10
+ }
11
+ export declare function renderDocumentOutline(outline: DocumentOutlineItem[], activeHeadingId?: string | null): string;
12
+ export declare function attachDocumentOutline(options: {
13
+ shell: HTMLElement;
14
+ outline: DocumentOutlineItem[];
15
+ scrollContainer: HTMLElement;
16
+ onSelect: (headingId: string) => void;
17
+ }): DocumentOutlineHandle | null;
@@ -0,0 +1,97 @@
1
+ import { escapeHtml } from '../../shared/escape-html.js';
2
+ function setActiveItem(nav, activeId) {
3
+ const buttons = Array.from(nav.querySelectorAll('[data-toc-id]'));
4
+ buttons.forEach((button) => {
5
+ const isActive = button.dataset.tocId === activeId;
6
+ button.classList.toggle('is-active', isActive);
7
+ button.setAttribute('aria-current', isActive ? 'location' : 'false');
8
+ });
9
+ }
10
+ function renderDocumentOutlineItems(outline, activeHeadingId) {
11
+ return outline.map((item) => {
12
+ const activeClass = item.id === activeHeadingId ? ' is-active' : '';
13
+ return `<button class="document-outline-link markdown-toc-link${activeClass}" type="button" data-toc-id="${escapeHtml(item.id)}" data-level="${item.level}" aria-current="${item.id === activeHeadingId ? 'location' : 'false'}">${escapeHtml(item.text)}</button>`;
14
+ }).join('');
15
+ }
16
+ function renderCollapseIcon() {
17
+ return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>';
18
+ }
19
+ function renderExpandIcon() {
20
+ return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
21
+ }
22
+ export function renderDocumentOutline(outline, activeHeadingId) {
23
+ if (outline.length === 0) {
24
+ return '';
25
+ }
26
+ return `
27
+ <aside class="document-outline-shell markdown-toc-shell" aria-label="Table of contents">
28
+ <div class="document-outline-header markdown-toc-header">
29
+ <span class="document-outline-title markdown-toc-title">Contents</span>
30
+ <button class="document-outline-toggle" id="toc-toggle" type="button" title="Collapse sidebar" aria-label="Collapse sidebar">${renderCollapseIcon()}</button>
31
+ </div>
32
+ <nav class="document-outline-nav markdown-toc-nav">${renderDocumentOutlineItems(outline, activeHeadingId)}</nav>
33
+ </aside>
34
+ `;
35
+ }
36
+ export function attachDocumentOutline(options) {
37
+ const nav = options.shell.querySelector('.document-outline-nav');
38
+ if (!nav) {
39
+ return null;
40
+ }
41
+ let currentOutline = options.outline;
42
+ const handleClick = (event) => {
43
+ const target = event.target;
44
+ const button = target?.closest('[data-toc-id]');
45
+ const headingId = button?.dataset.tocId;
46
+ if (!headingId) {
47
+ return;
48
+ }
49
+ options.onSelect(headingId);
50
+ setActiveItem(nav, headingId);
51
+ };
52
+ const updateActiveHeading = () => {
53
+ const headings = currentOutline
54
+ .map((item) => {
55
+ const element = document.getElementById(item.id);
56
+ return element ? { item, element } : null;
57
+ })
58
+ .filter((entry) => entry !== null);
59
+ if (headings.length === 0) {
60
+ return;
61
+ }
62
+ const scrollTop = options.scrollContainer.scrollTop;
63
+ const nextActive = headings.reduce((activeId, current) => {
64
+ if (current.element.offsetTop - scrollTop <= 96) {
65
+ return current.item.id;
66
+ }
67
+ return activeId;
68
+ }, headings[0].item.id);
69
+ setActiveItem(nav, nextActive);
70
+ };
71
+ const toggleButton = options.shell.querySelector('#toc-toggle');
72
+ const handleToggle = () => {
73
+ const isCollapsed = options.shell.classList.toggle('markdown-toc-collapsed');
74
+ if (toggleButton) {
75
+ toggleButton.innerHTML = isCollapsed ? renderExpandIcon() : renderCollapseIcon();
76
+ toggleButton.title = isCollapsed ? 'Expand sidebar' : 'Collapse sidebar';
77
+ toggleButton.setAttribute('aria-label', isCollapsed ? 'Expand sidebar' : 'Collapse sidebar');
78
+ }
79
+ };
80
+ toggleButton?.addEventListener('click', handleToggle);
81
+ nav.addEventListener('click', handleClick);
82
+ options.scrollContainer.addEventListener('scroll', updateActiveHeading, { passive: true });
83
+ updateActiveHeading();
84
+ return {
85
+ dispose: () => {
86
+ nav.removeEventListener('click', handleClick);
87
+ options.scrollContainer.removeEventListener('scroll', updateActiveHeading);
88
+ toggleButton?.removeEventListener('click', handleToggle);
89
+ },
90
+ refresh: (outline, activeHeadingId) => {
91
+ currentOutline = outline;
92
+ nav.innerHTML = renderDocumentOutlineItems(currentOutline, activeHeadingId);
93
+ setActiveItem(nav, activeHeadingId ?? null);
94
+ updateActiveHeading();
95
+ },
96
+ };
97
+ }
@@ -0,0 +1,19 @@
1
+ export interface ReadRange {
2
+ fromLine: number;
3
+ toLine: number;
4
+ totalLines: number;
5
+ isPartial: boolean;
6
+ /** 0-based offset for read_file calls. "from start" → 0, "from line N" → N. */
7
+ readOffset: number;
8
+ }
9
+ export declare function stripReadStatusLine(content: string): string;
10
+ export declare function parseReadRange(content: string): ReadRange | undefined;
11
+ export declare function getDocumentFullscreenAvailability(options: {
12
+ availableDisplayModes?: string[];
13
+ }): {
14
+ canFullscreen: true;
15
+ } | {
16
+ canFullscreen: false;
17
+ reason: string;
18
+ };
19
+ export declare function shouldAutoLoadDocumentOnEnterFullscreen(content: string): boolean;
@@ -0,0 +1,33 @@
1
+ export function stripReadStatusLine(content) {
2
+ return content.replace(/^\[Reading [^\]]+\]\r?\n(?:\r?\n)?/, '');
3
+ }
4
+ export function parseReadRange(content) {
5
+ const match = content.match(/^\[Reading (\d+) lines from (?:line )?(\d+|start) \(total: (\d+) lines/);
6
+ if (!match) {
7
+ return undefined;
8
+ }
9
+ const count = Number.parseInt(match[1], 10);
10
+ const isFromStart = match[2] === 'start';
11
+ const readOffset = isFromStart ? 0 : Number.parseInt(match[2], 10);
12
+ const fromLine = isFromStart ? 1 : readOffset;
13
+ const totalLines = Number.parseInt(match[3], 10);
14
+ return {
15
+ fromLine,
16
+ toLine: fromLine + count - 1,
17
+ totalLines,
18
+ isPartial: count < totalLines,
19
+ readOffset,
20
+ };
21
+ }
22
+ export function getDocumentFullscreenAvailability(options) {
23
+ if (!options.availableDisplayModes?.includes('fullscreen')) {
24
+ return {
25
+ canFullscreen: false,
26
+ reason: 'Fullscreen editing is unavailable in this host.',
27
+ };
28
+ }
29
+ return { canFullscreen: true };
30
+ }
31
+ export function shouldAutoLoadDocumentOnEnterFullscreen(content) {
32
+ return parseReadRange(content)?.isPartial === true;
33
+ }
@@ -0,0 +1,10 @@
1
+ import type { FileTypeCapabilities, RenderBodyResult, RenderPayload } from './model.js';
2
+ import type { MarkdownController } from './markdown/controller.js';
3
+ import type { HtmlPreviewMode } from './types.js';
4
+ export declare function getFileTypeCapabilities(payload: RenderPayload): FileTypeCapabilities;
5
+ export declare function renderPayloadBody(options: {
6
+ payload: RenderPayload;
7
+ htmlMode: HtmlPreviewMode;
8
+ startLine: number;
9
+ markdownController: MarkdownController;
10
+ }): RenderBodyResult;
@@ -0,0 +1,98 @@
1
+ import { formatJsonIfPossible, inferLanguageFromPath, renderCodeViewer } from './components/code-viewer.js';
2
+ import { escapeHtml } from './components/highlighting.js';
3
+ import { renderHtmlPreview } from './components/html-renderer.js';
4
+ import { renderDirectoryBody } from './directory-controller.js';
5
+ import { stripReadStatusLine } from './document-workspace.js';
6
+ import { isAllowedImageMimeType, normalizeImageMimeType } from './image-preview.js';
7
+ import { isLikelyUrl } from './payload-utils.js';
8
+ function renderRawFallback(source) {
9
+ return `<pre class="code-viewer"><code class="hljs language-text">${escapeHtml(source)}</code></pre>`;
10
+ }
11
+ function renderImageBody(payload) {
12
+ const mimeType = normalizeImageMimeType(payload.mimeType);
13
+ if (!isAllowedImageMimeType(mimeType)) {
14
+ return {
15
+ notice: 'Preview is unavailable for this image format.',
16
+ html: '<div class="panel-content source-content"></div>',
17
+ };
18
+ }
19
+ if (!payload.imageData || payload.imageData.trim().length === 0) {
20
+ return {
21
+ notice: 'Preview is unavailable because image data is missing.',
22
+ html: '<div class="panel-content source-content"></div>',
23
+ };
24
+ }
25
+ const src = `data:${mimeType};base64,${payload.imageData}`;
26
+ return {
27
+ html: `<div class="panel-content image-content"><div class="image-preview"><img src="${escapeHtml(src)}" alt="${escapeHtml(payload.fileName)}" loading="eager" decoding="async"></div></div>`,
28
+ };
29
+ }
30
+ function buildPreviewCapabilities(payload, canCopy) {
31
+ return {
32
+ supportsPreview: true,
33
+ canCopy,
34
+ canOpenInFolder: !isLikelyUrl(payload.filePath),
35
+ };
36
+ }
37
+ const handlerRegistry = {
38
+ directory: {
39
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
40
+ renderBody: ({ payload }) => renderDirectoryBody(stripReadStatusLine(payload.content), payload.filePath),
41
+ },
42
+ html: {
43
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
44
+ renderBody: ({ payload, htmlMode }) => renderHtmlPreview(stripReadStatusLine(payload.content), htmlMode),
45
+ },
46
+ image: {
47
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
48
+ renderBody: ({ payload }) => renderImageBody(payload),
49
+ },
50
+ markdown: {
51
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
52
+ renderBody: ({ payload, markdownController }) => {
53
+ try {
54
+ return markdownController.buildBody(payload);
55
+ }
56
+ catch {
57
+ return {
58
+ notice: 'Markdown renderer failed. Showing raw source instead.',
59
+ html: `<div class="panel-content source-content">${renderRawFallback(stripReadStatusLine(payload.content))}</div>`,
60
+ };
61
+ }
62
+ },
63
+ },
64
+ text: {
65
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
66
+ renderBody: ({ payload, startLine }) => {
67
+ const cleanedContent = stripReadStatusLine(payload.content);
68
+ const detectedLanguage = inferLanguageFromPath(payload.filePath);
69
+ const formatted = formatJsonIfPossible(cleanedContent, payload.filePath);
70
+ return {
71
+ notice: formatted.notice,
72
+ html: `<div class="panel-content source-content">${renderCodeViewer(formatted.content, detectedLanguage, startLine)}</div>`,
73
+ };
74
+ },
75
+ },
76
+ unsupported: {
77
+ getCapabilities: () => ({
78
+ supportsPreview: false,
79
+ canCopy: false,
80
+ canOpenInFolder: true,
81
+ }),
82
+ renderBody: () => ({
83
+ notice: 'Preview is not available for this file type.',
84
+ html: '<div class="panel-content source-content"></div>',
85
+ }),
86
+ },
87
+ };
88
+ export function getFileTypeCapabilities(payload) {
89
+ return handlerRegistry[payload.fileType]?.getCapabilities(payload) ?? {
90
+ supportsPreview: false,
91
+ canCopy: false,
92
+ canOpenInFolder: !isLikelyUrl(payload.filePath),
93
+ };
94
+ }
95
+ export function renderPayloadBody(options) {
96
+ const handler = handlerRegistry[options.payload.fileType] ?? handlerRegistry.text;
97
+ return handler.renderBody(options);
98
+ }