@hienlh/ppm 0.20.10 → 0.21.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/CHANGELOG.md +108 -0
- package/CLAUDE.md +42 -1
- package/LICENSE +5 -0
- package/THIRD-PARTY-NOTICES.md +83 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/bun.lock +38 -7
- package/dist/web/assets/KaTeX_Size3-Regular-gV2CO0n9.woff2 +0 -0
- package/dist/web/assets/accounts-settings-section-BuxD9zH3.js +1 -0
- package/dist/web/assets/ai-resource-editor-F09pf8Hd.js +1 -0
- package/dist/web/assets/ai-settings-section-Dd9tOUp0.js +1 -0
- package/dist/web/assets/ai-settings-section-FrU2X8Fu.js +1 -0
- package/dist/web/assets/{angular-html-D4qjt-75.js → angular-html-DkR4iCth.js} +1 -1
- package/dist/web/assets/{angular-ts-DvLn04T8.js → angular-ts-DcyL4Chx.js} +1 -1
- package/dist/web/assets/api-client-BUCo1lms.js +1 -0
- package/dist/web/assets/{api-client-DCzgxFNY.js → api-client-bfB7cXRM.js} +1 -1
- package/dist/web/assets/{api-settings-t5xLrBkQ.js → api-settings-BcNjZIvG.js} +1 -1
- package/dist/web/assets/{api-themes-CJmyQeMk.js → api-themes-DBfyVUtX.js} +1 -1
- package/dist/web/assets/{apl-DQOoPzqd.js → apl-BVlrVtjt.js} +1 -1
- package/dist/web/assets/appearance-settings-section-whgnq3ss.js +1 -0
- package/dist/web/assets/architecture-PBZL5I3N-5K0wEkAn.js +1 -0
- package/dist/web/assets/{astro-C2zFJ1Er.js → astro-MjJlozLj.js} +1 -1
- package/dist/web/assets/audio-preview-Bc54GCAV.js +1 -0
- package/dist/web/assets/{blade-CBD8sEa1.js → blade-DnJWi1fz.js} +1 -1
- package/dist/web/assets/{bsl-bs2JpeTQ.js → bsl-DCmJxSIz.js} +1 -1
- package/dist/web/assets/{button-DHI8IY_N.js → button-VW4QGKCn.js} +1 -1
- package/dist/web/assets/{cairo-DT2g4i_6.js → cairo-C8dDenub.js} +1 -1
- package/dist/web/assets/chat-tab-Cr6_KSGO.js +15 -0
- package/dist/web/assets/{cobol-B2rp6LA1.js → cobol-DPx_nifl.js} +1 -1
- package/dist/web/assets/code-editor-DfmlGamv.js +7 -0
- package/dist/web/assets/codex-daily-guard-CfybHv_c.js +1 -0
- package/dist/web/assets/{coffee-D5ShQC08.js → coffee-DvFzqhgN.js} +1 -1
- package/dist/web/assets/conflict-editor-DenQUOT2.js +19 -0
- package/dist/web/assets/context-menu-DOODKZdF.js +1 -0
- package/dist/web/assets/{cpp-BmKOH-E0.js → cpp-BLJN0umi.js} +1 -1
- package/dist/web/assets/{createLucideIcon-CLMdC3Kl.js → createLucideIcon-DoiEKeJ_.js} +1 -1
- package/dist/web/assets/{crystal-B7u_ZTpu.js → crystal-BXR-9fGw.js} +1 -1
- package/dist/web/assets/csv-preview-CClrJOuR.js +2 -0
- package/dist/web/assets/{data-grid-overlay-editor-DJWgclot.js → data-grid-overlay-editor-D4fhcMfT.js} +1 -1
- package/dist/web/assets/{data-grid-types-Uu77aFvI.js → data-grid-types-OgUxMLdQ.js} +1 -1
- package/dist/web/assets/database-viewer-DItjm8wB.js +1 -0
- package/dist/web/assets/dialog-DQTn55Mt.js +1 -0
- package/dist/web/assets/diff-viewer-BpNj7pN9.js +4 -0
- package/dist/web/assets/{dist-BTdRgQig.js → dist-CrBOCtCW.js} +1 -1
- package/dist/web/assets/docx-preview-DYBkiUaE.js +12 -0
- package/dist/web/assets/{edge--MpXROh5.js → edge-rWOlCmXT.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-ESj6hMoD.js → edit-diff-preview-COtmo54G.js} +3 -3
- package/dist/web/assets/editor-font-BDrdiGf1.js +1 -0
- package/dist/web/assets/editor-language-service-DxkZ51E5.js +1 -0
- package/dist/web/assets/{elixir-DL8mOfzH.js → elixir-E7Y82okW.js} +1 -1
- package/dist/web/assets/{elm-eVlzIFEZ.js → elm-DTPGbc-w.js} +1 -1
- package/dist/web/assets/{erb-BgvaH9l0.js → erb-DHqLHrE6.js} +1 -1
- package/dist/web/assets/{erlang-CEf8Sfhs.js → erlang-Byg0nNiV.js} +1 -1
- package/dist/web/assets/{esm-C5xqy163.js → esm-D_DmOM7n.js} +2 -2
- package/dist/web/assets/explorer-body-D-5z464e.js +2 -0
- package/dist/web/assets/explorer-window-content-7-1wuRul.js +1 -0
- package/dist/web/assets/extension-manager-section-BhwB6nqr.js +1 -0
- package/dist/web/assets/extension-webview-DI4VL2tJ.js +12 -0
- package/dist/web/assets/file-icons-EzPL0q-k.js +1 -0
- package/dist/web/assets/file-icons.generated-CfaJuvZu.css +1 -0
- package/dist/web/assets/file-store-DMABxOkV.js +1 -0
- package/dist/web/assets/files-settings-section-CZzABuKz.js +1 -0
- package/dist/web/assets/format-file-meta-DOpzJJhS.js +1 -0
- package/dist/web/assets/{fortran-fixed-form-yAUsSjab.js → fortran-fixed-form-CY1n0Xf6.js} +1 -1
- package/dist/web/assets/{fsharp-BEWvY_ZR.js → fsharp-_vEDSCJz.js} +1 -1
- package/dist/web/assets/{gdresource-CYZFZ057.js → gdresource-B6XT0wAC.js} +1 -1
- package/dist/web/assets/geist-cyrillic-ext-wght-italic-BYAq_K0C.woff2 +0 -0
- package/dist/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/web/assets/geist-cyrillic-wght-italic-Da0gXVk3.woff2 +0 -0
- package/dist/web/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/web/assets/geist-latin-ext-wght-italic-XgKbg5n7.woff2 +0 -0
- package/dist/web/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/web/assets/geist-latin-wght-italic-dTnRTFFJ.woff2 +0 -0
- package/dist/web/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/web/assets/geist-vietnamese-wght-italic-0fly6zkB.woff2 +0 -0
- package/dist/web/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/web/assets/general-settings-section-BcxwiZ0X.js +1 -0
- package/dist/web/assets/{git-commit-DedchUJ6.js → git-commit-Wk9ovq59.js} +1 -1
- package/dist/web/assets/git-log-panel-CRN4JVOx.js +1 -0
- package/dist/web/assets/{git-rebase-DPvHNzQr.js → git-rebase-DSarGPvK.js} +1 -1
- package/dist/web/assets/git-repo-store-Dy69YCHN.js +1 -0
- package/dist/web/assets/gitGraph-HDMCJU4V-DkVT2MAM.js +1 -0
- package/dist/web/assets/glide-data-grid-BvgAqSUr.js +141 -0
- package/dist/web/assets/{glimmer-js-B4hPYBMX.js → glimmer-js-CkYI35_P.js} +1 -1
- package/dist/web/assets/{glimmer-ts-C0WfcQnO.js → glimmer-ts-BqmIZcds.js} +1 -1
- package/dist/web/assets/{glsl-DHW88hTv.js → glsl-Be-yBCF5.js} +1 -1
- package/dist/web/assets/{graphql-CEvXbo6e.js → graphql-a5DrENHY.js} +1 -1
- package/dist/web/assets/group-chat-tab-DFa5mAx5.js +1 -0
- package/dist/web/assets/{hack-lKfhn1vw.js → hack-BLAg20aD.js} +1 -1
- package/dist/web/assets/{haml-AjKlANaB.js → haml-Dj6bGOQH.js} +1 -1
- package/dist/web/assets/{handlebars-B8fZzj2G.js → handlebars-dmEa36Oh.js} +1 -1
- package/dist/web/assets/{html-derivative-VZmoMdQD.js → html-derivative-lLi3-RNT.js} +1 -1
- package/dist/web/assets/{html-H_S3FJMj.js → html-yacZYzSE.js} +1 -1
- package/dist/web/assets/{http-DBxROFKc.js → http-1KaxcE4e.js} +1 -1
- package/dist/web/assets/{hurl-Hf7XWQHN.js → hurl-ST-dEEZR.js} +1 -1
- package/dist/web/assets/{hxml-BRhRKwSo.js → hxml-CpDtuq__.js} +1 -1
- package/dist/web/assets/icons-DQjqk0lJ.js +1 -0
- package/dist/web/assets/image-preview-CJVxL0uH.js +1 -0
- package/dist/web/assets/index-D7DbXD3G.css +1 -0
- package/dist/web/assets/index-ZtfxZOyb.js +52 -0
- package/dist/web/assets/info-3K5VOQVL-BBsmKGzA.js +1 -0
- package/dist/web/assets/input-D-dR8RI6.js +1 -0
- package/dist/web/assets/{jinja-D3jMH0jG.js → jinja-Cjw-evAn.js} +1 -1
- package/dist/web/assets/{jira-watcher-section-DZvWeUAW.js → jira-watcher-section-DIC1yIV3.js} +1 -1
- package/dist/web/assets/{jison-CZtpkLiY.js → jison-DfATMYoY.js} +1 -1
- package/dist/web/assets/{julia-DwFjOpos.js → julia-DDCaxiqT.js} +1 -1
- package/dist/web/assets/{just-BEfj8dHN.js → just-CJL529u6.js} +1 -1
- package/dist/web/assets/keybindings-store-tVfhPANS.js +1 -0
- package/dist/web/assets/keyboard-shortcuts-section-BW03P3AF.js +1 -0
- package/dist/web/assets/{latex-C6Rb_zGG.js → latex-Zc4EpLpW.js} +1 -1
- package/dist/web/assets/{lib-CFTK00ux.js → lib-BVwmtv2i.js} +1 -1
- package/dist/web/assets/{liquid-DTVs9cD3.js → liquid-B_6KMNYS.js} +1 -1
- package/dist/web/assets/{lua-C1zfiqhG.js → lua-BtS2idK7.js} +1 -1
- package/dist/web/assets/markdown-renderer-CvL1pWeK.js +3 -0
- package/dist/web/assets/markdown-renderer-sJNNVhlS.js +1 -0
- package/dist/web/assets/{marko-_hrXozl2.js → marko-Wk6LBnck.js} +1 -1
- package/dist/web/assets/{mdc-AX9XWu8K.js → mdc-cRaXBrzL.js} +1 -1
- package/dist/web/assets/{media-url-D43IHXnP.js → media-url-DL8OCGGg.js} +1 -1
- package/dist/web/assets/{mobile-bottom-sheet-GSto0_0m.js → mobile-bottom-sheet-CoUauvLF.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-CZ0HZ2E_.js +1 -0
- package/dist/web/assets/monaco-dotenv-language-BDYnKcnr.js +1 -0
- package/dist/web/assets/monaspace-argon-latin-400-italic-DHf095HZ.woff2 +0 -0
- package/dist/web/assets/monaspace-argon-latin-400-italic-DZMiIHEH.woff +0 -0
- package/dist/web/assets/monaspace-argon-latin-400-normal-DZUN4ACH.woff +0 -0
- package/dist/web/assets/monaspace-argon-latin-400-normal-RS-2TGNg.woff2 +0 -0
- package/dist/web/assets/monaspace-argon-latin-700-normal-4y--rLW1.woff +0 -0
- package/dist/web/assets/monaspace-argon-latin-700-normal-D9kWRRK5.woff2 +0 -0
- package/dist/web/assets/monaspace-krypton-latin-400-italic-BoBCEexI.woff2 +0 -0
- package/dist/web/assets/monaspace-krypton-latin-400-italic-LWEicbvC.woff +0 -0
- package/dist/web/assets/monaspace-krypton-latin-400-normal-D9XlxC9R.woff +0 -0
- package/dist/web/assets/monaspace-krypton-latin-400-normal-DsuVXUab.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-codicons-DSvMY_FK.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-devicons-BBab8P54.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-font-awesome-BzNW1pRA.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-font-awesome-ext-D30e--UY.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-font-awesome-legacy-D_qekXx9.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-font-logos-gdu3INfy.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-iec-power-Cw6TNeDf.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-material-l-CXi9Ay.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-misc-BaVfdyeB.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-octicons-CJLTTzKm.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-pomicons-D7T3Ya3H.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-powerline-Cgg0sdGS.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-seti-DYiUFq6z.woff2 +0 -0
- package/dist/web/assets/nerd-symbols-weather-D4Jrp5XD.woff2 +0 -0
- package/dist/web/assets/{nextflow-xJ5dkaQ2.js → nextflow-Bos2wvDV.js} +1 -1
- package/dist/web/assets/{nginx-BfbjvmIV.js → nginx-DMlOwzdr.js} +1 -1
- package/dist/web/assets/{nim-KrUnNSwZ.js → nim-D2dZQA88.js} +1 -1
- package/dist/web/assets/notification-store-BZbsPnW0.js +1 -0
- package/dist/web/assets/notifications-settings-section-DPUROMw-.js +1 -0
- package/dist/web/assets/{number-overlay-editor-CGZ1ObrN.js → number-overlay-editor-DZ2i_Bnb.js} +1 -1
- package/dist/web/assets/{overview-panel-Ni1Wqr3E.js → overview-panel-R146OIom.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-DwmYPOlx.js +1 -0
- package/dist/web/assets/panel-store-BVLBRn6M.js +1 -0
- package/dist/web/assets/pdf-preview-BWUPGLp6.js +1 -0
- package/dist/web/assets/{perl-DAexWIeo.js → perl-C5-Z6fPn.js} +1 -1
- package/dist/web/assets/{php-DXc7GdU9.js → php-BXNNhkMH.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-D0oogIFi.js +1 -0
- package/dist/web/assets/portal-container-context-BarKmT4S.js +1 -0
- package/dist/web/assets/{postgres-viewer-DmbVhmJ8.js → postgres-viewer-CjOvaruz.js} +3 -3
- package/dist/web/assets/ppmbot-settings-section-DrvWh8l8.js +1 -0
- package/dist/web/assets/problems-panel-B7BWVhdy.js +1 -0
- package/dist/web/assets/process-table-BRMS1MrX.js +1 -0
- package/dist/web/assets/{project-store-DCDLF-x3.js → project-store-BhMbVln3.js} +1 -1
- package/dist/web/assets/proxy-settings-section-Bv0Ny-Yy.js +1 -0
- package/dist/web/assets/{pug-CHds8FDl.js → pug-C1zf1yWy.js} +1 -1
- package/dist/web/assets/{qml-DBt6oNnU.js → qml-OW58jGpD.js} +1 -1
- package/dist/web/assets/query-audit-section-BcHJZcVC.js +1 -0
- package/dist/web/assets/radar-KQ55EAFF-CQIJOQGa.js +1 -0
- package/dist/web/assets/{razor-DVDe2z8Z.js → razor-DzjSaobM.js} +1 -1
- package/dist/web/assets/{react-Bf5xrFLG.js → react-Bghu0NUO.js} +1 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-ByjaeZKX.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-view-D13mtr9F.js +1 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BTzss2wX.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-CbqTCaC6.js +1 -0
- package/dist/web/assets/{rst-s3rP0H8p.js → rst-RfuihOUW.js} +1 -1
- package/dist/web/assets/{ruby-sRcfbjlr.js → ruby-CNO3pli1.js} +1 -1
- package/dist/web/assets/{run-in-terminal-Yt_lq4T9.js → run-in-terminal-Cb_hVU8x.js} +1 -1
- package/dist/web/assets/{sas-CuyZeQJw.js → sas-DZY5BtXx.js} +1 -1
- package/dist/web/assets/schedules-settings-section-DO8xAOVj.js +1 -0
- package/dist/web/assets/scroll-area-LtNV8g5o.js +1 -0
- package/dist/web/assets/{scss-B9m4FneT.js → scss--4g-REcN.js} +1 -1
- package/dist/web/assets/{send-to-chat-01eMNs3j.js → send-to-chat-Cnpru1M0.js} +1 -1
- package/dist/web/assets/separator-Cds1yxy8.js +1 -0
- package/dist/web/assets/settings-body-Rnu-FcX-.js +2 -0
- package/dist/web/assets/settings-store-DZPgPtEA.js +2 -0
- package/dist/web/assets/settings-tab-C6PHxs0Z.js +1 -0
- package/dist/web/assets/settings-window-content-CQ4gT2qj.js +1 -0
- package/dist/web/assets/{shaderlab-BuCltaXx.js → shaderlab-Cu4sBiVn.js} +1 -1
- package/dist/web/assets/{shellsession-DG_WIFRW.js → shellsession-DWzJfEv7.js} +1 -1
- package/dist/web/assets/{soy-CKNCwmqR.js → soy-BnqE-5Ff.js} +1 -1
- package/dist/web/assets/{sparql-BEH92-9e.js → sparql-Ctg__NhZ.js} +1 -1
- package/dist/web/assets/{sql-query-editor-BTMEy88p.js → sql-query-editor-D9k19T_M.js} +1 -1
- package/dist/web/assets/sqlite-viewer-DoV9hnWJ.js +1 -0
- package/dist/web/assets/{stata-Bt5IUWCl.js → stata-Qk2h66XW.js} +1 -1
- package/dist/web/assets/{streaming-store-Dw3ZR1E4.js → streaming-store-uDu3PoN1.js} +1 -1
- package/dist/web/assets/{surrealql-B5M94PT2.js → surrealql-8QEX7EfH.js} +1 -1
- package/dist/web/assets/{svelte-BqLoF5fB.js → svelte-D_mubC5-.js} +1 -1
- package/dist/web/assets/system-monitor-body-2vQ1kMxE.js +2 -0
- package/dist/web/assets/system-monitor-tab-krAcvwF7.js +1 -0
- package/dist/web/assets/system-monitor-window-content-qXLcicFM.js +1 -0
- package/dist/web/assets/tab-host-window-content-7fPZNEni.js +1 -0
- package/dist/web/assets/{tab-store-Dsk4jnlN.js → tab-store-DGJGnbwv.js} +1 -1
- package/dist/web/assets/team-member-sheet-2FnRmk1a.js +2 -0
- package/dist/web/assets/team-member-window-content-BgvJFypM.js +1 -0
- package/dist/web/assets/{templ-BxGWIwYz.js → templ-C1jV0fsO.js} +1 -1
- package/dist/web/assets/terminal-tab-Cs0sGljx.js +3 -0
- package/dist/web/assets/{tex-B9CPrNBA.js → tex-D_StFXy_.js} +1 -1
- package/dist/web/assets/tool-cards-DU_S2o51.js +9 -0
- package/dist/web/assets/treemap-KZPCXAKY-BhEtjljr.js +1 -0
- package/dist/web/assets/{ts-tags-CObhnP_s.js → ts-tags-B5m47rEm.js} +1 -1
- package/dist/web/assets/{twig-ZcDaz0E8.js → twig-C_br6GIl.js} +1 -1
- package/dist/web/assets/{use-blob-url-D-NnFGAr.js → use-blob-url-C-SGi_Hb.js} +1 -1
- package/dist/web/assets/use-inline-blame-B4trxGcR.js +16 -0
- package/dist/web/assets/{use-is-mobile-BsqeOLv4.js → use-is-mobile-BQ9Bv5Ga.js} +1 -1
- package/dist/web/assets/use-lsp-CV0vzILO.js +6 -0
- package/dist/web/assets/use-monaco-theme-DBqbWjWX.js +1 -0
- package/dist/web/assets/use-open-team-member-DENsjp0s.js +1 -0
- package/dist/web/assets/use-remote-desktop-display-choice-BK_f787P.js +1 -0
- package/dist/web/assets/{use-visual-viewport-hdC_hRtB.js → use-visual-viewport-CbwnktSG.js} +1 -1
- package/dist/web/assets/{use-websocket-CUKjQFAl.js → use-websocket-LgXiX1qN.js} +1 -1
- package/dist/web/assets/vendor-markdown-CuWCHIVb.js +291 -0
- package/dist/web/assets/{vendor-mermaid-BoRFiriK.js → vendor-mermaid-Cbig5zA6.js} +1 -1
- package/dist/web/assets/{vendor-ui-D1NQnrtd.js → vendor-ui-BBdkypKW.js} +1 -1
- package/dist/web/assets/video-preview-BDNwumbW.js +1 -0
- package/dist/web/assets/{vue-TgfQfAF8.js → vue-DQwCnLdr.js} +1 -1
- package/dist/web/assets/{vue-html-DbAh9aHW.js → vue-html-T_EoGpPJ.js} +1 -1
- package/dist/web/assets/{vue-vine-DQ8US6vO.js → vue-vine-DmxLqX50.js} +1 -1
- package/dist/web/assets/{window-pip-registry-DfPfSFQg.js → window-pip-registry-3l4hoxuD.js} +1 -1
- package/dist/web/assets/{window-store-BSXqIkwB.js → window-store-UC1jJeLM.js} +1 -1
- package/dist/web/assets/ws-auth-DEAJiGCR.js +1 -0
- package/dist/web/assets/{xml-CXzUNYMl.js → xml-Bs6Bw8is.js} +1 -1
- package/dist/web/assets/{xsl-CdnFww1s.js → xsl-f5ZNhRCc.js} +1 -1
- package/dist/web/index.html +107 -73
- package/dist/web/sw.js +1 -1
- package/docs/project-roadmap.md +2 -0
- package/licenses/Apache-2.0.txt +73 -0
- package/licenses/CC-BY-4.0.txt +156 -0
- package/licenses/MIT.txt +18 -0
- package/licenses/OFL-1.1.txt +43 -0
- package/licenses/Unlicense.txt +10 -0
- package/package.json +14 -7
- package/packages/ext-git-graph/src/blame-view.ts +4 -5
- package/packages/ext-git-graph/src/commit-detail-escaping.test.ts +205 -0
- package/packages/ext-git-graph/src/commit-detail-file-cap.test.ts +65 -0
- package/packages/ext-git-graph/src/commit-message-html.test.ts +214 -0
- package/packages/ext-git-graph/src/commit-message-html.ts +190 -0
- package/packages/ext-git-graph/src/commit-request-generation.test.ts +57 -0
- package/packages/ext-git-graph/src/compare-view.ts +4 -5
- package/packages/ext-git-graph/src/extension.ts +148 -36
- package/packages/ext-git-graph/src/file-history-view.ts +4 -5
- package/packages/ext-git-graph/src/log-args.test.ts +57 -0
- package/packages/ext-git-graph/src/ppm-api.ts +39 -6
- package/packages/ext-git-graph/src/project-scope.test.ts +77 -0
- package/packages/ext-git-graph/src/project-scope.ts +69 -0
- package/packages/ext-git-graph/src/shortstat-parser.test.ts +53 -0
- package/packages/ext-git-graph/src/shortstat-parser.ts +45 -0
- package/packages/ext-git-graph/src/types.ts +2 -0
- package/packages/ext-git-graph/src/webview-html.test.ts +407 -0
- package/packages/ext-git-graph/src/webview-html.ts +631 -108
- package/packages/ext-git-graph/src/webview-shell.test.ts +63 -0
- package/packages/ext-git-graph/src/webview-shell.ts +48 -7
- package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- package/scripts/check-ppm-dir-usage.sh +0 -0
- package/scripts/copy-monaco.ts +63 -0
- package/scripts/gen-file-icons.ts +485 -0
- package/scripts/gen-nerd-font.ts +311 -0
- package/scripts/gen-product-icons.ts +442 -0
- package/scripts/install.sh +0 -0
- package/scripts/monaco-staging.ts +32 -0
- package/scripts/precompress-web.ts +77 -0
- package/scripts/release.sh +0 -0
- package/scripts/third-party-notices.ts +160 -0
- package/scripts/vite-monaco-dev-assets.ts +63 -0
- package/src/providers/claude-agent-sdk.ts +32 -2
- package/src/server/index.ts +17 -0
- package/src/server/routes/chat.ts +16 -6
- package/src/server/routes/git.ts +113 -1
- package/src/server/routes/lsp.ts +58 -0
- package/src/server/routes/project-scoped.ts +2 -0
- package/src/server/routes/static-encoding.ts +73 -0
- package/src/server/routes/static-fallback.ts +51 -0
- package/src/server/routes/static.ts +41 -5
- package/src/server/ws/lsp.ts +433 -0
- package/src/services/chat-search.service.ts +211 -26
- package/src/services/edge-forwarder.ts +191 -191
- package/src/services/fs-ops/fs-real-path.ts +23 -0
- package/src/services/git-blame/commit-line-diff.ts +124 -0
- package/src/services/git-blame/git-blame.service.ts +96 -1
- package/src/services/git-repos/git-repo-discovery.ts +152 -0
- package/src/services/lsp/lsp-capabilities.ts +160 -0
- package/src/services/lsp/lsp-manager.ts +442 -0
- package/src/services/lsp/lsp-protocol.ts +170 -0
- package/src/services/lsp/lsp-session.ts +466 -0
- package/src/services/lsp/server-registry.ts +401 -0
- package/src/services/search-index-db.service.ts +10 -2
- package/src/services/windows-process-tree.ts +351 -351
- package/src/shared/blame.ts +51 -0
- package/src/shared/lsp-uri.ts +108 -0
- package/src/web/app.tsx +6 -0
- package/src/web/components/ai-resources/ai-resource-editor.tsx +1 -1
- package/src/web/components/ai-resources/ai-resources-panel.tsx +1 -1
- package/src/web/components/ai-resources/mcp-group.tsx +1 -1
- package/src/web/components/ai-resources/new-resource-menu.tsx +1 -1
- package/src/web/components/ai-resources/resource-visuals.tsx +1 -1
- package/src/web/components/auth/login-screen.tsx +1 -1
- package/src/web/components/auth/support-dialog.tsx +1 -1
- package/src/web/components/chat/attachment-chips.tsx +113 -5
- package/src/web/components/chat/background-command-bar.tsx +1 -1
- package/src/web/components/chat/background-output-panel.tsx +1 -1
- package/src/web/components/chat/change-edit-list.tsx +1 -1
- package/src/web/components/chat/change-file-row.tsx +1 -1
- package/src/web/components/chat/chat-history-bar.tsx +2 -2
- package/src/web/components/chat/chat-history-panel.tsx +1 -1
- package/src/web/components/chat/chat-placeholder.tsx +1 -1
- package/src/web/components/chat/chat-scroll-nav.tsx +1 -1
- package/src/web/components/chat/chat-tab.tsx +1 -1
- package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +1 -1
- package/src/web/components/chat/chat-welcome.tsx +1 -1
- package/src/web/components/chat/codex-usage-panel.tsx +1 -1
- package/src/web/components/chat/file-picker.tsx +1 -1
- package/src/web/components/chat/image-preview-states.tsx +1 -1
- package/src/web/components/chat/message-action-bar.tsx +1 -1
- package/src/web/components/chat/message-input.tsx +1 -1
- package/src/web/components/chat/message-list.tsx +1 -1
- package/src/web/components/chat/mode-selector.tsx +1 -1
- package/src/web/components/chat/model-selector.tsx +1 -1
- package/src/web/components/chat/model-thinking-selector.tsx +1 -1
- package/src/web/components/chat/pre-compact-button.tsx +1 -1
- package/src/web/components/chat/provider-selector.tsx +1 -1
- package/src/web/components/chat/send-message-card.tsx +1 -1
- package/src/web/components/chat/session-context-menu.tsx +1 -1
- package/src/web/components/chat/session-debug-dialog.tsx +1 -1
- package/src/web/components/chat/session-history-list.tsx +1 -1
- package/src/web/components/chat/session-list-panel.tsx +1 -1
- package/src/web/components/chat/session-picker.tsx +1 -1
- package/src/web/components/chat/slash-command-picker.tsx +1 -1
- package/src/web/components/chat/task-tracker.tsx +1 -1
- package/src/web/components/chat/team-activity-panel.tsx +1 -1
- package/src/web/components/chat/team-member-activity-row.tsx +1 -1
- package/src/web/components/chat/team-member-list.tsx +1 -1
- package/src/web/components/chat/team-member-sheet.tsx +1 -1
- package/src/web/components/chat/team-member-window-content.tsx +1 -1
- package/src/web/components/chat/team-working-bar.tsx +1 -1
- package/src/web/components/chat/tool-cards.tsx +2 -2
- package/src/web/components/chat/turn-change-sheet.tsx +1 -1
- package/src/web/components/chat/turn-change-tray.tsx +1 -1
- package/src/web/components/chat/turn-cost-warning.tsx +1 -1
- package/src/web/components/chat/usage-badge.tsx +1 -1
- package/src/web/components/chat/usage-panel-shell.tsx +1 -1
- package/src/web/components/chat/version-switcher.tsx +1 -1
- package/src/web/components/database/connection-import-export.tsx +1 -1
- package/src/web/components/database/connection-list.tsx +1 -1
- package/src/web/components/database/connection-row.tsx +1 -1
- package/src/web/components/database/database-sidebar.tsx +1 -1
- package/src/web/components/database/database-viewer.tsx +1 -1
- package/src/web/components/database/export-button.tsx +1 -1
- package/src/web/components/database/glide-context-menu.tsx +1 -1
- package/src/web/components/database/glide-data-grid.tsx +1 -1
- package/src/web/components/database/glide-data-preview-panel.tsx +2 -2
- package/src/web/components/database/glide-grid-pagination.tsx +1 -1
- package/src/web/components/database/glide-grid-toolbar.tsx +1 -1
- package/src/web/components/database/glide-header-menu.tsx +1 -1
- package/src/web/components/database/glide-save-bar.tsx +1 -1
- package/src/web/components/database/schema-table-tree.tsx +1 -1
- package/src/web/components/editor/audio-preview.tsx +1 -1
- package/src/web/components/editor/code-editor.tsx +167 -21
- package/src/web/components/editor/compare-picker.tsx +1 -1
- package/src/web/components/editor/conflict-editor.tsx +15 -6
- package/src/web/components/editor/csv-preview.tsx +1 -1
- package/src/web/components/editor/diff-viewer.tsx +59 -37
- package/src/web/components/editor/docx-preview.tsx +1 -1
- package/src/web/components/editor/editor-breadcrumb-external.tsx +1 -1
- package/src/web/components/editor/editor-breadcrumb.tsx +1 -1
- package/src/web/components/editor/editor-language-picker.tsx +3 -1
- package/src/web/components/editor/editor-language-service.tsx +77 -0
- package/src/web/components/editor/editor-mobile-toolbar.tsx +13 -2
- package/src/web/components/editor/editor-placeholder.tsx +1 -1
- package/src/web/components/editor/editor-toolbar.tsx +1 -1
- package/src/web/components/editor/image-preview.tsx +1 -1
- package/src/web/components/editor/lsp-status.tsx +241 -0
- package/src/web/components/editor/pdf-preview.tsx +1 -1
- package/src/web/components/editor/video-player/video-player-controls.tsx +1 -1
- package/src/web/components/editor/video-player/video-player.tsx +1 -1
- package/src/web/components/editor/video-player/video-settings-menu.tsx +1 -1
- package/src/web/components/editor/video-preview.tsx +1 -1
- package/src/web/components/explorer/file-tree.tsx +1 -1
- package/src/web/components/explorer/inline-tree-input.tsx +1 -1
- package/src/web/components/explorer/search-panel.tsx +3 -2
- package/src/web/components/explorer/tree-node-context-menu.tsx +1 -1
- package/src/web/components/explorer/tree-node.tsx +5 -12
- package/src/web/components/extensions/extension-quickpick.tsx +1 -1
- package/src/web/components/extensions/extension-tree-view.tsx +1 -1
- package/src/web/components/extensions/extension-webview.tsx +53 -20
- package/src/web/components/extensions/webview-theme.ts +121 -0
- package/src/web/components/floating-window/pip/pip-caption-button.tsx +1 -1
- package/src/web/components/git/create-worktree-dialog.tsx +5 -3
- package/src/web/components/git/git-log-panel.tsx +4 -2
- package/src/web/components/git/git-placeholder.tsx +1 -1
- package/src/web/components/git/git-ref-badge.tsx +1 -1
- package/src/web/components/git/git-repo-picker.tsx +145 -0
- package/src/web/components/git/git-status-panel.tsx +231 -250
- package/src/web/components/git/git-worktree-panel.tsx +6 -4
- package/src/web/components/git/hunk-stage-dialog.tsx +5 -3
- package/src/web/components/group-chat/group-chat-tab.tsx +1 -1
- package/src/web/components/group-chat/group-create-dialog.tsx +1 -1
- package/src/web/components/group-chat/group-full-transcript-view.tsx +1 -1
- package/src/web/components/group-chat/group-list.tsx +1 -1
- package/src/web/components/group-chat/group-member-edit-dialog.tsx +1 -1
- package/src/web/components/group-chat/group-member-roster.tsx +1 -1
- package/src/web/components/group-chat/group-message-item.tsx +1 -1
- package/src/web/components/group-chat/group-transcript-messages.tsx +1 -1
- package/src/web/components/jira/jira-config-form.tsx +1 -1
- package/src/web/components/jira/jira-filter-builder.tsx +1 -1
- package/src/web/components/jira/jira-panel.tsx +1 -1
- package/src/web/components/jira/jira-results-panel.tsx +1 -1
- package/src/web/components/jira/jira-ticket-card.tsx +1 -1
- package/src/web/components/jira/jira-ticket-detail.tsx +1 -1
- package/src/web/components/jira/jira-watcher-form.tsx +1 -1
- package/src/web/components/jira/jira-watcher-list.tsx +1 -1
- package/src/web/components/layout/add-project-form.tsx +1 -1
- package/src/web/components/layout/cloud-alias-row.tsx +1 -1
- package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +1 -1
- package/src/web/components/layout/cloud-share-popover.tsx +1 -1
- package/src/web/components/layout/command-palette-filter-chips.tsx +1 -1
- package/src/web/components/layout/command-palette.tsx +46 -8
- package/src/web/components/layout/dock-header.tsx +4 -4
- package/src/web/components/layout/dock-panel.tsx +3 -3
- package/src/web/components/layout/draggable-tab.tsx +20 -3
- package/src/web/components/layout/editor-panel.tsx +1 -1
- package/src/web/components/layout/mobile-drawer-tab-bar.tsx +10 -1
- package/src/web/components/layout/mobile-drawer.tsx +1 -1
- package/src/web/components/layout/mobile-nav.tsx +3 -3
- package/src/web/components/layout/mobile-tab-switcher-sheet.tsx +13 -4
- package/src/web/components/layout/nav-section-rail.tsx +1 -1
- package/src/web/components/layout/notification-bell-popover.tsx +1 -1
- package/src/web/components/layout/panel-layout.tsx +1 -1
- package/src/web/components/layout/project-bottom-sheet.tsx +4 -1
- package/src/web/components/layout/project-sort.ts +1 -1
- package/src/web/components/layout/project-switcher.tsx +1 -1
- package/src/web/components/layout/reparenting-tab.tsx +1 -1
- package/src/web/components/layout/sidebar.tsx +1 -1
- package/src/web/components/layout/status-bar.tsx +4 -1
- package/src/web/components/layout/tab-bar.tsx +9 -23
- package/src/web/components/layout/tab-content.tsx +6 -1
- package/src/web/components/layout/tab-pool.tsx +1 -0
- package/src/web/components/layout/tab-pop-out-menu-item.tsx +1 -1
- package/src/web/components/layout/upgrade-button.tsx +1 -1
- package/src/web/components/layout/wake-lock-indicator.tsx +1 -1
- package/src/web/components/os-explorer/explorer-body.tsx +1 -1
- package/src/web/components/os-explorer/explorer-breadcrumb.tsx +1 -1
- package/src/web/components/os-explorer/explorer-sidebar.tsx +1 -1
- package/src/web/components/os-explorer/explorer-sort-menu.tsx +1 -1
- package/src/web/components/os-explorer/explorer-toolbar.tsx +1 -1
- package/src/web/components/os-explorer/icons/file-type-icon-map.ts +10 -94
- package/src/web/components/os-explorer/icons/file-type-icon.tsx +17 -13
- package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +1 -1
- package/src/web/components/os-explorer/mobile/mobile-explorer-top-bar.tsx +1 -1
- package/src/web/components/os-explorer/mobile/mobile-more-sheet.tsx +1 -1
- package/src/web/components/os-explorer/mobile/mobile-places-sheet.tsx +1 -1
- package/src/web/components/os-explorer/mobile/mobile-places-strip.tsx +1 -1
- package/src/web/components/os-explorer/properties-dialog.tsx +1 -1
- package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +1 -1
- package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +1 -1
- package/src/web/components/os-explorer/upload/upload-batch-card.tsx +1 -1
- package/src/web/components/os-explorer/upload/upload-batch-row.tsx +1 -1
- package/src/web/components/os-explorer/use-coarse-long-press.ts +8 -0
- package/src/web/components/os-explorer/views/column-view-mobile.tsx +1 -1
- package/src/web/components/os-explorer/views/icons-view-tile.tsx +1 -1
- package/src/web/components/os-explorer/views/list-row.tsx +1 -1
- package/src/web/components/os-explorer/views/list-view.tsx +1 -1
- package/src/web/components/postgres/postgres-viewer.tsx +1 -1
- package/src/web/components/problems/problems-panel.tsx +230 -0
- package/src/web/components/problems/problems-status.tsx +53 -0
- package/src/web/components/projects/dir-suggest.tsx +1 -1
- package/src/web/components/projects/project-list.tsx +1 -1
- package/src/web/components/remote-desktop/remote-desktop-mobile-toolbar.tsx +1 -1
- package/src/web/components/remote-desktop/remote-desktop-mobile-view.tsx +1 -1
- package/src/web/components/remote-desktop/remote-desktop-readiness-gate.tsx +1 -1
- package/src/web/components/remote-desktop/remote-desktop-warning-gate.tsx +1 -1
- package/src/web/components/remote-desktop/remote-desktop-window-content.tsx +1 -1
- package/src/web/components/root-error-boundary.tsx +116 -0
- package/src/web/components/settings/accounts/account-add-dialog.tsx +1 -1
- package/src/web/components/settings/accounts/account-card.tsx +1 -1
- package/src/web/components/settings/accounts/account-export-dialog.tsx +1 -1
- package/src/web/components/settings/accounts/account-export-simulation.tsx +1 -1
- package/src/web/components/settings/accounts/account-import-dialog.tsx +1 -1
- package/src/web/components/settings/accounts/account-profile-panel.tsx +1 -1
- package/src/web/components/settings/accounts/account-rotation-settings.tsx +1 -1
- package/src/web/components/settings/accounts/account-token-test-dialog.tsx +1 -1
- package/src/web/components/settings/accounts/account-usage-pattern-chart.tsx +1 -1
- package/src/web/components/settings/accounts/accounts-pane-header.tsx +1 -1
- package/src/web/components/settings/accounts/accounts-settings-section.tsx +1 -1
- package/src/web/components/settings/accounts/claude-accounts-section.tsx +9 -1
- package/src/web/components/settings/accounts/codex-accounts-section.tsx +10 -1
- package/src/web/components/settings/accounts/codex-add-account-dialog.tsx +1 -1
- package/src/web/components/settings/accounts/codex-backup-dialog.tsx +1 -1
- package/src/web/components/settings/ai-settings-section.tsx +1 -1
- package/src/web/components/settings/appearance-settings-section.tsx +56 -1
- package/src/web/components/settings/change-password-section.tsx +1 -1
- package/src/web/components/settings/extension-manager-section.tsx +1 -1
- package/src/web/components/settings/general-settings-section.tsx +1 -1
- package/src/web/components/settings/glob-list-editor.tsx +1 -1
- package/src/web/components/settings/keyboard-shortcuts-section.tsx +1 -1
- package/src/web/components/settings/mcp-server-dialog.tsx +1 -1
- package/src/web/components/settings/notifications-settings-section.tsx +1 -1
- package/src/web/components/settings/ppmbot-settings-section.tsx +1 -1
- package/src/web/components/settings/proxy-settings-section.tsx +1 -1
- package/src/web/components/settings/proxy-test-section.tsx +1 -1
- package/src/web/components/settings/query-audit-section.tsx +1 -1
- package/src/web/components/settings/schedules/schedule-row.tsx +1 -1
- package/src/web/components/settings/schedules/schedules-settings-section.tsx +1 -1
- package/src/web/components/settings/settings-body.tsx +1 -1
- package/src/web/components/settings/settings-categories.ts +14 -3
- package/src/web/components/settings/settings-category-list.tsx +1 -1
- package/src/web/components/settings/settings-section-content.tsx +1 -1
- package/src/web/components/settings/tag-settings-section.tsx +1 -1
- package/src/web/components/settings/theme-grid.tsx +1 -1
- package/src/web/components/settings/theme-manager-section.tsx +1 -1
- package/src/web/components/settings/theme-picker.tsx +1 -1
- package/src/web/components/shared/bug-report-popup.tsx +1 -1
- package/src/web/components/shared/connection-lost-overlay.tsx +1 -1
- package/src/web/components/shared/diagram-overlay.tsx +1 -1
- package/src/web/components/shared/image-overlay.tsx +1 -1
- package/src/web/components/shared/theme-mode-menu.tsx +1 -1
- package/src/web/components/sqlite/sqlite-data-grid.tsx +1 -1
- package/src/web/components/sqlite/sqlite-table-list.tsx +1 -1
- package/src/web/components/sqlite/sqlite-viewer.tsx +1 -1
- package/src/web/components/system/process-group-row.tsx +1 -1
- package/src/web/components/system/process-row.tsx +1 -1
- package/src/web/components/system/process-table-toolbar.tsx +1 -1
- package/src/web/components/system/resource-status-bar.tsx +1 -1
- package/src/web/components/system/sortable-header.tsx +1 -1
- package/src/web/components/system/system-monitor-body.tsx +1 -1
- package/src/web/components/terminal/terminal-finish-login.tsx +1 -1
- package/src/web/components/terminal/terminal-links-sheet.tsx +1 -1
- package/src/web/components/terminal/terminal-mobile-toolbar.tsx +1 -1
- package/src/web/components/terminal/terminal-placeholder.tsx +1 -1
- package/src/web/components/terminal/terminal-tab.tsx +1 -1
- package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +1 -1
- package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +1 -1
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +1 -1
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +1 -1
- package/src/web/components/tunnels/tunnel-manager-tab.tsx +1 -1
- package/src/web/components/ui/accordion.tsx +1 -1
- package/src/web/components/ui/adaptive-context-menu.tsx +9 -2
- package/src/web/components/ui/browse-button.tsx +1 -1
- package/src/web/components/ui/context-menu.tsx +1 -1
- package/src/web/components/ui/dialog.tsx +1 -1
- package/src/web/components/ui/dropdown-menu.tsx +1 -1
- package/src/web/components/ui/file-browser-picker.tsx +4 -6
- package/src/web/components/ui/select.tsx +1 -1
- package/src/web/components/ui/sidebar-header.tsx +1 -1
- package/src/web/components/ui/sonner.tsx +1 -1
- package/src/web/hooks/use-git-repo.ts +124 -0
- package/src/web/hooks/use-global-keybindings.ts +11 -6
- package/src/web/hooks/use-inline-blame.ts +161 -11
- package/src/web/hooks/use-is-touch-only.ts +46 -0
- package/src/web/hooks/use-lsp.ts +182 -0
- package/src/web/hooks/use-terminal.ts +60 -2
- package/src/web/hooks/use-touch-tab-drag.ts +18 -2
- package/src/web/hooks/use-url-sync.ts +15 -1
- package/src/web/index.html +74 -0
- package/src/web/lib/blame-hover-commands.ts +82 -0
- package/src/web/lib/blame-hover.ts +199 -0
- package/src/web/lib/chunk-recovery.ts +113 -0
- package/src/web/lib/editor-font.ts +70 -0
- package/src/web/lib/ext-command-dispatch.ts +24 -0
- package/src/web/lib/file-icons.generated.ts +408 -0
- package/src/web/lib/file-icons.tsx +192 -0
- package/src/web/lib/fluent-icon.tsx +62 -0
- package/src/web/lib/git-file-tree.ts +83 -0
- package/src/web/lib/git-repo-scope.ts +157 -0
- package/src/web/lib/icons.generated.tsx +428 -0
- package/src/web/lib/icons.ts +17 -0
- package/src/web/lib/lsp/lsp-client.ts +321 -0
- package/src/web/lib/lsp/lsp-documents.ts +39 -0
- package/src/web/lib/lsp/lsp-monaco.ts +214 -0
- package/src/web/lib/lsp/lsp-navigation.ts +129 -0
- package/src/web/lib/lsp/lsp-responses.ts +244 -0
- package/src/web/lib/lsp/lsp-semantic-tokens.ts +180 -0
- package/src/web/lib/lsp/lsp-shadow-models.ts +254 -0
- package/src/web/lib/lsp/monaco-builtin-typescript.ts +149 -0
- package/src/web/lib/lsp/register-providers.ts +458 -0
- package/src/web/lib/monaco-diff-language.ts +62 -0
- package/src/web/lib/monaco-dotenv-language.ts +134 -0
- package/src/web/lib/sidebar-tabs/tab-registry.ts +11 -2
- package/src/web/lib/tab-type-icons.ts +32 -4
- package/src/web/main.tsx +30 -1
- package/src/web/stores/git-repo-store.ts +117 -0
- package/src/web/stores/git-status-store.ts +10 -7
- package/src/web/stores/keybindings-store.ts +1 -0
- package/src/web/stores/panel-utils.ts +5 -2
- package/src/web/stores/problems-store.ts +116 -0
- package/src/web/stores/settings-store.ts +40 -0
- package/src/web/stores/tab-store.ts +2 -1
- package/src/web/stores/window-panel-persistence.ts +1 -0
- package/src/web/styles/file-icons.generated.css +1007 -0
- package/src/web/styles/fonts/nerd-symbols-codicons.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-devicons.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-font-awesome-ext.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-font-awesome-legacy.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-font-awesome.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-font-logos.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-iec-power.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-material.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-misc.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-octicons.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-pomicons.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-powerline.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-seti.woff2 +0 -0
- package/src/web/styles/fonts/nerd-symbols-weather.woff2 +0 -0
- package/src/web/styles/globals.css +30 -3
- package/src/web/styles/nerd-font.generated.css +153 -0
- package/src/web/sw.ts +69 -2
- package/src/web/theme/adapters/monaco-adapter.ts +20 -1
- package/src/web/theme/diff-token-rules.ts +34 -0
- package/src/web/theme/semantic-token-rules.ts +103 -0
- package/src/web/theme/theme-mode-options.ts +1 -1
- package/vite.config.ts +24 -7
- package/dist/web/assets/accounts-settings-section-DC2A6FhQ.js +0 -1
- package/dist/web/assets/ai-resource-editor-DDhuy_AR.js +0 -1
- package/dist/web/assets/ai-settings-section-J9Rbs26g.js +0 -1
- package/dist/web/assets/ai-settings-section-OrhLykA2.js +0 -1
- package/dist/web/assets/api-client-PMwZQ4iC.js +0 -1
- package/dist/web/assets/appearance-settings-section-BQ1dH29t.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-D55g5j-p.js +0 -1
- package/dist/web/assets/arrow-left-y44wEZrw.js +0 -1
- package/dist/web/assets/arrow-right-SQ8KJIvE.js +0 -1
- package/dist/web/assets/audio-preview-CAVqEwDi.js +0 -1
- package/dist/web/assets/bot-BNu2OM_S.js +0 -1
- package/dist/web/assets/brain-BsjvCk4k.js +0 -1
- package/dist/web/assets/calendar-clock-Zydwzvp7.js +0 -1
- package/dist/web/assets/chat-tab-D2le8LxY.js +0 -15
- package/dist/web/assets/check-DczxQ5UD.js +0 -1
- package/dist/web/assets/chevron-down-BCt_kn-R.js +0 -1
- package/dist/web/assets/chevron-right-Lt-y9H_e.js +0 -1
- package/dist/web/assets/chevron-up-CRl1AF4q.js +0 -1
- package/dist/web/assets/circle-D4vp8Yky.js +0 -1
- package/dist/web/assets/circle-question-mark-BGbDcz7E.js +0 -1
- package/dist/web/assets/clock-BBIE-uf3.js +0 -1
- package/dist/web/assets/code-CvgQViOi.js +0 -1
- package/dist/web/assets/code-editor-D-8oqMBM.js +0 -7
- package/dist/web/assets/codex-daily-guard-h4ZpEemV.js +0 -1
- package/dist/web/assets/conflict-editor-B0Mj8pYR.js +0 -19
- package/dist/web/assets/context-menu-I07Ld1Yr.js +0 -1
- package/dist/web/assets/copy-Bqr2VxN5.js +0 -1
- package/dist/web/assets/csv-preview-Ds2oCW6U.js +0 -2
- package/dist/web/assets/database-BHxcoKlT.js +0 -1
- package/dist/web/assets/database-viewer-CiwQ6spt.js +0 -1
- package/dist/web/assets/diff-viewer-BomFSnpH.js +0 -4
- package/dist/web/assets/docx-preview-PsyMM8SN.js +0 -12
- package/dist/web/assets/download-hiDsGuxx.js +0 -1
- package/dist/web/assets/explorer-body-CExMoOiW.js +0 -2
- package/dist/web/assets/explorer-window-content-Hy9kB6Q7.js +0 -1
- package/dist/web/assets/extension-manager-section-DMb56aut.js +0 -1
- package/dist/web/assets/extension-webview-CQB0Uvdo.js +0 -3
- package/dist/web/assets/eye-DYS5JBeU.js +0 -1
- package/dist/web/assets/eye-off-YWCuob9F.js +0 -1
- package/dist/web/assets/file-exclamation-point-DpdJqj9-.js +0 -1
- package/dist/web/assets/files-settings-section-CVHPO3N9.js +0 -1
- package/dist/web/assets/flask-conical-BUxpYe-g.js +0 -1
- package/dist/web/assets/folder-symlink-DKTEop0L.js +0 -1
- package/dist/web/assets/general-settings-section-CWYR9F5y.js +0 -1
- package/dist/web/assets/git-log-panel-DYLF-XSq.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-At-P8hlA.js +0 -1
- package/dist/web/assets/glide-data-grid-BxFN-Z6F.js +0 -141
- package/dist/web/assets/group-chat-tab-Ch6OGMKj.js +0 -1
- package/dist/web/assets/hand-BomFk_WG.js +0 -1
- package/dist/web/assets/image-preview-DjT5Xb2L.js +0 -1
- package/dist/web/assets/index-BfDJvjH9.js +0 -52
- package/dist/web/assets/index-Di9nVG3y.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-btSsuixb.js +0 -1
- package/dist/web/assets/key-round-BhkPzOjZ.js +0 -1
- package/dist/web/assets/keybindings-store-CNqxSJxv.js +0 -1
- package/dist/web/assets/keyboard-IQMXPNIE.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-DAFNxA49.js +0 -1
- package/dist/web/assets/loader-circle-Bm-Dq_wA.js +0 -1
- package/dist/web/assets/markdown-renderer-BSiaxWjE.js +0 -1
- package/dist/web/assets/markdown-renderer-CMNnYOPG.js +0 -3
- package/dist/web/assets/mobile-explorer-sheet-BMg4Q9Bm.js +0 -1
- package/dist/web/assets/monitor-DEoVYSPl.js +0 -1
- package/dist/web/assets/notification-store-CRlOB9I9.js +0 -1
- package/dist/web/assets/notifications-settings-section-Cci_OOHx.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-B20_sIFd.js +0 -1
- package/dist/web/assets/panel-store-BcgZsiXU.js +0 -1
- package/dist/web/assets/pdf-preview-C28MEOND.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-nzfJdXCC.js +0 -1
- package/dist/web/assets/portal-container-context-DO44JpXO.js +0 -1
- package/dist/web/assets/power-BMdSjXYW.js +0 -1
- package/dist/web/assets/ppmbot-settings-section-Cef8FSS6.js +0 -1
- package/dist/web/assets/process-table-BfixzY3r.js +0 -1
- package/dist/web/assets/proxy-settings-section-BlLWfinY.js +0 -1
- package/dist/web/assets/query-audit-section-qnSL15x8.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-CS4sHKD5.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-CG6h4OL2.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-view-D__2WLV5.js +0 -1
- package/dist/web/assets/remote-desktop-readiness-gate-rL48PCUH.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-DlGUCbxq.js +0 -1
- package/dist/web/assets/save-CIuK3QI4.js +0 -1
- package/dist/web/assets/schedules-settings-section-BUqf3KTd.js +0 -1
- package/dist/web/assets/send-DQz3yIWM.js +0 -1
- package/dist/web/assets/separator-CE0YEyaB.js +0 -1
- package/dist/web/assets/settings-body-Baw2komX.js +0 -2
- package/dist/web/assets/settings-store-CuQlVCIe.js +0 -2
- package/dist/web/assets/settings-tab-DCW-3C38.js +0 -1
- package/dist/web/assets/settings-window-content-CVxOGqPV.js +0 -1
- package/dist/web/assets/shield-check-46EViZ6-.js +0 -1
- package/dist/web/assets/shield-off-Dx5mw3le.js +0 -1
- package/dist/web/assets/sparkles-Bay_CedB.js +0 -1
- package/dist/web/assets/sqlite-viewer-BWLSC3VJ.js +0 -1
- package/dist/web/assets/system-monitor-body-BqPyB0CY.js +0 -2
- package/dist/web/assets/system-monitor-tab-BXRvCThe.js +0 -1
- package/dist/web/assets/system-monitor-window-content-CvvwXkmW.js +0 -1
- package/dist/web/assets/tab-host-window-content-23IR3qzu.js +0 -1
- package/dist/web/assets/table-BbD_HNPU.js +0 -1
- package/dist/web/assets/team-member-sheet-BXJtrQAB.js +0 -2
- package/dist/web/assets/team-member-window-content-CBWnzwZ1.js +0 -1
- package/dist/web/assets/terminal-tab-uNw7Yvwg.js +0 -3
- package/dist/web/assets/text-wrap-97GXZlav.js +0 -1
- package/dist/web/assets/tool-cards-CjirOQfx.js +0 -9
- package/dist/web/assets/treemap-KZPCXAKY-BBrhTPZk.js +0 -1
- package/dist/web/assets/use-coarse-long-press-CynaAB7m.js +0 -1
- package/dist/web/assets/use-inline-blame-BLPCADZ8.js +0 -8
- package/dist/web/assets/use-monaco-theme-D2ETCHji.js +0 -1
- package/dist/web/assets/use-open-team-member-BlUqTp-l.js +0 -1
- package/dist/web/assets/use-remote-desktop-display-choice-B4O11KIj.js +0 -1
- package/dist/web/assets/vendor-markdown-3-bej77C.js +0 -291
- package/dist/web/assets/video-preview-BlD1DNP8.js +0 -1
- package/dist/web/assets/ws-auth-ZB8jvzhM.js +0 -1
- package/dist/web/assets/x-TEI-uJYo.js +0 -1
- package/dist/web/monacoeditorwork/css.worker.bundle.js +0 -54268
- package/dist/web/monacoeditorwork/editor.worker.bundle.js +0 -14316
- package/dist/web/monacoeditorwork/html.worker.bundle.js +0 -30452
- package/dist/web/monacoeditorwork/json.worker.bundle.js +0 -22095
- package/dist/web/monacoeditorwork/ts.worker.bundle.js +0 -225957
- package/src/web/components/explorer/file-icon-map.ts +0 -69
- /package/dist/web/assets/{abap-Dbc91hEB.js → abap-tkptwpsK.js} +0 -0
- /package/dist/web/assets/{actionscript-3-C14d4O5M.js → actionscript-3-Di9TMGwg.js} +0 -0
- /package/dist/web/assets/{ada-n8mPGtZF.js → ada-CB9F079D.js} +0 -0
- /package/dist/web/assets/{andromeeda-DAKL0TFq.js → andromeeda-Dcl8jpb7.js} +0 -0
- /package/dist/web/assets/{apache-BDCV8YqE.js → apache-D0Nk0qsH.js} +0 -0
- /package/dist/web/assets/{apex-BphlFNA_.js → apex-mQIoWncD.js} +0 -0
- /package/dist/web/assets/{applescript-F2pJar76.js → applescript-C6ljbcsI.js} +0 -0
- /package/dist/web/assets/{apply-theme-Abd1TNqE.js → apply-theme-BwIMNXyX.js} +0 -0
- /package/dist/web/assets/{ara-B32t5JRb.js → ara-WFqRPGPe.js} +0 -0
- /package/dist/web/assets/{asciidoc-DenFyKu-.js → asciidoc-bNd8w4nf.js} +0 -0
- /package/dist/web/assets/{asm-D5mJz41u.js → asm-BQ1_F580.js} +0 -0
- /package/dist/web/assets/{aurora-x-CUyAXiXM.js → aurora-x-Ciqs_Dbu.js} +0 -0
- /package/dist/web/assets/{awk-CUwaf-l-.js → awk-GCR-6KZV.js} +0 -0
- /package/dist/web/assets/{ayu-dark-Cgg8W7cK.js → ayu-dark-DxJXuj99.js} +0 -0
- /package/dist/web/assets/{ayu-light-B1c04Bhg.js → ayu-light-jvSyJWDV.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-CdWbuzp5.js → ayu-mirage-Cg3BPO6H.js} +0 -0
- /package/dist/web/assets/{ballerina-B2-GPRG0.js → ballerina-BPz4CrX6.js} +0 -0
- /package/dist/web/assets/{bat-Nss7Yr-0.js → bat-CSTs2hIG.js} +0 -0
- /package/dist/web/assets/{beancount-CgaWuvpQ.js → beancount-DMateAZX.js} +0 -0
- /package/dist/web/assets/{berry-DCFF4Zj1.js → berry-9lXg0GRM.js} +0 -0
- /package/dist/web/assets/{bibtex-BPNI-Gig.js → bibtex-DIbqmvFg.js} +0 -0
- /package/dist/web/assets/{bicep-qCj6DX1x.js → bicep-02WGsoJ8.js} +0 -0
- /package/dist/web/assets/{bird2-DYDjG-B_.js → bird2-BY0tbu3k.js} +0 -0
- /package/dist/web/assets/{c-CZV8SiOL.js → c-jMBX_9Je.js} +0 -0
- /package/dist/web/assets/{c3-BG7R2A4x.js → c3-B8JVbNjW.js} +0 -0
- /package/dist/web/assets/{cadence-BuiQVST4.js → cadence-DUIf1tvL.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-DU5MH6XF.js → can-open-in-ppm-DGEc0s4P.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-C-nwrEbb.js → catppuccin-frappe-FhUCVxex.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-nRLBO6vg.js → catppuccin-latte-CzfrtmgL.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-42eAAqCw.js → catppuccin-macchiato-6xL0lOtj.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-4lH0_4tX.js → catppuccin-mocha-D39-xS3P.js} +0 -0
- /package/dist/web/assets/{clarity-BCPLN5zJ.js → clarity-D8TeGvoT.js} +0 -0
- /package/dist/web/assets/{clojure-Btb509Z6.js → clojure-Dx_acSX7.js} +0 -0
- /package/dist/web/assets/{cmake-CGLZgJL3.js → cmake-CyeYPq8o.js} +0 -0
- /package/dist/web/assets/{codeowners-Dgqmdm5J.js → codeowners-DrTI0lmI.js} +0 -0
- /package/dist/web/assets/{codeql-DDUO6ZHS.js → codeql-CPkFxVW-.js} +0 -0
- /package/dist/web/assets/{common-lisp-DlhZ-mM8.js → common-lisp-B0k-3LTj.js} +0 -0
- /package/dist/web/assets/{coq-CVz-5qYC.js → coq-uygpo7to.js} +0 -0
- /package/dist/web/assets/{csharp-CXL6GcvM.js → csharp-DKUYGfSp.js} +0 -0
- /package/dist/web/assets/{css-CthwUm0E.js → css-DoOUp7v4.js} +0 -0
- /package/dist/web/assets/{csv-Bsal3rDr.js → csv-B3YE13gi.js} +0 -0
- /package/dist/web/assets/{csv-parser-iow1WWML.js → csv-parser-DXePqmXe.js} +0 -0
- /package/dist/web/assets/{cue-D2bSqa4C.js → cue-DViO2wvn.js} +0 -0
- /package/dist/web/assets/{cypher-u-EM8HmU.js → cypher-4BMCIW5N.js} +0 -0
- /package/dist/web/assets/{d-BFVkgfjO.js → d-BT_sTHas.js} +0 -0
- /package/dist/web/assets/{dark-plus-BXlM9uFB.js → dark-plus-DVVXu-1N.js} +0 -0
- /package/dist/web/assets/{dart-Hxx4mUdp.js → dart-DHz6f6_6.js} +0 -0
- /package/dist/web/assets/{dax-DQwsaFe_.js → dax-ChYCjweK.js} +0 -0
- /package/dist/web/assets/{desktop-CAHGHZLk.js → desktop-D6Lt4p04.js} +0 -0
- /package/dist/web/assets/{diff-CAbIXu6l.js → diff-D8TDe4hP.js} +0 -0
- /package/dist/web/assets/{dist-C_bG2Tku.js → dist-DOTlFQJA.js} +0 -0
- /package/dist/web/assets/{docker-51FhFKmM.js → docker-Bsp0YbPx.js} +0 -0
- /package/dist/web/assets/{dotenv-C4fc3fLK.js → dotenv-B_7giSY_.js} +0 -0
- /package/dist/web/assets/{dracula-CTtuacPO.js → dracula-TrQL2iB5.js} +0 -0
- /package/dist/web/assets/{dracula-soft-B-95hu1J.js → dracula-soft-n2XOlgh-.js} +0 -0
- /package/dist/web/assets/{dream-maker-Di3hAOzX.js → dream-maker-CdIEdhpT.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-C6btr6QV.js → emacs-lisp-CSbixs6u.js} +0 -0
- /package/dist/web/assets/{everforest-dark-CDQGzEiq.js → everforest-dark-BuZahZYp.js} +0 -0
- /package/dist/web/assets/{everforest-light-DRZC8v3w.js → everforest-light-DPH53z5H.js} +0 -0
- /package/dist/web/assets/{fennel-BZz92X8f.js → fennel-B1-K_hlJ.js} +0 -0
- /package/dist/web/assets/{fish-qpLXUfGf.js → fish-Cy12Dbua.js} +0 -0
- /package/dist/web/assets/{fluent-B3F6P-xc.js → fluent-B_82ys8E.js} +0 -0
- /package/dist/web/assets/{format-bytes-B9Dbme9a.js → format-bytes-D5sBgIqU.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-DjGQrmKa.js → fortran-free-form-BRQdNzZF.js} +0 -0
- /package/dist/web/assets/{gdscript-DToF1duE.js → gdscript-XBDmLUm9.js} +0 -0
- /package/dist/web/assets/{gdshader-FZCS76-j.js → gdshader-DhVfB3u4.js} +0 -0
- /package/dist/web/assets/{genie-CN3-FS9S.js → genie-X3K29Y49.js} +0 -0
- /package/dist/web/assets/{gherkin-DT66zHzt.js → gherkin-DKIx-6cX.js} +0 -0
- /package/dist/web/assets/{github-dark-5S2AJM2m.js → github-dark-Bf7zdp5s.js} +0 -0
- /package/dist/web/assets/{github-dark-default-DNEUWmc8.js → github-dark-default-DqsBBV11.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-BVgm_raB.js → github-dark-dimmed-X2gqRz6w.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Dai8qNkr.js → github-dark-high-contrast-Z7tvbGX4.js} +0 -0
- /package/dist/web/assets/{github-light-C49nlhDa.js → github-light-BKxt-7zZ.js} +0 -0
- /package/dist/web/assets/{github-light-default-BLQcyxQl.js → github-light-default-B0liF4d4.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-BH3u_hMd.js → github-light-high-contrast-F4encJwr.js} +0 -0
- /package/dist/web/assets/{gleam-G2907CEQ.js → gleam-Pz2bHgBB.js} +0 -0
- /package/dist/web/assets/{gn-fxgN7J9Q.js → gn-CgmdNsPU.js} +0 -0
- /package/dist/web/assets/{gnuplot-a1TK_67n.js → gnuplot-qLNF5yZ9.js} +0 -0
- /package/dist/web/assets/{go-DLqnNJpz.js → go-CSDUNhE7.js} +0 -0
- /package/dist/web/assets/{groovy-D8U-plxc.js → groovy-B3NEnOHF.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-DRYdA7rg.js → gruvbox-dark-hard-DcoftiUX.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-CJgayBQH.js → gruvbox-dark-medium-D1wVSuD8.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-spQNOlQ2.js → gruvbox-dark-soft-DWpunymH.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-FoElS0Wo.js → gruvbox-light-hard-rHMvyUdS.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-9E1Brisc.js → gruvbox-light-medium-3O2KiXO7.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-Coyp7RRB.js → gruvbox-light-soft-lNlXJPwH.js} +0 -0
- /package/dist/web/assets/{haskell-D1twJpgj.js → haskell-aaG3aC0h.js} +0 -0
- /package/dist/web/assets/{haxe-CppquubK.js → haxe-CPcHhUDd.js} +0 -0
- /package/dist/web/assets/{hcl-BWfTkyhR.js → hcl-CMQNlR_4.js} +0 -0
- /package/dist/web/assets/{hjson-fgd7F6t5.js → hjson-DeuklPFj.js} +0 -0
- /package/dist/web/assets/{hlsl-Ua1j-4aZ.js → hlsl-BI3hlsaM.js} +0 -0
- /package/dist/web/assets/{horizon-CTFgrxGb.js → horizon-C7-gOcjs.js} +0 -0
- /package/dist/web/assets/{horizon-bright-C4eTVZPB.js → horizon-bright-Cxt9bRW7.js} +0 -0
- /package/dist/web/assets/{houston-BeYbWPdk.js → houston-DbF2G7iD.js} +0 -0
- /package/dist/web/assets/{hy-BposFX9Q.js → hy-DRG6Hs2I.js} +0 -0
- /package/dist/web/assets/{image-gallery-COea0nSk.js → image-gallery-CObzTisL.js} +0 -0
- /package/dist/web/assets/{imba-D11-b73t.js → imba-CxKv_2TW.js} +0 -0
- /package/dist/web/assets/{ini-BCYCXf0w.js → ini-BiHsyCdO.js} +0 -0
- /package/dist/web/assets/{java-BqKIPPzY.js → java-D3RZzgDB.js} +0 -0
- /package/dist/web/assets/{javascript-CxvTx_wu.js → javascript-4FmSqG-T.js} +0 -0
- /package/dist/web/assets/{json-DiknJGdj.js → json-CjB236_E.js} +0 -0
- /package/dist/web/assets/{json5--8nFeehk.js → json5-bkfO-Rco.js} +0 -0
- /package/dist/web/assets/{jsonc-BFcq-Nx-.js → jsonc-BwaTeLyv.js} +0 -0
- /package/dist/web/assets/{jsonl-DKItgfTA.js → jsonl-CfxNSwGd.js} +0 -0
- /package/dist/web/assets/{jsonnet-sNz5wf7H.js → jsonnet-CQETCYrp.js} +0 -0
- /package/dist/web/assets/{jssm-BALAIF_E.js → jssm-D5o3Zzdz.js} +0 -0
- /package/dist/web/assets/{jsx-fXHHDCVl.js → jsx-BAMILPLo.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-nywk9qzg.js → kanagawa-dragon-BhGVxu3R.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-BmYPLC4f.js → kanagawa-lotus-FH4Y59ro.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-624mOWgc.js → kanagawa-wave-eilvP9MB.js} +0 -0
- /package/dist/web/assets/{kdl-DT8Argim.js → kdl-BQ-yvXUK.js} +0 -0
- /package/dist/web/assets/{kotlin-BvUjvPz2.js → kotlin-BuCx0-VT.js} +0 -0
- /package/dist/web/assets/{kusto-B0PONVdx.js → kusto-DAN_n_Cy.js} +0 -0
- /package/dist/web/assets/{laserwave-ByV7LuzT.js → laserwave-Cq2BlxrT.js} +0 -0
- /package/dist/web/assets/{lean-DQtq2qQC.js → lean-Dhq7uXKw.js} +0 -0
- /package/dist/web/assets/{less-DZeD4ccP.js → less-CxaMQb8j.js} +0 -0
- /package/dist/web/assets/{libesm-CcPYXCKp.js → libesm-DdtEjhIi.js} +0 -0
- /package/dist/web/assets/{light-plus-BCaKDxvd.js → light-plus-B4sMAend.js} +0 -0
- /package/dist/web/assets/{llvm-Dzok661y.js → llvm-DQ6-B_6Y.js} +0 -0
- /package/dist/web/assets/{log-C32HpwgI.js → log-Bb_vqvu7.js} +0 -0
- /package/dist/web/assets/{logo-Dtjk3XHO.js → logo-BzfYv3A_.js} +0 -0
- /package/dist/web/assets/{luau-BMbN7IqN.js → luau-BnAeNR77.js} +0 -0
- /package/dist/web/assets/{make-DIVSnx7D.js → make-B6IFuxpC.js} +0 -0
- /package/dist/web/assets/{markdown-B1JzcsJb.js → markdown-Z0xi77Fn.js} +0 -0
- /package/dist/web/assets/{material-theme-XMfEph9O.js → material-theme-1scy1SYn.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CRGzh4Ox.js → material-theme-darker-G-JykXQP.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-D6esgP3h.js → material-theme-lighter-BtKkCMVq.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-CGbfRrFG.js → material-theme-ocean-irrDC89L.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-DFW4xdPI.js → material-theme-palenight-Eq5_K4LM.js} +0 -0
- /package/dist/web/assets/{matlab-Zpc8hvmI.js → matlab-BE3oCXZC.js} +0 -0
- /package/dist/web/assets/{mdx-DLlDpnjI.js → mdx-DYiuFTGw.js} +0 -0
- /package/dist/web/assets/{mermaid-q_sEDHYr.js → mermaid-DVlaEvtw.js} +0 -0
- /package/dist/web/assets/{min-dark-DUklXai3.js → min-dark-DSkeTpQa.js} +0 -0
- /package/dist/web/assets/{min-light-Ps7CV3R0.js → min-light-CFv2Q0uF.js} +0 -0
- /package/dist/web/assets/{mipsasm-anKs0TGD.js → mipsasm-CiAFuZQ2.js} +0 -0
- /package/dist/web/assets/{mojo-CWTvit9D.js → mojo-ARshcaSQ.js} +0 -0
- /package/dist/web/assets/{monokai-DOSMe3B9.js → monokai-CPTV-SOg.js} +0 -0
- /package/dist/web/assets/{moonbit-zOAryA05.js → moonbit-D57B0dZr.js} +0 -0
- /package/dist/web/assets/{move-CA6YZdSC.js → move-qgy3G_o9.js} +0 -0
- /package/dist/web/assets/{narrat-CyMxkfZJ.js → narrat-CZ3rC-oc.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-D5beSS3L.js → nextflow-groovy-BxxIOcI4.js} +0 -0
- /package/dist/web/assets/{night-owl-3ALu1K6e.js → night-owl-B1ryGCda.js} +0 -0
- /package/dist/web/assets/{night-owl-light-_NLbQQrl.js → night-owl-light-BZvNnvMF.js} +0 -0
- /package/dist/web/assets/{nix-C_KqthNc.js → nix-BVBQi8yv.js} +0 -0
- /package/dist/web/assets/{nord-VG8J_Wfy.js → nord-3NXw613h.js} +0 -0
- /package/dist/web/assets/{nushell-Dx7K7YNI.js → nushell-BMOLRalb.js} +0 -0
- /package/dist/web/assets/{objective-c-DrEbGERB.js → objective-c-AxruEUgh.js} +0 -0
- /package/dist/web/assets/{objective-cpp-DpiXqKhj.js → objective-cpp-cFT0qRsD.js} +0 -0
- /package/dist/web/assets/{ocaml-G6x51MAm.js → ocaml-_8JH6O8J.js} +0 -0
- /package/dist/web/assets/{odin-tK6CU-OU.js → odin-nwYvR0O6.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-581te-yF.js → one-dark-pro-C1LaYJaH.js} +0 -0
- /package/dist/web/assets/{one-light-DpYva-U1.js → one-light-B7rMc__c.js} +0 -0
- /package/dist/web/assets/{openscad-C7LYrrI4.js → openscad-Cwes8bKO.js} +0 -0
- /package/dist/web/assets/{pascal-ChqM3eJD.js → pascal-DMt-6tdZ.js} +0 -0
- /package/dist/web/assets/{pkl-BlIRJsyQ.js → pkl-QBTyYQmB.js} +0 -0
- /package/dist/web/assets/{plastic-DxceXlOD.js → plastic-BTSUp8Fk.js} +0 -0
- /package/dist/web/assets/{plsql-CVikvjWK.js → plsql-DQv3IFXP.js} +0 -0
- /package/dist/web/assets/{po-BN9bpeJD.js → po-CNwZx4tW.js} +0 -0
- /package/dist/web/assets/{poimandres-NeQA7ZSh.js → poimandres-8Os7Qequ.js} +0 -0
- /package/dist/web/assets/{polar-DtRx-uzO.js → polar-b4yK8oD8.js} +0 -0
- /package/dist/web/assets/{postcss-EDnOs84S.js → postcss-sFctwpxx.js} +0 -0
- /package/dist/web/assets/{powerquery-mc-bbl3v.js → powerquery-Cg_WrtuN.js} +0 -0
- /package/dist/web/assets/{powershell-ZqZF93a-.js → powershell-C7Ifz95h.js} +0 -0
- /package/dist/web/assets/{prisma-vhORN1Sx.js → prisma-Z52HUJzQ.js} +0 -0
- /package/dist/web/assets/{prolog-DfIbN_m8.js → prolog-DLqW-zR1.js} +0 -0
- /package/dist/web/assets/{proto-BHcnh-Db.js → proto-BOIzxCCJ.js} +0 -0
- /package/dist/web/assets/{puppet-oLpQOx2h.js → puppet-De7TjZIf.js} +0 -0
- /package/dist/web/assets/{purescript-HbM4Dt8M.js → purescript-R76ou1WT.js} +0 -0
- /package/dist/web/assets/{python-Dlxo2z6Q.js → python-Dprm0tNP.js} +0 -0
- /package/dist/web/assets/{qmldir-B5ox9idu.js → qmldir-Clp_jpNw.js} +0 -0
- /package/dist/web/assets/{qss-CyegwBrl.js → qss-eQPYYzSo.js} +0 -0
- /package/dist/web/assets/{r-CxE2X3lg.js → r-CCcRHIf5.js} +0 -0
- /package/dist/web/assets/{racket-CpguQMOj.js → racket-CzE472yp.js} +0 -0
- /package/dist/web/assets/{raku-DDf8ASYE.js → raku-DQwXrTSi.js} +0 -0
- /package/dist/web/assets/{red-C634f6x3.js → red-KCS6wyop.js} +0 -0
- /package/dist/web/assets/{reg-4gnm7BOP.js → reg-CcrAddUh.js} +0 -0
- /package/dist/web/assets/{regexp-Cs-hPAru.js → regexp-DDbud-Ri.js} +0 -0
- /package/dist/web/assets/{rel-CrGcWbwM.js → rel-99GDgaHp.js} +0 -0
- /package/dist/web/assets/{resolve-theme-Dm8ehbOv.js → resolve-theme-CW2niGV2.js} +0 -0
- /package/dist/web/assets/{riscv-B2P26ROS.js → riscv-Dm2eNv0R.js} +0 -0
- /package/dist/web/assets/{ron-DDHGmvxW.js → ron-CzFt0ygH.js} +0 -0
- /package/dist/web/assets/{rose-pine-CUYRoYal.js → rose-pine-Ck6lCrCP.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-C9JfuUh8.js → rose-pine-dawn-vtALRJNj.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CrYHzRJm.js → rose-pine-moon-DPto8qXw.js} +0 -0
- /package/dist/web/assets/{rosmsg-iqzz1U38.js → rosmsg-NtS6429H.js} +0 -0
- /package/dist/web/assets/{rust-DVeWF3Is.js → rust-BjIXvF9h.js} +0 -0
- /package/dist/web/assets/{sass-CbVwBbUd.js → sass-CQ23wf5E.js} +0 -0
- /package/dist/web/assets/{scala-gZhcvPGv.js → scala-LfKLM143.js} +0 -0
- /package/dist/web/assets/{scheme-Z-DWgvmB.js → scheme-D3SLBXlF.js} +0 -0
- /package/dist/web/assets/{sdbl-wn_BtpSz.js → sdbl-ODRd2rGN.js} +0 -0
- /package/dist/web/assets/{shellscript-C09f889h.js → shellscript-3KB1G_oA.js} +0 -0
- /package/dist/web/assets/{slack-dark-D63Fbr3l.js → slack-dark-DTtyWmIy.js} +0 -0
- /package/dist/web/assets/{slack-ochin--Yu-v0r6.js → slack-ochin-Bu0PApk3.js} +0 -0
- /package/dist/web/assets/{smalltalk-LQDcL_tW.js → smalltalk-haMT-Sbe.js} +0 -0
- /package/dist/web/assets/{snazzy-light-bo9fX83t.js → snazzy-light-DXJzefE9.js} +0 -0
- /package/dist/web/assets/{solarized-dark-zSs85XH6.js → solarized-dark-B6LyYa18.js} +0 -0
- /package/dist/web/assets/{solarized-light-B6Q4CXBt.js → solarized-light-QLADebkv.js} +0 -0
- /package/dist/web/assets/{solidity-uUJPOjGx.js → solidity-mzfq1aDc.js} +0 -0
- /package/dist/web/assets/{splunk-C6oWgmrC.js → splunk-CyH4RWBp.js} +0 -0
- /package/dist/web/assets/{sql-DyUvXbLi.js → sql-CWVlT5D3.js} +0 -0
- /package/dist/web/assets/{ssh-config-62Vrd_7v.js → ssh-config-DNvQJ1Qx.js} +0 -0
- /package/dist/web/assets/{stylus-CmLQe7Fq.js → stylus-ByQQdtmf.js} +0 -0
- /package/dist/web/assets/{swift-DJwuT1eZ.js → swift-D1cpY4ow.js} +0 -0
- /package/dist/web/assets/{synthwave-84-CEeyTLD7.js → synthwave-84-BDF_-QiW.js} +0 -0
- /package/dist/web/assets/{system-verilog-DMqtAclw.js → system-verilog-BYrkMydC.js} +0 -0
- /package/dist/web/assets/{systemd-XnScP_8M.js → systemd-CQm3zyK0.js} +0 -0
- /package/dist/web/assets/{talonscript-CDoODzml.js → talonscript-DMW5CzE1.js} +0 -0
- /package/dist/web/assets/{tasl-DycI0-Tf.js → tasl-BhFzMCr2.js} +0 -0
- /package/dist/web/assets/{tcl-Dt8iP0sw.js → tcl-D7VEAF-9.js} +0 -0
- /package/dist/web/assets/{terraform-DXzABgqQ.js → terraform-DdT5A0Vy.js} +0 -0
- /package/dist/web/assets/{tokyo-night-DHB1Yc-3.js → tokyo-night-WGLMM6Q9.js} +0 -0
- /package/dist/web/assets/{toml-BkejsZF3.js → toml-CZ7ipXHZ.js} +0 -0
- /package/dist/web/assets/{tsv-ClmhsiiR.js → tsv-B1zVvoTr.js} +0 -0
- /package/dist/web/assets/{tsx-Cp-c_JHF.js → tsx-D4HwRUBq.js} +0 -0
- /package/dist/web/assets/{turtle-BbwC417u.js → turtle-B4r8KEJH.js} +0 -0
- /package/dist/web/assets/{typescript-DbwnrRKJ.js → typescript-BnHhxMtp.js} +0 -0
- /package/dist/web/assets/{typespec-DLL0LoZj.js → typespec-DP2q46GT.js} +0 -0
- /package/dist/web/assets/{typst-BmEouVT1.js → typst-DFsD_yaD.js} +0 -0
- /package/dist/web/assets/{utils-CwNUra6_.js → utils-Bmf_8h7Y.js} +0 -0
- /package/dist/web/assets/{v-C5rFgF81.js → v-Bji8hSVT.js} +0 -0
- /package/dist/web/assets/{vala-rBXMujLw.js → vala-D3TIgGmU.js} +0 -0
- /package/dist/web/assets/{vb-mxG_YZv2.js → vb-DvcxFS2q.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-BtjgHRUe.js → vendor-xterm-BqPDsE9b.js} +0 -0
- /package/dist/web/assets/{verilog-uQ-oJRKp.js → verilog-Dy7cF35d.js} +0 -0
- /package/dist/web/assets/{vesper-SO5Hw_2X.js → vesper-BzjwUv9J.js} +0 -0
- /package/dist/web/assets/{vhdl-8IeO85hx.js → vhdl-DuFnFNmW.js} +0 -0
- /package/dist/web/assets/{viml-De-Hm57y.js → viml-yAPgKlbz.js} +0 -0
- /package/dist/web/assets/{vitesse-black-BVm23GJE.js → vitesse-black-oSSQdyIZ.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-CR0XeT-h.js → vitesse-dark-BZxwPihB.js} +0 -0
- /package/dist/web/assets/{vitesse-light-CXIFICUA.js → vitesse-light-uIigycvt.js} +0 -0
- /package/dist/web/assets/{vyper-dUuvAUFJ.js → vyper-CX3NAxm5.js} +0 -0
- /package/dist/web/assets/{wasm-DbLMmiW0.js → wasm-6mEOOvVa.js} +0 -0
- /package/dist/web/assets/{wasm-D5Vd7qV1.js → wasm-D9td37qO.js} +0 -0
- /package/dist/web/assets/{wenyan-BafBYCBu.js → wenyan-lwNIHgk6.js} +0 -0
- /package/dist/web/assets/{wgsl-DY5sHamz.js → wgsl-DQAzCfog.js} +0 -0
- /package/dist/web/assets/{wikitext-QkQQVra5.js → wikitext-DTXmt5NE.js} +0 -0
- /package/dist/web/assets/{wit-BZjaDTy9.js → wit-Bdw_7WDH.js} +0 -0
- /package/dist/web/assets/{wolfram-vrjPFD7R.js → wolfram-DqyHDZ07.js} +0 -0
- /package/dist/web/assets/{yaml-D1as76NB.js → yaml-CPXhdByd.js} +0 -0
- /package/dist/web/assets/{zenscript-D31myxQh.js → zenscript-6s_i5zek.js} +0 -0
- /package/dist/web/assets/{zig-BbLb6ieN.js → zig-B2htezJ_.js} +0 -0
|
@@ -10,6 +10,7 @@ import { resolveTheme as resolvePpmTheme } from "@/theme/resolve-theme";
|
|
|
10
10
|
import { getCurrentAppliedTheme, THEME_CHANGE_EVENT } from "@/theme/apply-theme";
|
|
11
11
|
import { onHostResize } from "@/components/floating-window/pip/pip-resize-signal";
|
|
12
12
|
import type { PpmTheme } from "@/theme/types";
|
|
13
|
+
import { TERMINAL_FONT_FAMILY } from "@/lib/editor-font";
|
|
13
14
|
|
|
14
15
|
/** Current active PpmTheme → xterm ITheme (prefers the live applied theme). */
|
|
15
16
|
function currentXtermTheme(): ITheme {
|
|
@@ -347,9 +348,25 @@ export function useTerminal(
|
|
|
347
348
|
fontSize: 13,
|
|
348
349
|
scrollback: 50000,
|
|
349
350
|
// Explicit terminal-grade stack: the WebGL renderer builds its glyph
|
|
350
|
-
// atlas via ctx.font and cannot resolve CSS var() values.
|
|
351
|
-
|
|
351
|
+
// atlas via ctx.font and cannot resolve CSS var() values. Its own stack
|
|
352
|
+
// rather than the editor's, because a prompt needs the powerline and
|
|
353
|
+
// devicon glyphs only a patched Nerd Font has.
|
|
354
|
+
fontFamily: TERMINAL_FONT_FAMILY,
|
|
352
355
|
theme: currentXtermTheme(),
|
|
356
|
+
// The two ends of an ANSI palette collapse into the background, and a
|
|
357
|
+
// prompt cannot know which way round the terminal is. On PPM's light
|
|
358
|
+
// themes `white` is #e9edf5 against a #f3f7ff background — 1.09:1, i.e.
|
|
359
|
+
// invisible — and on the dark ones `black` is 1.10:1. oh-my-posh writes
|
|
360
|
+
// its second prompt line in plain SGR 37, which is correct on the dark
|
|
361
|
+
// terminal it was designed for and disappeared entirely here.
|
|
362
|
+
//
|
|
363
|
+
// Repainting those palette slots is the wrong fix: the same `white` is
|
|
364
|
+
// also the text *on* a coloured powerline segment, where it is right.
|
|
365
|
+
// xterm adjusts the foreground per cell against that cell's real
|
|
366
|
+
// background instead, which leaves every segment untouched and only
|
|
367
|
+
// rescues the text that had nothing behind it. 4.5 is WCAG AA, and the
|
|
368
|
+
// value VS Code ships as its own default.
|
|
369
|
+
minimumContrastRatio: 4.5,
|
|
353
370
|
});
|
|
354
371
|
|
|
355
372
|
const fitAddon = new FitAddon();
|
|
@@ -382,6 +399,23 @@ export function useTerminal(
|
|
|
382
399
|
termRef.current = term;
|
|
383
400
|
fitRef.current = fitAddon;
|
|
384
401
|
|
|
402
|
+
// A webfont that is still in flight is not in the stack yet: xterm measures
|
|
403
|
+
// the cell and bakes the glyph atlas from ctx.font at open(), so a terminal
|
|
404
|
+
// opened during the first paint would keep whatever fallback was resolved
|
|
405
|
+
// then, for the rest of the session. Re-measuring once the face lands is
|
|
406
|
+
// the whole fix; the atlas is rebuilt from the new metrics by fit().
|
|
407
|
+
let fontsSettled = false;
|
|
408
|
+
document.fonts.ready.then(() => {
|
|
409
|
+
if (fontsSettled || termRef.current !== term) return;
|
|
410
|
+
fontsSettled = true;
|
|
411
|
+
try {
|
|
412
|
+
term.options.fontFamily = TERMINAL_FONT_FAMILY;
|
|
413
|
+
fitAddon.fit();
|
|
414
|
+
} catch {
|
|
415
|
+
// A terminal disposed between the promise and here; nothing to redraw.
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
385
419
|
// Wire input to WS + track command boundaries
|
|
386
420
|
term.onData((data) => {
|
|
387
421
|
// When user presses Enter, mark next row as command output start
|
|
@@ -452,8 +486,32 @@ export function useTerminal(
|
|
|
452
486
|
window.addEventListener(THEME_CHANGE_EVENT, onThemeChange);
|
|
453
487
|
const unsubTheme = () => window.removeEventListener(THEME_CHANGE_EVENT, onThemeChange);
|
|
454
488
|
|
|
489
|
+
// The icon faces are fetched on demand — a `unicode-range` face is not
|
|
490
|
+
// requested until something lays out a character inside it, which for a
|
|
491
|
+
// prompt's Private Use Area glyphs is the first time the prompt is drawn.
|
|
492
|
+
// That is long after `document.fonts.ready` above has resolved, so the
|
|
493
|
+
// one-shot re-measure cannot see it.
|
|
494
|
+
//
|
|
495
|
+
// And nothing else redraws: measured in Chromium, a canvas `fillText` does
|
|
496
|
+
// start the fetch, but the glyph it painted is tofu and the canvas never
|
|
497
|
+
// repaints itself — ink stayed identical after the face finished loading
|
|
498
|
+
// and only tripled on a redraw. So the atlas the WebGL and canvas renderers
|
|
499
|
+
// baked has to be thrown away by hand, or the prompt is tofu for the rest
|
|
500
|
+
// of the session with the right font sitting loaded in the page.
|
|
501
|
+
const onFontLoaded = () => {
|
|
502
|
+
if (termRef.current !== term) return;
|
|
503
|
+
try {
|
|
504
|
+
term.clearTextureAtlas();
|
|
505
|
+
term.refresh(0, term.rows - 1);
|
|
506
|
+
} catch {
|
|
507
|
+
// Disposed between the event and here; nothing left to redraw.
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
document.fonts.addEventListener("loadingdone", onFontLoaded);
|
|
511
|
+
|
|
455
512
|
return () => {
|
|
456
513
|
unsubTheme();
|
|
514
|
+
document.fonts.removeEventListener("loadingdone", onFontLoaded);
|
|
457
515
|
unsubHostResize();
|
|
458
516
|
if (fitTimer) clearTimeout(fitTimer);
|
|
459
517
|
resizeObserver.disconnect();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
1
|
+
import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
|
|
2
2
|
import { setDragging, clearDragging, type DragPayload } from "./use-tab-drag";
|
|
3
3
|
import { usePanelStore } from "@/stores/panel-store";
|
|
4
4
|
import { findPanelPosition, maxColumns, MAX_ROWS } from "@/stores/panel-utils";
|
|
@@ -186,5 +186,21 @@ export function useTouchTabDrag(panelId: string) {
|
|
|
186
186
|
if (timer.current) { clearTimeout(timer.current); timer.current = null; }
|
|
187
187
|
}, []);
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
/**
|
|
190
|
+
* The *pre-arm* timer's cancel. There is already a document-level
|
|
191
|
+
* `touchcancel` above, but it belongs to a drag that has begun and is only
|
|
192
|
+
* registered once `beginDrag` has run — it says nothing about the 200ms
|
|
193
|
+
* window before that. And that window is exactly where the problem is: a
|
|
194
|
+
* scroll fires `touchcancel` and then delivers no further `touchmove` or
|
|
195
|
+
* `touchend` to the tab, so the `MOVE_PX` tolerance never sees the moves it
|
|
196
|
+
* would have measured and the drag begins under a finger that was scrolling.
|
|
197
|
+
*/
|
|
198
|
+
const handleTouchCancel = useCallback(() => {
|
|
199
|
+
if (timer.current) { clearTimeout(timer.current); timer.current = null; }
|
|
200
|
+
origin.current = null;
|
|
201
|
+
}, []);
|
|
202
|
+
|
|
203
|
+
useEffect(() => () => { if (timer.current) clearTimeout(timer.current); }, []);
|
|
204
|
+
|
|
205
|
+
return { handleTouchStart, handleTouchMove, handleTouchEnd, handleTouchCancel };
|
|
190
206
|
}
|
|
@@ -25,6 +25,20 @@ const VALID_TAB_TYPES: TabType[] = [
|
|
|
25
25
|
// Parse URL → state
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* `decodeURIComponent` throws `URIError` on a percent that is not an escape —
|
|
30
|
+
* a hand-edited address, a truncated share link, a `%` in a branch name that
|
|
31
|
+
* was never encoded. Thrown from here it reaches the root and unmounts the app,
|
|
32
|
+
* so a mistyped URL would blank the page instead of just not resolving to a tab.
|
|
33
|
+
*/
|
|
34
|
+
function decodePathSegment(segment: string): string {
|
|
35
|
+
try {
|
|
36
|
+
return decodeURIComponent(segment);
|
|
37
|
+
} catch {
|
|
38
|
+
return segment;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
/**
|
|
29
43
|
* Parse the current URL to extract project name and tab info.
|
|
30
44
|
* Format: /project/{name}/{tabType}/{...identifier}
|
|
@@ -37,7 +51,7 @@ export function parseUrlState(): UrlState {
|
|
|
37
51
|
const match = path.match(/^\/project\/([^/]+)(?:\/([^/]+)(\/.*)?)?/);
|
|
38
52
|
if (!match) return { projectName: null, tabType: null, tabIdentifier: null, openChat };
|
|
39
53
|
|
|
40
|
-
const projectName =
|
|
54
|
+
const projectName = decodePathSegment(match[1]!);
|
|
41
55
|
const rawType = match[2] ?? null;
|
|
42
56
|
const rawIdentifier = match[3] ? match[3].slice(1) : null; // strip leading /
|
|
43
57
|
|
package/src/web/index.html
CHANGED
|
@@ -48,6 +48,80 @@
|
|
|
48
48
|
<div id="portal" style="position: fixed; left: 0; top: 0; z-index: 9999;" /></div>
|
|
49
49
|
<div id="root"></div>
|
|
50
50
|
<script type="module" src="./main.tsx"></script>
|
|
51
|
+
<!-- Boot watchdog: the last resort, and the only code that can still run.
|
|
52
|
+
The entry's module graph is ~39 separately-hashed chunks, and if any one
|
|
53
|
+
of them 404s — an upgrade replaced dist/web, or a stale index.html is
|
|
54
|
+
still naming last week's hashes — the entry module never executes. No
|
|
55
|
+
React, no error boundary, no listener: `#root` stays empty and the page
|
|
56
|
+
shows nothing but the body's background. That is the white screen, and
|
|
57
|
+
nothing bundled can report it, because nothing bundled ran. Hence
|
|
58
|
+
inline, dependency-free, and gated on the flag main.tsx sets: a boundary
|
|
59
|
+
inside React already covers the case where the entry *did* run. -->
|
|
60
|
+
<script>
|
|
61
|
+
(function () {
|
|
62
|
+
var KEY = "ppm:boot-retry";
|
|
63
|
+
// Every cache, not just this app's: the stale index.html that named the
|
|
64
|
+
// missing hashes comes from the service worker's *precache*, which is
|
|
65
|
+
// workbox's to name. It repopulates itself on the next activation.
|
|
66
|
+
function purge() {
|
|
67
|
+
if (!window.caches) return Promise.resolve();
|
|
68
|
+
return caches
|
|
69
|
+
.keys()
|
|
70
|
+
.then(function (names) { return Promise.all(names.map(function (n) { return caches.delete(n); })); })
|
|
71
|
+
.catch(function () {});
|
|
72
|
+
}
|
|
73
|
+
function panic() {
|
|
74
|
+
// The wrapper carries its own background: if the stylesheet was one of
|
|
75
|
+
// the chunks that went missing, `var(--bg)` on <body> resolves to
|
|
76
|
+
// nothing and dark-mode text would be white on white.
|
|
77
|
+
document.getElementById("root").innerHTML =
|
|
78
|
+
'<div style="min-height:100dvh;display:flex;align-items:center;justify-content:center;padding:24px;' +
|
|
79
|
+
'background:var(--bg-solid,#0a0e17);color:var(--text,#eaeefb);font:16px/1.5 system-ui,sans-serif">' +
|
|
80
|
+
'<div role="alert" style="width:100%;max-width:440px;background:var(--panel,#141820);' +
|
|
81
|
+
'border:1px solid var(--border,rgba(255,255,255,0.12));border-radius:18px;padding:24px">' +
|
|
82
|
+
'<h1 style="margin:0;font-size:18px;font-weight:600">PPM could not finish loading</h1>' +
|
|
83
|
+
'<p style="margin:12px 0 0;color:var(--text-2,#9aa6c2)">Part of the app is missing from the server, ' +
|
|
84
|
+
'which usually means it was replaced by an upgrade. Reloading fetches the current version.</p>' +
|
|
85
|
+
'<button id="ppm-boot-retry" type="button" style="min-height:44px;width:100%;margin-top:20px;' +
|
|
86
|
+
'padding:0 20px;border:0;border-radius:12px;background:var(--accent,#5b8cff);' +
|
|
87
|
+
'color:var(--accent-fg,#fff);font:inherit;font-weight:600;cursor:pointer">Reload</button>' +
|
|
88
|
+
"</div></div>";
|
|
89
|
+
document.getElementById("ppm-boot-retry").onclick = function () {
|
|
90
|
+
try { sessionStorage.removeItem(KEY); } catch (e) {}
|
|
91
|
+
purge().then(function () { location.reload(); });
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function check() {
|
|
95
|
+
// Module scripts execute before `load`, so a flag still unset here is
|
|
96
|
+
// never going to be set — this cannot misfire on a slow boot.
|
|
97
|
+
//
|
|
98
|
+
// A boot that worked also clears the key. The silent retry is meant to
|
|
99
|
+
// be one per *incident*, and the key was only ever written: after one
|
|
100
|
+
// upgrade healed itself, a second upgrade in the same tab session went
|
|
101
|
+
// straight to the panic card without trying the reload that would have
|
|
102
|
+
// fixed it — on a long-lived tab, which is exactly the tab this is for.
|
|
103
|
+
if (window.__ppmEntryRan) {
|
|
104
|
+
try { sessionStorage.removeItem(KEY); } catch (e) {}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
var retried;
|
|
108
|
+
try {
|
|
109
|
+
retried = sessionStorage.getItem(KEY) === "1";
|
|
110
|
+
sessionStorage.setItem(KEY, "1");
|
|
111
|
+
} catch (e) {
|
|
112
|
+
// No storage means no way to count attempts, and an uncounted
|
|
113
|
+
// reload is a loop. Go straight to the message.
|
|
114
|
+
retried = true;
|
|
115
|
+
}
|
|
116
|
+
// One silent attempt first: index.html is served `no-cache`, so a
|
|
117
|
+
// reload with this origin's caches dropped is exactly how a tab
|
|
118
|
+
// holding an upgraded-away chunk list heals itself.
|
|
119
|
+
if (!retried) { purge().then(function () { location.reload(); }); return; }
|
|
120
|
+
panic();
|
|
121
|
+
}
|
|
122
|
+
window.addEventListener("load", function () { setTimeout(check, 4000); });
|
|
123
|
+
})();
|
|
124
|
+
</script>
|
|
51
125
|
<!-- Eruda: mobile console for debugging. Activate with ?debug in URL -->
|
|
52
126
|
<script>
|
|
53
127
|
if (/debug=true|debug(&|$)/.test(location.search)) {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The commands behind the blame hover's buttons.
|
|
3
|
+
*
|
|
4
|
+
* A Monaco hover can only contain markdown, so a button is a `command:` link
|
|
5
|
+
* and there has to be something registered under that id for it to reach. These
|
|
6
|
+
* are registered on the standalone `CommandsRegistry`, which is global to the
|
|
7
|
+
* page — hence the idempotence, and hence ids namespaced under `ppm.blame.`.
|
|
8
|
+
*
|
|
9
|
+
* Three of the four hand off to the Git Graph extension, which already has the
|
|
10
|
+
* views: `ext:command:execute` is the same event core UI uses elsewhere
|
|
11
|
+
* (`git-status-panel.tsx`), and `git-graph.blame` and `git-graph.fileHistory`
|
|
12
|
+
* already accept a file path as their second argument.
|
|
13
|
+
*
|
|
14
|
+
* Every handler re-checks its arguments even though `buildBlameHoverMarkdown`
|
|
15
|
+
* is the only thing that writes these links, and even though the hover's trust
|
|
16
|
+
* is narrowed so a commit message cannot forge one. The registry is global: any
|
|
17
|
+
* other markdown on the page could name these ids.
|
|
18
|
+
*/
|
|
19
|
+
import type * as MonacoType from "monaco-editor";
|
|
20
|
+
import { toast } from "sonner";
|
|
21
|
+
import { copyToClipboard } from "./clipboard";
|
|
22
|
+
|
|
23
|
+
let registered = false;
|
|
24
|
+
|
|
25
|
+
/** Dispatch an extension command the way the rest of the app does. */
|
|
26
|
+
function runExtensionCommand(command: string, args: unknown[]): void {
|
|
27
|
+
window.dispatchEvent(new CustomEvent("ext:command:execute", { detail: { command, args } }));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function asHash(value: unknown): string | null {
|
|
31
|
+
return typeof value === "string" && /^[0-9a-f]{7,40}$/.test(value) ? value : null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function asPath(value: unknown): string | null {
|
|
35
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Both paths are required. An extension view command reads a falsy first
|
|
40
|
+
* argument as "resolve the project yourself", which for a hover that named a
|
|
41
|
+
* specific file would silently open some other project's history.
|
|
42
|
+
*/
|
|
43
|
+
function runForFile(command: string, projectPath: unknown, filePath: unknown): void {
|
|
44
|
+
const root = asPath(projectPath);
|
|
45
|
+
const path = asPath(filePath);
|
|
46
|
+
if (!root || !path) return;
|
|
47
|
+
runExtensionCommand(command, [root, path]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function registerBlameHoverCommands(monaco: typeof MonacoType): void {
|
|
51
|
+
if (registered) return;
|
|
52
|
+
registered = true;
|
|
53
|
+
|
|
54
|
+
monaco.editor.registerCommand("ppm.blame.copySha", (_accessor, hash: unknown) => {
|
|
55
|
+
const sha = asHash(hash);
|
|
56
|
+
if (!sha) return;
|
|
57
|
+
// The full hash, not the abbreviation the link shows: an abbreviation is
|
|
58
|
+
// for reading, and what you paste into a command has to be unambiguous.
|
|
59
|
+
void copyToClipboard(sha).then((ok) => {
|
|
60
|
+
toast[ok ? "success" : "error"](ok ? `Copied ${sha.slice(0, 7)}` : "Could not copy");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
monaco.editor.registerCommand("ppm.blame.fileHistory", (_accessor, projectPath: unknown, filePath: unknown) => {
|
|
65
|
+
runForFile("git-graph.fileHistory", projectPath, filePath);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
monaco.editor.registerCommand("ppm.blame.blameFile", (_accessor, projectPath: unknown, filePath: unknown) => {
|
|
69
|
+
runForFile("git-graph.blame", projectPath, filePath);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
monaco.editor.registerCommand("ppm.blame.showInGraph", (_accessor, projectPath: unknown) => {
|
|
73
|
+
const root = asPath(projectPath);
|
|
74
|
+
if (!root) return;
|
|
75
|
+
runExtensionCommand("git-graph.view", [root]);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Test seam. */
|
|
80
|
+
export function _resetBlameHoverCommands(): void {
|
|
81
|
+
registered = false;
|
|
82
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The markdown behind the editor's blame hover — GitLens' hover, rebuilt.
|
|
3
|
+
*
|
|
4
|
+
* Monaco's hover renders a markdown string and nothing else, so everything the
|
|
5
|
+
* hover shows has to survive being written as markdown: the avatar is a data-URI
|
|
6
|
+
* image, the buttons are `command:` links, and the diff is a fenced block.
|
|
7
|
+
*
|
|
8
|
+
* Three things about that are load-bearing and were each verified against a real
|
|
9
|
+
* Monaco 0.55.1 rather than assumed:
|
|
10
|
+
*
|
|
11
|
+
* - `command:` links are stripped unless the string is trusted, and a trusted
|
|
12
|
+
* string with `isTrusted: true` allows *every* registered command. This one
|
|
13
|
+
* carries a commit message, and anyone who can land a commit can put
|
|
14
|
+
* `[click](command:whatever)` in one — so the trust is narrowed to the four
|
|
15
|
+
* commands here via `enabledCommands`, and the message is escaped on top.
|
|
16
|
+
* - `supportHtml` stays off. The avatar is ``, which
|
|
17
|
+
* renders inline at its own intrinsic size, so no `<img width>` is needed and
|
|
18
|
+
* no HTML from a commit message can render at all.
|
|
19
|
+
* - a ```diff block is only coloured because `monaco-diff-language.ts`
|
|
20
|
+
* registers the language Monaco lacks.
|
|
21
|
+
*/
|
|
22
|
+
import type * as MonacoType from "monaco-editor";
|
|
23
|
+
import {
|
|
24
|
+
formatAbsoluteTime,
|
|
25
|
+
formatRelativeTime,
|
|
26
|
+
isUncommittedHash,
|
|
27
|
+
type BlameCommitInfo,
|
|
28
|
+
type BlameLineDetail,
|
|
29
|
+
} from "../../shared/blame";
|
|
30
|
+
|
|
31
|
+
/** The commands the hover's links may run. Nothing else, whatever a message says. */
|
|
32
|
+
export const BLAME_HOVER_COMMANDS = [
|
|
33
|
+
"ppm.blame.copySha",
|
|
34
|
+
"ppm.blame.fileHistory",
|
|
35
|
+
"ppm.blame.blameFile",
|
|
36
|
+
"ppm.blame.showInGraph",
|
|
37
|
+
] as const;
|
|
38
|
+
|
|
39
|
+
/** How much of a sha to show. Git's own default abbreviation. */
|
|
40
|
+
const SHORT_SHA = 7;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Escape the markdown a commit message or an author name would otherwise be
|
|
44
|
+
* read as. The character set is VS Code's own `escapeMarkdownSyntaxTokens`.
|
|
45
|
+
*
|
|
46
|
+
* `[` and `]` are the ones that matter most: without them a message reading
|
|
47
|
+
* `[click](command:…)` becomes a button in the hover.
|
|
48
|
+
*
|
|
49
|
+
* `<` and `>` are added to VS Code's set because the renderer does not leave an
|
|
50
|
+
* unknown tag alone — it strips the tag and keeps the text inside, so a message
|
|
51
|
+
* mentioning `<script>alert(1)</script>` displayed as `alert(1)`. Not a script
|
|
52
|
+
* that runs, but a commit message rewritten in the one view whose job is to
|
|
53
|
+
* show it verbatim. A backslash escape rather than an entity: `<` would come
|
|
54
|
+
* back out literally, since `&` is not escaped here.
|
|
55
|
+
*
|
|
56
|
+
* Newlines are left alone; the message's own line breaks are wanted.
|
|
57
|
+
*/
|
|
58
|
+
export function escapeMarkdown(text: string): string {
|
|
59
|
+
return text.replace(/[\\`*_{}[\]()#+\-!<>]/g, (c) => `\\${c}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Initials for the avatar: first letters of the first and last word. */
|
|
63
|
+
export function authorInitials(author: string): string {
|
|
64
|
+
const words = author.trim().split(/\s+/).filter(Boolean);
|
|
65
|
+
if (words.length === 0) return "?";
|
|
66
|
+
const first = words[0]![0]!;
|
|
67
|
+
const last = words.length > 1 ? words[words.length - 1]![0]! : "";
|
|
68
|
+
return (first + last).toUpperCase();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A stable colour per author, from VS Code's chart palette.
|
|
73
|
+
*
|
|
74
|
+
* Deliberately not a gravatar. Fetching one would send a hash of the
|
|
75
|
+
* committer's email to a third party on every hover, which a self-hosted tool
|
|
76
|
+
* must not do silently — the same reason the git graph's author chips are
|
|
77
|
+
* initials.
|
|
78
|
+
*/
|
|
79
|
+
const AVATAR_COLOURS = ["4E79A7", "F28E2B", "E15759", "76B7B2", "59A14F", "AF7AA1", "9C755F", "B07AA1"];
|
|
80
|
+
|
|
81
|
+
export function authorColour(author: string): string {
|
|
82
|
+
let hash = 0;
|
|
83
|
+
for (let i = 0; i < author.length; i++) hash = (hash * 31 + author.charCodeAt(i)) | 0;
|
|
84
|
+
return AVATAR_COLOURS[Math.abs(hash) % AVATAR_COLOURS.length]!;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The avatar as an inline SVG data URI, sized 16×16 so it needs no HTML
|
|
89
|
+
* attributes to sit on the same line as the name.
|
|
90
|
+
*
|
|
91
|
+
* `charset=utf-8` matters: initials can be non-ASCII, and without it the
|
|
92
|
+
* browser decodes the percent-escapes as latin-1 and draws mojibake.
|
|
93
|
+
*/
|
|
94
|
+
export function avatarDataUri(author: string): string {
|
|
95
|
+
const svg =
|
|
96
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">` +
|
|
97
|
+
`<circle cx="8" cy="8" r="8" fill="#${authorColour(author)}"/>` +
|
|
98
|
+
`<text x="8" y="11.5" font-family="sans-serif" font-size="7" font-weight="700" ` +
|
|
99
|
+
`fill="#ffffff" text-anchor="middle">${escapeXml(authorInitials(author))}</text></svg>`;
|
|
100
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function escapeXml(text: string): string {
|
|
104
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** `command:id?["arg","arg"]`, percent-encoded as the opener expects. */
|
|
108
|
+
function commandUri(command: (typeof BLAME_HOVER_COMMANDS)[number], args: unknown[]): string {
|
|
109
|
+
return `command:${command}?${encodeURIComponent(JSON.stringify(args))}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface BlameHoverOptions {
|
|
113
|
+
commit: BlameCommitInfo;
|
|
114
|
+
/** Null while the `git show` is still in flight, or when it found nothing. */
|
|
115
|
+
detail: BlameLineDetail | null;
|
|
116
|
+
/** Project-relative path of the open file, for the action links. */
|
|
117
|
+
filePath: string;
|
|
118
|
+
/** Absolute path of the project, which is what the git-graph commands take. */
|
|
119
|
+
projectPath?: string;
|
|
120
|
+
/** Parameter rather than the clock, so the wording is testable. */
|
|
121
|
+
now?: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The hover for a committed line.
|
|
126
|
+
*
|
|
127
|
+
* Returns null for an uncommitted line: there is no commit to describe, and the
|
|
128
|
+
* annotation already says "You, uncommitted changes".
|
|
129
|
+
*/
|
|
130
|
+
export function buildBlameHoverMarkdown(options: BlameHoverOptions): MonacoType.IMarkdownString | null {
|
|
131
|
+
const { commit, detail, filePath, projectPath, now = Date.now() } = options;
|
|
132
|
+
if (isUncommittedHash(commit.hash)) return null;
|
|
133
|
+
|
|
134
|
+
const author = commit.author || "Unknown";
|
|
135
|
+
const shortSha = commit.hash.slice(0, SHORT_SHA);
|
|
136
|
+
const lines: string[] = [];
|
|
137
|
+
|
|
138
|
+
// Row 1: avatar, author, and both readings of the date — "9 months ago" is
|
|
139
|
+
// what you want to know, the exact date is what you need to go looking.
|
|
140
|
+
const when = commit.authorTime > 0
|
|
141
|
+
? `${formatRelativeTime(commit.authorTime * 1000, now)} (${formatAbsoluteTime(commit.authorTime * 1000)})`
|
|
142
|
+
: "";
|
|
143
|
+
lines.push(`}) **${escapeMarkdown(author)}**${when ? ` $(history) ${escapeMarkdown(when)}` : ""}`);
|
|
144
|
+
|
|
145
|
+
// Row 2: the whole message, not just the summary the annotation shows.
|
|
146
|
+
const message = detail?.message || commit.summary;
|
|
147
|
+
if (message) {
|
|
148
|
+
lines.push("");
|
|
149
|
+
// A blank line inside the message would end the markdown paragraph and
|
|
150
|
+
// leave the body unindented; two trailing spaces make each line its own.
|
|
151
|
+
lines.push(escapeMarkdown(message).split("\n").join(" \n"));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// A rule between sections, as GitLens has. It must be preceded by a blank
|
|
155
|
+
// line: `text` then `---` on the next line is a setext heading in markdown,
|
|
156
|
+
// which would turn the last line of the commit message into a title.
|
|
157
|
+
const RULE = ["", "---", ""];
|
|
158
|
+
|
|
159
|
+
// Row 3: the sha, and the things PPM can actually do with it.
|
|
160
|
+
const actions = [
|
|
161
|
+
`[$(git-commit) ${shortSha}](${commandUri("ppm.blame.copySha", [commit.hash])} "Copy commit hash")`,
|
|
162
|
+
];
|
|
163
|
+
// The Git Graph views are addressed by absolute project path. Without one the
|
|
164
|
+
// links would dispatch an empty first argument, which the extension reads as
|
|
165
|
+
// "resolve the project yourself" — so it might open a *different* project's
|
|
166
|
+
// history. Better to not offer the button.
|
|
167
|
+
if (projectPath) {
|
|
168
|
+
actions.push(
|
|
169
|
+
`[$(history) File History](${commandUri("ppm.blame.fileHistory", [projectPath, filePath])} "Open the file's history")`,
|
|
170
|
+
`[$(users) Blame](${commandUri("ppm.blame.blameFile", [projectPath, filePath])} "Open the blame view")`,
|
|
171
|
+
`[$(git-branch) Graph](${commandUri("ppm.blame.showInGraph", [projectPath])} "Open the commit graph")`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
lines.push(...RULE);
|
|
175
|
+
lines.push(actions.join(" "));
|
|
176
|
+
|
|
177
|
+
// Row 4: what this commit did to this line.
|
|
178
|
+
const diff = [...(detail?.removed ?? []).map((l) => `-${l}`), ...(detail?.added ?? []).map((l) => `+${l}`)];
|
|
179
|
+
if (diff.length > 0) {
|
|
180
|
+
lines.push(...RULE);
|
|
181
|
+
lines.push("```diff");
|
|
182
|
+
lines.push(...diff);
|
|
183
|
+
lines.push("```");
|
|
184
|
+
lines.push("");
|
|
185
|
+
// GitLens' wording, and the distinction is worth keeping: a line that only
|
|
186
|
+
// ever appeared in this commit reads differently from one it rewrote.
|
|
187
|
+
const verb = (detail?.removed.length ?? 0) === 0 ? "added in" : "in";
|
|
188
|
+
lines.push(`Changes ${verb} \`${shortSha}\``);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
value: lines.join("\n"),
|
|
193
|
+
// Narrowed on purpose. `true` here would let a commit message's own
|
|
194
|
+
// `command:` link run anything registered, and a commit message is not
|
|
195
|
+
// ours. See the module comment.
|
|
196
|
+
isTrusted: { enabledCommands: [...BLAME_HOVER_COMMANDS] },
|
|
197
|
+
supportThemeIcons: true,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery for the one failure that empties the screen instead of reporting an
|
|
3
|
+
* error: a lazy chunk the running app asks for and cannot get.
|
|
4
|
+
*
|
|
5
|
+
* The chain, reproduced end to end. An upgrade replaces `dist/web` and Vite's
|
|
6
|
+
* `emptyOutDir` deletes the previous content hashes, so a tab that has been open
|
|
7
|
+
* across the upgrade asks for a chunk that is no longer on disk. `static.ts`
|
|
8
|
+
* used to answer that with the app shell — `200 text/html` — which a module load
|
|
9
|
+
* refuses on its strict MIME check; it now answers 404, but a 404 is still a
|
|
10
|
+
* rejected `import()`, which is a throw inside `React.lazy`. A throw with no
|
|
11
|
+
* boundary above it unmounts the whole tree: `#root` empties and the page is
|
|
12
|
+
* left showing nothing but the body's background.
|
|
13
|
+
*
|
|
14
|
+
* The service worker made it *permanent*. `CacheFirst` on `/assets/` had stored
|
|
15
|
+
* that `text/html` under the chunk's own URL, and content-hashed assets are
|
|
16
|
+
* never revalidated — so restoring the file on the server changed nothing and
|
|
17
|
+
* only `caches.delete("ppm-assets")` recovered the tab. `sw.ts` now refuses to
|
|
18
|
+
* store or serve HTML for an asset, but an install that already holds a poisoned
|
|
19
|
+
* entry has to be cleaned from the page, which is what this does before
|
|
20
|
+
* reloading.
|
|
21
|
+
*
|
|
22
|
+
* Reloading is allowed once per tab. A second failure means the chunk is
|
|
23
|
+
* genuinely unavailable, and a page that reloads itself forever is worse than
|
|
24
|
+
* one that says what happened.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const RELOAD_KEY = "ppm:chunk-reload";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Set once a recovery reload is on its way, and read by the `beforeunload`
|
|
31
|
+
* guard in `app.tsx`.
|
|
32
|
+
*
|
|
33
|
+
* That guard is unconditional while authenticated — it exists to catch a stray
|
|
34
|
+
* Ctrl+W — and `beforeunload` cannot tell who asked for the navigation. So the
|
|
35
|
+
* automatic recovery put a "Leave site?" dialog in front of the one reload the
|
|
36
|
+
* user never chose and cannot act on knowledgeably: the tab is already showing
|
|
37
|
+
* a broken app. Declining it leaves them there.
|
|
38
|
+
*/
|
|
39
|
+
let recoveryReloadPending = false;
|
|
40
|
+
|
|
41
|
+
export function isRecoveryReloadPending(): boolean {
|
|
42
|
+
return recoveryReloadPending;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The wordings browsers use when a dynamic import does not produce a module.
|
|
47
|
+
* Chrome, Firefox and Safari each phrase it differently, and the MIME refusal
|
|
48
|
+
* is phrased differently again from a plain network failure.
|
|
49
|
+
*/
|
|
50
|
+
const CHUNK_ERROR =
|
|
51
|
+
/dynamically imported module|importing a module script failed|failed to load module script|error loading chunk|expected a javascript(-or-wasm)? module script/i;
|
|
52
|
+
|
|
53
|
+
export function isChunkLoadError(error: unknown): boolean {
|
|
54
|
+
if (!error) return false;
|
|
55
|
+
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
56
|
+
return CHUNK_ERROR.test(message);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Drop the caches this app owns, so the next load asks the server again. */
|
|
60
|
+
export async function purgeAssetCaches(): Promise<void> {
|
|
61
|
+
if (typeof caches === "undefined") return;
|
|
62
|
+
try {
|
|
63
|
+
const names = await caches.keys();
|
|
64
|
+
await Promise.all(names.filter((n) => n.startsWith("ppm-")).map((n) => caches.delete(n)));
|
|
65
|
+
} catch {
|
|
66
|
+
// A browser in private mode can refuse the Cache API outright. Reloading
|
|
67
|
+
// without the purge is still the right next move.
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Purge and reload unconditionally — the button in the error boundary. */
|
|
72
|
+
export async function purgeAndReload(): Promise<void> {
|
|
73
|
+
try {
|
|
74
|
+
sessionStorage.removeItem(RELOAD_KEY);
|
|
75
|
+
} catch {
|
|
76
|
+
// Nothing to clear; the reload below is what matters.
|
|
77
|
+
}
|
|
78
|
+
recoveryReloadPending = true;
|
|
79
|
+
await purgeAssetCaches();
|
|
80
|
+
window.location.reload();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Purge and reload at most once per tab. Returns whether a reload was started,
|
|
85
|
+
* so a caller can tell "recovering" from "this is as good as it gets".
|
|
86
|
+
*/
|
|
87
|
+
export function reloadOnceForChunkError(): boolean {
|
|
88
|
+
let already: boolean;
|
|
89
|
+
try {
|
|
90
|
+
already = sessionStorage.getItem(RELOAD_KEY) === "1";
|
|
91
|
+
sessionStorage.setItem(RELOAD_KEY, "1");
|
|
92
|
+
} catch {
|
|
93
|
+
// No storage means no way to count attempts, and an uncounted auto-reload
|
|
94
|
+
// is an infinite loop. Leave it to the boundary's button.
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (already) return false;
|
|
98
|
+
recoveryReloadPending = true;
|
|
99
|
+
void purgeAssetCaches().then(() => window.location.reload());
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function installChunkErrorRecovery(): void {
|
|
104
|
+
// Vite's preload helper dispatches this when a chunk, or one of the chunks it
|
|
105
|
+
// preloads, cannot be fetched. It is deliberately *not* `preventDefault`ed:
|
|
106
|
+
// cancelling the event makes the helper resolve with `undefined` rather than
|
|
107
|
+
// rethrow, and `React.lazy` then fails reading `.default` of undefined — an
|
|
108
|
+
// error that says nothing about what actually happened. The reload normally
|
|
109
|
+
// wins the race; when it does not, the boundary catches the real throw.
|
|
110
|
+
window.addEventListener("vite:preloadError", () => {
|
|
111
|
+
reloadOnceForChunkError();
|
|
112
|
+
});
|
|
113
|
+
}
|