@vesk/vesk-cli 0.2.50 → 0.2.52

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 +825 -85
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -199,6 +199,42 @@ var init_errors = __esm({
199
199
  * - `value` — `ns.max` read as a value. Component tags resolve; plain value
200
200
  * reads do not, because nothing binds `ns` at runtime.
201
201
  */
202
+ /**
203
+ * An imported `.ts`/`.js` module could not be parsed.
204
+ *
205
+ * This used to be silent, and that is the whole point of the diagnostic. A
206
+ * parse failure meant the module's RAW, untranspiled source was substituted,
207
+ * so TypeScript syntax reached `new Function` and the module blew up much
208
+ * later with a bare `Unexpected token ':'` — attributed to no file, at a
209
+ * point in the build far from the code that caused it. It also poisoned the
210
+ * whole shared module graph: one unparseable module left its exports
211
+ * undefined, so unrelated consumers failed with `X is not iterable`.
212
+ *
213
+ * Two real constructs hit this: a parameter annotation that survived the
214
+ * stripper only when the parameter also had a default value, and a generic
215
+ * arrow's type parameter list, which the JSX tokenizer cannot read at all.
216
+ * Both are fixed; this error exists so the NEXT such gap is reported at the
217
+ * right file with the right line instead of surfacing three modules later.
218
+ */
219
+ static moduleParseFailed(context = {}) {
220
+ return new _VeskError(
221
+ `Could not parse an imported module${context.reason ? `: ${context.reason}` : "."}`,
222
+ {
223
+ ...context,
224
+ code: context.code || "V0901",
225
+ suggestions: [
226
+ "Check the line the ^ marker points at \u2014 it is the construct the parser stopped on.",
227
+ "If it is TypeScript syntax the stripper does not handle, simplifying it here fixes every module that imports this file.",
228
+ "This is a bug in the compiler, not in your code, if the construct is ordinary TypeScript \u2014 please report it with the source line."
229
+ ],
230
+ nextSteps: [
231
+ "A module that fails to parse is substituted with its raw source, so every type annotation it contains becomes a runtime SyntaxError.",
232
+ "The failure is reported here, at the offending file and line, rather than as an `Unexpected token` in whichever module happened to import it."
233
+ ],
234
+ tip: "Ordinary TypeScript should parse; if this fires on valid TS, the parser is missing a construct."
235
+ }
236
+ );
237
+ }
202
238
  static vskNamespaceMember(context = {}) {
203
239
  const nested = context.form === "nested";
204
240
  return new _VeskError(
@@ -3569,7 +3605,17 @@ function flattenLayoutChain(tree, pathParts, result = []) {
3569
3605
  for (let i = 0; i < tree.length; i++) {
3570
3606
  const node = tree[i];
3571
3607
  if (node.isGroup) {
3608
+ const contributes = !!(node.layout || node.page);
3609
+ const marker = result.length;
3610
+ if (contributes) result.push(node);
3611
+ const before = result.length;
3572
3612
  flattenLayoutChain(node.children || [], pathParts, result);
3613
+ if (result.length > before) break;
3614
+ if (contributes) result.length = marker;
3615
+ if (node.page && (pathParts.length === 0 || pathParts.every((p) => p === ""))) {
3616
+ result.push(node);
3617
+ break;
3618
+ }
3573
3619
  continue;
3574
3620
  }
3575
3621
  const part = pathParts[0];
@@ -3591,6 +3637,11 @@ function flattenLayoutChain(tree, pathParts, result = []) {
3591
3637
  if (node.standalone) result.length = 0;
3592
3638
  result.push(node);
3593
3639
  if (isLeaf2) {
3640
+ if (!node.page && (node.children || []).length > 0) {
3641
+ const before = result.length;
3642
+ flattenLayoutChain(node.children || [], remaining, result);
3643
+ if (result.length > before) break;
3644
+ }
3594
3645
  break;
3595
3646
  } else if ((node.children || []).length > 0) {
3596
3647
  flattenLayoutChain(node.children || [], remaining, result);
@@ -3621,7 +3672,7 @@ function matchRoute(tree, pathname) {
3621
3672
  }
3622
3673
  partIdx += segCount;
3623
3674
  }
3624
- return { matchChain, params };
3675
+ return { matchChain, params, pathname };
3625
3676
  }
3626
3677
  function buildTreeFromMap(routes, _options) {
3627
3678
  const root3 = [];
@@ -18773,6 +18824,162 @@ function preprocessForClauses(source) {
18773
18824
  }
18774
18825
  return { code: chars.join(""), annotations };
18775
18826
  }
18827
+ function blankGenericArrowTypeParams(source) {
18828
+ let changed = false;
18829
+ const chars = source.split("");
18830
+ let i = 0;
18831
+ const isSpace = (ch) => isSpaceChar(ch);
18832
+ while (i < source.length) {
18833
+ const ch = source[i];
18834
+ if (ch === '"' || ch === "'" || ch === "`") {
18835
+ const quote = ch;
18836
+ let j2 = i + 1;
18837
+ while (j2 < source.length) {
18838
+ if (source[j2] === "\\") {
18839
+ j2 += 2;
18840
+ continue;
18841
+ }
18842
+ if (source[j2] === quote) {
18843
+ j2++;
18844
+ break;
18845
+ }
18846
+ if (quote === "`" && source[j2] === "$" && source[j2 + 1] === "{") {
18847
+ let depth = 1;
18848
+ j2 += 2;
18849
+ while (j2 < source.length && depth > 0) {
18850
+ if (source[j2] === "{") depth++;
18851
+ else if (source[j2] === "}") depth--;
18852
+ j2++;
18853
+ }
18854
+ continue;
18855
+ }
18856
+ j2++;
18857
+ }
18858
+ i = j2;
18859
+ continue;
18860
+ }
18861
+ if (ch === "/" && source[i + 1] === "/") {
18862
+ while (i < source.length && source[i] !== "\n") i++;
18863
+ continue;
18864
+ }
18865
+ if (ch === "/" && source[i + 1] === "*") {
18866
+ i += 2;
18867
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) i++;
18868
+ i += 2;
18869
+ continue;
18870
+ }
18871
+ if (ch !== "<") {
18872
+ i++;
18873
+ continue;
18874
+ }
18875
+ let j = i + 1;
18876
+ let angle = 1;
18877
+ let end = -1;
18878
+ let bail = false;
18879
+ while (j < source.length) {
18880
+ const c = source[j];
18881
+ if (c === "<") {
18882
+ angle++;
18883
+ j++;
18884
+ continue;
18885
+ }
18886
+ if (c === ">") {
18887
+ angle--;
18888
+ j++;
18889
+ if (angle === 0) {
18890
+ end = j;
18891
+ break;
18892
+ }
18893
+ continue;
18894
+ }
18895
+ if (c === "(" || c === "[" || c === "{") {
18896
+ const close = c === "(" ? ")" : c === "[" ? "]" : "}";
18897
+ let depth = 0;
18898
+ while (j < source.length) {
18899
+ const d = source[j];
18900
+ if (d === c) depth++;
18901
+ else if (d === close) {
18902
+ depth--;
18903
+ if (depth === 0) {
18904
+ j++;
18905
+ break;
18906
+ }
18907
+ }
18908
+ j++;
18909
+ }
18910
+ continue;
18911
+ }
18912
+ if (c === ";" || c === "\n") {
18913
+ bail = true;
18914
+ break;
18915
+ }
18916
+ j++;
18917
+ }
18918
+ if (bail || end < 0) {
18919
+ i++;
18920
+ continue;
18921
+ }
18922
+ if (!isArrowParameterList(source, end)) {
18923
+ i = end;
18924
+ continue;
18925
+ }
18926
+ for (let p = i; p < end; p++) {
18927
+ if (chars[p] !== "\n") chars[p] = " ";
18928
+ }
18929
+ changed = true;
18930
+ i = end;
18931
+ }
18932
+ return changed ? chars.join("") : source;
18933
+ }
18934
+ function isArrowParameterList(source, from) {
18935
+ let i = from;
18936
+ while (i < source.length && isSpaceChar(source[i])) i++;
18937
+ if (source[i] !== "(") return false;
18938
+ let depth = 0;
18939
+ while (i < source.length) {
18940
+ const ch = source[i];
18941
+ if (ch === "(" || ch === "[" || ch === "{") {
18942
+ depth++;
18943
+ i++;
18944
+ continue;
18945
+ }
18946
+ if (ch === ")" || ch === "]" || ch === "}") {
18947
+ depth--;
18948
+ i++;
18949
+ if (depth === 0) break;
18950
+ continue;
18951
+ }
18952
+ i++;
18953
+ }
18954
+ if (depth !== 0) return false;
18955
+ while (i < source.length && isSpaceChar(source[i])) i++;
18956
+ if (source[i] === ":") {
18957
+ i++;
18958
+ let tdepth = 0;
18959
+ while (i < source.length) {
18960
+ const ch = source[i];
18961
+ if (ch === "(" || ch === "[" || ch === "{") {
18962
+ tdepth++;
18963
+ i++;
18964
+ continue;
18965
+ }
18966
+ if (ch === ")" || ch === "]" || ch === "}") {
18967
+ if (tdepth === 0) return false;
18968
+ tdepth--;
18969
+ i++;
18970
+ continue;
18971
+ }
18972
+ if (tdepth === 0 && ch === "=" && source[i + 1] === ">") return true;
18973
+ if (tdepth === 0 && (ch === ";" || ch === "\n")) return false;
18974
+ i++;
18975
+ }
18976
+ return false;
18977
+ }
18978
+ return source[i] === "=" && source[i + 1] === ">";
18979
+ }
18980
+ function isSpaceChar(ch) {
18981
+ return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f" || ch === "\v";
18982
+ }
18776
18983
  function createBaseParser() {
18777
18984
  return Parser.extend(tsPlugin({}), VeskParserPlugin());
18778
18985
  }
@@ -18785,7 +18992,7 @@ function parseGeneratedJs(source) {
18785
18992
  }
18786
18993
  function parse4(source, options = {}) {
18787
18994
  const ParserClass = createBaseParser();
18788
- const { code, annotations } = preprocessForClauses(blankComments(source));
18995
+ const { code, annotations } = preprocessForClauses(blankGenericArrowTypeParams(blankComments(source)));
18789
18996
  const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
18790
18997
  const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
18791
18998
  let parseable = code;
@@ -18987,13 +19194,33 @@ function stripTsTypes(ast) {
18987
19194
  }
18988
19195
  });
18989
19196
  }
19197
+ function stripParamTypes(p) {
19198
+ if (!p) return;
19199
+ if (p.typeAnnotation) p.typeAnnotation = null;
19200
+ if (p.optional) p.optional = false;
19201
+ switch (p.type) {
19202
+ case "AssignmentPattern":
19203
+ stripParamTypes(p.left);
19204
+ break;
19205
+ case "RestElement":
19206
+ stripParamTypes(p.argument);
19207
+ break;
19208
+ case "ObjectPattern":
19209
+ for (const prop of p.properties || []) {
19210
+ stripParamTypes(prop.value || prop.argument || prop);
19211
+ }
19212
+ break;
19213
+ case "ArrayPattern":
19214
+ for (const el of p.elements || []) if (el) stripParamTypes(el);
19215
+ break;
19216
+ default:
19217
+ break;
19218
+ }
19219
+ }
18990
19220
  function stripFunctionTypes(node) {
18991
19221
  if (node.returnType) node.returnType = null;
18992
19222
  if (node.typeParameters) node.typeParameters = null;
18993
- for (const p of node.params || []) {
18994
- if (p.typeAnnotation) p.typeAnnotation = null;
18995
- if (p.optional) p.optional = false;
18996
- }
19223
+ for (const p of node.params || []) stripParamTypes(p);
18997
19224
  }
18998
19225
  function stripCodeTypes(code) {
18999
19226
  let ast;
@@ -19171,6 +19398,7 @@ function loadSsrModule(absPath) {
19171
19398
  }
19172
19399
  } else {
19173
19400
  const src2 = readSsrSource(absPath);
19401
+ if (src2?.parseError) throw src2.parseError;
19174
19402
  const body = src2?.ast?.body || [];
19175
19403
  if (src2 && isPureReexportBarrel(body)) {
19176
19404
  exportsObj = createLazyBarrelExports(buildBarrelSpec(body), dirname2(absPath));
@@ -19247,13 +19475,19 @@ function readSsrSource(absPath) {
19247
19475
  return null;
19248
19476
  }
19249
19477
  const raw2 = cachedRaw;
19250
- let ast = null;
19251
19478
  try {
19252
- ast = parse4(raw2, { filename: absPath });
19253
- } catch {
19254
- ast = null;
19479
+ return { raw: raw2, ast: parse4(raw2, { filename: absPath }) };
19480
+ } catch (e) {
19481
+ const err = e;
19482
+ let parseError;
19483
+ if (err instanceof VeskError) {
19484
+ parseError = err;
19485
+ if (err.code === void 0) err.code = "V0901";
19486
+ } else {
19487
+ parseError = VeskError.moduleParseFailed({ file: absPath, reason: e?.message });
19488
+ }
19489
+ return { raw: raw2, ast: null, parseError };
19255
19490
  }
19256
- return { raw: raw2, ast };
19257
19491
  }
19258
19492
  function isPureReexportBarrel(body) {
19259
19493
  for (const stmt of body) {
@@ -19319,7 +19553,7 @@ function createLazyBarrelExports(spec, dir) {
19319
19553
  const loadSource = (source) => {
19320
19554
  let target = targets.get(source);
19321
19555
  if (!target) {
19322
- target = resolveSsrModule(source, dir) ?? "";
19556
+ target = (isCompilerOwnedTarget(source) ? resolveCompilerOwnedModule(source) : resolveSsrModule(source, dir)) ?? "";
19323
19557
  if (!target) return null;
19324
19558
  targets.set(source, target);
19325
19559
  }
@@ -19404,6 +19638,7 @@ function evaluateModuleFile(absPath, exportsObj, src2) {
19404
19638
  let ast;
19405
19639
  if (src2) {
19406
19640
  ast = src2.ast;
19641
+ if (!ast && src2.parseError) throw src2.parseError;
19407
19642
  } else {
19408
19643
  try {
19409
19644
  ast = parse4(raw2, { filename: absPath });
@@ -19477,8 +19712,25 @@ function scanUnsupportedNode(node, inFunction = false) {
19477
19712
  }
19478
19713
  return null;
19479
19714
  }
19715
+ function resolveCompilerOwnedModule(specifier) {
19716
+ const viaExports = resolveViaPackageExports(specifier, process.cwd());
19717
+ if (viaExports) return viaExports;
19718
+ const viaModuleField = resolveViaPackageModuleField(specifier, process.cwd());
19719
+ if (viaModuleField) return viaModuleField;
19720
+ const native = nativeResolve(specifier, process.cwd());
19721
+ if (native && !isBuiltinPath(native)) return native;
19722
+ return null;
19723
+ }
19480
19724
  function createModuleRequire(fromDir) {
19481
19725
  return (specifier) => {
19726
+ if (isCompilerOwnedTarget(specifier)) {
19727
+ const resolved2 = resolveCompilerOwnedModule(specifier);
19728
+ if (resolved2) {
19729
+ const native = nativeRequireFallback(resolved2);
19730
+ if (native) return native;
19731
+ }
19732
+ throw new Error(`Cannot load module '${specifier}'`);
19733
+ }
19482
19734
  const resolved = resolveSsrModule(specifier, fromDir);
19483
19735
  if (!resolved) throw new Error(`Cannot find module '${specifier}'`);
19484
19736
  for (const frame of depStack) frame.add(resolved);
@@ -20026,6 +20278,7 @@ function collectModuleBundled(absPath, collector) {
20026
20278
  } else {
20027
20279
  const src2 = readSsrSource(absPath);
20028
20280
  if (!src2 || !src2.ast) {
20281
+ if (src2?.parseError) throw src2.parseError;
20029
20282
  const raw2 = src2 ? src2.raw : "// unreadable during build\nmodule.exports = {};";
20030
20283
  collector.modules.push({ key, code: raw2, dir, deps: {} });
20031
20284
  return key;
@@ -20072,6 +20325,7 @@ var init_module_imports = __esm({
20072
20325
  init_parser();
20073
20326
  init_strip_ts();
20074
20327
  init_tokens();
20328
+ init_errors();
20075
20329
  RUNTIME_PREFIXES = ["@vesk/runtime/", "@vesk/reactivity/", "@vesk/types", "@vesk/"];
20076
20330
  EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs", ".jsx", ".json"];
20077
20331
  BUILTIN_PREFIX = "\0builtin:";
@@ -20541,6 +20795,22 @@ function jsxTagDepth(nameNode) {
20541
20795
  }
20542
20796
  return depth;
20543
20797
  }
20798
+ function unwrapHelperBody(node) {
20799
+ let body = node;
20800
+ if (body?.type === "ArrowFunctionExpression" || body?.type === "FunctionExpression") body = body.body;
20801
+ if (body?.type === "BlockStatement") {
20802
+ const stmts = (body.body || []).filter((s) => s.type !== "EmptyStatement");
20803
+ if (stmts.length !== 1) return null;
20804
+ body = stmts[0];
20805
+ }
20806
+ if (body?.type === "ReturnStatement") body = body.argument;
20807
+ if (!body) return null;
20808
+ if (body.type !== "CallExpression") return null;
20809
+ if (body.callee?.type !== "Identifier") return null;
20810
+ const args2 = body.arguments || [];
20811
+ if (args2.length === 0 || args2[0]?.type !== "ObjectExpression") return null;
20812
+ return body;
20813
+ }
20544
20814
  function collectVskNamespaceLocals(ast) {
20545
20815
  const namespaceLocals = /* @__PURE__ */ new Map();
20546
20816
  for (const node of ast.body || []) {
@@ -20574,6 +20844,34 @@ function markShadowedBindings(node, namespaceLocals) {
20574
20844
  markShadowedBindings(node[key], namespaceLocals);
20575
20845
  }
20576
20846
  }
20847
+ function collectFileValueBindings(ast) {
20848
+ const names = /* @__PURE__ */ new Set();
20849
+ for (const node of ast.body || []) {
20850
+ if (node.type === "ComponentDeclaration") continue;
20851
+ if (node.type === "ImportDeclaration") continue;
20852
+ const target = node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" ? node.declaration : node;
20853
+ if (!target) continue;
20854
+ if (target.type === "VariableDeclaration") {
20855
+ for (const d of target.declarations || []) for (const n of declaredBindingNames(d)) names.add(n);
20856
+ continue;
20857
+ }
20858
+ for (const n of declaredBindingNames(target)) names.add(n);
20859
+ }
20860
+ return names;
20861
+ }
20862
+ function collectComponentValueNames(compNode) {
20863
+ const names = /* @__PURE__ */ new Set();
20864
+ if (!compNode) return names;
20865
+ for (const p of compNode.params || []) for (const n of declaredBindingNames(p)) names.add(n);
20866
+ for (const stmt of compNode.body?.body || []) {
20867
+ if (stmt.type === "VariableDeclaration") {
20868
+ for (const d of stmt.declarations || []) for (const n of declaredBindingNames(d)) names.add(n);
20869
+ continue;
20870
+ }
20871
+ for (const n of declaredBindingNames(stmt)) names.add(n);
20872
+ }
20873
+ return names;
20874
+ }
20577
20875
  function declaredBindingNames(node) {
20578
20876
  const out = [];
20579
20877
  const pushPattern = (id) => {
@@ -20643,9 +20941,149 @@ function findNamespaceValueUse(node, locals2) {
20643
20941
  }
20644
20942
  return null;
20645
20943
  }
20944
+ function collectComponentCallHelpers(source, ast) {
20945
+ const out = /* @__PURE__ */ new Map();
20946
+ for (const node of ast.body || []) {
20947
+ const decl = node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" ? node.declaration : node;
20948
+ if (!decl) continue;
20949
+ let name = null;
20950
+ let fn = null;
20951
+ if (decl.type === "VariableDeclaration" && decl.declarations?.length === 1) {
20952
+ const d = decl.declarations[0];
20953
+ if (d.id?.type === "Identifier") {
20954
+ name = d.id.name;
20955
+ fn = d.init;
20956
+ }
20957
+ } else if (decl.type === "FunctionDeclaration" && decl.id?.name) {
20958
+ name = decl.id.name;
20959
+ fn = decl;
20960
+ }
20961
+ if (!name || !fn) continue;
20962
+ if (fn.type !== "ArrowFunctionExpression" && fn.type !== "FunctionExpression" && fn.type !== "FunctionDeclaration") continue;
20963
+ const params = fn.params || [];
20964
+ if (params.some((p) => p.type !== "Identifier")) continue;
20965
+ const body = unwrapHelperBody(fn);
20966
+ if (body === null) continue;
20967
+ const args2 = body.arguments || [];
20968
+ const propsObj = args2[0];
20969
+ const props = [];
20970
+ const spreadProps = [];
20971
+ const slots = [];
20972
+ for (const prop of propsObj.properties || []) {
20973
+ if (prop.type === "SpreadElement") {
20974
+ spreadProps.push(prop.argument);
20975
+ continue;
20976
+ }
20977
+ const pname = prop.key.type === "Identifier" ? prop.key.name : prop.key.value;
20978
+ if (prop.value.type === "JSXElement" || prop.value.type === "JSXFragment") {
20979
+ slots.push({ name: pname, nodes: exprToIR(source, prop.value) });
20980
+ continue;
20981
+ }
20982
+ props.push({ name: pname, value: prop.value });
20983
+ }
20984
+ const paramNames = params.map((p) => p.name);
20985
+ out.set(name, { props, spreadProps, slots, paramNames, componentName: body.callee.name });
20986
+ }
20987
+ return out;
20988
+ }
20989
+ function substituteHelperParams(node, bindings) {
20990
+ if (!node || typeof node !== "object") return node;
20991
+ if (Array.isArray(node)) {
20992
+ const out2 = [];
20993
+ for (const child of node) {
20994
+ const next = substituteHelperParams(child, bindings);
20995
+ if (next === null) return null;
20996
+ out2.push(next);
20997
+ }
20998
+ return out2;
20999
+ }
21000
+ if (typeof node.type !== "string") return node;
21001
+ if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") return null;
21002
+ if (node.type === "Identifier" && bindings.has(node.name)) {
21003
+ const bound = bindings.get(node.name);
21004
+ return bound === null ? null : bound;
21005
+ }
21006
+ const out = {};
21007
+ for (const key of Object.keys(node)) {
21008
+ if (key === "loc" || key === "range" || key === "start" || key === "end") {
21009
+ out[key] = node[key];
21010
+ continue;
21011
+ }
21012
+ const next = substituteHelperParams(node[key], bindings);
21013
+ if (next === null) return null;
21014
+ out[key] = next;
21015
+ }
21016
+ return out;
21017
+ }
21018
+ function helperCallToIR(source, helper, args2) {
21019
+ const compName = helper.componentName;
21020
+ const bindings = /* @__PURE__ */ new Map();
21021
+ helper.paramNames.forEach((param, i) => bindings.set(param, args2[i] ?? null));
21022
+ for (const bound of bindings.values()) if (bound === null) return null;
21023
+ const props = [];
21024
+ for (const p of helper.props) {
21025
+ const substituted = substituteHelperParams(p.value, bindings);
21026
+ if (substituted === null) return null;
21027
+ props.push({ name: p.name, value: toExpression(source, substituted) });
21028
+ }
21029
+ const spreadProps = [];
21030
+ for (const sp of helper.spreadProps) {
21031
+ const substituted = substituteHelperParams(sp, bindings);
21032
+ if (substituted === null) return null;
21033
+ spreadProps.push(toExpression(source, substituted));
21034
+ }
21035
+ return [new ComponentCall(compName, props, helper.slots.flatMap((s) => [new PropSlot(s.name, s.nodes)]), spreadProps, -1, componentValueCallee(compName))];
21036
+ }
20646
21037
  function isHTMLTag(name) {
20647
21038
  return name.length > 0 && name[0] === name[0].toLowerCase();
20648
21039
  }
21040
+ function componentValueCallee(tagName) {
21041
+ if (!currentComponentValues || !currentComponentValues.has(tagName)) return null;
21042
+ return tagName;
21043
+ }
21044
+ function componentCallInExpression(expr) {
21045
+ if (!expr || expr.type !== "CallExpression") return null;
21046
+ const callee = expr.callee;
21047
+ if (!callee || callee.type !== "Identifier") return null;
21048
+ if (!isComponentValueName(callee.name)) return null;
21049
+ const args2 = expr.arguments || [];
21050
+ if (args2.length === 0 || !args2[0] || args2[0].type !== "ObjectExpression") return null;
21051
+ return expr;
21052
+ }
21053
+ function isComponentValueName(name) {
21054
+ if (currentFileComponentNames?.has(name)) return true;
21055
+ if (currentComponentValues?.has(name)) return true;
21056
+ return currentFileValueBindings?.has(name) || currentImportedNames?.has(name) || false;
21057
+ }
21058
+ function componentCallToIR(source, expr) {
21059
+ const calleeName = expr.callee.name;
21060
+ const args2 = expr.arguments || [];
21061
+ const propsArg = args2[0];
21062
+ const props = [];
21063
+ const spreadProps = [];
21064
+ const slots = [];
21065
+ for (const prop of propsArg.properties || []) {
21066
+ if (prop.type === "SpreadElement") {
21067
+ spreadProps.push(toExpression(source, prop.argument));
21068
+ continue;
21069
+ }
21070
+ const name = prop.key.type === "Identifier" ? prop.key.name : prop.key.value;
21071
+ if (prop.value.type === "JSXElement" || prop.value.type === "JSXFragment") {
21072
+ slots.push(new PropSlot(name, exprToIR(source, prop.value)));
21073
+ continue;
21074
+ }
21075
+ props.push({ name, value: toExpression(source, prop.value) });
21076
+ }
21077
+ const children = args2.length > 1 ? [new RuntimeStatement(`/* [vesk] extra arguments to a component call are ignored */ ${getSource(source, args2[1])}`)] : [];
21078
+ return [new ComponentCall(
21079
+ calleeName,
21080
+ props,
21081
+ [...children, ...slots],
21082
+ spreadProps,
21083
+ expr.start ?? -1,
21084
+ componentValueCallee(calleeName)
21085
+ )];
21086
+ }
20649
21087
  function isMapCall(expr) {
20650
21088
  return expr.type === "CallExpression" && expr.callee.type === "MemberExpression" && expr.callee.property.name === "map" && expr.arguments.length === 1 && expr.arguments[0].type === "ArrowFunctionExpression";
20651
21089
  }
@@ -20914,7 +21352,7 @@ function processJSXChildren(source, children) {
20914
21352
  continue;
20915
21353
  }
20916
21354
  }
20917
- result.push(new DynamicBinding(toExpression(source, expr)));
21355
+ result.push(...exprToIR(source, expr));
20918
21356
  i++;
20919
21357
  } else if (child.type === "JSXElement") {
20920
21358
  result.push(...processJSXElement(source, child));
@@ -20960,6 +21398,12 @@ function exprToIR(source, expr) {
20960
21398
  return [new MapRegion(arrayExpr, itemVar, bodyNodes, keyExpr, indexVar)];
20961
21399
  }
20962
21400
  if (expr.type === "ParenthesizedExpression") return exprToIR(source, expr.expression);
21401
+ if (componentCallInExpression(expr) !== null) return componentCallToIR(source, expr);
21402
+ if (expr?.type === "CallExpression" && currentComponentCallHelpers?.has(expr.callee?.name)) {
21403
+ const helper = currentComponentCallHelpers.get(expr.callee.name);
21404
+ const inlined = helperCallToIR(source, helper, expr.arguments || []);
21405
+ if (inlined !== null) return inlined;
21406
+ }
20963
21407
  if (expr.type === "ConditionalExpression") {
20964
21408
  const condExpr = toExpression(source, expr.test);
20965
21409
  const consequent = exprToIR(source, expr.consequent);
@@ -21027,12 +21471,12 @@ function processJSXElement(source, element) {
21027
21471
  }
21028
21472
  if (!isHTMLTag(tagName) && selfClosing) {
21029
21473
  const { props, spreadProps, slots } = extractProps(source, element);
21030
- return [new ComponentCall(tagName, props, slots.map((s) => new PropSlot(s.name, s.nodes)), spreadProps, element.start)];
21474
+ return [new ComponentCall(tagName, props, slots.map((s) => new PropSlot(s.name, s.nodes)), spreadProps, element.start, componentValueCallee(tagName))];
21031
21475
  }
21032
21476
  if (!isHTMLTag(tagName)) {
21033
21477
  const { props, spreadProps, slots } = extractProps(source, element);
21034
21478
  const children2 = processJSXChildren(source, element.children || []);
21035
- return [new ComponentCall(tagName, props, [...children2, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start)];
21479
+ return [new ComponentCall(tagName, props, [...children2, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start, componentValueCallee(tagName))];
21036
21480
  }
21037
21481
  const attributes = element.openingElement.attributes.filter((attr) => attr.type !== "JSXSpreadAttribute").map((attr) => processAttribute(source, attr));
21038
21482
  const staticAttrs = [];
@@ -21445,6 +21889,17 @@ function generateIR(ast, source, filename) {
21445
21889
  const vskNamespaceLocals = collectVskNamespaceLocals(ast);
21446
21890
  const prevNamespaceLocals = currentVskNamespaceLocals;
21447
21891
  const prevSourceFile = currentSourceFile;
21892
+ const fileValueBindings = collectFileValueBindings(ast);
21893
+ currentComponentCallHelpers = collectComponentCallHelpers(source, ast);
21894
+ const prevFileComponentNames = currentFileComponentNames;
21895
+ const prevFileValueBindings = currentFileValueBindings;
21896
+ const prevImportedNames = currentImportedNames;
21897
+ const fileComponentNames = new Set(
21898
+ (ast.body || []).map((n) => n.type === "ExportNamedDeclaration" || n.type === "ExportDefaultDeclaration" ? n.declaration : n).filter((n) => n?.type === "ComponentDeclaration").map((n) => n.id.name)
21899
+ );
21900
+ currentFileComponentNames = fileComponentNames;
21901
+ currentFileValueBindings = fileValueBindings;
21902
+ currentImportedNames = importedNames;
21448
21903
  currentVskNamespaceLocals = vskNamespaceLocals;
21449
21904
  currentSourceFile = file;
21450
21905
  try {
@@ -21550,61 +22005,68 @@ function generateIR(ast, source, filename) {
21550
22005
  }
21551
22006
  const name = inner.id.name;
21552
22007
  const paramNames = getParamNames(inner.params, source);
21553
- const firstParam = inner.params?.[0];
21554
- const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
21555
- const propsType = getPropsType(inner.params, source);
21556
- const bodyStmts = inner.body.body;
21557
- const isClientComp = !!inner.client;
21558
- const prevSlotProps = __slotProps;
21559
- __slotProps = slotPropNamesFromType(propsType);
21560
- __propsParam = propsAlias || null;
21561
- if (isStatementMode(bodyStmts)) {
21562
- const raw2 = processStatementModeBody(source, bodyStmts, file);
21563
- const { body, css } = extractStyle(raw2);
21564
- validateBlocks(name, isClientComp, body, file, source);
21565
- const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21566
- comp.style = css;
21567
- components.push(comp);
21568
- __slotProps = prevSlotProps;
21569
- } else {
21570
- const guardClauses = [];
21571
- let mainReturn = null;
21572
- const preamble = [];
21573
- for (const stmt of bodyStmts) {
21574
- if (stmt.type === "VeskBlock") {
21575
- const innerBody = processStatementModeBody(source, stmt.body, file);
21576
- if (stmt.tag === "server") {
21577
- preamble.push(new ServerBlock(innerBody));
21578
- } else if (stmt.tag === "client") {
21579
- preamble.push(new ClientBlock(innerBody));
21580
- }
21581
- } else if (stmt.type === "ReturnStatement") {
21582
- mainReturn = stmt;
21583
- } else if (isTrackDeclaration(stmt)) {
21584
- const elements = stmt.declarations[0].id.elements;
21585
- const trackName = elements[0]?.name;
21586
- const rawName = elements.length > 1 ? elements[1]?.name : null;
21587
- const init = getSource(source, stmt.declarations[0].init);
21588
- if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
21589
- const refName = getComponentRefName(stmt);
21590
- if (refName) preamble.push(new ComponentRef(refName));
21591
- } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
21592
- guardClauses.push(stmt);
21593
- } else if (stmt.type === "ClassDeclaration") {
21594
- const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
21595
- throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
21596
- } else {
21597
- const raw2 = getSource(source, stmt);
21598
- if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
22008
+ const valueNames = collectComponentValueNames(inner);
22009
+ const prevComponentValues = currentComponentValues;
22010
+ currentComponentValues = new Set([...valueNames].filter((n) => !fileComponentNames.has(n)));
22011
+ try {
22012
+ const firstParam = inner.params?.[0];
22013
+ const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
22014
+ const propsType = getPropsType(inner.params, source);
22015
+ const bodyStmts = inner.body.body;
22016
+ const isClientComp = !!inner.client;
22017
+ const prevSlotProps = __slotProps;
22018
+ __slotProps = slotPropNamesFromType(propsType);
22019
+ __propsParam = propsAlias || null;
22020
+ if (isStatementMode(bodyStmts)) {
22021
+ const raw2 = processStatementModeBody(source, bodyStmts, file);
22022
+ const { body, css } = extractStyle(raw2);
22023
+ validateBlocks(name, isClientComp, body, file, source);
22024
+ const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
22025
+ comp.style = css;
22026
+ components.push(comp);
22027
+ __slotProps = prevSlotProps;
22028
+ } else {
22029
+ const guardClauses = [];
22030
+ let mainReturn = null;
22031
+ const preamble = [];
22032
+ for (const stmt of bodyStmts) {
22033
+ if (stmt.type === "VeskBlock") {
22034
+ const innerBody = processStatementModeBody(source, stmt.body, file);
22035
+ if (stmt.tag === "server") {
22036
+ preamble.push(new ServerBlock(innerBody));
22037
+ } else if (stmt.tag === "client") {
22038
+ preamble.push(new ClientBlock(innerBody));
22039
+ }
22040
+ } else if (stmt.type === "ReturnStatement") {
22041
+ mainReturn = stmt;
22042
+ } else if (isTrackDeclaration(stmt)) {
22043
+ const elements = stmt.declarations[0].id.elements;
22044
+ const trackName = elements[0]?.name;
22045
+ const rawName = elements.length > 1 ? elements[1]?.name : null;
22046
+ const init = getSource(source, stmt.declarations[0].init);
22047
+ if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
22048
+ const refName = getComponentRefName(stmt);
22049
+ if (refName) preamble.push(new ComponentRef(refName));
22050
+ } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
22051
+ guardClauses.push(stmt);
22052
+ } else if (stmt.type === "ClassDeclaration") {
22053
+ const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
22054
+ throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
22055
+ } else {
22056
+ const raw2 = getSource(source, stmt);
22057
+ if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
22058
+ }
21599
22059
  }
22060
+ const guardBody = buildGuardChain(source, guardClauses, mainReturn);
22061
+ const { body, css } = extractStyle([...preamble, ...guardBody]);
22062
+ validateBlocks(name, isClientComp, body, file, source);
22063
+ const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
22064
+ comp.style = css;
22065
+ components.push(comp);
22066
+ __slotProps = prevSlotProps;
21600
22067
  }
21601
- const guardBody = buildGuardChain(source, guardClauses, mainReturn);
21602
- const { body, css } = extractStyle([...preamble, ...guardBody]);
21603
- validateBlocks(name, isClientComp, body, file, source);
21604
- const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21605
- comp.style = css;
21606
- components.push(comp);
21607
- __slotProps = prevSlotProps;
22068
+ } finally {
22069
+ currentComponentValues = prevComponentValues;
21608
22070
  }
21609
22071
  }
21610
22072
  const asyncNames = new Set(components.filter((c) => c.isAsync || c.ssrAwait).map((c) => c.name));
@@ -21701,9 +22163,13 @@ function generateIR(ast, source, filename) {
21701
22163
  } finally {
21702
22164
  currentVskNamespaceLocals = prevNamespaceLocals;
21703
22165
  currentSourceFile = prevSourceFile;
22166
+ currentFileComponentNames = prevFileComponentNames;
22167
+ currentFileValueBindings = prevFileValueBindings;
22168
+ currentImportedNames = prevImportedNames;
22169
+ currentComponentCallHelpers = null;
21704
22170
  }
21705
22171
  }
21706
- var __vskAnnotations, __slotProps, __propsParam, currentVskNamespaceLocals, currentSourceFile;
22172
+ var __vskAnnotations, __slotProps, __propsParam, currentVskNamespaceLocals, currentSourceFile, currentComponentValues, currentFileComponentNames, currentFileValueBindings, currentImportedNames, currentComponentCallHelpers;
21707
22173
  var init_ir_generator = __esm({
21708
22174
  "../compiler/src/ir-generator.ts"() {
21709
22175
  "use strict";
@@ -21719,6 +22185,11 @@ var init_ir_generator = __esm({
21719
22185
  __slotProps = null;
21720
22186
  __propsParam = null;
21721
22187
  currentVskNamespaceLocals = null;
22188
+ currentComponentValues = null;
22189
+ currentFileComponentNames = null;
22190
+ currentFileValueBindings = null;
22191
+ currentImportedNames = null;
22192
+ currentComponentCallHelpers = null;
21722
22193
  }
21723
22194
  });
21724
22195
 
@@ -21727,6 +22198,7 @@ var server_utils_exports = {};
21727
22198
  __export(server_utils_exports, {
21728
22199
  CorsResponse: () => CorsResponse,
21729
22200
  DEFAULT_MAX_BODY_BYTES: () => DEFAULT_MAX_BODY_BYTES,
22201
+ VOID_ELEMENTS: () => VOID_ELEMENTS2,
21730
22202
  __vskForceClaim: () => __vskForceClaim,
21731
22203
  __vskHydrate: () => __vskHydrate,
21732
22204
  __vskId: () => __vskId,
@@ -32203,7 +32675,7 @@ function componentMarker(compName) {
32203
32675
  }
32204
32676
  function irNodeToJS(node, importedNames, isAsync = false, tracked2) {
32205
32677
  importedNames = importedNames || __vskImportedNames;
32206
- if (node instanceof StaticNode) return staticNodeToJS(node, isAsync, tracked2);
32678
+ if (node instanceof StaticNode) return staticNodeToJS(node, isAsync, tracked2, __inForeignContent);
32207
32679
  if (node instanceof TextNode) {
32208
32680
  if (!node.value) return "";
32209
32681
  return `__out.push(${JSON.stringify(escapeHtml(node.value))});`;
@@ -32281,7 +32753,7 @@ function exprJSX(node, tracked2) {
32281
32753
  }
32282
32754
  return exprJS(transformTracked({ ...node, ast: lowered }, tracked2 || /* @__PURE__ */ new Map()));
32283
32755
  }
32284
- function staticNodeToJS(node, isAsync = false, tracked2) {
32756
+ function staticNodeToJS(node, isAsync = false, tracked2, inForeign = false) {
32285
32757
  const lines = [];
32286
32758
  const dynAttrTargets = /* @__PURE__ */ new Set();
32287
32759
  for (const child of node.children) {
@@ -32307,17 +32779,19 @@ function staticNodeToJS(node, isAsync = false, tracked2) {
32307
32779
  }
32308
32780
  }
32309
32781
  if (node.selfClosing) {
32310
- let tag = openTag + " />";
32782
+ const voidOrForeign = VOID_ELEMENTS2.has(node.tag) || inForeign;
32783
+ const tail = voidOrForeign ? " />" : `></${node.tag}>`;
32311
32784
  if (hasDynamicAttrs) {
32312
- let expr = JSON.stringify(tag);
32785
+ let expr = JSON.stringify(openTag);
32313
32786
  for (const child of node.children) {
32314
32787
  if (child instanceof DynamicBinding && child.kind === "attribute" && child.target !== "ref" && !isEvent(child.target)) {
32315
32788
  expr += ` + __attr(${JSON.stringify(child.target)}, ${exprJSX(child.expression, tracked2)})`;
32316
32789
  }
32317
32790
  }
32791
+ expr += ` + ${JSON.stringify(tail)}`;
32318
32792
  lines.push(`__out.push(${expr});`);
32319
32793
  } else {
32320
- lines.push(`__out.push(${JSON.stringify(tag)});`);
32794
+ lines.push(`__out.push(${JSON.stringify(openTag + tail)});`);
32321
32795
  }
32322
32796
  return lines.join("\n");
32323
32797
  }
@@ -32336,10 +32810,13 @@ function staticNodeToJS(node, isAsync = false, tracked2) {
32336
32810
  } else {
32337
32811
  lines.push(`__out.push(${JSON.stringify(openTag + ">")});`);
32338
32812
  }
32813
+ const prevForeign = __inForeignContent;
32814
+ if (FOREIGN_ROOTS.has(node.tag)) __inForeignContent = true;
32339
32815
  for (const child of childNodes) {
32340
32816
  const code = irNodeToJS(child, null, isAsync, tracked2);
32341
32817
  if (code) lines.push(code);
32342
32818
  }
32819
+ __inForeignContent = prevForeign;
32343
32820
  lines.push(`__out.push(${JSON.stringify("</" + node.tag + ">")});`);
32344
32821
  return lines.join("\n");
32345
32822
  }
@@ -32736,7 +33213,7 @@ ${entry.source}
32736
33213
  }
32737
33214
  return map;
32738
33215
  }
32739
- var __currentCompName;
33216
+ var __currentCompName, __inForeignContent, FOREIGN_ROOTS;
32740
33217
  var init_server_jsgen = __esm({
32741
33218
  "../compiler/src/server-jsgen.ts"() {
32742
33219
  "use strict";
@@ -32748,6 +33225,8 @@ var init_server_jsgen = __esm({
32748
33225
  init_server_jsx_lowering();
32749
33226
  init_vsk_imports();
32750
33227
  __currentCompName = "";
33228
+ __inForeignContent = false;
33229
+ FOREIGN_ROOTS = /* @__PURE__ */ new Set(["svg", "math"]);
32751
33230
  }
32752
33231
  });
32753
33232
 
@@ -38733,6 +39212,39 @@ var init_errors2 = __esm({
38733
39212
  * - `value` — `ns.max` read as a value. Component tags resolve; plain value
38734
39213
  * reads do not, because nothing binds `ns` at runtime.
38735
39214
  */
39215
+ /**
39216
+ * An imported `.ts`/`.js` module could not be parsed.
39217
+ *
39218
+ * This used to be silent, and that is the whole point of the diagnostic. A
39219
+ * parse failure meant the module's RAW, untranspiled source was substituted,
39220
+ * so TypeScript syntax reached `new Function` and the module blew up much
39221
+ * later with a bare `Unexpected token ':'` — attributed to no file, at a
39222
+ * point in the build far from the code that caused it. It also poisoned the
39223
+ * whole shared module graph: one unparseable module left its exports
39224
+ * undefined, so unrelated consumers failed with `X is not iterable`.
39225
+ *
39226
+ * Two real constructs hit this: a parameter annotation that survived the
39227
+ * stripper only when the parameter also had a default value, and a generic
39228
+ * arrow's type parameter list, which the JSX tokenizer cannot read at all.
39229
+ * Both are fixed; this error exists so the NEXT such gap is reported at the
39230
+ * right file with the right line instead of surfacing three modules later.
39231
+ */
39232
+ static moduleParseFailed(context = {}) {
39233
+ return new _VeskError(`Could not parse an imported module${context.reason ? `: ${context.reason}` : "."}`, {
39234
+ ...context,
39235
+ code: context.code || "V0901",
39236
+ suggestions: [
39237
+ "Check the line the ^ marker points at \u2014 it is the construct the parser stopped on.",
39238
+ "If it is TypeScript syntax the stripper does not handle, simplifying it here fixes every module that imports this file.",
39239
+ "This is a bug in the compiler, not in your code, if the construct is ordinary TypeScript \u2014 please report it with the source line."
39240
+ ],
39241
+ nextSteps: [
39242
+ "A module that fails to parse is substituted with its raw source, so every type annotation it contains becomes a runtime SyntaxError.",
39243
+ "The failure is reported here, at the offending file and line, rather than as an `Unexpected token` in whichever module happened to import it."
39244
+ ],
39245
+ tip: "Ordinary TypeScript should parse; if this fires on valid TS, the parser is missing a construct."
39246
+ });
39247
+ }
38736
39248
  static vskNamespaceMember(context = {}) {
38737
39249
  const nested = context.form === "nested";
38738
39250
  return new _VeskError(nested ? "A `.vsk` namespace is flat, so `<ns.Sub.Icon />` cannot be resolved." : "A `.vsk` namespace resolves component tags only, so `ns.value` is not available.", {
@@ -46239,12 +46751,182 @@ function preprocessForClauses2(source) {
46239
46751
  }
46240
46752
  return { code: chars.join(""), annotations };
46241
46753
  }
46754
+ function blankGenericArrowTypeParams2(source) {
46755
+ let changed = false;
46756
+ const chars = source.split("");
46757
+ let i = 0;
46758
+ const isSpace = (ch) => isSpaceChar2(ch);
46759
+ while (i < source.length) {
46760
+ const ch = source[i];
46761
+ if (ch === '"' || ch === "'" || ch === "`") {
46762
+ const quote = ch;
46763
+ let j2 = i + 1;
46764
+ while (j2 < source.length) {
46765
+ if (source[j2] === "\\") {
46766
+ j2 += 2;
46767
+ continue;
46768
+ }
46769
+ if (source[j2] === quote) {
46770
+ j2++;
46771
+ break;
46772
+ }
46773
+ if (quote === "`" && source[j2] === "$" && source[j2 + 1] === "{") {
46774
+ let depth = 1;
46775
+ j2 += 2;
46776
+ while (j2 < source.length && depth > 0) {
46777
+ if (source[j2] === "{")
46778
+ depth++;
46779
+ else if (source[j2] === "}")
46780
+ depth--;
46781
+ j2++;
46782
+ }
46783
+ continue;
46784
+ }
46785
+ j2++;
46786
+ }
46787
+ i = j2;
46788
+ continue;
46789
+ }
46790
+ if (ch === "/" && source[i + 1] === "/") {
46791
+ while (i < source.length && source[i] !== "\n")
46792
+ i++;
46793
+ continue;
46794
+ }
46795
+ if (ch === "/" && source[i + 1] === "*") {
46796
+ i += 2;
46797
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/"))
46798
+ i++;
46799
+ i += 2;
46800
+ continue;
46801
+ }
46802
+ if (ch !== "<") {
46803
+ i++;
46804
+ continue;
46805
+ }
46806
+ let j = i + 1;
46807
+ let angle = 1;
46808
+ let end = -1;
46809
+ let bail = false;
46810
+ while (j < source.length) {
46811
+ const c = source[j];
46812
+ if (c === "<") {
46813
+ angle++;
46814
+ j++;
46815
+ continue;
46816
+ }
46817
+ if (c === ">") {
46818
+ angle--;
46819
+ j++;
46820
+ if (angle === 0) {
46821
+ end = j;
46822
+ break;
46823
+ }
46824
+ continue;
46825
+ }
46826
+ if (c === "(" || c === "[" || c === "{") {
46827
+ const close = c === "(" ? ")" : c === "[" ? "]" : "}";
46828
+ let depth = 0;
46829
+ while (j < source.length) {
46830
+ const d = source[j];
46831
+ if (d === c)
46832
+ depth++;
46833
+ else if (d === close) {
46834
+ depth--;
46835
+ if (depth === 0) {
46836
+ j++;
46837
+ break;
46838
+ }
46839
+ }
46840
+ j++;
46841
+ }
46842
+ continue;
46843
+ }
46844
+ if (c === ";" || c === "\n") {
46845
+ bail = true;
46846
+ break;
46847
+ }
46848
+ j++;
46849
+ }
46850
+ if (bail || end < 0) {
46851
+ i++;
46852
+ continue;
46853
+ }
46854
+ if (!isArrowParameterList2(source, end)) {
46855
+ i = end;
46856
+ continue;
46857
+ }
46858
+ for (let p = i; p < end; p++) {
46859
+ if (chars[p] !== "\n")
46860
+ chars[p] = " ";
46861
+ }
46862
+ changed = true;
46863
+ i = end;
46864
+ }
46865
+ return changed ? chars.join("") : source;
46866
+ }
46867
+ function isArrowParameterList2(source, from) {
46868
+ let i = from;
46869
+ while (i < source.length && isSpaceChar2(source[i]))
46870
+ i++;
46871
+ if (source[i] !== "(")
46872
+ return false;
46873
+ let depth = 0;
46874
+ while (i < source.length) {
46875
+ const ch = source[i];
46876
+ if (ch === "(" || ch === "[" || ch === "{") {
46877
+ depth++;
46878
+ i++;
46879
+ continue;
46880
+ }
46881
+ if (ch === ")" || ch === "]" || ch === "}") {
46882
+ depth--;
46883
+ i++;
46884
+ if (depth === 0)
46885
+ break;
46886
+ continue;
46887
+ }
46888
+ i++;
46889
+ }
46890
+ if (depth !== 0)
46891
+ return false;
46892
+ while (i < source.length && isSpaceChar2(source[i]))
46893
+ i++;
46894
+ if (source[i] === ":") {
46895
+ i++;
46896
+ let tdepth = 0;
46897
+ while (i < source.length) {
46898
+ const ch = source[i];
46899
+ if (ch === "(" || ch === "[" || ch === "{") {
46900
+ tdepth++;
46901
+ i++;
46902
+ continue;
46903
+ }
46904
+ if (ch === ")" || ch === "]" || ch === "}") {
46905
+ if (tdepth === 0)
46906
+ return false;
46907
+ tdepth--;
46908
+ i++;
46909
+ continue;
46910
+ }
46911
+ if (tdepth === 0 && ch === "=" && source[i + 1] === ">")
46912
+ return true;
46913
+ if (tdepth === 0 && (ch === ";" || ch === "\n"))
46914
+ return false;
46915
+ i++;
46916
+ }
46917
+ return false;
46918
+ }
46919
+ return source[i] === "=" && source[i + 1] === ">";
46920
+ }
46921
+ function isSpaceChar2(ch) {
46922
+ return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f" || ch === "\v";
46923
+ }
46242
46924
  function createBaseParser2() {
46243
46925
  return Parser.extend(tsPlugin2({}), VeskParserPlugin());
46244
46926
  }
46245
46927
  function parse5(source, options = {}) {
46246
46928
  const ParserClass = createBaseParser2();
46247
- const { code, annotations } = preprocessForClauses2(blankComments(source));
46929
+ const { code, annotations } = preprocessForClauses2(blankGenericArrowTypeParams2(blankComments(source)));
46248
46930
  const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
46249
46931
  const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
46250
46932
  let parseable = code;
@@ -49189,12 +49871,26 @@ ${entry.code}
49189
49871
  write: false,
49190
49872
  logLevel: "silent",
49191
49873
  loader: { ".js": "tsx" },
49874
+ // Bundled dependencies (lucide-vesk above all) carry a license
49875
+ // banner per module, and a barrel import pulls in hundreds of
49876
+ // them. Those banners were ~339 KB of a 350 KB chunk, which is
49877
+ // what kept a barrel import from being usable at all. Attribution
49878
+ // for a dependency stays in its own package; shipping every
49879
+ // module's header inside our own chunk adds nothing.
49880
+ legalComments: "none",
49192
49881
  ...appTsconfig ? { tsconfig: appTsconfig } : {}
49193
49882
  });
49194
49883
  finalCode = result.outputFiles[0].text;
49195
49884
  } catch (e) {
49196
49885
  const err = e;
49197
- console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
49886
+ const detail = err?.errors?.map((x) => {
49887
+ const at2 = x.location?.file ? ` (${x.location.file}${x.location.line ? `:${x.location.line}` : ""})` : "";
49888
+ return x.text + at2;
49889
+ }).join(" | ") || err?.message || String(e);
49890
+ console.error("[vesk] chunk bundle failed", entry.name, detail);
49891
+ if (options?.strict) {
49892
+ throw new Error(`[vesk] chunk bundle failed: ${entry.name} \u2014 ${detail}`);
49893
+ }
49198
49894
  const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
49199
49895
  finalCode = chunkIIFE(nativeLibraryImportStubs(entry.code) + stripped);
49200
49896
  } finally {
@@ -50378,6 +51074,8 @@ async function build2(appDir, options) {
50378
51074
  bundleOpts.codeSplit = true;
50379
51075
  if (options?.hmr)
50380
51076
  bundleOpts.hmr = true;
51077
+ if (options?.strict)
51078
+ bundleOpts.strict = true;
50381
51079
  if (options?.routeDataCache !== void 0)
50382
51080
  bundleOpts.routeDataCache = options.routeDataCache;
50383
51081
  if (pluginsPipelines.length > 0)
@@ -50756,17 +51454,41 @@ function stripTsTypes2(ast) {
50756
51454
  }
50757
51455
  });
50758
51456
  }
51457
+ function stripParamTypes2(p) {
51458
+ if (!p)
51459
+ return;
51460
+ if (p.typeAnnotation)
51461
+ p.typeAnnotation = null;
51462
+ if (p.optional)
51463
+ p.optional = false;
51464
+ switch (p.type) {
51465
+ case "AssignmentPattern":
51466
+ stripParamTypes2(p.left);
51467
+ break;
51468
+ case "RestElement":
51469
+ stripParamTypes2(p.argument);
51470
+ break;
51471
+ case "ObjectPattern":
51472
+ for (const prop of p.properties || []) {
51473
+ stripParamTypes2(prop.value || prop.argument || prop);
51474
+ }
51475
+ break;
51476
+ case "ArrayPattern":
51477
+ for (const el of p.elements || [])
51478
+ if (el)
51479
+ stripParamTypes2(el);
51480
+ break;
51481
+ default:
51482
+ break;
51483
+ }
51484
+ }
50759
51485
  function stripFunctionTypes2(node) {
50760
51486
  if (node.returnType)
50761
51487
  node.returnType = null;
50762
51488
  if (node.typeParameters)
50763
51489
  node.typeParameters = null;
50764
- for (const p of node.params || []) {
50765
- if (p.typeAnnotation)
50766
- p.typeAnnotation = null;
50767
- if (p.optional)
50768
- p.optional = false;
50769
- }
51490
+ for (const p of node.params || [])
51491
+ stripParamTypes2(p);
50770
51492
  }
50771
51493
  function stripCodeTypes2(code) {
50772
51494
  let ast;
@@ -53546,6 +54268,10 @@ function matchUrl(tree, pathname) {
53546
54268
  pushWithStandalone(node);
53547
54269
  return true;
53548
54270
  }
54271
+ if (partIndex >= parts.length && node.page && node.fullPath === "/" + parts.join("/")) {
54272
+ pushWithStandalone(node);
54273
+ return true;
54274
+ }
53549
54275
  continue;
53550
54276
  }
53551
54277
  if (node.fullPath === "/") {
@@ -55115,12 +55841,26 @@ ${entry.code}
55115
55841
  write: false,
55116
55842
  logLevel: "silent",
55117
55843
  loader: { ".js": "tsx" },
55844
+ // Bundled dependencies (lucide-vesk above all) carry a license
55845
+ // banner per module, and a barrel import pulls in hundreds of
55846
+ // them. Those banners were ~339 KB of a 350 KB chunk, which is
55847
+ // what kept a barrel import from being usable at all. Attribution
55848
+ // for a dependency stays in its own package; shipping every
55849
+ // module's header inside our own chunk adds nothing.
55850
+ legalComments: "none",
55118
55851
  ...appTsconfig ? { tsconfig: appTsconfig } : {}
55119
55852
  });
55120
55853
  finalCode = result.outputFiles[0].text;
55121
55854
  } catch (e) {
55122
55855
  const err = e;
55123
- console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
55856
+ const detail = err?.errors?.map((x) => {
55857
+ const at2 = x.location?.file ? ` (${x.location.file}${x.location.line ? `:${x.location.line}` : ""})` : "";
55858
+ return x.text + at2;
55859
+ }).join(" | ") || err?.message || String(e);
55860
+ console.error("[vesk] chunk bundle failed", entry.name, detail);
55861
+ if (options?.strict) {
55862
+ throw new Error(`[vesk] chunk bundle failed: ${entry.name} \u2014 ${detail}`);
55863
+ }
55124
55864
  const stripped = demoteExports2(removeCompiledNodes2(entry.code, isAnyImport2));
55125
55865
  finalCode = chunkIIFE(nativeLibraryImportStubs2(entry.code) + stripped);
55126
55866
  } finally {
@@ -63558,7 +64298,7 @@ if (cmd === "build") {
63558
64298
  const config = rawConfig;
63559
64299
  const plugins = config.plugins || [];
63560
64300
  const mdCfg = config.md;
63561
- const opts = { outDir, publicDir, plugins, seo, strictSeo: strict, codeSplit: !restArgs.includes("--skip-split"), target };
64301
+ const opts = { outDir, publicDir, plugins, seo, strictSeo: strict, strict, codeSplit: !restArgs.includes("--skip-split"), target };
63562
64302
  if (mdCfg) opts.md = mdCfg;
63563
64303
  if (config.routeDataCache !== void 0) opts.routeDataCache = config.routeDataCache;
63564
64304
  if (platform) opts.platform = platform;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/vesk-cli",
3
- "version": "0.2.50",
3
+ "version": "0.2.52",
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.50",
12
- "@vesk/compiler": "^0.2.50",
13
- "@vesk/plugin-tailwind": "^0.2.50",
14
- "@vesk/runtime": "^0.2.50",
11
+ "@vesk/adapter": "^0.2.52",
12
+ "@vesk/compiler": "^0.2.52",
13
+ "@vesk/plugin-tailwind": "^0.2.52",
14
+ "@vesk/runtime": "^0.2.52",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",