@motion-proto/live-tokens 0.6.1 → 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 +149 -136
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +147 -135
- package/package.json +26 -41
- 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,15 +142,35 @@ async function dispatch(req, res, routes) {
|
|
|
142
142
|
return false;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
//
|
|
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
|
+
})();
|
|
146
165
|
function themeFileApi(opts) {
|
|
147
166
|
const THEMES_DIR = import_path2.default.resolve(opts.themesDir);
|
|
148
167
|
const CSS_PATH = import_path2.default.resolve(opts.tokensCssPath);
|
|
149
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");
|
|
150
169
|
const API_BASE = opts.apiBase ?? "/api";
|
|
151
170
|
const COMPONENT_CONFIGS_DIR = opts.componentConfigsDir ? import_path2.default.resolve(opts.componentConfigsDir) : import_path2.default.resolve("component-configs");
|
|
152
|
-
const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? import_path2.default.resolve(opts.componentsSrcDir) : import_path2.default.resolve("src/components");
|
|
153
|
-
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");
|
|
154
174
|
const themesResource = versionedFileResourceServer({
|
|
155
175
|
dir: THEMES_DIR
|
|
156
176
|
});
|
|
@@ -163,7 +183,7 @@ function themeFileApi(opts) {
|
|
|
163
183
|
}
|
|
164
184
|
return r;
|
|
165
185
|
}
|
|
166
|
-
const
|
|
186
|
+
const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
|
|
167
187
|
function ensureThemesDir() {
|
|
168
188
|
themesResource.ensureDir();
|
|
169
189
|
if (!import_fs2.default.existsSync(import_path2.default.join(THEMES_DIR, "default.json"))) {
|
|
@@ -359,25 +379,63 @@ ${newVars}
|
|
|
359
379
|
r.ensureMeta();
|
|
360
380
|
}
|
|
361
381
|
}
|
|
362
|
-
function
|
|
363
|
-
|
|
364
|
-
|
|
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");
|
|
365
390
|
if (!import_fs2.default.existsSync(defaultPath)) {
|
|
366
391
|
const componentConfigs = {};
|
|
367
392
|
for (const comp of listComponentNames()) {
|
|
368
393
|
componentConfigs[comp] = componentResource(comp).getActiveName();
|
|
369
394
|
}
|
|
370
395
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
|
-
const
|
|
372
|
-
name: "Default
|
|
396
|
+
const defaultManifest = {
|
|
397
|
+
name: "Default",
|
|
373
398
|
createdAt: now,
|
|
374
399
|
updatedAt: now,
|
|
375
400
|
theme: themesResource.getActiveName(),
|
|
376
401
|
componentConfigs
|
|
377
402
|
};
|
|
378
|
-
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
|
+
}
|
|
379
415
|
}
|
|
380
|
-
|
|
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;
|
|
381
439
|
}
|
|
382
440
|
function readComponentConfig(comp, name) {
|
|
383
441
|
const filePath = componentResource(comp).filePath(name);
|
|
@@ -442,16 +500,15 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
442
500
|
const THEMES_ACTIVE_ROUTE = `${API_BASE}/themes/active`;
|
|
443
501
|
const THEMES_PRODUCTION_ROUTE = `${API_BASE}/themes/production`;
|
|
444
502
|
const COMPONENT_CONFIGS_ROUTE = `${API_BASE}/component-configs`;
|
|
445
|
-
const
|
|
446
|
-
const
|
|
447
|
-
const PRESETS_PRODUCTION_ROUTE = `${API_BASE}/presets/production`;
|
|
503
|
+
const MANIFESTS_ROUTE = `${API_BASE}/manifests`;
|
|
504
|
+
const MANIFESTS_ACTIVE_ROUTE = `${API_BASE}/manifests/active`;
|
|
448
505
|
const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
|
|
449
506
|
const COMP_LIST_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)$`);
|
|
450
507
|
const COMP_ACTIVE_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/active$`);
|
|
451
508
|
const COMP_PRODUCTION_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/production$`);
|
|
452
509
|
const COMP_BY_NAME_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/([a-z0-9\\-_]+)$`);
|
|
453
|
-
const
|
|
454
|
-
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\\-_]+)$`);
|
|
455
512
|
async function handleListThemes(_ctx) {
|
|
456
513
|
const activeFile = themesResource.getActiveName();
|
|
457
514
|
const files = import_fs2.default.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
@@ -510,10 +567,18 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
510
567
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
511
568
|
return;
|
|
512
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
|
+
}
|
|
513
577
|
themesResource.setProductionName(fileName);
|
|
514
578
|
syncTokensToCss(fileName);
|
|
515
579
|
syncFontsToCss(fileName);
|
|
516
580
|
syncComponentsToCss();
|
|
581
|
+
patchActiveManifest("theme", null, fileName);
|
|
517
582
|
const data = JSON.parse(import_fs2.default.readFileSync(themesResource.filePath(fileName), "utf-8"));
|
|
518
583
|
jsonResponse(res, 200, {
|
|
519
584
|
ok: true,
|
|
@@ -560,6 +625,13 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
560
625
|
jsonResponse(res, 403, { error: "Cannot delete the default theme" });
|
|
561
626
|
return;
|
|
562
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
|
+
}
|
|
563
635
|
if (import_fs2.default.existsSync(filePath)) {
|
|
564
636
|
import_fs2.default.unlinkSync(filePath);
|
|
565
637
|
if (themesResource.getActiveName() === fileName) {
|
|
@@ -627,9 +699,17 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
627
699
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
628
700
|
return;
|
|
629
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
|
+
}
|
|
630
709
|
r.ensureDir();
|
|
631
710
|
r.setProductionName(fileName);
|
|
632
711
|
syncComponentsToCss();
|
|
712
|
+
patchActiveManifest("component", comp, fileName);
|
|
633
713
|
const cfg = readComponentConfig(comp, fileName);
|
|
634
714
|
jsonResponse(res, 200, {
|
|
635
715
|
ok: true,
|
|
@@ -719,112 +799,46 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
719
799
|
});
|
|
720
800
|
jsonResponse(res, 200, { component: comp, files, activeFile, productionFile });
|
|
721
801
|
}
|
|
722
|
-
async function
|
|
723
|
-
const activeFile =
|
|
724
|
-
const files = import_fs2.default.readdirSync(
|
|
725
|
-
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);
|
|
726
806
|
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
727
807
|
const fileName = f.replace(".json", "");
|
|
728
808
|
return {
|
|
729
809
|
name: data.name || fileName,
|
|
730
810
|
fileName,
|
|
731
811
|
updatedAt: data.updatedAt || "",
|
|
732
|
-
isActive: fileName === activeFile
|
|
812
|
+
isActive: fileName === activeFile,
|
|
813
|
+
isProtected: fileName === "default"
|
|
733
814
|
};
|
|
734
815
|
});
|
|
735
816
|
jsonResponse(res, 200, { files, activeFile });
|
|
736
817
|
}
|
|
737
|
-
async function
|
|
738
|
-
const activeFile =
|
|
739
|
-
const filePath =
|
|
818
|
+
async function handleGetActiveManifest({ res }) {
|
|
819
|
+
const activeFile = manifestsResource.getActiveName();
|
|
820
|
+
const filePath = manifestsResource.filePath(activeFile);
|
|
740
821
|
if (!import_fs2.default.existsSync(filePath)) {
|
|
741
|
-
jsonResponse(res, 404, { error: "Active
|
|
822
|
+
jsonResponse(res, 404, { error: "Active manifest not found" });
|
|
742
823
|
return;
|
|
743
824
|
}
|
|
744
825
|
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
745
826
|
data._fileName = activeFile;
|
|
746
827
|
jsonResponse(res, 200, data);
|
|
747
828
|
}
|
|
748
|
-
async function
|
|
829
|
+
async function handleSetActiveManifest({ req, res }) {
|
|
749
830
|
const body = JSON.parse(await readBody(req));
|
|
750
831
|
const fileName = sanitizeFileName(body.name || "default");
|
|
751
|
-
if (!import_fs2.default.existsSync(
|
|
752
|
-
jsonResponse(res, 404, { error: "
|
|
832
|
+
if (!import_fs2.default.existsSync(manifestsResource.filePath(fileName))) {
|
|
833
|
+
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
753
834
|
return;
|
|
754
835
|
}
|
|
755
|
-
|
|
836
|
+
manifestsResource.setActiveName(fileName);
|
|
756
837
|
jsonResponse(res, 200, { ok: true, activeFile: fileName });
|
|
757
838
|
}
|
|
758
|
-
async function
|
|
759
|
-
const prodFile = presetsResource.getProductionName();
|
|
760
|
-
const filePath = presetsResource.filePath(prodFile);
|
|
761
|
-
if (!import_fs2.default.existsSync(filePath)) {
|
|
762
|
-
jsonResponse(res, 200, {
|
|
763
|
-
fileName: prodFile,
|
|
764
|
-
name: prodFile,
|
|
765
|
-
theme: "default",
|
|
766
|
-
componentConfigs: {},
|
|
767
|
-
updatedAt: ""
|
|
768
|
-
});
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
|
|
772
|
-
jsonResponse(res, 200, {
|
|
773
|
-
fileName: prodFile,
|
|
774
|
-
name: data.name || prodFile,
|
|
775
|
-
theme: data.theme || "default",
|
|
776
|
-
componentConfigs: data.componentConfigs || {},
|
|
777
|
-
updatedAt: data.updatedAt || ""
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
async function handleSetProductionPreset({ req, res }) {
|
|
781
|
-
const body = JSON.parse(await readBody(req));
|
|
782
|
-
const fileName = sanitizeFileName(body.name || "default");
|
|
783
|
-
const presetPath = presetsResource.filePath(fileName);
|
|
784
|
-
if (!import_fs2.default.existsSync(presetPath)) {
|
|
785
|
-
jsonResponse(res, 404, { error: "Preset not found" });
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
const preset = JSON.parse(import_fs2.default.readFileSync(presetPath, "utf-8"));
|
|
789
|
-
const themeName = sanitizeFileName(preset.theme || "default");
|
|
790
|
-
if (!import_fs2.default.existsSync(themesResource.filePath(themeName))) {
|
|
791
|
-
jsonResponse(res, 422, { error: `Preset references missing theme: ${themeName}` });
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
const knownComponents = new Set(listComponentNames());
|
|
795
|
-
const componentConfigs = preset.componentConfigs ?? {};
|
|
796
|
-
const apply = [];
|
|
797
|
-
for (const [comp, configFile] of Object.entries(componentConfigs)) {
|
|
798
|
-
if (!knownComponents.has(comp)) continue;
|
|
799
|
-
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
800
|
-
if (!import_fs2.default.existsSync(componentResource(comp).filePath(sanitized))) {
|
|
801
|
-
jsonResponse(res, 422, {
|
|
802
|
-
error: `Preset references missing config: ${comp}/${sanitized}`
|
|
803
|
-
});
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
apply.push([comp, sanitized]);
|
|
807
|
-
}
|
|
808
|
-
themesResource.setProductionName(themeName);
|
|
809
|
-
for (const [comp, configFile] of apply) {
|
|
810
|
-
componentResource(comp).setProductionName(configFile);
|
|
811
|
-
}
|
|
812
|
-
presetsResource.setProductionName(fileName);
|
|
813
|
-
syncTokensToCss(themeName);
|
|
814
|
-
syncFontsToCss(themeName);
|
|
815
|
-
syncComponentsToCss();
|
|
816
|
-
jsonResponse(res, 200, {
|
|
817
|
-
ok: true,
|
|
818
|
-
fileName,
|
|
819
|
-
name: preset.name || fileName,
|
|
820
|
-
theme: themeName,
|
|
821
|
-
componentConfigs: Object.fromEntries(apply),
|
|
822
|
-
updatedAt: preset.updatedAt || ""
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
async function handlePresetByName({ params, req, res }) {
|
|
839
|
+
async function handleManifestByName({ params, req, res }) {
|
|
826
840
|
const [fileName] = params;
|
|
827
|
-
const filePath =
|
|
841
|
+
const filePath = manifestsResource.filePath(fileName);
|
|
828
842
|
if (req.method === "GET") {
|
|
829
843
|
if (!import_fs2.default.existsSync(filePath)) {
|
|
830
844
|
jsonResponse(res, 404, { error: "Not found" });
|
|
@@ -837,7 +851,7 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
837
851
|
}
|
|
838
852
|
if (req.method === "PUT") {
|
|
839
853
|
if (fileName === "default") {
|
|
840
|
-
jsonResponse(res, 403, { error: "Cannot overwrite the default
|
|
854
|
+
jsonResponse(res, 403, { error: "Cannot overwrite the default manifest" });
|
|
841
855
|
return;
|
|
842
856
|
}
|
|
843
857
|
const body = JSON.parse(await readBody(req));
|
|
@@ -856,35 +870,35 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
856
870
|
}
|
|
857
871
|
if (req.method === "DELETE") {
|
|
858
872
|
if (fileName === "default") {
|
|
859
|
-
jsonResponse(res, 403, { error: "Cannot delete the default
|
|
873
|
+
jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
|
|
860
874
|
return;
|
|
861
875
|
}
|
|
862
876
|
if (import_fs2.default.existsSync(filePath)) {
|
|
863
877
|
import_fs2.default.unlinkSync(filePath);
|
|
864
|
-
if (
|
|
865
|
-
|
|
878
|
+
if (manifestsResource.getActiveName() === fileName) {
|
|
879
|
+
manifestsResource.setActiveName("default");
|
|
866
880
|
}
|
|
867
881
|
}
|
|
868
882
|
jsonResponse(res, 200, { ok: true });
|
|
869
883
|
return;
|
|
870
884
|
}
|
|
871
885
|
}
|
|
872
|
-
async function
|
|
886
|
+
async function handleApplyManifest({ params, res }) {
|
|
873
887
|
const [fileName] = params;
|
|
874
|
-
const
|
|
875
|
-
if (!import_fs2.default.existsSync(
|
|
876
|
-
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" });
|
|
877
891
|
return;
|
|
878
892
|
}
|
|
879
|
-
const
|
|
880
|
-
const themeName = sanitizeFileName(
|
|
893
|
+
const manifest = JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
894
|
+
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
881
895
|
const themePath = themesResource.filePath(themeName);
|
|
882
896
|
if (!import_fs2.default.existsSync(themePath)) {
|
|
883
|
-
jsonResponse(res, 422, { error: `
|
|
897
|
+
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
884
898
|
return;
|
|
885
899
|
}
|
|
886
900
|
const knownComponents = new Set(listComponentNames());
|
|
887
|
-
const componentConfigs =
|
|
901
|
+
const componentConfigs = manifest.componentConfigs ?? {};
|
|
888
902
|
const resolvedConfigs = {};
|
|
889
903
|
const apply = [];
|
|
890
904
|
for (const [comp, configFile] of Object.entries(componentConfigs)) {
|
|
@@ -894,7 +908,7 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
894
908
|
const cfgPath = r.filePath(sanitized);
|
|
895
909
|
if (!import_fs2.default.existsSync(cfgPath)) {
|
|
896
910
|
jsonResponse(res, 422, {
|
|
897
|
-
error: `
|
|
911
|
+
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
898
912
|
});
|
|
899
913
|
return;
|
|
900
914
|
}
|
|
@@ -915,10 +929,10 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
915
929
|
const cfg = readComponentConfig(comp, activeName);
|
|
916
930
|
if (cfg) resolvedConfigs[comp] = { ...cfg, _fileName: activeName };
|
|
917
931
|
}
|
|
918
|
-
|
|
932
|
+
manifestsResource.setActiveName(fileName);
|
|
919
933
|
jsonResponse(res, 200, {
|
|
920
934
|
ok: true,
|
|
921
|
-
|
|
935
|
+
manifest: { ...manifest, _fileName: fileName },
|
|
922
936
|
theme: themeData,
|
|
923
937
|
componentConfigs: resolvedConfigs
|
|
924
938
|
});
|
|
@@ -956,35 +970,34 @@ ${COMPONENT_OVERRIDES_END}
|
|
|
956
970
|
{ method: "GET", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
957
971
|
{ method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
958
972
|
{ method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
|
|
959
|
-
//
|
|
960
|
-
{ method: "GET", pattern:
|
|
961
|
-
{ method: "GET", pattern:
|
|
962
|
-
{ method: "PUT", pattern:
|
|
963
|
-
|
|
964
|
-
{ method: "PUT", pattern:
|
|
965
|
-
|
|
966
|
-
{ method: "
|
|
967
|
-
{ method: "
|
|
968
|
-
|
|
969
|
-
{ method: "
|
|
970
|
-
|
|
971
|
-
{ method: "
|
|
972
|
-
{ method: "PUT", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName },
|
|
973
|
-
{ 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 }
|
|
974
986
|
];
|
|
975
987
|
return {
|
|
976
988
|
name: "theme-file-api",
|
|
977
989
|
config() {
|
|
978
990
|
return {
|
|
979
991
|
define: {
|
|
980
|
-
__PROJECT_ROOT__: JSON.stringify(process.cwd())
|
|
992
|
+
__PROJECT_ROOT__: JSON.stringify(process.cwd()),
|
|
993
|
+
__APP_VERSION__: JSON.stringify(PKG_VERSION)
|
|
981
994
|
}
|
|
982
995
|
};
|
|
983
996
|
},
|
|
984
997
|
configureServer(server) {
|
|
985
998
|
ensureThemesDir();
|
|
986
999
|
ensureComponentConfigsDir();
|
|
987
|
-
|
|
1000
|
+
ensureManifestsDir();
|
|
988
1001
|
server.middlewares.use(async (req, res, next) => {
|
|
989
1002
|
const handled = await dispatch(req, res, routes);
|
|
990
1003
|
if (!handled) next();
|
package/dist-plugin/index.d.cts
CHANGED
package/dist-plugin/index.d.ts
CHANGED