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.
- package/README.md +3 -1
- package/dist/astro/index.d.ts +43 -0
- package/dist/astro/index.d.ts.map +1 -0
- package/dist/astro/index.js +223 -0
- package/{src → dist}/client/Admin.svelte +20 -11
- package/dist/client/Admin.svelte.d.ts +11 -0
- package/dist/client/Admin.svelte.d.ts.map +1 -0
- package/dist/client/components/BackendPicker.svelte.d.ts +4 -0
- package/dist/client/components/BackendPicker.svelte.d.ts.map +1 -0
- package/dist/client/components/DraftChip.svelte.d.ts +10 -0
- package/dist/client/components/DraftChip.svelte.d.ts.map +1 -0
- package/dist/client/components/MetadataForm.svelte.d.ts +12 -0
- package/dist/client/components/MetadataForm.svelte.d.ts.map +1 -0
- package/dist/client/components/ThemeToggle.svelte.d.ts +19 -0
- package/dist/client/components/ThemeToggle.svelte.d.ts.map +1 -0
- package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts +11 -0
- package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts.map +1 -0
- package/{src → dist}/client/components/dialogs/FilenameDialog.svelte +1 -2
- package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts +13 -0
- package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts.map +1 -0
- package/dist/client/components/editor/EditorPane.svelte.d.ts +4 -0
- package/dist/client/components/editor/EditorPane.svelte.d.ts.map +1 -0
- package/dist/client/components/editor/EditorTabs.svelte.d.ts +8 -0
- package/dist/client/components/editor/EditorTabs.svelte.d.ts.map +1 -0
- package/dist/client/components/editor/EditorToolbar.svelte.d.ts +4 -0
- package/dist/client/components/editor/EditorToolbar.svelte.d.ts.map +1 -0
- package/dist/client/components/editor/FormatSelector.svelte.d.ts +4 -0
- package/dist/client/components/editor/FormatSelector.svelte.d.ts.map +1 -0
- package/dist/client/components/editor/Toolbar.svelte.d.ts +19 -0
- package/dist/client/components/editor/Toolbar.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/ArrayField.svelte.d.ts +15 -0
- package/dist/client/components/fields/ArrayField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/ArrayItem.svelte.d.ts +28 -0
- package/dist/client/components/fields/ArrayItem.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/BooleanField.svelte.d.ts +16 -0
- package/dist/client/components/fields/BooleanField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/DateField.svelte.d.ts +16 -0
- package/dist/client/components/fields/DateField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/EnumField.svelte.d.ts +17 -0
- package/dist/client/components/fields/EnumField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/FieldWrapper.svelte.d.ts +18 -0
- package/dist/client/components/fields/FieldWrapper.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/NumberField.svelte.d.ts +16 -0
- package/dist/client/components/fields/NumberField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/ObjectField.svelte.d.ts +16 -0
- package/dist/client/components/fields/ObjectField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/SchemaField.svelte.d.ts +16 -0
- package/dist/client/components/fields/SchemaField.svelte.d.ts.map +1 -0
- package/dist/client/components/fields/StringField.svelte.d.ts +16 -0
- package/dist/client/components/fields/StringField.svelte.d.ts.map +1 -0
- package/{src → dist}/client/components/sidebar/AdminSidebar.svelte +2 -4
- package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts +19 -0
- package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts.map +1 -0
- package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts +12 -0
- package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts.map +1 -0
- package/dist/client/css/icons.css +29 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/js/drafts/merge.svelte.d.ts +24 -0
- package/dist/client/js/drafts/merge.svelte.d.ts.map +1 -0
- package/dist/client/js/drafts/merge.svelte.js +106 -0
- package/dist/client/js/drafts/ops.svelte.d.ts +31 -0
- package/dist/client/js/drafts/ops.svelte.d.ts.map +1 -0
- package/dist/client/js/drafts/ops.svelte.js +182 -0
- package/dist/client/js/drafts/storage.d.ts +45 -0
- package/dist/client/js/drafts/storage.d.ts.map +1 -0
- package/dist/client/js/drafts/storage.js +76 -0
- package/dist/client/js/drafts/workers/diff.d.ts +2 -0
- package/dist/client/js/drafts/workers/diff.d.ts.map +1 -0
- package/dist/client/js/drafts/workers/diff.js +20 -0
- package/dist/client/js/editor/editor.svelte.d.ts +124 -0
- package/dist/client/js/editor/editor.svelte.d.ts.map +1 -0
- package/dist/client/js/editor/editor.svelte.js +294 -0
- package/dist/client/js/editor/languages.d.ts +11 -0
- package/dist/client/js/editor/languages.d.ts.map +1 -0
- package/dist/client/js/editor/languages.js +93 -0
- package/dist/client/js/editor/link-wrap.d.ts +6 -0
- package/dist/client/js/editor/link-wrap.d.ts.map +1 -0
- package/{src/client/js/editor/link-wrap.ts → dist/client/js/editor/link-wrap.js} +17 -24
- package/dist/client/js/editor/markdown-shortcuts.d.ts +4 -0
- package/dist/client/js/editor/markdown-shortcuts.d.ts.map +1 -0
- package/dist/client/js/editor/markdown-shortcuts.js +219 -0
- package/dist/client/js/handlers/admin.d.ts +64 -0
- package/dist/client/js/handlers/admin.d.ts.map +1 -0
- package/dist/client/js/handlers/admin.js +186 -0
- package/dist/client/js/state/dialogs.svelte.d.ts +16 -0
- package/dist/client/js/state/dialogs.svelte.d.ts.map +1 -0
- package/dist/client/js/state/dialogs.svelte.js +28 -0
- package/dist/client/js/state/router.svelte.d.ts +44 -0
- package/dist/client/js/state/router.svelte.d.ts.map +1 -0
- package/dist/client/js/state/router.svelte.js +141 -0
- package/dist/client/js/state/schema.svelte.d.ts +51 -0
- package/dist/client/js/state/schema.svelte.d.ts.map +1 -0
- package/{src/client/js/state/schema.svelte.ts → dist/client/js/state/schema.svelte.js} +55 -70
- package/dist/client/js/state/state.svelte.d.ts +68 -0
- package/dist/client/js/state/state.svelte.d.ts.map +1 -0
- package/dist/client/js/state/state.svelte.js +300 -0
- package/dist/client/js/state/theme.svelte.d.ts +24 -0
- package/dist/client/js/state/theme.svelte.d.ts.map +1 -0
- package/{src/client/js/state/theme.svelte.ts → dist/client/js/state/theme.svelte.js} +54 -91
- package/dist/client/js/storage/adapter.d.ts +130 -0
- package/dist/client/js/storage/adapter.d.ts.map +1 -0
- package/dist/client/js/storage/adapter.js +5 -0
- package/dist/client/js/storage/client.d.ts +72 -0
- package/dist/client/js/storage/client.d.ts.map +1 -0
- package/dist/client/js/storage/client.js +121 -0
- package/dist/client/js/storage/db.d.ts +8 -0
- package/dist/client/js/storage/db.d.ts.map +1 -0
- package/dist/client/js/storage/db.js +35 -0
- package/dist/client/js/storage/fsa.d.ts +51 -0
- package/dist/client/js/storage/fsa.d.ts.map +1 -0
- package/dist/client/js/storage/fsa.js +91 -0
- package/dist/client/js/storage/github.d.ts +62 -0
- package/dist/client/js/storage/github.d.ts.map +1 -0
- package/dist/client/js/storage/github.js +216 -0
- package/dist/client/js/storage/storage.d.ts +32 -0
- package/dist/client/js/storage/storage.d.ts.map +1 -0
- package/dist/client/js/storage/storage.js +68 -0
- package/dist/client/js/storage/workers/frontmatter.d.ts +2 -0
- package/dist/client/js/storage/workers/frontmatter.d.ts.map +1 -0
- package/dist/client/js/storage/workers/frontmatter.js +253 -0
- package/dist/client/js/storage/workers/storage.d.ts +2 -0
- package/dist/client/js/storage/workers/storage.d.ts.map +1 -0
- package/dist/client/js/storage/workers/storage.js +167 -0
- package/dist/client/js/storage/workers/toml-parser.d.ts +2 -0
- package/dist/client/js/storage/workers/toml-parser.d.ts.map +1 -0
- package/dist/client/js/storage/workers/toml-parser.js +75 -0
- package/dist/client/js/storage/workers/yaml-parser.d.ts +2 -0
- package/dist/client/js/storage/workers/yaml-parser.d.ts.map +1 -0
- package/dist/client/js/storage/workers/yaml-parser.js +100 -0
- package/dist/client/js/utils/file-types.d.ts +58 -0
- package/dist/client/js/utils/file-types.d.ts.map +1 -0
- package/{src/client/js/utils/file-types.ts → dist/client/js/utils/file-types.js} +75 -107
- package/dist/client/js/utils/format.d.ts +8 -0
- package/dist/client/js/utils/format.d.ts.map +1 -0
- package/{src/client/js/utils/format.ts → dist/client/js/utils/format.js} +5 -6
- package/dist/client/js/utils/frontmatter.d.ts +12 -0
- package/dist/client/js/utils/frontmatter.d.ts.map +1 -0
- package/dist/client/js/utils/frontmatter.js +29 -0
- package/dist/client/js/utils/schema-utils.d.ts +110 -0
- package/dist/client/js/utils/schema-utils.d.ts.map +1 -0
- package/dist/client/js/utils/schema-utils.js +242 -0
- package/dist/client/js/utils/slug.d.ts +8 -0
- package/dist/client/js/utils/slug.d.ts.map +1 -0
- package/{src/client/js/utils/slug.ts → dist/client/js/utils/slug.js} +6 -7
- package/dist/client/js/utils/sort.d.ts +41 -0
- package/dist/client/js/utils/sort.d.ts.map +1 -0
- package/dist/client/js/utils/sort.js +65 -0
- package/dist/client/js/utils/stable-stringify.d.ts +8 -0
- package/dist/client/js/utils/stable-stringify.d.ts.map +1 -0
- package/dist/client/js/utils/stable-stringify.js +23 -0
- package/dist/client/js/utils/url-utils.d.ts +11 -0
- package/dist/client/js/utils/url-utils.d.ts.map +1 -0
- package/{src/client/js/utils/url-utils.ts → dist/client/js/utils/url-utils.js} +22 -23
- package/dist/client/types/browser-apis.d.ts +39 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +13 -3
- package/.github/workflows/ci.yml +0 -27
- package/.github/workflows/publish.yml +0 -34
- package/.mcp.json +0 -12
- package/.prettierignore +0 -5
- package/.prettierrc.cjs +0 -22
- package/AGENTS.md +0 -183
- package/playground/astro.config.mjs +0 -7
- package/playground/node_modules/.bin/astro +0 -21
- package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js +0 -85
- package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js.map +0 -7
- package/playground/node_modules/.vite/deps/_metadata.json +0 -184
- package/playground/node_modules/.vite/deps/astro___aria-query.js +0 -6776
- package/playground/node_modules/.vite/deps/astro___aria-query.js.map +0 -7
- package/playground/node_modules/.vite/deps/astro___axobject-query.js +0 -3754
- package/playground/node_modules/.vite/deps/astro___axobject-query.js.map +0 -7
- package/playground/node_modules/.vite/deps/astro___html-escaper.js +0 -34
- package/playground/node_modules/.vite/deps/astro___html-escaper.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js +0 -0
- package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js +0 -8
- package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js +0 -21
- package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js +0 -223
- package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js +0 -27
- package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js +0 -1005
- package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js +0 -204
- package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js +0 -688
- package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js +0 -5099
- package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js +0 -4376
- package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js +0 -23
- package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js.map +0 -7
- package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js +0 -148
- package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js.map +0 -7
- package/playground/node_modules/.vite/deps/package.json +0 -3
- package/playground/node_modules/.vite/deps/smol-toml.js +0 -843
- package/playground/node_modules/.vite/deps/smol-toml.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte.js +0 -55
- package/playground/node_modules/.vite/deps/svelte.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte___clsx.js +0 -9
- package/playground/node_modules/.vite/deps/svelte___clsx.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_animate.js +0 -57
- package/playground/node_modules/.vite/deps/svelte_animate.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_attachments.js +0 -15
- package/playground/node_modules/.vite/deps/svelte_attachments.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_easing.js +0 -67
- package/playground/node_modules/.vite/deps/svelte_easing.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_events.js +0 -11
- package/playground/node_modules/.vite/deps/svelte_events.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal.js +0 -5
- package/playground/node_modules/.vite/deps/svelte_internal.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal_client.js +0 -402
- package/playground/node_modules/.vite/deps/svelte_internal_client.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js +0 -10
- package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js +0 -8
- package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js +0 -8
- package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js +0 -8
- package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_legacy.js +0 -35
- package/playground/node_modules/.vite/deps/svelte_legacy.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_motion.js +0 -545
- package/playground/node_modules/.vite/deps/svelte_motion.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_reactivity.js +0 -29
- package/playground/node_modules/.vite/deps/svelte_reactivity.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_reactivity_window.js +0 -127
- package/playground/node_modules/.vite/deps/svelte_reactivity_window.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_store.js +0 -103
- package/playground/node_modules/.vite/deps/svelte_store.js.map +0 -7
- package/playground/node_modules/.vite/deps/svelte_transition.js +0 -208
- package/playground/node_modules/.vite/deps/svelte_transition.js.map +0 -7
- package/playground/package.json +0 -16
- package/playground/pnpm-lock.yaml +0 -3167
- package/playground/src/content/authors/jane-doe.json +0 -8
- package/playground/src/content/config/build.toml +0 -2
- package/playground/src/content/courses/web-fundamentals.json +0 -29
- package/playground/src/content/docs/advanced.mdx +0 -6
- package/playground/src/content/docs/intro.md +0 -6
- package/playground/src/content/guides/getting-started.mdx +0 -6
- package/playground/src/content/posts/hello-world.md +0 -7
- package/playground/src/content/products/t-shirt.json +0 -16
- package/playground/src/content/recipes/pancakes.mdoc +0 -8
- package/playground/src/content/settings/site.yml +0 -2
- package/playground/src/content.config.ts +0 -198
- package/playground/src/env.d.ts +0 -1
- package/playground/src/pages/index.astro +0 -11
- package/playground/src/pages/nebula.astro +0 -14
- package/pnpm-workspace.yaml +0 -2
- package/scripts/subset-icons.mjs +0 -178
- package/src/astro/index.ts +0 -295
- package/src/client/js/drafts/merge.svelte.ts +0 -121
- package/src/client/js/drafts/ops.svelte.ts +0 -227
- package/src/client/js/drafts/storage.ts +0 -108
- package/src/client/js/drafts/workers/diff.ts +0 -40
- package/src/client/js/editor/editor.svelte.ts +0 -343
- package/src/client/js/editor/languages.ts +0 -98
- package/src/client/js/editor/markdown-shortcuts.ts +0 -261
- package/src/client/js/handlers/admin.ts +0 -246
- package/src/client/js/state/dialogs.svelte.ts +0 -35
- package/src/client/js/state/router.svelte.ts +0 -156
- package/src/client/js/state/state.svelte.ts +0 -334
- package/src/client/js/storage/adapter.ts +0 -102
- package/src/client/js/storage/client.ts +0 -150
- package/src/client/js/storage/db.ts +0 -36
- package/src/client/js/storage/fsa.ts +0 -110
- package/src/client/js/storage/github.ts +0 -297
- package/src/client/js/storage/storage.ts +0 -83
- package/src/client/js/storage/workers/frontmatter.ts +0 -320
- package/src/client/js/storage/workers/storage.ts +0 -177
- package/src/client/js/storage/workers/toml-parser.ts +0 -106
- package/src/client/js/storage/workers/yaml-parser.ts +0 -132
- package/src/client/js/utils/frontmatter.ts +0 -38
- package/src/client/js/utils/schema-utils.ts +0 -295
- package/src/client/js/utils/sort.ts +0 -84
- package/src/client/js/utils/stable-stringify.ts +0 -27
- package/src/types.ts +0 -25
- package/svelte.config.js +0 -4
- package/tests/astro/build.test.ts +0 -63
- package/tests/astro/index.test.ts +0 -689
- package/tests/client/components/Admin.test.ts +0 -446
- package/tests/client/components/BackendPicker.test.ts +0 -239
- package/tests/client/components/DraftChip.test.ts +0 -53
- package/tests/client/components/MetadataForm.test.ts +0 -164
- package/tests/client/components/dialogs/DeleteDraftDialog.test.ts +0 -91
- package/tests/client/components/dialogs/FilenameDialog.test.ts +0 -209
- package/tests/client/components/dialogs/dialog-stubs.ts +0 -19
- package/tests/client/components/editor/EditorPane.test.ts +0 -100
- package/tests/client/components/editor/EditorTabs.test.ts +0 -253
- package/tests/client/components/editor/EditorToolbar.test.ts +0 -252
- package/tests/client/components/editor/fixtures.ts +0 -31
- package/tests/client/components/fields/ArrayField.test.ts +0 -197
- package/tests/client/components/fields/BooleanField.test.ts +0 -206
- package/tests/client/components/fields/DateField.test.ts +0 -210
- package/tests/client/components/fields/EnumField.test.ts +0 -246
- package/tests/client/components/fields/NumberField.test.ts +0 -240
- package/tests/client/components/fields/ObjectField.test.ts +0 -157
- package/tests/client/components/fields/SchemaField.test.ts +0 -190
- package/tests/client/components/fields/StringField.test.ts +0 -223
- package/tests/client/components/sidebar/AdminSidebar.test.ts +0 -285
- package/tests/client/components/sidebar/AdminSidebarSort.test.ts +0 -135
- package/tests/client/components/sidebar/sort-mock.ts +0 -23
- package/tests/client/js/drafts/fixtures.ts +0 -22
- package/tests/client/js/drafts/merge.test.ts +0 -282
- package/tests/client/js/drafts/ops.test.ts +0 -658
- package/tests/client/js/drafts/storage.test.ts +0 -200
- package/tests/client/js/drafts/workers/diff.test.ts +0 -165
- package/tests/client/js/editor/editor.test.ts +0 -616
- package/tests/client/js/editor/link-wrap.test.ts +0 -225
- package/tests/client/js/editor/markdown-shortcuts.test.ts +0 -370
- package/tests/client/js/handlers/admin.test.ts +0 -467
- package/tests/client/js/state/router.test.ts +0 -619
- package/tests/client/js/state/schema.test.ts +0 -266
- package/tests/client/js/state/state.test.ts +0 -328
- package/tests/client/js/storage/adapter.test.ts +0 -115
- package/tests/client/js/storage/client.test.ts +0 -250
- package/tests/client/js/storage/db.test.ts +0 -59
- package/tests/client/js/storage/fsa.test.ts +0 -284
- package/tests/client/js/storage/github.test.ts +0 -349
- package/tests/client/js/storage/mock-port.ts +0 -95
- package/tests/client/js/storage/storage.test.ts +0 -77
- package/tests/client/js/storage/workers/frontmatter.test.ts +0 -479
- package/tests/client/js/storage/workers/storage.test.ts +0 -299
- package/tests/client/js/storage/workers/toml-parser.test.ts +0 -169
- package/tests/client/js/storage/workers/yaml-parser.test.ts +0 -168
- package/tests/client/js/utils/file-types.test.ts +0 -268
- package/tests/client/js/utils/frontmatter.test.ts +0 -87
- package/tests/client/js/utils/schema-utils.test.ts +0 -318
- package/tests/client/js/utils/slug.test.ts +0 -58
- package/tests/client/js/utils/sort.test.ts +0 -276
- package/tests/client/js/utils/stable-stringify.test.ts +0 -68
- package/tests/client/js/utils/url-utils.test.ts +0 -70
- package/tests/e2e/backend-connection.test.ts +0 -301
- package/tests/e2e/draft-lifecycle.test.ts +0 -388
- package/tests/e2e/editing.test.ts +0 -355
- package/tests/e2e/github-adapter.test.ts +0 -330
- package/tests/e2e/helpers/mock-adapter.ts +0 -166
- package/tests/e2e/helpers/test-app.ts +0 -155
- package/tests/e2e/navigation.test.ts +0 -358
- package/tests/e2e/publishing.test.ts +0 -345
- package/tests/e2e/unsaved-changes.test.ts +0 -317
- package/tests/setup.ts +0 -2
- package/tests/stubs/codemirror.ts +0 -197
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -178
- /package/{src → dist}/client/components/BackendPicker.svelte +0 -0
- /package/{src → dist}/client/components/DraftChip.svelte +0 -0
- /package/{src → dist}/client/components/MetadataForm.svelte +0 -0
- /package/{src → dist}/client/components/ThemeToggle.svelte +0 -0
- /package/{src → dist}/client/components/dialogs/DeleteDraftDialog.svelte +0 -0
- /package/{src → dist}/client/components/editor/EditorPane.svelte +0 -0
- /package/{src → dist}/client/components/editor/EditorTabs.svelte +0 -0
- /package/{src → dist}/client/components/editor/EditorToolbar.svelte +0 -0
- /package/{src → dist}/client/components/editor/FormatSelector.svelte +0 -0
- /package/{src → dist}/client/components/editor/Toolbar.svelte +0 -0
- /package/{src → dist}/client/components/fields/ArrayField.svelte +0 -0
- /package/{src → dist}/client/components/fields/ArrayItem.svelte +0 -0
- /package/{src → dist}/client/components/fields/BooleanField.svelte +0 -0
- /package/{src → dist}/client/components/fields/DateField.svelte +0 -0
- /package/{src → dist}/client/components/fields/EnumField.svelte +0 -0
- /package/{src → dist}/client/components/fields/FieldWrapper.svelte +0 -0
- /package/{src → dist}/client/components/fields/NumberField.svelte +0 -0
- /package/{src → dist}/client/components/fields/ObjectField.svelte +0 -0
- /package/{src → dist}/client/components/fields/SchemaField.svelte +0 -0
- /package/{src → dist}/client/components/fields/StringField.svelte +0 -0
- /package/{src → dist}/client/components/sidebar/AdminSidebarSort.svelte +0 -0
- /package/{src → dist}/client/css/a11y.css +0 -0
- /package/{src → dist}/client/css/btn.css +0 -0
- /package/{src → dist}/client/css/dialog.css +0 -0
- /package/{src → dist}/client/css/field-input.css +0 -0
- /package/{src → dist}/client/css/reset.css +0 -0
- /package/{src → dist}/client/css/theme.css +0 -0
- /package/{src/client/index.ts → dist/client/index.js} +0 -0
- /package/{src → dist}/virtual.d.ts +0 -0
|
@@ -0,0 +1,242 @@
|
|
|
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
|
+
import { toTitleCase } from './format';
|
|
7
|
+
/*
|
|
8
|
+
//////////////////////////////
|
|
9
|
+
// resolveFieldType
|
|
10
|
+
//////////////////////////////
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Resolves a JSON Schema node to a `FieldType` discriminated union.
|
|
14
|
+
* Handles anyOf nullable unwrapping, enum detection, and date-time format.
|
|
15
|
+
* @param {SchemaNode} schema - The JSON Schema node to resolve
|
|
16
|
+
* @return {FieldType} The resolved field type descriptor
|
|
17
|
+
*/
|
|
18
|
+
export function resolveFieldType(schema) {
|
|
19
|
+
// Unwrap nullable anyOf: [<innerType>, { type: 'null' }]
|
|
20
|
+
const anyOf = schema['anyOf'];
|
|
21
|
+
if (Array.isArray(anyOf)) {
|
|
22
|
+
const nonNull = anyOf.find((s) => s['type'] !== 'null');
|
|
23
|
+
if (nonNull) {
|
|
24
|
+
const inner = resolveFieldType(nonNull);
|
|
25
|
+
return { ...inner, nullable: true };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const type = schema['type'];
|
|
29
|
+
const format = schema['format'];
|
|
30
|
+
const enumValues = schema['enum'];
|
|
31
|
+
// date-time format takes precedence over plain string
|
|
32
|
+
if (type === 'string' && format === 'date-time') {
|
|
33
|
+
return { kind: 'date' };
|
|
34
|
+
}
|
|
35
|
+
// enum values present — treat as enum regardless of string subtype
|
|
36
|
+
if (type === 'string' && Array.isArray(enumValues)) {
|
|
37
|
+
return { kind: 'enum', options: enumValues };
|
|
38
|
+
}
|
|
39
|
+
if (type === 'string')
|
|
40
|
+
return { kind: 'string' };
|
|
41
|
+
if (type === 'number' || type === 'integer')
|
|
42
|
+
return { kind: 'number' };
|
|
43
|
+
if (type === 'boolean')
|
|
44
|
+
return { kind: 'boolean' };
|
|
45
|
+
if (type === 'array')
|
|
46
|
+
return { kind: 'array' };
|
|
47
|
+
if (type === 'object')
|
|
48
|
+
return { kind: 'object' };
|
|
49
|
+
return { kind: 'unknown' };
|
|
50
|
+
}
|
|
51
|
+
/*
|
|
52
|
+
//////////////////////////////
|
|
53
|
+
// extractTabs
|
|
54
|
+
//////////////////////////////
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Scans an object schema's properties for `tab` arrays and returns a sorted, deduplicated list of all tab names found.
|
|
58
|
+
* @param {SchemaNode} schema - A JSON Schema node with an optional `properties` map
|
|
59
|
+
* @return {string[]} Sorted, deduplicated list of tab names
|
|
60
|
+
*/
|
|
61
|
+
export function extractTabs(schema) {
|
|
62
|
+
const properties = getProperties(schema);
|
|
63
|
+
if (!properties)
|
|
64
|
+
return [];
|
|
65
|
+
const tabs = new Set();
|
|
66
|
+
for (const field of Object.values(properties)) {
|
|
67
|
+
const tab = field['tab'];
|
|
68
|
+
if (Array.isArray(tab)) {
|
|
69
|
+
for (const name of tab) {
|
|
70
|
+
tabs.add(name);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return Array.from(tabs).sort();
|
|
75
|
+
}
|
|
76
|
+
/*
|
|
77
|
+
//////////////////////////////
|
|
78
|
+
// createDefaultValue
|
|
79
|
+
//////////////////////////////
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* Returns a type-appropriate default value for a given JSON Schema node.
|
|
83
|
+
* Honors `schema.default` when present, returns null for nullable types, and recurses into object properties.
|
|
84
|
+
* @param {SchemaNode} schema - The JSON Schema node to generate a default value for
|
|
85
|
+
* @return {unknown} A default value appropriate for the schema type
|
|
86
|
+
*/
|
|
87
|
+
export function createDefaultValue(schema) {
|
|
88
|
+
// Honour an explicit schema default first
|
|
89
|
+
if ('default' in schema) {
|
|
90
|
+
return schema['default'];
|
|
91
|
+
}
|
|
92
|
+
// Nullable anyOf — default to null
|
|
93
|
+
const anyOf = schema['anyOf'];
|
|
94
|
+
if (Array.isArray(anyOf)) {
|
|
95
|
+
const hasNull = anyOf.some((s) => s['type'] === 'null');
|
|
96
|
+
if (hasNull)
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const type = schema['type'];
|
|
100
|
+
if (type === 'string')
|
|
101
|
+
return '';
|
|
102
|
+
if (type === 'number' || type === 'integer')
|
|
103
|
+
return 0;
|
|
104
|
+
if (type === 'boolean')
|
|
105
|
+
return false;
|
|
106
|
+
if (type === 'array')
|
|
107
|
+
return [];
|
|
108
|
+
if (type === 'object') {
|
|
109
|
+
const properties = getProperties(schema);
|
|
110
|
+
if (!properties)
|
|
111
|
+
return {};
|
|
112
|
+
const result = {};
|
|
113
|
+
for (const [key, fieldSchema] of Object.entries(properties)) {
|
|
114
|
+
result[key] = createDefaultValue(fieldSchema);
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/*
|
|
121
|
+
//////////////////////////////
|
|
122
|
+
// getByPath
|
|
123
|
+
//////////////////////////////
|
|
124
|
+
*/
|
|
125
|
+
/**
|
|
126
|
+
* Reads a deeply nested value from an object by following path segments.
|
|
127
|
+
* Returns `undefined` if any segment along the path is missing.
|
|
128
|
+
* @param {unknown} obj - The root object to traverse
|
|
129
|
+
* @param {PathSegment[]} path - Ordered path segments (string keys or numeric indices)
|
|
130
|
+
* @return {unknown} The value at the resolved path, or undefined if any segment is missing
|
|
131
|
+
*/
|
|
132
|
+
export function getByPath(obj, path) {
|
|
133
|
+
let current = obj;
|
|
134
|
+
for (const segment of path) {
|
|
135
|
+
if (current === null || current === undefined)
|
|
136
|
+
return undefined;
|
|
137
|
+
current = current[segment];
|
|
138
|
+
}
|
|
139
|
+
return current;
|
|
140
|
+
}
|
|
141
|
+
/*
|
|
142
|
+
//////////////////////////////
|
|
143
|
+
// setByPath
|
|
144
|
+
//////////////////////////////
|
|
145
|
+
*/
|
|
146
|
+
/**
|
|
147
|
+
* Sets a deeply nested value in an object by following path segments, creating intermediate objects as needed.
|
|
148
|
+
* @param {unknown} obj - The root object to mutate
|
|
149
|
+
* @param {PathSegment[]} path - Ordered path segments (string keys or numeric indices)
|
|
150
|
+
* @param {unknown} value - The value to assign at the resolved path
|
|
151
|
+
* @return {void}
|
|
152
|
+
*/
|
|
153
|
+
export function setByPath(obj, path, value) {
|
|
154
|
+
if (path.length === 0)
|
|
155
|
+
return;
|
|
156
|
+
let current = obj;
|
|
157
|
+
// Walk down to the parent of the final segment, creating objects as needed
|
|
158
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
159
|
+
const segment = path[i];
|
|
160
|
+
if (current[segment] === null || current[segment] === undefined) {
|
|
161
|
+
current[segment] = {};
|
|
162
|
+
}
|
|
163
|
+
current = current[segment];
|
|
164
|
+
}
|
|
165
|
+
current[path[path.length - 1]] = value;
|
|
166
|
+
}
|
|
167
|
+
/*
|
|
168
|
+
//////////////////////////////
|
|
169
|
+
// getFieldsForTab
|
|
170
|
+
//////////////////////////////
|
|
171
|
+
*/
|
|
172
|
+
/**
|
|
173
|
+
* Returns property names from a schema that belong to the given tab.
|
|
174
|
+
* When `tab` is `null`, all property names are returned (no filtering — every field appears in the catch-all Metadata view).
|
|
175
|
+
* @param {SchemaNode} schema - A JSON Schema node with an optional `properties` map
|
|
176
|
+
* @param {string | null} tab - Tab name to filter by, or `null` to return all fields
|
|
177
|
+
* @return {string[]} Array of property names belonging to the specified tab
|
|
178
|
+
*/
|
|
179
|
+
export function getFieldsForTab(schema, tab) {
|
|
180
|
+
const properties = getProperties(schema);
|
|
181
|
+
if (!properties)
|
|
182
|
+
return [];
|
|
183
|
+
// Filter out $schema — it's a JSON Schema meta-property that Astro adds
|
|
184
|
+
// to every generated schema, not a user-editable frontmatter field
|
|
185
|
+
const keys = Object.keys(properties).filter((k) => k !== '$schema');
|
|
186
|
+
// null means "all fields" — no tab filtering applied
|
|
187
|
+
if (tab === null) {
|
|
188
|
+
return keys;
|
|
189
|
+
}
|
|
190
|
+
return keys.filter((key) => {
|
|
191
|
+
const fieldTab = properties[key]['tab'];
|
|
192
|
+
return Array.isArray(fieldTab) && fieldTab.includes(tab);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/*
|
|
196
|
+
//////////////////////////////
|
|
197
|
+
// Schema property accessors
|
|
198
|
+
//////////////////////////////
|
|
199
|
+
*/
|
|
200
|
+
/**
|
|
201
|
+
* Extracts the `properties` map from a schema node, with a safe cast.
|
|
202
|
+
* @param {SchemaNode} schema - A JSON Schema node
|
|
203
|
+
* @return {Record<string, SchemaNode> | undefined} The properties map, or undefined if absent
|
|
204
|
+
*/
|
|
205
|
+
export function getProperties(schema) {
|
|
206
|
+
return schema['properties'];
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Extracts the `required` array from a schema node, returning an empty array if absent.
|
|
210
|
+
* @param {SchemaNode} schema - A JSON Schema node
|
|
211
|
+
* @return {string[]} Array of required property names
|
|
212
|
+
*/
|
|
213
|
+
export function getRequiredFields(schema) {
|
|
214
|
+
return Array.isArray(schema['required'])
|
|
215
|
+
? schema['required']
|
|
216
|
+
: [];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Returns whether a schema node is marked as read-only.
|
|
220
|
+
* @param {SchemaNode} schema - A JSON Schema node
|
|
221
|
+
* @return {boolean} True if the schema has readOnly set to true
|
|
222
|
+
*/
|
|
223
|
+
export function isReadOnly(schema) {
|
|
224
|
+
return !!schema['readOnly'];
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Returns whether a schema node was unwrapped from a nullable anyOf and flagged as nullable by SchemaField.
|
|
228
|
+
* @param {SchemaNode} schema - A JSON Schema node (possibly annotated with _nullable)
|
|
229
|
+
* @return {boolean} True if the schema has the _nullable annotation
|
|
230
|
+
*/
|
|
231
|
+
export function isNullable(schema) {
|
|
232
|
+
return !!schema['_nullable'];
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Returns the display label for a schema field — the schema title if present, otherwise the property name converted to title case.
|
|
236
|
+
* @param {SchemaNode} schema - A JSON Schema node
|
|
237
|
+
* @param {string} name - The raw property name used as a fallback
|
|
238
|
+
* @return {string} The human-readable label
|
|
239
|
+
*/
|
|
240
|
+
export function getLabel(schema, name) {
|
|
241
|
+
return schema['title'] ?? toTitleCase(name);
|
|
242
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a string to a URL-friendly slug.
|
|
3
|
+
* Lowercases, replaces non-alphanumeric characters with hyphens, collapses consecutive hyphens, and trims edge hyphens.
|
|
4
|
+
* @param {string} input - The string to slugify
|
|
5
|
+
* @return {string} A URL-safe slug
|
|
6
|
+
*/
|
|
7
|
+
export declare function slugify(input: string): string;
|
|
8
|
+
//# sourceMappingURL=slug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../../../../src/client/js/utils/slug.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C"}
|
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
* URL-friendly slug generation without external dependencies.
|
|
3
3
|
* Replicates the behavior of the `slugify` package with `lower: true, strict: true`.
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* Converts a string to a URL-friendly slug.
|
|
8
7
|
* Lowercases, replaces non-alphanumeric characters with hyphens, collapses consecutive hyphens, and trims edge hyphens.
|
|
9
8
|
* @param {string} input - The string to slugify
|
|
10
9
|
* @return {string} A URL-safe slug
|
|
11
10
|
*/
|
|
12
|
-
export function slugify(input
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
export function slugify(input) {
|
|
12
|
+
return input
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
15
|
+
.replace(/-{2,}/g, '-')
|
|
16
|
+
.replace(/^-|-$/g, '');
|
|
18
17
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type SidebarItem = {
|
|
2
|
+
label: string;
|
|
3
|
+
href: string;
|
|
4
|
+
subtitle?: string;
|
|
5
|
+
date?: Date;
|
|
6
|
+
draftId?: string;
|
|
7
|
+
isDraft?: boolean;
|
|
8
|
+
isOutdated?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type SortMode = 'alpha' | 'date-asc' | 'date-desc';
|
|
11
|
+
export declare const SORT_MODES: Record<SortMode, {
|
|
12
|
+
icon: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const SORT_ORDER: SortMode[];
|
|
16
|
+
/**
|
|
17
|
+
* Reads the persisted sort mode from localStorage, defaulting to 'alpha' if absent or invalid.
|
|
18
|
+
* @param {string} key - Collection name used to construct the storage key
|
|
19
|
+
* @return {SortMode} The persisted sort mode, or 'alpha' if not set
|
|
20
|
+
*/
|
|
21
|
+
export declare function readSortMode(key: string): SortMode;
|
|
22
|
+
/**
|
|
23
|
+
* Persists the sort mode to localStorage.
|
|
24
|
+
* @param {string} key - Collection name used to construct the storage key
|
|
25
|
+
* @param {SortMode} mode - The sort mode to persist
|
|
26
|
+
* @return {void}
|
|
27
|
+
*/
|
|
28
|
+
export declare function writeSortMode(key: string, mode: SortMode): void;
|
|
29
|
+
/**
|
|
30
|
+
* 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.
|
|
31
|
+
* @param {unknown} val - The published value from frontmatter
|
|
32
|
+
* @return {Date | undefined} The resolved Date, or undefined
|
|
33
|
+
*/
|
|
34
|
+
export declare function toSortDate(val: unknown): Date | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Returns a comparator function for sorting SidebarItems by the given mode.
|
|
37
|
+
* @param {SortMode} mode - The sort mode to use
|
|
38
|
+
* @return {(a: SidebarItem, b: SidebarItem) => number} A comparator function suitable for Array.sort
|
|
39
|
+
*/
|
|
40
|
+
export declare function createComparator(mode: SortMode): (a: SidebarItem, b: SidebarItem) => number;
|
|
41
|
+
//# sourceMappingURL=sort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../../../src/client/js/utils/sort.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IAEZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAG1D,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAIxE,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,QAAQ,EAAuC,CAAC;AAEzE;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAMlD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAGzD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,GACb,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,KAAK,MAAM,CAa5C"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Sorting utilities and types for admin sidebar content lists.
|
|
3
|
+
* Handles sort mode persistence, date coercion, and comparator generation.
|
|
4
|
+
*/
|
|
5
|
+
// Sort mode configuration: icon name and display label
|
|
6
|
+
export const SORT_MODES = {
|
|
7
|
+
alpha: { icon: 'sort_by_alpha', label: 'Alphabetical' },
|
|
8
|
+
'date-asc': { icon: 'hourglass_arrow_down', label: 'Oldest first' },
|
|
9
|
+
'date-desc': { icon: 'hourglass_arrow_up', label: 'Newest first' },
|
|
10
|
+
};
|
|
11
|
+
// Fixed display order for sort options in the popover
|
|
12
|
+
export const SORT_ORDER = ['alpha', 'date-asc', 'date-desc'];
|
|
13
|
+
/**
|
|
14
|
+
* Reads the persisted sort mode from localStorage, defaulting to 'alpha' if absent or invalid.
|
|
15
|
+
* @param {string} key - Collection name used to construct the storage key
|
|
16
|
+
* @return {SortMode} The persisted sort mode, or 'alpha' if not set
|
|
17
|
+
*/
|
|
18
|
+
export function readSortMode(key) {
|
|
19
|
+
const stored = localStorage.getItem(`cms-sort-${key}`);
|
|
20
|
+
if (stored === 'alpha' || stored === 'date-asc' || stored === 'date-desc') {
|
|
21
|
+
return stored;
|
|
22
|
+
}
|
|
23
|
+
return 'alpha';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Persists the sort mode to localStorage.
|
|
27
|
+
* @param {string} key - Collection name used to construct the storage key
|
|
28
|
+
* @param {SortMode} mode - The sort mode to persist
|
|
29
|
+
* @return {void}
|
|
30
|
+
*/
|
|
31
|
+
export function writeSortMode(key, mode) {
|
|
32
|
+
localStorage.setItem(`cms-sort-${key}`, mode);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 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.
|
|
36
|
+
* @param {unknown} val - The published value from frontmatter
|
|
37
|
+
* @return {Date | undefined} The resolved Date, or undefined
|
|
38
|
+
*/
|
|
39
|
+
export function toSortDate(val) {
|
|
40
|
+
if (val instanceof Date)
|
|
41
|
+
return val;
|
|
42
|
+
return typeof val === 'string' ? new Date(val) : undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a comparator function for sorting SidebarItems by the given mode.
|
|
46
|
+
* @param {SortMode} mode - The sort mode to use
|
|
47
|
+
* @return {(a: SidebarItem, b: SidebarItem) => number} A comparator function suitable for Array.sort
|
|
48
|
+
*/
|
|
49
|
+
export function createComparator(mode) {
|
|
50
|
+
return (a, b) => {
|
|
51
|
+
if (mode === 'date-asc' || mode === 'date-desc') {
|
|
52
|
+
// Items without a date sort to the top (e.g. new drafts without a published date)
|
|
53
|
+
if (!a.date && !b.date)
|
|
54
|
+
return 0;
|
|
55
|
+
if (!a.date)
|
|
56
|
+
return -1;
|
|
57
|
+
if (!b.date)
|
|
58
|
+
return 1;
|
|
59
|
+
return mode === 'date-asc'
|
|
60
|
+
? a.date.getTime() - b.date.getTime()
|
|
61
|
+
: b.date.getTime() - a.date.getTime();
|
|
62
|
+
}
|
|
63
|
+
return a.label.toLowerCase().localeCompare(b.label.toLowerCase());
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively sorts object keys and serializes to JSON.
|
|
3
|
+
* Produces deterministic output regardless of key insertion order.
|
|
4
|
+
* @param {unknown} value - The value to serialize
|
|
5
|
+
* @return {string} A JSON string with sorted keys at every nesting level
|
|
6
|
+
*/
|
|
7
|
+
export declare function stableStringify(value: unknown): string;
|
|
8
|
+
//# sourceMappingURL=stable-stringify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-stringify.d.ts","sourceRoot":"","sources":["../../../../src/client/js/utils/stable-stringify.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAetD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Deterministic JSON serialization with sorted keys.
|
|
3
|
+
* Prevents false-positive outdated detection when comparing snapshots.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Recursively sorts object keys and serializes to JSON.
|
|
7
|
+
* Produces deterministic output regardless of key insertion order.
|
|
8
|
+
* @param {unknown} value - The value to serialize
|
|
9
|
+
* @return {string} A JSON string with sorted keys at every nesting level
|
|
10
|
+
*/
|
|
11
|
+
export function stableStringify(value) {
|
|
12
|
+
return JSON.stringify(value, (_key, val) => {
|
|
13
|
+
if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
|
|
14
|
+
return Object.keys(val)
|
|
15
|
+
.sort()
|
|
16
|
+
.reduce((sorted, k) => {
|
|
17
|
+
sorted[k] = val[k];
|
|
18
|
+
return sorted;
|
|
19
|
+
}, {});
|
|
20
|
+
}
|
|
21
|
+
return val;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a string is a valid URL (absolute with scheme, or absolute path).
|
|
3
|
+
* Used by the smart paste handler to determine whether clipboard content should
|
|
4
|
+
* be auto-wrapped as a markdown link rather than inserted as plain text.
|
|
5
|
+
* Trims whitespace before validating. Rejects plain words and relative paths
|
|
6
|
+
* without a leading slash to avoid false positives on normal text.
|
|
7
|
+
* @param {string} text - The string to validate
|
|
8
|
+
* @return {boolean} True if the text is a valid URL or absolute path
|
|
9
|
+
*/
|
|
10
|
+
export declare function isURL(text: string): boolean;
|
|
11
|
+
//# sourceMappingURL=url-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-utils.d.ts","sourceRoot":"","sources":["../../../../src/client/js/utils/url-utils.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAwB3C"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* URL validation utilities for the editor's smart paste handler.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Checks whether a string is a valid URL (absolute with scheme, or absolute path).
|
|
7
6
|
* Used by the smart paste handler to determine whether clipboard content should
|
|
@@ -11,28 +10,28 @@
|
|
|
11
10
|
* @param {string} text - The string to validate
|
|
12
11
|
* @return {boolean} True if the text is a valid URL or absolute path
|
|
13
12
|
*/
|
|
14
|
-
export function isURL(text
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
new URL(trimmed);
|
|
21
|
-
return true;
|
|
22
|
-
} catch {
|
|
23
|
-
// Not an absolute URL — fall through
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Absolute path starting with /
|
|
27
|
-
if (trimmed.startsWith('/')) {
|
|
13
|
+
export function isURL(text) {
|
|
14
|
+
const trimmed = text.trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return false;
|
|
17
|
+
// Absolute URL with scheme (https://, mailto:, etc.)
|
|
28
18
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return true;
|
|
32
|
-
} catch {
|
|
33
|
-
return false;
|
|
19
|
+
new URL(trimmed);
|
|
20
|
+
return true;
|
|
34
21
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
catch {
|
|
23
|
+
// Not an absolute URL — fall through
|
|
24
|
+
}
|
|
25
|
+
// Absolute path starting with /
|
|
26
|
+
if (trimmed.startsWith('/')) {
|
|
27
|
+
try {
|
|
28
|
+
// Dummy base required by URL constructor to resolve absolute paths
|
|
29
|
+
new URL(trimmed, 'https://a.com');
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
38
37
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Type augmentations for browser APIs not fully covered by installed @types packages.
|
|
3
|
+
* The side-effect import makes this a module file so `declare global` adds to the
|
|
4
|
+
* global scope and `declare module` augments (rather than redeclares) the target.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import 'svelte/elements';
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
//////////////////////////////
|
|
11
|
+
// Navigation API
|
|
12
|
+
//////////////////////////////
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* @types/dom-navigation provides the Navigation class and augments Window,
|
|
17
|
+
* but omits the global variable declaration that lets code use bare
|
|
18
|
+
* `navigation` (like bare `document` or `location`).
|
|
19
|
+
*/
|
|
20
|
+
declare global {
|
|
21
|
+
var navigation: Navigation;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
//////////////////////////////
|
|
26
|
+
// Interest Invokers API
|
|
27
|
+
//////////////////////////////
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* No @types package exists for this spec.
|
|
32
|
+
* See: https://open-ui.org/components/interest-invokers.explainer/
|
|
33
|
+
*/
|
|
34
|
+
declare module 'svelte/elements' {
|
|
35
|
+
// Extends all HTML elements with the interestfor attribute
|
|
36
|
+
interface HTMLAttributes<T> {
|
|
37
|
+
interestfor?: string;
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface NebulaCMSConfig {
|
|
2
|
+
/**
|
|
3
|
+
* URL prefix for the admin SPA.
|
|
4
|
+
* Accepts a relative or absolute path. Normalized automatically: leading `/`
|
|
5
|
+
* prepended if missing, consecutive slashes collapsed, trailing `/` stripped.
|
|
6
|
+
* After normalization, must contain only segments of letters, digits, hyphens,
|
|
7
|
+
* and underscores — or be `/` for root mount.
|
|
8
|
+
* @default '/admin'
|
|
9
|
+
*/
|
|
10
|
+
basePath?: string;
|
|
11
|
+
/**
|
|
12
|
+
* URL prefix under which collection schema files are served.
|
|
13
|
+
* Accepts a relative or absolute path. Normalized automatically: leading `/`
|
|
14
|
+
* prepended if missing, consecutive slashes collapsed, trailing `/` stripped.
|
|
15
|
+
* After normalization, must contain only segments of letters, digits, hyphens,
|
|
16
|
+
* and underscores. Cannot be `/` (root) — collections require at least one
|
|
17
|
+
* path segment.
|
|
18
|
+
* @default '/collections'
|
|
19
|
+
*/
|
|
20
|
+
collectionsPath?: string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nebula-cms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A native CMS for Astro",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -47,13 +47,20 @@
|
|
|
47
47
|
"svelte": "^5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"author": "Sam Richard<sam@snug.ug>",
|
|
50
|
+
"files": [
|
|
51
|
+
"dist"
|
|
52
|
+
],
|
|
50
53
|
"license": "Apache-2.0",
|
|
51
54
|
"devDependencies": {
|
|
52
55
|
"@astrojs/svelte": "^8.0.3",
|
|
53
56
|
"@sveltejs/package": "^2.5.7",
|
|
54
57
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
55
58
|
"@testing-library/svelte": "^5.3.1",
|
|
56
|
-
"
|
|
59
|
+
"@types/dom-navigation": "^1.0.7",
|
|
60
|
+
"@types/js-yaml": "^4.0.9",
|
|
61
|
+
"@types/node": "^25.5.2",
|
|
62
|
+
"@types/sharedworker": "^0.0.223",
|
|
63
|
+
"@types/wicg-file-system-access": "^2023.10.7",
|
|
57
64
|
"@vitest/browser": "^4.1.2",
|
|
58
65
|
"@vitest/browser-playwright": "^4.1.2",
|
|
59
66
|
"@vitest/coverage-v8": "^4.1.2",
|
|
@@ -65,12 +72,15 @@
|
|
|
65
72
|
"prettier-plugin-astro": "^0.14.1",
|
|
66
73
|
"prettier-plugin-svelte": "^3.5.1",
|
|
67
74
|
"svelte": "^5.54.1",
|
|
68
|
-
"
|
|
75
|
+
"svelte-check": "^4.4.6",
|
|
76
|
+
"typescript": "^5.9.3",
|
|
77
|
+
"vitest": "^4.1.2"
|
|
69
78
|
},
|
|
70
79
|
"scripts": {
|
|
71
80
|
"prebuild": "node scripts/subset-icons.mjs",
|
|
72
81
|
"build": "svelte-package --input src --output dist",
|
|
73
82
|
"lint": "prettier -c .",
|
|
83
|
+
"check": "svelte-check",
|
|
74
84
|
"fix": "prettier --write .",
|
|
75
85
|
"test": "vitest run",
|
|
76
86
|
"test:continuous": "vitest"
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
test:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
- uses: actions/checkout@v6
|
|
13
|
-
- uses: pnpm/action-setup@v5
|
|
14
|
-
- uses: actions/setup-node@v6
|
|
15
|
-
with:
|
|
16
|
-
node-version: 24
|
|
17
|
-
cache: pnpm
|
|
18
|
-
registry-url: https://registry.npmjs.org
|
|
19
|
-
|
|
20
|
-
- name: Install dependencies
|
|
21
|
-
run: pnpm install
|
|
22
|
-
- name: Install Playwright browsers
|
|
23
|
-
run: pnpm exec playwright install --with-deps chromium
|
|
24
|
-
- name: Lint
|
|
25
|
-
run: pnpm lint
|
|
26
|
-
- name: Test
|
|
27
|
-
run: pnpm test
|