@constela/server 5.0.1 → 7.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 +27 -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
@@ -225,6 +225,9 @@ function evaluate(expr, ctx) {
225
225
  return val == null ? "" : String(val);
226
226
  }).join("");
227
227
  }
228
+ case "validity": {
229
+ return false;
230
+ }
228
231
  default: {
229
232
  const _exhaustiveCheck = expr;
230
233
  throw new Error(`Unknown expression type: ${JSON.stringify(_exhaustiveCheck)}`);
@@ -371,6 +374,10 @@ async function renderNode(node, ctx) {
371
374
  return await renderCode(node, ctx);
372
375
  case "slot":
373
376
  return "";
377
+ case "portal":
378
+ return await renderPortal(node, ctx);
379
+ case "localState":
380
+ return await renderLocalState(node, ctx);
374
381
  default: {
375
382
  const _exhaustiveCheck = node;
376
383
  throw new Error(`Unknown node kind: ${JSON.stringify(_exhaustiveCheck)}`);
@@ -461,6 +468,26 @@ async function renderCode(node, ctx) {
461
468
  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>`;
462
469
  return `<div class="constela-code" data-code-content="${escapeHtml(content)}"><div class="group relative">${languageBadge}${copyButton}${highlightedCode}</div></div>`;
463
470
  }
471
+ async function renderPortal(node, ctx) {
472
+ const childrenHtml = await Promise.all(
473
+ node.children.map((child) => renderNode(child, ctx))
474
+ );
475
+ return `<!--portal:${node.target}-->${childrenHtml.join("")}<!--/portal-->`;
476
+ }
477
+ async function renderLocalState(node, ctx) {
478
+ const localStateValues = {};
479
+ for (const [name, field] of Object.entries(node.state)) {
480
+ localStateValues[name] = field.initial;
481
+ }
482
+ const childCtx = {
483
+ ...ctx,
484
+ locals: {
485
+ ...ctx.locals,
486
+ ...localStateValues
487
+ }
488
+ };
489
+ return await renderNode(node.child, childCtx);
490
+ }
464
491
  async function renderToString(program, options) {
465
492
  const state = /* @__PURE__ */ new Map();
466
493
  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.1",
3
+ "version": "7.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.1"
18
+ "@constela/compiler": "^0.11.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.1"
31
+ "@constela/compiler": "0.11.0"
32
32
  },
33
33
  "engines": {
34
34
  "node": ">=20.0.0"