@hienlh/ppm 0.21.0 → 0.22.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 +41 -0
- package/CLAUDE.md +29 -4
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/bun.lock +16 -1
- package/dist/web/assets/accounts-settings-section-BVr9-FZJ.js +1 -0
- package/dist/web/assets/{ai-resource-editor-F09pf8Hd.js → ai-resource-editor-CdDpOwjh.js} +1 -1
- package/dist/web/assets/ai-settings-section-B1hQyjAd.js +1 -0
- package/dist/web/assets/ai-settings-section-X2UOfSaS.js +1 -0
- package/dist/web/assets/{angular-html-DkR4iCth.js → angular-html-G66FNlyn.js} +1 -1
- package/dist/web/assets/{angular-ts-DcyL4Chx.js → angular-ts-B-PnUMyt.js} +1 -1
- package/dist/web/assets/{api-client-bfB7cXRM.js → api-client-C1ZwRL4Y.js} +1 -1
- package/dist/web/assets/api-client-pQL53cDQ.js +1 -0
- package/dist/web/assets/{api-settings-BcNjZIvG.js → api-settings-_7Q-ULxp.js} +1 -1
- package/dist/web/assets/{api-themes-DBfyVUtX.js → api-themes-DRAERo4Q.js} +1 -1
- package/dist/web/assets/{apl-BVlrVtjt.js → apl-BmDqqwE8.js} +1 -1
- package/dist/web/assets/{appearance-settings-section-whgnq3ss.js → appearance-settings-section-DLoPK0LD.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-Dx6nBEKT.js +1 -0
- package/dist/web/assets/{astro-MjJlozLj.js → astro-BfwMNfxr.js} +1 -1
- package/dist/web/assets/{audio-preview-Bc54GCAV.js → audio-preview-DsYvgKqj.js} +1 -1
- package/dist/web/assets/{blade-DnJWi1fz.js → blade-BsFV4pnN.js} +1 -1
- package/dist/web/assets/branch-review-tab-G84Ojzae.js +1 -0
- package/dist/web/assets/{bsl-DCmJxSIz.js → bsl-Cw9Outng.js} +1 -1
- package/dist/web/assets/{button-VW4QGKCn.js → button-B9CTrsEf.js} +1 -1
- package/dist/web/assets/{cairo-C8dDenub.js → cairo-DOK5Wqnd.js} +1 -1
- package/dist/web/assets/chat-tab-DQJfjm8E.js +15 -0
- package/dist/web/assets/{cobol-DPx_nifl.js → cobol-DRaRy4FK.js} +1 -1
- package/dist/web/assets/code-editor-D04iUPsZ.js +7 -0
- package/dist/web/assets/{codex-daily-guard-CfybHv_c.js → codex-daily-guard-BSccLRGT.js} +1 -1
- package/dist/web/assets/{coffee-DvFzqhgN.js → coffee-DvXuBmEJ.js} +1 -1
- package/dist/web/assets/{conflict-editor-DenQUOT2.js → conflict-editor-C4ay676e.js} +2 -2
- package/dist/web/assets/context-menu-C6pIsf83.js +1 -0
- package/dist/web/assets/{cpp-BLJN0umi.js → cpp-zCmm8rKA.js} +1 -1
- package/dist/web/assets/{crystal-BXR-9fGw.js → crystal-CdQx6lB6.js} +1 -1
- package/dist/web/assets/{csv-preview-CClrJOuR.js → csv-preview-DbwEmG7o.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-D4fhcMfT.js → data-grid-overlay-editor-6xUCeLHh.js} +1 -1
- package/dist/web/assets/{database-viewer-DItjm8wB.js → database-viewer-S6LsALjX.js} +1 -1
- package/dist/web/assets/{dialog-DQTn55Mt.js → dialog-B84_DJQ8.js} +1 -1
- package/dist/web/assets/diff-viewer-3oBA7vgQ.js +4 -0
- package/dist/web/assets/{docx-preview-DYBkiUaE.js → docx-preview-CXuk-emm.js} +1 -1
- package/dist/web/assets/{edge-rWOlCmXT.js → edge-E8QLt7oi.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-COtmo54G.js → edit-diff-preview-BGGGecVw.js} +1 -1
- package/dist/web/assets/{editor-language-service-DxkZ51E5.js → editor-language-service-DJmaKVY0.js} +1 -1
- package/dist/web/assets/{elixir-E7Y82okW.js → elixir-DPb_-72P.js} +1 -1
- package/dist/web/assets/{elm-DTPGbc-w.js → elm-BMzJY5b0.js} +1 -1
- package/dist/web/assets/{erb-DHqLHrE6.js → erb-AABQNtMK.js} +1 -1
- package/dist/web/assets/{erlang-Byg0nNiV.js → erlang-CEIKOkfP.js} +1 -1
- package/dist/web/assets/{esm-D_DmOM7n.js → esm-B9RVMpwV.js} +1 -1
- package/dist/web/assets/explorer-body-BQ0jyAGv.js +2 -0
- package/dist/web/assets/explorer-window-content-jdkWt34J.js +1 -0
- package/dist/web/assets/{extension-manager-section-BhwB6nqr.js → extension-manager-section-DG1guILi.js} +1 -1
- package/dist/web/assets/{extension-webview-DI4VL2tJ.js → extension-webview-BGSDUbdK.js} +1 -1
- package/dist/web/assets/file-icons-BXdvggK2.js +1 -0
- package/dist/web/assets/file-icons.generated-BtBErEwb.css +1 -0
- package/dist/web/assets/file-store-ojgMXgAw.js +1 -0
- package/dist/web/assets/files-settings-section-Gnyd7han.js +1 -0
- package/dist/web/assets/{format-file-meta-DOpzJJhS.js → format-file-meta-C77h04cZ.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-CY1n0Xf6.js → fortran-fixed-form-CrXvLHyi.js} +1 -1
- package/dist/web/assets/{fsharp-_vEDSCJz.js → fsharp-DCI4qAz_.js} +1 -1
- package/dist/web/assets/{gdresource-B6XT0wAC.js → gdresource-Vb2kO1MG.js} +1 -1
- package/dist/web/assets/{general-settings-section-BcxwiZ0X.js → general-settings-section-V6Khh15V.js} +1 -1
- package/dist/web/assets/{git-commit-Wk9ovq59.js → git-commit-BMI_OWn-.js} +1 -1
- package/dist/web/assets/git-log-panel-Bi513qjT.js +1 -0
- package/dist/web/assets/{git-rebase-DSarGPvK.js → git-rebase-D-d_2iqZ.js} +1 -1
- package/dist/web/assets/{git-repo-store-Dy69YCHN.js → git-repo-store-88Z8v-pF.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-C6qRruHI.js +1 -0
- package/dist/web/assets/{glide-data-grid-BvgAqSUr.js → glide-data-grid-DnQwYSmQ.js} +7 -7
- package/dist/web/assets/{glimmer-js-CkYI35_P.js → glimmer-js-BmNNiR0Z.js} +1 -1
- package/dist/web/assets/{glimmer-ts-BqmIZcds.js → glimmer-ts-DQE2Ufha.js} +1 -1
- package/dist/web/assets/{glsl-Be-yBCF5.js → glsl-BcIDsxRJ.js} +1 -1
- package/dist/web/assets/{graphql-a5DrENHY.js → graphql-DGKSLmGH.js} +1 -1
- package/dist/web/assets/group-chat-tab-DpczdwyV.js +1 -0
- package/dist/web/assets/{hack-BLAg20aD.js → hack-YiC8bEIb.js} +1 -1
- package/dist/web/assets/{haml-Dj6bGOQH.js → haml-DjblxAsz.js} +1 -1
- package/dist/web/assets/{handlebars-dmEa36Oh.js → handlebars-BQepOXaU.js} +1 -1
- package/dist/web/assets/{html-yacZYzSE.js → html-Cayj_2GP.js} +1 -1
- package/dist/web/assets/{html-derivative-lLi3-RNT.js → html-derivative-Weq79bL6.js} +1 -1
- package/dist/web/assets/{http-1KaxcE4e.js → http-BeLfdGdz.js} +1 -1
- package/dist/web/assets/{hurl-ST-dEEZR.js → hurl-D9rypCLK.js} +1 -1
- package/dist/web/assets/{hxml-CpDtuq__.js → hxml-clG8mmSH.js} +1 -1
- package/dist/web/assets/{image-preview-CJVxL0uH.js → image-preview-CzCc4_Do.js} +1 -1
- package/dist/web/assets/image-preview-geometry-9lgeLYB3.js +1 -0
- package/dist/web/assets/index-BH99TIE0.css +1 -0
- package/dist/web/assets/index-DU68xk06.js +52 -0
- package/dist/web/assets/info-3K5VOQVL-BOSpdwlz.js +1 -0
- package/dist/web/assets/{jinja-Cjw-evAn.js → jinja-BShBWfs5.js} +1 -1
- package/dist/web/assets/{jira-watcher-section-DIC1yIV3.js → jira-watcher-section-f2HUbGDY.js} +1 -1
- package/dist/web/assets/{jison-DfATMYoY.js → jison-dN2Nf_Dr.js} +1 -1
- package/dist/web/assets/{julia-DDCaxiqT.js → julia-5U0vR-uJ.js} +1 -1
- package/dist/web/assets/{just-CJL529u6.js → just-BMppVRy6.js} +1 -1
- package/dist/web/assets/keybindings-store-DCRsnKg5.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-BW03P3AF.js → keyboard-shortcuts-section-BpvVEw_Y.js} +1 -1
- package/dist/web/assets/{latex-Zc4EpLpW.js → latex-DSSOKjis.js} +1 -1
- package/dist/web/assets/{liquid-B_6KMNYS.js → liquid-C24dKoyI.js} +1 -1
- package/dist/web/assets/{lua-BtS2idK7.js → lua-DNOsnyhn.js} +1 -1
- package/dist/web/assets/markdown-renderer-Bcaf9_bA.js +1 -0
- package/dist/web/assets/markdown-renderer-DGJp8HC3.js +3 -0
- package/dist/web/assets/{marko-Wk6LBnck.js → marko-26MHO_Q9.js} +1 -1
- package/dist/web/assets/{mdc-cRaXBrzL.js → mdc-Dhw9mGrC.js} +1 -1
- package/dist/web/assets/{media-url-DL8OCGGg.js → media-url-yfqHpPz0.js} +1 -1
- package/dist/web/assets/{mobile-bottom-sheet-CoUauvLF.js → mobile-bottom-sheet-C3TniEP-.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-Bol3XAO1.js +1 -0
- package/dist/web/assets/{nextflow-Bos2wvDV.js → nextflow-xH4oJTex.js} +1 -1
- package/dist/web/assets/{nginx-DMlOwzdr.js → nginx-CMz4w0M8.js} +1 -1
- package/dist/web/assets/{nim-D2dZQA88.js → nim-D8FnIYsx.js} +1 -1
- package/dist/web/assets/notification-store-BXt54VIn.js +1 -0
- package/dist/web/assets/{notifications-settings-section-DPUROMw-.js → notifications-settings-section-DqlPDfNX.js} +1 -1
- package/dist/web/assets/{number-overlay-editor-DZ2i_Bnb.js → number-overlay-editor-CRGwULhR.js} +1 -1
- package/dist/web/assets/{overview-panel-R146OIom.js → overview-panel-Di-3aV9p.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-BGIE1QdU.js +1 -0
- package/dist/web/assets/panel-store-CboGJAwh.js +1 -0
- package/dist/web/assets/{pdf-preview-BWUPGLp6.js → pdf-preview-CmBI6E7d.js} +1 -1
- package/dist/web/assets/{perl-C5-Z6fPn.js → perl-D9iNWYwb.js} +1 -1
- package/dist/web/assets/{php-BXNNhkMH.js → php-Bw3Qo0Zv.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-Dg-QTbXX.js +1 -0
- package/dist/web/assets/{postgres-viewer-CjOvaruz.js → postgres-viewer-8ZAqEALv.js} +3 -3
- package/dist/web/assets/{ppmbot-settings-section-DrvWh8l8.js → ppmbot-settings-section-DKJUA3Kq.js} +1 -1
- package/dist/web/assets/problems-panel-CFcoUx8h.js +1 -0
- package/dist/web/assets/{process-table-BRMS1MrX.js → process-table-EKr2dqG6.js} +1 -1
- package/dist/web/assets/project-framework-store-B70Q3dNM.js +1 -0
- package/dist/web/assets/project-store-B87hLRSk.js +1 -0
- package/dist/web/assets/{proxy-settings-section-Bv0Ny-Yy.js → proxy-settings-section-B7qRVl8w.js} +1 -1
- package/dist/web/assets/{pug-C1zf1yWy.js → pug-fT5JC6Vm.js} +1 -1
- package/dist/web/assets/{qml-OW58jGpD.js → qml-P_wEDB1w.js} +1 -1
- package/dist/web/assets/{query-audit-section-BcHJZcVC.js → query-audit-section-By6qyqdB.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-DZ6IVu2s.js +1 -0
- package/dist/web/assets/{razor-DzjSaobM.js → razor-Drrt2_Ph.js} +1 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-0WDYsyCA.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-COYDg16H.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-view-2DqSuS2U.js +1 -0
- package/dist/web/assets/{remote-desktop-readiness-gate-BTzss2wX.js → remote-desktop-readiness-gate-Dm_qMJMH.js} +1 -1
- package/dist/web/assets/remote-desktop-window-content-UodhsF7W.js +1 -0
- package/dist/web/assets/{rst-RfuihOUW.js → rst-Dr2mW4-h.js} +1 -1
- package/dist/web/assets/{ruby-CNO3pli1.js → ruby-C6EpUsTY.js} +1 -1
- package/dist/web/assets/{run-in-terminal-Cb_hVU8x.js → run-in-terminal-CdefEe_R.js} +1 -1
- package/dist/web/assets/{sas-DZY5BtXx.js → sas-D8ZEeP6v.js} +1 -1
- package/dist/web/assets/{schedules-settings-section-DO8xAOVj.js → schedules-settings-section-bG2lYfGv.js} +1 -1
- package/dist/web/assets/{scroll-area-LtNV8g5o.js → scroll-area-BzeiOd-B.js} +1 -1
- package/dist/web/assets/{scss--4g-REcN.js → scss-ITL7jQ1f.js} +1 -1
- package/dist/web/assets/{send-to-chat-Cnpru1M0.js → send-to-chat-F207yH3u.js} +1 -1
- package/dist/web/assets/{separator-Cds1yxy8.js → separator-TRMsJUYe.js} +1 -1
- package/dist/web/assets/settings-body-C06bFarv.js +2 -0
- package/dist/web/assets/settings-store-krC6bc79.js +2 -0
- package/dist/web/assets/settings-tab-34RSaASd.js +1 -0
- package/dist/web/assets/settings-window-content-Dr_2lmHH.js +1 -0
- package/dist/web/assets/{shaderlab-Cu4sBiVn.js → shaderlab-mW-IIlhk.js} +1 -1
- package/dist/web/assets/{shellsession-DWzJfEv7.js → shellsession-DhNl5STt.js} +1 -1
- package/dist/web/assets/{soy-BnqE-5Ff.js → soy-SdY0Qjtr.js} +1 -1
- package/dist/web/assets/{sparql-Ctg__NhZ.js → sparql-ftqZo2i-.js} +1 -1
- package/dist/web/assets/{sql-query-editor-D9k19T_M.js → sql-query-editor-BgRH0cHD.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-DoV9hnWJ.js → sqlite-viewer-DUxGslpa.js} +1 -1
- package/dist/web/assets/{stata-Qk2h66XW.js → stata-Bj7Yjb4b.js} +1 -1
- package/dist/web/assets/{surrealql-8QEX7EfH.js → surrealql-CLhYGAfB.js} +1 -1
- package/dist/web/assets/{svelte-D_mubC5-.js → svelte-DTAlRHhK.js} +1 -1
- package/dist/web/assets/system-monitor-body-IZuLn7Qh.js +2 -0
- package/dist/web/assets/system-monitor-tab-DiSA490Z.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-qXLcicFM.js → system-monitor-window-content-CEaFISgj.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-7fPZNEni.js → tab-host-window-content-D0TN8Wrq.js} +1 -1
- package/dist/web/assets/{tab-store-DGJGnbwv.js → tab-store-OJa1GPCq.js} +1 -1
- package/dist/web/assets/team-member-sheet-DDPNcCjd.js +2 -0
- package/dist/web/assets/{team-member-window-content-BgvJFypM.js → team-member-window-content-DCiW_1-E.js} +1 -1
- package/dist/web/assets/{templ-C1jV0fsO.js → templ-BMfhACxb.js} +1 -1
- package/dist/web/assets/{terminal-tab-Cs0sGljx.js → terminal-tab-4ypP0NDY.js} +3 -3
- package/dist/web/assets/{tex-D_StFXy_.js → tex-BcssM-QA.js} +1 -1
- package/dist/web/assets/tool-cards-Dd6E7Q3k.js +9 -0
- package/dist/web/assets/treemap-KZPCXAKY-CE30wCXa.js +1 -0
- package/dist/web/assets/{ts-tags-B5m47rEm.js → ts-tags-CrR5IYI8.js} +1 -1
- package/dist/web/assets/{twig-C_br6GIl.js → twig-DchfUmyI.js} +1 -1
- package/dist/web/assets/{use-blob-url-C-SGi_Hb.js → use-blob-url-CPtCcY3i.js} +1 -1
- package/dist/web/assets/{use-inline-blame-B4trxGcR.js → use-inline-blame-vrfFHuaR.js} +1 -1
- package/dist/web/assets/{use-lsp-CV0vzILO.js → use-lsp-CsuZu49X.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-DBqbWjWX.js → use-monaco-theme-BIVYJBIn.js} +1 -1
- package/dist/web/assets/{use-open-team-member-DENsjp0s.js → use-open-team-member-C3mrUzIC.js} +1 -1
- package/dist/web/assets/{use-websocket-LgXiX1qN.js → use-websocket-BMbufhX7.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-Cbig5zA6.js → vendor-mermaid-BitiXJlL.js} +1 -1
- package/dist/web/assets/{vendor-ui-BBdkypKW.js → vendor-ui-DmZ-Mb-H.js} +1 -1
- package/dist/web/assets/video-preview-Byj8P_jA.js +1 -0
- package/dist/web/assets/{vue-DQwCnLdr.js → vue-1EL6Pw1h.js} +1 -1
- package/dist/web/assets/{vue-html-T_EoGpPJ.js → vue-html-BPQNwPC6.js} +1 -1
- package/dist/web/assets/{vue-vine-DmxLqX50.js → vue-vine-Bb_dsWLt.js} +1 -1
- package/dist/web/assets/{window-pip-registry-3l4hoxuD.js → window-pip-registry-yD6esSju.js} +1 -1
- package/dist/web/assets/ws-auth-CEYVQ8NH.js +1 -0
- package/dist/web/assets/{xml-Bs6Bw8is.js → xml-dxkLNA0K.js} +1 -1
- package/dist/web/assets/{xsl-f5ZNhRCc.js → xsl-Bw2adwrl.js} +1 -1
- package/dist/web/index.html +27 -26
- package/dist/web/sw.js +1 -1
- package/docs/architecture/plugins-and-tracing.md +285 -0
- package/docs/lessons-learned.md +31 -0
- package/docs/system-architecture.md +1 -0
- package/package.json +2 -1
- package/packages/ext-git-graph/src/compare-diff-base.test.ts +173 -0
- package/packages/ext-git-graph/src/compare-view.ts +22 -3
- package/packages/ext-git-graph/src/extension.ts +6 -0
- package/packages/ext-git-graph/src/types.ts +19 -0
- package/packages/ext-git-graph/src/webview-html.test.ts +134 -1
- package/packages/ext-git-graph/src/webview-html.ts +277 -27
- package/scripts/gen-file-icons.ts +493 -242
- package/src/providers/claude-agent-sdk.ts +42 -1
- package/src/providers/codex-app-server/codex-history.ts +77 -23
- package/src/server/index.ts +42 -7
- package/src/server/routes/chat.ts +15 -11
- package/src/server/routes/git.ts +83 -3
- package/src/server/routes/remote-desktop.ts +7 -2
- package/src/server/ws/global.ts +1 -1
- package/src/server/ws/remote-desktop.ts +12 -5
- package/src/services/binary-content.ts +25 -0
- package/src/services/chat-search.service.ts +1 -1
- package/src/services/chat.service.ts +9 -0
- package/src/services/event-loop-lag.ts +208 -0
- package/src/services/file-lines.ts +114 -0
- package/src/services/file-watcher/recreated-dir-poller.ts +108 -6
- package/src/services/file-watcher/watch-tree.ts +131 -10
- package/src/services/file-watcher.service.ts +73 -23
- package/src/services/git-branch-diff/branch-diff-parse.ts +151 -0
- package/src/services/git-branch-diff/branch-diff.service.ts +79 -0
- package/src/services/git-hunks/git-hunks.service.ts +26 -11
- package/src/services/git-hunks/unified-diff.ts +15 -1
- package/src/services/git.service.ts +74 -24
- package/src/services/jsonl-transcript-parser.ts +138 -6
- package/src/services/log-rotate.ts +142 -0
- package/src/services/media-transcode/ffmpeg-capabilities.ts +72 -2
- package/src/services/remote-desktop/remote-desktop-audio.ts +193 -0
- package/src/services/remote-desktop/remote-desktop-capture-input.ts +87 -14
- package/src/services/remote-desktop/remote-desktop-capture.ts +40 -7
- package/src/services/remote-desktop/remote-desktop-clipboard.ts +166 -0
- package/src/services/remote-desktop/remote-desktop-displays.ts +77 -1
- package/src/services/remote-desktop/remote-desktop-encoder-args.ts +25 -6
- package/src/services/remote-desktop/remote-desktop-evdev-key-map.ts +69 -0
- package/src/services/remote-desktop/remote-desktop-input-linux.ts +253 -0
- package/src/services/remote-desktop/remote-desktop-input-uinput.ts +242 -0
- package/src/services/remote-desktop/remote-desktop-input.ts +40 -8
- package/src/services/remote-desktop/remote-desktop-linux-session.ts +146 -0
- package/src/services/remote-desktop/remote-desktop-ogg-opus.ts +144 -0
- package/src/services/remote-desktop/remote-desktop-privacy.ts +163 -0
- package/src/services/remote-desktop/remote-desktop-quality.ts +138 -0
- package/src/services/remote-desktop/remote-desktop-requirements.ts +158 -5
- package/src/services/remote-desktop/remote-desktop-resolution.ts +302 -0
- package/src/services/remote-desktop/remote-desktop-session.ts +523 -21
- package/src/services/remote-desktop/remote-desktop-x11.ts +250 -0
- package/src/services/supervisor.ts +47 -4
- package/src/shared/remote-desktop-custom-quality.ts +117 -0
- package/src/shared/remote-desktop-quality.ts +127 -0
- package/src/types/chat.ts +4 -0
- package/src/types/git.ts +52 -0
- package/src/web/components/branch-review/branch-review-tab.tsx +360 -0
- package/src/web/components/branch-review/branch-review-tree-row.tsx +138 -0
- package/src/web/components/chat/attachment-chips.tsx +30 -6
- package/src/web/components/chat/chat-tab.tsx +12 -1
- package/src/web/components/chat/message-events.tsx +273 -0
- package/src/web/components/chat/message-list.tsx +107 -861
- package/src/web/components/chat/message-markdown.tsx +34 -0
- package/src/web/components/chat/message-media.tsx +174 -0
- package/src/web/components/chat/message-user-bubble.tsx +399 -0
- package/src/web/components/chat/provider-selector.tsx +30 -22
- package/src/web/components/chat/session-history-list.tsx +2 -2
- package/src/web/components/chat/session-list-panel.tsx +3 -2
- package/src/web/components/editor/binary-diff-view.tsx +212 -0
- package/src/web/components/editor/diff-viewer.tsx +76 -3
- package/src/web/components/explorer/file-tree.tsx +235 -134
- package/src/web/components/explorer/flatten-visible-tree.ts +35 -40
- package/src/web/components/explorer/tree-node.tsx +69 -69
- package/src/web/components/explorer/use-tree-row-dnd.ts +3 -4
- package/src/web/components/git/git-status-panel.tsx +25 -0
- package/src/web/components/layout/draggable-tab.tsx +4 -2
- package/src/web/components/layout/nav-section-rail.tsx +12 -3
- package/src/web/components/layout/status-bar.tsx +10 -6
- package/src/web/components/layout/tab-content.tsx +5 -0
- package/src/web/components/layout/tab-pool.tsx +1 -0
- package/src/web/components/layout/upgrade-button.tsx +5 -1
- package/src/web/components/remote-desktop/remote-desktop-clipboard-client.ts +67 -0
- package/src/web/components/remote-desktop/remote-desktop-clipboard-notice.tsx +127 -0
- package/src/web/components/remote-desktop/remote-desktop-codec-labels.ts +28 -0
- package/src/web/components/remote-desktop/remote-desktop-custom-quality-dialog.tsx +144 -0
- package/src/web/components/remote-desktop/remote-desktop-mobile-key-bar.tsx +13 -2
- package/src/web/components/remote-desktop/remote-desktop-mobile-settings.tsx +232 -0
- package/src/web/components/remote-desktop/remote-desktop-mobile-toolbar.tsx +21 -8
- package/src/web/components/remote-desktop/remote-desktop-mobile-view.tsx +82 -3
- package/src/web/components/remote-desktop/remote-desktop-recording.ts +76 -0
- package/src/web/components/remote-desktop/remote-desktop-resolution-list.ts +100 -0
- package/src/web/components/remote-desktop/remote-desktop-toolbar.tsx +497 -0
- package/src/web/components/remote-desktop/remote-desktop-view-style.ts +145 -0
- package/src/web/components/remote-desktop/remote-desktop-window-content.tsx +126 -35
- package/src/web/components/remote-desktop/use-h264-canvas-decoder.ts +11 -0
- package/src/web/components/remote-desktop/use-opus-audio-player.ts +148 -0
- package/src/web/components/remote-desktop/use-remote-desktop-connection.ts +284 -1
- package/src/web/components/remote-desktop/use-remote-desktop-readiness.ts +75 -1
- package/src/web/components/remote-desktop/use-remote-desktop-recorder.ts +103 -0
- package/src/web/components/remote-desktop/use-remote-desktop-virtual-keyboard.ts +19 -2
- package/src/web/components/remote-desktop/use-remote-input-capture.ts +39 -3
- package/src/web/components/settings/theme-picker.tsx +2 -1
- package/src/web/components/ui/tooltip.tsx +15 -2
- package/src/web/hooks/use-delayed-flag.ts +35 -0
- package/src/web/lib/branch-review-state.ts +175 -0
- package/src/web/lib/file-icon-name.ts +62 -0
- package/src/web/lib/file-icons.generated.ts +3287 -25
- package/src/web/lib/file-icons.tsx +71 -73
- package/src/web/lib/flatten-expansions.ts +18 -5
- package/src/web/lib/message-ordinals.ts +23 -0
- package/src/web/lib/provider-logos.tsx +143 -0
- package/src/web/lib/tab-type-icons.ts +11 -0
- package/src/web/stores/file-store.ts +73 -35
- package/src/web/stores/panel-utils.ts +5 -0
- package/src/web/stores/project-framework-store.ts +82 -0
- package/src/web/stores/project-store.ts +7 -1
- package/src/web/stores/settings-store.ts +128 -0
- package/src/web/stores/tab-store.ts +1 -0
- package/src/web/stores/window-panel-persistence.ts +1 -0
- package/src/web/styles/file-icons.generated.css +3282 -234
- package/src/web/styles/globals.css +26 -0
- package/dist/web/assets/accounts-settings-section-BuxD9zH3.js +0 -1
- package/dist/web/assets/ai-settings-section-Dd9tOUp0.js +0 -1
- package/dist/web/assets/ai-settings-section-FrU2X8Fu.js +0 -1
- package/dist/web/assets/api-client-BUCo1lms.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-5K0wEkAn.js +0 -1
- package/dist/web/assets/chat-tab-Cr6_KSGO.js +0 -15
- package/dist/web/assets/code-editor-DfmlGamv.js +0 -7
- package/dist/web/assets/context-menu-DOODKZdF.js +0 -1
- package/dist/web/assets/diff-viewer-BpNj7pN9.js +0 -4
- package/dist/web/assets/explorer-body-D-5z464e.js +0 -2
- package/dist/web/assets/explorer-window-content-7-1wuRul.js +0 -1
- package/dist/web/assets/file-icons-EzPL0q-k.js +0 -1
- package/dist/web/assets/file-icons.generated-CfaJuvZu.css +0 -1
- package/dist/web/assets/file-store-DMABxOkV.js +0 -1
- package/dist/web/assets/files-settings-section-CZzABuKz.js +0 -1
- package/dist/web/assets/git-log-panel-CRN4JVOx.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-DkVT2MAM.js +0 -1
- package/dist/web/assets/group-chat-tab-DFa5mAx5.js +0 -1
- package/dist/web/assets/index-D7DbXD3G.css +0 -1
- package/dist/web/assets/index-ZtfxZOyb.js +0 -52
- package/dist/web/assets/info-3K5VOQVL-BBsmKGzA.js +0 -1
- package/dist/web/assets/keybindings-store-tVfhPANS.js +0 -1
- package/dist/web/assets/markdown-renderer-CvL1pWeK.js +0 -3
- package/dist/web/assets/markdown-renderer-sJNNVhlS.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-CZ0HZ2E_.js +0 -1
- package/dist/web/assets/notification-store-BZbsPnW0.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-DwmYPOlx.js +0 -1
- package/dist/web/assets/panel-store-BVLBRn6M.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-D0oogIFi.js +0 -1
- package/dist/web/assets/problems-panel-B7BWVhdy.js +0 -1
- package/dist/web/assets/project-store-BhMbVln3.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-CQIJOQGa.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-ByjaeZKX.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-view-D13mtr9F.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-CbqTCaC6.js +0 -1
- package/dist/web/assets/settings-body-Rnu-FcX-.js +0 -2
- package/dist/web/assets/settings-store-DZPgPtEA.js +0 -2
- package/dist/web/assets/settings-tab-C6PHxs0Z.js +0 -1
- package/dist/web/assets/settings-window-content-CQ4gT2qj.js +0 -1
- package/dist/web/assets/system-monitor-body-2vQ1kMxE.js +0 -2
- package/dist/web/assets/system-monitor-tab-krAcvwF7.js +0 -1
- package/dist/web/assets/team-member-sheet-2FnRmk1a.js +0 -2
- package/dist/web/assets/tool-cards-DU_S2o51.js +0 -9
- package/dist/web/assets/treemap-KZPCXAKY-BhEtjljr.js +0 -1
- package/dist/web/assets/use-remote-desktop-display-choice-BK_f787P.js +0 -1
- package/dist/web/assets/video-preview-BDNwumbW.js +0 -1
- package/dist/web/assets/ws-auth-DEAJiGCR.js +0 -1
- /package/dist/web/assets/{abap-tkptwpsK.js → abap-IN2yINdN.js} +0 -0
- /package/dist/web/assets/{actionscript-3-Di9TMGwg.js → actionscript-3-C_t772eR.js} +0 -0
- /package/dist/web/assets/{ada-CB9F079D.js → ada-DPme3emm.js} +0 -0
- /package/dist/web/assets/{andromeeda-Dcl8jpb7.js → andromeeda-DSV4i4mZ.js} +0 -0
- /package/dist/web/assets/{apache-D0Nk0qsH.js → apache-CWr8s8I8.js} +0 -0
- /package/dist/web/assets/{apex-mQIoWncD.js → apex-Z20JnDF5.js} +0 -0
- /package/dist/web/assets/{applescript-C6ljbcsI.js → applescript-BKNPu3ga.js} +0 -0
- /package/dist/web/assets/{apply-theme-BwIMNXyX.js → apply-theme-CbR31K6I.js} +0 -0
- /package/dist/web/assets/{ara-WFqRPGPe.js → ara-hWdY3O96.js} +0 -0
- /package/dist/web/assets/{asciidoc-bNd8w4nf.js → asciidoc-eynhq496.js} +0 -0
- /package/dist/web/assets/{asm-BQ1_F580.js → asm-Bu02Kq4P.js} +0 -0
- /package/dist/web/assets/{aurora-x-Ciqs_Dbu.js → aurora-x-BHBGXbIZ.js} +0 -0
- /package/dist/web/assets/{awk-GCR-6KZV.js → awk-B4ojezyv.js} +0 -0
- /package/dist/web/assets/{ayu-dark-DxJXuj99.js → ayu-dark-D0GQzFi9.js} +0 -0
- /package/dist/web/assets/{ayu-light-jvSyJWDV.js → ayu-light-BVYb5Yn8.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-Cg3BPO6H.js → ayu-mirage-BGFW6oNb.js} +0 -0
- /package/dist/web/assets/{ballerina-BPz4CrX6.js → ballerina-B6Og3IKT.js} +0 -0
- /package/dist/web/assets/{bat-CSTs2hIG.js → bat-D8YFILfx.js} +0 -0
- /package/dist/web/assets/{beancount-DMateAZX.js → beancount-BjlbBBuX.js} +0 -0
- /package/dist/web/assets/{berry-9lXg0GRM.js → berry-Cz1ygeoj.js} +0 -0
- /package/dist/web/assets/{bibtex-DIbqmvFg.js → bibtex-CVkJceJh.js} +0 -0
- /package/dist/web/assets/{bicep-02WGsoJ8.js → bicep-DrhYI5GX.js} +0 -0
- /package/dist/web/assets/{bird2-BY0tbu3k.js → bird2-BV-KJtmc.js} +0 -0
- /package/dist/web/assets/{c-jMBX_9Je.js → c-CuLlvxbG.js} +0 -0
- /package/dist/web/assets/{c3-B8JVbNjW.js → c3-CI7-1CJ0.js} +0 -0
- /package/dist/web/assets/{cadence-DUIf1tvL.js → cadence-DjxhNP3Q.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-DGEc0s4P.js → can-open-in-ppm-cv5--yHX.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-FhUCVxex.js → catppuccin-frappe-CEozpJRh.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-CzfrtmgL.js → catppuccin-latte-C4sXQFMc.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-6xL0lOtj.js → catppuccin-macchiato-Ci-fDhXy.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-D39-xS3P.js → catppuccin-mocha-CH7YXw8d.js} +0 -0
- /package/dist/web/assets/{clarity-D8TeGvoT.js → clarity-BWrJ7UmT.js} +0 -0
- /package/dist/web/assets/{clojure-Dx_acSX7.js → clojure-C94fh2hb.js} +0 -0
- /package/dist/web/assets/{cmake-CyeYPq8o.js → cmake-CtvCkMsG.js} +0 -0
- /package/dist/web/assets/{codeowners-DrTI0lmI.js → codeowners-CJnubqzH.js} +0 -0
- /package/dist/web/assets/{codeql-CPkFxVW-.js → codeql-BOoP5HY2.js} +0 -0
- /package/dist/web/assets/{common-lisp-B0k-3LTj.js → common-lisp-B9nlMFJd.js} +0 -0
- /package/dist/web/assets/{coq-uygpo7to.js → coq-CgzIQiSH.js} +0 -0
- /package/dist/web/assets/{csharp-DKUYGfSp.js → csharp-4xAIx3jw.js} +0 -0
- /package/dist/web/assets/{css-DoOUp7v4.js → css-D4YoLYGn.js} +0 -0
- /package/dist/web/assets/{csv-B3YE13gi.js → csv-C2v-ZakW.js} +0 -0
- /package/dist/web/assets/{csv-parser-DXePqmXe.js → csv-parser-_oDBUkwQ.js} +0 -0
- /package/dist/web/assets/{cue-DViO2wvn.js → cue-Bbznh_an.js} +0 -0
- /package/dist/web/assets/{cypher-4BMCIW5N.js → cypher-BKhVEARF.js} +0 -0
- /package/dist/web/assets/{d-BT_sTHas.js → d-D6IhWopl.js} +0 -0
- /package/dist/web/assets/{dark-plus-DVVXu-1N.js → dark-plus-xAWu790O.js} +0 -0
- /package/dist/web/assets/{dart-DHz6f6_6.js → dart-Bj6S9O1j.js} +0 -0
- /package/dist/web/assets/{data-grid-types-OgUxMLdQ.js → data-grid-types-C5bthITf.js} +0 -0
- /package/dist/web/assets/{dax-ChYCjweK.js → dax-CF2zvaqq.js} +0 -0
- /package/dist/web/assets/{desktop-D6Lt4p04.js → desktop-CnmyxMKE.js} +0 -0
- /package/dist/web/assets/{diff-D8TDe4hP.js → diff-Qi8WuJsI.js} +0 -0
- /package/dist/web/assets/{dist-DOTlFQJA.js → dist-Bjseolz4.js} +0 -0
- /package/dist/web/assets/{dist-CrBOCtCW.js → dist-Czq7BUMy.js} +0 -0
- /package/dist/web/assets/{docker-Bsp0YbPx.js → docker-vLbbNP5d.js} +0 -0
- /package/dist/web/assets/{dotenv-B_7giSY_.js → dotenv-DJMvvNzn.js} +0 -0
- /package/dist/web/assets/{dracula-TrQL2iB5.js → dracula-CtAh2rhB.js} +0 -0
- /package/dist/web/assets/{dracula-soft-n2XOlgh-.js → dracula-soft-CXtuAAf6.js} +0 -0
- /package/dist/web/assets/{dream-maker-CdIEdhpT.js → dream-maker-D5YQyK49.js} +0 -0
- /package/dist/web/assets/{editor-font-BDrdiGf1.js → editor-font-ClTC9gaD.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CSbixs6u.js → emacs-lisp-CGTjbiqF.js} +0 -0
- /package/dist/web/assets/{everforest-dark-BuZahZYp.js → everforest-dark-D59p7vAQ.js} +0 -0
- /package/dist/web/assets/{everforest-light-DPH53z5H.js → everforest-light-B3Qtud3V.js} +0 -0
- /package/dist/web/assets/{fennel-B1-K_hlJ.js → fennel-BCyHNUwf.js} +0 -0
- /package/dist/web/assets/{fish-Cy12Dbua.js → fish-DDDlLV2G.js} +0 -0
- /package/dist/web/assets/{fluent-B_82ys8E.js → fluent-By54R9tl.js} +0 -0
- /package/dist/web/assets/{format-bytes-D5sBgIqU.js → format-bytes-D1AQyUCt.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-BRQdNzZF.js → fortran-free-form-tP8mRym_.js} +0 -0
- /package/dist/web/assets/{gdscript-XBDmLUm9.js → gdscript-nHC2z6Te.js} +0 -0
- /package/dist/web/assets/{gdshader-DhVfB3u4.js → gdshader-K-cSmPlW.js} +0 -0
- /package/dist/web/assets/{genie-X3K29Y49.js → genie-BAcRhvEe.js} +0 -0
- /package/dist/web/assets/{gherkin-DKIx-6cX.js → gherkin-CcifxMLb.js} +0 -0
- /package/dist/web/assets/{github-dark-Bf7zdp5s.js → github-dark-67KKlMdB.js} +0 -0
- /package/dist/web/assets/{github-dark-default-DqsBBV11.js → github-dark-default-tja8pidR.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-X2gqRz6w.js → github-dark-dimmed-CtjhYQtx.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Z7tvbGX4.js → github-dark-high-contrast-Bf-LPFgn.js} +0 -0
- /package/dist/web/assets/{github-light-BKxt-7zZ.js → github-light-CbJxE7n3.js} +0 -0
- /package/dist/web/assets/{github-light-default-B0liF4d4.js → github-light-default-DRQmdHxt.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-F4encJwr.js → github-light-high-contrast-CJkDgTeM.js} +0 -0
- /package/dist/web/assets/{gleam-Pz2bHgBB.js → gleam-D4LCl2ri.js} +0 -0
- /package/dist/web/assets/{gn-CgmdNsPU.js → gn-COY8zZmC.js} +0 -0
- /package/dist/web/assets/{gnuplot-qLNF5yZ9.js → gnuplot-ROk1VitR.js} +0 -0
- /package/dist/web/assets/{go-CSDUNhE7.js → go-H30c3p0C.js} +0 -0
- /package/dist/web/assets/{groovy-B3NEnOHF.js → groovy-DBLCaelV.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-DcoftiUX.js → gruvbox-dark-hard-DJy4irps.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-D1wVSuD8.js → gruvbox-dark-medium-Dhfw1QTO.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-DWpunymH.js → gruvbox-dark-soft-BncJU-8w.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-rHMvyUdS.js → gruvbox-light-hard-Cq12_YvM.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-3O2KiXO7.js → gruvbox-light-medium-DqVja5_v.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-lNlXJPwH.js → gruvbox-light-soft-IvwhveGF.js} +0 -0
- /package/dist/web/assets/{haskell-aaG3aC0h.js → haskell-DA1JV-MC.js} +0 -0
- /package/dist/web/assets/{haxe-CPcHhUDd.js → haxe-V9RTRc5E.js} +0 -0
- /package/dist/web/assets/{hcl-CMQNlR_4.js → hcl-hr1lyZ10.js} +0 -0
- /package/dist/web/assets/{hjson-DeuklPFj.js → hjson-D3vW3i7X.js} +0 -0
- /package/dist/web/assets/{hlsl-BI3hlsaM.js → hlsl-BB85gfJT.js} +0 -0
- /package/dist/web/assets/{horizon-C7-gOcjs.js → horizon-DU8OOnj8.js} +0 -0
- /package/dist/web/assets/{horizon-bright-Cxt9bRW7.js → horizon-bright-DNMUclW6.js} +0 -0
- /package/dist/web/assets/{houston-DbF2G7iD.js → houston-DAiZKf6T.js} +0 -0
- /package/dist/web/assets/{hy-DRG6Hs2I.js → hy-C6Zv0LMe.js} +0 -0
- /package/dist/web/assets/{image-gallery-CObzTisL.js → image-gallery-CGvlv8zR.js} +0 -0
- /package/dist/web/assets/{imba-CxKv_2TW.js → imba-Didnp6Y-.js} +0 -0
- /package/dist/web/assets/{ini-BiHsyCdO.js → ini-m0T7q4gQ.js} +0 -0
- /package/dist/web/assets/{input-D-dR8RI6.js → input-C7Q8FxeL.js} +0 -0
- /package/dist/web/assets/{java-D3RZzgDB.js → java-Buy07jGn.js} +0 -0
- /package/dist/web/assets/{javascript-4FmSqG-T.js → javascript-Cjq3CbRL.js} +0 -0
- /package/dist/web/assets/{json-CjB236_E.js → json-BSVu8IqD.js} +0 -0
- /package/dist/web/assets/{json5-bkfO-Rco.js → json5-NN_Vb7e6.js} +0 -0
- /package/dist/web/assets/{jsonc-BwaTeLyv.js → jsonc-BdyZhBUw.js} +0 -0
- /package/dist/web/assets/{jsonl-CfxNSwGd.js → jsonl-BsDSNvwi.js} +0 -0
- /package/dist/web/assets/{jsonnet-CQETCYrp.js → jsonnet-Gm963F-U.js} +0 -0
- /package/dist/web/assets/{jssm-D5o3Zzdz.js → jssm-Ds3bKWgJ.js} +0 -0
- /package/dist/web/assets/{jsx-BAMILPLo.js → jsx-BT5mW58X.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-BhGVxu3R.js → kanagawa-dragon-BvNvf7xd.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-FH4Y59ro.js → kanagawa-lotus-CuSiliSn.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-eilvP9MB.js → kanagawa-wave-C6g-d6jT.js} +0 -0
- /package/dist/web/assets/{kdl-BQ-yvXUK.js → kdl-Bx4kZef-.js} +0 -0
- /package/dist/web/assets/{kotlin-BuCx0-VT.js → kotlin-qvaVvCcm.js} +0 -0
- /package/dist/web/assets/{kusto-DAN_n_Cy.js → kusto-BPLyNCN6.js} +0 -0
- /package/dist/web/assets/{laserwave-Cq2BlxrT.js → laserwave-Sf8ZEhWP.js} +0 -0
- /package/dist/web/assets/{lean-Dhq7uXKw.js → lean-DGe6uqgk.js} +0 -0
- /package/dist/web/assets/{less-CxaMQb8j.js → less-CqM85x-9.js} +0 -0
- /package/dist/web/assets/{lib-BVwmtv2i.js → lib-CD6pOS4u.js} +0 -0
- /package/dist/web/assets/{libesm-DdtEjhIi.js → libesm-CPh1Av0r.js} +0 -0
- /package/dist/web/assets/{light-plus-B4sMAend.js → light-plus-DBtKwhFA.js} +0 -0
- /package/dist/web/assets/{llvm-DQ6-B_6Y.js → llvm-Dpbq3gky.js} +0 -0
- /package/dist/web/assets/{log-Bb_vqvu7.js → log-qKMcPm9S.js} +0 -0
- /package/dist/web/assets/{logo-BzfYv3A_.js → logo-DFo7i5KH.js} +0 -0
- /package/dist/web/assets/{luau-BnAeNR77.js → luau-DGlqWFyL.js} +0 -0
- /package/dist/web/assets/{make-B6IFuxpC.js → make-CixdvUQe.js} +0 -0
- /package/dist/web/assets/{markdown-Z0xi77Fn.js → markdown-CmRnbngE.js} +0 -0
- /package/dist/web/assets/{material-theme-1scy1SYn.js → material-theme-WDUbafB-.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-G-JykXQP.js → material-theme-darker-u8y2xpOk.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-BtKkCMVq.js → material-theme-lighter-cyQZK3Tg.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-irrDC89L.js → material-theme-ocean-LBAVvw7k.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-Eq5_K4LM.js → material-theme-palenight-BJqhBxL0.js} +0 -0
- /package/dist/web/assets/{matlab-BE3oCXZC.js → matlab-B38sOJee.js} +0 -0
- /package/dist/web/assets/{mdx-DYiuFTGw.js → mdx-C8QrE_IW.js} +0 -0
- /package/dist/web/assets/{mermaid-DVlaEvtw.js → mermaid-BQ-eeU8A.js} +0 -0
- /package/dist/web/assets/{min-dark-DSkeTpQa.js → min-dark-D4gNa5tv.js} +0 -0
- /package/dist/web/assets/{min-light-CFv2Q0uF.js → min-light-Dfbhn_PL.js} +0 -0
- /package/dist/web/assets/{mipsasm-CiAFuZQ2.js → mipsasm-bLOhJkdm.js} +0 -0
- /package/dist/web/assets/{mojo-ARshcaSQ.js → mojo-B0BCOMQW.js} +0 -0
- /package/dist/web/assets/{monaco-dotenv-language-BDYnKcnr.js → monaco-dotenv-language-uB-wok6C.js} +0 -0
- /package/dist/web/assets/{monokai-CPTV-SOg.js → monokai-Bdw_07OM.js} +0 -0
- /package/dist/web/assets/{moonbit-D57B0dZr.js → moonbit-BFdGaeuk.js} +0 -0
- /package/dist/web/assets/{move-qgy3G_o9.js → move-CyXQFGPM.js} +0 -0
- /package/dist/web/assets/{narrat-CZ3rC-oc.js → narrat-9DvTD3_3.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-BxxIOcI4.js → nextflow-groovy-C4VY3kNY.js} +0 -0
- /package/dist/web/assets/{night-owl-B1ryGCda.js → night-owl-feYm66V0.js} +0 -0
- /package/dist/web/assets/{night-owl-light-BZvNnvMF.js → night-owl-light-DALqFjvx.js} +0 -0
- /package/dist/web/assets/{nix-BVBQi8yv.js → nix-C1kPA9Sw.js} +0 -0
- /package/dist/web/assets/{nord-3NXw613h.js → nord-1dvrj1Al.js} +0 -0
- /package/dist/web/assets/{nushell-BMOLRalb.js → nushell-DSQ_9Uqj.js} +0 -0
- /package/dist/web/assets/{objective-c-AxruEUgh.js → objective-c-Dhcn5ZK8.js} +0 -0
- /package/dist/web/assets/{objective-cpp-cFT0qRsD.js → objective-cpp-CGVYCSrp.js} +0 -0
- /package/dist/web/assets/{ocaml-_8JH6O8J.js → ocaml-rxXW21An.js} +0 -0
- /package/dist/web/assets/{odin-nwYvR0O6.js → odin-ClSJX2DE.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-C1LaYJaH.js → one-dark-pro-3gbWDfFW.js} +0 -0
- /package/dist/web/assets/{one-light-B7rMc__c.js → one-light-C2q5ZZAw.js} +0 -0
- /package/dist/web/assets/{openscad-Cwes8bKO.js → openscad-eHXeafBl.js} +0 -0
- /package/dist/web/assets/{pascal-DMt-6tdZ.js → pascal-kKha3Txs.js} +0 -0
- /package/dist/web/assets/{pkl-QBTyYQmB.js → pkl-CTiPytg-.js} +0 -0
- /package/dist/web/assets/{plastic-BTSUp8Fk.js → plastic-D1Ygezi4.js} +0 -0
- /package/dist/web/assets/{plsql-DQv3IFXP.js → plsql-D_gbgZIr.js} +0 -0
- /package/dist/web/assets/{po-CNwZx4tW.js → po-BkhbDUnq.js} +0 -0
- /package/dist/web/assets/{poimandres-8Os7Qequ.js → poimandres-Do6NywrA.js} +0 -0
- /package/dist/web/assets/{polar-b4yK8oD8.js → polar-B3B23wca.js} +0 -0
- /package/dist/web/assets/{postcss-sFctwpxx.js → postcss-Dv_YBvWd.js} +0 -0
- /package/dist/web/assets/{powerquery-Cg_WrtuN.js → powerquery-fKJWI-Sh.js} +0 -0
- /package/dist/web/assets/{powershell-C7Ifz95h.js → powershell-B4Y7KIgx.js} +0 -0
- /package/dist/web/assets/{prisma-Z52HUJzQ.js → prisma-J--XdTXX.js} +0 -0
- /package/dist/web/assets/{prolog-DLqW-zR1.js → prolog-BBTg4Vb3.js} +0 -0
- /package/dist/web/assets/{proto-BOIzxCCJ.js → proto-DWlum3T8.js} +0 -0
- /package/dist/web/assets/{puppet-De7TjZIf.js → puppet-ZiUfc9JV.js} +0 -0
- /package/dist/web/assets/{purescript-R76ou1WT.js → purescript-CmT8SCHB.js} +0 -0
- /package/dist/web/assets/{python-Dprm0tNP.js → python-BURpj-fq.js} +0 -0
- /package/dist/web/assets/{qmldir-Clp_jpNw.js → qmldir-CpaiJywQ.js} +0 -0
- /package/dist/web/assets/{qss-eQPYYzSo.js → qss-C-zdz0i5.js} +0 -0
- /package/dist/web/assets/{r-CCcRHIf5.js → r-K56BeS-s.js} +0 -0
- /package/dist/web/assets/{racket-CzE472yp.js → racket-gkn6Z_Jw.js} +0 -0
- /package/dist/web/assets/{raku-DQwXrTSi.js → raku-C0ZBuKlx.js} +0 -0
- /package/dist/web/assets/{red-KCS6wyop.js → red-BWZ6x-3p.js} +0 -0
- /package/dist/web/assets/{reg-CcrAddUh.js → reg-Dt_EsyGR.js} +0 -0
- /package/dist/web/assets/{regexp-DDbud-Ri.js → regexp-CT6BLG2C.js} +0 -0
- /package/dist/web/assets/{rel-99GDgaHp.js → rel-MJ2LcyzJ.js} +0 -0
- /package/dist/web/assets/{resolve-theme-CW2niGV2.js → resolve-theme-B_ukrg_8.js} +0 -0
- /package/dist/web/assets/{riscv-Dm2eNv0R.js → riscv-BZYWzMAA.js} +0 -0
- /package/dist/web/assets/{ron-CzFt0ygH.js → ron-CLbwHWMn.js} +0 -0
- /package/dist/web/assets/{rose-pine-Ck6lCrCP.js → rose-pine-BPiI_daR.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-vtALRJNj.js → rose-pine-dawn-BjkJc7dW.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-DPto8qXw.js → rose-pine-moon-BQSxkt7g.js} +0 -0
- /package/dist/web/assets/{rosmsg-NtS6429H.js → rosmsg-yt4151pJ.js} +0 -0
- /package/dist/web/assets/{rust-BjIXvF9h.js → rust-1dAcengL.js} +0 -0
- /package/dist/web/assets/{sass-CQ23wf5E.js → sass-DUgtQJsg.js} +0 -0
- /package/dist/web/assets/{scala-LfKLM143.js → scala-CxoGYpS0.js} +0 -0
- /package/dist/web/assets/{scheme-D3SLBXlF.js → scheme-B2K3u9e3.js} +0 -0
- /package/dist/web/assets/{sdbl-ODRd2rGN.js → sdbl-C0Ygk0n6.js} +0 -0
- /package/dist/web/assets/{shellscript-3KB1G_oA.js → shellscript-C2CvhqMk.js} +0 -0
- /package/dist/web/assets/{slack-dark-DTtyWmIy.js → slack-dark-DYdgzRGj.js} +0 -0
- /package/dist/web/assets/{slack-ochin-Bu0PApk3.js → slack-ochin-X-WD0WCg.js} +0 -0
- /package/dist/web/assets/{smalltalk-haMT-Sbe.js → smalltalk-Dp7g_zb9.js} +0 -0
- /package/dist/web/assets/{snazzy-light-DXJzefE9.js → snazzy-light-DWHWr-a6.js} +0 -0
- /package/dist/web/assets/{solarized-dark-B6LyYa18.js → solarized-dark-CxdLsjvb.js} +0 -0
- /package/dist/web/assets/{solarized-light-QLADebkv.js → solarized-light-Cz9rAvG5.js} +0 -0
- /package/dist/web/assets/{solidity-mzfq1aDc.js → solidity-D33gHHdn.js} +0 -0
- /package/dist/web/assets/{splunk-CyH4RWBp.js → splunk-BFbOroYw.js} +0 -0
- /package/dist/web/assets/{sql-CWVlT5D3.js → sql-ChpxvmdY.js} +0 -0
- /package/dist/web/assets/{ssh-config-DNvQJ1Qx.js → ssh-config-CUuSQ6JG.js} +0 -0
- /package/dist/web/assets/{streaming-store-uDu3PoN1.js → streaming-store-BYukdB56.js} +0 -0
- /package/dist/web/assets/{stylus-ByQQdtmf.js → stylus-DDihP0_W.js} +0 -0
- /package/dist/web/assets/{swift-D1cpY4ow.js → swift-XoalUn4x.js} +0 -0
- /package/dist/web/assets/{synthwave-84-BDF_-QiW.js → synthwave-84-DjkG0Bff.js} +0 -0
- /package/dist/web/assets/{system-verilog-BYrkMydC.js → system-verilog-f_pLKMYd.js} +0 -0
- /package/dist/web/assets/{systemd-CQm3zyK0.js → systemd-DjDcLfxp.js} +0 -0
- /package/dist/web/assets/{talonscript-DMW5CzE1.js → talonscript-BpUzYcDl.js} +0 -0
- /package/dist/web/assets/{tasl-BhFzMCr2.js → tasl-DP-cUbg8.js} +0 -0
- /package/dist/web/assets/{tcl-D7VEAF-9.js → tcl-BHoy-dfE.js} +0 -0
- /package/dist/web/assets/{terraform-DdT5A0Vy.js → terraform-vCVxN25B.js} +0 -0
- /package/dist/web/assets/{tokyo-night-WGLMM6Q9.js → tokyo-night-D0u4xZba.js} +0 -0
- /package/dist/web/assets/{toml-CZ7ipXHZ.js → toml-BS8D0__A.js} +0 -0
- /package/dist/web/assets/{tsv-B1zVvoTr.js → tsv-DCb-NQh3.js} +0 -0
- /package/dist/web/assets/{tsx-D4HwRUBq.js → tsx-DF8YeRgG.js} +0 -0
- /package/dist/web/assets/{turtle-B4r8KEJH.js → turtle-Bhx1GlIy.js} +0 -0
- /package/dist/web/assets/{typescript-BnHhxMtp.js → typescript-CAVD2Wb6.js} +0 -0
- /package/dist/web/assets/{typespec-DP2q46GT.js → typespec-D7mchdY_.js} +0 -0
- /package/dist/web/assets/{typst-DFsD_yaD.js → typst-CeXzq6Yw.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-BQ9Bv5Ga.js → use-is-mobile-TkcwP1Gx.js} +0 -0
- /package/dist/web/assets/{use-visual-viewport-CbwnktSG.js → use-visual-viewport-Lp878uzs.js} +0 -0
- /package/dist/web/assets/{v-Bji8hSVT.js → v-DhzO54je.js} +0 -0
- /package/dist/web/assets/{vala-D3TIgGmU.js → vala-Dw_RAk3E.js} +0 -0
- /package/dist/web/assets/{vb-DvcxFS2q.js → vb-CiXdNh2Y.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-BqPDsE9b.js → vendor-xterm-BHEY6Ctu.js} +0 -0
- /package/dist/web/assets/{verilog-Dy7cF35d.js → verilog-fITdxqwV.js} +0 -0
- /package/dist/web/assets/{vesper-BzjwUv9J.js → vesper-B1wm_At7.js} +0 -0
- /package/dist/web/assets/{vhdl-DuFnFNmW.js → vhdl-ebHjqKp9.js} +0 -0
- /package/dist/web/assets/{viml-yAPgKlbz.js → viml-Dgmnoxoo.js} +0 -0
- /package/dist/web/assets/{vitesse-black-oSSQdyIZ.js → vitesse-black-BZ5gMb7l.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-BZxwPihB.js → vitesse-dark-Lij7kkOt.js} +0 -0
- /package/dist/web/assets/{vitesse-light-uIigycvt.js → vitesse-light-DW6Wq7VC.js} +0 -0
- /package/dist/web/assets/{vyper-CX3NAxm5.js → vyper-6FxDnVNg.js} +0 -0
- /package/dist/web/assets/{wasm-6mEOOvVa.js → wasm-BDxaNPCj.js} +0 -0
- /package/dist/web/assets/{wasm-D9td37qO.js → wasm-DKhAtzfe.js} +0 -0
- /package/dist/web/assets/{wenyan-lwNIHgk6.js → wenyan-C0k0DYG_.js} +0 -0
- /package/dist/web/assets/{wgsl-DQAzCfog.js → wgsl-Y2zagbdn.js} +0 -0
- /package/dist/web/assets/{wikitext-DTXmt5NE.js → wikitext-C4QGWzkY.js} +0 -0
- /package/dist/web/assets/{wit-Bdw_7WDH.js → wit-CQESzjHy.js} +0 -0
- /package/dist/web/assets/{wolfram-DqyHDZ07.js → wolfram-B-ia69Ia.js} +0 -0
- /package/dist/web/assets/{yaml-CPXhdByd.js → yaml-CEYYTQPm.js} +0 -0
- /package/dist/web/assets/{zenscript-6s_i5zek.js → zenscript-BggWXIeJ.js} +0 -0
- /package/dist/web/assets/{zig-B2htezJ_.js → zig-CbaUfBQe.js} +0 -0
|
@@ -1,68 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vendor the vscode-icons file icon theme into a module the browser can use.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* the Iconify collection generated out of that extension, and the
|
|
6
|
-
* the extension's own
|
|
7
|
-
*
|
|
8
|
-
* a dedicated icon (`package.json`, `Dockerfile`, `.prettierrc`) gets it.
|
|
4
|
+
* Both halves come from `vscode-icons-team.vscode-icons` itself: the artwork
|
|
5
|
+
* from the Iconify collection generated out of that extension, and the
|
|
6
|
+
* *mapping* from the extension's own `src/iconsManifest/` — pinned, digested
|
|
7
|
+
* and re-implemented below exactly as `manifestBuilder.ts` builds it.
|
|
9
8
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
9
|
+
* The mapping used to come from `vscode-icons-js` alone, a third-party
|
|
10
|
+
* repackaging, and that is the whole reason this file was rewritten. It is
|
|
11
|
+
* versioned apart from the extension and lags it badly: its table of
|
|
12
|
+
* *multi-dot* extensions held **41** entries against the real manifest's 1006,
|
|
13
|
+
* so `app.controller.ts`, `app.module.ts` and `app.service.ts` all drew the
|
|
14
|
+
* plain TypeScript glyph while the Nest artwork sat unused in the bundle. It
|
|
15
|
+
* also knows nothing of the manifest's glob form (`babel.config.{js,cjs,mjs,json}`)
|
|
16
|
+
* or of the presets, so every gap had to be patched by hand in an `OVERRIDES`
|
|
17
|
+
* table that only ever grew.
|
|
15
18
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
+
* It is still read, second, and that is not laziness — the two sources are
|
|
20
|
+
* complementary in a way worth stating. The manifest associates a great many
|
|
21
|
+
* types by *VS Code language id* and nothing else: the `dotenv` entry has
|
|
22
|
+
* `extensions: []`, and `.cc`, `.htm`, `.conf`, `.kts` and twenty more reach
|
|
23
|
+
* their icon only because VS Code already knows which language owns them.
|
|
24
|
+
* `languages.ts` carries one `knownExtensions` list per language and it is the
|
|
25
|
+
* short one, so a manifest-only port silently drops those — measured, against
|
|
26
|
+
* the previous tables: 36 names that had an icon stopped having one. So the
|
|
27
|
+
* manifest wins wherever it answers, `vscode-icons-js` fills the rest, and
|
|
28
|
+
* `LANGUAGE_EXTRAS` holds the handful neither knows.
|
|
29
|
+
*
|
|
30
|
+
* Both are **build-time** dependencies. Resolving names at run time would mean
|
|
31
|
+
* shipping the manifest itself (200 KB of TypeScript) and the lookup code with
|
|
32
|
+
* it, to answer a question whose answer never changes between releases.
|
|
33
|
+
*
|
|
34
|
+
* The outputs are committed. Re-run after bumping `MANIFEST_VERSION`:
|
|
19
35
|
*
|
|
20
36
|
* bun scripts/gen-file-icons.ts
|
|
21
37
|
*/
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// those are the glyphs a TypeScript repository shows most after `.ts` itself.
|
|
26
|
-
// Hand-listing them would drift; if the path ever moves, this script fails
|
|
27
|
-
// loudly at generation time rather than quietly emitting worse icons.
|
|
28
|
-
import { FileExtensions2ToIcon } from "vscode-icons-js/dist/generated/FileExtensions2ToIcon";
|
|
29
|
-
import { writeFileSync } from "node:fs";
|
|
38
|
+
import { createHash } from "node:crypto";
|
|
39
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
40
|
+
import { tmpdir } from "node:os";
|
|
30
41
|
import { resolve } from "node:path";
|
|
31
42
|
import { writeNotices } from "./third-party-notices.ts";
|
|
32
43
|
|
|
33
44
|
const OUT_TS = resolve(import.meta.dir, "../src/web/lib/file-icons.generated.ts");
|
|
34
45
|
const OUT_CSS = resolve(import.meta.dir, "../src/web/styles/file-icons.generated.css");
|
|
35
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Pinned, and checked against a digest rather than trusted.
|
|
49
|
+
*
|
|
50
|
+
* These are the three files the extension builds its own icon theme from. A
|
|
51
|
+
* branch can be force-pushed and a tag moved, so "fetch master" would make the
|
|
52
|
+
* committed tables unreproducible — and a mapping that changed under us moves
|
|
53
|
+
* icons all over the tree with nothing to point at. Bump the tag, run the
|
|
54
|
+
* script, and it will print the digests it actually got.
|
|
55
|
+
*/
|
|
56
|
+
const MANIFEST_VERSION = "v12.19.0";
|
|
57
|
+
const MANIFEST_FILES: Record<string, string> = {
|
|
58
|
+
supportedExtensions: "277b81ecebe527dea6deedf39b891d9746cc58b14dd2e311bc2da0bf2ff8eee6",
|
|
59
|
+
supportedFolders: "8b638f423efdcbeabbc5ede863db7d54ee6738da2eece29cf07833a627a12685",
|
|
60
|
+
languages: "43542118e7438a0c5f31b1c48c085c6b1b8079b2902e241664c4cff1e4c8568e",
|
|
61
|
+
};
|
|
62
|
+
|
|
36
63
|
/**
|
|
37
64
|
* A glyph bigger than this is dropped, and whatever asked for it falls back to
|
|
38
|
-
* the
|
|
65
|
+
* the next shorter suffix — `.controller.ts` to `.ts`, and past that to the
|
|
66
|
+
* neutral default.
|
|
39
67
|
*
|
|
40
|
-
* The set is extremely skewed
|
|
68
|
+
* The set is extremely skewed: the median body is ~1 KB and `file-type-composer`
|
|
41
69
|
* alone is 83 KB, because some of these are detailed illustrations rather than
|
|
42
70
|
* icons. At the 16px a file tree draws them at, that detail is invisible; all it
|
|
43
|
-
* costs is download.
|
|
71
|
+
* costs is download.
|
|
44
72
|
*
|
|
45
73
|
* 5000 rather than something tighter because the distribution has no useful gap
|
|
46
74
|
* below it, and a tight budget cuts by weight rather than by worth: at 1800,
|
|
47
75
|
* `.tsx` (`file-type-reactts`, 1833 bytes — 33 over) drew the blank-page default,
|
|
48
76
|
* and so did `.jsx` (1833), `.go` (1825) and `.rs` (3957). Everything above 5000
|
|
49
|
-
* really is an illustration.
|
|
77
|
+
* really is an illustration. `KEEP_ANY_SIZE` exempts the few worth paying for.
|
|
50
78
|
*/
|
|
51
79
|
const MAX_BODY_BYTES = 5000;
|
|
52
80
|
|
|
53
|
-
/**
|
|
54
|
-
* Keys the mapping names that the collection spells differently.
|
|
55
|
-
*
|
|
56
|
-
* vscode-icons revises a glyph by publishing it under a numbered name, and the
|
|
57
|
-
* two packages are versioned apart — so the mapping can hand back a name the
|
|
58
|
-
* collection no longer has. The script reports every unresolved key rather than
|
|
59
|
-
* dropping it quietly, and this is where the answer goes. `Makefile` has no
|
|
60
|
-
* glyph in the collection at all and falls back to the default on purpose.
|
|
61
|
-
*/
|
|
62
|
-
const ALIASES: Record<string, string> = {
|
|
63
|
-
"file-type-pdf": "file-type-pdf2",
|
|
64
|
-
};
|
|
65
|
-
|
|
66
81
|
/** Languages common enough to keep whatever they weigh. */
|
|
67
82
|
const KEEP_ANY_SIZE = new Set(
|
|
68
83
|
`file-type-ruby file-type-perl file-type-groovy file-type-maven file-type-http
|
|
@@ -72,148 +87,199 @@ const KEEP_ANY_SIZE = new Set(
|
|
|
72
87
|
);
|
|
73
88
|
|
|
74
89
|
/**
|
|
75
|
-
*
|
|
90
|
+
* Keys the manifest names that the collection spells differently.
|
|
91
|
+
*
|
|
92
|
+
* vscode-icons revises a glyph by publishing it under a numbered name, and the
|
|
93
|
+
* artwork package is versioned apart from the extension — so the manifest can
|
|
94
|
+
* name an icon the collection no longer has. Every unresolved name is reported
|
|
95
|
+
* at the end of a run rather than dropped quietly, and this is where the answer
|
|
96
|
+
* goes.
|
|
97
|
+
*/
|
|
98
|
+
const ALIASES: Record<string, string> = {
|
|
99
|
+
"file-type-pdf": "file-type-pdf2",
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What neither source knows, because VS Code answers it from somewhere else.
|
|
76
104
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* `
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* which is `bunfig.toml` getting the generic TOML glyph.
|
|
105
|
+
* All of these resolve in VS Code through a language association contributed by
|
|
106
|
+
* a *different* extension or by a built-in grammar, which is a table neither the
|
|
107
|
+
* icon manifest nor `vscode-icons-js` contains. `.env.local` is the one that
|
|
108
|
+
* matters most here — the manifest's `dotenv` entry declares no extensions at
|
|
109
|
+
* all and leans entirely on the `dotenv` language id, so every qualified env
|
|
110
|
+
* file drew a blank page.
|
|
84
111
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* (23 KB) and `file.pug` (6 KB) are over the budget below.
|
|
112
|
+
* Keys are matched the way the runtime matches: whole filename first, then a
|
|
113
|
+
* dotted suffix. Values are checked against the collection at generation time,
|
|
114
|
+
* so an entry that stops resolving is reported rather than silently dropped.
|
|
89
115
|
*/
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
jsonl: "file-type-json",
|
|
130
|
-
pyi: "file-type-python",
|
|
131
|
-
kts: "file-type-kotlin",
|
|
132
|
-
exs: "file-type-elixir",
|
|
133
|
-
ini: "file-type-ini",
|
|
134
|
-
graphql: "file-type-graphql",
|
|
135
|
-
proto: "file-type-protobuf",
|
|
136
|
-
tif: "file-type-image",
|
|
137
|
-
rest: "file-type-rest",
|
|
138
|
-
tfvars: "file-type-terraform",
|
|
139
|
-
npmrc: "file-type-npm",
|
|
140
|
-
nvmrc: "file-type-node",
|
|
141
|
-
apk: "file-type-binary",
|
|
142
|
-
deb: "file-type-binary",
|
|
143
|
-
rpm: "file-type-binary",
|
|
116
|
+
const LANGUAGE_EXTRAS: { names: Record<string, string>; extensions: Record<string, string> } = {
|
|
117
|
+
names: {
|
|
118
|
+
// Bazel, whose two marker files have no extension at all.
|
|
119
|
+
build: "bazel",
|
|
120
|
+
workspace: "bazel",
|
|
121
|
+
// Wrapper scripts and pipeline definitions named after their tool.
|
|
122
|
+
gradlew: "gradle",
|
|
123
|
+
"gradlew.bat": "gradle",
|
|
124
|
+
jenkinsfile: "groovy",
|
|
125
|
+
"cargo.lock": "rust",
|
|
126
|
+
// `file-type-bundler` is 43 KB — an illustration, not an icon, so the
|
|
127
|
+
// budget drops it and Ruby's own glyph is the honest stand-in.
|
|
128
|
+
gemfile: "ruby",
|
|
129
|
+
"gemfile.lock": "ruby",
|
|
130
|
+
},
|
|
131
|
+
extensions: {
|
|
132
|
+
// Languages and formats VS Code associates through a grammar neither source
|
|
133
|
+
// enumerates. Each of these was a line in the old hand-written `OVERRIDES`
|
|
134
|
+
// and drew a blank page without it.
|
|
135
|
+
graphql: "graphql",
|
|
136
|
+
gql: "graphql",
|
|
137
|
+
kts: "kotlin",
|
|
138
|
+
exs: "elixir",
|
|
139
|
+
tif: "image",
|
|
140
|
+
rest: "rest",
|
|
141
|
+
apk: "binary",
|
|
142
|
+
rpm: "binary",
|
|
143
|
+
npmrc: "npm",
|
|
144
|
+
nvmrc: "node",
|
|
145
|
+
// `.env.local`, `.env.production`, `.env.test.local` — the manifest has the
|
|
146
|
+
// artwork and reaches it only by language id.
|
|
147
|
+
"env.local": "dotenv",
|
|
148
|
+
"env.development": "dotenv",
|
|
149
|
+
"env.production": "dotenv",
|
|
150
|
+
"env.staging": "dotenv",
|
|
151
|
+
"env.test": "dotenv",
|
|
152
|
+
"env.example": "dotenv",
|
|
153
|
+
"env.sample": "dotenv",
|
|
154
|
+
},
|
|
144
155
|
};
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
/** Whole filenames the theme gives a dedicated glyph. */
|
|
166
|
-
const FILENAMES = `
|
|
167
|
-
package.json package-lock.json bun.lock bun.lockb yarn.lock pnpm-lock.yaml
|
|
168
|
-
tsconfig.json jsconfig.json bunfig.toml deno.json
|
|
169
|
-
.gitignore .gitattributes .gitmodules .gitkeep .mailmap
|
|
170
|
-
.npmrc .npmignore .nvmrc .yarnrc .editorconfig .browserslistrc
|
|
171
|
-
.prettierrc .prettierrc.json .prettierignore
|
|
172
|
-
.eslintrc .eslintrc.js .eslintrc.json eslint.config.js eslint.config.mjs
|
|
173
|
-
.env .env.local .env.development .env.production .env.example .env.test
|
|
174
|
-
Dockerfile dockerfile docker-compose.yml docker-compose.yaml compose.yaml .dockerignore
|
|
175
|
-
Makefile makefile CMakeLists.txt meson.build BUILD WORKSPACE Justfile
|
|
176
|
-
README.md readme.md LICENSE LICENSE.md COPYING CHANGELOG.md CONTRIBUTING.md
|
|
177
|
-
CODE_OF_CONDUCT.md SECURITY.md CODEOWNERS AUTHORS
|
|
178
|
-
vite.config.ts vite.config.js rollup.config.js webpack.config.js
|
|
179
|
-
tailwind.config.js tailwind.config.ts postcss.config.js postcss.config.mjs
|
|
180
|
-
babel.config.js .babelrc jest.config.js jest.config.ts vitest.config.ts
|
|
181
|
-
playwright.config.ts cypress.config.ts karma.conf.js nodemon.json pm2.config.js
|
|
182
|
-
next.config.js next.config.mjs nuxt.config.ts svelte.config.js astro.config.mjs
|
|
183
|
-
angular.json vue.config.js remix.config.js gatsby-config.js metro.config.js
|
|
184
|
-
go.mod go.sum go.work Cargo.toml Cargo.lock
|
|
185
|
-
requirements.txt pyproject.toml setup.py setup.cfg Pipfile Pipfile.lock poetry.lock
|
|
186
|
-
tox.ini pytest.ini manage.py
|
|
187
|
-
Gemfile Gemfile.lock Rakefile composer.json composer.lock
|
|
188
|
-
pom.xml build.gradle build.gradle.kts settings.gradle gradlew mix.exs
|
|
189
|
-
.gitlab-ci.yml .travis.yml appveyor.yml azure-pipelines.yml Jenkinsfile
|
|
190
|
-
netlify.toml vercel.json now.json firebase.json app.json fly.toml railway.json
|
|
191
|
-
serverless.yml Procfile Vagrantfile
|
|
192
|
-
manifest.json robots.txt sitemap.xml humans.txt .htaccess favicon.ico
|
|
193
|
-
index.html index.ts index.js main.ts main.go
|
|
194
|
-
CLAUDE.md AGENTS.md
|
|
195
|
-
`.trim().split(/\s+/);
|
|
196
|
-
|
|
197
|
-
/** Folder names the theme gives a dedicated glyph. */
|
|
198
|
-
const FOLDERS = `
|
|
199
|
-
src app apps packages lib dist build public assets images fonts
|
|
200
|
-
components hooks utils helpers shared config api server client services
|
|
201
|
-
store views controllers routes middleware
|
|
202
|
-
test tests __tests__ e2e coverage docs examples scripts bin
|
|
203
|
-
database db migrations types locales i18n functions
|
|
204
|
-
node_modules vendor .git .github .vscode .husky
|
|
205
|
-
android ios logs tmp temp cache
|
|
206
|
-
`.trim().split(/\s+/);
|
|
207
|
-
|
|
208
|
-
/** `file_type_typescript.svg` → `file-type-typescript` (the Iconify key). */
|
|
209
|
-
function iconifyKey(svgName: string | undefined): string | null {
|
|
210
|
-
if (!svgName) return null;
|
|
211
|
-
return svgName.replace(/\.svg$/, "").replace(/_/g, "-");
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// The manifest
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
/** One entry of `supportedExtensions.ts` / `supportedFolders.ts`. */
|
|
162
|
+
interface ManifestEntry {
|
|
163
|
+
icon: string;
|
|
164
|
+
extensions: string[];
|
|
165
|
+
/** The strings in `extensions` are whole filenames, not suffixes. */
|
|
166
|
+
filename?: boolean;
|
|
167
|
+
/** Cartesian product with `extensionsGlob`, joined by a dot. */
|
|
168
|
+
filenamesGlob?: string[];
|
|
169
|
+
extensionsGlob?: string[];
|
|
170
|
+
languages?: { ids: string | string[]; knownExtensions?: string[]; knownFilenames?: string[] }[];
|
|
171
|
+
/** The theme ships a second drawing of this glyph, for a light workbench. */
|
|
172
|
+
light?: boolean;
|
|
173
|
+
/** Off unless a preset turns it on — `nest_*`, `ng_*`, the `*2` redraws. */
|
|
174
|
+
disabled?: boolean;
|
|
212
175
|
}
|
|
213
176
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
177
|
+
interface Manifest {
|
|
178
|
+
files: ManifestEntry[];
|
|
179
|
+
folders: ManifestEntry[];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Fetch the three manifest modules and evaluate them.
|
|
184
|
+
*
|
|
185
|
+
* They are TypeScript that imports its types from `../models`, so they are
|
|
186
|
+
* staged in one temp directory next to a stub supplying that module. Evaluating
|
|
187
|
+
* them is the point: these tables are 200 KB of nested literals, and a regex
|
|
188
|
+
* over them would be a second, worse parser that fails silently the first time
|
|
189
|
+
* upstream reformats a line.
|
|
190
|
+
*/
|
|
191
|
+
async function loadManifest(): Promise<Manifest> {
|
|
192
|
+
const dir = mkdtempSync(resolve(tmpdir(), "ppm-vscode-icons-"));
|
|
193
|
+
try {
|
|
194
|
+
writeFileSync(
|
|
195
|
+
resolve(dir, "models.ts"),
|
|
196
|
+
"export const FileFormat = { svg: 'svg', png: 'png' };\n" +
|
|
197
|
+
"export const IFileCollection = undefined, IFolderCollection = undefined, ILanguage = undefined;\n",
|
|
198
|
+
);
|
|
199
|
+
for (const [name, digest] of Object.entries(MANIFEST_FILES)) {
|
|
200
|
+
const url =
|
|
201
|
+
`https://raw.githubusercontent.com/vscode-icons/vscode-icons/` +
|
|
202
|
+
`${MANIFEST_VERSION}/src/iconsManifest/${name}.ts`;
|
|
203
|
+
const res = await fetch(url);
|
|
204
|
+
if (!res.ok) throw new Error(`${url} → HTTP ${res.status}`);
|
|
205
|
+
const body = Buffer.from(await res.arrayBuffer());
|
|
206
|
+
const got = createHash("sha256").update(body).digest("hex");
|
|
207
|
+
if (got !== digest) {
|
|
208
|
+
throw new Error(`${name}.ts digest mismatch\n expected ${digest}\n got ${got}`);
|
|
209
|
+
}
|
|
210
|
+
writeFileSync(resolve(dir, `${name}.ts`), body.toString("utf8").replace("../models", "./models"));
|
|
211
|
+
}
|
|
212
|
+
const files = (await import(resolve(dir, "supportedExtensions.ts"))).extensions;
|
|
213
|
+
const folders = (await import(resolve(dir, "supportedFolders.ts"))).extensions;
|
|
214
|
+
return { files: files.supported, folders: folders.supported };
|
|
215
|
+
} finally {
|
|
216
|
+
rmSync(dir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** `nest_controller_ts` → `file-type-nest-controller-ts`, the Iconify key. */
|
|
221
|
+
function iconifyKey(prefix: string, icon: string): string {
|
|
222
|
+
const key = `${prefix}-${icon.replace(/_/g, "-")}`.toLowerCase();
|
|
223
|
+
return ALIASES[key] ?? key;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The tables one preset of the manifest produces, built the way
|
|
228
|
+
* `manifestBuilder.buildFiles` builds them.
|
|
229
|
+
*
|
|
230
|
+
* Two details are load-bearing and neither is obvious. Entries are walked in
|
|
231
|
+
* order of *icon name*, because that is what upstream sorts by and later
|
|
232
|
+
* writes overwrite earlier ones — so two icons claiming `service.ts` resolve
|
|
233
|
+
* the same way here as they do in VS Code. And the language layer is written
|
|
234
|
+
* first and then overwritten by the explicit `extensions`, so a hand-declared
|
|
235
|
+
* association always beats one inferred from a language's known extensions.
|
|
236
|
+
*/
|
|
237
|
+
function buildFiles(entries: ManifestEntry[]): {
|
|
238
|
+
fileNames: Record<string, string>;
|
|
239
|
+
fileExtensions: Record<string, string>;
|
|
240
|
+
langNames: Record<string, string>;
|
|
241
|
+
langExtensions: Record<string, string>;
|
|
242
|
+
} {
|
|
243
|
+
const langNames: Record<string, string> = {};
|
|
244
|
+
const langExtensions: Record<string, string> = {};
|
|
245
|
+
const names: Record<string, string> = {};
|
|
246
|
+
const extensions: Record<string, string> = {};
|
|
247
|
+
|
|
248
|
+
for (const entry of [...entries].sort((a, b) => (a.icon < b.icon ? -1 : a.icon > b.icon ? 1 : 0))) {
|
|
249
|
+
for (const lang of entry.languages ?? []) {
|
|
250
|
+
for (const ext of lang.knownExtensions ?? []) langExtensions[ext.toLowerCase()] = entry.icon;
|
|
251
|
+
for (const name of lang.knownFilenames ?? []) langNames[name.toLowerCase()] = entry.icon;
|
|
252
|
+
}
|
|
253
|
+
const put = (value: string) => {
|
|
254
|
+
if (entry.filename) names[value.toLowerCase()] = entry.icon;
|
|
255
|
+
// `removeFirstDot`: the manifest writes `.babelrc` and means the suffix
|
|
256
|
+
// `babelrc`. Only the *leading* dot goes — `controller.ts` stays whole.
|
|
257
|
+
else extensions[value.replace(/^\./, "").toLowerCase()] = entry.icon;
|
|
258
|
+
};
|
|
259
|
+
for (const value of entry.extensions) put(value);
|
|
260
|
+
if (entry.filenamesGlob?.length && entry.extensionsGlob?.length) {
|
|
261
|
+
for (const stem of entry.filenamesGlob) for (const ext of entry.extensionsGlob) put(`${stem}.${ext}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// The language layer is handed back *separately* rather than merged under the
|
|
265
|
+
// explicit one, because it is the weaker claim in a way the merge cannot
|
|
266
|
+
// express. `knownExtensions` flattens "this language is known by .css" into
|
|
267
|
+
// "a .css file is this icon", and two languages may claim one extension —
|
|
268
|
+
// `tailwindcss` also lists `css`, sorts after it, and so every stylesheet in
|
|
269
|
+
// the app came out with the Tailwind logo. VS Code never sees that collision
|
|
270
|
+
// because it matches the file's *actual* language id. So this layer ranks
|
|
271
|
+
// below `vscode-icons-js`'s flattening of VS Code's own associations, and
|
|
272
|
+
// only answers for languages that package is too old to know.
|
|
273
|
+
return { fileNames: names, fileExtensions: extensions, langNames, langExtensions };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// The artwork
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
const collection = (
|
|
281
|
+
await import("@iconify-json/vscode-icons/icons.json", { with: { type: "json" } })
|
|
282
|
+
).default as { icons: Record<string, { body: string }>; width?: number; height?: number };
|
|
217
283
|
|
|
218
284
|
/**
|
|
219
285
|
* The *artwork* version, which is the one the notice has to name.
|
|
@@ -234,39 +300,23 @@ const mappingVersion = (
|
|
|
234
300
|
/** Both drawings of one glyph; `light` only when the theme ships a second one. */
|
|
235
301
|
type Glyph = { dark: string; light?: string };
|
|
236
302
|
|
|
237
|
-
const used = new Map<string, Glyph>();
|
|
303
|
+
const used = new Map<string, Glyph>();
|
|
238
304
|
const missing = new Set<string>();
|
|
239
305
|
const overBudget = new Map<string, number>();
|
|
240
306
|
let lightVariants = 0;
|
|
241
307
|
|
|
242
308
|
/**
|
|
243
|
-
*
|
|
309
|
+
* Claim a glyph, or report why it cannot be drawn.
|
|
244
310
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* `
|
|
248
|
-
* when the *workbench* theme is light: `#fbc02d` where the normal one is
|
|
249
|
-
* `#f5de19`, and for `toml` a path with no `fill` at all, i.e. black. Shipping
|
|
250
|
-
* them as the only artwork is how the JSON braces came out muddy and the TOML
|
|
251
|
-
* glyph came out invisible on every dark PPM theme. So the class is named after
|
|
252
|
-
* the theme-independent glyph and carries both drawings.
|
|
311
|
+
* A `null` here is not an error at the call site: the name simply gets no entry
|
|
312
|
+
* in the tables, and the runtime falls through to a shorter suffix — which for
|
|
313
|
+
* `foo.controller.ts` means the TypeScript glyph rather than a blank page.
|
|
253
314
|
*/
|
|
254
|
-
function
|
|
255
|
-
return key.replace(/^file-type-light-/, "file-type-");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function take(svgName: string | undefined): string | null {
|
|
259
|
-
const named = iconifyKey(svgName);
|
|
260
|
-
return named === null ? null : takeKey(named);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function takeKey(named: string): string | null {
|
|
264
|
-
const aliased = ALIASES[named] ?? named;
|
|
265
|
-
const key = canonical(aliased);
|
|
315
|
+
function takeIcon(key: string): string | null {
|
|
266
316
|
if (used.has(key)) return key;
|
|
267
317
|
const icon = collection.icons[key];
|
|
268
318
|
if (!icon) {
|
|
269
|
-
// A name the
|
|
319
|
+
// A name the manifest knows and the collection does not: the two are
|
|
270
320
|
// versioned separately, so this is reported rather than silently dropped.
|
|
271
321
|
missing.add(key);
|
|
272
322
|
return null;
|
|
@@ -275,56 +325,208 @@ function takeKey(named: string): string | null {
|
|
|
275
325
|
overBudget.set(key, icon.body.length);
|
|
276
326
|
return null;
|
|
277
327
|
}
|
|
278
|
-
|
|
328
|
+
// The theme draws 132 of these twice, the second for a light workbench:
|
|
329
|
+
// `#fbc02d` where the normal one is `#f5de19`, and for `toml` a path with no
|
|
330
|
+
// `fill` at all, i.e. black. Shipping the light one as the *only* artwork is
|
|
331
|
+
// how the TOML glyph came out invisible on every dark PPM theme, so the class
|
|
332
|
+
// is named after the theme-independent glyph and carries both drawings.
|
|
333
|
+
// One `replace` per prefix, never a `??` chain: a pattern that does not match
|
|
334
|
+
// returns the key *unchanged*, so chaining would find the dark drawing again
|
|
335
|
+
// and ship it as its own light variant — 1187 of them, silently.
|
|
336
|
+
const lightKey = key.startsWith("file-type-")
|
|
337
|
+
? key.replace(/^file-type-/, "file-type-light-")
|
|
338
|
+
: key.startsWith("folder-type-")
|
|
339
|
+
? key.replace(/^folder-type-/, "folder-type-light-")
|
|
340
|
+
: null;
|
|
341
|
+
const light = lightKey === null ? undefined : collection.icons[lightKey];
|
|
279
342
|
// A light drawing over the budget is simply left out: the class still has its
|
|
280
343
|
// dark one, which is legible on a light background, just not tuned for it.
|
|
281
|
-
const within = light && light.body.length <= MAX_BODY_BYTES;
|
|
344
|
+
const within = light !== undefined && light.body.length <= MAX_BODY_BYTES;
|
|
282
345
|
if (within) lightVariants++;
|
|
283
|
-
used.set(key, { dark: icon.body, light: within ? light
|
|
346
|
+
used.set(key, { dark: icon.body, light: within ? light!.body : undefined });
|
|
284
347
|
return key;
|
|
285
348
|
}
|
|
286
349
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Rewrite tables of manifest icon names into one table of drawable classes,
|
|
352
|
+
* earlier tables winning.
|
|
353
|
+
*
|
|
354
|
+
* Per key rather than merging first and resolving after, and that is the whole
|
|
355
|
+
* point: a key the manifest claims with a glyph that is missing or over the
|
|
356
|
+
* budget would otherwise be *lost* instead of falling through — `cargo.lock`
|
|
357
|
+
* reached `file-type-cargo`, which the collection does not have, and ended up
|
|
358
|
+
* with no icon at all while the second source's answer sat right there.
|
|
359
|
+
*/
|
|
360
|
+
function resolve_(prefix: string, ...tables: Record<string, string>[]): Record<string, string> {
|
|
361
|
+
const out: Record<string, string> = {};
|
|
362
|
+
for (const name of new Set(tables.flatMap((t) => Object.keys(t)))) {
|
|
363
|
+
for (const table of tables) {
|
|
364
|
+
const icon = table[name];
|
|
365
|
+
if (icon === undefined) continue;
|
|
366
|
+
const key = takeIcon(iconifyKey(prefix, icon));
|
|
367
|
+
if (key) {
|
|
368
|
+
out[name] = key;
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return out;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
// Build
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
const manifest = await loadManifest();
|
|
381
|
+
|
|
382
|
+
const DEFAULT_FILE = takeIcon("default-file")!;
|
|
383
|
+
const DEFAULT_FOLDER = takeIcon("default-folder")!;
|
|
384
|
+
const DEFAULT_FOLDER_OPEN = takeIcon("default-folder-opened")!;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* The presets, which are the reason this is three passes rather than one.
|
|
388
|
+
*
|
|
389
|
+
* `nest_*` and `ng_*` ship `disabled: true` — in VS Code they are behind
|
|
390
|
+
* `vsicons.presets.nestjs` and `vsicons.presets.angular`, off by default and
|
|
391
|
+
* *mutually exclusive in practice*: they claim the same six suffixes
|
|
392
|
+
* (`module`, `service`, `guard`, `pipe`, `interceptor`, `controller`, each in
|
|
393
|
+
* `.ts` and `.js`), and enabling both would silently hand a NestJS repository
|
|
394
|
+
* the Angular artwork, since `ng_` sorts after `nest_`.
|
|
395
|
+
*
|
|
396
|
+
* So the base tables have neither, and each preset is emitted as an overlay the
|
|
397
|
+
* runtime consults first once it knows which framework the project is built
|
|
398
|
+
* with. Off both overlays, `app.service.ts` falls through to `.ts` — the plain
|
|
399
|
+
* TypeScript glyph, which is what VS Code with no preset also shows.
|
|
400
|
+
*/
|
|
401
|
+
const isNest = (icon: string) => icon.startsWith("nest_");
|
|
402
|
+
const isAngular = (icon: string) => icon.startsWith("ng_");
|
|
403
|
+
|
|
404
|
+
const base = buildFiles(manifest.files.filter((e) => e.icon && !e.disabled));
|
|
405
|
+
const withNest = buildFiles(manifest.files.filter((e) => e.icon && (!e.disabled || isNest(e.icon))));
|
|
406
|
+
const withAngular = buildFiles(
|
|
407
|
+
manifest.files.filter((e) => e.icon && (!e.disabled || isAngular(e.icon))),
|
|
408
|
+
);
|
|
290
409
|
|
|
291
|
-
/**
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
410
|
+
/**
|
|
411
|
+
* The second source, consulted only where the manifest said nothing.
|
|
412
|
+
*
|
|
413
|
+
* `file_type_typescript.svg` → `typescript`, back into the manifest's own
|
|
414
|
+
* vocabulary so both layers go through one `resolve_` and one budget check.
|
|
415
|
+
*/
|
|
416
|
+
async function legacyTable(name: string): Promise<Record<string, string>> {
|
|
417
|
+
const table = (await import(`vscode-icons-js/dist/generated/${name}`))[name] as Record<
|
|
418
|
+
string,
|
|
419
|
+
string
|
|
420
|
+
>;
|
|
421
|
+
const out: Record<string, string> = {};
|
|
422
|
+
for (const [key, svg] of Object.entries(table)) {
|
|
423
|
+
// `file_type_light_ini.svg` → `ini`. These tables answer with the **light**
|
|
424
|
+
// drawing for 143 glyphs and offer no way to ask for the other one, and
|
|
425
|
+
// those are darker ink meant for a light workbench — `light_toml` has no
|
|
426
|
+
// `fill` at all, i.e. black on black. The class is named after the
|
|
427
|
+
// theme-independent glyph and `takeIcon` attaches both drawings.
|
|
428
|
+
out[key.toLowerCase()] = svg
|
|
429
|
+
.replace(/\.svg$/, "")
|
|
430
|
+
.replace(/^(file|folder)_type_/, "")
|
|
431
|
+
.replace(/^light_/, "");
|
|
432
|
+
}
|
|
433
|
+
return out;
|
|
295
434
|
}
|
|
296
435
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
// Only worth an entry when it differs from the fallback the component uses.
|
|
301
|
-
if (key && key !== DEFAULT_FILE) extIcon[ext] = key;
|
|
436
|
+
/** `b` fills the keys `a` has no answer for; `a` always wins. */
|
|
437
|
+
function fill(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
|
|
438
|
+
return { ...b, ...a };
|
|
302
439
|
}
|
|
303
440
|
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
441
|
+
const legacyExtensions = fill(
|
|
442
|
+
await legacyTable("FileExtensions2ToIcon"),
|
|
443
|
+
await legacyTable("FileExtensions1ToIcon"),
|
|
444
|
+
);
|
|
445
|
+
/**
|
|
446
|
+
* The table that actually earns `vscode-icons-js` its place.
|
|
447
|
+
*
|
|
448
|
+
* It is that package's flattening of VS Code's *language* associations — `cc`
|
|
449
|
+
* and `cxx` to C++, `htm` to HTML, `conf` to INI — which is precisely what the
|
|
450
|
+
* icon manifest leaves to the editor and a port therefore has to find
|
|
451
|
+
* somewhere.
|
|
452
|
+
*/
|
|
453
|
+
const legacyLanguages = await legacyTable("LanguagesToIcon");
|
|
454
|
+
const legacyNames = await legacyTable("FileNamesToIcon");
|
|
455
|
+
const legacyFolders = await legacyTable("FolderNamesToIcon");
|
|
456
|
+
|
|
457
|
+
const extensionSources = [
|
|
458
|
+
base.fileExtensions,
|
|
459
|
+
legacyExtensions,
|
|
460
|
+
legacyLanguages,
|
|
461
|
+
base.langExtensions,
|
|
462
|
+
LANGUAGE_EXTRAS.extensions,
|
|
463
|
+
];
|
|
464
|
+
const nameSources = [base.fileNames, legacyNames, base.langNames, LANGUAGE_EXTRAS.names];
|
|
465
|
+
|
|
466
|
+
const extensionIcons = resolve_("file-type", ...extensionSources);
|
|
467
|
+
const filenameIcons = resolve_("file-type", ...nameSources);
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* The same cascade, un-resolved, for the preset diff below.
|
|
471
|
+
*
|
|
472
|
+
* The overlay has to be compared at *manifest icon name* level — against the
|
|
473
|
+
* already-resolved class names it would differ on every single key, because
|
|
474
|
+
* `nest_service_ts` is never equal to `file-type-typescript`, and the two
|
|
475
|
+
* overlays came out at 2459 entries instead of 22.
|
|
476
|
+
*/
|
|
477
|
+
const baseNameSource = nameSources.reduceRight((acc, t) => fill(t, acc));
|
|
478
|
+
const baseExtensionSource = extensionSources.reduceRight((acc, t) => fill(t, acc));
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Only what the preset *changes*, so the overlay is 45 lines rather than 1000.
|
|
482
|
+
*
|
|
483
|
+
* Diffed against the *combined* base rather than the manifest's, or an entry
|
|
484
|
+
* the second source already answers identically would ship twice.
|
|
485
|
+
*/
|
|
486
|
+
function overlay(
|
|
487
|
+
preset: { fileNames: Record<string, string>; fileExtensions: Record<string, string> },
|
|
488
|
+
): { names: Record<string, string>; extensions: Record<string, string> } {
|
|
489
|
+
const diff = (a: Record<string, string>, b: Record<string, string>) =>
|
|
490
|
+
Object.fromEntries(Object.entries(a).filter(([k, v]) => b[k] !== v));
|
|
491
|
+
return {
|
|
492
|
+
names: resolve_("file-type", diff(preset.fileNames, baseNameSource)),
|
|
493
|
+
extensions: resolve_("file-type", diff(preset.fileExtensions, baseExtensionSource)),
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const frameworks = { nest: overlay(withNest), angular: overlay(withAngular) };
|
|
498
|
+
|
|
499
|
+
/** `{ … }` on one line when there is nothing in it, so the output reads clean. */
|
|
500
|
+
function block(map: Record<string, string>, key: string): string {
|
|
501
|
+
return Object.keys(map).length === 0 ? ` ${key}: {},` : ` ${key}: {\n${record(map, " ")}\n },`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const folderTables = buildFiles(manifest.folders.filter((e) => e.icon && !e.disabled));
|
|
505
|
+
const baseFolders = fill(folderTables.fileExtensions, legacyFolders);
|
|
506
|
+
const folderIcons = resolve_("folder-type", folderTables.fileExtensions, legacyFolders);
|
|
507
|
+
const folderOpenIcons: Record<string, string> = {};
|
|
508
|
+
for (const [name, icon] of Object.entries(baseFolders)) {
|
|
509
|
+
const key = takeIcon(iconifyKey("folder-type", `${icon}_opened`));
|
|
510
|
+
if (key) folderOpenIcons[name] = key;
|
|
313
511
|
}
|
|
314
512
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
for (const
|
|
318
|
-
|
|
319
|
-
const open = take(getIconForOpenFolder(folder));
|
|
320
|
-
if (closed && closed !== DEFAULT_FOLDER) folderIcon[folder.toLowerCase()] = closed;
|
|
321
|
-
if (open && open !== DEFAULT_FOLDER_OPEN) folderOpenIcon[folder.toLowerCase()] = open;
|
|
513
|
+
// A folder whose closed glyph was dropped but whose open one survived would
|
|
514
|
+
// change picture on expand for no reason; keep the pair or neither.
|
|
515
|
+
for (const name of Object.keys(folderOpenIcons)) {
|
|
516
|
+
if (!folderIcons[name]) delete folderOpenIcons[name];
|
|
322
517
|
}
|
|
518
|
+
for (const name of Object.keys(folderIcons)) {
|
|
519
|
+
if (!folderOpenIcons[name]) delete folderIcons[name];
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
// Emit
|
|
524
|
+
// ---------------------------------------------------------------------------
|
|
323
525
|
|
|
324
|
-
function record(map: Record<string, string
|
|
526
|
+
function record(map: Record<string, string>, indent = " "): string {
|
|
325
527
|
return Object.keys(map)
|
|
326
528
|
.sort()
|
|
327
|
-
.map((k) =>
|
|
529
|
+
.map((k) => `${indent}${JSON.stringify(k)}: ${JSON.stringify(map[k])},`)
|
|
328
530
|
.join("\n");
|
|
329
531
|
}
|
|
330
532
|
|
|
@@ -334,9 +536,10 @@ const names = [...used.keys()].sort();
|
|
|
334
536
|
const ts = `/**
|
|
335
537
|
* GENERATED by \`bun scripts/gen-file-icons.ts\` — do not edit.
|
|
336
538
|
*
|
|
337
|
-
* Which glyph of the vscode-icons theme (MIT, vscode-icons-team) a name gets
|
|
539
|
+
* Which glyph of the vscode-icons theme (MIT, vscode-icons-team) a name gets,
|
|
540
|
+
* built from that extension's own \`src/iconsManifest\` at ${MANIFEST_VERSION}.
|
|
338
541
|
* The glyphs themselves are in \`src/web/styles/file-icons.generated.css\`, one
|
|
339
|
-
* class each:
|
|
542
|
+
* class each: 3 MB of full-colour SVG has no business in a JS bundle, and as
|
|
340
543
|
* CSS the browser decodes each icon once however many rows use it — which is
|
|
341
544
|
* also how VS Code draws its own file icon themes.
|
|
342
545
|
*
|
|
@@ -349,37 +552,78 @@ const ts = `/**
|
|
|
349
552
|
* be called \`constructor\`; a directory really can be called \`toString\`.
|
|
350
553
|
*/
|
|
351
554
|
|
|
352
|
-
/** Lowercased extension → icon class suffix. */
|
|
555
|
+
/** Lowercased extension → icon class suffix. Longest suffix wins. */
|
|
353
556
|
export const EXTENSION_ICONS: Record<string, string> = {
|
|
354
|
-
${record(
|
|
557
|
+
${record(extensionIcons)}
|
|
355
558
|
};
|
|
356
559
|
|
|
357
|
-
/** Lowercased whole filename → icon; checked before
|
|
560
|
+
/** Lowercased whole filename → icon; checked before any extension. */
|
|
358
561
|
export const FILENAME_ICONS: Record<string, string> = {
|
|
359
|
-
${record(
|
|
562
|
+
${record(filenameIcons)}
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* The frameworks whose file-naming convention has artwork of its own.
|
|
567
|
+
*
|
|
568
|
+
* Upstream ships these as presets a user turns on, because they collide: both
|
|
569
|
+
* claim \`.module.ts\`, \`.service.ts\`, \`.guard.ts\`, \`.pipe.ts\`,
|
|
570
|
+
* \`.interceptor.ts\` and \`.controller.ts\`. PPM picks one per project instead —
|
|
571
|
+
* see \`project-framework-store.ts\`.
|
|
572
|
+
*/
|
|
573
|
+
export type IconFramework = ${Object.keys(frameworks)
|
|
574
|
+
.map((k) => JSON.stringify(k))
|
|
575
|
+
.join(" | ")};
|
|
576
|
+
|
|
577
|
+
/** Checked before {@link EXTENSION_ICONS} when a project names a framework. */
|
|
578
|
+
export const FRAMEWORK_EXTENSION_ICONS: Record<IconFramework, Record<string, string>> = {
|
|
579
|
+
${Object.entries(frameworks)
|
|
580
|
+
.map(([key, o]) => block(o.extensions, key))
|
|
581
|
+
.join("\n")}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
/** Checked before {@link FILENAME_ICONS} when a project names a framework. */
|
|
585
|
+
export const FRAMEWORK_FILENAME_ICONS: Record<IconFramework, Record<string, string>> = {
|
|
586
|
+
${Object.entries(frameworks)
|
|
587
|
+
.map(([key, o]) => block(o.names, key))
|
|
588
|
+
.join("\n")}
|
|
360
589
|
};
|
|
361
590
|
|
|
362
591
|
/** Lowercased folder name → icon. */
|
|
363
592
|
export const FOLDER_ICONS: Record<string, string> = {
|
|
364
|
-
${record(
|
|
593
|
+
${record(folderIcons)}
|
|
365
594
|
};
|
|
366
595
|
|
|
367
596
|
/** Lowercased folder name → icon, for an expanded folder. */
|
|
368
597
|
export const FOLDER_OPEN_ICONS: Record<string, string> = {
|
|
369
|
-
${record(
|
|
598
|
+
${record(folderOpenIcons)}
|
|
370
599
|
};
|
|
371
600
|
|
|
372
601
|
export const DEFAULT_FILE_ICON = ${JSON.stringify(DEFAULT_FILE)};
|
|
373
602
|
export const DEFAULT_FOLDER_ICON = ${JSON.stringify(DEFAULT_FOLDER)};
|
|
374
603
|
export const DEFAULT_FOLDER_OPEN_ICON = ${JSON.stringify(DEFAULT_FOLDER_OPEN)};
|
|
375
604
|
|
|
605
|
+
/** The longest suffix any entry of {@link EXTENSION_ICONS} is, in dot-segments. */
|
|
606
|
+
export const MAX_EXTENSION_SEGMENTS = ${Math.max(
|
|
607
|
+
...Object.keys(extensionIcons).map((k) => k.split(".").length),
|
|
608
|
+
...Object.values(frameworks).flatMap((f) => Object.keys(f.extensions).map((k) => k.split(".").length)),
|
|
609
|
+
)};
|
|
610
|
+
|
|
376
611
|
/** Every icon this module can name, for the test that pairs the two files. */
|
|
377
612
|
export const ICON_NAMES: readonly string[] = ${JSON.stringify(names)};
|
|
378
613
|
|
|
379
614
|
// After the literals rather than \`Object.create(null)\` around each, so the
|
|
380
615
|
// tables above stay readable as data and \`Record<string, string>\` still
|
|
381
|
-
// describes them.
|
|
382
|
-
|
|
616
|
+
// describes them. The framework overlays are included because they are indexed
|
|
617
|
+
// by filename too — \`fileIconName\` consults them *before* the plain tables, so
|
|
618
|
+
// an inherited property there answers first.
|
|
619
|
+
for (const table of [
|
|
620
|
+
EXTENSION_ICONS,
|
|
621
|
+
FILENAME_ICONS,
|
|
622
|
+
FOLDER_ICONS,
|
|
623
|
+
FOLDER_OPEN_ICONS,
|
|
624
|
+
...Object.values(FRAMEWORK_EXTENSION_ICONS),
|
|
625
|
+
...Object.values(FRAMEWORK_FILENAME_ICONS),
|
|
626
|
+
]) {
|
|
383
627
|
Object.setPrototypeOf(table, null);
|
|
384
628
|
}
|
|
385
629
|
`;
|
|
@@ -466,9 +710,16 @@ const bodyBytes = [...used.values()].reduce(
|
|
|
466
710
|
0,
|
|
467
711
|
);
|
|
468
712
|
console.log(
|
|
469
|
-
`file icons ${used.size} glyphs
|
|
470
|
-
|
|
471
|
-
|
|
713
|
+
`file icons vscode-icons ${MANIFEST_VERSION} ${used.size} glyphs ` +
|
|
714
|
+
`(${lightVariants} with a light-theme drawing)`,
|
|
715
|
+
);
|
|
716
|
+
console.log(
|
|
717
|
+
` ${Object.keys(extensionIcons).length} extensions ` +
|
|
718
|
+
`${Object.keys(filenameIcons).length} filenames ` +
|
|
719
|
+
`${Object.keys(folderIcons).length} folders ` +
|
|
720
|
+
Object.entries(frameworks)
|
|
721
|
+
.map(([k, o]) => `${Object.keys(o.extensions).length + Object.keys(o.names).length} ${k}`)
|
|
722
|
+
.join(" "),
|
|
472
723
|
);
|
|
473
724
|
console.log(
|
|
474
725
|
` ${(Buffer.byteLength(ts) / 1024).toFixed(1)} KiB of mapping (JS) ` +
|