@jxsuite/studio 6.1.0 → 6.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/2020-f2gkpy8d.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-4912g339.js +4 -0
- package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
- package/dist/chunks/cf-settings-br6105tr.js +4 -0
- package/dist/chunks/color-28ksk2qm.js +4 -0
- package/dist/chunks/color-area-0fj8a4ga.js +4 -0
- package/dist/chunks/color-field-xch8kx2g.js +4 -0
- package/dist/chunks/color-slider-jxd8v350.js +4 -0
- package/dist/chunks/combobox-p0efwjke.js +4 -0
- package/dist/chunks/components-db68vsn7.js +4 -0
- package/dist/chunks/content-source-1449qesq.js +4 -0
- package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-x9jn86a7.js +4 -0
- package/dist/chunks/entry-commands-may24cpt.js +4 -0
- package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
- package/dist/chunks/file-ops-x9v54pcj.js +4 -0
- package/dist/chunks/files-j3knqf0s.js +4 -0
- package/dist/chunks/format-host-tyre2trb.js +4 -0
- package/dist/chunks/fs-events-64ma9htc.js +4 -0
- package/dist/chunks/git-panel-84ps5dex.js +4 -0
- package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
- package/dist/chunks/icons-pnfz478q.js +4 -0
- package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
- package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
- package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
- package/dist/chunks/iframe-entry-zap785cw.js +5 -0
- package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
- package/dist/chunks/index-b8xw3vy9.js +4 -0
- package/dist/chunks/{index-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
- package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
- package/dist/chunks/layers-h4xp1pss.js +4 -0
- package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
- package/dist/chunks/listbox-e74qjyq6.js +4 -0
- package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
- package/dist/chunks/media-picker-2cweexc5.js +4 -0
- package/dist/chunks/menu-n6yzswmy.js +4 -0
- package/dist/chunks/menu-ynw13y0s.js +4 -0
- package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
- package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
- package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
- package/dist/chunks/notify-cj5zbrs2.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-b7ddhr8m.js +4 -0
- package/dist/chunks/platform-3dfws9js.js +4 -0
- package/dist/chunks/popover-jt2gxmzs.js +4 -0
- package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
- package/dist/chunks/quick-search-0dajrwqg.js +4 -0
- package/dist/chunks/references-49qgt404.js +4 -0
- package/dist/chunks/right-panel-jm1bwe53.js +4 -0
- package/dist/chunks/section-registry-6kwc4fky.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/split-n2gfpm5m.js +4 -0
- package/dist/chunks/{studio-5g0ag7c0.js → studio-0q988f9w.js} +3 -3
- package/dist/chunks/studio-0rt52vpq.js +5 -0
- package/dist/chunks/studio-18vgbhs5.js +5 -0
- package/dist/chunks/{studio-pxg4ap1e.js → studio-1fxkaaea.js} +4 -4
- package/dist/chunks/studio-24mccdrj.js +5 -0
- package/dist/chunks/studio-2eh507zk.js +9 -0
- package/dist/chunks/studio-2hcbccfv.js +5 -0
- package/dist/chunks/studio-2j1cb95x.js +5 -0
- package/dist/chunks/studio-2jbs3rxv.js +5 -0
- package/dist/chunks/{studio-qbj760tx.js → studio-485046te.js} +7 -7
- package/dist/chunks/studio-4h8k4dw9.js +5 -0
- package/dist/chunks/studio-5f6n18kx.js +5 -0
- package/dist/chunks/studio-5gthpky6.js +5 -0
- package/dist/chunks/studio-5ve6bbep.js +5 -0
- package/dist/chunks/studio-6ep3js6b.js +9 -0
- package/dist/chunks/studio-6wkmf3wz.js +9 -0
- package/dist/chunks/studio-841rf3cg.js +5 -0
- package/dist/chunks/studio-8gmwgheg.js +5 -0
- package/dist/chunks/studio-8qm0ep50.js +5 -0
- package/dist/chunks/{studio-anyrgzvb.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-v2bvmbjj.js → studio-a3g98wjr.js} +4 -4
- package/dist/chunks/studio-a3shpz9y.js +5 -0
- package/dist/chunks/studio-amsbaaar.js +6 -0
- package/dist/chunks/studio-at5spjbc.js +7 -0
- package/dist/chunks/studio-b2xv945e.js +5 -0
- package/dist/chunks/studio-bn5nkafw.js +5 -0
- package/dist/chunks/studio-bw6q5xjf.js +9 -0
- package/dist/chunks/studio-c7q0t9x1.js +5 -0
- package/dist/chunks/studio-camnhc96.js +6 -0
- package/dist/chunks/studio-cffqvnzd.js +5 -0
- package/dist/chunks/studio-d81xfh1g.js +5 -0
- package/dist/chunks/studio-dgz8d0c1.js +5 -0
- package/dist/chunks/studio-efvfrsf8.js +5 -0
- package/dist/chunks/studio-er30bpcx.js +5 -0
- package/dist/chunks/studio-ezscgr64.js +5 -0
- package/dist/chunks/studio-ffrrncvz.js +5 -0
- package/dist/chunks/studio-fpphgn8y.js +10 -0
- package/dist/chunks/studio-j1kvhdjk.js +4 -0
- package/dist/chunks/{studio-txjjzrsm.js → studio-j430n16g.js} +5 -5
- package/dist/chunks/studio-jjkg84nj.js +5 -0
- package/dist/chunks/studio-m0q32ars.js +4 -0
- package/dist/chunks/studio-m6bdst11.js +5 -0
- package/dist/chunks/studio-nv2cptd4.js +64 -0
- package/dist/chunks/studio-nwfrc98n.js +5 -0
- package/dist/chunks/studio-p1wgvp7r.js +5 -0
- package/dist/chunks/studio-pag2wncm.js +5 -0
- package/dist/chunks/studio-qvanvzfd.js +5 -0
- package/dist/chunks/studio-qwa64kt7.js +5 -0
- package/dist/chunks/studio-rk1zc4x3.js +928 -0
- package/dist/chunks/studio-se2r3ptc.js +5 -0
- package/dist/chunks/studio-sg2a0dh0.js +5 -0
- package/dist/chunks/studio-tjzjhe68.js +5 -0
- package/dist/chunks/{studio-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-cpxkgjrj.js → studio-v0jzqdjm.js} +4 -4
- package/dist/chunks/studio-v2w7q8r1.js +7 -0
- package/dist/chunks/studio-v5vjq1h0.js +4 -0
- package/dist/chunks/studio-v8aga3vp.js +14 -0
- package/dist/chunks/studio-vfcdrfmv.js +5 -0
- package/dist/chunks/studio-vmfkgdjf.js +5 -0
- package/dist/chunks/studio-wt1816jj.js +5 -0
- package/dist/chunks/studio-wz73q5kq.js +4 -0
- package/dist/chunks/studio-y04qtxvp.js +7 -0
- package/dist/chunks/studio-y21g8zzg.js +5 -0
- package/dist/chunks/studio-y64hrt8p.js +12 -0
- package/dist/chunks/studio-ynn90f58.js +16 -0
- package/dist/chunks/studio-yxz682sx.js +5 -0
- package/dist/chunks/studio-zp7snvkq.js +5 -0
- package/dist/chunks/studio-zq4z6tm6.js +5 -0
- package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
- package/dist/chunks/tabs-f5cw3tgp.js +4 -0
- package/dist/chunks/textfield-wewc8rq2.js +4 -0
- package/dist/chunks/toast-c9fn075p.js +4 -0
- package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
- package/dist/chunks/tree-mdq3v5cw.js +4 -0
- package/dist/chunks/tsMode-sf49ee9x.js +14 -0
- package/dist/chunks/workspace-jtfahpee.js +4 -0
- package/dist/chunks/ws-client-nze0k6mv.js +4 -0
- package/dist/iframe-entry.js +16 -16
- package/dist/manifest.json +63 -63
- package/dist/studio.js +98 -98
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +11 -11
- package/src/about/about-modal.ts +4 -3
- package/src/account/action-flow.ts +45 -38
- package/src/account-status.ts +7 -2
- package/src/browse/library-layouts.ts +8 -5
- package/src/browse/library-model.ts +18 -6
- package/src/browse/library-pane.ts +37 -21
- package/src/browse/library-preview.ts +14 -9
- package/src/browse/library-source.ts +1 -1
- package/src/canvas/asset-refs.ts +24 -9
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +44 -53
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +66 -42
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +163 -64
- package/src/canvas/dialog-path.ts +9 -4
- package/src/canvas/dialog-state.ts +1 -2
- package/src/canvas/diff-marks.ts +9 -16
- package/src/canvas/diff-toolbar.ts +8 -7
- package/src/canvas/edit-width-drag.ts +4 -1
- package/src/canvas/edit-width.ts +1 -3
- package/src/canvas/iframe-channel.ts +27 -13
- package/src/canvas/iframe-drop.ts +13 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +80 -63
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +203 -118
- package/src/canvas/iframe-inline-edit.ts +69 -32
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +37 -26
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +18 -15
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +15 -16
- package/src/canvas/iframe-render.ts +41 -36
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +6 -2
- package/src/canvas/path-mapping.ts +19 -12
- package/src/canvas/popover-path.ts +7 -3
- package/src/canvas/popover-state.ts +1 -2
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +2 -1
- package/src/canvas/surface-registry.ts +21 -3
- package/src/collab/collab-commands.ts +7 -2
- package/src/collab/collab-session.ts +84 -45
- package/src/collab/collab-state.ts +4 -3
- package/src/collab/monaco-binding.ts +16 -13
- package/src/collab/monaco-cursors.ts +5 -2
- package/src/commands/budget.ts +3 -3
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +22 -20
- package/src/commands/defaults.ts +4 -1
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +10 -8
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +12 -10
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +5 -4
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +3 -2
- package/src/content/entry-editor.ts +29 -17
- package/src/content/entry-fields.ts +12 -7
- package/src/content/entry-model.ts +21 -12
- package/src/editor/canvas-context-menu.ts +1 -2
- package/src/editor/canvas-slash-bridge.ts +3 -6
- package/src/editor/content-slice.ts +16 -14
- package/src/editor/context-menu.ts +35 -22
- package/src/editor/convert-targets.ts +30 -35
- package/src/editor/convert-to-component.ts +11 -5
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +21 -22
- package/src/editor/inline-edit-apply.ts +35 -17
- package/src/editor/inline-edit.ts +66 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +87 -47
- package/src/editor/slash-menu.ts +1 -6
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +15 -10
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +77 -36
- package/src/files/files.ts +90 -95
- package/src/files/media-meta.ts +2 -1
- package/src/files/media-paths.ts +6 -1
- package/src/files/serialize-document.ts +2 -2
- package/src/format/constraints.ts +1 -1
- package/src/format/convert-file.ts +27 -13
- package/src/format/format-choices.ts +2 -1
- package/src/format/format-host.ts +76 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +19 -9
- package/src/github/github-publish.ts +24 -20
- package/src/grid/cell-editors.ts +46 -31
- package/src/grid/cell-popovers.ts +5 -3
- package/src/grid/edit-buffer.ts +10 -9
- package/src/grid/grid-controller.ts +20 -22
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -6
- package/src/grid/grid-panel.ts +11 -4
- package/src/grid/grid-source.ts +8 -8
- package/src/grid/grid-view.ts +14 -17
- package/src/grid/redirects-grid.ts +14 -5
- package/src/grid/redirects.ts +16 -14
- package/src/grid/schema-columns.ts +25 -19
- package/src/grid/sources/connector-source.ts +47 -20
- package/src/grid/sources/content-source.ts +25 -24
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +55 -34
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +1 -2
- package/src/media/media-pane.ts +4 -1
- package/src/new-project/add-repo-modal.ts +20 -19
- package/src/new-project/import-tab.ts +10 -14
- package/src/new-project/location-fields.ts +2 -1
- package/src/new-project/new-project-modal.ts +12 -9
- package/src/packages/jxsuite-update.ts +4 -3
- package/src/packages/pull-package-sync.ts +26 -25
- package/src/page-params.ts +97 -68
- package/src/panels/activity-panel.ts +17 -9
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-view.ts +80 -73
- package/src/panels/ai-chat/composer.ts +30 -33
- package/src/panels/ai-chat/sessions-view.ts +1 -2
- package/src/panels/ai-panel.ts +23 -20
- package/src/panels/block-action-bar.ts +46 -35
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +31 -24
- package/src/panels/data-explorer.ts +62 -25
- package/src/panels/data-grid.ts +14 -11
- package/src/panels/dnd.ts +108 -118
- package/src/panels/editors.ts +55 -22
- package/src/panels/elements-panel.ts +10 -3
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +76 -51
- package/src/panels/frontmatter-fields.ts +24 -19
- package/src/panels/frontmatter-panel.ts +44 -34
- package/src/panels/git-diff-open.ts +4 -4
- package/src/panels/git-panel.ts +49 -61
- package/src/panels/head-panel.ts +131 -111
- package/src/panels/i18n-panel.ts +10 -3
- package/src/panels/imports-panel.ts +23 -47
- package/src/panels/jump-bar.ts +48 -29
- package/src/panels/layers-panel.ts +97 -74
- package/src/panels/left-panel.ts +3 -3
- package/src/panels/pane-context.ts +31 -22
- package/src/panels/pane-grid.ts +49 -20
- package/src/panels/panel-registry.ts +22 -37
- package/src/panels/properties-panel.ts +175 -121
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +3 -3
- package/src/panels/seo-modal.ts +13 -17
- package/src/panels/settings-menu.ts +15 -15
- package/src/panels/signals-panel.ts +153 -131
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +254 -216
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +57 -54
- package/src/panels/stylebook-layers-panel.ts +9 -9
- package/src/panels/stylebook-panel.ts +13 -17
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +36 -26
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +58 -30
- package/src/platforms/cloud.ts +345 -175
- package/src/platforms/default-platform.ts +10 -4
- package/src/platforms/devserver.ts +174 -127
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +8 -2
- package/src/publish/pages-service.ts +28 -13
- package/src/publish/publish-commands.ts +5 -4
- package/src/publish/publish-panel.ts +10 -6
- package/src/recent-projects.ts +15 -8
- package/src/resize-edges.ts +26 -36
- package/src/services/a11y-report.ts +26 -19
- package/src/services/agent-seed.ts +23 -11
- package/src/services/ai-ask.ts +9 -12
- package/src/services/ai-command-tools.ts +68 -62
- package/src/services/ai-import-tools.ts +80 -67
- package/src/services/ai-models.ts +17 -13
- package/src/services/ai-project-tools.ts +68 -32
- package/src/services/ai-session-store.ts +19 -10
- package/src/services/ai-system-prompt.ts +46 -20
- package/src/services/ai-tools.ts +71 -27
- package/src/services/ai-write-report.ts +20 -12
- package/src/services/ai-writes.ts +4 -4
- package/src/services/automation.ts +58 -31
- package/src/services/cem-export.ts +149 -58
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/context-manager.ts +14 -10
- package/src/services/context-resolver.ts +20 -8
- package/src/services/data-service.ts +19 -15
- package/src/services/directory-picker.ts +18 -12
- package/src/services/document-assistant.ts +39 -19
- package/src/services/gated-registry.ts +10 -6
- package/src/services/harness/chat-reducer.ts +23 -1
- package/src/services/import-client.ts +91 -38
- package/src/services/import-seed.ts +8 -2
- package/src/services/jx-validate.ts +28 -31
- package/src/services/live-preview.ts +0 -0
- package/src/services/live-surfaces.ts +6 -3
- package/src/services/model-uri.ts +10 -2
- package/src/services/module-preloads.ts +12 -8
- package/src/services/monaco-buffer.ts +43 -24
- package/src/services/monaco-lazy.ts +7 -8
- package/src/services/monaco-setup.ts +23 -16
- package/src/services/notify.ts +44 -17
- package/src/services/popover-report.ts +25 -10
- package/src/services/preview-eval.ts +20 -8
- package/src/services/profile.ts +13 -6
- package/src/services/project-path.ts +13 -10
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +8 -7
- package/src/services/settings/kernel.ts +13 -4
- package/src/services/settings/write-queue.ts +9 -9
- package/src/services/token-lint.ts +12 -10
- package/src/services/tool-executor.ts +17 -5
- package/src/services/tool-outcomes.ts +44 -24
- package/src/services/trusted-types.ts +24 -7
- package/src/settings/contexts-section.ts +11 -8
- package/src/settings/contributed-section.ts +79 -60
- package/src/settings/css-vars-editor.ts +37 -16
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +23 -13
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +11 -8
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +9 -6
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +1 -1
- package/src/settings/schema-field-ui.ts +9 -0
- package/src/settings/settings-document.ts +5 -5
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +104 -81
- package/src/site-context.ts +37 -22
- package/src/state.ts +41 -49
- package/src/store.ts +54 -34
- package/src/studio.ts +39 -77
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +6 -7
- package/src/style/token-ref.ts +5 -4
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +31 -36
- package/src/surfaces/ai-credentials-form.ts +6 -16
- package/src/surfaces/ai-managed-connect.ts +3 -4
- package/src/surfaces/ai-model-picker.ts +3 -5
- package/src/surfaces/block-action-bar.ts +22 -11
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.ts +12 -11
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/commandbar.ts +14 -9
- package/src/surfaces/convert-repeater.ts +17 -19
- package/src/surfaces/data-actions.ts +9 -7
- package/src/surfaces/dialog.ts +26 -28
- package/src/surfaces/diff-toolbar.ts +9 -7
- package/src/surfaces/doc-header.ts +10 -19
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.ts +14 -11
- package/src/surfaces/expression-editor.ts +11 -25
- package/src/surfaces/files-panel.ts +27 -14
- package/src/surfaces/formula-palette.ts +4 -5
- package/src/surfaces/git-panel.ts +7 -15
- package/src/surfaces/github-auth.ts +16 -20
- package/src/surfaces/github-publish.ts +17 -22
- package/src/surfaces/grid-cell.ts +30 -31
- package/src/surfaces/grid-open.ts +10 -14
- package/src/surfaces/grid-panel.ts +13 -9
- package/src/surfaces/grid-replace.ts +13 -13
- package/src/surfaces/grid-views.ts +15 -18
- package/src/surfaces/inspector-dock.ts +13 -12
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.ts +25 -20
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.ts +11 -10
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/menu.ts +29 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.ts +20 -25
- package/src/surfaces/pane-grid.ts +15 -10
- package/src/surfaces/panel-activity.ts +5 -6
- package/src/surfaces/panel-data.ts +3 -4
- package/src/surfaces/panel-deploy-checklist.ts +5 -6
- package/src/surfaces/panel-elements.ts +5 -7
- package/src/surfaces/panel-i18n.ts +5 -7
- package/src/surfaces/panel-imports.ts +6 -13
- package/src/surfaces/panel-outline.ts +25 -19
- package/src/surfaces/panel-page.ts +11 -18
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.ts +20 -34
- package/src/surfaces/panel-stylebook-layers.ts +5 -8
- package/src/surfaces/preferences.ts +21 -11
- package/src/surfaces/progress-modal.ts +15 -9
- package/src/surfaces/properties-panel.json +1 -1
- package/src/surfaces/properties-panel.ts +20 -42
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +126 -73
- package/src/surfaces/rail.ts +38 -12
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.ts +15 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.ts +14 -10
- package/src/surfaces/settings-css-vars.ts +5 -12
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.ts +8 -15
- package/src/surfaces/settings-extensions.ts +5 -6
- package/src/surfaces/settings-head.ts +33 -39
- package/src/surfaces/settings-locales.ts +8 -20
- package/src/surfaces/settings-overview.ts +5 -6
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.ts +9 -18
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/slash-menu.ts +19 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +17 -14
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +5 -7
- package/src/tabs/patch-ops.ts +4 -3
- package/src/tabs/project-config.ts +32 -21
- package/src/tabs/selection.ts +36 -8
- package/src/tabs/tab.ts +52 -41
- package/src/tabs/transact.ts +98 -53
- package/src/tabs/typing.ts +31 -0
- package/src/types.ts +32 -17
- package/src/ui/ai-credentials-form.ts +10 -13
- package/src/ui/ai-model-picker.ts +3 -3
- package/src/ui/cf-account-picker.ts +7 -9
- package/src/ui/color-selector.ts +9 -5
- package/src/ui/dynamic-slot.ts +7 -8
- package/src/ui/expression-editor.ts +112 -105
- package/src/ui/form-controls.ts +57 -48
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +44 -31
- package/src/ui/media-picker.ts +18 -9
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +113 -70
- package/src/ui/surface.ts +71 -8
- package/src/ui/timing.ts +9 -0
- package/src/ui/value-source.ts +44 -31
- package/src/ui/virtual-window.ts +3 -2
- package/src/utils/base64.ts +3 -1
- package/src/utils/edit-display.ts +103 -74
- package/src/utils/element-selectors.ts +3 -2
- package/src/utils/google-fonts.ts +15 -14
- package/src/utils/inherited-style.ts +18 -20
- package/src/utils/link-target.ts +1 -1
- package/src/utils/preview-format.ts +25 -3
- package/src/utils/strip-events.ts +49 -22
- package/src/utils/studio-utils.ts +29 -14
- package/src/view.ts +2 -3
- package/src/workspace/pane-derive.ts +10 -12
- package/src/workspace/session.ts +53 -43
- package/src/workspace/workspace.ts +47 -36
- package/dist/chunks/2020-nkxms0ay.js +0 -4
- package/dist/chunks/adapter-m948ab5f.js +0 -4
- package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
- package/dist/chunks/cf-settings-356xdtne.js +0 -4
- package/dist/chunks/color-area-jqhna8zy.js +0 -4
- package/dist/chunks/color-field-embq5ctg.js +0 -4
- package/dist/chunks/color-fpezvnkt.js +0 -4
- package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
- package/dist/chunks/combobox-773hdzyj.js +0 -4
- package/dist/chunks/components-yk3t844e.js +0 -4
- package/dist/chunks/content-source-bawmyc09.js +0 -4
- package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-6sc8nacq.js +0 -4
- package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
- package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
- package/dist/chunks/file-ops-gye0qw56.js +0 -4
- package/dist/chunks/files-dmc2xvcq.js +0 -4
- package/dist/chunks/format-host-t76b53f8.js +0 -4
- package/dist/chunks/fs-events-cg4tpz06.js +0 -4
- package/dist/chunks/git-panel-yef7bshy.js +0 -4
- package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
- package/dist/chunks/icons-qbh8akb1.js +0 -4
- package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
- package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
- package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
- package/dist/chunks/iframe-host-tmz30gfp.js +0 -4
- package/dist/chunks/index-nag78a9h.js +0 -4
- package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
- package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
- package/dist/chunks/layers-fvz99859.js +0 -4
- package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-9agdspkt.js +0 -4
- package/dist/chunks/media-picker-rhjvyy00.js +0 -4
- package/dist/chunks/menu-2e4y9j7b.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
- package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
- package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
- package/dist/chunks/notify-h3www560.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-hz34wcd7.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
- package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
- package/dist/chunks/references-2cgdxnb8.js +0 -4
- package/dist/chunks/right-panel-jf856w5w.js +0 -4
- package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0f55h9ye.js +0 -5
- package/dist/chunks/studio-0sqdhnew.js +0 -12
- package/dist/chunks/studio-19x1c75w.js +0 -5
- package/dist/chunks/studio-2sqcndak.js +0 -5
- package/dist/chunks/studio-3aey7dd3.js +0 -5
- package/dist/chunks/studio-3bpdkq2s.js +0 -5
- package/dist/chunks/studio-47y6fbpf.js +0 -5
- package/dist/chunks/studio-4m3826v2.js +0 -5
- package/dist/chunks/studio-4nx2dj1g.js +0 -4
- package/dist/chunks/studio-4xv5s47r.js +0 -9
- package/dist/chunks/studio-5g4t8v6w.js +0 -5
- package/dist/chunks/studio-5py436sf.js +0 -5
- package/dist/chunks/studio-77kt594t.js +0 -5
- package/dist/chunks/studio-8f87n763.js +0 -10
- package/dist/chunks/studio-8mb00b84.js +0 -5
- package/dist/chunks/studio-8p51gq2h.js +0 -6
- package/dist/chunks/studio-954ds834.js +0 -5
- package/dist/chunks/studio-9ft45c83.js +0 -9
- package/dist/chunks/studio-a2138x5k.js +0 -7
- package/dist/chunks/studio-a9yzstqj.js +0 -5
- package/dist/chunks/studio-acdksxx6.js +0 -5
- package/dist/chunks/studio-ar8jcf2y.js +0 -5
- package/dist/chunks/studio-bmn4mn9j.js +0 -7
- package/dist/chunks/studio-e7xxa0sj.js +0 -5
- package/dist/chunks/studio-ecaz25vk.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-fzdywr6p.js +0 -9
- package/dist/chunks/studio-g5fmf0c1.js +0 -5
- package/dist/chunks/studio-g7nse7zb.js +0 -5
- package/dist/chunks/studio-geq1ea6k.js +0 -14
- package/dist/chunks/studio-ghkb32r8.js +0 -5
- package/dist/chunks/studio-ghrhy2y7.js +0 -5
- package/dist/chunks/studio-grawhey1.js +0 -5
- package/dist/chunks/studio-h0xgswew.js +0 -5
- package/dist/chunks/studio-h9c4p2tx.js +0 -5
- package/dist/chunks/studio-jyzj5cxs.js +0 -5
- package/dist/chunks/studio-mgx8yhnz.js +0 -64
- package/dist/chunks/studio-mpb04y1d.js +0 -6
- package/dist/chunks/studio-n17mty64.js +0 -5
- package/dist/chunks/studio-nwh2eqsk.js +0 -6
- package/dist/chunks/studio-q1h883bt.js +0 -16
- package/dist/chunks/studio-q4tv82h7.js +0 -9
- package/dist/chunks/studio-qpqa7vk3.js +0 -5
- package/dist/chunks/studio-qqz8e5gk.js +0 -5
- package/dist/chunks/studio-qvasen3f.js +0 -5
- package/dist/chunks/studio-rggdb3hm.js +0 -5
- package/dist/chunks/studio-sghy936h.js +0 -4
- package/dist/chunks/studio-skprc6ef.js +0 -5
- package/dist/chunks/studio-tt2nactf.js +0 -5
- package/dist/chunks/studio-tyasmc39.js +0 -5
- package/dist/chunks/studio-vk9ezads.js +0 -5
- package/dist/chunks/studio-vzacdfsc.js +0 -4
- package/dist/chunks/studio-w4c0xmrw.js +0 -5
- package/dist/chunks/studio-wfjqhhbk.js +0 -5
- package/dist/chunks/studio-wgh5kxpj.js +0 -5
- package/dist/chunks/studio-xasj0796.js +0 -5
- package/dist/chunks/studio-y78s8r2n.js +0 -5
- package/dist/chunks/studio-z8w183sh.js +0 -5
- package/dist/chunks/studio-zscd9ty4.js +0 -928
- package/dist/chunks/studio-zxp13sss.js +0 -7
- package/dist/chunks/studio-zygnmm01.js +0 -5
- package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
- package/dist/chunks/tabs-jwthg40w.js +0 -4
- package/dist/chunks/textfield-spy3hc77.js +0 -4
- package/dist/chunks/toast-4d35zd64.js +0 -4
- package/dist/chunks/toast-host-8sjmfed3.js +0 -4
- package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
- package/dist/chunks/tree-h19v1jfz.js +0 -4
- package/dist/chunks/tsMode-gr0m4dzr.js +0 -14
- package/dist/chunks/workspace-m15qtcqp.js +0 -4
- package/dist/chunks/ws-client-nf61frr1.js +0 -4
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
42
42
|
import { layerHost } from "../ui/layers";
|
|
43
43
|
import { enumArg, enumProperty } from "../commands/command-args";
|
|
44
|
+
import type { CommandArgValues } from "../commands/command-args";
|
|
44
45
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
45
46
|
import { getPlatform } from "../platform";
|
|
46
47
|
import { installUrlOf } from "../platform-errors";
|
|
@@ -118,9 +119,9 @@ let _nameError = "";
|
|
|
118
119
|
/** GitHub-App install link carried by a structured needs_installation_access failure. */
|
|
119
120
|
let _errorInstallUrl = "";
|
|
120
121
|
|
|
121
|
-
function captureError(
|
|
122
|
-
_error = errorMessage(
|
|
123
|
-
_errorInstallUrl = installUrlOf(
|
|
122
|
+
function captureError(cause: unknown) {
|
|
123
|
+
_error = errorMessage(cause);
|
|
124
|
+
_errorInstallUrl = installUrlOf(cause) ?? "";
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
let _creating = false;
|
|
@@ -244,6 +245,8 @@ export function openNewProjectModal(options?: { tab?: NewProjectTab }): Promise<
|
|
|
244
245
|
if (_creating) {
|
|
245
246
|
return;
|
|
246
247
|
}
|
|
248
|
+
/* SAFETY: `value` is the selected `jx-tab`'s value, and the strip renders one tab per
|
|
249
|
+
`viewOf().tabs` entry, whose values are "starter", "import" and "agent". */
|
|
247
250
|
_tab = value as NewProjectTab;
|
|
248
251
|
_error = "";
|
|
249
252
|
redraw();
|
|
@@ -348,10 +351,10 @@ async function finishCreated(result: { root: string; config: ProjectConfig }) {
|
|
|
348
351
|
getTab: () => null,
|
|
349
352
|
});
|
|
350
353
|
if (!adopted && !openedElsewhere) {
|
|
351
|
-
notify.warn(
|
|
352
|
-
|
|
353
|
-
source: "New Project",
|
|
354
|
-
|
|
354
|
+
notify.warn(
|
|
355
|
+
"Created the project, but could not open it here.",
|
|
356
|
+
error === null ? { source: "New Project" } : { detail: error, source: "New Project" },
|
|
357
|
+
);
|
|
355
358
|
}
|
|
356
359
|
finish(result);
|
|
357
360
|
}
|
|
@@ -708,9 +711,9 @@ export function newProjectCommands(): AnyCommand[] {
|
|
|
708
711
|
group: "1_file",
|
|
709
712
|
/* No `aiTool`: application-level, refused at registration; it opens the wizard, and the
|
|
710
713
|
model's own door is `create_project` / `import_site` (studio-ui-guidelines.md §12.4). */
|
|
711
|
-
run: (_commandCtx, args) => {
|
|
714
|
+
run: (_commandCtx, args: CommandArgValues) => {
|
|
712
715
|
const tab =
|
|
713
|
-
|
|
716
|
+
args.tab === undefined
|
|
714
717
|
? undefined
|
|
715
718
|
: enumArg("project.new", args, "tab", NEW_PROJECT_TABS);
|
|
716
719
|
void openNewProjectModal(tab === undefined ? {} : { tab });
|
|
@@ -29,9 +29,10 @@ import { openJxsuiteUpdateSurface } from "../surfaces/jxsuite-update";
|
|
|
29
29
|
import { showProgressModal } from "../ui/progress-modal";
|
|
30
30
|
import { notify } from "../services/notify";
|
|
31
31
|
import { isUpgrade } from "./semver";
|
|
32
|
-
import type {
|
|
32
|
+
import type { DialogLayerHandle } from "../ui/surface";
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
/** The npm scope every first-party package is published under. */
|
|
35
|
+
export const JXSUITE_PREFIX = "@jxsuite/";
|
|
35
36
|
|
|
36
37
|
export interface JxsuiteUpdate {
|
|
37
38
|
name: string;
|
|
@@ -170,7 +171,7 @@ function askToUpdate(outdated: JxsuiteUpdate[]): Promise<boolean> {
|
|
|
170
171
|
closing = true;
|
|
171
172
|
handle.close();
|
|
172
173
|
};
|
|
173
|
-
const handle:
|
|
174
|
+
const handle: DialogLayerHandle = openJxsuiteUpdateSurface({
|
|
174
175
|
layer: layerHost("dialog"),
|
|
175
176
|
onCancel: () => {
|
|
176
177
|
takeDown();
|
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
13
|
+
import { isJsonObject } from "@jxsuite/schema/guards";
|
|
14
|
+
import type { JsonObject, JsonValue } from "@jxsuite/schema/types";
|
|
13
15
|
import { getPlatform } from "../platform";
|
|
14
16
|
import { showConfirmDialog } from "../ui/layers";
|
|
15
17
|
import { showProgressModal } from "../ui/progress-modal";
|
|
16
18
|
import { notify } from "../services/notify";
|
|
17
|
-
import { applyJxsuiteUpdate, checkJxsuiteUpdate } from "./jxsuite-update";
|
|
19
|
+
import { JXSUITE_PREFIX, applyJxsuiteUpdate, checkJxsuiteUpdate } from "./jxsuite-update";
|
|
18
20
|
import type { GitStatusResult } from "../types";
|
|
19
21
|
|
|
20
22
|
const PKG_PATHS = ["package.json", "bun.lock", "bun.lockb"];
|
|
@@ -29,20 +31,16 @@ const UNTRACKED_STATUSES = new Set(["??", "U"]);
|
|
|
29
31
|
/** Above this many dirty files, skip the per-file upstream comparison and leave the error as-is. */
|
|
30
32
|
const MAX_CONFLICT_SCAN = 25;
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
35
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function sortKeys(value: unknown): unknown {
|
|
34
|
+
/** A copy of a JSON value with every object's keys in sorted order, so equal data prints equal. */
|
|
35
|
+
function sortKeys(value: JsonValue): JsonValue {
|
|
39
36
|
if (Array.isArray(value)) {
|
|
40
37
|
return value.map((entry) => sortKeys(entry));
|
|
41
38
|
}
|
|
42
|
-
if (
|
|
43
|
-
const out:
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
if (isJsonObject(value)) {
|
|
40
|
+
const out: JsonObject = {};
|
|
41
|
+
// Keys are unique, so the comparator never sees a tie; `<` is the default sort's code-unit order.
|
|
42
|
+
for (const [key, entry] of Object.entries(value).toSorted(([a], [b]) => (a < b ? -1 : 1))) {
|
|
43
|
+
out[key] = sortKeys(entry);
|
|
46
44
|
}
|
|
47
45
|
return out;
|
|
48
46
|
}
|
|
@@ -50,11 +48,11 @@ function sortKeys(value: unknown): unknown {
|
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
/** Replace every @jxsuite/* version in dependencies/devDependencies so they compare equal. */
|
|
53
|
-
function maskJxsuiteVersions(pkg:
|
|
51
|
+
function maskJxsuiteVersions(pkg: JsonObject): JsonObject {
|
|
54
52
|
const out = { ...pkg };
|
|
55
53
|
for (const section of ["dependencies", "devDependencies"]) {
|
|
56
54
|
const deps = out[section];
|
|
57
|
-
if (!
|
|
55
|
+
if (!isJsonObject(deps)) {
|
|
58
56
|
continue;
|
|
59
57
|
}
|
|
60
58
|
const masked = { ...deps };
|
|
@@ -88,7 +86,7 @@ export function isAutomatedPackageDiff(
|
|
|
88
86
|
} catch {
|
|
89
87
|
return false;
|
|
90
88
|
}
|
|
91
|
-
if (!
|
|
89
|
+
if (!isJsonObject(head) || !isJsonObject(working)) {
|
|
92
90
|
return false;
|
|
93
91
|
}
|
|
94
92
|
return (
|
|
@@ -251,20 +249,20 @@ async function discardPullAndSync(plan: PackagePullPlan): Promise<void> {
|
|
|
251
249
|
await syncPackagesAfterPull();
|
|
252
250
|
}
|
|
253
251
|
|
|
254
|
-
async function recoverAfterFailedPull(
|
|
252
|
+
async function recoverAfterFailedPull(cause: unknown): Promise<void> {
|
|
255
253
|
const platform = getPlatform();
|
|
256
254
|
let status: GitStatusResult;
|
|
257
255
|
try {
|
|
258
256
|
status = await platform.gitStatus();
|
|
259
257
|
} catch {
|
|
260
|
-
throw
|
|
258
|
+
throw cause;
|
|
261
259
|
}
|
|
262
260
|
if (!(status.behind > 0)) {
|
|
263
|
-
throw
|
|
261
|
+
throw cause;
|
|
264
262
|
}
|
|
265
263
|
const plan = await planPackageDiscard(status);
|
|
266
264
|
if (planIsEmpty(plan) || (await otherFilesConflict(status))) {
|
|
267
|
-
throw
|
|
265
|
+
throw cause;
|
|
268
266
|
}
|
|
269
267
|
if (!plan.automated) {
|
|
270
268
|
const confirmed = await showConfirmDialog(
|
|
@@ -273,7 +271,7 @@ async function recoverAfterFailedPull(original: unknown): Promise<void> {
|
|
|
273
271
|
{ confirmLabel: "Discard and pull", destructive: true },
|
|
274
272
|
);
|
|
275
273
|
if (!confirmed) {
|
|
276
|
-
throw
|
|
274
|
+
throw cause;
|
|
277
275
|
}
|
|
278
276
|
}
|
|
279
277
|
await discardPullAndSync(plan);
|
|
@@ -346,15 +344,18 @@ export async function pullWithPackageSync(): Promise<void> {
|
|
|
346
344
|
*/
|
|
347
345
|
export async function autoSyncProjectOnOpen(): Promise<void> {
|
|
348
346
|
const platform = getPlatform();
|
|
349
|
-
let status: GitStatusResult;
|
|
350
347
|
try {
|
|
351
|
-
status
|
|
348
|
+
/* The status is host wire data. A host may leave `remotes` out (as `deploy-checklist.ts` and
|
|
349
|
+
`git-panel.ts` also allow), which reads as "nothing to sync"; a host that sends no status at
|
|
350
|
+
all throws on the first read and is caught below the same way, so a malformed status never
|
|
351
|
+
aborts the project open that awaits this. */
|
|
352
|
+
const status = await platform.gitStatus();
|
|
353
|
+
if (!status.isRepo || !Array.isArray(status.remotes) || status.remotes.length === 0) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
352
356
|
} catch {
|
|
353
357
|
return;
|
|
354
358
|
}
|
|
355
|
-
if (!status?.isRepo || (status.remotes?.length ?? 0) === 0) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
359
|
notify.info("Syncing project…", { key: "project.sync", source: "Source Control" });
|
|
359
360
|
try {
|
|
360
361
|
await pullWithPackageSync();
|
package/src/page-params.ts
CHANGED
|
@@ -10,14 +10,28 @@
|
|
|
10
10
|
* produces for the matching built page.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { documentUrlPattern
|
|
13
|
+
import { documentUrlPattern } from "@jxsuite/site/routes";
|
|
14
14
|
import { getPlatform } from "./platform";
|
|
15
15
|
import { loadExtensions } from "./format/format-host";
|
|
16
|
-
import
|
|
16
|
+
import { isJsonObject, isRef, isString } from "@jxsuite/schema/guards";
|
|
17
|
+
import type {
|
|
18
|
+
JsonObject,
|
|
19
|
+
JsonValue,
|
|
20
|
+
JxDocumentValue,
|
|
21
|
+
JxMutableNode,
|
|
22
|
+
JxPathsDef,
|
|
23
|
+
JxStateDefinition,
|
|
24
|
+
} from "@jxsuite/schema/types";
|
|
17
25
|
|
|
18
26
|
/** Param name → candidate values, in `$paths` declaration order. */
|
|
19
27
|
export type ParamValues = Record<string, string[]>;
|
|
20
28
|
|
|
29
|
+
/** One entry of a resolved ContentCollection, as `/__jx_resolve__` serializes it to JSON. */
|
|
30
|
+
interface ResolvedContentEntry {
|
|
31
|
+
id?: JsonValue;
|
|
32
|
+
data?: JsonObject;
|
|
33
|
+
}
|
|
34
|
+
|
|
21
35
|
/**
|
|
22
36
|
* Route derivation is `@jxsuite/site/routes`, re-exported so this module stays the studio's one
|
|
23
37
|
* import for everything `$params`.
|
|
@@ -34,14 +48,21 @@ export { documentUrlPattern, dynamicRouteParams } from "@jxsuite/site/routes";
|
|
|
34
48
|
* The `$paths` declaration of an open document. JSON pages carry it on the document root;
|
|
35
49
|
* format-class pages (markdown) keep it in the frontmatter.
|
|
36
50
|
*
|
|
37
|
-
* @param {{
|
|
51
|
+
* @param {{
|
|
52
|
+
* document?: JxMutableNode | null;
|
|
53
|
+
* frontmatter?: Record<string, JxDocumentValue | undefined> | null;
|
|
54
|
+
* }} doc
|
|
38
55
|
* @returns {JxPathsDef | null}
|
|
39
56
|
*/
|
|
40
57
|
export function pagePathsDef(doc: {
|
|
41
58
|
document?: JxMutableNode | null;
|
|
42
|
-
frontmatter?: Record<string,
|
|
59
|
+
frontmatter?: Record<string, JxDocumentValue | undefined> | null;
|
|
43
60
|
}) {
|
|
44
|
-
const fromDoc =
|
|
61
|
+
const fromDoc = doc.document?.$paths;
|
|
62
|
+
/* SAFETY: frontmatter `$paths` is the format-page form of the root `$paths` block
|
|
63
|
+
(site-architecture.md §4.3). Its only consumer, loadParamValues, re-checks every JxPathsDef
|
|
64
|
+
shape (array, contentType, values, $ref) before reading it and turns any other value into an
|
|
65
|
+
empty result, so an off-shape block degrades to "no candidates" rather than a crash. */
|
|
45
66
|
const fromFrontmatter = doc.frontmatter?.$paths as JxPathsDef | undefined;
|
|
46
67
|
return fromDoc ?? fromFrontmatter ?? null;
|
|
47
68
|
}
|
|
@@ -67,15 +88,15 @@ export function loadParamValues(
|
|
|
67
88
|
pathsDef: JxPathsDef | null,
|
|
68
89
|
) {
|
|
69
90
|
if (!pathsDef) {
|
|
70
|
-
return Promise.resolve({}
|
|
91
|
+
return Promise.resolve<ParamValues>({});
|
|
71
92
|
}
|
|
72
93
|
const key = `${documentPath ?? ""}::${JSON.stringify(pathsDef)}`;
|
|
73
94
|
let pending = valueCache.get(key);
|
|
74
95
|
if (!pending) {
|
|
75
|
-
pending = resolveParamValues(pathsDef).catch((error:
|
|
96
|
+
pending = resolveParamValues(pathsDef).catch((error): ParamValues => {
|
|
76
97
|
valueCache.delete(key);
|
|
77
98
|
console.warn("page-params: failed to enumerate $paths values:", error);
|
|
78
|
-
return {}
|
|
99
|
+
return {};
|
|
79
100
|
});
|
|
80
101
|
valueCache.set(key, pending);
|
|
81
102
|
}
|
|
@@ -104,21 +125,19 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
|
|
|
104
125
|
// Discriminator member on JxPathsDef, so narrow to string. Resolved through the backend's
|
|
105
126
|
// ContentCollection pipeline (the same one the canvas's ContentEntry uses), so every offered
|
|
106
127
|
// Value is guaranteed to resolve in preview.
|
|
107
|
-
if (
|
|
108
|
-
"contentType" in pathsDef &&
|
|
109
|
-
typeof pathsDef.contentType === "string" &&
|
|
110
|
-
pathsDef.contentType
|
|
111
|
-
) {
|
|
128
|
+
if ("contentType" in pathsDef && isString(pathsDef.contentType) && pathsDef.contentType) {
|
|
112
129
|
const param = pathsDef.param ?? "slug";
|
|
113
130
|
const field = pathsDef.field ?? "id";
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}[];
|
|
118
|
-
const out: ParamValues = { [param]: [] };
|
|
119
|
-
if (!Array.isArray(entries)) {
|
|
131
|
+
const resolved = await resolveContentCollection(pathsDef.contentType);
|
|
132
|
+
const out = { [param]: [] } satisfies ParamValues;
|
|
133
|
+
if (!Array.isArray(resolved)) {
|
|
120
134
|
return out;
|
|
121
135
|
}
|
|
136
|
+
/* SAFETY: a resolved ContentCollection is its entries array, each `{ id, data }` (the parser's
|
|
137
|
+
ContentLoaderEntry after the JSON hop). Off-shape entries stay harmless: a primitive reads as
|
|
138
|
+
having no id and is skipped, and a null throws on `.id`, which loadParamValues catches and
|
|
139
|
+
degrades to an empty result. */
|
|
140
|
+
const entries = resolved as ResolvedContentEntry[];
|
|
122
141
|
for (const entry of entries) {
|
|
123
142
|
pushValue(out, param, field === "id" ? entry.id : (entry.data?.[field] ?? entry.id));
|
|
124
143
|
}
|
|
@@ -128,7 +147,7 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
|
|
|
128
147
|
// Explicit values: { values: ["en", "fr"], param: "lang" }
|
|
129
148
|
if ("values" in pathsDef && Array.isArray(pathsDef.values)) {
|
|
130
149
|
const param = pathsDef.param ?? "value";
|
|
131
|
-
const out
|
|
150
|
+
const out = { [param]: [] } satisfies ParamValues;
|
|
132
151
|
for (const value of pathsDef.values) {
|
|
133
152
|
pushValue(out, param, value);
|
|
134
153
|
}
|
|
@@ -137,17 +156,18 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
|
|
|
137
156
|
|
|
138
157
|
// Data file ref: { "$ref": "./data/products.json", param: "id", field: "sku" } — `$ref` also
|
|
139
158
|
// Reaches here as an open discriminator key, so narrow to a non-empty string.
|
|
140
|
-
if ("$ref" in pathsDef &&
|
|
159
|
+
if ("$ref" in pathsDef && isString(pathsDef.$ref) && pathsDef.$ref) {
|
|
141
160
|
const param = pathsDef.param ?? "id";
|
|
142
161
|
const field = pathsDef.field ?? "id";
|
|
143
162
|
const content = await getPlatform().readFile(pathsDef.$ref.replace(/^\.\//, ""));
|
|
144
|
-
|
|
145
|
-
const
|
|
163
|
+
// SAFETY: JSON.parse only ever produces JSON values.
|
|
164
|
+
const data = JSON.parse(content) as JsonValue;
|
|
165
|
+
const out = { [param]: [] } satisfies ParamValues;
|
|
146
166
|
if (!Array.isArray(data)) {
|
|
147
167
|
return out;
|
|
148
168
|
}
|
|
149
|
-
for (const item of data
|
|
150
|
-
pushValue(out, param, item
|
|
169
|
+
for (const item of data) {
|
|
170
|
+
pushValue(out, param, isJsonObject(item) ? (item[field] ?? item.id ?? item) : item);
|
|
151
171
|
}
|
|
152
172
|
return out;
|
|
153
173
|
}
|
|
@@ -179,9 +199,9 @@ async function contentCollectionSrc(): Promise<string> {
|
|
|
179
199
|
* fetch on platforms that predate `resolveClass`.
|
|
180
200
|
*
|
|
181
201
|
* @param {string} contentType
|
|
182
|
-
* @returns {Promise<
|
|
202
|
+
* @returns {Promise<JsonValue>}
|
|
183
203
|
*/
|
|
184
|
-
async function resolveContentCollection(contentType: string) {
|
|
204
|
+
async function resolveContentCollection(contentType: string): Promise<JsonValue> {
|
|
185
205
|
const body = {
|
|
186
206
|
$prototype: "ContentCollection",
|
|
187
207
|
$src: await contentCollectionSrc(),
|
|
@@ -189,26 +209,28 @@ async function resolveContentCollection(contentType: string) {
|
|
|
189
209
|
};
|
|
190
210
|
const platform = getPlatform();
|
|
191
211
|
if (platform.resolveClass) {
|
|
192
|
-
|
|
212
|
+
/* SAFETY: resolveClass hands back the backend's parsed `/__jx_resolve__` response, and that
|
|
213
|
+
endpoint answers with a JSON body, so the value is a JSON value. */
|
|
214
|
+
return platform.resolveClass(body) as Promise<JsonValue>;
|
|
193
215
|
}
|
|
194
216
|
return fetch("/__jx_resolve__", {
|
|
195
217
|
body: JSON.stringify(body),
|
|
196
218
|
headers: { "content-type": "application/json" },
|
|
197
219
|
method: "POST",
|
|
198
|
-
}).then((res) => {
|
|
220
|
+
}).then((res): Promise<JsonValue> => {
|
|
199
221
|
if (!res.ok) {
|
|
200
222
|
throw new Error(`Class resolution failed: ${res.status}`);
|
|
201
223
|
}
|
|
202
|
-
return res.json()
|
|
224
|
+
return res.json();
|
|
203
225
|
});
|
|
204
226
|
}
|
|
205
227
|
|
|
206
228
|
/**
|
|
207
229
|
* @param {ParamValues} out
|
|
208
230
|
* @param {string} param
|
|
209
|
-
* @param {
|
|
231
|
+
* @param {JsonValue | undefined} value
|
|
210
232
|
*/
|
|
211
|
-
function pushValue(out: ParamValues, param: string, value:
|
|
233
|
+
function pushValue(out: ParamValues, param: string, value: JsonValue | undefined) {
|
|
212
234
|
if (value === null || value === undefined || value === "") {
|
|
213
235
|
return;
|
|
214
236
|
}
|
|
@@ -245,15 +267,15 @@ export function substitutePreviewParams(
|
|
|
245
267
|
if (Object.keys(params).length === 0) {
|
|
246
268
|
return renderDoc;
|
|
247
269
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
270
|
+
/* SAFETY: a render document is a JSON tree (it reaches the canvas iframe by structured clone and
|
|
271
|
+
is serialized back to disk), so its root is a JSON object; substituteObjectRefs rebuilds it key
|
|
272
|
+
for key, replacing only `$params` ref values with strings, so the copy keeps the node's shape. */
|
|
273
|
+
const doc = substituteObjectRefs(renderDoc as JsonObject, params) as JxMutableNode;
|
|
252
274
|
doc.state ??= {};
|
|
253
275
|
doc.state.$page = {
|
|
254
276
|
params: { ...params },
|
|
255
|
-
title:
|
|
256
|
-
url:
|
|
277
|
+
title: isString(doc.title) ? doc.title : "",
|
|
278
|
+
url: documentUrlPattern(documentPath),
|
|
257
279
|
};
|
|
258
280
|
return doc;
|
|
259
281
|
}
|
|
@@ -263,21 +285,20 @@ export function substitutePreviewParams(
|
|
|
263
285
|
* These are the entries `substitutePreviewParams` rewrites, and the ones `resolveParamBoundState`
|
|
264
286
|
* bakes.
|
|
265
287
|
*
|
|
266
|
-
* @param {Record<string,
|
|
267
|
-
* `$ref`s intact — substitution removes the marker)
|
|
288
|
+
* @param {Record<string, JxStateDefinition> | null | undefined} state - The ORIGINAL document state
|
|
289
|
+
* (with `$ref`s intact — substitution removes the marker)
|
|
268
290
|
* @returns {string[]}
|
|
269
291
|
*/
|
|
270
|
-
export function paramBoundStateKeys(state: Record<string,
|
|
292
|
+
export function paramBoundStateKeys(state: Record<string, JxStateDefinition> | null | undefined) {
|
|
271
293
|
if (!state) {
|
|
272
294
|
return [];
|
|
273
295
|
}
|
|
274
296
|
return Object.keys(state).filter((key) => {
|
|
275
|
-
const entry = state[key]
|
|
297
|
+
const entry = state[key];
|
|
276
298
|
return (
|
|
277
|
-
entry &&
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
typeof entry.$src === "string" &&
|
|
299
|
+
isJsonObject(entry) &&
|
|
300
|
+
isString(entry.$prototype) &&
|
|
301
|
+
isString(entry.$src) &&
|
|
281
302
|
JSON.stringify(entry).includes('"#/$params/')
|
|
282
303
|
);
|
|
283
304
|
});
|
|
@@ -306,24 +327,30 @@ export async function resolveParamBoundState(
|
|
|
306
327
|
return;
|
|
307
328
|
}
|
|
308
329
|
const platform = getPlatform();
|
|
309
|
-
|
|
330
|
+
const { resolveClass } = platform;
|
|
331
|
+
if (!resolveClass) {
|
|
310
332
|
return;
|
|
311
333
|
}
|
|
312
|
-
const { state } = renderDoc
|
|
334
|
+
const { state } = renderDoc;
|
|
313
335
|
if (!state) {
|
|
314
336
|
return;
|
|
315
337
|
}
|
|
316
338
|
await Promise.all(
|
|
317
339
|
keys.map(async (key) => {
|
|
340
|
+
/* Keys come from paramBoundStateKeys, which only selects plain-object entries; substitution
|
|
341
|
+
keeps such an entry an object unless the whole entry was a param ref (then a string). */
|
|
318
342
|
const entry = state[key];
|
|
319
|
-
if (!entry
|
|
343
|
+
if (!isJsonObject(entry)) {
|
|
320
344
|
return;
|
|
321
345
|
}
|
|
346
|
+
const body = { ...entry };
|
|
347
|
+
if (docBase) {
|
|
348
|
+
body.$base = docBase;
|
|
349
|
+
}
|
|
322
350
|
try {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
});
|
|
351
|
+
/* SAFETY: the backend answers with the class's resolved JSON value (no `$prototype`), which
|
|
352
|
+
the runtime reads as a naked-value state entry, so it is a JxStateDefinition. */
|
|
353
|
+
state[key] = (await resolveClass.call(platform, body)) as JxStateDefinition;
|
|
327
354
|
} catch (error) {
|
|
328
355
|
console.warn(`page-params: failed to resolve state.${key} for preview:`, error);
|
|
329
356
|
}
|
|
@@ -332,22 +359,28 @@ export async function resolveParamBoundState(
|
|
|
332
359
|
}
|
|
333
360
|
|
|
334
361
|
/**
|
|
335
|
-
* @param {
|
|
362
|
+
* @param {JsonValue} node
|
|
336
363
|
* @param {Record<string, string>} params
|
|
337
|
-
* @returns {
|
|
364
|
+
* @returns {JsonValue} — a rebuilt copy with matched param refs replaced by literals
|
|
338
365
|
*/
|
|
339
|
-
function substituteParamRefs(node:
|
|
366
|
+
function substituteParamRefs(node: JsonValue, params: Record<string, string>): JsonValue {
|
|
340
367
|
const replaced = paramRefValue(node, params);
|
|
341
368
|
if (replaced !== null) {
|
|
342
369
|
return replaced;
|
|
343
370
|
}
|
|
344
|
-
if (!node || typeof node !== "object") {
|
|
345
|
-
return node;
|
|
346
|
-
}
|
|
347
371
|
if (Array.isArray(node)) {
|
|
348
372
|
return node.map((item) => substituteParamRefs(item, params));
|
|
349
373
|
}
|
|
350
|
-
|
|
374
|
+
return isJsonObject(node) ? substituteObjectRefs(node, params) : node;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @param {JsonObject} node
|
|
379
|
+
* @param {Record<string, string>} params
|
|
380
|
+
* @returns {JsonObject} — a rebuilt copy of every member, param refs replaced by literals
|
|
381
|
+
*/
|
|
382
|
+
function substituteObjectRefs(node: JsonObject, params: Record<string, string>): JsonObject {
|
|
383
|
+
const out: JsonObject = {};
|
|
351
384
|
for (const [key, value] of Object.entries(node)) {
|
|
352
385
|
out[key] = substituteParamRefs(value, params);
|
|
353
386
|
}
|
|
@@ -358,17 +391,13 @@ function substituteParamRefs(node: unknown, params: Record<string, string>): unk
|
|
|
358
391
|
* The chosen literal for a `{ "$ref": "#/$params/<name>" }` value, or null when the value is not a
|
|
359
392
|
* param ref (or no value was chosen for it).
|
|
360
393
|
*
|
|
361
|
-
* @param {
|
|
394
|
+
* @param {JsonValue} value
|
|
362
395
|
* @param {Record<string, string>} params
|
|
363
396
|
* @returns {string | null}
|
|
364
397
|
*/
|
|
365
|
-
function paramRefValue(value:
|
|
366
|
-
if (!value ||
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
const ref = (value as { $ref?: unknown }).$ref;
|
|
370
|
-
if (typeof ref !== "string" || !ref.startsWith("#/$params/")) {
|
|
398
|
+
function paramRefValue(value: JsonValue, params: Record<string, string>) {
|
|
399
|
+
if (!isRef(value) || !value.$ref.startsWith("#/$params/")) {
|
|
371
400
|
return null;
|
|
372
401
|
}
|
|
373
|
-
return params[ref.slice("#/$params/".length)] ?? null;
|
|
402
|
+
return params[value.$ref.slice("#/$params/".length)] ?? null;
|
|
374
403
|
}
|
|
@@ -42,6 +42,7 @@ import { disposeActivitySurface, mountActivitySurface } from "../surfaces/panel-
|
|
|
42
42
|
import { reactive } from "../reactivity";
|
|
43
43
|
import { now } from "../services/clock";
|
|
44
44
|
import { notify } from "../services/notify";
|
|
45
|
+
import type { NotifyOptions } from "../services/notify";
|
|
45
46
|
import { registerPanel } from "./panel-registry";
|
|
46
47
|
import type { PanelBody } from "./panel-registry";
|
|
47
48
|
import type {
|
|
@@ -189,7 +190,7 @@ export interface ActivityHandle {
|
|
|
189
190
|
* @returns {ActivityHandle}
|
|
190
191
|
*/
|
|
191
192
|
export function beginActivity(options: ActivityOptions): ActivityHandle {
|
|
192
|
-
const
|
|
193
|
+
const fields = {
|
|
193
194
|
cancellable: options.cancel !== undefined,
|
|
194
195
|
endedAt: null,
|
|
195
196
|
expanded: false,
|
|
@@ -200,8 +201,9 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
|
|
|
200
201
|
status: options.status ?? "",
|
|
201
202
|
steps: (options.steps ?? []).map((label) => ({ label, state: "pending" as const })),
|
|
202
203
|
title: options.title,
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
} satisfies ActivityEntry;
|
|
205
|
+
const entry: ActivityEntry =
|
|
206
|
+
options.source === undefined ? fields : { ...fields, source: options.source };
|
|
205
207
|
if (options.cancel) {
|
|
206
208
|
_cancels.set(entry.id, options.cancel);
|
|
207
209
|
}
|
|
@@ -209,6 +211,7 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
|
|
|
209
211
|
// The PROXY, not the literal: writing through the raw object a `reactive()` array was handed
|
|
210
212
|
// Skips every effect depending on it, which is the one bug that would make a running operation
|
|
211
213
|
// Look frozen. Read back before anything is retired, so the reference is unambiguous.
|
|
214
|
+
// SAFETY: `activities.push(entry)` just above guarantees the array has a last element.
|
|
212
215
|
const live = activities.at(-1) as ActivityEntry;
|
|
213
216
|
retireOldest();
|
|
214
217
|
|
|
@@ -243,12 +246,17 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
|
|
|
243
246
|
}
|
|
244
247
|
const detail = live.log.join("\n");
|
|
245
248
|
finish("failed", message);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
const notice: NotifyOptions = { source: live.source ?? live.title };
|
|
250
|
+
if (detail !== "") {
|
|
251
|
+
notice.detail = detail;
|
|
252
|
+
}
|
|
253
|
+
if (opts.action !== undefined) {
|
|
254
|
+
notice.action = opts.action;
|
|
255
|
+
}
|
|
256
|
+
if (opts.path !== undefined) {
|
|
257
|
+
notice.path = opts.path;
|
|
258
|
+
}
|
|
259
|
+
notify.error(message, notice);
|
|
252
260
|
},
|
|
253
261
|
id: live.id,
|
|
254
262
|
log(chunk: string) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Attached-context.js — the composer's "attach context" message-content convention.
|
|
3
3
|
*
|
|
4
|
-
* Attached context (current page, selected element) is embedded into the user message
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Attached context (current page, selected element) is embedded into the user message content after
|
|
5
|
+
* a delimiter line: it's the only channel the LLM sees (the streaming payload carries message
|
|
6
|
+
* content only) and it persists with the session for free. The chat view splits the content back
|
|
7
|
+
* apart to show chips instead of the raw block.
|
|
8
8
|
*
|
|
9
|
-
* The delimiter is a soft convention — a model echoing it would at worst render stray
|
|
10
|
-
*
|
|
9
|
+
* The delimiter is a soft convention — a model echoing it would at worst render stray chips (no
|
|
10
|
+
* security impact; assistant markdown is sanitized separately).
|
|
11
11
|
*
|
|
12
12
|
* @license MIT
|
|
13
13
|
*/
|
|
@@ -36,8 +36,14 @@ export function buildMessageWithContext(text: string, chips: ContextChip[]): str
|
|
|
36
36
|
return `${text}\n\n${ATTACHED_CONTEXT_DELIMITER}\n${lines}`;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/** A user message split into its typed body and its attached-context lines. */
|
|
40
|
+
export interface SplitMessage {
|
|
41
|
+
body: string;
|
|
42
|
+
contextLines: string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
/** Split a user message back into its typed body and any attached-context lines. */
|
|
40
|
-
export function splitAttachedContext(content: string):
|
|
46
|
+
export function splitAttachedContext(content: string): SplitMessage {
|
|
41
47
|
const idx = content.indexOf(`\n\n${ATTACHED_CONTEXT_DELIMITER}\n`);
|
|
42
48
|
if (idx === -1) {
|
|
43
49
|
return { body: content, contextLines: [] };
|