@jxsuite/studio 2.4.3 → 4.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.
Files changed (208) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/Overlay.dev-723bv0df.js +23 -0
  3. package/dist/chunks/cf-settings-45fgyx8y.js +21 -0
  4. package/dist/chunks/{components-z6cnkyy1.js → components-zmx10t62.js} +6 -5
  5. package/dist/chunks/content-source-t88vb2dr.js +49 -0
  6. package/dist/chunks/{convert-to-repeater-k10dvcc7.js → convert-to-repeater-dhw1nrz9.js} +27 -18
  7. package/dist/chunks/entry-commands-6z6bhxg0.js +46 -0
  8. package/dist/chunks/{extension-sections-0ada0xcw.js → extension-sections-3ydgjbdy.js} +32 -23
  9. package/dist/chunks/file-ops-rskmhxyq.js +48 -0
  10. package/dist/chunks/files-0cratsr0.js +92 -0
  11. package/dist/chunks/{format-host-wewba4nq.js → format-host-tgcmfs4p.js} +3 -3
  12. package/dist/chunks/fs-events-hrrg328g.js +21 -0
  13. package/dist/chunks/{git-panel-2dh1aw50.js → git-panel-0yywyk76.js} +21 -15
  14. package/dist/chunks/{jx-validate-jj9rnt4n.js → jx-validate-8q2g05x1.js} +6 -4
  15. package/dist/chunks/layers-panel-z3tqe5cd.js +67 -0
  16. package/dist/chunks/layers-q75tj2mf.js +45 -0
  17. package/dist/chunks/lit-html-j055mkh8.js +22 -0
  18. package/dist/chunks/monaco-buffer-dqw0xxpx.js +25 -0
  19. package/dist/chunks/{monaco-setup-a5wkmbgh.js → monaco-setup-rws7k4br.js} +4 -4
  20. package/dist/chunks/notify-yjm79n4s.js +30 -0
  21. package/dist/chunks/parse-24d0gay3.js +19 -0
  22. package/dist/chunks/platform-ba1j1gbh.js +16 -0
  23. package/dist/chunks/publish-panel-54jvhskq.js +28 -0
  24. package/dist/chunks/quick-search-cgfmjwq5.js +65 -0
  25. package/dist/chunks/references-3qx8fkyp.js +29 -0
  26. package/dist/chunks/right-panel-cqp8bc4v.js +46 -0
  27. package/dist/chunks/sp-overlay.dev-yztmtrs1.js +18 -0
  28. package/dist/chunks/sp-popover.dev-n2etmqdp.js +9 -0
  29. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +15 -0
  30. package/dist/chunks/sp-tooltip.dev-xcvpnqr0.js +15 -0
  31. package/dist/chunks/{sp-tray.dev-64v4pxw8.js → sp-tray.dev-tkbscm06.js} +5 -5
  32. package/dist/chunks/{studio-f5yyvqxv.js → studio-1hbqnt19.js} +37 -31
  33. package/dist/chunks/studio-2zkz8evn.js +3163 -0
  34. package/dist/chunks/{studio-0b6fs05q.js → studio-4pqqxbrt.js} +23 -15
  35. package/dist/chunks/{studio-kvfx9z2c.js → studio-4rzyrtjz.js} +70 -31
  36. package/dist/chunks/{studio-ef8t53vc.js → studio-5q69gfag.js} +60 -56
  37. package/dist/chunks/{studio-v2c5pmjj.js → studio-5rywrkxz.js} +565 -133
  38. package/dist/chunks/{studio-6kv3apa9.js → studio-68n67094.js} +25 -9
  39. package/dist/chunks/{studio-0rqqhrdy.js → studio-7nte2hj4.js} +2 -2
  40. package/dist/chunks/{studio-hyn3vhwr.js → studio-8swrjbny.js} +31 -18
  41. package/dist/chunks/studio-92ab2jqe.js +282 -0
  42. package/dist/chunks/{studio-sas7mt3k.js → studio-9ab8gqsm.js} +2 -2
  43. package/dist/chunks/{studio-28xc8ws4.js → studio-9c4k4vhv.js} +14 -10
  44. package/dist/chunks/studio-9n4mrmnb.js +184 -0
  45. package/dist/chunks/{studio-tr20m8g8.js → studio-9r6j5ev1.js} +37 -2
  46. package/dist/chunks/{studio-aweyr4v1.js → studio-ahjfdy6e.js} +9 -7
  47. package/dist/chunks/{studio-s519zc99.js → studio-bgxt93ga.js} +3 -3
  48. package/dist/chunks/{studio-26sv44br.js → studio-cb12yz9w.js} +8543 -8784
  49. package/dist/chunks/studio-cft9r4r7.js +119 -0
  50. package/dist/chunks/{studio-rqemfhz6.js → studio-eenfkt4e.js} +6 -6
  51. package/dist/chunks/studio-eesa1myv.js +498 -0
  52. package/dist/chunks/{studio-ay8wcr2b.js → studio-eqq1w638.js} +7 -9
  53. package/dist/chunks/{studio-ke244pam.js → studio-ex8zyp98.js} +51 -25
  54. package/dist/chunks/studio-gv8vvshc.js +118 -0
  55. package/dist/chunks/studio-hbtp0eh1.js +1315 -0
  56. package/dist/chunks/{studio-cz2j1c0g.js → studio-htsf0w6m.js} +75 -123
  57. package/dist/chunks/{studio-pyrw8h0w.js → studio-kjjsjak4.js} +528 -212
  58. package/dist/chunks/{studio-5x5774ak.js → studio-kryvsw6j.js} +3 -3
  59. package/dist/chunks/studio-kyh9avvv.js +28 -0
  60. package/dist/chunks/{studio-jnakhg87.js → studio-kyk2v92a.js} +14 -14
  61. package/dist/chunks/{studio-twsafr1e.js → studio-m3hwn7y1.js} +3 -3
  62. package/dist/chunks/{studio-tzx3xmvx.js → studio-mmv72a27.js} +8 -8
  63. package/dist/chunks/{studio-vhk5fmfv.js → studio-n8b9wqwy.js} +5 -5
  64. package/dist/chunks/{studio-cjm7fdjf.js → studio-p4ngc046.js} +8 -104
  65. package/dist/chunks/{studio-sccge2wf.js → studio-p8j86wag.js} +2 -2
  66. package/dist/chunks/{studio-v1va0vhd.js → studio-pdfjntbk.js} +75 -139
  67. package/dist/chunks/studio-q43a5y9h.js +394 -0
  68. package/dist/chunks/studio-q7v10cg2.js +106 -0
  69. package/dist/chunks/{studio-2w11grav.js → studio-qq6jym04.js} +3 -3
  70. package/dist/chunks/studio-r1r7afxx.js +1066 -0
  71. package/dist/chunks/{studio-3fk1ac9z.js → studio-rdx8jcxy.js} +4 -4
  72. package/dist/chunks/{studio-4mqb9a0j.js → studio-rn9ta2mz.js} +4 -4
  73. package/dist/chunks/studio-sf7zjgv1.js +91 -0
  74. package/dist/chunks/studio-t7qb9db8.js +665 -0
  75. package/dist/chunks/studio-tmc5emrw.js +8 -0
  76. package/dist/chunks/{studio-wdt9y92a.js → studio-txwkm6p9.js} +2 -2
  77. package/dist/chunks/{studio-dgj7gq44.js → studio-v38hmvx1.js} +7 -7
  78. package/dist/chunks/{studio-7ejemhej.js → studio-vadzgkrz.js} +6 -6
  79. package/dist/chunks/studio-wcy8trfx.js +263 -0
  80. package/dist/chunks/{studio-hb7c46jy.js → studio-wx5609xd.js} +21 -15
  81. package/dist/chunks/studio-xrapxwwc.js +1539 -0
  82. package/dist/chunks/{studio-ws6ef6js.js → studio-yxrkyv8a.js} +41 -29
  83. package/dist/chunks/{studio-xm3dbxvn.js → studio-zczps70q.js} +2 -2
  84. package/dist/chunks/workspace-xpres40v.js +89 -0
  85. package/dist/iframe-entry.js +450 -48
  86. package/dist/studio.js +2455 -1761
  87. package/package.json +16 -15
  88. package/src/browse/library-layouts.ts +3 -3
  89. package/src/browse/library-pane.ts +59 -5
  90. package/src/browse/library-preview.ts +19 -3
  91. package/src/canvas/asset-refs.ts +119 -0
  92. package/src/canvas/asset-resolve.ts +256 -0
  93. package/src/canvas/canvas-live-render.ts +23 -15
  94. package/src/canvas/canvas-render.ts +23 -1
  95. package/src/canvas/iframe-entry.ts +1 -0
  96. package/src/canvas/iframe-host.ts +4 -0
  97. package/src/canvas/iframe-patch.ts +47 -21
  98. package/src/canvas/iframe-protocol.ts +9 -0
  99. package/src/canvas/iframe-render.ts +50 -16
  100. package/src/commands/app-commands.ts +4 -0
  101. package/src/commands/command-args.ts +29 -0
  102. package/src/commands/context.ts +15 -1
  103. package/src/commands/defaults.ts +29 -1
  104. package/src/commands/levels.ts +16 -0
  105. package/src/commands/live-context.ts +3 -0
  106. package/src/content/collection-match.ts +267 -0
  107. package/src/content/entry-commands.ts +38 -29
  108. package/src/content/entry-fields.ts +6 -0
  109. package/src/editor/file-drop-action.ts +2 -1
  110. package/src/editor/shortcuts.ts +5 -0
  111. package/src/files/file-ops.ts +10 -42
  112. package/src/files/files.ts +487 -61
  113. package/src/files/fs-events.ts +9 -0
  114. package/src/files/gitignore.ts +432 -0
  115. package/src/files/media-paths.ts +37 -14
  116. package/src/files/media-upload.ts +47 -6
  117. package/src/files/serialize-document.ts +60 -0
  118. package/src/format/convert-file.ts +511 -0
  119. package/src/format/format-choices.ts +199 -0
  120. package/src/grid/grid-idle.ts +45 -0
  121. package/src/grid/grid-view.ts +35 -0
  122. package/src/grid/schema-columns.ts +2 -1
  123. package/src/grid/sources/content-source.ts +24 -3
  124. package/src/media/media-open.ts +58 -0
  125. package/src/media/media-pane.ts +310 -0
  126. package/src/new-project/import-tab.ts +333 -160
  127. package/src/new-project/new-project-modal.ts +27 -34
  128. package/src/packages/ensure-deps.ts +14 -7
  129. package/src/packages/jxsuite-update.ts +11 -11
  130. package/src/page-params.ts +10 -46
  131. package/src/panels/activity-bar.ts +45 -16
  132. package/src/panels/ai-chat/attached-context.ts +6 -1
  133. package/src/panels/ai-chat/chat-view.ts +255 -13
  134. package/src/panels/ai-chat/composer.ts +21 -80
  135. package/src/panels/ai-panel.ts +116 -2
  136. package/src/panels/frontmatter-fields.ts +6 -2
  137. package/src/panels/navigator-panels.ts +7 -6
  138. package/src/panels/properties-panel.ts +8 -2
  139. package/src/panels/seo-modal.ts +5 -6
  140. package/src/panels/settings-menu.ts +799 -0
  141. package/src/panels/signals-panel.ts +2 -1
  142. package/src/panels/toolbar.ts +135 -15
  143. package/src/platforms/cloud.ts +34 -3
  144. package/src/platforms/devserver.ts +72 -34
  145. package/src/preview/preview-overlay.ts +226 -0
  146. package/src/services/ai-ask.ts +247 -0
  147. package/src/services/ai-import-tools.ts +494 -0
  148. package/src/services/ai-models.ts +101 -11
  149. package/src/services/ai-project-tools.ts +20 -26
  150. package/src/services/ai-settings.ts +69 -71
  151. package/src/services/ai-system-prompt.ts +88 -2
  152. package/src/services/ai-turn-signal.ts +70 -0
  153. package/src/services/cf-settings.ts +19 -37
  154. package/src/services/connection.ts +74 -0
  155. package/src/services/context-manager.ts +89 -0
  156. package/src/services/document-assistant.ts +49 -7
  157. package/src/services/idle.ts +6 -1
  158. package/src/services/import-client.ts +33 -6
  159. package/src/services/import-run.ts +158 -0
  160. package/src/services/import-seed.ts +120 -0
  161. package/src/services/jx-validate.ts +58 -6
  162. package/src/services/project-adoption.ts +71 -0
  163. package/src/services/references.ts +0 -0
  164. package/src/services/settings/definitions.ts +181 -0
  165. package/src/services/settings/kernel.ts +335 -0
  166. package/src/services/settings/write-queue.ts +116 -0
  167. package/src/services/tool-executor.ts +34 -2
  168. package/src/settings/contexts-section.ts +45 -3
  169. package/src/settings/dependencies-editor.ts +43 -23
  170. package/src/settings/general-settings.ts +30 -12
  171. package/src/settings/preferences-accounts.ts +6 -19
  172. package/src/settings/preferences-dialog.ts +18 -41
  173. package/src/settings/preferences-keymap.ts +8 -18
  174. package/src/settings/preferences-sections.ts +57 -0
  175. package/src/settings/schema-field-ui.ts +2 -2
  176. package/src/settings/settings-document.ts +65 -9
  177. package/src/shell.ts +6 -14
  178. package/src/studio.ts +65 -7
  179. package/src/tabs/transact.ts +42 -19
  180. package/src/types.ts +164 -8
  181. package/src/ui/ai-credentials-form.ts +52 -27
  182. package/src/ui/ai-model-picker.ts +162 -0
  183. package/src/ui/choice-field.ts +72 -0
  184. package/src/ui/layers.ts +83 -5
  185. package/src/ui/media-picker.ts +6 -11
  186. package/src/utils/studio-utils.ts +43 -31
  187. package/styles/forced-colors.css +7 -0
  188. package/styles/overlays.css +256 -0
  189. package/styles/panels.css +13 -1
  190. package/styles/shell.css +111 -0
  191. package/dist/chunks/Overlay.dev-d2ajy6sj.js +0 -23
  192. package/dist/chunks/cf-settings-g5fbf2zp.js +0 -17
  193. package/dist/chunks/content-source-k9724vcv.js +0 -39
  194. package/dist/chunks/files-yew27sn9.js +0 -69
  195. package/dist/chunks/layers-panel-qnsghwwd.js +0 -59
  196. package/dist/chunks/publish-panel-a0pdft5w.js +0 -21
  197. package/dist/chunks/quick-search-9avyc4pc.js +0 -54
  198. package/dist/chunks/right-panel-kcnhtc5j.js +0 -38
  199. package/dist/chunks/sp-overlay.dev-s18hymn9.js +0 -18
  200. package/dist/chunks/sp-popover.dev-dj9x7e7a.js +0 -9
  201. package/dist/chunks/sp-progress-circle.dev-0zxcyz3r.js +0 -15
  202. package/dist/chunks/sp-tooltip.dev-5c6d1kjz.js +0 -15
  203. package/dist/chunks/studio-a7pzveq1.js +0 -110
  204. package/dist/chunks/studio-c31yb4t6.js +0 -55
  205. package/dist/chunks/studio-ra7ar50f.js +0 -6682
  206. package/src/canvas/content-assets.ts +0 -263
  207. package/src/canvas/site-style-css.ts +0 -121
  208. package/src/services/settings-store.ts +0 -99
@@ -0,0 +1,119 @@
1
+ import {
2
+ errorMessage
3
+ } from "./studio-9n4mrmnb.js";
4
+ import {
5
+ getPlatform,
6
+ hasPlatform
7
+ } from "./studio-9ab8gqsm.js";
8
+
9
+ // src/services/references.ts
10
+ function usagesSupported() {
11
+ return hasPlatform() && typeof getPlatform().findReferences === "function";
12
+ }
13
+ function keyOf(query) {
14
+ return `${query.path ?? ""}\x00${query.tagName ?? ""}`;
15
+ }
16
+ var settled = new Map;
17
+ var inFlight = new Map;
18
+ function peekUsages(query) {
19
+ if (!usagesSupported()) {
20
+ return { status: "unsupported" };
21
+ }
22
+ return settled.get(keyOf(query)) ?? (inFlight.has(keyOf(query)) ? { status: "pending" } : null);
23
+ }
24
+ async function loadUsages(query) {
25
+ if (!usagesSupported()) {
26
+ return { status: "unsupported" };
27
+ }
28
+ if (!query.path && !query.tagName) {
29
+ return { status: "failed", message: "no target to look for" };
30
+ }
31
+ const key = keyOf(query);
32
+ const done = settled.get(key);
33
+ if (done) {
34
+ return done;
35
+ }
36
+ const running = inFlight.get(key);
37
+ if (running) {
38
+ return running;
39
+ }
40
+ const pending = (async () => {
41
+ try {
42
+ const result = await getPlatform().findReferences({
43
+ ...query.path === undefined ? {} : { path: query.path },
44
+ ...query.tagName === undefined ? {} : { tagName: query.tagName }
45
+ });
46
+ return { result, status: "ready" };
47
+ } catch (error) {
48
+ return { message: errorMessage(error), status: "failed" };
49
+ } finally {
50
+ inFlight.delete(key);
51
+ }
52
+ })();
53
+ inFlight.set(key, pending);
54
+ const state = await pending;
55
+ settled.set(key, state);
56
+ return state;
57
+ }
58
+ function retryUsages(query) {
59
+ settled.delete(keyOf(query));
60
+ return loadUsages(query);
61
+ }
62
+ function invalidateUsages() {
63
+ settled.clear();
64
+ }
65
+ function splitUsages(result) {
66
+ let pages = 0;
67
+ for (const file of result.files) {
68
+ if (file.path.startsWith("pages/")) {
69
+ pages += 1;
70
+ }
71
+ }
72
+ return { others: result.files.length - pages, pages };
73
+ }
74
+ function usageHeadline(result) {
75
+ const { others, pages } = splitUsages(result);
76
+ if (pages === 0 && others === 0) {
77
+ return "Not used yet";
78
+ }
79
+ const parts = [];
80
+ if (pages > 0) {
81
+ parts.push(`${pages} page${pages === 1 ? "" : "s"}`);
82
+ }
83
+ if (others > 0) {
84
+ parts.push(`${others} other file${others === 1 ? "" : "s"}`);
85
+ }
86
+ return `Used on ${parts.join(" and ")}`;
87
+ }
88
+ function usageWarning(state, verb) {
89
+ if (state.status === "unsupported") {
90
+ return null;
91
+ }
92
+ if (state.status === "pending") {
93
+ return "Counting references…";
94
+ }
95
+ if (state.status === "failed") {
96
+ return `References could not be counted (${state.message}) — this may break more than it appears to.`;
97
+ }
98
+ const { files, refsTotal } = state.result;
99
+ if (files.length === 0) {
100
+ return verb === "delete" ? "Nothing else in this project refers to it." : "Nothing else in this project refers to it, so nothing needs updating.";
101
+ }
102
+ const where = `${refsTotal} reference${refsTotal === 1 ? "" : "s"} in ${files.length} file${files.length === 1 ? "" : "s"}`;
103
+ const floor = state.result.errors.length > 0 ? " (at least — some documents could not be read)" : "";
104
+ if (verb === "delete") {
105
+ return `${where}${floor} will break. Those files stay on disk; the references in them stop resolving.`;
106
+ }
107
+ if (verb === "convert") {
108
+ return `${where}${floor} will be updated automatically to point at the new file.`;
109
+ }
110
+ return `${where}${floor} will be updated automatically. Nothing else changes.`;
111
+ }
112
+ function usageFiles(result) {
113
+ return result.files.toSorted((a, b) => b.count - a.count || a.path.localeCompare(b.path));
114
+ }
115
+
116
+ export { usagesSupported, peekUsages, loadUsages, retryUsages, invalidateUsages, splitUsages, usageHeadline, usageWarning, usageFiles };
117
+
118
+ //# debugId=F66D72E5CAE74C4664756E2164756E21
119
+ //# sourceMappingURL=studio-cft9r4r7.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getPlatform
3
- } from "./studio-sas7mt3k.js";
3
+ } from "./studio-9ab8gqsm.js";
4
4
  import {
5
5
  __require
6
6
  } from "./studio-a0tswy0w.js";
@@ -21,7 +21,7 @@ async function applyPendingSchemas() {
21
21
  }
22
22
  _pendingSchemasDirty = false;
23
23
  try {
24
- const { applyProjectSchemas } = await import("./monaco-setup-a5wkmbgh.js");
24
+ const { applyProjectSchemas } = await import("./monaco-setup-rws7k4br.js");
25
25
  applyProjectSchemas(_pendingSchemas);
26
26
  } catch {}
27
27
  }
@@ -32,7 +32,7 @@ function loadMonaco() {
32
32
  _loading ??= (async () => {
33
33
  const [monaco] = await Promise.all([
34
34
  import("./editor-cptq5jp1.js"),
35
- import("./monaco-setup-a5wkmbgh.js")
35
+ import("./monaco-setup-rws7k4br.js")
36
36
  ]);
37
37
  _monaco = monaco;
38
38
  await applyPendingSchemas();
@@ -106,11 +106,11 @@ async function shareProjectSchemas(platform) {
106
106
  schemas = await platform.fetchProjectSchemas?.() ?? null;
107
107
  } catch {}
108
108
  setProjectSchemasForMonaco(schemas);
109
- await import("./jx-validate-jj9rnt4n.js").then(({ applyProjectSchemas }) => applyProjectSchemas(schemas)).catch(() => false);
109
+ await import("./jx-validate-8q2g05x1.js").then(({ applyProjectSchemas }) => applyProjectSchemas(schemas)).catch(() => false);
110
110
  }
111
111
  function refreshExtensionUi(platform) {
112
112
  shareProjectSchemas(platform);
113
- import("./extension-sections-0ada0xcw.js").then(({ syncExtensionSettingsSections }) => syncExtensionSettingsSections()).catch(() => {});
113
+ import("./extension-sections-3ydgjbdy.js").then(({ syncExtensionSettingsSections }) => syncExtensionSettingsSections()).catch(() => {});
114
114
  }
115
115
  function getFormats() {
116
116
  return _formats;
@@ -225,4 +225,4 @@ function splitFormatDocument(format, doc) {
225
225
  export { loadMonaco, loadedMonaco, mountStillWanted, loadFormats, refreshFormats, setFormats, loadExtensions, getExtensions, setExtensions, refreshExtensionUi, getFormats, formatByExtension, formatByName, noFormatError, formatForPath, documentExtensions, defaultContentFormat, formatParse, formatSerialize, splitFormatDocument };
226
226
 
227
227
  //# debugId=7A0A51B7AA10806664756E2164756E21
228
- //# sourceMappingURL=studio-rqemfhz6.js.map
228
+ //# sourceMappingURL=studio-eenfkt4e.js.map
@@ -0,0 +1,498 @@
1
+ import {
2
+ columnsFromSchema,
3
+ getGridController,
4
+ inferColumnsFromRows,
5
+ makeGridTabId,
6
+ parseSourceForPath
7
+ } from "./studio-cb12yz9w.js";
8
+ import {
9
+ isRecentLocal,
10
+ markLocalMutation
11
+ } from "./studio-q43a5y9h.js";
12
+ import {
13
+ workspace
14
+ } from "./studio-2zkz8evn.js";
15
+ import {
16
+ reactive
17
+ } from "./studio-xrapxwwc.js";
18
+ import {
19
+ projectState
20
+ } from "./studio-p4ngc046.js";
21
+ import {
22
+ defaultContentFormat,
23
+ documentExtensions,
24
+ formatByName,
25
+ formatForPath,
26
+ formatSerialize,
27
+ loadFormats
28
+ } from "./studio-eenfkt4e.js";
29
+ import {
30
+ getPlatform
31
+ } from "./studio-9ab8gqsm.js";
32
+ import {
33
+ __require
34
+ } from "./studio-a0tswy0w.js";
35
+
36
+ // src/content/draft-state.ts
37
+ var DRAFT_FIELD = "draft";
38
+ var DRAFT_MEANING = "Marked a draft. Studio filters drafts out of its own lists; the build does not exclude them yet.";
39
+ function isDraftEntry(fields) {
40
+ return fields?.[DRAFT_FIELD] === true;
41
+ }
42
+ function schemaDeclaresDraft(schema) {
43
+ return schema?.properties?.[DRAFT_FIELD]?.type === "boolean";
44
+ }
45
+ function hasDraftAxis(schema, fields) {
46
+ return schemaDeclaresDraft(schema) || isDraftEntry(fields);
47
+ }
48
+ var draftView = reactive({ includeDrafts: false });
49
+ function includingDrafts() {
50
+ return draftView.includeDrafts;
51
+ }
52
+ function setIncludeDrafts(include) {
53
+ draftView.includeDrafts = include;
54
+ }
55
+ function applyDraftFilter(items, fieldsOf, includeDrafts) {
56
+ return includeDrafts ? items : items.filter((item) => !isDraftEntry(fieldsOf(item)));
57
+ }
58
+
59
+ // src/grid/sources/content-source.ts
60
+ var PATH_FIELD = "__path";
61
+ function collectionInfo(typeName) {
62
+ const content = projectState?.projectConfig?.content ?? {};
63
+ const def = content[typeName];
64
+ if (!def?.source) {
65
+ return null;
66
+ }
67
+ const dir = def.source.replace(/^\.\//, "").replace(/\/$/, "");
68
+ const ext = def.format === "json" ? ".json" : formatByName(def.format)?.extensions[0] ?? defaultContentFormat()?.extensions[0] ?? ".json";
69
+ return { def, dir, ext, name: typeName };
70
+ }
71
+ function collectionDirs() {
72
+ const content = projectState?.projectConfig?.content ?? {};
73
+ return Object.entries(content).filter(([, def]) => {
74
+ const source = def.source?.replace(/^\.\//, "") ?? "";
75
+ return source !== "" && !/\.[a-z0-9]+$/i.test(source);
76
+ }).map(([name, def]) => ({ dir: def.source.replace(/^\.\//, "").replace(/\/$/, ""), name }));
77
+ }
78
+ async function listEntryFiles(dir, exts) {
79
+ const platform = getPlatform();
80
+ const results = [];
81
+ const walk = async (current) => {
82
+ let children;
83
+ try {
84
+ children = await platform.listDirectory(current);
85
+ } catch {
86
+ return;
87
+ }
88
+ for (const entry of children) {
89
+ if (entry.type === "directory") {
90
+ await walk(entry.path);
91
+ } else if (exts.some((ext) => entry.path.endsWith(ext))) {
92
+ results.push(entry.path);
93
+ }
94
+ }
95
+ };
96
+ await walk(dir);
97
+ return results.toSorted();
98
+ }
99
+ async function listCollectionEntryIds(typeName) {
100
+ await loadFormats().catch(() => {});
101
+ const info = collectionInfo(typeName);
102
+ if (!info) {
103
+ return [];
104
+ }
105
+ const files = await listEntryFiles(info.dir, [info.ext]);
106
+ return files.map((path) => {
107
+ const base = path.split("/").pop() ?? path;
108
+ return base.slice(0, base.length - info.ext.length);
109
+ });
110
+ }
111
+ async function mapLimit(items, limit, fn) {
112
+ const results = Array.from({ length: items.length });
113
+ let next = 0;
114
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
115
+ while (next < items.length) {
116
+ const index = next;
117
+ next += 1;
118
+ results[index] = await fn(items[index]);
119
+ }
120
+ });
121
+ await Promise.all(workers);
122
+ return results;
123
+ }
124
+ function toCellValue(value) {
125
+ if (value === null || value === undefined) {
126
+ return null;
127
+ }
128
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
129
+ return value;
130
+ }
131
+ if (Array.isArray(value) && value.every((v) => typeof v !== "object" || v === null)) {
132
+ return value.map(String);
133
+ }
134
+ return JSON.stringify(value);
135
+ }
136
+ function openTabFor(path) {
137
+ for (const tab of workspace.tabs.values()) {
138
+ if (tab.documentPath === path) {
139
+ return tab;
140
+ }
141
+ }
142
+ return null;
143
+ }
144
+ function extraRowsAreStrings(rows, field) {
145
+ return rows.every((row) => {
146
+ const value = row[field];
147
+ return value === null || value === undefined || typeof value !== "string" ? true : !value.startsWith("{") && !value.startsWith("[");
148
+ });
149
+ }
150
+ var draftAwareSources = new WeakSet;
151
+ async function reloadDraftAwareGrids() {
152
+ const reloads = [];
153
+ for (const tab of workspace.tabs.values()) {
154
+ const controller = getGridController(tab);
155
+ if (controller && draftAwareSources.has(controller.source)) {
156
+ reloads.push(controller.load());
157
+ }
158
+ }
159
+ await Promise.all(reloads);
160
+ }
161
+ function createEntryFileSource(opts) {
162
+ const source = buildEntryFileSource(opts);
163
+ if (opts.drafts) {
164
+ draftAwareSources.add(source);
165
+ }
166
+ return source;
167
+ }
168
+ function buildEntryFileSource(opts) {
169
+ const entries = new Map;
170
+ let loadPromise = null;
171
+ let columnsCache = null;
172
+ const load = (force = false) => {
173
+ if (!force && loadPromise) {
174
+ return loadPromise;
175
+ }
176
+ loadPromise = (async () => {
177
+ await loadFormats().catch(() => {});
178
+ const platform = getPlatform();
179
+ const files = await opts.list();
180
+ entries.clear();
181
+ columnsCache = null;
182
+ const loaded = await mapLimit(files, 8, async (path) => {
183
+ try {
184
+ const text = await platform.readFile(path);
185
+ const parsed = await parseSourceForPath(path, text);
186
+ return {
187
+ document: parsed.document,
188
+ formatName: parsed.format.name,
189
+ frontmatter: parsed.frontmatter ?? {},
190
+ rawText: text
191
+ };
192
+ } catch {
193
+ return null;
194
+ }
195
+ });
196
+ for (const [index, path] of files.entries()) {
197
+ const record = loaded[index];
198
+ if (record) {
199
+ entries.set(path, record);
200
+ }
201
+ }
202
+ })();
203
+ return loadPromise;
204
+ };
205
+ const buildColumns = () => {
206
+ if (columnsCache) {
207
+ return columnsCache;
208
+ }
209
+ const pathColumn = {
210
+ editable: false,
211
+ field: PATH_FIELD,
212
+ insertOnly: true,
213
+ kind: "string",
214
+ pk: true,
215
+ required: true,
216
+ title: "Path",
217
+ widthHint: 220
218
+ };
219
+ const schemaColumns = columnsFromSchema(opts.schema());
220
+ const known = new Set([PATH_FIELD, ...schemaColumns.map((c) => c.field)]);
221
+ const extraRows = [...entries.values()].map((entry) => {
222
+ const cells = {};
223
+ for (const [key, value] of Object.entries(entry.frontmatter)) {
224
+ if (!known.has(key) && !key.startsWith("$")) {
225
+ cells[key] = toCellValue(value);
226
+ }
227
+ }
228
+ return cells;
229
+ });
230
+ const extraColumns = inferColumnsFromRows(extraRows);
231
+ for (const column of extraColumns) {
232
+ column.editable = column.kind !== "text" || extraRowsAreStrings(extraRows, column.field);
233
+ }
234
+ if (opts.priorityFields?.length) {
235
+ const rank = (c) => {
236
+ const index = opts.priorityFields.indexOf(c.field);
237
+ return index === -1 ? opts.priorityFields.length : index;
238
+ };
239
+ extraColumns.sort((a, b) => rank(a) - rank(b));
240
+ }
241
+ columnsCache = withDraftColumn([pathColumn, ...schemaColumns, ...extraColumns]);
242
+ return columnsCache;
243
+ };
244
+ const draftAxis = () => {
245
+ if (!opts.drafts) {
246
+ return false;
247
+ }
248
+ const schema = opts.schema();
249
+ return hasDraftAxis(schema) || [...entries.values()].some((entry) => hasDraftAxis(schema, entry.frontmatter));
250
+ };
251
+ const withDraftColumn = (columns) => {
252
+ const index = columns.findIndex((column) => column.field === DRAFT_FIELD);
253
+ if (index < 1 || !draftAxis()) {
254
+ return columns;
255
+ }
256
+ const rest = columns.filter((column) => column.field !== DRAFT_FIELD);
257
+ return [rest[0], columns[index], ...rest.slice(1)];
258
+ };
259
+ const rowFor = (path, entry) => {
260
+ const cells = { [PATH_FIELD]: path };
261
+ for (const column of buildColumns()) {
262
+ if (column.field === PATH_FIELD) {
263
+ continue;
264
+ }
265
+ cells[column.field] = toCellValue(entry.frontmatter[column.field]);
266
+ }
267
+ return { cells, fingerprint: entry.rawText, key: path };
268
+ };
269
+ const writeEntry = async (path, entry, patches) => {
270
+ const platform = getPlatform();
271
+ const frontmatter = { ...entry.frontmatter };
272
+ for (const patch of patches) {
273
+ if (patch.value === null) {
274
+ delete frontmatter[patch.field];
275
+ } else {
276
+ frontmatter[patch.field] = patch.value;
277
+ }
278
+ }
279
+ const doc = entry.document;
280
+ const fullDoc = { ...frontmatter, ...doc, children: doc.children ?? [] };
281
+ const text = await formatSerialize(entry.formatName, fullDoc, { mode: "roundtrip" });
282
+ markLocalMutation(path);
283
+ await platform.writeFile(path, text);
284
+ entries.set(path, { ...entry, frontmatter, rawText: text });
285
+ };
286
+ return {
287
+ backingPaths: () => new Map([...entries.keys()].map((path) => [path, path])),
288
+ capabilities: { delete: true, insert: true, remotePaging: false, remoteSort: false },
289
+ async columns() {
290
+ await load();
291
+ return buildColumns();
292
+ },
293
+ async commit(batch) {
294
+ await load();
295
+ const platform = getPlatform();
296
+ const result = { cells: [], deletes: [], inserts: [] };
297
+ const byRow = new Map;
298
+ for (const cell of batch.cells) {
299
+ const list = byRow.get(cell.rowKey) ?? [];
300
+ list.push({ field: cell.field, value: cell.value });
301
+ byRow.set(cell.rowKey, list);
302
+ }
303
+ for (const [path, patches] of byRow) {
304
+ const outcome = (ok, error, stale) => {
305
+ for (const patch of patches) {
306
+ result.cells.push({ error, field: patch.field, ok, rowKey: path, stale });
307
+ }
308
+ };
309
+ const entry = entries.get(path);
310
+ if (!entry) {
311
+ outcome(false, "Entry no longer loaded — refresh the grid");
312
+ continue;
313
+ }
314
+ const openTab = openTabFor(path);
315
+ if (openTab?.doc.dirty) {
316
+ outcome(false, "Open in a tab with unsaved changes — save or close it first");
317
+ continue;
318
+ }
319
+ let onDisk = null;
320
+ try {
321
+ onDisk = await platform.readFile(path);
322
+ } catch {
323
+ onDisk = null;
324
+ }
325
+ if (onDisk !== entry.rawText && !isRecentLocal(path)) {
326
+ outcome(false, "File changed on disk — refresh to reload", true);
327
+ continue;
328
+ }
329
+ try {
330
+ await writeEntry(path, entry, patches);
331
+ outcome(true);
332
+ if (openTab) {
333
+ const { reloadFileInTab } = await import("./files-0cratsr0.js");
334
+ reloadFileInTab(path);
335
+ }
336
+ } catch (error) {
337
+ outcome(false, error instanceof Error ? error.message : String(error));
338
+ }
339
+ }
340
+ for (const insert of batch.inserts) {
341
+ const rawPath = insert.cells[PATH_FIELD];
342
+ if (typeof rawPath !== "string" || rawPath.trim() === "") {
343
+ result.inserts.push({ error: "Path is required", ok: false, tempKey: insert.tempKey });
344
+ continue;
345
+ }
346
+ const path = opts.resolveInsertPath(rawPath);
347
+ let exists = entries.has(path);
348
+ if (!exists) {
349
+ try {
350
+ await platform.readFile(path);
351
+ exists = true;
352
+ } catch {
353
+ exists = false;
354
+ }
355
+ }
356
+ if (exists) {
357
+ result.inserts.push({
358
+ error: `${path} already exists`,
359
+ ok: false,
360
+ tempKey: insert.tempKey
361
+ });
362
+ continue;
363
+ }
364
+ const formatName = opts.insertFormatName(path);
365
+ if (!formatName) {
366
+ result.inserts.push({
367
+ error: `No format can serialize ${path}`,
368
+ ok: false,
369
+ tempKey: insert.tempKey
370
+ });
371
+ continue;
372
+ }
373
+ try {
374
+ const frontmatter = {};
375
+ for (const [field, value] of Object.entries(insert.cells)) {
376
+ if (field !== PATH_FIELD && value !== null) {
377
+ frontmatter[field] = value;
378
+ }
379
+ }
380
+ const text = await formatSerialize(formatName, { ...frontmatter, children: [] }, { frontmatter: Object.keys(frontmatter).length > 0, mode: "roundtrip" });
381
+ markLocalMutation(path);
382
+ await platform.writeFile(path, text);
383
+ const parsed = await parseSourceForPath(path, text);
384
+ entries.set(path, {
385
+ document: parsed.document,
386
+ formatName: parsed.format.name,
387
+ frontmatter: parsed.frontmatter ?? {},
388
+ rawText: text
389
+ });
390
+ result.inserts.push({ newKey: path, ok: true, tempKey: insert.tempKey });
391
+ } catch (error) {
392
+ result.inserts.push({
393
+ error: error instanceof Error ? error.message : String(error),
394
+ ok: false,
395
+ tempKey: insert.tempKey
396
+ });
397
+ }
398
+ }
399
+ for (const del of batch.deletes) {
400
+ if (openTabFor(del.rowKey)) {
401
+ result.deletes.push({
402
+ error: "Open in a tab — close it first",
403
+ ok: false,
404
+ rowKey: del.rowKey
405
+ });
406
+ continue;
407
+ }
408
+ try {
409
+ markLocalMutation(del.rowKey);
410
+ await platform.deleteFile(del.rowKey);
411
+ entries.delete(del.rowKey);
412
+ result.deletes.push({ ok: true, rowKey: del.rowKey });
413
+ } catch (error) {
414
+ result.deletes.push({
415
+ error: error instanceof Error ? error.message : String(error),
416
+ ok: false,
417
+ rowKey: del.rowKey
418
+ });
419
+ }
420
+ }
421
+ return result;
422
+ },
423
+ id: opts.id,
424
+ label: opts.label,
425
+ async refresh() {
426
+ await load(true);
427
+ },
428
+ async rows() {
429
+ await load();
430
+ const listed = opts.drafts ? applyDraftFilter([...entries.entries()], ([, entry]) => entry.frontmatter, includingDrafts()) : [...entries.entries()];
431
+ const rows = listed.map(([path, entry]) => rowFor(path, entry));
432
+ return { rows, total: rows.length };
433
+ }
434
+ };
435
+ }
436
+ function createCollectionSource(typeName) {
437
+ const requireInfo = () => {
438
+ const info = collectionInfo(typeName);
439
+ if (!info) {
440
+ throw new Error(`No content collection named "${typeName}" in project.json`);
441
+ }
442
+ return info;
443
+ };
444
+ return createEntryFileSource({
445
+ drafts: true,
446
+ id: makeGridTabId({ kind: "collection", name: typeName }),
447
+ insertFormatName: (path) => {
448
+ const info = requireInfo();
449
+ return (info.def.format ? formatByName(info.def.format)?.name : undefined) ?? formatForPath(path)?.name ?? defaultContentFormat()?.name ?? null;
450
+ },
451
+ label: typeName,
452
+ list: () => {
453
+ const info = requireInfo();
454
+ return listEntryFiles(info.dir, [info.ext]);
455
+ },
456
+ resolveInsertPath: (raw) => {
457
+ const info = requireInfo();
458
+ let path = raw.trim().replace(/^\.\//, "").replace(/^\//, "");
459
+ if (!path.includes("/")) {
460
+ path = `${info.dir}/${path}`;
461
+ }
462
+ if (!path.endsWith(info.ext)) {
463
+ path = `${path}${info.ext}`;
464
+ }
465
+ return path;
466
+ },
467
+ schema: () => requireInfo().def.schema
468
+ });
469
+ }
470
+ function createPagesSource() {
471
+ const pageExts = () => {
472
+ const exts = documentExtensions("page").filter((ext) => ext !== ".json");
473
+ return exts.length > 0 ? exts : [".md"];
474
+ };
475
+ return createEntryFileSource({
476
+ id: makeGridTabId({ kind: "pages" }),
477
+ insertFormatName: (path) => formatForPath(path)?.name ?? null,
478
+ label: "Pages",
479
+ list: () => listEntryFiles("pages", pageExts()),
480
+ priorityFields: ["title", "description"],
481
+ resolveInsertPath: (raw) => {
482
+ let path = raw.trim().replace(/^\.\//, "").replace(/^\//, "");
483
+ if (!path.startsWith("pages/")) {
484
+ path = `pages/${path}`;
485
+ }
486
+ if (!pageExts().some((ext) => path.endsWith(ext))) {
487
+ path = `${path}${pageExts()[0]}`;
488
+ }
489
+ return path;
490
+ },
491
+ schema: () => null
492
+ });
493
+ }
494
+
495
+ export { DRAFT_FIELD, DRAFT_MEANING, isDraftEntry, hasDraftAxis, setIncludeDrafts, PATH_FIELD, collectionInfo, collectionDirs, listCollectionEntryIds, reloadDraftAwareGrids, createCollectionSource, createPagesSource };
496
+
497
+ //# debugId=0CDA93DC776D9A2264756E2164756E21
498
+ //# sourceMappingURL=studio-eesa1myv.js.map
@@ -2,10 +2,11 @@ import {
2
2
  AsyncDirective,
3
3
  directive,
4
4
  isPrimitive
5
- } from "./studio-kvfx9z2c.js";
5
+ } from "./studio-4rzyrtjz.js";
6
6
  import {
7
7
  noChange
8
- } from "./studio-5x5774ak.js";
8
+ } from "./studio-kryvsw6j.js";
9
+
9
10
  // ../../node_modules/lit-html/development/directives/private-async-helpers.js
10
11
  class PseudoWeakRef {
11
12
  constructor(ref) {
@@ -105,11 +106,8 @@ class UntilDirective extends AsyncDirective {
105
106
  }
106
107
  }
107
108
  var until = directive(UntilDirective);
108
- // ../../node_modules/lit-html/development/directives/when.js
109
- function when(condition, trueCase, falseCase) {
110
- return condition ? trueCase(condition) : falseCase?.(condition);
111
- }
112
- export { until, when };
113
109
 
114
- //# debugId=6810A26C9093588464756E2164756E21
115
- //# sourceMappingURL=studio-ay8wcr2b.js.map
110
+ export { until };
111
+
112
+ //# debugId=1A6E4B9F13159A4A64756E2164756E21
113
+ //# sourceMappingURL=studio-eqq1w638.js.map