tutuca 0.9.28 → 0.9.30

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.
package/README.md CHANGED
@@ -11,6 +11,9 @@ Zero-dependency batteries included SPA framework.
11
11
 
12
12
  ## Quick Start
13
13
 
14
+ For an interactive walk-through with editable examples, see the
15
+ [tutorial](https://marianoguerra.github.io/tutuca/tutorial.html).
16
+
14
17
  ### CDN (no install)
15
18
 
16
19
  ```html
@@ -1372,13 +1372,13 @@ class IterInfo {
1372
1372
  }
1373
1373
 
1374
1374
  class ParseContext {
1375
- constructor(DOMParser, Text, Comment, nodes, events, macroNodes, frame, parent) {
1375
+ constructor(document2, Text, Comment, nodes, events, macroNodes, frame, parent) {
1376
1376
  this.nodes = nodes ?? [];
1377
1377
  this.events = events ?? [];
1378
1378
  this.macroNodes = macroNodes ?? [];
1379
1379
  this.parent = parent ?? null;
1380
1380
  this.frame = frame ?? {};
1381
- this.DOMParser = DOMParser ?? globalThis.DOMParser;
1381
+ this.document = document2 ?? globalThis.document;
1382
1382
  this.Text = Text ?? globalThis.Text;
1383
1383
  this.Comment = Comment ?? globalThis.Comment;
1384
1384
  this.cacheConstNodes = true;
@@ -1387,12 +1387,14 @@ class ParseContext {
1387
1387
  return this.frame.macroName === name || this.parent?.isInsideMacro(name);
1388
1388
  }
1389
1389
  enterMacro(macroName, macroVars, macroSlots) {
1390
- const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
1390
+ const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
1391
1391
  const frame = { macroName, macroVars, macroSlots };
1392
- return new ParseContext(DP, Text, Comment, nodes, events, macroNodes, frame, this);
1392
+ return new ParseContext(document2, Text, Comment, nodes, events, macroNodes, frame, this);
1393
1393
  }
1394
- newDOMParser() {
1395
- return new this.DOMParser;
1394
+ parseHTML(html) {
1395
+ const t = this.document.createElement("template");
1396
+ t.innerHTML = html;
1397
+ return Array.from(t.content.childNodes);
1396
1398
  }
1397
1399
  addNodeIf(Class, val, extra) {
1398
1400
  if (val !== null) {
@@ -1515,7 +1517,7 @@ function compileModifiers(eventName, names) {
1515
1517
  return w(this, f, args, ctx);
1516
1518
  };
1517
1519
  }
1518
- var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, _parser = null, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderEachNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, filterAlwaysTrue = (_v, _k, _seq) => true, nullLoopWith = (seq) => ({ seq }), 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) => {
1520
+ 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, filterAlwaysTrue = (_v, _k, _seq) => true, nullLoopWith = (seq) => ({ seq }), 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) => {
1519
1521
  const node = n instanceof FragmentNode ? n.childs[0] : n;
1520
1522
  return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
1521
1523
  }, isMac, 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;
@@ -1612,9 +1614,7 @@ var init_anode = __esm(() => {
1612
1614
  return this.val.toPathItem();
1613
1615
  }
1614
1616
  static parse(html, px) {
1615
- _parser ??= px.newDOMParser();
1616
- const nodes = _parser.parseFromString(html, "text/html").body.childNodes;
1617
- return ANode.fromDOM(nodes[0] ?? new px.Text(""), px);
1617
+ return ANode.fromDOM(px.parseHTML(html)[0] ?? new px.Text(""), px);
1618
1618
  }
1619
1619
  static fromDOM(node, px) {
1620
1620
  if (node instanceof px.Text)
@@ -2258,8 +2258,21 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedComputed) {
2258
2258
  for (const attr of view.ctx.attrs) {
2259
2259
  const { attrs, wrapperAttrs, textChild, isMacroCall } = attr;
2260
2260
  if (attrs?.constructor.name === "DynAttrs") {
2261
+ const seenNames = new Set;
2261
2262
  for (const attr2 of attrs.items) {
2262
- if (attr2?.constructor.name === "Attr") {
2263
+ const name = attr2?.name;
2264
+ if (name !== undefined && name !== "data-eid") {
2265
+ if (seenNames.has(name)) {
2266
+ lx.error(DUPLICATE_ATTR_DEFINITION, { name });
2267
+ } else {
2268
+ seenNames.add(name);
2269
+ }
2270
+ }
2271
+ if (attr2?.constructor.name === "IfAttr") {
2272
+ for (const subVal of [attr2.condVal, attr2.thenVal, attr2.elseVal]) {
2273
+ checkConsistentAttrVal(lx, subVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
2274
+ }
2275
+ } else if (attr2?.val !== undefined) {
2263
2276
  checkConsistentAttrVal(lx, attr2.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
2264
2277
  }
2265
2278
  }
@@ -2346,7 +2359,7 @@ class LintContext {
2346
2359
  this.reports.push({ id, info, level, context: { ...this.frame } });
2347
2360
  }
2348
2361
  }
2349
- var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", 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", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
2362
+ var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", 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", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
2350
2363
  var init_lint_check = __esm(() => {
2351
2364
  init_anode();
2352
2365
  NO_WRAPPERS = {};
@@ -2371,8 +2384,8 @@ var init_lint_check = __esm(() => {
2371
2384
  "dragInfo"
2372
2385
  ]);
2373
2386
  LintParseContext = class LintParseContext extends ParseContext {
2374
- constructor(DOMParser, Text, Comment) {
2375
- super(DOMParser, Text, Comment);
2387
+ constructor(document2, Text, Comment) {
2388
+ super(document2, Text, Comment);
2376
2389
  this.attrs = [];
2377
2390
  }
2378
2391
  onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false) {
@@ -8183,18 +8196,18 @@ init_lint_check();
8183
8196
  import { JSDOM } from "jsdom";
8184
8197
  async function createNodeEnv() {
8185
8198
  const dom = new JSDOM("<!DOCTYPE html><html><head></head><body></body></html>");
8186
- const { DOMParser, Text, Comment } = dom.window;
8187
- globalThis.document = dom.window.document;
8199
+ const { document: document2, Text, Comment } = dom.window;
8200
+ globalThis.document = document2;
8188
8201
 
8189
8202
  class HeadlessParseContext extends ParseContext {
8190
8203
  constructor() {
8191
- super(DOMParser, Text, Comment);
8204
+ super(document2, Text, Comment);
8192
8205
  }
8193
8206
  }
8194
8207
 
8195
8208
  class HeadlessLintParseContext extends LintParseContext {
8196
8209
  constructor() {
8197
- super(DOMParser, Text, Comment);
8210
+ super(document2, Text, Comment);
8198
8211
  }
8199
8212
  }
8200
8213
  return {
@@ -812,6 +812,7 @@ class Attr extends BaseAttr {
812
812
 
813
813
  class ConstAttr extends Attr {
814
814
  }
815
+
815
816
  class RawHtmlAttr extends Attr {
816
817
  constructor(val) {
817
818
  super("dangerouslySetInnerHTML", val ?? vp.nullConstVal);
@@ -993,7 +994,6 @@ class FragmentNode extends ChildsNode {
993
994
  }
994
995
  var maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs);
995
996
  var VALID_NODE_RE = /^[a-zA-Z][a-zA-Z0-9-]*$/;
996
- var _parser = null;
997
997
 
998
998
  class ANode extends BaseNode {
999
999
  constructor(nodeId, val) {
@@ -1005,9 +1005,7 @@ class ANode extends BaseNode {
1005
1005
  return this.val.toPathItem();
1006
1006
  }
1007
1007
  static parse(html, px) {
1008
- _parser ??= px.newDOMParser();
1009
- const nodes = _parser.parseFromString(html, "text/html").body.childNodes;
1010
- return ANode.fromDOM(nodes[0] ?? new px.Text(""), px);
1008
+ return ANode.fromDOM(px.parseHTML(html)[0] ?? new px.Text(""), px);
1011
1009
  }
1012
1010
  static fromDOM(node, px) {
1013
1011
  if (node instanceof px.Text)
@@ -1300,13 +1298,13 @@ var WRAPPER_NODES = {
1300
1298
  };
1301
1299
 
1302
1300
  class ParseContext {
1303
- constructor(DOMParser, Text, Comment, nodes, events, macroNodes, frame, parent) {
1301
+ constructor(document2, Text, Comment, nodes, events, macroNodes, frame, parent) {
1304
1302
  this.nodes = nodes ?? [];
1305
1303
  this.events = events ?? [];
1306
1304
  this.macroNodes = macroNodes ?? [];
1307
1305
  this.parent = parent ?? null;
1308
1306
  this.frame = frame ?? {};
1309
- this.DOMParser = DOMParser ?? globalThis.DOMParser;
1307
+ this.document = document2 ?? globalThis.document;
1310
1308
  this.Text = Text ?? globalThis.Text;
1311
1309
  this.Comment = Comment ?? globalThis.Comment;
1312
1310
  this.cacheConstNodes = true;
@@ -1315,12 +1313,14 @@ class ParseContext {
1315
1313
  return this.frame.macroName === name || this.parent?.isInsideMacro(name);
1316
1314
  }
1317
1315
  enterMacro(macroName, macroVars, macroSlots) {
1318
- const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
1316
+ const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
1319
1317
  const frame = { macroName, macroVars, macroSlots };
1320
- return new ParseContext(DP, Text, Comment, nodes, events, macroNodes, frame, this);
1318
+ return new ParseContext(document2, Text, Comment, nodes, events, macroNodes, frame, this);
1321
1319
  }
1322
- newDOMParser() {
1323
- return new this.DOMParser;
1320
+ parseHTML(html) {
1321
+ const t = this.document.createElement("template");
1322
+ t.innerHTML = html;
1323
+ return Array.from(t.content.childNodes);
1324
1324
  }
1325
1325
  addNodeIf(Class, val, extra) {
1326
1326
  if (val !== null) {
@@ -1500,9 +1500,9 @@ class ParseCtxClassSetCollector extends ParseContext {
1500
1500
  }
1501
1501
  }
1502
1502
  enterMacro(macroName, macroVars, macroSlots) {
1503
- const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
1503
+ const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
1504
1504
  const frame = { macroName, macroVars, macroSlots };
1505
- const v = new ParseCtxClassSetCollector(DP, Text, Comment, nodes, events, macroNodes, frame, this);
1505
+ const v = new ParseCtxClassSetCollector(document2, Text, Comment, nodes, events, macroNodes, frame, this);
1506
1506
  v.classes = this.classes;
1507
1507
  return v;
1508
1508
  }
@@ -1559,6 +1559,7 @@ var INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HAN
1559
1559
  var FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED";
1560
1560
  var COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED";
1561
1561
  var COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED";
1562
+ var DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION";
1562
1563
  var UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME";
1563
1564
  var UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME";
1564
1565
  var UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG";
@@ -1792,8 +1793,21 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedComputed) {
1792
1793
  for (const attr of view.ctx.attrs) {
1793
1794
  const { attrs, wrapperAttrs, textChild, isMacroCall } = attr;
1794
1795
  if (attrs?.constructor.name === "DynAttrs") {
1796
+ const seenNames = new Set;
1795
1797
  for (const attr2 of attrs.items) {
1796
- if (attr2?.constructor.name === "Attr") {
1798
+ const name = attr2?.name;
1799
+ if (name !== undefined && name !== "data-eid") {
1800
+ if (seenNames.has(name)) {
1801
+ lx.error(DUPLICATE_ATTR_DEFINITION, { name });
1802
+ } else {
1803
+ seenNames.add(name);
1804
+ }
1805
+ }
1806
+ if (attr2?.constructor.name === "IfAttr") {
1807
+ for (const subVal of [attr2.condVal, attr2.thenVal, attr2.elseVal]) {
1808
+ checkConsistentAttrVal(lx, subVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
1809
+ }
1810
+ } else if (attr2?.val !== undefined) {
1797
1811
  checkConsistentAttrVal(lx, attr2.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
1798
1812
  }
1799
1813
  }
@@ -1882,8 +1896,8 @@ class LintContext {
1882
1896
  }
1883
1897
 
1884
1898
  class LintParseContext extends ParseContext {
1885
- constructor(DOMParser, Text, Comment) {
1886
- super(DOMParser, Text, Comment);
1899
+ constructor(document2, Text, Comment) {
1900
+ super(document2, Text, Comment);
1887
1901
  this.attrs = [];
1888
1902
  }
1889
1903
  onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false) {
@@ -1916,6 +1930,8 @@ function lintIdToMessage(id, info) {
1916
1930
  return `Computed property '$${info.name}' is not defined`;
1917
1931
  case "COMPUTED_NOT_REFERENCED":
1918
1932
  return `Computed property '$${info.name}' is defined but not referenced`;
1933
+ case "DUPLICATE_ATTR_DEFINITION":
1934
+ return `Attribute '${info.name}' is defined more than once`;
1919
1935
  case "UNKNOWN_REQUEST_NAME":
1920
1936
  return `Unknown request '!${info.name}'`;
1921
1937
  case "UNKNOWN_COMPONENT_NAME":
@@ -7739,12 +7755,6 @@ class Field {
7739
7755
  proto[`reset${uname}`] = function() {
7740
7756
  return this.set(name, that.defaultValue);
7741
7757
  };
7742
- proto[`is${uname}NotSet`] = function() {
7743
- return this.get(name) == null;
7744
- };
7745
- proto[`is${uname}Set`] = function() {
7746
- return this.get(name) != null;
7747
- };
7748
7758
  this.extendProtoForType(proto, uname);
7749
7759
  }
7750
7760
  }
@@ -7797,6 +7807,7 @@ class FieldBool extends Field {
7797
7807
  proto[`set${uname}`] = function(v) {
7798
7808
  return this.set(name, !!v);
7799
7809
  };
7810
+ extendProtoTruthy(proto, name, uname);
7800
7811
  }
7801
7812
  }
7802
7813
 
@@ -7809,6 +7820,10 @@ class FieldAny extends Field {
7809
7820
  const type = getTypeName(dv) ?? "any";
7810
7821
  return { type, defaultValue: dv?.toJS ? dv.toJS() : dv };
7811
7822
  }
7823
+ extendProtoForType(proto, uname) {
7824
+ extendProtoNullable(proto, this.name, uname);
7825
+ extendProtoTruthy(proto, this.name, uname);
7826
+ }
7812
7827
  }
7813
7828
  var stringCoercer = (v) => v?.toString?.() ?? "";
7814
7829
 
@@ -7826,6 +7841,9 @@ class FieldInt extends Field {
7826
7841
  constructor(name, defaultValue = 0) {
7827
7842
  super("int", name, CHECK_TYPE_INT, intCoercer, defaultValue);
7828
7843
  }
7844
+ extendProtoForType(proto, uname) {
7845
+ extendProtoTruthy(proto, this.name, uname);
7846
+ }
7829
7847
  }
7830
7848
  var floatCoercer = (_) => null;
7831
7849
 
@@ -7833,6 +7851,9 @@ class FieldFloat extends Field {
7833
7851
  constructor(name, defaultValue = 0) {
7834
7852
  super("float", name, CHECK_TYPE_FLOAT, floatCoercer, defaultValue);
7835
7853
  }
7854
+ extendProtoForType(proto, uname) {
7855
+ extendProtoTruthy(proto, this.name, uname);
7856
+ }
7836
7857
  }
7837
7858
  var getTypeName = (v) => v?.constructor?.getMetaClass?.()?.name;
7838
7859
 
@@ -7857,6 +7878,10 @@ class FieldComp extends Field {
7857
7878
  toDataDef() {
7858
7879
  return { component: this.typeName, args: this.args };
7859
7880
  }
7881
+ extendProtoForType(proto, uname) {
7882
+ extendProtoNullable(proto, this.name, uname);
7883
+ extendProtoTruthy(proto, this.name, uname);
7884
+ }
7860
7885
  }
7861
7886
  var NONE2 = Symbol("NONE");
7862
7887
  function extendProtoForKeyed(proto, name, uname) {
@@ -7928,6 +7953,25 @@ function extendProtoSized(proto, name, uname, defaultEmpty, propName = "size") {
7928
7953
  proto[`${name}Len`] = function() {
7929
7954
  return this.get(name, defaultEmpty)[propName];
7930
7955
  };
7956
+ proto[`is${uname}Truthy`] = function() {
7957
+ return this.get(name, defaultEmpty)[propName] > 0;
7958
+ };
7959
+ proto[`is${uname}Falsy`] = function() {
7960
+ return this.get(name, defaultEmpty)[propName] === 0;
7961
+ };
7962
+ }
7963
+ function extendProtoNullable(proto, name, uname) {
7964
+ proto[`is${uname}Null`] = function() {
7965
+ return this.get(name) == null;
7966
+ };
7967
+ }
7968
+ function extendProtoTruthy(proto, name, uname) {
7969
+ proto[`is${uname}Truthy`] = function() {
7970
+ return !!this.get(name);
7971
+ };
7972
+ proto[`is${uname}Falsy`] = function() {
7973
+ return !this.get(name);
7974
+ };
7931
7975
  }
7932
7976
  var EMPTY_SET2 = Set2();
7933
7977
  var isetCoercer = (v) => Array.isArray(v) ? Set2(v) : v instanceof Set ? Set2(v) : null;
@@ -8564,9 +8608,9 @@ class LintClassCollectorCtx extends ParseCtxClassSetCollector {
8564
8608
  this.attrs = [];
8565
8609
  }
8566
8610
  enterMacro(macroName, macroVars, macroSlots) {
8567
- const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
8611
+ const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
8568
8612
  const frame = { macroName, macroVars, macroSlots };
8569
- const v = new LintClassCollectorCtx(DP, Text, Comment, nodes, events, macroNodes, frame, this);
8613
+ const v = new LintClassCollectorCtx(document2, Text, Comment, nodes, events, macroNodes, frame, this);
8570
8614
  v.classes = this.classes;
8571
8615
  v.attrs = this.attrs;
8572
8616
  return v;
@@ -8659,6 +8703,7 @@ export {
8659
8703
  INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD,
8660
8704
  Map2 as IMap,
8661
8705
  FIELD_VAL_NOT_DEFINED,
8706
+ DUPLICATE_ATTR_DEFINITION,
8662
8707
  Collection,
8663
8708
  COMPUTED_VAL_NOT_DEFINED,
8664
8709
  COMPUTED_NOT_REFERENCED,