tutuca 0.9.107 → 0.9.108

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.
@@ -4424,19 +4424,12 @@ class Path {
4424
4424
  eventIds.push(eid);
4425
4425
  const metas = metaChain(node.previousSibling);
4426
4426
  let sawComp = false;
4427
- for (let i = 0;i < metas.length; i++) {
4428
- const m = metas[i];
4427
+ for (const m of metas) {
4429
4428
  if (m.$ === "Comp") {
4430
4429
  sawComp = true;
4431
4430
  if (!crossComponent(m.cid, m.vid))
4432
4431
  return NO_EVENT_INFO;
4433
- const outer = metas[i + 1];
4434
- if (outer?.$ === "Each" && outer.nid === m.nid) {
4435
- nodeIds.push({ nid: outer.nid, si: outer.si, sk: outer.sk });
4436
- i += 1;
4437
- } else {
4438
- nodeIds.push({ nid: m.nid });
4439
- }
4432
+ nodeIds.push({ nid: m.nid });
4440
4433
  } else {
4441
4434
  nodeIds.push({ nid: m.nid, si: m.si, sk: m.sk });
4442
4435
  }
@@ -4743,7 +4736,7 @@ class ValParser {
4743
4736
  parseToken(s, px) {
4744
4737
  const c0 = s.charCodeAt(0);
4745
4738
  if (c0 === 39)
4746
- return s.length >= 2 && s.charCodeAt(s.length - 1) === 39 ? new ConstVal(unescapeStr(s.slice(1, -1)), K_STR | K_STRTPL) : null;
4739
+ return s.length >= 2 && s.charCodeAt(s.length - 1) === 39 ? new ConstVal(unescapeStr(s.slice(1, -1))) : null;
4747
4740
  if (c0 === 36 && s.charCodeAt(1) === 39)
4748
4741
  return s.length >= 3 && s.charCodeAt(s.length - 1) === 39 ? StrTplVal.parse(s.slice(2, -1), px) : null;
4749
4742
  if (s.indexOf("[") !== -1 || s.indexOf("]") !== -1)
@@ -4768,14 +4761,18 @@ class ValParser {
4768
4761
  }
4769
4762
  case 36:
4770
4763
  return mkVal(s.slice(1), MethodVal);
4771
- case 64:
4772
- return mkVal(s.slice(1), BindVal);
4764
+ case 64: {
4765
+ const dot = s.indexOf(".", 1);
4766
+ if (dot === -1)
4767
+ return mkVal(s.slice(1), BindVal);
4768
+ const name = s.slice(1, dot);
4769
+ const member = s.slice(dot + 1);
4770
+ return isValidValId(name) && isValidValId(member) ? new BindMemberVal(name, member) : null;
4771
+ }
4773
4772
  case 42:
4774
4773
  return mkVal(s.slice(1), DynVal);
4775
4774
  case 46:
4776
4775
  return mkVal(s.slice(1), FieldVal);
4777
- case 33:
4778
- return mkVal(s.slice(1), RequestVal);
4779
4776
  }
4780
4777
  const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
4781
4778
  if (Number.isFinite(num))
@@ -4828,7 +4825,7 @@ class ValParser {
4828
4825
  return this._parseSingle(s, px, G_PROVIDE);
4829
4826
  }
4830
4827
  parseHandlerArg(s, px) {
4831
- return this._parseSingle(s, px, G_HANDLER_ARG);
4828
+ return this._parseSingle(s, px, G_VALUE);
4832
4829
  }
4833
4830
  parseMacroAttr(s, px) {
4834
4831
  return this._parseSingle(s, px, G_ALL);
@@ -4860,7 +4857,7 @@ class ValParser {
4860
4857
  const args = new Array(tokens.length - 1);
4861
4858
  for (let i = 1;i < tokens.length; i++) {
4862
4859
  const val = this.parseToken(tokens[i], px);
4863
- if (val !== null && kindOf(val) & G_HANDLER_ARG)
4860
+ if (val !== null && kindOf(val) & G_VALUE)
4864
4861
  args[i - 1] = val;
4865
4862
  else {
4866
4863
  if (report)
@@ -4886,7 +4883,7 @@ class ValParser {
4886
4883
  for (let i = 0;i < arity; i++) {
4887
4884
  const tok = tokens[i + 1];
4888
4885
  const val = this.parseToken(tok, px);
4889
- if (val === null || !(kindOf(val) & G_PRED_ARG)) {
4886
+ if (val === null || !(kindOf(val) & G_BOOL)) {
4890
4887
  px.onParseIssue("bad-value", { role: "predicate-arg", value: tok });
4891
4888
  return null;
4892
4889
  }
@@ -4901,7 +4898,7 @@ function kindOf(val) {
4901
4898
  if (val instanceof ConstVal)
4902
4899
  return val.kind;
4903
4900
  if (val instanceof StrTplVal)
4904
- return K_STRTPL;
4901
+ return val.kind;
4905
4902
  if (val instanceof SeqAccessVal)
4906
4903
  return K_SEQ;
4907
4904
  if (val instanceof FieldVal)
@@ -4912,8 +4909,6 @@ function kindOf(val) {
4912
4909
  return K_BIND;
4913
4910
  if (val instanceof DynVal)
4914
4911
  return K_DYN;
4915
- if (val instanceof RequestVal)
4916
- return K_REQUEST;
4917
4912
  if (val instanceof TypeVal)
4918
4913
  return K_TYPE;
4919
4914
  if (val instanceof NameVal)
@@ -4931,13 +4926,13 @@ class BaseVal {
4931
4926
  return this.eval(stack);
4932
4927
  }
4933
4928
  }
4934
- var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64, K_REQUEST = 128, K_SEQ = 256, K_STR = 512, K_METHOD = 1024, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_PRED_ARG, G_HANDLER_ARG, G_ALL, predTruthy = (v) => {
4929
+ var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64, K_SEQ = 256, K_METHOD = 1024, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_ALL, predTruthy = (v) => {
4935
4930
  const n = sizeOf(v);
4936
4931
  return n === null ? !!v : n > 0;
4937
4932
  }, PREDICATES, ConstVal, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler = (type, name) => function(...args) {
4938
4933
  console.warn("handler not found", { type, name, args }, this);
4939
4934
  return this;
4940
- }, TypeVal, RequestVal, RenderVal, RenderNameVal, BindVal, DynVal, FieldVal, MethodVal, SeqAccessVal, vp;
4935
+ }, TypeVal, RenderVal, RenderNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal, vp;
4941
4936
  var init_value = __esm(() => {
4942
4937
  init_immutable();
4943
4938
  init_path();
@@ -4950,10 +4945,8 @@ var init_value = __esm(() => {
4950
4945
  G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
4951
4946
  G_SEQUENCE = K_FIELD | K_DYN;
4952
4947
  G_PROVIDE = K_FIELD | K_SEQ;
4953
- G_FIELD = K_FIELD | K_METHOD | K_CONST | K_STR | K_SEQ;
4954
- G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_REQUEST | K_CONST;
4955
- G_PRED_ARG = G_BOOL | K_STR;
4956
- G_HANDLER_ARG = G_VALUE | K_STR;
4948
+ G_FIELD = K_FIELD | K_METHOD | K_CONST | K_SEQ;
4949
+ G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_CONST;
4957
4950
  G_ALL = G_VALUE | K_STRTPL | K_SEQ;
4958
4951
  PREDICATES = {
4959
4952
  "empty?": { name: "empty?", arity: 1, fn: (v) => v == null || sizeOf(v) === 0 },
@@ -5002,6 +4995,13 @@ var init_value = __esm(() => {
5002
4995
  constructor(vals) {
5003
4996
  super();
5004
4997
  this.vals = vals;
4998
+ this.kind = this.isLiteral() ? K_CONST : K_STRTPL;
4999
+ }
5000
+ isLiteral() {
5001
+ for (const v of this.vals)
5002
+ if (!(v instanceof ConstVal) || v.fromMacroVar)
5003
+ return false;
5004
+ return true;
5005
5005
  }
5006
5006
  render(stack, _rx) {
5007
5007
  return this.eval(stack);
@@ -5013,12 +5013,11 @@ var init_value = __esm(() => {
5013
5013
  return strs.join("");
5014
5014
  }
5015
5015
  toLiteralSource() {
5016
+ if (!this.isLiteral())
5017
+ return null;
5016
5018
  let out = "";
5017
- for (const v of this.vals) {
5018
- if (!(v instanceof ConstVal) || v.fromMacroVar)
5019
- return null;
5019
+ for (const v of this.vals)
5020
5020
  out += v.val;
5021
- }
5022
5021
  return new ConstVal(out).toString();
5023
5022
  }
5024
5023
  static parse(s, px) {
@@ -5065,14 +5064,6 @@ var init_value = __esm(() => {
5065
5064
  return stack.lookupType(this.name);
5066
5065
  }
5067
5066
  };
5068
- RequestVal = class RequestVal extends NameVal {
5069
- eval(stack) {
5070
- return stack.lookupRequest(this.name);
5071
- }
5072
- toString() {
5073
- return `!${this.name}`;
5074
- }
5075
- };
5076
5067
  RenderVal = class RenderVal extends BaseVal {
5077
5068
  render(stack, _rx) {
5078
5069
  return this.eval(stack);
@@ -5092,6 +5083,19 @@ var init_value = __esm(() => {
5092
5083
  return `@${this.name}`;
5093
5084
  }
5094
5085
  };
5086
+ BindMemberVal = class BindMemberVal extends BindVal {
5087
+ constructor(name, member) {
5088
+ super(name);
5089
+ this.member = member;
5090
+ }
5091
+ eval(stack) {
5092
+ const v = stack.lookupBind(this.name);
5093
+ return typeof v?.get === "function" ? v.get(this.member, null) : v?.[this.member] ?? null;
5094
+ }
5095
+ toString() {
5096
+ return `@${this.name}.${this.member}`;
5097
+ }
5098
+ };
5095
5099
  DynVal = class DynVal extends RenderNameVal {
5096
5100
  eval(stack) {
5097
5101
  return stack.lookupDynamic(this.name);
@@ -5234,9 +5238,6 @@ class AttrParser {
5234
5238
  this.attrs.push(new RawHtmlAttr(this._parseDirectiveValue(directiveName, s, vp.parseText)));
5235
5239
  this.hasDynamic = true;
5236
5240
  return;
5237
- case "slot":
5238
- this.pushWrapper("slot", s, vp.const(s));
5239
- return;
5240
5241
  case "push-view":
5241
5242
  this.pushWrapper("push-view", s, this._parseDirectiveValue(directiveName, s, vp.parseText));
5242
5243
  return;
@@ -5346,11 +5347,6 @@ class RequestHandler {
5346
5347
  this.name = name;
5347
5348
  this.fn = fn;
5348
5349
  }
5349
- toHandlerArg(disp) {
5350
- const f = (...args) => disp.request(this.name, args);
5351
- f.withOpts = (...args) => disp.request(this.name, args.slice(0, -1), args.at(-1));
5352
- return f;
5353
- }
5354
5350
  }
5355
5351
  var booleanAttrsRaw = "itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected", booleanAttrs, ConstAttrs, DynAttrs, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr, _attrParser = null;
5356
5352
  var init_attribute = __esm(() => {
@@ -5942,24 +5938,6 @@ class Renderer {
5942
5938
  pushEachEntry(r, nid, attrName, key, dom) {
5943
5939
  r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
5944
5940
  }
5945
- renderEach(stack, iterInfo, node, viewName) {
5946
- const { seq, filter, loopWith } = iterInfo.eval(stack);
5947
- const r = [];
5948
- const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
5949
- const renderOne = (key, value, attrName) => {
5950
- const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
5951
- if (dom != null)
5952
- this.pushEachEntry(r, node.nodeId, attrName, key, dom);
5953
- };
5954
- if (keys)
5955
- imKeysIter(seq, renderOne, keys);
5956
- else
5957
- getSeqInfo(seq)(seq, (key, value, attrName) => {
5958
- if (filter.call(stack.it, key, value, iterData))
5959
- renderOne(key, value, attrName);
5960
- }, start, end);
5961
- return r;
5962
- }
5963
5941
  renderEachWhen(stack, iterInfo, view, nid) {
5964
5942
  const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
5965
5943
  const r = [];
@@ -5970,7 +5948,7 @@ class Renderer {
5970
5948
  const binds = { key, value };
5971
5949
  const cacheKey = `${stack.viewsId ?? ""}\x1F${nid}\x1F${key}`;
5972
5950
  if (enricher)
5973
- enricher.call(it, binds, key, value, iterData);
5951
+ callEnricher(enricher, it, binds, key, value, iterData);
5974
5952
  const cachedNode = this.cache.get(cachePath, cacheKey);
5975
5953
  if (cachedNode)
5976
5954
  this.pushEachEntry(r, nid, attrName, key, cachedNode);
@@ -6017,6 +5995,11 @@ var DATASET_ATTRS, getSeqInfo = (seq) => isIndexed(seq) ? imIndexedIter : isKeye
6017
5995
  s = s < 0 ? 0 : s > size ? size : s;
6018
5996
  e = e < 0 ? 0 : e > size ? size : e;
6019
5997
  return [s, e < s ? s : e];
5998
+ }, callEnricher = (enricher, it, binds, key, value, iterData) => {
5999
+ enricher.call(it, binds, key, value, iterData);
6000
+ console.assert(binds.key === key && binds.value === value, "@enrich-with handlers must not overwrite binds.key or binds.value");
6001
+ binds.key = key;
6002
+ binds.value = value;
6020
6003
  }, filterAlwaysTrue = (_v, _k, _seq) => true, nullLoopWith = (seq) => ({ iterData: { seq } }), unpackLoopResult = (result, seq) => {
6021
6004
  const r = result ?? {};
6022
6005
  return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
@@ -6085,6 +6068,9 @@ class BaseNode {
6085
6068
  isConstant() {
6086
6069
  return false;
6087
6070
  }
6071
+ isWhiteSpace() {
6072
+ return false;
6073
+ }
6088
6074
  optimize() {}
6089
6075
  }
6090
6076
  function optimizeChilds(childs) {
@@ -6106,6 +6092,8 @@ function parseXOp(attrs, childs, opIdx, px) {
6106
6092
  if (attrs.length <= opIdx)
6107
6093
  return maybeFragment(childs);
6108
6094
  const { name, value } = attrs[opIdx];
6095
+ if (X_OPS[name]?.ignoresChildren && hasMeaningfulChilds(childs))
6096
+ px.onParseIssue("x-op-ignores-children", { op: name });
6109
6097
  const asAttr = attrs.getNamedItem("as")?.value ?? null;
6110
6098
  const as = asAttr === null ? null : parseViewName(asAttr, px);
6111
6099
  let node;
@@ -6123,7 +6111,7 @@ function parseXOp(attrs, childs, opIdx, px) {
6123
6111
  node = px.addNodeIf(RenderItNode, vp.bindValIt, as);
6124
6112
  break;
6125
6113
  case "render-each":
6126
- node = RenderEachNode.parse(px, vp, value, as, attrs);
6114
+ node = parseRenderEach(px, value, as, attrs);
6127
6115
  break;
6128
6116
  case "show": {
6129
6117
  const val = parseXOpVal(name, value, px, vp.parseBool);
@@ -6158,8 +6146,12 @@ function processXExtras(node, attrs, opName, startIdx, px) {
6158
6146
  const aName = a.name;
6159
6147
  if (consumed.has(aName))
6160
6148
  continue;
6161
- const wrapper = wrappable ? X_OPS[aName]?.wrapper : null;
6149
+ const atPrefixed = aName.charCodeAt(0) === 64;
6150
+ const baseName = atPrefixed ? aName.slice(1) : aName;
6151
+ const wrapper = wrappable ? X_OPS[baseName]?.wrapper : null;
6162
6152
  if (wrapper) {
6153
+ if (!atPrefixed)
6154
+ maybeDeprecateBareXDirective(px, opName, baseName);
6163
6155
  wrappers.push([wrapper, vp.parseBool(a.value, px)]);
6164
6156
  continue;
6165
6157
  }
@@ -6174,6 +6166,9 @@ function processXExtras(node, attrs, opName, startIdx, px) {
6174
6166
  }
6175
6167
  return node;
6176
6168
  }
6169
+ function maybeDeprecateBareXDirective(px, opName, name) {
6170
+ px.onDeprecatedSyntax("bare-x-directive", { op: opName, name });
6171
+ }
6177
6172
  function wrap(node, px, wrappers) {
6178
6173
  if (wrappers) {
6179
6174
  for (let i = wrappers.length - 1;i >= 0; i--) {
@@ -6202,6 +6197,29 @@ function dynRenderStep(comp, name, key) {
6202
6197
  return null;
6203
6198
  return key === undefined ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
6204
6199
  }
6200
+ function parseRenderEach(px, value, as, attrs) {
6201
+ const seqVal = parseXOpVal("render-each", value, px, vp.parseSequence);
6202
+ if (seqVal === null)
6203
+ return null;
6204
+ const renderIt = px.addNodeIf(RenderItNode, vp.bindValIt, as);
6205
+ const attrParser = getAttrParser(px);
6206
+ const eachAttr = attrParser.eachAttr = attrParser.pushWrapper("each", value, seqVal);
6207
+ const when = attrs.getNamedItem("@when") ?? attrs.getNamedItem("when");
6208
+ if (when) {
6209
+ if (when.name.charCodeAt(0) !== 64)
6210
+ maybeDeprecateBareXDirective(px, "render-each", "when");
6211
+ attrParser._parseWhen(when.value);
6212
+ }
6213
+ const lWith = attrs.getNamedItem("loop-with");
6214
+ if (lWith)
6215
+ attrParser._parseLoopWith(lWith.value);
6216
+ const each = px.addNodeIf(EachNode, seqVal);
6217
+ each.iterInfo.whenVal = eachAttr.whenVal ?? null;
6218
+ each.iterInfo.loopWithVal = eachAttr.loopWithVal ?? null;
6219
+ each.fromRenderEach = true;
6220
+ each.wrapNode(renderIt);
6221
+ return each;
6222
+ }
6205
6223
 
6206
6224
  class IterInfo {
6207
6225
  constructor(val, whenVal, loopWithVal, enrichWithVal) {
@@ -6223,13 +6241,13 @@ class IterInfo {
6223
6241
  const binds = { key, value };
6224
6242
  if (enricher) {
6225
6243
  const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
6226
- enricher.call(stack.it, binds, key, value, iterData);
6244
+ callEnricher(enricher, stack.it, binds, key, value, iterData);
6227
6245
  }
6228
6246
  return binds;
6229
6247
  }
6230
6248
  }
6231
- function xOp(consumed = [], { wrappable = false, wrapper = null } = {}) {
6232
- return { consumed: new Set(consumed), wrappable, wrapper };
6249
+ function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
6250
+ return { consumed: new Set(consumed), wrappable, wrapper, ignoresChildren };
6233
6251
  }
6234
6252
 
6235
6253
  class ParseContext {
@@ -6277,9 +6295,9 @@ class ParseContext {
6277
6295
  const anySlot = [];
6278
6296
  const slots = { _: new FragmentNode(anySlot) };
6279
6297
  for (const child of childs)
6280
- if (child instanceof SlotNode)
6298
+ if (child.isSlotNode)
6281
6299
  slots[child.val.val] = child.node;
6282
- else if (!(child instanceof TextNode) || !child.isWhiteSpace())
6300
+ else if (!child.isWhiteSpace())
6283
6301
  anySlot.push(child);
6284
6302
  const node = new MacroNode(macroName, mAttrs, slots, this);
6285
6303
  this.macroNodes.push(node);
@@ -6303,6 +6321,7 @@ class ParseContext {
6303
6321
  onParseIssue(kind, info) {
6304
6322
  console.warn(`tutuca parse issue [${kind}]`, info);
6305
6323
  }
6324
+ onDeprecatedSyntax(_kind, _info) {}
6306
6325
  }
6307
6326
  function trimEdgeWhite(node) {
6308
6327
  if (!node.isWhiteSpace?.())
@@ -6382,10 +6401,10 @@ function compileModifiers(eventName, names) {
6382
6401
  return w(this, f, args, ctx);
6383
6402
  };
6384
6403
  }
6385
- var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderEachNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, X_OPS, WRAPPER_NODES, _htmlBlockTags = "ADDRESS,ARTICLE,ASIDE,BLOCKQUOTE,CAPTION,COL,COLGROUP,DETAILS,DIALOG,DIV,DD,DL,DT,FIELDSET,FIGCAPTION,FIGURE,FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEADER,HGROUP,HR,LEGEND,LI,MAIN,MENU,NAV,OL,P,PRE,SECTION,SUMMARY,TABLE,TBODY,TD,TFOOT,TH,THEAD,TR,UL", HTML_BLOCK_TAGS, isBlockDomNode = (n) => {
6404
+ var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, X_OPS, WRAPPER_NODES, _htmlBlockTags = "ADDRESS,ARTICLE,ASIDE,BLOCKQUOTE,CAPTION,COL,COLGROUP,DETAILS,DIALOG,DIV,DD,DL,DT,FIELDSET,FIGCAPTION,FIGURE,FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEADER,HGROUP,HR,LEGEND,LI,MAIN,MENU,NAV,OL,P,PRE,SECTION,SUMMARY,TABLE,TBODY,TD,TFOOT,TH,THEAD,TR,UL", HTML_BLOCK_TAGS, isBlockDomNode = (n) => {
6386
6405
  const node = n instanceof FragmentNode ? n.childs[0] : n;
6387
6406
  return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
6388
- }, isEmptyText = (c) => c instanceof TextNode && c.val === "", fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that, fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName), fwdCtrl, fwdMeta, fwdAlt, metaWraps, MOD_WRAPPERS_BY_EVENT, identityModifierWrapper = (f, _ctx) => f;
6407
+ }, isEmptyText = (c) => c instanceof TextNode && c.val === "", isIgnorableXChild = (c) => c instanceof CommentNode || (c.isWhiteSpace?.() ?? false), hasMeaningfulChilds = (childs) => childs.some((c) => !isIgnorableXChild(c)), fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that, fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName), fwdCtrl, fwdMeta, fwdAlt, metaWraps, MOD_WRAPPERS_BY_EVENT, identityModifierWrapper = (f, _ctx) => f;
6389
6408
  var init_anode = __esm(() => {
6390
6409
  init_attribute();
6391
6410
  init_path();
@@ -6617,36 +6636,6 @@ var init_anode = __esm(() => {
6617
6636
  return null;
6618
6637
  }
6619
6638
  };
6620
- RenderEachNode = class RenderEachNode extends RenderViewId {
6621
- constructor(nodeId, val, viewVal) {
6622
- super(nodeId, val, viewVal);
6623
- this.iterInfo = new IterInfo(val, null, null, null);
6624
- }
6625
- render(stack, rx) {
6626
- return rx.renderEach(stack, this.iterInfo, this, this.evalViewName(stack));
6627
- }
6628
- toPathStep(ctx) {
6629
- if (this.val instanceof DynVal)
6630
- return ctx.hasKey ? dynRenderStep(ctx.comp, this.val.name, ctx.key) : null;
6631
- return super.toPathStep(ctx);
6632
- }
6633
- static parse(px, vp2, s, as, attrs) {
6634
- const node = px.addNodeIf(RenderEachNode, parseXOpVal("render-each", s, px, vp2.parseSequence), as);
6635
- if (node !== null) {
6636
- const attrParser = getAttrParser(px);
6637
- attrParser.eachAttr = attrParser.pushWrapper("each", s, node.val);
6638
- const when = attrs.getNamedItem("when");
6639
- if (when)
6640
- attrParser._parseWhen(when.value);
6641
- const lWith = attrs.getNamedItem("loop-with");
6642
- if (lWith)
6643
- attrParser._parseLoopWith(lWith.value);
6644
- node.iterInfo.whenVal = attrParser.eachAttr.whenVal ?? null;
6645
- node.iterInfo.loopWithVal = attrParser.eachAttr.loopWithVal ?? null;
6646
- }
6647
- return node;
6648
- }
6649
- };
6650
6639
  RenderTextNode = class RenderTextNode extends ANode {
6651
6640
  render(stack, _rx) {
6652
6641
  return this.val.eval(stack);
@@ -6699,6 +6688,7 @@ var init_anode = __esm(() => {
6699
6688
  }
6700
6689
  };
6701
6690
  SlotNode = class SlotNode extends WrapperNode {
6691
+ isSlotNode = true;
6702
6692
  optimize() {
6703
6693
  this.node.optimize();
6704
6694
  }
@@ -6733,15 +6723,17 @@ var init_anode = __esm(() => {
6733
6723
  };
6734
6724
  X_OPS = {
6735
6725
  slot: xOp(),
6736
- text: xOp([], { wrappable: true }),
6737
- render: xOp(["as"], { wrappable: true }),
6738
- "render-it": xOp(["as"], { wrappable: true }),
6739
- "render-each": xOp(["as", "when", "loop-with"], { wrappable: true }),
6726
+ text: xOp([], { wrappable: true, ignoresChildren: true }),
6727
+ render: xOp(["as"], { wrappable: true, ignoresChildren: true }),
6728
+ "render-it": xOp(["as"], { wrappable: true, ignoresChildren: true }),
6729
+ "render-each": xOp(["as", "when", "loop-with", "@when"], {
6730
+ wrappable: true,
6731
+ ignoresChildren: true
6732
+ }),
6740
6733
  show: xOp([], { wrapper: ShowNode }),
6741
6734
  hide: xOp([], { wrapper: HideNode })
6742
6735
  };
6743
6736
  WRAPPER_NODES = {
6744
- slot: SlotNode,
6745
6737
  show: ShowNode,
6746
6738
  hide: HideNode,
6747
6739
  each: EachNode,
@@ -9011,14 +9003,17 @@ function closestName(name, candidates, maxDistance = 2) {
9011
9003
 
9012
9004
  // tools/core/lint-check.js
9013
9005
  function protoHasMethod(proto, name) {
9006
+ return protoMethodValue(proto, name) !== null;
9007
+ }
9008
+ function protoMethodValue(proto, name) {
9014
9009
  let cursor = proto;
9015
9010
  while (cursor && cursor !== Object.prototype) {
9016
9011
  const desc = Object.getOwnPropertyDescriptor(cursor, name);
9017
9012
  if (desc !== undefined)
9018
- return typeof desc.value === "function";
9013
+ return typeof desc.value === "function" ? desc.value : null;
9019
9014
  cursor = Object.getPrototypeOf(cursor);
9020
9015
  }
9021
- return false;
9016
+ return null;
9022
9017
  }
9023
9018
  function collectProtoMethodNames(proto) {
9024
9019
  const out = [];
@@ -9062,6 +9057,8 @@ function classifyBadValue(value) {
9062
9057
  return "logical";
9063
9058
  if (/^[.$][A-Za-z_]\w*\s+\S/.test(s))
9064
9059
  return "call-with-args";
9060
+ if (/^\.[A-Za-z_]\w*\??(\.[A-Za-z_]\w*\??)+$/.test(s))
9061
+ return "field-path";
9065
9062
  return null;
9066
9063
  }
9067
9064
  function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SET2 } = {}) {
@@ -9090,6 +9087,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
9090
9087
  function checkView(lx, view, Comp, referencedAlters, referencedDynamics) {
9091
9088
  checkParseIssues(lx, view);
9092
9089
  checkRenderItInLoop(lx, view);
9090
+ checkEnrichProjection(lx, view, Comp);
9093
9091
  checkEventModifiers(lx, view);
9094
9092
  checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedDynamics);
9095
9093
  checkMacroCallArgs(lx, view, Comp);
@@ -9105,11 +9103,31 @@ function checkParseIssues(lx, view) {
9105
9103
  if (!issues)
9106
9104
  return;
9107
9105
  for (const { kind, info } of issues) {
9106
+ if (kind === "deprecated:bare-x-directive") {
9107
+ lx.warn(DEPRECATED_BARE_X_DIRECTIVE, info, {
9108
+ kind: "add-prefix",
9109
+ from: info.name,
9110
+ to: `@${info.name}`
9111
+ });
9112
+ continue;
9113
+ }
9114
+ if (kind === "x-op-ignores-children") {
9115
+ lx.warn(X_OP_IGNORES_CHILDREN, info, { kind: "remove", what: "the ignored children" });
9116
+ continue;
9117
+ }
9108
9118
  const rule = PARSE_ISSUES[kind];
9109
9119
  if (!rule)
9110
9120
  continue;
9111
9121
  const id = rule.id;
9112
9122
  if (kind === "bad-value") {
9123
+ if (typeof info.value === "string" && BINDING_MEMBER_TOO_DEEP_RE.test(info.value.trim())) {
9124
+ lx.error(BINDING_MEMBER_TOO_DEEP, info, {
9125
+ kind: "rephrase",
9126
+ from: info.value,
9127
+ text: "Read one level off the binding and compute the rest in a method or an '@enrich-with' handler."
9128
+ });
9129
+ continue;
9130
+ }
9113
9131
  const detected = classifyBadValue(info.value);
9114
9132
  if (detected) {
9115
9133
  lx.error(UNSUPPORTED_EXPR_SYNTAX, { ...info, detected }, { kind: "rephrase", from: info.value, text: UNSUPPORTED_EXPR_GUIDANCE[detected] });
@@ -9156,6 +9174,54 @@ function checkRenderItInLoop(lx, view) {
9156
9174
  return;
9157
9175
  walkForRenderIt(lx, view.anode, 0);
9158
9176
  }
9177
+ function pureProjectionBinds(fn) {
9178
+ const src = Function.prototype.toString.call(fn);
9179
+ const head = src.match(/^[^(]*\(([^)]*)\)\s*(?:=>)?\s*/);
9180
+ if (!head)
9181
+ return null;
9182
+ const params = head[1].split(",").map((p) => p.trim());
9183
+ const [bindsName, , valueName] = params;
9184
+ if (!/^\w+$/.test(bindsName ?? "") || !/^\w+$/.test(valueName ?? ""))
9185
+ return null;
9186
+ let body = src.slice(head[0].length).trim();
9187
+ if (body.startsWith("{")) {
9188
+ if (!body.endsWith("}"))
9189
+ return null;
9190
+ body = body.slice(1, -1);
9191
+ }
9192
+ const statements = body.split(/[;\n]/).map((s) => s.trim()).filter((s) => s !== "" && !s.startsWith("//"));
9193
+ if (statements.length === 0)
9194
+ return null;
9195
+ const projectionRe = new RegExp(`^${bindsName}\\.(\\w+)\\s*=\\s*${valueName}(?:\\.(\\w+)|\\.get\\((['"])(\\w+)\\3\\))$`);
9196
+ const members = [];
9197
+ for (const statement of statements) {
9198
+ const m = statement.match(projectionRe);
9199
+ if (!m)
9200
+ return null;
9201
+ members.push({ bind: m[1], member: m[2] ?? m[4] });
9202
+ }
9203
+ return members;
9204
+ }
9205
+ function checkEnrichProjection(lx, view, Comp) {
9206
+ for (const node of view.ctx.nodes) {
9207
+ if (node.constructor.name !== "EachNode")
9208
+ continue;
9209
+ const enrich = node.iterInfo?.enrichWithVal;
9210
+ if (!enrich?.name)
9211
+ continue;
9212
+ const fn = enrich.constructor.name === "MethodVal" ? protoMethodValue(Comp.Class?.prototype, enrich.name) : Comp.alter?.[enrich.name];
9213
+ if (typeof fn !== "function")
9214
+ continue;
9215
+ const members = pureProjectionBinds(fn);
9216
+ if (members === null)
9217
+ continue;
9218
+ const rewrites = members.map(({ bind, member }) => `'@${bind}' -> '@value.${member}'`);
9219
+ lx.hint(SUGGEST_BINDING_MEMBER, { name: enrich.name, members }, {
9220
+ kind: "rephrase",
9221
+ text: `Replace ${rewrites.join(", ")} in the view, then remove the '@enrich-with' and the '${enrich.name}' alter handler.`
9222
+ });
9223
+ }
9224
+ }
9159
9225
  function walkForRenderIt(lx, node, loopDepth) {
9160
9226
  if (node === null || node === undefined)
9161
9227
  return;
@@ -9403,7 +9469,7 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
9403
9469
  if (node.val) {
9404
9470
  checkConsistentAttrVal(lx, node.val, env, false, baseCtx);
9405
9471
  }
9406
- if (nodeKind === "RenderEachNode") {
9472
+ if (nodeKind === "EachNode" && node.fromRenderEach) {
9407
9473
  const iter = node.iterInfo;
9408
9474
  if (iter.whenVal)
9409
9475
  checkConsistentAttrVal(lx, iter.whenVal, env, false, {
@@ -9630,7 +9696,7 @@ class LintContext {
9630
9696
  this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
9631
9697
  }
9632
9698
  }
9633
- var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", ASYNC_HANDLER = "ASYNC_HANDLER", TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE", GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE", FIELD_NAME_RESERVED_BY_RECORD = "FIELD_NAME_RESERVED_BY_RECORD", RECORD_FIELD_NAME_COLLISIONS, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun = (m) => m.replace(/[^\n]/g, " "), STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintParseContext;
9699
+ var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", X_OP_IGNORES_CHILDREN = "X_OP_IGNORES_CHILDREN", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", DEPRECATED_BARE_X_DIRECTIVE = "DEPRECATED_BARE_X_DIRECTIVE", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", BINDING_MEMBER_TOO_DEEP = "BINDING_MEMBER_TOO_DEEP", SUGGEST_BINDING_MEMBER = "SUGGEST_BINDING_MEMBER", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", CONSTANT_CONDITION = "CONSTANT_CONDITION", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", ASYNC_HANDLER = "ASYNC_HANDLER", TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE", GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE", FIELD_NAME_RESERVED_BY_RECORD = "FIELD_NAME_RESERVED_BY_RECORD", RECORD_FIELD_NAME_COLLISIONS, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), BOOL_CONDITION_ORIGINS, isBoolConditionCtx = (errCtx) => errCtx != null && (BOOL_CONDITION_ORIGINS.has(errCtx.originAttr) || errCtx.branch === "@if"), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun = (m) => m.replace(/[^\n]/g, " "), STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintParseContext;
9634
9700
  var init_lint_check = __esm(() => {
9635
9701
  init_anode();
9636
9702
  init_htmllinter();
@@ -9673,11 +9739,13 @@ var init_lint_check = __esm(() => {
9673
9739
  },
9674
9740
  "bad-value": { id: BAD_VALUE }
9675
9741
  };
9742
+ BINDING_MEMBER_TOO_DEEP_RE = /^@[a-zA-Z]\w*\??(\.[a-zA-Z]\w*\??){2,}$/;
9676
9743
  UNSUPPORTED_EXPR_GUIDANCE = {
9677
9744
  ternary: "Ternary expressions aren't supported in dynamic attributes. Define a method or computed field on the component that returns the value, then reference it as '$methodName'.",
9678
9745
  comparison: "Comparisons aren't supported in dynamic attributes. Define a method like 'isFooSelected' that returns the boolean, then reference it as '$isFooSelected'.",
9679
9746
  logical: "Logical operators aren't supported in dynamic attributes. Combine the conditions in a method on the component and reference it as '$methodName'.",
9680
- "call-with-args": "Method calls with arguments aren't supported here. Reference a no-arg method ('$methodName') and read what you need from component state, or split into per-case methods."
9747
+ "call-with-args": "Method calls with arguments aren't supported here. Reference a no-arg method ('$methodName') and read what you need from component state, or split into per-case methods.",
9748
+ "field-path": "Fields can't be read through a dotted path. Define a method that returns the value, render a child component for the nested data, or — inside a loop — read one member off a binding ('@value.member')."
9681
9749
  };
9682
9750
  HTML_LINT_OPTS = {
9683
9751
  fragmentContext: "template",
@@ -9704,7 +9772,12 @@ var init_lint_check = __esm(() => {
9704
9772
  "ctx",
9705
9773
  "dragInfo"
9706
9774
  ]);
9775
+ BOOL_CONDITION_ORIGINS = new Set(["@show", "@hide", "<x show>", "<x hide>"]);
9707
9776
  ATTR_VAL_CHECKERS = {
9777
+ ConstVal({ lx, val, errCtx }) {
9778
+ if (isBoolConditionCtx(errCtx) && typeof val.val !== "boolean")
9779
+ lx.warn(CONSTANT_CONDITION, { ...errCtx, literal: String(val) });
9780
+ },
9708
9781
  FieldVal({ lx, val, env, errCtx }) {
9709
9782
  const { fields, proto } = env;
9710
9783
  const { name } = val;
@@ -9732,10 +9805,6 @@ var init_lint_check = __esm(() => {
9732
9805
  recurse(val.seqVal);
9733
9806
  recurse(val.keyVal);
9734
9807
  },
9735
- RequestVal({ lx, val, env, errCtx }) {
9736
- if (env.scope.lookupRequest(val.name) === null)
9737
- reportUnknownName(lx, UNKNOWN_REQUEST_NAME, val.name, scopeKeysAlong(env.scope, "reqsByName"), errCtx);
9738
- },
9739
9808
  TypeVal({ lx, val, env, errCtx }) {
9740
9809
  if (env.scope.lookupComponent(val.name) === null)
9741
9810
  reportUnknownName(lx, UNKNOWN_COMPONENT_NAME, val.name, scopeKeysAlong(env.scope, "byName"), errCtx);
@@ -9748,7 +9817,11 @@ var init_lint_check = __esm(() => {
9748
9817
  const vs = val.vals;
9749
9818
  const literal = val.toLiteralSource();
9750
9819
  if (literal !== null) {
9751
- lx.hint(PLACEHOLDERLESS_TEMPLATE_STRING, { ...errCtx, literal }, fixTo(`$${literal}`, literal));
9820
+ if (isBoolConditionCtx(errCtx))
9821
+ lx.warn(CONSTANT_CONDITION, { ...errCtx, literal });
9822
+ else
9823
+ lx.hint(PLACEHOLDERLESS_TEMPLATE_STRING, { ...errCtx, literal }, fixTo(`$${literal}`, literal));
9824
+ return;
9752
9825
  } else if (vs.length === 1) {
9753
9826
  const simpler = String(vs[0]);
9754
9827
  lx.warn(REDUNDANT_TEMPLATE_STRING, { ...errCtx, simpler }, fixTo(`$'{${simpler}}'`, simpler));
@@ -9775,7 +9848,6 @@ var init_lint_check = __esm(() => {
9775
9848
  RenderTextNode: { originAttr: "<x text>" },
9776
9849
  RenderNode: { originAttr: "<x render>" },
9777
9850
  RenderItNode: { originAttr: "<x render-it>" },
9778
- RenderEachNode: { originAttr: "<x render-each>" },
9779
9851
  ShowNode: { originAttr: "<x show>" },
9780
9852
  HideNode: { originAttr: "<x hide>" },
9781
9853
  PushViewNameNode: { originAttr: "<x push-view>" }
@@ -9800,6 +9872,13 @@ var init_lint_check = __esm(() => {
9800
9872
  const tag = this.currentTag;
9801
9873
  this.parseIssues.push({ kind, info: tag && info.tag === undefined ? { ...info, tag } : info });
9802
9874
  }
9875
+ onDeprecatedSyntax(kind, info) {
9876
+ const tag = this.currentTag;
9877
+ this.parseIssues.push({
9878
+ kind: `deprecated:${kind}`,
9879
+ info: tag && info.tag === undefined ? { ...info, tag } : info
9880
+ });
9881
+ }
9803
9882
  };
9804
9883
  });
9805
9884
 
@@ -9888,6 +9967,12 @@ var init_lint_rules = __esm(() => {
9888
9967
  group: "Iteration helpers (`alter`)",
9889
9968
  summary: "`alter` entry is defined but never used."
9890
9969
  },
9970
+ {
9971
+ code: SUGGEST_BINDING_MEMBER,
9972
+ level: "hint",
9973
+ group: "Iteration helpers (`alter`)",
9974
+ summary: "`@enrich-with` handler only copies members of the loop value — read them directly as `@value.member` and drop the enrich."
9975
+ },
9891
9976
  {
9892
9977
  code: DYN_VAL_NOT_DEFINED,
9893
9978
  level: "error",
@@ -9966,6 +10051,12 @@ var init_lint_rules = __esm(() => {
9966
10051
  group: "Templates / events",
9967
10052
  summary: "Extra attribute on `<x op>` not consumed by the op and not a known wrapper."
9968
10053
  },
10054
+ {
10055
+ code: X_OP_IGNORES_CHILDREN,
10056
+ level: "warn",
10057
+ group: "Templates / events",
10058
+ summary: "`<x text/render/render-it/render-each>` has child content the op silently drops."
10059
+ },
9969
10060
  {
9970
10061
  code: MAYBE_DROP_AT_PREFIX,
9971
10062
  level: "hint",
@@ -9978,6 +10069,12 @@ var init_lint_rules = __esm(() => {
9978
10069
  group: "Templates / events",
9979
10070
  summary: "A directive name (`when`/`enrich-with`/`loop-with`/`show`/`hide`) was written as a plain attribute on a host element — add the `@` prefix."
9980
10071
  },
10072
+ {
10073
+ code: DEPRECATED_BARE_X_DIRECTIVE,
10074
+ level: "warn",
10075
+ group: "Templates / events",
10076
+ summary: "Bare `show`/`hide`/`when` on an `<x>` op is deprecated — use the `@`-prefixed directive (`@show`/`@hide`/`@when`)."
10077
+ },
9981
10078
  {
9982
10079
  code: BAD_VALUE,
9983
10080
  level: "error",
@@ -9988,7 +10085,13 @@ var init_lint_rules = __esm(() => {
9988
10085
  code: UNSUPPORTED_EXPR_SYNTAX,
9989
10086
  level: "error",
9990
10087
  group: "Value expressions",
9991
- summary: "Value uses JS-style syntax (ternary, comparison, logical, call-with-args) tutuca does not support — move the logic into a method."
10088
+ summary: "Value uses JS-style syntax (ternary, comparison, logical, call-with-args, dotted field path) tutuca does not support — move the logic into a method."
10089
+ },
10090
+ {
10091
+ code: BINDING_MEMBER_TOO_DEEP,
10092
+ level: "error",
10093
+ group: "Value expressions",
10094
+ summary: "A binding member read goes more than one level deep (`@x.a.b`) — only one member is allowed."
9992
10095
  },
9993
10096
  {
9994
10097
  code: REDUNDANT_TEMPLATE_STRING,
@@ -10003,10 +10106,10 @@ var init_lint_rules = __esm(() => {
10003
10106
  summary: "`$'…'` template has no `{}` placeholder — use a plain string literal."
10004
10107
  },
10005
10108
  {
10006
- code: UNKNOWN_REQUEST_NAME,
10007
- level: "error",
10008
- group: "Names registered with the app",
10009
- summary: "`!name` references a request handler not registered with the app."
10109
+ code: CONSTANT_CONDITION,
10110
+ level: "warn",
10111
+ group: "Value expressions",
10112
+ summary: "A non-boolean literal in a boolean condition (`@show`, `@hide`, `@if`) never changes — reference a field or method instead."
10010
10113
  },
10011
10114
  {
10012
10115
  code: UNKNOWN_COMPONENT_NAME,
@@ -10179,8 +10282,6 @@ function lintIdToMessage(id, info) {
10179
10282
  }
10180
10283
  case "IF_NO_BRANCH_SET":
10181
10284
  return `'@if.${info.attr}' has no '@then' or '@else' branch — add '@then="…"' or '@else="…"' (or both)${fmtTagSuffix(info)}`;
10182
- case "UNKNOWN_REQUEST_NAME":
10183
- return `Unknown request '!${info.name}'${fmtOriginSuffix(info)}`;
10184
10285
  case "UNKNOWN_COMPONENT_NAME":
10185
10286
  return `Unknown component '${info.name}'${fmtOriginSuffix(info)}`;
10186
10287
  case "ALT_HANDLER_NOT_DEFINED":
@@ -10205,20 +10306,32 @@ function lintIdToMessage(id, info) {
10205
10306
  return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
10206
10307
  case "UNKNOWN_X_ATTR":
10207
10308
  return `Unknown attribute '${info.name}=${JSON.stringify(info.value)}' on <x ${info.op}>${fmtTagSuffix(info)}`;
10309
+ case "X_OP_IGNORES_CHILDREN":
10310
+ return `<x ${info.op}> has child content, but the '${info.op}' op ignores its children — they are silently dropped when the template is parsed; remove them${fmtTagSuffix(info)}`;
10208
10311
  case "MAYBE_DROP_AT_PREFIX": {
10209
10312
  const written = info.value !== undefined ? `${info.name}=${JSON.stringify(info.value)}` : info.name;
10210
10313
  return `'${written}' on <x> looks like a directive but is actually an x op/attr written with a leading '@'`;
10211
10314
  }
10212
10315
  case "MAYBE_ADD_AT_PREFIX":
10213
10316
  return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
10317
+ case "DEPRECATED_BARE_X_DIRECTIVE":
10318
+ return `'${info.name}' on <x ${info.op}> is deprecated — write '@${info.name}' instead${fmtTagSuffix(info)}`;
10214
10319
  case "BAD_VALUE":
10215
10320
  return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
10216
10321
  case "UNSUPPORTED_EXPR_SYNTAX":
10217
10322
  return `${unsupportedExprMessage(info)}${fmtTagSuffix(info)}`;
10323
+ case "BINDING_MEMBER_TOO_DEEP":
10324
+ return `Binding member read ${JSON.stringify(info.value)} goes more than one level deep — only one member is allowed (like '@value.title')${fmtTagSuffix(info)}`;
10325
+ case "SUGGEST_BINDING_MEMBER": {
10326
+ const reads = (info.members ?? []).map(({ member }) => `'@value.${member}'`).join(", ");
10327
+ return `Enrich handler '${info.name}' only copies members of the loop value — read them directly${reads ? ` (${reads})` : ""} and remove the '@enrich-with'`;
10328
+ }
10218
10329
  case "REDUNDANT_TEMPLATE_STRING":
10219
10330
  return `Redundant template string — '{${info.simpler}}' should be just '${info.simpler}'${fmtOriginSuffix(info)}`;
10220
10331
  case "PLACEHOLDERLESS_TEMPLATE_STRING":
10221
10332
  return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
10333
+ case "CONSTANT_CONDITION":
10334
+ return `Condition is the constant literal ${info.literal} — it never changes; reference a field ('.name') or a method ('$name') instead${fmtOriginSuffix(info)}`;
10222
10335
  case "UNKNOWN_COMPONENT_SPEC_KEY":
10223
10336
  return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
10224
10337
  case "COMP_FIELD_BAD_SHAPE":
@@ -10321,7 +10434,8 @@ var init_lint = __esm(() => {
10321
10434
  ternary: "ternary expression",
10322
10435
  comparison: "comparison",
10323
10436
  logical: "logical expression",
10324
- "call-with-args": "method call with arguments"
10437
+ "call-with-args": "method call with arguments",
10438
+ "field-path": "dotted field path"
10325
10439
  };
10326
10440
  });
10327
10441
 
@@ -15129,9 +15243,6 @@ class Stack2 {
15129
15243
  getHandlerFor(name, key) {
15130
15244
  return this.comps.getHandlerFor(this.it, name, key);
15131
15245
  }
15132
- lookupRequest(name) {
15133
- return this.comps.getRequestFor(this.it, name);
15134
- }
15135
15246
  lookupBestView(views, defaultViewName) {
15136
15247
  let n = this.views;
15137
15248
  while (n !== null) {
@@ -15540,13 +15651,6 @@ var init_transactor = __esm(() => {
15540
15651
  const stack = this.buildStack(root, comps);
15541
15652
  const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
15542
15653
  const path = this.dispatchPath;
15543
- let dispatcher;
15544
- for (let i = 0;i < args.length; i++) {
15545
- if (args[i]?.toHandlerArg) {
15546
- dispatcher ??= new Dispatcher(path, this.transactor, this);
15547
- args[i] = args[i].toHandlerArg(dispatcher);
15548
- }
15549
- }
15550
15654
  args.push(new EventContext(path, this.transactor, this));
15551
15655
  return [handler, args];
15552
15656
  }