@hienlh/ppm 0.22.11 → 0.23.1
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 +24 -1
- package/CLAUDE.md +14 -0
- 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 +17 -0
- package/dist/web/assets/__vite-browser-external-CHpXvvmW.js +1 -0
- package/dist/web/assets/accounts-settings-section-BR7t8CEk.js +1 -0
- package/dist/web/assets/ai-resource-editor-BFVg2d2a.js +1 -0
- package/dist/web/assets/ai-settings-section-BJw7E_lM.js +1 -0
- package/dist/web/assets/ai-settings-section-CO-i3ghA.js +1 -0
- package/dist/web/assets/angular-html-D-rbk4zq.js +1 -0
- package/dist/web/assets/angular-ts-B_ldKah2.js +1 -0
- package/dist/web/assets/api-client-BgedDTvo.js +1 -0
- package/dist/web/assets/api-client-c8YOpTlT.js +1 -0
- package/dist/web/assets/api-settings-0s1Rfgcu.js +1 -0
- package/dist/web/assets/api-settings-Bnp28Ysw.js +1 -0
- package/dist/web/assets/api-themes-Pp-AZvwV.js +1 -0
- package/dist/web/assets/apl-19Dr02g6.js +1 -0
- package/dist/web/assets/appearance-settings-section-Ck_FPs9g.js +1 -0
- package/dist/web/assets/architecture-PBZL5I3N-B_n8ddB4.js +1 -0
- package/dist/web/assets/astro-1q5o0N64.js +1 -0
- package/dist/web/assets/audio-preview-DXtE1Lpz.js +1 -0
- package/dist/web/assets/blade-BNgXZCCk.js +1 -0
- package/dist/web/assets/branch-review-tab-CNVxMRuo.js +1 -0
- package/dist/web/assets/bsl-C5u8-gEq.js +1 -0
- package/dist/web/assets/button-CBehaXpV.js +1 -0
- package/dist/web/assets/c-Dko4ZphN.js +1 -0
- package/dist/web/assets/cairo-CrhmfCJH.js +1 -0
- package/dist/web/assets/chat-tab-DqLqcBci.js +1 -0
- package/dist/web/assets/chat-tab-MdU9Jr3F.js +15 -0
- package/dist/web/assets/cobol-BgRxrYyZ.js +1 -0
- package/dist/web/assets/code-editor-wEeCvvMR.js +7 -0
- package/dist/web/assets/codex-daily-guard-B21M4m-P.js +1 -0
- package/dist/web/assets/coffee-9hmEOIYs.js +1 -0
- package/dist/web/assets/conflict-editor-Cu-z_LdX.js +19 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js +1 -0
- package/dist/web/assets/cpp-BntsLe3X.js +1 -0
- package/dist/web/assets/createLucideIcon-DBXq3G0e.js +1 -0
- package/dist/web/assets/crystal-CoXN2Gj8.js +1 -0
- package/dist/web/assets/css-DKuKlxIj.js +1 -0
- package/dist/web/assets/csv-preview-DHbBIqUu.js +2 -0
- package/dist/web/assets/data-grid-overlay-editor-2ERlh7_N.js +1 -0
- package/dist/web/assets/data-grid-types-DatI2Wee.js +1 -0
- package/dist/web/assets/database-viewer-_McYjRzc.js +1 -0
- package/dist/web/assets/design-export-client-SWCbGwwU.js +1 -0
- package/dist/web/assets/design-responsive-dialog-CcJETHO2.js +1 -0
- package/dist/web/assets/design-tab-C0TUD5g-.js +33 -0
- package/dist/web/assets/designs-sidebar-panel-XCAwSNtg.js +1 -0
- package/dist/web/assets/dialog-tzBRkGeW.js +1 -0
- package/dist/web/assets/diff-viewer-C4z-_68x.js +4 -0
- package/dist/web/assets/dist-CgtN5c7X.js +1 -0
- package/dist/web/assets/dist-wmDsBD_Z.js +1 -0
- package/dist/web/assets/docx-preview-C-UKGMXR.js +12 -0
- package/dist/web/assets/edge-gf7weBFr.js +1 -0
- package/dist/web/assets/edit-diff-preview-8nIct7kS.js +7 -0
- package/dist/web/assets/editor-language-service-D8hW_eew.js +1 -0
- package/dist/web/assets/elixir-DOEwBYus.js +1 -0
- package/dist/web/assets/elm-7yx1A5qt.js +1 -0
- package/dist/web/assets/erb-Bm_J_rBw.js +1 -0
- package/dist/web/assets/erlang-DgkAVj5y.js +1 -0
- package/dist/web/assets/esm-wquH4IhX.js +2 -0
- package/dist/web/assets/explorer-body-CdxolRQG.js +2 -0
- package/dist/web/assets/explorer-window-content-D1fkI_cL.js +1 -0
- package/dist/web/assets/extension-manager-section-CAaSoAuG.js +1 -0
- package/dist/web/assets/extension-webview-DmBZun_i.js +12 -0
- package/dist/web/assets/file-icons-BlOxPo3P.js +1 -0
- package/dist/web/assets/file-store-CTlJqj2m.js +1 -0
- package/dist/web/assets/files-settings-section-BFIzSuBh.js +1 -0
- package/dist/web/assets/format-date-BMtvCeb9.js +1 -0
- package/dist/web/assets/format-file-meta-DLaHgkdx.js +1 -0
- package/dist/web/assets/fortran-fixed-form-s8lQifxM.js +1 -0
- package/dist/web/assets/fs-api-RVc5RtTA.js +1 -0
- package/dist/web/assets/fsharp-D6bmDjka.js +1 -0
- package/dist/web/assets/gdresource-wPII3GWW.js +1 -0
- package/dist/web/assets/general-settings-section-BLLUvdhX.js +1 -0
- package/dist/web/assets/git-commit-DqLhxK6K.js +1 -0
- package/dist/web/assets/git-log-panel-Lq2Vkm8w.js +1 -0
- package/dist/web/assets/git-rebase-Cy0Mp9W1.js +1 -0
- package/dist/web/assets/git-repo-store-DFTJ5ngK.js +1 -0
- package/dist/web/assets/gitGraph-HDMCJU4V-w1WApLyy.js +1 -0
- package/dist/web/assets/glide-data-grid-CHdKFqis.js +141 -0
- package/dist/web/assets/glimmer-js-CmHFqq4N.js +1 -0
- package/dist/web/assets/glimmer-ts-vLmZC1JJ.js +1 -0
- package/dist/web/assets/glsl-DArPh0ws.js +1 -0
- package/dist/web/assets/graphql-B-_Ilekp.js +1 -0
- package/dist/web/assets/group-chat-tab-D2bluLme.js +1 -0
- package/dist/web/assets/hack-4KVRpwwM.js +1 -0
- package/dist/web/assets/haml-DoK94C5G.js +1 -0
- package/dist/web/assets/handlebars-D0_6yNlK.js +1 -0
- package/dist/web/assets/html-BOqZwhzR.js +1 -0
- package/dist/web/assets/html-derivative-If_2xbJ8.js +1 -0
- package/dist/web/assets/http-B6pQhqN4.js +1 -0
- package/dist/web/assets/hurl-BjW79rql.js +1 -0
- package/dist/web/assets/hxml-B1Yl76u6.js +1 -0
- package/dist/web/assets/icons-CO_II6D-.js +1 -0
- package/dist/web/assets/image-preview-78Fguk1f.js +1 -0
- package/dist/web/assets/index-CzYrKDUF.css +1 -0
- package/dist/web/assets/index-DSbUqWiH.js +52 -0
- package/dist/web/assets/info-3K5VOQVL-Bv1wKdPY.js +1 -0
- package/dist/web/assets/input-CP31LZnN.js +1 -0
- package/dist/web/assets/java-DPqGHyuh.js +1 -0
- package/dist/web/assets/javascript-D8x_R8ev.js +1 -0
- package/dist/web/assets/jinja-DOkXV84k.js +1 -0
- package/dist/web/assets/jira-watcher-section-BOe_ztas.js +1 -0
- package/dist/web/assets/jison-CGzlyBWT.js +1 -0
- package/dist/web/assets/json-kcFjaEWA.js +1 -0
- package/dist/web/assets/jsx-BzlJCumN.js +1 -0
- package/dist/web/assets/julia-CZrbm1Fa.js +1 -0
- package/dist/web/assets/just-bRG6zWI_.js +1 -0
- package/dist/web/assets/keybindings-store-DFPJBiXT.js +1 -0
- package/dist/web/assets/keyboard-shortcuts-section-CJubMhMq.js +1 -0
- package/dist/web/assets/latex-CZHLEkde.js +1 -0
- package/dist/web/assets/lib-KePrAxj7.js +4 -0
- package/dist/web/assets/liquid-Dcfq3Ccc.js +1 -0
- package/dist/web/assets/lua-Ggfu9EYp.js +1 -0
- package/dist/web/assets/markdown-renderer-6oU-L6RN.js +5 -0
- package/dist/web/assets/markdown-renderer-DxSQ4aqW.js +1 -0
- package/dist/web/assets/marko-BUwN_Iax.js +1 -0
- package/dist/web/assets/mdc-CIifdeNY.js +1 -0
- package/dist/web/assets/media-url-GqzhazJS.js +1 -0
- package/dist/web/assets/mobile-bottom-sheet-Cf4kV1hS.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-D0968cuP.js +1 -0
- package/dist/web/assets/monaco-dotenv-language-COsgiuQg.js +1 -0
- package/dist/web/assets/new-chat-provider-CJx_waY3.js +1 -0
- package/dist/web/assets/new-design-dialog-CbrMbKum.js +1 -0
- package/dist/web/assets/nextflow-DufnRZW1.js +1 -0
- package/dist/web/assets/nginx-DtUJGfad.js +1 -0
- package/dist/web/assets/nim-BeBPwibr.js +1 -0
- package/dist/web/assets/notification-store-BO3RInEL.js +1 -0
- package/dist/web/assets/notifications-settings-section-Bfxqz65i.js +1 -0
- package/dist/web/assets/number-overlay-editor-xzM7GhYV.js +9 -0
- package/dist/web/assets/onboarding-entry-CcvySZ_l.js +1 -0
- package/dist/web/assets/onboarding-quick-orientation-CT4PylG0.js +1 -0
- package/dist/web/assets/overview-panel-DshAIz6C.js +1 -0
- package/dist/web/assets/packet-RMMSAZCW-Scl5HE6U.js +1 -0
- package/dist/web/assets/panel-store-BUQ-CPsd.js +1 -0
- package/dist/web/assets/pdf-preview-BWim6mu1.js +1 -0
- package/dist/web/assets/perl-hV0EoLCp.js +1 -0
- package/dist/web/assets/php-N1YBqBhK.js +1 -0
- package/dist/web/assets/pie-UPGHQEXC-sY83O9qJ.js +1 -0
- package/dist/web/assets/portal-container-context-NFSuymMu.js +1 -0
- package/dist/web/assets/postgres-viewer-HwlL1UTJ.js +3 -0
- package/dist/web/assets/ppmbot-settings-section-CHr2FIDj.js +1 -0
- package/dist/web/assets/pptx-export-D6DOknBD.js +111 -0
- package/dist/web/assets/problems-panel-41z59l78.js +1 -0
- package/dist/web/assets/process-table-CVMEMJqQ.js +1 -0
- package/dist/web/assets/project-framework-store-XxFXcUpb.js +1 -0
- package/dist/web/assets/project-store-C5gJXkvb.js +1 -0
- package/dist/web/assets/proxy-settings-section-B4dkvCCx.js +1 -0
- package/dist/web/assets/pug-IMA1knL7.js +1 -0
- package/dist/web/assets/qml-DuwVuXga.js +1 -0
- package/dist/web/assets/query-audit-section-Cn11xqgz.js +1 -0
- package/dist/web/assets/r-DsXT2lmn.js +1 -0
- package/dist/web/assets/radar-KQ55EAFF-CNhm_kzj.js +1 -0
- package/dist/web/assets/razor-Be4LE-G0.js +1 -0
- package/dist/web/assets/react-CzUPVyyG.js +1 -0
- package/dist/web/assets/regexp-ztLDvplH.js +1 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Co4vEiiB.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-Cv4yo7K4.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-view-CcuulHIu.js +1 -0
- package/dist/web/assets/remote-desktop-readiness-gate-ouPRvBlu.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-DmH3jBuG.js +1 -0
- package/dist/web/assets/rolldown-runtime-C5c2KzVm.js +1 -0
- package/dist/web/assets/rst-BdtOZUlL.js +1 -0
- package/dist/web/assets/ruby-DTna6e9n.js +1 -0
- package/dist/web/assets/run-in-terminal-SU9cwoZ4.js +1 -0
- package/dist/web/assets/sas-X50YKLBX.js +1 -0
- package/dist/web/assets/schedules-settings-section-Dy6hARk0.js +1 -0
- package/dist/web/assets/scroll-area-xAtds1T-.js +1 -0
- package/dist/web/assets/scss-cQk9zuqD.js +1 -0
- package/dist/web/assets/send-to-chat-TSKk3fI9.js +1 -0
- package/dist/web/assets/separator-D8SNZI6E.js +1 -0
- package/dist/web/assets/settings-body-CZSwxG0i.js +2 -0
- package/dist/web/assets/settings-store-DXmQug0m.js +2 -0
- package/dist/web/assets/settings-tab-B_WPC-y7.js +1 -0
- package/dist/web/assets/settings-window-content-CSWdwQn1.js +1 -0
- package/dist/web/assets/shaderlab-CSeOcwk6.js +1 -0
- package/dist/web/assets/shellscript-Dtzjnpp9.js +1 -0
- package/dist/web/assets/shellsession-AqADqsjv.js +1 -0
- package/dist/web/assets/soy-DeMex-y3.js +1 -0
- package/dist/web/assets/sparql-CDZTYDwx.js +1 -0
- package/dist/web/assets/sql-BS_vTOM8.js +1 -0
- package/dist/web/assets/sql-query-editor-6Ee_Zn5j.js +1 -0
- package/dist/web/assets/sqlite-viewer-Cj0S_m9V.js +1 -0
- package/dist/web/assets/stata-PkjbLwNy.js +1 -0
- package/dist/web/assets/surrealql-BJ6bKPXV.js +1 -0
- package/dist/web/assets/svelte-D4u1sGpe.js +1 -0
- package/dist/web/assets/system-monitor-body-PQqXdK4a.js +2 -0
- package/dist/web/assets/system-monitor-tab-BEjvgQuQ.js +1 -0
- package/dist/web/assets/system-monitor-window-content-DZwvvN-M.js +1 -0
- package/dist/web/assets/tab-host-window-content-CnV4Z4Yt.js +1 -0
- package/dist/web/assets/tab-store-DqeaGhhE.js +1 -0
- package/dist/web/assets/team-member-sheet-8EVCTM-X.js +2 -0
- package/dist/web/assets/team-member-window-content-Bc0ydBAn.js +1 -0
- package/dist/web/assets/templ-vtFoIgGG.js +1 -0
- package/dist/web/assets/terminal-tab-0b63-txz.js +3 -0
- package/dist/web/assets/tex-o6JLe3Qo.js +1 -0
- package/dist/web/assets/tool-cards-C09WknHl.js +9 -0
- package/dist/web/assets/treemap-KZPCXAKY-CfpX4ULx.js +1 -0
- package/dist/web/assets/ts-tags-DkmPnhIx.js +1 -0
- package/dist/web/assets/tsx-BUq9xm2T.js +1 -0
- package/dist/web/assets/twig-I9ja_Rk_.js +1 -0
- package/dist/web/assets/typescript-CP3RLBKz.js +1 -0
- package/dist/web/assets/use-blob-url-mZfScQdx.js +1 -0
- package/dist/web/assets/use-inline-blame-BuAc9IXE.js +16 -0
- package/dist/web/assets/use-is-mobile-CkO33jqU.js +1 -0
- package/dist/web/assets/use-lsp-DAtq1G0M.js +6 -0
- package/dist/web/assets/use-monaco-theme-Ch_znquJ.js +1 -0
- package/dist/web/assets/use-open-team-member-DHzZiJZw.js +1 -0
- package/dist/web/assets/use-visual-viewport-C307OVeV.js +1 -0
- package/dist/web/assets/use-websocket-DGEOad8p.js +1 -0
- package/dist/web/assets/vendor-markdown-QKPNiWEd.js +291 -0
- package/dist/web/assets/vendor-mermaid-eg2XWIjK.js +2921 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js +45 -0
- package/dist/web/assets/video-preview-DH3RtwVT.js +1 -0
- package/dist/web/assets/vue-DJf-APPD.js +1 -0
- package/dist/web/assets/vue-html-DUJ89Ycn.js +1 -0
- package/dist/web/assets/vue-vine-CWUFwuRE.js +1 -0
- package/dist/web/assets/window-pip-registry-DH07f_8k.js +1 -0
- package/dist/web/assets/window-store-B4cbZ5rr.js +1 -0
- package/dist/web/assets/ws-auth-B_y5rMfZ.js +1 -0
- package/dist/web/assets/xml-DshhaDKq.js +1 -0
- package/dist/web/assets/xsl-BlRNlmF7.js +1 -0
- package/dist/web/assets/yaml-seUOGdyI.js +1 -0
- package/dist/web/index.html +37 -36
- package/dist/web/sw.js +1 -1
- package/docs/architecture/workspace-and-ui.md +47 -0
- package/docs/project-roadmap.md +16 -0
- package/docs/system-architecture.md +11 -1
- package/package.json +4 -1
- package/scripts/gen-product-icons.ts +10 -0
- package/src/providers/claude-agent-sdk-query-options.ts +68 -1
- package/src/providers/claude-agent-sdk.ts +44 -15
- package/src/providers/codex-app-server/codex-event-mapper.ts +18 -1
- package/src/providers/codex-app-server/codex-jsonrpc-client.ts +4 -3
- package/src/providers/codex-app-server/codex-permission-map.ts +11 -1
- package/src/providers/codex-app-server/codex-protocol.ts +5 -0
- package/src/providers/codex-app-server/codex-provider.ts +32 -15
- package/src/providers/codex-app-server/codex-thread-params.ts +96 -0
- package/src/server/helpers/preview-asset-guard.ts +36 -0
- package/src/server/index.ts +15 -0
- package/src/server/routes/chat.ts +41 -4
- package/src/server/routes/design-check.ts +48 -0
- package/src/server/routes/design-comments.ts +63 -0
- package/src/server/routes/design-export.ts +84 -0
- package/src/server/routes/design-preview.ts +159 -0
- package/src/server/routes/design-route-helpers.ts +25 -0
- package/src/server/routes/design-style.ts +28 -0
- package/src/server/routes/design-tweaks.ts +38 -0
- package/src/server/routes/design-undo.ts +27 -0
- package/src/server/routes/designs.ts +101 -0
- package/src/server/routes/html-preview.ts +4 -24
- package/src/server/routes/project-scoped.ts +2 -0
- package/src/server/ws/chat.ts +8 -1
- package/src/server/ws/global.ts +22 -1
- package/src/services/chat.service.ts +64 -1
- package/src/services/db.service.ts +73 -4
- package/src/services/design/bridge/bridge-anchor-resolve.ts +96 -0
- package/src/services/design/bridge/bridge-core.ts +205 -0
- package/src/services/design/bridge/bridge-element-info.ts +180 -0
- package/src/services/design/bridge/bridge-extract-blocks.ts +115 -0
- package/src/services/design/bridge/bridge-extract-images.ts +96 -0
- package/src/services/design/bridge/bridge-extract-slides.ts +169 -0
- package/src/services/design/bridge/bridge-extract-text.ts +187 -0
- package/src/services/design/bridge/bridge-layout-boxes.ts +137 -0
- package/src/services/design/bridge/bridge-layout-check.ts +99 -0
- package/src/services/design/bridge/bridge-layout-grid.ts +165 -0
- package/src/services/design/bridge/bridge-layout-screenshot.ts +106 -0
- package/src/services/design/bridge/bridge-nav-guard.ts +61 -0
- package/src/services/design/bridge/bridge-picker-overlay.ts +54 -0
- package/src/services/design/bridge/bridge-picker.ts +174 -0
- package/src/services/design/bridge/bridge-pins.ts +157 -0
- package/src/services/design/bridge/bridge-script.ts +104 -0
- package/src/services/design/bridge/bridge-transform-math.ts +104 -0
- package/src/services/design/bridge/bridge-transform-overlay.ts +94 -0
- package/src/services/design/bridge/bridge-transform-style.ts +78 -0
- package/src/services/design/bridge/bridge-transform.ts +201 -0
- package/src/services/design/bridge/bridge-tweaks.ts +118 -0
- package/src/services/design/check/design-canvas-check-broker.ts +77 -0
- package/src/services/design/comments/design-comment-element-context.ts +81 -0
- package/src/services/design/comments/design-comments-store.ts +81 -0
- package/src/services/design/design-comments.service.ts +140 -0
- package/src/services/design/design-edit-undo-journal.ts +125 -0
- package/src/services/design/design-error.ts +19 -0
- package/src/services/design/design-events.ts +46 -0
- package/src/services/design/design-fs.ts +67 -0
- package/src/services/design/design-instructions.ts +97 -0
- package/src/services/design/design-lock.ts +74 -0
- package/src/services/design/design-manifest.ts +92 -0
- package/src/services/design/design-paths.ts +97 -0
- package/src/services/design/design-restore-journal.ts +143 -0
- package/src/services/design/design-restore.service.ts +77 -0
- package/src/services/design/design-safe-walk.ts +114 -0
- package/src/services/design/design-slug.ts +35 -0
- package/src/services/design/design-snapshot-history.ts +159 -0
- package/src/services/design/design-snapshots.service.ts +161 -0
- package/src/services/design/design-starter-template.ts +100 -0
- package/src/services/design/design-store.service.ts +156 -0
- package/src/services/design/design-style-patch.service.ts +83 -0
- package/src/services/design/design-tool-policy.ts +111 -0
- package/src/services/design/design-turn-snapshot.ts +80 -0
- package/src/services/design/design-tweaks-commit.service.ts +138 -0
- package/src/services/design/design-write-rate-limit.ts +51 -0
- package/src/services/design/export/css-url-inline.ts +130 -0
- package/src/services/design/export/design-export-asset-reader.ts +57 -0
- package/src/services/design/export/design-export-entry.ts +33 -0
- package/src/services/design/export/design-standalone-html.ts +167 -0
- package/src/services/design/export/design-zip-export.ts +106 -0
- package/src/services/design/mcp/design-mcp-access.ts +16 -0
- package/src/services/design/mcp/design-mcp-endpoint.ts +118 -0
- package/src/services/design/mcp/design-mcp-tokens.ts +82 -0
- package/src/services/design/mcp/design-mcp-tool.ts +41 -0
- package/src/services/design/preview/design-csp.ts +31 -0
- package/src/services/design/preview/design-preview-html.ts +98 -0
- package/src/services/design/preview/design-preview-scope.ts +66 -0
- package/src/services/design/preview/design-preview-tokens.ts +137 -0
- package/src/services/design/preview/expired-page.ts +30 -0
- package/src/services/design/preview/html-instrument.ts +119 -0
- package/src/services/design/preview/print-view.ts +62 -0
- package/src/services/design/source/css-root-selector.ts +20 -0
- package/src/services/design/source/css-root-vars-patch.ts +202 -0
- package/src/services/design/source/design-source-file.ts +62 -0
- package/src/services/design/source/design-style-sources.ts +101 -0
- package/src/services/design/source/element-source-range.ts +65 -0
- package/src/services/design/source/html-style-blocks.ts +87 -0
- package/src/services/design/source/inline-style-declarations.ts +131 -0
- package/src/services/design/source/inline-style-patch.ts +79 -0
- package/src/services/design/source/tweak-patch-plan.ts +143 -0
- package/src/services/file-watcher/ignore-rules.ts +9 -1
- package/src/services/server-listen-address.ts +25 -0
- package/src/shared/design-bridge-messages-check.ts +44 -0
- package/src/shared/design-bridge-messages-picker.ts +142 -0
- package/src/shared/design-bridge-messages-slides.ts +37 -0
- package/src/shared/design-bridge-messages-transform.ts +121 -0
- package/src/shared/design-bridge-messages-tweaks.ts +65 -0
- package/src/shared/design-bridge-protocol.ts +158 -0
- package/src/shared/design-canvas-check-format.ts +69 -0
- package/src/shared/design-canvas-check.ts +148 -0
- package/src/shared/design-cdn-hosts.ts +17 -0
- package/src/shared/design-comment-types.ts +111 -0
- package/src/shared/design-slide-doc-parse.ts +140 -0
- package/src/shared/design-slide-doc.ts +91 -0
- package/src/shared/design-system-init-prompt.ts +35 -0
- package/src/shared/design-tweaks.ts +175 -0
- package/src/shared/design-types.ts +63 -0
- package/src/shared/untrusted-text.ts +15 -0
- package/src/types/chat.ts +22 -0
- package/src/types/config.ts +1 -1
- package/src/web/components/chat/chat-history-bar.tsx +18 -15
- package/src/web/components/chat/chat-history-panel.tsx +3 -9
- package/src/web/components/chat/chat-tab.tsx +74 -40
- package/src/web/components/chat/message-input.tsx +11 -4
- package/src/web/components/chat/session-history-list.tsx +5 -9
- package/src/web/components/design/canvas/canvas-geometry.ts +47 -0
- package/src/web/components/design/canvas/design-canvas-pane.tsx +192 -0
- package/src/web/components/design/canvas/design-issues-badge.tsx +71 -0
- package/src/web/components/design/canvas/device-frame-presets.ts +37 -0
- package/src/web/components/design/canvas/use-design-bridge.ts +169 -0
- package/src/web/components/design/canvas/use-design-canvas-check.ts +110 -0
- package/src/web/components/design/canvas/use-design-canvas.ts +107 -0
- package/src/web/components/design/canvas/use-design-live-reload.ts +86 -0
- package/src/web/components/design/canvas/use-design-preview-url.ts +74 -0
- package/src/web/components/design/canvas/use-expanded-canvas-escape.ts +29 -0
- package/src/web/components/design/comments/comment-composer.tsx +107 -0
- package/src/web/components/design/comments/comment-overlay-geometry.ts +50 -0
- package/src/web/components/design/comments/comment-pins-overlay.tsx +70 -0
- package/src/web/components/design/comments/comments-panel.tsx +118 -0
- package/src/web/components/design/comments/comments-send-preview.tsx +43 -0
- package/src/web/components/design/comments/design-comments-layer.tsx +73 -0
- package/src/web/components/design/comments/element-action-bar.tsx +105 -0
- package/src/web/components/design/comments/use-comment-pins.ts +118 -0
- package/src/web/components/design/comments/use-design-comments-feature.ts +124 -0
- package/src/web/components/design/comments/use-design-comments.ts +89 -0
- package/src/web/components/design/comments/use-element-picker.ts +87 -0
- package/src/web/components/design/design-chat-pane.tsx +51 -0
- package/src/web/components/design/design-layout-controls.tsx +84 -0
- package/src/web/components/design/design-mobile-layout.tsx +34 -0
- package/src/web/components/design/design-split-layout.tsx +99 -0
- package/src/web/components/design/design-tab-context.ts +44 -0
- package/src/web/components/design/design-tab.tsx +116 -0
- package/src/web/components/design/design-toolbar-list.tsx +36 -0
- package/src/web/components/design/design-toolbar.tsx +200 -0
- package/src/web/components/design/designs-sidebar-panel.tsx +117 -0
- package/src/web/components/design/dialogs/delete-design-dialog.tsx +69 -0
- package/src/web/components/design/dialogs/design-responsive-dialog.tsx +48 -0
- package/src/web/components/design/dialogs/new-design-dialog.tsx +113 -0
- package/src/web/components/design/dialogs/rename-design-dialog.tsx +56 -0
- package/src/web/components/design/export/export-menu.tsx +108 -0
- package/src/web/components/design/export/export-warnings-sheet.tsx +35 -0
- package/src/web/components/design/export/pptx-export.ts +38 -0
- package/src/web/components/design/export/use-design-export.ts +142 -0
- package/src/web/components/design/history/design-history-panel.tsx +119 -0
- package/src/web/components/design/transform/design-undo-stack.ts +90 -0
- package/src/web/components/design/transform/transform-readout.tsx +50 -0
- package/src/web/components/design/transform/use-canvas-transform.ts +181 -0
- package/src/web/components/design/tweaks/tweak-control.tsx +94 -0
- package/src/web/components/design/tweaks/tweaks-panel.tsx +99 -0
- package/src/web/components/design/tweaks/use-design-tweaks.ts +151 -0
- package/src/web/components/design/use-design-auto-check.ts +94 -0
- package/src/web/components/design/use-design-layout.ts +55 -0
- package/src/web/components/design/use-design-summary.ts +63 -0
- package/src/web/components/layout/command-palette-design-commands.tsx +75 -0
- package/src/web/components/layout/command-palette.tsx +12 -4
- package/src/web/components/layout/editor-panel.tsx +4 -10
- package/src/web/components/layout/mobile-drawer.tsx +9 -2
- package/src/web/components/layout/mobile-nav.tsx +3 -2
- package/src/web/components/layout/mobile-tab-switcher-sheet.tsx +4 -5
- package/src/web/components/layout/sidebar.tsx +8 -1
- package/src/web/components/layout/tab-bar.tsx +3 -2
- package/src/web/components/layout/tab-content.tsx +5 -0
- package/src/web/components/layout/tab-pool.tsx +1 -0
- package/src/web/components/onboarding/onboarding-quick-orientation.tsx +1 -0
- package/src/web/hooks/use-chat.ts +8 -4
- package/src/web/hooks/use-design-session-redirect.ts +39 -0
- package/src/web/hooks/use-design-session-state.ts +94 -0
- package/src/web/hooks/use-global-events.ts +4 -1
- package/src/web/hooks/use-session-history.ts +4 -10
- package/src/web/hooks/use-url-sync.ts +10 -2
- package/src/web/lib/design/api-design-comments.ts +42 -0
- package/src/web/lib/design/api-design-edits.ts +62 -0
- package/src/web/lib/design/api-design-tweaks.ts +64 -0
- package/src/web/lib/design/api-designs.ts +81 -0
- package/src/web/lib/design/deliver-to-design-chat.ts +63 -0
- package/src/web/lib/design/design-auto-check-rounds.ts +32 -0
- package/src/web/lib/design/design-change-filter.ts +27 -0
- package/src/web/lib/design/design-comments-prompt.ts +55 -0
- package/src/web/lib/design/design-export-client.ts +101 -0
- package/src/web/lib/design/design-handoff-prompt.ts +48 -0
- package/src/web/lib/design/design-layout-mode.ts +79 -0
- package/src/web/lib/design/design-tab-metadata.ts +41 -0
- package/src/web/lib/design/design-transform-proposal.ts +62 -0
- package/src/web/lib/design/design-tweaks-model.ts +76 -0
- package/src/web/lib/design/design-ui-events.ts +25 -0
- package/src/web/lib/design/design-view-prefs.ts +90 -0
- package/src/web/lib/design/open-design-tab.ts +78 -0
- package/src/web/lib/design/pptx-slide-mapper.ts +118 -0
- package/src/web/lib/feature-badges.ts +2 -0
- package/src/web/lib/fluent-icon.tsx +38 -2
- package/src/web/lib/icons.generated.tsx +17 -1
- package/src/web/lib/patch-tab-metadata.ts +30 -0
- package/src/web/lib/send-to-chat.ts +16 -2
- package/src/web/lib/sidebar-tabs/tab-registry.ts +2 -0
- package/src/web/lib/tab-session-id.ts +16 -0
- package/src/web/lib/tab-type-icons.ts +2 -1
- package/src/web/stores/panel-store.ts +29 -1
- package/src/web/stores/panel-utils.ts +8 -1
- package/src/web/stores/settings-store.ts +2 -2
- package/src/web/stores/tab-store.ts +2 -1
- package/src/web/stores/window-panel-persistence.ts +1 -0
- package/dist/web/assets/accounts-settings-section-BDXYG6tT.js +0 -1
- package/dist/web/assets/ai-resource-editor-C3rKcZKN.js +0 -1
- package/dist/web/assets/ai-settings-section-ArqD8Nlg.js +0 -1
- package/dist/web/assets/ai-settings-section-DeWoAdLc.js +0 -1
- package/dist/web/assets/angular-html-DnrsWZqK.js +0 -1
- package/dist/web/assets/angular-ts-BXEqA9t1.js +0 -1
- package/dist/web/assets/api-client-Jn3njtNw.js +0 -1
- package/dist/web/assets/api-client-rSFnnCj4.js +0 -1
- package/dist/web/assets/api-settings-BZFSteM_.js +0 -1
- package/dist/web/assets/api-themes-CvKtX6Hd.js +0 -1
- package/dist/web/assets/apl-DUQ6Oyth.js +0 -1
- package/dist/web/assets/appearance-settings-section-K5o_Di4V.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-B9M_VqZI.js +0 -1
- package/dist/web/assets/astro-CakOjJ6X.js +0 -1
- package/dist/web/assets/audio-preview-CwCDCN-_.js +0 -1
- package/dist/web/assets/blade-C903KM82.js +0 -1
- package/dist/web/assets/branch-review-tab-BNpYiUhC.js +0 -1
- package/dist/web/assets/bsl-slfcE_kB.js +0 -1
- package/dist/web/assets/button-B9CTrsEf.js +0 -1
- package/dist/web/assets/c-BWO-aeyf.js +0 -1
- package/dist/web/assets/cairo-DRwEaH6w.js +0 -1
- package/dist/web/assets/chat-tab-CC8KANoK.js +0 -15
- package/dist/web/assets/cobol--n4m6b70.js +0 -1
- package/dist/web/assets/code-editor-Ccf0Egrc.js +0 -7
- package/dist/web/assets/codex-daily-guard-CKk2WFlV.js +0 -1
- package/dist/web/assets/coffee-CjyFmw8_.js +0 -1
- package/dist/web/assets/conflict-editor-BCKbdpXy.js +0 -19
- package/dist/web/assets/context-menu-C6pIsf83.js +0 -1
- package/dist/web/assets/cpp-D18jdQPZ.js +0 -1
- package/dist/web/assets/createLucideIcon-DoiEKeJ_.js +0 -1
- package/dist/web/assets/crystal-CySzfH-7.js +0 -1
- package/dist/web/assets/css-Ca_hTmU6.js +0 -1
- package/dist/web/assets/csv-preview-I3a2lGUx.js +0 -2
- package/dist/web/assets/data-grid-overlay-editor-BD9eJweQ.js +0 -1
- package/dist/web/assets/data-grid-types-C6UX8kgh.js +0 -1
- package/dist/web/assets/database-viewer-DCuBR-bZ.js +0 -1
- package/dist/web/assets/dialog-B84_DJQ8.js +0 -1
- package/dist/web/assets/diff-viewer-DGaBe_Ln.js +0 -4
- package/dist/web/assets/dist-BD2gbdy0.js +0 -1
- package/dist/web/assets/docx-preview-CeH6p2Oi.js +0 -12
- package/dist/web/assets/edge-B6b5FHmU.js +0 -1
- package/dist/web/assets/edit-diff-preview-BG5DsLJG.js +0 -7
- package/dist/web/assets/editor-language-service-BaocEaLc.js +0 -1
- package/dist/web/assets/elixir-Dpo1rvn2.js +0 -1
- package/dist/web/assets/elm-D9CNOsWT.js +0 -1
- package/dist/web/assets/erb-sY7Yee1W.js +0 -1
- package/dist/web/assets/erlang-CfyrBxyF.js +0 -1
- package/dist/web/assets/esm-5AhGJcV8.js +0 -2
- package/dist/web/assets/explorer-body-2GYIYmUh.js +0 -2
- package/dist/web/assets/explorer-window-content-CYQSEX-g.js +0 -1
- package/dist/web/assets/extension-manager-section-BFAGdy3G.js +0 -1
- package/dist/web/assets/extension-webview-D5TXIBMf.js +0 -12
- package/dist/web/assets/file-icons-wS-OmEVu.js +0 -1
- package/dist/web/assets/file-store-Ds3qJ4hC.js +0 -1
- package/dist/web/assets/files-settings-section-BE6o-oHu.js +0 -1
- package/dist/web/assets/format-file-meta-eKLstbCL.js +0 -1
- package/dist/web/assets/fortran-fixed-form-N67gM_wp.js +0 -1
- package/dist/web/assets/fs-api-orca76dV.js +0 -1
- package/dist/web/assets/fsharp-Dq0K01wX.js +0 -1
- package/dist/web/assets/gdresource-DkFbszqY.js +0 -1
- package/dist/web/assets/general-settings-section-mQiXM537.js +0 -1
- package/dist/web/assets/git-commit-Ddt_nerD.js +0 -1
- package/dist/web/assets/git-log-panel-DqbcM9eC.js +0 -1
- package/dist/web/assets/git-rebase-CVK5OA7i.js +0 -1
- package/dist/web/assets/git-repo-store-BCEPfUGT.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D3RB33aA.js +0 -1
- package/dist/web/assets/glide-data-grid-BjEF7M5i.js +0 -141
- package/dist/web/assets/glimmer-js-51jbYnyY.js +0 -1
- package/dist/web/assets/glimmer-ts-C5L1J32J.js +0 -1
- package/dist/web/assets/glsl-BcsfmwJZ.js +0 -1
- package/dist/web/assets/graphql-dv4wuJsK.js +0 -1
- package/dist/web/assets/group-chat-tab-aX2GEnkD.js +0 -1
- package/dist/web/assets/hack-DLE5d3bx.js +0 -1
- package/dist/web/assets/haml-CoKfcM3E.js +0 -1
- package/dist/web/assets/handlebars-Bn0jy8pD.js +0 -1
- package/dist/web/assets/html-DXzY5Cew.js +0 -1
- package/dist/web/assets/html-derivative-DhcVfYuw.js +0 -1
- package/dist/web/assets/http-DepeIWQ1.js +0 -1
- package/dist/web/assets/hurl-CfsP4sCj.js +0 -1
- package/dist/web/assets/hxml-IfVkY3HL.js +0 -1
- package/dist/web/assets/icons-DQjqk0lJ.js +0 -1
- package/dist/web/assets/image-preview-CWncz5iI.js +0 -1
- package/dist/web/assets/index-BoaecXhu.js +0 -52
- package/dist/web/assets/index-aXJy_SvC.css +0 -1
- package/dist/web/assets/info-3K5VOQVL-DDX-2VB7.js +0 -1
- package/dist/web/assets/input-QNG_gTHh.js +0 -1
- package/dist/web/assets/java-JWdrzVo8.js +0 -1
- package/dist/web/assets/javascript-5aQKJRxB.js +0 -1
- package/dist/web/assets/jinja-DcCmNDQ8.js +0 -1
- package/dist/web/assets/jira-watcher-section-BKn3A8zI.js +0 -1
- package/dist/web/assets/jison-Bt-5cKVZ.js +0 -1
- package/dist/web/assets/json-BOq7QblK.js +0 -1
- package/dist/web/assets/jsx-BSLWViGE.js +0 -1
- package/dist/web/assets/julia-DewYVRtE.js +0 -1
- package/dist/web/assets/just-CLT_ggBy.js +0 -1
- package/dist/web/assets/keybindings-store-Brz0qepi.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-Ck8KIbJ8.js +0 -1
- package/dist/web/assets/latex-DXmcayW1.js +0 -1
- package/dist/web/assets/lib-BWyA9SvU.js +0 -4
- package/dist/web/assets/liquid-BVcHf0IA.js +0 -1
- package/dist/web/assets/lua-BYupsB1B.js +0 -1
- package/dist/web/assets/markdown-renderer-BGuM2PBI.js +0 -5
- package/dist/web/assets/markdown-renderer-Ddz8tPbb.js +0 -1
- package/dist/web/assets/marko-CsD0R5tv.js +0 -1
- package/dist/web/assets/mdc-DP2tC4Kc.js +0 -1
- package/dist/web/assets/media-url-CVO4m4zr.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-C3TniEP-.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-DpKfB6iF.js +0 -1
- package/dist/web/assets/monaco-dotenv-language-DD8_UQG7.js +0 -1
- package/dist/web/assets/nextflow-FQM6iZO2.js +0 -1
- package/dist/web/assets/nginx-Bg0TK_a9.js +0 -1
- package/dist/web/assets/nim-D1kSCHdq.js +0 -1
- package/dist/web/assets/notification-store-ByCdTvCC.js +0 -1
- package/dist/web/assets/notifications-settings-section-C5v8FoH9.js +0 -1
- package/dist/web/assets/number-overlay-editor-Bsr04yCI.js +0 -9
- package/dist/web/assets/onboarding-entry-C81awoR5.js +0 -1
- package/dist/web/assets/onboarding-quick-orientation-Dqmis-E5.js +0 -1
- package/dist/web/assets/overview-panel-9OdBcYJC.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-B0ZSm6VM.js +0 -1
- package/dist/web/assets/panel-store-D20Zuf3i.js +0 -1
- package/dist/web/assets/pdf-preview-DuR07OfN.js +0 -1
- package/dist/web/assets/perl-B6QNc69s.js +0 -1
- package/dist/web/assets/php-Bvwf1t96.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-DKM0oPn7.js +0 -1
- package/dist/web/assets/portal-container-context-BarKmT4S.js +0 -1
- package/dist/web/assets/postgres-viewer-CGf7_g6Z.js +0 -3
- package/dist/web/assets/ppmbot-settings-section-DeTFU1b-.js +0 -1
- package/dist/web/assets/problems-panel-Bgkcge5_.js +0 -1
- package/dist/web/assets/process-table-DH7pnH5I.js +0 -1
- package/dist/web/assets/project-framework-store-ViZgce6y.js +0 -1
- package/dist/web/assets/project-store-hNvwfqX3.js +0 -1
- package/dist/web/assets/proxy-settings-section-DMGMRHH-.js +0 -1
- package/dist/web/assets/pug-I8oitXP4.js +0 -1
- package/dist/web/assets/qml-LKb7CHg-.js +0 -1
- package/dist/web/assets/query-audit-section-CpiXQVcS.js +0 -1
- package/dist/web/assets/r-DHu15BOo.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-DKhtzXmy.js +0 -1
- package/dist/web/assets/razor-CIPT897U.js +0 -1
- package/dist/web/assets/react-Bghu0NUO.js +0 -1
- package/dist/web/assets/regexp-Vdt2OEkk.js +0 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-Bj5FtU0O.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-BhwVrKxv.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-view-B1oAqbjG.js +0 -1
- package/dist/web/assets/remote-desktop-readiness-gate-2LE86aTu.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-u8HwuzyN.js +0 -1
- package/dist/web/assets/rolldown-runtime-FhOqtrmT.js +0 -1
- package/dist/web/assets/rst-BpcmfJFA.js +0 -1
- package/dist/web/assets/ruby-Cx413jgE.js +0 -1
- package/dist/web/assets/run-in-terminal-BFR70TLU.js +0 -1
- package/dist/web/assets/sas-B3ui_NHy.js +0 -1
- package/dist/web/assets/schedules-settings-section-C8XNDdi9.js +0 -1
- package/dist/web/assets/scroll-area-C0fQWNnx.js +0 -1
- package/dist/web/assets/scss-V4NlXnGi.js +0 -1
- package/dist/web/assets/send-to-chat-C8l7AcV4.js +0 -1
- package/dist/web/assets/separator-DwDoQpxS.js +0 -1
- package/dist/web/assets/settings-body-DelxmiKf.js +0 -2
- package/dist/web/assets/settings-store-m6qOXoy4.js +0 -2
- package/dist/web/assets/settings-tab-Cb_dFdA6.js +0 -1
- package/dist/web/assets/settings-window-content-5EQQfC1t.js +0 -1
- package/dist/web/assets/shaderlab-Cf7qZ4DR.js +0 -1
- package/dist/web/assets/shellscript-DRxJLgrx.js +0 -1
- package/dist/web/assets/shellsession-BfA8Fmhb.js +0 -1
- package/dist/web/assets/soy-CGKN9rxg.js +0 -1
- package/dist/web/assets/sparql-CArCsIdI.js +0 -1
- package/dist/web/assets/sql-ljEiM8nf.js +0 -1
- package/dist/web/assets/sql-query-editor-B3wrPR6K.js +0 -1
- package/dist/web/assets/sqlite-viewer-iQXNp0kH.js +0 -1
- package/dist/web/assets/stata-CplvndbA.js +0 -1
- package/dist/web/assets/surrealql-DwX1PCpP.js +0 -1
- package/dist/web/assets/svelte-DYCNmQjy.js +0 -1
- package/dist/web/assets/system-monitor-body-5grJyA7C.js +0 -2
- package/dist/web/assets/system-monitor-tab-CJr797F8.js +0 -1
- package/dist/web/assets/system-monitor-window-content-OGAhFXXo.js +0 -1
- package/dist/web/assets/tab-host-window-content-C-eEo8I7.js +0 -1
- package/dist/web/assets/tab-store-krAuHQ6_.js +0 -1
- package/dist/web/assets/team-member-sheet-CRvJUtdh.js +0 -2
- package/dist/web/assets/team-member-window-content-C97N4RXb.js +0 -1
- package/dist/web/assets/templ-b_h2-Z9l.js +0 -1
- package/dist/web/assets/terminal-tab-eZwpkvEe.js +0 -3
- package/dist/web/assets/tex-022M3-MR.js +0 -1
- package/dist/web/assets/tool-cards-Bg4vjDYu.js +0 -9
- package/dist/web/assets/treemap-KZPCXAKY-CxqsD_6n.js +0 -1
- package/dist/web/assets/ts-tags-BUl0AdO6.js +0 -1
- package/dist/web/assets/tsx-CKaH7SzK.js +0 -1
- package/dist/web/assets/twig-CMzYUcSa.js +0 -1
- package/dist/web/assets/typescript-DZozDFsi.js +0 -1
- package/dist/web/assets/use-blob-url-C0VR6Uhh.js +0 -1
- package/dist/web/assets/use-inline-blame-CzR8CnOZ.js +0 -16
- package/dist/web/assets/use-is-mobile-TkcwP1Gx.js +0 -1
- package/dist/web/assets/use-lsp-BAoOSc-L.js +0 -6
- package/dist/web/assets/use-monaco-theme-Gd8cpt9n.js +0 -1
- package/dist/web/assets/use-open-team-member-y9sVhaNr.js +0 -1
- package/dist/web/assets/use-visual-viewport-Lp878uzs.js +0 -1
- package/dist/web/assets/use-websocket-CDfXkXo3.js +0 -1
- package/dist/web/assets/vendor-markdown-CuWCHIVb.js +0 -291
- package/dist/web/assets/vendor-mermaid-D6lgjvVE.js +0 -2921
- package/dist/web/assets/vendor-ui-DmZ-Mb-H.js +0 -45
- package/dist/web/assets/video-preview-BYJ3aVo1.js +0 -1
- package/dist/web/assets/vue-D83SsURi.js +0 -1
- package/dist/web/assets/vue-html-BGU-OYYb.js +0 -1
- package/dist/web/assets/vue-vine-1sHE1gZn.js +0 -1
- package/dist/web/assets/window-pip-registry-D1oXq-Dq.js +0 -1
- package/dist/web/assets/window-store-UC1jJeLM.js +0 -1
- package/dist/web/assets/ws-auth-CaxV807E.js +0 -1
- package/dist/web/assets/xml-bWQJszMK.js +0 -1
- package/dist/web/assets/xsl-DTMc1Tsm.js +0 -1
- package/dist/web/assets/yaml-4pzZq5KT.js +0 -1
- /package/dist/web/assets/{abap-DrxZXLHj.js → abap-DWbETETF.js} +0 -0
- /package/dist/web/assets/{actionscript-3-DOPR4pRC.js → actionscript-3-C278tgAF.js} +0 -0
- /package/dist/web/assets/{ada-DkqjEnDr.js → ada-C_5J29IC.js} +0 -0
- /package/dist/web/assets/{andromeeda-BSZjevw2.js → andromeeda-Ct0fb9Zo.js} +0 -0
- /package/dist/web/assets/{apache-DYwdQ5F_.js → apache-oMwCqc2o.js} +0 -0
- /package/dist/web/assets/{apex-Dohu7DfB.js → apex-n6XQQudq.js} +0 -0
- /package/dist/web/assets/{applescript-CdfGIVqp.js → applescript-QDMA6blY.js} +0 -0
- /package/dist/web/assets/{apply-theme-CbR31K6I.js → apply-theme-aVoqSG0I.js} +0 -0
- /package/dist/web/assets/{ara-i3_3TMnI.js → ara-D6rg_rTp.js} +0 -0
- /package/dist/web/assets/{asciidoc-DJFM-7vl.js → asciidoc-DVeBWv0S.js} +0 -0
- /package/dist/web/assets/{asm-bMFssizQ.js → asm-DzHQzzqu.js} +0 -0
- /package/dist/web/assets/{aurora-x-CetC7M8b.js → aurora-x-pJESoXa6.js} +0 -0
- /package/dist/web/assets/{awk-FFWx9ZrE.js → awk-BwfK4mzn.js} +0 -0
- /package/dist/web/assets/{ayu-dark-D4ION2wO.js → ayu-dark-CG-9c7ej.js} +0 -0
- /package/dist/web/assets/{ayu-light-BZN99P5A.js → ayu-light-BGUfMG6m.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-B-IpsKiL.js → ayu-mirage-CMD89qy6.js} +0 -0
- /package/dist/web/assets/{ballerina-DhyJcKkq.js → ballerina-CP5gYaiB.js} +0 -0
- /package/dist/web/assets/{bat-GOVQY81F.js → bat-DCRdiK45.js} +0 -0
- /package/dist/web/assets/{beancount-BO749Rhc.js → beancount-DHkDiOKO.js} +0 -0
- /package/dist/web/assets/{berry-CHYYKXmK.js → berry-B6TPldKS.js} +0 -0
- /package/dist/web/assets/{bibtex-BnYiDnxT.js → bibtex-DIor8yh9.js} +0 -0
- /package/dist/web/assets/{bicep-kljgR_G3.js → bicep-BbIdLZZ_.js} +0 -0
- /package/dist/web/assets/{bird2-DnLtJGhV.js → bird2-C76TmOG1.js} +0 -0
- /package/dist/web/assets/{c3-fc_jio6D.js → c3-CqZ77xXr.js} +0 -0
- /package/dist/web/assets/{cadence-DopRCrdB.js → cadence-BlaAb6F6.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-CUW3vVJg.js → can-open-in-ppm-D8T6Xca-.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DL6iCUa8.js → catppuccin-frappe-BuV7Zg67.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-DNF7n3uY.js → catppuccin-latte-B7HXEZf7.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-ByMic_k0.js → catppuccin-macchiato-B0KctcoC.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-DcrJtZtv.js → catppuccin-mocha-Bofr5rzo.js} +0 -0
- /package/dist/web/assets/{clarity-0cRLlvQe.js → clarity-CerfZ3dW.js} +0 -0
- /package/dist/web/assets/{clojure-DPqZAcpI.js → clojure-BCEG1uj6.js} +0 -0
- /package/dist/web/assets/{cmake-Bx26bw5u.js → cmake-CRxSSKSr.js} +0 -0
- /package/dist/web/assets/{codeowners-BpgxIgxr.js → codeowners-BqW6DYSk.js} +0 -0
- /package/dist/web/assets/{codeql-TRoWjo5g.js → codeql-DlnOpgWF.js} +0 -0
- /package/dist/web/assets/{common-lisp-Ctohamsb.js → common-lisp-DgIX9jkq.js} +0 -0
- /package/dist/web/assets/{coq-BO6TJSED.js → coq-CFeLOER-.js} +0 -0
- /package/dist/web/assets/{csharp-DSy4nlrl.js → csharp-BGFGcV8G.js} +0 -0
- /package/dist/web/assets/{csv-DND7YJXD.js → csv-Cx126-fo.js} +0 -0
- /package/dist/web/assets/{csv-parser-DZ_75eCb.js → csv-parser-BXeH-yzY.js} +0 -0
- /package/dist/web/assets/{cue-BUnWK221.js → cue-Cd0PEGFL.js} +0 -0
- /package/dist/web/assets/{cypher-CInm9Etl.js → cypher-QS9S-1Nu.js} +0 -0
- /package/dist/web/assets/{d-BbsB8r6R.js → d-Bx6zK6J7.js} +0 -0
- /package/dist/web/assets/{dark-plus-DkzIiuQX.js → dark-plus-DLqXEd2I.js} +0 -0
- /package/dist/web/assets/{dart-BG2nw7Se.js → dart-BL2C2Z6E.js} +0 -0
- /package/dist/web/assets/{dax-j4h6VhlV.js → dax-ClxUDxvY.js} +0 -0
- /package/dist/web/assets/{desktop-Dg34JDlS.js → desktop-DLEkw1UR.js} +0 -0
- /package/dist/web/assets/{diff-CRrKo-mH.js → diff-Dlp9KQSL.js} +0 -0
- /package/dist/web/assets/{dist-D39GQICe.js → dist-CDpxSUMU.js} +0 -0
- /package/dist/web/assets/{docker-DAtcxZjt.js → docker-DVBsQYb-.js} +0 -0
- /package/dist/web/assets/{dotenv-DNUcgQCn.js → dotenv-DjBB7S8B.js} +0 -0
- /package/dist/web/assets/{dracula-bhhaShNC.js → dracula-Cu055q9D.js} +0 -0
- /package/dist/web/assets/{dracula-soft-CeHAoi-D.js → dracula-soft-BiX_luwV.js} +0 -0
- /package/dist/web/assets/{dream-maker-BMH1JI2G.js → dream-maker-S6ie6kFg.js} +0 -0
- /package/dist/web/assets/{editor-font-D_4aaSCa.js → editor-font-BOjGgYeg.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-BaAYIdWN.js → emacs-lisp-DpOda430.js} +0 -0
- /package/dist/web/assets/{everforest-dark-Cs91gPa_.js → everforest-dark-BAfSXdLG.js} +0 -0
- /package/dist/web/assets/{everforest-light-lTkE6qWA.js → everforest-light-Dp59kp4R.js} +0 -0
- /package/dist/web/assets/{fennel-CmhYEhcM.js → fennel-CNaNUmMo.js} +0 -0
- /package/dist/web/assets/{fish-p1jauFum.js → fish-C8Z04ic7.js} +0 -0
- /package/dist/web/assets/{fluent-BsH-lUh2.js → fluent-Bugk01mf.js} +0 -0
- /package/dist/web/assets/{format-bytes-amUJ8Js8.js → format-bytes-DBBzVCYA.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-CB6SdVKB.js → fortran-free-form-csIz6MQj.js} +0 -0
- /package/dist/web/assets/{gdscript--YoKuvEA.js → gdscript-fdzYQLfk.js} +0 -0
- /package/dist/web/assets/{gdshader-BRtMwf5z.js → gdshader-CfsEtDeZ.js} +0 -0
- /package/dist/web/assets/{genie-wrzVG2Z8.js → genie-CtHN5N2Q.js} +0 -0
- /package/dist/web/assets/{gherkin-HnpURN27.js → gherkin-gSp2ZJTf.js} +0 -0
- /package/dist/web/assets/{github-dark-XlZ3pGhn.js → github-dark-D7O9efii.js} +0 -0
- /package/dist/web/assets/{github-dark-default-D_R0hfJe.js → github-dark-default-Bv2wIhqD.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-BHQgHLnK.js → github-dark-dimmed-BuY_SpCX.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Pbl4mEFe.js → github-dark-high-contrast-Chv0f5Wu.js} +0 -0
- /package/dist/web/assets/{github-light-0P0VANJn.js → github-light-DV8f-W2f.js} +0 -0
- /package/dist/web/assets/{github-light-default-DTfsnyDq.js → github-light-default-CNBSU3dB.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-DKITR-5Y.js → github-light-high-contrast-sg94tHwU.js} +0 -0
- /package/dist/web/assets/{gleam-refSZtkM.js → gleam-w7270-PJ.js} +0 -0
- /package/dist/web/assets/{gn-BZ9cGckR.js → gn-yo_iE_A_.js} +0 -0
- /package/dist/web/assets/{gnuplot-CMHqDcTW.js → gnuplot-DSBPrzl4.js} +0 -0
- /package/dist/web/assets/{go-bFdCrzvY.js → go-D1S7g97D.js} +0 -0
- /package/dist/web/assets/{groovy-Dvz5tluQ.js → groovy-C7xW-5IV.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-D0Z-pclr.js → gruvbox-dark-hard-BZald7Z_.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-BG6oIRQR.js → gruvbox-dark-medium-v6W4PZne.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-ILJ-3tU6.js → gruvbox-dark-soft-CN5mIGkw.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-Bl95khkz.js → gruvbox-light-hard-D3NIGRxd.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-CdislFOh.js → gruvbox-light-medium-m4ShuCnD.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-CTcEyxlX.js → gruvbox-light-soft-BEEYNyk-.js} +0 -0
- /package/dist/web/assets/{haskell-D9jfkQuH.js → haskell-CgtdXIH3.js} +0 -0
- /package/dist/web/assets/{haxe-Ckfl4osD.js → haxe-D7HQqtIx.js} +0 -0
- /package/dist/web/assets/{hcl-t03N4k5N.js → hcl-C-YHDaXH.js} +0 -0
- /package/dist/web/assets/{hjson-B_TIVRki.js → hjson-BrgEMvJK.js} +0 -0
- /package/dist/web/assets/{hlsl-BBCTeANz.js → hlsl-BsDumu1j.js} +0 -0
- /package/dist/web/assets/{horizon-CRY-xdGU.js → horizon-D9Kre3KQ.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BpUM2C5u.js → horizon-bright-DJq8c_Yq.js} +0 -0
- /package/dist/web/assets/{houston-RVyAGlyS.js → houston-B9tnxzX8.js} +0 -0
- /package/dist/web/assets/{hy-BHFJHuHd.js → hy-DUYVvXOj.js} +0 -0
- /package/dist/web/assets/{image-gallery-DdQblMAe.js → image-gallery-DvAgPQ3L.js} +0 -0
- /package/dist/web/assets/{image-preview-geometry-BFKR37Pj.js → image-preview-geometry-B-SdD7_D.js} +0 -0
- /package/dist/web/assets/{imba-DyG0_0MS.js → imba-CGW-TsRm.js} +0 -0
- /package/dist/web/assets/{ini-CsCTH-_o.js → ini-PqgYiEAV.js} +0 -0
- /package/dist/web/assets/{json5-g3g-IFTV.js → json5-sbkvqHou.js} +0 -0
- /package/dist/web/assets/{jsonc-DQHBJwib.js → jsonc-pnywfpws.js} +0 -0
- /package/dist/web/assets/{jsonl-zFLDm4eB.js → jsonl-ZPOQ0pRn.js} +0 -0
- /package/dist/web/assets/{jsonnet-DgNm2IGn.js → jsonnet-B_Q7j1YF.js} +0 -0
- /package/dist/web/assets/{jssm-BErkU0In.js → jssm-K-xYeQyp.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-Dgymfjca.js → kanagawa-dragon-DAdLBtU8.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-CWZEYd27.js → kanagawa-lotus-5BwvVGu8.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-CQg17ecf.js → kanagawa-wave-C0h9fsDT.js} +0 -0
- /package/dist/web/assets/{kdl-DY4GHmJC.js → kdl-DXSsFcms.js} +0 -0
- /package/dist/web/assets/{kotlin-DeGTz7bl.js → kotlin-BXNIvloo.js} +0 -0
- /package/dist/web/assets/{kusto-BN-OqpQj.js → kusto-wM3eio5V.js} +0 -0
- /package/dist/web/assets/{laserwave-bAqiAiOp.js → laserwave-FcbxdP2A.js} +0 -0
- /package/dist/web/assets/{lean-CAypLWCf.js → lean-RenzGeoM.js} +0 -0
- /package/dist/web/assets/{less-ikHAUlPb.js → less-CcUdtNJi.js} +0 -0
- /package/dist/web/assets/{libesm-cUHvIIuW.js → libesm-DMnQ3WlF.js} +0 -0
- /package/dist/web/assets/{light-plus-BamuTcT9.js → light-plus-BsMoOZJR.js} +0 -0
- /package/dist/web/assets/{llvm-CddObVkW.js → llvm-CyylMBuq.js} +0 -0
- /package/dist/web/assets/{log-CWbfGTTc.js → log-BOi0GB58.js} +0 -0
- /package/dist/web/assets/{logo-AHyhxX3Z.js → logo-BQUr3X2Y.js} +0 -0
- /package/dist/web/assets/{luau-y7she9L3.js → luau-3YZRDIsh.js} +0 -0
- /package/dist/web/assets/{make-DP3sQaP3.js → make-DEkKRDRU.js} +0 -0
- /package/dist/web/assets/{markdown-9Nuxib8a.js → markdown-BmFN0-A1.js} +0 -0
- /package/dist/web/assets/{material-theme-DDpm-uS7.js → material-theme-DqLHjEZ8.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CHk91wbm.js → material-theme-darker-DhbvULnI.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-LkmOI8KM.js → material-theme-lighter-C_aA4yVe.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-PpkUhB4-.js → material-theme-ocean-Pk5JltJS.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-DZAigXgW.js → material-theme-palenight-DNi3VguV.js} +0 -0
- /package/dist/web/assets/{matlab-CexKVVPc.js → matlab-BqUtv2ml.js} +0 -0
- /package/dist/web/assets/{mdx-BrcepHfI.js → mdx-DFMrnHBn.js} +0 -0
- /package/dist/web/assets/{mermaid-CNFhZZaG.js → mermaid-BpyuE0L_.js} +0 -0
- /package/dist/web/assets/{min-dark-hd3nbDV4.js → min-dark-DVfCMEPW.js} +0 -0
- /package/dist/web/assets/{min-light-AqA5jmks.js → min-light-B96aMADV.js} +0 -0
- /package/dist/web/assets/{mipsasm-B3x4L8Zk.js → mipsasm-DHhEcvKr.js} +0 -0
- /package/dist/web/assets/{mojo-CvfXy3YL.js → mojo-BQ6HsVIQ.js} +0 -0
- /package/dist/web/assets/{monokai-CdxwmnU_.js → monokai-amcXAKGG.js} +0 -0
- /package/dist/web/assets/{moonbit-6Z_VCO0_.js → moonbit-CGSXXQJI.js} +0 -0
- /package/dist/web/assets/{move-B2__B6Po.js → move-BOa4mq0q.js} +0 -0
- /package/dist/web/assets/{narrat-D6vL6wL-.js → narrat-dBYNSnhr.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-L-FBME4e.js → nextflow-groovy-Dm2Y_qgn.js} +0 -0
- /package/dist/web/assets/{night-owl-DjKrkDjv.js → night-owl-Dy9ibYHN.js} +0 -0
- /package/dist/web/assets/{night-owl-light-CeGjPuUQ.js → night-owl-light-DamYjQKi.js} +0 -0
- /package/dist/web/assets/{nix-dr279CcA.js → nix-C1LyoszC.js} +0 -0
- /package/dist/web/assets/{nord-Dxn-_H_Y.js → nord-LtGRYAFI.js} +0 -0
- /package/dist/web/assets/{nushell-DgeAQO7j.js → nushell-BMoOkt47.js} +0 -0
- /package/dist/web/assets/{objective-c-CO0-Pacn.js → objective-c-CILaOZJu.js} +0 -0
- /package/dist/web/assets/{objective-cpp-SkrjegYw.js → objective-cpp-D5Fo-SoM.js} +0 -0
- /package/dist/web/assets/{ocaml-CAihtkib.js → ocaml-D1TCTCEJ.js} +0 -0
- /package/dist/web/assets/{odin-D0XZbUDB.js → odin-CjdYcmpW.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-BUMNMxjX.js → one-dark-pro-GpsZUGZl.js} +0 -0
- /package/dist/web/assets/{one-light-C0Ui69Bx.js → one-light-DlketcS4.js} +0 -0
- /package/dist/web/assets/{openscad-fZ9ggqM-.js → openscad-BoT8wwuI.js} +0 -0
- /package/dist/web/assets/{pascal-DvZm-eun.js → pascal-Cqy403Sf.js} +0 -0
- /package/dist/web/assets/{pkl-CQSIp_z8.js → pkl-D6gRI9qQ.js} +0 -0
- /package/dist/web/assets/{plastic-CMspsouJ.js → plastic-DgvX8DXX.js} +0 -0
- /package/dist/web/assets/{plsql-B_HL7UfT.js → plsql-CTDnCVE3.js} +0 -0
- /package/dist/web/assets/{po-DxAfbdfe.js → po-DDnzm7AQ.js} +0 -0
- /package/dist/web/assets/{poimandres-JGmqmwux.js → poimandres-C4HQwFp-.js} +0 -0
- /package/dist/web/assets/{polar-_mNmplk8.js → polar-WBTQdMzX.js} +0 -0
- /package/dist/web/assets/{postcss-GpU0Sjqc.js → postcss-CWxogTg1.js} +0 -0
- /package/dist/web/assets/{powerquery-B1IP1lCQ.js → powerquery-DVtReIRR.js} +0 -0
- /package/dist/web/assets/{powershell-BiSO9XmG.js → powershell-Cb_RNzSh.js} +0 -0
- /package/dist/web/assets/{prisma-4QqDYSnH.js → prisma-nKLUh3DY.js} +0 -0
- /package/dist/web/assets/{prolog-BNjvyRqT.js → prolog-BD9orEy4.js} +0 -0
- /package/dist/web/assets/{proto-RNOumnkw.js → proto-B-AFoz75.js} +0 -0
- /package/dist/web/assets/{puppet-CDfv5o8f.js → puppet-DDW6wWm4.js} +0 -0
- /package/dist/web/assets/{purescript-YTjSoifd.js → purescript-DXy49AJg.js} +0 -0
- /package/dist/web/assets/{python-Mh7JD25U.js → python-BQnvDlc7.js} +0 -0
- /package/dist/web/assets/{qmldir-Da_ZrqZy.js → qmldir-CboMQXQW.js} +0 -0
- /package/dist/web/assets/{qss-DANVkyhy.js → qss-8XaprLEt.js} +0 -0
- /package/dist/web/assets/{racket-CwPOn4T1.js → racket-ChcVp15M.js} +0 -0
- /package/dist/web/assets/{raku-B04lBsXd.js → raku-dEgEXW0A.js} +0 -0
- /package/dist/web/assets/{red-MW6Zm5pd.js → red-hmwjontD.js} +0 -0
- /package/dist/web/assets/{reg-44SURM-E.js → reg-CIkOufh2.js} +0 -0
- /package/dist/web/assets/{rel-Gu5Erhpm.js → rel-NXKKDiTi.js} +0 -0
- /package/dist/web/assets/{resolve-theme-BNubecVz.js → resolve-theme-B87m6l4i.js} +0 -0
- /package/dist/web/assets/{riscv-DZDP0Ce7.js → riscv-BEIzhPcg.js} +0 -0
- /package/dist/web/assets/{ron-BwLObbl6.js → ron-CW2Bt8rN.js} +0 -0
- /package/dist/web/assets/{rose-pine-Bz6ToXok.js → rose-pine-DhnBfr5a.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-LyFogzAh.js → rose-pine-dawn-Jyj59rVs.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CpjkefjD.js → rose-pine-moon-BMulxhJC.js} +0 -0
- /package/dist/web/assets/{rosmsg-BldDLaz1.js → rosmsg-DuctJm-Q.js} +0 -0
- /package/dist/web/assets/{rust-74skZ8CC.js → rust-FbJ2fCp9.js} +0 -0
- /package/dist/web/assets/{sass-CitUFDWl.js → sass-Dfxwdu2h.js} +0 -0
- /package/dist/web/assets/{scala-D2kl5ghT.js → scala-ClsSR0wG.js} +0 -0
- /package/dist/web/assets/{scheme-DZqhC9Xs.js → scheme-Jj_Cc-8H.js} +0 -0
- /package/dist/web/assets/{sdbl-D6a8sHP9.js → sdbl-Bi8D_DGN.js} +0 -0
- /package/dist/web/assets/{slack-dark-DrlPLUB_.js → slack-dark-B7gbmJT9.js} +0 -0
- /package/dist/web/assets/{slack-ochin-Djgychog.js → slack-ochin-O7j_c76D.js} +0 -0
- /package/dist/web/assets/{smalltalk-CYQHXftK.js → smalltalk-BD5-U3JK.js} +0 -0
- /package/dist/web/assets/{snazzy-light-BQAdF14K.js → snazzy-light-BbiRB69_.js} +0 -0
- /package/dist/web/assets/{solarized-dark-JDtJfY-g.js → solarized-dark-2OWHYEBu.js} +0 -0
- /package/dist/web/assets/{solarized-light-DHzVPLDD.js → solarized-light-Cew4YqT3.js} +0 -0
- /package/dist/web/assets/{solidity-CYCEiPu1.js → solidity-Bpbne2Tx.js} +0 -0
- /package/dist/web/assets/{splunk-B7RHmJY2.js → splunk-Dq86L1_O.js} +0 -0
- /package/dist/web/assets/{ssh-config-B74-n00O.js → ssh-config-j5hsMvbs.js} +0 -0
- /package/dist/web/assets/{stylus-xlRhcbpN.js → stylus-DWhCIBg0.js} +0 -0
- /package/dist/web/assets/{swift-DTFwWJtu.js → swift-29fG5ztW.js} +0 -0
- /package/dist/web/assets/{synthwave-84-BuCpuX2E.js → synthwave-84-DraIUmiw.js} +0 -0
- /package/dist/web/assets/{system-verilog-CgxJCrOK.js → system-verilog-DqcJAWq_.js} +0 -0
- /package/dist/web/assets/{systemd-D0x7_XYJ.js → systemd-BUPJrx1D.js} +0 -0
- /package/dist/web/assets/{talonscript-B50aQRuc.js → talonscript-BGYbnAKh.js} +0 -0
- /package/dist/web/assets/{tasl-Byv8gHCL.js → tasl-CwbSJqng.js} +0 -0
- /package/dist/web/assets/{tcl-CzMjCzWo.js → tcl-Ba9376wa.js} +0 -0
- /package/dist/web/assets/{terraform-D6GH4CXG.js → terraform-ChSasWu8.js} +0 -0
- /package/dist/web/assets/{tokyo-night-CQ4rTpHY.js → tokyo-night-Bbw1Yguv.js} +0 -0
- /package/dist/web/assets/{toml-D9W-BuJE.js → toml-CYb7zi5B.js} +0 -0
- /package/dist/web/assets/{tsv-BddanT8p.js → tsv-P2eVmwf9.js} +0 -0
- /package/dist/web/assets/{turtle-BddVklvD.js → turtle-DIoQTATC.js} +0 -0
- /package/dist/web/assets/{typespec-D60I2kfB.js → typespec-Dpr1bC2k.js} +0 -0
- /package/dist/web/assets/{typst-Bxvc-9ID.js → typst-D4WMCDMn.js} +0 -0
- /package/dist/web/assets/{utils-Bmf_8h7Y.js → utils-btZ8C8-R.js} +0 -0
- /package/dist/web/assets/{v-kVYZE10o.js → v-B1wY-VFU.js} +0 -0
- /package/dist/web/assets/{vala-B3zj44PV.js → vala-BKqhrirP.js} +0 -0
- /package/dist/web/assets/{vb-CHgWrFTj.js → vb-S9PHCa7-.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-BHKF_Nsf.js} +0 -0
- /package/dist/web/assets/{verilog-zIMuE3hE.js → verilog-CrztYl3V.js} +0 -0
- /package/dist/web/assets/{vesper-BjqPTQr0.js → vesper-C5KfcyFv.js} +0 -0
- /package/dist/web/assets/{vhdl-Q2EtgpQN.js → vhdl-D0qMeIJu.js} +0 -0
- /package/dist/web/assets/{viml-CrtDZkFz.js → viml-Dsv9mRPK.js} +0 -0
- /package/dist/web/assets/{vitesse-black-D2VWO3oN.js → vitesse-black-rJvNN5GN.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-lleZmHBJ.js → vitesse-dark-CYp0WWjf.js} +0 -0
- /package/dist/web/assets/{vitesse-light-utUY298S.js → vitesse-light-BczSAvzE.js} +0 -0
- /package/dist/web/assets/{vyper-LQ1KxOUo.js → vyper-DM7bKz7E.js} +0 -0
- /package/dist/web/assets/{wasm-CJ9U4zWg.js → wasm-BXCHhbrz.js} +0 -0
- /package/dist/web/assets/{wasm-B-mpMVDM.js → wasm-CAJoqhGc.js} +0 -0
- /package/dist/web/assets/{wenyan-LqMyA7px.js → wenyan-NQ8fdbEq.js} +0 -0
- /package/dist/web/assets/{wgsl-eI4U21sm.js → wgsl-C88C7vmC.js} +0 -0
- /package/dist/web/assets/{wikitext-CuWC2dfS.js → wikitext-D92r7uX8.js} +0 -0
- /package/dist/web/assets/{wit-CCPY0MNz.js → wit-DNvTfQjW.js} +0 -0
- /package/dist/web/assets/{wolfram-CXhjyJun.js → wolfram-CNS5lCGj.js} +0 -0
- /package/dist/web/assets/{zenscript-BzHPI08Q.js → zenscript-B_rGi-H_.js} +0 -0
- /package/dist/web/assets/{zig-CBuhKUve.js → zig-BRi9UYQa.js} +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readDesignFileSafe } from "../design-safe-walk.ts";
|
|
3
|
+
import { writeFileAtomic } from "../design-fs.ts";
|
|
4
|
+
import { DesignError } from "../design-error.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A design source file (HTML or CSS) as text, plus its `gen`.
|
|
8
|
+
*
|
|
9
|
+
* Everything that addresses a position in a design file — `data-ppm-id` start-tag offsets,
|
|
10
|
+
* style-attribute spans, `:root` declarations — addresses the text *after* a leading BOM is
|
|
11
|
+
* removed, and the gen hashes that same text. The BOM has to go before parsing, not after:
|
|
12
|
+
* parse5 reads U+FEFF as body text, which silently drops the source location of an explicit
|
|
13
|
+
* `<html>`, `<head>` and `<body>`. It is remembered and written back, so a round trip never
|
|
14
|
+
* changes a byte the user did not ask to change.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const BOM = "";
|
|
18
|
+
/** Largest source file read as text at all; far above anything an agent writes. */
|
|
19
|
+
export const MAX_DESIGN_SOURCE_BYTES = 64 * 1024 * 1024;
|
|
20
|
+
|
|
21
|
+
export interface DesignSource {
|
|
22
|
+
text: string;
|
|
23
|
+
bom: boolean;
|
|
24
|
+
gen: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 16 hex chars of SHA-256 over the BOM-less text: a staleness check, not a secret. */
|
|
28
|
+
export function computeGen(text: string): string {
|
|
29
|
+
return createHash("sha256").update(text, "utf8").digest("hex").slice(0, 16);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Bytes to text. `lossy` is for serving only: an invalid sequence becomes U+FFFD, which
|
|
34
|
+
* would corrupt the file if it were ever written back, so write paths use the strict form.
|
|
35
|
+
*/
|
|
36
|
+
export function decodeDesignText(bytes: Uint8Array, opts: { lossy?: boolean } = {}): DesignSource {
|
|
37
|
+
let raw: string;
|
|
38
|
+
try {
|
|
39
|
+
// ignoreBOM keeps U+FEFF in the output, so it is detected here instead of vanishing.
|
|
40
|
+
raw = new TextDecoder("utf-8", { fatal: !opts.lossy, ignoreBOM: true }).decode(bytes);
|
|
41
|
+
} catch {
|
|
42
|
+
throw new DesignError(422, "ENOTUTF8", "Design file is not valid UTF-8");
|
|
43
|
+
}
|
|
44
|
+
const bom = raw.startsWith(BOM);
|
|
45
|
+
const text = bom ? raw.slice(BOM.length) : raw;
|
|
46
|
+
return { text, bom, gen: computeGen(text) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function readDesignSource(
|
|
50
|
+
abs: string,
|
|
51
|
+
opts: { lossy?: boolean; maxBytes?: number } = {},
|
|
52
|
+
): Promise<DesignSource> {
|
|
53
|
+
const bytes = await readDesignFileSafe(abs, opts.maxBytes ?? MAX_DESIGN_SOURCE_BYTES);
|
|
54
|
+
return decodeDesignText(bytes, opts);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Atomic write that restores the BOM the file was read with. Returns the new gen. */
|
|
58
|
+
export async function writeDesignSource(abs: string, text: string, opts: { bom: boolean }): Promise<string> {
|
|
59
|
+
if (text.startsWith(BOM)) throw new DesignError(400, "EBOM", "Source text must not start with a BOM");
|
|
60
|
+
await writeFileAtomic(abs, opts.bom ? BOM + text : text);
|
|
61
|
+
return computeGen(text);
|
|
62
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import { resolveScopedPath, TOKENS_CSS_ALIAS } from "../preview/design-preview-scope.ts";
|
|
3
|
+
import type { DesignRef } from "../preview/design-preview-tokens.ts";
|
|
4
|
+
import { readDesignSource, type DesignSource } from "./design-source-file.ts";
|
|
5
|
+
import { htmlStyleNodes } from "./html-style-blocks.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The stylesheets one design page is styled by, in cascade order, read from disk.
|
|
9
|
+
*
|
|
10
|
+
* Inline `<style>` blocks and local `<link rel=stylesheet>` files, in document order —
|
|
11
|
+
* which is the order in which a later `:root` declaration beats an earlier one. CDN sheets
|
|
12
|
+
* are skipped (not ours to read or write), as are links the canvas cannot load either:
|
|
13
|
+
* missing files, anything outside the design folder except the shared `tokens.css`, and
|
|
14
|
+
* non-`.css` targets. `tokens.css` stays in the list, marked `outside`, because a variable
|
|
15
|
+
* it sets last really does win on screen — the tweak commit refuses that case rather than
|
|
16
|
+
* patching a declaration that would lose to it.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** Local stylesheets considered per page; the preview reports gens for the same number. */
|
|
20
|
+
export const MAX_LINKED_STYLE_SOURCES = 32;
|
|
21
|
+
|
|
22
|
+
export interface StyleSource {
|
|
23
|
+
/** Design-relative path of the file holding the CSS; `../tokens.css` for the shared one. */
|
|
24
|
+
file: string;
|
|
25
|
+
kind: "inline" | "linked";
|
|
26
|
+
/** Offsets of the CSS text inside the file's (BOM-less) text; the whole file when linked. */
|
|
27
|
+
start: number;
|
|
28
|
+
end: number;
|
|
29
|
+
/** A `media` attribute limits the whole sheet. */
|
|
30
|
+
conditional: boolean;
|
|
31
|
+
/** Outside the design folder: part of the cascade, never written. */
|
|
32
|
+
outside: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface StyleFile {
|
|
36
|
+
abs: string;
|
|
37
|
+
source: DesignSource;
|
|
38
|
+
outside: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface DesignStyleSources {
|
|
42
|
+
entry: StyleFile;
|
|
43
|
+
sources: StyleSource[];
|
|
44
|
+
/** Every file read, keyed like {@link StyleSource.file}; the entry HTML included. */
|
|
45
|
+
files: Map<string, StyleFile>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The design-relative path an href names, or null when it cannot be one of the design's files. */
|
|
49
|
+
export function linkedStylePath(entryRel: string, href: string): string | null {
|
|
50
|
+
let rel: string;
|
|
51
|
+
try {
|
|
52
|
+
rel = posix.normalize(posix.join(posix.dirname(entryRel), decodeURIComponent(href.split(/[?#]/)[0]!)));
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (!/\.css$/i.test(rel)) return null;
|
|
57
|
+
if (rel === `../${TOKENS_CSS_ALIAS}`) return rel;
|
|
58
|
+
if (rel === ".." || rel.startsWith("../") || rel.startsWith("/")) return null;
|
|
59
|
+
return rel;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function readLinked(design: DesignRef, rel: string): Promise<{ rel: string; file: StyleFile } | null> {
|
|
63
|
+
const outside = rel.startsWith("../");
|
|
64
|
+
let asset: { abs: string; rel: string };
|
|
65
|
+
try {
|
|
66
|
+
asset = await resolveScopedPath(design, outside ? TOKENS_CSS_ALIAS : `${design.slug}/${rel}`);
|
|
67
|
+
} catch {
|
|
68
|
+
// Missing, or refused by the preview's own guard: the canvas does not load it, so it is not in the cascade.
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Keyed by the scope's own relative path, which is also how the preview names it in `cssGens`.
|
|
72
|
+
return { rel: asset.rel, file: { abs: asset.abs, source: await readDesignSource(asset.abs), outside } };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function styleSources(design: DesignRef, entryRel: string): Promise<DesignStyleSources> {
|
|
76
|
+
const entryAbs = (await resolveScopedPath(design, `${design.slug}/${entryRel}`)).abs;
|
|
77
|
+
const entry: StyleFile = { abs: entryAbs, source: await readDesignSource(entryAbs), outside: false };
|
|
78
|
+
const files = new Map<string, StyleFile>([[entryRel, entry]]);
|
|
79
|
+
const sources: StyleSource[] = [];
|
|
80
|
+
let linked = 0;
|
|
81
|
+
|
|
82
|
+
for (const node of htmlStyleNodes(entry.source.text)) {
|
|
83
|
+
if (node.kind === "inline") {
|
|
84
|
+
sources.push({ file: entryRel, kind: "inline", start: node.start, end: node.end, conditional: node.conditional, outside: false });
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (linked >= MAX_LINKED_STYLE_SOURCES) continue;
|
|
88
|
+
const path = linkedStylePath(entryRel, node.href);
|
|
89
|
+
if (!path) continue;
|
|
90
|
+
linked++;
|
|
91
|
+
const read = await readLinked(design, path);
|
|
92
|
+
if (!read || read.rel === entryRel) continue;
|
|
93
|
+
const { rel } = read;
|
|
94
|
+
const file = files.get(rel) ?? read.file;
|
|
95
|
+
files.set(rel, file);
|
|
96
|
+
sources.push({
|
|
97
|
+
file: rel, kind: "linked", start: 0, end: file.source.text.length, conditional: node.conditional, outside: file.outside,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return { entry, sources, files };
|
|
101
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { parse, type DefaultTreeAdapterMap } from "parse5";
|
|
2
|
+
import { elementQuote, type TreeAccess } from "../bridge/bridge-element-info.ts";
|
|
3
|
+
import type { CommentQuote } from "../../../shared/design-comment-types.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The source text of the element whose start tag is at `ppmId` (a `data-ppm-id`), read
|
|
7
|
+
* from the file itself rather than from anything the page reported.
|
|
8
|
+
*
|
|
9
|
+
* The range runs from the `<` of the start tag to the end of the end tag (or of the last
|
|
10
|
+
* child, when the end tag is implied; a void element is just its start tag). The quote is
|
|
11
|
+
* computed by the same `elementQuote` the canvas uses, over the parse5 tree, so a stored
|
|
12
|
+
* quote and a source quote are comparable. `text` must be the BOM-less text the gen and the
|
|
13
|
+
* ids were computed over (`readDesignSource`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
type Node = DefaultTreeAdapterMap["node"];
|
|
17
|
+
type Element = DefaultTreeAdapterMap["element"];
|
|
18
|
+
type ParentNode = DefaultTreeAdapterMap["parentNode"];
|
|
19
|
+
|
|
20
|
+
export interface ElementSourceRange {
|
|
21
|
+
start: number;
|
|
22
|
+
end: number;
|
|
23
|
+
tag: string;
|
|
24
|
+
/** The element's collapsed text, up to the quote's 160 chars. */
|
|
25
|
+
textContent: string;
|
|
26
|
+
quote: CommentQuote;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const isElement = (node: Node): node is Element => "tagName" in node;
|
|
30
|
+
|
|
31
|
+
const PARSE5_ACCESS: TreeAccess<Node> = {
|
|
32
|
+
parent: (n) => ((n as { parentNode?: ParentNode | null }).parentNode ?? null) as Node | null,
|
|
33
|
+
children: (n) => ("childNodes" in n ? (n as ParentNode).childNodes : []),
|
|
34
|
+
text: (n) => (n.nodeName === "#text" ? (n as DefaultTreeAdapterMap["textNode"]).value : null),
|
|
35
|
+
tag: (n) => (isElement(n) ? n.tagName.toLowerCase() : null),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function findByStartOffset(root: Node, offset: number): Element | null {
|
|
39
|
+
// Iterative, so a pathologically deep document cannot overflow the stack.
|
|
40
|
+
const stack: Node[] = [root];
|
|
41
|
+
while (stack.length) {
|
|
42
|
+
const node = stack.pop()!;
|
|
43
|
+
if (isElement(node)) {
|
|
44
|
+
const start = node.sourceCodeLocation?.startTag?.startOffset;
|
|
45
|
+
if (start === offset) return node;
|
|
46
|
+
if (node.tagName === "template") stack.push((node as DefaultTreeAdapterMap["template"]).content);
|
|
47
|
+
}
|
|
48
|
+
if ("childNodes" in node) {
|
|
49
|
+
const kids = (node as ParentNode).childNodes;
|
|
50
|
+
for (let i = kids.length - 1; i >= 0; i--) stack.push(kids[i]!);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function elementSourceRange(text: string, ppmId: number): ElementSourceRange | null {
|
|
57
|
+
if (!Number.isInteger(ppmId) || ppmId < 0 || ppmId >= text.length || text.charCodeAt(ppmId) !== 60 /* < */) return null;
|
|
58
|
+
const doc = parse(text, { sourceCodeLocationInfo: true });
|
|
59
|
+
const el = findByStartOffset(doc, ppmId);
|
|
60
|
+
const loc = el?.sourceCodeLocation;
|
|
61
|
+
if (!el || !loc?.startTag) return null;
|
|
62
|
+
const end = Math.max(loc.startTag.endOffset, loc.endTag?.endOffset ?? loc.endOffset);
|
|
63
|
+
const quote = elementQuote<Node>(el, PARSE5_ACCESS);
|
|
64
|
+
return { start: ppmId, end, tag: el.tagName.toLowerCase(), textContent: quote.exact, quote };
|
|
65
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { parse, type DefaultTreeAdapterMap } from "parse5";
|
|
2
|
+
import { isLocalHref } from "../preview/html-instrument.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where an HTML page's styles come from, in document (= cascade) order: its `<style>`
|
|
6
|
+
* blocks as text-content offsets into the source, and its local `<link rel=stylesheet>`
|
|
7
|
+
* hrefs. Offsets are parse5's, UTF-16 indices into exactly the text given (see
|
|
8
|
+
* `html-instrument.ts`), so a slice of the source is the CSS the browser reads.
|
|
9
|
+
*
|
|
10
|
+
* Left out, because the browser does not apply them: anything inside `<template>`, a
|
|
11
|
+
* `<style>` whose `type` is not CSS, and alternate or `disabled` stylesheet links. A
|
|
12
|
+
* `media` attribute other than `all` makes the whole sheet conditional.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
type Node = DefaultTreeAdapterMap["node"];
|
|
16
|
+
type Element = DefaultTreeAdapterMap["element"];
|
|
17
|
+
|
|
18
|
+
export type HtmlStyleNode =
|
|
19
|
+
| { kind: "inline"; start: number; end: number; conditional: boolean }
|
|
20
|
+
| { kind: "linked"; href: string; conditional: boolean };
|
|
21
|
+
|
|
22
|
+
const isElement = (node: Node): node is Element => "tagName" in node;
|
|
23
|
+
const attr = (el: Element, name: string): string | undefined => el.attrs.find((a) => a.name === name)?.value;
|
|
24
|
+
|
|
25
|
+
function conditionalMedia(el: Element): boolean {
|
|
26
|
+
const media = (attr(el, "media") ?? "").trim().toLowerCase();
|
|
27
|
+
return media !== "" && media !== "all";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function walk(text: string, visit: (el: Element) => void): void {
|
|
31
|
+
const doc = parse(text, { sourceCodeLocationInfo: true });
|
|
32
|
+
// Iterative, so a pathologically deep document cannot overflow the stack.
|
|
33
|
+
const stack: Node[] = [...doc.childNodes].reverse();
|
|
34
|
+
while (stack.length) {
|
|
35
|
+
const node = stack.pop()!;
|
|
36
|
+
if (!isElement(node) || node.tagName === "template") continue;
|
|
37
|
+
visit(node);
|
|
38
|
+
for (let i = node.childNodes.length - 1; i >= 0; i--) stack.push(node.childNodes[i]!);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function htmlStyleNodes(html: string): HtmlStyleNode[] {
|
|
43
|
+
const out: HtmlStyleNode[] = [];
|
|
44
|
+
walk(html, (el) => {
|
|
45
|
+
const loc = el.sourceCodeLocation;
|
|
46
|
+
if (el.tagName === "style" && loc?.startTag) {
|
|
47
|
+
const type = (attr(el, "type") ?? "").trim().toLowerCase();
|
|
48
|
+
if (type !== "" && type !== "text/css") return;
|
|
49
|
+
const start = loc.startTag.endOffset;
|
|
50
|
+
// Style text is raw: without a `</style>` it runs to the end of the document.
|
|
51
|
+
out.push({ kind: "inline", start, end: loc.endTag?.startOffset ?? html.length, conditional: conditionalMedia(el) });
|
|
52
|
+
} else if (el.tagName === "link") {
|
|
53
|
+
const rel = (attr(el, "rel") ?? "").toLowerCase().split(/\s+/);
|
|
54
|
+
const href = attr(el, "href");
|
|
55
|
+
if (!rel.includes("stylesheet") || rel.includes("alternate") || attr(el, "disabled") !== undefined) return;
|
|
56
|
+
if (href !== undefined && isLocalHref(href)) out.push({ kind: "linked", href: href.trim(), conditional: conditionalMedia(el) });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Text-content offsets of every applied `<style>` element, in document order. */
|
|
63
|
+
export function findStyleBlocks(html: string): Array<{ start: number; end: number }> {
|
|
64
|
+
return htmlStyleNodes(html).flatMap((n) => (n.kind === "inline" ? [{ start: n.start, end: n.end }] : []));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Where a new `<style>` element goes so it lands last in `<head>`: before `</head>`, else
|
|
69
|
+
* after the `<head>` start tag, else before `<body>`, else after `<html>` or the doctype.
|
|
70
|
+
*/
|
|
71
|
+
export function headEndOffset(html: string): number {
|
|
72
|
+
let head: Element | undefined, body: Element | undefined, root: Element | undefined;
|
|
73
|
+
walk(html, (el) => {
|
|
74
|
+
if (el.tagName === "head" && !head) head = el;
|
|
75
|
+
else if (el.tagName === "body" && !body) body = el;
|
|
76
|
+
else if (el.tagName === "html" && !root) root = el;
|
|
77
|
+
});
|
|
78
|
+
const h = head?.sourceCodeLocation;
|
|
79
|
+
if (h?.endTag) return h.endTag.startOffset;
|
|
80
|
+
if (h?.startTag) return h.startTag.endOffset;
|
|
81
|
+
const b = body?.sourceCodeLocation?.startTag;
|
|
82
|
+
if (b) return b.startOffset;
|
|
83
|
+
const r = root?.sourceCodeLocation?.startTag;
|
|
84
|
+
if (r) return r.endOffset;
|
|
85
|
+
const doctype = /^\s*<!doctype[^>]*>/i.exec(html);
|
|
86
|
+
return doctype ? doctype[0].length : 0;
|
|
87
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The declarations of a `style` attribute value, read from its raw source text — entities
|
|
3
|
+
* and all — so a merge can change some declarations and leave every other byte alone.
|
|
4
|
+
*
|
|
5
|
+
* The scanner walks the raw text, but decides structure on what each piece *decodes* to:
|
|
6
|
+
* `"` opens a string exactly like `"` does, and the `;` that ends an entity is not a
|
|
7
|
+
* declaration separator (`font-family: "Inter"; color: red` is two declarations,
|
|
8
|
+
* not four). Strings, parentheses (`url(data:…;base64,…)`) and comments are skipped as
|
|
9
|
+
* units. Names are compared case-insensitively, as CSS does.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface StyleDeclaration {
|
|
13
|
+
/** Lowercased property name. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Raw span of the whole declaration, without the `;` that ends it. */
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
important: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const NAMED: Record<string, string> = { quot: '"', apos: "'", amp: "&", lt: "<", gt: ">", semi: ";", lpar: "(", rpar: ")", colon: ":", sol: "/", ast: "*" };
|
|
22
|
+
|
|
23
|
+
/** The character a raw unit stands for, and how many raw characters it spans. */
|
|
24
|
+
function unitAt(raw: string, i: number): [string, number] {
|
|
25
|
+
if (raw[i] !== "&") return [raw[i]!, 1];
|
|
26
|
+
const m = /^&(#[0-9]{1,7}|#[xX][0-9a-fA-F]{1,6}|[A-Za-z][A-Za-z0-9]{0,31});/.exec(raw.slice(i, i + 40));
|
|
27
|
+
if (!m) return ["&", 1];
|
|
28
|
+
const ref = m[1]!;
|
|
29
|
+
let ch: string | undefined;
|
|
30
|
+
if (ref[0] === "#") {
|
|
31
|
+
const code = ref[1] === "x" || ref[1] === "X" ? parseInt(ref.slice(2), 16) : parseInt(ref.slice(1), 10);
|
|
32
|
+
ch = code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : "\uFFFD";
|
|
33
|
+
} else {
|
|
34
|
+
// An entity outside this table decodes to text that has no meaning to the scanner.
|
|
35
|
+
ch = NAMED[ref] ?? "x";
|
|
36
|
+
}
|
|
37
|
+
return [ch, m[0].length];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function parseStyleDeclarations(raw: string): StyleDeclaration[] {
|
|
41
|
+
const out: StyleDeclaration[] = [];
|
|
42
|
+
let declStart = 0;
|
|
43
|
+
let colon = -1;
|
|
44
|
+
let depth = 0;
|
|
45
|
+
let quote: string | null = null;
|
|
46
|
+
let comment = false;
|
|
47
|
+
const finish = (end: number): void => {
|
|
48
|
+
if (colon >= 0) {
|
|
49
|
+
const head = raw.slice(declStart, colon);
|
|
50
|
+
// A comment in front of the name belongs to the declaration's span but not to its name.
|
|
51
|
+
const name = head.replace(/\/\*[\s\S]*?\*\//g, "").trim().toLowerCase();
|
|
52
|
+
const start = declStart + (head.length - head.trimStart().length);
|
|
53
|
+
const important = /!\s*important\s*$/i.test(raw.slice(colon + 1, end).trim());
|
|
54
|
+
if (name) out.push({ name, start, end: trimEnd(raw, end, start), important });
|
|
55
|
+
}
|
|
56
|
+
colon = -1;
|
|
57
|
+
};
|
|
58
|
+
for (let i = 0; i < raw.length;) {
|
|
59
|
+
const [ch, len] = unitAt(raw, i);
|
|
60
|
+
if (comment) {
|
|
61
|
+
if (ch === "*" && unitAt(raw, i + len)[0] === "/") {
|
|
62
|
+
comment = false;
|
|
63
|
+
i += len + unitAt(raw, i + len)[1];
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
} else if (quote) {
|
|
67
|
+
if (ch === "\\") i += len;
|
|
68
|
+
else if (ch === quote) quote = null;
|
|
69
|
+
} else if (ch === "/" && unitAt(raw, i + len)[0] === "*") {
|
|
70
|
+
comment = true;
|
|
71
|
+
i += len + unitAt(raw, i + len)[1];
|
|
72
|
+
continue;
|
|
73
|
+
} else if (ch === '"' || ch === "'") {
|
|
74
|
+
quote = ch;
|
|
75
|
+
} else if (ch === "(") {
|
|
76
|
+
depth++;
|
|
77
|
+
} else if (ch === ")") {
|
|
78
|
+
depth = Math.max(0, depth - 1);
|
|
79
|
+
} else if (ch === ":" && colon < 0 && depth === 0) {
|
|
80
|
+
colon = i;
|
|
81
|
+
} else if (ch === ";" && depth === 0) {
|
|
82
|
+
finish(i);
|
|
83
|
+
declStart = i + len;
|
|
84
|
+
}
|
|
85
|
+
i += len;
|
|
86
|
+
}
|
|
87
|
+
finish(raw.length);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function trimEnd(raw: string, end: number, floor: number): number {
|
|
92
|
+
let e = end;
|
|
93
|
+
while (e > floor && /\s/.test(raw[e - 1]!)) e--;
|
|
94
|
+
return e;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* `raw` with each prop set. The last declaration of a property is rewritten in place (its
|
|
99
|
+
* `!important` kept, so it still wins where it won before); earlier declarations of the same
|
|
100
|
+
* property are removed, since they are dead text that would now disagree with it; a property
|
|
101
|
+
* the attribute does not have is appended. Every other byte is kept.
|
|
102
|
+
*/
|
|
103
|
+
export function mergeStyle(raw: string, props: Readonly<Record<string, string>>): string {
|
|
104
|
+
const decls = parseStyleDeclarations(raw);
|
|
105
|
+
const edits: Array<{ start: number; end: number; text: string }> = [];
|
|
106
|
+
const appended: string[] = [];
|
|
107
|
+
for (const [name, value] of Object.entries(props)) {
|
|
108
|
+
const same = decls.filter((d) => d.name === name);
|
|
109
|
+
const last = same[same.length - 1];
|
|
110
|
+
if (!last) {
|
|
111
|
+
appended.push(`${name}: ${value}`);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
edits.push({ start: last.start, end: last.end, text: `${name}: ${value}${last.important ? " !important" : ""}` });
|
|
115
|
+
for (const d of same.slice(0, -1)) {
|
|
116
|
+
// The declaration and the `;` (plus spacing) that followed it.
|
|
117
|
+
let end = d.end;
|
|
118
|
+
while (end < raw.length && /\s/.test(raw[end]!)) end++;
|
|
119
|
+
if (raw[end] === ";") end++;
|
|
120
|
+
while (end < raw.length && /[ \t]/.test(raw[end]!)) end++;
|
|
121
|
+
edits.push({ start: d.start, end, text: "" });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
let text = raw;
|
|
125
|
+
for (const e of edits.sort((a, b) => b.start - a.start)) text = text.slice(0, e.start) + e.text + text.slice(e.end);
|
|
126
|
+
if (appended.length === 0) return text;
|
|
127
|
+
const body = text.replace(/\s+$/, "");
|
|
128
|
+
const tail = text.slice(body.length);
|
|
129
|
+
const sep = body === "" ? "" : body.endsWith(";") ? " " : "; ";
|
|
130
|
+
return `${body}${sep}${appended.join("; ")}${tail}`;
|
|
131
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { parse } from "parse5";
|
|
2
|
+
import { tagNameEnd } from "../preview/html-instrument.ts";
|
|
3
|
+
import { findByStartOffset } from "./element-source-range.ts";
|
|
4
|
+
import { mergeStyle } from "./inline-style-declarations.ts";
|
|
5
|
+
|
|
6
|
+
export { mergeStyle, parseStyleDeclarations } from "./inline-style-declarations.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Writes a canvas move/resize into the source: the `style` attribute of one element's start
|
|
10
|
+
* tag, and nothing else.
|
|
11
|
+
*
|
|
12
|
+
* The element is the one whose start tag begins at `ppmId` (its `data-ppm-id`, i.e. the
|
|
13
|
+
* offset of its `<` in the BOM-less text) and must have the expected tag, or the edit is
|
|
14
|
+
* refused as `element-moved`. parse5 records each attribute's location (keyed by lowercased
|
|
15
|
+
* name, spanning `name=value`, the first of two duplicates — the one the browser keeps), so
|
|
16
|
+
* only that span is rewritten: the original name spelling (`STYLE`), quote character and
|
|
17
|
+
* every declaration not being set stay byte-for-byte. A tag with no `style` gets one right
|
|
18
|
+
* after its name, which also works for a self-closing `<rect/>`. The element's own start
|
|
19
|
+
* offset never moves, so its id stays valid for the reloaded canvas.
|
|
20
|
+
*
|
|
21
|
+
* The returned span is exactly what changed, for the undo journal.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export interface SourceSpan {
|
|
25
|
+
start: number;
|
|
26
|
+
oldText: string;
|
|
27
|
+
newText: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type StylePatchResult =
|
|
31
|
+
| { text: string; span: SourceSpan }
|
|
32
|
+
| { error: "element-moved"; message: string };
|
|
33
|
+
|
|
34
|
+
/** Text safe inside a double- or single-quoted attribute value. */
|
|
35
|
+
export function escapeAttr(value: string): string {
|
|
36
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const moved = (message: string): StylePatchResult => ({ error: "element-moved", message });
|
|
40
|
+
|
|
41
|
+
function styleAttribute(attrText: string, props: Record<string, string>): string {
|
|
42
|
+
const m = /^([^\s=]+)(\s*=\s*)([\s\S]*)$/.exec(attrText);
|
|
43
|
+
// A bare `style` with no value.
|
|
44
|
+
if (!m) return `${attrText}="${mergeStyle("", props)}"`;
|
|
45
|
+
const [, name, eq, value] = m as unknown as [string, string, string, string];
|
|
46
|
+
const q = value[0] === '"' || value[0] === "'" ? value[0] : null;
|
|
47
|
+
if (!q) {
|
|
48
|
+
// Unquoted: the new declarations hold spaces, so the value has to be quoted now. An
|
|
49
|
+
// unquoted value cannot contain a quote, so nothing in it needs escaping.
|
|
50
|
+
return `${name}${eq}"${mergeStyle(value, props)}"`;
|
|
51
|
+
}
|
|
52
|
+
const closed = value.length > 1 && value.endsWith(q);
|
|
53
|
+
const inner = closed ? value.slice(1, -1) : value.slice(1);
|
|
54
|
+
return `${name}${eq}${q}${mergeStyle(inner, props)}${closed ? q : ""}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function patchStartTagStyle(
|
|
58
|
+
text: string,
|
|
59
|
+
ppmId: number,
|
|
60
|
+
tag: string,
|
|
61
|
+
props: Readonly<Record<string, string>>,
|
|
62
|
+
): StylePatchResult {
|
|
63
|
+
if (!Number.isInteger(ppmId) || ppmId < 0 || ppmId >= text.length || text.charCodeAt(ppmId) !== 60 /* < */) {
|
|
64
|
+
return moved("There is no element at that position any more");
|
|
65
|
+
}
|
|
66
|
+
const el = findByStartOffset(parse(text, { sourceCodeLocationInfo: true }), ppmId);
|
|
67
|
+
const startTag = el?.sourceCodeLocation?.startTag;
|
|
68
|
+
if (!el || !startTag) return moved("There is no element at that position any more");
|
|
69
|
+
if (el.tagName.toLowerCase() !== tag) return moved(`The element at that position is a <${el.tagName.toLowerCase()}>, not a <${tag}>`);
|
|
70
|
+
|
|
71
|
+
// Validated px values need no escaping; escaping anyway keeps this safe for any caller.
|
|
72
|
+
const safe = Object.fromEntries(Object.entries(props).map(([k, v]) => [k, escapeAttr(v)]));
|
|
73
|
+
const loc = el.sourceCodeLocation?.attrs?.style;
|
|
74
|
+
const span: SourceSpan = loc
|
|
75
|
+
? { start: loc.startOffset, oldText: text.slice(loc.startOffset, loc.endOffset), newText: "" }
|
|
76
|
+
: { start: tagNameEnd(text, ppmId), oldText: "", newText: "" };
|
|
77
|
+
span.newText = loc ? styleAttribute(span.oldText, safe) : ` style="${mergeStyle("", safe)}"`;
|
|
78
|
+
return { text: text.slice(0, span.start) + span.newText + text.slice(span.start + span.oldText.length), span };
|
|
79
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { TweakDef } from "../../../shared/design-tweaks.ts";
|
|
2
|
+
import { DesignError } from "../design-error.ts";
|
|
3
|
+
import { appendRootBlock, replaceValue, scanRootVars, type CssRootScan } from "./css-root-vars-patch.ts";
|
|
4
|
+
import { headEndOffset } from "./html-style-blocks.ts";
|
|
5
|
+
import type { StyleSource } from "./design-style-sources.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Decides, per tweak, which bytes of which file change — pure, so every cascade case is
|
|
9
|
+
* testable without a disk.
|
|
10
|
+
*
|
|
11
|
+
* The declaration to patch is the one that wins on screen: the **last** declaration of the
|
|
12
|
+
* variable across the page's style sources in cascade order. When that last one is:
|
|
13
|
+
* - in an exclusive top-level `:root`/`html` rule of a design file → its value is replaced;
|
|
14
|
+
* - in a rule shared with other selectors (`:root, .dark`) → a new `:root` block is appended
|
|
15
|
+
* after it, so only the root changes;
|
|
16
|
+
* - absent → a new `:root` block is appended at the end of the tweak's `file` or else of
|
|
17
|
+
* the last design stylesheet, never prepended (an earlier block would lose the cascade);
|
|
18
|
+
* a page with no stylesheet of its own gets a `<style>` at the end of `<head>`;
|
|
19
|
+
* - inside an at-rule or a media-limited sheet, outside the design folder (the shared
|
|
20
|
+
* `tokens.css`), or anywhere `!important` → refused with an explanation, because any write
|
|
21
|
+
* the server could make would either not show or restyle every design in the project.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export interface PlannedTweak {
|
|
25
|
+
def: TweakDef;
|
|
26
|
+
/** Already validated against `def`. */
|
|
27
|
+
value: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const refuse = (message: string): DesignError => new DesignError(422, "ETWEAKTARGET", message);
|
|
31
|
+
const eolOf = (text: string): string => (text.includes("\r\n") ? "\r\n" : "\n");
|
|
32
|
+
|
|
33
|
+
interface Found {
|
|
34
|
+
index: number;
|
|
35
|
+
start: number;
|
|
36
|
+
end: number;
|
|
37
|
+
conditional: boolean;
|
|
38
|
+
atRule: string | null;
|
|
39
|
+
exclusive: boolean;
|
|
40
|
+
important: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** New text of every file that changes. `texts` holds each source file's current text. */
|
|
44
|
+
export function planTweakPatches(
|
|
45
|
+
entry: string,
|
|
46
|
+
sources: readonly StyleSource[],
|
|
47
|
+
texts: ReadonlyMap<string, string>,
|
|
48
|
+
tweaks: readonly PlannedTweak[],
|
|
49
|
+
): Map<string, string> {
|
|
50
|
+
const textOf = (file: string): string => {
|
|
51
|
+
const t = texts.get(file);
|
|
52
|
+
if (t === undefined) throw new Error(`no text for style source ${file}`);
|
|
53
|
+
return t;
|
|
54
|
+
};
|
|
55
|
+
const scans = sources.map((s): CssRootScan => scanRootVars(textOf(s.file).slice(s.start, s.end)));
|
|
56
|
+
const writable = (i: number): boolean => !sources[i]!.outside && !sources[i]!.conditional && scans[i]!.endsClean;
|
|
57
|
+
|
|
58
|
+
const replacements = new Map<string, { file: string; start: number; end: number; value: string }>();
|
|
59
|
+
const appends = new Map<number, Array<[string, string]>>();
|
|
60
|
+
const newBlock: Array<[string, string]> = [];
|
|
61
|
+
|
|
62
|
+
for (const { def, value } of tweaks) {
|
|
63
|
+
const found: Found[] = [];
|
|
64
|
+
sources.forEach((s, index) => {
|
|
65
|
+
for (const d of scans[index]!.declarations) {
|
|
66
|
+
if (d.var !== def.var) continue;
|
|
67
|
+
found.push({
|
|
68
|
+
index, start: s.start + d.valueStart, end: s.start + d.valueEnd, conditional: d.conditional || s.conditional,
|
|
69
|
+
atRule: d.atRule, exclusive: d.exclusive, important: d.important,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const important = found.find((f) => f.important);
|
|
74
|
+
if (important) {
|
|
75
|
+
throw refuse(`${def.var} is marked !important in ${sources[important.index]!.file}, so a tweak cannot take its place. Ask the AI to drop the !important.`);
|
|
76
|
+
}
|
|
77
|
+
const last = found[found.length - 1];
|
|
78
|
+
const lastFile = last ? sources[last.index]!.file : "";
|
|
79
|
+
if (last && sources[last.index]!.outside) {
|
|
80
|
+
throw refuse(`${def.var} is set last in ${lastFile}, which every design in the project shares. Ask the AI to declare it in this design's own :root instead.`);
|
|
81
|
+
}
|
|
82
|
+
if (last?.conditional) {
|
|
83
|
+
const where = last.atRule ? `an ${last.atRule} block` : "a stylesheet limited by its media attribute";
|
|
84
|
+
throw refuse(`${def.var} is set last inside ${where} in ${lastFile}, so a new value would only apply some of the time. Ask the AI to move it into an unconditional :root block.`);
|
|
85
|
+
}
|
|
86
|
+
if (last?.exclusive) {
|
|
87
|
+
replacements.set(`${lastFile}:${last.start}`, { file: lastFile, start: last.start, end: last.end, value });
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
// Append. After a shared-selector declaration, the block must come at or after its source.
|
|
91
|
+
const from = last ? last.index : 0;
|
|
92
|
+
const candidates = sources.map((_, i) => i).filter((i) => i >= from && writable(i));
|
|
93
|
+
const preferred = def.file ? candidates.filter((i) => sources[i]!.file === def.file).pop() : undefined;
|
|
94
|
+
const target = preferred ?? candidates.pop();
|
|
95
|
+
if (target !== undefined) {
|
|
96
|
+
appends.set(target, [...(appends.get(target) ?? []), [def.var, value]]);
|
|
97
|
+
} else if (last) {
|
|
98
|
+
throw refuse(`${lastFile} does not end cleanly (an unclosed comment, string or rule), so a :root block for ${def.var} cannot be added after it safely.`);
|
|
99
|
+
} else {
|
|
100
|
+
newBlock.push([def.var, value]);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// One edit per source region: its in-place replacements first, then its appended block.
|
|
105
|
+
type Edit = { start: number; end: number; text: string };
|
|
106
|
+
const edits = new Map<string, Edit[]>();
|
|
107
|
+
const addEdit = (file: string, edit: Edit) => edits.set(file, [...(edits.get(file) ?? []), edit]);
|
|
108
|
+
const regions = new Set<number>([...appends.keys()]);
|
|
109
|
+
for (const r of replacements.values()) {
|
|
110
|
+
const i = sources.findIndex((s) => s.file === r.file && s.start <= r.start && r.end <= s.end);
|
|
111
|
+
if (i >= 0) regions.add(i);
|
|
112
|
+
}
|
|
113
|
+
const seen = new Set<string>();
|
|
114
|
+
for (const i of [...regions].sort((a, b) => a - b)) {
|
|
115
|
+
const s = sources[i]!;
|
|
116
|
+
const key = `${s.file}:${s.start}`;
|
|
117
|
+
if (seen.has(key)) continue;
|
|
118
|
+
seen.add(key);
|
|
119
|
+
let css = textOf(s.file).slice(s.start, s.end);
|
|
120
|
+
const inside = [...replacements.values()]
|
|
121
|
+
.filter((r) => r.file === s.file && s.start <= r.start && r.end <= s.end)
|
|
122
|
+
.sort((a, b) => b.start - a.start);
|
|
123
|
+
for (const r of inside) css = replaceValue(css, { valueStart: r.start - s.start, valueEnd: r.end - s.start }, r.value);
|
|
124
|
+
const extra = sources.flatMap((o, j) => (`${o.file}:${o.start}` === key ? appends.get(j) ?? [] : []));
|
|
125
|
+
const next = appendRootBlock(css, extra);
|
|
126
|
+
if (next === null) throw refuse(`${s.file} does not end cleanly, so a :root block cannot be added to it safely.`);
|
|
127
|
+
addEdit(s.file, { start: s.start, end: s.end, text: next });
|
|
128
|
+
}
|
|
129
|
+
if (newBlock.length > 0) {
|
|
130
|
+
const html = textOf(entry);
|
|
131
|
+
const eol = eolOf(html);
|
|
132
|
+
const block = appendRootBlock("", newBlock)!.replace(/\n/g, eol);
|
|
133
|
+
addEdit(entry, { start: headEndOffset(html), end: headEndOffset(html), text: `<style>${eol}${block}</style>${eol}` });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const out = new Map<string, string>();
|
|
137
|
+
for (const [file, list] of edits) {
|
|
138
|
+
let text = textOf(file);
|
|
139
|
+
for (const e of [...list].sort((a, b) => b.start - a.start)) text = text.slice(0, e.start) + e.text + text.slice(e.end);
|
|
140
|
+
if (text !== textOf(file)) out.set(file, text);
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|