nebula-cms 0.1.3 → 0.1.5

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 (381) hide show
  1. package/README.md +3 -1
  2. package/dist/astro/index.d.ts +43 -0
  3. package/dist/astro/index.d.ts.map +1 -0
  4. package/dist/astro/index.js +223 -0
  5. package/{src → dist}/client/Admin.svelte +20 -11
  6. package/dist/client/Admin.svelte.d.ts +11 -0
  7. package/dist/client/Admin.svelte.d.ts.map +1 -0
  8. package/dist/client/components/BackendPicker.svelte.d.ts +4 -0
  9. package/dist/client/components/BackendPicker.svelte.d.ts.map +1 -0
  10. package/dist/client/components/DraftChip.svelte.d.ts +10 -0
  11. package/dist/client/components/DraftChip.svelte.d.ts.map +1 -0
  12. package/dist/client/components/MetadataForm.svelte.d.ts +12 -0
  13. package/dist/client/components/MetadataForm.svelte.d.ts.map +1 -0
  14. package/dist/client/components/ThemeToggle.svelte.d.ts +19 -0
  15. package/dist/client/components/ThemeToggle.svelte.d.ts.map +1 -0
  16. package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts +11 -0
  17. package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts.map +1 -0
  18. package/{src → dist}/client/components/dialogs/FilenameDialog.svelte +1 -2
  19. package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts +13 -0
  20. package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts.map +1 -0
  21. package/dist/client/components/editor/EditorPane.svelte.d.ts +4 -0
  22. package/dist/client/components/editor/EditorPane.svelte.d.ts.map +1 -0
  23. package/dist/client/components/editor/EditorTabs.svelte.d.ts +8 -0
  24. package/dist/client/components/editor/EditorTabs.svelte.d.ts.map +1 -0
  25. package/dist/client/components/editor/EditorToolbar.svelte.d.ts +4 -0
  26. package/dist/client/components/editor/EditorToolbar.svelte.d.ts.map +1 -0
  27. package/dist/client/components/editor/FormatSelector.svelte.d.ts +4 -0
  28. package/dist/client/components/editor/FormatSelector.svelte.d.ts.map +1 -0
  29. package/dist/client/components/editor/Toolbar.svelte.d.ts +19 -0
  30. package/dist/client/components/editor/Toolbar.svelte.d.ts.map +1 -0
  31. package/dist/client/components/fields/ArrayField.svelte.d.ts +15 -0
  32. package/dist/client/components/fields/ArrayField.svelte.d.ts.map +1 -0
  33. package/dist/client/components/fields/ArrayItem.svelte.d.ts +28 -0
  34. package/dist/client/components/fields/ArrayItem.svelte.d.ts.map +1 -0
  35. package/dist/client/components/fields/BooleanField.svelte.d.ts +16 -0
  36. package/dist/client/components/fields/BooleanField.svelte.d.ts.map +1 -0
  37. package/dist/client/components/fields/DateField.svelte.d.ts +16 -0
  38. package/dist/client/components/fields/DateField.svelte.d.ts.map +1 -0
  39. package/dist/client/components/fields/EnumField.svelte.d.ts +17 -0
  40. package/dist/client/components/fields/EnumField.svelte.d.ts.map +1 -0
  41. package/dist/client/components/fields/FieldWrapper.svelte.d.ts +18 -0
  42. package/dist/client/components/fields/FieldWrapper.svelte.d.ts.map +1 -0
  43. package/dist/client/components/fields/NumberField.svelte.d.ts +16 -0
  44. package/dist/client/components/fields/NumberField.svelte.d.ts.map +1 -0
  45. package/dist/client/components/fields/ObjectField.svelte.d.ts +16 -0
  46. package/dist/client/components/fields/ObjectField.svelte.d.ts.map +1 -0
  47. package/dist/client/components/fields/SchemaField.svelte.d.ts +16 -0
  48. package/dist/client/components/fields/SchemaField.svelte.d.ts.map +1 -0
  49. package/dist/client/components/fields/StringField.svelte.d.ts +16 -0
  50. package/dist/client/components/fields/StringField.svelte.d.ts.map +1 -0
  51. package/{src → dist}/client/components/sidebar/AdminSidebar.svelte +2 -4
  52. package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts +19 -0
  53. package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts.map +1 -0
  54. package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts +12 -0
  55. package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts.map +1 -0
  56. package/dist/client/css/icons.css +29 -0
  57. package/dist/client/index.d.ts +2 -0
  58. package/dist/client/index.d.ts.map +1 -0
  59. package/dist/client/js/drafts/merge.svelte.d.ts +24 -0
  60. package/dist/client/js/drafts/merge.svelte.d.ts.map +1 -0
  61. package/dist/client/js/drafts/merge.svelte.js +106 -0
  62. package/dist/client/js/drafts/ops.svelte.d.ts +31 -0
  63. package/dist/client/js/drafts/ops.svelte.d.ts.map +1 -0
  64. package/dist/client/js/drafts/ops.svelte.js +182 -0
  65. package/dist/client/js/drafts/storage.d.ts +45 -0
  66. package/dist/client/js/drafts/storage.d.ts.map +1 -0
  67. package/dist/client/js/drafts/storage.js +76 -0
  68. package/dist/client/js/drafts/workers/diff.d.ts +2 -0
  69. package/dist/client/js/drafts/workers/diff.d.ts.map +1 -0
  70. package/dist/client/js/drafts/workers/diff.js +20 -0
  71. package/dist/client/js/editor/editor.svelte.d.ts +124 -0
  72. package/dist/client/js/editor/editor.svelte.d.ts.map +1 -0
  73. package/dist/client/js/editor/editor.svelte.js +294 -0
  74. package/dist/client/js/editor/languages.d.ts +11 -0
  75. package/dist/client/js/editor/languages.d.ts.map +1 -0
  76. package/dist/client/js/editor/languages.js +93 -0
  77. package/dist/client/js/editor/link-wrap.d.ts +6 -0
  78. package/dist/client/js/editor/link-wrap.d.ts.map +1 -0
  79. package/{src/client/js/editor/link-wrap.ts → dist/client/js/editor/link-wrap.js} +17 -24
  80. package/dist/client/js/editor/markdown-shortcuts.d.ts +4 -0
  81. package/dist/client/js/editor/markdown-shortcuts.d.ts.map +1 -0
  82. package/dist/client/js/editor/markdown-shortcuts.js +219 -0
  83. package/dist/client/js/handlers/admin.d.ts +64 -0
  84. package/dist/client/js/handlers/admin.d.ts.map +1 -0
  85. package/dist/client/js/handlers/admin.js +186 -0
  86. package/dist/client/js/state/dialogs.svelte.d.ts +16 -0
  87. package/dist/client/js/state/dialogs.svelte.d.ts.map +1 -0
  88. package/dist/client/js/state/dialogs.svelte.js +28 -0
  89. package/dist/client/js/state/router.svelte.d.ts +44 -0
  90. package/dist/client/js/state/router.svelte.d.ts.map +1 -0
  91. package/dist/client/js/state/router.svelte.js +141 -0
  92. package/dist/client/js/state/schema.svelte.d.ts +51 -0
  93. package/dist/client/js/state/schema.svelte.d.ts.map +1 -0
  94. package/{src/client/js/state/schema.svelte.ts → dist/client/js/state/schema.svelte.js} +55 -70
  95. package/dist/client/js/state/state.svelte.d.ts +68 -0
  96. package/dist/client/js/state/state.svelte.d.ts.map +1 -0
  97. package/dist/client/js/state/state.svelte.js +300 -0
  98. package/dist/client/js/state/theme.svelte.d.ts +24 -0
  99. package/dist/client/js/state/theme.svelte.d.ts.map +1 -0
  100. package/{src/client/js/state/theme.svelte.ts → dist/client/js/state/theme.svelte.js} +54 -91
  101. package/dist/client/js/storage/adapter.d.ts +130 -0
  102. package/dist/client/js/storage/adapter.d.ts.map +1 -0
  103. package/dist/client/js/storage/adapter.js +5 -0
  104. package/dist/client/js/storage/client.d.ts +72 -0
  105. package/dist/client/js/storage/client.d.ts.map +1 -0
  106. package/dist/client/js/storage/client.js +121 -0
  107. package/dist/client/js/storage/db.d.ts +8 -0
  108. package/dist/client/js/storage/db.d.ts.map +1 -0
  109. package/dist/client/js/storage/db.js +35 -0
  110. package/dist/client/js/storage/fsa.d.ts +51 -0
  111. package/dist/client/js/storage/fsa.d.ts.map +1 -0
  112. package/dist/client/js/storage/fsa.js +91 -0
  113. package/dist/client/js/storage/github.d.ts +62 -0
  114. package/dist/client/js/storage/github.d.ts.map +1 -0
  115. package/dist/client/js/storage/github.js +216 -0
  116. package/dist/client/js/storage/storage.d.ts +32 -0
  117. package/dist/client/js/storage/storage.d.ts.map +1 -0
  118. package/dist/client/js/storage/storage.js +68 -0
  119. package/dist/client/js/storage/workers/frontmatter.d.ts +2 -0
  120. package/dist/client/js/storage/workers/frontmatter.d.ts.map +1 -0
  121. package/dist/client/js/storage/workers/frontmatter.js +253 -0
  122. package/dist/client/js/storage/workers/storage.d.ts +2 -0
  123. package/dist/client/js/storage/workers/storage.d.ts.map +1 -0
  124. package/dist/client/js/storage/workers/storage.js +167 -0
  125. package/dist/client/js/storage/workers/toml-parser.d.ts +2 -0
  126. package/dist/client/js/storage/workers/toml-parser.d.ts.map +1 -0
  127. package/dist/client/js/storage/workers/toml-parser.js +75 -0
  128. package/dist/client/js/storage/workers/yaml-parser.d.ts +2 -0
  129. package/dist/client/js/storage/workers/yaml-parser.d.ts.map +1 -0
  130. package/dist/client/js/storage/workers/yaml-parser.js +100 -0
  131. package/dist/client/js/utils/file-types.d.ts +58 -0
  132. package/dist/client/js/utils/file-types.d.ts.map +1 -0
  133. package/{src/client/js/utils/file-types.ts → dist/client/js/utils/file-types.js} +75 -107
  134. package/dist/client/js/utils/format.d.ts +8 -0
  135. package/dist/client/js/utils/format.d.ts.map +1 -0
  136. package/{src/client/js/utils/format.ts → dist/client/js/utils/format.js} +5 -6
  137. package/dist/client/js/utils/frontmatter.d.ts +12 -0
  138. package/dist/client/js/utils/frontmatter.d.ts.map +1 -0
  139. package/dist/client/js/utils/frontmatter.js +29 -0
  140. package/dist/client/js/utils/schema-utils.d.ts +110 -0
  141. package/dist/client/js/utils/schema-utils.d.ts.map +1 -0
  142. package/dist/client/js/utils/schema-utils.js +242 -0
  143. package/dist/client/js/utils/slug.d.ts +8 -0
  144. package/dist/client/js/utils/slug.d.ts.map +1 -0
  145. package/{src/client/js/utils/slug.ts → dist/client/js/utils/slug.js} +6 -7
  146. package/dist/client/js/utils/sort.d.ts +41 -0
  147. package/dist/client/js/utils/sort.d.ts.map +1 -0
  148. package/dist/client/js/utils/sort.js +65 -0
  149. package/dist/client/js/utils/stable-stringify.d.ts +8 -0
  150. package/dist/client/js/utils/stable-stringify.d.ts.map +1 -0
  151. package/dist/client/js/utils/stable-stringify.js +23 -0
  152. package/dist/client/js/utils/url-utils.d.ts +11 -0
  153. package/dist/client/js/utils/url-utils.d.ts.map +1 -0
  154. package/{src/client/js/utils/url-utils.ts → dist/client/js/utils/url-utils.js} +22 -23
  155. package/dist/client/types/browser-apis.d.ts +39 -0
  156. package/dist/types.d.ts +22 -0
  157. package/dist/types.d.ts.map +1 -0
  158. package/dist/types.js +1 -0
  159. package/package.json +13 -3
  160. package/.github/workflows/ci.yml +0 -27
  161. package/.github/workflows/publish.yml +0 -34
  162. package/.mcp.json +0 -12
  163. package/.prettierignore +0 -5
  164. package/.prettierrc.cjs +0 -22
  165. package/AGENTS.md +0 -183
  166. package/playground/astro.config.mjs +0 -7
  167. package/playground/node_modules/.bin/astro +0 -21
  168. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js +0 -85
  169. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js.map +0 -7
  170. package/playground/node_modules/.vite/deps/_metadata.json +0 -184
  171. package/playground/node_modules/.vite/deps/astro___aria-query.js +0 -6776
  172. package/playground/node_modules/.vite/deps/astro___aria-query.js.map +0 -7
  173. package/playground/node_modules/.vite/deps/astro___axobject-query.js +0 -3754
  174. package/playground/node_modules/.vite/deps/astro___axobject-query.js.map +0 -7
  175. package/playground/node_modules/.vite/deps/astro___html-escaper.js +0 -34
  176. package/playground/node_modules/.vite/deps/astro___html-escaper.js.map +0 -7
  177. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js +0 -0
  178. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js.map +0 -7
  179. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js +0 -8
  180. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +0 -7
  181. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js +0 -21
  182. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js.map +0 -7
  183. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js +0 -223
  184. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js.map +0 -7
  185. package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js +0 -27
  186. package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js.map +0 -7
  187. package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js +0 -1005
  188. package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js.map +0 -7
  189. package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js +0 -204
  190. package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js.map +0 -7
  191. package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js +0 -688
  192. package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js.map +0 -7
  193. package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js +0 -5099
  194. package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js.map +0 -7
  195. package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js +0 -4376
  196. package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js.map +0 -7
  197. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js +0 -23
  198. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js.map +0 -7
  199. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js +0 -148
  200. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js.map +0 -7
  201. package/playground/node_modules/.vite/deps/package.json +0 -3
  202. package/playground/node_modules/.vite/deps/smol-toml.js +0 -843
  203. package/playground/node_modules/.vite/deps/smol-toml.js.map +0 -7
  204. package/playground/node_modules/.vite/deps/svelte.js +0 -55
  205. package/playground/node_modules/.vite/deps/svelte.js.map +0 -7
  206. package/playground/node_modules/.vite/deps/svelte___clsx.js +0 -9
  207. package/playground/node_modules/.vite/deps/svelte___clsx.js.map +0 -7
  208. package/playground/node_modules/.vite/deps/svelte_animate.js +0 -57
  209. package/playground/node_modules/.vite/deps/svelte_animate.js.map +0 -7
  210. package/playground/node_modules/.vite/deps/svelte_attachments.js +0 -15
  211. package/playground/node_modules/.vite/deps/svelte_attachments.js.map +0 -7
  212. package/playground/node_modules/.vite/deps/svelte_easing.js +0 -67
  213. package/playground/node_modules/.vite/deps/svelte_easing.js.map +0 -7
  214. package/playground/node_modules/.vite/deps/svelte_events.js +0 -11
  215. package/playground/node_modules/.vite/deps/svelte_events.js.map +0 -7
  216. package/playground/node_modules/.vite/deps/svelte_internal.js +0 -5
  217. package/playground/node_modules/.vite/deps/svelte_internal.js.map +0 -7
  218. package/playground/node_modules/.vite/deps/svelte_internal_client.js +0 -402
  219. package/playground/node_modules/.vite/deps/svelte_internal_client.js.map +0 -7
  220. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js +0 -10
  221. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js.map +0 -7
  222. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js +0 -8
  223. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js.map +0 -7
  224. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js +0 -8
  225. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js.map +0 -7
  226. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js +0 -8
  227. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js.map +0 -7
  228. package/playground/node_modules/.vite/deps/svelte_legacy.js +0 -35
  229. package/playground/node_modules/.vite/deps/svelte_legacy.js.map +0 -7
  230. package/playground/node_modules/.vite/deps/svelte_motion.js +0 -545
  231. package/playground/node_modules/.vite/deps/svelte_motion.js.map +0 -7
  232. package/playground/node_modules/.vite/deps/svelte_reactivity.js +0 -29
  233. package/playground/node_modules/.vite/deps/svelte_reactivity.js.map +0 -7
  234. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js +0 -127
  235. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js.map +0 -7
  236. package/playground/node_modules/.vite/deps/svelte_store.js +0 -103
  237. package/playground/node_modules/.vite/deps/svelte_store.js.map +0 -7
  238. package/playground/node_modules/.vite/deps/svelte_transition.js +0 -208
  239. package/playground/node_modules/.vite/deps/svelte_transition.js.map +0 -7
  240. package/playground/package.json +0 -16
  241. package/playground/pnpm-lock.yaml +0 -3167
  242. package/playground/src/content/authors/jane-doe.json +0 -8
  243. package/playground/src/content/config/build.toml +0 -2
  244. package/playground/src/content/courses/web-fundamentals.json +0 -29
  245. package/playground/src/content/docs/advanced.mdx +0 -6
  246. package/playground/src/content/docs/intro.md +0 -6
  247. package/playground/src/content/guides/getting-started.mdx +0 -6
  248. package/playground/src/content/posts/hello-world.md +0 -7
  249. package/playground/src/content/products/t-shirt.json +0 -16
  250. package/playground/src/content/recipes/pancakes.mdoc +0 -8
  251. package/playground/src/content/settings/site.yml +0 -2
  252. package/playground/src/content.config.ts +0 -198
  253. package/playground/src/env.d.ts +0 -1
  254. package/playground/src/pages/index.astro +0 -11
  255. package/playground/src/pages/nebula.astro +0 -14
  256. package/pnpm-workspace.yaml +0 -2
  257. package/scripts/subset-icons.mjs +0 -178
  258. package/src/astro/index.ts +0 -295
  259. package/src/client/js/drafts/merge.svelte.ts +0 -121
  260. package/src/client/js/drafts/ops.svelte.ts +0 -227
  261. package/src/client/js/drafts/storage.ts +0 -108
  262. package/src/client/js/drafts/workers/diff.ts +0 -40
  263. package/src/client/js/editor/editor.svelte.ts +0 -343
  264. package/src/client/js/editor/languages.ts +0 -98
  265. package/src/client/js/editor/markdown-shortcuts.ts +0 -261
  266. package/src/client/js/handlers/admin.ts +0 -246
  267. package/src/client/js/state/dialogs.svelte.ts +0 -35
  268. package/src/client/js/state/router.svelte.ts +0 -156
  269. package/src/client/js/state/state.svelte.ts +0 -334
  270. package/src/client/js/storage/adapter.ts +0 -102
  271. package/src/client/js/storage/client.ts +0 -150
  272. package/src/client/js/storage/db.ts +0 -36
  273. package/src/client/js/storage/fsa.ts +0 -110
  274. package/src/client/js/storage/github.ts +0 -297
  275. package/src/client/js/storage/storage.ts +0 -83
  276. package/src/client/js/storage/workers/frontmatter.ts +0 -320
  277. package/src/client/js/storage/workers/storage.ts +0 -177
  278. package/src/client/js/storage/workers/toml-parser.ts +0 -106
  279. package/src/client/js/storage/workers/yaml-parser.ts +0 -132
  280. package/src/client/js/utils/frontmatter.ts +0 -38
  281. package/src/client/js/utils/schema-utils.ts +0 -295
  282. package/src/client/js/utils/sort.ts +0 -84
  283. package/src/client/js/utils/stable-stringify.ts +0 -27
  284. package/src/types.ts +0 -25
  285. package/svelte.config.js +0 -4
  286. package/tests/astro/build.test.ts +0 -63
  287. package/tests/astro/index.test.ts +0 -689
  288. package/tests/client/components/Admin.test.ts +0 -446
  289. package/tests/client/components/BackendPicker.test.ts +0 -239
  290. package/tests/client/components/DraftChip.test.ts +0 -53
  291. package/tests/client/components/MetadataForm.test.ts +0 -164
  292. package/tests/client/components/dialogs/DeleteDraftDialog.test.ts +0 -91
  293. package/tests/client/components/dialogs/FilenameDialog.test.ts +0 -209
  294. package/tests/client/components/dialogs/dialog-stubs.ts +0 -19
  295. package/tests/client/components/editor/EditorPane.test.ts +0 -100
  296. package/tests/client/components/editor/EditorTabs.test.ts +0 -253
  297. package/tests/client/components/editor/EditorToolbar.test.ts +0 -252
  298. package/tests/client/components/editor/fixtures.ts +0 -31
  299. package/tests/client/components/fields/ArrayField.test.ts +0 -197
  300. package/tests/client/components/fields/BooleanField.test.ts +0 -206
  301. package/tests/client/components/fields/DateField.test.ts +0 -210
  302. package/tests/client/components/fields/EnumField.test.ts +0 -246
  303. package/tests/client/components/fields/NumberField.test.ts +0 -240
  304. package/tests/client/components/fields/ObjectField.test.ts +0 -157
  305. package/tests/client/components/fields/SchemaField.test.ts +0 -190
  306. package/tests/client/components/fields/StringField.test.ts +0 -223
  307. package/tests/client/components/sidebar/AdminSidebar.test.ts +0 -285
  308. package/tests/client/components/sidebar/AdminSidebarSort.test.ts +0 -135
  309. package/tests/client/components/sidebar/sort-mock.ts +0 -23
  310. package/tests/client/js/drafts/fixtures.ts +0 -22
  311. package/tests/client/js/drafts/merge.test.ts +0 -282
  312. package/tests/client/js/drafts/ops.test.ts +0 -658
  313. package/tests/client/js/drafts/storage.test.ts +0 -200
  314. package/tests/client/js/drafts/workers/diff.test.ts +0 -165
  315. package/tests/client/js/editor/editor.test.ts +0 -616
  316. package/tests/client/js/editor/link-wrap.test.ts +0 -225
  317. package/tests/client/js/editor/markdown-shortcuts.test.ts +0 -370
  318. package/tests/client/js/handlers/admin.test.ts +0 -467
  319. package/tests/client/js/state/router.test.ts +0 -619
  320. package/tests/client/js/state/schema.test.ts +0 -266
  321. package/tests/client/js/state/state.test.ts +0 -328
  322. package/tests/client/js/storage/adapter.test.ts +0 -115
  323. package/tests/client/js/storage/client.test.ts +0 -250
  324. package/tests/client/js/storage/db.test.ts +0 -59
  325. package/tests/client/js/storage/fsa.test.ts +0 -284
  326. package/tests/client/js/storage/github.test.ts +0 -349
  327. package/tests/client/js/storage/mock-port.ts +0 -95
  328. package/tests/client/js/storage/storage.test.ts +0 -77
  329. package/tests/client/js/storage/workers/frontmatter.test.ts +0 -479
  330. package/tests/client/js/storage/workers/storage.test.ts +0 -299
  331. package/tests/client/js/storage/workers/toml-parser.test.ts +0 -169
  332. package/tests/client/js/storage/workers/yaml-parser.test.ts +0 -168
  333. package/tests/client/js/utils/file-types.test.ts +0 -268
  334. package/tests/client/js/utils/frontmatter.test.ts +0 -87
  335. package/tests/client/js/utils/schema-utils.test.ts +0 -318
  336. package/tests/client/js/utils/slug.test.ts +0 -58
  337. package/tests/client/js/utils/sort.test.ts +0 -276
  338. package/tests/client/js/utils/stable-stringify.test.ts +0 -68
  339. package/tests/client/js/utils/url-utils.test.ts +0 -70
  340. package/tests/e2e/backend-connection.test.ts +0 -301
  341. package/tests/e2e/draft-lifecycle.test.ts +0 -388
  342. package/tests/e2e/editing.test.ts +0 -355
  343. package/tests/e2e/github-adapter.test.ts +0 -330
  344. package/tests/e2e/helpers/mock-adapter.ts +0 -166
  345. package/tests/e2e/helpers/test-app.ts +0 -155
  346. package/tests/e2e/navigation.test.ts +0 -358
  347. package/tests/e2e/publishing.test.ts +0 -345
  348. package/tests/e2e/unsaved-changes.test.ts +0 -317
  349. package/tests/setup.ts +0 -2
  350. package/tests/stubs/codemirror.ts +0 -197
  351. package/tsconfig.json +0 -19
  352. package/vitest.config.ts +0 -178
  353. /package/{src → dist}/client/components/BackendPicker.svelte +0 -0
  354. /package/{src → dist}/client/components/DraftChip.svelte +0 -0
  355. /package/{src → dist}/client/components/MetadataForm.svelte +0 -0
  356. /package/{src → dist}/client/components/ThemeToggle.svelte +0 -0
  357. /package/{src → dist}/client/components/dialogs/DeleteDraftDialog.svelte +0 -0
  358. /package/{src → dist}/client/components/editor/EditorPane.svelte +0 -0
  359. /package/{src → dist}/client/components/editor/EditorTabs.svelte +0 -0
  360. /package/{src → dist}/client/components/editor/EditorToolbar.svelte +0 -0
  361. /package/{src → dist}/client/components/editor/FormatSelector.svelte +0 -0
  362. /package/{src → dist}/client/components/editor/Toolbar.svelte +0 -0
  363. /package/{src → dist}/client/components/fields/ArrayField.svelte +0 -0
  364. /package/{src → dist}/client/components/fields/ArrayItem.svelte +0 -0
  365. /package/{src → dist}/client/components/fields/BooleanField.svelte +0 -0
  366. /package/{src → dist}/client/components/fields/DateField.svelte +0 -0
  367. /package/{src → dist}/client/components/fields/EnumField.svelte +0 -0
  368. /package/{src → dist}/client/components/fields/FieldWrapper.svelte +0 -0
  369. /package/{src → dist}/client/components/fields/NumberField.svelte +0 -0
  370. /package/{src → dist}/client/components/fields/ObjectField.svelte +0 -0
  371. /package/{src → dist}/client/components/fields/SchemaField.svelte +0 -0
  372. /package/{src → dist}/client/components/fields/StringField.svelte +0 -0
  373. /package/{src → dist}/client/components/sidebar/AdminSidebarSort.svelte +0 -0
  374. /package/{src → dist}/client/css/a11y.css +0 -0
  375. /package/{src → dist}/client/css/btn.css +0 -0
  376. /package/{src → dist}/client/css/dialog.css +0 -0
  377. /package/{src → dist}/client/css/field-input.css +0 -0
  378. /package/{src → dist}/client/css/reset.css +0 -0
  379. /package/{src → dist}/client/css/theme.css +0 -0
  380. /package/{src/client/index.ts → dist/client/index.js} +0 -0
  381. /package/{src → dist}/virtual.d.ts +0 -0
@@ -1,132 +0,0 @@
1
- /*
2
- * YAML Parser Worker
3
- *
4
- * Handles YAML parsing and serialization on behalf of the main thread.
5
- * Messages are dispatched by type: 'parse', 'parse-batch', 'stringify'.
6
- * Each handler wraps its logic in try/catch and always posts a typed result.
7
- */
8
-
9
- import { load, dump } from 'js-yaml';
10
-
11
- // Inbound message shape for a single YAML parse request.
12
- interface ParseMessage {
13
- type: 'parse';
14
- id: string;
15
- content: string;
16
- }
17
-
18
- // A single item in a batch parse request.
19
- interface BatchItem {
20
- key: string;
21
- content: string;
22
- }
23
-
24
- // Inbound message shape for a batch YAML parse request.
25
- interface ParseBatchMessage {
26
- type: 'parse-batch';
27
- id: string;
28
- items: BatchItem[];
29
- }
30
-
31
- // Inbound message shape for a YAML stringify request.
32
- interface StringifyMessage {
33
- type: 'stringify';
34
- id: string;
35
- data: Record<string, unknown>;
36
- }
37
-
38
- // Union of all inbound message types.
39
- type InboundMessage = ParseMessage | ParseBatchMessage | StringifyMessage;
40
-
41
- /*
42
- //////////////////////////////
43
- // Message handler
44
- //////////////////////////////
45
- */
46
-
47
- /**
48
- * Handles a single YAML parse request. Parses the provided content string
49
- * and posts a parse-result message with the resulting data object or error.
50
- * @param {ParseMessage} msg - The inbound parse message
51
- * @return {void}
52
- */
53
- function handleParse(msg: ParseMessage): void {
54
- try {
55
- const data = load(msg.content) as Record<string, unknown>;
56
- self.postMessage({ type: 'parse-result', id: msg.id, ok: true, data });
57
- } catch (err) {
58
- const error = err instanceof Error ? err.message : String(err);
59
- self.postMessage({ type: 'parse-result', id: msg.id, ok: false, error });
60
- }
61
- }
62
-
63
- /**
64
- * Handles a batch YAML parse request. Iterates over all items, parses each
65
- * one, and posts a parse-batch-result with a key-to-data results map.
66
- * If any item fails to parse, the entire batch result is marked as failed.
67
- * @param {ParseBatchMessage} msg - The inbound parse-batch message
68
- * @return {void}
69
- */
70
- function handleParseBatch(msg: ParseBatchMessage): void {
71
- try {
72
- const results: Record<string, Record<string, unknown>> = {};
73
- for (const item of msg.items) {
74
- results[item.key] = load(item.content) as Record<string, unknown>;
75
- }
76
- self.postMessage({
77
- type: 'parse-batch-result',
78
- id: msg.id,
79
- ok: true,
80
- results,
81
- });
82
- } catch (err) {
83
- const error = err instanceof Error ? err.message : String(err);
84
- self.postMessage({
85
- type: 'parse-batch-result',
86
- id: msg.id,
87
- ok: false,
88
- error,
89
- });
90
- }
91
- }
92
-
93
- /**
94
- * Handles a YAML stringify request. Serializes the provided data object to
95
- * a YAML string and posts a stringify-result message with the content.
96
- * lineWidth: -1 disables js-yaml's automatic line folding so long values
97
- * are not wrapped across lines, which would corrupt multi-line string values.
98
- * @param {StringifyMessage} msg - The inbound stringify message
99
- * @return {void}
100
- */
101
- function handleStringify(msg: StringifyMessage): void {
102
- try {
103
- const content = dump(msg.data, { lineWidth: -1 });
104
- self.postMessage({
105
- type: 'stringify-result',
106
- id: msg.id,
107
- ok: true,
108
- content,
109
- });
110
- } catch (err) {
111
- const error = err instanceof Error ? err.message : String(err);
112
- self.postMessage({
113
- type: 'stringify-result',
114
- id: msg.id,
115
- ok: false,
116
- error,
117
- });
118
- }
119
- }
120
-
121
- // Listen for messages from the main thread and dispatch by type
122
- self.addEventListener('message', (event: MessageEvent<InboundMessage>) => {
123
- const msg = event.data;
124
-
125
- if (msg.type === 'parse') {
126
- handleParse(msg);
127
- } else if (msg.type === 'parse-batch') {
128
- handleParseBatch(msg);
129
- } else if (msg.type === 'stringify') {
130
- handleStringify(msg);
131
- }
132
- });
@@ -1,38 +0,0 @@
1
- // Result of splitting a file into frontmatter and body.
2
- export type SplitResult = {
3
- rawFrontmatter: string;
4
- body: string;
5
- };
6
-
7
- /**
8
- * Splits a markdown/MDX file into raw YAML frontmatter and body content.
9
- * Handles BOM stripping, CRLF normalization, and horizontal rule rejection.
10
- * @param {string} content - Raw file content
11
- * @return {SplitResult} The separated frontmatter and body strings
12
- */
13
- export function splitFrontmatter(content: string): SplitResult {
14
- let str = content.startsWith('\uFEFF') ? content.slice(1) : content;
15
- str = str.replace(/\r\n/g, '\n');
16
-
17
- // Reject horizontal rules (----) and content not starting with frontmatter delimiter
18
- if (str.startsWith('----') || !str.startsWith('---\n')) {
19
- return { rawFrontmatter: '', body: str };
20
- }
21
-
22
- const closeIndex = str.indexOf('\n---\n', 3);
23
- if (closeIndex === -1) {
24
- // Check for --- at end of file with no trailing newline
25
- if (str.endsWith('\n---')) {
26
- return {
27
- rawFrontmatter: str.slice(4, str.length - 4),
28
- body: '',
29
- };
30
- }
31
- return { rawFrontmatter: '', body: str };
32
- }
33
-
34
- return {
35
- rawFrontmatter: str.slice(4, closeIndex),
36
- body: str.slice(closeIndex + 5),
37
- };
38
- }
@@ -1,295 +0,0 @@
1
- /*
2
- * Utilities for reading and resolving JSON Schema nodes.
3
- * Provides type resolution, path traversal, tab extraction, and
4
- * convenience accessors for common schema annotations.
5
- */
6
-
7
- import { toTitleCase } from './format';
8
-
9
- // A generic JSON Schema node represented as a plain object.
10
- export type SchemaNode = Record<string, unknown>;
11
-
12
- /**
13
- * Discriminated union describing the resolved type of a schema field. All variants carry an optional `nullable` flag set when the field was expressed as `anyOf: [<type>, { type: 'null' }]`.
14
- */
15
- export type FieldType =
16
- | { kind: 'string'; nullable?: boolean }
17
- | { kind: 'number'; nullable?: boolean }
18
- | { kind: 'boolean'; nullable?: boolean }
19
- | { kind: 'date'; nullable?: boolean }
20
- | { kind: 'enum'; options: string[]; nullable?: boolean }
21
- | { kind: 'array'; nullable?: boolean }
22
- | { kind: 'object'; nullable?: boolean }
23
- | { kind: 'unknown'; nullable?: boolean };
24
-
25
- /**
26
- * A path segment used to address nested values. Strings address object keys; numbers address array indices.
27
- */
28
- export type PathSegment = string | number;
29
-
30
- /*
31
- //////////////////////////////
32
- // resolveFieldType
33
- //////////////////////////////
34
- */
35
-
36
- /**
37
- * Resolves a JSON Schema node to a `FieldType` discriminated union.
38
- * Handles anyOf nullable unwrapping, enum detection, and date-time format.
39
- * @param {SchemaNode} schema - The JSON Schema node to resolve
40
- * @return {FieldType} The resolved field type descriptor
41
- */
42
- export function resolveFieldType(schema: SchemaNode): FieldType {
43
- // Unwrap nullable anyOf: [<innerType>, { type: 'null' }]
44
- const anyOf = schema['anyOf'];
45
- if (Array.isArray(anyOf)) {
46
- const nonNull = (anyOf as SchemaNode[]).find((s) => s['type'] !== 'null');
47
- if (nonNull) {
48
- const inner = resolveFieldType(nonNull);
49
- return { ...inner, nullable: true } as FieldType;
50
- }
51
- }
52
-
53
- const type = schema['type'] as string | undefined;
54
- const format = schema['format'] as string | undefined;
55
- const enumValues = schema['enum'];
56
-
57
- // date-time format takes precedence over plain string
58
- if (type === 'string' && format === 'date-time') {
59
- return { kind: 'date' };
60
- }
61
-
62
- // enum values present — treat as enum regardless of string subtype
63
- if (type === 'string' && Array.isArray(enumValues)) {
64
- return { kind: 'enum', options: enumValues as string[] };
65
- }
66
-
67
- if (type === 'string') return { kind: 'string' };
68
- if (type === 'number' || type === 'integer') return { kind: 'number' };
69
- if (type === 'boolean') return { kind: 'boolean' };
70
- if (type === 'array') return { kind: 'array' };
71
- if (type === 'object') return { kind: 'object' };
72
-
73
- return { kind: 'unknown' };
74
- }
75
-
76
- /*
77
- //////////////////////////////
78
- // extractTabs
79
- //////////////////////////////
80
- */
81
-
82
- /**
83
- * Scans an object schema's properties for `tab` arrays and returns a sorted, deduplicated list of all tab names found.
84
- * @param {SchemaNode} schema - A JSON Schema node with an optional `properties` map
85
- * @return {string[]} Sorted, deduplicated list of tab names
86
- */
87
- export function extractTabs(schema: SchemaNode): string[] {
88
- const properties = getProperties(schema);
89
- if (!properties) return [];
90
-
91
- const tabs = new Set<string>();
92
-
93
- for (const field of Object.values(properties)) {
94
- const tab = field['tab'];
95
- if (Array.isArray(tab)) {
96
- for (const name of tab as string[]) {
97
- tabs.add(name);
98
- }
99
- }
100
- }
101
-
102
- return Array.from(tabs).sort();
103
- }
104
-
105
- /*
106
- //////////////////////////////
107
- // createDefaultValue
108
- //////////////////////////////
109
- */
110
-
111
- /**
112
- * Returns a type-appropriate default value for a given JSON Schema node.
113
- * Honors `schema.default` when present, returns null for nullable types, and recurses into object properties.
114
- * @param {SchemaNode} schema - The JSON Schema node to generate a default value for
115
- * @return {unknown} A default value appropriate for the schema type
116
- */
117
- export function createDefaultValue(schema: SchemaNode): unknown {
118
- // Honour an explicit schema default first
119
- if ('default' in schema) {
120
- return schema['default'];
121
- }
122
-
123
- // Nullable anyOf — default to null
124
- const anyOf = schema['anyOf'];
125
- if (Array.isArray(anyOf)) {
126
- const hasNull = (anyOf as SchemaNode[]).some((s) => s['type'] === 'null');
127
- if (hasNull) return null;
128
- }
129
-
130
- const type = schema['type'] as string | undefined;
131
-
132
- if (type === 'string') return '';
133
- if (type === 'number' || type === 'integer') return 0;
134
- if (type === 'boolean') return false;
135
- if (type === 'array') return [];
136
-
137
- if (type === 'object') {
138
- const properties = getProperties(schema);
139
- if (!properties) return {};
140
- const result: Record<string, unknown> = {};
141
- for (const [key, fieldSchema] of Object.entries(properties)) {
142
- result[key] = createDefaultValue(fieldSchema);
143
- }
144
- return result;
145
- }
146
-
147
- return null;
148
- }
149
-
150
- /*
151
- //////////////////////////////
152
- // getByPath
153
- //////////////////////////////
154
- */
155
-
156
- /**
157
- * Reads a deeply nested value from an object by following path segments.
158
- * Returns `undefined` if any segment along the path is missing.
159
- * @param {unknown} obj - The root object to traverse
160
- * @param {PathSegment[]} path - Ordered path segments (string keys or numeric indices)
161
- * @return {unknown} The value at the resolved path, or undefined if any segment is missing
162
- */
163
- export function getByPath(obj: unknown, path: PathSegment[]): unknown {
164
- let current: unknown = obj;
165
- for (const segment of path) {
166
- if (current === null || current === undefined) return undefined;
167
- current = (current as Record<string | number, unknown>)[segment];
168
- }
169
- return current;
170
- }
171
-
172
- /*
173
- //////////////////////////////
174
- // setByPath
175
- //////////////////////////////
176
- */
177
-
178
- /**
179
- * Sets a deeply nested value in an object by following path segments, creating intermediate objects as needed.
180
- * @param {unknown} obj - The root object to mutate
181
- * @param {PathSegment[]} path - Ordered path segments (string keys or numeric indices)
182
- * @param {unknown} value - The value to assign at the resolved path
183
- * @return {void}
184
- */
185
- export function setByPath(
186
- obj: unknown,
187
- path: PathSegment[],
188
- value: unknown,
189
- ): void {
190
- if (path.length === 0) return;
191
-
192
- let current = obj as Record<string | number, unknown>;
193
-
194
- // Walk down to the parent of the final segment, creating objects as needed
195
- for (let i = 0; i < path.length - 1; i++) {
196
- const segment = path[i];
197
- if (current[segment] === null || current[segment] === undefined) {
198
- current[segment] = {};
199
- }
200
- current = current[segment] as Record<string | number, unknown>;
201
- }
202
-
203
- current[path[path.length - 1]] = value;
204
- }
205
-
206
- /*
207
- //////////////////////////////
208
- // getFieldsForTab
209
- //////////////////////////////
210
- */
211
-
212
- /**
213
- * Returns property names from a schema that belong to the given tab.
214
- * When `tab` is `null`, all property names are returned (no filtering — every field appears in the catch-all Metadata view).
215
- * @param {SchemaNode} schema - A JSON Schema node with an optional `properties` map
216
- * @param {string | null} tab - Tab name to filter by, or `null` to return all fields
217
- * @return {string[]} Array of property names belonging to the specified tab
218
- */
219
- export function getFieldsForTab(
220
- schema: SchemaNode,
221
- tab: string | null,
222
- ): string[] {
223
- const properties = getProperties(schema);
224
- if (!properties) return [];
225
-
226
- // Filter out $schema — it's a JSON Schema meta-property that Astro adds
227
- // to every generated schema, not a user-editable frontmatter field
228
- const keys = Object.keys(properties).filter((k) => k !== '$schema');
229
-
230
- // null means "all fields" — no tab filtering applied
231
- if (tab === null) {
232
- return keys;
233
- }
234
-
235
- return keys.filter((key) => {
236
- const fieldTab = properties[key]['tab'];
237
- return Array.isArray(fieldTab) && (fieldTab as string[]).includes(tab);
238
- });
239
- }
240
-
241
- /*
242
- //////////////////////////////
243
- // Schema property accessors
244
- //////////////////////////////
245
- */
246
-
247
- /**
248
- * Extracts the `properties` map from a schema node, with a safe cast.
249
- * @param {SchemaNode} schema - A JSON Schema node
250
- * @return {Record<string, SchemaNode> | undefined} The properties map, or undefined if absent
251
- */
252
- export function getProperties(
253
- schema: SchemaNode,
254
- ): Record<string, SchemaNode> | undefined {
255
- return schema['properties'] as Record<string, SchemaNode> | undefined;
256
- }
257
-
258
- /**
259
- * Extracts the `required` array from a schema node, returning an empty array if absent.
260
- * @param {SchemaNode} schema - A JSON Schema node
261
- * @return {string[]} Array of required property names
262
- */
263
- export function getRequiredFields(schema: SchemaNode): string[] {
264
- return Array.isArray(schema['required'])
265
- ? (schema['required'] as string[])
266
- : [];
267
- }
268
-
269
- /**
270
- * Returns whether a schema node is marked as read-only.
271
- * @param {SchemaNode} schema - A JSON Schema node
272
- * @return {boolean} True if the schema has readOnly set to true
273
- */
274
- export function isReadOnly(schema: SchemaNode): boolean {
275
- return !!(schema['readOnly'] as boolean | undefined);
276
- }
277
-
278
- /**
279
- * Returns whether a schema node was unwrapped from a nullable anyOf and flagged as nullable by SchemaField.
280
- * @param {SchemaNode} schema - A JSON Schema node (possibly annotated with _nullable)
281
- * @return {boolean} True if the schema has the _nullable annotation
282
- */
283
- export function isNullable(schema: SchemaNode): boolean {
284
- return !!(schema['_nullable'] as boolean | undefined);
285
- }
286
-
287
- /**
288
- * Returns the display label for a schema field — the schema title if present, otherwise the property name converted to title case.
289
- * @param {SchemaNode} schema - A JSON Schema node
290
- * @param {string} name - The raw property name used as a fallback
291
- * @return {string} The human-readable label
292
- */
293
- export function getLabel(schema: SchemaNode, name: string): string {
294
- return (schema['title'] as string | undefined) ?? toTitleCase(name);
295
- }
@@ -1,84 +0,0 @@
1
- /*
2
- * Sorting utilities and types for admin sidebar content lists.
3
- * Handles sort mode persistence, date coercion, and comparator generation.
4
- */
5
-
6
- // Sidebar item displayed as a link in the admin navigation. Used by AdminSidebar for both collections and content lists.
7
- export type SidebarItem = {
8
- label: string;
9
- href: string;
10
- subtitle?: string;
11
- date?: Date;
12
- // Draft-specific fields
13
- draftId?: string;
14
- isDraft?: boolean;
15
- isOutdated?: boolean;
16
- };
17
-
18
- // Sort mode identifiers.
19
- export type SortMode = 'alpha' | 'date-asc' | 'date-desc';
20
-
21
- // Sort mode configuration: icon name and display label
22
- export const SORT_MODES: Record<SortMode, { icon: string; label: string }> = {
23
- alpha: { icon: 'sort_by_alpha', label: 'Alphabetical' },
24
- 'date-asc': { icon: 'hourglass_arrow_down', label: 'Oldest first' },
25
- 'date-desc': { icon: 'hourglass_arrow_up', label: 'Newest first' },
26
- };
27
-
28
- // Fixed display order for sort options in the popover
29
- export const SORT_ORDER: SortMode[] = ['alpha', 'date-asc', 'date-desc'];
30
-
31
- /**
32
- * Reads the persisted sort mode from localStorage, defaulting to 'alpha' if absent or invalid.
33
- * @param {string} key - Collection name used to construct the storage key
34
- * @return {SortMode} The persisted sort mode, or 'alpha' if not set
35
- */
36
- export function readSortMode(key: string): SortMode {
37
- const stored = localStorage.getItem(`cms-sort-${key}`);
38
- if (stored === 'alpha' || stored === 'date-asc' || stored === 'date-desc') {
39
- return stored;
40
- }
41
- return 'alpha';
42
- }
43
-
44
- /**
45
- * Persists the sort mode to localStorage.
46
- * @param {string} key - Collection name used to construct the storage key
47
- * @param {SortMode} mode - The sort mode to persist
48
- * @return {void}
49
- */
50
- export function writeSortMode(key: string, mode: SortMode): void {
51
- localStorage.setItem(`cms-sort-${key}`, mode);
52
- }
53
-
54
- /**
55
- * Coerces a frontmatter published value (Date object or ISO string) into a Date for sorting. Returns undefined if the value is not a recognized date type.
56
- * @param {unknown} val - The published value from frontmatter
57
- * @return {Date | undefined} The resolved Date, or undefined
58
- */
59
- export function toSortDate(val: unknown): Date | undefined {
60
- if (val instanceof Date) return val;
61
- return typeof val === 'string' ? new Date(val) : undefined;
62
- }
63
-
64
- /**
65
- * Returns a comparator function for sorting SidebarItems by the given mode.
66
- * @param {SortMode} mode - The sort mode to use
67
- * @return {(a: SidebarItem, b: SidebarItem) => number} A comparator function suitable for Array.sort
68
- */
69
- export function createComparator(
70
- mode: SortMode,
71
- ): (a: SidebarItem, b: SidebarItem) => number {
72
- return (a, b) => {
73
- if (mode === 'date-asc' || mode === 'date-desc') {
74
- // Items without a date sort to the top (e.g. new drafts without a published date)
75
- if (!a.date && !b.date) return 0;
76
- if (!a.date) return -1;
77
- if (!b.date) return 1;
78
- return mode === 'date-asc'
79
- ? a.date.getTime() - b.date.getTime()
80
- : b.date.getTime() - a.date.getTime();
81
- }
82
- return a.label.toLowerCase().localeCompare(b.label.toLowerCase());
83
- };
84
- }
@@ -1,27 +0,0 @@
1
- /*
2
- * Deterministic JSON serialization with sorted keys.
3
- * Prevents false-positive outdated detection when comparing snapshots.
4
- */
5
-
6
- /**
7
- * Recursively sorts object keys and serializes to JSON.
8
- * Produces deterministic output regardless of key insertion order.
9
- * @param {unknown} value - The value to serialize
10
- * @return {string} A JSON string with sorted keys at every nesting level
11
- */
12
- export function stableStringify(value: unknown): string {
13
- return JSON.stringify(value, (_key, val) => {
14
- if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
15
- return Object.keys(val as Record<string, unknown>)
16
- .sort()
17
- .reduce(
18
- (sorted, k) => {
19
- sorted[k] = (val as Record<string, unknown>)[k];
20
- return sorted;
21
- },
22
- {} as Record<string, unknown>,
23
- );
24
- }
25
- return val;
26
- });
27
- }
package/src/types.ts DELETED
@@ -1,25 +0,0 @@
1
- /*
2
- * Configuration options for the nebula-cms Astro integration.
3
- */
4
- export interface NebulaCMSConfig {
5
- /**
6
- * URL prefix for the admin SPA.
7
- * Accepts a relative or absolute path. Normalized automatically: leading `/`
8
- * prepended if missing, consecutive slashes collapsed, trailing `/` stripped.
9
- * After normalization, must contain only segments of letters, digits, hyphens,
10
- * and underscores — or be `/` for root mount.
11
- * @default '/admin'
12
- */
13
- basePath?: string;
14
-
15
- /**
16
- * URL prefix under which collection schema files are served.
17
- * Accepts a relative or absolute path. Normalized automatically: leading `/`
18
- * prepended if missing, consecutive slashes collapsed, trailing `/` stripped.
19
- * After normalization, must contain only segments of letters, digits, hyphens,
20
- * and underscores. Cannot be `/` (root) — collections require at least one
21
- * path segment.
22
- * @default '/collections'
23
- */
24
- collectionsPath?: string;
25
- }
package/svelte.config.js DELETED
@@ -1,4 +0,0 @@
1
- /** @type {import('@sveltejs/package').Config} */
2
- const config = {};
3
-
4
- export default config;
@@ -1,63 +0,0 @@
1
- import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
- import { execFileSync } from 'node:child_process';
3
- import { resolve } from 'node:path';
4
- import { existsSync, readdirSync, readFileSync, rmSync } from 'node:fs';
5
-
6
- // Resolve playground path relative to this test file
7
- const playgroundDir = resolve(import.meta.dirname, '../../playground');
8
- const rootDir = resolve(playgroundDir, '..');
9
-
10
- describe('playground build integration', () => {
11
- beforeAll(() => {
12
- // Build root package so playground can resolve the nebula-cms integration.
13
- // The prebuild script generates icons.css automatically before svelte-package runs.
14
- execFileSync('pnpm', ['build'], { cwd: rootDir, stdio: 'pipe' });
15
- // Generate collection schemas, then build the Astro site
16
- execFileSync('pnpm', ['sync'], { cwd: playgroundDir, stdio: 'pipe' });
17
- execFileSync('pnpm', ['build'], { cwd: playgroundDir, stdio: 'pipe' });
18
- }, 60_000);
19
-
20
- afterAll(() => {
21
- const dist = resolve(playgroundDir, 'dist');
22
- if (existsSync(dist)) rmSync(dist, { recursive: true });
23
- });
24
-
25
- it('copies schema files into dist/collections/ via astro:build:done', () => {
26
- const distCollections = resolve(playgroundDir, 'dist/collections');
27
- expect(existsSync(distCollections)).toBe(true);
28
-
29
- const files = readdirSync(distCollections).filter((f) =>
30
- f.endsWith('.schema.json'),
31
- );
32
- const names = files.map((f) => f.replace('.schema.json', ''));
33
- expect(names).toContain('posts');
34
- expect(names).toContain('authors');
35
- });
36
-
37
- it('generates .schema.json for all four collections', () => {
38
- const collectionsDir = resolve(playgroundDir, '.astro/collections');
39
- const files = readdirSync(collectionsDir).filter((f) =>
40
- f.endsWith('.schema.json'),
41
- );
42
- const names = files.map((f) => f.replace('.schema.json', ''));
43
-
44
- expect(names).toContain('posts');
45
- expect(names).toContain('authors');
46
- expect(names).toContain('products');
47
- expect(names).toContain('courses');
48
- });
49
-
50
- it('bundles collection schema paths into the client JS', () => {
51
- // Admin uses client:only="svelte", so collection data lives in the JS
52
- // bundle via the virtual:collections module, not in the static HTML.
53
- const assetDir = resolve(playgroundDir, 'dist/_astro');
54
- const jsFiles = readdirSync(assetDir).filter((f) => f.endsWith('.js'));
55
- const allJs = jsFiles
56
- .map((f) => readFileSync(resolve(assetDir, f), 'utf-8'))
57
- .join('\n');
58
-
59
- for (const name of ['posts', 'authors', 'products', 'courses']) {
60
- expect(allJs).toContain(`/collections/${name}.schema.json`);
61
- }
62
- });
63
- });