tutuca 0.9.31 → 0.9.32
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 +113 -19
- package/dist/tutuca-dev.js +132 -17
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.js +70 -17
- package/dist/tutuca-extra.min.js +1 -1
- package/dist/tutuca.js +70 -17
- package/dist/tutuca.min.js +1 -1
- package/package.json +1 -1
- package/skill/cli.md +3 -0
- package/skill/core.md +10 -0
package/dist/tutuca-cli.js
CHANGED
|
@@ -1147,6 +1147,8 @@ class AttrParser {
|
|
|
1147
1147
|
this.parseThen(s);
|
|
1148
1148
|
else if (directiveName.startsWith("else."))
|
|
1149
1149
|
this.parseElse(s);
|
|
1150
|
+
else
|
|
1151
|
+
this.px.onParseIssue("unknown-directive", { name: directiveName, value: s });
|
|
1150
1152
|
}
|
|
1151
1153
|
_parseWhen(s) {
|
|
1152
1154
|
if (this.eachAttr !== null)
|
|
@@ -1332,6 +1334,30 @@ function optimizeNode(node) {
|
|
|
1332
1334
|
node.optimize();
|
|
1333
1335
|
return node;
|
|
1334
1336
|
}
|
|
1337
|
+
function processXExtras(node, attrs, opName, startIdx, px) {
|
|
1338
|
+
const consumed = X_OP_CONSUMED[opName];
|
|
1339
|
+
const wrappable = X_OP_WRAPPABLE.has(opName);
|
|
1340
|
+
const wrappers = [];
|
|
1341
|
+
for (let i = startIdx;i < attrs.length; i++) {
|
|
1342
|
+
const a = attrs[i];
|
|
1343
|
+
const aName = a.name;
|
|
1344
|
+
if (consumed.has(aName))
|
|
1345
|
+
continue;
|
|
1346
|
+
if (wrappable && X_ATTR_WRAPPERS[aName]) {
|
|
1347
|
+
wrappers.push([X_ATTR_WRAPPERS[aName], vp.parseCondValue(a.value, px)]);
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
const issueInfo = { op: opName, name: aName, value: a.value };
|
|
1351
|
+
px.onParseIssue("unknown-x-attr", issueInfo);
|
|
1352
|
+
}
|
|
1353
|
+
for (let i = wrappers.length - 1;i >= 0; i--) {
|
|
1354
|
+
const [Cls, val] = wrappers[i];
|
|
1355
|
+
const wrapper = px.addNodeIf(Cls, val, node);
|
|
1356
|
+
if (wrapper !== null)
|
|
1357
|
+
node = wrapper;
|
|
1358
|
+
}
|
|
1359
|
+
return node;
|
|
1360
|
+
}
|
|
1335
1361
|
function wrap(node, px, wrappers) {
|
|
1336
1362
|
if (wrappers) {
|
|
1337
1363
|
for (let i = wrappers.length - 1;i >= 0; i--) {
|
|
@@ -1438,6 +1464,9 @@ class ParseContext {
|
|
|
1438
1464
|
return this.nodes[id] ?? null;
|
|
1439
1465
|
}
|
|
1440
1466
|
onAttributes(_attrs, _wrapperAttrs, _textChild, _isMacroCall) {}
|
|
1467
|
+
onParseIssue(kind, info) {
|
|
1468
|
+
console.warn(`tutuca parse issue [${kind}]`, info);
|
|
1469
|
+
}
|
|
1441
1470
|
}
|
|
1442
1471
|
function condenseChildsWhites(childs) {
|
|
1443
1472
|
if (childs.length === 0)
|
|
@@ -1517,7 +1546,7 @@ function compileModifiers(eventName, names) {
|
|
|
1517
1546
|
return w(this, f, args, ctx);
|
|
1518
1547
|
};
|
|
1519
1548
|
}
|
|
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) => {
|
|
1549
|
+
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 }), X_OP_CONSUMED, X_OP_WRAPPABLE, X_ATTR_WRAPPERS, 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) => {
|
|
1521
1550
|
const node = n instanceof FragmentNode ? n.childs[0] : n;
|
|
1522
1551
|
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
1523
1552
|
}, 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;
|
|
@@ -1616,18 +1645,19 @@ var init_anode = __esm(() => {
|
|
|
1616
1645
|
static parse(html, px) {
|
|
1617
1646
|
const nodes = px.parseHTML(html);
|
|
1618
1647
|
if (nodes.length === 0)
|
|
1619
|
-
return new
|
|
1648
|
+
return new CommentNode("Empty View in ANode.parse");
|
|
1620
1649
|
if (nodes.length === 1)
|
|
1621
1650
|
return ANode.fromDOM(nodes[0], px);
|
|
1622
|
-
const childs =
|
|
1623
|
-
for (let i = 0;i < nodes.length; i++)
|
|
1624
|
-
|
|
1651
|
+
const childs = [];
|
|
1652
|
+
for (let i = 0;i < nodes.length; i++) {
|
|
1653
|
+
const child = ANode.fromDOM(nodes[i], px);
|
|
1654
|
+
if (child !== null)
|
|
1655
|
+
childs.push(child);
|
|
1656
|
+
}
|
|
1625
1657
|
const trimmed = condenseChildsWhites(childs);
|
|
1626
1658
|
if (trimmed.length === 0)
|
|
1627
|
-
return new
|
|
1628
|
-
|
|
1629
|
-
return trimmed[0];
|
|
1630
|
-
return new FragmentNode(trimmed);
|
|
1659
|
+
return new CommentNode("Empty View in ANode.parse");
|
|
1660
|
+
return maybeFragment(trimmed);
|
|
1631
1661
|
}
|
|
1632
1662
|
static fromDOM(node, px) {
|
|
1633
1663
|
if (node instanceof px.Text)
|
|
@@ -1642,25 +1672,37 @@ var init_anode = __esm(() => {
|
|
|
1642
1672
|
if (tag === "X" || isPseudoX) {
|
|
1643
1673
|
if (attrs.length === 0)
|
|
1644
1674
|
return maybeFragment(childs);
|
|
1645
|
-
const
|
|
1675
|
+
const opIdx = isPseudoX ? 1 : 0;
|
|
1676
|
+
const { name, value } = attrs[opIdx];
|
|
1646
1677
|
const as = attrs.getNamedItem("as")?.value ?? null;
|
|
1678
|
+
let node2;
|
|
1647
1679
|
switch (name) {
|
|
1648
1680
|
case "slot":
|
|
1649
|
-
|
|
1681
|
+
node2 = new SlotNode(null, vp.const(value), maybeFragment(childs));
|
|
1682
|
+
break;
|
|
1650
1683
|
case "text":
|
|
1651
|
-
|
|
1684
|
+
node2 = px.addNodeIf(RenderTextNode, vp.parseText(value, px));
|
|
1685
|
+
break;
|
|
1652
1686
|
case "render":
|
|
1653
|
-
|
|
1687
|
+
node2 = px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
|
|
1688
|
+
break;
|
|
1654
1689
|
case "render-it":
|
|
1655
|
-
|
|
1690
|
+
node2 = px.addNodeIf(RenderItNode, vp.bindValIt, as);
|
|
1691
|
+
break;
|
|
1656
1692
|
case "render-each":
|
|
1657
|
-
|
|
1693
|
+
node2 = RenderEachNode.parse(px, vp, value, as, attrs);
|
|
1694
|
+
break;
|
|
1658
1695
|
case "show":
|
|
1659
|
-
|
|
1696
|
+
node2 = px.addNodeIf(ShowNode, vp.parseCondValue(value, px), maybeFragment(childs));
|
|
1697
|
+
break;
|
|
1660
1698
|
case "hide":
|
|
1661
|
-
|
|
1699
|
+
node2 = px.addNodeIf(HideNode, vp.parseCondValue(value, px), maybeFragment(childs));
|
|
1700
|
+
break;
|
|
1701
|
+
default:
|
|
1702
|
+
px.onParseIssue("unknown-x-op", { name, value });
|
|
1703
|
+
return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
|
|
1662
1704
|
}
|
|
1663
|
-
return
|
|
1705
|
+
return processXExtras(node2, attrs, name, (isPseudoX ? 1 : 0) + 1, px);
|
|
1664
1706
|
} else if (tag.charCodeAt(1) === 58 && tag.charCodeAt(0) === 88) {
|
|
1665
1707
|
const macroName = tag.slice(2).toLowerCase();
|
|
1666
1708
|
if (macroName === "slot") {
|
|
@@ -1844,6 +1886,17 @@ var init_anode = __esm(() => {
|
|
|
1844
1886
|
}
|
|
1845
1887
|
static register = true;
|
|
1846
1888
|
};
|
|
1889
|
+
X_OP_CONSUMED = {
|
|
1890
|
+
slot: new Set,
|
|
1891
|
+
text: new Set,
|
|
1892
|
+
render: new Set(["as"]),
|
|
1893
|
+
"render-it": new Set(["as"]),
|
|
1894
|
+
"render-each": new Set(["as", "when", "loop-with"]),
|
|
1895
|
+
show: new Set,
|
|
1896
|
+
hide: new Set
|
|
1897
|
+
};
|
|
1898
|
+
X_OP_WRAPPABLE = new Set(["text", "render", "render-it", "render-each"]);
|
|
1899
|
+
X_ATTR_WRAPPERS = { show: ShowNode, hide: HideNode };
|
|
1847
1900
|
WRAPPER_NODES = {
|
|
1848
1901
|
slot: SlotNode,
|
|
1849
1902
|
show: ShowNode,
|
|
@@ -2084,11 +2137,29 @@ function checkComponent(Comp, lx = new LintContext) {
|
|
|
2084
2137
|
});
|
|
2085
2138
|
}
|
|
2086
2139
|
function checkView(lx, view, Comp, referencedAlters, referencedComputed) {
|
|
2140
|
+
checkParseIssues(lx, view);
|
|
2087
2141
|
checkRenderItInLoop(lx, view);
|
|
2088
2142
|
checkEventModifiers(lx, view);
|
|
2089
2143
|
checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedComputed);
|
|
2090
2144
|
checkMacroCallArgs(lx, view, Comp);
|
|
2091
2145
|
}
|
|
2146
|
+
function checkParseIssues(lx, view) {
|
|
2147
|
+
const issues = view.ctx.parseIssues;
|
|
2148
|
+
if (!issues)
|
|
2149
|
+
return;
|
|
2150
|
+
for (const { kind, info } of issues) {
|
|
2151
|
+
const id = PARSE_ISSUE_KIND_TO_LINT_ID[kind];
|
|
2152
|
+
if (!id)
|
|
2153
|
+
continue;
|
|
2154
|
+
lx.error(id, info);
|
|
2155
|
+
const known = AT_PREFIX_HINT_KNOWN_BY_KIND[kind];
|
|
2156
|
+
if (known && info.name?.startsWith("@")) {
|
|
2157
|
+
const suggestion = info.name.slice(1);
|
|
2158
|
+
if (known.has(suggestion))
|
|
2159
|
+
lx.hint(MAYBE_DROP_AT_PREFIX, { ...info, suggestion });
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2092
2163
|
function checkMacroCallArgs(lx, view, Comp) {
|
|
2093
2164
|
const { scope } = Comp;
|
|
2094
2165
|
for (const macroNode of view.ctx.macroNodes) {
|
|
@@ -2377,9 +2448,28 @@ class LintContext {
|
|
|
2377
2448
|
this.reports.push({ id, info, level, context: { ...this.frame } });
|
|
2378
2449
|
}
|
|
2379
2450
|
}
|
|
2380
|
-
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;
|
|
2451
|
+
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", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", PARSE_ISSUE_KIND_TO_LINT_ID, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, AT_PREFIX_HINT_KNOWN_BY_KIND, LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
|
|
2381
2452
|
var init_lint_check = __esm(() => {
|
|
2382
2453
|
init_anode();
|
|
2454
|
+
PARSE_ISSUE_KIND_TO_LINT_ID = {
|
|
2455
|
+
"unknown-directive": UNKNOWN_DIRECTIVE,
|
|
2456
|
+
"unknown-x-op": UNKNOWN_X_OP,
|
|
2457
|
+
"unknown-x-attr": UNKNOWN_X_ATTR
|
|
2458
|
+
};
|
|
2459
|
+
X_KNOWN_OP_NAMES = new Set([
|
|
2460
|
+
"slot",
|
|
2461
|
+
"text",
|
|
2462
|
+
"render",
|
|
2463
|
+
"render-it",
|
|
2464
|
+
"render-each",
|
|
2465
|
+
"show",
|
|
2466
|
+
"hide"
|
|
2467
|
+
]);
|
|
2468
|
+
X_KNOWN_ATTR_NAMES = new Set(["as", "when", "loop-with", "show", "hide"]);
|
|
2469
|
+
AT_PREFIX_HINT_KNOWN_BY_KIND = {
|
|
2470
|
+
"unknown-x-op": X_KNOWN_OP_NAMES,
|
|
2471
|
+
"unknown-x-attr": X_KNOWN_ATTR_NAMES
|
|
2472
|
+
};
|
|
2383
2473
|
NO_WRAPPERS = {};
|
|
2384
2474
|
KNOWN_HANDLER_NAMES = new Set([
|
|
2385
2475
|
"value",
|
|
@@ -2405,10 +2495,14 @@ var init_lint_check = __esm(() => {
|
|
|
2405
2495
|
constructor(document2, Text, Comment) {
|
|
2406
2496
|
super(document2, Text, Comment);
|
|
2407
2497
|
this.attrs = [];
|
|
2498
|
+
this.parseIssues = [];
|
|
2408
2499
|
}
|
|
2409
2500
|
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false) {
|
|
2410
2501
|
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall });
|
|
2411
2502
|
}
|
|
2503
|
+
onParseIssue(kind, info) {
|
|
2504
|
+
this.parseIssues.push({ kind, info });
|
|
2505
|
+
}
|
|
2412
2506
|
};
|
|
2413
2507
|
});
|
|
2414
2508
|
|
package/dist/tutuca-dev.js
CHANGED
|
@@ -722,6 +722,8 @@ class AttrParser {
|
|
|
722
722
|
this.parseThen(s);
|
|
723
723
|
else if (directiveName.startsWith("else."))
|
|
724
724
|
this.parseElse(s);
|
|
725
|
+
else
|
|
726
|
+
this.px.onParseIssue("unknown-directive", { name: directiveName, value: s });
|
|
725
727
|
}
|
|
726
728
|
_parseWhen(s) {
|
|
727
729
|
if (this.eachAttr !== null)
|
|
@@ -1007,18 +1009,19 @@ class ANode extends BaseNode {
|
|
|
1007
1009
|
static parse(html, px) {
|
|
1008
1010
|
const nodes = px.parseHTML(html);
|
|
1009
1011
|
if (nodes.length === 0)
|
|
1010
|
-
return new
|
|
1012
|
+
return new CommentNode("Empty View in ANode.parse");
|
|
1011
1013
|
if (nodes.length === 1)
|
|
1012
1014
|
return ANode.fromDOM(nodes[0], px);
|
|
1013
|
-
const childs =
|
|
1014
|
-
for (let i = 0;i < nodes.length; i++)
|
|
1015
|
-
|
|
1015
|
+
const childs = [];
|
|
1016
|
+
for (let i = 0;i < nodes.length; i++) {
|
|
1017
|
+
const child = ANode.fromDOM(nodes[i], px);
|
|
1018
|
+
if (child !== null)
|
|
1019
|
+
childs.push(child);
|
|
1020
|
+
}
|
|
1016
1021
|
const trimmed = condenseChildsWhites(childs);
|
|
1017
1022
|
if (trimmed.length === 0)
|
|
1018
|
-
return new
|
|
1019
|
-
|
|
1020
|
-
return trimmed[0];
|
|
1021
|
-
return new FragmentNode(trimmed);
|
|
1023
|
+
return new CommentNode("Empty View in ANode.parse");
|
|
1024
|
+
return maybeFragment(trimmed);
|
|
1022
1025
|
}
|
|
1023
1026
|
static fromDOM(node, px) {
|
|
1024
1027
|
if (node instanceof px.Text)
|
|
@@ -1033,25 +1036,37 @@ class ANode extends BaseNode {
|
|
|
1033
1036
|
if (tag === "X" || isPseudoX) {
|
|
1034
1037
|
if (attrs.length === 0)
|
|
1035
1038
|
return maybeFragment(childs);
|
|
1036
|
-
const
|
|
1039
|
+
const opIdx = isPseudoX ? 1 : 0;
|
|
1040
|
+
const { name, value } = attrs[opIdx];
|
|
1037
1041
|
const as = attrs.getNamedItem("as")?.value ?? null;
|
|
1042
|
+
let node2;
|
|
1038
1043
|
switch (name) {
|
|
1039
1044
|
case "slot":
|
|
1040
|
-
|
|
1045
|
+
node2 = new SlotNode(null, vp.const(value), maybeFragment(childs));
|
|
1046
|
+
break;
|
|
1041
1047
|
case "text":
|
|
1042
|
-
|
|
1048
|
+
node2 = px.addNodeIf(RenderTextNode, vp.parseText(value, px));
|
|
1049
|
+
break;
|
|
1043
1050
|
case "render":
|
|
1044
|
-
|
|
1051
|
+
node2 = px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
|
|
1052
|
+
break;
|
|
1045
1053
|
case "render-it":
|
|
1046
|
-
|
|
1054
|
+
node2 = px.addNodeIf(RenderItNode, vp.bindValIt, as);
|
|
1055
|
+
break;
|
|
1047
1056
|
case "render-each":
|
|
1048
|
-
|
|
1057
|
+
node2 = RenderEachNode.parse(px, vp, value, as, attrs);
|
|
1058
|
+
break;
|
|
1049
1059
|
case "show":
|
|
1050
|
-
|
|
1060
|
+
node2 = px.addNodeIf(ShowNode, vp.parseCondValue(value, px), maybeFragment(childs));
|
|
1061
|
+
break;
|
|
1051
1062
|
case "hide":
|
|
1052
|
-
|
|
1063
|
+
node2 = px.addNodeIf(HideNode, vp.parseCondValue(value, px), maybeFragment(childs));
|
|
1064
|
+
break;
|
|
1065
|
+
default:
|
|
1066
|
+
px.onParseIssue("unknown-x-op", { name, value });
|
|
1067
|
+
return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
|
|
1053
1068
|
}
|
|
1054
|
-
return
|
|
1069
|
+
return processXExtras(node2, attrs, name, (isPseudoX ? 1 : 0) + 1, px);
|
|
1055
1070
|
} else if (tag.charCodeAt(1) === 58 && tag.charCodeAt(0) === 88) {
|
|
1056
1071
|
const macroName = tag.slice(2).toLowerCase();
|
|
1057
1072
|
if (macroName === "slot") {
|
|
@@ -1072,6 +1087,30 @@ class ANode extends BaseNode {
|
|
|
1072
1087
|
return new CommentNode(`Error: InvalidTagName ${tag}`);
|
|
1073
1088
|
}
|
|
1074
1089
|
}
|
|
1090
|
+
function processXExtras(node, attrs, opName, startIdx, px) {
|
|
1091
|
+
const consumed = X_OP_CONSUMED[opName];
|
|
1092
|
+
const wrappable = X_OP_WRAPPABLE.has(opName);
|
|
1093
|
+
const wrappers = [];
|
|
1094
|
+
for (let i = startIdx;i < attrs.length; i++) {
|
|
1095
|
+
const a = attrs[i];
|
|
1096
|
+
const aName = a.name;
|
|
1097
|
+
if (consumed.has(aName))
|
|
1098
|
+
continue;
|
|
1099
|
+
if (wrappable && X_ATTR_WRAPPERS[aName]) {
|
|
1100
|
+
wrappers.push([X_ATTR_WRAPPERS[aName], vp.parseCondValue(a.value, px)]);
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
const issueInfo = { op: opName, name: aName, value: a.value };
|
|
1104
|
+
px.onParseIssue("unknown-x-attr", issueInfo);
|
|
1105
|
+
}
|
|
1106
|
+
for (let i = wrappers.length - 1;i >= 0; i--) {
|
|
1107
|
+
const [Cls, val] = wrappers[i];
|
|
1108
|
+
const wrapper = px.addNodeIf(Cls, val, node);
|
|
1109
|
+
if (wrapper !== null)
|
|
1110
|
+
node = wrapper;
|
|
1111
|
+
}
|
|
1112
|
+
return node;
|
|
1113
|
+
}
|
|
1075
1114
|
function wrap(node, px, wrappers) {
|
|
1076
1115
|
if (wrappers) {
|
|
1077
1116
|
for (let i = wrappers.length - 1;i >= 0; i--) {
|
|
@@ -1299,6 +1338,17 @@ class IterInfo {
|
|
|
1299
1338
|
}
|
|
1300
1339
|
var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
1301
1340
|
var nullLoopWith = (seq) => ({ seq });
|
|
1341
|
+
var X_OP_CONSUMED = {
|
|
1342
|
+
slot: new Set,
|
|
1343
|
+
text: new Set,
|
|
1344
|
+
render: new Set(["as"]),
|
|
1345
|
+
"render-it": new Set(["as"]),
|
|
1346
|
+
"render-each": new Set(["as", "when", "loop-with"]),
|
|
1347
|
+
show: new Set,
|
|
1348
|
+
hide: new Set
|
|
1349
|
+
};
|
|
1350
|
+
var X_OP_WRAPPABLE = new Set(["text", "render", "render-it", "render-each"]);
|
|
1351
|
+
var X_ATTR_WRAPPERS = { show: ShowNode, hide: HideNode };
|
|
1302
1352
|
var WRAPPER_NODES = {
|
|
1303
1353
|
slot: SlotNode,
|
|
1304
1354
|
show: ShowNode,
|
|
@@ -1375,6 +1425,9 @@ class ParseContext {
|
|
|
1375
1425
|
return this.nodes[id] ?? null;
|
|
1376
1426
|
}
|
|
1377
1427
|
onAttributes(_attrs, _wrapperAttrs, _textChild, _isMacroCall) {}
|
|
1428
|
+
onParseIssue(kind, info) {
|
|
1429
|
+
console.warn(`tutuca parse issue [${kind}]`, info);
|
|
1430
|
+
}
|
|
1378
1431
|
}
|
|
1379
1432
|
var _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";
|
|
1380
1433
|
var HTML_BLOCK_TAGS = new Set(_htmlBlockTags.split(","));
|
|
@@ -1574,6 +1627,29 @@ var DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION";
|
|
|
1574
1627
|
var UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME";
|
|
1575
1628
|
var UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME";
|
|
1576
1629
|
var UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG";
|
|
1630
|
+
var UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE";
|
|
1631
|
+
var UNKNOWN_X_OP = "UNKNOWN_X_OP";
|
|
1632
|
+
var UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR";
|
|
1633
|
+
var MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX";
|
|
1634
|
+
var PARSE_ISSUE_KIND_TO_LINT_ID = {
|
|
1635
|
+
"unknown-directive": UNKNOWN_DIRECTIVE,
|
|
1636
|
+
"unknown-x-op": UNKNOWN_X_OP,
|
|
1637
|
+
"unknown-x-attr": UNKNOWN_X_ATTR
|
|
1638
|
+
};
|
|
1639
|
+
var X_KNOWN_OP_NAMES = new Set([
|
|
1640
|
+
"slot",
|
|
1641
|
+
"text",
|
|
1642
|
+
"render",
|
|
1643
|
+
"render-it",
|
|
1644
|
+
"render-each",
|
|
1645
|
+
"show",
|
|
1646
|
+
"hide"
|
|
1647
|
+
]);
|
|
1648
|
+
var X_KNOWN_ATTR_NAMES = new Set(["as", "when", "loop-with", "show", "hide"]);
|
|
1649
|
+
var AT_PREFIX_HINT_KNOWN_BY_KIND = {
|
|
1650
|
+
"unknown-x-op": X_KNOWN_OP_NAMES,
|
|
1651
|
+
"unknown-x-attr": X_KNOWN_ATTR_NAMES
|
|
1652
|
+
};
|
|
1577
1653
|
var LEVEL_WARN = "warn";
|
|
1578
1654
|
var LEVEL_ERROR = "error";
|
|
1579
1655
|
var LEVEL_HINT = "hint";
|
|
@@ -1594,11 +1670,29 @@ function checkComponent(Comp, lx = new LintContext) {
|
|
|
1594
1670
|
});
|
|
1595
1671
|
}
|
|
1596
1672
|
function checkView(lx, view, Comp, referencedAlters, referencedComputed) {
|
|
1673
|
+
checkParseIssues(lx, view);
|
|
1597
1674
|
checkRenderItInLoop(lx, view);
|
|
1598
1675
|
checkEventModifiers(lx, view);
|
|
1599
1676
|
checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedComputed);
|
|
1600
1677
|
checkMacroCallArgs(lx, view, Comp);
|
|
1601
1678
|
}
|
|
1679
|
+
function checkParseIssues(lx, view) {
|
|
1680
|
+
const issues = view.ctx.parseIssues;
|
|
1681
|
+
if (!issues)
|
|
1682
|
+
return;
|
|
1683
|
+
for (const { kind, info } of issues) {
|
|
1684
|
+
const id = PARSE_ISSUE_KIND_TO_LINT_ID[kind];
|
|
1685
|
+
if (!id)
|
|
1686
|
+
continue;
|
|
1687
|
+
lx.error(id, info);
|
|
1688
|
+
const known = AT_PREFIX_HINT_KNOWN_BY_KIND[kind];
|
|
1689
|
+
if (known && info.name?.startsWith("@")) {
|
|
1690
|
+
const suggestion = info.name.slice(1);
|
|
1691
|
+
if (known.has(suggestion))
|
|
1692
|
+
lx.hint(MAYBE_DROP_AT_PREFIX, { ...info, suggestion });
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1602
1696
|
function checkMacroCallArgs(lx, view, Comp) {
|
|
1603
1697
|
const { scope } = Comp;
|
|
1604
1698
|
for (const macroNode of view.ctx.macroNodes) {
|
|
@@ -1913,10 +2007,14 @@ class LintParseContext extends ParseContext {
|
|
|
1913
2007
|
constructor(document2, Text, Comment) {
|
|
1914
2008
|
super(document2, Text, Comment);
|
|
1915
2009
|
this.attrs = [];
|
|
2010
|
+
this.parseIssues = [];
|
|
1916
2011
|
}
|
|
1917
2012
|
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false) {
|
|
1918
2013
|
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall });
|
|
1919
2014
|
}
|
|
2015
|
+
onParseIssue(kind, info) {
|
|
2016
|
+
this.parseIssues.push({ kind, info });
|
|
2017
|
+
}
|
|
1920
2018
|
}
|
|
1921
2019
|
|
|
1922
2020
|
// tools/format/lint.js
|
|
@@ -1956,6 +2054,14 @@ function lintIdToMessage(id, info) {
|
|
|
1956
2054
|
return `Alter handler '${info.name}' is defined but not referenced`;
|
|
1957
2055
|
case "UNKNOWN_MACRO_ARG":
|
|
1958
2056
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
2057
|
+
case "UNKNOWN_DIRECTIVE":
|
|
2058
|
+
return `Unknown directive '@${info.name}=${JSON.stringify(info.value)}'`;
|
|
2059
|
+
case "UNKNOWN_X_OP":
|
|
2060
|
+
return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'`;
|
|
2061
|
+
case "UNKNOWN_X_ATTR":
|
|
2062
|
+
return `Unknown attribute '${info.name}=${JSON.stringify(info.value)}' on <x ${info.op}>`;
|
|
2063
|
+
case "MAYBE_DROP_AT_PREFIX":
|
|
2064
|
+
return `Did you mean '${info.suggestion}'? Drop the '@' prefix on <x>.`;
|
|
1959
2065
|
case "LINT_ERROR":
|
|
1960
2066
|
return info.message;
|
|
1961
2067
|
default:
|
|
@@ -8624,6 +8730,7 @@ class LintClassCollectorCtx extends ParseCtxClassSetCollector {
|
|
|
8624
8730
|
constructor(...args) {
|
|
8625
8731
|
super(...args);
|
|
8626
8732
|
this.attrs = [];
|
|
8733
|
+
this.parseIssues = [];
|
|
8627
8734
|
}
|
|
8628
8735
|
enterMacro(macroName, macroVars, macroSlots) {
|
|
8629
8736
|
const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
|
|
@@ -8631,12 +8738,16 @@ class LintClassCollectorCtx extends ParseCtxClassSetCollector {
|
|
|
8631
8738
|
const v = new LintClassCollectorCtx(document2, Text, Comment, nodes, events, macroNodes, frame, this);
|
|
8632
8739
|
v.classes = this.classes;
|
|
8633
8740
|
v.attrs = this.attrs;
|
|
8741
|
+
v.parseIssues = this.parseIssues;
|
|
8634
8742
|
return v;
|
|
8635
8743
|
}
|
|
8636
8744
|
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false) {
|
|
8637
8745
|
super.onAttributes(attrs, wrapperAttrs, textChild, isMacroCall);
|
|
8638
8746
|
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall });
|
|
8639
8747
|
}
|
|
8748
|
+
onParseIssue(kind, info) {
|
|
8749
|
+
this.parseIssues.push({ kind, info });
|
|
8750
|
+
}
|
|
8640
8751
|
}
|
|
8641
8752
|
export {
|
|
8642
8753
|
version,
|
|
@@ -8688,10 +8799,13 @@ export {
|
|
|
8688
8799
|
compileClassesToStyle,
|
|
8689
8800
|
checkComponent,
|
|
8690
8801
|
check,
|
|
8802
|
+
UNKNOWN_X_OP,
|
|
8803
|
+
UNKNOWN_X_ATTR,
|
|
8691
8804
|
UNKNOWN_REQUEST_NAME,
|
|
8692
8805
|
UNKNOWN_MACRO_ARG,
|
|
8693
8806
|
UNKNOWN_HANDLER_ARG_NAME,
|
|
8694
8807
|
UNKNOWN_EVENT_MODIFIER,
|
|
8808
|
+
UNKNOWN_DIRECTIVE,
|
|
8695
8809
|
UNKNOWN_COMPONENT_NAME,
|
|
8696
8810
|
Stack2 as Stack,
|
|
8697
8811
|
Set2 as Set,
|
|
@@ -8707,6 +8821,7 @@ export {
|
|
|
8707
8821
|
OrderedMap,
|
|
8708
8822
|
OrderedMap as OMap,
|
|
8709
8823
|
Map2 as Map,
|
|
8824
|
+
MAYBE_DROP_AT_PREFIX,
|
|
8710
8825
|
List,
|
|
8711
8826
|
LintParseContext,
|
|
8712
8827
|
LintContext,
|