@vesk/vesk-cli 0.2.47 → 0.2.48

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 +462 -324
  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);
@@ -28740,273 +28740,6 @@ var init_esbuild_fallback = __esm({
28740
28740
  }
28741
28741
  });
28742
28742
 
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
28743
  // ../compiler/src/actions.ts
29011
28744
  import { walk as walk3 } from "zimmerframe";
29012
28745
  import { print as print4 } from "esrap";
@@ -31322,6 +31055,409 @@ var init_client_codegen = __esm({
31322
31055
  }
31323
31056
  });
31324
31057
 
31058
+ // ../compiler/src/server-head.ts
31059
+ import { walk as walk5 } from "zimmerframe";
31060
+ function isHtmlNameChar(ch) {
31061
+ const code = ch.charCodeAt(0);
31062
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || ch === "-";
31063
+ }
31064
+ function isAttrBoundaryChar(ch) {
31065
+ return isWhitespaceChar(ch) || ch === "=" || ch === "/" || ch === ">";
31066
+ }
31067
+ function isValueBoundaryChar(ch) {
31068
+ return isWhitespaceChar(ch) || ch === "/" || ch === ">";
31069
+ }
31070
+ function headCell(value) {
31071
+ const cell = {
31072
+ __vskHeadValue: value,
31073
+ toString() {
31074
+ return String(cell.__vskHeadValue);
31075
+ },
31076
+ // Present so `+count` / `String(count)` on the cell itself still yields the
31077
+ // value; the return type is widened because `valueOf` must return `this`.
31078
+ valueOf() {
31079
+ return cell;
31080
+ }
31081
+ };
31082
+ return cell;
31083
+ }
31084
+ function headEvalScope(ctx2) {
31085
+ return { ...ctx2.scope, ...ctx2.locals, ...headRuntimeShims() };
31086
+ }
31087
+ function evalHeadExpression(expression, ctx2) {
31088
+ const code = transformTracked(expression, ctx2.tracked);
31089
+ return tryEvalExpr(code, ctx2.props, headEvalScope(ctx2));
31090
+ }
31091
+ function evalWithScope(raw2, props, scope2) {
31092
+ const names = Object.keys(scope2);
31093
+ const fn = new Function("props", ...names, "return (" + raw2 + ")");
31094
+ return fn(props, ...names.map((n) => scope2[n]));
31095
+ }
31096
+ function identifiersOf(ast, into) {
31097
+ if (!ast || typeof ast !== "object") return;
31098
+ walk5(ast, null, {
31099
+ Identifier(n, context) {
31100
+ const parent = context.path.at(-1);
31101
+ if (parent) {
31102
+ if (parent.type === "MemberExpression" && !parent.computed && parent.property === n) return context.next();
31103
+ if (parent.type === "Property" && parent.key === n) return context.next();
31104
+ }
31105
+ into.add(n.name);
31106
+ return context.next();
31107
+ }
31108
+ });
31109
+ }
31110
+ function collectHeadExprs(node, out) {
31111
+ if (node instanceof StaticNode) {
31112
+ for (const child of node.children) {
31113
+ if (child instanceof DynamicBinding) out.push(child.expression);
31114
+ else collectHeadExprs(child, out);
31115
+ }
31116
+ }
31117
+ }
31118
+ function declaredNames(comp) {
31119
+ const out = /* @__PURE__ */ new Map();
31120
+ for (const node of comp.body) {
31121
+ if (node instanceof TrackDecl) {
31122
+ const cellName = node.rawName || node.name;
31123
+ let initAst = null;
31124
+ try {
31125
+ initAst = parse4(node.init);
31126
+ } catch {
31127
+ }
31128
+ const entry = { kind: "track", initSrc: node.init, initAst, names: [cellName] };
31129
+ out.set(cellName, entry);
31130
+ if (node.name !== cellName) {
31131
+ out.set(node.name, entry);
31132
+ entry.names.push(node.name);
31133
+ }
31134
+ } else if (node instanceof RuntimeStatement && node.ast) {
31135
+ const stmt = node.ast;
31136
+ if (stmt.type !== "VariableDeclaration") continue;
31137
+ for (const decl of stmt.declarations) {
31138
+ if (decl.id.type !== "Identifier" || !decl.init || !node.source) continue;
31139
+ out.set(decl.id.name, {
31140
+ kind: "const",
31141
+ initSrc: node.source.slice(decl.init.start, decl.init.end),
31142
+ initAst: decl.init,
31143
+ names: [decl.id.name]
31144
+ });
31145
+ }
31146
+ }
31147
+ }
31148
+ return out;
31149
+ }
31150
+ function headNeededNames(comp) {
31151
+ const wanted = /* @__PURE__ */ new Set();
31152
+ for (const node of comp.body) {
31153
+ if (!(node instanceof HeadBlock)) continue;
31154
+ const exprs = [];
31155
+ for (const child of node.children) collectHeadExprs(child, exprs);
31156
+ for (const e of exprs) identifiersOf(e.ast, wanted);
31157
+ }
31158
+ const declared = declaredNames(comp);
31159
+ const needed = /* @__PURE__ */ new Set();
31160
+ const queue = [...wanted].filter((n) => declared.has(n));
31161
+ while (queue.length > 0) {
31162
+ const name = queue.shift();
31163
+ if (needed.has(name)) continue;
31164
+ needed.add(name);
31165
+ const entry = declared.get(name);
31166
+ if (!entry) continue;
31167
+ const deps = /* @__PURE__ */ new Set();
31168
+ identifiersOf(entry.initAst, deps);
31169
+ for (const d of deps) {
31170
+ if (declared.has(d) && !needed.has(d)) queue.push(d);
31171
+ }
31172
+ }
31173
+ return needed;
31174
+ }
31175
+ function evaluateLocals(comp, props, scope2 = {}, tracked2 = /* @__PURE__ */ new Map(), needed = null) {
31176
+ const locals2 = {};
31177
+ const wanted = (name) => needed === null || needed.has(name);
31178
+ for (const node of comp.body) {
31179
+ if (node instanceof TrackDecl) {
31180
+ const cellName = node.rawName || node.name;
31181
+ if (!wanted(cellName) && !wanted(node.name)) continue;
31182
+ const init = transformTrackedInit(node.init, tracked2);
31183
+ let value;
31184
+ try {
31185
+ value = evalWithScope(init, props, { ...scope2, ...locals2, ...headRuntimeShims() });
31186
+ } catch {
31187
+ value = void 0;
31188
+ }
31189
+ const cell = headCell(value);
31190
+ if (node.name !== cellName) locals2[node.name] = cell;
31191
+ locals2[cellName] = cell;
31192
+ continue;
31193
+ }
31194
+ if (node instanceof RuntimeStatement && node.ast) {
31195
+ const stmt = node.ast;
31196
+ if (stmt.type === "VariableDeclaration") {
31197
+ for (const decl of stmt.declarations) {
31198
+ if (decl.id.type === "Identifier" && decl.init && node.source) {
31199
+ const name = decl.id.name;
31200
+ if (!wanted(name)) continue;
31201
+ const initSrc = node.source.slice(decl.init.start, decl.init.end);
31202
+ try {
31203
+ locals2[name] = evalWithScope(initSrc, props, {
31204
+ ...scope2,
31205
+ ...locals2,
31206
+ ...headRuntimeShims()
31207
+ });
31208
+ } catch {
31209
+ }
31210
+ }
31211
+ }
31212
+ }
31213
+ }
31214
+ }
31215
+ return locals2;
31216
+ }
31217
+ function headElementKey(node, ctx2) {
31218
+ if (!(node instanceof StaticNode)) return null;
31219
+ const tag = node.tag;
31220
+ if (tag === "title") return "title";
31221
+ if (tag === "base") return "base";
31222
+ const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
31223
+ for (const child of node.children) {
31224
+ if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
31225
+ try {
31226
+ attrMap.set(child.target, String(evalHeadExpression(child.expression, ctx2)));
31227
+ } catch {
31228
+ }
31229
+ }
31230
+ }
31231
+ if (tag === "meta") {
31232
+ if (attrMap.has("name")) return `meta[name=${attrMap.get("name")}]`;
31233
+ if (attrMap.has("property")) return `meta[property=${attrMap.get("property")}]`;
31234
+ if (attrMap.has("charset")) return "meta[charset]";
31235
+ if (attrMap.has("http-equiv")) return `meta[http-equiv=${attrMap.get("http-equiv")}]`;
31236
+ return null;
31237
+ }
31238
+ if (tag === "link") {
31239
+ if (attrMap.has("href")) return `link[href=${attrMap.get("href")}]`;
31240
+ if (attrMap.has("id")) return `link[id=${attrMap.get("id")}]`;
31241
+ return null;
31242
+ }
31243
+ if (tag === "script") {
31244
+ if (attrMap.has("src")) return `script[src=${attrMap.get("src")}]`;
31245
+ return null;
31246
+ }
31247
+ if (tag === "style") return null;
31248
+ return null;
31249
+ }
31250
+ function headIsReconcilable(tag, attrMap) {
31251
+ if (!HEAD_RECONCILE_TAGS.has(tag)) return false;
31252
+ if (tag === "meta" && attrMap.has("charset")) return false;
31253
+ return true;
31254
+ }
31255
+ function irNodeToHeadHtml(node, ctx2, reconcileable = false) {
31256
+ if (node instanceof StaticNode) {
31257
+ const attrMap = new Map(node.attributes.map((a) => [a.name, a.value]));
31258
+ for (const child of node.children) {
31259
+ if (child instanceof DynamicBinding && child.kind === "attribute" && child.target && child.target !== "ref") {
31260
+ try {
31261
+ attrMap.set(child.target, String(evalHeadExpression(child.expression, ctx2)));
31262
+ } catch {
31263
+ }
31264
+ }
31265
+ }
31266
+ const marker = reconcileable && headIsReconcilable(node.tag, attrMap) ? ` ${HEAD_RECONCILE_MARKER}` : "";
31267
+ const attrs = [...attrMap.entries()].map(([k, v]) => ` ${k}="${escapeHtml(v)}"`).join("");
31268
+ if (node.selfClosing) return `<${node.tag}${attrs}${marker} />`;
31269
+ const inner = node.children.filter((c) => !(c instanceof DynamicBinding && c.kind === "attribute" && c.target !== "ref")).map((c) => irNodeToHeadHtml(c, ctx2, false)).join("");
31270
+ return `<${node.tag}${attrs}${marker}>${inner}</${node.tag}>`;
31271
+ }
31272
+ if (node instanceof TextNode) return node.value;
31273
+ if (node instanceof DynamicBinding) {
31274
+ try {
31275
+ return escapeHtml(String(evalHeadExpression(node.expression, ctx2)));
31276
+ } catch {
31277
+ return "";
31278
+ }
31279
+ }
31280
+ return "";
31281
+ }
31282
+ function renderHeadHtml(comp, props = {}, scope2 = {}) {
31283
+ const tracked2 = collectTrackedNames(comp.body);
31284
+ const needed = headNeededNames(comp);
31285
+ const locals2 = evaluateLocals(comp, props, scope2, tracked2, needed);
31286
+ const ctx2 = { props, locals: locals2, tracked: tracked2, scope: scope2 };
31287
+ const seen = /* @__PURE__ */ new Set();
31288
+ const parts = [];
31289
+ for (const node of comp.body) {
31290
+ if (node instanceof HeadBlock) {
31291
+ for (const child of node.children) {
31292
+ const key = headElementKey(child, ctx2);
31293
+ if (key !== null && seen.has(key)) continue;
31294
+ if (key !== null) seen.add(key);
31295
+ parts.push(irNodeToHeadHtml(child, ctx2, true));
31296
+ }
31297
+ }
31298
+ }
31299
+ return parts.join("\n");
31300
+ }
31301
+ function scanHeadTag(html, lt) {
31302
+ let i = lt + 1;
31303
+ if (html[i] === "/") i++;
31304
+ const nameStart = i;
31305
+ while (i < html.length && isHtmlNameChar(html[i])) i++;
31306
+ const tag = html.slice(nameStart, i).toLowerCase();
31307
+ if (!tag) return null;
31308
+ const attrs = /* @__PURE__ */ new Map();
31309
+ let selfClosing = false;
31310
+ while (i < html.length) {
31311
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31312
+ if (html[i] === ">") {
31313
+ i++;
31314
+ break;
31315
+ }
31316
+ if (html[i] === "/" && html[i + 1] === ">") {
31317
+ selfClosing = true;
31318
+ i += 2;
31319
+ break;
31320
+ }
31321
+ if (i >= html.length || html[i] === ">" || html[i] === "/") continue;
31322
+ const aStart = i;
31323
+ while (i < html.length && !isAttrBoundaryChar(html[i])) i++;
31324
+ const aName = html.slice(aStart, i).toLowerCase();
31325
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31326
+ let value = "";
31327
+ if (html[i] === "=") {
31328
+ i++;
31329
+ while (i < html.length && isWhitespaceChar(html[i])) i++;
31330
+ const q = html[i];
31331
+ if (q === '"' || q === "'") {
31332
+ i++;
31333
+ const vStart = i;
31334
+ while (i < html.length && html[i] !== q) i++;
31335
+ value = html.slice(vStart, i);
31336
+ if (i < html.length) i++;
31337
+ } else {
31338
+ const vStart = i;
31339
+ while (i < html.length && !isValueBoundaryChar(html[i])) i++;
31340
+ value = html.slice(vStart, i);
31341
+ }
31342
+ }
31343
+ if (aName) attrs.set(aName, value);
31344
+ }
31345
+ let raw2 = html.slice(lt, i);
31346
+ const nonVoidTags = /* @__PURE__ */ new Set(["title", "script", "style", "noscript"]);
31347
+ if (!selfClosing && nonVoidTags.has(tag)) {
31348
+ const closeTag = html.indexOf("</" + tag, i);
31349
+ if (closeTag !== -1) {
31350
+ const end = html.indexOf(">", closeTag);
31351
+ if (end !== -1) {
31352
+ raw2 = html.slice(lt, end + 1);
31353
+ i = end + 1;
31354
+ }
31355
+ }
31356
+ }
31357
+ return { raw: raw2, tag, attrs, selfClosing, end: i };
31358
+ }
31359
+ function parseHeadTags(html) {
31360
+ const entries = [];
31361
+ let i = 0;
31362
+ while (i < html.length) {
31363
+ const lt = html.indexOf("<", i);
31364
+ if (lt === -1) break;
31365
+ if (html.startsWith("<!--", lt)) {
31366
+ const close = html.indexOf("-->", lt + 4);
31367
+ i = close === -1 ? html.length : close + 3;
31368
+ continue;
31369
+ }
31370
+ const entry = scanHeadTag(html, lt);
31371
+ if (!entry) break;
31372
+ entries.push(entry);
31373
+ i = entry.end;
31374
+ }
31375
+ return entries;
31376
+ }
31377
+ function mergeHeadHtml(pageHead, layoutHead) {
31378
+ const extractKey = (entry) => {
31379
+ if (entry.tag === "title") return "title";
31380
+ if (entry.tag === "base") {
31381
+ const h = entry.attrs.get("href");
31382
+ return h !== void 0 ? `base[href=${h}]` : "base";
31383
+ }
31384
+ if (entry.tag === "meta") {
31385
+ const n = entry.attrs.get("name");
31386
+ if (n !== void 0) return `meta[name=${n}]`;
31387
+ const p = entry.attrs.get("property");
31388
+ if (p !== void 0) return `meta[property=${p}]`;
31389
+ if (entry.attrs.has("charset")) return "meta[charset]";
31390
+ return null;
31391
+ }
31392
+ if (entry.tag === "link") {
31393
+ const h = entry.attrs.get("href");
31394
+ if (h !== void 0) return `link[href=${h}]`;
31395
+ return null;
31396
+ }
31397
+ if (entry.tag === "script") {
31398
+ const s = entry.attrs.get("src");
31399
+ if (s !== void 0) return `script[src=${s}]`;
31400
+ return null;
31401
+ }
31402
+ return null;
31403
+ };
31404
+ const layoutEntries = parseHeadTags(layoutHead);
31405
+ const pageEntries = parseHeadTags(pageHead);
31406
+ const merged = /* @__PURE__ */ new Map();
31407
+ for (const tag of layoutEntries) {
31408
+ const key = extractKey(tag);
31409
+ if (key) merged.set(key, { html: tag.raw, source: "layout" });
31410
+ }
31411
+ const conflicts = [];
31412
+ for (const tag of pageEntries) {
31413
+ const key = extractKey(tag);
31414
+ if (key) {
31415
+ if (merged.has(key) && merged.get(key).source === "page") {
31416
+ conflicts.push({ key, message: `Sibling conflict for <head> key "${key}":
31417
+ ${merged.get(key).html}
31418
+ ${tag.raw}` });
31419
+ }
31420
+ merged.set(key, { html: tag.raw, source: "page" });
31421
+ }
31422
+ }
31423
+ const order = ["title", "base", "meta", "link", "script", "style"];
31424
+ const sorted = [...merged.values()].sort((a, b) => {
31425
+ const ak = [...merged.entries()].find((e) => e[1] === a)?.[0] || "";
31426
+ const bk = [...merged.entries()].find((e) => e[1] === b)?.[0] || "";
31427
+ const ai = order.findIndex((o) => ak.startsWith(o));
31428
+ const bi = order.findIndex((o) => bk.startsWith(o));
31429
+ return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
31430
+ });
31431
+ const unkeyed = [];
31432
+ for (const e of [...layoutEntries, ...pageEntries]) {
31433
+ if (extractKey(e) === null && !unkeyed.includes(e.raw)) unkeyed.push(e.raw);
31434
+ }
31435
+ return {
31436
+ html: [...sorted.map((e) => e.html), ...unkeyed].join("\n"),
31437
+ conflicts
31438
+ };
31439
+ }
31440
+ var headRuntimeShims, HEAD_RECONCILE_MARKER, HEAD_RECONCILE_TAGS;
31441
+ var init_server_head = __esm({
31442
+ "../compiler/src/server-head.ts"() {
31443
+ "use strict";
31444
+ init_ir();
31445
+ init_server_utils();
31446
+ init_scan();
31447
+ init_parser();
31448
+ init_client_codegen();
31449
+ headRuntimeShims = () => ({
31450
+ track: (init) => headCell(init),
31451
+ derived: (fn) => headCell(typeof fn === "function" ? fn() : fn),
31452
+ get: (cell) => cell && typeof cell === "object" && "__vskHeadValue" in cell ? cell.__vskHeadValue : cell,
31453
+ peek: (cell) => cell && typeof cell === "object" && "__vskHeadValue" in cell ? cell.__vskHeadValue : cell,
31454
+ untrack: (fn) => typeof fn === "function" ? fn() : fn
31455
+ });
31456
+ HEAD_RECONCILE_MARKER = "data-vesk-head";
31457
+ HEAD_RECONCILE_TAGS = /* @__PURE__ */ new Set(["title", "meta", "link", "base", "style"]);
31458
+ }
31459
+ });
31460
+
31325
31461
  // ../compiler/src/server-jsgen.ts
31326
31462
  function sanitizeMarkerName(name) {
31327
31463
  return String(name).split("--").join("-").split("<").join("").split(">").join("");
@@ -32097,7 +32233,9 @@ function renderPage(source, componentName, props = {}, registry = /* @__PURE__ *
32097
32233
  }
32098
32234
  return {
32099
32235
  body: bodyHtml2,
32100
- head: renderHeadHtml(targetComp, ssrProps),
32236
+ // The component's own scope, so head expressions that read an import
32237
+ // resolve (see renderHeadHtml).
32238
+ head: renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk)),
32101
32239
  props: ssrProps
32102
32240
  };
32103
32241
  })();
@@ -32108,7 +32246,7 @@ function renderPage(source, componentName, props = {}, registry = /* @__PURE__ *
32108
32246
  } finally {
32109
32247
  delete globalThis.__vsk_ssr;
32110
32248
  }
32111
- const headHtml = targetComp ? renderHeadHtml(targetComp, ssrProps) : "";
32249
+ const headHtml = targetComp ? renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk)) : "";
32112
32250
  const pending = globalThis[`__vsk_ssr_promises_${renderToken}`];
32113
32251
  if (pending && pending.length > 0) {
32114
32252
  return (async () => {
@@ -32423,7 +32561,7 @@ function renderPageStream(source, componentName, props = {}, registry = /* @__PU
32423
32561
  }
32424
32562
  let streamHeadHtml = null;
32425
32563
  if (targetComp) {
32426
- let headHtml = renderHeadHtml(targetComp, ssrProps);
32564
+ let headHtml = renderHeadHtml(targetComp, ssrProps, scopedVesk(renderFn, __vesk));
32427
32565
  if (options.pageHead) {
32428
32566
  const merged = mergeHeadHtml(options.pageHead, headHtml);
32429
32567
  headHtml = merged.html;
@@ -33538,7 +33676,7 @@ async function generateSsgRoutes(routeTree, appDir, outDir, plugins, headExtra,
33538
33676
  return null;
33539
33677
  }
33540
33678
  }
33541
- async function walk7(nodes) {
33679
+ async function walk8(nodes) {
33542
33680
  for (const node of nodes) {
33543
33681
  if (node.page) {
33544
33682
  const pagePath = resolve15(appDir, node.sourceDir, "page.vsk");
@@ -33581,10 +33719,10 @@ async function generateSsgRoutes(routeTree, appDir, outDir, plugins, headExtra,
33581
33719
  }
33582
33720
  }
33583
33721
  }
33584
- await walk7(node.children || []);
33722
+ await walk8(node.children || []);
33585
33723
  }
33586
33724
  }
33587
- await walk7(routeTree);
33725
+ await walk8(routeTree);
33588
33726
  return results;
33589
33727
  }
33590
33728
  function generateSitemap(_routeTree, ssrRoutes, prerenderedRoutes, { siteUrl = "http://localhost:3000" } = {}) {
@@ -33600,15 +33738,15 @@ function generateSitemap(_routeTree, ssrRoutes, prerenderedRoutes, { siteUrl = "
33600
33738
  for (const r of prerenderedRoutes) {
33601
33739
  addUrl(r.path, "0.80", "weekly");
33602
33740
  }
33603
- function walk7(nodes) {
33741
+ function walk8(nodes) {
33604
33742
  for (const node of nodes) {
33605
33743
  if (node.page && !node.fullPath.includes(":")) {
33606
33744
  addUrl(node.fullPath, "0.64", "daily");
33607
33745
  }
33608
- walk7(node.children || []);
33746
+ walk8(node.children || []);
33609
33747
  }
33610
33748
  }
33611
- walk7(ssrRoutes);
33749
+ walk8(ssrRoutes);
33612
33750
  let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
33613
33751
  xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
33614
33752
  for (const u of urls) {
@@ -33735,7 +33873,7 @@ async function processImage(srcPath, outDir, baseName) {
33735
33873
  }
33736
33874
  function collectImageRefs(appDir) {
33737
33875
  const refs = [];
33738
- function walk7(dir) {
33876
+ function walk8(dir) {
33739
33877
  let entries;
33740
33878
  try {
33741
33879
  entries = readdirSync4(dir);
@@ -33748,7 +33886,7 @@ function collectImageRefs(appDir) {
33748
33886
  if (st.isDirectory()) {
33749
33887
  if (entry.startsWith("."))
33750
33888
  continue;
33751
- walk7(full);
33889
+ walk8(full);
33752
33890
  } else if (entry === "page.vsk") {
33753
33891
  const src2 = readFileSync18(full, "utf-8");
33754
33892
  const imgRegex = /<Image\s+src=["']([^"']+)["']/g;
@@ -33759,7 +33897,7 @@ function collectImageRefs(appDir) {
33759
33897
  }
33760
33898
  }
33761
33899
  }
33762
- walk7(appDir);
33900
+ walk8(appDir);
33763
33901
  return refs;
33764
33902
  }
33765
33903
  async function optimizeImages(appDir, outDir) {
@@ -34391,18 +34529,18 @@ function writePrerenderedStatic(prerenderedRoutes, platformStaticDir) {
34391
34529
  function listStaticDir(dir) {
34392
34530
  const out = [];
34393
34531
  if (!existsSync21(dir)) return out;
34394
- function walk7(d, prefix) {
34532
+ function walk8(d, prefix) {
34395
34533
  for (const entry of readdirSync6(d)) {
34396
34534
  const full = join14(d, entry);
34397
34535
  const rel = prefix ? `${prefix}/${entry}` : entry;
34398
34536
  if (statSync11(full).isDirectory()) {
34399
- walk7(full, rel);
34537
+ walk8(full, rel);
34400
34538
  } else {
34401
34539
  out.push({ rel, buffer: readFileSync20(full) });
34402
34540
  }
34403
34541
  }
34404
34542
  }
34405
- walk7(dir, "");
34543
+ walk8(dir, "");
34406
34544
  return out;
34407
34545
  }
34408
34546
  function mimeFor(path) {
@@ -39069,7 +39207,7 @@ import * as ts8 from "typescript";
39069
39207
  function walkProjectFiles(projectRoot) {
39070
39208
  const code = [];
39071
39209
  const js = [];
39072
- const walk7 = (dir) => {
39210
+ const walk8 = (dir) => {
39073
39211
  let entries = [];
39074
39212
  try {
39075
39213
  entries = readdirSync14(dir);
@@ -39087,7 +39225,7 @@ function walkProjectFiles(projectRoot) {
39087
39225
  if (st.isDirectory()) {
39088
39226
  if (SKIP_DIRS.has(e))
39089
39227
  continue;
39090
- walk7(p);
39228
+ walk8(p);
39091
39229
  } else if (e.endsWith(".vsk")) {
39092
39230
  code.push(p);
39093
39231
  } else if (e.endsWith(".ts") || e.endsWith(".tsx")) {
@@ -39101,7 +39239,7 @@ function walkProjectFiles(projectRoot) {
39101
39239
  }
39102
39240
  }
39103
39241
  };
39104
- walk7(projectRoot);
39242
+ walk8(projectRoot);
39105
39243
  return { code, js };
39106
39244
  }
39107
39245
  function isUnder(dir, file) {
@@ -40906,13 +41044,13 @@ function hydrateInvoke(planExpr) {
40906
41044
  function buildParamExtraction(node, urlParts) {
40907
41045
  const parts = [];
40908
41046
  let partIdx = Math.max(0, urlParts.length - 1);
40909
- function walk7(n) {
41047
+ function walk8(n) {
40910
41048
  if (n.fullPath === "/") {
40911
- for (const child of n.children || []) walk7(child);
41049
+ for (const child of n.children || []) walk8(child);
40912
41050
  return;
40913
41051
  }
40914
41052
  if (n.isGroup) {
40915
- for (const child of n.children || []) walk7(child);
41053
+ for (const child of n.children || []) walk8(child);
40916
41054
  return;
40917
41055
  }
40918
41056
  if (partIdx >= urlParts.length) return;
@@ -40926,15 +41064,15 @@ function buildParamExtraction(node, urlParts) {
40926
41064
  const paramName = n.path.startsWith(":") ? n.path.slice(1) : "param";
40927
41065
  parts.push(`${JSON.stringify(paramName)}: urlParts[${partIdx}]`);
40928
41066
  partIdx++;
40929
- for (const child of n.children || []) walk7(child);
41067
+ for (const child of n.children || []) walk8(child);
40930
41068
  return;
40931
41069
  }
40932
41070
  if (n.path === urlParts[partIdx]) {
40933
41071
  partIdx++;
40934
- for (const child of n.children || []) walk7(child);
41072
+ for (const child of n.children || []) walk8(child);
40935
41073
  }
40936
41074
  }
40937
- walk7(node);
41075
+ walk8(node);
40938
41076
  return parts;
40939
41077
  }
40940
41078
  function generateSsrFunction(routeNode, appDir, outDir, componentMap, options) {
@@ -43629,7 +43767,7 @@ async function build2(appDir, options) {
43629
43767
  await bundleRuntime(appDir, outDir);
43630
43768
  const ssrRoutes = [];
43631
43769
  const actionMap = {};
43632
- function walk7(nodes, ancestorLayouts = []) {
43770
+ function walk8(nodes, ancestorLayouts = []) {
43633
43771
  for (const node of nodes) {
43634
43772
  const isStandalone = node.standalone === true;
43635
43773
  let childAncestorLayouts = isStandalone ? [] : ancestorLayouts;
@@ -43673,10 +43811,10 @@ async function build2(appDir, options) {
43673
43811
  ssrRoutes.push(node);
43674
43812
  console.error(`vesk build: ssr \u2192 server/functions/${name}.js (${node.fullPath})${mwCode ? " [mw]" : ""}`);
43675
43813
  }
43676
- walk7(node.children || [], childAncestorLayouts);
43814
+ walk8(node.children || [], childAncestorLayouts);
43677
43815
  }
43678
43816
  }
43679
- walk7(routeTree);
43817
+ walk8(routeTree);
43680
43818
  markPhase("server runtime + ssr functions");
43681
43819
  const apiRoutes = [];
43682
43820
  function walkApi(nodes) {
@@ -43823,7 +43961,7 @@ import { WebSocketServer as WebSocketServer2 } from "ws";
43823
43961
 
43824
43962
  // ../compiler/dist/strip-ts.js
43825
43963
  init_parser();
43826
- import { walk as walk5 } from "zimmerframe";
43964
+ import { walk as walk6 } from "zimmerframe";
43827
43965
  import { print as print6 } from "esrap";
43828
43966
  import ts6 from "esrap/languages/ts";
43829
43967
  var TS_NODE_TYPES2 = /* @__PURE__ */ new Set([
@@ -43865,7 +44003,7 @@ function isTypeOnlySpecifier2(node) {
43865
44003
  }
43866
44004
  function hasTsSyntax2(ast) {
43867
44005
  let found = false;
43868
- walk5(ast, null, {
44006
+ walk6(ast, null, {
43869
44007
  _(node, context) {
43870
44008
  if (TS_NODE_TYPES2.has(node.type)) {
43871
44009
  found = true;
@@ -43903,7 +44041,7 @@ function isTypeOnlyStatement2(node) {
43903
44041
  return TYPE_ONLY_STATEMENTS2.has(node.type);
43904
44042
  }
43905
44043
  function stripTsTypes2(ast) {
43906
- return walk5(ast, null, {
44044
+ return walk6(ast, null, {
43907
44045
  TSAsExpression(node, context) {
43908
44046
  return context.visit(node.expression);
43909
44047
  },
@@ -44159,7 +44297,7 @@ init_tokens();
44159
44297
  init_vsk_imports();
44160
44298
  init_md_inline();
44161
44299
  init_strip_ts();
44162
- import { walk as walk6 } from "zimmerframe";
44300
+ import { walk as walk7 } from "zimmerframe";
44163
44301
  import { print as print7 } from "esrap";
44164
44302
  import ts7 from "esrap/languages/ts";
44165
44303
  import tsx2 from "esrap/languages/tsx";
@@ -44275,7 +44413,7 @@ function transformTracked2(irNode, tracked2) {
44275
44413
  return printAst2(stripTsTypes(ast));
44276
44414
  }
44277
44415
  const stripped = stripTsTypes(ast);
44278
- const transformed = walk6(stripped, tracked2, {
44416
+ const transformed = walk7(stripped, tracked2, {
44279
44417
  AssignmentExpression(node, context) {
44280
44418
  if (node.left.type === "Identifier") {
44281
44419
  const info = context.state.get(node.left.name);
@@ -44388,7 +44526,7 @@ function collectTrackedDeps2(value, tracked2) {
44388
44526
  return [];
44389
44527
  const found = [];
44390
44528
  const seen = /* @__PURE__ */ new Set();
44391
- walk6(ast, tracked2, {
44529
+ walk7(ast, tracked2, {
44392
44530
  Identifier(node, context) {
44393
44531
  const parent = context.path.at(-1);
44394
44532
  if (parent) {
@@ -44940,7 +45078,7 @@ function isReactiveExpression2(node, tracked2) {
44940
45078
  if (!ast)
44941
45079
  return false;
44942
45080
  let reactive = false;
44943
- walk6(ast, tracked2, {
45081
+ walk7(ast, tracked2, {
44944
45082
  Identifier(n, context) {
44945
45083
  if (reactive)
44946
45084
  return;
@@ -45630,7 +45768,7 @@ function emitForLoop2(ctx2, node, tracked2, parentVar, skipK = 0, regionBudget)
45630
45768
  const seen = /* @__PURE__ */ new Set();
45631
45769
  const condAst = node.condition?.ast;
45632
45770
  if (condAst) {
45633
- walk6(condAst, tracked2, {
45771
+ walk7(condAst, tracked2, {
45634
45772
  Identifier(n, context) {
45635
45773
  const parent2 = context.path.at(-1);
45636
45774
  if (parent2) {
@@ -46308,7 +46446,7 @@ function astHasBinding2(ast, names) {
46308
46446
  if (!ast)
46309
46447
  return false;
46310
46448
  let found = false;
46311
- walk6(ast, null, {
46449
+ walk7(ast, null, {
46312
46450
  Identifier(node, context) {
46313
46451
  if (names.has(node.name))
46314
46452
  found = true;
@@ -46562,7 +46700,7 @@ function scanComponents(componentsDir) {
46562
46700
  const map = /* @__PURE__ */ new Map();
46563
46701
  if (!existsSync23(componentsDir))
46564
46702
  return map;
46565
- function walk7(dir, prefix) {
46703
+ function walk8(dir, prefix) {
46566
46704
  let entries;
46567
46705
  try {
46568
46706
  entries = readdirSync7(dir);
@@ -46579,7 +46717,7 @@ function scanComponents(componentsDir) {
46579
46717
  }
46580
46718
  if (stat.isDirectory()) {
46581
46719
  if (!entry.startsWith("_")) {
46582
- walk7(full, prefix ? prefix + capitalize(entry) : capitalize(entry));
46720
+ walk8(full, prefix ? prefix + capitalize(entry) : capitalize(entry));
46583
46721
  }
46584
46722
  } else if (entry.endsWith(".vsk")) {
46585
46723
  const name = prefix ? prefix + capitalize(entry.slice(0, -4)) : entry.slice(0, -4);
@@ -46589,7 +46727,7 @@ function scanComponents(componentsDir) {
46589
46727
  }
46590
46728
  }
46591
46729
  }
46592
- walk7(componentsDir, "");
46730
+ walk8(componentsDir, "");
46593
46731
  return map;
46594
46732
  }
46595
46733
  function scanDirectory(rootDir, dir, parentPath, options) {
@@ -46741,7 +46879,7 @@ function extractComponentName(dir, type, rootDir) {
46741
46879
  }
46742
46880
  function collectSources(tree) {
46743
46881
  const map = /* @__PURE__ */ new Map();
46744
- function walk7(nodes) {
46882
+ function walk8(nodes) {
46745
46883
  for (const node of nodes) {
46746
46884
  if (node.page)
46747
46885
  map.set(node.page, join15(node.sourceDir, "page.vsk"));
@@ -46757,10 +46895,10 @@ function collectSources(tree) {
46757
46895
  map.set(node.offline, join15(node.sourceDir, "offline.vsk"));
46758
46896
  if (node.network)
46759
46897
  map.set(node.network, join15(node.sourceDir, "network.vsk"));
46760
- walk7(node.children);
46898
+ walk8(node.children);
46761
46899
  }
46762
46900
  }
46763
- walk7(tree);
46901
+ walk8(tree);
46764
46902
  return map;
46765
46903
  }
46766
46904
  function matchUrl(tree, pathname) {
@@ -47255,16 +47393,16 @@ function parseCookies2(str3) {
47255
47393
  function collectMiddlewareChain(routeTree, url, appDir) {
47256
47394
  const parts = url.split("/").filter(Boolean);
47257
47395
  const chain = [];
47258
- function walk7(nodes, depth) {
47396
+ function walk8(nodes, depth) {
47259
47397
  for (const node of nodes) {
47260
47398
  if (node.isGroup) {
47261
- if (walk7(node.children, depth))
47399
+ if (walk8(node.children, depth))
47262
47400
  return true;
47263
47401
  continue;
47264
47402
  }
47265
47403
  if (node.fullPath === "/") {
47266
47404
  collectForNode(node);
47267
- return walk7(node.children, depth);
47405
+ return walk8(node.children, depth);
47268
47406
  }
47269
47407
  if (depth >= parts.length) {
47270
47408
  if (node.page) {
@@ -47302,16 +47440,16 @@ function collectMiddlewareChain(routeTree, url, appDir) {
47302
47440
  function tryCollectAndRecurse(node, depth) {
47303
47441
  collectForNode(node);
47304
47442
  if (node.children.length > 0) {
47305
- return walk7(node.children, depth + 1);
47443
+ return walk8(node.children, depth + 1);
47306
47444
  }
47307
47445
  return !!node.page;
47308
47446
  }
47309
47447
  const root3 = routeTree.find((n) => n.fullPath === "/");
47310
47448
  if (root3) {
47311
47449
  collectForNode(root3);
47312
- walk7(root3.children, 0);
47450
+ walk8(root3.children, 0);
47313
47451
  } else {
47314
- walk7(routeTree, 0);
47452
+ walk8(routeTree, 0);
47315
47453
  }
47316
47454
  return chain;
47317
47455
  }
@@ -50622,7 +50760,7 @@ function hasIdentifierAst(source, name) {
50622
50760
  if (!ast)
50623
50761
  return source.includes(name);
50624
50762
  let found = false;
50625
- function walk7(node) {
50763
+ function walk8(node) {
50626
50764
  if (!node || typeof node !== "object" || found)
50627
50765
  return;
50628
50766
  if (node.type === "Identifier" && node.name === name) {
@@ -50633,12 +50771,12 @@ function hasIdentifierAst(source, name) {
50633
50771
  const v = node[k];
50634
50772
  if (Array.isArray(v))
50635
50773
  for (const el of v)
50636
- walk7(el);
50774
+ walk8(el);
50637
50775
  else if (v && typeof v.type === "string")
50638
- walk7(v);
50776
+ walk8(v);
50639
50777
  }
50640
50778
  }
50641
- walk7(ast);
50779
+ walk8(ast);
50642
50780
  return found;
50643
50781
  }
50644
50782
  async function addPluginToConfig2(projectDir, pkg) {
@@ -54473,14 +54611,14 @@ function chainForPath(routeTree, pathname) {
54473
54611
  }
54474
54612
  function pageSourcesFor(appDirPath, routeTree) {
54475
54613
  const out = [];
54476
- function walk7(nodes) {
54614
+ function walk8(nodes) {
54477
54615
  for (const node of nodes) {
54478
54616
  if (node.page) out.push(resolve37(appDirPath, node.sourceDir, "page.vsk"));
54479
54617
  if (node.layout) out.push(resolve37(appDirPath, node.sourceDir, "layout.vsk"));
54480
- walk7(node.children);
54618
+ walk8(node.children);
54481
54619
  }
54482
54620
  }
54483
- walk7(routeTree);
54621
+ walk8(routeTree);
54484
54622
  return out;
54485
54623
  }
54486
54624
  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.48",
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.48",
12
+ "@vesk/compiler": "^0.2.48",
13
+ "@vesk/plugin-tailwind": "^0.2.48",
14
+ "@vesk/runtime": "^0.2.48",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",