tutuca 0.9.70 → 0.9.72

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.
@@ -8960,6 +8960,23 @@ function attrOriginAttr(attr) {
8960
8960
  return "@dangerouslysetinnerhtml";
8961
8961
  return `:${attr.name}`;
8962
8962
  }
8963
+ function checkHostBareDirectives(lx, attrs, tag, isMacroCall) {
8964
+ if (isMacroCall || !attrs)
8965
+ return;
8966
+ const kind = attrs.constructor.name;
8967
+ let names;
8968
+ if (kind === "ConstAttrs")
8969
+ names = Object.keys(attrs.items);
8970
+ else if (kind === "DynAttrs")
8971
+ names = attrs.items.map((a) => a?.name);
8972
+ else
8973
+ return;
8974
+ for (const name of names) {
8975
+ if (HOST_DIRECTIVE_ONLY_NAMES.has(name)) {
8976
+ lx.hint(MAYBE_ADD_AT_PREFIX, { name, tag, suggestion: `@${name}` }, { kind: "add-prefix", from: name, to: `@${name}` });
8977
+ }
8978
+ }
8979
+ }
8963
8980
  function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
8964
8981
  const { views } = Comp;
8965
8982
  const env = mkAttrValEnv(Comp, referencedAlters, referencedDynamics);
@@ -8968,6 +8985,7 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
8968
8985
  const view = views[viewName];
8969
8986
  for (const entry of view.ctx.attrs) {
8970
8987
  const { attrs, wrapperAttrs, textChild, isMacroCall, tag } = entry;
8988
+ checkHostBareDirectives(lx, attrs, tag, isMacroCall);
8971
8989
  if (attrs?.constructor.name === "DynAttrs") {
8972
8990
  const sourcesByName = new Map;
8973
8991
  for (const attr of attrs.items) {
@@ -9144,7 +9162,7 @@ class LintContext {
9144
9162
  this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
9145
9163
  }
9146
9164
  }
9147
- var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, 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", 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", 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", X_KNOWN_OP_NAMES, X_KNOWN_ATTR_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, LintParseContext;
9165
+ var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, 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", 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", 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, LintParseContext;
9148
9166
  var init_lint_check = __esm(() => {
9149
9167
  init_anode();
9150
9168
  init_htmllinter();
@@ -9174,6 +9192,7 @@ var init_lint_check = __esm(() => {
9174
9192
  "hide"
9175
9193
  ]);
9176
9194
  X_KNOWN_ATTR_NAMES = new Set(["as", "when", "loop-with", "show", "hide"]);
9195
+ HOST_DIRECTIVE_ONLY_NAMES = new Set(["when", "enrich-with", "loop-with", "show", "hide"]);
9177
9196
  PARSE_ISSUES = {
9178
9197
  "unknown-directive": { id: UNKNOWN_DIRECTIVE, candidates: KNOWN_DIRECTIVE_NAMES },
9179
9198
  "unknown-x-op": { id: UNKNOWN_X_OP, candidates: X_KNOWN_OP_NAMES, atPrefix: X_KNOWN_OP_NAMES },
@@ -9459,6 +9478,12 @@ var init_lint_rules = __esm(() => {
9459
9478
  group: "Templates / events",
9460
9479
  summary: "An `<x>` op/attr was written with a leading `@` like a directive."
9461
9480
  },
9481
+ {
9482
+ code: MAYBE_ADD_AT_PREFIX,
9483
+ level: "hint",
9484
+ group: "Templates / events",
9485
+ summary: "A directive name (`when`/`enrich-with`/`loop-with`/`show`/`hide`) was written as a plain attribute on a host element — add the `@` prefix."
9486
+ },
9462
9487
  {
9463
9488
  code: BAD_VALUE,
9464
9489
  level: "error",
@@ -12806,6 +12831,111 @@ var init_chai = __esm(() => {
12806
12831
  __name(use, "use");
12807
12832
  });
12808
12833
 
12834
+ // src/chai-jest.js
12835
+ function jestMatchers(chai, utils) {
12836
+ const A = chai.Assertion;
12837
+ const m = (name, fn) => A.addMethod(name, fn);
12838
+ m("toBe", function(expected) {
12839
+ this.assert(Object.is(this._obj, expected), "expected #{this} to be #{exp}", "expected #{this} not to be #{exp}", expected, this._obj);
12840
+ });
12841
+ m("toEqual", function(expected) {
12842
+ this.assert(utils.eql(this._obj, expected), "expected #{this} to deeply equal #{exp}", "expected #{this} not to deeply equal #{exp}", expected, this._obj, true);
12843
+ });
12844
+ m("toBeTruthy", function() {
12845
+ this.assert(Boolean(this._obj), "expected #{this} to be truthy", "expected #{this} not to be truthy");
12846
+ });
12847
+ m("toBeFalsy", function() {
12848
+ this.assert(!this._obj, "expected #{this} to be falsy", "expected #{this} not to be falsy");
12849
+ });
12850
+ m("toBeNull", function() {
12851
+ this.assert(this._obj === null, "expected #{this} to be null", "expected #{this} not to be null");
12852
+ });
12853
+ m("toBeUndefined", function() {
12854
+ this.assert(this._obj === undefined, "expected #{this} to be undefined", "expected #{this} not to be undefined");
12855
+ });
12856
+ m("toBeDefined", function() {
12857
+ this.assert(this._obj !== undefined, "expected #{this} to be defined", "expected #{this} to be undefined");
12858
+ });
12859
+ m("toBeNaN", function() {
12860
+ this.assert(Number.isNaN(this._obj), "expected #{this} to be NaN", "expected #{this} not to be NaN");
12861
+ });
12862
+ const compare = (name, op, word) => m(name, function(expected) {
12863
+ this.assert(op(this._obj, expected), `expected #{this} to be ${word} #{exp}`, `expected #{this} not to be ${word} #{exp}`, expected);
12864
+ });
12865
+ compare("toBeGreaterThan", (a, b) => a > b, "greater than");
12866
+ compare("toBeGreaterThanOrEqual", (a, b) => a >= b, "greater than or equal to");
12867
+ compare("toBeLessThan", (a, b) => a < b, "less than");
12868
+ compare("toBeLessThanOrEqual", (a, b) => a <= b, "less than or equal to");
12869
+ m("toBeCloseTo", function(expected, numDigits = 2) {
12870
+ const pass = Math.abs(expected - this._obj) < 10 ** -numDigits / 2;
12871
+ this.assert(pass, `expected #{this} to be close to #{exp} (${numDigits} digits)`, `expected #{this} not to be close to #{exp} (${numDigits} digits)`, expected);
12872
+ });
12873
+ m("toContain", function(item) {
12874
+ const obj = this._obj;
12875
+ const ok = typeof obj === "string" ? obj.includes(item) : Array.from(obj).includes(item);
12876
+ this.assert(ok, "expected #{this} to contain #{exp}", "expected #{this} not to contain #{exp}", item);
12877
+ });
12878
+ m("toHaveLength", function(length) {
12879
+ const actual = this._obj == null ? undefined : this._obj.length;
12880
+ this.assert(actual === length, "expected #{this} to have length #{exp}", "expected #{this} not to have length #{exp}", length, actual);
12881
+ });
12882
+ m("toMatch", function(expected) {
12883
+ const obj = this._obj;
12884
+ const ok = expected instanceof RegExp ? expected.test(obj) : String(obj).includes(expected);
12885
+ this.assert(ok, "expected #{this} to match #{exp}", "expected #{this} not to match #{exp}", expected);
12886
+ });
12887
+ m("toHaveProperty", function(path, ...rest) {
12888
+ const keys = Array.isArray(path) ? path : String(path).split(".");
12889
+ let cur = this._obj;
12890
+ let found = true;
12891
+ for (const k of keys) {
12892
+ if (cur != null && k in Object(cur))
12893
+ cur = cur[k];
12894
+ else {
12895
+ found = false;
12896
+ break;
12897
+ }
12898
+ }
12899
+ const pass = found && (rest.length === 0 || utils.eql(cur, rest[0]));
12900
+ this.assert(pass, "expected #{this} to have property #{exp}", "expected #{this} not to have property #{exp}", path);
12901
+ });
12902
+ m("toBeInstanceOf", function(ctor) {
12903
+ this.assert(this._obj instanceof ctor, "expected #{this} to be an instance of #{exp}", "expected #{this} not to be an instance of #{exp}", ctor.name ?? ctor);
12904
+ });
12905
+ m("toThrow", function(expected) {
12906
+ const a = new chai.Assertion(this._obj);
12907
+ if (utils.flag(this, "negate")) {
12908
+ expected === undefined ? a.to.not.throw() : a.to.not.throw(expected);
12909
+ } else {
12910
+ expected === undefined ? a.to.throw() : a.to.throw(expected);
12911
+ }
12912
+ });
12913
+ }
12914
+ var JEST_MATCHERS;
12915
+ var init_chai_jest = __esm(() => {
12916
+ JEST_MATCHERS = [
12917
+ "toBe",
12918
+ "toEqual",
12919
+ "toBeTruthy",
12920
+ "toBeFalsy",
12921
+ "toBeNull",
12922
+ "toBeUndefined",
12923
+ "toBeDefined",
12924
+ "toBeNaN",
12925
+ "toBeGreaterThan",
12926
+ "toBeGreaterThanOrEqual",
12927
+ "toBeLessThan",
12928
+ "toBeLessThanOrEqual",
12929
+ "toBeCloseTo",
12930
+ "toContain",
12931
+ "toHaveLength",
12932
+ "toMatch",
12933
+ "toHaveProperty",
12934
+ "toBeInstanceOf",
12935
+ "toThrow"
12936
+ ];
12937
+ });
12938
+
12809
12939
  // tools/core/results.js
12810
12940
  class ModuleInfo {
12811
12941
  constructor({ path = null, present = new Set, counts = {}, warnings = [] }) {
@@ -14718,12 +14848,14 @@ function parseLimit(raw) {
14718
14848
  var COMMANDS;
14719
14849
  var init__registry = __esm(() => {
14720
14850
  init_chai();
14851
+ init_chai_jest();
14721
14852
  init_describe();
14722
14853
  init_docs();
14723
14854
  init_list();
14724
14855
  init_lint();
14725
14856
  init_render2();
14726
14857
  init_test();
14858
+ use(jestMatchers);
14727
14859
  COMMANDS = {
14728
14860
  get: {
14729
14861
  describe: "Summarize the module's exports and counts.",
@@ -14925,6 +15057,8 @@ function lintIdToMessage(id, info) {
14925
15057
  const written = info.value !== undefined ? `${info.name}=${JSON.stringify(info.value)}` : info.name;
14926
15058
  return `'${written}' on <x> looks like a directive but is actually an x op/attr written with a leading '@'`;
14927
15059
  }
15060
+ case "MAYBE_ADD_AT_PREFIX":
15061
+ return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
14928
15062
  case "BAD_VALUE":
14929
15063
  return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
14930
15064
  case "UNSUPPORTED_EXPR_SYNTAX":
@@ -14935,6 +15069,8 @@ function lintIdToMessage(id, info) {
14935
15069
  return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
14936
15070
  case "UNKNOWN_COMPONENT_SPEC_KEY":
14937
15071
  return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
15072
+ case "COMP_FIELD_BAD_SHAPE":
15073
+ return info.kind === "args-not-object" ? `Field '${info.fieldName}': in { component, args }, 'args' must be a plain object, got ${info.got}` : `Field '${info.fieldName}': in { component, args }, 'component' must be the component name as a string, got ${info.gotName ? `the ${info.gotName} class` : info.got}`;
14938
15074
  case "HTML_TAG_NAME_HAS_UPPERCASE":
14939
15075
  return `Tag <${info.raw}> will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
14940
15076
  case "HTML_SVG_TAG_WILL_LOWERCASE":
@@ -15589,6 +15725,7 @@ init__registry();
15589
15725
  init_feedback();
15590
15726
 
15591
15727
  // tools/cli/commands/help.js
15728
+ init_chai_jest();
15592
15729
  var exports_help = {};
15593
15730
  __export(exports_help, {
15594
15731
  run: () => run4,
@@ -15641,7 +15778,9 @@ MODULE CONVENTION
15641
15778
  describe(title, fn) // untagged
15642
15779
  describe(title, { component }, fn)// explicit tag with custom title
15643
15780
  and test(title, fn) // fn may be async
15644
- and expect comes from chai
15781
+ and expect is chai, with jest-style matchers added:
15782
+ ${JEST_MATCHERS.join(", ")}
15783
+ (chai's BDD chain like .to.equal also works; use .not to negate)
15645
15784
 
15646
15785
  export function getRoot() // optional; returned by info
15647
15786