@velastack/cms 0.4.0 → 0.5.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.
Files changed (127) hide show
  1. package/README.md +107 -18
  2. package/dist/backend/index.d.ts +1 -1
  3. package/dist/backend/routes/seed.d.ts +6 -0
  4. package/dist/backend/routes/seed.js +96 -0
  5. package/dist/backend/routes/table.js +3 -0
  6. package/dist/backend/store/queries.d.ts +6 -1
  7. package/dist/backend/store/queries.js +89 -0
  8. package/dist/cms.js +13 -16
  9. package/dist/components/admin-bar/admin-bar-internal.svelte +4 -4
  10. package/dist/components/admin-bar/admin-bar.css +1 -1
  11. package/dist/components/admin-bar/field-input.svelte +220 -0
  12. package/dist/components/admin-bar/field-input.svelte.d.ts +29 -0
  13. package/dist/components/admin-bar/icons/pencil.svelte +19 -0
  14. package/dist/components/admin-bar/icons/pencil.svelte.d.ts +3 -0
  15. package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +1 -1
  16. package/dist/components/admin-bar/locales-panel.svelte +42 -1
  17. package/dist/components/admin-bar/page-config.d.ts +8 -1
  18. package/dist/components/admin-bar/page-config.js +15 -2
  19. package/dist/components/admin-bar/reorder-buttons.svelte +52 -0
  20. package/dist/components/admin-bar/reorder-buttons.svelte.d.ts +10 -0
  21. package/dist/components/admin-bar/seo-panel.svelte +144 -189
  22. package/dist/components/admin-bar/site-options-panel.svelte +115 -0
  23. package/dist/components/admin-bar/site-options-panel.svelte.d.ts +7 -0
  24. package/dist/components/admin-bar/structured-editor-popover.svelte +250 -0
  25. package/dist/components/admin-bar/structured-editor-popover.svelte.d.ts +48 -0
  26. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte +36 -0
  27. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte.d.ts +5 -0
  28. package/dist/components/admin-bar/ui/checkbox/index.d.ts +2 -0
  29. package/dist/components/admin-bar/ui/checkbox/index.js +2 -0
  30. package/dist/components/admin-bar/ui/popover/index.d.ts +5 -0
  31. package/dist/components/admin-bar/ui/popover/index.js +7 -0
  32. package/dist/components/admin-bar/ui/popover/popover-close.svelte +7 -0
  33. package/dist/components/admin-bar/ui/popover/popover-close.svelte.d.ts +4 -0
  34. package/dist/components/admin-bar/ui/popover/popover-content.svelte +35 -0
  35. package/dist/components/admin-bar/ui/popover/popover-content.svelte.d.ts +10 -0
  36. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte +7 -0
  37. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte.d.ts +4 -0
  38. package/dist/components/admin-bar/ui/popover/popover.svelte +7 -0
  39. package/dist/components/admin-bar/ui/popover/popover.svelte.d.ts +3 -0
  40. package/dist/components/admin-bar/ui/sheet/index.d.ts +10 -0
  41. package/dist/components/admin-bar/ui/sheet/index.js +12 -0
  42. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte +7 -0
  43. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte.d.ts +4 -0
  44. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte +64 -0
  45. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte.d.ts +17 -0
  46. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte +17 -0
  47. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte.d.ts +4 -0
  48. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte +23 -0
  49. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  50. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte +20 -0
  51. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte.d.ts +5 -0
  52. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte +20 -0
  53. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  54. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte +17 -0
  55. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte.d.ts +4 -0
  56. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte +7 -0
  57. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  58. package/dist/components/admin-bar/ui/sheet/sheet.svelte +7 -0
  59. package/dist/components/admin-bar/ui/sheet/sheet.svelte.d.ts +3 -0
  60. package/dist/components/admin-bar/ui/switch/index.d.ts +2 -0
  61. package/dist/components/admin-bar/ui/switch/index.js +2 -0
  62. package/dist/components/admin-bar/ui/switch/switch.svelte +27 -0
  63. package/dist/components/admin-bar/ui/switch/switch.svelte.d.ts +5 -0
  64. package/dist/components/admin-bar/ui/tabs/index.d.ts +5 -0
  65. package/dist/components/admin-bar/ui/tabs/index.js +7 -0
  66. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte +17 -0
  67. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte.d.ts +4 -0
  68. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte +16 -0
  69. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte.d.ts +4 -0
  70. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte +20 -0
  71. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  72. package/dist/components/admin-bar/ui/tabs/tabs.svelte +19 -0
  73. package/dist/components/admin-bar/ui/tabs/tabs.svelte.d.ts +4 -0
  74. package/dist/components/cms/cms-boolean.svelte +9 -18
  75. package/dist/components/cms/cms-boolean.svelte.d.ts +1 -0
  76. package/dist/components/cms/cms-date-time-editable.svelte +3 -3
  77. package/dist/components/cms/cms-date-time.svelte +17 -17
  78. package/dist/components/cms/cms-date-time.svelte.d.ts +2 -1
  79. package/dist/components/cms/cms-image-editable.svelte +13 -4
  80. package/dist/components/cms/cms-image.svelte +37 -30
  81. package/dist/components/cms/cms-image.svelte.d.ts +11 -4
  82. package/dist/components/cms/cms-link.svelte +26 -19
  83. package/dist/components/cms/cms-link.svelte.d.ts +2 -0
  84. package/dist/components/cms/cms-markdown.svelte +15 -16
  85. package/dist/components/cms/cms-markdown.svelte.d.ts +1 -0
  86. package/dist/components/cms/cms-number-editable.svelte +4 -2
  87. package/dist/components/cms/cms-number.svelte +18 -17
  88. package/dist/components/cms/cms-number.svelte.d.ts +2 -1
  89. package/dist/components/cms/cms-repeater.svelte +15 -18
  90. package/dist/components/cms/cms-repeater.svelte.d.ts +1 -0
  91. package/dist/components/cms/cms-rich-text.svelte +17 -22
  92. package/dist/components/cms/cms-rich-text.svelte.d.ts +1 -0
  93. package/dist/components/cms/cms-store.svelte.d.ts +14 -0
  94. package/dist/components/cms/cms-store.svelte.js +39 -2
  95. package/dist/components/cms/cms-text.svelte +23 -30
  96. package/dist/components/cms/cms-text.svelte.d.ts +3 -1
  97. package/dist/components/cms/scope.d.ts +25 -5
  98. package/dist/components/cms/structured-registry.d.ts +10 -0
  99. package/dist/components/cms/structured-registry.js +6 -0
  100. package/dist/components/cms/use-cms-field.svelte.d.ts +54 -0
  101. package/dist/components/cms/use-cms-field.svelte.js +83 -0
  102. package/dist/core/metadata.d.ts +44 -0
  103. package/dist/core/metadata.js +59 -0
  104. package/dist/core/structured.d.ts +108 -0
  105. package/dist/core/structured.js +184 -0
  106. package/dist/core/wire.d.ts +31 -1
  107. package/dist/editor.d.ts +22 -0
  108. package/dist/editor.js +21 -0
  109. package/dist/index.d.ts +12 -4
  110. package/dist/index.js +13 -3
  111. package/dist/server/load-cms.js +1 -0
  112. package/package.json +12 -3
  113. package/plugin/README.md +22 -2
  114. package/plugin/dist/build.d.ts +74 -0
  115. package/plugin/dist/build.js +210 -0
  116. package/plugin/dist/build.js.map +1 -0
  117. package/plugin/dist/index.d.ts +10 -1
  118. package/plugin/dist/index.js +63 -4
  119. package/plugin/dist/index.js.map +1 -1
  120. package/plugin/dist/manifest.d.ts +31 -0
  121. package/plugin/dist/manifest.js +146 -41
  122. package/plugin/dist/manifest.js.map +1 -1
  123. package/plugin/dist/parse-svelte.d.ts +15 -0
  124. package/plugin/dist/parse-svelte.js +26 -16
  125. package/plugin/dist/parse-svelte.js.map +1 -1
  126. package/dist/components/admin-bar/site-settings-panel.svelte +0 -225
  127. package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +0 -7
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@velastack/cms/editor` — the editing chrome a structured component's
3
+ * editable sibling imports lazily, so none of it reaches the public bundle:
4
+ *
5
+ * ```svelte
6
+ * {#await import('@velastack/cms/editor') then { StructuredEditorPopover, FieldInput, ReorderButtons }}
7
+ * ```
8
+ */
9
+ export { default as StructuredEditorPopover } from './components/admin-bar/structured-editor-popover.svelte';
10
+ export { default as FieldInput } from './components/admin-bar/field-input.svelte';
11
+ export type { FieldInputType } from './components/admin-bar/field-input.svelte';
12
+ export { default as ReorderButtons } from './components/admin-bar/reorder-buttons.svelte';
13
+ export { default as CssRoot } from './components/admin-bar/css-root.svelte';
14
+ export { Button } from './components/admin-bar/ui/button/index.js';
15
+ export { Input } from './components/admin-bar/ui/input/index.js';
16
+ export { Textarea } from './components/admin-bar/ui/textarea/index.js';
17
+ export { Switch } from './components/admin-bar/ui/switch/index.js';
18
+ export { Checkbox } from './components/admin-bar/ui/checkbox/index.js';
19
+ export * as Popover from './components/admin-bar/ui/popover/index.js';
20
+ export * as Tabs from './components/admin-bar/ui/tabs/index.js';
21
+ export * as Sheet from './components/admin-bar/ui/sheet/index.js';
22
+ export { default as CmsMediaPicker } from './components/cms/cms-media-picker.svelte';
package/dist/editor.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `@velastack/cms/editor` — the editing chrome a structured component's
3
+ * editable sibling imports lazily, so none of it reaches the public bundle:
4
+ *
5
+ * ```svelte
6
+ * {#await import('@velastack/cms/editor') then { StructuredEditorPopover, FieldInput, ReorderButtons }}
7
+ * ```
8
+ */
9
+ export { default as StructuredEditorPopover } from './components/admin-bar/structured-editor-popover.svelte';
10
+ export { default as FieldInput } from './components/admin-bar/field-input.svelte';
11
+ export { default as ReorderButtons } from './components/admin-bar/reorder-buttons.svelte';
12
+ export { default as CssRoot } from './components/admin-bar/css-root.svelte';
13
+ export { Button } from './components/admin-bar/ui/button/index.js';
14
+ export { Input } from './components/admin-bar/ui/input/index.js';
15
+ export { Textarea } from './components/admin-bar/ui/textarea/index.js';
16
+ export { Switch } from './components/admin-bar/ui/switch/index.js';
17
+ export { Checkbox } from './components/admin-bar/ui/checkbox/index.js';
18
+ export * as Popover from './components/admin-bar/ui/popover/index.js';
19
+ export * as Tabs from './components/admin-bar/ui/tabs/index.js';
20
+ export * as Sheet from './components/admin-bar/ui/sheet/index.js';
21
+ export { default as CmsMediaPicker } from './components/cms/cms-media-picker.svelte';
package/dist/index.d.ts CHANGED
@@ -7,21 +7,29 @@
7
7
  export { default as CmsText } from './components/cms/cms-text.svelte';
8
8
  export { default as CmsRichText } from './components/cms/cms-rich-text.svelte';
9
9
  export { default as CmsMarkdown } from './components/cms/cms-markdown.svelte';
10
- export { default as CmsImage } from './components/cms/cms-image.svelte';
10
+ export { default as CmsImage, normalizeImage } from './components/cms/cms-image.svelte';
11
+ export type { CmsImageValue } from './components/cms/cms-image.svelte';
11
12
  export { default as CmsBoolean } from './components/cms/cms-boolean.svelte';
12
13
  export { default as CmsNumber } from './components/cms/cms-number.svelte';
13
14
  export type { CmsNumberProps } from './components/cms/cms-number.svelte';
14
15
  export { default as CmsDateTime } from './components/cms/cms-date-time.svelte';
15
16
  export type { CmsDateTimeMode, CmsDateTimeProps } from './components/cms/cms-date-time.svelte';
16
- export { default as CmsLink } from './components/cms/cms-link.svelte';
17
+ export { default as CmsLink, normalizeLink } from './components/cms/cms-link.svelte';
17
18
  export type { CmsLinkValue, CmsLinkRenderProps } from './components/cms/cms-link.svelte';
18
19
  export { default as CmsRepeater } from './components/cms/cms-repeater.svelte';
19
20
  export { default as CmsEntries } from './components/cms/cms-entries.svelte';
20
21
  export { default as AdminBar } from './components/admin-bar/admin-bar.svelte';
21
- export { definePage } from './components/admin-bar/page-config.js';
22
+ export { useCmsField, resolveScopeRef, ROOT_SCOPE_ID } from './components/cms/use-cms-field.svelte.js';
23
+ export type { CmsField, CmsFieldInput } from './components/cms/use-cms-field.svelte.js';
24
+ export { defineStructured, applyTranslations, countTranslations, extractTranslations, stripTranslations, translatableFields, translationPath, asBoolean, asItems, asNumber, asString, newItemId, ROOT_ID, TRANSLATIONS_KEY } from './core/structured.js';
25
+ export type { Structured, StructuredItem, StructuredSchema, TranslatableField, TranslationOverlay } from './core/structured.js';
26
+ export { registerStructured, getStructured } from './components/cms/structured-registry.js';
27
+ export { toMetaTags } from './core/metadata.js';
28
+ export type { MetaTagsOptions, MetaTagsOutput } from './core/metadata.js';
29
+ export { definePage, DEFAULT_METADATA_SCHEMA, metadataSchemaFor } from './components/admin-bar/page-config.js';
22
30
  export type { CmsPageConfig, CmsCreatablePageConfig, CmsStaticPageConfig, CmsPageField, CmsPageMetadataSchema, MetadataFieldSchema, MetadataPrimitive } from './components/admin-bar/page-config.js';
23
31
  export { cmsStore } from './components/cms/cms-store.svelte.js';
24
32
  export { cms } from './components/cms/cms-store.svelte.js';
25
33
  export { CMS_SCOPE, getCmsScope, getCmsValue, getPageScope } from './components/cms/scope.js';
26
34
  export { installCmsScope } from './components/cms/install-scope.svelte.js';
27
- export type { CmsEntry, CmsManifest, CmsManifestRoute, CmsManifestScope, CmsPayload, CmsScope, CmsScopeEntry } from './components/cms/scope.js';
35
+ export type { CmsEntry, CmsManifest, CmsManifestRoute, CmsManifestScope, CmsManifestUsage, CmsPayload, CmsScope, CmsScopeEntry, SiteFieldSchema, SiteFieldType, SiteSchema } from './components/cms/scope.js';
package/dist/index.js CHANGED
@@ -8,17 +8,27 @@
8
8
  export { default as CmsText } from './components/cms/cms-text.svelte';
9
9
  export { default as CmsRichText } from './components/cms/cms-rich-text.svelte';
10
10
  export { default as CmsMarkdown } from './components/cms/cms-markdown.svelte';
11
- export { default as CmsImage } from './components/cms/cms-image.svelte';
11
+ export { default as CmsImage, normalizeImage } from './components/cms/cms-image.svelte';
12
12
  export { default as CmsBoolean } from './components/cms/cms-boolean.svelte';
13
13
  export { default as CmsNumber } from './components/cms/cms-number.svelte';
14
14
  export { default as CmsDateTime } from './components/cms/cms-date-time.svelte';
15
- export { default as CmsLink } from './components/cms/cms-link.svelte';
15
+ export { default as CmsLink, normalizeLink } from './components/cms/cms-link.svelte';
16
16
  export { default as CmsRepeater } from './components/cms/cms-repeater.svelte';
17
17
  export { default as CmsEntries } from './components/cms/cms-entries.svelte';
18
18
  // Admin bar (sync wrapper; admin-bar-internal + seo-panel are async chunks)
19
19
  export { default as AdminBar } from './components/admin-bar/admin-bar.svelte';
20
+ // Building blocks for structured components: the field hook, the value
21
+ // rules (versioned shapes, `$t` overlay) and the registry the Locales panel
22
+ // reads. The editor popover and field inputs are admin-bar chunks, imported
23
+ // lazily by editable siblings:
24
+ // `import('@velastack/cms/editor')`
25
+ export { useCmsField, resolveScopeRef, ROOT_SCOPE_ID } from './components/cms/use-cms-field.svelte.js';
26
+ export { defineStructured, applyTranslations, countTranslations, extractTranslations, stripTranslations, translatableFields, translationPath, asBoolean, asItems, asNumber, asString, newItemId, ROOT_ID, TRANSLATIONS_KEY } from './core/structured.js';
27
+ export { registerStructured, getStructured } from './components/cms/structured-registry.js';
28
+ // Page metadata → svelte-meta-tags props.
29
+ export { toMetaTags } from './core/metadata.js';
20
30
  // Per-route page configuration — declare in `page.cms.ts` next to `+page.svelte`.
21
- export { definePage } from './components/admin-bar/page-config.js';
31
+ export { definePage, DEFAULT_METADATA_SCHEMA, metadataSchemaFor } from './components/admin-bar/page-config.js';
22
32
  // Edit-mode store
23
33
  export { cmsStore } from './components/cms/cms-store.svelte.js';
24
34
  // Merged CMS read view (server payload + client overlay), shaped like CmsPayload
@@ -61,6 +61,7 @@ export const resolveCmsPayload = async (args) => {
61
61
  routeId: scope.routeId,
62
62
  params: scopeParams,
63
63
  fields: scope.fields,
64
+ ...(scope.usages ? { usages: scope.usages } : {}),
64
65
  locale: forLocale
65
66
  };
66
67
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velastack/cms",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "A scope-aware CMS for SvelteKit, for static or dynamic sites.",
5
5
  "keywords": [
6
6
  "svelte",
@@ -57,6 +57,11 @@
57
57
  "svelte": "./dist/index.js",
58
58
  "default": "./dist/index.js"
59
59
  },
60
+ "./editor": {
61
+ "types": "./dist/editor.d.ts",
62
+ "svelte": "./dist/editor.js",
63
+ "default": "./dist/editor.js"
64
+ },
60
65
  "./server": {
61
66
  "types": "./dist/server/index.d.ts",
62
67
  "default": "./dist/server/index.js"
@@ -72,6 +77,10 @@
72
77
  "./adapter": {
73
78
  "types": "./plugin/dist/adapter.d.ts",
74
79
  "default": "./plugin/dist/adapter.js"
80
+ },
81
+ "./build": {
82
+ "types": "./plugin/dist/build.d.ts",
83
+ "default": "./plugin/dist/build.js"
75
84
  }
76
85
  },
77
86
  "peerDependencies": {
@@ -110,7 +119,7 @@
110
119
  "tw-animate-css": "^1.4.0",
111
120
  "typescript": "^6.0.3",
112
121
  "vite": "^8.2.2",
113
- "vitest": "^4.1.11"
122
+ "vitest": "^5.0.1"
114
123
  },
115
124
  "dependencies": {
116
125
  "@sveltejs/adapter-static": "^3.0.10",
@@ -119,7 +128,7 @@
119
128
  "@tiptap/pm": "^3.30.6",
120
129
  "@tiptap/starter-kit": "^3.30.6",
121
130
  "bits-ui": "^2.19.0",
122
- "devalue": "^5.9.2",
131
+ "devalue": "^6.0.0",
123
132
  "tailwind-merge": "^3.6.0"
124
133
  }
125
134
  }
package/plugin/README.md CHANGED
@@ -31,6 +31,11 @@ type CmsPluginOptions = {
31
31
  libDir?: string; // default: 'src/lib'
32
32
  components?: ExternalCmsComponentSpec[];
33
33
  traverse?: (string | RegExp)[];
34
+ endpoint?: string; // media download at build time
35
+ locales?: string[]; // default: ['en']; locales[0] is the default locale
36
+ mediaDir?: string;
37
+ mediaPrefix?: string;
38
+ content?: string | false; // default: 'content' — see "Content manifest"
34
39
  };
35
40
 
36
41
  type ExternalCmsComponentSpec =
@@ -48,6 +53,14 @@ type ExternalCmsComponentSpec =
48
53
  `source === pattern || source.startsWith(pattern + '/')`. Auto-populated with
49
54
  every `components[].source`.
50
55
 
56
+ - `content` — directory of per-locale content manifests. See below.
57
+
58
+ ## Content manifest
59
+
60
+ When `<content>/<defaultLocale>.json` exists, the plugin reads it — an object keyed by scope id (`layout:/`, `page:/(public)/about`, `site`) — and injects each usage's value as a `fallback={…}` prop (`initial` for `CmsBoolean`) into every walked `.svelte` file, route entrypoints and shared components alike. A `scope="root"` usage reads `layout:/`; any other usage reads the scopes that reach its file, leaf first. Components in source stay name-only; the value the visitor sees before the CMS answers comes from the manifest. The file is watched, so edits apply in dev.
61
+
62
+ The same operation is available to other tooling from `@velastack/cms/build` (`scanUsages`, `injectFallbacks` / `inlineFallbacks`, `buildManifest`, `fallbackResolverFor`), so `pack` and `verify` in a templates repo share this parser instead of carrying their own.
63
+
51
64
  ## Virtual modules
52
65
 
53
66
  ### `virtual:vela-cms/manifest`
@@ -57,6 +70,7 @@ import { cmsManifest } from 'virtual:vela-cms/manifest';
57
70
 
58
71
  type CmsManifest = {
59
72
  version: 1;
73
+ // each scope lists `fields` (names) and `usages` ({ name, component, preset? })
60
74
  routes: Record<string, { scopes: CmsManifestScope[] }>;
61
75
  };
62
76
 
@@ -107,6 +121,8 @@ For each route entrypoint (`+page.svelte` or `+layout.svelte`), the plugin
107
121
  parses with `svelte/compiler` and follows static imports of `.svelte` files.
108
122
  Imports get classified as CMS components by:
109
123
 
124
+ 0. **`@velastack/cms` by name** — every named import from the package
125
+ specifier, with no resolver needed.
110
126
  1. **In-tree barrel** — anything from `<libDir>/components/cms/index.{ts,js}`.
111
127
  Named imports are CMS components; default isn't.
112
128
  2. **In-tree files** — `.svelte` files directly under `<libDir>/components/cms/`.
@@ -116,8 +132,12 @@ Imports get classified as CMS components by:
116
132
  4. **External `components` spec** — user-declared packs.
117
133
 
118
134
  Component usages with a `name=<static>` prop are recorded as field
119
- references; `value=<…>` opts the call out (it's a runtime override, not a
120
- field). Dynamic `name={expr}` props are ignored.
135
+ references with their component type; `value=<…>` opts the call out (it's a
136
+ runtime override, not a field). A `scope="root"` (or `scope="layout:/x"`)
137
+ attribute records the usage under that layout scope instead of the file's
138
+ own. Dynamic `name={expr}` props and `scope=` attributes naming a scope
139
+ outside the route's chain are reported as warnings on the build result and
140
+ logged by the plugin.
121
141
 
122
142
  ## HMR
123
143
 
@@ -0,0 +1,74 @@
1
+ import { buildManifest, resolveScopeAttr, ROOT_SCOPE_ID, type BuildManifestOptions, type BuildManifestResult, type CmsManifest, type CmsManifestScope, type CmsManifestUsage } from './manifest.js';
2
+ export { buildManifest, resolveScopeAttr, ROOT_SCOPE_ID };
3
+ export type Tree = Record<string, unknown>;
4
+ export type { BuildManifestOptions, BuildManifestResult, CmsManifest, CmsManifestScope, CmsManifestUsage };
5
+ export type CmsUsage = {
6
+ /** Static `name=` literal, or `null` when absent or dynamic. */
7
+ name: string | null;
8
+ /** Canonical exported component name (`CmsText`, `CmsHours`, …). */
9
+ component: string;
10
+ /** Local binding used in the template. */
11
+ local: string;
12
+ /** Resolved scope id from `scope=`, or `null` for the enclosing route scope. */
13
+ scope: string | null;
14
+ preset: string | null;
15
+ /** `name=` was present but not a static string. */
16
+ dynamic: boolean;
17
+ hasValue: boolean;
18
+ hasFallback: boolean;
19
+ line: number;
20
+ /** Source offsets of the component node. */
21
+ start: number;
22
+ end: number;
23
+ };
24
+ export type ScanOptions = {
25
+ filename?: string;
26
+ /**
27
+ * Extra local names to treat as CMS components, for wrappers a template
28
+ * declares itself. Package imports and `$lib/components/cms/*` are always
29
+ * recognized.
30
+ */
31
+ components?: string[];
32
+ };
33
+ export type ScanResult = {
34
+ usages: CmsUsage[];
35
+ /** Dynamic names, which no manifest can record. */
36
+ warnings: string[];
37
+ };
38
+ /** Every CMS component usage in one `.svelte` source. */
39
+ export declare const scanUsages: (source: string, options?: ScanOptions) => ScanResult;
40
+ /** Returns the value to inject for a usage, or `undefined` to leave it alone. */
41
+ export type FallbackResolver = (usage: CmsUsage) => unknown;
42
+ export type InjectOptions = ScanOptions & {
43
+ /** Replace an existing `fallback` / `initial` prop instead of skipping it. */
44
+ overwrite?: boolean;
45
+ };
46
+ export type InjectResult = {
47
+ code: string;
48
+ /** Names that received a fallback. */
49
+ injected: string[];
50
+ /** Static names the resolver had no value for. */
51
+ missing: string[];
52
+ };
53
+ /**
54
+ * Write values into a file's CMS usages as `fallback={…}` props (the JSON
55
+ * literal of the value), leaving the source otherwise untouched. `resolve`
56
+ * is a content tree keyed by name, or a function for callers that know
57
+ * which scope each usage's value lives in (see {@link fallbackResolverFor}).
58
+ *
59
+ * Usages with a `value=` prop, a dynamic name, or (unless `overwrite`) an
60
+ * existing fallback are skipped. The plugin calls this in memory at build
61
+ * time in the templates repo; `pack` calls it to write the tarball's
62
+ * components, which is why it is also exported as {@link inlineFallbacks}.
63
+ */
64
+ export declare const injectFallbacks: (source: string, resolve: Tree | FallbackResolver, options?: InjectOptions) => InjectResult;
65
+ /** Same operation as {@link injectFallbacks}, named for the `pack` step that
66
+ * writes the result to disk. */
67
+ export declare const inlineFallbacks: (source: string, resolve: Tree | FallbackResolver, options?: InjectOptions) => InjectResult;
68
+ /**
69
+ * A resolver for one file, given a built manifest and a content manifest
70
+ * keyed by scope id (`layout:/`, `page:/(public)/about`, …). A usage with
71
+ * `scope=` reads that scope; otherwise the scopes that reach the file are
72
+ * tried leaf first, and the first one holding the value wins.
73
+ */
74
+ export declare const fallbackResolverFor: (result: Pick<BuildManifestResult, "scopesByFile">, file: string, content: Record<string, Tree>) => FallbackResolver;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * `@velastack/cms/build` — the one Svelte parser for build tooling.
3
+ *
4
+ * The templates repo's `pack` and `verify` steps, and this package's own Vite
5
+ * plugin, all need the same three things: which CMS components a `.svelte`
6
+ * file uses ({@link scanUsages}), how to write a content manifest's values
7
+ * into those usages as `fallback` props ({@link injectFallbacks}), and which
8
+ * scope a file's values live in ({@link fallbackResolverFor}, on top of
9
+ * {@link buildManifest}). Keeping them here means no consumer carries a Svelte
10
+ * parser of its own.
11
+ */
12
+ import { basename } from 'node:path';
13
+ import { parseSvelteSource } from './parse-svelte.js';
14
+ import { buildManifest, isPackageSource, resolveScopeAttr, ROOT_SCOPE_ID } from './manifest.js';
15
+ export { buildManifest, resolveScopeAttr, ROOT_SCOPE_ID };
16
+ /** Dot-path read, the same rule as `core/path.ts` (numeric segments index arrays). */
17
+ const get = (tree, path) => {
18
+ let cur = tree;
19
+ for (const seg of path.split('.')) {
20
+ if (cur == null || typeof cur !== 'object')
21
+ return undefined;
22
+ cur = cur[seg];
23
+ }
24
+ return cur;
25
+ };
26
+ const IN_TREE_CMS_DIR = '$lib/components/cms';
27
+ /**
28
+ * Classify a single file's imports without a bundler: the package by name,
29
+ * the in-tree `$lib/components/cms` barrel or files, and the caller's own
30
+ * list. Returns local binding → canonical component name.
31
+ */
32
+ const classifyImports = (imports, extra) => {
33
+ const out = new Map();
34
+ for (const imp of imports) {
35
+ const source = imp.source;
36
+ if (isPackageSource(source) ||
37
+ source === IN_TREE_CMS_DIR ||
38
+ source === IN_TREE_CMS_DIR + '/index.js') {
39
+ for (const b of imp.bindings)
40
+ if (b.imported !== 'default')
41
+ out.set(b.local, b.imported);
42
+ continue;
43
+ }
44
+ if (source.startsWith(IN_TREE_CMS_DIR + '/') && source.endsWith('.svelte')) {
45
+ for (const b of imp.bindings) {
46
+ if (b.imported === 'default')
47
+ out.set(b.local, basename(source, '.svelte'));
48
+ }
49
+ }
50
+ }
51
+ for (const name of extra)
52
+ if (!out.has(name))
53
+ out.set(name, name);
54
+ return out;
55
+ };
56
+ const toUsage = (u, component) => ({
57
+ name: u.fieldName,
58
+ component,
59
+ local: u.componentName,
60
+ scope: u.scopeAttr ? resolveScopeAttr(u.scopeAttr) : null,
61
+ preset: u.presetAttr,
62
+ dynamic: u.dynamicName,
63
+ hasValue: u.hasValueAttr,
64
+ hasFallback: u.hasFallbackAttr,
65
+ line: u.line,
66
+ start: u.start,
67
+ end: u.end
68
+ });
69
+ /** Every CMS component usage in one `.svelte` source. */
70
+ export const scanUsages = (source, options = {}) => {
71
+ const parsed = parseSvelteSource(source, options.filename);
72
+ const locals = classifyImports(parsed.imports, options.components ?? []);
73
+ const usages = [];
74
+ const warnings = [];
75
+ const where = options.filename ?? '<source>';
76
+ for (const u of parsed.componentUsages) {
77
+ const component = locals.get(u.componentName);
78
+ if (!component)
79
+ continue;
80
+ const usage = toUsage(u, component);
81
+ usages.push(usage);
82
+ if (usage.dynamic) {
83
+ warnings.push(`${where}:${u.line} <${u.componentName}> has a dynamic name`);
84
+ }
85
+ }
86
+ return { usages, warnings };
87
+ };
88
+ /** Components whose fallback prop is not called `fallback`. */
89
+ const FALLBACK_PROP = { CmsBoolean: 'initial' };
90
+ /**
91
+ * Write values into a file's CMS usages as `fallback={…}` props (the JSON
92
+ * literal of the value), leaving the source otherwise untouched. `resolve`
93
+ * is a content tree keyed by name, or a function for callers that know
94
+ * which scope each usage's value lives in (see {@link fallbackResolverFor}).
95
+ *
96
+ * Usages with a `value=` prop, a dynamic name, or (unless `overwrite`) an
97
+ * existing fallback are skipped. The plugin calls this in memory at build
98
+ * time in the templates repo; `pack` calls it to write the tarball's
99
+ * components, which is why it is also exported as {@link inlineFallbacks}.
100
+ */
101
+ export const injectFallbacks = (source, resolve, options = {}) => {
102
+ const parsed = parseSvelteSource(source, options.filename);
103
+ const locals = classifyImports(parsed.imports, options.components ?? []);
104
+ const resolver = typeof resolve === 'function' ? resolve : (u) => (u.name ? get(resolve, u.name) : undefined);
105
+ const edits = [];
106
+ const injected = [];
107
+ const missing = [];
108
+ for (const u of parsed.componentUsages) {
109
+ const component = locals.get(u.componentName);
110
+ if (!component || !u.fieldName || u.hasValueAttr || u.nameAttrEnd === null)
111
+ continue;
112
+ if (u.hasFallbackAttr && !options.overwrite)
113
+ continue;
114
+ const value = resolver(toUsage(u, component));
115
+ if (value === undefined) {
116
+ missing.push(u.fieldName);
117
+ continue;
118
+ }
119
+ const prop = FALLBACK_PROP[component] ?? 'fallback';
120
+ const literal = JSON.stringify(value);
121
+ if (u.hasFallbackAttr) {
122
+ const existing = findAttr(source, u.start, u.end, prop);
123
+ if (existing)
124
+ edits.push({ at: existing[0], text: `${prop}={${literal}}`, replace: existing });
125
+ else
126
+ edits.push({ at: u.nameAttrEnd, text: ` ${prop}={${literal}}` });
127
+ }
128
+ else {
129
+ edits.push({ at: u.nameAttrEnd, text: ` ${prop}={${literal}}` });
130
+ }
131
+ injected.push(u.fieldName);
132
+ }
133
+ // Apply from the end so earlier offsets stay valid.
134
+ edits.sort((a, b) => b.at - a.at);
135
+ let code = source;
136
+ for (const e of edits) {
137
+ if (e.replace)
138
+ code = code.slice(0, e.replace[0]) + e.text + code.slice(e.replace[1]);
139
+ else
140
+ code = code.slice(0, e.at) + e.text + code.slice(e.at);
141
+ }
142
+ return { code, injected, missing };
143
+ };
144
+ /** Same operation as {@link injectFallbacks}, named for the `pack` step that
145
+ * writes the result to disk. */
146
+ export const inlineFallbacks = injectFallbacks;
147
+ /** Locate `prop=` inside a component node's source. Returns `[start, end]`. */
148
+ const findAttr = (source, start, end, prop) => {
149
+ const re = new RegExp(`\\s${prop}\\s*=`, 'g');
150
+ const slice = source.slice(start, end);
151
+ const m = re.exec(slice);
152
+ if (!m)
153
+ return null;
154
+ const attrStart = start + m.index + 1;
155
+ // Find the matching end: either a quoted string or a balanced `{…}`.
156
+ let i = start + m.index + m[0].length;
157
+ while (i < end && /\s/.test(source[i]))
158
+ i++;
159
+ if (source[i] === '"' || source[i] === "'") {
160
+ const q = source[i];
161
+ i++;
162
+ while (i < end && source[i] !== q)
163
+ i++;
164
+ return [attrStart, i + 1];
165
+ }
166
+ if (source[i] === '{') {
167
+ let depth = 0;
168
+ for (; i < end; i++) {
169
+ const c = source[i];
170
+ if (c === '{')
171
+ depth++;
172
+ else if (c === '}') {
173
+ depth--;
174
+ if (depth === 0)
175
+ return [attrStart, i + 1];
176
+ }
177
+ else if (c === '"' || c === "'" || c === '`') {
178
+ const q = c;
179
+ i++;
180
+ while (i < end && source[i] !== q) {
181
+ if (source[i] === '\\')
182
+ i++;
183
+ i++;
184
+ }
185
+ }
186
+ }
187
+ }
188
+ return null;
189
+ };
190
+ /**
191
+ * A resolver for one file, given a built manifest and a content manifest
192
+ * keyed by scope id (`layout:/`, `page:/(public)/about`, …). A usage with
193
+ * `scope=` reads that scope; otherwise the scopes that reach the file are
194
+ * tried leaf first, and the first one holding the value wins.
195
+ */
196
+ export const fallbackResolverFor = (result, file, content) => {
197
+ const reach = result.scopesByFile.get(file) ?? [];
198
+ return (usage) => {
199
+ if (!usage.name)
200
+ return undefined;
201
+ const candidates = usage.scope ? [usage.scope] : reach;
202
+ for (const scopeId of candidates) {
203
+ const v = get(content[scopeId], usage.name);
204
+ if (v !== undefined)
205
+ return v;
206
+ }
207
+ return undefined;
208
+ };
209
+ };
210
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,15 @@ export type CmsPluginOptions = {
35
35
  mediaDir?: string;
36
36
  /** URL prefix used in rewritten content. Defaults to `'/cms-media'`. */
37
37
  mediaPrefix?: string;
38
+ /**
39
+ * Directory of per-locale content manifests, `content/<locale>.json`,
40
+ * keyed by scope id (`layout:/`, `page:/(public)/about`, `site`). When the
41
+ * default locale's file exists (`locales[0]`, else `en`), its values are
42
+ * injected into every walked `.svelte` file as `fallback` props, so
43
+ * components stay name-only in source. Relative to the Vite root; defaults
44
+ * to `'content'`. Pass `false` to disable.
45
+ */
46
+ content?: string | false;
38
47
  };
39
48
  /**
40
49
  * Vite plugin that scans SvelteKit route files, walks the static Svelte
@@ -53,4 +62,4 @@ export type CmsPluginOptions = {
53
62
  * aren't themselves CMS components.
54
63
  */
55
64
  export declare const cms: (options?: CmsPluginOptions) => Plugin;
56
- export type { CmsManifest, CmsManifestScope, ExternalCmsComponentSpec } from './manifest.js';
65
+ export type { CmsManifest, CmsManifestScope, CmsManifestUsage, ExternalCmsComponentSpec } from './manifest.js';