@motion-proto/live-tokens 0.6.2 → 0.7.1
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 +14 -13
- package/dist-plugin/index.cjs +147 -136
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +145 -135
- package/package.json +25 -40
- package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
- package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
- package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
- package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +3 -3
- package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
- package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
- package/src/editor/component-editor/ImageEditor.svelte +30 -0
- package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
- package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
- package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +64 -37
- package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
- package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
- package/src/{component-editor → editor/component-editor}/SectionDividerEditor.svelte +57 -84
- package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
- package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +16 -20
- package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
- package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
- package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
- package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
- package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +2 -2
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +144 -416
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
- package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
- package/src/{component-editor → editor/component-editor}/scaffolding/DividerEditor.svelte +1 -1
- package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
- package/src/{component-editor → editor/component-editor}/scaffolding/GradientCard.svelte +6 -6
- package/src/{component-editor → editor/component-editor}/scaffolding/LinkageChart.svelte +6 -6
- package/src/{component-editor → editor/component-editor}/scaffolding/LinkedBlock.svelte +6 -11
- package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
- package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +72 -0
- package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +257 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +9 -7
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +644 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
- package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
- package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +14 -0
- package/src/{lib → editor/core/components}/componentConfigService.ts +2 -2
- package/src/{lib → editor/core/components}/componentPersist.ts +5 -5
- package/src/editor/core/flashStatus.ts +30 -0
- package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
- package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
- package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
- package/src/editor/core/manifests/manifestService.ts +116 -0
- package/src/{lib → editor/core/palettes}/paletteDerivation.ts +2 -2
- package/src/{lib → editor/core/palettes}/tokenRegistry.ts +5 -5
- package/src/editor/core/productionPulse.ts +37 -0
- package/src/{lib → editor/core/routing}/router.ts +1 -1
- package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
- package/src/{lib → editor/core/store}/editorCore.ts +24 -8
- package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
- package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
- package/src/{lib → editor/core/store}/editorStore.ts +17 -17
- package/src/{lib → editor/core/store}/editorTypes.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
- package/src/{lib → editor/core/themes}/slices/components.ts +2 -2
- package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/gradients.ts +2 -2
- package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
- package/src/{lib → editor/core/themes}/themeInit.ts +6 -6
- package/src/{lib → editor/core/themes}/themeService.ts +6 -6
- package/src/{lib → editor/core/themes}/themeTypes.ts +11 -7
- package/src/editor/index.ts +69 -0
- package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +79 -125
- package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
- package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
- package/src/{pages → editor/pages}/Editor.svelte +4 -4
- package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
- package/src/{styles → editor/styles}/ui-editor.css +41 -21
- package/src/{styles → editor/styles}/ui-form-controls.css +8 -8
- package/src/{ui → editor/ui}/BezierCurveEditor.svelte +8 -8
- package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
- package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +8 -6
- package/src/editor/ui/FileLoadList.svelte +350 -0
- package/src/editor/ui/FilePill.svelte +80 -0
- package/src/{ui → editor/ui}/FontStackEditor.svelte +7 -7
- package/src/{ui → editor/ui}/GradientEditor.svelte +11 -11
- package/src/{ui → editor/ui}/GradientStopPicker.svelte +1 -1
- package/src/editor/ui/ManifestFileManager.svelte +371 -0
- package/src/{ui → editor/ui}/PaletteEditor.svelte +132 -598
- package/src/{ui → editor/ui}/ProjectFontsSection.svelte +102 -144
- package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
- package/src/{ui → editor/ui}/TextTab.svelte +3 -3
- package/src/{ui → editor/ui}/ThemeFileManager.svelte +286 -519
- package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
- package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -6
- package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +1 -1
- package/src/editor/ui/UIInfoPopover.svelte +244 -0
- package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
- package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
- package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
- package/src/{ui → editor/ui}/UIPaletteSelector.svelte +26 -26
- package/src/editor/ui/UIPillButton.svelte +138 -0
- package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
- package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
- package/src/editor/ui/UISquareButton.svelte +172 -0
- package/src/{ui → editor/ui}/UITokenSelector.svelte +10 -10
- package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
- package/src/{ui → editor/ui}/VariablesTab.svelte +31 -8
- package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
- package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +13 -13
- package/src/{ui → editor/ui}/palette/PaletteBase.svelte +8 -5
- package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
- package/src/editor/ui/palette/paletteMath.ts +275 -0
- package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -17
- package/src/{ui → editor/ui}/sections/GradientsSection.svelte +7 -7
- package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +17 -17
- package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +22 -22
- package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
- package/src/{components → system/components}/Badge.svelte +0 -36
- package/src/{components → system/components}/Card.svelte +8 -62
- package/src/{components → system/components}/CornerBadge.svelte +8 -24
- package/src/{components → system/components}/Dialog.svelte +1 -1
- package/src/system/components/FloatingTokenTags.css +256 -0
- package/src/system/components/FloatingTokenTags.svelte +592 -0
- package/src/{components → system/components}/InlineEditActions.svelte +6 -4
- package/src/system/components/MenuSelect.svelte +229 -0
- package/src/{components → system/components}/ProgressBar.svelte +29 -11
- package/src/{components → system/components}/SegmentedControl.svelte +49 -43
- package/src/{components → system/components}/TabBar.svelte +81 -65
- package/src/{components → system/components}/Table.svelte +17 -3
- package/src/{components → system/components}/Tooltip.svelte +6 -4
- package/src/system/styles/CONVENTIONS.md +178 -0
- package/src/{styles → system/styles}/fonts.css +6 -3
- package/src/{styles → system/styles}/tokens.css +149 -29
- package/src/component-editor/ImageEditor.svelte +0 -74
- package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
- package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
- package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
- package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
- package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
- package/src/data/google-fonts.json +0 -75
- package/src/lib/index.ts +0 -68
- package/src/lib/presetService.ts +0 -214
- package/src/lib/productionPulse.ts +0 -32
- package/src/ui/PresetFileManager.svelte +0 -1116
- package/src/ui/UnsavedComponentsDialog.svelte +0 -315
- /package/src/{styles → app}/site.css +0 -0
- /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
- /package/src/{lib → editor/core/components}/componentConfigKeys.ts +0 -0
- /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
- /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
- /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
- /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
- /package/src/{lib → editor/core/storage}/storage.ts +0 -0
- /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
- /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
- /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
- /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/index.ts +0 -0
- /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
- /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
- /package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -0
- /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
- /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
- /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
- /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
- /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
- /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
- /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
- /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
- /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
- /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
- /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
- /package/src/{ui → editor/ui}/index.ts +0 -0
- /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
- /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
- /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
- /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
- /package/src/{ui → editor/ui}/variantScales.ts +0 -0
- /package/src/{assets → system/assets}/newspaper.webp +0 -0
- /package/src/{assets → system/assets}/offering.webp +0 -0
- /package/src/{components → system/components}/Button.svelte +0 -0
- /package/src/{components → system/components}/Callout.svelte +0 -0
- /package/src/{components → system/components}/CollapsibleSection.svelte +0 -0
- /package/src/{components → system/components}/Image.svelte +0 -0
- /package/src/{components → system/components}/Notification.svelte +0 -0
- /package/src/{components → system/components}/RadioButton.svelte +0 -0
- /package/src/{components → system/components}/SectionDivider.svelte +0 -0
- /package/src/{components → system/components}/types.ts +0 -0
- /package/src/{styles → system/styles}/_padding.scss +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ export default defineConfig({
|
|
|
33
33
|
svelte(),
|
|
34
34
|
themeFileApi({
|
|
35
35
|
themesDir: 'themes',
|
|
36
|
-
tokensCssPath: 'src/styles/tokens.css',
|
|
36
|
+
tokensCssPath: 'src/system/styles/tokens.css',
|
|
37
37
|
}),
|
|
38
38
|
],
|
|
39
39
|
optimizeDeps: {
|
|
@@ -44,7 +44,7 @@ export default defineConfig({
|
|
|
44
44
|
|
|
45
45
|
The `themeFileApi` plugin:
|
|
46
46
|
- Seeds `themes/` with a default theme on first dev-server start.
|
|
47
|
-
- Discovers components at `src/components/*.svelte` and seeds `component-configs/{comp}/default.json` from each component's `:global(:root)` block.
|
|
47
|
+
- Discovers components at `src/system/components/*.svelte` and seeds `component-configs/{comp}/default.json` from each component's `:global(:root)` block.
|
|
48
48
|
- Hosts the `/api/*` routes the editor uses to save and load themes + per-component configs.
|
|
49
49
|
- Auto-injects `__PROJECT_ROOT__` for the overlay's "Page Source" link.
|
|
50
50
|
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
initEditorStore,
|
|
62
62
|
} from '@motion-proto/live-tokens';
|
|
63
63
|
import App from './App.svelte';
|
|
64
|
+
import { mount } from 'svelte';
|
|
64
65
|
|
|
65
66
|
configureEditor({ storagePrefix: 'my-app-' });
|
|
66
67
|
|
|
@@ -72,7 +73,7 @@ async function boot() {
|
|
|
72
73
|
if (import.meta.env.DEV) {
|
|
73
74
|
await initializeTheme();
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
+
mount(App, { target: document.getElementById('app')! });
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
boot();
|
|
@@ -95,7 +96,7 @@ boot();
|
|
|
95
96
|
{ path: '/components', label: 'Components', icon: 'fa-puzzle-piece' },
|
|
96
97
|
]}
|
|
97
98
|
pageSources={{
|
|
98
|
-
'/': 'src/
|
|
99
|
+
'/': 'src/app/Home.svelte',
|
|
99
100
|
}}
|
|
100
101
|
/>
|
|
101
102
|
<ColumnsOverlay />
|
|
@@ -135,12 +136,12 @@ CSS variables on `:root`.
|
|
|
135
136
|
You can use the package's default as a starting point:
|
|
136
137
|
|
|
137
138
|
```ts
|
|
138
|
-
import '@motion-proto/live-tokens/
|
|
139
|
-
import '@motion-proto/live-tokens/
|
|
140
|
-
import '@motion-proto/live-tokens/
|
|
139
|
+
import '@motion-proto/live-tokens/app/tokens.css';
|
|
140
|
+
import '@motion-proto/live-tokens/app/site.css'; // optional: themed h1/p/a styles
|
|
141
|
+
import '@motion-proto/live-tokens/app/fonts.css'; // optional: Fraunces + Manrope @font-face
|
|
141
142
|
```
|
|
142
143
|
|
|
143
|
-
…or copy `node_modules/@motion-proto/live-tokens/src/styles/tokens.css` into
|
|
144
|
+
…or copy `node_modules/@motion-proto/live-tokens/src/system/styles/tokens.css` into
|
|
144
145
|
your project and edit. The editor will seed `themes/default.json` on first
|
|
145
146
|
run and you can promote your edits back into the file.
|
|
146
147
|
|
|
@@ -150,7 +151,7 @@ The minimum a consumer needs after `npm install @motion-proto/live-tokens`:
|
|
|
150
151
|
|
|
151
152
|
```ts
|
|
152
153
|
// src/main.ts
|
|
153
|
-
import '@motion-proto/live-tokens/
|
|
154
|
+
import '@motion-proto/live-tokens/app/tokens.css';
|
|
154
155
|
import { mount } from 'svelte';
|
|
155
156
|
import App from './App.svelte';
|
|
156
157
|
|
|
@@ -189,12 +190,12 @@ npm install
|
|
|
189
190
|
npm run dev
|
|
190
191
|
```
|
|
191
192
|
|
|
192
|
-
Open http://localhost:5173 and replace `src/
|
|
193
|
+
Open http://localhost:5173 and replace `src/app/Home.svelte` with your content. The rest of the wiring is already done — it's the same code the npm package ships, just with the App-shell scaffolding included.
|
|
193
194
|
|
|
194
195
|
## How the editor ships changes to prod
|
|
195
196
|
|
|
196
197
|
1. Edit in `/editor` or `/components`. Saves write to `themes/{name}.json` and `component-configs/{comp}/{name}.json`.
|
|
197
|
-
2. Promote a theme to "production." Its variables are written into `src/styles/tokens.css` and backed up under `src/styles/_backups/`.
|
|
198
|
+
2. Promote a theme to "production." Its variables are written into `src/system/styles/tokens.css` and backed up under `src/system/styles/_backups/`.
|
|
198
199
|
3. `npm run build` bundles `tokens.css` as plain CSS. No editor code, no JSON lookups, no dev surfaces ship to prod.
|
|
199
200
|
|
|
200
201
|
## File ownership — what the plugin writes
|
|
@@ -213,8 +214,8 @@ Knowing which files the plugin touches matters when upgrading the package or wor
|
|
|
213
214
|
**At dev-time editor actions, these files get rewritten by your explicit save/promote:**
|
|
214
215
|
|
|
215
216
|
- `themes/{name}.json` — every save in the editor.
|
|
216
|
-
- `src/styles/tokens.css` — fully regenerated when you save or promote the production theme. **Treat this as a build artifact.** Hand-edits get clobbered next time the production theme is saved; promote a theme instead.
|
|
217
|
-
- `src/styles/fonts.css` — same rule: regenerated from the theme's font sources.
|
|
217
|
+
- `src/system/styles/tokens.css` — fully regenerated when you save or promote the production theme. **Treat this as a build artifact.** Hand-edits get clobbered next time the production theme is saved; promote a theme instead.
|
|
218
|
+
- `src/system/styles/fonts.css` — same rule: regenerated from the theme's font sources.
|
|
218
219
|
- `component-configs/{comp}/{name}.json` — every save of a per-component config.
|
|
219
220
|
|
|
220
221
|
## Maintainer notes — publishing
|
package/dist-plugin/index.cjs
CHANGED
|
@@ -27,18 +27,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
|
-
//
|
|
30
|
+
// vite-plugin/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
themeFileApi: () => themeFileApi
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// vite-plugin/themeFileApi.ts
|
|
38
38
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
39
39
|
var import_path2 = __toESM(require("path"), 1);
|
|
40
40
|
|
|
41
|
-
// src/
|
|
41
|
+
// src/editor/core/themes/parsers/globalRootBlock.ts
|
|
42
42
|
function extractGlobalRootBody(source) {
|
|
43
43
|
const re = /:global\(:root\)\s*\{([^}]*)\}/g;
|
|
44
44
|
const bodies = [];
|
|
@@ -49,12 +49,12 @@ function extractGlobalRootBody(source) {
|
|
|
49
49
|
return bodies.join("\n");
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// src/
|
|
52
|
+
// src/editor/core/storage/files/versionedFileResourceClient.ts
|
|
53
53
|
function sanitizeFileName(name) {
|
|
54
54
|
return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "") || "unnamed";
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
//
|
|
57
|
+
// vite-plugin/files/versionedFileResourceServer.ts
|
|
58
58
|
var import_fs = __toESM(require("fs"), 1);
|
|
59
59
|
var import_path = __toESM(require("path"), 1);
|
|
60
60
|
function versionedFileResourceServer(opts) {
|
|
@@ -114,7 +114,7 @@ function versionedFileResourceServer(opts) {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
//
|
|
117
|
+
// vite-plugin/files/routeTable.ts
|
|
118
118
|
async function dispatch(req, res, routes) {
|
|
119
119
|
const url = req.url || "";
|
|
120
120
|
const method = req.method || "GET";
|
|
@@ -142,16 +142,35 @@ async function dispatch(req, res, routes) {
|
|
|
142
142
|
return false;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
//
|
|
146
|
-
var
|
|
145
|
+
// vite-plugin/themeFileApi.ts
|
|
146
|
+
var import_node_url = require("url");
|
|
147
|
+
var import_meta = {};
|
|
148
|
+
var PKG_VERSION = (() => {
|
|
149
|
+
try {
|
|
150
|
+
let dir = import_path2.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
151
|
+
for (let i = 0; i < 4; i++) {
|
|
152
|
+
const p = import_path2.default.join(dir, "package.json");
|
|
153
|
+
if (import_fs2.default.existsSync(p)) {
|
|
154
|
+
const json = JSON.parse(import_fs2.default.readFileSync(p, "utf-8"));
|
|
155
|
+
if (json?.name === "@motion-proto/live-tokens") return json.version ?? "";
|
|
156
|
+
}
|
|
157
|
+
const up = import_path2.default.dirname(dir);
|
|
158
|
+
if (up === dir) break;
|
|
159
|
+
dir = up;
|
|
160
|
+
}
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
return "";
|
|
164
|
+
})();
|
|
147
165
|
function themeFileApi(opts) {
|
|
148
166
|
const THEMES_DIR = import_path2.default.resolve(opts.themesDir);
|
|
149
167
|
const CSS_PATH = import_path2.default.resolve(opts.tokensCssPath);
|
|
150
168
|
const FONTS_CSS_PATH = opts.fontsCssPath ? import_path2.default.resolve(opts.fontsCssPath) : import_path2.default.join(import_path2.default.dirname(CSS_PATH), "fonts.css");
|
|
151
169
|
const API_BASE = opts.apiBase ?? "/api";
|
|
152
170
|
const COMPONENT_CONFIGS_DIR = opts.componentConfigsDir ? import_path2.default.resolve(opts.componentConfigsDir) : import_path2.default.resolve("component-configs");
|
|
153
|
-
const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? import_path2.default.resolve(opts.componentsSrcDir) : import_path2.default.resolve("src/components");
|
|
154
|
-
const
|
|
171
|
+
const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? import_path2.default.resolve(opts.componentsSrcDir) : import_path2.default.resolve("src/system/components");
|
|
172
|
+
const MANIFESTS_DIR = opts.manifestsDir ? import_path2.default.resolve(opts.manifestsDir) : import_path2.default.resolve("manifests");
|
|
173
|
+
const LEGACY_PRESETS_DIR = import_path2.default.resolve("presets");
|
|
155
174
|
const themesResource = versionedFileResourceServer({
|
|
156
175
|
dir: THEMES_DIR
|
|
157
176
|
});
|
|
@@ -164,7 +183,7 @@ function themeFileApi(opts) {
|
|
|
164
183
|
}
|
|
165
184
|
return r;
|
|
166
185
|
}
|
|
167
|
-
const
|
|
186
|
+
const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
|
|
168
187
|
function ensureThemesDir() {
|
|
169
188
|
themesResource.ensureDir();
|
|
170
189
|
if (!import_fs2.default.existsSync(import_path2.default.join(THEMES_DIR, "default.json"))) {
|
|
@@ -360,25 +379,63 @@ ${newVars}
|
|
|
360
379
|
r.ensureMeta();
|
|
361
380
|
}
|
|
362
381
|
}
|
|
363
|
-
function
|
|
364
|
-
|
|
365
|
-
|
|
382
|
+
function ensureManifestsDir() {
|
|
383
|
+
if (!import_fs2.default.existsSync(MANIFESTS_DIR) && import_fs2.default.existsSync(LEGACY_PRESETS_DIR)) {
|
|
384
|
+
import_fs2.default.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
|
|
385
|
+
const legacyProd = import_path2.default.join(MANIFESTS_DIR, "_production.json");
|
|
386
|
+
if (import_fs2.default.existsSync(legacyProd)) import_fs2.default.unlinkSync(legacyProd);
|
|
387
|
+
}
|
|
388
|
+
manifestsResource.ensureDir();
|
|
389
|
+
const defaultPath = import_path2.default.join(MANIFESTS_DIR, "default.json");
|
|
366
390
|
if (!import_fs2.default.existsSync(defaultPath)) {
|
|
367
391
|
const componentConfigs = {};
|
|
368
392
|
for (const comp of listComponentNames()) {
|
|
369
393
|
componentConfigs[comp] = componentResource(comp).getActiveName();
|
|
370
394
|
}
|
|
371
395
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
372
|
-
const
|
|
373
|
-
name: "Default
|
|
396
|
+
const defaultManifest = {
|
|
397
|
+
name: "Default",
|
|
374
398
|
createdAt: now,
|
|
375
399
|
updatedAt: now,
|
|
376
400
|
theme: themesResource.getActiveName(),
|
|
377
401
|
componentConfigs
|
|
378
402
|
};
|
|
379
|
-
import_fs2.default.writeFileSync(defaultPath, JSON.stringify(
|
|
403
|
+
import_fs2.default.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
|
|
404
|
+
}
|
|
405
|
+
if (!import_fs2.default.existsSync(manifestsResource.activePath)) {
|
|
406
|
+
import_fs2.default.writeFileSync(
|
|
407
|
+
manifestsResource.activePath,
|
|
408
|
+
JSON.stringify({ activeFile: "default" })
|
|
409
|
+
);
|
|
410
|
+
} else {
|
|
411
|
+
const activeName = manifestsResource.getActiveName();
|
|
412
|
+
if (!import_fs2.default.existsSync(manifestsResource.filePath(activeName))) {
|
|
413
|
+
manifestsResource.setActiveName("default");
|
|
414
|
+
}
|
|
380
415
|
}
|
|
381
|
-
|
|
416
|
+
const stragglerProd = import_path2.default.join(MANIFESTS_DIR, "_production.json");
|
|
417
|
+
if (import_fs2.default.existsSync(stragglerProd)) import_fs2.default.unlinkSync(stragglerProd);
|
|
418
|
+
}
|
|
419
|
+
function patchActiveManifest(field, comp, fileName) {
|
|
420
|
+
const activeFile = manifestsResource.getActiveName();
|
|
421
|
+
if (activeFile === "default") return false;
|
|
422
|
+
const manifestPath = manifestsResource.filePath(activeFile);
|
|
423
|
+
if (!import_fs2.default.existsSync(manifestPath)) return false;
|
|
424
|
+
let manifest;
|
|
425
|
+
try {
|
|
426
|
+
manifest = JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
427
|
+
} catch {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
if (field === "theme") {
|
|
431
|
+
manifest.theme = fileName;
|
|
432
|
+
} else if (field === "component" && comp) {
|
|
433
|
+
manifest.componentConfigs = manifest.componentConfigs ?? {};
|
|
434
|
+
manifest.componentConfigs[comp] = fileName;
|
|
435
|
+
}
|
|
436
|
+
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
437
|
+
import_fs2.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
438
|
+
return true;
|
|
382
439
|
}
|
|
383
440
|
function readComponentConfig(comp, name) {
|
|
384
441
|
const filePath = componentResource(comp).filePath(name);
|
|
@@ -443,16 +500,15 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
443
500
|
const THEMES_ACTIVE_ROUTE = `${API_BASE}/themes/active`;
|
|
444
501
|
const THEMES_PRODUCTION_ROUTE = `${API_BASE}/themes/production`;
|
|
445
502
|
const COMPONENT_CONFIGS_ROUTE = `${API_BASE}/component-configs`;
|
|
446
|
-
const
|
|
447
|
-
const
|
|
448
|
-
const PRESETS_PRODUCTION_ROUTE = `${API_BASE}/presets/production`;
|
|
503
|
+
const MANIFESTS_ROUTE = `${API_BASE}/manifests`;
|
|
504
|
+
const MANIFESTS_ACTIVE_ROUTE = `${API_BASE}/manifests/active`;
|
|
449
505
|
const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
|
|
450
506
|
const COMP_LIST_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)$`);
|
|
451
507
|
const COMP_ACTIVE_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/active$`);
|
|
452
508
|
const COMP_PRODUCTION_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/production$`);
|
|
453
509
|
const COMP_BY_NAME_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/([a-z0-9\\-_]+)$`);
|
|
454
|
-
const
|
|
455
|
-
const
|
|
510
|
+
const MANIFEST_APPLY_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)/apply$`);
|
|
511
|
+
const MANIFEST_BY_NAME_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)$`);
|
|
456
512
|
async function handleListThemes(_ctx) {
|
|
457
513
|
const activeFile = themesResource.getActiveName();
|
|
458
514
|
const files = import_fs2.default.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
@@ -511,10 +567,18 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
511
567
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
512
568
|
return;
|
|
513
569
|
}
|
|
570
|
+
if (manifestsResource.getActiveName() === "default") {
|
|
571
|
+
jsonResponse(res, 409, {
|
|
572
|
+
error: "Active manifest is protected. Save As first.",
|
|
573
|
+
code: "ACTIVE_IS_PROTECTED"
|
|
574
|
+
});
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
514
577
|
themesResource.setProductionName(fileName);
|
|
515
578
|
syncTokensToCss(fileName);
|
|
516
579
|
syncFontsToCss(fileName);
|
|
517
580
|
syncComponentsToCss();
|
|
581
|
+
patchActiveManifest("theme", null, fileName);
|
|
518
582
|
const data = JSON.parse(import_fs2.default.readFileSync(themesResource.filePath(fileName), "utf-8"));
|
|
519
583
|
jsonResponse(res, 200, {
|
|
520
584
|
ok: true,
|
|
@@ -561,6 +625,13 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
561
625
|
jsonResponse(res, 403, { error: "Cannot delete the default theme" });
|
|
562
626
|
return;
|
|
563
627
|
}
|
|
628
|
+
if (themesResource.getProductionName() === fileName) {
|
|
629
|
+
jsonResponse(res, 403, {
|
|
630
|
+
error: "Cannot delete the production theme. Adopt a different theme first.",
|
|
631
|
+
code: "PRODUCTION_THEME"
|
|
632
|
+
});
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
564
635
|
if (import_fs2.default.existsSync(filePath)) {
|
|
565
636
|
import_fs2.default.unlinkSync(filePath);
|
|
566
637
|
if (themesResource.getActiveName() === fileName) {
|
|
@@ -628,9 +699,17 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
628
699
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
629
700
|
return;
|
|
630
701
|
}
|
|
702
|
+
if (manifestsResource.getActiveName() === "default") {
|
|
703
|
+
jsonResponse(res, 409, {
|
|
704
|
+
error: "Active manifest is protected. Save As first.",
|
|
705
|
+
code: "ACTIVE_IS_PROTECTED"
|
|
706
|
+
});
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
631
709
|
r.ensureDir();
|
|
632
710
|
r.setProductionName(fileName);
|
|
633
711
|
syncComponentsToCss();
|
|
712
|
+
patchActiveManifest("component", comp, fileName);
|
|
634
713
|
const cfg = readComponentConfig(comp, fileName);
|
|
635
714
|
jsonResponse(res, 200, {
|
|
636
715
|
ok: true,
|
|
@@ -720,112 +799,46 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
720
799
|
});
|
|
721
800
|
jsonResponse(res, 200, { component: comp, files, activeFile, productionFile });
|
|
722
801
|
}
|
|
723
|
-
async function
|
|
724
|
-
const activeFile =
|
|
725
|
-
const files = import_fs2.default.readdirSync(
|
|
726
|
-
const filePath = import_path2.default.join(
|
|
802
|
+
async function handleListManifests({ res }) {
|
|
803
|
+
const activeFile = manifestsResource.getActiveName();
|
|
804
|
+
const files = import_fs2.default.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
805
|
+
const filePath = import_path2.default.join(MANIFESTS_DIR, f);
|
|
727
806
|
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
728
807
|
const fileName = f.replace(".json", "");
|
|
729
808
|
return {
|
|
730
809
|
name: data.name || fileName,
|
|
731
810
|
fileName,
|
|
732
811
|
updatedAt: data.updatedAt || "",
|
|
733
|
-
isActive: fileName === activeFile
|
|
812
|
+
isActive: fileName === activeFile,
|
|
813
|
+
isProtected: fileName === "default"
|
|
734
814
|
};
|
|
735
815
|
});
|
|
736
816
|
jsonResponse(res, 200, { files, activeFile });
|
|
737
817
|
}
|
|
738
|
-
async function
|
|
739
|
-
const activeFile =
|
|
740
|
-
const filePath =
|
|
818
|
+
async function handleGetActiveManifest({ res }) {
|
|
819
|
+
const activeFile = manifestsResource.getActiveName();
|
|
820
|
+
const filePath = manifestsResource.filePath(activeFile);
|
|
741
821
|
if (!import_fs2.default.existsSync(filePath)) {
|
|
742
|
-
jsonResponse(res, 404, { error: "Active
|
|
822
|
+
jsonResponse(res, 404, { error: "Active manifest not found" });
|
|
743
823
|
return;
|
|
744
824
|
}
|
|
745
825
|
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
746
826
|
data._fileName = activeFile;
|
|
747
827
|
jsonResponse(res, 200, data);
|
|
748
828
|
}
|
|
749
|
-
async function
|
|
829
|
+
async function handleSetActiveManifest({ req, res }) {
|
|
750
830
|
const body = JSON.parse(await readBody(req));
|
|
751
831
|
const fileName = sanitizeFileName(body.name || "default");
|
|
752
|
-
if (!import_fs2.default.existsSync(
|
|
753
|
-
jsonResponse(res, 404, { error: "
|
|
832
|
+
if (!import_fs2.default.existsSync(manifestsResource.filePath(fileName))) {
|
|
833
|
+
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
754
834
|
return;
|
|
755
835
|
}
|
|
756
|
-
|
|
836
|
+
manifestsResource.setActiveName(fileName);
|
|
757
837
|
jsonResponse(res, 200, { ok: true, activeFile: fileName });
|
|
758
838
|
}
|
|
759
|
-
async function
|
|
760
|
-
const prodFile = presetsResource.getProductionName();
|
|
761
|
-
const filePath = presetsResource.filePath(prodFile);
|
|
762
|
-
if (!import_fs2.default.existsSync(filePath)) {
|
|
763
|
-
jsonResponse(res, 200, {
|
|
764
|
-
fileName: prodFile,
|
|
765
|
-
name: prodFile,
|
|
766
|
-
theme: "default",
|
|
767
|
-
componentConfigs: {},
|
|
768
|
-
updatedAt: ""
|
|
769
|
-
});
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
773
|
-
jsonResponse(res, 200, {
|
|
774
|
-
fileName: prodFile,
|
|
775
|
-
name: data.name || prodFile,
|
|
776
|
-
theme: data.theme || "default",
|
|
777
|
-
componentConfigs: data.componentConfigs || {},
|
|
778
|
-
updatedAt: data.updatedAt || ""
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
async function handleSetProductionPreset({ req, res }) {
|
|
782
|
-
const body = JSON.parse(await readBody(req));
|
|
783
|
-
const fileName = sanitizeFileName(body.name || "default");
|
|
784
|
-
const presetPath = presetsResource.filePath(fileName);
|
|
785
|
-
if (!import_fs2.default.existsSync(presetPath)) {
|
|
786
|
-
jsonResponse(res, 404, { error: "Preset not found" });
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
const preset = JSON.parse(import_fs2.default.readFileSync(presetPath, "utf-8"));
|
|
790
|
-
const themeName = sanitizeFileName(preset.theme || "default");
|
|
791
|
-
if (!import_fs2.default.existsSync(themesResource.filePath(themeName))) {
|
|
792
|
-
jsonResponse(res, 422, { error: `Preset references missing theme: ${themeName}` });
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
const knownComponents = new Set(listComponentNames());
|
|
796
|
-
const componentConfigs = preset.componentConfigs ?? {};
|
|
797
|
-
const apply = [];
|
|
798
|
-
for (const [comp, configFile] of Object.entries(componentConfigs)) {
|
|
799
|
-
if (!knownComponents.has(comp)) continue;
|
|
800
|
-
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
801
|
-
if (!import_fs2.default.existsSync(componentResource(comp).filePath(sanitized))) {
|
|
802
|
-
jsonResponse(res, 422, {
|
|
803
|
-
error: `Preset references missing config: ${comp}/${sanitized}`
|
|
804
|
-
});
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
|
-
apply.push([comp, sanitized]);
|
|
808
|
-
}
|
|
809
|
-
themesResource.setProductionName(themeName);
|
|
810
|
-
for (const [comp, configFile] of apply) {
|
|
811
|
-
componentResource(comp).setProductionName(configFile);
|
|
812
|
-
}
|
|
813
|
-
presetsResource.setProductionName(fileName);
|
|
814
|
-
syncTokensToCss(themeName);
|
|
815
|
-
syncFontsToCss(themeName);
|
|
816
|
-
syncComponentsToCss();
|
|
817
|
-
jsonResponse(res, 200, {
|
|
818
|
-
ok: true,
|
|
819
|
-
fileName,
|
|
820
|
-
name: preset.name || fileName,
|
|
821
|
-
theme: themeName,
|
|
822
|
-
componentConfigs: Object.fromEntries(apply),
|
|
823
|
-
updatedAt: preset.updatedAt || ""
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
async function handlePresetByName({ params, req, res }) {
|
|
839
|
+
async function handleManifestByName({ params, req, res }) {
|
|
827
840
|
const [fileName] = params;
|
|
828
|
-
const filePath =
|
|
841
|
+
const filePath = manifestsResource.filePath(fileName);
|
|
829
842
|
if (req.method === "GET") {
|
|
830
843
|
if (!import_fs2.default.existsSync(filePath)) {
|
|
831
844
|
jsonResponse(res, 404, { error: "Not found" });
|
|
@@ -838,7 +851,7 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
838
851
|
}
|
|
839
852
|
if (req.method === "PUT") {
|
|
840
853
|
if (fileName === "default") {
|
|
841
|
-
jsonResponse(res, 403, { error: "Cannot overwrite the default
|
|
854
|
+
jsonResponse(res, 403, { error: "Cannot overwrite the default manifest" });
|
|
842
855
|
return;
|
|
843
856
|
}
|
|
844
857
|
const body = JSON.parse(await readBody(req));
|
|
@@ -857,35 +870,35 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
857
870
|
}
|
|
858
871
|
if (req.method === "DELETE") {
|
|
859
872
|
if (fileName === "default") {
|
|
860
|
-
jsonResponse(res, 403, { error: "Cannot delete the default
|
|
873
|
+
jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
|
|
861
874
|
return;
|
|
862
875
|
}
|
|
863
876
|
if (import_fs2.default.existsSync(filePath)) {
|
|
864
877
|
import_fs2.default.unlinkSync(filePath);
|
|
865
|
-
if (
|
|
866
|
-
|
|
878
|
+
if (manifestsResource.getActiveName() === fileName) {
|
|
879
|
+
manifestsResource.setActiveName("default");
|
|
867
880
|
}
|
|
868
881
|
}
|
|
869
882
|
jsonResponse(res, 200, { ok: true });
|
|
870
883
|
return;
|
|
871
884
|
}
|
|
872
885
|
}
|
|
873
|
-
async function
|
|
886
|
+
async function handleApplyManifest({ params, res }) {
|
|
874
887
|
const [fileName] = params;
|
|
875
|
-
const
|
|
876
|
-
if (!import_fs2.default.existsSync(
|
|
877
|
-
jsonResponse(res, 404, { error: "
|
|
888
|
+
const manifestPath = manifestsResource.filePath(fileName);
|
|
889
|
+
if (!import_fs2.default.existsSync(manifestPath)) {
|
|
890
|
+
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
878
891
|
return;
|
|
879
892
|
}
|
|
880
|
-
const
|
|
881
|
-
const themeName = sanitizeFileName(
|
|
893
|
+
const manifest = JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
894
|
+
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
882
895
|
const themePath = themesResource.filePath(themeName);
|
|
883
896
|
if (!import_fs2.default.existsSync(themePath)) {
|
|
884
|
-
jsonResponse(res, 422, { error: `
|
|
897
|
+
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
885
898
|
return;
|
|
886
899
|
}
|
|
887
900
|
const knownComponents = new Set(listComponentNames());
|
|
888
|
-
const componentConfigs =
|
|
901
|
+
const componentConfigs = manifest.componentConfigs ?? {};
|
|
889
902
|
const resolvedConfigs = {};
|
|
890
903
|
const apply = [];
|
|
891
904
|
for (const [comp, configFile] of Object.entries(componentConfigs)) {
|
|
@@ -895,7 +908,7 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
895
908
|
const cfgPath = r.filePath(sanitized);
|
|
896
909
|
if (!import_fs2.default.existsSync(cfgPath)) {
|
|
897
910
|
jsonResponse(res, 422, {
|
|
898
|
-
error: `
|
|
911
|
+
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
899
912
|
});
|
|
900
913
|
return;
|
|
901
914
|
}
|
|
@@ -916,10 +929,10 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
916
929
|
const cfg = readComponentConfig(comp, activeName);
|
|
917
930
|
if (cfg) resolvedConfigs[comp] = { ...cfg, _fileName: activeName };
|
|
918
931
|
}
|
|
919
|
-
|
|
932
|
+
manifestsResource.setActiveName(fileName);
|
|
920
933
|
jsonResponse(res, 200, {
|
|
921
934
|
ok: true,
|
|
922
|
-
|
|
935
|
+
manifest: { ...manifest, _fileName: fileName },
|
|
923
936
|
theme: themeData,
|
|
924
937
|
componentConfigs: resolvedConfigs
|
|
925
938
|
});
|
|
@@ -957,21 +970,19 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
957
970
|
{ method: "GET", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
958
971
|
{ method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
959
972
|
{ method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
960
|
-
//
|
|
961
|
-
{ method: "GET", pattern:
|
|
962
|
-
{ method: "GET", pattern:
|
|
963
|
-
{ method: "PUT", pattern:
|
|
964
|
-
|
|
965
|
-
{ method: "PUT", pattern:
|
|
966
|
-
|
|
967
|
-
{ method: "
|
|
968
|
-
{ method: "
|
|
969
|
-
|
|
970
|
-
{ method: "
|
|
971
|
-
|
|
972
|
-
{ method: "
|
|
973
|
-
{ method: "PUT", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName },
|
|
974
|
-
{ method: "DELETE", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName }
|
|
973
|
+
// Manifests — list / active are exact strings, must run before regexes
|
|
974
|
+
{ method: "GET", pattern: MANIFESTS_ROUTE, handler: handleListManifests },
|
|
975
|
+
{ method: "GET", pattern: MANIFESTS_ACTIVE_ROUTE, handler: handleGetActiveManifest },
|
|
976
|
+
{ method: "PUT", pattern: MANIFESTS_ACTIVE_ROUTE, handler: handleSetActiveManifest },
|
|
977
|
+
// Manifests — :name/apply (more specific than :name)
|
|
978
|
+
{ method: "PUT", pattern: MANIFEST_APPLY_REGEX, handler: handleApplyManifest },
|
|
979
|
+
{ method: "POST", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
|
|
980
|
+
{ method: "GET", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
|
|
981
|
+
{ method: "DELETE", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
|
|
982
|
+
// Manifests — :name CRUD (broadest manifest route, runs last)
|
|
983
|
+
{ method: "GET", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName },
|
|
984
|
+
{ method: "PUT", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName },
|
|
985
|
+
{ method: "DELETE", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName }
|
|
975
986
|
];
|
|
976
987
|
return {
|
|
977
988
|
name: "theme-file-api",
|
|
@@ -986,7 +997,7 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
986
997
|
configureServer(server) {
|
|
987
998
|
ensureThemesDir();
|
|
988
999
|
ensureComponentConfigsDir();
|
|
989
|
-
|
|
1000
|
+
ensureManifestsDir();
|
|
990
1001
|
server.middlewares.use(async (req, res, next) => {
|
|
991
1002
|
const handled = await dispatch(req, res, routes);
|
|
992
1003
|
if (!handled) next();
|
package/dist-plugin/index.d.cts
CHANGED
package/dist-plugin/index.d.ts
CHANGED