tutuca 0.9.82 → 0.9.83
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 +3 -3
- package/dist/tutuca-cli.js +12805 -12787
- package/dist/tutuca-dev.ext.js +551 -629
- package/dist/tutuca-dev.js +481 -570
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +333 -432
- package/dist/tutuca-extra.js +266 -365
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca.ext.js +274 -280
- package/dist/tutuca.js +253 -259
- package/dist/tutuca.min.js +2 -2
- package/package.json +4 -2
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +14 -4
- package/skill/tutuca/cli.md +1 -0
- package/skill/tutuca/component-design.md +1 -1
- package/skill/tutuca/patterns/README.md +1 -0
- package/skill/tutuca/patterns/file-input.md +39 -0
- package/skill/tutuca-source/tutuca.ext.js +274 -280
package/dist/tutuca.ext.js
CHANGED
|
@@ -850,9 +850,6 @@ class DynVal extends RenderNameVal {
|
|
|
850
850
|
eval(stack) {
|
|
851
851
|
return stack.lookupDynamic(this.name);
|
|
852
852
|
}
|
|
853
|
-
toPathItem() {
|
|
854
|
-
return null;
|
|
855
|
-
}
|
|
856
853
|
toString() {
|
|
857
854
|
return `*${this.name}`;
|
|
858
855
|
}
|
|
@@ -1090,7 +1087,7 @@ class ConstAttrs extends Attributes {
|
|
|
1090
1087
|
toMacroVars() {
|
|
1091
1088
|
const r = {};
|
|
1092
1089
|
for (const name in this.items)
|
|
1093
|
-
r[name] =
|
|
1090
|
+
r[name] = new ConstVal(`${this.items[name]}`).toString();
|
|
1094
1091
|
return r;
|
|
1095
1092
|
}
|
|
1096
1093
|
isConstant() {
|
|
@@ -1196,6 +1193,79 @@ class RequestHandler {
|
|
|
1196
1193
|
}
|
|
1197
1194
|
}
|
|
1198
1195
|
|
|
1196
|
+
// src/renderer.js
|
|
1197
|
+
import { isIndexed, isKeyed } from "immutable";
|
|
1198
|
+
|
|
1199
|
+
// src/cache.js
|
|
1200
|
+
class NullDomCache {
|
|
1201
|
+
get(_keys, _cacheKey) {}
|
|
1202
|
+
set(_keys, _cacheKey, _v) {}
|
|
1203
|
+
evict() {
|
|
1204
|
+
return { hit: 0, miss: 0, badKey: 0 };
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
class WeakMapDomCache {
|
|
1209
|
+
constructor() {
|
|
1210
|
+
this.hit = this.miss = this.badKey = 0;
|
|
1211
|
+
this.keysByLen = new Map;
|
|
1212
|
+
}
|
|
1213
|
+
_returnValue(r) {
|
|
1214
|
+
if (r === undefined)
|
|
1215
|
+
this.miss += 1;
|
|
1216
|
+
else
|
|
1217
|
+
this.hit += 1;
|
|
1218
|
+
return r;
|
|
1219
|
+
}
|
|
1220
|
+
get(keys, cacheKey) {
|
|
1221
|
+
const len = keys.length;
|
|
1222
|
+
let cur = this.keysByLen.get(len);
|
|
1223
|
+
if (!cur)
|
|
1224
|
+
return this._returnValue(undefined);
|
|
1225
|
+
for (let i = 0;i < len - 1; i++) {
|
|
1226
|
+
cur = cur.get(keys[i]);
|
|
1227
|
+
if (!cur)
|
|
1228
|
+
return this._returnValue(undefined);
|
|
1229
|
+
}
|
|
1230
|
+
return this._returnValue(cur.get(keys[len - 1])?.[cacheKey]);
|
|
1231
|
+
}
|
|
1232
|
+
set(keys, cacheKey, v) {
|
|
1233
|
+
const len = keys.length;
|
|
1234
|
+
let cur = this.keysByLen.get(len);
|
|
1235
|
+
if (!cur) {
|
|
1236
|
+
cur = new WeakMap;
|
|
1237
|
+
this.keysByLen.set(len, cur);
|
|
1238
|
+
}
|
|
1239
|
+
for (let i = 0;i < len - 1; i++) {
|
|
1240
|
+
const key = keys[i];
|
|
1241
|
+
let next = cur.get(key);
|
|
1242
|
+
if (!next) {
|
|
1243
|
+
if (typeof key !== "object") {
|
|
1244
|
+
this.badKey += 1;
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
next = new WeakMap;
|
|
1248
|
+
cur.set(key, next);
|
|
1249
|
+
}
|
|
1250
|
+
cur = next;
|
|
1251
|
+
}
|
|
1252
|
+
const lastKey = keys[len - 1];
|
|
1253
|
+
const leaf = cur.get(lastKey);
|
|
1254
|
+
if (leaf)
|
|
1255
|
+
leaf[cacheKey] = v;
|
|
1256
|
+
else if (typeof lastKey === "object")
|
|
1257
|
+
cur.set(lastKey, { [cacheKey]: v });
|
|
1258
|
+
else
|
|
1259
|
+
this.badKey += 1;
|
|
1260
|
+
}
|
|
1261
|
+
evict() {
|
|
1262
|
+
const { hit, miss, badKey } = this;
|
|
1263
|
+
this.hit = this.miss = this.badKey = 0;
|
|
1264
|
+
this.keysByLen = new Map;
|
|
1265
|
+
return { hit, miss, badKey };
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1199
1269
|
// src/vdom.js
|
|
1200
1270
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
1201
1271
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
@@ -1223,6 +1293,7 @@ var NEVER_ASSIGN = new Set([
|
|
|
1223
1293
|
"role",
|
|
1224
1294
|
"popover"
|
|
1225
1295
|
]);
|
|
1296
|
+
var PROP_ATTR_NAME = { className: "class", htmlFor: "for" };
|
|
1226
1297
|
function applyProperties(node, props) {
|
|
1227
1298
|
const namespaced = isNamespaced(node);
|
|
1228
1299
|
for (const name in props)
|
|
@@ -1241,15 +1312,22 @@ function setProp(node, name, value, namespaced) {
|
|
|
1241
1312
|
}
|
|
1242
1313
|
if (typeof value === "function")
|
|
1243
1314
|
return;
|
|
1244
|
-
|
|
1315
|
+
const usesProp = !namespaced && !NEVER_ASSIGN.has(name) && name in node;
|
|
1316
|
+
if (usesProp && value != null) {
|
|
1245
1317
|
try {
|
|
1246
|
-
node[name] = value
|
|
1318
|
+
node[name] = value;
|
|
1247
1319
|
return;
|
|
1248
1320
|
} catch {}
|
|
1249
1321
|
}
|
|
1250
|
-
if (value == null || value === false && name[4] !== "-")
|
|
1251
|
-
|
|
1252
|
-
|
|
1322
|
+
if (value == null || value === false && name[4] !== "-") {
|
|
1323
|
+
if (usesProp) {
|
|
1324
|
+
try {
|
|
1325
|
+
node[name] = "";
|
|
1326
|
+
} catch {}
|
|
1327
|
+
node.removeAttribute(PROP_ATTR_NAME[name] ?? name);
|
|
1328
|
+
} else
|
|
1329
|
+
node.removeAttribute(name);
|
|
1330
|
+
} else
|
|
1253
1331
|
node.setAttribute(name, value);
|
|
1254
1332
|
}
|
|
1255
1333
|
function applyValueLast(node, value) {
|
|
@@ -1430,22 +1508,12 @@ function morphNode(domNode, source, target, opts) {
|
|
|
1430
1508
|
}
|
|
1431
1509
|
if (type === 1 && source.isSameKind(target)) {
|
|
1432
1510
|
const propsDiff = diffProps(source.attrs, target.attrs);
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
let applyValue = false;
|
|
1436
|
-
let applyChecked = false;
|
|
1511
|
+
const hasValue = propsDiff != null && "value" in propsDiff;
|
|
1512
|
+
const hasChecked = propsDiff != null && "checked" in propsDiff;
|
|
1437
1513
|
if (propsDiff) {
|
|
1438
|
-
if (
|
|
1439
|
-
const { value, checked, ...rest } = propsDiff;
|
|
1514
|
+
if (hasValue || hasChecked) {
|
|
1515
|
+
const { value: _v, checked: _c, ...rest } = propsDiff;
|
|
1440
1516
|
applyProperties(domNode, rest);
|
|
1441
|
-
if ("value" in propsDiff) {
|
|
1442
|
-
pendingValue = value;
|
|
1443
|
-
applyValue = true;
|
|
1444
|
-
}
|
|
1445
|
-
if ("checked" in propsDiff) {
|
|
1446
|
-
pendingChecked = checked;
|
|
1447
|
-
applyChecked = true;
|
|
1448
|
-
}
|
|
1449
1517
|
} else
|
|
1450
1518
|
applyProperties(domNode, propsDiff);
|
|
1451
1519
|
}
|
|
@@ -1453,14 +1521,12 @@ function morphNode(domNode, source, target, opts) {
|
|
|
1453
1521
|
const ns = effectiveNs(target, opts);
|
|
1454
1522
|
morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
|
|
1455
1523
|
}
|
|
1456
|
-
if (
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
if (
|
|
1461
|
-
|
|
1462
|
-
if (applyChecked)
|
|
1463
|
-
setProp(domNode, "checked", pendingChecked, false);
|
|
1524
|
+
if (hasValue)
|
|
1525
|
+
applyValueLast(domNode, propsDiff.value);
|
|
1526
|
+
else if (source.tag === "SELECT" && target.attrs.value !== undefined)
|
|
1527
|
+
applyValueLast(domNode, target.attrs.value);
|
|
1528
|
+
if (hasChecked)
|
|
1529
|
+
setProp(domNode, "checked", propsDiff.checked, false);
|
|
1464
1530
|
return domNode;
|
|
1465
1531
|
}
|
|
1466
1532
|
if (type === 11) {
|
|
@@ -1581,6 +1647,161 @@ function h(tagName, properties, children, namespace) {
|
|
|
1581
1647
|
return new VNode(tag, props, normalizedChildren, key, namespace);
|
|
1582
1648
|
}
|
|
1583
1649
|
|
|
1650
|
+
// src/renderer.js
|
|
1651
|
+
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
1652
|
+
|
|
1653
|
+
class Renderer {
|
|
1654
|
+
constructor(comps) {
|
|
1655
|
+
this.comps = comps;
|
|
1656
|
+
this.cache = new WeakMapDomCache;
|
|
1657
|
+
this.renderTag = h;
|
|
1658
|
+
}
|
|
1659
|
+
renderFragment(childs) {
|
|
1660
|
+
return new VFragment(childs);
|
|
1661
|
+
}
|
|
1662
|
+
renderComment(text) {
|
|
1663
|
+
return new VComment(text);
|
|
1664
|
+
}
|
|
1665
|
+
setNullCache() {
|
|
1666
|
+
this.cache = new NullDomCache;
|
|
1667
|
+
}
|
|
1668
|
+
renderToDOM(stack, val) {
|
|
1669
|
+
const rootNode = document.createElement("div");
|
|
1670
|
+
const rOpts = { document };
|
|
1671
|
+
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
1672
|
+
return rootNode.childNodes[0];
|
|
1673
|
+
}
|
|
1674
|
+
renderToString(stack, val, cleanAttrs = true) {
|
|
1675
|
+
const dom = this.renderToDOM(stack, val);
|
|
1676
|
+
if (cleanAttrs) {
|
|
1677
|
+
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
1678
|
+
for (const { dataset } of nodes)
|
|
1679
|
+
for (const name of DATASET_ATTRS)
|
|
1680
|
+
delete dataset[name];
|
|
1681
|
+
}
|
|
1682
|
+
return dom.innerHTML;
|
|
1683
|
+
}
|
|
1684
|
+
renderRoot(stack, val, viewName = null) {
|
|
1685
|
+
const comp = this.comps.getCompFor(val);
|
|
1686
|
+
if (comp === null)
|
|
1687
|
+
return null;
|
|
1688
|
+
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
1689
|
+
}
|
|
1690
|
+
renderIt(stack, node, key, viewName) {
|
|
1691
|
+
const comp = this.comps.getCompFor(stack.it);
|
|
1692
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
1693
|
+
}
|
|
1694
|
+
_rValComp(stack, val, comp, node, key, viewName) {
|
|
1695
|
+
const cacheKey = `${viewName ?? stack.viewsId ?? ""}-${key}`;
|
|
1696
|
+
const cachePath = [node, val];
|
|
1697
|
+
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
1698
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
1699
|
+
if (cachedNode)
|
|
1700
|
+
return cachedNode;
|
|
1701
|
+
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
1702
|
+
const meta = this._renderMetadata({
|
|
1703
|
+
$: "Comp",
|
|
1704
|
+
nid: node?.nodeId ?? null,
|
|
1705
|
+
cid: comp.id,
|
|
1706
|
+
vid: view.name
|
|
1707
|
+
});
|
|
1708
|
+
const dom = new VFragment([meta, this.renderView(view, stack)]);
|
|
1709
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
1710
|
+
return dom;
|
|
1711
|
+
}
|
|
1712
|
+
pushEachEntry(r, nid, attrName, key, dom) {
|
|
1713
|
+
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
1714
|
+
}
|
|
1715
|
+
renderEach(stack, iterInfo, node, viewName) {
|
|
1716
|
+
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
1717
|
+
const r = [];
|
|
1718
|
+
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
1719
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1720
|
+
if (filter.call(stack.it, key, value, iterData)) {
|
|
1721
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
1722
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
1723
|
+
}
|
|
1724
|
+
}, start, end);
|
|
1725
|
+
return r;
|
|
1726
|
+
}
|
|
1727
|
+
renderEachWhen(stack, iterInfo, view, nid) {
|
|
1728
|
+
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
1729
|
+
const r = [];
|
|
1730
|
+
const it = stack.it;
|
|
1731
|
+
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
1732
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1733
|
+
if (filter.call(it, key, value, iterData)) {
|
|
1734
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
1735
|
+
const binds = { key, value };
|
|
1736
|
+
const cacheKey = `${nid}-${key}`;
|
|
1737
|
+
if (enricher)
|
|
1738
|
+
enricher.call(it, binds, key, value, iterData);
|
|
1739
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
1740
|
+
if (cachedNode)
|
|
1741
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
1742
|
+
else {
|
|
1743
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
1744
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
1745
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}, start, end);
|
|
1749
|
+
return r;
|
|
1750
|
+
}
|
|
1751
|
+
renderView(view, stack) {
|
|
1752
|
+
let n = stack.binds[1];
|
|
1753
|
+
while (n !== null) {
|
|
1754
|
+
const b = n[0];
|
|
1755
|
+
if (b.isFrame) {
|
|
1756
|
+
if (stack.it !== b.it)
|
|
1757
|
+
break;
|
|
1758
|
+
console.error("recursion detected", stack.it, b.it);
|
|
1759
|
+
return new VComment("RECURSION AVOIDED");
|
|
1760
|
+
}
|
|
1761
|
+
n = n[1];
|
|
1762
|
+
}
|
|
1763
|
+
return view.render(stack, this);
|
|
1764
|
+
}
|
|
1765
|
+
_renderMetadata(info) {
|
|
1766
|
+
return new VComment(`§${JSON.stringify(info)}§`);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
var getSeqInfo = (seq) => isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
1770
|
+
var normalizeRange = (start, end, size) => {
|
|
1771
|
+
let s = start == null ? 0 : start < 0 ? size + start : start;
|
|
1772
|
+
let e = end == null ? size : end < 0 ? size + end : end;
|
|
1773
|
+
s = s < 0 ? 0 : s > size ? size : s;
|
|
1774
|
+
e = e < 0 ? 0 : e > size ? size : e;
|
|
1775
|
+
return [s, e < s ? s : e];
|
|
1776
|
+
};
|
|
1777
|
+
var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
1778
|
+
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
1779
|
+
var unpackLoopResult = (result, seq) => {
|
|
1780
|
+
const r = result ?? {};
|
|
1781
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
1782
|
+
};
|
|
1783
|
+
var imIndexedIter = (seq, visit, start, end) => {
|
|
1784
|
+
const [s, e] = normalizeRange(start, end, seq.size);
|
|
1785
|
+
for (let i = s;i < e; i++)
|
|
1786
|
+
visit(i, seq.get(i), "si");
|
|
1787
|
+
};
|
|
1788
|
+
var imKeyedIter = (seq, visit, start, end) => {
|
|
1789
|
+
const [s, e] = normalizeRange(start, end, seq.size);
|
|
1790
|
+
let i = 0;
|
|
1791
|
+
for (const [k, v] of seq.toSeq().entries()) {
|
|
1792
|
+
if (i >= e)
|
|
1793
|
+
break;
|
|
1794
|
+
if (i >= s)
|
|
1795
|
+
visit(k, v, "sk");
|
|
1796
|
+
i++;
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
var unkIter = () => {};
|
|
1800
|
+
var SEQ_INFO = Symbol.for("tutuca.seqInfo");
|
|
1801
|
+
|
|
1802
|
+
// src/util/env.js
|
|
1803
|
+
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1804
|
+
|
|
1584
1805
|
// src/anode.js
|
|
1585
1806
|
function resolveDynProducer(comp, name) {
|
|
1586
1807
|
let producerComp, producerProvide;
|
|
@@ -1784,7 +2005,7 @@ class ANode extends BaseNode {
|
|
|
1784
2005
|
}
|
|
1785
2006
|
}
|
|
1786
2007
|
function parseXOp(attrs, childs, opIdx, px) {
|
|
1787
|
-
if (attrs.length
|
|
2008
|
+
if (attrs.length <= opIdx)
|
|
1788
2009
|
return maybeFragment(childs);
|
|
1789
2010
|
const { name, value } = attrs[opIdx];
|
|
1790
2011
|
const as = attrs.getNamedItem("as")?.value ?? null;
|
|
@@ -2105,8 +2326,6 @@ class IterInfo {
|
|
|
2105
2326
|
return { seq, filter, loopWith, enricher };
|
|
2106
2327
|
}
|
|
2107
2328
|
}
|
|
2108
|
-
var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
2109
|
-
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
2110
2329
|
function xOp(consumed = [], { wrappable = false, wrapper = null } = {}) {
|
|
2111
2330
|
return { consumed: new Set(consumed), wrappable, wrapper };
|
|
2112
2331
|
}
|
|
@@ -2293,7 +2512,6 @@ class NodeEvent {
|
|
|
2293
2512
|
return r;
|
|
2294
2513
|
}
|
|
2295
2514
|
}
|
|
2296
|
-
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
2297
2515
|
var fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that;
|
|
2298
2516
|
var fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName);
|
|
2299
2517
|
var fwdCtrl = fwdIfCtxPred(({ e }) => isMac && e.metaKey || e.ctrlKey);
|
|
@@ -2801,7 +3019,6 @@ class Transaction {
|
|
|
2801
3019
|
return null;
|
|
2802
3020
|
}
|
|
2803
3021
|
}
|
|
2804
|
-
var isMac2 = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
2805
3022
|
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
2806
3023
|
function getValue(e) {
|
|
2807
3024
|
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
@@ -2855,7 +3072,7 @@ class InputEvent extends Transaction {
|
|
|
2855
3072
|
return e.shiftKey;
|
|
2856
3073
|
case "isCtrl":
|
|
2857
3074
|
case "isCmd":
|
|
2858
|
-
return
|
|
3075
|
+
return isMac && e.metaKey || e.ctrlKey;
|
|
2859
3076
|
case "key":
|
|
2860
3077
|
return e.key;
|
|
2861
3078
|
case "keyCode":
|
|
@@ -3279,249 +3496,15 @@ class DragInfo {
|
|
|
3279
3496
|
}
|
|
3280
3497
|
}
|
|
3281
3498
|
|
|
3282
|
-
// src/renderer.js
|
|
3283
|
-
import { isIndexed, isKeyed } from "immutable";
|
|
3284
|
-
|
|
3285
|
-
// src/cache.js
|
|
3286
|
-
class NullDomCache {
|
|
3287
|
-
get(_keys, _cacheKey) {}
|
|
3288
|
-
set(_keys, _cacheKey, _v) {}
|
|
3289
|
-
evict() {
|
|
3290
|
-
return { hit: 0, miss: 0, badKey: 0 };
|
|
3291
|
-
}
|
|
3292
|
-
}
|
|
3293
|
-
|
|
3294
|
-
class WeakMapDomCache {
|
|
3295
|
-
constructor() {
|
|
3296
|
-
this.hit = this.miss = this.badKey = 0;
|
|
3297
|
-
this.keysByLen = new Map;
|
|
3298
|
-
}
|
|
3299
|
-
_returnValue(r) {
|
|
3300
|
-
if (r === undefined)
|
|
3301
|
-
this.miss += 1;
|
|
3302
|
-
else
|
|
3303
|
-
this.hit += 1;
|
|
3304
|
-
return r;
|
|
3305
|
-
}
|
|
3306
|
-
get(keys, cacheKey) {
|
|
3307
|
-
const len = keys.length;
|
|
3308
|
-
let cur = this.keysByLen.get(len);
|
|
3309
|
-
if (!cur)
|
|
3310
|
-
return this._returnValue(undefined);
|
|
3311
|
-
for (let i = 0;i < len - 1; i++) {
|
|
3312
|
-
cur = cur.get(keys[i]);
|
|
3313
|
-
if (!cur)
|
|
3314
|
-
return this._returnValue(undefined);
|
|
3315
|
-
}
|
|
3316
|
-
return this._returnValue(cur.get(keys[len - 1])?.[cacheKey]);
|
|
3317
|
-
}
|
|
3318
|
-
set(keys, cacheKey, v) {
|
|
3319
|
-
const len = keys.length;
|
|
3320
|
-
let cur = this.keysByLen.get(len);
|
|
3321
|
-
if (!cur) {
|
|
3322
|
-
cur = new WeakMap;
|
|
3323
|
-
this.keysByLen.set(len, cur);
|
|
3324
|
-
}
|
|
3325
|
-
for (let i = 0;i < len - 1; i++) {
|
|
3326
|
-
const key = keys[i];
|
|
3327
|
-
let next = cur.get(key);
|
|
3328
|
-
if (!next) {
|
|
3329
|
-
if (typeof key !== "object") {
|
|
3330
|
-
this.badKey += 1;
|
|
3331
|
-
return;
|
|
3332
|
-
}
|
|
3333
|
-
next = new WeakMap;
|
|
3334
|
-
cur.set(key, next);
|
|
3335
|
-
}
|
|
3336
|
-
cur = next;
|
|
3337
|
-
}
|
|
3338
|
-
const lastKey = keys[len - 1];
|
|
3339
|
-
const leaf = cur.get(lastKey);
|
|
3340
|
-
if (leaf)
|
|
3341
|
-
leaf[cacheKey] = v;
|
|
3342
|
-
else if (typeof lastKey === "object")
|
|
3343
|
-
cur.set(lastKey, { [cacheKey]: v });
|
|
3344
|
-
else
|
|
3345
|
-
this.badKey += 1;
|
|
3346
|
-
}
|
|
3347
|
-
evict() {
|
|
3348
|
-
const { hit, miss, badKey } = this;
|
|
3349
|
-
this.hit = this.miss = this.badKey = 0;
|
|
3350
|
-
this.keysByLen = new Map;
|
|
3351
|
-
return { hit, miss, badKey };
|
|
3352
|
-
}
|
|
3353
|
-
}
|
|
3354
|
-
|
|
3355
|
-
// src/renderer.js
|
|
3356
|
-
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
3357
|
-
|
|
3358
|
-
class Renderer {
|
|
3359
|
-
constructor(comps) {
|
|
3360
|
-
this.comps = comps;
|
|
3361
|
-
this.cache = new WeakMapDomCache;
|
|
3362
|
-
this.renderTag = h;
|
|
3363
|
-
}
|
|
3364
|
-
renderFragment(childs) {
|
|
3365
|
-
return new VFragment(childs);
|
|
3366
|
-
}
|
|
3367
|
-
renderComment(text) {
|
|
3368
|
-
return new VComment(text);
|
|
3369
|
-
}
|
|
3370
|
-
setNullCache() {
|
|
3371
|
-
this.cache = new NullDomCache;
|
|
3372
|
-
}
|
|
3373
|
-
renderToDOM(stack, val) {
|
|
3374
|
-
const rootNode = document.createElement("div");
|
|
3375
|
-
const rOpts = { document };
|
|
3376
|
-
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
3377
|
-
return rootNode.childNodes[0];
|
|
3378
|
-
}
|
|
3379
|
-
renderToString(stack, val, cleanAttrs = true) {
|
|
3380
|
-
const dom = this.renderToDOM(stack, val);
|
|
3381
|
-
if (cleanAttrs) {
|
|
3382
|
-
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
3383
|
-
for (const { dataset } of nodes)
|
|
3384
|
-
for (const name of DATASET_ATTRS)
|
|
3385
|
-
delete dataset[name];
|
|
3386
|
-
}
|
|
3387
|
-
return dom.innerHTML;
|
|
3388
|
-
}
|
|
3389
|
-
renderRoot(stack, val, viewName = null) {
|
|
3390
|
-
const comp = this.comps.getCompFor(val);
|
|
3391
|
-
if (comp === null)
|
|
3392
|
-
return null;
|
|
3393
|
-
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
3394
|
-
}
|
|
3395
|
-
renderIt(stack, node, key, viewName) {
|
|
3396
|
-
const comp = this.comps.getCompFor(stack.it);
|
|
3397
|
-
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
3398
|
-
}
|
|
3399
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
3400
|
-
const cacheKey = `${viewName ?? stack.viewsId ?? ""}-${key}`;
|
|
3401
|
-
const cachePath = [node, val];
|
|
3402
|
-
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
3403
|
-
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
3404
|
-
if (cachedNode)
|
|
3405
|
-
return cachedNode;
|
|
3406
|
-
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
3407
|
-
const meta = this._renderMetadata({
|
|
3408
|
-
$: "Comp",
|
|
3409
|
-
nid: node?.nodeId ?? null,
|
|
3410
|
-
cid: comp.id,
|
|
3411
|
-
vid: view.name
|
|
3412
|
-
});
|
|
3413
|
-
const dom = new VFragment([meta, this.renderView(view, stack)]);
|
|
3414
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
3415
|
-
return dom;
|
|
3416
|
-
}
|
|
3417
|
-
pushEachEntry(r, nid, attrName, key, dom) {
|
|
3418
|
-
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
3419
|
-
}
|
|
3420
|
-
renderEach(stack, iterInfo, node, viewName) {
|
|
3421
|
-
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
3422
|
-
const r = [];
|
|
3423
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
3424
|
-
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
3425
|
-
if (filter.call(stack.it, key, value, iterData)) {
|
|
3426
|
-
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
3427
|
-
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
3428
|
-
}
|
|
3429
|
-
}, start, end);
|
|
3430
|
-
return r;
|
|
3431
|
-
}
|
|
3432
|
-
renderEachWhen(stack, iterInfo, view, nid) {
|
|
3433
|
-
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
3434
|
-
const r = [];
|
|
3435
|
-
const it = stack.it;
|
|
3436
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
3437
|
-
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
3438
|
-
if (filter.call(it, key, value, iterData)) {
|
|
3439
|
-
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
3440
|
-
const binds = { key, value };
|
|
3441
|
-
const cacheKey = `${nid}-${key}`;
|
|
3442
|
-
if (enricher)
|
|
3443
|
-
enricher.call(it, binds, key, value, iterData);
|
|
3444
|
-
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
3445
|
-
if (cachedNode)
|
|
3446
|
-
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
3447
|
-
else {
|
|
3448
|
-
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
3449
|
-
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
3450
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
3451
|
-
}
|
|
3452
|
-
}
|
|
3453
|
-
}, start, end);
|
|
3454
|
-
return r;
|
|
3455
|
-
}
|
|
3456
|
-
renderView(view, stack) {
|
|
3457
|
-
let n = stack.binds[1];
|
|
3458
|
-
while (n !== null) {
|
|
3459
|
-
const b = n[0];
|
|
3460
|
-
if (b.isFrame) {
|
|
3461
|
-
if (stack.it !== b.it)
|
|
3462
|
-
break;
|
|
3463
|
-
console.error("recursion detected", stack.it, b.it);
|
|
3464
|
-
return new VComment("RECURSION AVOIDED");
|
|
3465
|
-
}
|
|
3466
|
-
n = n[1];
|
|
3467
|
-
}
|
|
3468
|
-
return view.render(stack, this);
|
|
3469
|
-
}
|
|
3470
|
-
_renderMetadata(info) {
|
|
3471
|
-
return new VComment(`§${JSON.stringify(info)}§`);
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
var getSeqInfo = (seq) => isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
3475
|
-
var normalizeRange = (start, end, size) => {
|
|
3476
|
-
let s = start == null ? 0 : start < 0 ? size + start : start;
|
|
3477
|
-
let e = end == null ? size : end < 0 ? size + end : end;
|
|
3478
|
-
s = s < 0 ? 0 : s > size ? size : s;
|
|
3479
|
-
e = e < 0 ? 0 : e > size ? size : e;
|
|
3480
|
-
return [s, e < s ? s : e];
|
|
3481
|
-
};
|
|
3482
|
-
var unpackLoopResult = (result, seq) => {
|
|
3483
|
-
const r = result ?? {};
|
|
3484
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
3485
|
-
};
|
|
3486
|
-
var imIndexedIter = (seq, visit, start, end) => {
|
|
3487
|
-
const [s, e] = normalizeRange(start, end, seq.size);
|
|
3488
|
-
for (let i = s;i < e; i++)
|
|
3489
|
-
visit(i, seq.get(i), "si");
|
|
3490
|
-
};
|
|
3491
|
-
var imKeyedIter = (seq, visit, start, end) => {
|
|
3492
|
-
const [s, e] = normalizeRange(start, end, seq.size);
|
|
3493
|
-
let i = 0;
|
|
3494
|
-
for (const [k, v] of seq.toSeq().entries()) {
|
|
3495
|
-
if (i >= e)
|
|
3496
|
-
break;
|
|
3497
|
-
if (i >= s)
|
|
3498
|
-
visit(k, v, "sk");
|
|
3499
|
-
i++;
|
|
3500
|
-
}
|
|
3501
|
-
};
|
|
3502
|
-
var unkIter = () => {};
|
|
3503
|
-
var SEQ_INFO = Symbol.for("tutuca.seqInfo");
|
|
3504
|
-
|
|
3505
3499
|
// index.js
|
|
3506
3500
|
import {
|
|
3507
3501
|
Collection,
|
|
3508
|
-
List as List2,
|
|
3509
|
-
Map as Map2,
|
|
3510
|
-
OrderedMap as OrderedMap2,
|
|
3511
|
-
OrderedSet,
|
|
3512
|
-
PairSorting,
|
|
3513
|
-
Range,
|
|
3514
|
-
Record as Record2,
|
|
3515
|
-
Repeat,
|
|
3516
|
-
Seq,
|
|
3517
|
-
Set as Set2,
|
|
3518
|
-
Stack as Stack2,
|
|
3519
3502
|
fromJS,
|
|
3520
3503
|
get,
|
|
3521
3504
|
getIn,
|
|
3522
3505
|
has,
|
|
3523
|
-
hasIn,
|
|
3524
3506
|
hash,
|
|
3507
|
+
hasIn,
|
|
3525
3508
|
is as is2,
|
|
3526
3509
|
isAssociative,
|
|
3527
3510
|
isCollection,
|
|
@@ -3530,8 +3513,10 @@ import {
|
|
|
3530
3513
|
isKeyed as isKeyed2,
|
|
3531
3514
|
isList,
|
|
3532
3515
|
isMap,
|
|
3516
|
+
isMap as isMap2,
|
|
3533
3517
|
isOrdered,
|
|
3534
3518
|
isOrderedMap,
|
|
3519
|
+
isOrderedMap as isOrderedMap2,
|
|
3535
3520
|
isOrderedSet,
|
|
3536
3521
|
isPlainObject,
|
|
3537
3522
|
isRecord,
|
|
@@ -3539,22 +3524,31 @@ import {
|
|
|
3539
3524
|
isSet,
|
|
3540
3525
|
isStack,
|
|
3541
3526
|
isValueObject,
|
|
3527
|
+
List as List2,
|
|
3528
|
+
Map as Map2,
|
|
3529
|
+
Map as Map3,
|
|
3542
3530
|
merge,
|
|
3543
3531
|
mergeDeep,
|
|
3544
3532
|
mergeDeepWith,
|
|
3545
3533
|
mergeWith,
|
|
3534
|
+
OrderedMap as OrderedMap2,
|
|
3535
|
+
OrderedMap as OrderedMap3,
|
|
3536
|
+
OrderedSet,
|
|
3537
|
+
PairSorting,
|
|
3538
|
+
Range,
|
|
3539
|
+
Record as Record2,
|
|
3540
|
+
Repeat,
|
|
3546
3541
|
remove,
|
|
3547
3542
|
removeIn,
|
|
3543
|
+
Seq,
|
|
3544
|
+
Set as Set2,
|
|
3545
|
+
Set as Set3,
|
|
3546
|
+
Stack as Stack2,
|
|
3548
3547
|
set,
|
|
3549
3548
|
setIn,
|
|
3550
3549
|
update,
|
|
3551
3550
|
updateIn,
|
|
3552
|
-
version
|
|
3553
|
-
isMap as isMap2,
|
|
3554
|
-
isOrderedMap as isOrderedMap2,
|
|
3555
|
-
Map as Map3,
|
|
3556
|
-
OrderedMap as OrderedMap3,
|
|
3557
|
-
Set as Set3
|
|
3551
|
+
version
|
|
3558
3552
|
} from "immutable";
|
|
3559
3553
|
|
|
3560
3554
|
// src/oo.js
|
|
@@ -3824,8 +3818,8 @@ class FieldSet extends Field {
|
|
|
3824
3818
|
}
|
|
3825
3819
|
}
|
|
3826
3820
|
function mkCompField(field, scope, args) {
|
|
3827
|
-
const Comp = scope
|
|
3828
|
-
console.assert(Comp !== null, "component not found", { field });
|
|
3821
|
+
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
3822
|
+
console.assert(!scope || Comp !== null, "component not found", { field });
|
|
3829
3823
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
3830
3824
|
}
|
|
3831
3825
|
|