@constela/server 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +33 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,46 @@ Pass external data at render time:
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Style Evaluation
|
|
96
|
+
|
|
97
|
+
Style expressions are evaluated during SSR, producing CSS class strings:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"styles": {
|
|
102
|
+
"button": {
|
|
103
|
+
"base": "px-4 py-2 rounded",
|
|
104
|
+
"variants": {
|
|
105
|
+
"variant": {
|
|
106
|
+
"primary": "bg-blue-500 text-white",
|
|
107
|
+
"secondary": "bg-gray-200 text-gray-800"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"defaultVariants": { "variant": "primary" }
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"view": {
|
|
114
|
+
"kind": "element",
|
|
115
|
+
"tag": "button",
|
|
116
|
+
"props": {
|
|
117
|
+
"className": {
|
|
118
|
+
"expr": "style",
|
|
119
|
+
"name": "button",
|
|
120
|
+
"variants": { "variant": { "expr": "lit", "value": "primary" } }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
↓ SSR
|
|
128
|
+
|
|
129
|
+
```html
|
|
130
|
+
<button class="px-4 py-2 rounded bg-blue-500 text-white">...</button>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Pass style presets via `RenderOptions.styles` for evaluation.
|
|
134
|
+
|
|
95
135
|
## Output Structure
|
|
96
136
|
|
|
97
137
|
### Code Block HTML
|
|
@@ -142,6 +182,18 @@ const html = await renderToString(compiledProgram, {
|
|
|
142
182
|
imports: {
|
|
143
183
|
config: { siteName: 'My Site' },
|
|
144
184
|
},
|
|
185
|
+
styles: {
|
|
186
|
+
button: {
|
|
187
|
+
base: 'px-4 py-2 rounded',
|
|
188
|
+
variants: {
|
|
189
|
+
variant: {
|
|
190
|
+
primary: 'bg-blue-500 text-white',
|
|
191
|
+
secondary: 'bg-gray-200 text-gray-800',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
defaultVariants: { variant: 'primary' },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
145
197
|
});
|
|
146
198
|
```
|
|
147
199
|
|
|
@@ -155,6 +207,13 @@ interface RenderOptions {
|
|
|
155
207
|
path?: string;
|
|
156
208
|
};
|
|
157
209
|
imports?: Record<string, unknown>;
|
|
210
|
+
styles?: Record<string, StylePreset>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
interface StylePreset {
|
|
214
|
+
base: string;
|
|
215
|
+
variants?: Record<string, Record<string, string>>;
|
|
216
|
+
defaultVariants?: Record<string, string>;
|
|
158
217
|
}
|
|
159
218
|
```
|
|
160
219
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,17 @@ import { CompiledProgram } from '@constela/compiler';
|
|
|
6
6
|
* Renders CompiledProgram to HTML string for Server-Side Rendering.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Style preset definition for SSR
|
|
11
|
+
*/
|
|
12
|
+
interface StylePreset {
|
|
13
|
+
base: string;
|
|
14
|
+
variants?: Record<string, Record<string, string>>;
|
|
15
|
+
defaultVariants?: Record<string, string>;
|
|
16
|
+
compoundVariants?: Array<Record<string, string> & {
|
|
17
|
+
class: string;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
9
20
|
/**
|
|
10
21
|
* Options for renderToString
|
|
11
22
|
*/
|
|
@@ -16,6 +27,7 @@ interface RenderOptions {
|
|
|
16
27
|
path?: string;
|
|
17
28
|
};
|
|
18
29
|
imports?: Record<string, unknown>;
|
|
30
|
+
styles?: Record<string, StylePreset>;
|
|
19
31
|
}
|
|
20
32
|
/**
|
|
21
33
|
* Renders a CompiledProgram to an HTML string.
|
package/dist/index.js
CHANGED
|
@@ -217,7 +217,7 @@ function evaluate(expr, ctx) {
|
|
|
217
217
|
return void 0;
|
|
218
218
|
}
|
|
219
219
|
case "style": {
|
|
220
|
-
return
|
|
220
|
+
return evaluateStyle(expr, ctx);
|
|
221
221
|
}
|
|
222
222
|
default: {
|
|
223
223
|
const _exhaustiveCheck = expr;
|
|
@@ -310,6 +310,36 @@ function evaluateBinary(op, left, right, ctx) {
|
|
|
310
310
|
throw new Error("Unknown binary operator: " + op);
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
+
function evaluateStyle(expr, ctx) {
|
|
314
|
+
const preset = ctx.styles?.[expr.name];
|
|
315
|
+
if (!preset) return "";
|
|
316
|
+
let classes = preset.base;
|
|
317
|
+
if (preset.variants) {
|
|
318
|
+
for (const variantKey of Object.keys(preset.variants)) {
|
|
319
|
+
let variantValueStr = null;
|
|
320
|
+
if (expr.variants?.[variantKey]) {
|
|
321
|
+
let variantValue;
|
|
322
|
+
try {
|
|
323
|
+
variantValue = evaluate(expr.variants[variantKey], ctx);
|
|
324
|
+
} catch {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (variantValue != null) {
|
|
328
|
+
variantValueStr = String(variantValue);
|
|
329
|
+
}
|
|
330
|
+
} else if (preset.defaultVariants?.[variantKey] !== void 0) {
|
|
331
|
+
variantValueStr = preset.defaultVariants[variantKey];
|
|
332
|
+
}
|
|
333
|
+
if (variantValueStr !== null) {
|
|
334
|
+
const variantClasses = preset.variants[variantKey]?.[variantValueStr];
|
|
335
|
+
if (variantClasses) {
|
|
336
|
+
classes += " " + variantClasses;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return classes.trim();
|
|
342
|
+
}
|
|
313
343
|
function formatValue(value) {
|
|
314
344
|
if (value === null || value === void 0) {
|
|
315
345
|
return "";
|
|
@@ -438,7 +468,8 @@ async function renderToString(program, options) {
|
|
|
438
468
|
query: options.route.query ?? {},
|
|
439
469
|
path: options.route.path ?? ""
|
|
440
470
|
} : void 0,
|
|
441
|
-
imports: options?.imports ?? program.importData
|
|
471
|
+
imports: options?.imports ?? program.importData,
|
|
472
|
+
styles: options?.styles
|
|
442
473
|
};
|
|
443
474
|
return await renderNode(program.view, ctx);
|
|
444
475
|
}
|