@openspecui/web 0.9.0

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 (463) hide show
  1. package/dist/assets/abap-BdImnpbu.js +1 -0
  2. package/dist/assets/actionscript-3-CfeIJUat.js +1 -0
  3. package/dist/assets/ada-bCR0ucgS.js +1 -0
  4. package/dist/assets/andromeeda-C-Jbm3Hp.js +1 -0
  5. package/dist/assets/angular-html-CU67Zn6k.js +1 -0
  6. package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
  7. package/dist/assets/apache-Pmp26Uib.js +1 -0
  8. package/dist/assets/apex-DDbsPZ6N.js +1 -0
  9. package/dist/assets/apl-B4CMkyY2.js +1 -0
  10. package/dist/assets/apl-dKokRX4l.js +1 -0
  11. package/dist/assets/applescript-Co6uUVPk.js +1 -0
  12. package/dist/assets/ara-BRHolxvo.js +1 -0
  13. package/dist/assets/asciiarmor-Df11BRmG.js +1 -0
  14. package/dist/assets/asciidoc-Dv7Oe6Be.js +1 -0
  15. package/dist/assets/asm-D_Q5rh1f.js +1 -0
  16. package/dist/assets/asn1-EdZsLKOL.js +1 -0
  17. package/dist/assets/asterisk-B-8jnY81.js +1 -0
  18. package/dist/assets/astro-CbQHKStN.js +1 -0
  19. package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
  20. package/dist/assets/awk-DMzUqQB5.js +1 -0
  21. package/dist/assets/ayu-dark-Cv9koXgw.js +1 -0
  22. package/dist/assets/ballerina-BFfxhgS-.js +1 -0
  23. package/dist/assets/bat-BkioyH1T.js +1 -0
  24. package/dist/assets/beancount-k_qm7-4y.js +1 -0
  25. package/dist/assets/berry-uYugtg8r.js +1 -0
  26. package/dist/assets/bibtex-CHM0blh-.js +1 -0
  27. package/dist/assets/bicep-Bmn6On1c.js +1 -0
  28. package/dist/assets/blade-DVc8C-J4.js +1 -0
  29. package/dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  30. package/dist/assets/bsl-BO_Y6i37.js +1 -0
  31. package/dist/assets/c-BIGW1oBm.js +1 -0
  32. package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
  33. package/dist/assets/cairo-KRGpt6FW.js +1 -0
  34. package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  35. package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  36. package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  37. package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  38. package/dist/assets/clarity-D53aC0YG.js +1 -0
  39. package/dist/assets/clike-B9uivgTg.js +1 -0
  40. package/dist/assets/clojure-BMjYHr_A.js +1 -0
  41. package/dist/assets/clojure-P80f7IUj.js +1 -0
  42. package/dist/assets/cmake-BQqOBYOt.js +1 -0
  43. package/dist/assets/cmake-D1j8_8rp.js +1 -0
  44. package/dist/assets/cobol-CWcv1MsR.js +1 -0
  45. package/dist/assets/cobol-nwyudZeR.js +1 -0
  46. package/dist/assets/codeowners-Bp6g37R7.js +1 -0
  47. package/dist/assets/codeql-DsOJ9woJ.js +1 -0
  48. package/dist/assets/coffee-Ch7k5sss.js +1 -0
  49. package/dist/assets/coffeescript-S37ZYGWr.js +1 -0
  50. package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
  51. package/dist/assets/commonlisp-DBKNyK5s.js +1 -0
  52. package/dist/assets/coq-DkFqJrB1.js +1 -0
  53. package/dist/assets/cpp-CofmeUqb.js +1 -0
  54. package/dist/assets/crystal-SjHAIU92.js +1 -0
  55. package/dist/assets/crystal-tKQVLTB8.js +1 -0
  56. package/dist/assets/csharp-K5feNrxe.js +1 -0
  57. package/dist/assets/css-BnMrqG3P.js +1 -0
  58. package/dist/assets/css-DPfMkruS.js +1 -0
  59. package/dist/assets/csv-fuZLfV_i.js +1 -0
  60. package/dist/assets/cue-D82EKSYY.js +1 -0
  61. package/dist/assets/cypher-COkxafJQ.js +1 -0
  62. package/dist/assets/cypher-C_CwsFkJ.js +1 -0
  63. package/dist/assets/d-85-TOEBH.js +1 -0
  64. package/dist/assets/d-pRatUO7H.js +1 -0
  65. package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
  66. package/dist/assets/dart-CF10PKvl.js +1 -0
  67. package/dist/assets/dax-CEL-wOlO.js +1 -0
  68. package/dist/assets/desktop-BmXAJ9_W.js +1 -0
  69. package/dist/assets/diff-D97Zzqfu.js +1 -0
  70. package/dist/assets/diff-DbItnlRl.js +1 -0
  71. package/dist/assets/docker-BcOcwvcX.js +1 -0
  72. package/dist/assets/dockerfile-BKs6k2Af.js +1 -0
  73. package/dist/assets/dotenv-Da5cRb03.js +1 -0
  74. package/dist/assets/dracula-BzJJZx-M.js +1 -0
  75. package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
  76. package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
  77. package/dist/assets/dtd-DF_7sFjM.js +1 -0
  78. package/dist/assets/dylan-DwRh75JA.js +1 -0
  79. package/dist/assets/ebnf-CDyGwa7X.js +1 -0
  80. package/dist/assets/ecl-Cabwm37j.js +1 -0
  81. package/dist/assets/edge-BkV0erSs.js +1 -0
  82. package/dist/assets/eiffel-CnydiIhH.js +1 -0
  83. package/dist/assets/elixir-CDX3lj18.js +1 -0
  84. package/dist/assets/elm-DbKCFpqz.js +1 -0
  85. package/dist/assets/elm-vLlmbW-K.js +1 -0
  86. package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
  87. package/dist/assets/erb-BOJIQeun.js +1 -0
  88. package/dist/assets/erlang-BNw1qcRV.js +1 -0
  89. package/dist/assets/erlang-DsQrWhSR.js +1 -0
  90. package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
  91. package/dist/assets/everforest-light-C8M2exoo.js +1 -0
  92. package/dist/assets/factor-kuTfRLto.js +1 -0
  93. package/dist/assets/fcl-Kvtd6kyn.js +1 -0
  94. package/dist/assets/fennel-BYunw83y.js +1 -0
  95. package/dist/assets/fish-BvzEVeQv.js +1 -0
  96. package/dist/assets/fluent-C4IJs8-o.js +1 -0
  97. package/dist/assets/forth-Ffai-XNe.js +1 -0
  98. package/dist/assets/fortran-DYz_wnZ1.js +1 -0
  99. package/dist/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  100. package/dist/assets/fortran-free-form-D22FLkUw.js +1 -0
  101. package/dist/assets/fsharp-CXgrBDvD.js +1 -0
  102. package/dist/assets/gas-Bneqetm1.js +1 -0
  103. package/dist/assets/gdresource-B7Tvp0Sc.js +1 -0
  104. package/dist/assets/gdscript-DTMYz4Jt.js +1 -0
  105. package/dist/assets/gdshader-DkwncUOv.js +1 -0
  106. package/dist/assets/genie-D0YGMca9.js +1 -0
  107. package/dist/assets/gherkin-DyxjwDmM.js +1 -0
  108. package/dist/assets/gherkin-heZmZLOM.js +1 -0
  109. package/dist/assets/git-commit-F4YmCXRG.js +1 -0
  110. package/dist/assets/git-rebase-r7XF79zn.js +1 -0
  111. package/dist/assets/github-dark-DHJKELXO.js +1 -0
  112. package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
  113. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  114. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  115. package/dist/assets/github-light-DAi9KRSo.js +1 -0
  116. package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
  117. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  118. package/dist/assets/gleam-BspZqrRM.js +1 -0
  119. package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
  120. package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
  121. package/dist/assets/glsl-DplSGwfg.js +1 -0
  122. package/dist/assets/gnuplot-DdkO51Og.js +1 -0
  123. package/dist/assets/go-Dn2_MT6a.js +1 -0
  124. package/dist/assets/graphql-ChdNCCLP.js +1 -0
  125. package/dist/assets/groovy-D9Dt4D0W.js +1 -0
  126. package/dist/assets/groovy-gcz8RCvz.js +1 -0
  127. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  128. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  129. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  130. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  131. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  132. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  133. package/dist/assets/hack-CaT9iCJl.js +1 -0
  134. package/dist/assets/haml-B8DHNrY2.js +1 -0
  135. package/dist/assets/handlebars-BL8al0AC.js +1 -0
  136. package/dist/assets/haskell-Cw1EW3IL.js +1 -0
  137. package/dist/assets/haskell-Df6bDoY_.js +1 -0
  138. package/dist/assets/haxe-CzTSHFRz.js +1 -0
  139. package/dist/assets/haxe-H-WmDvRZ.js +1 -0
  140. package/dist/assets/hcl-BWvSN4gD.js +1 -0
  141. package/dist/assets/hjson-D5-asLiD.js +1 -0
  142. package/dist/assets/hlsl-D3lLCCz7.js +1 -0
  143. package/dist/assets/houston-DnULxvSX.js +1 -0
  144. package/dist/assets/html-GMplVEZG.js +1 -0
  145. package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
  146. package/dist/assets/http-DBlCnlav.js +1 -0
  147. package/dist/assets/http-jrhK8wxY.js +1 -0
  148. package/dist/assets/hurl-irOxFIW8.js +1 -0
  149. package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
  150. package/dist/assets/hy-DFXneXwc.js +1 -0
  151. package/dist/assets/idl-BEugSyMb.js +1 -0
  152. package/dist/assets/imba-DGztddWO.js +1 -0
  153. package/dist/assets/index-8c6bEJ99.js +1 -0
  154. package/dist/assets/index-AbWe21oh.js +2 -0
  155. package/dist/assets/index-ArhptQw0.js +1 -0
  156. package/dist/assets/index-B1hpa--1.js +3 -0
  157. package/dist/assets/index-Bafja8o4.js +1 -0
  158. package/dist/assets/index-Bp00uZNc.js +1 -0
  159. package/dist/assets/index-BsTieXqQ.js +1 -0
  160. package/dist/assets/index-BvGAWAqS.js +1 -0
  161. package/dist/assets/index-CCfVkFzN.js +1 -0
  162. package/dist/assets/index-D-Urq2hl.css +1 -0
  163. package/dist/assets/index-D3mXuuih.js +1 -0
  164. package/dist/assets/index-DFOLYN6W.js +1 -0
  165. package/dist/assets/index-DpxkOmNJ.js +7 -0
  166. package/dist/assets/index-YZ-iXB95.js +309 -0
  167. package/dist/assets/index-eA_XNQ_L.js +1 -0
  168. package/dist/assets/index-ftYom_wU.js +1 -0
  169. package/dist/assets/index-gvPT4BlL.js +1 -0
  170. package/dist/assets/ini-BEwlwnbL.js +1 -0
  171. package/dist/assets/java-CylS5w8V.js +1 -0
  172. package/dist/assets/javascript-iXu5QeM3.js +1 -0
  173. package/dist/assets/javascript-wDzz0qaB.js +1 -0
  174. package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
  175. package/dist/assets/jison-wvAkD_A8.js +1 -0
  176. package/dist/assets/json-Cp-IABpG.js +1 -0
  177. package/dist/assets/json5-C9tS-k6U.js +1 -0
  178. package/dist/assets/jsonc-Des-eS-w.js +1 -0
  179. package/dist/assets/jsonl-DcaNXYhu.js +1 -0
  180. package/dist/assets/jsonnet-DFQXde-d.js +1 -0
  181. package/dist/assets/jssm-C2t-YnRu.js +1 -0
  182. package/dist/assets/jsx-g9-lgVsj.js +1 -0
  183. package/dist/assets/julia-C8NyazO9.js +1 -0
  184. package/dist/assets/julia-DuME0IfC.js +1 -0
  185. package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  186. package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  187. package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
  188. package/dist/assets/kdl-DV7GczEv.js +1 -0
  189. package/dist/assets/kotlin-BdnUsdx6.js +1 -0
  190. package/dist/assets/kusto-BvAqAH-y.js +1 -0
  191. package/dist/assets/laserwave-DUszq2jm.js +1 -0
  192. package/dist/assets/latex-BdAV_C_H.js +1 -0
  193. package/dist/assets/lean-Bc6EcWN3.js +1 -0
  194. package/dist/assets/less-B1dDrJ26.js +1 -0
  195. package/dist/assets/light-plus-B7mTdjB0.js +1 -0
  196. package/dist/assets/liquid-DYVedYrR.js +1 -0
  197. package/dist/assets/livescript-BwQOo05w.js +1 -0
  198. package/dist/assets/llvm-BtvRca6l.js +1 -0
  199. package/dist/assets/log-2UxHyX5q.js +1 -0
  200. package/dist/assets/logo-BtOb2qkB.js +1 -0
  201. package/dist/assets/lua-BbnMAYS6.js +1 -0
  202. package/dist/assets/lua-BgMRiT3U.js +1 -0
  203. package/dist/assets/luau-CXu1NL6O.js +1 -0
  204. package/dist/assets/make-CHLpvVh8.js +1 -0
  205. package/dist/assets/markdown-Cvjx9yec.js +1 -0
  206. package/dist/assets/marko-CPi9NSCl.js +1 -0
  207. package/dist/assets/material-theme-D5KoaKCx.js +1 -0
  208. package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
  209. package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  210. package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
  211. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  212. package/dist/assets/mathematica-DTrFuWx2.js +1 -0
  213. package/dist/assets/matlab-D7o27uSR.js +1 -0
  214. package/dist/assets/mbox-CNhZ1qSd.js +1 -0
  215. package/dist/assets/mdc-DUICxH0z.js +1 -0
  216. package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
  217. package/dist/assets/mermaid-DKYwYmdq.js +1 -0
  218. package/dist/assets/min-dark-CafNBF8u.js +1 -0
  219. package/dist/assets/min-light-CTRr51gU.js +1 -0
  220. package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
  221. package/dist/assets/mirc-CjQqDB4T.js +1 -0
  222. package/dist/assets/mllike-CXdrOF99.js +1 -0
  223. package/dist/assets/modelica-Dc1JOy9r.js +1 -0
  224. package/dist/assets/mojo-1DNp92w6.js +1 -0
  225. package/dist/assets/monokai-D4h5O-jR.js +1 -0
  226. package/dist/assets/move-Bu9oaDYs.js +1 -0
  227. package/dist/assets/mscgen-BA5vi2Kp.js +1 -0
  228. package/dist/assets/mumps-BT43cFF4.js +1 -0
  229. package/dist/assets/narrat-DRg8JJMk.js +1 -0
  230. package/dist/assets/nextflow-BrzmwbiE.js +1 -0
  231. package/dist/assets/nginx-DdIZxoE0.js +1 -0
  232. package/dist/assets/nginx-DknmC5AR.js +1 -0
  233. package/dist/assets/night-owl-C39BiMTA.js +1 -0
  234. package/dist/assets/nim-CVrawwO9.js +1 -0
  235. package/dist/assets/nix-c8nO5XWb.js +1 -0
  236. package/dist/assets/nord-Ddv68eIx.js +1 -0
  237. package/dist/assets/nsis-LdVXkNf5.js +1 -0
  238. package/dist/assets/ntriples-BfvgReVJ.js +1 -0
  239. package/dist/assets/nushell-C-sUppwS.js +1 -0
  240. package/dist/assets/objective-c-DXmwc3jG.js +1 -0
  241. package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
  242. package/dist/assets/ocaml-C0hk2d4L.js +1 -0
  243. package/dist/assets/octave-Ck1zUtKM.js +1 -0
  244. package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  245. package/dist/assets/one-light-PoHY5YXO.js +1 -0
  246. package/dist/assets/openscad-C4EeE6gA.js +1 -0
  247. package/dist/assets/oz-BzwKVEFT.js +1 -0
  248. package/dist/assets/pascal--L3eBynH.js +1 -0
  249. package/dist/assets/pascal-D93ZcfNL.js +1 -0
  250. package/dist/assets/perl-C0TMdlhV.js +1 -0
  251. package/dist/assets/perl-CdXCOZ3F.js +1 -0
  252. package/dist/assets/php-CDn_0X-4.js +1 -0
  253. package/dist/assets/pig-CevX1Tat.js +1 -0
  254. package/dist/assets/pkl-u5AG7uiY.js +1 -0
  255. package/dist/assets/plastic-3e1v2bzS.js +1 -0
  256. package/dist/assets/plsql-ChMvpjG-.js +1 -0
  257. package/dist/assets/po-BTJTHyun.js +1 -0
  258. package/dist/assets/poimandres-CS3Unz2-.js +1 -0
  259. package/dist/assets/polar-C0HS_06l.js +1 -0
  260. package/dist/assets/postcss-CXtECtnM.js +1 -0
  261. package/dist/assets/powerquery-CEu0bR-o.js +1 -0
  262. package/dist/assets/powershell-CFHJl5sT.js +1 -0
  263. package/dist/assets/powershell-Dpen1YoG.js +1 -0
  264. package/dist/assets/prisma-Dd19v3D-.js +1 -0
  265. package/dist/assets/prolog-CbFg5uaA.js +1 -0
  266. package/dist/assets/properties-C78fOPTZ.js +1 -0
  267. package/dist/assets/proto-DyJlTyXw.js +1 -0
  268. package/dist/assets/protobuf-ChK-085T.js +1 -0
  269. package/dist/assets/pug-CGlum2m_.js +1 -0
  270. package/dist/assets/pug-DeIclll2.js +1 -0
  271. package/dist/assets/puppet-BMWR74SV.js +1 -0
  272. package/dist/assets/puppet-DMA9R1ak.js +1 -0
  273. package/dist/assets/purescript-CklMAg4u.js +1 -0
  274. package/dist/assets/python-B6aJPvgy.js +1 -0
  275. package/dist/assets/python-BuPzkPfP.js +1 -0
  276. package/dist/assets/q-pXgVlZs6.js +1 -0
  277. package/dist/assets/qml-3beO22l8.js +1 -0
  278. package/dist/assets/qmldir-C8lEn-DE.js +1 -0
  279. package/dist/assets/qss-IeuSbFQv.js +1 -0
  280. package/dist/assets/r-B6wPVr8A.js +1 -0
  281. package/dist/assets/r-DiinP2Uv.js +1 -0
  282. package/dist/assets/racket-BqYA7rlc.js +1 -0
  283. package/dist/assets/raku-DXvB9xmW.js +1 -0
  284. package/dist/assets/razor-CE9lU5zL.js +1 -0
  285. package/dist/assets/red-bN70gL4F.js +1 -0
  286. package/dist/assets/reg-C-SQnVFl.js +1 -0
  287. package/dist/assets/regexp-CDVJQ6XC.js +1 -0
  288. package/dist/assets/rel-C3B-1QV4.js +1 -0
  289. package/dist/assets/riscv-BM1_JUlF.js +1 -0
  290. package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  291. package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  292. package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
  293. package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
  294. package/dist/assets/rpm-CTu-6PCP.js +1 -0
  295. package/dist/assets/rst-B0xPkSld.js +1 -0
  296. package/dist/assets/ruby-B2Rjki9n.js +1 -0
  297. package/dist/assets/ruby-BvKwtOVI.js +1 -0
  298. package/dist/assets/rust-B1yitclQ.js +1 -0
  299. package/dist/assets/sas-B4kiWyti.js +1 -0
  300. package/dist/assets/sas-cz2c8ADy.js +1 -0
  301. package/dist/assets/sass-Cj5Yp3dK.js +1 -0
  302. package/dist/assets/scala-C151Ov-r.js +1 -0
  303. package/dist/assets/scheme-C41bIUwD.js +1 -0
  304. package/dist/assets/scheme-C98Dy4si.js +1 -0
  305. package/dist/assets/scss-OYdSNvt2.js +1 -0
  306. package/dist/assets/sdbl-DVxCFoDh.js +1 -0
  307. package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
  308. package/dist/assets/shell-CjFT_Tl9.js +1 -0
  309. package/dist/assets/shellscript-Yzrsuije.js +1 -0
  310. package/dist/assets/shellsession-BADoaaVG.js +1 -0
  311. package/dist/assets/sieve-C3Gn_uJK.js +1 -0
  312. package/dist/assets/simple-mode-GW_nhZxv.js +1 -0
  313. package/dist/assets/slack-dark-BthQWCQV.js +1 -0
  314. package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
  315. package/dist/assets/smalltalk-BERRCDM3.js +1 -0
  316. package/dist/assets/smalltalk-CnHTOXQT.js +1 -0
  317. package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
  318. package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
  319. package/dist/assets/solarized-light-L9t79GZl.js +1 -0
  320. package/dist/assets/solidity-rGO070M0.js +1 -0
  321. package/dist/assets/solr-DehyRSwq.js +1 -0
  322. package/dist/assets/soy-Brmx7dQM.js +1 -0
  323. package/dist/assets/sparql-DkYu6x3z.js +1 -0
  324. package/dist/assets/sparql-rVzFXLq3.js +1 -0
  325. package/dist/assets/splunk-BtCnVYZw.js +1 -0
  326. package/dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  327. package/dist/assets/sql-BLtJtn59.js +1 -0
  328. package/dist/assets/sql-D0XecflT.js +1 -0
  329. package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
  330. package/dist/assets/stata-BH5u7GGu.js +1 -0
  331. package/dist/assets/stex-C3f8Ysf7.js +1 -0
  332. package/dist/assets/stylus-B533Al4x.js +1 -0
  333. package/dist/assets/stylus-BEDo0Tqx.js +1 -0
  334. package/dist/assets/svelte-3Dk4HxPD.js +1 -0
  335. package/dist/assets/swift-BzpIVaGY.js +1 -0
  336. package/dist/assets/swift-Dg5xB15N.js +1 -0
  337. package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
  338. package/dist/assets/system-verilog-CnnmHF94.js +1 -0
  339. package/dist/assets/systemd-4A_iFExJ.js +1 -0
  340. package/dist/assets/talonscript-CkByrt1z.js +1 -0
  341. package/dist/assets/tasl-QIJgUcNo.js +1 -0
  342. package/dist/assets/tcl-DVfN8rqt.js +1 -0
  343. package/dist/assets/tcl-dwOrl1Do.js +1 -0
  344. package/dist/assets/templ-W15q3VgB.js +1 -0
  345. package/dist/assets/terraform-BETggiCN.js +1 -0
  346. package/dist/assets/tex-CxkMU7Pf.js +1 -0
  347. package/dist/assets/textile-CnDTJFAw.js +1 -0
  348. package/dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  349. package/dist/assets/tiki-DGYXhP31.js +1 -0
  350. package/dist/assets/tokyo-night-hegEt444.js +1 -0
  351. package/dist/assets/toml-Bm5Em-hy.js +1 -0
  352. package/dist/assets/toml-vGWfd6FD.js +1 -0
  353. package/dist/assets/troff-wAsdV37c.js +1 -0
  354. package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
  355. package/dist/assets/tsv-B_m7g4N7.js +1 -0
  356. package/dist/assets/tsx-COt5Ahok.js +1 -0
  357. package/dist/assets/ttcn-CfJYG6tj.js +1 -0
  358. package/dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  359. package/dist/assets/turtle-B1tBg_DP.js +1 -0
  360. package/dist/assets/turtle-BsS91CYL.js +1 -0
  361. package/dist/assets/twig-CO9l9SDP.js +1 -0
  362. package/dist/assets/typescript-BPQ3VLAy.js +1 -0
  363. package/dist/assets/typespec-BGHnOYBU.js +1 -0
  364. package/dist/assets/typst-DHCkPAjA.js +1 -0
  365. package/dist/assets/v-BcVCzyr7.js +1 -0
  366. package/dist/assets/vala-CsfeWuGM.js +1 -0
  367. package/dist/assets/vb-CmGdzxic.js +1 -0
  368. package/dist/assets/vb-D17OF-Vu.js +1 -0
  369. package/dist/assets/vbscript-BuJXcnF6.js +1 -0
  370. package/dist/assets/velocity-D8B20fx6.js +1 -0
  371. package/dist/assets/verilog-BQ8w6xss.js +1 -0
  372. package/dist/assets/verilog-C6RDOZhf.js +1 -0
  373. package/dist/assets/vesper-DU1UobuO.js +1 -0
  374. package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
  375. package/dist/assets/vhdl-lSbBsy5d.js +1 -0
  376. package/dist/assets/viml-CJc9bBzg.js +1 -0
  377. package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
  378. package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
  379. package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
  380. package/dist/assets/vue-DnHKYNfI.js +1 -0
  381. package/dist/assets/vue-html-CChd_i61.js +1 -0
  382. package/dist/assets/vue-vine-8moa0y9V.js +1 -0
  383. package/dist/assets/vyper-CDx5xZoG.js +1 -0
  384. package/dist/assets/wasm-CG6Dc4jp.js +1 -0
  385. package/dist/assets/wasm-MzD3tlZU.js +1 -0
  386. package/dist/assets/webidl-ZXfAyPTL.js +1 -0
  387. package/dist/assets/wenyan-BV7otONQ.js +1 -0
  388. package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
  389. package/dist/assets/wikitext-BhOHFoWU.js +1 -0
  390. package/dist/assets/wit-5i3qLPDT.js +1 -0
  391. package/dist/assets/wolfram-lXgVvXCa.js +1 -0
  392. package/dist/assets/xml-sdJ4AIDG.js +1 -0
  393. package/dist/assets/xquery-DzFWVndE.js +1 -0
  394. package/dist/assets/xsl-CtQFsRM5.js +1 -0
  395. package/dist/assets/yacas-BJ4BC0dw.js +1 -0
  396. package/dist/assets/yaml-Buea-lGh.js +1 -0
  397. package/dist/assets/z80-Hz9HOZM7.js +1 -0
  398. package/dist/assets/zenscript-DVFEvuxE.js +1 -0
  399. package/dist/assets/zig-VOosw3JB.js +1 -0
  400. package/dist/index.html +47 -0
  401. package/dist/logo.svg +8 -0
  402. package/dist/openspec_pixel_dark.svg +89 -0
  403. package/dist/openspec_pixel_light.svg +89 -0
  404. package/index.html +46 -0
  405. package/package.json +66 -0
  406. package/src/App.tsx +124 -0
  407. package/src/components/StaticModeBanner.tsx +46 -0
  408. package/src/components/change-overview.tsx +156 -0
  409. package/src/components/cli-terminal.tsx +93 -0
  410. package/src/components/code-editor.tsx +232 -0
  411. package/src/components/copyable-path.tsx +44 -0
  412. package/src/components/dialog.tsx +193 -0
  413. package/src/components/folder-editor-viewer.tsx +411 -0
  414. package/src/components/global-archive-modal.tsx +205 -0
  415. package/src/components/layout/desktop-sidebar.tsx +48 -0
  416. package/src/components/layout/index.ts +6 -0
  417. package/src/components/layout/mobile-header.tsx +91 -0
  418. package/src/components/layout/mobile-tabbar.tsx +20 -0
  419. package/src/components/layout/nav-items.ts +33 -0
  420. package/src/components/layout/root-layout.tsx +67 -0
  421. package/src/components/layout/status-bar.tsx +69 -0
  422. package/src/components/markdown-content.tsx +104 -0
  423. package/src/components/markdown-viewer.tsx +415 -0
  424. package/src/components/path-marquee.tsx +104 -0
  425. package/src/components/tabs.tsx +151 -0
  426. package/src/components/tasks-view.test.tsx +45 -0
  427. package/src/components/tasks-view.tsx +209 -0
  428. package/src/components/toc-context.tsx +177 -0
  429. package/src/components/toc.tsx +290 -0
  430. package/src/entry-client.tsx +47 -0
  431. package/src/index.css +481 -0
  432. package/src/lib/api-config.ts +72 -0
  433. package/src/lib/archive-modal-context.tsx +45 -0
  434. package/src/lib/codemirror-markdown-preview.ts +494 -0
  435. package/src/lib/format-time.ts +51 -0
  436. package/src/lib/shiki-highlighter.ts +47 -0
  437. package/src/lib/static-data-provider.ts +386 -0
  438. package/src/lib/static-mode.ts +158 -0
  439. package/src/lib/trpc.ts +107 -0
  440. package/src/lib/use-cli-runner.tsx +433 -0
  441. package/src/lib/use-dark-mode.ts +28 -0
  442. package/src/lib/use-server-status.ts +208 -0
  443. package/src/lib/use-subscription.ts +375 -0
  444. package/src/lib/use-tabs-status-by-query.ts +78 -0
  445. package/src/main.tsx +9 -0
  446. package/src/routes/archive-list.tsx +65 -0
  447. package/src/routes/archive-view.tsx +116 -0
  448. package/src/routes/change-list.tsx +63 -0
  449. package/src/routes/change-view.tsx +188 -0
  450. package/src/routes/dashboard.tsx +204 -0
  451. package/src/routes/project.tsx +272 -0
  452. package/src/routes/settings.tsx +816 -0
  453. package/src/routes/spec-list.tsx +49 -0
  454. package/src/routes/spec-view.tsx +164 -0
  455. package/src/ssg/entry-server.tsx +111 -0
  456. package/src/ssg/index.ts +6 -0
  457. package/src/ssg/prerender.ts +111 -0
  458. package/src/ssg/static-data-context.tsx +49 -0
  459. package/src/ssg/types.ts +5 -0
  460. package/src/test/setup.ts +1 -0
  461. package/src/vite-env.d.ts +6 -0
  462. package/tsconfig.json +18 -0
  463. package/vite.config.ts +58 -0
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Static Data Provider
3
+ *
4
+ * Provides data from the static snapshot (data.json) instead of WebSocket subscriptions
5
+ *
6
+ * The snapshot includes fully parsed markdown content generated during export,
7
+ * so specs, changes, and archives can be displayed with proper rendering.
8
+ */
9
+
10
+ import type { ArchiveMeta, Change, ChangeFile, ChangeMeta, Spec, SpecMeta } from '@openspecui/core'
11
+ import type { ExportSnapshot } from '../ssg/types'
12
+ import type { ChangeRaw, DashboardData, OpenSpecUIConfig } from './use-subscription'
13
+ import { getBasePath, getInitialData } from './static-mode'
14
+
15
+ /**
16
+ * In-memory cache of the loaded snapshot
17
+ */
18
+ let snapshotCache: ExportSnapshot | null = null
19
+ let snapshotPromise: Promise<ExportSnapshot | null> | null = null
20
+
21
+ /**
22
+ * Load the static snapshot once
23
+ */
24
+ export async function loadSnapshot(): Promise<ExportSnapshot | null> {
25
+ // Return cached data if available
26
+ if (snapshotCache) {
27
+ return snapshotCache
28
+ }
29
+
30
+ // Check for injected initial data first (SSR/SSG)
31
+ const initialData = getInitialData()
32
+ if (initialData) {
33
+ snapshotCache = initialData
34
+ return initialData
35
+ }
36
+
37
+ // Reuse in-flight request if exists
38
+ if (snapshotPromise) {
39
+ return snapshotPromise
40
+ }
41
+
42
+ snapshotPromise = (async () => {
43
+ try {
44
+ const basePath = getBasePath()
45
+ const dataUrl = `${basePath}data.json`.replace('//', '/')
46
+ const response = await fetch(dataUrl)
47
+
48
+ if (!response.ok) {
49
+ console.error('Failed to load data snapshot:', response.statusText)
50
+ return null
51
+ }
52
+
53
+ const snapshot = (await response.json()) as ExportSnapshot
54
+ snapshotCache = snapshot
55
+ return snapshot
56
+ } catch (error) {
57
+ console.error('Error loading static snapshot:', error)
58
+ return null
59
+ }
60
+ })()
61
+
62
+ return snapshotPromise
63
+ }
64
+
65
+ /**
66
+ * Convert snapshot spec to Spec type (with parsed content from export)
67
+ */
68
+ function snapshotSpecToSpec(snapSpec: ExportSnapshot['specs'][0]): Spec {
69
+ return {
70
+ id: snapSpec.id,
71
+ name: snapSpec.name,
72
+ overview: snapSpec.overview,
73
+ requirements: snapSpec.requirements,
74
+ metadata: {
75
+ version: '1.0',
76
+ format: 'openspec' as const,
77
+ },
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Convert snapshot change to Change type (with parsed content from export)
83
+ */
84
+ function snapshotChangeToChange(snapChange: ExportSnapshot['changes'][0]): Change {
85
+ return {
86
+ id: snapChange.id,
87
+ name: snapChange.name,
88
+ why: snapChange.why,
89
+ whatChanges: snapChange.whatChanges,
90
+ design: snapChange.design,
91
+ deltas: [], // Simplified - not used in UI directly
92
+ tasks: snapChange.parsedTasks,
93
+ progress: snapChange.progress,
94
+ } as Change
95
+ }
96
+
97
+ /**
98
+ * Get dashboard data from snapshot
99
+ */
100
+ export async function getDashboardData(): Promise<DashboardData | null> {
101
+ const snapshot = await loadSnapshot()
102
+ if (!snapshot) return null
103
+
104
+ const specs = snapshot.specs.map(snapshotSpecToSpec)
105
+ const changes = snapshot.changes.map(snapshotChangeToChange)
106
+ const archives = snapshot.archives
107
+
108
+ // Calculate summary
109
+ const specCount = specs.length
110
+ const requirementCount = 0 // Simplified for static mode
111
+ const activeChangeCount = changes.length
112
+ const archivedChangeCount = archives.length
113
+
114
+ // Calculate task progress from snapshot data
115
+ let totalTasks = 0
116
+ let completedTasks = 0
117
+
118
+ for (const change of snapshot.changes) {
119
+ totalTasks += change.progress.total
120
+ completedTasks += change.progress.completed
121
+ }
122
+
123
+ const progressPercent = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0
124
+
125
+ return {
126
+ specs,
127
+ changes,
128
+ archivedCount: archivedChangeCount,
129
+ summary: {
130
+ specCount,
131
+ requirementCount,
132
+ activeChangeCount,
133
+ archivedChangeCount,
134
+ totalTasks,
135
+ completedTasks,
136
+ progressPercent,
137
+ },
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Check if OpenSpec is initialized (always true in static mode)
143
+ */
144
+ export async function getInitialized(): Promise<boolean> {
145
+ const snapshot = await loadSnapshot()
146
+ return snapshot !== null
147
+ }
148
+
149
+ /**
150
+ * Get all specs metadata
151
+ */
152
+ export async function getSpecs(): Promise<SpecMeta[]> {
153
+ const snapshot = await loadSnapshot()
154
+ if (!snapshot) return []
155
+
156
+ return snapshot.specs.map((spec) => ({
157
+ id: spec.id,
158
+ name: spec.name,
159
+ createdAt: spec.createdAt,
160
+ updatedAt: spec.updatedAt,
161
+ }))
162
+ }
163
+
164
+ /**
165
+ * Get a single spec by ID
166
+ */
167
+ export async function getSpec(id: string): Promise<Spec | null> {
168
+ const snapshot = await loadSnapshot()
169
+ if (!snapshot) return null
170
+
171
+ const snapSpec = snapshot.specs.find((s) => s.id === id)
172
+ if (!snapSpec) return null
173
+
174
+ return snapshotSpecToSpec(snapSpec)
175
+ }
176
+
177
+ /**
178
+ * Get raw spec content (markdown)
179
+ */
180
+ export async function getSpecRaw(id: string): Promise<string | null> {
181
+ const snapshot = await loadSnapshot()
182
+ if (!snapshot) return null
183
+
184
+ const spec = snapshot.specs.find((s) => s.id === id)
185
+ return spec?.content || null
186
+ }
187
+
188
+ /**
189
+ * Get all changes metadata
190
+ */
191
+ export async function getChanges(): Promise<ChangeMeta[]> {
192
+ const snapshot = await loadSnapshot()
193
+ if (!snapshot) return []
194
+
195
+ return snapshot.changes.map((change) => ({
196
+ id: change.id,
197
+ name: change.name,
198
+ progress: change.progress,
199
+ createdAt: change.createdAt,
200
+ updatedAt: change.updatedAt,
201
+ }))
202
+ }
203
+
204
+ /**
205
+ * Get a single change by ID
206
+ */
207
+ export async function getChange(id: string): Promise<Change | null> {
208
+ const snapshot = await loadSnapshot()
209
+ if (!snapshot) return null
210
+
211
+ const snapChange = snapshot.changes.find((c) => c.id === id)
212
+ if (!snapChange) return null
213
+
214
+ return snapshotChangeToChange(snapChange)
215
+ }
216
+
217
+ /**
218
+ * Get change files
219
+ */
220
+ export async function getChangeFiles(id: string): Promise<ChangeFile[]> {
221
+ const snapshot = await loadSnapshot()
222
+ if (!snapshot) return []
223
+
224
+ const change = snapshot.changes.find((c) => c.id === id)
225
+ if (!change) return []
226
+
227
+ const files: ChangeFile[] = []
228
+
229
+ files.push({
230
+ path: 'proposal.md',
231
+ type: 'file' as const,
232
+ content: change.proposal,
233
+ })
234
+
235
+ if (change.tasks) {
236
+ files.push({
237
+ path: 'tasks.md',
238
+ type: 'file' as const,
239
+ content: change.tasks,
240
+ })
241
+ }
242
+
243
+ if (change.design) {
244
+ files.push({
245
+ path: 'design.md',
246
+ type: 'file' as const,
247
+ content: change.design,
248
+ })
249
+ }
250
+
251
+ // Add delta spec files
252
+ change.deltas.forEach((delta) => {
253
+ files.push({
254
+ path: `specs/${delta.capability}/spec.md`,
255
+ type: 'file' as const,
256
+ content: delta.content,
257
+ })
258
+ })
259
+
260
+ return files
261
+ }
262
+
263
+ /**
264
+ * Get raw change content
265
+ */
266
+ export async function getChangeRaw(id: string): Promise<ChangeRaw | null> {
267
+ const snapshot = await loadSnapshot()
268
+ if (!snapshot) return null
269
+
270
+ const change = snapshot.changes.find((c) => c.id === id)
271
+ if (!change) return null
272
+
273
+ return {
274
+ proposal: change.proposal,
275
+ tasks: change.tasks,
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Get all archives metadata
281
+ */
282
+ export async function getArchives(): Promise<ArchiveMeta[]> {
283
+ const snapshot = await loadSnapshot()
284
+ if (!snapshot) return []
285
+
286
+ return snapshot.archives.map((archive) => ({
287
+ id: archive.id,
288
+ name: archive.name,
289
+ createdAt: archive.createdAt,
290
+ updatedAt: archive.updatedAt,
291
+ }))
292
+ }
293
+
294
+ /**
295
+ * Get a single archive by ID
296
+ */
297
+ export async function getArchive(id: string): Promise<Change | null> {
298
+ const snapshot = await loadSnapshot()
299
+ if (!snapshot) return null
300
+
301
+ const snapArchive = snapshot.archives.find((a) => a.id === id)
302
+ if (!snapArchive) return null
303
+
304
+ // Convert archive to Change with parsed content
305
+ return {
306
+ id: snapArchive.id,
307
+ name: snapArchive.name,
308
+ why: snapArchive.why,
309
+ whatChanges: snapArchive.whatChanges,
310
+ design: snapArchive.design,
311
+ deltas: [],
312
+ tasks: snapArchive.parsedTasks,
313
+ progress: { total: 0, completed: 0 },
314
+ } as Change
315
+ }
316
+
317
+ /**
318
+ * Get archive files
319
+ */
320
+ export async function getArchiveFiles(id: string): Promise<ChangeFile[]> {
321
+ const snapshot = await loadSnapshot()
322
+ if (!snapshot) return []
323
+
324
+ const archive = snapshot.archives.find((a) => a.id === id)
325
+ if (!archive) return []
326
+
327
+ const files: ChangeFile[] = []
328
+
329
+ files.push({
330
+ path: 'proposal.md',
331
+ type: 'file' as const,
332
+ content: archive.proposal,
333
+ })
334
+
335
+ if (archive.tasks) {
336
+ files.push({
337
+ path: 'tasks.md',
338
+ type: 'file' as const,
339
+ content: archive.tasks,
340
+ })
341
+ }
342
+
343
+ if (archive.design) {
344
+ files.push({
345
+ path: 'design.md',
346
+ type: 'file' as const,
347
+ content: archive.design,
348
+ })
349
+ }
350
+
351
+ return files
352
+ }
353
+
354
+ /**
355
+ * Get project.md content (not in snapshot currently)
356
+ */
357
+ export async function getProjectMd(): Promise<string | null> {
358
+ const snapshot = await loadSnapshot()
359
+ return snapshot?.projectMd || null
360
+ }
361
+
362
+ /**
363
+ * Get AGENTS.md content (not in snapshot currently)
364
+ */
365
+ export async function getAgentsMd(): Promise<string | null> {
366
+ const snapshot = await loadSnapshot()
367
+ return snapshot?.agentsMd || null
368
+ }
369
+
370
+ /**
371
+ * Get UI config (default in static mode)
372
+ */
373
+ export async function getConfig(): Promise<OpenSpecUIConfig> {
374
+ // In static mode, return default config
375
+ return {
376
+ cli: { command: 'openspecui' },
377
+ ui: { theme: 'system' },
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Get configured tools (empty in static mode)
383
+ */
384
+ export async function getConfiguredTools(): Promise<string[]> {
385
+ return []
386
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Static Mode Detection and Data Loading
3
+ *
4
+ * This module detects whether the app is running in static export mode
5
+ * and provides data snapshot loading functionality.
6
+ */
7
+
8
+ import type { ExportSnapshot } from '../ssg/types'
9
+
10
+ let staticModeDetected: boolean | null = null
11
+
12
+ // Check for static mode flag set by SSG at build time
13
+ // This is the preferred detection method - no network requests needed
14
+ if (typeof window !== 'undefined' && (window as any).__OPENSPEC_STATIC_MODE__ === true) {
15
+ staticModeDetected = true
16
+ console.log('[static-mode] Detected static export mode (via flag)')
17
+ }
18
+
19
+ /**
20
+ * Check if running in static export mode
21
+ * Static mode is detected by:
22
+ * 1. window.__OPENSPEC_STATIC_MODE__ flag (set by SSG)
23
+ * 2. Fallback: attempting to load data.json
24
+ */
25
+ export async function detectStaticMode(): Promise<boolean> {
26
+ if (staticModeDetected !== null) {
27
+ return staticModeDetected
28
+ }
29
+
30
+ // Fallback: check for data.json
31
+ try {
32
+ const basePath = getBasePath()
33
+ const dataUrl = `${basePath}data.json`.replace('//', '/')
34
+ const response = await fetch(dataUrl, { method: 'HEAD' })
35
+ staticModeDetected = response.ok
36
+ } catch {
37
+ staticModeDetected = false
38
+ }
39
+
40
+ return staticModeDetected
41
+ }
42
+
43
+ /**
44
+ * Check if running in static export mode (synchronous)
45
+ */
46
+ export function isStaticMode(): boolean {
47
+ return staticModeDetected === true
48
+ }
49
+
50
+ /**
51
+ * Set static mode (used during app initialization)
52
+ */
53
+ export function setStaticMode(value: boolean): void {
54
+ staticModeDetected = value
55
+ }
56
+
57
+ // SSR basePath - set during server-side rendering
58
+ let ssrBasePath: string | null = null
59
+
60
+ /**
61
+ * Set base path for SSR (called before rendering)
62
+ */
63
+ export function setSSRBasePath(basePath: string): void {
64
+ ssrBasePath = basePath
65
+ }
66
+
67
+ /**
68
+ * Get the base path for the application
69
+ */
70
+ export function getBasePath(): string {
71
+ // SSR mode: use the set basePath
72
+ if (ssrBasePath !== null) {
73
+ return ssrBasePath
74
+ }
75
+ // Browser mode: use window variable
76
+ if (typeof window !== 'undefined') {
77
+ return (window as any).__OPENSPEC_BASE_PATH__ || './'
78
+ }
79
+ return './'
80
+ }
81
+
82
+ /**
83
+ * Get initial data injected by SSG (if available)
84
+ */
85
+ export function getInitialData(): ExportSnapshot | null {
86
+ if (typeof window !== 'undefined' && (window as any).__INITIAL_DATA__) {
87
+ return (window as any).__INITIAL_DATA__ as ExportSnapshot
88
+ }
89
+ return null
90
+ }
91
+
92
+ /**
93
+ * Load the data snapshot in static mode
94
+ */
95
+ export async function loadStaticSnapshot(): Promise<ExportSnapshot | null> {
96
+ // First check for injected data (faster, no network request)
97
+ const initialData = getInitialData()
98
+ if (initialData) {
99
+ return initialData
100
+ }
101
+
102
+ // Fallback: fetch from data.json
103
+ const isStatic = await detectStaticMode()
104
+ if (!isStatic) {
105
+ return null
106
+ }
107
+
108
+ try {
109
+ const basePath = getBasePath()
110
+ const dataUrl = `${basePath}data.json`.replace('//', '/')
111
+ const response = await fetch(dataUrl)
112
+
113
+ if (!response.ok) {
114
+ console.error('Failed to load data snapshot:', response.statusText)
115
+ return null
116
+ }
117
+
118
+ const snapshot = (await response.json()) as ExportSnapshot
119
+ return snapshot
120
+ } catch (error) {
121
+ console.error('Error loading static snapshot:', error)
122
+ return null
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Static snapshot cache - loaded once and reused
128
+ */
129
+ let snapshotCache: ExportSnapshot | null | undefined = undefined
130
+
131
+ /**
132
+ * Get the cached snapshot or load it if not yet loaded
133
+ */
134
+ export async function getStaticSnapshot(): Promise<ExportSnapshot | null> {
135
+ if (snapshotCache !== undefined) {
136
+ return snapshotCache
137
+ }
138
+
139
+ snapshotCache = await loadStaticSnapshot()
140
+ return snapshotCache
141
+ }
142
+
143
+ /**
144
+ * Check if snapshot is loaded
145
+ */
146
+ export function isSnapshotLoaded(): boolean {
147
+ return snapshotCache !== undefined && snapshotCache !== null
148
+ }
149
+
150
+ /**
151
+ * Get snapshot metadata (timestamp, version, etc.)
152
+ */
153
+ export function getSnapshotMeta() {
154
+ if (!isSnapshotLoaded() || !snapshotCache) {
155
+ return null
156
+ }
157
+ return snapshotCache.meta
158
+ }
@@ -0,0 +1,107 @@
1
+ import type { AppRouter } from '@openspecui/server'
2
+ import { QueryClient } from '@tanstack/react-query'
3
+ import {
4
+ createTRPCClient,
5
+ createWSClient,
6
+ httpBatchLink,
7
+ splitLink,
8
+ wsLink,
9
+ type TRPCLink,
10
+ } from '@trpc/client'
11
+ import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query'
12
+ import { getTrpcUrl, getWsUrl } from './api-config'
13
+ import { isStaticMode } from './static-mode'
14
+
15
+ // Check if running in browser
16
+ const isBrowser = typeof window !== 'undefined'
17
+
18
+ // Query client singleton for SPA
19
+ export const queryClient = new QueryClient({
20
+ defaultOptions: {
21
+ queries: {
22
+ staleTime: 60 * 1000,
23
+ },
24
+ },
25
+ })
26
+
27
+ /** WebSocket 重连延迟(毫秒) */
28
+ export const WS_RETRY_DELAY_MS = 3000
29
+
30
+ // Lazy WebSocket client creation
31
+ let wsClient: ReturnType<typeof createWSClient> | null = null
32
+ function getWsClient() {
33
+ if (!isBrowser || isStaticMode()) {
34
+ return null
35
+ }
36
+ if (!wsClient) {
37
+ try {
38
+ wsClient = createWSClient({
39
+ url: getWsUrl(),
40
+ retryDelayMs: () => WS_RETRY_DELAY_MS,
41
+ // Suppress connection errors in console
42
+ onOpen: () => {
43
+ // Connection opened successfully
44
+ },
45
+ onClose: (cause) => {
46
+ // Only log if not in static mode (shouldn't happen, but just in case)
47
+ if (!isStaticMode()) {
48
+ console.log('WebSocket closed:', cause)
49
+ }
50
+ },
51
+ })
52
+ } catch (error) {
53
+ // Suppress WebSocket creation errors in static mode
54
+ if (!isStaticMode()) {
55
+ console.error('Failed to create WebSocket client:', error)
56
+ }
57
+ return null
58
+ }
59
+ }
60
+ return wsClient
61
+ }
62
+
63
+ // Export for cleanup if needed
64
+ export function getWsClientInstance() {
65
+ return wsClient
66
+ }
67
+
68
+ // Create tRPC client only in browser environment
69
+ function createTrpcClientSafe() {
70
+ if (!isBrowser) {
71
+ // Return a dummy client for SSR that throws on use
72
+ return null as unknown as ReturnType<typeof createTRPCClient<AppRouter>>
73
+ }
74
+
75
+ return createTRPCClient<AppRouter>({
76
+ links: [
77
+ splitLink({
78
+ // Use WebSocket for subscriptions (only if not in static mode)
79
+ condition: (op) => op.type === 'subscription' && !isStaticMode(),
80
+ true: ((runtime) => {
81
+ const ws = getWsClient()
82
+ if (ws) {
83
+ return wsLink({ client: ws })(runtime)
84
+ }
85
+ return httpBatchLink({ url: getTrpcUrl() })(runtime)
86
+ }) as TRPCLink<AppRouter>,
87
+ // Use HTTP for queries and mutations
88
+ false: httpBatchLink({
89
+ url: getTrpcUrl(),
90
+ }),
91
+ }),
92
+ ],
93
+ })
94
+ }
95
+
96
+ // tRPC client singleton with WebSocket support for subscriptions
97
+ export const trpcClient = createTrpcClientSafe()
98
+
99
+ // tRPC options proxy for use with React Query hooks
100
+ // Use: trpc.router.procedure.queryOptions() with useQuery()
101
+ // Use: trpcClient.router.procedure.mutate() with useMutation()
102
+ export const trpc = isBrowser
103
+ ? createTRPCOptionsProxy<AppRouter>({
104
+ client: trpcClient,
105
+ queryClient,
106
+ })
107
+ : (null as unknown as ReturnType<typeof createTRPCOptionsProxy<AppRouter>>)