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,110 +0,0 @@
1
- /*
2
- * Storage adapter backed by the File System Access API.
3
- * Traverses from a project root handle through src/content/{collection}/ for all operations.
4
- */
5
-
6
- import type { StorageAdapter, FileEntry, FileWrite } from './adapter';
7
-
8
- // FSA adapter implementation
9
- export class FsaAdapter implements StorageAdapter {
10
- /**
11
- * Creates an FSA adapter rooted at the given directory handle.
12
- * @param {FileSystemDirectoryHandle} root - The project root directory handle
13
- */
14
- constructor(private root: FileSystemDirectoryHandle) {}
15
-
16
- /**
17
- * Traverses root → src → content → {collection}.
18
- * @param {string} collection - The collection name
19
- * @return {Promise<FileSystemDirectoryHandle>} The collection directory handle
20
- */
21
- private async getCollectionDir(
22
- collection: string,
23
- ): Promise<FileSystemDirectoryHandle> {
24
- const src = await this.root.getDirectoryHandle('src');
25
- const content = await src.getDirectoryHandle('content');
26
- return content.getDirectoryHandle(collection);
27
- }
28
-
29
- /**
30
- * Lists files in the collection matching the given extensions, with their content.
31
- * @param {string} collection - The collection name
32
- * @param {string[]} extensions - File extensions to include (e.g. ['.md', '.mdx'])
33
- * @return {Promise<FileEntry[]>} Array of filename + content pairs
34
- */
35
- async listFiles(
36
- collection: string,
37
- extensions: string[],
38
- ): Promise<FileEntry[]> {
39
- const dir = await this.getCollectionDir(collection);
40
- const entries: FileEntry[] = [];
41
-
42
- for await (const [name, entry] of dir.entries()) {
43
- if (
44
- entry.kind !== 'file' ||
45
- !extensions.some((ext) => name.endsWith(ext))
46
- ) {
47
- continue;
48
- }
49
- const file = await entry.getFile();
50
- const content = await file.text();
51
- entries.push({ filename: name, content });
52
- }
53
-
54
- return entries;
55
- }
56
-
57
- /**
58
- * Deletes a file from the collection directory.
59
- * @param {string} collection - The collection name
60
- * @param {string} filename - The filename to delete
61
- * @return {Promise<void>}
62
- */
63
- async deleteFile(collection: string, filename: string): Promise<void> {
64
- const dir = await this.getCollectionDir(collection);
65
- await dir.removeEntry(filename);
66
- }
67
-
68
- /**
69
- * Reads a single file's content from the collection.
70
- * @param {string} collection - The collection name
71
- * @param {string} filename - The filename
72
- * @return {Promise<string>} The file content
73
- */
74
- async readFile(collection: string, filename: string): Promise<string> {
75
- const dir = await this.getCollectionDir(collection);
76
- const fileHandle = await dir.getFileHandle(filename);
77
- const file = await fileHandle.getFile();
78
- return file.text();
79
- }
80
-
81
- /**
82
- * Writes content to a file, creating it if necessary.
83
- * @param {string} collection - The collection name
84
- * @param {string} filename - The filename
85
- * @param {string} content - The content to write
86
- * @return {Promise<void>}
87
- */
88
- async writeFile(
89
- collection: string,
90
- filename: string,
91
- content: string,
92
- ): Promise<void> {
93
- const dir = await this.getCollectionDir(collection);
94
- const fileHandle = await dir.getFileHandle(filename, { create: true });
95
- const writable = await fileHandle.createWritable();
96
- await writable.write(content);
97
- await writable.close();
98
- }
99
-
100
- /**
101
- * Writes multiple files sequentially (FSA has no atomic multi-file write).
102
- * @param {FileWrite[]} files - Array of files to write
103
- * @return {Promise<void>}
104
- */
105
- async writeFiles(files: FileWrite[]): Promise<void> {
106
- for (const f of files) {
107
- await this.writeFile(f.collection, f.filename, f.content);
108
- }
109
- }
110
- }
@@ -1,297 +0,0 @@
1
- /*
2
- * Storage adapter backed by the GitHub REST API.
3
- * Uses a Personal Access Token for authentication. All file operations
4
- * target src/content/{collection}/ within the repository.
5
- */
6
-
7
- import type { StorageAdapter, FileEntry, FileWrite } from './adapter';
8
-
9
- /**
10
- * Encodes a Uint8Array to a base64 string without using deprecated unescape().
11
- * @param {Uint8Array} bytes - The bytes to encode
12
- * @return {string} Base64-encoded string
13
- */
14
- function uint8ToBase64(bytes: Uint8Array): string {
15
- let binary = '';
16
- for (const byte of bytes) binary += String.fromCharCode(byte);
17
- return btoa(binary);
18
- }
19
-
20
- export class GitHubAdapter implements StorageAdapter {
21
- private token: string;
22
- private owner: string;
23
- private repo: string;
24
- // Cached on validate(); defaults to 'main' before validation
25
- private defaultBranch: string = 'main';
26
-
27
- /**
28
- * @param {string} token - GitHub Personal Access Token
29
- * @param {string} repoSlug - Repository in "owner/repo" format
30
- */
31
- constructor(token: string, repoSlug: string) {
32
- this.token = token;
33
- const [owner, repo] = repoSlug.split('/');
34
- this.owner = owner;
35
- this.repo = repo;
36
- }
37
-
38
- /**
39
- * Validates credentials by fetching repo metadata and caches the default branch.
40
- * @return {Promise<void>}
41
- */
42
- async validate(): Promise<void> {
43
- const res = await this.request('GET', `/repos/${this.owner}/${this.repo}`);
44
- if (!res.ok) {
45
- const status = res.status;
46
- if (status === 401) throw new Error('Invalid or expired token');
47
- if (status === 403) throw new Error('Token lacks repository access');
48
- if (status === 404)
49
- throw new Error(`Repository "${this.owner}/${this.repo}" not found`);
50
- throw new Error(`GitHub API error: ${status}`);
51
- }
52
- const data = await res.json();
53
- this.defaultBranch = data.default_branch;
54
- }
55
-
56
- /**
57
- * Lists files in a collection matching the given extensions, with their raw content.
58
- * @param {string} collection - The collection name
59
- * @param {string[]} extensions - File extensions to include (e.g. ['.md', '.mdx'])
60
- * @return {Promise<FileEntry[]>} Array of filename + content pairs
61
- */
62
- async listFiles(
63
- collection: string,
64
- extensions: string[],
65
- ): Promise<FileEntry[]> {
66
- const path = `src/content/${collection}`;
67
- // Get directory listing
68
- const listRes = await this.request(
69
- 'GET',
70
- `/repos/${this.owner}/${this.repo}/contents/${path}?ref=${this.defaultBranch}`,
71
- );
72
- if (!listRes.ok) {
73
- if (listRes.status === 404) return [];
74
- throw new Error(`Failed to list files: ${listRes.status}`);
75
- }
76
- const listing: Array<{ name: string; download_url: string }> =
77
- await listRes.json();
78
-
79
- // Filter to requested extensions and fetch all files in parallel
80
- const filtered = listing.filter((f) =>
81
- extensions.some((ext) => f.name.endsWith(ext)),
82
- );
83
-
84
- return Promise.all(
85
- filtered.map(async (file) => ({
86
- filename: file.name,
87
- content: await this.readFile(collection, file.name),
88
- })),
89
- );
90
- }
91
-
92
- /**
93
- * Deletes a file from the repository via the Contents API.
94
- * @param {string} collection - The collection name
95
- * @param {string} filename - The filename to delete
96
- * @return {Promise<void>}
97
- */
98
- async deleteFile(collection: string, filename: string): Promise<void> {
99
- const path = `src/content/${collection}/${filename}`;
100
- // Get the current SHA (required by the GitHub Contents API for deletion)
101
- const existing = await this.request(
102
- 'GET',
103
- `/repos/${this.owner}/${this.repo}/contents/${path}?ref=${this.defaultBranch}`,
104
- );
105
- if (!existing.ok) throw new Error(`File not found for deletion: ${path}`);
106
- const data = await existing.json();
107
-
108
- const res = await this.request(
109
- 'DELETE',
110
- `/repos/${this.owner}/${this.repo}/contents/${path}`,
111
- undefined,
112
- {
113
- message: `Delete ${path}`,
114
- sha: data.sha,
115
- branch: this.defaultBranch,
116
- },
117
- );
118
- if (!res.ok) throw new Error(`Failed to delete ${path}: ${res.status}`);
119
- }
120
-
121
- /**
122
- * Reads a single file's raw content via the raw+json Accept header.
123
- * @param {string} collection - The collection name
124
- * @param {string} filename - The filename
125
- * @return {Promise<string>} The file content
126
- */
127
- async readFile(collection: string, filename: string): Promise<string> {
128
- const path = `src/content/${collection}/${filename}`;
129
- const res = await this.request(
130
- 'GET',
131
- `/repos/${this.owner}/${this.repo}/contents/${path}?ref=${this.defaultBranch}`,
132
- { Accept: 'application/vnd.github.raw+json' },
133
- );
134
- if (!res.ok) {
135
- throw new Error(`Failed to read ${path}: ${res.status}`);
136
- }
137
- return res.text();
138
- }
139
-
140
- /**
141
- * Writes a single file via the Contents API. Fetches the current SHA for updates.
142
- * @param {string} collection - The collection name
143
- * @param {string} filename - The filename
144
- * @param {string} content - The content to write
145
- * @return {Promise<void>}
146
- */
147
- async writeFile(
148
- collection: string,
149
- filename: string,
150
- content: string,
151
- ): Promise<void> {
152
- const path = `src/content/${collection}/${filename}`;
153
- // Get current SHA if file exists (required by GitHub API for updates)
154
- let sha: string | undefined;
155
- const existing = await this.request(
156
- 'GET',
157
- `/repos/${this.owner}/${this.repo}/contents/${path}?ref=${this.defaultBranch}`,
158
- );
159
- if (existing.ok) {
160
- const data = await existing.json();
161
- sha = data.sha;
162
- }
163
-
164
- const body: Record<string, string> = {
165
- message: `Update ${path}`,
166
- content: uint8ToBase64(new TextEncoder().encode(content)),
167
- branch: this.defaultBranch,
168
- };
169
- if (sha) body.sha = sha;
170
-
171
- const res = await this.request(
172
- 'PUT',
173
- `/repos/${this.owner}/${this.repo}/contents/${path}`,
174
- undefined,
175
- body,
176
- );
177
- if (!res.ok) {
178
- const errText = await res.text();
179
- throw new Error(`Failed to write ${path}: ${res.status} ${errText}`);
180
- }
181
- }
182
-
183
- /**
184
- * Writes multiple files in a single atomic commit using the Git Trees + Commits API.
185
- * @param {FileWrite[]} files - Array of files to write
186
- * @return {Promise<void>}
187
- */
188
- async writeFiles(files: FileWrite[]): Promise<void> {
189
- if (files.length === 0) return;
190
- if (files.length === 1) {
191
- await this.writeFile(
192
- files[0].collection,
193
- files[0].filename,
194
- files[0].content,
195
- );
196
- return;
197
- }
198
-
199
- // 1. Get current commit SHA for the default branch
200
- const refRes = await this.request(
201
- 'GET',
202
- `/repos/${this.owner}/${this.repo}/git/ref/heads/${this.defaultBranch}`,
203
- );
204
- if (!refRes.ok)
205
- throw new Error(`Failed to get branch ref: ${refRes.status}`);
206
- const refData = await refRes.json();
207
- const baseCommitSHA = refData.object.sha;
208
-
209
- // Get the base tree SHA from the current commit
210
- const commitRes = await this.request(
211
- 'GET',
212
- `/repos/${this.owner}/${this.repo}/git/commits/${baseCommitSHA}`,
213
- );
214
- if (!commitRes.ok)
215
- throw new Error(`Failed to get commit: ${commitRes.status}`);
216
- const commitData = await commitRes.json();
217
- const baseTreeSHA = commitData.tree.sha;
218
-
219
- // 2. Create a new tree containing all file changes
220
- const tree = files.map((f) => ({
221
- path: `src/content/${f.collection}/${f.filename}`,
222
- mode: '100644' as const,
223
- type: 'blob' as const,
224
- content: f.content,
225
- }));
226
-
227
- const treeRes = await this.request(
228
- 'POST',
229
- `/repos/${this.owner}/${this.repo}/git/trees`,
230
- undefined,
231
- { base_tree: baseTreeSHA, tree },
232
- );
233
- if (!treeRes.ok)
234
- throw new Error(`Failed to create tree: ${treeRes.status}`);
235
- const treeData = await treeRes.json();
236
-
237
- // 3. Create a new commit pointing at the new tree
238
- const paths = files.map((f) => `${f.collection}/${f.filename}`).join(', ');
239
- const newCommitRes = await this.request(
240
- 'POST',
241
- `/repos/${this.owner}/${this.repo}/git/commits`,
242
- undefined,
243
- {
244
- message: `Update ${paths}`,
245
- tree: treeData.sha,
246
- parents: [baseCommitSHA],
247
- },
248
- );
249
- if (!newCommitRes.ok)
250
- throw new Error(`Failed to create commit: ${newCommitRes.status}`);
251
- const newCommitData = await newCommitRes.json();
252
-
253
- // 4. Advance the branch ref to the new commit
254
- const updateRefRes = await this.request(
255
- 'PATCH',
256
- `/repos/${this.owner}/${this.repo}/git/refs/heads/${this.defaultBranch}`,
257
- undefined,
258
- { sha: newCommitData.sha },
259
- );
260
- if (!updateRefRes.ok)
261
- throw new Error(`Failed to update ref: ${updateRefRes.status}`);
262
- }
263
-
264
- /**
265
- * Makes an authenticated request to the GitHub API.
266
- * @param {string} method - HTTP method
267
- * @param {string} path - API path (appended to https://api.github.com)
268
- * @param {Record<string, string>} [extraHeaders] - Additional headers to merge
269
- * @param {unknown} [body] - JSON body to send
270
- * @return {Promise<Response>} The fetch response
271
- */
272
- private async request(
273
- method: string,
274
- path: string,
275
- extraHeaders?: Record<string, string>,
276
- body?: unknown,
277
- ): Promise<Response> {
278
- const headers: Record<string, string> = {
279
- Authorization: `Bearer ${this.token}`,
280
- 'X-GitHub-Api-Version': '2026-03-10',
281
- // Default to JSON so the browser cache distinguishes from raw content requests
282
- Accept: 'application/vnd.github+json',
283
- ...extraHeaders,
284
- };
285
- if (body) {
286
- headers['Content-Type'] = 'application/json';
287
- }
288
-
289
- return fetch(`https://api.github.com${path}`, {
290
- method,
291
- headers,
292
- body: body ? JSON.stringify(body) : undefined,
293
- // API responses must never be served from browser cache
294
- cache: 'no-store',
295
- });
296
- }
297
- }
@@ -1,83 +0,0 @@
1
- /*
2
- * Backend configuration persistence using IndexedDB.
3
- * Stores and retrieves the active storage backend (FSA or GitHub).
4
- */
5
-
6
- import { openDB } from './db';
7
-
8
- // Fixed key for the backend config
9
- const BACKEND_KEY = 'backend';
10
-
11
- /**
12
- * Backend configuration stored in IndexedDB. Tagged union discriminated on `type`.
13
- * Security note: the GitHub token is stored in plaintext in IndexedDB. This is a
14
- * deliberate trade-off for a client-only app with no server to proxy through.
15
- * Same-origin policy protects it from other sites, but any XSS vulnerability
16
- * would expose the token.
17
- */
18
- export type BackendConfig =
19
- | { type: 'fsa'; handle: FileSystemDirectoryHandle }
20
- | { type: 'github'; token: string; repo: string };
21
-
22
- /**
23
- * Stores backend configuration in IndexedDB for persistence across sessions.
24
- * @param {BackendConfig} config - The backend config to store
25
- * @return {Promise<void>}
26
- */
27
- export async function saveBackend(config: BackendConfig): Promise<void> {
28
- const db = await openDB();
29
- return new Promise((resolve, reject) => {
30
- const tx = db.transaction('handles', 'readwrite');
31
- tx.objectStore('handles').put(config, BACKEND_KEY);
32
- tx.oncomplete = () => resolve();
33
- tx.onerror = () => reject(tx.error);
34
- });
35
- }
36
-
37
- /**
38
- * Retrieves stored backend configuration from IndexedDB. Handles migration from the old format where a bare FileSystemDirectoryHandle was stored.
39
- * @return {Promise<BackendConfig | null>} The stored config, or null if none exists
40
- */
41
- export async function loadBackend(): Promise<BackendConfig | null> {
42
- const db = await openDB();
43
- return new Promise((resolve, reject) => {
44
- const tx = db.transaction('handles', 'readonly');
45
- const request = tx.objectStore('handles').get(BACKEND_KEY);
46
- request.onsuccess = () => {
47
- const result = request.result;
48
- if (!result) {
49
- // Check for old-format handle stored under the legacy key
50
- const legacyRequest = tx.objectStore('handles').get('projectRoot');
51
- legacyRequest.onsuccess = () => {
52
- const legacy = legacyRequest.result;
53
- if (legacy && legacy instanceof FileSystemDirectoryHandle) {
54
- resolve({ type: 'fsa', handle: legacy });
55
- } else {
56
- resolve(null);
57
- }
58
- };
59
- legacyRequest.onerror = () => resolve(null);
60
- return;
61
- }
62
- resolve(result as BackendConfig);
63
- };
64
- request.onerror = () => reject(request.error);
65
- });
66
- }
67
-
68
- /**
69
- * Removes the stored backend configuration from IndexedDB. Also clears the legacy key if present.
70
- * @return {Promise<void>}
71
- */
72
- export async function clearBackend(): Promise<void> {
73
- const db = await openDB();
74
- return new Promise((resolve, reject) => {
75
- const tx = db.transaction('handles', 'readwrite');
76
- const store = tx.objectStore('handles');
77
- store.delete(BACKEND_KEY);
78
- // Clean up legacy key if present
79
- store.delete('projectRoot');
80
- tx.oncomplete = () => resolve();
81
- tx.onerror = () => reject(tx.error);
82
- });
83
- }