nebula-cms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +42 -0
- package/.github/workflows/ci.yml +31 -0
- package/.mcp.json +12 -0
- package/.prettierignore +5 -0
- package/.prettierrc.cjs +22 -0
- package/AGENTS.md +183 -0
- package/LICENSE +201 -0
- package/README.md +128 -0
- package/package.json +74 -0
- package/playground/.claude/settings.local.json +5 -0
- package/playground/astro.config.mjs +7 -0
- package/playground/node_modules/.bin/astro +21 -0
- package/playground/node_modules/.bin/rollup +21 -0
- package/playground/node_modules/.bin/tsc +21 -0
- package/playground/node_modules/.bin/tsserver +21 -0
- package/playground/node_modules/.bin/vite +21 -0
- package/playground/node_modules/.vite/_svelte_metadata.json +1 -0
- package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js +80 -0
- package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js.map +7 -0
- package/playground/node_modules/.vite/deps/_metadata.json +184 -0
- package/playground/node_modules/.vite/deps/astro___aria-query.js +6776 -0
- package/playground/node_modules/.vite/deps/astro___aria-query.js.map +7 -0
- package/playground/node_modules/.vite/deps/astro___axobject-query.js +3754 -0
- package/playground/node_modules/.vite/deps/astro___axobject-query.js.map +7 -0
- package/playground/node_modules/.vite/deps/astro___html-escaper.js +34 -0
- package/playground/node_modules/.vite/deps/astro___html-escaper.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js +0 -0
- package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-ALJIOON6.js +1005 -0
- package/playground/node_modules/.vite/deps/chunk-ALJIOON6.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js +8 -0
- package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js +21 -0
- package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js +223 -0
- package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-G3C2FXJT.js +204 -0
- package/playground/node_modules/.vite/deps/chunk-G3C2FXJT.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-GKDKFWC5.js +27 -0
- package/playground/node_modules/.vite/deps/chunk-GKDKFWC5.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-HNCLEOC5.js +4376 -0
- package/playground/node_modules/.vite/deps/chunk-HNCLEOC5.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-JICYXBFU.js +688 -0
- package/playground/node_modules/.vite/deps/chunk-JICYXBFU.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-KCUTL6DD.js +5099 -0
- package/playground/node_modules/.vite/deps/chunk-KCUTL6DD.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js +23 -0
- package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js.map +7 -0
- package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js +148 -0
- package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js.map +7 -0
- package/playground/node_modules/.vite/deps/package.json +3 -0
- package/playground/node_modules/.vite/deps/smol-toml.js +843 -0
- package/playground/node_modules/.vite/deps/smol-toml.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte.js +55 -0
- package/playground/node_modules/.vite/deps/svelte.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte___clsx.js +9 -0
- package/playground/node_modules/.vite/deps/svelte___clsx.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_animate.js +57 -0
- package/playground/node_modules/.vite/deps/svelte_animate.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_attachments.js +15 -0
- package/playground/node_modules/.vite/deps/svelte_attachments.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_easing.js +67 -0
- package/playground/node_modules/.vite/deps/svelte_easing.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_events.js +11 -0
- package/playground/node_modules/.vite/deps/svelte_events.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal.js +5 -0
- package/playground/node_modules/.vite/deps/svelte_internal.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal_client.js +402 -0
- package/playground/node_modules/.vite/deps/svelte_internal_client.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js +10 -0
- package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js +8 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js +8 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js +8 -0
- package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_legacy.js +35 -0
- package/playground/node_modules/.vite/deps/svelte_legacy.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_motion.js +545 -0
- package/playground/node_modules/.vite/deps/svelte_motion.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_reactivity.js +29 -0
- package/playground/node_modules/.vite/deps/svelte_reactivity.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_reactivity_window.js +127 -0
- package/playground/node_modules/.vite/deps/svelte_reactivity_window.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_store.js +103 -0
- package/playground/node_modules/.vite/deps/svelte_store.js.map +7 -0
- package/playground/node_modules/.vite/deps/svelte_transition.js +208 -0
- package/playground/node_modules/.vite/deps/svelte_transition.js.map +7 -0
- package/playground/package.json +16 -0
- package/playground/pnpm-lock.yaml +3167 -0
- package/playground/src/content/authors/jane-doe.json +8 -0
- package/playground/src/content/config/build.toml +2 -0
- package/playground/src/content/courses/web-fundamentals.json +29 -0
- package/playground/src/content/docs/advanced.mdx +6 -0
- package/playground/src/content/docs/intro.md +6 -0
- package/playground/src/content/guides/getting-started.mdx +6 -0
- package/playground/src/content/posts/hello-world.md +7 -0
- package/playground/src/content/products/t-shirt.json +16 -0
- package/playground/src/content/recipes/pancakes.mdoc +8 -0
- package/playground/src/content/settings/site.yml +2 -0
- package/playground/src/content.config.ts +198 -0
- package/playground/src/env.d.ts +1 -0
- package/playground/src/pages/index.astro +11 -0
- package/playground/src/pages/nebula.astro +14 -0
- package/pnpm-workspace.yaml +2 -0
- package/scripts/subset-icons.mjs +178 -0
- package/src/astro/index.ts +295 -0
- package/src/client/Admin.svelte +283 -0
- package/src/client/components/BackendPicker.svelte +291 -0
- package/src/client/components/DraftChip.svelte +46 -0
- package/src/client/components/MetadataForm.svelte +56 -0
- package/src/client/components/ThemeToggle.svelte +18 -0
- package/src/client/components/dialogs/DeleteDraftDialog.svelte +51 -0
- package/src/client/components/dialogs/FilenameDialog.svelte +129 -0
- package/src/client/components/editor/EditorPane.svelte +227 -0
- package/src/client/components/editor/EditorTabs.svelte +81 -0
- package/src/client/components/editor/EditorToolbar.svelte +131 -0
- package/src/client/components/editor/FormatSelector.svelte +66 -0
- package/src/client/components/editor/Toolbar.svelte +17 -0
- package/src/client/components/fields/ArrayField.svelte +339 -0
- package/src/client/components/fields/ArrayItem.svelte +325 -0
- package/src/client/components/fields/BooleanField.svelte +114 -0
- package/src/client/components/fields/DateField.svelte +82 -0
- package/src/client/components/fields/EnumField.svelte +74 -0
- package/src/client/components/fields/FieldWrapper.svelte +96 -0
- package/src/client/components/fields/NumberField.svelte +99 -0
- package/src/client/components/fields/ObjectField.svelte +121 -0
- package/src/client/components/fields/SchemaField.svelte +107 -0
- package/src/client/components/fields/StringField.svelte +104 -0
- package/src/client/components/sidebar/AdminSidebar.svelte +339 -0
- package/src/client/components/sidebar/AdminSidebarSort.svelte +123 -0
- package/src/client/css/a11y.css +14 -0
- package/src/client/css/btn.css +113 -0
- package/src/client/css/dialog.css +29 -0
- package/src/client/css/field-input.css +39 -0
- package/src/client/css/reset.css +59 -0
- package/src/client/css/theme.css +77 -0
- package/src/client/index.ts +1 -0
- package/src/client/js/drafts/merge.svelte.ts +121 -0
- package/src/client/js/drafts/ops.svelte.ts +227 -0
- package/src/client/js/drafts/storage.ts +108 -0
- package/src/client/js/drafts/workers/diff.ts +40 -0
- package/src/client/js/editor/editor.svelte.ts +343 -0
- package/src/client/js/editor/languages.ts +98 -0
- package/src/client/js/editor/link-wrap.ts +45 -0
- package/src/client/js/editor/markdown-shortcuts.ts +261 -0
- package/src/client/js/handlers/admin.ts +246 -0
- package/src/client/js/state/dialogs.svelte.ts +35 -0
- package/src/client/js/state/router.svelte.ts +156 -0
- package/src/client/js/state/schema.svelte.ts +140 -0
- package/src/client/js/state/state.svelte.ts +334 -0
- package/src/client/js/state/theme.svelte.ts +173 -0
- package/src/client/js/storage/adapter.ts +102 -0
- package/src/client/js/storage/client.ts +150 -0
- package/src/client/js/storage/db.ts +36 -0
- package/src/client/js/storage/fsa.ts +110 -0
- package/src/client/js/storage/github.ts +297 -0
- package/src/client/js/storage/storage.ts +83 -0
- package/src/client/js/storage/workers/frontmatter.ts +320 -0
- package/src/client/js/storage/workers/storage.ts +177 -0
- package/src/client/js/storage/workers/toml-parser.ts +106 -0
- package/src/client/js/storage/workers/yaml-parser.ts +132 -0
- package/src/client/js/utils/file-types.ts +192 -0
- package/src/client/js/utils/format.ts +16 -0
- package/src/client/js/utils/frontmatter.ts +38 -0
- package/src/client/js/utils/schema-utils.ts +295 -0
- package/src/client/js/utils/slug.ts +18 -0
- package/src/client/js/utils/sort.ts +84 -0
- package/src/client/js/utils/stable-stringify.ts +27 -0
- package/src/client/js/utils/url-utils.ts +38 -0
- package/src/types.ts +25 -0
- package/src/virtual.d.ts +22 -0
- package/svelte.config.js +4 -0
- package/tests/astro/build.test.ts +63 -0
- package/tests/astro/index.test.ts +689 -0
- package/tests/client/components/Admin.test.ts +446 -0
- package/tests/client/components/BackendPicker.test.ts +239 -0
- package/tests/client/components/DraftChip.test.ts +53 -0
- package/tests/client/components/MetadataForm.test.ts +164 -0
- package/tests/client/components/dialogs/DeleteDraftDialog.test.ts +91 -0
- package/tests/client/components/dialogs/FilenameDialog.test.ts +209 -0
- package/tests/client/components/dialogs/dialog-stubs.ts +19 -0
- package/tests/client/components/editor/EditorPane.test.ts +100 -0
- package/tests/client/components/editor/EditorTabs.test.ts +253 -0
- package/tests/client/components/editor/EditorToolbar.test.ts +252 -0
- package/tests/client/components/editor/fixtures.ts +31 -0
- package/tests/client/components/fields/ArrayField.test.ts +197 -0
- package/tests/client/components/fields/BooleanField.test.ts +206 -0
- package/tests/client/components/fields/DateField.test.ts +210 -0
- package/tests/client/components/fields/EnumField.test.ts +246 -0
- package/tests/client/components/fields/NumberField.test.ts +240 -0
- package/tests/client/components/fields/ObjectField.test.ts +157 -0
- package/tests/client/components/fields/SchemaField.test.ts +190 -0
- package/tests/client/components/fields/StringField.test.ts +223 -0
- package/tests/client/components/sidebar/AdminSidebar.test.ts +285 -0
- package/tests/client/components/sidebar/AdminSidebarSort.test.ts +135 -0
- package/tests/client/components/sidebar/sort-mock.ts +23 -0
- package/tests/client/js/drafts/fixtures.ts +22 -0
- package/tests/client/js/drafts/merge.test.ts +282 -0
- package/tests/client/js/drafts/ops.test.ts +658 -0
- package/tests/client/js/drafts/storage.test.ts +200 -0
- package/tests/client/js/drafts/workers/diff.test.ts +165 -0
- package/tests/client/js/editor/editor.test.ts +616 -0
- package/tests/client/js/editor/link-wrap.test.ts +225 -0
- package/tests/client/js/editor/markdown-shortcuts.test.ts +370 -0
- package/tests/client/js/handlers/admin.test.ts +467 -0
- package/tests/client/js/state/router.test.ts +619 -0
- package/tests/client/js/state/schema.test.ts +266 -0
- package/tests/client/js/state/state.test.ts +328 -0
- package/tests/client/js/storage/adapter.test.ts +115 -0
- package/tests/client/js/storage/client.test.ts +250 -0
- package/tests/client/js/storage/db.test.ts +59 -0
- package/tests/client/js/storage/fsa.test.ts +284 -0
- package/tests/client/js/storage/github.test.ts +349 -0
- package/tests/client/js/storage/mock-port.ts +95 -0
- package/tests/client/js/storage/storage.test.ts +77 -0
- package/tests/client/js/storage/workers/frontmatter.test.ts +479 -0
- package/tests/client/js/storage/workers/storage.test.ts +299 -0
- package/tests/client/js/storage/workers/toml-parser.test.ts +169 -0
- package/tests/client/js/storage/workers/yaml-parser.test.ts +168 -0
- package/tests/client/js/utils/file-types.test.ts +268 -0
- package/tests/client/js/utils/frontmatter.test.ts +87 -0
- package/tests/client/js/utils/schema-utils.test.ts +318 -0
- package/tests/client/js/utils/slug.test.ts +58 -0
- package/tests/client/js/utils/sort.test.ts +276 -0
- package/tests/client/js/utils/stable-stringify.test.ts +68 -0
- package/tests/client/js/utils/url-utils.test.ts +70 -0
- package/tests/e2e/backend-connection.test.ts +301 -0
- package/tests/e2e/draft-lifecycle.test.ts +388 -0
- package/tests/e2e/editing.test.ts +355 -0
- package/tests/e2e/github-adapter.test.ts +330 -0
- package/tests/e2e/helpers/mock-adapter.ts +166 -0
- package/tests/e2e/helpers/test-app.ts +155 -0
- package/tests/e2e/navigation.test.ts +358 -0
- package/tests/e2e/publishing.test.ts +345 -0
- package/tests/e2e/unsaved-changes.test.ts +317 -0
- package/tests/setup.ts +2 -0
- package/tests/stubs/codemirror.ts +197 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +178 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stub module for all @codemirror/* and @lezer/* imports used in the component test environment.
|
|
3
|
+
* These packages are runtime-only dependencies not installed as devDependencies.
|
|
4
|
+
* The vitest.config.ts components project redirects every @codemirror/* and @lezer/*
|
|
5
|
+
* specifier here so EditorPane can be imported without resolution failures.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Noop class standing in for CodeMirror's EditorView.
|
|
10
|
+
* Static members cover all call sites in EditorPane, link-wrap, and markdown-shortcuts.
|
|
11
|
+
*/
|
|
12
|
+
export class EditorView {
|
|
13
|
+
static theme = () => ({});
|
|
14
|
+
static lineWrapping = {};
|
|
15
|
+
static updateListener = { of: () => ({}) };
|
|
16
|
+
static contentAttributes = { of: () => ({}) };
|
|
17
|
+
// Used by markdown-shortcuts to register a paste event handler
|
|
18
|
+
static domEventHandlers = () => ({});
|
|
19
|
+
// Used by markdown-shortcuts for bracket/quote wrapping
|
|
20
|
+
static inputHandler = { of: () => ({}) };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Noop replacement for EditorView.destroy().
|
|
24
|
+
* @return {void}
|
|
25
|
+
*/
|
|
26
|
+
destroy() {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Noop replacement for EditorView.setState().
|
|
30
|
+
* @param {unknown} _state - Ignored
|
|
31
|
+
* @return {void}
|
|
32
|
+
*/
|
|
33
|
+
setState(_state?: unknown) {}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Noop replacement for EditorView.dispatch().
|
|
37
|
+
* @param {unknown} _tr - Ignored
|
|
38
|
+
* @return {void}
|
|
39
|
+
*/
|
|
40
|
+
dispatch(_tr?: unknown) {}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Stub getter returning a minimal EditorState-like shape.
|
|
44
|
+
* @return {{ selection: { main: { from: number, to: number, empty: boolean } }, changeByRange: Function, sliceDoc: Function }}
|
|
45
|
+
*/
|
|
46
|
+
get state() {
|
|
47
|
+
return {
|
|
48
|
+
selection: { main: { from: 0, to: 0, empty: true } },
|
|
49
|
+
changeByRange: () => ({ changes: [], selection: {} }),
|
|
50
|
+
sliceDoc: () => '',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Noop standing in for EditorState
|
|
56
|
+
export const EditorState = {
|
|
57
|
+
create: () => ({}),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Noop class standing in for CodeMirror's Compartment.
|
|
62
|
+
* Used by EditorPane to isolate the language extension for runtime reconfiguration.
|
|
63
|
+
*/
|
|
64
|
+
export class Compartment {
|
|
65
|
+
/**
|
|
66
|
+
* Wraps an extension value for initial configuration.
|
|
67
|
+
* @param {unknown} _ext - Ignored
|
|
68
|
+
* @return {Record<string, never>} Empty object
|
|
69
|
+
*/
|
|
70
|
+
of(_ext?: unknown) {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns a StateEffect for reconfiguring this compartment.
|
|
76
|
+
* @param {unknown} _ext - Ignored
|
|
77
|
+
* @return {Record<string, never>} Empty object standing in for a StateEffect
|
|
78
|
+
*/
|
|
79
|
+
reconfigure(_ext?: unknown) {
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Minimal keymap stub
|
|
85
|
+
export const keymap = { of: () => ({}) };
|
|
86
|
+
|
|
87
|
+
// Command stubs
|
|
88
|
+
export const defaultKeymap: unknown[] = [];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Noop replacement for CodeMirror's history extension.
|
|
92
|
+
* @return {Record<string, never>} Empty object
|
|
93
|
+
*/
|
|
94
|
+
export function history() {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
export const historyKeymap: unknown[] = [];
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Noop replacement for CodeMirror's markdown language extension.
|
|
101
|
+
* @return {Record<string, never>} Empty object
|
|
102
|
+
*/
|
|
103
|
+
export function markdown() {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
export const markdownLanguage = {};
|
|
107
|
+
|
|
108
|
+
// Language data stub
|
|
109
|
+
export const languages: unknown[] = [];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Noop replacement for CodeMirror's syntaxHighlighting extension.
|
|
113
|
+
* @return {Record<string, never>} Empty object
|
|
114
|
+
*/
|
|
115
|
+
export function syntaxHighlighting() {
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
export const HighlightStyle = {
|
|
119
|
+
define: () => ({}),
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// ViewPlugin stub (used by link-wrap and markdown-shortcuts)
|
|
123
|
+
// Both .define() and .fromClass() are used across the editor modules.
|
|
124
|
+
export const ViewPlugin = {
|
|
125
|
+
define: () => ({}),
|
|
126
|
+
fromClass: () => ({}),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Decoration stub (used by link-wrap)
|
|
130
|
+
export const Decoration = {
|
|
131
|
+
mark: () => ({}),
|
|
132
|
+
none: {},
|
|
133
|
+
set: () => ({}),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Noop replacement for CodeMirror's RangeSetBuilder.
|
|
138
|
+
* Used by link-wrap to build decoration sets.
|
|
139
|
+
*/
|
|
140
|
+
export class RangeSetBuilder {
|
|
141
|
+
/**
|
|
142
|
+
* Noop replacement for RangeSetBuilder.add().
|
|
143
|
+
* @param {unknown} _from - Ignored
|
|
144
|
+
* @param {unknown} _to - Ignored
|
|
145
|
+
* @param {unknown} _value - Ignored
|
|
146
|
+
* @return {void}
|
|
147
|
+
*/
|
|
148
|
+
add(_from?: unknown, _to?: unknown, _value?: unknown) {}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Noop replacement for RangeSetBuilder.finish().
|
|
152
|
+
* @return {Record<string, never>} Empty object standing in for a DecorationSet
|
|
153
|
+
*/
|
|
154
|
+
finish() {
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// EditorSelection stub (used by markdown-shortcuts)
|
|
160
|
+
export const EditorSelection = {
|
|
161
|
+
cursor: () => ({}),
|
|
162
|
+
range: () => ({}),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Tags stub — returns a proxy so any tag property access is valid
|
|
166
|
+
export const tags = new Proxy(
|
|
167
|
+
{},
|
|
168
|
+
{
|
|
169
|
+
get: () =>
|
|
170
|
+
new Proxy(() => ({}), {
|
|
171
|
+
get: () => () => ({}),
|
|
172
|
+
apply: () => ({}),
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Noop replacement for CodeMirror's syntaxTree function.
|
|
179
|
+
* Used by link-wrap and markdown-shortcuts for AST traversal.
|
|
180
|
+
* @return {{ cursor: Function }} Minimal tree stub
|
|
181
|
+
*/
|
|
182
|
+
export function syntaxTree() {
|
|
183
|
+
return { cursor: () => ({ next: () => false }) };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Stub for url-utils isURL. Always returns false in the test environment.
|
|
188
|
+
* @return {boolean} Always false
|
|
189
|
+
*/
|
|
190
|
+
export function isURL() {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Stub type standing in for CodeMirror's KeyBinding interface.
|
|
196
|
+
*/
|
|
197
|
+
export type KeyBinding = unknown;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"strict": true,
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"declaration": true,
|
|
11
|
+
"declarationMap": true,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
"outDir": "dist",
|
|
14
|
+
"rootDir": "src",
|
|
15
|
+
"types": ["svelte", "vitest/globals"]
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules", "dist", "playground", "tests"]
|
|
19
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { defineConfig } from 'vitest/config';
|
|
3
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
4
|
+
import { playwright } from '@vitest/browser-playwright';
|
|
5
|
+
|
|
6
|
+
// icons.css is generated by scripts/subset-icons.mjs and gitignored.
|
|
7
|
+
// Stub it to an empty string in tests so they pass without generating the font.
|
|
8
|
+
const iconsPath = new URL('src/client/css/icons.css', import.meta.url).pathname;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Vite plugin that stubs the generated icons.css import when the file doesn't exist.
|
|
12
|
+
* This allows tests to run in CI or fresh clones without first running the subset script.
|
|
13
|
+
* @return {import('vite').Plugin} The Vite plugin
|
|
14
|
+
*/
|
|
15
|
+
function stubIconsCSS(): import('vite').Plugin {
|
|
16
|
+
return {
|
|
17
|
+
name: 'stub-icons-css',
|
|
18
|
+
resolveId(id: string) {
|
|
19
|
+
if (id.endsWith('css/icons.css') && !existsSync(iconsPath)) {
|
|
20
|
+
return '\0stub-icons-css';
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
load(id: string) {
|
|
24
|
+
if (id === '\0stub-icons-css') return '';
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
test: {
|
|
31
|
+
// Inline project definitions replace the separate vitest.workspace.ts file.
|
|
32
|
+
// This keeps the config co-located with package.json so Vite's config
|
|
33
|
+
// search stops here rather than walking up to the parent repo root.
|
|
34
|
+
projects: [
|
|
35
|
+
//////////////////////////////
|
|
36
|
+
// Unit tests — Node.js environment (pure JS/TS, no DOM)
|
|
37
|
+
//////////////////////////////
|
|
38
|
+
{
|
|
39
|
+
plugins: [svelte(), stubIconsCSS()],
|
|
40
|
+
test: {
|
|
41
|
+
name: 'unit',
|
|
42
|
+
include: [
|
|
43
|
+
'tests/**/*.test.ts',
|
|
44
|
+
'!tests/e2e/**',
|
|
45
|
+
'!tests/**/*components*/**',
|
|
46
|
+
],
|
|
47
|
+
setupFiles: ['tests/setup.ts'],
|
|
48
|
+
coverage: {
|
|
49
|
+
provider: 'v8',
|
|
50
|
+
reportsDirectory: '.coverage',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
//////////////////////////////
|
|
56
|
+
// Component tests — jsdom environment (Svelte components via @testing-library/svelte)
|
|
57
|
+
//////////////////////////////
|
|
58
|
+
{
|
|
59
|
+
plugins: [svelte(), stubIconsCSS()],
|
|
60
|
+
// browser condition is required so Vite resolves Svelte's client-side
|
|
61
|
+
// entry point instead of the SSR server entry, which does not have `mount`
|
|
62
|
+
resolve: {
|
|
63
|
+
conditions: ['browser'],
|
|
64
|
+
// @codemirror/* and @lezer/* require a real browser DOM that jsdom cannot
|
|
65
|
+
// provide. Redirect them to a stub so EditorPane (and its transitive
|
|
66
|
+
// imports) can be loaded in the jsdom test environment.
|
|
67
|
+
alias: [
|
|
68
|
+
{
|
|
69
|
+
find: /^@codemirror\/.+/,
|
|
70
|
+
replacement: new URL('tests/stubs/codemirror.ts', import.meta.url)
|
|
71
|
+
.pathname,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
find: /^@lezer\/.+/,
|
|
75
|
+
replacement: new URL('tests/stubs/codemirror.ts', import.meta.url)
|
|
76
|
+
.pathname,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
test: {
|
|
81
|
+
name: 'components',
|
|
82
|
+
environment: 'jsdom',
|
|
83
|
+
include: ['tests/**/components/**/*.test.ts'],
|
|
84
|
+
setupFiles: ['tests/setup.ts'],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
//////////////////////////////
|
|
89
|
+
// Browser tests — Playwright via system Chrome
|
|
90
|
+
//////////////////////////////
|
|
91
|
+
{
|
|
92
|
+
plugins: [
|
|
93
|
+
svelte(),
|
|
94
|
+
stubIconsCSS(),
|
|
95
|
+
/*
|
|
96
|
+
* Stub plugin that resolves virtual:nebula/* for the browser test
|
|
97
|
+
* environment. The real virtual:nebula/* plugins are injected by the
|
|
98
|
+
* Astro integration, which is not running during Vitest browser tests.
|
|
99
|
+
* They are mocked in tests, but Vite's dependency scanner runs before
|
|
100
|
+
* mocks are applied and would fail without a resolver.
|
|
101
|
+
*/
|
|
102
|
+
{
|
|
103
|
+
name: 'stub-virtual-modules',
|
|
104
|
+
/**
|
|
105
|
+
* Resolves virtual:nebula/* to internal stubs so Vite's dependency scanner doesn't fail before mocks apply.
|
|
106
|
+
* @param {string} id - The module specifier to resolve
|
|
107
|
+
* @return {string | undefined} The resolved internal ID, or undefined to skip
|
|
108
|
+
*/
|
|
109
|
+
resolveId(id: string) {
|
|
110
|
+
if (id === 'virtual:nebula/collections')
|
|
111
|
+
return '\0virtual:nebula/collections';
|
|
112
|
+
if (id === 'virtual:nebula/config')
|
|
113
|
+
return '\0virtual:nebula/config';
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* Provides stub module source for virtual:nebula/* modules.
|
|
117
|
+
* @param {string} id - The internal module ID to load
|
|
118
|
+
* @return {string | undefined} The module source code, or undefined to skip
|
|
119
|
+
*/
|
|
120
|
+
load(id: string) {
|
|
121
|
+
if (id === '\0virtual:nebula/collections')
|
|
122
|
+
return 'export default {};';
|
|
123
|
+
if (id === '\0virtual:nebula/config') {
|
|
124
|
+
return 'export default { basePath: "/admin", collectionsPath: "/collections" };';
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
// Exclude @testing-library/svelte-core from pre-bundling so its
|
|
130
|
+
// .svelte.js files go through the Svelte plugin's transform pipeline
|
|
131
|
+
// (Vite pre-bundling skips plugin transforms, which leaves $state
|
|
132
|
+
// runes uncompiled and causes ReferenceError at runtime).
|
|
133
|
+
optimizeDeps: {
|
|
134
|
+
exclude: ['@testing-library/svelte-core'],
|
|
135
|
+
},
|
|
136
|
+
// browser condition ensures Vite resolves Svelte's client-side entry
|
|
137
|
+
// instead of the SSR server entry. @codemirror/* and @lezer/* are
|
|
138
|
+
// stubbed because browser tests mock the editor — the same stub used
|
|
139
|
+
// by component tests is reused here.
|
|
140
|
+
resolve: {
|
|
141
|
+
conditions: ['browser'],
|
|
142
|
+
alias: [
|
|
143
|
+
{
|
|
144
|
+
find: /^@codemirror\/.+/,
|
|
145
|
+
replacement: new URL('tests/stubs/codemirror.ts', import.meta.url)
|
|
146
|
+
.pathname,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
find: /^@lezer\/.+/,
|
|
150
|
+
replacement: new URL('tests/stubs/codemirror.ts', import.meta.url)
|
|
151
|
+
.pathname,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
test: {
|
|
156
|
+
name: 'browser',
|
|
157
|
+
include: ['tests/e2e/**/*.test.ts'],
|
|
158
|
+
browser: {
|
|
159
|
+
enabled: true,
|
|
160
|
+
headless: true,
|
|
161
|
+
// Uses system Chrome via the 'chrome' channel to avoid downloading
|
|
162
|
+
// a separate Chromium binary. CI adds --no-sandbox because most CI
|
|
163
|
+
// containers lack the kernel namespace support sandboxing requires.
|
|
164
|
+
provider: playwright({
|
|
165
|
+
launchOptions: {
|
|
166
|
+
channel: 'chrome',
|
|
167
|
+
...(process.env.CI
|
|
168
|
+
? { args: ['--no-sandbox', '--disable-setuid-sandbox'] }
|
|
169
|
+
: {}),
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
instances: [{ browser: 'chromium' }],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
});
|