tutuca 0.9.69 → 0.9.71
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/dist/tutuca-cli.js +120 -85
- package/dist/tutuca-dev.ext.js +107 -73
- package/dist/tutuca-dev.js +105 -73
- package/dist/tutuca-dev.min.js +2 -2
- package/package.json +1 -1
- package/skill/tutuca/cli.md +6 -4
- package/skill/tutuca/core.md +21 -3
package/dist/tutuca-dev.js
CHANGED
|
@@ -12324,18 +12324,13 @@ var UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE";
|
|
|
12324
12324
|
var UNKNOWN_X_OP = "UNKNOWN_X_OP";
|
|
12325
12325
|
var UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR";
|
|
12326
12326
|
var MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX";
|
|
12327
|
+
var MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX";
|
|
12327
12328
|
var BAD_VALUE = "BAD_VALUE";
|
|
12328
12329
|
var UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX";
|
|
12329
12330
|
var REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING";
|
|
12330
12331
|
var PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING";
|
|
12331
12332
|
var UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY";
|
|
12332
12333
|
var COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE";
|
|
12333
|
-
var PARSE_ISSUE_KIND_TO_LINT_ID = {
|
|
12334
|
-
"unknown-directive": UNKNOWN_DIRECTIVE,
|
|
12335
|
-
"unknown-x-op": UNKNOWN_X_OP,
|
|
12336
|
-
"unknown-x-attr": UNKNOWN_X_ATTR,
|
|
12337
|
-
"bad-value": BAD_VALUE
|
|
12338
|
-
};
|
|
12339
12334
|
var X_KNOWN_OP_NAMES = new Set([
|
|
12340
12335
|
"slot",
|
|
12341
12336
|
"text",
|
|
@@ -12346,17 +12341,19 @@ var X_KNOWN_OP_NAMES = new Set([
|
|
|
12346
12341
|
"hide"
|
|
12347
12342
|
]);
|
|
12348
12343
|
var X_KNOWN_ATTR_NAMES = new Set(["as", "when", "loop-with", "show", "hide"]);
|
|
12349
|
-
var
|
|
12350
|
-
"unknown-x-op": X_KNOWN_OP_NAMES,
|
|
12351
|
-
"unknown-x-attr": X_KNOWN_ATTR_NAMES
|
|
12352
|
-
};
|
|
12344
|
+
var HOST_DIRECTIVE_ONLY_NAMES = new Set(["when", "enrich-with", "loop-with", "show", "hide"]);
|
|
12353
12345
|
var LEVEL_WARN2 = "warn";
|
|
12354
12346
|
var LEVEL_ERROR2 = "error";
|
|
12355
12347
|
var LEVEL_HINT = "hint";
|
|
12356
|
-
var
|
|
12357
|
-
"unknown-directive": KNOWN_DIRECTIVE_NAMES,
|
|
12358
|
-
"unknown-x-op": X_KNOWN_OP_NAMES,
|
|
12359
|
-
"unknown-x-attr":
|
|
12348
|
+
var PARSE_ISSUES = {
|
|
12349
|
+
"unknown-directive": { id: UNKNOWN_DIRECTIVE, candidates: KNOWN_DIRECTIVE_NAMES },
|
|
12350
|
+
"unknown-x-op": { id: UNKNOWN_X_OP, candidates: X_KNOWN_OP_NAMES, atPrefix: X_KNOWN_OP_NAMES },
|
|
12351
|
+
"unknown-x-attr": {
|
|
12352
|
+
id: UNKNOWN_X_ATTR,
|
|
12353
|
+
candidates: X_KNOWN_ATTR_NAMES,
|
|
12354
|
+
atPrefix: X_KNOWN_ATTR_NAMES
|
|
12355
|
+
},
|
|
12356
|
+
"bad-value": { id: BAD_VALUE }
|
|
12360
12357
|
};
|
|
12361
12358
|
function collectProtoMethodNames(proto) {
|
|
12362
12359
|
const out = [];
|
|
@@ -12451,9 +12448,10 @@ function checkParseIssues(lx, view) {
|
|
|
12451
12448
|
if (!issues)
|
|
12452
12449
|
return;
|
|
12453
12450
|
for (const { kind, info } of issues) {
|
|
12454
|
-
const
|
|
12455
|
-
if (!
|
|
12451
|
+
const rule = PARSE_ISSUES[kind];
|
|
12452
|
+
if (!rule)
|
|
12456
12453
|
continue;
|
|
12454
|
+
const id = rule.id;
|
|
12457
12455
|
if (kind === "bad-value") {
|
|
12458
12456
|
const detected = classifyBadValue(info.value);
|
|
12459
12457
|
if (detected) {
|
|
@@ -12461,15 +12459,13 @@ function checkParseIssues(lx, view) {
|
|
|
12461
12459
|
continue;
|
|
12462
12460
|
}
|
|
12463
12461
|
}
|
|
12464
|
-
const atPrefixKnown =
|
|
12462
|
+
const atPrefixKnown = rule.atPrefix;
|
|
12465
12463
|
const isAtPrefixedTypo = atPrefixKnown && info.name?.startsWith("@") && atPrefixKnown.has(info.name.slice(1));
|
|
12466
12464
|
let suggestion = null;
|
|
12467
12465
|
if (isAtPrefixedTypo) {
|
|
12468
12466
|
suggestion = { kind: "drop-prefix", from: info.name, to: info.name.slice(1) };
|
|
12469
|
-
} else {
|
|
12470
|
-
|
|
12471
|
-
if (candidates)
|
|
12472
|
-
suggestion = replaceNameSuggestion(info.name, candidates);
|
|
12467
|
+
} else if (rule.candidates) {
|
|
12468
|
+
suggestion = replaceNameSuggestion(info.name, rule.candidates);
|
|
12473
12469
|
}
|
|
12474
12470
|
lx.error(id, info, suggestion);
|
|
12475
12471
|
if (isAtPrefixedTypo) {
|
|
@@ -12639,70 +12635,83 @@ function checkEventHandlersHaveImpls(lx, Comp, referencedInputs) {
|
|
|
12639
12635
|
});
|
|
12640
12636
|
}
|
|
12641
12637
|
}
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12638
|
+
var fixTo = (from, to) => ({ kind: "rewrite", from, to });
|
|
12639
|
+
function reportUnknownName(lx, code, name, candidates, info) {
|
|
12640
|
+
lx.error(code, { ...info, name }, replaceNameSuggestion(name, candidates));
|
|
12641
|
+
}
|
|
12642
|
+
var ATTR_VAL_CHECKERS = {
|
|
12643
|
+
FieldVal({ lx, val, env, errCtx }) {
|
|
12644
|
+
const { fields, proto } = env;
|
|
12646
12645
|
const { name } = val;
|
|
12647
|
-
if (fields[name]
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
}
|
|
12651
|
-
|
|
12652
|
-
}
|
|
12653
|
-
|
|
12654
|
-
|
|
12646
|
+
if (fields[name] !== undefined)
|
|
12647
|
+
return;
|
|
12648
|
+
if (proto[name] !== undefined)
|
|
12649
|
+
lx.error(FIELD_VAL_IS_METHOD, { ...errCtx, val, name }, fixTo(`.${name}`, `$${name}`));
|
|
12650
|
+
else
|
|
12651
|
+
reportUnknownName(lx, FIELD_VAL_NOT_DEFINED, name, Object.keys(fields), { ...errCtx, val });
|
|
12652
|
+
},
|
|
12653
|
+
MethodVal({ lx, val, env, errCtx }) {
|
|
12654
|
+
const { fields, proto } = env;
|
|
12655
12655
|
const { name } = val;
|
|
12656
|
-
if (proto[name]
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
}
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
if (scope.
|
|
12672
|
-
lx
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
if (
|
|
12676
|
-
lx
|
|
12677
|
-
|
|
12678
|
-
|
|
12656
|
+
if (proto[name] !== undefined)
|
|
12657
|
+
return;
|
|
12658
|
+
if (fields[name] !== undefined)
|
|
12659
|
+
lx.error(METHOD_VAL_IS_FIELD, { ...errCtx, val, name }, fixTo(`$${name}`, `.${name}`));
|
|
12660
|
+
else
|
|
12661
|
+
reportUnknownName(lx, METHOD_VAL_NOT_DEFINED, name, collectProtoMethodNames(proto), {
|
|
12662
|
+
...errCtx,
|
|
12663
|
+
val
|
|
12664
|
+
});
|
|
12665
|
+
},
|
|
12666
|
+
SeqAccessVal({ val, recurse }) {
|
|
12667
|
+
recurse(val.seqVal);
|
|
12668
|
+
recurse(val.keyVal);
|
|
12669
|
+
},
|
|
12670
|
+
RequestVal({ lx, val, env, errCtx }) {
|
|
12671
|
+
if (env.scope.lookupRequest(val.name) === null)
|
|
12672
|
+
reportUnknownName(lx, UNKNOWN_REQUEST_NAME, val.name, scopeKeysAlong(env.scope, "reqsByName"), errCtx);
|
|
12673
|
+
},
|
|
12674
|
+
TypeVal({ lx, val, env, errCtx }) {
|
|
12675
|
+
if (env.scope.lookupComponent(val.name) === null)
|
|
12676
|
+
reportUnknownName(lx, UNKNOWN_COMPONENT_NAME, val.name, scopeKeysAlong(env.scope, "byName"), errCtx);
|
|
12677
|
+
},
|
|
12678
|
+
NameVal({ lx, val, errCtx, skipNameVal }) {
|
|
12679
|
+
if (!skipNameVal && !isKnownHandlerName(val.name))
|
|
12680
|
+
reportUnknownName(lx, UNKNOWN_HANDLER_ARG_NAME, val.name, KNOWN_HANDLER_NAMES, errCtx);
|
|
12681
|
+
},
|
|
12682
|
+
StrTplVal({ lx, val, errCtx, recurse }) {
|
|
12679
12683
|
const vs = val.vals;
|
|
12680
12684
|
const literal = val.toLiteralSource();
|
|
12681
12685
|
if (literal !== null) {
|
|
12682
|
-
lx.hint(PLACEHOLDERLESS_TEMPLATE_STRING, { ...errCtx, literal },
|
|
12686
|
+
lx.hint(PLACEHOLDERLESS_TEMPLATE_STRING, { ...errCtx, literal }, fixTo(`$${literal}`, literal));
|
|
12683
12687
|
} else if (vs.length === 1) {
|
|
12684
12688
|
const simpler = String(vs[0]);
|
|
12685
|
-
lx.warn(REDUNDANT_TEMPLATE_STRING, { ...errCtx, simpler },
|
|
12686
|
-
}
|
|
12687
|
-
for (const subVal of vs) {
|
|
12688
|
-
checkConsistentAttrVal(lx, subVal, env, skipNameVal, errCtx);
|
|
12689
|
+
lx.warn(REDUNDANT_TEMPLATE_STRING, { ...errCtx, simpler }, fixTo(`$'{${simpler}}'`, simpler));
|
|
12689
12690
|
}
|
|
12690
|
-
|
|
12691
|
+
for (const subVal of vs)
|
|
12692
|
+
recurse(subVal);
|
|
12693
|
+
},
|
|
12694
|
+
HandlerNameVal({ lx, val, env, errCtx }) {
|
|
12691
12695
|
env.referencedAlters?.add(val.name);
|
|
12692
|
-
if (alter[val.name] === undefined)
|
|
12693
|
-
lx
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
+
if (env.alter[val.name] === undefined)
|
|
12697
|
+
reportUnknownName(lx, ALT_HANDLER_NOT_DEFINED, val.name, Object.keys(env.alter), errCtx);
|
|
12698
|
+
},
|
|
12699
|
+
PredicateVal({ val, recurse }) {
|
|
12696
12700
|
for (const arg of val.args)
|
|
12697
|
-
|
|
12698
|
-
}
|
|
12701
|
+
recurse(arg);
|
|
12702
|
+
},
|
|
12703
|
+
DynVal({ lx, val, env, errCtx }) {
|
|
12699
12704
|
env.referencedDynamics?.add(val.name);
|
|
12700
|
-
if (env.dynamicMap[val.name] === undefined)
|
|
12701
|
-
lx
|
|
12702
|
-
}
|
|
12703
|
-
} else if (valName !== "ConstVal" && valName !== "BindVal") {
|
|
12704
|
-
console.log(val);
|
|
12705
|
+
if (env.dynamicMap[val.name] === undefined)
|
|
12706
|
+
reportUnknownName(lx, DYN_VAL_NOT_DEFINED, val.name, Object.keys(env.dynamicMap), errCtx);
|
|
12705
12707
|
}
|
|
12708
|
+
};
|
|
12709
|
+
function checkConsistentAttrVal(lx, val, env, skipNameVal = false, errCtx = null) {
|
|
12710
|
+
const check = ATTR_VAL_CHECKERS[val?.constructor.name];
|
|
12711
|
+
if (check === undefined)
|
|
12712
|
+
return;
|
|
12713
|
+
const recurse = (sub) => checkConsistentAttrVal(lx, sub, env, skipNameVal, errCtx);
|
|
12714
|
+
check({ lx, val, env, errCtx, skipNameVal, recurse });
|
|
12706
12715
|
}
|
|
12707
12716
|
var NODE_KIND_TO_CTX = {
|
|
12708
12717
|
RenderTextNode: { originAttr: "<x text>" },
|
|
@@ -12734,6 +12743,23 @@ function attrOriginAttr(attr) {
|
|
|
12734
12743
|
return "@dangerouslysetinnerhtml";
|
|
12735
12744
|
return `:${attr.name}`;
|
|
12736
12745
|
}
|
|
12746
|
+
function checkHostBareDirectives(lx, attrs, tag, isMacroCall) {
|
|
12747
|
+
if (isMacroCall || !attrs)
|
|
12748
|
+
return;
|
|
12749
|
+
const kind = attrs.constructor.name;
|
|
12750
|
+
let names;
|
|
12751
|
+
if (kind === "ConstAttrs")
|
|
12752
|
+
names = Object.keys(attrs.items);
|
|
12753
|
+
else if (kind === "DynAttrs")
|
|
12754
|
+
names = attrs.items.map((a) => a?.name);
|
|
12755
|
+
else
|
|
12756
|
+
return;
|
|
12757
|
+
for (const name of names) {
|
|
12758
|
+
if (HOST_DIRECTIVE_ONLY_NAMES.has(name)) {
|
|
12759
|
+
lx.hint(MAYBE_ADD_AT_PREFIX, { name, tag, suggestion: `@${name}` }, { kind: "add-prefix", from: name, to: `@${name}` });
|
|
12760
|
+
}
|
|
12761
|
+
}
|
|
12762
|
+
}
|
|
12737
12763
|
function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
|
|
12738
12764
|
const { views } = Comp;
|
|
12739
12765
|
const env = mkAttrValEnv(Comp, referencedAlters, referencedDynamics);
|
|
@@ -12742,6 +12768,7 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
|
|
|
12742
12768
|
const view = views[viewName];
|
|
12743
12769
|
for (const entry of view.ctx.attrs) {
|
|
12744
12770
|
const { attrs, wrapperAttrs, textChild, isMacroCall, tag } = entry;
|
|
12771
|
+
checkHostBareDirectives(lx, attrs, tag, isMacroCall);
|
|
12745
12772
|
if (attrs?.constructor.name === "DynAttrs") {
|
|
12746
12773
|
const sourcesByName = new Map;
|
|
12747
12774
|
for (const attr of attrs.items) {
|
|
@@ -13500,6 +13527,8 @@ function lintIdToMessage(id, info) {
|
|
|
13500
13527
|
const written = info.value !== undefined ? `${info.name}=${JSON.stringify(info.value)}` : info.name;
|
|
13501
13528
|
return `'${written}' on <x> looks like a directive but is actually an x op/attr written with a leading '@'`;
|
|
13502
13529
|
}
|
|
13530
|
+
case "MAYBE_ADD_AT_PREFIX":
|
|
13531
|
+
return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
|
|
13503
13532
|
case "BAD_VALUE":
|
|
13504
13533
|
return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
|
|
13505
13534
|
case "UNSUPPORTED_EXPR_SYNTAX":
|
|
@@ -13510,6 +13539,8 @@ function lintIdToMessage(id, info) {
|
|
|
13510
13539
|
return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
|
|
13511
13540
|
case "UNKNOWN_COMPONENT_SPEC_KEY":
|
|
13512
13541
|
return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
|
|
13542
|
+
case "COMP_FIELD_BAD_SHAPE":
|
|
13543
|
+
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}`;
|
|
13513
13544
|
case "HTML_TAG_NAME_HAS_UPPERCASE":
|
|
13514
13545
|
return `Tag <${info.raw}> will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
|
|
13515
13546
|
case "HTML_SVG_TAG_WILL_LOWERCASE":
|
|
@@ -15639,6 +15670,7 @@ export {
|
|
|
15639
15670
|
METHOD_VAL_NOT_DEFINED,
|
|
15640
15671
|
METHOD_VAL_IS_FIELD,
|
|
15641
15672
|
MAYBE_DROP_AT_PREFIX,
|
|
15673
|
+
MAYBE_ADD_AT_PREFIX,
|
|
15642
15674
|
List,
|
|
15643
15675
|
LintReport,
|
|
15644
15676
|
LintParseContext,
|