@constela/server 17.0.0 → 18.0.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/dist/index.d.ts +4 -24
- package/dist/index.js +59 -1131
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import { CompiledProgram } from '@constela/compiler';
|
|
2
|
-
import { StreamingRenderOptions } from '@constela/core';
|
|
2
|
+
import { StylePreset, StreamingRenderOptions } from '@constela/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SSR Renderer
|
|
6
6
|
*
|
|
7
7
|
* Renders CompiledProgram to HTML string for Server-Side Rendering.
|
|
8
|
+
* Uses the unified evaluate module from @constela/core.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
/**
|
|
11
|
-
* Style preset definition for SSR
|
|
12
|
-
*/
|
|
13
|
-
interface StylePreset$1 {
|
|
14
|
-
base: string;
|
|
15
|
-
variants?: Record<string, Record<string, string>>;
|
|
16
|
-
defaultVariants?: Record<string, string>;
|
|
17
|
-
compoundVariants?: Array<Record<string, string> & {
|
|
18
|
-
class: string;
|
|
19
|
-
}>;
|
|
20
|
-
}
|
|
21
11
|
/**
|
|
22
12
|
* Options for renderToString
|
|
23
13
|
*/
|
|
@@ -28,7 +18,7 @@ interface RenderOptions {
|
|
|
28
18
|
path?: string;
|
|
29
19
|
};
|
|
30
20
|
imports?: Record<string, unknown>;
|
|
31
|
-
styles?: Record<string, StylePreset
|
|
21
|
+
styles?: Record<string, StylePreset>;
|
|
32
22
|
stateOverrides?: Record<string, unknown>;
|
|
33
23
|
cookies?: Record<string, string>;
|
|
34
24
|
}
|
|
@@ -46,6 +36,7 @@ declare function renderToString(program: CompiledProgram, options?: RenderOption
|
|
|
46
36
|
*
|
|
47
37
|
* Renders CompiledProgram to a ReadableStream for Server-Side Rendering.
|
|
48
38
|
* Uses Web Streams API for Edge Runtime compatibility.
|
|
39
|
+
* Uses the unified evaluate module from @constela/core.
|
|
49
40
|
*
|
|
50
41
|
* Features:
|
|
51
42
|
* - Three flush strategies: immediate, batched, manual
|
|
@@ -54,17 +45,6 @@ declare function renderToString(program: CompiledProgram, options?: RenderOption
|
|
|
54
45
|
* - Suspense boundary support for async content
|
|
55
46
|
*/
|
|
56
47
|
|
|
57
|
-
/**
|
|
58
|
-
* Style preset definition for SSR
|
|
59
|
-
*/
|
|
60
|
-
interface StylePreset {
|
|
61
|
-
base: string;
|
|
62
|
-
variants?: Record<string, Record<string, string>>;
|
|
63
|
-
defaultVariants?: Record<string, string>;
|
|
64
|
-
compoundVariants?: Array<Record<string, string> & {
|
|
65
|
-
class: string;
|
|
66
|
-
}>;
|
|
67
|
-
}
|
|
68
48
|
/**
|
|
69
49
|
* Extended options for streaming render
|
|
70
50
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/renderer.ts
|
|
2
|
-
import { isCookieInitialExpr,
|
|
2
|
+
import { isCookieInitialExpr, evaluate as coreEvaluate } from "@constela/core";
|
|
3
3
|
|
|
4
4
|
// src/markdown.ts
|
|
5
5
|
import { marked } from "marked";
|
|
@@ -108,7 +108,37 @@ async function parseMarkdownSSRAsync(content) {
|
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
// src/
|
|
111
|
+
// src/shared.ts
|
|
112
|
+
import { GLOBAL_FUNCTIONS } from "@constela/core";
|
|
113
|
+
var ssrAdapter = {
|
|
114
|
+
resolveRef: () => null,
|
|
115
|
+
resolveValidity: () => false,
|
|
116
|
+
resolveGlobal(name) {
|
|
117
|
+
const safeGlobals = {
|
|
118
|
+
JSON,
|
|
119
|
+
Math,
|
|
120
|
+
Date,
|
|
121
|
+
Object,
|
|
122
|
+
Array,
|
|
123
|
+
String,
|
|
124
|
+
Number,
|
|
125
|
+
Boolean,
|
|
126
|
+
console,
|
|
127
|
+
...GLOBAL_FUNCTIONS
|
|
128
|
+
};
|
|
129
|
+
return safeGlobals[name];
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
function toCoreContext(ctx) {
|
|
133
|
+
return {
|
|
134
|
+
state: ctx.state,
|
|
135
|
+
locals: ctx.locals,
|
|
136
|
+
route: ctx.route,
|
|
137
|
+
imports: ctx.imports,
|
|
138
|
+
styles: ctx.styles,
|
|
139
|
+
env: ssrAdapter
|
|
140
|
+
};
|
|
141
|
+
}
|
|
112
142
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
113
143
|
"area",
|
|
114
144
|
"base",
|
|
@@ -125,551 +155,6 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
125
155
|
"track",
|
|
126
156
|
"wbr"
|
|
127
157
|
]);
|
|
128
|
-
var SAFE_ARRAY_METHODS = /* @__PURE__ */ new Set([
|
|
129
|
-
"length",
|
|
130
|
-
"at",
|
|
131
|
-
"includes",
|
|
132
|
-
"slice",
|
|
133
|
-
"indexOf",
|
|
134
|
-
"join",
|
|
135
|
-
"filter",
|
|
136
|
-
"map",
|
|
137
|
-
"find",
|
|
138
|
-
"findIndex",
|
|
139
|
-
"some",
|
|
140
|
-
"every"
|
|
141
|
-
]);
|
|
142
|
-
var SAFE_STRING_METHODS = /* @__PURE__ */ new Set([
|
|
143
|
-
"length",
|
|
144
|
-
"charAt",
|
|
145
|
-
"substring",
|
|
146
|
-
"slice",
|
|
147
|
-
"split",
|
|
148
|
-
"trim",
|
|
149
|
-
"toUpperCase",
|
|
150
|
-
"toLowerCase",
|
|
151
|
-
"replace",
|
|
152
|
-
"includes",
|
|
153
|
-
"startsWith",
|
|
154
|
-
"endsWith",
|
|
155
|
-
"indexOf"
|
|
156
|
-
]);
|
|
157
|
-
var SAFE_MATH_METHODS = /* @__PURE__ */ new Set([
|
|
158
|
-
"min",
|
|
159
|
-
"max",
|
|
160
|
-
"round",
|
|
161
|
-
"floor",
|
|
162
|
-
"ceil",
|
|
163
|
-
"abs",
|
|
164
|
-
"sqrt",
|
|
165
|
-
"pow",
|
|
166
|
-
"random",
|
|
167
|
-
"sin",
|
|
168
|
-
"cos",
|
|
169
|
-
"tan"
|
|
170
|
-
]);
|
|
171
|
-
var SAFE_DATE_STATIC_METHODS = /* @__PURE__ */ new Set(["now", "parse"]);
|
|
172
|
-
var SAFE_DATE_INSTANCE_METHODS = /* @__PURE__ */ new Set([
|
|
173
|
-
"toISOString",
|
|
174
|
-
"toDateString",
|
|
175
|
-
"toTimeString",
|
|
176
|
-
"getTime",
|
|
177
|
-
"getFullYear",
|
|
178
|
-
"getMonth",
|
|
179
|
-
"getDate",
|
|
180
|
-
"getHours",
|
|
181
|
-
"getMinutes",
|
|
182
|
-
"getSeconds",
|
|
183
|
-
"getMilliseconds"
|
|
184
|
-
]);
|
|
185
|
-
function isEventHandler(value) {
|
|
186
|
-
return typeof value === "object" && value !== null && "event" in value && "action" in value;
|
|
187
|
-
}
|
|
188
|
-
function createLambdaFunction(lambda, ctx) {
|
|
189
|
-
return (item, index) => {
|
|
190
|
-
const lambdaLocals = {
|
|
191
|
-
...ctx.locals,
|
|
192
|
-
[lambda.param]: item
|
|
193
|
-
};
|
|
194
|
-
if (lambda.index !== void 0) {
|
|
195
|
-
lambdaLocals[lambda.index] = index;
|
|
196
|
-
}
|
|
197
|
-
return evaluate(lambda.body, { ...ctx, locals: lambdaLocals });
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
function callArrayMethod(target, method, args, ctx, rawArgs) {
|
|
201
|
-
if (!SAFE_ARRAY_METHODS.has(method)) return void 0;
|
|
202
|
-
switch (method) {
|
|
203
|
-
case "length":
|
|
204
|
-
return target.length;
|
|
205
|
-
case "at": {
|
|
206
|
-
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
207
|
-
return target.at(index);
|
|
208
|
-
}
|
|
209
|
-
case "includes": {
|
|
210
|
-
const searchElement = args[0];
|
|
211
|
-
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
212
|
-
return target.includes(searchElement, fromIndex);
|
|
213
|
-
}
|
|
214
|
-
case "slice": {
|
|
215
|
-
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
216
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
217
|
-
return target.slice(start, end);
|
|
218
|
-
}
|
|
219
|
-
case "indexOf": {
|
|
220
|
-
const searchElement = args[0];
|
|
221
|
-
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
222
|
-
return target.indexOf(searchElement, fromIndex);
|
|
223
|
-
}
|
|
224
|
-
case "join": {
|
|
225
|
-
const separator = typeof args[0] === "string" ? args[0] : ",";
|
|
226
|
-
return target.join(separator);
|
|
227
|
-
}
|
|
228
|
-
case "filter": {
|
|
229
|
-
const lambdaExpr = rawArgs?.[0];
|
|
230
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
231
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
232
|
-
return target.filter((item, index) => !!fn(item, index));
|
|
233
|
-
}
|
|
234
|
-
case "map": {
|
|
235
|
-
const lambdaExpr = rawArgs?.[0];
|
|
236
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
237
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
238
|
-
return target.map((item, index) => fn(item, index));
|
|
239
|
-
}
|
|
240
|
-
case "find": {
|
|
241
|
-
const lambdaExpr = rawArgs?.[0];
|
|
242
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
243
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
244
|
-
return target.find((item, index) => !!fn(item, index));
|
|
245
|
-
}
|
|
246
|
-
case "findIndex": {
|
|
247
|
-
const lambdaExpr = rawArgs?.[0];
|
|
248
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
249
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
250
|
-
return target.findIndex((item, index) => !!fn(item, index));
|
|
251
|
-
}
|
|
252
|
-
case "some": {
|
|
253
|
-
const lambdaExpr = rawArgs?.[0];
|
|
254
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
255
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
256
|
-
return target.some((item, index) => !!fn(item, index));
|
|
257
|
-
}
|
|
258
|
-
case "every": {
|
|
259
|
-
const lambdaExpr = rawArgs?.[0];
|
|
260
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
261
|
-
const fn = createLambdaFunction(lambdaExpr, ctx);
|
|
262
|
-
return target.every((item, index) => !!fn(item, index));
|
|
263
|
-
}
|
|
264
|
-
default:
|
|
265
|
-
return void 0;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
function callStringMethod(target, method, args) {
|
|
269
|
-
if (!SAFE_STRING_METHODS.has(method)) return void 0;
|
|
270
|
-
switch (method) {
|
|
271
|
-
case "length":
|
|
272
|
-
return target.length;
|
|
273
|
-
case "charAt": {
|
|
274
|
-
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
275
|
-
return target.charAt(index);
|
|
276
|
-
}
|
|
277
|
-
case "substring": {
|
|
278
|
-
const start = typeof args[0] === "number" ? args[0] : 0;
|
|
279
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
280
|
-
return target.substring(start, end);
|
|
281
|
-
}
|
|
282
|
-
case "slice": {
|
|
283
|
-
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
284
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
285
|
-
return target.slice(start, end);
|
|
286
|
-
}
|
|
287
|
-
case "split": {
|
|
288
|
-
const separator = typeof args[0] === "string" ? args[0] : "";
|
|
289
|
-
return target.split(separator);
|
|
290
|
-
}
|
|
291
|
-
case "trim":
|
|
292
|
-
return target.trim();
|
|
293
|
-
case "toUpperCase":
|
|
294
|
-
return target.toUpperCase();
|
|
295
|
-
case "toLowerCase":
|
|
296
|
-
return target.toLowerCase();
|
|
297
|
-
case "replace": {
|
|
298
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
299
|
-
const replace = typeof args[1] === "string" ? args[1] : "";
|
|
300
|
-
return target.replace(search, replace);
|
|
301
|
-
}
|
|
302
|
-
case "includes": {
|
|
303
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
304
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
305
|
-
return target.includes(search, position);
|
|
306
|
-
}
|
|
307
|
-
case "startsWith": {
|
|
308
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
309
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
310
|
-
return target.startsWith(search, position);
|
|
311
|
-
}
|
|
312
|
-
case "endsWith": {
|
|
313
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
314
|
-
const length = typeof args[1] === "number" ? args[1] : void 0;
|
|
315
|
-
return target.endsWith(search, length);
|
|
316
|
-
}
|
|
317
|
-
case "indexOf": {
|
|
318
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
319
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
320
|
-
return target.indexOf(search, position);
|
|
321
|
-
}
|
|
322
|
-
default:
|
|
323
|
-
return void 0;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
function callMathMethod(method, args) {
|
|
327
|
-
if (!SAFE_MATH_METHODS.has(method)) return void 0;
|
|
328
|
-
const numbers = args.filter((a) => typeof a === "number");
|
|
329
|
-
switch (method) {
|
|
330
|
-
case "min":
|
|
331
|
-
return numbers.length > 0 ? Math.min(...numbers) : void 0;
|
|
332
|
-
case "max":
|
|
333
|
-
return numbers.length > 0 ? Math.max(...numbers) : void 0;
|
|
334
|
-
case "round":
|
|
335
|
-
return numbers[0] !== void 0 ? Math.round(numbers[0]) : void 0;
|
|
336
|
-
case "floor":
|
|
337
|
-
return numbers[0] !== void 0 ? Math.floor(numbers[0]) : void 0;
|
|
338
|
-
case "ceil":
|
|
339
|
-
return numbers[0] !== void 0 ? Math.ceil(numbers[0]) : void 0;
|
|
340
|
-
case "abs":
|
|
341
|
-
return numbers[0] !== void 0 ? Math.abs(numbers[0]) : void 0;
|
|
342
|
-
case "sqrt":
|
|
343
|
-
return numbers[0] !== void 0 ? Math.sqrt(numbers[0]) : void 0;
|
|
344
|
-
case "pow":
|
|
345
|
-
return numbers[0] !== void 0 && numbers[1] !== void 0 ? Math.pow(numbers[0], numbers[1]) : void 0;
|
|
346
|
-
case "random":
|
|
347
|
-
return Math.random();
|
|
348
|
-
case "sin":
|
|
349
|
-
return numbers[0] !== void 0 ? Math.sin(numbers[0]) : void 0;
|
|
350
|
-
case "cos":
|
|
351
|
-
return numbers[0] !== void 0 ? Math.cos(numbers[0]) : void 0;
|
|
352
|
-
case "tan":
|
|
353
|
-
return numbers[0] !== void 0 ? Math.tan(numbers[0]) : void 0;
|
|
354
|
-
default:
|
|
355
|
-
return void 0;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
function callDateStaticMethod(method, args) {
|
|
359
|
-
if (!SAFE_DATE_STATIC_METHODS.has(method)) return void 0;
|
|
360
|
-
switch (method) {
|
|
361
|
-
case "now":
|
|
362
|
-
return Date.now();
|
|
363
|
-
case "parse": {
|
|
364
|
-
const dateString = args[0];
|
|
365
|
-
return typeof dateString === "string" ? Date.parse(dateString) : void 0;
|
|
366
|
-
}
|
|
367
|
-
default:
|
|
368
|
-
return void 0;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
function callDateInstanceMethod(target, method) {
|
|
372
|
-
if (!SAFE_DATE_INSTANCE_METHODS.has(method)) return void 0;
|
|
373
|
-
switch (method) {
|
|
374
|
-
case "toISOString":
|
|
375
|
-
return target.toISOString();
|
|
376
|
-
case "toDateString":
|
|
377
|
-
return target.toDateString();
|
|
378
|
-
case "toTimeString":
|
|
379
|
-
return target.toTimeString();
|
|
380
|
-
case "getTime":
|
|
381
|
-
return target.getTime();
|
|
382
|
-
case "getFullYear":
|
|
383
|
-
return target.getFullYear();
|
|
384
|
-
case "getMonth":
|
|
385
|
-
return target.getMonth();
|
|
386
|
-
case "getDate":
|
|
387
|
-
return target.getDate();
|
|
388
|
-
case "getHours":
|
|
389
|
-
return target.getHours();
|
|
390
|
-
case "getMinutes":
|
|
391
|
-
return target.getMinutes();
|
|
392
|
-
case "getSeconds":
|
|
393
|
-
return target.getSeconds();
|
|
394
|
-
case "getMilliseconds":
|
|
395
|
-
return target.getMilliseconds();
|
|
396
|
-
default:
|
|
397
|
-
return void 0;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
function evaluate(expr, ctx) {
|
|
401
|
-
switch (expr.expr) {
|
|
402
|
-
case "lit":
|
|
403
|
-
return expr.value;
|
|
404
|
-
case "state":
|
|
405
|
-
return ctx.state.get(expr.name);
|
|
406
|
-
case "local":
|
|
407
|
-
return ctx.locals[expr.name];
|
|
408
|
-
case "var": {
|
|
409
|
-
let varName = expr.name;
|
|
410
|
-
let pathParts = [];
|
|
411
|
-
if (varName.includes(".")) {
|
|
412
|
-
const parts = varName.split(".");
|
|
413
|
-
varName = parts[0];
|
|
414
|
-
pathParts = parts.slice(1);
|
|
415
|
-
}
|
|
416
|
-
if (expr.path) {
|
|
417
|
-
pathParts = pathParts.concat(expr.path.split("."));
|
|
418
|
-
}
|
|
419
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
420
|
-
for (const part of pathParts) {
|
|
421
|
-
if (forbiddenKeys.has(part)) {
|
|
422
|
-
return void 0;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
let value = ctx.locals[varName];
|
|
426
|
-
for (const part of pathParts) {
|
|
427
|
-
if (value == null) break;
|
|
428
|
-
value = value[part];
|
|
429
|
-
}
|
|
430
|
-
return value;
|
|
431
|
-
}
|
|
432
|
-
case "bin":
|
|
433
|
-
return evaluateBinary(expr.op, expr.left, expr.right, ctx);
|
|
434
|
-
case "not":
|
|
435
|
-
return !evaluate(expr.operand, ctx);
|
|
436
|
-
case "cond":
|
|
437
|
-
return evaluate(expr.if, ctx) ? evaluate(expr.then, ctx) : evaluate(expr.else, ctx);
|
|
438
|
-
case "get": {
|
|
439
|
-
const baseValue = evaluate(expr.base, ctx);
|
|
440
|
-
if (baseValue == null) return void 0;
|
|
441
|
-
const pathParts = expr.path.split(".");
|
|
442
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
443
|
-
let value = baseValue;
|
|
444
|
-
for (const part of pathParts) {
|
|
445
|
-
if (forbiddenKeys.has(part)) return void 0;
|
|
446
|
-
if (value == null) return void 0;
|
|
447
|
-
value = value[part];
|
|
448
|
-
}
|
|
449
|
-
return value;
|
|
450
|
-
}
|
|
451
|
-
case "route": {
|
|
452
|
-
const source = expr.source ?? "param";
|
|
453
|
-
const routeCtx = ctx.route;
|
|
454
|
-
if (!routeCtx) return "";
|
|
455
|
-
switch (source) {
|
|
456
|
-
case "param":
|
|
457
|
-
return routeCtx.params[expr.name] ?? "";
|
|
458
|
-
case "query":
|
|
459
|
-
return routeCtx.query[expr.name] ?? "";
|
|
460
|
-
case "path":
|
|
461
|
-
return routeCtx.path;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
case "import": {
|
|
465
|
-
const importData = ctx.imports?.[expr.name];
|
|
466
|
-
if (importData === void 0) return void 0;
|
|
467
|
-
if (expr.path) {
|
|
468
|
-
return getNestedValue(importData, expr.path);
|
|
469
|
-
}
|
|
470
|
-
return importData;
|
|
471
|
-
}
|
|
472
|
-
case "data": {
|
|
473
|
-
const dataValue = ctx.imports?.[expr.name];
|
|
474
|
-
if (dataValue === void 0) return void 0;
|
|
475
|
-
if (expr.path) {
|
|
476
|
-
return getNestedValue(dataValue, expr.path);
|
|
477
|
-
}
|
|
478
|
-
return dataValue;
|
|
479
|
-
}
|
|
480
|
-
case "ref":
|
|
481
|
-
return null;
|
|
482
|
-
case "index": {
|
|
483
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
484
|
-
const base = evaluate(expr.base, ctx);
|
|
485
|
-
const key = evaluate(expr.key, ctx);
|
|
486
|
-
if (base == null || key == null) return void 0;
|
|
487
|
-
if (typeof key === "string" && forbiddenKeys.has(key)) return void 0;
|
|
488
|
-
return base[key];
|
|
489
|
-
}
|
|
490
|
-
case "param": {
|
|
491
|
-
return void 0;
|
|
492
|
-
}
|
|
493
|
-
case "style": {
|
|
494
|
-
return evaluateStyle(expr, ctx);
|
|
495
|
-
}
|
|
496
|
-
case "concat": {
|
|
497
|
-
return expr.items.map((item) => {
|
|
498
|
-
const val = evaluate(item, ctx);
|
|
499
|
-
return val == null ? "" : String(val);
|
|
500
|
-
}).join("");
|
|
501
|
-
}
|
|
502
|
-
case "validity": {
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
case "call": {
|
|
506
|
-
const callExpr = expr;
|
|
507
|
-
if (callExpr.target === null) {
|
|
508
|
-
const globalArgs = callExpr.args?.map((arg) => {
|
|
509
|
-
if (arg.expr === "lambda") return arg;
|
|
510
|
-
return evaluate(arg, ctx);
|
|
511
|
-
}) ?? [];
|
|
512
|
-
return callGlobalFunction(callExpr.method, globalArgs);
|
|
513
|
-
}
|
|
514
|
-
const target = evaluate(callExpr.target, ctx);
|
|
515
|
-
if (target == null) return void 0;
|
|
516
|
-
const args = callExpr.args?.map((arg) => {
|
|
517
|
-
if (arg.expr === "lambda") return arg;
|
|
518
|
-
return evaluate(arg, ctx);
|
|
519
|
-
}) ?? [];
|
|
520
|
-
if (Array.isArray(target)) {
|
|
521
|
-
return callArrayMethod(target, callExpr.method, args, ctx, callExpr.args);
|
|
522
|
-
}
|
|
523
|
-
if (typeof target === "string") {
|
|
524
|
-
return callStringMethod(target, callExpr.method, args);
|
|
525
|
-
}
|
|
526
|
-
if (target === Math) {
|
|
527
|
-
return callMathMethod(callExpr.method, args);
|
|
528
|
-
}
|
|
529
|
-
if (target === Date) {
|
|
530
|
-
return callDateStaticMethod(callExpr.method, args);
|
|
531
|
-
}
|
|
532
|
-
if (target instanceof Date) {
|
|
533
|
-
return callDateInstanceMethod(target, callExpr.method);
|
|
534
|
-
}
|
|
535
|
-
return void 0;
|
|
536
|
-
}
|
|
537
|
-
case "lambda": {
|
|
538
|
-
return void 0;
|
|
539
|
-
}
|
|
540
|
-
case "array": {
|
|
541
|
-
const arrayExpr = expr;
|
|
542
|
-
return arrayExpr.elements.map((elem) => evaluate(elem, ctx));
|
|
543
|
-
}
|
|
544
|
-
case "obj": {
|
|
545
|
-
const objExpr = expr;
|
|
546
|
-
const result = {};
|
|
547
|
-
for (const [key, value] of Object.entries(objExpr.props)) {
|
|
548
|
-
result[key] = evaluate(value, ctx);
|
|
549
|
-
}
|
|
550
|
-
return result;
|
|
551
|
-
}
|
|
552
|
-
default: {
|
|
553
|
-
const _exhaustiveCheck = expr;
|
|
554
|
-
throw new Error(`Unknown expression type: ${JSON.stringify(_exhaustiveCheck)}`);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
function getNestedValue(obj, path) {
|
|
559
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
560
|
-
const parts = path.split(".");
|
|
561
|
-
let value = obj;
|
|
562
|
-
for (const part of parts) {
|
|
563
|
-
if (forbiddenKeys.has(part)) {
|
|
564
|
-
return void 0;
|
|
565
|
-
}
|
|
566
|
-
if (value == null) {
|
|
567
|
-
return void 0;
|
|
568
|
-
}
|
|
569
|
-
if (Array.isArray(value)) {
|
|
570
|
-
const index = Number(part);
|
|
571
|
-
if (Number.isInteger(index) && index >= 0) {
|
|
572
|
-
value = value[index];
|
|
573
|
-
} else {
|
|
574
|
-
value = value[part];
|
|
575
|
-
}
|
|
576
|
-
} else if (typeof value === "object") {
|
|
577
|
-
value = value[part];
|
|
578
|
-
} else {
|
|
579
|
-
return void 0;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
return value;
|
|
583
|
-
}
|
|
584
|
-
function evaluateBinary(op, left, right, ctx) {
|
|
585
|
-
if (op === "&&") {
|
|
586
|
-
const leftVal2 = evaluate(left, ctx);
|
|
587
|
-
if (!leftVal2) return leftVal2;
|
|
588
|
-
return evaluate(right, ctx);
|
|
589
|
-
}
|
|
590
|
-
if (op === "||") {
|
|
591
|
-
const leftVal2 = evaluate(left, ctx);
|
|
592
|
-
if (leftVal2) return leftVal2;
|
|
593
|
-
return evaluate(right, ctx);
|
|
594
|
-
}
|
|
595
|
-
const leftVal = evaluate(left, ctx);
|
|
596
|
-
const rightVal = evaluate(right, ctx);
|
|
597
|
-
switch (op) {
|
|
598
|
-
case "+":
|
|
599
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
600
|
-
return leftVal + rightVal;
|
|
601
|
-
}
|
|
602
|
-
return String(leftVal) + String(rightVal);
|
|
603
|
-
case "-":
|
|
604
|
-
return (typeof leftVal === "number" ? leftVal : 0) - (typeof rightVal === "number" ? rightVal : 0);
|
|
605
|
-
case "*":
|
|
606
|
-
return (typeof leftVal === "number" ? leftVal : 0) * (typeof rightVal === "number" ? rightVal : 0);
|
|
607
|
-
case "/": {
|
|
608
|
-
const dividend = typeof leftVal === "number" ? leftVal : 0;
|
|
609
|
-
const divisor = typeof rightVal === "number" ? rightVal : 0;
|
|
610
|
-
if (divisor === 0) {
|
|
611
|
-
return dividend === 0 ? NaN : dividend > 0 ? Infinity : -Infinity;
|
|
612
|
-
}
|
|
613
|
-
return dividend / divisor;
|
|
614
|
-
}
|
|
615
|
-
case "==":
|
|
616
|
-
return leftVal === rightVal;
|
|
617
|
-
case "!=":
|
|
618
|
-
return leftVal !== rightVal;
|
|
619
|
-
case "<":
|
|
620
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
621
|
-
return leftVal < rightVal;
|
|
622
|
-
}
|
|
623
|
-
return String(leftVal) < String(rightVal);
|
|
624
|
-
case "<=":
|
|
625
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
626
|
-
return leftVal <= rightVal;
|
|
627
|
-
}
|
|
628
|
-
return String(leftVal) <= String(rightVal);
|
|
629
|
-
case ">":
|
|
630
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
631
|
-
return leftVal > rightVal;
|
|
632
|
-
}
|
|
633
|
-
return String(leftVal) > String(rightVal);
|
|
634
|
-
case ">=":
|
|
635
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
636
|
-
return leftVal >= rightVal;
|
|
637
|
-
}
|
|
638
|
-
return String(leftVal) >= String(rightVal);
|
|
639
|
-
default:
|
|
640
|
-
throw new Error("Unknown binary operator: " + op);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
function evaluateStyle(expr, ctx) {
|
|
644
|
-
const preset = ctx.styles?.[expr.name];
|
|
645
|
-
if (!preset) return "";
|
|
646
|
-
let classes = preset.base;
|
|
647
|
-
if (preset.variants) {
|
|
648
|
-
for (const variantKey of Object.keys(preset.variants)) {
|
|
649
|
-
let variantValueStr = null;
|
|
650
|
-
if (expr.variants?.[variantKey]) {
|
|
651
|
-
let variantValue;
|
|
652
|
-
try {
|
|
653
|
-
variantValue = evaluate(expr.variants[variantKey], ctx);
|
|
654
|
-
} catch {
|
|
655
|
-
continue;
|
|
656
|
-
}
|
|
657
|
-
if (variantValue != null) {
|
|
658
|
-
variantValueStr = String(variantValue);
|
|
659
|
-
}
|
|
660
|
-
} else if (preset.defaultVariants?.[variantKey] !== void 0) {
|
|
661
|
-
variantValueStr = preset.defaultVariants[variantKey];
|
|
662
|
-
}
|
|
663
|
-
if (variantValueStr !== null) {
|
|
664
|
-
const variantClasses = preset.variants[variantKey]?.[variantValueStr];
|
|
665
|
-
if (variantClasses) {
|
|
666
|
-
classes += " " + variantClasses;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
return classes.trim();
|
|
672
|
-
}
|
|
673
158
|
function formatValue(value) {
|
|
674
159
|
if (value === null || value === void 0) {
|
|
675
160
|
return "";
|
|
@@ -679,6 +164,11 @@ function formatValue(value) {
|
|
|
679
164
|
}
|
|
680
165
|
return String(value);
|
|
681
166
|
}
|
|
167
|
+
|
|
168
|
+
// src/renderer.ts
|
|
169
|
+
function isEventHandler(value) {
|
|
170
|
+
return typeof value === "object" && value !== null && "event" in value && "action" in value;
|
|
171
|
+
}
|
|
682
172
|
async function renderNode(node, ctx) {
|
|
683
173
|
switch (node.kind) {
|
|
684
174
|
case "element":
|
|
@@ -720,7 +210,7 @@ async function renderElement(node, ctx) {
|
|
|
720
210
|
if (isEventHandler(propValue)) {
|
|
721
211
|
continue;
|
|
722
212
|
}
|
|
723
|
-
const value =
|
|
213
|
+
const value = coreEvaluate(propValue, toCoreContext(ctx));
|
|
724
214
|
if (value === false) {
|
|
725
215
|
continue;
|
|
726
216
|
}
|
|
@@ -746,11 +236,11 @@ async function renderElement(node, ctx) {
|
|
|
746
236
|
return `<${tag}${attrs}>${childrenHtml}</${tag}>`;
|
|
747
237
|
}
|
|
748
238
|
function renderText(node, ctx) {
|
|
749
|
-
const value =
|
|
239
|
+
const value = coreEvaluate(node.value, toCoreContext(ctx));
|
|
750
240
|
return escapeHtml(formatValue(value));
|
|
751
241
|
}
|
|
752
242
|
async function renderIf(node, ctx) {
|
|
753
|
-
const condition =
|
|
243
|
+
const condition = coreEvaluate(node.condition, toCoreContext(ctx));
|
|
754
244
|
if (condition) {
|
|
755
245
|
const content = await renderNode(node.then, ctx);
|
|
756
246
|
return `<!--if:then-->${content}`;
|
|
@@ -762,7 +252,7 @@ async function renderIf(node, ctx) {
|
|
|
762
252
|
return "<!--if:none-->";
|
|
763
253
|
}
|
|
764
254
|
async function renderEach(node, ctx) {
|
|
765
|
-
const items =
|
|
255
|
+
const items = coreEvaluate(node.items, toCoreContext(ctx));
|
|
766
256
|
if (!Array.isArray(items)) {
|
|
767
257
|
return "";
|
|
768
258
|
}
|
|
@@ -785,13 +275,14 @@ async function renderEach(node, ctx) {
|
|
|
785
275
|
return result;
|
|
786
276
|
}
|
|
787
277
|
async function renderMarkdown(node, ctx) {
|
|
788
|
-
const content =
|
|
278
|
+
const content = coreEvaluate(node.content, toCoreContext(ctx));
|
|
789
279
|
const html = await parseMarkdownSSRAsync(formatValue(content));
|
|
790
280
|
return `<div class="constela-markdown">${html}</div>`;
|
|
791
281
|
}
|
|
792
282
|
async function renderCode(node, ctx) {
|
|
793
|
-
const
|
|
794
|
-
const
|
|
283
|
+
const coreCtx = toCoreContext(ctx);
|
|
284
|
+
const language = formatValue(coreEvaluate(node.language, coreCtx));
|
|
285
|
+
const content = formatValue(coreEvaluate(node.content, coreCtx));
|
|
795
286
|
const highlightedCode = await renderCodeSSR(content, language);
|
|
796
287
|
const languageBadge = language ? `<div class="absolute right-12 top-3 z-10 rounded bg-muted-foreground/20 px-2 py-0.5 text-xs font-medium text-muted-foreground">${escapeHtml(language)}</div>` : "";
|
|
797
288
|
const copyButton = `<button class="constela-copy-btn absolute right-3 top-3 z-10 flex h-8 w-8 items-center justify-center rounded-md border border-border bg-background/80 opacity-0 transition-opacity hover:bg-muted group-hover:opacity-100" data-copy-target="code" aria-label="Copy code"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>`;
|
|
@@ -810,7 +301,7 @@ async function renderLocalState(node, ctx) {
|
|
|
810
301
|
const initial = field.initial;
|
|
811
302
|
if (initial && typeof initial === "object" && "expr" in initial) {
|
|
812
303
|
const evalCtx = { ...ctx, locals: progressiveLocals };
|
|
813
|
-
localStateValues[name] =
|
|
304
|
+
localStateValues[name] = coreEvaluate(initial, toCoreContext(evalCtx));
|
|
814
305
|
} else {
|
|
815
306
|
localStateValues[name] = initial;
|
|
816
307
|
}
|
|
@@ -881,575 +372,11 @@ async function renderToString(program, options) {
|
|
|
881
372
|
}
|
|
882
373
|
|
|
883
374
|
// src/streaming.ts
|
|
884
|
-
import { isCookieInitialExpr as isCookieInitialExpr2 } from "@constela/core";
|
|
885
|
-
var VOID_ELEMENTS2 = /* @__PURE__ */ new Set([
|
|
886
|
-
"area",
|
|
887
|
-
"base",
|
|
888
|
-
"br",
|
|
889
|
-
"col",
|
|
890
|
-
"embed",
|
|
891
|
-
"hr",
|
|
892
|
-
"img",
|
|
893
|
-
"input",
|
|
894
|
-
"link",
|
|
895
|
-
"meta",
|
|
896
|
-
"param",
|
|
897
|
-
"source",
|
|
898
|
-
"track",
|
|
899
|
-
"wbr"
|
|
900
|
-
]);
|
|
901
|
-
var SAFE_ARRAY_METHODS2 = /* @__PURE__ */ new Set([
|
|
902
|
-
"length",
|
|
903
|
-
"at",
|
|
904
|
-
"includes",
|
|
905
|
-
"slice",
|
|
906
|
-
"indexOf",
|
|
907
|
-
"join",
|
|
908
|
-
"filter",
|
|
909
|
-
"map",
|
|
910
|
-
"find",
|
|
911
|
-
"findIndex",
|
|
912
|
-
"some",
|
|
913
|
-
"every"
|
|
914
|
-
]);
|
|
915
|
-
var SAFE_STRING_METHODS2 = /* @__PURE__ */ new Set([
|
|
916
|
-
"length",
|
|
917
|
-
"charAt",
|
|
918
|
-
"substring",
|
|
919
|
-
"slice",
|
|
920
|
-
"split",
|
|
921
|
-
"trim",
|
|
922
|
-
"toUpperCase",
|
|
923
|
-
"toLowerCase",
|
|
924
|
-
"replace",
|
|
925
|
-
"includes",
|
|
926
|
-
"startsWith",
|
|
927
|
-
"endsWith",
|
|
928
|
-
"indexOf"
|
|
929
|
-
]);
|
|
930
|
-
var SAFE_MATH_METHODS2 = /* @__PURE__ */ new Set([
|
|
931
|
-
"min",
|
|
932
|
-
"max",
|
|
933
|
-
"round",
|
|
934
|
-
"floor",
|
|
935
|
-
"ceil",
|
|
936
|
-
"abs",
|
|
937
|
-
"sqrt",
|
|
938
|
-
"pow",
|
|
939
|
-
"random",
|
|
940
|
-
"sin",
|
|
941
|
-
"cos",
|
|
942
|
-
"tan"
|
|
943
|
-
]);
|
|
944
|
-
var SAFE_DATE_STATIC_METHODS2 = /* @__PURE__ */ new Set(["now", "parse"]);
|
|
945
|
-
var SAFE_DATE_INSTANCE_METHODS2 = /* @__PURE__ */ new Set([
|
|
946
|
-
"toISOString",
|
|
947
|
-
"toDateString",
|
|
948
|
-
"toTimeString",
|
|
949
|
-
"getTime",
|
|
950
|
-
"getFullYear",
|
|
951
|
-
"getMonth",
|
|
952
|
-
"getDate",
|
|
953
|
-
"getHours",
|
|
954
|
-
"getMinutes",
|
|
955
|
-
"getSeconds",
|
|
956
|
-
"getMilliseconds"
|
|
957
|
-
]);
|
|
375
|
+
import { isCookieInitialExpr as isCookieInitialExpr2, evaluate as coreEvaluate2 } from "@constela/core";
|
|
958
376
|
var CHUNK_SIZE_THRESHOLD = 1024;
|
|
959
377
|
function isEventHandler2(value) {
|
|
960
378
|
return typeof value === "object" && value !== null && "event" in value && "action" in value;
|
|
961
379
|
}
|
|
962
|
-
function createLambdaFunction2(lambda, ctx) {
|
|
963
|
-
return (item, index) => {
|
|
964
|
-
const lambdaLocals = {
|
|
965
|
-
...ctx.locals,
|
|
966
|
-
[lambda.param]: item
|
|
967
|
-
};
|
|
968
|
-
if (lambda.index !== void 0) {
|
|
969
|
-
lambdaLocals[lambda.index] = index;
|
|
970
|
-
}
|
|
971
|
-
return evaluate2(lambda.body, { ...ctx, locals: lambdaLocals });
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
function callArrayMethod2(target, method, args, ctx, rawArgs) {
|
|
975
|
-
if (!SAFE_ARRAY_METHODS2.has(method)) return void 0;
|
|
976
|
-
switch (method) {
|
|
977
|
-
case "length":
|
|
978
|
-
return target.length;
|
|
979
|
-
case "at": {
|
|
980
|
-
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
981
|
-
return target.at(index);
|
|
982
|
-
}
|
|
983
|
-
case "includes": {
|
|
984
|
-
const searchElement = args[0];
|
|
985
|
-
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
986
|
-
return target.includes(searchElement, fromIndex);
|
|
987
|
-
}
|
|
988
|
-
case "slice": {
|
|
989
|
-
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
990
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
991
|
-
return target.slice(start, end);
|
|
992
|
-
}
|
|
993
|
-
case "indexOf": {
|
|
994
|
-
const searchElement = args[0];
|
|
995
|
-
const fromIndex = typeof args[1] === "number" ? args[1] : void 0;
|
|
996
|
-
return target.indexOf(searchElement, fromIndex);
|
|
997
|
-
}
|
|
998
|
-
case "join": {
|
|
999
|
-
const separator = typeof args[0] === "string" ? args[0] : ",";
|
|
1000
|
-
return target.join(separator);
|
|
1001
|
-
}
|
|
1002
|
-
case "filter": {
|
|
1003
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1004
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1005
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1006
|
-
return target.filter((item, index) => !!fn(item, index));
|
|
1007
|
-
}
|
|
1008
|
-
case "map": {
|
|
1009
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1010
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1011
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1012
|
-
return target.map((item, index) => fn(item, index));
|
|
1013
|
-
}
|
|
1014
|
-
case "find": {
|
|
1015
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1016
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1017
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1018
|
-
return target.find((item, index) => !!fn(item, index));
|
|
1019
|
-
}
|
|
1020
|
-
case "findIndex": {
|
|
1021
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1022
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1023
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1024
|
-
return target.findIndex((item, index) => !!fn(item, index));
|
|
1025
|
-
}
|
|
1026
|
-
case "some": {
|
|
1027
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1028
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1029
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1030
|
-
return target.some((item, index) => !!fn(item, index));
|
|
1031
|
-
}
|
|
1032
|
-
case "every": {
|
|
1033
|
-
const lambdaExpr = rawArgs?.[0];
|
|
1034
|
-
if (!lambdaExpr || lambdaExpr.expr !== "lambda") return void 0;
|
|
1035
|
-
const fn = createLambdaFunction2(lambdaExpr, ctx);
|
|
1036
|
-
return target.every((item, index) => !!fn(item, index));
|
|
1037
|
-
}
|
|
1038
|
-
default:
|
|
1039
|
-
return void 0;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
function callStringMethod2(target, method, args) {
|
|
1043
|
-
if (!SAFE_STRING_METHODS2.has(method)) return void 0;
|
|
1044
|
-
switch (method) {
|
|
1045
|
-
case "length":
|
|
1046
|
-
return target.length;
|
|
1047
|
-
case "charAt": {
|
|
1048
|
-
const index = typeof args[0] === "number" ? args[0] : 0;
|
|
1049
|
-
return target.charAt(index);
|
|
1050
|
-
}
|
|
1051
|
-
case "substring": {
|
|
1052
|
-
const start = typeof args[0] === "number" ? args[0] : 0;
|
|
1053
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
1054
|
-
return target.substring(start, end);
|
|
1055
|
-
}
|
|
1056
|
-
case "slice": {
|
|
1057
|
-
const start = typeof args[0] === "number" ? args[0] : void 0;
|
|
1058
|
-
const end = typeof args[1] === "number" ? args[1] : void 0;
|
|
1059
|
-
return target.slice(start, end);
|
|
1060
|
-
}
|
|
1061
|
-
case "split": {
|
|
1062
|
-
const separator = typeof args[0] === "string" ? args[0] : "";
|
|
1063
|
-
return target.split(separator);
|
|
1064
|
-
}
|
|
1065
|
-
case "trim":
|
|
1066
|
-
return target.trim();
|
|
1067
|
-
case "toUpperCase":
|
|
1068
|
-
return target.toUpperCase();
|
|
1069
|
-
case "toLowerCase":
|
|
1070
|
-
return target.toLowerCase();
|
|
1071
|
-
case "replace": {
|
|
1072
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
1073
|
-
const replace = typeof args[1] === "string" ? args[1] : "";
|
|
1074
|
-
return target.replace(search, replace);
|
|
1075
|
-
}
|
|
1076
|
-
case "includes": {
|
|
1077
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
1078
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
1079
|
-
return target.includes(search, position);
|
|
1080
|
-
}
|
|
1081
|
-
case "startsWith": {
|
|
1082
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
1083
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
1084
|
-
return target.startsWith(search, position);
|
|
1085
|
-
}
|
|
1086
|
-
case "endsWith": {
|
|
1087
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
1088
|
-
const length = typeof args[1] === "number" ? args[1] : void 0;
|
|
1089
|
-
return target.endsWith(search, length);
|
|
1090
|
-
}
|
|
1091
|
-
case "indexOf": {
|
|
1092
|
-
const search = typeof args[0] === "string" ? args[0] : "";
|
|
1093
|
-
const position = typeof args[1] === "number" ? args[1] : void 0;
|
|
1094
|
-
return target.indexOf(search, position);
|
|
1095
|
-
}
|
|
1096
|
-
default:
|
|
1097
|
-
return void 0;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
function callMathMethod2(method, args) {
|
|
1101
|
-
if (!SAFE_MATH_METHODS2.has(method)) return void 0;
|
|
1102
|
-
const numbers = args.filter((a) => typeof a === "number");
|
|
1103
|
-
switch (method) {
|
|
1104
|
-
case "min":
|
|
1105
|
-
return numbers.length > 0 ? Math.min(...numbers) : void 0;
|
|
1106
|
-
case "max":
|
|
1107
|
-
return numbers.length > 0 ? Math.max(...numbers) : void 0;
|
|
1108
|
-
case "round":
|
|
1109
|
-
return numbers[0] !== void 0 ? Math.round(numbers[0]) : void 0;
|
|
1110
|
-
case "floor":
|
|
1111
|
-
return numbers[0] !== void 0 ? Math.floor(numbers[0]) : void 0;
|
|
1112
|
-
case "ceil":
|
|
1113
|
-
return numbers[0] !== void 0 ? Math.ceil(numbers[0]) : void 0;
|
|
1114
|
-
case "abs":
|
|
1115
|
-
return numbers[0] !== void 0 ? Math.abs(numbers[0]) : void 0;
|
|
1116
|
-
case "sqrt":
|
|
1117
|
-
return numbers[0] !== void 0 ? Math.sqrt(numbers[0]) : void 0;
|
|
1118
|
-
case "pow":
|
|
1119
|
-
return numbers[0] !== void 0 && numbers[1] !== void 0 ? Math.pow(numbers[0], numbers[1]) : void 0;
|
|
1120
|
-
case "random":
|
|
1121
|
-
return Math.random();
|
|
1122
|
-
case "sin":
|
|
1123
|
-
return numbers[0] !== void 0 ? Math.sin(numbers[0]) : void 0;
|
|
1124
|
-
case "cos":
|
|
1125
|
-
return numbers[0] !== void 0 ? Math.cos(numbers[0]) : void 0;
|
|
1126
|
-
case "tan":
|
|
1127
|
-
return numbers[0] !== void 0 ? Math.tan(numbers[0]) : void 0;
|
|
1128
|
-
default:
|
|
1129
|
-
return void 0;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
function callDateStaticMethod2(method, args) {
|
|
1133
|
-
if (!SAFE_DATE_STATIC_METHODS2.has(method)) return void 0;
|
|
1134
|
-
switch (method) {
|
|
1135
|
-
case "now":
|
|
1136
|
-
return Date.now();
|
|
1137
|
-
case "parse": {
|
|
1138
|
-
const dateString = args[0];
|
|
1139
|
-
return typeof dateString === "string" ? Date.parse(dateString) : void 0;
|
|
1140
|
-
}
|
|
1141
|
-
default:
|
|
1142
|
-
return void 0;
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
function callDateInstanceMethod2(target, method) {
|
|
1146
|
-
if (!SAFE_DATE_INSTANCE_METHODS2.has(method)) return void 0;
|
|
1147
|
-
switch (method) {
|
|
1148
|
-
case "toISOString":
|
|
1149
|
-
return target.toISOString();
|
|
1150
|
-
case "toDateString":
|
|
1151
|
-
return target.toDateString();
|
|
1152
|
-
case "toTimeString":
|
|
1153
|
-
return target.toTimeString();
|
|
1154
|
-
case "getTime":
|
|
1155
|
-
return target.getTime();
|
|
1156
|
-
case "getFullYear":
|
|
1157
|
-
return target.getFullYear();
|
|
1158
|
-
case "getMonth":
|
|
1159
|
-
return target.getMonth();
|
|
1160
|
-
case "getDate":
|
|
1161
|
-
return target.getDate();
|
|
1162
|
-
case "getHours":
|
|
1163
|
-
return target.getHours();
|
|
1164
|
-
case "getMinutes":
|
|
1165
|
-
return target.getMinutes();
|
|
1166
|
-
case "getSeconds":
|
|
1167
|
-
return target.getSeconds();
|
|
1168
|
-
case "getMilliseconds":
|
|
1169
|
-
return target.getMilliseconds();
|
|
1170
|
-
default:
|
|
1171
|
-
return void 0;
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
function evaluate2(expr, ctx) {
|
|
1175
|
-
switch (expr.expr) {
|
|
1176
|
-
case "lit":
|
|
1177
|
-
return expr.value;
|
|
1178
|
-
case "state":
|
|
1179
|
-
return ctx.state.get(expr.name);
|
|
1180
|
-
case "local":
|
|
1181
|
-
return ctx.locals[expr.name];
|
|
1182
|
-
case "var": {
|
|
1183
|
-
let varName = expr.name;
|
|
1184
|
-
let pathParts = [];
|
|
1185
|
-
if (varName.includes(".")) {
|
|
1186
|
-
const parts = varName.split(".");
|
|
1187
|
-
varName = parts[0];
|
|
1188
|
-
pathParts = parts.slice(1);
|
|
1189
|
-
}
|
|
1190
|
-
if (expr.path) {
|
|
1191
|
-
pathParts = pathParts.concat(expr.path.split("."));
|
|
1192
|
-
}
|
|
1193
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1194
|
-
for (const part of pathParts) {
|
|
1195
|
-
if (forbiddenKeys.has(part)) {
|
|
1196
|
-
return void 0;
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
let value = ctx.locals[varName];
|
|
1200
|
-
for (const part of pathParts) {
|
|
1201
|
-
if (value == null) break;
|
|
1202
|
-
value = value[part];
|
|
1203
|
-
}
|
|
1204
|
-
return value;
|
|
1205
|
-
}
|
|
1206
|
-
case "bin":
|
|
1207
|
-
return evaluateBinary2(expr.op, expr.left, expr.right, ctx);
|
|
1208
|
-
case "not":
|
|
1209
|
-
return !evaluate2(expr.operand, ctx);
|
|
1210
|
-
case "cond":
|
|
1211
|
-
return evaluate2(expr.if, ctx) ? evaluate2(expr.then, ctx) : evaluate2(expr.else, ctx);
|
|
1212
|
-
case "get": {
|
|
1213
|
-
const baseValue = evaluate2(expr.base, ctx);
|
|
1214
|
-
if (baseValue == null) return void 0;
|
|
1215
|
-
const pathParts = expr.path.split(".");
|
|
1216
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1217
|
-
let value = baseValue;
|
|
1218
|
-
for (const part of pathParts) {
|
|
1219
|
-
if (forbiddenKeys.has(part)) return void 0;
|
|
1220
|
-
if (value == null) return void 0;
|
|
1221
|
-
value = value[part];
|
|
1222
|
-
}
|
|
1223
|
-
return value;
|
|
1224
|
-
}
|
|
1225
|
-
case "route": {
|
|
1226
|
-
const source = expr.source ?? "param";
|
|
1227
|
-
const routeCtx = ctx.route;
|
|
1228
|
-
if (!routeCtx) return "";
|
|
1229
|
-
switch (source) {
|
|
1230
|
-
case "param":
|
|
1231
|
-
return routeCtx.params[expr.name] ?? "";
|
|
1232
|
-
case "query":
|
|
1233
|
-
return routeCtx.query[expr.name] ?? "";
|
|
1234
|
-
case "path":
|
|
1235
|
-
return routeCtx.path;
|
|
1236
|
-
default:
|
|
1237
|
-
return "";
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
case "import": {
|
|
1241
|
-
const importData = ctx.imports?.[expr.name];
|
|
1242
|
-
if (importData === void 0) return void 0;
|
|
1243
|
-
if (expr.path) {
|
|
1244
|
-
return getNestedValue2(importData, expr.path);
|
|
1245
|
-
}
|
|
1246
|
-
return importData;
|
|
1247
|
-
}
|
|
1248
|
-
case "data": {
|
|
1249
|
-
const dataValue = ctx.imports?.[expr.name];
|
|
1250
|
-
if (dataValue === void 0) return void 0;
|
|
1251
|
-
if (expr.path) {
|
|
1252
|
-
return getNestedValue2(dataValue, expr.path);
|
|
1253
|
-
}
|
|
1254
|
-
return dataValue;
|
|
1255
|
-
}
|
|
1256
|
-
case "ref":
|
|
1257
|
-
return null;
|
|
1258
|
-
case "index": {
|
|
1259
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1260
|
-
const base = evaluate2(expr.base, ctx);
|
|
1261
|
-
const key = evaluate2(expr.key, ctx);
|
|
1262
|
-
if (base == null || key == null) return void 0;
|
|
1263
|
-
if (typeof key === "string" && forbiddenKeys.has(key)) return void 0;
|
|
1264
|
-
return base[key];
|
|
1265
|
-
}
|
|
1266
|
-
case "param": {
|
|
1267
|
-
return void 0;
|
|
1268
|
-
}
|
|
1269
|
-
case "style": {
|
|
1270
|
-
return evaluateStyle2(expr, ctx);
|
|
1271
|
-
}
|
|
1272
|
-
case "concat": {
|
|
1273
|
-
return expr.items.map((item) => {
|
|
1274
|
-
const val = evaluate2(item, ctx);
|
|
1275
|
-
return val == null ? "" : String(val);
|
|
1276
|
-
}).join("");
|
|
1277
|
-
}
|
|
1278
|
-
case "validity": {
|
|
1279
|
-
return false;
|
|
1280
|
-
}
|
|
1281
|
-
case "call": {
|
|
1282
|
-
const callExpr = expr;
|
|
1283
|
-
if (callExpr.target === null) {
|
|
1284
|
-
return void 0;
|
|
1285
|
-
}
|
|
1286
|
-
const target = evaluate2(callExpr.target, ctx);
|
|
1287
|
-
if (target == null) return void 0;
|
|
1288
|
-
const args = callExpr.args?.map((arg) => {
|
|
1289
|
-
if (arg.expr === "lambda") return arg;
|
|
1290
|
-
return evaluate2(arg, ctx);
|
|
1291
|
-
}) ?? [];
|
|
1292
|
-
if (Array.isArray(target)) {
|
|
1293
|
-
return callArrayMethod2(target, callExpr.method, args, ctx, callExpr.args);
|
|
1294
|
-
}
|
|
1295
|
-
if (typeof target === "string") {
|
|
1296
|
-
return callStringMethod2(target, callExpr.method, args);
|
|
1297
|
-
}
|
|
1298
|
-
if (target === Math) {
|
|
1299
|
-
return callMathMethod2(callExpr.method, args);
|
|
1300
|
-
}
|
|
1301
|
-
if (target === Date) {
|
|
1302
|
-
return callDateStaticMethod2(callExpr.method, args);
|
|
1303
|
-
}
|
|
1304
|
-
if (target instanceof Date) {
|
|
1305
|
-
return callDateInstanceMethod2(target, callExpr.method);
|
|
1306
|
-
}
|
|
1307
|
-
return void 0;
|
|
1308
|
-
}
|
|
1309
|
-
case "lambda": {
|
|
1310
|
-
return void 0;
|
|
1311
|
-
}
|
|
1312
|
-
case "array": {
|
|
1313
|
-
const arrayExpr = expr;
|
|
1314
|
-
return arrayExpr.elements.map((elem) => evaluate2(elem, ctx));
|
|
1315
|
-
}
|
|
1316
|
-
case "obj": {
|
|
1317
|
-
const objExpr = expr;
|
|
1318
|
-
const result = {};
|
|
1319
|
-
for (const [key, value] of Object.entries(objExpr.props)) {
|
|
1320
|
-
result[key] = evaluate2(value, ctx);
|
|
1321
|
-
}
|
|
1322
|
-
return result;
|
|
1323
|
-
}
|
|
1324
|
-
default: {
|
|
1325
|
-
return void 0;
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
function getNestedValue2(obj, path) {
|
|
1330
|
-
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1331
|
-
const parts = path.split(".");
|
|
1332
|
-
let value = obj;
|
|
1333
|
-
for (const part of parts) {
|
|
1334
|
-
if (forbiddenKeys.has(part)) {
|
|
1335
|
-
return void 0;
|
|
1336
|
-
}
|
|
1337
|
-
if (value == null) {
|
|
1338
|
-
return void 0;
|
|
1339
|
-
}
|
|
1340
|
-
if (Array.isArray(value)) {
|
|
1341
|
-
const index = Number(part);
|
|
1342
|
-
if (Number.isInteger(index) && index >= 0) {
|
|
1343
|
-
value = value[index];
|
|
1344
|
-
} else {
|
|
1345
|
-
value = value[part];
|
|
1346
|
-
}
|
|
1347
|
-
} else if (typeof value === "object") {
|
|
1348
|
-
value = value[part];
|
|
1349
|
-
} else {
|
|
1350
|
-
return void 0;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
return value;
|
|
1354
|
-
}
|
|
1355
|
-
function evaluateBinary2(op, left, right, ctx) {
|
|
1356
|
-
if (op === "&&") {
|
|
1357
|
-
const leftVal2 = evaluate2(left, ctx);
|
|
1358
|
-
if (!leftVal2) return leftVal2;
|
|
1359
|
-
return evaluate2(right, ctx);
|
|
1360
|
-
}
|
|
1361
|
-
if (op === "||") {
|
|
1362
|
-
const leftVal2 = evaluate2(left, ctx);
|
|
1363
|
-
if (leftVal2) return leftVal2;
|
|
1364
|
-
return evaluate2(right, ctx);
|
|
1365
|
-
}
|
|
1366
|
-
const leftVal = evaluate2(left, ctx);
|
|
1367
|
-
const rightVal = evaluate2(right, ctx);
|
|
1368
|
-
switch (op) {
|
|
1369
|
-
case "+":
|
|
1370
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
1371
|
-
return leftVal + rightVal;
|
|
1372
|
-
}
|
|
1373
|
-
return String(leftVal) + String(rightVal);
|
|
1374
|
-
case "-":
|
|
1375
|
-
return (typeof leftVal === "number" ? leftVal : 0) - (typeof rightVal === "number" ? rightVal : 0);
|
|
1376
|
-
case "*":
|
|
1377
|
-
return (typeof leftVal === "number" ? leftVal : 0) * (typeof rightVal === "number" ? rightVal : 0);
|
|
1378
|
-
case "/": {
|
|
1379
|
-
const dividend = typeof leftVal === "number" ? leftVal : 0;
|
|
1380
|
-
const divisor = typeof rightVal === "number" ? rightVal : 0;
|
|
1381
|
-
if (divisor === 0) {
|
|
1382
|
-
return dividend === 0 ? NaN : dividend > 0 ? Infinity : -Infinity;
|
|
1383
|
-
}
|
|
1384
|
-
return dividend / divisor;
|
|
1385
|
-
}
|
|
1386
|
-
case "==":
|
|
1387
|
-
return leftVal === rightVal;
|
|
1388
|
-
case "!=":
|
|
1389
|
-
return leftVal !== rightVal;
|
|
1390
|
-
case "<":
|
|
1391
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
1392
|
-
return leftVal < rightVal;
|
|
1393
|
-
}
|
|
1394
|
-
return String(leftVal) < String(rightVal);
|
|
1395
|
-
case "<=":
|
|
1396
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
1397
|
-
return leftVal <= rightVal;
|
|
1398
|
-
}
|
|
1399
|
-
return String(leftVal) <= String(rightVal);
|
|
1400
|
-
case ">":
|
|
1401
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
1402
|
-
return leftVal > rightVal;
|
|
1403
|
-
}
|
|
1404
|
-
return String(leftVal) > String(rightVal);
|
|
1405
|
-
case ">=":
|
|
1406
|
-
if (typeof leftVal === "number" && typeof rightVal === "number") {
|
|
1407
|
-
return leftVal >= rightVal;
|
|
1408
|
-
}
|
|
1409
|
-
return String(leftVal) >= String(rightVal);
|
|
1410
|
-
default:
|
|
1411
|
-
throw new Error("Unknown binary operator: " + op);
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
function evaluateStyle2(expr, ctx) {
|
|
1415
|
-
const preset = ctx.styles?.[expr.name];
|
|
1416
|
-
if (!preset) return "";
|
|
1417
|
-
let classes = preset.base;
|
|
1418
|
-
if (preset.variants) {
|
|
1419
|
-
for (const variantKey of Object.keys(preset.variants)) {
|
|
1420
|
-
let variantValueStr = null;
|
|
1421
|
-
if (expr.variants?.[variantKey]) {
|
|
1422
|
-
let variantValue;
|
|
1423
|
-
try {
|
|
1424
|
-
variantValue = evaluate2(expr.variants[variantKey], ctx);
|
|
1425
|
-
} catch {
|
|
1426
|
-
continue;
|
|
1427
|
-
}
|
|
1428
|
-
if (variantValue != null) {
|
|
1429
|
-
variantValueStr = String(variantValue);
|
|
1430
|
-
}
|
|
1431
|
-
} else if (preset.defaultVariants?.[variantKey] !== void 0) {
|
|
1432
|
-
variantValueStr = preset.defaultVariants[variantKey];
|
|
1433
|
-
}
|
|
1434
|
-
if (variantValueStr !== null) {
|
|
1435
|
-
const variantClasses = preset.variants[variantKey]?.[variantValueStr];
|
|
1436
|
-
if (variantClasses) {
|
|
1437
|
-
classes += " " + variantClasses;
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
return classes.trim();
|
|
1443
|
-
}
|
|
1444
|
-
function formatValue2(value) {
|
|
1445
|
-
if (value === null || value === void 0) {
|
|
1446
|
-
return "";
|
|
1447
|
-
}
|
|
1448
|
-
if (typeof value === "object") {
|
|
1449
|
-
return JSON.stringify(value);
|
|
1450
|
-
}
|
|
1451
|
-
return String(value);
|
|
1452
|
-
}
|
|
1453
380
|
function flush(ctx, force = false) {
|
|
1454
381
|
if (ctx.aborted) return;
|
|
1455
382
|
const { buffer, options, controller } = ctx;
|
|
@@ -1535,14 +462,14 @@ async function renderSuspenseToStream(node, ctx) {
|
|
|
1535
462
|
async function renderElementToStream(node, ctx) {
|
|
1536
463
|
if (checkAbort(ctx)) return;
|
|
1537
464
|
const tag = node.tag;
|
|
1538
|
-
const isVoid =
|
|
465
|
+
const isVoid = VOID_ELEMENTS.has(tag);
|
|
1539
466
|
let attrs = "";
|
|
1540
467
|
if (node.props) {
|
|
1541
468
|
for (const [propName, propValue] of Object.entries(node.props)) {
|
|
1542
469
|
if (isEventHandler2(propValue)) {
|
|
1543
470
|
continue;
|
|
1544
471
|
}
|
|
1545
|
-
const value =
|
|
472
|
+
const value = coreEvaluate2(propValue, toCoreContext(ctx));
|
|
1546
473
|
if (value === false) {
|
|
1547
474
|
continue;
|
|
1548
475
|
}
|
|
@@ -1569,12 +496,12 @@ async function renderElementToStream(node, ctx) {
|
|
|
1569
496
|
write(ctx, "</" + tag + ">");
|
|
1570
497
|
}
|
|
1571
498
|
function renderTextToStream(node, ctx) {
|
|
1572
|
-
const value =
|
|
1573
|
-
write(ctx, escapeHtml(
|
|
499
|
+
const value = coreEvaluate2(node.value, toCoreContext(ctx));
|
|
500
|
+
write(ctx, escapeHtml(formatValue(value)));
|
|
1574
501
|
}
|
|
1575
502
|
async function renderIfToStream(node, ctx) {
|
|
1576
503
|
if (checkAbort(ctx)) return;
|
|
1577
|
-
const condition =
|
|
504
|
+
const condition = coreEvaluate2(node.condition, toCoreContext(ctx));
|
|
1578
505
|
if (condition) {
|
|
1579
506
|
write(ctx, "<!--if:then-->");
|
|
1580
507
|
await renderNodeToStream(node.then, ctx);
|
|
@@ -1587,7 +514,7 @@ async function renderIfToStream(node, ctx) {
|
|
|
1587
514
|
}
|
|
1588
515
|
async function renderEachToStream(node, ctx) {
|
|
1589
516
|
if (checkAbort(ctx)) return;
|
|
1590
|
-
const items =
|
|
517
|
+
const items = coreEvaluate2(node.items, toCoreContext(ctx));
|
|
1591
518
|
if (!Array.isArray(items)) {
|
|
1592
519
|
return;
|
|
1593
520
|
}
|
|
@@ -1612,12 +539,13 @@ async function renderEachToStream(node, ctx) {
|
|
|
1612
539
|
}
|
|
1613
540
|
}
|
|
1614
541
|
async function renderMarkdownToStream(node, ctx) {
|
|
1615
|
-
const content =
|
|
1616
|
-
write(ctx, '<div class="constela-markdown">' + escapeHtml(
|
|
542
|
+
const content = coreEvaluate2(node.content, toCoreContext(ctx));
|
|
543
|
+
write(ctx, '<div class="constela-markdown">' + escapeHtml(formatValue(content)) + "</div>");
|
|
1617
544
|
}
|
|
1618
545
|
async function renderCodeToStream(node, ctx) {
|
|
1619
|
-
const
|
|
1620
|
-
const
|
|
546
|
+
const coreCtx = toCoreContext(ctx);
|
|
547
|
+
const language = formatValue(coreEvaluate2(node.language, coreCtx));
|
|
548
|
+
const content = formatValue(coreEvaluate2(node.content, coreCtx));
|
|
1621
549
|
const languageBadge = language ? '<div class="absolute right-12 top-3 z-10 rounded bg-muted-foreground/20 px-2 py-0.5 text-xs font-medium text-muted-foreground">' + escapeHtml(language) + "</div>" : "";
|
|
1622
550
|
const copyButton = '<button class="constela-copy-btn absolute right-3 top-3 z-10 flex h-8 w-8 items-center justify-center rounded-md border border-border bg-background/80 opacity-0 transition-opacity hover:bg-muted group-hover:opacity-100" data-copy-target="code" aria-label="Copy code"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>';
|
|
1623
551
|
write(ctx, '<div class="constela-code" data-code-content="' + escapeHtml(content) + '"><div class="group relative">' + languageBadge + copyButton + "<pre><code>" + escapeHtml(content) + "</code></pre></div></div>");
|
|
@@ -1636,7 +564,7 @@ async function renderLocalStateToStream(node, ctx) {
|
|
|
1636
564
|
const initial = field.initial;
|
|
1637
565
|
if (initial && typeof initial === "object" && "expr" in initial) {
|
|
1638
566
|
const evalCtx = { ...ctx, locals: progressiveLocals };
|
|
1639
|
-
localStateValues[name] =
|
|
567
|
+
localStateValues[name] = coreEvaluate2(initial, toCoreContext(evalCtx));
|
|
1640
568
|
} else {
|
|
1641
569
|
localStateValues[name] = initial;
|
|
1642
570
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"description": "Server-side rendering for Constela UI framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@constela/compiler": "^0.15.
|
|
19
|
-
"@constela/core": "^0.
|
|
18
|
+
"@constela/compiler": "^0.15.21",
|
|
19
|
+
"@constela/core": "^0.22.0"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"isomorphic-dompurify": "^2.35.0",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"tsup": "^8.0.0",
|
|
30
30
|
"typescript": "^5.3.0",
|
|
31
31
|
"vitest": "^2.0.0",
|
|
32
|
-
"@constela/
|
|
33
|
-
"@constela/
|
|
32
|
+
"@constela/compiler": "0.15.21",
|
|
33
|
+
"@constela/core": "0.22.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=20.0.0"
|