synabun 2.0.0 → 2.0.5

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 (334) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/THIRD-PARTY-LICENSES.md +46 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +2 -2
  8. package/hooks/claude-code/pre-compact.mjs +11 -0
  9. package/hooks/claude-code/prompt-submit.mjs +60 -184
  10. package/hooks/claude-code/session-start.mjs +73 -16
  11. package/hooks/claude-code/shared.mjs +20 -0
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/lib/start-launcher.js +88 -1
  14. package/mcp-server/package-lock.json +2 -2
  15. package/mcp-server/package.json +1 -3
  16. package/neural-interface/i18n/en.json +1500 -153
  17. package/neural-interface/i18n/pt-BR.json +1498 -152
  18. package/neural-interface/lib/assistant-api.js +62 -6
  19. package/neural-interface/lib/assistant-brains/claude.js +4 -0
  20. package/neural-interface/lib/assistant-catalog.js +179 -27
  21. package/neural-interface/lib/assistant-config.js +31 -2
  22. package/neural-interface/lib/assistant-dispatch.js +62 -13
  23. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  24. package/neural-interface/lib/assistant-memory.js +24 -10
  25. package/neural-interface/lib/assistant-persona.js +6 -2
  26. package/neural-interface/lib/assistant-pricing.js +21 -6
  27. package/neural-interface/lib/assistant-runtime.js +181 -12
  28. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  29. package/neural-interface/lib/assistant-test-density.js +142 -0
  30. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  31. package/neural-interface/lib/assistant-user-context.js +908 -0
  32. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  33. package/neural-interface/lib/assistant-user-learn.js +404 -0
  34. package/neural-interface/lib/assistant-user-threads.js +226 -0
  35. package/neural-interface/lib/assistant-user-writer.js +181 -0
  36. package/neural-interface/lib/browser-background-tab.js +134 -0
  37. package/neural-interface/lib/browser-screenshot.js +678 -61
  38. package/neural-interface/lib/claude-agent-bridge.js +33 -6
  39. package/neural-interface/lib/claude-model-catalog.js +30 -2
  40. package/neural-interface/lib/claude-temporary.js +46 -7
  41. package/neural-interface/lib/cloudflared/install.js +533 -0
  42. package/neural-interface/lib/cloudflared/manager.js +545 -0
  43. package/neural-interface/lib/cloudflared/pins.js +115 -0
  44. package/neural-interface/lib/cloudflared/pins.json +63 -0
  45. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  46. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  47. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  48. package/neural-interface/lib/editor-completion.js +714 -0
  49. package/neural-interface/lib/editor-config.js +149 -0
  50. package/neural-interface/lib/editor-files-api.js +268 -0
  51. package/neural-interface/lib/editor-git-api.js +134 -0
  52. package/neural-interface/lib/file-explorer-api.js +1039 -0
  53. package/neural-interface/lib/file-explorer-system.js +355 -0
  54. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  55. package/neural-interface/lib/file-explorer-watch.js +239 -0
  56. package/neural-interface/lib/git-diff-api.js +103 -0
  57. package/neural-interface/lib/git-read.js +202 -0
  58. package/neural-interface/lib/greeting/api.js +89 -0
  59. package/neural-interface/lib/greeting/budgets.js +90 -0
  60. package/neural-interface/lib/greeting/engine.js +461 -0
  61. package/neural-interface/lib/greeting/facts.js +320 -0
  62. package/neural-interface/lib/greeting/sources.js +252 -0
  63. package/neural-interface/lib/greeting/writer.js +139 -0
  64. package/neural-interface/lib/http-guards.js +189 -13
  65. package/neural-interface/lib/machine-names.js +88 -0
  66. package/neural-interface/lib/memory-api.js +31 -7
  67. package/neural-interface/lib/native-loop-providers.js +10 -5
  68. package/neural-interface/lib/plugin-installer.js +4 -2
  69. package/neural-interface/lib/project-storage.js +5 -7
  70. package/neural-interface/lib/request-gate.js +589 -0
  71. package/neural-interface/lib/ui-blob-api.js +108 -0
  72. package/neural-interface/lib/ui-blob-store.js +68 -0
  73. package/neural-interface/package-lock.json +701 -2
  74. package/neural-interface/package.json +13 -2
  75. package/neural-interface/public/install-app.html +9 -6
  76. package/neural-interface/public/offline.html +3 -2
  77. package/neural-interface/public/onboarding.html +12 -1
  78. package/neural-interface/public/shared/agent-runtime-options.js +22 -6
  79. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  80. package/neural-interface/public/shared/assistant/asst-brain-picker.js +312 -62
  81. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  82. package/neural-interface/public/shared/assistant/asst-mascot.js +18 -58
  83. package/neural-interface/public/shared/assistant/asst-menu.js +12 -8
  84. package/neural-interface/public/shared/assistant/asst-panel.js +150 -28
  85. package/neural-interface/public/shared/assistant/asst-render.js +162 -19
  86. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  87. package/neural-interface/public/shared/assistant/asst-route.js +23 -329
  88. package/neural-interface/public/shared/assistant/asst-routes-editor.js +495 -0
  89. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  90. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  91. package/neural-interface/public/shared/assistant/asst-state.js +185 -1
  92. package/neural-interface/public/shared/assistant/asst-styles.js +158 -4
  93. package/neural-interface/public/shared/blob-store.js +111 -22
  94. package/neural-interface/public/shared/cdx/cdx-panel.js +32 -11
  95. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  96. package/neural-interface/public/shared/cdx/cdx-styles.js +36 -0
  97. package/neural-interface/public/shared/cdx/cdx-tabs.js +87 -4
  98. package/neural-interface/public/shared/constants.js +6 -1
  99. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  100. package/neural-interface/public/shared/cp/cp-styles.js +15 -0
  101. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  102. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  103. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  104. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  105. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  106. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  107. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  108. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  109. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  110. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  111. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  112. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  113. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  114. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  115. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  116. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  117. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  118. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  119. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  120. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  121. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  122. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  123. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  124. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  125. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  126. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  127. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  128. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  129. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  130. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  131. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  132. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  133. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  134. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  135. package/neural-interface/public/shared/file-links.js +339 -0
  136. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  137. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  138. package/neural-interface/public/shared/html-shell.js +160 -165
  139. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  140. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  141. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +99 -17
  142. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  143. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +5 -0
  144. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +40 -0
  145. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  146. package/neural-interface/public/shared/pwa-install-page.js +29 -1
  147. package/neural-interface/public/shared/pwa-install.css +3 -3
  148. package/neural-interface/public/shared/pwa-install.js +100 -1
  149. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  150. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  151. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  152. package/neural-interface/public/shared/settings/settings-ia.js +18 -4
  153. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  154. package/neural-interface/public/shared/start-bridge.js +238 -19
  155. package/neural-interface/public/shared/styles.css +1414 -721
  156. package/neural-interface/public/shared/synabun-mascot.js +20 -56
  157. package/neural-interface/public/shared/tunnel-view.js +167 -0
  158. package/neural-interface/public/shared/ui-claude-panel.js +157 -16
  159. package/neural-interface/public/shared/ui-detail.js +15 -0
  160. package/neural-interface/public/shared/ui-explorer.js +22 -0
  161. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  162. package/neural-interface/public/shared/ui-file-links.js +103 -0
  163. package/neural-interface/public/shared/ui-help.js +26 -0
  164. package/neural-interface/public/shared/ui-invite.js +126 -116
  165. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  166. package/neural-interface/public/shared/ui-loading.js +159 -15
  167. package/neural-interface/public/shared/ui-menubar.js +12 -30
  168. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  169. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  170. package/neural-interface/public/shared/ui-navbar.js +45 -21
  171. package/neural-interface/public/shared/ui-settings.js +455 -488
  172. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  173. package/neural-interface/public/shared/ui-sync.js +16 -0
  174. package/neural-interface/public/shared/ui-terminal.js +23 -5
  175. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  176. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  177. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  178. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  179. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  180. package/neural-interface/public/shared/worker-end.js +251 -0
  181. package/neural-interface/public/sw.js +2 -2
  182. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  183. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  184. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  185. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  186. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  187. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  188. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  189. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  190. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  191. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  192. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  193. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  194. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  195. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  196. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  197. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  198. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  199. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  200. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  201. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  202. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  203. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  204. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  205. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  206. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  207. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  208. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  209. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  210. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  211. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  212. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  213. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  214. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  215. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  216. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  217. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  218. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  219. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  220. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  221. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  222. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  223. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  224. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  225. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  226. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  227. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  228. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  229. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  230. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  231. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  232. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  233. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  234. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  235. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  236. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  237. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  238. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  239. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  240. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  241. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  242. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  243. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  244. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  245. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  246. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  247. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  248. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  249. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  250. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  251. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  252. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  253. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  254. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  255. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  256. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  257. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  258. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  259. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  260. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  261. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  262. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  263. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  264. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  265. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  266. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  267. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  268. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  269. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  270. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  271. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  272. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  273. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  274. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  275. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  276. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  277. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  278. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  279. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  280. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  281. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  282. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  283. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  284. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  285. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  286. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  287. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  288. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  289. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  290. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  291. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  292. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  293. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  294. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  295. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  296. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  297. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  298. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  299. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  300. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  301. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  302. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  303. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  304. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  305. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  306. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  307. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  308. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  309. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  310. package/neural-interface/scripts/build-vendor.mjs +78 -2
  311. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  312. package/neural-interface/server.js +873 -1028
  313. package/neural-interface/templates/rulesets/README.md +1 -1
  314. package/package.json +2 -8
  315. package/setup.js +44 -7
  316. package/benchmarks/browser-live-results.json +0 -79
  317. package/benchmarks/browser-v2-results.json +0 -258
  318. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  319. package/neural-interface/public/category-logos/claude.svg +0 -1
  320. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  321. package/neural-interface/public/category-logos/openai.svg +0 -1
  322. package/neural-interface/public/category-logos/synabun.png +0 -0
  323. package/neural-interface/public/claude.svg +0 -1
  324. package/neural-interface/public/gallery.svg +0 -6
  325. package/neural-interface/public/leonardoai.svg +0 -1
  326. package/neural-interface/public/mcp.svg +0 -4
  327. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  328. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  329. package/neural-interface/public/sessionicon.svg +0 -8
  330. package/neural-interface/public/toolbar-album.svg +0 -8
  331. package/neural-interface/public/toolbar-question.svg +0 -6
  332. package/neural-interface/public/toolbar-sessions.svg +0 -6
  333. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  334. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,244 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Code editor: theme
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // The CodeMirror theme and highlight style of the File Explorer's editor.
6
+ // Every colour is a `var(--ed-*)` declared on `.fe-editor-panel` in styles.css,
7
+ // with the values the editor had before CodeMirror, so a skin restyles the
8
+ // editor by overriding those variables. Sizes that follow a preference are
9
+ // variables too (`--ed-font-size`, `--ed-ligatures`), set on the panel by
10
+ // editor-panel.js. Takes the vendored bundle as an argument: no imports.
11
+
12
+ export const EDITOR_FONT_FAMILY = "'JetBrains Mono', 'SF Mono', 'Consolas', monospace";
13
+ /** 12px on a 20px line; the height follows the size. */
14
+ export const EDITOR_LINE_HEIGHT = '1.667';
15
+
16
+ /**
17
+ * The ten colours of the old regular-expression highlighter, mapped onto syntax tags. Kinds it never coloured
18
+ * take the nearest of them (SPEC, section 6). The highlight style is built from this table, and the minimap
19
+ * colours its blocks by it.
20
+ * @param {object} t the bundle's `tags`
21
+ * @returns {{ tag: any, color?: string, fontStyle?: string, fontWeight?: string, textDecoration?: string }[]}
22
+ */
23
+ export function highlightSpecs(t) {
24
+ return [
25
+ { tag: t.keyword, color: 'var(--ed-kw)' },
26
+ { tag: [t.modifier, t.self], color: 'var(--ed-kw)' },
27
+ { tag: [t.string, t.special(t.string), t.character, t.docString, t.attributeValue, t.regexp, t.escape, t.monospace], color: 'var(--ed-str)' },
28
+ { tag: t.comment, color: 'var(--ed-cm)', fontStyle: 'italic' },
29
+ { tag: [t.number, t.bool, t.null, t.atom, t.constant(t.name), t.unit, t.color], color: 'var(--ed-num)' },
30
+ {
31
+ tag: [t.function(t.variableName), t.function(t.propertyName), t.function(t.definition(t.variableName)),
32
+ t.className, t.typeName, t.namespace, t.labelName, t.macroName],
33
+ color: 'var(--ed-fn)',
34
+ },
35
+ { tag: [t.angleBracket, t.processingInstruction, t.contentSeparator, t.documentMeta], color: 'var(--ed-op)' },
36
+ { tag: t.tagName, color: 'var(--ed-tag)' },
37
+ { tag: [t.attributeName, t.constant(t.className), t.annotation, t.meta], color: 'var(--ed-attr)' },
38
+ { tag: [t.propertyName, t.special(t.variableName)], color: 'var(--ed-prop)' },
39
+ { tag: [t.paren, t.squareBracket, t.brace], color: 'var(--ed-br)' },
40
+ { tag: t.heading, color: 'var(--ed-kw)', fontWeight: '600' },
41
+ { tag: t.strong, fontWeight: '600' },
42
+ { tag: t.emphasis, fontStyle: 'italic' },
43
+ { tag: t.strikethrough, textDecoration: 'line-through' },
44
+ { tag: [t.link, t.url], color: 'var(--ed-prop)', textDecoration: 'underline' },
45
+ { tag: t.quote, color: 'var(--ed-str)' },
46
+ { tag: t.inserted, color: 'var(--ed-add)' },
47
+ { tag: t.deleted, color: 'var(--ed-del)' },
48
+ { tag: t.changed, color: 'var(--ed-warn)' },
49
+ { tag: t.invalid, color: 'var(--ed-error)' },
50
+ ];
51
+ }
52
+
53
+ /**
54
+ * @param {object} cm the vendored CodeMirror bundle (editor-loader.js)
55
+ * @returns {import('@codemirror/state').Extension[]}
56
+ */
57
+ export function editorTheme(cm) {
58
+ const { EditorView, HighlightStyle, syntaxHighlighting, tags: t } = cm;
59
+
60
+ const theme = EditorView.theme({
61
+ '&': {
62
+ height: '100%',
63
+ color: 'var(--ed-fg)',
64
+ backgroundColor: 'transparent',
65
+ fontSize: 'var(--ed-font-size, 12px)',
66
+ },
67
+ '&.cm-focused': { outline: 'none' },
68
+ '.cm-scroller': {
69
+ fontFamily: EDITOR_FONT_FAMILY,
70
+ lineHeight: EDITOR_LINE_HEIGHT,
71
+ overflow: 'auto',
72
+ },
73
+ '.cm-content': {
74
+ padding: '10px 0',
75
+ caretColor: 'var(--ed-caret)',
76
+ fontVariantLigatures: 'var(--ed-ligatures, normal)',
77
+ },
78
+ '.cm-line': { padding: '0 16px' },
79
+
80
+ // Gutter: line numbers, then the fold arrows. 48px in a file of up to 9,999 lines, as before.
81
+ '.cm-gutters': {
82
+ backgroundColor: 'var(--ed-gutter-bg)',
83
+ color: 'var(--ed-gutter-fg)',
84
+ border: 'none',
85
+ borderRight: '1px solid var(--ed-gutter-border)',
86
+ userSelect: 'none',
87
+ },
88
+ '.cm-lineNumbers .cm-gutterElement': { padding: '0 2px 0 6px', minWidth: '37px', textAlign: 'right' },
89
+ '.cm-foldGutter .cm-gutterElement': { width: '10px', padding: '0', textAlign: 'center', cursor: 'pointer' },
90
+ '.cm-foldGutter .cm-gutterElement span': { color: 'var(--ed-gutter-fg)' },
91
+ '.cm-foldGutter .cm-gutterElement:hover span': { color: 'var(--ed-gutter-fg-active)' },
92
+ '.cm-activeLineGutter': { backgroundColor: 'transparent', color: 'var(--ed-gutter-fg-active)' },
93
+ '.cm-activeLine': { backgroundColor: 'var(--ed-line-active)' },
94
+
95
+ // Carets and selections (drawn by CodeMirror, so several can show at once).
96
+ '.cm-cursor, .cm-dropCursor': { borderLeftColor: 'var(--ed-caret)' },
97
+ '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground': {
98
+ backgroundColor: 'var(--ed-selection)',
99
+ },
100
+ '.cm-content ::selection': { backgroundColor: 'var(--ed-selection)' },
101
+ '.cm-selectionMatch': { backgroundColor: 'var(--ed-match)' },
102
+ '.cm-searchMatch': { backgroundColor: 'var(--ed-match)', outline: 'none' },
103
+ '.cm-searchMatch.cm-searchMatch-selected': { backgroundColor: 'var(--ed-match-current)' },
104
+ '&.cm-focused .cm-matchingBracket': { backgroundColor: 'var(--ed-match)', outline: '1px solid var(--ed-gutter-fg)' },
105
+ '&.cm-focused .cm-nonmatchingBracket': { backgroundColor: 'transparent', color: 'var(--ed-error)' },
106
+ '.cm-specialChar': { color: 'var(--ed-error)' },
107
+ '.cm-foldPlaceholder': {
108
+ backgroundColor: 'var(--ed-match)',
109
+ border: 'none',
110
+ color: 'var(--ed-gutter-fg-active)',
111
+ margin: '0 2px',
112
+ padding: '0 4px',
113
+ borderRadius: '3px',
114
+ },
115
+
116
+ // An AI suggestion: upright, so it is never taken for a comment (those are italic), whatever it sits in.
117
+ '.cm-ghost': { color: 'var(--ed-ghost)', fontStyle: 'normal', fontWeight: 'normal', textDecoration: 'none' },
118
+
119
+ // A comparison with another version (editor-compare.js): the diff colours of the design, the gutter says
120
+ // which lines changed. What the other version had is not part of the document: it is drawn in the delete colour.
121
+ '&.cm-merge-b .cm-changedLine, & .cm-inlineChangedLine': { backgroundColor: 'var(--ed-add-bg)' },
122
+ '&.cm-merge-b .cm-changedText': { background: 'var(--ed-add-bg)' },
123
+ // A line that is new as a whole has the line's tint and no second layer of it (the two together took the text
124
+ // under 4.5:1). The words changed inside a modified line keep theirs: that is what tells them from the rest.
125
+ '&.cm-merge-b .cm-addedWhole .cm-changedText': { background: 'none' },
126
+ // The block of a difference (what the other version had) is what its button is placed in, and the button never
127
+ // lies over text. With wrapped lines it floats at the block's end: the rows of removed text are shorter beside
128
+ // it. The block contains the float, so a difference that only adds lines, whose block holds no removed line,
129
+ // still has a row for the button (it was a box of no height that the button hung out of, under the first added
130
+ // line: a line is positioned, and comes later). With lines that are not wrapped, text makes no room for a float
131
+ // and the block is as wide as the longest line: there the button has a row of its own, and is held at the end of
132
+ // what is in view (clear of the minimap, which is 64 px of the scroller) however far the text is scrolled.
133
+ '& .cm-deletedChunk': { position: 'relative', display: 'flow-root', backgroundColor: 'var(--ed-del-bg)', color: 'var(--ed-del)', paddingLeft: '16px' },
134
+ '& .cm-deletedChunk .cm-chunkButtons': { position: 'static', float: 'right', marginInlineEnd: '5px' },
135
+ '& .cm-content:not(.cm-lineWrapping) .cm-deletedChunk .cm-chunkButtons': { float: 'none', position: 'sticky', right: '5px', width: 'fit-content', marginInlineStart: 'auto' },
136
+ '& .cm-scroller:has(.cm-minimap) .cm-content:not(.cm-lineWrapping) .cm-deletedChunk .cm-chunkButtons': { right: '69px' },
137
+ // A block that holds the button alone took nothing away: its row is not tinted as removed text is.
138
+ '& .cm-deletedChunk:not(:has(.cm-deletedLine))': { backgroundColor: 'transparent' },
139
+ '& .cm-deletedChunk .cm-deletedText': { background: 'var(--ed-del-bg)' },
140
+ '& .cm-deletedChunk .cm-deletedLine, & .cm-deletedChunk .cm-deletedLine del, & .cm-insertedLine': { textDecoration: 'none' },
141
+ '&.cm-merge-b .cm-changedLineGutter': { background: 'var(--ed-add)' },
142
+ '& .cm-deletedLineGutter': { background: 'var(--ed-del)' },
143
+ '& .cm-collapsedLines': {
144
+ background: 'var(--ed-gutter-bg)',
145
+ color: 'var(--ed-gutter-fg-active)',
146
+ padding: '2px 16px',
147
+ fontSize: '11px',
148
+ },
149
+ '& .cm-collapsedLines:hover': { color: 'var(--ed-menu-fg-active)' },
150
+ '& .cm-collapsedLines:before, & .cm-collapsedLines:after': { content: '""', margin: '0' },
151
+
152
+ // Git markers (editor-git.js): a 4px column after the fold arrows. Added and modified lines carry a bar in
153
+ // the diff colours; where committed lines were removed, a mark sits on the edge between two lines.
154
+ '.cm-gitGutter': { width: '4px' },
155
+ '.cm-gitGutter .cm-gutterElement': { position: 'relative', padding: '0' },
156
+ '.cm-gitGutter .cm-gitLine-added': { backgroundColor: 'var(--ed-add)' },
157
+ '.cm-gitGutter .cm-gitLine-modified': { backgroundColor: 'var(--ed-warn)' },
158
+ '.cm-gitGutter .cm-gitLine-deleted::before': {
159
+ content: '""', position: 'absolute', left: '0', top: '-2px', width: '4px', height: '4px', backgroundColor: 'var(--ed-del)',
160
+ },
161
+ '.cm-gitGutter .cm-gitLine-deleted.cm-gitLine-after::before': { top: 'auto', bottom: '-2px' },
162
+
163
+ // Problems (editor-lint.js): a wavy underline, a dot in a narrow column of its own, the message in the
164
+ // editor's tooltip.
165
+ '.cm-lintRange': { backgroundImage: 'none', paddingBottom: '0' },
166
+ '.cm-lintRange-error': { textDecoration: 'underline wavy var(--ed-error)', textUnderlineOffset: '3px', textDecorationSkipInk: 'none' },
167
+ '.cm-lintRange-warning': { textDecoration: 'underline wavy var(--ed-warn)', textUnderlineOffset: '3px', textDecorationSkipInk: 'none' },
168
+ '.cm-lintRange-active': { backgroundColor: 'var(--ed-match)' },
169
+ '.cm-lintPoint:after': { borderBottomColor: 'var(--ed-error)' },
170
+ '.cm-gutter-lint': { width: '10px' },
171
+ '.cm-gutter-lint .cm-gutterElement': { padding: '0', display: 'flex', alignItems: 'center', justifyContent: 'center' },
172
+ '.cm-lint-marker': { content: 'normal', width: '6px', height: '6px', borderRadius: '50%', cursor: 'default' },
173
+ '.cm-lint-marker-error': { content: 'normal', backgroundColor: 'var(--ed-error)' },
174
+ '.cm-lint-marker-warning': { content: 'normal', backgroundColor: 'var(--ed-warn)' },
175
+ '.cm-tooltip.cm-tooltip-lint, .cm-tooltip.cm-tooltip-hover': { fontFamily: EDITOR_FONT_FAMILY, fontSize: '11px', maxWidth: '480px' },
176
+ '.cm-diagnostic': { padding: '4px 8px', marginLeft: '0', whiteSpace: 'pre-wrap', lineHeight: '1.5' },
177
+ '.cm-diagnostic-error': { borderLeft: '2px solid var(--ed-error)' },
178
+ '.cm-diagnostic-warning': { borderLeft: '2px solid var(--ed-warn)' },
179
+
180
+ // Spaces and tabs made visible (the whitespace preference): a dot, and a rule the width of the tab.
181
+ '.cm-highlightSpace': { backgroundImage: 'radial-gradient(circle at 50% 55%, var(--ed-whitespace) 20%, transparent 5%)' },
182
+ '.cm-highlightTab': {
183
+ backgroundImage: 'linear-gradient(var(--ed-whitespace), var(--ed-whitespace))',
184
+ backgroundSize: 'calc(100% - 4px) 1px',
185
+ backgroundPosition: 'center',
186
+ backgroundRepeat: 'no-repeat',
187
+ },
188
+
189
+ // The minimap (editor-minimap.js): a part of the scroller that stays in view; the text is laid out beside it.
190
+ '.cm-minimap': {
191
+ position: 'sticky',
192
+ top: '0',
193
+ right: '0',
194
+ zIndex: '3',
195
+ flexShrink: '0',
196
+ boxSizing: 'border-box',
197
+ width: '64px',
198
+ height: '100%',
199
+ overflow: 'hidden',
200
+ backgroundColor: 'var(--ed-bg)',
201
+ boxShadow: 'inset 1px 0 0 var(--ed-gutter-border)',
202
+ cursor: 'default',
203
+ userSelect: 'none',
204
+ touchAction: 'none',
205
+ },
206
+ '.cm-minimap canvas': { display: 'block', width: '100%', height: '100%' },
207
+ '.cm-minimap-box': { position: 'absolute', left: '0', right: '0', backgroundColor: 'var(--ed-minimap-box)', boxShadow: 'inset 0 0 0 1px var(--ed-minimap-edge)', pointerEvents: 'none' },
208
+ '.cm-minimap:hover .cm-minimap-box, .cm-minimap-dragging .cm-minimap-box': { backgroundColor: 'var(--ed-minimap-box-active)' },
209
+
210
+ // The find and go-to-line bars are panels: their own look is in styles.css (.fe-editor-find, .fe-editor-goto).
211
+ '.cm-panels': { backgroundColor: 'transparent', color: 'inherit' },
212
+ '.cm-panels.cm-panels-top': { borderBottom: 'none' },
213
+ '.cm-panels.cm-panels-bottom': { borderTop: 'none' },
214
+
215
+ // Completion list: the menu treatment of DESIGN.md.
216
+ '.cm-tooltip': {
217
+ backgroundColor: 'var(--ed-menu-bg)',
218
+ color: 'var(--ed-menu-fg)',
219
+ border: '1px solid var(--ed-menu-border)',
220
+ borderRadius: 'var(--ed-menu-radius, 8px)',
221
+ boxShadow: 'var(--ed-menu-shadow)',
222
+ overflow: 'hidden',
223
+ },
224
+ '.cm-tooltip.cm-tooltip-autocomplete > ul': {
225
+ fontFamily: EDITOR_FONT_FAMILY,
226
+ fontSize: '11px',
227
+ maxHeight: '14em',
228
+ padding: '4px',
229
+ },
230
+ '.cm-tooltip.cm-tooltip-autocomplete > ul > li': { padding: '2px 8px', borderRadius: '4px', lineHeight: '1.6' },
231
+ '.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
232
+ backgroundColor: 'var(--ed-menu-hover)',
233
+ color: 'var(--ed-menu-fg-active)',
234
+ },
235
+ '.cm-completionMatchedText': { textDecoration: 'none', color: 'var(--ed-menu-fg-active)', fontWeight: '600' },
236
+ '.cm-completionDetail': { color: 'var(--ed-gutter-fg-active)', fontStyle: 'normal' },
237
+ '.cm-completionIcon': { opacity: '0.5', width: '1em', paddingRight: '0.5em' },
238
+ '.cm-tooltip.cm-completionInfo': { padding: '6px 8px', fontSize: '11px', maxWidth: '360px' },
239
+ }, { dark: true });
240
+
241
+ const highlight = HighlightStyle.define(highlightSpecs(t));
242
+
243
+ return [theme, syntaxHighlighting(highlight)];
244
+ }
@@ -0,0 +1,332 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Code editor: the CodeMirror view
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // Builds the editor: one CodeMirror view for the panel, and a state for each
6
+ // document it is given (its own history, selection, folds and find bar). The
7
+ // panel keeps the state of every open tab and hands the view the one to show;
8
+ // a state that is not showing can still be changed (a language that arrives
9
+ // late, a file reloaded from disk). What can change while a document is open
10
+ // sits in a compartment: language, line wrapping, indentation, read-only, the
11
+ // editing preferences, the comparison with another text, the git markers, the
12
+ // problem check and the minimap.
13
+ // Takes the vendored bundle as an argument.
14
+
15
+ import { editorTheme } from './editor-theme.js';
16
+ import { EDITOR_COMMANDS, commandKeymap, physicalKeyHandler } from './editor-commands.js';
17
+ import { baseName, resolveLanguage } from './editor-languages.js';
18
+ import { positionAt } from './editor-doc.js';
19
+ import { editorCompletionList } from './editor-completion-list.js';
20
+
21
+ // After an edit the parser reuses, from the tree it had, only the nodes stored as trees of their own; smaller
22
+ // ones are packed into buffers and read again. With the parser's default buffer (1024) a file made of many
23
+ // small pieces, such as a stylesheet's rules, is read again from its start on every keystroke, for up to the
24
+ // 20 ms CodeMirror allows per edit. A quarter of that keeps those pieces reusable: measured on a 1 MB
25
+ // stylesheet, the parse after a keystroke went from 59 ms to 1 ms, for 4 MB more memory per MB of text.
26
+ export const PARSER_BUFFER_LENGTH = 256;
27
+
28
+ /** A language's support with its parser set up for small edits in large files. Other kinds of parser pass through. */
29
+ export function withReusableNodes(cm, support) {
30
+ const language = support?.language;
31
+ if (typeof language?.configure !== 'function' || typeof language.parser?.configure !== 'function') return support;
32
+ if (!(language.parser.bufferLength > PARSER_BUFFER_LENGTH)) return support;
33
+ return new cm.LanguageSupport(language.configure({ bufferLength: PARSER_BUFFER_LENGTH }), support.support);
34
+ }
35
+
36
+ /** What the panel offers to commands: each is called on the panel's `actions` when a command asks for it. */
37
+ export const PANEL_ACTIONS = Object.freeze([
38
+ 'save', 'toggleWordWrap', 'nextTab', 'previousTab', 'closeTab',
39
+ 'toggleMinimap', 'toggleIndentGuides', 'cycleWhitespace', 'fontLarger', 'fontSmaller', 'fontReset',
40
+ 'openPalette', 'openGoToFile', 'nextProblem', 'previousProblem', 'toggleDiff',
41
+ ]);
42
+
43
+ /**
44
+ * Spaces and tabs drawn inside the selection only. They take the classes CodeMirror's own "all whitespace"
45
+ * extension uses, so the theme styles both the same way.
46
+ */
47
+ export function selectionWhitespace(cm) {
48
+ const { Decoration, RangeSetBuilder, ViewPlugin } = cm;
49
+ const space = Decoration.mark({ class: 'cm-highlightSpace' });
50
+ const tab = Decoration.mark({ class: 'cm-highlightTab' });
51
+ const build = (view) => {
52
+ const builder = new RangeSetBuilder();
53
+ const selected = view.state.selection.ranges.filter((range) => !range.empty);
54
+ if (!selected.length) return builder.finish();
55
+ for (const visible of view.visibleRanges) {
56
+ for (const range of selected) {
57
+ const from = Math.max(range.from, visible.from);
58
+ const to = Math.min(range.to, visible.to);
59
+ if (from >= to) continue;
60
+ const text = view.state.sliceDoc(from, to);
61
+ for (let i = 0; i < text.length; i++) {
62
+ const c = text.charCodeAt(i);
63
+ if (c === 32) builder.add(from + i, from + i + 1, space);
64
+ else if (c === 9) builder.add(from + i, from + i + 1, tab);
65
+ }
66
+ }
67
+ }
68
+ return builder.finish();
69
+ };
70
+ return ViewPlugin.fromClass(class {
71
+ constructor(view) { this.decorations = build(view); }
72
+ update(update) { if (update.docChanged || update.selectionSet || update.viewportChanged) this.decorations = build(update.view); }
73
+ }, { decorations: (plugin) => plugin.decorations });
74
+ }
75
+
76
+ const FOLD_ICON = {
77
+ open: '<svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>',
78
+ closed: '<svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="9 6 15 12 9 18"/></svg>',
79
+ };
80
+
81
+ /**
82
+ * @param {object} cm the vendored CodeMirror bundle (editor-loader.js)
83
+ * @param {object} o
84
+ * @param {HTMLElement} o.parent where the editor is mounted
85
+ * @param {object} o.search what editorSearch() returned
86
+ * @param {object} [o.ai] what editorAi() returned: the suggestion extension and its commands
87
+ * @param {{ save: () => void, toggleWordWrap: () => void, nextTab?: () => void, previousTab?: () => void, closeTab?: () => void }} o.actions
88
+ * what the panel offers to commands (PANEL_ACTIONS names them all)
89
+ * @param {(key: string, params?: object) => string} o.t
90
+ * @param {(update: object) => void} [o.onUpdate] called for every view update
91
+ */
92
+ export function createEditorView(cm, { parent, search, ai = null, actions, t, onUpdate = () => {} }) {
93
+ const { Compartment, EditorState, EditorView, StateEffect, StateField, keymap } = cm;
94
+
95
+ const language = new Compartment();
96
+ const wrapping = new Compartment();
97
+ const indentation = new Compartment();
98
+ const readOnly = new Compartment();
99
+ const preferences = new Compartment();
100
+ const comparing = new Compartment();
101
+ const gitMarkers = new Compartment();
102
+ const problems = new Compartment();
103
+ const minimap = new Compartment();
104
+
105
+ const commandContext = {
106
+ cm,
107
+ actions: {
108
+ // The panel's own: looked up when a command runs, so the panel may add to them after the view exists.
109
+ ...Object.fromEntries(PANEL_ACTIONS.map((name) => [name, (...args) => actions[name]?.(...args)])),
110
+ openFind: search.openFind,
111
+ openReplace: search.openReplace,
112
+ findNext: search.findNext,
113
+ findPrevious: search.findPrevious,
114
+ openGoToLine: search.openGoToLine,
115
+ dismiss: search.dismiss,
116
+ aiAccept: ai?.accept,
117
+ aiAcceptWord: ai?.acceptWord,
118
+ aiDismiss: ai?.dismiss,
119
+ aiTrigger: ai?.trigger,
120
+ },
121
+ };
122
+ const physicalKey = physicalKeyHandler(EDITOR_COMMANDS, commandContext);
123
+
124
+ // The completion list: what the language offers, and the words of the document (in every language). While AI
125
+ // autocomplete is expected to suggest for the document, its words wait to be asked for (Ctrl-Space).
126
+ const completionList = editorCompletionList(cm, { wordsYield: () => ai?.expectsSuggestions?.() === true });
127
+
128
+ const foldMarker = (open) => {
129
+ const marker = document.createElement('span');
130
+ marker.className = open ? 'fe-editor-fold fe-editor-fold--open' : 'fe-editor-fold fe-editor-fold--closed';
131
+ marker.innerHTML = open ? FOLD_ICON.open : FOLD_ICON.closed;
132
+ marker.setAttribute('aria-label', t(open ? 'editor.fold.fold' : 'editor.fold.unfold'));
133
+ return marker;
134
+ };
135
+
136
+ // A save is an undo boundary: the first edit after it starts a step of its own, so undoing it lands on
137
+ // what was saved instead of on some point before. The mark is part of the document's state: each tab has its own.
138
+ const markSaved = StateEffect.define();
139
+ const savedBoundary = StateField.define({
140
+ create: () => false,
141
+ update(value, tr) {
142
+ if (tr.docChanged) return false;
143
+ return tr.effects.some((effect) => effect.is(markSaved)) ? true : value;
144
+ },
145
+ });
146
+ const startUndoStep = EditorState.transactionExtender.of((tr) => (
147
+ tr.docChanged && tr.startState.field(savedBoundary, false) ? { annotations: cm.isolateHistory.of('before') } : null
148
+ ));
149
+
150
+ // The same for every document.
151
+ const fixed = [
152
+ savedBoundary,
153
+ startUndoStep,
154
+ cm.lineNumbers(),
155
+ cm.highlightActiveLineGutter(),
156
+ cm.highlightSpecialChars(),
157
+ cm.history(),
158
+ cm.foldGutter({ markerDOM: foldMarker }),
159
+ cm.drawSelection(),
160
+ cm.dropCursor(),
161
+ EditorState.allowMultipleSelections.of(true),
162
+ // Alt-click adds a caret; Shift-Alt-drag selects a column (VS Code's gestures).
163
+ EditorView.clickAddsSelectionRange.of((event) => event.altKey && !event.shiftKey),
164
+ cm.rectangularSelection({ eventFilter: (event) => event.altKey && event.shiftKey && event.button === 0 }),
165
+ cm.indentOnInput(),
166
+ cm.bracketMatching(),
167
+ cm.closeBrackets(),
168
+ completionList.extension,
169
+ cm.highlightActiveLine(),
170
+ cm.highlightSelectionMatches(),
171
+ search.extension,
172
+ ai ? ai.extension : [],
173
+ editorTheme(cm),
174
+ EditorView.contentAttributes.of({ 'aria-label': t('editor.aria.content') }),
175
+ EditorView.domEventHandlers({ keydown: (event, view) => physicalKey(event, view) }),
176
+ keymap.of([
177
+ ...commandKeymap(EDITOR_COMMANDS, commandContext),
178
+ ...cm.closeBracketsKeymap,
179
+ ...cm.defaultKeymap,
180
+ ...cm.historyKeymap,
181
+ ...cm.foldKeymap,
182
+ ...cm.completionKeymap,
183
+ ]),
184
+ EditorView.updateListener.of((update) => onUpdate(update)),
185
+ ];
186
+
187
+ const wrapExtension = (on) => (on ? EditorView.lineWrapping : []);
188
+ const indentExtension = ({ unit = ' ', tabSize = 2 } = {}) => [cm.indentUnit.of(unit), EditorState.tabSize.of(tabSize)];
189
+ const readOnlyExtension = (on) => EditorState.readOnly.of(!!on);
190
+ const indentGuides = cm.indentationMarkers({
191
+ highlightActiveBlock: true,
192
+ thickness: 1,
193
+ colors: {
194
+ light: 'var(--ed-guide)', dark: 'var(--ed-guide)',
195
+ activeLight: 'var(--ed-guide-active)', activeDark: 'var(--ed-guide-active)',
196
+ },
197
+ });
198
+ const whitespace = { all: cm.highlightWhitespace(), selection: selectionWhitespace(cm) };
199
+ const preferenceExtension = (editing = {}) => [
200
+ editing.indentGuides === false ? [] : indentGuides,
201
+ whitespace[editing.renderWhitespace] || [],
202
+ ];
203
+
204
+ const stateFor = ({ text = '', indent, wrap = true, editing, locked = false, git = null, lint = null, minimap: map = null } = {}) => EditorState.create({
205
+ doc: text,
206
+ extensions: [
207
+ fixed,
208
+ language.of([]),
209
+ wrapping.of(wrapExtension(wrap)),
210
+ indentation.of(indentExtension(indent)),
211
+ readOnly.of(readOnlyExtension(locked)),
212
+ preferences.of(preferenceExtension(editing)),
213
+ comparing.of([]),
214
+ gitMarkers.of(git || []),
215
+ problems.of(lint || []),
216
+ minimap.of(map || []),
217
+ ],
218
+ });
219
+
220
+ const view = new EditorView({ state: stateFor(), parent });
221
+
222
+ // A key pressed in the editor (the text, or one of its bars) is the editor's: it does not travel on to the
223
+ // document, where the app's shortcuts and "Escape closes this" listeners wait.
224
+ for (const type of ['keydown', 'keyup', 'keypress']) {
225
+ view.dom.addEventListener(type, (event) => event.stopPropagation());
226
+ }
227
+
228
+ // A language's support, once loaded, is the same object for every tab that uses it.
229
+ const supports = new Map();
230
+
231
+ return {
232
+ view,
233
+ /** What commands are given to act with (the palette runs a command through the same ones). */
234
+ actions: commandContext.actions,
235
+
236
+ /**
237
+ * A state for a document. Its history starts empty.
238
+ * @param {{ text: string, indent: { unit: string, tabSize: number }, wrap: boolean, editing: object,
239
+ * git?: any, lint?: any, minimap?: any }} doc `git`, `lint`, `minimap`: what the document has of each from
240
+ * the start (an extension of editor-git.js, editor-lint.js, editor-minimap.js), nothing when left out
241
+ */
242
+ createState: (doc) => stateFor(doc),
243
+
244
+ /**
245
+ * Put a document's state in the view.
246
+ * @param {object} state from createState(), or one the view held before
247
+ * @param {{ scroll?: object | null, top?: number | null }} [o] `scroll`: what snapshotScroll() returned when
248
+ * this document was last showing; `top`: else a document position to put at the top of the view
249
+ */
250
+ show(state, { scroll = null, top = null } = {}) {
251
+ view.setState(state);
252
+ if (scroll) view.dispatch({ effects: scroll });
253
+ else if (top) view.dispatch({ effects: EditorView.scrollIntoView(Math.min(top, state.doc.length), { y: 'start', yMargin: 0 }) });
254
+ },
255
+
256
+ /** Where the view is scrolled to, as something show() puts back. */
257
+ snapshotScroll: () => view.scrollSnapshot(),
258
+ /** The document position of the first line that is visible. */
259
+ topPosition: () => view.lineBlockAtHeight(view.scrollDOM.getBoundingClientRect().top - view.documentTop).from,
260
+
261
+ /**
262
+ * Change a document: through the view when its state is the one showing (pass null), on the state itself
263
+ * otherwise. Returns the state after the change.
264
+ */
265
+ apply(state, spec) {
266
+ if (!state || state === view.state) { view.dispatch(spec); return view.state; }
267
+ return state.update(spec).state;
268
+ },
269
+
270
+ /** Effects for apply(), one for each thing that can change while a document is open. */
271
+ effects: {
272
+ wrap: (on) => wrapping.reconfigure(wrapExtension(on)),
273
+ indent: (indent) => indentation.reconfigure(indentExtension(indent)),
274
+ readOnly: (on) => readOnly.reconfigure(readOnlyExtension(on)),
275
+ editing: (editing) => preferences.reconfigure(preferenceExtension(editing)),
276
+ /** `support`: what loadLanguage() resolved to; nothing for plain text. */
277
+ language: (support) => language.reconfigure(support || []),
278
+ /** `extension`: what editor-compare.js built; nothing to leave the comparison. */
279
+ compare: (extension) => comparing.reconfigure(extension || []),
280
+ /** `extension`: editor-git.js's column; nothing for a document git markers are not shown for. */
281
+ git: (extension) => gitMarkers.reconfigure(extension || []),
282
+ /** `extension`: editor-lint.js's check for the document's kind; nothing for a document that is not checked. */
283
+ lint: (extension) => problems.reconfigure(extension || []),
284
+ /** `extension`: editor-minimap.js's; nothing while the document shows no minimap. */
285
+ minimap: (extension) => minimap.reconfigure(extension || []),
286
+ /** The next edit starts a new undo step (after a save, or a reload from disk). */
287
+ saved: () => markSaved.of(null),
288
+ },
289
+
290
+ /** The language a file name is highlighted as (a description of the bundle's language-data), or null. */
291
+ describeLanguage(fileName) {
292
+ const wanted = resolveLanguage(fileName);
293
+ if (wanted.known) return wanted.language ? cm.languages.find((entry) => entry.name === wanted.language) || null : null;
294
+ return cm.LanguageDescription.matchFilename(cm.languages, baseName(fileName));
295
+ },
296
+ /** Every language of the bundle. */
297
+ languages: () => cm.languages,
298
+ /**
299
+ * Load a language (its chunk is fetched the first time). Resolves to null when it cannot be loaded: the
300
+ * file stays readable and editable as plain text.
301
+ */
302
+ loadLanguage(description) {
303
+ if (!description) return Promise.resolve(null);
304
+ if (!supports.has(description.name)) {
305
+ supports.set(description.name, description.load().then((support) => withReusableNodes(cm, support)));
306
+ }
307
+ return supports.get(description.name).catch((error) => {
308
+ supports.delete(description.name);
309
+ console.warn(`[editor] could not load the ${description.name} language`, error);
310
+ return null;
311
+ });
312
+ },
313
+
314
+ /** Drop the document (the panel closed). */
315
+ clear() { view.setState(stateFor()); },
316
+
317
+ /** Put the caret at a 1-based line and column, with a few lines of context above it. */
318
+ reveal(line, column = 1) {
319
+ const { pos } = positionAt(view.state.doc, line, column);
320
+ view.dispatch({ selection: { anchor: pos }, effects: EditorView.scrollIntoView(pos, { y: 'start', yMargin: 100 }) });
321
+ },
322
+
323
+ focus() { view.focus(); },
324
+ hasFocus() { return view.hasFocus; },
325
+ /** The showing document, line breaks as "\n". */
326
+ text() { return view.state.doc.toString(); },
327
+ doc() { return view.state.doc; },
328
+ /** Sizes changed from outside (font size, the panel's width): measure again. */
329
+ remeasure() { view.requestMeasure(); },
330
+ destroy() { view.destroy(); },
331
+ };
332
+ }