@constela/server 5.0.0 → 6.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.
Files changed (3) hide show
  1. package/README.md +26 -0
  2. package/dist/index.js +22 -0
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -38,6 +38,32 @@ JSON program → HTML string
38
38
 
39
39
  ## Features
40
40
 
41
+ ### String Concatenation (concat)
42
+
43
+ Build dynamic strings during SSR:
44
+
45
+ ```json
46
+ {
47
+ "kind": "element",
48
+ "tag": "a",
49
+ "props": {
50
+ "href": {
51
+ "expr": "concat",
52
+ "items": [
53
+ { "expr": "lit", "value": "/posts/" },
54
+ { "expr": "data", "name": "post", "path": "slug" }
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ↓ SSR
62
+
63
+ ```html
64
+ <a href="/posts/hello-world">...</a>
65
+ ```
66
+
41
67
  ### Markdown Rendering
42
68
 
43
69
  ```json
package/dist/index.js CHANGED
@@ -219,6 +219,12 @@ function evaluate(expr, ctx) {
219
219
  case "style": {
220
220
  return evaluateStyle(expr, ctx);
221
221
  }
222
+ case "concat": {
223
+ return expr.items.map((item) => {
224
+ const val = evaluate(item, ctx);
225
+ return val == null ? "" : String(val);
226
+ }).join("");
227
+ }
222
228
  default: {
223
229
  const _exhaustiveCheck = expr;
224
230
  throw new Error(`Unknown expression type: ${JSON.stringify(_exhaustiveCheck)}`);
@@ -365,6 +371,8 @@ async function renderNode(node, ctx) {
365
371
  return await renderCode(node, ctx);
366
372
  case "slot":
367
373
  return "";
374
+ case "localState":
375
+ return await renderLocalState(node, ctx);
368
376
  default: {
369
377
  const _exhaustiveCheck = node;
370
378
  throw new Error(`Unknown node kind: ${JSON.stringify(_exhaustiveCheck)}`);
@@ -455,6 +463,20 @@ async function renderCode(node, ctx) {
455
463
  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>`;
456
464
  return `<div class="constela-code" data-code-content="${escapeHtml(content)}"><div class="group relative">${languageBadge}${copyButton}${highlightedCode}</div></div>`;
457
465
  }
466
+ async function renderLocalState(node, ctx) {
467
+ const localStateValues = {};
468
+ for (const [name, field] of Object.entries(node.state)) {
469
+ localStateValues[name] = field.initial;
470
+ }
471
+ const childCtx = {
472
+ ...ctx,
473
+ locals: {
474
+ ...ctx.locals,
475
+ ...localStateValues
476
+ }
477
+ };
478
+ return await renderNode(node.child, childCtx);
479
+ }
458
480
  async function renderToString(program, options) {
459
481
  const state = /* @__PURE__ */ new Map();
460
482
  for (const [name, field] of Object.entries(program.state)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/server",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "description": "Server-side rendering for Constela UI framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "dist"
16
16
  ],
17
17
  "peerDependencies": {
18
- "@constela/compiler": "^0.9.0"
18
+ "@constela/compiler": "^0.10.0"
19
19
  },
20
20
  "dependencies": {
21
21
  "isomorphic-dompurify": "^2.35.0",
@@ -28,7 +28,7 @@
28
28
  "tsup": "^8.0.0",
29
29
  "typescript": "^5.3.0",
30
30
  "vitest": "^2.0.0",
31
- "@constela/compiler": "0.9.0"
31
+ "@constela/compiler": "0.10.0"
32
32
  },
33
33
  "engines": {
34
34
  "node": ">=20.0.0"