tutuca 0.9.101 → 0.9.102
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 +89 -6
- package/dist/tutuca-dev.ext.js +27 -3
- package/dist/tutuca-dev.js +27 -3
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +11 -3
- package/dist/tutuca-extra.js +11 -3
- package/dist/tutuca-extra.min.js +1 -1
- package/dist/tutuca-storybook.js +168 -45
- package/dist/tutuca.ext.js +11 -3
- package/dist/tutuca.js +11 -3
- package/dist/tutuca.min.js +1 -1
- package/package.json +1 -1
- package/skill/tutuca-source/tutuca.ext.js +11 -3
package/dist/tutuca-cli.js
CHANGED
|
@@ -3447,9 +3447,10 @@ function resolveComponentName(value, components) {
|
|
|
3447
3447
|
}
|
|
3448
3448
|
|
|
3449
3449
|
class ExampleSection {
|
|
3450
|
-
constructor({ title, description = null, items = [] }) {
|
|
3450
|
+
constructor({ title, description = null, group = "", items = [] }) {
|
|
3451
3451
|
this.title = title;
|
|
3452
3452
|
this.description = description;
|
|
3453
|
+
this.group = group;
|
|
3453
3454
|
this.items = items;
|
|
3454
3455
|
}
|
|
3455
3456
|
}
|
|
@@ -3500,9 +3501,13 @@ function parseSection(raw, components, where) {
|
|
|
3500
3501
|
if (items.length === 0) {
|
|
3501
3502
|
throw shapeError(`section at ${where} has no items`, where);
|
|
3502
3503
|
}
|
|
3504
|
+
if (raw.group != null && typeof raw.group !== "string") {
|
|
3505
|
+
throw shapeError(`section at ${where} has a non-string "group" (got ${typeof raw.group}); ` + `group must be a string naming the sidebar group, or be omitted`, where);
|
|
3506
|
+
}
|
|
3503
3507
|
return new ExampleSection({
|
|
3504
3508
|
title: raw.title ?? "Examples",
|
|
3505
3509
|
description: raw.description ?? null,
|
|
3510
|
+
group: raw.group ?? "",
|
|
3506
3511
|
items
|
|
3507
3512
|
});
|
|
3508
3513
|
}
|
|
@@ -3547,6 +3552,34 @@ function normalizeModule(mod, { path = null } = {}) {
|
|
|
3547
3552
|
present
|
|
3548
3553
|
};
|
|
3549
3554
|
}
|
|
3555
|
+
function findComponentNameConflicts(entries) {
|
|
3556
|
+
const byName = new Map;
|
|
3557
|
+
for (const { path, components } of entries) {
|
|
3558
|
+
for (const comp of components ?? []) {
|
|
3559
|
+
if (!comp || typeof comp.name !== "string")
|
|
3560
|
+
continue;
|
|
3561
|
+
let objs = byName.get(comp.name);
|
|
3562
|
+
if (!objs)
|
|
3563
|
+
byName.set(comp.name, objs = new Map);
|
|
3564
|
+
let paths = objs.get(comp);
|
|
3565
|
+
if (!paths)
|
|
3566
|
+
objs.set(comp, paths = new Set);
|
|
3567
|
+
if (path != null)
|
|
3568
|
+
paths.add(path);
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
const conflicts = [];
|
|
3572
|
+
for (const [name, objs] of byName) {
|
|
3573
|
+
if (objs.size < 2)
|
|
3574
|
+
continue;
|
|
3575
|
+
const paths = new Set;
|
|
3576
|
+
for (const set2 of objs.values())
|
|
3577
|
+
for (const p of set2)
|
|
3578
|
+
paths.add(p);
|
|
3579
|
+
conflicts.push({ name, paths: [...paths].sort() });
|
|
3580
|
+
}
|
|
3581
|
+
return conflicts.sort((a, b) => a.name.localeCompare(b.name));
|
|
3582
|
+
}
|
|
3550
3583
|
var EXAMPLES_SHAPE_MISMATCH = "EXAMPLES_SHAPE_MISMATCH";
|
|
3551
3584
|
|
|
3552
3585
|
// tools/core/results.js
|
|
@@ -9783,13 +9816,16 @@ class Renderer {
|
|
|
9783
9816
|
if (cachedNode)
|
|
9784
9817
|
return cachedNode;
|
|
9785
9818
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
9819
|
+
const body = this.renderView(view, stack);
|
|
9820
|
+
if (body == null)
|
|
9821
|
+
return null;
|
|
9786
9822
|
const meta = this._renderMetadata({
|
|
9787
9823
|
$: "Comp",
|
|
9788
9824
|
nid: node?.nodeId ?? null,
|
|
9789
9825
|
cid: comp.id,
|
|
9790
9826
|
vid: view.name
|
|
9791
9827
|
});
|
|
9792
|
-
const dom = new VFragment([meta,
|
|
9828
|
+
const dom = new VFragment([meta, body]);
|
|
9793
9829
|
this.cache.set(cachePath, cacheKey, dom);
|
|
9794
9830
|
return dom;
|
|
9795
9831
|
}
|
|
@@ -9802,7 +9838,8 @@ class Renderer {
|
|
|
9802
9838
|
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9803
9839
|
const renderOne = (key, value, attrName) => {
|
|
9804
9840
|
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
9805
|
-
|
|
9841
|
+
if (dom != null)
|
|
9842
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
9806
9843
|
};
|
|
9807
9844
|
if (keys)
|
|
9808
9845
|
imKeysIter(seq, renderOne, keys);
|
|
@@ -9829,7 +9866,8 @@ class Renderer {
|
|
|
9829
9866
|
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
9830
9867
|
else {
|
|
9831
9868
|
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
9832
|
-
|
|
9869
|
+
if (dom != null)
|
|
9870
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
9833
9871
|
this.cache.set(cachePath, cacheKey, dom);
|
|
9834
9872
|
}
|
|
9835
9873
|
};
|
|
@@ -13010,6 +13048,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
|
|
|
13010
13048
|
return lx.push({ componentName: Comp.name }, () => {
|
|
13011
13049
|
checkUnknownSpecKeys(lx, Comp, wellKnownExtras);
|
|
13012
13050
|
checkFieldDeclarations(lx, Comp);
|
|
13051
|
+
checkRecordFieldNameCollisions(lx, Comp);
|
|
13013
13052
|
checkProvidesAreAddressable(lx, Comp);
|
|
13014
13053
|
checkLookupShapes(lx, Comp);
|
|
13015
13054
|
checkHandlersNotAsync(lx, Comp);
|
|
@@ -13400,6 +13439,16 @@ function checkFieldDeclarations(lx, Comp) {
|
|
|
13400
13439
|
}
|
|
13401
13440
|
}
|
|
13402
13441
|
}
|
|
13442
|
+
function checkRecordFieldNameCollisions(lx, Comp) {
|
|
13443
|
+
const fields = Comp.Class?.getMetaClass?.().fields;
|
|
13444
|
+
if (!fields)
|
|
13445
|
+
return;
|
|
13446
|
+
for (const name in fields) {
|
|
13447
|
+
if (RECORD_FIELD_NAME_COLLISIONS.has(name)) {
|
|
13448
|
+
lx.error(FIELD_NAME_RESERVED_BY_RECORD, { name });
|
|
13449
|
+
}
|
|
13450
|
+
}
|
|
13451
|
+
}
|
|
13403
13452
|
function checkUnreferencedAlterHandlers(lx, Comp, referencedAlters) {
|
|
13404
13453
|
for (const name in Comp.alter) {
|
|
13405
13454
|
if (!referencedAlters.has(name)) {
|
|
@@ -13561,7 +13610,7 @@ class LintContext {
|
|
|
13561
13610
|
this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
|
|
13562
13611
|
}
|
|
13563
13612
|
}
|
|
13564
|
-
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", 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;
|
|
13613
|
+
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;
|
|
13565
13614
|
var init_lint_check = __esm(() => {
|
|
13566
13615
|
init_anode();
|
|
13567
13616
|
init_htmllinter();
|
|
@@ -13582,6 +13631,7 @@ var init_lint_check = __esm(() => {
|
|
|
13582
13631
|
"then",
|
|
13583
13632
|
"else"
|
|
13584
13633
|
]);
|
|
13634
|
+
RECORD_FIELD_NAME_COLLISIONS = new Set(["entries", "hashCode"]);
|
|
13585
13635
|
X_KNOWN_OP_NAMES = new Set([
|
|
13586
13636
|
"slot",
|
|
13587
13637
|
"text",
|
|
@@ -15415,6 +15465,12 @@ var init_lint_rules = __esm(() => {
|
|
|
15415
15465
|
level: "error",
|
|
15416
15466
|
group: "Component field declarations",
|
|
15417
15467
|
summary: "`fields: { x: { component, args } }` shape is wrong: `component` must be a string and `args` must be a plain object."
|
|
15468
|
+
},
|
|
15469
|
+
{
|
|
15470
|
+
code: FIELD_NAME_RESERVED_BY_RECORD,
|
|
15471
|
+
level: "error",
|
|
15472
|
+
group: "Component field declarations",
|
|
15473
|
+
summary: "Field name matches an Immutable Record API member, so `.field` reads the API member instead of the value."
|
|
15418
15474
|
}
|
|
15419
15475
|
];
|
|
15420
15476
|
});
|
|
@@ -15508,6 +15564,8 @@ function lintIdToMessage(id, info) {
|
|
|
15508
15564
|
return `'$${info.name}' is a method reference, but '${info.name}' is defined as an input handler${fmtEventSuffix(info)}`;
|
|
15509
15565
|
case "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER":
|
|
15510
15566
|
return `'${info.name}' is an input handler reference, but '${info.name}' is defined as a method${fmtEventSuffix(info)}`;
|
|
15567
|
+
case "FIELD_NAME_RESERVED_BY_RECORD":
|
|
15568
|
+
return `Field '${info.name}' collides with the Immutable Record API: '.${info.name}' reads the Record member, not your value — rename the field (its value is only reachable via .get('${info.name}'))`;
|
|
15511
15569
|
case "FIELD_VAL_NOT_DEFINED":
|
|
15512
15570
|
return `Field '.${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
15513
15571
|
case "FIELD_VAL_IS_METHOD":
|
|
@@ -16212,6 +16270,23 @@ async function runDevTests(projectDir, devModuleUrls) {
|
|
|
16212
16270
|
}
|
|
16213
16271
|
return { totalTests, failedTests, withTests, failures, importErrors };
|
|
16214
16272
|
}
|
|
16273
|
+
async function checkComponentNameConflicts(projectDir, devModuleUrls) {
|
|
16274
|
+
await createNodeEnv();
|
|
16275
|
+
const entries = [];
|
|
16276
|
+
for (const url of devModuleUrls) {
|
|
16277
|
+
const abs = resolve5(projectDir, url.slice(1));
|
|
16278
|
+
try {
|
|
16279
|
+
const mod = await import(abs);
|
|
16280
|
+
const components = typeof mod.getComponents === "function" ? mod.getComponents() : [];
|
|
16281
|
+
entries.push({ path: url, components });
|
|
16282
|
+
} catch {}
|
|
16283
|
+
}
|
|
16284
|
+
return findComponentNameConflicts(entries);
|
|
16285
|
+
}
|
|
16286
|
+
function formatComponentNameConflict(c) {
|
|
16287
|
+
return ` ! component name conflict: "${c.name}" is defined by different component objects in ${c.paths.length} modules (${c.paths.join(", ")}). They share a name but are distinct objects, so the storybook registers one and the other renders uncompiled (throws on ` + `render). Make those modules import the same definition — e.g. all from "tutuca/components" ` + `rather than a relative path.
|
|
16288
|
+
`;
|
|
16289
|
+
}
|
|
16215
16290
|
async function discoverModules(projectDir, devModuleUrls) {
|
|
16216
16291
|
await createNodeEnv();
|
|
16217
16292
|
const modules = [];
|
|
@@ -16353,6 +16428,7 @@ async function run4(argv, opts = {}) {
|
|
|
16353
16428
|
const imports2 = buildImports(base2, { margaui });
|
|
16354
16429
|
const modules = await discoverModules(projectDir, devModuleUrls);
|
|
16355
16430
|
const tests = parsed.values["no-tests"] ? null : await runDevTests(projectDir, devModuleUrls);
|
|
16431
|
+
const componentNameConflicts = await checkComponentNameConflicts(projectDir, devModuleUrls);
|
|
16356
16432
|
const source = tutucaSource(base2);
|
|
16357
16433
|
const result = {
|
|
16358
16434
|
projectDir,
|
|
@@ -16360,7 +16436,8 @@ async function run4(argv, opts = {}) {
|
|
|
16360
16436
|
options: { margaui, check, noCache, runTests: !parsed.values["no-tests"] },
|
|
16361
16437
|
imports: imports2,
|
|
16362
16438
|
modules,
|
|
16363
|
-
tests
|
|
16439
|
+
tests,
|
|
16440
|
+
componentNameConflicts
|
|
16364
16441
|
};
|
|
16365
16442
|
if (opts.format === "json") {
|
|
16366
16443
|
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
@@ -16403,6 +16480,9 @@ async function run4(argv, opts = {}) {
|
|
|
16403
16480
|
process.stdout.write(` tests: skipped (--no-tests)
|
|
16404
16481
|
`);
|
|
16405
16482
|
}
|
|
16483
|
+
for (const c of componentNameConflicts) {
|
|
16484
|
+
process.stdout.write(formatComponentNameConflict(c));
|
|
16485
|
+
}
|
|
16406
16486
|
return;
|
|
16407
16487
|
}
|
|
16408
16488
|
if (!parsed.values["no-tests"]) {
|
|
@@ -16423,6 +16503,9 @@ async function run4(argv, opts = {}) {
|
|
|
16423
16503
|
}
|
|
16424
16504
|
}
|
|
16425
16505
|
}
|
|
16506
|
+
for (const c of await checkComponentNameConflicts(projectDir, devModuleUrls)) {
|
|
16507
|
+
process.stdout.write(formatComponentNameConflict(c));
|
|
16508
|
+
}
|
|
16426
16509
|
const { base, serveDist } = resolveTutucaBase(projectDir, self, false);
|
|
16427
16510
|
const imports = buildImports(base, { margaui });
|
|
16428
16511
|
const indexHtml = renderIndexHtml(imports, { margaui, bootstrapUrl: BOOTSTRAP_URL });
|
package/dist/tutuca-dev.ext.js
CHANGED
|
@@ -1825,13 +1825,16 @@ class Renderer {
|
|
|
1825
1825
|
if (cachedNode)
|
|
1826
1826
|
return cachedNode;
|
|
1827
1827
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
1828
|
+
const body = this.renderView(view, stack);
|
|
1829
|
+
if (body == null)
|
|
1830
|
+
return null;
|
|
1828
1831
|
const meta = this._renderMetadata({
|
|
1829
1832
|
$: "Comp",
|
|
1830
1833
|
nid: node?.nodeId ?? null,
|
|
1831
1834
|
cid: comp.id,
|
|
1832
1835
|
vid: view.name
|
|
1833
1836
|
});
|
|
1834
|
-
const dom = new VFragment([meta,
|
|
1837
|
+
const dom = new VFragment([meta, body]);
|
|
1835
1838
|
this.cache.set(cachePath, cacheKey, dom);
|
|
1836
1839
|
return dom;
|
|
1837
1840
|
}
|
|
@@ -1844,7 +1847,8 @@ class Renderer {
|
|
|
1844
1847
|
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
1845
1848
|
const renderOne = (key, value, attrName) => {
|
|
1846
1849
|
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
1847
|
-
|
|
1850
|
+
if (dom != null)
|
|
1851
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
1848
1852
|
};
|
|
1849
1853
|
if (keys)
|
|
1850
1854
|
imKeysIter(seq, renderOne, keys);
|
|
@@ -1871,7 +1875,8 @@ class Renderer {
|
|
|
1871
1875
|
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
1872
1876
|
else {
|
|
1873
1877
|
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
1874
|
-
|
|
1878
|
+
if (dom != null)
|
|
1879
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
1875
1880
|
this.cache.set(cachePath, cacheKey, dom);
|
|
1876
1881
|
}
|
|
1877
1882
|
};
|
|
@@ -2635,6 +2640,9 @@ class View {
|
|
|
2635
2640
|
this.anode = optimizeNode(this.anode);
|
|
2636
2641
|
}
|
|
2637
2642
|
render(stack, rx) {
|
|
2643
|
+
if (this.anode === null) {
|
|
2644
|
+
throw new Error(`tutuca: view "${this.name}" was rendered before it was compiled — its ` + `component is not registered in this app/scope. Source: ` + `${String(this.rawView).slice(0, 80).replace(/\s+/g, " ")}…`);
|
|
2645
|
+
}
|
|
2638
2646
|
return this.anode.render(stack, rx);
|
|
2639
2647
|
}
|
|
2640
2648
|
}
|
|
@@ -5088,6 +5096,8 @@ var COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE";
|
|
|
5088
5096
|
var ASYNC_HANDLER = "ASYNC_HANDLER";
|
|
5089
5097
|
var TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE";
|
|
5090
5098
|
var GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE";
|
|
5099
|
+
var FIELD_NAME_RESERVED_BY_RECORD = "FIELD_NAME_RESERVED_BY_RECORD";
|
|
5100
|
+
var RECORD_FIELD_NAME_COLLISIONS = new Set(["entries", "hashCode"]);
|
|
5091
5101
|
var X_KNOWN_OP_NAMES = new Set([
|
|
5092
5102
|
"slot",
|
|
5093
5103
|
"text",
|
|
@@ -5176,6 +5186,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
|
|
|
5176
5186
|
return lx.push({ componentName: Comp.name }, () => {
|
|
5177
5187
|
checkUnknownSpecKeys(lx, Comp, wellKnownExtras);
|
|
5178
5188
|
checkFieldDeclarations(lx, Comp);
|
|
5189
|
+
checkRecordFieldNameCollisions(lx, Comp);
|
|
5179
5190
|
checkProvidesAreAddressable(lx, Comp);
|
|
5180
5191
|
checkLookupShapes(lx, Comp);
|
|
5181
5192
|
checkHandlersNotAsync(lx, Comp);
|
|
@@ -5668,6 +5679,16 @@ function checkFieldDeclarations(lx, Comp) {
|
|
|
5668
5679
|
}
|
|
5669
5680
|
}
|
|
5670
5681
|
}
|
|
5682
|
+
function checkRecordFieldNameCollisions(lx, Comp) {
|
|
5683
|
+
const fields = Comp.Class?.getMetaClass?.().fields;
|
|
5684
|
+
if (!fields)
|
|
5685
|
+
return;
|
|
5686
|
+
for (const name in fields) {
|
|
5687
|
+
if (RECORD_FIELD_NAME_COLLISIONS.has(name)) {
|
|
5688
|
+
lx.error(FIELD_NAME_RESERVED_BY_RECORD, { name });
|
|
5689
|
+
}
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5671
5692
|
function checkUnreferencedAlterHandlers(lx, Comp, referencedAlters) {
|
|
5672
5693
|
for (const name in Comp.alter) {
|
|
5673
5694
|
if (!referencedAlters.has(name)) {
|
|
@@ -7256,6 +7277,8 @@ function lintIdToMessage(id, info) {
|
|
|
7256
7277
|
return `'$${info.name}' is a method reference, but '${info.name}' is defined as an input handler${fmtEventSuffix(info)}`;
|
|
7257
7278
|
case "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER":
|
|
7258
7279
|
return `'${info.name}' is an input handler reference, but '${info.name}' is defined as a method${fmtEventSuffix(info)}`;
|
|
7280
|
+
case "FIELD_NAME_RESERVED_BY_RECORD":
|
|
7281
|
+
return `Field '${info.name}' collides with the Immutable Record API: '.${info.name}' reads the Record member, not your value — rename the field (its value is only reachable via .get('${info.name}'))`;
|
|
7259
7282
|
case "FIELD_VAL_NOT_DEFINED":
|
|
7260
7283
|
return `Field '.${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
7261
7284
|
case "FIELD_VAL_IS_METHOD":
|
|
@@ -8569,6 +8592,7 @@ export {
|
|
|
8569
8592
|
GLOBAL_SELECTOR_IN_SCOPED_STYLE,
|
|
8570
8593
|
FIELD_VAL_NOT_DEFINED,
|
|
8571
8594
|
FIELD_VAL_IS_METHOD,
|
|
8595
|
+
FIELD_NAME_RESERVED_BY_RECORD,
|
|
8572
8596
|
FIELD_CLASS,
|
|
8573
8597
|
ExampleIndex,
|
|
8574
8598
|
DescribeResult,
|
package/dist/tutuca-dev.js
CHANGED
|
@@ -9476,13 +9476,16 @@ class Renderer {
|
|
|
9476
9476
|
if (cachedNode)
|
|
9477
9477
|
return cachedNode;
|
|
9478
9478
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
9479
|
+
const body = this.renderView(view, stack);
|
|
9480
|
+
if (body == null)
|
|
9481
|
+
return null;
|
|
9479
9482
|
const meta = this._renderMetadata({
|
|
9480
9483
|
$: "Comp",
|
|
9481
9484
|
nid: node?.nodeId ?? null,
|
|
9482
9485
|
cid: comp.id,
|
|
9483
9486
|
vid: view.name
|
|
9484
9487
|
});
|
|
9485
|
-
const dom = new VFragment([meta,
|
|
9488
|
+
const dom = new VFragment([meta, body]);
|
|
9486
9489
|
this.cache.set(cachePath, cacheKey, dom);
|
|
9487
9490
|
return dom;
|
|
9488
9491
|
}
|
|
@@ -9495,7 +9498,8 @@ class Renderer {
|
|
|
9495
9498
|
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9496
9499
|
const renderOne = (key, value, attrName) => {
|
|
9497
9500
|
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
9498
|
-
|
|
9501
|
+
if (dom != null)
|
|
9502
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
9499
9503
|
};
|
|
9500
9504
|
if (keys)
|
|
9501
9505
|
imKeysIter(seq, renderOne, keys);
|
|
@@ -9522,7 +9526,8 @@ class Renderer {
|
|
|
9522
9526
|
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
9523
9527
|
else {
|
|
9524
9528
|
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
9525
|
-
|
|
9529
|
+
if (dom != null)
|
|
9530
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
9526
9531
|
this.cache.set(cachePath, cacheKey, dom);
|
|
9527
9532
|
}
|
|
9528
9533
|
};
|
|
@@ -10286,6 +10291,9 @@ class View {
|
|
|
10286
10291
|
this.anode = optimizeNode(this.anode);
|
|
10287
10292
|
}
|
|
10288
10293
|
render(stack, rx) {
|
|
10294
|
+
if (this.anode === null) {
|
|
10295
|
+
throw new Error(`tutuca: view "${this.name}" was rendered before it was compiled — its ` + `component is not registered in this app/scope. Source: ` + `${String(this.rawView).slice(0, 80).replace(/\s+/g, " ")}…`);
|
|
10296
|
+
}
|
|
10289
10297
|
return this.anode.render(stack, rx);
|
|
10290
10298
|
}
|
|
10291
10299
|
}
|
|
@@ -12739,6 +12747,8 @@ var COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE";
|
|
|
12739
12747
|
var ASYNC_HANDLER = "ASYNC_HANDLER";
|
|
12740
12748
|
var TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE";
|
|
12741
12749
|
var GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE";
|
|
12750
|
+
var FIELD_NAME_RESERVED_BY_RECORD = "FIELD_NAME_RESERVED_BY_RECORD";
|
|
12751
|
+
var RECORD_FIELD_NAME_COLLISIONS = new Set(["entries", "hashCode"]);
|
|
12742
12752
|
var X_KNOWN_OP_NAMES = new Set([
|
|
12743
12753
|
"slot",
|
|
12744
12754
|
"text",
|
|
@@ -12827,6 +12837,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
|
|
|
12827
12837
|
return lx.push({ componentName: Comp.name }, () => {
|
|
12828
12838
|
checkUnknownSpecKeys(lx, Comp, wellKnownExtras);
|
|
12829
12839
|
checkFieldDeclarations(lx, Comp);
|
|
12840
|
+
checkRecordFieldNameCollisions(lx, Comp);
|
|
12830
12841
|
checkProvidesAreAddressable(lx, Comp);
|
|
12831
12842
|
checkLookupShapes(lx, Comp);
|
|
12832
12843
|
checkHandlersNotAsync(lx, Comp);
|
|
@@ -13319,6 +13330,16 @@ function checkFieldDeclarations(lx, Comp) {
|
|
|
13319
13330
|
}
|
|
13320
13331
|
}
|
|
13321
13332
|
}
|
|
13333
|
+
function checkRecordFieldNameCollisions(lx, Comp) {
|
|
13334
|
+
const fields = Comp.Class?.getMetaClass?.().fields;
|
|
13335
|
+
if (!fields)
|
|
13336
|
+
return;
|
|
13337
|
+
for (const name in fields) {
|
|
13338
|
+
if (RECORD_FIELD_NAME_COLLISIONS.has(name)) {
|
|
13339
|
+
lx.error(FIELD_NAME_RESERVED_BY_RECORD, { name });
|
|
13340
|
+
}
|
|
13341
|
+
}
|
|
13342
|
+
}
|
|
13322
13343
|
function checkUnreferencedAlterHandlers(lx, Comp, referencedAlters) {
|
|
13323
13344
|
for (const name in Comp.alter) {
|
|
13324
13345
|
if (!referencedAlters.has(name)) {
|
|
@@ -14907,6 +14928,8 @@ function lintIdToMessage(id, info) {
|
|
|
14907
14928
|
return `'$${info.name}' is a method reference, but '${info.name}' is defined as an input handler${fmtEventSuffix(info)}`;
|
|
14908
14929
|
case "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER":
|
|
14909
14930
|
return `'${info.name}' is an input handler reference, but '${info.name}' is defined as a method${fmtEventSuffix(info)}`;
|
|
14931
|
+
case "FIELD_NAME_RESERVED_BY_RECORD":
|
|
14932
|
+
return `Field '${info.name}' collides with the Immutable Record API: '.${info.name}' reads the Record member, not your value — rename the field (its value is only reachable via .get('${info.name}'))`;
|
|
14910
14933
|
case "FIELD_VAL_NOT_DEFINED":
|
|
14911
14934
|
return `Field '.${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
14912
14935
|
case "FIELD_VAL_IS_METHOD":
|
|
@@ -16163,6 +16186,7 @@ export {
|
|
|
16163
16186
|
GLOBAL_SELECTOR_IN_SCOPED_STYLE,
|
|
16164
16187
|
FIELD_VAL_NOT_DEFINED,
|
|
16165
16188
|
FIELD_VAL_IS_METHOD,
|
|
16189
|
+
FIELD_NAME_RESERVED_BY_RECORD,
|
|
16166
16190
|
FIELD_CLASS,
|
|
16167
16191
|
ExampleIndex,
|
|
16168
16192
|
DescribeResult,
|