@vesk/vesk-cli 0.2.47 → 0.2.49

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 (2) hide show
  1. package/dist/cli.js +491 -328
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -2400,13 +2400,13 @@ function normText(el) {
2400
2400
  }
2401
2401
  function collectElements(rootEl) {
2402
2402
  const out = [];
2403
- (function walk7(n) {
2403
+ (function walk8(n) {
2404
2404
  const kids = n.childNodes;
2405
2405
  for (let i = 0; i < kids.length; i++) {
2406
2406
  const c = kids[i];
2407
2407
  if (c.nodeType === 1) {
2408
2408
  out.push(c);
2409
- walk7(c);
2409
+ walk8(c);
2410
2410
  }
2411
2411
  }
2412
2412
  })(rootEl);
@@ -3917,12 +3917,29 @@ function handleScroll(pathname, isReplace, scrollBehavior) {
3917
3917
  requestAnimationFrame(() => window.scrollTo({ top: 0, behavior }));
3918
3918
  }
3919
3919
  }
3920
+ function decodeHeadText(value) {
3921
+ if (value.indexOf("&") === -1) return value;
3922
+ return value.replace(/&(#x[0-9a-fA-F]+|#\d+|[a-zA-Z][a-zA-Z0-9]*);/g, (match, body) => {
3923
+ if (body.charCodeAt(0) === 35) {
3924
+ const hex = body.charCodeAt(1) === 120 || body.charCodeAt(1) === 88;
3925
+ const num = parseInt(hex ? body.slice(2) : body.slice(1), hex ? 16 : 10);
3926
+ if (!Number.isFinite(num) || num < 0 || num > 1114111) return match;
3927
+ try {
3928
+ return String.fromCodePoint(num);
3929
+ } catch {
3930
+ return match;
3931
+ }
3932
+ }
3933
+ const named = HEAD_ENTITIES[body.toLowerCase()];
3934
+ return named === void 0 ? match : named;
3935
+ });
3936
+ }
3920
3937
  function applyHeadAttrs(el, raw2) {
3921
3938
  for (const attrMatch of raw2.matchAll(/([a-zA-Z0-9\-:]+)\s*=\s*("([^"]*)"|'([^']*)')/g)) {
3922
3939
  const name = attrMatch[1];
3923
3940
  const value = attrMatch[3] ?? attrMatch[4] ?? "";
3924
3941
  if (name.toLowerCase() === "charset") continue;
3925
- el.setAttribute(name, value);
3942
+ el.setAttribute(name, decodeHeadText(value));
3926
3943
  }
3927
3944
  }
3928
3945
  function applyHead(headHtml) {
@@ -3936,7 +3953,7 @@ function applyHead(headHtml) {
3936
3953
  const titleMatch = headHtml.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
3937
3954
  if (titleMatch) {
3938
3955
  const t = document.createElement("title");
3939
- t.textContent = titleMatch[1];
3956
+ t.textContent = decodeHeadText(titleMatch[1]);
3940
3957
  t.setAttribute(HEAD_MARKER, "");
3941
3958
  head.appendChild(t);
3942
3959
  }
@@ -3965,7 +3982,7 @@ function applyHead(headHtml) {
3965
3982
  }
3966
3983
  for (const m of headHtml.matchAll(/<style\b([^>]*)>([\s\S]*?)<\/style>/gi)) {
3967
3984
  const style = document.createElement("style");
3968
- style.textContent = m[2];
3985
+ style.textContent = decodeHeadText(m[2]);
3969
3986
  style.setAttribute(HEAD_MARKER, "");
3970
3987
  head.appendChild(style);
3971
3988
  }
@@ -4245,7 +4262,7 @@ function useRouter() {
4245
4262
  }
4246
4263
  };
4247
4264
  }
4248
- var Redirect, NotFoundError, RouterCtx, _currentRouter, _outletId, __isHydrating, _state, _scrollPositions, _isPopStateNavigation, HEAD_MARKER;
4265
+ var Redirect, NotFoundError, RouterCtx, _currentRouter, _outletId, __isHydrating, _state, _scrollPositions, _isPopStateNavigation, HEAD_MARKER, HEAD_ENTITIES;
4249
4266
  var init_router_components = __esm({
4250
4267
  "../runtime/src/router-components.ts"() {
4251
4268
  "use strict";
@@ -4281,6 +4298,14 @@ var init_router_components = __esm({
4281
4298
  _scrollPositions = /* @__PURE__ */ new Map();
4282
4299
  _isPopStateNavigation = false;
4283
4300
  HEAD_MARKER = "data-vesk-head";
4301
+ HEAD_ENTITIES = {
4302
+ amp: "&",
4303
+ lt: "<",
4304
+ gt: ">",
4305
+ quot: '"',
4306
+ apos: "'",
4307
+ nbsp: "\xA0"
4308
+ };
4284
4309
  }
4285
4310
  });
4286
4311
 
@@ -28740,273 +28765,6 @@ var init_esbuild_fallback = __esm({
28740
28765
  }
28741
28766
  });
28742
28767
 
28743
- // ../compiler/src/server-head.ts
28744
- function isHtmlNameChar(ch) {
28745
- const code = ch.charCodeAt(0);
28746
- return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || ch === "-";
28747
- }
28748
- function isAttrBoundaryChar(ch) {
28749
- return isWhitespaceChar(ch) || ch === "=" || ch === "/" || ch === ">";
28750
- }
28751
- function isValueBoundaryChar(ch) {
28752
- return isWhitespaceChar(ch) || ch === "/" || ch === ">";
28753
- }
28754
- function evaluateLocals(comp, props) {
28755
- const locals2 = {};
28756
- for (const node of comp.body) {
28757
- if (node instanceof RuntimeStatement && node.ast) {
28758
- const stmt = node.ast;
28759
- if (stmt.type === "VariableDeclaration") {
28760
- for (const decl of stmt.declarations) {
28761
- if (decl.id.type === "Identifier" && decl.init && node.source) {
28762
- const name = decl.id.name;
28763
- const initSrc = node.source.slice(decl.init.start, decl.init.end);
28764
- try {
28765
- const fn = new Function("props", "return (" + initSrc + ")");
28766
- locals2[name] = fn(props);
28767
- } catch {
28768
- }
28769
- }
28770
- }
28771
- }
28772
- }
28773
- }
28774
- return locals2;
28775
- }
28776
- function headElementKey(node, props, locals2) {
28777
- if (!(node instanceof StaticNode)) return null;
28778
- const tag = node.tag;
28779
- if (tag === "title") return "title";
28780
- if (tag === "base") return "base";
28781
- const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
28782
- for (const child of node.children) {
28783
- if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
28784
- try {
28785
- attrMap.set(child.target, String(tryEvalExpr(child.expression.raw, props, locals2)));
28786
- } catch {
28787
- }
28788
- }
28789
- }
28790
- if (tag === "meta") {
28791
- if (attrMap.has("name")) return `meta[name=${attrMap.get("name")}]`;
28792
- if (attrMap.has("property")) return `meta[property=${attrMap.get("property")}]`;
28793
- if (attrMap.has("charset")) return "meta[charset]";
28794
- if (attrMap.has("http-equiv")) return `meta[http-equiv=${attrMap.get("http-equiv")}]`;
28795
- return null;
28796
- }
28797
- if (tag === "link") {
28798
- if (attrMap.has("href")) return `link[href=${attrMap.get("href")}]`;
28799
- if (attrMap.has("id")) return `link[id=${attrMap.get("id")}]`;
28800
- return null;
28801
- }
28802
- if (tag === "script") {
28803
- if (attrMap.has("src")) return `script[src=${attrMap.get("src")}]`;
28804
- return null;
28805
- }
28806
- if (tag === "style") return null;
28807
- return null;
28808
- }
28809
- function headIsReconcilable(tag, attrMap) {
28810
- if (!HEAD_RECONCILE_TAGS.has(tag)) return false;
28811
- if (tag === "meta" && attrMap.has("charset")) return false;
28812
- return true;
28813
- }
28814
- function irNodeToHeadHtml(node, props, locals2 = {}, reconcileable = false) {
28815
- if (node instanceof StaticNode) {
28816
- const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
28817
- for (const child of node.children) {
28818
- if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
28819
- try {
28820
- const val = tryEvalExpr(child.expression.raw, props, locals2);
28821
- attrMap.set(child.target, String(val));
28822
- } catch {
28823
- }
28824
- }
28825
- }
28826
- const marker = reconcileable && headIsReconcilable(node.tag, attrMap) ? ` ${HEAD_RECONCILE_MARKER}` : "";
28827
- const attrs = [...attrMap.entries()].map(([k, v]) => ` ${k}="${escapeHtml(v)}"`).join("");
28828
- if (node.selfClosing) return `<${node.tag}${attrs}${marker} />`;
28829
- const inner = node.children.filter((c) => !(c instanceof DynamicBinding && c.kind === "attribute" && c.target !== "ref")).map((c) => irNodeToHeadHtml(c, props, locals2, false)).join("");
28830
- return `<${node.tag}${attrs}${marker}>${inner}</${node.tag}>`;
28831
- }
28832
- if (node instanceof TextNode) return node.value;
28833
- if (node instanceof DynamicBinding) {
28834
- try {
28835
- const val = tryEvalExpr(node.expression.raw, props, locals2);
28836
- return escapeHtml(String(val));
28837
- } catch {
28838
- return "";
28839
- }
28840
- }
28841
- return "";
28842
- }
28843
- function renderHeadHtml(comp, props = {}) {
28844
- const locals2 = evaluateLocals(comp, props);
28845
- const seen = /* @__PURE__ */ new Set();
28846
- const parts = [];
28847
- for (const node of comp.body) {
28848
- if (node instanceof HeadBlock) {
28849
- for (const child of node.children) {
28850
- const key = headElementKey(child, props, locals2);
28851
- if (key !== null && seen.has(key)) continue;
28852
- if (key !== null) seen.add(key);
28853
- parts.push(irNodeToHeadHtml(child, props, locals2, true));
28854
- }
28855
- }
28856
- }
28857
- return parts.join("\n");
28858
- }
28859
- function scanHeadTag(html, lt) {
28860
- let i = lt + 1;
28861
- if (html[i] === "/") i++;
28862
- const nameStart = i;
28863
- while (i < html.length && isHtmlNameChar(html[i])) i++;
28864
- const tag = html.slice(nameStart, i).toLowerCase();
28865
- if (!tag) return null;
28866
- const attrs = /* @__PURE__ */ new Map();
28867
- let selfClosing = false;
28868
- while (i < html.length) {
28869
- while (i < html.length && isWhitespaceChar(html[i])) i++;
28870
- if (html[i] === ">") {
28871
- i++;
28872
- break;
28873
- }
28874
- if (html[i] === "/" && html[i + 1] === ">") {
28875
- selfClosing = true;
28876
- i += 2;
28877
- break;
28878
- }
28879
- if (i >= html.length || html[i] === ">" || html[i] === "/") continue;
28880
- const aStart = i;
28881
- while (i < html.length && !isAttrBoundaryChar(html[i])) i++;
28882
- const aName = html.slice(aStart, i).toLowerCase();
28883
- while (i < html.length && isWhitespaceChar(html[i])) i++;
28884
- let value = "";
28885
- if (html[i] === "=") {
28886
- i++;
28887
- while (i < html.length && isWhitespaceChar(html[i])) i++;
28888
- const q = html[i];
28889
- if (q === '"' || q === "'") {
28890
- i++;
28891
- const vStart = i;
28892
- while (i < html.length && html[i] !== q) i++;
28893
- value = html.slice(vStart, i);
28894
- if (i < html.length) i++;
28895
- } else {
28896
- const vStart = i;
28897
- while (i < html.length && !isValueBoundaryChar(html[i])) i++;
28898
- value = html.slice(vStart, i);
28899
- }
28900
- }
28901
- if (aName) attrs.set(aName, value);
28902
- }
28903
- let raw2 = html.slice(lt, i);
28904
- const nonVoidTags = /* @__PURE__ */ new Set(["title", "script", "style", "noscript"]);
28905
- if (!selfClosing && nonVoidTags.has(tag)) {
28906
- const closeTag = html.indexOf("</" + tag, i);
28907
- if (closeTag !== -1) {
28908
- const end = html.indexOf(">", closeTag);
28909
- if (end !== -1) {
28910
- raw2 = html.slice(lt, end + 1);
28911
- i = end + 1;
28912
- }
28913
- }
28914
- }
28915
- return { raw: raw2, tag, attrs, selfClosing, end: i };
28916
- }
28917
- function parseHeadTags(html) {
28918
- const entries = [];
28919
- let i = 0;
28920
- while (i < html.length) {
28921
- const lt = html.indexOf("<", i);
28922
- if (lt === -1) break;
28923
- if (html.startsWith("<!--", lt)) {
28924
- const close = html.indexOf("-->", lt + 4);
28925
- i = close === -1 ? html.length : close + 3;
28926
- continue;
28927
- }
28928
- const entry = scanHeadTag(html, lt);
28929
- if (!entry) break;
28930
- entries.push(entry);
28931
- i = entry.end;
28932
- }
28933
- return entries;
28934
- }
28935
- function mergeHeadHtml(pageHead, layoutHead) {
28936
- const extractKey = (entry) => {
28937
- if (entry.tag === "title") return "title";
28938
- if (entry.tag === "base") {
28939
- const h = entry.attrs.get("href");
28940
- return h !== void 0 ? `base[href=${h}]` : "base";
28941
- }
28942
- if (entry.tag === "meta") {
28943
- const n = entry.attrs.get("name");
28944
- if (n !== void 0) return `meta[name=${n}]`;
28945
- const p = entry.attrs.get("property");
28946
- if (p !== void 0) return `meta[property=${p}]`;
28947
- if (entry.attrs.has("charset")) return "meta[charset]";
28948
- return null;
28949
- }
28950
- if (entry.tag === "link") {
28951
- const h = entry.attrs.get("href");
28952
- if (h !== void 0) return `link[href=${h}]`;
28953
- return null;
28954
- }
28955
- if (entry.tag === "script") {
28956
- const s = entry.attrs.get("src");
28957
- if (s !== void 0) return `script[src=${s}]`;
28958
- return null;
28959
- }
28960
- return null;
28961
- };
28962
- const layoutEntries = parseHeadTags(layoutHead);
28963
- const pageEntries = parseHeadTags(pageHead);
28964
- const merged = /* @__PURE__ */ new Map();
28965
- for (const tag of layoutEntries) {
28966
- const key = extractKey(tag);
28967
- if (key) merged.set(key, { html: tag.raw, source: "layout" });
28968
- }
28969
- const conflicts = [];
28970
- for (const tag of pageEntries) {
28971
- const key = extractKey(tag);
28972
- if (key) {
28973
- if (merged.has(key) && merged.get(key).source === "page") {
28974
- conflicts.push({ key, message: `Sibling conflict for <head> key "${key}":
28975
- ${merged.get(key).html}
28976
- ${tag.raw}` });
28977
- }
28978
- merged.set(key, { html: tag.raw, source: "page" });
28979
- }
28980
- }
28981
- const order = ["title", "base", "meta", "link", "script", "style"];
28982
- const sorted = [...merged.values()].sort((a, b) => {
28983
- const ak = [...merged.entries()].find((e) => e[1] === a)?.[0] || "";
28984
- const bk = [...merged.entries()].find((e) => e[1] === b)?.[0] || "";
28985
- const ai = order.findIndex((o) => ak.startsWith(o));
28986
- const bi = order.findIndex((o) => bk.startsWith(o));
28987
- return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
28988
- });
28989
- const unkeyed = [];
28990
- for (const e of [...layoutEntries, ...pageEntries]) {
28991
- if (extractKey(e) === null && !unkeyed.includes(e.raw)) unkeyed.push(e.raw);
28992
- }
28993
- return {
28994
- html: [...sorted.map((e) => e.html), ...unkeyed].join("\n"),
28995
- conflicts
28996
- };
28997
- }
28998
- var HEAD_RECONCILE_MARKER, HEAD_RECONCILE_TAGS;
28999
- var init_server_head = __esm({
29000
- "../compiler/src/server-head.ts"() {
29001
- "use strict";
29002
- init_ir();
29003
- init_server_utils();
29004
- init_scan();
29005
- HEAD_RECONCILE_MARKER = "data-vesk-head";
29006
- HEAD_RECONCILE_TAGS = /* @__PURE__ */ new Set(["title", "meta", "link", "base", "style"]);
29007
- }
29008
- });
29009
-
29010
28768
  // ../compiler/src/actions.ts
29011
28769
  import { walk as walk3 } from "zimmerframe";
29012
28770
  import { print as print4 } from "esrap";
@@ -31322,6 +31080,409 @@ var init_client_codegen = __esm({
31322
31080
  }
31323
31081
  });
31324
31082
 
31083
+ // ../compiler/src/server-head.ts
31084
+ import { walk as walk5 } from "zimmerframe";
31085
+ function isHtmlNameChar(ch) {
31086
+ const code = ch.charCodeAt(0);
31087
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || ch === "-";
31088
+ }
31089
+ function isAttrBoundaryChar(ch) {
31090
+ return isWhitespaceChar(ch) || ch === "=" || ch === "/" || ch === ">";
31091
+ }
31092
+ function isValueBoundaryChar(ch) {
31093
+ return isWhitespaceChar(ch) || ch === "/" || ch === ">";
31094
+ }
31095
+ function headCell(value) {
31096
+ const cell = {
31097
+ __vskHeadValue: value,
31098
+ toString() {
31099
+ return String(cell.__vskHeadValue);
31100
+ },
31101
+ // Present so `+count` / `String(count)` on the cell itself still yields the
31102
+ // value; the return type is widened because `valueOf` must return `this`.
31103
+ valueOf() {
31104
+ return cell;
31105
+ }
31106
+ };
31107
+ return cell;
31108
+ }
31109
+ function headEvalScope(ctx2) {
31110
+ return { ...ctx2.scope, ...ctx2.locals, ...headRuntimeShims() };
31111
+ }
31112
+ function evalHeadExpression(expression, ctx2) {
31113
+ const code = transformTracked(expression, ctx2.tracked);
31114
+ return tryEvalExpr(code, ctx2.props, headEvalScope(ctx2));
31115
+ }
31116
+ function evalWithScope(raw2, props, scope2) {
31117
+ const names = Object.keys(scope2);
31118
+ const fn = new Function("props", ...names, "return (" + raw2 + ")");
31119
+ return fn(props, ...names.map((n) => scope2[n]));
31120
+ }
31121
+ function identifiersOf(ast, into) {
31122
+ if (!ast || typeof ast !== "object") return;
31123
+ walk5(ast, null, {
31124
+ Identifier(n, context) {
31125
+ const parent = context.path.at(-1);
31126
+ if (parent) {
31127
+ if (parent.type === "MemberExpression" && !parent.computed && parent.property === n) return context.next();
31128
+ if (parent.type === "Property" && parent.key === n) return context.next();
31129
+ }
31130
+ into.add(n.name);
31131
+ return context.next();
31132
+ }
31133
+ });
31134
+ }
31135
+ function collectHeadExprs(node, out) {
31136
+ if (node instanceof StaticNode) {
31137
+ for (const child of node.children) {
31138
+ if (child instanceof DynamicBinding) out.push(child.expression);
31139
+ else collectHeadExprs(child, out);
31140
+ }
31141
+ }
31142
+ }
31143
+ function declaredNames(comp) {
31144
+ const out = /* @__PURE__ */ new Map();
31145
+ for (const node of comp.body) {
31146
+ if (node instanceof TrackDecl) {
31147
+ const cellName = node.rawName || node.name;
31148
+ let initAst = null;
31149
+ try {
31150
+ initAst = parse4(node.init);
31151
+ } catch {
31152
+ }
31153
+ const entry = { kind: "track", initSrc: node.init, initAst, names: [cellName] };
31154
+ out.set(cellName, entry);
31155
+ if (node.name !== cellName) {
31156
+ out.set(node.name, entry);
31157
+ entry.names.push(node.name);
31158
+ }
31159
+ } else if (node instanceof RuntimeStatement && node.ast) {
31160
+ const stmt = node.ast;
31161
+ if (stmt.type !== "VariableDeclaration") continue;
31162
+ for (const decl of stmt.declarations) {
31163
+ if (decl.id.type !== "Identifier" || !decl.init || !node.source) continue;
31164
+ out.set(decl.id.name, {
31165
+ kind: "const",
31166
+ initSrc: node.source.slice(decl.init.start, decl.init.end),
31167
+ initAst: decl.init,
31168
+ names: [decl.id.name]
31169
+ });
31170
+ }
31171
+ }
31172
+ }
31173
+ return out;
31174
+ }
31175
+ function headNeededNames(comp) {
31176
+ const wanted = /* @__PURE__ */ new Set();
31177
+ for (const node of comp.body) {
31178
+ if (!(node instanceof HeadBlock)) continue;
31179
+ const exprs = [];
31180
+ for (const child of node.children) collectHeadExprs(child, exprs);
31181
+ for (const e of exprs) identifiersOf(e.ast, wanted);
31182
+ }
31183
+ const declared = declaredNames(comp);
31184
+ const needed = /* @__PURE__ */ new Set();
31185
+ const queue = [...wanted].filter((n) => declared.has(n));
31186
+ while (queue.length > 0) {
31187
+ const name = queue.shift();
31188
+ if (needed.has(name)) continue;
31189
+ needed.add(name);
31190
+ const entry = declared.get(name);
31191
+ if (!entry) continue;
31192
+ const deps = /* @__PURE__ */ new Set();
31193
+ identifiersOf(entry.initAst, deps);
31194
+ for (const d of deps) {
31195
+ if (declared.has(d) && !needed.has(d)) queue.push(d);
31196
+ }
31197
+ }
31198
+ return needed;
31199
+ }
31200
+ function evaluateLocals(comp, props, scope2 = {}, tracked2 = /* @__PURE__ */ new Map(), needed = null) {
31201
+ const locals2 = {};
31202
+ const wanted = (name) => needed === null || needed.has(name);
31203
+ for (const node of comp.body) {
31204
+ if (node instanceof TrackDecl) {
31205
+ const cellName = node.rawName || node.name;
31206
+ if (!wanted(cellName) && !wanted(node.name)) continue;
31207
+ const init = transformTrackedInit(node.init, tracked2);
31208
+ let value;
31209
+ try {
31210
+ value = evalWithScope(init, props, { ...scope2, ...locals2, ...headRuntimeShims() });
31211
+ } catch {
31212
+ value = void 0;
31213
+ }
31214
+ const cell = headCell(value);
31215
+ if (node.name !== cellName) locals2[node.name] = cell;
31216
+ locals2[cellName] = cell;
31217
+ continue;
31218
+ }
31219
+ if (node instanceof RuntimeStatement && node.ast) {
31220
+ const stmt = node.ast;
31221
+ if (stmt.type === "VariableDeclaration") {
31222
+ for (const decl of stmt.declarations) {
31223
+ if (decl.id.type === "Identifier" && decl.init && node.source) {
31224
+ const name = decl.id.name;
31225
+ if (!wanted(name)) continue;
31226
+ const initSrc = node.source.slice(decl.init.start, decl.init.end);
31227
+ try {
31228
+ locals2[name] = evalWithScope(initSrc, props, {
31229
+ ...scope2,
31230
+ ...locals2,
31231
+ ...headRuntimeShims()
31232
+ });
31233
+ } catch {
31234
+ }
31235
+ }
31236
+ }
31237
+ }
31238
+ }
31239
+ }
31240
+ return locals2;
31241
+ }
31242
+ function headElementKey(node, ctx2) {
31243
+ if (!(node instanceof StaticNode)) return null;
31244
+ const tag = node.tag;
31245
+ if (tag === "title") return "title";
31246
+ if (tag === "base") return "base";
31247
+ const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
31248
+ for (const child of node.children) {
31249
+ if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
31250
+ try {
31251
+ attrMap.set(child.target, String(evalHeadExpression(child.expression, ctx2)));
31252
+ } catch {
31253
+ }
31254
+ }
31255
+ }
31256
+ if (tag === "meta") {
31257
+ if (attrMap.has("name")) return `meta[name=${attrMap.get("name")}]`;
31258
+ if (attrMap.has("property")) return `meta[property=${attrMap.get("property")}]`;
31259
+ if (attrMap.has("charset")) return "meta[charset]";
31260
+ if (attrMap.has("http-equiv")) return `meta[http-equiv=${attrMap.get("http-equiv")}]`;
31261
+ return null;
31262
+ }
31263
+ if (tag === "link") {
31264
+ if (attrMap.has("href")) return `link[href=${attrMap.get("href")}]`;
31265
+ if (attrMap.has("id")) return `link[id=${attrMap.get("id")}]`;
31266
+ return null;
31267
+ }
31268
+ if (tag === "script") {
31269
+ if (attrMap.has("src")) return `script[src=${attrMap.get("src")}]`;
31270
+ return null;
31271
+ }
31272
+ if (tag === "style") return null;
31273
+ return null;
31274
+ }
31275
+ function headIsReconcilable(tag, attrMap) {
31276
+ if (!HEAD_RECONCILE_TAGS.has(tag)) return false;
31277
+ if (tag === "meta" && attrMap.has("charset")) return false;
31278
+ return true;
31279
+ }
31280
+ function irNodeToHeadHtml(node, ctx2, reconcileable = false) {
31281
+ if (node instanceof StaticNode) {
31282
+ const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
31283
+ for (const child of node.children) {
31284
+ if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
31285
+ try {
31286
+ attrMap.set(child.target, String(evalHeadExpression(child.expression, ctx2)));
31287
+ } catch {
31288
+ }
31289
+ }
31290
+ }
31291
+ const marker = reconcileable && headIsReconcilable(node.tag, attrMap) ? ` ${HEAD_RECONCILE_MARKER}` : "";
31292
+ const attrs = [...attrMap.entries()].map(([k, v]) => ` ${k}="${escapeHtml(v)}"`).join("");
31293
+ if (node.selfClosing) return `<${node.tag}${attrs}${marker} />`;
31294
+ const inner = node.children.filter((c) => !(c instanceof DynamicBinding && c.kind === "attribute" && c.target !== "ref")).map((c) => irNodeToHeadHtml(c, ctx2, false)).join("");
31295
+ return `<${node.tag}${attrs}${marker}>${inner}</${node.tag}>`;
31296
+ }
31297
+ if (node instanceof TextNode) return node.value;
31298
+ if (node instanceof DynamicBinding) {
31299
+ try {
31300
+ return escapeHtml(String(evalHeadExpression(node.expression, ctx2)));
31301
+ } catch {
31302
+ return "";
31303
+ }
31304
+ }
31305
+ return "";
31306
+ }
31307
+ function renderHeadHtml(comp, props = {}, scope2 = {}) {
31308
+ const tracked2 = collectTrackedNames(comp.body);
31309
+ const needed = headNeededNames(comp);
31310
+ const locals2 = evaluateLocals(comp, props, scope2, tracked2, needed);
31311
+ const ctx2 = { props, locals: locals2, tracked: tracked2, scope: scope2 };
31312
+ const seen = /* @__PURE__ */ new Set();
31313
+ const parts = [];
31314
+ for (const node of comp.body) {
31315
+ if (node instanceof HeadBlock) {
31316
+ for (const child of node.children) {
31317
+ const key = headElementKey(child, ctx2);
31318
+ if (key !== null && seen.has(key)) continue;
31319
+ if (key !== null) seen.add(key);
31320
+ parts.push(irNodeToHeadHtml(child, ctx2, true));
31321
+ }
31322
+ }
31323
+ }
31324
+ return parts.join("\n");
31325
+ }
31326
+ function scanHeadTag(html, lt) {
31327
+ let i = lt + 1;
31328
+ if (html[i] === "/") i++;
31329
+ const nameStart = i;
31330
+ while (i < html.length && isHtmlNameChar(html[i])) i++;
31331
+ const tag = html.slice(nameStart, i).toLowerCase();
31332
+ if (!tag) return null;
31333
+ const attrs = /* @__PURE__ */ new Map();
31334
+ let selfClosing = false;
31335
+ while (i < html.length) {
31336
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31337
+ if (html[i] === ">") {
31338
+ i++;
31339
+ break;
31340
+ }
31341
+ if (html[i] === "/" && html[i + 1] === ">") {
31342
+ selfClosing = true;
31343
+ i += 2;
31344
+ break;
31345
+ }
31346
+ if (i >= html.length || html[i] === ">" || html[i] === "/") continue;
31347
+ const aStart = i;
31348
+ while (i < html.length && !isAttrBoundaryChar(html[i])) i++;
31349
+ const aName = html.slice(aStart, i).toLowerCase();
31350
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31351
+ let value = "";
31352
+ if (html[i] === "=") {
31353
+ i++;
31354
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31355
+ const q = html[i];
31356
+ if (q === '"' || q === "'") {
31357
+ i++;
31358
+ const vStart = i;
31359
+ while (i < html.length && html[i] !== q) i++;
31360
+ value = html.slice(vStart, i);
31361
+ if (i < html.length) i++;
31362
+ } else {
31363
+ const vStart = i;
31364
+ while (i < html.length && !isValueBoundaryChar(html[i])) i++;
31365
+ value = html.slice(vStart, i);
31366
+ }
31367
+ }
31368
+ if (aName) attrs.set(aName, value);
31369
+ }
31370
+ let raw2 = html.slice(lt, i);
31371
+ const nonVoidTags = /* @__PURE__ */ new Set(["title", "script", "style", "noscript"]);
31372
+ if (!selfClosing && nonVoidTags.has(tag)) {
31373
+ const closeTag = html.indexOf("</" + tag, i);
31374
+ if (closeTag !== -1) {
31375
+ const end = html.indexOf(">", closeTag);
31376
+ if (end !== -1) {
31377
+ raw2 = html.slice(lt, end + 1);
31378
+ i = end + 1;
31379
+ }
31380
+ }
31381
+ }
31382
+ return { raw: raw2, tag, attrs, selfClosing, end: i };
31383
+ }
31384
+ function parseHeadTags(html) {
31385
+ const entries = [];
31386
+ let i = 0;
31387
+ while (i < html.length) {
31388
+ const lt = html.indexOf("<", i);
31389
+ if (lt === -1) break;
31390
+ if (html.startsWith("<!--", lt)) {
31391
+ const close = html.indexOf("-->", lt + 4);
31392
+ i = close === -1 ? html.length : close + 3;
31393
+ continue;
31394
+ }
31395
+ const entry = scanHeadTag(html, lt);
31396
+ if (!entry) break;
31397
+ entries.push(entry);
31398
+ i = entry.end;
31399
+ }
31400
+ return entries;
31401
+ }
31402
+ function mergeHeadHtml(pageHead, layoutHead) {
31403
+ const extractKey = (entry) => {
31404
+ if (entry.tag === "title") return "title";
31405
+ if (entry.tag === "base") {
31406
+ const h = entry.attrs.get("href");
31407
+ return h !== void 0 ? `base[href=${h}]` : "base";
31408
+ }
31409
+ if (entry.tag === "meta") {
31410
+ const n = entry.attrs.get("name");
31411
+ if (n !== void 0) return `meta[name=${n}]`;
31412
+ const p = entry.attrs.get("property");
31413
+ if (p !== void 0) return `meta[property=${p}]`;
31414
+ if (entry.attrs.has("charset")) return "meta[charset]";
31415
+ return null;
31416
+ }
31417
+ if (entry.tag === "link") {
31418
+ const h = entry.attrs.get("href");
31419
+ if (h !== void 0) return `link[href=${h}]`;
31420
+ return null;
31421
+ }
31422
+ if (entry.tag === "script") {
31423
+ const s = entry.attrs.get("src");
31424
+ if (s !== void 0) return `script[src=${s}]`;
31425
+ return null;
31426
+ }
31427
+ return null;
31428
+ };
31429
+ const layoutEntries = parseHeadTags(layoutHead);
31430
+ const pageEntries = parseHeadTags(pageHead);
31431
+ const merged = /* @__PURE__ */ new Map();
31432
+ for (const tag of layoutEntries) {
31433
+ const key = extractKey(tag);
31434
+ if (key) merged.set(key, { html: tag.raw, source: "layout" });
31435
+ }
31436
+ const conflicts = [];
31437
+ for (const tag of pageEntries) {
31438
+ const key = extractKey(tag);
31439
+ if (key) {
31440
+ if (merged.has(key) && merged.get(key).source === "page") {
31441
+ conflicts.push({ key, message: `Sibling conflict for <head> key "${key}":
31442
+ ${merged.get(key).html}
31443
+ ${tag.raw}` });
31444
+ }
31445
+ merged.set(key, { html: tag.raw, source: "page" });
31446
+ }
31447
+ }
31448
+ const order = ["title", "base", "meta", "link", "script", "style"];
31449
+ const sorted = [...merged.values()].sort((a, b) => {
31450
+ const ak = [...merged.entries()].find((e) => e[1] === a)?.[0] || "";
31451
+ const bk = [...merged.entries()].find((e) => e[1] === b)?.[0] || "";
31452
+ const ai = order.findIndex((o) => ak.startsWith(o));
31453
+ const bi = order.findIndex((o) => bk.startsWith(o));
31454
+ return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
31455
+ });
31456
+ const unkeyed = [];
31457
+ for (const e of [...layoutEntries, ...pageEntries]) {
31458
+ if (extractKey(e) === null && !unkeyed.includes(e.raw)) unkeyed.push(e.raw);
31459
+ }
31460
+ return {
31461
+ html: [...sorted.map((e) => e.html), ...unkeyed].join("\n"),
31462
+ conflicts
31463
+ };
31464
+ }
31465
+ var headRuntimeShims, HEAD_RECONCILE_MARKER, HEAD_RECONCILE_TAGS;
31466
+ var init_server_head = __esm({
31467
+ "../compiler/src/server-head.ts"() {
31468
+ "use strict";
31469
+ init_ir();
31470
+ init_server_utils();
31471
+ init_scan();
31472
+ init_parser();
31473
+ init_client_codegen();
31474
+ headRuntimeShims = () => ({
31475
+ track: (init) => headCell(init),
31476
+ derived: (fn) => headCell(typeof fn === "function" ? fn() : fn),
31477
+ get: (cell) => cell && typeof cell === "object" && "__vskHeadValue" in cell ? cell.__vskHeadValue : cell,
31478
+ peek: (cell) => cell && typeof cell === "object" && "__vskHeadValue" in cell ? cell.__vskHeadValue : cell,
31479
+ untrack: (fn) => typeof fn === "function" ? fn() : fn
31480
+ });
31481
+ HEAD_RECONCILE_MARKER = "data-vesk-head";
31482
+ HEAD_RECONCILE_TAGS = /* @__PURE__ */ new Set(["title", "meta", "link", "base", "style"]);
31483
+ }
31484
+ });
31485
+
31325
31486
  // ../compiler/src/server-jsgen.ts
31326
31487
  function sanitizeMarkerName(name) {
31327
31488
  return String(name).split("--").join("-").split("<").join("").split(">").join("");
@@ -32097,7 +32258,9 @@ function renderPage(source, componentName, props = {}, registry = /* @__PURE__ *
32097
32258
  }
32098
32259
  return {
32099
32260
  body: bodyHtml2,
32100
- head: renderHeadHtml(targetComp, ssrProps),
32261
+ // The component's own scope, so head expressions that read an import
32262
+ // resolve (see renderHeadHtml).
32263
+ head: renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk)),
32101
32264
  props: ssrProps
32102
32265
  };
32103
32266
  })();
@@ -32108,7 +32271,7 @@ function renderPage(source, componentName, props = {}, registry = /* @__PURE__ *
32108
32271
  } finally {
32109
32272
  delete globalThis.__vsk_ssr;
32110
32273
  }
32111
- const headHtml = targetComp ? renderHeadHtml(targetComp, ssrProps) : "";
32274
+ const headHtml = targetComp ? renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk)) : "";
32112
32275
  const pending = globalThis[`__vsk_ssr_promises_${renderToken}`];
32113
32276
  if (pending && pending.length > 0) {
32114
32277
  return (async () => {
@@ -32423,7 +32586,7 @@ function renderPageStream(source, componentName, props = {}, registry = /* @__PU
32423
32586
  }
32424
32587
  let streamHeadHtml = null;
32425
32588
  if (targetComp) {
32426
- let headHtml = renderHeadHtml(targetComp, ssrProps);
32589
+ let headHtml = renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk));
32427
32590
  if (options.pageHead) {
32428
32591
  const merged = mergeHeadHtml(options.pageHead, headHtml);
32429
32592
  headHtml = merged.html;
@@ -33538,7 +33701,7 @@ async function generateSsgRoutes(routeTree, appDir, outDir, plugins, headExtra,
33538
33701
  return null;
33539
33702
  }
33540
33703
  }
33541
- async function walk7(nodes) {
33704
+ async function walk8(nodes) {
33542
33705
  for (const node of nodes) {
33543
33706
  if (node.page) {
33544
33707
  const pagePath = resolve15(appDir, node.sourceDir, "page.vsk");
@@ -33581,10 +33744,10 @@ async function generateSsgRoutes(routeTree, appDir, outDir, plugins, headExtra,
33581
33744
  }
33582
33745
  }
33583
33746
  }
33584
- await walk7(node.children || []);
33747
+ await walk8(node.children || []);
33585
33748
  }
33586
33749
  }
33587
- await walk7(routeTree);
33750
+ await walk8(routeTree);
33588
33751
  return results;
33589
33752
  }
33590
33753
  function generateSitemap(_routeTree, ssrRoutes, prerenderedRoutes, { siteUrl = "http://localhost:3000" } = {}) {
@@ -33600,15 +33763,15 @@ function generateSitemap(_routeTree, ssrRoutes, prerenderedRoutes, { siteUrl = "
33600
33763
  for (const r of prerenderedRoutes) {
33601
33764
  addUrl(r.path, "0.80", "weekly");
33602
33765
  }
33603
- function walk7(nodes) {
33766
+ function walk8(nodes) {
33604
33767
  for (const node of nodes) {
33605
33768
  if (node.page && !node.fullPath.includes(":")) {
33606
33769
  addUrl(node.fullPath, "0.64", "daily");
33607
33770
  }
33608
- walk7(node.children || []);
33771
+ walk8(node.children || []);
33609
33772
  }
33610
33773
  }
33611
- walk7(ssrRoutes);
33774
+ walk8(ssrRoutes);
33612
33775
  let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
33613
33776
  xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
33614
33777
  for (const u of urls) {
@@ -33735,7 +33898,7 @@ async function processImage(srcPath, outDir, baseName) {
33735
33898
  }
33736
33899
  function collectImageRefs(appDir) {
33737
33900
  const refs = [];
33738
- function walk7(dir) {
33901
+ function walk8(dir) {
33739
33902
  let entries;
33740
33903
  try {
33741
33904
  entries = readdirSync4(dir);
@@ -33748,7 +33911,7 @@ function collectImageRefs(appDir) {
33748
33911
  if (st.isDirectory()) {
33749
33912
  if (entry.startsWith("."))
33750
33913
  continue;
33751
- walk7(full);
33914
+ walk8(full);
33752
33915
  } else if (entry === "page.vsk") {
33753
33916
  const src2 = readFileSync18(full, "utf-8");
33754
33917
  const imgRegex = /<Image\s+src=["']([^"']+)["']/g;
@@ -33759,7 +33922,7 @@ function collectImageRefs(appDir) {
33759
33922
  }
33760
33923
  }
33761
33924
  }
33762
- walk7(appDir);
33925
+ walk8(appDir);
33763
33926
  return refs;
33764
33927
  }
33765
33928
  async function optimizeImages(appDir, outDir) {
@@ -34391,18 +34554,18 @@ function writePrerenderedStatic(prerenderedRoutes, platformStaticDir) {
34391
34554
  function listStaticDir(dir) {
34392
34555
  const out = [];
34393
34556
  if (!existsSync21(dir)) return out;
34394
- function walk7(d, prefix) {
34557
+ function walk8(d, prefix) {
34395
34558
  for (const entry of readdirSync6(d)) {
34396
34559
  const full = join14(d, entry);
34397
34560
  const rel = prefix ? `${prefix}/${entry}` : entry;
34398
34561
  if (statSync11(full).isDirectory()) {
34399
- walk7(full, rel);
34562
+ walk8(full, rel);
34400
34563
  } else {
34401
34564
  out.push({ rel, buffer: readFileSync20(full) });
34402
34565
  }
34403
34566
  }
34404
34567
  }
34405
- walk7(dir, "");
34568
+ walk8(dir, "");
34406
34569
  return out;
34407
34570
  }
34408
34571
  function mimeFor(path) {
@@ -39069,7 +39232,7 @@ import * as ts8 from "typescript";
39069
39232
  function walkProjectFiles(projectRoot) {
39070
39233
  const code = [];
39071
39234
  const js = [];
39072
- const walk7 = (dir) => {
39235
+ const walk8 = (dir) => {
39073
39236
  let entries = [];
39074
39237
  try {
39075
39238
  entries = readdirSync14(dir);
@@ -39087,7 +39250,7 @@ function walkProjectFiles(projectRoot) {
39087
39250
  if (st.isDirectory()) {
39088
39251
  if (SKIP_DIRS.has(e))
39089
39252
  continue;
39090
- walk7(p);
39253
+ walk8(p);
39091
39254
  } else if (e.endsWith(".vsk")) {
39092
39255
  code.push(p);
39093
39256
  } else if (e.endsWith(".ts") || e.endsWith(".tsx")) {
@@ -39101,7 +39264,7 @@ function walkProjectFiles(projectRoot) {
39101
39264
  }
39102
39265
  }
39103
39266
  };
39104
- walk7(projectRoot);
39267
+ walk8(projectRoot);
39105
39268
  return { code, js };
39106
39269
  }
39107
39270
  function isUnder(dir, file) {
@@ -40906,13 +41069,13 @@ function hydrateInvoke(planExpr) {
40906
41069
  function buildParamExtraction(node, urlParts) {
40907
41070
  const parts = [];
40908
41071
  let partIdx = Math.max(0, urlParts.length - 1);
40909
- function walk7(n) {
41072
+ function walk8(n) {
40910
41073
  if (n.fullPath === "/") {
40911
- for (const child of n.children || []) walk7(child);
41074
+ for (const child of n.children || []) walk8(child);
40912
41075
  return;
40913
41076
  }
40914
41077
  if (n.isGroup) {
40915
- for (const child of n.children || []) walk7(child);
41078
+ for (const child of n.children || []) walk8(child);
40916
41079
  return;
40917
41080
  }
40918
41081
  if (partIdx >= urlParts.length) return;
@@ -40926,15 +41089,15 @@ function buildParamExtraction(node, urlParts) {
40926
41089
  const paramName = n.path.startsWith(":") ? n.path.slice(1) : "param";
40927
41090
  parts.push(`${JSON.stringify(paramName)}: urlParts[${partIdx}]`);
40928
41091
  partIdx++;
40929
- for (const child of n.children || []) walk7(child);
41092
+ for (const child of n.children || []) walk8(child);
40930
41093
  return;
40931
41094
  }
40932
41095
  if (n.path === urlParts[partIdx]) {
40933
41096
  partIdx++;
40934
- for (const child of n.children || []) walk7(child);
41097
+ for (const child of n.children || []) walk8(child);
40935
41098
  }
40936
41099
  }
40937
- walk7(node);
41100
+ walk8(node);
40938
41101
  return parts;
40939
41102
  }
40940
41103
  function generateSsrFunction(routeNode, appDir, outDir, componentMap, options) {
@@ -43629,7 +43792,7 @@ async function build2(appDir, options) {
43629
43792
  await bundleRuntime(appDir, outDir);
43630
43793
  const ssrRoutes = [];
43631
43794
  const actionMap = {};
43632
- function walk7(nodes, ancestorLayouts = []) {
43795
+ function walk8(nodes, ancestorLayouts = []) {
43633
43796
  for (const node of nodes) {
43634
43797
  const isStandalone = node.standalone === true;
43635
43798
  let childAncestorLayouts = isStandalone ? [] : ancestorLayouts;
@@ -43673,10 +43836,10 @@ async function build2(appDir, options) {
43673
43836
  ssrRoutes.push(node);
43674
43837
  console.error(`vesk build: ssr \u2192 server/functions/${name}.js (${node.fullPath})${mwCode ? " [mw]" : ""}`);
43675
43838
  }
43676
- walk7(node.children || [], childAncestorLayouts);
43839
+ walk8(node.children || [], childAncestorLayouts);
43677
43840
  }
43678
43841
  }
43679
- walk7(routeTree);
43842
+ walk8(routeTree);
43680
43843
  markPhase("server runtime + ssr functions");
43681
43844
  const apiRoutes = [];
43682
43845
  function walkApi(nodes) {
@@ -43823,7 +43986,7 @@ import { WebSocketServer as WebSocketServer2 } from "ws";
43823
43986
 
43824
43987
  // ../compiler/dist/strip-ts.js
43825
43988
  init_parser();
43826
- import { walk as walk5 } from "zimmerframe";
43989
+ import { walk as walk6 } from "zimmerframe";
43827
43990
  import { print as print6 } from "esrap";
43828
43991
  import ts6 from "esrap/languages/ts";
43829
43992
  var TS_NODE_TYPES2 = /* @__PURE__ */ new Set([
@@ -43865,7 +44028,7 @@ function isTypeOnlySpecifier2(node) {
43865
44028
  }
43866
44029
  function hasTsSyntax2(ast) {
43867
44030
  let found = false;
43868
- walk5(ast, null, {
44031
+ walk6(ast, null, {
43869
44032
  _(node, context) {
43870
44033
  if (TS_NODE_TYPES2.has(node.type)) {
43871
44034
  found = true;
@@ -43903,7 +44066,7 @@ function isTypeOnlyStatement2(node) {
43903
44066
  return TYPE_ONLY_STATEMENTS2.has(node.type);
43904
44067
  }
43905
44068
  function stripTsTypes2(ast) {
43906
- return walk5(ast, null, {
44069
+ return walk6(ast, null, {
43907
44070
  TSAsExpression(node, context) {
43908
44071
  return context.visit(node.expression);
43909
44072
  },
@@ -44159,7 +44322,7 @@ init_tokens();
44159
44322
  init_vsk_imports();
44160
44323
  init_md_inline();
44161
44324
  init_strip_ts();
44162
- import { walk as walk6 } from "zimmerframe";
44325
+ import { walk as walk7 } from "zimmerframe";
44163
44326
  import { print as print7 } from "esrap";
44164
44327
  import ts7 from "esrap/languages/ts";
44165
44328
  import tsx2 from "esrap/languages/tsx";
@@ -44275,7 +44438,7 @@ function transformTracked2(irNode, tracked2) {
44275
44438
  return printAst2(stripTsTypes(ast));
44276
44439
  }
44277
44440
  const stripped = stripTsTypes(ast);
44278
- const transformed = walk6(stripped, tracked2, {
44441
+ const transformed = walk7(stripped, tracked2, {
44279
44442
  AssignmentExpression(node, context) {
44280
44443
  if (node.left.type === "Identifier") {
44281
44444
  const info = context.state.get(node.left.name);
@@ -44388,7 +44551,7 @@ function collectTrackedDeps2(value, tracked2) {
44388
44551
  return [];
44389
44552
  const found = [];
44390
44553
  const seen = /* @__PURE__ */ new Set();
44391
- walk6(ast, tracked2, {
44554
+ walk7(ast, tracked2, {
44392
44555
  Identifier(node, context) {
44393
44556
  const parent = context.path.at(-1);
44394
44557
  if (parent) {
@@ -44940,7 +45103,7 @@ function isReactiveExpression2(node, tracked2) {
44940
45103
  if (!ast)
44941
45104
  return false;
44942
45105
  let reactive = false;
44943
- walk6(ast, tracked2, {
45106
+ walk7(ast, tracked2, {
44944
45107
  Identifier(n, context) {
44945
45108
  if (reactive)
44946
45109
  return;
@@ -45630,7 +45793,7 @@ function emitForLoop2(ctx2, node, tracked2, parentVar, skipK = 0, regionBudget)
45630
45793
  const seen = /* @__PURE__ */ new Set();
45631
45794
  const condAst = node.condition?.ast;
45632
45795
  if (condAst) {
45633
- walk6(condAst, tracked2, {
45796
+ walk7(condAst, tracked2, {
45634
45797
  Identifier(n, context) {
45635
45798
  const parent2 = context.path.at(-1);
45636
45799
  if (parent2) {
@@ -46308,7 +46471,7 @@ function astHasBinding2(ast, names) {
46308
46471
  if (!ast)
46309
46472
  return false;
46310
46473
  let found = false;
46311
- walk6(ast, null, {
46474
+ walk7(ast, null, {
46312
46475
  Identifier(node, context) {
46313
46476
  if (names.has(node.name))
46314
46477
  found = true;
@@ -46562,7 +46725,7 @@ function scanComponents(componentsDir) {
46562
46725
  const map = /* @__PURE__ */ new Map();
46563
46726
  if (!existsSync23(componentsDir))
46564
46727
  return map;
46565
- function walk7(dir, prefix) {
46728
+ function walk8(dir, prefix) {
46566
46729
  let entries;
46567
46730
  try {
46568
46731
  entries = readdirSync7(dir);
@@ -46579,7 +46742,7 @@ function scanComponents(componentsDir) {
46579
46742
  }
46580
46743
  if (stat.isDirectory()) {
46581
46744
  if (!entry.startsWith("_")) {
46582
- walk7(full, prefix ? prefix + capitalize(entry) : capitalize(entry));
46745
+ walk8(full, prefix ? prefix + capitalize(entry) : capitalize(entry));
46583
46746
  }
46584
46747
  } else if (entry.endsWith(".vsk")) {
46585
46748
  const name = prefix ? prefix + capitalize(entry.slice(0, -4)) : entry.slice(0, -4);
@@ -46589,7 +46752,7 @@ function scanComponents(componentsDir) {
46589
46752
  }
46590
46753
  }
46591
46754
  }
46592
- walk7(componentsDir, "");
46755
+ walk8(componentsDir, "");
46593
46756
  return map;
46594
46757
  }
46595
46758
  function scanDirectory(rootDir, dir, parentPath, options) {
@@ -46741,7 +46904,7 @@ function extractComponentName(dir, type, rootDir) {
46741
46904
  }
46742
46905
  function collectSources(tree) {
46743
46906
  const map = /* @__PURE__ */ new Map();
46744
- function walk7(nodes) {
46907
+ function walk8(nodes) {
46745
46908
  for (const node of nodes) {
46746
46909
  if (node.page)
46747
46910
  map.set(node.page, join15(node.sourceDir, "page.vsk"));
@@ -46757,10 +46920,10 @@ function collectSources(tree) {
46757
46920
  map.set(node.offline, join15(node.sourceDir, "offline.vsk"));
46758
46921
  if (node.network)
46759
46922
  map.set(node.network, join15(node.sourceDir, "network.vsk"));
46760
- walk7(node.children);
46923
+ walk8(node.children);
46761
46924
  }
46762
46925
  }
46763
- walk7(tree);
46926
+ walk8(tree);
46764
46927
  return map;
46765
46928
  }
46766
46929
  function matchUrl(tree, pathname) {
@@ -47255,16 +47418,16 @@ function parseCookies2(str3) {
47255
47418
  function collectMiddlewareChain(routeTree, url, appDir) {
47256
47419
  const parts = url.split("/").filter(Boolean);
47257
47420
  const chain = [];
47258
- function walk7(nodes, depth) {
47421
+ function walk8(nodes, depth) {
47259
47422
  for (const node of nodes) {
47260
47423
  if (node.isGroup) {
47261
- if (walk7(node.children, depth))
47424
+ if (walk8(node.children, depth))
47262
47425
  return true;
47263
47426
  continue;
47264
47427
  }
47265
47428
  if (node.fullPath === "/") {
47266
47429
  collectForNode(node);
47267
- return walk7(node.children, depth);
47430
+ return walk8(node.children, depth);
47268
47431
  }
47269
47432
  if (depth >= parts.length) {
47270
47433
  if (node.page) {
@@ -47302,16 +47465,16 @@ function collectMiddlewareChain(routeTree, url, appDir) {
47302
47465
  function tryCollectAndRecurse(node, depth) {
47303
47466
  collectForNode(node);
47304
47467
  if (node.children.length > 0) {
47305
- return walk7(node.children, depth + 1);
47468
+ return walk8(node.children, depth + 1);
47306
47469
  }
47307
47470
  return !!node.page;
47308
47471
  }
47309
47472
  const root3 = routeTree.find((n) => n.fullPath === "/");
47310
47473
  if (root3) {
47311
47474
  collectForNode(root3);
47312
- walk7(root3.children, 0);
47475
+ walk8(root3.children, 0);
47313
47476
  } else {
47314
- walk7(routeTree, 0);
47477
+ walk8(routeTree, 0);
47315
47478
  }
47316
47479
  return chain;
47317
47480
  }
@@ -50622,7 +50785,7 @@ function hasIdentifierAst(source, name) {
50622
50785
  if (!ast)
50623
50786
  return source.includes(name);
50624
50787
  let found = false;
50625
- function walk7(node) {
50788
+ function walk8(node) {
50626
50789
  if (!node || typeof node !== "object" || found)
50627
50790
  return;
50628
50791
  if (node.type === "Identifier" && node.name === name) {
@@ -50633,12 +50796,12 @@ function hasIdentifierAst(source, name) {
50633
50796
  const v = node[k];
50634
50797
  if (Array.isArray(v))
50635
50798
  for (const el of v)
50636
- walk7(el);
50799
+ walk8(el);
50637
50800
  else if (v && typeof v.type === "string")
50638
- walk7(v);
50801
+ walk8(v);
50639
50802
  }
50640
50803
  }
50641
- walk7(ast);
50804
+ walk8(ast);
50642
50805
  return found;
50643
50806
  }
50644
50807
  async function addPluginToConfig2(projectDir, pkg) {
@@ -54473,14 +54636,14 @@ function chainForPath(routeTree, pathname) {
54473
54636
  }
54474
54637
  function pageSourcesFor(appDirPath, routeTree) {
54475
54638
  const out = [];
54476
- function walk7(nodes) {
54639
+ function walk8(nodes) {
54477
54640
  for (const node of nodes) {
54478
54641
  if (node.page) out.push(resolve37(appDirPath, node.sourceDir, "page.vsk"));
54479
54642
  if (node.layout) out.push(resolve37(appDirPath, node.sourceDir, "layout.vsk"));
54480
- walk7(node.children);
54643
+ walk8(node.children);
54481
54644
  }
54482
54645
  }
54483
- walk7(routeTree);
54646
+ walk8(routeTree);
54484
54647
  return out;
54485
54648
  }
54486
54649
  function walkVskFiles(dir, out, seen) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/vesk-cli",
3
- "version": "0.2.47",
3
+ "version": "0.2.49",
4
4
  "type": "module",
5
5
  "description": "Vesk — compiler-first framework for the post-VDOM web. vesk dev, vesk build.",
6
6
  "bin": {
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "main": "./dist/cli.js",
10
10
  "dependencies": {
11
- "@vesk/adapter": "^0.2.47",
12
- "@vesk/compiler": "^0.2.47",
13
- "@vesk/plugin-tailwind": "^0.2.47",
14
- "@vesk/runtime": "^0.2.47",
11
+ "@vesk/adapter": "^0.2.49",
12
+ "@vesk/compiler": "^0.2.49",
13
+ "@vesk/plugin-tailwind": "^0.2.49",
14
+ "@vesk/runtime": "^0.2.49",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",