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,616 +0,0 @@
1
- import { describe, it, expect, vi, afterEach } from 'vitest';
2
-
3
- //////////////////////////////
4
- // Editor module test strategy
5
- //
6
- // editor.svelte.ts calls registerDirtyChecker() at the top level when the
7
- // module is first evaluated, which requires the router to already be mocked.
8
- // The module also holds all state at module scope — to get a clean starting
9
- // state for each describe block that needs it we use vi.resetModules() +
10
- // dynamic import. All dependency mocks are declared here before static
11
- // imports so Vitest's vi.mock() hoisting guarantees they are in place.
12
- //////////////////////////////
13
-
14
- vi.mock('../../../../src/client/js/state/router.svelte', () => ({
15
- registerDirtyChecker: vi.fn(),
16
- adminPath: vi.fn((...segments) =>
17
- segments.length === 0 ? '/admin' : '/admin/' + segments.join('/'),
18
- ),
19
- }));
20
-
21
- vi.mock('../../../../src/client/js/utils/frontmatter', () => ({
22
- splitFrontmatter: vi.fn((text: string) => ({
23
- rawFrontmatter: '',
24
- body: text,
25
- })),
26
- }));
27
-
28
- vi.mock('../../../../src/client/js/utils/schema-utils', () => ({
29
- setByPath: vi.fn(
30
- (
31
- obj: Record<string, unknown>,
32
- path: (string | number)[],
33
- value: unknown,
34
- ) => {
35
- // Minimal real implementation so updateFormField tests work correctly
36
- let current = obj as Record<string | number, unknown>;
37
- for (let i = 0; i < path.length - 1; i++) {
38
- if (!current[path[i]]) current[path[i]] = {};
39
- current = current[path[i]] as Record<string | number, unknown>;
40
- }
41
- current[path[path.length - 1]] = value;
42
- },
43
- ),
44
- }));
45
-
46
- vi.mock('../../../../src/client/js/drafts/storage', () => ({
47
- getDraftByFile: vi.fn(async () => null),
48
- }));
49
-
50
- // storageClient is a direct object export (not a getter function), so the
51
- // mock uses a hoisted ref that tests swap between null and a fake client.
52
- const { mockStorageClientRef } = vi.hoisted(() => ({
53
- mockStorageClientRef: { current: null as any },
54
- }));
55
- vi.mock('../../../../src/client/js/state/state.svelte', () => ({
56
- get storageClient() {
57
- return mockStorageClientRef.current;
58
- },
59
- }));
60
-
61
- vi.mock(
62
- import('../../../../src/client/js/utils/file-types'),
63
- async (importOriginal) => ({
64
- ...(await importOriginal()),
65
- getFileCategory: vi.fn(() => null),
66
- }),
67
- );
68
-
69
- // ops.svelte re-exports — editor.svelte.ts re-exports these; mock them so
70
- // importing the editor does not pull in the real ops module's dependencies.
71
- vi.mock('../../../../src/client/js/drafts/ops.svelte', () => ({
72
- saveDraftToIDB: vi.fn(async () => undefined),
73
- saveFile: vi.fn(async () => undefined),
74
- publishFile: vi.fn(async () => undefined),
75
- loadDraftById: vi.fn(async () => undefined),
76
- deleteCurrentDraft: vi.fn(async () => undefined),
77
- }));
78
-
79
- import { getDraftByFile } from '../../../../src/client/js/drafts/storage';
80
- // storageClient import removed — tests configure mockStorageClientRef.current directly
81
- import { splitFrontmatter } from '../../../../src/client/js/utils/frontmatter';
82
- import { getFileCategory } from '../../../../src/client/js/utils/file-types';
83
-
84
- import type { Draft } from '../../../../src/client/js/drafts/storage';
85
-
86
- /**
87
- * Builds a minimal Draft fixture for editor tests.
88
- * @param {Partial<Draft>} overrides - Optional field overrides
89
- * @return {Draft} A complete Draft object
90
- */
91
- function makeDraft(overrides: Partial<Draft> = {}): Draft {
92
- return {
93
- id: 'ed-draft-01',
94
- collection: 'posts',
95
- filename: 'post.md',
96
- isNew: false,
97
- formData: { title: 'Draft Title' },
98
- body: 'Draft body content',
99
- snapshot: '{"body":"orig","formData":{"title":"Orig"}}',
100
- createdAt: '2026-01-01T00:00:00.000Z',
101
- ...overrides,
102
- };
103
- }
104
-
105
- //////////////////////////////
106
- // getEditorFile / formData — initial state
107
- //////////////////////////////
108
-
109
- describe('getEditorFile — initial state', () => {
110
- afterEach(() => {
111
- vi.resetModules();
112
- });
113
-
114
- it('returns null when no file has been opened', async () => {
115
- vi.resetModules();
116
- const { getEditorFile } =
117
- await import('../../../../src/client/js/editor/editor.svelte');
118
- expect(getEditorFile()).toBeNull();
119
- });
120
- });
121
-
122
- describe('formData — initial state', () => {
123
- afterEach(() => {
124
- vi.resetModules();
125
- });
126
-
127
- it('returns an empty object before any file is loaded', async () => {
128
- vi.resetModules();
129
- const { editor } =
130
- await import('../../../../src/client/js/editor/editor.svelte');
131
- expect(editor.data).toEqual({});
132
- });
133
- });
134
-
135
- //////////////////////////////
136
- // activeTab / setActiveTab
137
- //////////////////////////////
138
-
139
- describe('activeTab / setActiveTab', () => {
140
- afterEach(() => {
141
- vi.resetModules();
142
- });
143
-
144
- it('returns "metadata" as the default active tab', async () => {
145
- vi.resetModules();
146
- const { editor } =
147
- await import('../../../../src/client/js/editor/editor.svelte');
148
- expect(editor.tab).toBe('metadata');
149
- });
150
-
151
- it('updates the active tab via setActiveTab', async () => {
152
- vi.resetModules();
153
- const mod = await import('../../../../src/client/js/editor/editor.svelte');
154
- mod.setActiveTab('content');
155
- expect(mod.editor.tab).toBe('content');
156
- });
157
-
158
- it('can set any arbitrary tab string', async () => {
159
- vi.resetModules();
160
- const mod = await import('../../../../src/client/js/editor/editor.svelte');
161
- mod.setActiveTab('seo');
162
- expect(mod.editor.tab).toBe('seo');
163
- });
164
- });
165
-
166
- //////////////////////////////
167
- // applyEditorState
168
- //////////////////////////////
169
-
170
- describe('applyEditorState', () => {
171
- afterEach(() => {
172
- vi.resetModules();
173
- });
174
-
175
- it('opens the file and populates getEditorFile when open=true', async () => {
176
- vi.resetModules();
177
- const { applyEditorState, getEditorFile } =
178
- await import('../../../../src/client/js/editor/editor.svelte');
179
- applyEditorState(
180
- {
181
- body: 'Hello',
182
- formData: { title: 'T' },
183
- filename: 'test.md',
184
- bodyLoaded: true,
185
- draftId: null,
186
- isNewDraft: false,
187
- snapshot: null,
188
- collection: 'posts',
189
- draftCreatedAt: null,
190
- },
191
- true,
192
- );
193
- const file = getEditorFile();
194
- expect(file).not.toBeNull();
195
- expect(file?.body).toBe('Hello');
196
- expect(file?.filename).toBe('test.md');
197
- expect(file?.dirty).toBe(false);
198
- });
199
-
200
- it('resets activeTab to "metadata" on each apply', async () => {
201
- vi.resetModules();
202
- const mod = await import('../../../../src/client/js/editor/editor.svelte');
203
- mod.setActiveTab('content');
204
- mod.applyEditorState(
205
- {
206
- body: '',
207
- formData: {},
208
- filename: 'x.md',
209
- bodyLoaded: false,
210
- draftId: null,
211
- isNewDraft: false,
212
- snapshot: null,
213
- collection: 'posts',
214
- draftCreatedAt: null,
215
- },
216
- true,
217
- );
218
- expect(mod.editor.tab).toBe('metadata');
219
- });
220
-
221
- it('keeps getEditorFile null when open=false', async () => {
222
- vi.resetModules();
223
- const { applyEditorState, getEditorFile } =
224
- await import('../../../../src/client/js/editor/editor.svelte');
225
- applyEditorState(
226
- {
227
- body: '',
228
- formData: {},
229
- filename: '',
230
- bodyLoaded: false,
231
- draftId: null,
232
- isNewDraft: false,
233
- snapshot: null,
234
- collection: '',
235
- draftCreatedAt: null,
236
- },
237
- false,
238
- );
239
- expect(getEditorFile()).toBeNull();
240
- });
241
- });
242
-
243
- //////////////////////////////
244
- // updateFormField
245
- //////////////////////////////
246
-
247
- describe('updateFormField', () => {
248
- afterEach(() => {
249
- vi.resetModules();
250
- });
251
-
252
- it('updates a top-level formData field', async () => {
253
- vi.resetModules();
254
- const mod = await import('../../../../src/client/js/editor/editor.svelte');
255
- mod.applyEditorState(
256
- {
257
- body: '',
258
- formData: { title: 'Original' },
259
- filename: 'f.md',
260
- bodyLoaded: true,
261
- draftId: null,
262
- isNewDraft: false,
263
- snapshot: null,
264
- collection: 'posts',
265
- draftCreatedAt: null,
266
- },
267
- true,
268
- );
269
- mod.updateFormField(['title'], 'Updated');
270
- expect(mod.editor.data['title']).toBe('Updated');
271
- });
272
-
273
- it('marks the file dirty after a formData change', async () => {
274
- vi.resetModules();
275
- const { applyEditorState, updateFormField, getEditorFile } =
276
- await import('../../../../src/client/js/editor/editor.svelte');
277
- applyEditorState(
278
- {
279
- body: '',
280
- formData: { title: 'Same' },
281
- filename: 'f.md',
282
- bodyLoaded: true,
283
- draftId: null,
284
- isNewDraft: false,
285
- snapshot: null,
286
- collection: 'posts',
287
- draftCreatedAt: null,
288
- },
289
- true,
290
- );
291
- updateFormField(['title'], 'Different');
292
- expect(getEditorFile()?.dirty).toBe(true);
293
- });
294
- });
295
-
296
- //////////////////////////////
297
- // updateBody
298
- //////////////////////////////
299
-
300
- describe('updateBody', () => {
301
- afterEach(() => {
302
- vi.resetModules();
303
- });
304
-
305
- it('updates the body content', async () => {
306
- vi.resetModules();
307
- const { applyEditorState, updateBody, getEditorFile } =
308
- await import('../../../../src/client/js/editor/editor.svelte');
309
- applyEditorState(
310
- {
311
- body: 'original',
312
- formData: {},
313
- filename: 'f.md',
314
- bodyLoaded: true,
315
- draftId: null,
316
- isNewDraft: false,
317
- snapshot: null,
318
- collection: 'posts',
319
- draftCreatedAt: null,
320
- },
321
- true,
322
- );
323
- updateBody('new content');
324
- expect(getEditorFile()?.body).toBe('new content');
325
- });
326
-
327
- it('marks the file dirty when body differs from last saved', async () => {
328
- vi.resetModules();
329
- const { applyEditorState, updateBody, getEditorFile } =
330
- await import('../../../../src/client/js/editor/editor.svelte');
331
- applyEditorState(
332
- {
333
- body: 'saved',
334
- formData: {},
335
- filename: 'f.md',
336
- bodyLoaded: true,
337
- draftId: null,
338
- isNewDraft: false,
339
- snapshot: null,
340
- collection: 'posts',
341
- draftCreatedAt: null,
342
- },
343
- true,
344
- );
345
- updateBody('changed');
346
- expect(getEditorFile()?.dirty).toBe(true);
347
- });
348
-
349
- it('clears dirty when body is restored to last saved value', async () => {
350
- vi.resetModules();
351
- const { applyEditorState, updateBody, getEditorFile } =
352
- await import('../../../../src/client/js/editor/editor.svelte');
353
- applyEditorState(
354
- {
355
- body: 'saved body',
356
- formData: {},
357
- filename: 'f.md',
358
- bodyLoaded: true,
359
- draftId: null,
360
- isNewDraft: false,
361
- snapshot: null,
362
- collection: 'posts',
363
- draftCreatedAt: null,
364
- },
365
- true,
366
- );
367
- updateBody('changed');
368
- updateBody('saved body');
369
- expect(getEditorFile()?.dirty).toBe(false);
370
- });
371
- });
372
-
373
- //////////////////////////////
374
- // clearEditor
375
- //////////////////////////////
376
-
377
- describe('clearEditor', () => {
378
- afterEach(() => {
379
- vi.resetModules();
380
- });
381
-
382
- it('returns null from getEditorFile after clearing', async () => {
383
- vi.resetModules();
384
- const { applyEditorState, clearEditor, getEditorFile } =
385
- await import('../../../../src/client/js/editor/editor.svelte');
386
- applyEditorState(
387
- {
388
- body: 'content',
389
- formData: { title: 'T' },
390
- filename: 'f.md',
391
- bodyLoaded: true,
392
- draftId: null,
393
- isNewDraft: false,
394
- snapshot: null,
395
- collection: 'posts',
396
- draftCreatedAt: null,
397
- },
398
- true,
399
- );
400
- clearEditor();
401
- expect(getEditorFile()).toBeNull();
402
- });
403
-
404
- it('resets formData to empty object', async () => {
405
- vi.resetModules();
406
- const mod = await import('../../../../src/client/js/editor/editor.svelte');
407
- mod.applyEditorState(
408
- {
409
- body: '',
410
- formData: { title: 'X' },
411
- filename: 'f.md',
412
- bodyLoaded: true,
413
- draftId: null,
414
- isNewDraft: false,
415
- snapshot: null,
416
- collection: 'posts',
417
- draftCreatedAt: null,
418
- },
419
- true,
420
- );
421
- mod.clearEditor();
422
- expect(mod.editor.data).toEqual({});
423
- });
424
- });
425
-
426
- //////////////////////////////
427
- // preloadFile
428
- //////////////////////////////
429
-
430
- describe('preloadFile', () => {
431
- afterEach(() => {
432
- vi.resetModules();
433
- vi.clearAllMocks();
434
- });
435
-
436
- it('loads draft data when a draft exists for the file', async () => {
437
- vi.resetModules();
438
- const draft = makeDraft();
439
- vi.mocked(getDraftByFile).mockResolvedValue(draft);
440
-
441
- const { preloadFile, getEditorFile } =
442
- await import('../../../../src/client/js/editor/editor.svelte');
443
- await preloadFile('posts', 'post.md', { title: 'Live' });
444
-
445
- const file = getEditorFile();
446
- expect(file?.body).toBe(draft.body);
447
- expect(file?.formData).toEqual(draft.formData);
448
- expect(file?.draftId).toBe(draft.id);
449
- expect(file?.bodyLoaded).toBe(true);
450
- });
451
-
452
- it('loads live data when no draft exists', async () => {
453
- vi.resetModules();
454
- vi.mocked(getDraftByFile).mockResolvedValue(null);
455
-
456
- const { preloadFile, getEditorFile } =
457
- await import('../../../../src/client/js/editor/editor.svelte');
458
- await preloadFile('posts', 'live-file.md', { title: 'Live Title' });
459
-
460
- const file = getEditorFile();
461
- expect(file?.body).toBe('');
462
- expect(file?.formData).toEqual({ title: 'Live Title' });
463
- expect(file?.draftId).toBeNull();
464
- expect(file?.bodyLoaded).toBe(false);
465
- });
466
-
467
- it('is a no-op when the same file is already open', async () => {
468
- vi.resetModules();
469
- vi.mocked(getDraftByFile).mockResolvedValue(null);
470
-
471
- const { preloadFile } =
472
- await import('../../../../src/client/js/editor/editor.svelte');
473
- await preloadFile('posts', 'same.md', { title: 'First' });
474
-
475
- vi.clearAllMocks();
476
- await preloadFile('posts', 'same.md', { title: 'Second' });
477
-
478
- // getDraftByFile should not be called on the second preload of the same file
479
- expect(getDraftByFile).not.toHaveBeenCalled();
480
- });
481
- });
482
-
483
- //////////////////////////////
484
- // loadFileBody
485
- //////////////////////////////
486
-
487
- describe('loadFileBody', () => {
488
- afterEach(() => {
489
- vi.resetModules();
490
- vi.clearAllMocks();
491
- });
492
-
493
- it('does nothing when no storage client is connected', async () => {
494
- vi.resetModules();
495
- mockStorageClientRef.current = null;
496
- vi.mocked(getDraftByFile).mockResolvedValue(null);
497
-
498
- const { preloadFile, loadFileBody, getEditorFile } =
499
- await import('../../../../src/client/js/editor/editor.svelte');
500
- await preloadFile('posts', 'f.md', {});
501
- await loadFileBody('posts', 'f.md');
502
-
503
- // bodyLoaded should remain false since client was null
504
- expect(getEditorFile()?.bodyLoaded).toBe(false);
505
- });
506
-
507
- it('reads the file and updates body + bodyLoaded flag', async () => {
508
- vi.resetModules();
509
- vi.mocked(getDraftByFile).mockResolvedValue(null);
510
- vi.mocked(splitFrontmatter).mockReturnValue({
511
- rawFrontmatter: 'title: T',
512
- body: '\n\nThe markdown body\n\n',
513
- });
514
- const fakeClient = {
515
- readFile: vi.fn(
516
- async () => '---\ntitle: T\n---\n\nThe markdown body\n\n',
517
- ),
518
- };
519
- mockStorageClientRef.current = fakeClient;
520
-
521
- const { preloadFile, loadFileBody, getEditorFile } =
522
- await import('../../../../src/client/js/editor/editor.svelte');
523
- await preloadFile('posts', 'body-file.md', { title: 'T' });
524
- await loadFileBody('posts', 'body-file.md');
525
-
526
- const file = getEditorFile();
527
- expect(file?.bodyLoaded).toBe(true);
528
- // Leading/trailing newlines are stripped from the body
529
- expect(file?.body).toBe('The markdown body');
530
- });
531
-
532
- it('skips disk read and sets bodyLoaded for data-only files', async () => {
533
- vi.resetModules();
534
- vi.mocked(getDraftByFile).mockResolvedValue(null);
535
- // Simulate a data file — category is 'data', so no disk read should occur
536
- vi.mocked(getFileCategory).mockReturnValue('data');
537
- const fakeClient = {
538
- readFile: vi.fn(async () => '{}'),
539
- };
540
- mockStorageClientRef.current = fakeClient;
541
-
542
- const { preloadFile, loadFileBody, getEditorFile } =
543
- await import('../../../../src/client/js/editor/editor.svelte');
544
- await preloadFile('authors', 'jane.json', { name: 'Jane' });
545
- await loadFileBody('authors', 'jane.json');
546
-
547
- // readFile must not be called — data files have no body to read
548
- expect(fakeClient.readFile).not.toHaveBeenCalled();
549
- expect(getEditorFile()?.bodyLoaded).toBe(true);
550
- });
551
- });
552
-
553
- //////////////////////////////
554
- // _getDraftState / _setDraftState
555
- //////////////////////////////
556
-
557
- describe('_getDraftState / _setDraftState', () => {
558
- afterEach(() => {
559
- vi.resetModules();
560
- });
561
-
562
- it('_getDraftState returns current internal state snapshot', async () => {
563
- vi.resetModules();
564
- const { _getDraftState } =
565
- await import('../../../../src/client/js/editor/editor.svelte');
566
- const state = _getDraftState();
567
- expect(state).toHaveProperty('saving');
568
- expect(state).toHaveProperty('draftId');
569
- expect(state).toHaveProperty('isNewDraft');
570
- expect(state).toHaveProperty('snapshot');
571
- expect(state).toHaveProperty('currentCollection');
572
- expect(state).toHaveProperty('body');
573
- expect(state).toHaveProperty('formData');
574
- });
575
-
576
- it('_setDraftState updates the saving flag', async () => {
577
- vi.resetModules();
578
- const { _setDraftState, _getDraftState } =
579
- await import('../../../../src/client/js/editor/editor.svelte');
580
- _setDraftState({ saving: true });
581
- expect(_getDraftState().saving).toBe(true);
582
- _setDraftState({ saving: false });
583
- expect(_getDraftState().saving).toBe(false);
584
- });
585
-
586
- it('_setDraftState updates draftId', async () => {
587
- vi.resetModules();
588
- const { _setDraftState, _getDraftState } =
589
- await import('../../../../src/client/js/editor/editor.svelte');
590
- _setDraftState({ draftId: 'new-id' });
591
- expect(_getDraftState().draftId).toBe('new-id');
592
- });
593
-
594
- it('_setDraftState only mutates the specified fields', async () => {
595
- vi.resetModules();
596
- const { applyEditorState, _setDraftState, _getDraftState } =
597
- await import('../../../../src/client/js/editor/editor.svelte');
598
- applyEditorState(
599
- {
600
- body: 'body',
601
- formData: { title: 'T' },
602
- filename: 'f.md',
603
- bodyLoaded: true,
604
- draftId: null,
605
- isNewDraft: true,
606
- snapshot: null,
607
- collection: 'posts',
608
- draftCreatedAt: null,
609
- },
610
- true,
611
- );
612
- _setDraftState({ saving: true });
613
- // isNewDraft should be unchanged
614
- expect(_getDraftState().isNewDraft).toBe(true);
615
- });
616
- });