@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.
- package/dist/assets/abap-BdImnpbu.js +1 -0
- package/dist/assets/actionscript-3-CfeIJUat.js +1 -0
- package/dist/assets/ada-bCR0ucgS.js +1 -0
- package/dist/assets/andromeeda-C-Jbm3Hp.js +1 -0
- package/dist/assets/angular-html-CU67Zn6k.js +1 -0
- package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
- package/dist/assets/apache-Pmp26Uib.js +1 -0
- package/dist/assets/apex-DDbsPZ6N.js +1 -0
- package/dist/assets/apl-B4CMkyY2.js +1 -0
- package/dist/assets/apl-dKokRX4l.js +1 -0
- package/dist/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/assets/ara-BRHolxvo.js +1 -0
- package/dist/assets/asciiarmor-Df11BRmG.js +1 -0
- package/dist/assets/asciidoc-Dv7Oe6Be.js +1 -0
- package/dist/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/assets/asn1-EdZsLKOL.js +1 -0
- package/dist/assets/asterisk-B-8jnY81.js +1 -0
- package/dist/assets/astro-CbQHKStN.js +1 -0
- package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/assets/awk-DMzUqQB5.js +1 -0
- package/dist/assets/ayu-dark-Cv9koXgw.js +1 -0
- package/dist/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/assets/bat-BkioyH1T.js +1 -0
- package/dist/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/assets/berry-uYugtg8r.js +1 -0
- package/dist/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/assets/blade-DVc8C-J4.js +1 -0
- package/dist/assets/brainfuck-C4LP7Hcl.js +1 -0
- package/dist/assets/bsl-BO_Y6i37.js +1 -0
- package/dist/assets/c-BIGW1oBm.js +1 -0
- package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/dist/assets/clarity-D53aC0YG.js +1 -0
- package/dist/assets/clike-B9uivgTg.js +1 -0
- package/dist/assets/clojure-BMjYHr_A.js +1 -0
- package/dist/assets/clojure-P80f7IUj.js +1 -0
- package/dist/assets/cmake-BQqOBYOt.js +1 -0
- package/dist/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/assets/cobol-CWcv1MsR.js +1 -0
- package/dist/assets/cobol-nwyudZeR.js +1 -0
- package/dist/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/assets/coffeescript-S37ZYGWr.js +1 -0
- package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/assets/commonlisp-DBKNyK5s.js +1 -0
- package/dist/assets/coq-DkFqJrB1.js +1 -0
- package/dist/assets/cpp-CofmeUqb.js +1 -0
- package/dist/assets/crystal-SjHAIU92.js +1 -0
- package/dist/assets/crystal-tKQVLTB8.js +1 -0
- package/dist/assets/csharp-K5feNrxe.js +1 -0
- package/dist/assets/css-BnMrqG3P.js +1 -0
- package/dist/assets/css-DPfMkruS.js +1 -0
- package/dist/assets/csv-fuZLfV_i.js +1 -0
- package/dist/assets/cue-D82EKSYY.js +1 -0
- package/dist/assets/cypher-COkxafJQ.js +1 -0
- package/dist/assets/cypher-C_CwsFkJ.js +1 -0
- package/dist/assets/d-85-TOEBH.js +1 -0
- package/dist/assets/d-pRatUO7H.js +1 -0
- package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/assets/dart-CF10PKvl.js +1 -0
- package/dist/assets/dax-CEL-wOlO.js +1 -0
- package/dist/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/assets/diff-D97Zzqfu.js +1 -0
- package/dist/assets/diff-DbItnlRl.js +1 -0
- package/dist/assets/docker-BcOcwvcX.js +1 -0
- package/dist/assets/dockerfile-BKs6k2Af.js +1 -0
- package/dist/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/assets/dtd-DF_7sFjM.js +1 -0
- package/dist/assets/dylan-DwRh75JA.js +1 -0
- package/dist/assets/ebnf-CDyGwa7X.js +1 -0
- package/dist/assets/ecl-Cabwm37j.js +1 -0
- package/dist/assets/edge-BkV0erSs.js +1 -0
- package/dist/assets/eiffel-CnydiIhH.js +1 -0
- package/dist/assets/elixir-CDX3lj18.js +1 -0
- package/dist/assets/elm-DbKCFpqz.js +1 -0
- package/dist/assets/elm-vLlmbW-K.js +1 -0
- package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/dist/assets/erb-BOJIQeun.js +1 -0
- package/dist/assets/erlang-BNw1qcRV.js +1 -0
- package/dist/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/assets/factor-kuTfRLto.js +1 -0
- package/dist/assets/fcl-Kvtd6kyn.js +1 -0
- package/dist/assets/fennel-BYunw83y.js +1 -0
- package/dist/assets/fish-BvzEVeQv.js +1 -0
- package/dist/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/assets/forth-Ffai-XNe.js +1 -0
- package/dist/assets/fortran-DYz_wnZ1.js +1 -0
- package/dist/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
- package/dist/assets/fortran-free-form-D22FLkUw.js +1 -0
- package/dist/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/assets/gas-Bneqetm1.js +1 -0
- package/dist/assets/gdresource-B7Tvp0Sc.js +1 -0
- package/dist/assets/gdscript-DTMYz4Jt.js +1 -0
- package/dist/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/assets/genie-D0YGMca9.js +1 -0
- package/dist/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/assets/gherkin-heZmZLOM.js +1 -0
- package/dist/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/assets/gleam-BspZqrRM.js +1 -0
- package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
- package/dist/assets/glsl-DplSGwfg.js +1 -0
- package/dist/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/assets/go-Dn2_MT6a.js +1 -0
- package/dist/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/assets/groovy-D9Dt4D0W.js +1 -0
- package/dist/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/assets/hack-CaT9iCJl.js +1 -0
- package/dist/assets/haml-B8DHNrY2.js +1 -0
- package/dist/assets/handlebars-BL8al0AC.js +1 -0
- package/dist/assets/haskell-Cw1EW3IL.js +1 -0
- package/dist/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/assets/haxe-CzTSHFRz.js +1 -0
- package/dist/assets/haxe-H-WmDvRZ.js +1 -0
- package/dist/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/assets/hjson-D5-asLiD.js +1 -0
- package/dist/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/assets/houston-DnULxvSX.js +1 -0
- package/dist/assets/html-GMplVEZG.js +1 -0
- package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/dist/assets/http-DBlCnlav.js +1 -0
- package/dist/assets/http-jrhK8wxY.js +1 -0
- package/dist/assets/hurl-irOxFIW8.js +1 -0
- package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
- package/dist/assets/hy-DFXneXwc.js +1 -0
- package/dist/assets/idl-BEugSyMb.js +1 -0
- package/dist/assets/imba-DGztddWO.js +1 -0
- package/dist/assets/index-8c6bEJ99.js +1 -0
- package/dist/assets/index-AbWe21oh.js +2 -0
- package/dist/assets/index-ArhptQw0.js +1 -0
- package/dist/assets/index-B1hpa--1.js +3 -0
- package/dist/assets/index-Bafja8o4.js +1 -0
- package/dist/assets/index-Bp00uZNc.js +1 -0
- package/dist/assets/index-BsTieXqQ.js +1 -0
- package/dist/assets/index-BvGAWAqS.js +1 -0
- package/dist/assets/index-CCfVkFzN.js +1 -0
- package/dist/assets/index-D-Urq2hl.css +1 -0
- package/dist/assets/index-D3mXuuih.js +1 -0
- package/dist/assets/index-DFOLYN6W.js +1 -0
- package/dist/assets/index-DpxkOmNJ.js +7 -0
- package/dist/assets/index-YZ-iXB95.js +309 -0
- package/dist/assets/index-eA_XNQ_L.js +1 -0
- package/dist/assets/index-ftYom_wU.js +1 -0
- package/dist/assets/index-gvPT4BlL.js +1 -0
- package/dist/assets/ini-BEwlwnbL.js +1 -0
- package/dist/assets/java-CylS5w8V.js +1 -0
- package/dist/assets/javascript-iXu5QeM3.js +1 -0
- package/dist/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
- package/dist/assets/jison-wvAkD_A8.js +1 -0
- package/dist/assets/json-Cp-IABpG.js +1 -0
- package/dist/assets/json5-C9tS-k6U.js +1 -0
- package/dist/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/assets/julia-C8NyazO9.js +1 -0
- package/dist/assets/julia-DuME0IfC.js +1 -0
- package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/assets/kdl-DV7GczEv.js +1 -0
- package/dist/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/assets/kusto-BvAqAH-y.js +1 -0
- package/dist/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/assets/latex-BdAV_C_H.js +1 -0
- package/dist/assets/lean-Bc6EcWN3.js +1 -0
- package/dist/assets/less-B1dDrJ26.js +1 -0
- package/dist/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/assets/liquid-DYVedYrR.js +1 -0
- package/dist/assets/livescript-BwQOo05w.js +1 -0
- package/dist/assets/llvm-BtvRca6l.js +1 -0
- package/dist/assets/log-2UxHyX5q.js +1 -0
- package/dist/assets/logo-BtOb2qkB.js +1 -0
- package/dist/assets/lua-BbnMAYS6.js +1 -0
- package/dist/assets/lua-BgMRiT3U.js +1 -0
- package/dist/assets/luau-CXu1NL6O.js +1 -0
- package/dist/assets/make-CHLpvVh8.js +1 -0
- package/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/assets/marko-CPi9NSCl.js +1 -0
- package/dist/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/assets/mathematica-DTrFuWx2.js +1 -0
- package/dist/assets/matlab-D7o27uSR.js +1 -0
- package/dist/assets/mbox-CNhZ1qSd.js +1 -0
- package/dist/assets/mdc-DUICxH0z.js +1 -0
- package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/assets/mermaid-DKYwYmdq.js +1 -0
- package/dist/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/assets/min-light-CTRr51gU.js +1 -0
- package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/assets/mirc-CjQqDB4T.js +1 -0
- package/dist/assets/mllike-CXdrOF99.js +1 -0
- package/dist/assets/modelica-Dc1JOy9r.js +1 -0
- package/dist/assets/mojo-1DNp92w6.js +1 -0
- package/dist/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/assets/move-Bu9oaDYs.js +1 -0
- package/dist/assets/mscgen-BA5vi2Kp.js +1 -0
- package/dist/assets/mumps-BT43cFF4.js +1 -0
- package/dist/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/assets/nextflow-BrzmwbiE.js +1 -0
- package/dist/assets/nginx-DdIZxoE0.js +1 -0
- package/dist/assets/nginx-DknmC5AR.js +1 -0
- package/dist/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/assets/nim-CVrawwO9.js +1 -0
- package/dist/assets/nix-c8nO5XWb.js +1 -0
- package/dist/assets/nord-Ddv68eIx.js +1 -0
- package/dist/assets/nsis-LdVXkNf5.js +1 -0
- package/dist/assets/ntriples-BfvgReVJ.js +1 -0
- package/dist/assets/nushell-C-sUppwS.js +1 -0
- package/dist/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/assets/octave-Ck1zUtKM.js +1 -0
- package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/assets/one-light-PoHY5YXO.js +1 -0
- package/dist/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/assets/oz-BzwKVEFT.js +1 -0
- package/dist/assets/pascal--L3eBynH.js +1 -0
- package/dist/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/assets/perl-C0TMdlhV.js +1 -0
- package/dist/assets/perl-CdXCOZ3F.js +1 -0
- package/dist/assets/php-CDn_0X-4.js +1 -0
- package/dist/assets/pig-CevX1Tat.js +1 -0
- package/dist/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/assets/po-BTJTHyun.js +1 -0
- package/dist/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/assets/polar-C0HS_06l.js +1 -0
- package/dist/assets/postcss-CXtECtnM.js +1 -0
- package/dist/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/assets/powershell-CFHJl5sT.js +1 -0
- package/dist/assets/powershell-Dpen1YoG.js +1 -0
- package/dist/assets/prisma-Dd19v3D-.js +1 -0
- package/dist/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/assets/properties-C78fOPTZ.js +1 -0
- package/dist/assets/proto-DyJlTyXw.js +1 -0
- package/dist/assets/protobuf-ChK-085T.js +1 -0
- package/dist/assets/pug-CGlum2m_.js +1 -0
- package/dist/assets/pug-DeIclll2.js +1 -0
- package/dist/assets/puppet-BMWR74SV.js +1 -0
- package/dist/assets/puppet-DMA9R1ak.js +1 -0
- package/dist/assets/purescript-CklMAg4u.js +1 -0
- package/dist/assets/python-B6aJPvgy.js +1 -0
- package/dist/assets/python-BuPzkPfP.js +1 -0
- package/dist/assets/q-pXgVlZs6.js +1 -0
- package/dist/assets/qml-3beO22l8.js +1 -0
- package/dist/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/assets/qss-IeuSbFQv.js +1 -0
- package/dist/assets/r-B6wPVr8A.js +1 -0
- package/dist/assets/r-DiinP2Uv.js +1 -0
- package/dist/assets/racket-BqYA7rlc.js +1 -0
- package/dist/assets/raku-DXvB9xmW.js +1 -0
- package/dist/assets/razor-CE9lU5zL.js +1 -0
- package/dist/assets/red-bN70gL4F.js +1 -0
- package/dist/assets/reg-C-SQnVFl.js +1 -0
- package/dist/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/assets/rel-C3B-1QV4.js +1 -0
- package/dist/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
- package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/assets/rpm-CTu-6PCP.js +1 -0
- package/dist/assets/rst-B0xPkSld.js +1 -0
- package/dist/assets/ruby-B2Rjki9n.js +1 -0
- package/dist/assets/ruby-BvKwtOVI.js +1 -0
- package/dist/assets/rust-B1yitclQ.js +1 -0
- package/dist/assets/sas-B4kiWyti.js +1 -0
- package/dist/assets/sas-cz2c8ADy.js +1 -0
- package/dist/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/assets/scala-C151Ov-r.js +1 -0
- package/dist/assets/scheme-C41bIUwD.js +1 -0
- package/dist/assets/scheme-C98Dy4si.js +1 -0
- package/dist/assets/scss-OYdSNvt2.js +1 -0
- package/dist/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/assets/shell-CjFT_Tl9.js +1 -0
- package/dist/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/assets/sieve-C3Gn_uJK.js +1 -0
- package/dist/assets/simple-mode-GW_nhZxv.js +1 -0
- package/dist/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/assets/smalltalk-BERRCDM3.js +1 -0
- package/dist/assets/smalltalk-CnHTOXQT.js +1 -0
- package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/assets/solidity-rGO070M0.js +1 -0
- package/dist/assets/solr-DehyRSwq.js +1 -0
- package/dist/assets/soy-Brmx7dQM.js +1 -0
- package/dist/assets/sparql-DkYu6x3z.js +1 -0
- package/dist/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/assets/spreadsheet-BCZA_wO0.js +1 -0
- package/dist/assets/sql-BLtJtn59.js +1 -0
- package/dist/assets/sql-D0XecflT.js +1 -0
- package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/assets/stata-BH5u7GGu.js +1 -0
- package/dist/assets/stex-C3f8Ysf7.js +1 -0
- package/dist/assets/stylus-B533Al4x.js +1 -0
- package/dist/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/assets/svelte-3Dk4HxPD.js +1 -0
- package/dist/assets/swift-BzpIVaGY.js +1 -0
- package/dist/assets/swift-Dg5xB15N.js +1 -0
- package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/assets/system-verilog-CnnmHF94.js +1 -0
- package/dist/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/assets/tcl-DVfN8rqt.js +1 -0
- package/dist/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/assets/templ-W15q3VgB.js +1 -0
- package/dist/assets/terraform-BETggiCN.js +1 -0
- package/dist/assets/tex-CxkMU7Pf.js +1 -0
- package/dist/assets/textile-CnDTJFAw.js +1 -0
- package/dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
- package/dist/assets/tiki-DGYXhP31.js +1 -0
- package/dist/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/assets/toml-Bm5Em-hy.js +1 -0
- package/dist/assets/toml-vGWfd6FD.js +1 -0
- package/dist/assets/troff-wAsdV37c.js +1 -0
- package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/dist/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/assets/tsx-COt5Ahok.js +1 -0
- package/dist/assets/ttcn-CfJYG6tj.js +1 -0
- package/dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
- package/dist/assets/turtle-B1tBg_DP.js +1 -0
- package/dist/assets/turtle-BsS91CYL.js +1 -0
- package/dist/assets/twig-CO9l9SDP.js +1 -0
- package/dist/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/assets/typespec-BGHnOYBU.js +1 -0
- package/dist/assets/typst-DHCkPAjA.js +1 -0
- package/dist/assets/v-BcVCzyr7.js +1 -0
- package/dist/assets/vala-CsfeWuGM.js +1 -0
- package/dist/assets/vb-CmGdzxic.js +1 -0
- package/dist/assets/vb-D17OF-Vu.js +1 -0
- package/dist/assets/vbscript-BuJXcnF6.js +1 -0
- package/dist/assets/velocity-D8B20fx6.js +1 -0
- package/dist/assets/verilog-BQ8w6xss.js +1 -0
- package/dist/assets/verilog-C6RDOZhf.js +1 -0
- package/dist/assets/vesper-DU1UobuO.js +1 -0
- package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/assets/vhdl-lSbBsy5d.js +1 -0
- package/dist/assets/viml-CJc9bBzg.js +1 -0
- package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/assets/vue-DnHKYNfI.js +1 -0
- package/dist/assets/vue-html-CChd_i61.js +1 -0
- package/dist/assets/vue-vine-8moa0y9V.js +1 -0
- package/dist/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/assets/webidl-ZXfAyPTL.js +1 -0
- package/dist/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/assets/wit-5i3qLPDT.js +1 -0
- package/dist/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/assets/xquery-DzFWVndE.js +1 -0
- package/dist/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/assets/yacas-BJ4BC0dw.js +1 -0
- package/dist/assets/yaml-Buea-lGh.js +1 -0
- package/dist/assets/z80-Hz9HOZM7.js +1 -0
- package/dist/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/assets/zig-VOosw3JB.js +1 -0
- package/dist/index.html +47 -0
- package/dist/logo.svg +8 -0
- package/dist/openspec_pixel_dark.svg +89 -0
- package/dist/openspec_pixel_light.svg +89 -0
- package/index.html +46 -0
- package/package.json +66 -0
- package/src/App.tsx +124 -0
- package/src/components/StaticModeBanner.tsx +46 -0
- package/src/components/change-overview.tsx +156 -0
- package/src/components/cli-terminal.tsx +93 -0
- package/src/components/code-editor.tsx +232 -0
- package/src/components/copyable-path.tsx +44 -0
- package/src/components/dialog.tsx +193 -0
- package/src/components/folder-editor-viewer.tsx +411 -0
- package/src/components/global-archive-modal.tsx +205 -0
- package/src/components/layout/desktop-sidebar.tsx +48 -0
- package/src/components/layout/index.ts +6 -0
- package/src/components/layout/mobile-header.tsx +91 -0
- package/src/components/layout/mobile-tabbar.tsx +20 -0
- package/src/components/layout/nav-items.ts +33 -0
- package/src/components/layout/root-layout.tsx +67 -0
- package/src/components/layout/status-bar.tsx +69 -0
- package/src/components/markdown-content.tsx +104 -0
- package/src/components/markdown-viewer.tsx +415 -0
- package/src/components/path-marquee.tsx +104 -0
- package/src/components/tabs.tsx +151 -0
- package/src/components/tasks-view.test.tsx +45 -0
- package/src/components/tasks-view.tsx +209 -0
- package/src/components/toc-context.tsx +177 -0
- package/src/components/toc.tsx +290 -0
- package/src/entry-client.tsx +47 -0
- package/src/index.css +481 -0
- package/src/lib/api-config.ts +72 -0
- package/src/lib/archive-modal-context.tsx +45 -0
- package/src/lib/codemirror-markdown-preview.ts +494 -0
- package/src/lib/format-time.ts +51 -0
- package/src/lib/shiki-highlighter.ts +47 -0
- package/src/lib/static-data-provider.ts +386 -0
- package/src/lib/static-mode.ts +158 -0
- package/src/lib/trpc.ts +107 -0
- package/src/lib/use-cli-runner.tsx +433 -0
- package/src/lib/use-dark-mode.ts +28 -0
- package/src/lib/use-server-status.ts +208 -0
- package/src/lib/use-subscription.ts +375 -0
- package/src/lib/use-tabs-status-by-query.ts +78 -0
- package/src/main.tsx +9 -0
- package/src/routes/archive-list.tsx +65 -0
- package/src/routes/archive-view.tsx +116 -0
- package/src/routes/change-list.tsx +63 -0
- package/src/routes/change-view.tsx +188 -0
- package/src/routes/dashboard.tsx +204 -0
- package/src/routes/project.tsx +272 -0
- package/src/routes/settings.tsx +816 -0
- package/src/routes/spec-list.tsx +49 -0
- package/src/routes/spec-view.tsx +164 -0
- package/src/ssg/entry-server.tsx +111 -0
- package/src/ssg/index.ts +6 -0
- package/src/ssg/prerender.ts +111 -0
- package/src/ssg/static-data-context.tsx +49 -0
- package/src/ssg/types.ts +5 -0
- package/src/test/setup.ts +1 -0
- package/src/vite-env.d.ts +6 -0
- package/tsconfig.json +18 -0
- 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
|
+
}
|
package/src/lib/trpc.ts
ADDED
|
@@ -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>>)
|