tutuca 0.9.97 → 0.9.99
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 +5 -3
- package/dist/tutuca-cli.js +208 -69
- package/dist/tutuca-components.js +2444 -0
- package/dist/tutuca-dev.ext.js +92 -45
- package/dist/tutuca-dev.js +92 -45
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +56 -28
- package/dist/tutuca-extra.js +56 -28
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +136 -10
- package/dist/tutuca.ext.js +56 -28
- package/dist/tutuca.js +56 -28
- package/dist/tutuca.min.js +2 -2
- package/package.json +5 -3
- package/skill/tutuca/advanced.md +14 -5
- package/skill/tutuca/cli.md +10 -68
- package/skill/tutuca/core.md +103 -89
- package/skill/tutuca/margaui.md +25 -13
- package/skill/tutuca/patterns/README.md +1 -0
- package/skill/tutuca/patterns/filter-a-list.md +3 -1
- package/skill/tutuca/patterns/filter-and-paginate.md +116 -0
- package/skill/tutuca/patterns/paginate-a-list.md +3 -1
- package/skill/tutuca/semantics.md +4 -3
- package/skill/tutuca/storybook.md +7 -2
- package/skill/tutuca/testing.md +14 -6
- package/skill/tutuca-source/tutuca.ext.js +56 -28
package/dist/tutuca-dev.ext.js
CHANGED
|
@@ -95,7 +95,6 @@ import {
|
|
|
95
95
|
util
|
|
96
96
|
} from "chai";
|
|
97
97
|
chai.use(jestMatchers);
|
|
98
|
-
|
|
99
98
|
// src/value.js
|
|
100
99
|
import { is } from "immutable";
|
|
101
100
|
|
|
@@ -1842,37 +1841,47 @@ class Renderer {
|
|
|
1842
1841
|
renderEach(stack, iterInfo, node, viewName) {
|
|
1843
1842
|
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
1844
1843
|
const r = [];
|
|
1845
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1844
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
1845
|
+
const renderOne = (key, value, attrName) => {
|
|
1846
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
1847
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
1848
|
+
};
|
|
1849
|
+
if (keys)
|
|
1850
|
+
imKeysIter(seq, renderOne, keys);
|
|
1851
|
+
else
|
|
1852
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1853
|
+
if (filter.call(stack.it, key, value, iterData))
|
|
1854
|
+
renderOne(key, value, attrName);
|
|
1855
|
+
}, start, end);
|
|
1852
1856
|
return r;
|
|
1853
1857
|
}
|
|
1854
1858
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
1855
1859
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
1856
1860
|
const r = [];
|
|
1857
1861
|
const it = stack.it;
|
|
1858
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
1873
|
-
}
|
|
1862
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
|
|
1863
|
+
const renderOne = (key, value, attrName) => {
|
|
1864
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
1865
|
+
const binds = { key, value };
|
|
1866
|
+
const cacheKey = `${nid}-${key}`;
|
|
1867
|
+
if (enricher)
|
|
1868
|
+
enricher.call(it, binds, key, value, iterData);
|
|
1869
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
1870
|
+
if (cachedNode)
|
|
1871
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
1872
|
+
else {
|
|
1873
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
1874
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
1875
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
1874
1876
|
}
|
|
1875
|
-
}
|
|
1877
|
+
};
|
|
1878
|
+
if (keys)
|
|
1879
|
+
imKeysIter(seq, renderOne, keys);
|
|
1880
|
+
else
|
|
1881
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1882
|
+
if (filter.call(it, key, value, iterData))
|
|
1883
|
+
renderOne(key, value, attrName);
|
|
1884
|
+
}, start, end);
|
|
1876
1885
|
return r;
|
|
1877
1886
|
}
|
|
1878
1887
|
renderView(view, stack) {
|
|
@@ -1908,8 +1917,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
|
1908
1917
|
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
1909
1918
|
var unpackLoopResult = (result, seq) => {
|
|
1910
1919
|
const r = result ?? {};
|
|
1911
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
1920
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
1921
|
+
};
|
|
1922
|
+
var imKeysIter = (seq, visit, keys) => {
|
|
1923
|
+
const attrName = isIndexed(seq) ? "si" : "sk";
|
|
1924
|
+
for (const key of keys)
|
|
1925
|
+
visit(key, seq.get(key), attrName);
|
|
1912
1926
|
};
|
|
1927
|
+
var makeLoopCtx = (stack, filter) => ({
|
|
1928
|
+
lookup: (name) => stack.lookupBind(name),
|
|
1929
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
1930
|
+
});
|
|
1913
1931
|
var imIndexedIter = (seq, visit, start, end) => {
|
|
1914
1932
|
const [s, e] = normalizeRange(start, end, seq.size);
|
|
1915
1933
|
for (let i = s;i < e; i++)
|
|
@@ -2457,11 +2475,11 @@ class IterInfo {
|
|
|
2457
2475
|
return { seq, filter, loopWith, enricher };
|
|
2458
2476
|
}
|
|
2459
2477
|
enrichBinds(stack, key) {
|
|
2460
|
-
const { seq, loopWith, enricher } = this.eval(stack);
|
|
2478
|
+
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
2461
2479
|
const value = seq?.get ? seq.get(key, null) : null;
|
|
2462
2480
|
const binds = { key, value };
|
|
2463
2481
|
if (enricher) {
|
|
2464
|
-
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
2482
|
+
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
2465
2483
|
enricher.call(stack.it, binds, key, value, iterData);
|
|
2466
2484
|
}
|
|
2467
2485
|
return binds;
|
|
@@ -3470,7 +3488,6 @@ var RAW_TEXT_ELEMENTS = new Set([
|
|
|
3470
3488
|
"xmp",
|
|
3471
3489
|
"plaintext"
|
|
3472
3490
|
]);
|
|
3473
|
-
var RCDATA_ELEMENTS = new Set(["textarea", "title"]);
|
|
3474
3491
|
var SPECIAL_ELEMENTS = new Set([
|
|
3475
3492
|
"address",
|
|
3476
3493
|
"applet",
|
|
@@ -3585,7 +3602,6 @@ var SCOPE_LIST_ITEM = new Set([...DEFAULT_SCOPE_BOUNDARIES, "ol", "ul"]);
|
|
|
3585
3602
|
var SCOPE_BUTTON = new Set([...DEFAULT_SCOPE_BOUNDARIES, "button"]);
|
|
3586
3603
|
var SCOPE_DEFAULT = DEFAULT_SCOPE_BOUNDARIES;
|
|
3587
3604
|
var SCOPE_TABLE = new Set(["html", "table", "template"]);
|
|
3588
|
-
var SCOPE_SELECT = new Set;
|
|
3589
3605
|
var STANDARD_SVG_CAMEL_ELEMENTS = new Set([
|
|
3590
3606
|
"altGlyph",
|
|
3591
3607
|
"altGlyphDef",
|
|
@@ -3737,7 +3753,6 @@ var FOREIGN_BREAKOUT_TAGS = new Set([
|
|
|
3737
3753
|
"ul",
|
|
3738
3754
|
"var"
|
|
3739
3755
|
]);
|
|
3740
|
-
var MATHML_TEXT_INTEGRATION_POINTS = new Set(["mi", "mo", "mn", "ms", "mtext"]);
|
|
3741
3756
|
var BLOCK_LEVEL_AUTO_CLOSE_P = new Set([
|
|
3742
3757
|
"address",
|
|
3743
3758
|
"article",
|
|
@@ -3780,7 +3795,6 @@ var BLOCK_LEVEL_AUTO_CLOSE_P = new Set([
|
|
|
3780
3795
|
"dd",
|
|
3781
3796
|
"dt"
|
|
3782
3797
|
]);
|
|
3783
|
-
var SELECT_VALID_CHILDREN = new Set(["option", "optgroup", "hr", "script", "template"]);
|
|
3784
3798
|
var SELECT_BREAKOUT_TAGS = new Set(["input", "keygen", "textarea", "select"]);
|
|
3785
3799
|
var MODES = Object.freeze({
|
|
3786
3800
|
inBody: "inBody",
|
|
@@ -6040,6 +6054,13 @@ function phaseOps(phase) {
|
|
|
6040
6054
|
function resolveArgs(args, self) {
|
|
6041
6055
|
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
6042
6056
|
}
|
|
6057
|
+
function phaseHasBubble(phase) {
|
|
6058
|
+
if (!phase)
|
|
6059
|
+
return false;
|
|
6060
|
+
if (phase.bubble?.length)
|
|
6061
|
+
return true;
|
|
6062
|
+
return (phase.do ?? []).some((op) => op.type === "bubble");
|
|
6063
|
+
}
|
|
6043
6064
|
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
6044
6065
|
if (!phase)
|
|
6045
6066
|
return;
|
|
@@ -6976,6 +6997,8 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
6976
6997
|
const t = info?.transaction;
|
|
6977
6998
|
opts.onMessage({ kind: t?.handlerProp ?? "input", name: t?.name, args: t?.args, path: t?.path }, old, val);
|
|
6978
6999
|
});
|
|
7000
|
+
if (phaseHasBubble(phase))
|
|
7001
|
+
console.warn("drive(): a `bubble` action is a no-op here — drive originates at the root and bubbles travel child→parent, so there is no ancestor to receive it (and the root's own bubble handler is skipped). To exercise a bubble handler, call it directly.");
|
|
6979
7002
|
dispatchPhase(rootDispatcher(transactor), new Path([]), phase, value);
|
|
6980
7003
|
await transactor.settle();
|
|
6981
7004
|
return transactor.state.val;
|
|
@@ -7964,7 +7987,8 @@ class FieldSet extends Field {
|
|
|
7964
7987
|
}
|
|
7965
7988
|
function mkCompField(field, scope, args) {
|
|
7966
7989
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
7967
|
-
|
|
7990
|
+
if (Comp === null)
|
|
7991
|
+
console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
|
|
7968
7992
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
7969
7993
|
}
|
|
7970
7994
|
|
|
@@ -8138,13 +8162,30 @@ function resolveAlter(Comp, name) {
|
|
|
8138
8162
|
}
|
|
8139
8163
|
return fn;
|
|
8140
8164
|
}
|
|
8165
|
+
var seqGet = (seq, key) => Array.isArray(seq) ? seq[key] : seq.get ? seq.get(key) : seq[key];
|
|
8141
8166
|
function collectIterBindings(Comp, compInstance, seq, opts = {}) {
|
|
8142
8167
|
const whenFn = resolveAlter(Comp, opts.when) ?? filterAlwaysTrue;
|
|
8143
8168
|
const loopWithFn = resolveAlter(Comp, opts.loopWith) ?? nullLoopWith;
|
|
8144
8169
|
const enrichFn = resolveAlter(Comp, opts.enrichWith);
|
|
8170
|
+
const scopeEnrichFn = resolveAlter(Comp, opts.scopeEnrich);
|
|
8145
8171
|
const it = compInstance;
|
|
8146
|
-
const
|
|
8172
|
+
const scope = scopeEnrichFn ? scopeEnrichFn.call(it) ?? {} : opts.scope ?? {};
|
|
8173
|
+
const ctx = {
|
|
8174
|
+
lookup: (name) => scope[name],
|
|
8175
|
+
filter: (key, value, iterData2) => whenFn.call(it, key, value, iterData2)
|
|
8176
|
+
};
|
|
8177
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWithFn.call(it, seq, ctx), seq);
|
|
8147
8178
|
const out = [];
|
|
8179
|
+
if (keys) {
|
|
8180
|
+
for (const key of keys) {
|
|
8181
|
+
const value = seqGet(seq, key);
|
|
8182
|
+
const binds = { key, value };
|
|
8183
|
+
if (enrichFn)
|
|
8184
|
+
enrichFn.call(it, binds, key, value, iterData);
|
|
8185
|
+
out.push(binds);
|
|
8186
|
+
}
|
|
8187
|
+
return out;
|
|
8188
|
+
}
|
|
8148
8189
|
const iter = pickIter(seq);
|
|
8149
8190
|
iter(seq, (key, value) => {
|
|
8150
8191
|
if (!whenFn.call(it, key, value, iterData))
|
|
@@ -8333,20 +8374,23 @@ async function test2(opts = {}) {
|
|
|
8333
8374
|
reportTestReportToConsole(report);
|
|
8334
8375
|
return report;
|
|
8335
8376
|
}
|
|
8377
|
+
function shadowCheckComponent(Comp) {
|
|
8378
|
+
const shadowViews = {};
|
|
8379
|
+
for (const name in Comp.views) {
|
|
8380
|
+
const rawView = Comp.views[name].rawView;
|
|
8381
|
+
const ctx = new LintParseContext;
|
|
8382
|
+
ANode.parse(rawView, ctx);
|
|
8383
|
+
ctx.compile(Comp.scope);
|
|
8384
|
+
shadowViews[name] = { name, ctx, rawView };
|
|
8385
|
+
}
|
|
8386
|
+
const shadowComp = Object.create(Comp);
|
|
8387
|
+
shadowComp.views = shadowViews;
|
|
8388
|
+
return checkComponent(shadowComp).reports;
|
|
8389
|
+
}
|
|
8336
8390
|
function check(app) {
|
|
8337
8391
|
const counts = { error: 0, warn: 0, hint: 0 };
|
|
8338
8392
|
for (const Comp of app.comps.byId.values()) {
|
|
8339
|
-
const
|
|
8340
|
-
for (const name in Comp.views) {
|
|
8341
|
-
const rawView = Comp.views[name].rawView;
|
|
8342
|
-
const ctx = new LintParseContext;
|
|
8343
|
-
ANode.parse(rawView, ctx);
|
|
8344
|
-
ctx.compile(Comp.scope);
|
|
8345
|
-
shadowViews[name] = { name, ctx, rawView };
|
|
8346
|
-
}
|
|
8347
|
-
const shadowComp = Object.create(Comp);
|
|
8348
|
-
shadowComp.views = shadowViews;
|
|
8349
|
-
const { reports } = checkComponent(shadowComp);
|
|
8393
|
+
const reports = shadowCheckComponent(Comp);
|
|
8350
8394
|
if (reports.length === 0)
|
|
8351
8395
|
continue;
|
|
8352
8396
|
console.group(Comp.name);
|
|
@@ -8400,6 +8444,7 @@ export {
|
|
|
8400
8444
|
tutuca,
|
|
8401
8445
|
test2 as test,
|
|
8402
8446
|
suggestionToMessage,
|
|
8447
|
+
shadowCheckComponent,
|
|
8403
8448
|
setIn,
|
|
8404
8449
|
set,
|
|
8405
8450
|
runTests,
|
|
@@ -8408,6 +8453,7 @@ export {
|
|
|
8408
8453
|
removeIn,
|
|
8409
8454
|
remove,
|
|
8410
8455
|
phaseOps,
|
|
8456
|
+
phaseHasBubble,
|
|
8411
8457
|
mergeWith,
|
|
8412
8458
|
mergeDeepWith,
|
|
8413
8459
|
mergeDeep,
|
|
@@ -8443,6 +8489,7 @@ export {
|
|
|
8443
8489
|
getComponentsDocs,
|
|
8444
8490
|
get,
|
|
8445
8491
|
fromJS,
|
|
8492
|
+
expect,
|
|
8446
8493
|
drive,
|
|
8447
8494
|
docComponents,
|
|
8448
8495
|
dispatchPhase,
|
package/dist/tutuca-dev.js
CHANGED
|
@@ -3376,7 +3376,6 @@ function jestMatchers(chai, utils) {
|
|
|
3376
3376
|
|
|
3377
3377
|
// deps/chai.js
|
|
3378
3378
|
use(jestMatchers);
|
|
3379
|
-
|
|
3380
3379
|
// deps/immutable.js
|
|
3381
3380
|
function invariant(condition, error) {
|
|
3382
3381
|
if (!condition)
|
|
@@ -9493,37 +9492,47 @@ class Renderer {
|
|
|
9493
9492
|
renderEach(stack, iterInfo, node, viewName) {
|
|
9494
9493
|
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
9495
9494
|
const r = [];
|
|
9496
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9495
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9496
|
+
const renderOne = (key, value, attrName) => {
|
|
9497
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
9498
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
9499
|
+
};
|
|
9500
|
+
if (keys)
|
|
9501
|
+
imKeysIter(seq, renderOne, keys);
|
|
9502
|
+
else
|
|
9503
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
9504
|
+
if (filter.call(stack.it, key, value, iterData))
|
|
9505
|
+
renderOne(key, value, attrName);
|
|
9506
|
+
}, start, end);
|
|
9503
9507
|
return r;
|
|
9504
9508
|
}
|
|
9505
9509
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
9506
9510
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
9507
9511
|
const r = [];
|
|
9508
9512
|
const it = stack.it;
|
|
9509
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
9524
|
-
}
|
|
9513
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9514
|
+
const renderOne = (key, value, attrName) => {
|
|
9515
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
9516
|
+
const binds = { key, value };
|
|
9517
|
+
const cacheKey = `${nid}-${key}`;
|
|
9518
|
+
if (enricher)
|
|
9519
|
+
enricher.call(it, binds, key, value, iterData);
|
|
9520
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
9521
|
+
if (cachedNode)
|
|
9522
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
9523
|
+
else {
|
|
9524
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
9525
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
9526
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
9525
9527
|
}
|
|
9526
|
-
}
|
|
9528
|
+
};
|
|
9529
|
+
if (keys)
|
|
9530
|
+
imKeysIter(seq, renderOne, keys);
|
|
9531
|
+
else
|
|
9532
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
9533
|
+
if (filter.call(it, key, value, iterData))
|
|
9534
|
+
renderOne(key, value, attrName);
|
|
9535
|
+
}, start, end);
|
|
9527
9536
|
return r;
|
|
9528
9537
|
}
|
|
9529
9538
|
renderView(view, stack) {
|
|
@@ -9559,8 +9568,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
|
9559
9568
|
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
9560
9569
|
var unpackLoopResult = (result, seq) => {
|
|
9561
9570
|
const r = result ?? {};
|
|
9562
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
9571
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
9572
|
+
};
|
|
9573
|
+
var imKeysIter = (seq, visit, keys) => {
|
|
9574
|
+
const attrName = isIndexed(seq) ? "si" : "sk";
|
|
9575
|
+
for (const key of keys)
|
|
9576
|
+
visit(key, seq.get(key), attrName);
|
|
9563
9577
|
};
|
|
9578
|
+
var makeLoopCtx = (stack, filter) => ({
|
|
9579
|
+
lookup: (name) => stack.lookupBind(name),
|
|
9580
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
9581
|
+
});
|
|
9564
9582
|
var imIndexedIter = (seq, visit, start, end) => {
|
|
9565
9583
|
const [s, e] = normalizeRange(start, end, seq.size);
|
|
9566
9584
|
for (let i = s;i < e; i++)
|
|
@@ -10108,11 +10126,11 @@ class IterInfo {
|
|
|
10108
10126
|
return { seq, filter, loopWith, enricher };
|
|
10109
10127
|
}
|
|
10110
10128
|
enrichBinds(stack, key) {
|
|
10111
|
-
const { seq, loopWith, enricher } = this.eval(stack);
|
|
10129
|
+
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
10112
10130
|
const value = seq?.get ? seq.get(key, null) : null;
|
|
10113
10131
|
const binds = { key, value };
|
|
10114
10132
|
if (enricher) {
|
|
10115
|
-
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
10133
|
+
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
10116
10134
|
enricher.call(stack.it, binds, key, value, iterData);
|
|
10117
10135
|
}
|
|
10118
10136
|
return binds;
|
|
@@ -11121,7 +11139,6 @@ var RAW_TEXT_ELEMENTS = new Set([
|
|
|
11121
11139
|
"xmp",
|
|
11122
11140
|
"plaintext"
|
|
11123
11141
|
]);
|
|
11124
|
-
var RCDATA_ELEMENTS = new Set(["textarea", "title"]);
|
|
11125
11142
|
var SPECIAL_ELEMENTS = new Set([
|
|
11126
11143
|
"address",
|
|
11127
11144
|
"applet",
|
|
@@ -11236,7 +11253,6 @@ var SCOPE_LIST_ITEM = new Set([...DEFAULT_SCOPE_BOUNDARIES, "ol", "ul"]);
|
|
|
11236
11253
|
var SCOPE_BUTTON = new Set([...DEFAULT_SCOPE_BOUNDARIES, "button"]);
|
|
11237
11254
|
var SCOPE_DEFAULT = DEFAULT_SCOPE_BOUNDARIES;
|
|
11238
11255
|
var SCOPE_TABLE = new Set(["html", "table", "template"]);
|
|
11239
|
-
var SCOPE_SELECT = new Set;
|
|
11240
11256
|
var STANDARD_SVG_CAMEL_ELEMENTS = new Set([
|
|
11241
11257
|
"altGlyph",
|
|
11242
11258
|
"altGlyphDef",
|
|
@@ -11388,7 +11404,6 @@ var FOREIGN_BREAKOUT_TAGS = new Set([
|
|
|
11388
11404
|
"ul",
|
|
11389
11405
|
"var"
|
|
11390
11406
|
]);
|
|
11391
|
-
var MATHML_TEXT_INTEGRATION_POINTS = new Set(["mi", "mo", "mn", "ms", "mtext"]);
|
|
11392
11407
|
var BLOCK_LEVEL_AUTO_CLOSE_P = new Set([
|
|
11393
11408
|
"address",
|
|
11394
11409
|
"article",
|
|
@@ -11431,7 +11446,6 @@ var BLOCK_LEVEL_AUTO_CLOSE_P = new Set([
|
|
|
11431
11446
|
"dd",
|
|
11432
11447
|
"dt"
|
|
11433
11448
|
]);
|
|
11434
|
-
var SELECT_VALID_CHILDREN = new Set(["option", "optgroup", "hr", "script", "template"]);
|
|
11435
11449
|
var SELECT_BREAKOUT_TAGS = new Set(["input", "keygen", "textarea", "select"]);
|
|
11436
11450
|
var MODES = Object.freeze({
|
|
11437
11451
|
inBody: "inBody",
|
|
@@ -13691,6 +13705,13 @@ function phaseOps(phase) {
|
|
|
13691
13705
|
function resolveArgs(args, self) {
|
|
13692
13706
|
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
13693
13707
|
}
|
|
13708
|
+
function phaseHasBubble(phase) {
|
|
13709
|
+
if (!phase)
|
|
13710
|
+
return false;
|
|
13711
|
+
if (phase.bubble?.length)
|
|
13712
|
+
return true;
|
|
13713
|
+
return (phase.do ?? []).some((op) => op.type === "bubble");
|
|
13714
|
+
}
|
|
13694
13715
|
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
13695
13716
|
if (!phase)
|
|
13696
13717
|
return;
|
|
@@ -14627,6 +14648,8 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
14627
14648
|
const t = info?.transaction;
|
|
14628
14649
|
opts.onMessage({ kind: t?.handlerProp ?? "input", name: t?.name, args: t?.args, path: t?.path }, old, val);
|
|
14629
14650
|
});
|
|
14651
|
+
if (phaseHasBubble(phase))
|
|
14652
|
+
console.warn("drive(): a `bubble` action is a no-op here — drive originates at the root and bubbles travel child→parent, so there is no ancestor to receive it (and the root's own bubble handler is skipped). To exercise a bubble handler, call it directly.");
|
|
14630
14653
|
dispatchPhase(rootDispatcher(transactor), new Path([]), phase, value);
|
|
14631
14654
|
await transactor.settle();
|
|
14632
14655
|
return transactor.state.val;
|
|
@@ -15558,7 +15581,8 @@ class FieldSet extends Field {
|
|
|
15558
15581
|
}
|
|
15559
15582
|
function mkCompField(field, scope, args) {
|
|
15560
15583
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
15561
|
-
|
|
15584
|
+
if (Comp === null)
|
|
15585
|
+
console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
|
|
15562
15586
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
15563
15587
|
}
|
|
15564
15588
|
|
|
@@ -15732,13 +15756,30 @@ function resolveAlter(Comp, name) {
|
|
|
15732
15756
|
}
|
|
15733
15757
|
return fn;
|
|
15734
15758
|
}
|
|
15759
|
+
var seqGet = (seq, key) => Array.isArray(seq) ? seq[key] : seq.get ? seq.get(key) : seq[key];
|
|
15735
15760
|
function collectIterBindings(Comp, compInstance, seq, opts = {}) {
|
|
15736
15761
|
const whenFn = resolveAlter(Comp, opts.when) ?? filterAlwaysTrue;
|
|
15737
15762
|
const loopWithFn = resolveAlter(Comp, opts.loopWith) ?? nullLoopWith;
|
|
15738
15763
|
const enrichFn = resolveAlter(Comp, opts.enrichWith);
|
|
15764
|
+
const scopeEnrichFn = resolveAlter(Comp, opts.scopeEnrich);
|
|
15739
15765
|
const it = compInstance;
|
|
15740
|
-
const
|
|
15766
|
+
const scope = scopeEnrichFn ? scopeEnrichFn.call(it) ?? {} : opts.scope ?? {};
|
|
15767
|
+
const ctx = {
|
|
15768
|
+
lookup: (name) => scope[name],
|
|
15769
|
+
filter: (key, value, iterData2) => whenFn.call(it, key, value, iterData2)
|
|
15770
|
+
};
|
|
15771
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWithFn.call(it, seq, ctx), seq);
|
|
15741
15772
|
const out = [];
|
|
15773
|
+
if (keys) {
|
|
15774
|
+
for (const key of keys) {
|
|
15775
|
+
const value = seqGet(seq, key);
|
|
15776
|
+
const binds = { key, value };
|
|
15777
|
+
if (enrichFn)
|
|
15778
|
+
enrichFn.call(it, binds, key, value, iterData);
|
|
15779
|
+
out.push(binds);
|
|
15780
|
+
}
|
|
15781
|
+
return out;
|
|
15782
|
+
}
|
|
15742
15783
|
const iter = pickIter(seq);
|
|
15743
15784
|
iter(seq, (key, value) => {
|
|
15744
15785
|
if (!whenFn.call(it, key, value, iterData))
|
|
@@ -15927,20 +15968,23 @@ async function test3(opts = {}) {
|
|
|
15927
15968
|
reportTestReportToConsole(report);
|
|
15928
15969
|
return report;
|
|
15929
15970
|
}
|
|
15971
|
+
function shadowCheckComponent(Comp) {
|
|
15972
|
+
const shadowViews = {};
|
|
15973
|
+
for (const name in Comp.views) {
|
|
15974
|
+
const rawView = Comp.views[name].rawView;
|
|
15975
|
+
const ctx = new LintParseContext;
|
|
15976
|
+
ANode.parse(rawView, ctx);
|
|
15977
|
+
ctx.compile(Comp.scope);
|
|
15978
|
+
shadowViews[name] = { name, ctx, rawView };
|
|
15979
|
+
}
|
|
15980
|
+
const shadowComp = Object.create(Comp);
|
|
15981
|
+
shadowComp.views = shadowViews;
|
|
15982
|
+
return checkComponent(shadowComp).reports;
|
|
15983
|
+
}
|
|
15930
15984
|
function check(app) {
|
|
15931
15985
|
const counts = { error: 0, warn: 0, hint: 0 };
|
|
15932
15986
|
for (const Comp of app.comps.byId.values()) {
|
|
15933
|
-
const
|
|
15934
|
-
for (const name in Comp.views) {
|
|
15935
|
-
const rawView = Comp.views[name].rawView;
|
|
15936
|
-
const ctx = new LintParseContext;
|
|
15937
|
-
ANode.parse(rawView, ctx);
|
|
15938
|
-
ctx.compile(Comp.scope);
|
|
15939
|
-
shadowViews[name] = { name, ctx, rawView };
|
|
15940
|
-
}
|
|
15941
|
-
const shadowComp = Object.create(Comp);
|
|
15942
|
-
shadowComp.views = shadowViews;
|
|
15943
|
-
const { reports } = checkComponent(shadowComp);
|
|
15987
|
+
const reports = shadowCheckComponent(Comp);
|
|
15944
15988
|
if (reports.length === 0)
|
|
15945
15989
|
continue;
|
|
15946
15990
|
console.group(Comp.name);
|
|
@@ -15994,6 +16038,7 @@ export {
|
|
|
15994
16038
|
tutuca,
|
|
15995
16039
|
test3 as test,
|
|
15996
16040
|
suggestionToMessage,
|
|
16041
|
+
shadowCheckComponent,
|
|
15997
16042
|
setIn$1 as setIn,
|
|
15998
16043
|
set2 as set,
|
|
15999
16044
|
runTests,
|
|
@@ -16002,6 +16047,7 @@ export {
|
|
|
16002
16047
|
removeIn,
|
|
16003
16048
|
remove,
|
|
16004
16049
|
phaseOps,
|
|
16050
|
+
phaseHasBubble,
|
|
16005
16051
|
mergeWith$1 as mergeWith,
|
|
16006
16052
|
mergeDeepWith$1 as mergeDeepWith,
|
|
16007
16053
|
mergeDeep$1 as mergeDeep,
|
|
@@ -16037,6 +16083,7 @@ export {
|
|
|
16037
16083
|
getComponentsDocs,
|
|
16038
16084
|
get2 as get,
|
|
16039
16085
|
fromJS,
|
|
16086
|
+
expect,
|
|
16040
16087
|
drive,
|
|
16041
16088
|
docComponents,
|
|
16042
16089
|
dispatchPhase,
|