@jxsuite/studio 6.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-5tphg7xe.js +4 -0
- package/dist/chunks/add-new-flow-psym14sn.js +4 -0
- package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
- package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
- package/dist/chunks/color-area-6rbra5dy.js +4 -0
- package/dist/chunks/color-field-gy56c94g.js +4 -0
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
- package/dist/chunks/combobox-72h32ejk.js +4 -0
- package/dist/chunks/components-r22xca09.js +4 -0
- package/dist/chunks/content-source-mmppmcyg.js +4 -0
- package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-ccd9jwsa.js +4 -0
- package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
- package/dist/chunks/extension-sections-0egb88dm.js +4 -0
- package/dist/chunks/file-ops-qnab36ek.js +4 -0
- package/dist/chunks/files-rcn56qvm.js +4 -0
- package/dist/chunks/format-host-yxz0kjjs.js +4 -0
- package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
- package/dist/chunks/grid-open-4z1g062t.js +4 -0
- package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
- package/dist/chunks/icons-63bjtbs7.js +4 -0
- package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
- package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
- package/dist/chunks/jsonMode-njkvsa02.js +13 -0
- package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
- package/dist/chunks/layers-bgyr11tr.js +4 -0
- package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
- package/dist/chunks/listbox-c421cf8c.js +4 -0
- package/dist/chunks/lit-html-v9gh687x.js +4 -0
- package/dist/chunks/media-library-sq468wts.js +4 -0
- package/dist/chunks/media-picker-shfe59pt.js +4 -0
- package/dist/chunks/menu-bdpzbfvs.js +4 -0
- package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
- package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
- package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
- package/dist/chunks/notify-kzrjr3fv.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-7v4rtd7m.js +4 -0
- package/dist/chunks/popover-b89sfej7.js +4 -0
- package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
- package/dist/chunks/publish-quick-qx2455cj.js +4 -0
- package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
- package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
- package/dist/chunks/references-9547rg5s.js +4 -0
- package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/split-c9zfdgxf.js +4 -0
- package/dist/chunks/studio-03ct6yfv.js +9 -0
- package/dist/chunks/studio-07rcfje3.js +5 -0
- package/dist/chunks/studio-3e54qh39.js +7 -0
- package/dist/chunks/studio-3exxhz5g.js +5 -0
- package/dist/chunks/studio-3q40e3rj.js +5 -0
- package/dist/chunks/studio-3qeh9t0h.js +6 -0
- package/dist/chunks/studio-3qqjeep5.js +6 -0
- package/dist/chunks/studio-43sd2mam.js +4 -0
- package/dist/chunks/studio-4hp8pkyt.js +5 -0
- package/dist/chunks/studio-58xg6j2q.js +9 -0
- package/dist/chunks/studio-5g0rprdt.js +7 -0
- package/dist/chunks/studio-6m380wp7.js +5 -0
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/studio-8tr6cfrc.js +5 -0
- package/dist/chunks/studio-8vcvfs7r.js +6 -0
- package/dist/chunks/studio-9tmebf0s.js +5 -0
- package/dist/chunks/studio-a2bvaptz.js +5 -0
- package/dist/chunks/studio-b7y5mr30.js +5 -0
- package/dist/chunks/studio-bavb31r0.js +5 -0
- package/dist/chunks/studio-bbe4c90a.js +5 -0
- package/dist/chunks/studio-c05wdnt3.js +5 -0
- package/dist/chunks/studio-ccv2svc6.js +5 -0
- package/dist/chunks/studio-d5grtb9e.js +16 -0
- package/dist/chunks/studio-df0baea9.js +5 -0
- package/dist/chunks/studio-dgk4dqtx.js +7 -0
- package/dist/chunks/studio-e1g64q43.js +5 -0
- package/dist/chunks/studio-ed1hp6zf.js +6 -0
- package/dist/chunks/studio-ed3xx40h.js +7 -0
- package/dist/chunks/studio-f14e1zdj.js +5 -0
- package/dist/chunks/studio-fbhxxc5f.js +5 -0
- package/dist/chunks/studio-fyh0jc96.js +5 -0
- package/dist/chunks/studio-gcxk20n7.js +5 -0
- package/dist/chunks/studio-jaaz8ce9.js +5 -0
- package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/studio-k7evxqh4.js +5 -0
- package/dist/chunks/studio-kt3pjkwd.js +5 -0
- package/dist/chunks/studio-m8g16bgz.js +5 -0
- package/dist/chunks/studio-mn0476ag.js +5 -0
- package/dist/chunks/studio-mx1smyq0.js +5 -0
- package/dist/chunks/studio-n0c5h6mf.js +5 -0
- package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/studio-p4nrkvqr.js +5 -0
- package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
- package/dist/chunks/studio-pgmvdv7z.js +7 -0
- package/dist/chunks/studio-ph84avkf.js +5 -0
- package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
- package/dist/chunks/studio-q0tccd43.js +5 -0
- package/dist/chunks/studio-q7rtx6zq.js +14 -0
- package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
- package/dist/chunks/studio-qmn1xc24.js +5 -0
- package/dist/chunks/studio-qwdqwkj0.js +5 -0
- package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
- package/dist/chunks/studio-rj9eamf8.js +5 -0
- package/dist/chunks/studio-rptgsk96.js +5 -0
- package/dist/chunks/studio-rthyg42z.js +928 -0
- package/dist/chunks/studio-s19tp1xr.js +5 -0
- package/dist/chunks/studio-s32578pn.js +5 -0
- package/dist/chunks/studio-svb7yyve.js +5 -0
- package/dist/chunks/studio-syreb644.js +5 -0
- package/dist/chunks/studio-tf9jryb1.js +10 -0
- package/dist/chunks/studio-tfkznv39.js +5 -0
- package/dist/chunks/studio-tft6r105.js +5 -0
- package/dist/chunks/studio-txf2kysx.js +5 -0
- package/dist/chunks/studio-v8867ddv.js +12 -0
- package/dist/chunks/studio-vxq7fcvv.js +5 -0
- package/dist/chunks/studio-w4rz9hdk.js +5 -0
- package/dist/chunks/studio-wbcjbhy1.js +9 -0
- package/dist/chunks/studio-wc649wss.js +5 -0
- package/dist/chunks/studio-wys23mxz.js +5 -0
- package/dist/chunks/studio-x1x167jh.js +5 -0
- package/dist/chunks/studio-x9hsze61.js +5 -0
- package/dist/chunks/studio-y0n7yxea.js +9 -0
- package/dist/chunks/studio-y3ahhdpx.js +5 -0
- package/dist/chunks/studio-z97c48fk.js +5 -0
- package/dist/chunks/studio-zat62m0c.js +5 -0
- package/dist/chunks/studio-zcd2e7yz.js +5 -0
- package/dist/chunks/studio-zz9qe3rw.js +64 -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-1gv0h53h.js +4 -0
- package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-yypz28gq.js +4 -0
- package/dist/chunks/tree-9xa4hm7n.js +4 -0
- package/dist/chunks/tsMode-epyfz1hv.js +14 -0
- package/dist/chunks/workspace-dz7nxfhv.js +4 -0
- package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
- package/dist/chunks/ws-client-bv552sfx.js +4 -0
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +106 -107
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +17 -16
- 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/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +270 -53
- package/src/browse/library-model.ts +194 -134
- package/src/browse/library-pane.ts +748 -440
- package/src/browse/library-preview.ts +161 -26
- package/src/browse/library-source.ts +308 -41
- package/src/browse/preview-root.ts +78 -0
- package/src/browse/preview-style.ts +155 -0
- package/src/canvas/asset-refs.ts +40 -10
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +260 -77
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +175 -148
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +147 -61
- 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 +120 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +104 -75
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +269 -158
- package/src/canvas/iframe-inline-edit.ts +49 -30
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +30 -25
- package/src/canvas/iframe-keys.ts +11 -0
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +25 -21
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +36 -21
- package/src/canvas/iframe-render.ts +84 -35
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +10 -3
- package/src/canvas/npm-modules.ts +22 -0
- 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/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +7 -2
- package/src/canvas/surface-registry.ts +27 -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/app-commands.ts +16 -6
- package/src/commands/budget.ts +13 -11
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +55 -28
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +56 -43
- package/src/commands/levels.ts +14 -8
- package/src/commands/live-context.ts +9 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +22 -11
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +11 -9
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +54 -62
- package/src/content/entry-editor.ts +137 -32
- package/src/content/entry-fields.ts +25 -8
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +38 -15
- package/src/content/entry-open.ts +80 -0
- package/src/content/entry-summaries.ts +440 -0
- package/src/content/file-record-ids.ts +80 -0
- package/src/content/file-records.ts +125 -0
- package/src/content/page-summaries.ts +129 -0
- package/src/content/record-entry.ts +201 -0
- package/src/content/writing-banner.ts +177 -0
- package/src/create/add-new-commands.ts +185 -0
- package/src/create/add-new-flow.ts +1116 -0
- package/src/create/add-new.ts +1014 -0
- package/src/create/element-name.ts +121 -0
- 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 +78 -48
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +29 -22
- package/src/editor/inline-edit-apply.ts +79 -17
- package/src/editor/inline-edit.ts +76 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +14 -5
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +76 -42
- package/src/editor/slash-menu.ts +52 -14
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +89 -20
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +92 -41
- package/src/files/files.ts +248 -239
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +97 -2
- package/src/files/media-paths.ts +3 -0
- package/src/files/media-types.ts +55 -0
- package/src/files/media-upload.ts +209 -52
- package/src/files/new-file-name.ts +156 -0
- package/src/files/serialize-document.ts +15 -5
- 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 +91 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +21 -11
- package/src/github/github-publish.ts +28 -23
- 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 +25 -23
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -33
- package/src/grid/grid-panel.ts +65 -6
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +9 -31
- package/src/grid/grid-view.ts +45 -23
- 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 +100 -31
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +61 -34
- package/src/hosting/document.ts +2 -2
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +3 -3
- package/src/media/media-commands.ts +181 -0
- package/src/media/media-library-model.ts +232 -0
- package/src/media/media-library.ts +1283 -0
- package/src/media/media-pane.ts +51 -20
- 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 +38 -14
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- 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 +57 -46
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +36 -26
- package/src/panels/chat-panel.ts +6 -6
- package/src/panels/collections-panel.ts +306 -0
- package/src/panels/component-preview.ts +35 -13
- package/src/panels/data-explorer.ts +63 -26
- package/src/panels/data-grid.ts +18 -11
- package/src/panels/dnd.ts +115 -138
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +19 -5
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +78 -54
- package/src/panels/frontmatter-fields.ts +33 -28
- package/src/panels/git-diff-open.ts +10 -6
- package/src/panels/head-panel.ts +488 -202
- package/src/panels/i18n-panel.ts +20 -12
- package/src/panels/imports-panel.ts +25 -47
- package/src/panels/jump-bar.ts +75 -31
- package/src/panels/layers-panel.ts +130 -101
- package/src/panels/left-panel.ts +25 -11
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +140 -49
- package/src/panels/pane-grid.ts +55 -26
- package/src/panels/panel-registry.ts +36 -46
- package/src/panels/properties-panel.ts +182 -124
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +201 -45
- package/src/panels/seo-modal.ts +54 -125
- package/src/panels/settings-menu.ts +63 -61
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +156 -135
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +253 -206
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +195 -60
- package/src/panels/stylebook-layers-panel.ts +48 -89
- package/src/panels/stylebook-panel.ts +60 -27
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +143 -49
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +59 -31
- package/src/platforms/cloud.ts +373 -176
- package/src/platforms/default-platform.ts +14 -8
- package/src/platforms/devserver.ts +180 -142
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +20 -9
- package/src/publish/pages-service.ts +66 -27
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +88 -22
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-panel.ts +10 -6
- package/src/publish/publish-quick.ts +148 -0
- package/src/publish/publish-workspace.ts +926 -0
- package/src/publish/source-control.ts +907 -0
- 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 +74 -51
- package/src/services/cem-export.ts +149 -58
- package/src/services/cf-settings.ts +4 -4
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/connection.ts +2 -2
- 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 +20 -14
- 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 +29 -9
- package/src/services/settings/definitions.ts +25 -14
- 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 +128 -70
- package/src/settings/css-vars-editor.ts +119 -32
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +42 -14
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +101 -28
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +17 -7
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +28 -11
- package/src/settings/schema-field-ui.ts +12 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +186 -166
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +536 -477
- package/src/site-context.ts +101 -32
- package/src/state.ts +68 -57
- package/src/store.ts +54 -34
- package/src/studio.ts +219 -116
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +40 -7
- package/src/style/stylebook-specimens.ts +89 -0
- package/src/style/stylebook-target.ts +26 -0
- package/src/style/tag-inheritance.ts +105 -0
- package/src/style/token-ref.ts +5 -4
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +33 -38
- 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.json +4 -3
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +17 -16
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/collections-panel.json +615 -0
- package/src/surfaces/collections-panel.ts +168 -0
- package/src/surfaces/commandbar.json +241 -96
- package/src/surfaces/commandbar.ts +145 -105
- 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/empty-state.json +1 -1
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +35 -11
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- 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/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.json +162 -14
- package/src/surfaces/inspector-dock.ts +59 -31
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +111 -77
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +26 -11
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +47 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +44 -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.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +8 -7
- 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.json +72 -2
- package/src/surfaces/panel-page.ts +49 -25
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +25 -39
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +5 -29
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +29 -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-quick.json +428 -0
- package/src/surfaces/publish-quick.ts +165 -0
- package/src/surfaces/publish-workspace.json +2892 -0
- package/src/surfaces/publish-workspace.ts +391 -0
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +22 -79
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +17 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +32 -12
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +82 -16
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +9 -16
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- 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.json +3 -3
- package/src/surfaces/settings-overview.ts +14 -8
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +88 -36
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/site-panel.json +1029 -0
- package/src/surfaces/site-panel.ts +233 -0
- package/src/surfaces/slash-menu.json +63 -21
- package/src/surfaces/slash-menu.ts +42 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +56 -29
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/styles-panel.json +735 -0
- package/src/surfaces/styles-panel.ts +195 -0
- package/src/surfaces/styles-variables.json +149 -0
- package/src/surfaces/styles-variables.ts +145 -0
- package/src/surfaces/tab-strip.json +4 -4
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +6 -8
- package/src/surfaces/writing-banner.json +94 -0
- package/src/surfaces/writing-banner.ts +80 -0
- package/src/tabs/bare-repeaters.ts +101 -0
- 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 +99 -48
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +53 -43
- 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 +104 -56
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +57 -31
- package/src/ui/media-picker.ts +300 -47
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +14 -12
- package/src/ui/schema-form.ts +372 -97
- 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 +29 -3
- package/src/utils/base64.ts +6 -4
- package/src/utils/edit-display.ts +366 -111
- 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/local-day.ts +18 -0
- 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 +14 -16
- package/src/workspace/session.ts +81 -50
- package/src/workspace/tab-workspace.ts +137 -0
- package/src/workspace/workspace-back.ts +189 -0
- package/src/workspace/workspace-home.ts +133 -0
- package/src/workspace/workspace-ids.ts +129 -0
- package/src/workspace/workspace-switch.ts +372 -0
- package/src/workspace/workspace.ts +165 -47
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-va2wwra4.js +0 -4
- package/dist/chunks/adapter-f93pafd7.js +0 -4
- package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
- package/dist/chunks/cf-settings-125tdm0w.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-ax2f1fnn.js +0 -4
- package/dist/chunks/content-source-108aqtk1.js +0 -4
- package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-pfgdmkb0.js +0 -4
- package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
- package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
- package/dist/chunks/file-ops-meej5mqf.js +0 -4
- package/dist/chunks/files-44vp8a2s.js +0 -4
- package/dist/chunks/format-host-7q1petb9.js +0 -4
- package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
- package/dist/chunks/git-panel-zngbymvd.js +0 -4
- package/dist/chunks/grid-view-sx9vynsp.js +0 -51
- package/dist/chunks/icons-p44xhjf0.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-qk3ycq87.js +0 -4
- package/dist/chunks/index-wkyfjeqz.js +0 -4
- package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
- package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
- package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
- package/dist/chunks/layers-xd92fg8d.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
- package/dist/chunks/media-picker-0svzkdyb.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/menu-5c55ea3d.js +0 -4
- package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
- package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
- package/dist/chunks/notify-0xgtn8q1.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-v1qctbe6.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
- package/dist/chunks/quick-search-a54e6t5n.js +0 -4
- package/dist/chunks/references-gmqp82fs.js +0 -4
- package/dist/chunks/right-panel-v7t9awbk.js +0 -4
- package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0bhx5hz6.js +0 -5
- package/dist/chunks/studio-0k1ddnyy.js +0 -6
- package/dist/chunks/studio-1b04pd0j.js +0 -64
- package/dist/chunks/studio-4dwbj6gb.js +0 -5
- package/dist/chunks/studio-4tanh828.js +0 -5
- package/dist/chunks/studio-55h4mstj.js +0 -4
- package/dist/chunks/studio-5tnvjkz4.js +0 -5
- package/dist/chunks/studio-60dqgb0c.js +0 -5
- package/dist/chunks/studio-61dp09qg.js +0 -9
- package/dist/chunks/studio-63epcrj2.js +0 -5
- package/dist/chunks/studio-74k29dy9.js +0 -5
- package/dist/chunks/studio-7vg6jcd3.js +0 -5
- package/dist/chunks/studio-7zx31knw.js +0 -9
- package/dist/chunks/studio-8bxk97km.js +0 -5
- package/dist/chunks/studio-933e30n4.js +0 -5
- package/dist/chunks/studio-98wnwhbg.js +0 -5
- package/dist/chunks/studio-9mccjwjh.js +0 -14
- package/dist/chunks/studio-a2ke1e4t.js +0 -5
- package/dist/chunks/studio-e3a2a6v3.js +0 -4
- package/dist/chunks/studio-e81q1vb9.js +0 -5
- package/dist/chunks/studio-epgrmqqm.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-g1shz58g.js +0 -5
- package/dist/chunks/studio-gf0fz03c.js +0 -5
- package/dist/chunks/studio-gjtpe62q.js +0 -6
- package/dist/chunks/studio-gkskhg7m.js +0 -5
- package/dist/chunks/studio-gx4dnjzd.js +0 -5
- package/dist/chunks/studio-j03zga3y.js +0 -9
- package/dist/chunks/studio-jhpxeckz.js +0 -5
- package/dist/chunks/studio-k01r7ykp.js +0 -5
- package/dist/chunks/studio-kk7h30ne.js +0 -7
- package/dist/chunks/studio-kt1zqney.js +0 -5
- package/dist/chunks/studio-m3cwhvye.js +0 -5
- package/dist/chunks/studio-mcayt6hz.js +0 -5
- package/dist/chunks/studio-myjcghv3.js +0 -5
- package/dist/chunks/studio-n8bxwc3y.js +0 -4
- package/dist/chunks/studio-ngm8gvpb.js +0 -5
- package/dist/chunks/studio-nj5a01jy.js +0 -928
- package/dist/chunks/studio-pcgz8heb.js +0 -5
- package/dist/chunks/studio-qcsq0t15.js +0 -5
- package/dist/chunks/studio-qkstvve9.js +0 -5
- package/dist/chunks/studio-qv1pwd3c.js +0 -5
- package/dist/chunks/studio-rc6dvxjb.js +0 -7
- package/dist/chunks/studio-s8dmmz66.js +0 -5
- package/dist/chunks/studio-sp5xzbj4.js +0 -6
- package/dist/chunks/studio-szsjbj0g.js +0 -5
- package/dist/chunks/studio-t1xzawhr.js +0 -16
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vrmcjf9g.js +0 -7
- package/dist/chunks/studio-vyc0b4he.js +0 -10
- package/dist/chunks/studio-w0cgf6jg.js +0 -5
- package/dist/chunks/studio-w3hskzqk.js +0 -5
- package/dist/chunks/studio-xgrgcdyh.js +0 -9
- package/dist/chunks/studio-xz2yxfcb.js +0 -5
- package/dist/chunks/studio-y6n42tgs.js +0 -5
- package/dist/chunks/studio-yb560vxr.js +0 -5
- package/dist/chunks/studio-yn9f8vtx.js +0 -5
- package/dist/chunks/studio-yw05w8f0.js +0 -7
- package/dist/chunks/studio-z16sgavc.js +0 -5
- package/dist/chunks/studio-zey7zsdw.js +0 -12
- package/dist/chunks/studio-zyqn40w4.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-2frah6h1.js +0 -14
- package/dist/chunks/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -701
- package/src/panels/git-panel.ts +0 -1120
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -231
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -272
|
@@ -9,32 +9,47 @@
|
|
|
9
9
|
* identical sentence — "No files found" — which is the lie §16 exists to end.
|
|
10
10
|
* {@link scanLibrary} returns {@link LibraryScan.failures} beside the files; the pane raises
|
|
11
11
|
* them as Problems with a Retry and refuses to call an incomplete listing empty.
|
|
12
|
-
* 2. **A
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* 2. **A file is in one collection or in none.** The Library this model served filtered by FOLDER
|
|
13
|
+
* (Pages, Layouts, Components, Content, Media) and matched content with a third matcher of its
|
|
14
|
+
* own, which disagreed with the collection grid about the same entry. Every file now carries the
|
|
15
|
+
* key of the collection the Content workspace lists it under ({@link LibraryFile.collection}),
|
|
16
|
+
* from `content/content-collections.ts`, whose one matcher is `content/collection-match.ts`
|
|
17
|
+
* (studio.md §9.1.2).
|
|
16
18
|
*
|
|
17
19
|
* Everything here is pure over its inputs (the scan takes the platform as an argument) so the
|
|
18
20
|
* 300-page acceptance case can be measured without a DOM.
|
|
19
21
|
*/
|
|
20
22
|
|
|
21
23
|
import { MEDIA_EXTENSIONS, extensionOf } from "../files/media-upload";
|
|
24
|
+
import { PAGES_COLLECTION, collectionKeyOfPath } from "../content/content-collections";
|
|
25
|
+
import { isRoutedPageFile } from "@jxsuite/site/routes";
|
|
26
|
+
import { collectionForFile } from "../content/collection-match";
|
|
27
|
+
import { LOCALE_PLACEHOLDER } from "@jxsuite/schema/asset-paths";
|
|
22
28
|
import { projectState } from "../store";
|
|
23
29
|
import { notedListing } from "../files/asset-versions";
|
|
30
|
+
import { localDay } from "../utils/local-day";
|
|
24
31
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
32
|
+
import { isString } from "@jxsuite/schema/guards";
|
|
25
33
|
import { resolveI18n, servedLocaleOfPath } from "@jxsuite/schema/locale";
|
|
26
34
|
import type { ResolvedI18n } from "@jxsuite/schema/locale";
|
|
27
35
|
import type { ContentSectionEntry, DirEntry, StudioPlatform } from "../types";
|
|
36
|
+
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
28
37
|
|
|
29
38
|
// ─── Files ───────────────────────────────────────────────────────────────────
|
|
30
39
|
|
|
31
|
-
/** One
|
|
40
|
+
/** One scanned file, whichever layout is drawing it. */
|
|
32
41
|
export interface LibraryFile {
|
|
33
42
|
name: string;
|
|
34
43
|
path: string;
|
|
35
|
-
/** The
|
|
44
|
+
/** The extension, or `"file"` for a name without one. */
|
|
36
45
|
type: string;
|
|
37
|
-
|
|
46
|
+
/**
|
|
47
|
+
* The key of the collection the file is in (`pages`, or a collection's name), or `null` for a
|
|
48
|
+
* file in none: a template, a component, a media file, anything else.
|
|
49
|
+
*/
|
|
50
|
+
collection: string | null;
|
|
51
|
+
/** Whether the file is media by its extension — never an entry, whatever folder it is in. */
|
|
52
|
+
media: boolean;
|
|
38
53
|
ext: string;
|
|
39
54
|
/** Bytes, when the platform reported them. */
|
|
40
55
|
size?: number | undefined;
|
|
@@ -52,6 +67,13 @@ export interface LibraryFile {
|
|
|
52
67
|
* is in none.
|
|
53
68
|
*/
|
|
54
69
|
locale?: string | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Set when this row is one RECORD of a file-backed collection rather than a file: `path` is then
|
|
72
|
+
* the record's key (`prices.csv#3`), and `source` the file it is stored in, which is what opening
|
|
73
|
+
* it opens (`content/file-records.ts`); `row` is its place among the file's data rows, which is
|
|
74
|
+
* the row that file's grid lands on.
|
|
75
|
+
*/
|
|
76
|
+
record?: { source: string; row: number; fields: Readonly<Record<string, string>> } | undefined;
|
|
55
77
|
}
|
|
56
78
|
|
|
57
79
|
/** A directory the scan could not read. Its presence means the listing is INCOMPLETE, not empty. */
|
|
@@ -66,100 +88,117 @@ export interface LibraryScan {
|
|
|
66
88
|
failures: ScanFailure[];
|
|
67
89
|
}
|
|
68
90
|
|
|
69
|
-
// ───
|
|
91
|
+
// ─── The scan ────────────────────────────────────────────────────────────────
|
|
70
92
|
|
|
71
|
-
/** A
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
/** A project-relative path without `./`, backslashes or a trailing slash. */
|
|
94
|
+
function normalizeDir(path: string): string {
|
|
95
|
+
return path
|
|
96
|
+
.replaceAll("\\", "/")
|
|
97
|
+
.replace(/^(?:\.\/)+/, "")
|
|
98
|
+
.replace(/\/+$/, "");
|
|
77
99
|
}
|
|
78
100
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
/** The category keys, for a command's `enum` — so `library.setCategory` refuses an unknown one. */
|
|
89
|
-
export const LIBRARY_CATEGORY_KEYS: readonly string[] = LIBRARY_CATEGORIES.map((c) => c.key);
|
|
90
|
-
|
|
91
|
-
/** The category with this key, or undefined. */
|
|
92
|
-
export function libraryCategory(key: string): LibraryCategory | undefined {
|
|
93
|
-
return LIBRARY_CATEGORIES.find((c) => c.key === key);
|
|
101
|
+
/** Whether a `source` names one file (a CSV catalogue) rather than a directory to walk. */
|
|
102
|
+
function namesOneFile(source: string): boolean {
|
|
103
|
+
if (source.endsWith("/")) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const base = source.slice(source.lastIndexOf("/") + 1);
|
|
107
|
+
return /\.[a-z\d]+$/i.test(base);
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
/**
|
|
97
|
-
* The
|
|
111
|
+
* The directories the Content scan walks: the conventional project directories that exist, plus
|
|
112
|
+
* every declared directory-collection `source` none of them already covers.
|
|
113
|
+
*
|
|
114
|
+
* The conventional list alone missed two real collections. A collection may live BESIDE the project
|
|
115
|
+
* (`sites/jxsuite.com` declares `content.docs.source: "../../docs"`), which no project directory
|
|
116
|
+
* can contain; and a collection created after the project opened (Add new › Collection) has its
|
|
117
|
+
* source under a `content/` that did not exist when the conventional list was read. Both were
|
|
118
|
+
* listed as empty, which is the lie {@link LibraryScan.failures} exists to end.
|
|
98
119
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
120
|
+
* A localized source is walked from the directory above its `{locale}` segment, which the walk
|
|
121
|
+
* descends into on its own. A file-backed source is a file, not a directory to walk.
|
|
122
|
+
*
|
|
123
|
+
* @param projectDirs The conventional directories present at the project root.
|
|
124
|
+
* @param config The project configuration whose `content` section declares the collections.
|
|
102
125
|
*/
|
|
103
|
-
export function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return "Media";
|
|
111
|
-
}
|
|
112
|
-
if (dir.startsWith("pages")) {
|
|
113
|
-
return "Pages";
|
|
114
|
-
}
|
|
115
|
-
if (dir.startsWith("layouts")) {
|
|
116
|
-
return "Layouts";
|
|
117
|
-
}
|
|
118
|
-
if (dir.startsWith("components")) {
|
|
119
|
-
return "Components";
|
|
120
|
-
}
|
|
121
|
-
if (dir.startsWith("content")) {
|
|
122
|
-
return "Content";
|
|
126
|
+
export function libraryScanDirs(
|
|
127
|
+
projectDirs: readonly string[],
|
|
128
|
+
config: ProjectConfig | null | undefined,
|
|
129
|
+
): readonly string[] {
|
|
130
|
+
const dirs: string[] = [];
|
|
131
|
+
for (const dir of projectDirs) {
|
|
132
|
+
dirs.push(normalizeDir(dir));
|
|
123
133
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
const extra: string[] = [];
|
|
135
|
+
/* SAFETY: `content` is the parser extension's section, collection name → entry object; only the
|
|
136
|
+
optional string `source` is read, and it is tested before use. */
|
|
137
|
+
const content = (config?.content ?? {}) as Record<string, ContentSectionEntry>;
|
|
138
|
+
for (const def of Object.values(content)) {
|
|
139
|
+
if (!isString(def.source) || def.source === "" || namesOneFile(def.source)) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
let source = normalizeDir(def.source);
|
|
143
|
+
const cut = source.indexOf(LOCALE_PLACEHOLDER);
|
|
144
|
+
if (cut !== -1) {
|
|
145
|
+
source = normalizeDir(source.slice(0, cut));
|
|
146
|
+
}
|
|
147
|
+
if (source === "" || source === ".") {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const covered = [...dirs, ...extra].some(
|
|
151
|
+
(dir) => source === dir || source.startsWith(`${dir}/`),
|
|
152
|
+
);
|
|
153
|
+
if (!covered) {
|
|
154
|
+
extra.push(source);
|
|
155
|
+
}
|
|
132
156
|
}
|
|
133
|
-
|
|
157
|
+
// The project's own list, unchanged, when every collection is already under it.
|
|
158
|
+
return extra.length === 0 ? projectDirs : [...projectDirs, ...extra];
|
|
134
159
|
}
|
|
135
160
|
|
|
136
161
|
/**
|
|
137
|
-
* The
|
|
162
|
+
* The collection a scanned file is an ENTRY of, or `null`.
|
|
163
|
+
*
|
|
164
|
+
* `collectionKeyOfPath` answers which collection's folder holds a file, which is the question a
|
|
165
|
+
* convert or a creation asks. A listing asks a narrower one: is this a file the collection's loader
|
|
166
|
+
* reads? A Markdown collection's folder may hold a `nav.json` beside its pages (the jxsuite docs
|
|
167
|
+
* do), and counting it made the Content home and the Site panel disagree about one collection. So a
|
|
168
|
+
* collection that DECLARES its format lists only the files carrying that format's extension; one
|
|
169
|
+
* that declares none is left to the loader's reading of the source, as before.
|
|
138
170
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
171
|
+
* Pages are judged the way the build's walk judges them: with `pageExtensions` given, a file under
|
|
172
|
+
* `pages/` is a page only when it carries one of them, so `index.json.bak` beside the home page is
|
|
173
|
+
* a file in the folder rather than a second page (it publishes nothing).
|
|
174
|
+
*
|
|
175
|
+
* @param path The project-relative file.
|
|
176
|
+
* @param pageExtensions The extensions the build routes (`routedPageExtensions`); omitted, a page's
|
|
177
|
+
* extension is not judged.
|
|
141
178
|
*/
|
|
142
|
-
export function
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
>;
|
|
147
|
-
for (const [name, entry] of Object.entries(content)) {
|
|
148
|
-
if (!entry.source) {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
const prefix = entry.source.replace(/^\.\//, "").replace(/\/$/, "");
|
|
152
|
-
if (filePath.startsWith(`${prefix}/`) || filePath === prefix) {
|
|
153
|
-
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
154
|
-
}
|
|
179
|
+
export function entryCollectionOf(path: string, pageExtensions?: readonly string[]): string | null {
|
|
180
|
+
const key = collectionKeyOfPath(path);
|
|
181
|
+
if (key === null) {
|
|
182
|
+
return null;
|
|
155
183
|
}
|
|
156
|
-
|
|
184
|
+
if (key === PAGES_COLLECTION) {
|
|
185
|
+
return pageExtensions === undefined || isRoutedPageFile(path, pageExtensions) ? key : null;
|
|
186
|
+
}
|
|
187
|
+
const match = collectionForFile(path);
|
|
188
|
+
if (!match || match.name !== key || !match.def.format || match.ext === null) {
|
|
189
|
+
return key;
|
|
190
|
+
}
|
|
191
|
+
return path.toLowerCase().endsWith(match.ext.toLowerCase()) ? key : null;
|
|
157
192
|
}
|
|
158
193
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Directory names never worth walking — a `node_modules` scan is minutes, not milliseconds.
|
|
196
|
+
*
|
|
197
|
+
* Not `build` or `dist`: the scan starts inside the project's own directories, never at its root
|
|
198
|
+
* where a build writes, and a collection is free to name a section `build` (the jxsuite docs file
|
|
199
|
+
* their CLI pages under `framework/build/`). Skipping the name dropped those entries silently.
|
|
200
|
+
*/
|
|
201
|
+
const SKIP_DIRS = new Set(["node_modules", ".git", ".jx", ".cache"]);
|
|
163
202
|
|
|
164
203
|
/**
|
|
165
204
|
* Walk one directory tree, collecting files and recording — never swallowing — what it could not
|
|
@@ -172,13 +211,18 @@ async function walk(
|
|
|
172
211
|
out: LibraryFile[],
|
|
173
212
|
failures: ScanFailure[],
|
|
174
213
|
i18n: ResolvedI18n | null,
|
|
214
|
+
optional = false,
|
|
215
|
+
pageExtensions?: readonly string[],
|
|
175
216
|
): Promise<void> {
|
|
176
217
|
let entries: DirEntry[];
|
|
177
218
|
try {
|
|
178
219
|
// Noted: the Library walks every media directory, so it is where most versions are learned.
|
|
179
220
|
entries = await notedListing(() => platform.listDirectory(dir));
|
|
180
221
|
} catch (error) {
|
|
181
|
-
|
|
222
|
+
// A declared collection's folder that does not exist yet is an empty collection, not a fault.
|
|
223
|
+
if (!optional) {
|
|
224
|
+
failures.push({ dir, error: errorMessage(error) });
|
|
225
|
+
}
|
|
182
226
|
return;
|
|
183
227
|
}
|
|
184
228
|
const subdirectories: string[] = [];
|
|
@@ -190,21 +234,23 @@ async function walk(
|
|
|
190
234
|
continue;
|
|
191
235
|
}
|
|
192
236
|
const ext = extensionOf(entry.name);
|
|
193
|
-
const category = categoryFor(entry.path, ext);
|
|
194
237
|
out.push({
|
|
195
|
-
|
|
238
|
+
collection: entryCollectionOf(entry.path, pageExtensions),
|
|
196
239
|
ext,
|
|
197
240
|
locale: servedLocaleOfPath(entry.path, i18n) ?? undefined,
|
|
241
|
+
media: MEDIA_EXTENSIONS.has(ext),
|
|
198
242
|
modified: entry.modified,
|
|
199
243
|
name: entry.name,
|
|
200
244
|
path: entry.path,
|
|
201
245
|
size: entry.size,
|
|
202
|
-
type:
|
|
246
|
+
type: ext || "file",
|
|
203
247
|
});
|
|
204
248
|
}
|
|
205
249
|
// Siblings in parallel, depth serialized per branch: the platform counts every call as in-flight,
|
|
206
250
|
// So `probe.idle()` already knows the scan is running without the Library declaring a source.
|
|
207
|
-
await Promise.all(
|
|
251
|
+
await Promise.all(
|
|
252
|
+
subdirectories.map((sub) => walk(sub, platform, out, failures, i18n, false, pageExtensions)),
|
|
253
|
+
);
|
|
208
254
|
}
|
|
209
255
|
|
|
210
256
|
/**
|
|
@@ -216,13 +262,19 @@ async function walk(
|
|
|
216
262
|
export async function scanLibrary(
|
|
217
263
|
dirs: readonly string[],
|
|
218
264
|
platform: Pick<StudioPlatform, "listDirectory">,
|
|
265
|
+
optional: ReadonlySet<string> = new Set(),
|
|
266
|
+
pageExtensions?: readonly string[],
|
|
219
267
|
): Promise<LibraryScan> {
|
|
220
268
|
const files: LibraryFile[] = [];
|
|
221
269
|
const failures: ScanFailure[] = [];
|
|
222
270
|
// Resolved ONCE for the whole walk. `resolveI18n` canonicalizes every declared tag through
|
|
223
271
|
// `Intl.Locale`, and a project with 300 pages would otherwise pay for that per file.
|
|
224
272
|
const { i18n } = resolveI18n(projectState?.projectConfig ?? {});
|
|
225
|
-
await Promise.all(
|
|
273
|
+
await Promise.all(
|
|
274
|
+
dirs.map((dir) =>
|
|
275
|
+
walk(dir, platform, files, failures, i18n, optional.has(dir), pageExtensions),
|
|
276
|
+
),
|
|
277
|
+
);
|
|
226
278
|
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
227
279
|
return { failures, files };
|
|
228
280
|
}
|
|
@@ -230,25 +282,19 @@ export async function scanLibrary(
|
|
|
230
282
|
// ─── Filtering ───────────────────────────────────────────────────────────────
|
|
231
283
|
|
|
232
284
|
export interface LibraryFilter {
|
|
233
|
-
|
|
285
|
+
/** The collection key to keep: `pages`, or a declared collection's name. */
|
|
286
|
+
collection: string;
|
|
234
287
|
query: string;
|
|
235
288
|
/** A canonical tag, or "" for every language. Never a label — the labels are not unique. */
|
|
236
289
|
locale?: string;
|
|
237
290
|
}
|
|
238
291
|
|
|
239
|
-
/**
|
|
240
|
-
* Category, then text over name and path, then language. Returns the input array unchanged when
|
|
241
|
-
* nothing filters.
|
|
242
|
-
*/
|
|
292
|
+
/** Collection, then text over name and path, then language. */
|
|
243
293
|
export function filterLibrary(
|
|
244
294
|
files: readonly LibraryFile[],
|
|
245
295
|
filter: LibraryFilter,
|
|
246
296
|
): readonly LibraryFile[] {
|
|
247
|
-
let result = files;
|
|
248
|
-
const category = libraryCategory(filter.category);
|
|
249
|
-
if (category && category.key !== "all") {
|
|
250
|
-
result = result.filter((f) => f.category === category.label);
|
|
251
|
-
}
|
|
297
|
+
let result = files.filter((f) => f.collection === filter.collection);
|
|
252
298
|
const query = filter.query.trim().toLowerCase();
|
|
253
299
|
if (query) {
|
|
254
300
|
result = result.filter(
|
|
@@ -264,7 +310,8 @@ export function filterLibrary(
|
|
|
264
310
|
|
|
265
311
|
// ─── Layouts ─────────────────────────────────────────────────────────────────
|
|
266
312
|
|
|
267
|
-
|
|
313
|
+
/** The Content home's four views (studio.md §22.5), in the order its view switch draws them. */
|
|
314
|
+
export const LIBRARY_LAYOUTS = ["table", "cards", "calendar", "board"] as const;
|
|
268
315
|
|
|
269
316
|
export type LibraryLayout = (typeof LIBRARY_LAYOUTS)[number];
|
|
270
317
|
|
|
@@ -272,20 +319,16 @@ export const LIBRARY_LAYOUT_LABELS: Readonly<Record<LibraryLayout, string>> = {
|
|
|
272
319
|
board: "Board",
|
|
273
320
|
calendar: "Calendar",
|
|
274
321
|
cards: "Cards",
|
|
275
|
-
media: "Media",
|
|
276
322
|
table: "Table",
|
|
277
323
|
};
|
|
278
324
|
|
|
279
|
-
/** Whether a string names a layout — the guard behind `
|
|
325
|
+
/** Whether a string names a layout — the guard behind `content.setLayout`'s argument. */
|
|
280
326
|
export function isLibraryLayout(value: string): value is LibraryLayout {
|
|
281
|
-
return (
|
|
327
|
+
return LIBRARY_LAYOUTS.some((layout) => layout === value);
|
|
282
328
|
}
|
|
283
329
|
|
|
284
|
-
/** Layouts that draw a live preview per item. Table and Board draw text
|
|
285
|
-
export const PREVIEW_LAYOUTS: ReadonlySet<LibraryLayout> = new Set<LibraryLayout>([
|
|
286
|
-
"cards",
|
|
287
|
-
"media",
|
|
288
|
-
]);
|
|
330
|
+
/** Layouts that draw a live preview per item. Table, Calendar and Board draw text. */
|
|
331
|
+
export const PREVIEW_LAYOUTS: ReadonlySet<LibraryLayout> = new Set<LibraryLayout>(["cards"]);
|
|
289
332
|
|
|
290
333
|
// ─── Derived axes (Calendar and Board) ───────────────────────────────────────
|
|
291
334
|
|
|
@@ -305,9 +348,10 @@ export function libraryDate(file: LibraryFile): string | null {
|
|
|
305
348
|
return prefix[1]!;
|
|
306
349
|
}
|
|
307
350
|
if (file.modified) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
351
|
+
// The day it was modified where the reader is, not in UTC (`utils/local-day.ts`).
|
|
352
|
+
const day = localDay(new Date(file.modified));
|
|
353
|
+
if (day) {
|
|
354
|
+
return day;
|
|
311
355
|
}
|
|
312
356
|
}
|
|
313
357
|
return null;
|
|
@@ -315,7 +359,7 @@ export function libraryDate(file: LibraryFile): string | null {
|
|
|
315
359
|
|
|
316
360
|
/**
|
|
317
361
|
* The locales this project DECLARES, canonical and in declaration order — the value space of the
|
|
318
|
-
*
|
|
362
|
+
* Content home's language facet and of `content.setLocale`'s `enum`.
|
|
319
363
|
*
|
|
320
364
|
* Read at call time rather than cached: `projectState` is a plain binding replaced wholesale on a
|
|
321
365
|
* project switch, so a cached list would describe the project before last.
|
|
@@ -327,10 +371,9 @@ export function projectLocales(): readonly string[] {
|
|
|
327
371
|
/**
|
|
328
372
|
* The locales actually PRESENT among these files, in the project's declaration order.
|
|
329
373
|
*
|
|
330
|
-
* Ordered by the project and not by the scan
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
* because {@link resolveI18n} guarantees it is `locales[0]`.
|
|
374
|
+
* Ordered by the project and not by the scan: a facet whose options reshuffle when a file is added
|
|
375
|
+
* is a facet nobody can build muscle memory for. Declaration order also puts the default locale
|
|
376
|
+
* first, because {@link resolveI18n} guarantees it is `locales[0]`.
|
|
334
377
|
*
|
|
335
378
|
* Only declared tags can appear — `localeOfPath` matches nothing else — so filtering the
|
|
336
379
|
* declaration through the presence set loses no file.
|
|
@@ -345,15 +388,27 @@ export function libraryLocales(files: readonly LibraryFile[]): string[] {
|
|
|
345
388
|
return projectLocales().filter((tag) => present.has(tag));
|
|
346
389
|
}
|
|
347
390
|
|
|
391
|
+
/** One Calendar day: the files whose derived date is `date`. */
|
|
392
|
+
export interface LibraryDay {
|
|
393
|
+
date: string;
|
|
394
|
+
files: LibraryFile[];
|
|
395
|
+
}
|
|
396
|
+
|
|
348
397
|
/** Calendar buckets, newest day first, plus the files no date could be derived for. */
|
|
349
|
-
export
|
|
350
|
-
days:
|
|
398
|
+
export interface LibraryDateGroups {
|
|
399
|
+
days: LibraryDay[];
|
|
351
400
|
undated: LibraryFile[];
|
|
352
|
-
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** Calendar buckets, newest day first, plus the files no date could be derived for. */
|
|
404
|
+
export function groupByDate(
|
|
405
|
+
files: readonly LibraryFile[],
|
|
406
|
+
dateOf: (file: LibraryFile) => string | null = libraryDate,
|
|
407
|
+
): LibraryDateGroups {
|
|
353
408
|
const byDay = new Map<string, LibraryFile[]>();
|
|
354
409
|
const undated: LibraryFile[] = [];
|
|
355
410
|
for (const file of files) {
|
|
356
|
-
const date =
|
|
411
|
+
const date = dateOf(file);
|
|
357
412
|
if (date === null) {
|
|
358
413
|
undated.push(file);
|
|
359
414
|
continue;
|
|
@@ -366,33 +421,38 @@ export function groupByDate(files: readonly LibraryFile[]): {
|
|
|
366
421
|
}
|
|
367
422
|
}
|
|
368
423
|
const days = [...byDay.entries()]
|
|
369
|
-
.map(([date, dayFiles]) => ({ date, files: dayFiles }))
|
|
424
|
+
.map(([date, dayFiles]): LibraryDay => ({ date, files: dayFiles }))
|
|
370
425
|
.toSorted((a, b) => b.date.localeCompare(a.date));
|
|
371
426
|
return { days, undated };
|
|
372
427
|
}
|
|
373
428
|
|
|
374
|
-
/**
|
|
375
|
-
export function
|
|
429
|
+
/** The folder a file is in, project-relative: `pages/blog/a.md` → `pages/blog`. */
|
|
430
|
+
export function folderOf(path: string): string {
|
|
431
|
+
const slash = path.lastIndexOf("/");
|
|
432
|
+
return slash === -1 ? "." : path.slice(0, slash);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Board columns: one per folder the files are in, in path order.
|
|
437
|
+
*
|
|
438
|
+
* A collection is browsed one at a time, so a column per collection would be one column; the
|
|
439
|
+
* folders inside it (`pages/` and `pages/blog/`, a dated archive's years) are the grouping a
|
|
440
|
+
* collection already has on disk, and the one a Board can state without reading any file.
|
|
441
|
+
*/
|
|
442
|
+
export function groupByFolder(
|
|
376
443
|
files: readonly LibraryFile[],
|
|
377
444
|
): { group: string; files: LibraryFile[] }[] {
|
|
378
445
|
const byGroup = new Map<string, LibraryFile[]>();
|
|
379
446
|
for (const file of files) {
|
|
380
|
-
const
|
|
447
|
+
const folder = folderOf(file.path);
|
|
448
|
+
const bucket = byGroup.get(folder);
|
|
381
449
|
if (bucket) {
|
|
382
450
|
bucket.push(file);
|
|
383
451
|
} else {
|
|
384
|
-
byGroup.set(
|
|
452
|
+
byGroup.set(folder, [file]);
|
|
385
453
|
}
|
|
386
454
|
}
|
|
387
|
-
const order = LIBRARY_CATEGORIES.map((c) => c.label);
|
|
388
455
|
return [...byGroup.entries()]
|
|
389
456
|
.map(([group, groupFiles]) => ({ files: groupFiles, group }))
|
|
390
|
-
.toSorted((a, b) =>
|
|
391
|
-
const ai = order.indexOf(a.group);
|
|
392
|
-
const bi = order.indexOf(b.group);
|
|
393
|
-
if (ai === bi) {
|
|
394
|
-
return a.group.localeCompare(b.group);
|
|
395
|
-
}
|
|
396
|
-
return (ai === -1 ? order.length : ai) - (bi === -1 ? order.length : bi);
|
|
397
|
-
});
|
|
457
|
+
.toSorted((a, b) => a.group.localeCompare(b.group));
|
|
398
458
|
}
|