tutuca 0.9.26 → 0.9.28
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 +4 -4
- package/dist/tutuca-cli.js +129 -130
- package/dist/tutuca-dev.js +128 -122
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.js +128 -122
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca.js +128 -122
- package/dist/tutuca.min.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Zero-dependency batteries included SPA framework.
|
|
|
7
7
|
- **Fits in your head** (and the context window)
|
|
8
8
|
- **View source friendly** — step through the whole stack
|
|
9
9
|
- **As much HTML as possible, as little JS as needed**
|
|
10
|
-
- ~
|
|
10
|
+
- ~169KB minified, ~37KB brotli compressed
|
|
11
11
|
|
|
12
12
|
## Quick Start
|
|
13
13
|
|
|
@@ -64,17 +64,17 @@ Zero-dependency batteries included SPA framework.
|
|
|
64
64
|
Tutuca ships a single-file CLI (`dist/tutuca-cli.js`) for inspecting, linting,
|
|
65
65
|
documenting, and rendering components defined in an ES module. The module just
|
|
66
66
|
needs to export `getComponents()` and, for render-time commands, `getExamples()`
|
|
67
|
-
in the storybook shape `{ title, description?,
|
|
67
|
+
in the storybook shape `{ title, description?, items: [{ title, description?, value, view? }] }` (a single section, or an array of sections).
|
|
68
68
|
|
|
69
69
|
### Setup
|
|
70
70
|
|
|
71
71
|
```sh
|
|
72
|
-
npm install --save-dev tutuca
|
|
72
|
+
npm install --save-dev tutuca
|
|
73
73
|
# prettier is optional, only needed for --pretty
|
|
74
74
|
npm install --save-dev prettier
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
The package exposes `tutuca` via `bin`, so `npx tutuca` (or a global `npm i -g tutuca
|
|
77
|
+
The package exposes `tutuca` via `bin`, so `npx tutuca` (or a global `npm i -g tutuca`) just works. `jsdom` ships as a regular dependency (it's needed by `render`, `lint`, and `doctor`) and is installed automatically.
|
|
78
78
|
|
|
79
79
|
### Commands
|
|
80
80
|
|
package/dist/tutuca-cli.js
CHANGED
|
@@ -221,15 +221,11 @@ function normalizeModule(mod, { path = null } = {}) {
|
|
|
221
221
|
"getMacros",
|
|
222
222
|
"getRequestHandlers",
|
|
223
223
|
"getExamples",
|
|
224
|
-
"getStoryBookSection",
|
|
225
224
|
"getRoot"
|
|
226
225
|
]) {
|
|
227
226
|
if (typeof mod[key] === "function")
|
|
228
227
|
present.add(key);
|
|
229
228
|
}
|
|
230
|
-
if (present.has("getStoryBookSection") && !present.has("getExamples")) {
|
|
231
|
-
throw shapeError("module exports getStoryBookSection; rename it to getExamples.", "module");
|
|
232
|
-
}
|
|
233
229
|
const components = present.has("getComponents") ? mod.getComponents() : [];
|
|
234
230
|
const macros = present.has("getMacros") ? mod.getMacros() : null;
|
|
235
231
|
const requestHandlers = present.has("getRequestHandlers") ? mod.getRequestHandlers() : null;
|
|
@@ -739,13 +735,10 @@ class ValParser {
|
|
|
739
735
|
switch (charCode) {
|
|
740
736
|
case 94: {
|
|
741
737
|
const newS = px.frame.macroVars?.[s.slice(1)];
|
|
742
|
-
if (newS !== undefined)
|
|
738
|
+
if (newS !== undefined)
|
|
743
739
|
return this.parse(newS, px);
|
|
744
|
-
}
|
|
745
740
|
return null;
|
|
746
741
|
}
|
|
747
|
-
case 126:
|
|
748
|
-
return this.okStrTpl ? parseConst(s.slice(1), px) : null;
|
|
749
742
|
case 39:
|
|
750
743
|
return this.okStrTpl ? parseConst(s.slice(1, -1), px) : null;
|
|
751
744
|
case 64:
|
|
@@ -858,7 +851,7 @@ function getValSubType(s) {
|
|
|
858
851
|
return open === 1 && close === 1 ? VAL_SUB_TYPE_SEQ_ACCESS : VAL_SUB_TYPE_INVALID;
|
|
859
852
|
return -1;
|
|
860
853
|
}
|
|
861
|
-
var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, parseStrTemplate = (v, px) => StrTplVal.parse(v, px), parseConst = (v, _) => new ConstVal(v), parseName = (v, _) => isValidValId(v) ? new NameVal(v) : null, parseType = (v, _) => isValidValId(v) ? new TypeVal(v) : null, parseBind = (v, _) => isValidValId(v) ? new BindVal(v) : null, parseDyn = (v, _) => isValidValId(v) ? new DynVal(v) : null, parseField = (v, _) => isValidValId(v) ? new FieldVal(v) : null, parseComp = (v, _) => isValidValId(v) ? new ComputedVal(v) : null, parseReq = (v, _) => isValidValId(v) ? new RequestVal(v) : null, ConstVal, VarVal, StrTplVal, NameVal, InputHandlerNameVal, AlterHandlerNameVal, mk404Handler = (type, name) => function(...args) {
|
|
854
|
+
var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, parseStrTemplate = (v, px) => StrTplVal.parse(v, px), parseConst = (v, _) => new ConstVal(v), parseName = (v, _) => isValidValId(v) ? new NameVal(v) : null, parseType = (v, _) => isValidValId(v) ? new TypeVal(v) : null, parseBind = (v, _) => isValidValId(v) ? new BindVal(v) : null, parseDyn = (v, _) => isValidValId(v) ? new DynVal(v) : null, parseField = (v, _) => isValidValId(v) ? new FieldVal(v) : null, parseComp = (v, _) => isValidValId(v) ? new ComputedVal(v) : null, parseReq = (v, _) => isValidValId(v) ? new RequestVal(v) : null, ConstVal, VarVal, StrTplVal, NameVal, InputHandlerNameVal, AlterHandlerNameVal, mk404Handler = (type, name) => function(...args) {
|
|
862
855
|
console.warn("handler not found", { type, name, args }, this);
|
|
863
856
|
return this;
|
|
864
857
|
}, TypeVal, RequestVal, RawFieldVal, RenderVal, RenderNameVal, BindVal, DynVal, FieldVal, ComputedVal, SeqAccessVal, VAL_SUB_TYPE_STRING_TEMPLATE = 0, VAL_SUB_TYPE_SEQ_ACCESS = 1, VAL_SUB_TYPE_INVALID = 2, VAL_SUB_TYPE_CONST_STRING = 3, vp;
|
|
@@ -866,6 +859,7 @@ var init_value = __esm(() => {
|
|
|
866
859
|
init_path();
|
|
867
860
|
VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
868
861
|
VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
|
|
862
|
+
STR_TPL_SPLIT_RE = /(\{[^}]+\})/g;
|
|
869
863
|
ConstVal = class ConstVal extends BaseVal {
|
|
870
864
|
constructor(val) {
|
|
871
865
|
super();
|
|
@@ -899,7 +893,7 @@ var init_value = __esm(() => {
|
|
|
899
893
|
return strs.join("");
|
|
900
894
|
}
|
|
901
895
|
static parse(s, px) {
|
|
902
|
-
const parts = s.split(
|
|
896
|
+
const parts = s.split(STR_TPL_SPLIT_RE);
|
|
903
897
|
const vals = new Array(parts.length);
|
|
904
898
|
let allConsts = true;
|
|
905
899
|
for (let i = 0;i < parts.length; i++) {
|
|
@@ -1333,9 +1327,8 @@ function optimizeChilds(childs) {
|
|
|
1333
1327
|
}
|
|
1334
1328
|
}
|
|
1335
1329
|
function optimizeNode(node) {
|
|
1336
|
-
if (node.isConstant())
|
|
1330
|
+
if (node.isConstant())
|
|
1337
1331
|
return new RenderOnceNode(node);
|
|
1338
|
-
}
|
|
1339
1332
|
node.optimize();
|
|
1340
1333
|
return node;
|
|
1341
1334
|
}
|
|
@@ -1401,12 +1394,6 @@ class ParseContext {
|
|
|
1401
1394
|
newDOMParser() {
|
|
1402
1395
|
return new this.DOMParser;
|
|
1403
1396
|
}
|
|
1404
|
-
isTextNode(v) {
|
|
1405
|
-
return v instanceof this.Text;
|
|
1406
|
-
}
|
|
1407
|
-
isCommentNode(v) {
|
|
1408
|
-
return v instanceof this.Comment;
|
|
1409
|
-
}
|
|
1410
1397
|
addNodeIf(Class, val, extra) {
|
|
1411
1398
|
if (val !== null) {
|
|
1412
1399
|
const nodeId = this.nodes.length;
|
|
@@ -1425,21 +1412,18 @@ class ParseContext {
|
|
|
1425
1412
|
newMacroNode(macroName, mAttrs, childs) {
|
|
1426
1413
|
const anySlot = [];
|
|
1427
1414
|
const slots = { _: new FragmentNode(anySlot) };
|
|
1428
|
-
for (const child of childs)
|
|
1429
|
-
if (child instanceof SlotNode)
|
|
1415
|
+
for (const child of childs)
|
|
1416
|
+
if (child instanceof SlotNode)
|
|
1430
1417
|
slots[child.val.val] = child.node;
|
|
1431
|
-
|
|
1418
|
+
else if (!(child instanceof TextNode) || !child.isWhiteSpace())
|
|
1432
1419
|
anySlot.push(child);
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
1420
|
const node = new MacroNode(macroName, mAttrs, slots, this);
|
|
1436
1421
|
this.macroNodes.push(node);
|
|
1437
1422
|
return node;
|
|
1438
1423
|
}
|
|
1439
1424
|
compile(scope) {
|
|
1440
|
-
for (let i = 0;i < this.macroNodes.length; i++)
|
|
1425
|
+
for (let i = 0;i < this.macroNodes.length; i++)
|
|
1441
1426
|
this.macroNodes[i].compile(scope);
|
|
1442
|
-
}
|
|
1443
1427
|
}
|
|
1444
1428
|
*genEventNames() {
|
|
1445
1429
|
for (const event of this.events)
|
|
@@ -1454,26 +1438,28 @@ class ParseContext {
|
|
|
1454
1438
|
onAttributes(_attrs, _wrapperAttrs, _textChild, _isMacroCall) {}
|
|
1455
1439
|
}
|
|
1456
1440
|
function condenseChildsWhites(childs) {
|
|
1457
|
-
|
|
1458
|
-
if (end === 0)
|
|
1441
|
+
if (childs.length === 0)
|
|
1459
1442
|
return childs;
|
|
1460
|
-
let start = 0;
|
|
1461
1443
|
let changed = false;
|
|
1462
|
-
if (
|
|
1463
|
-
|
|
1444
|
+
if (childs[0].isWhiteSpace?.()) {
|
|
1445
|
+
childs[0].condenseWhiteSpace();
|
|
1464
1446
|
changed = true;
|
|
1465
1447
|
}
|
|
1466
|
-
|
|
1467
|
-
|
|
1448
|
+
const last = childs.length - 1;
|
|
1449
|
+
if (last > 0 && childs[last].isWhiteSpace?.()) {
|
|
1450
|
+
childs[last].condenseWhiteSpace();
|
|
1468
1451
|
changed = true;
|
|
1469
1452
|
}
|
|
1470
|
-
for (let i = 1;i <
|
|
1453
|
+
for (let i = 1;i < last; i++) {
|
|
1471
1454
|
const cur = childs[i];
|
|
1472
|
-
if (
|
|
1473
|
-
|
|
1455
|
+
if (cur.isWhiteSpace?.() && cur.hasNewLine()) {
|
|
1456
|
+
const bothBlock = isBlockDomNode(childs[i - 1]) && isBlockDomNode(childs[i + 1]);
|
|
1457
|
+
cur.condenseWhiteSpace(bothBlock ? "" : " ");
|
|
1458
|
+
if (bothBlock)
|
|
1459
|
+
changed = true;
|
|
1474
1460
|
}
|
|
1475
1461
|
}
|
|
1476
|
-
return changed ? childs.
|
|
1462
|
+
return changed ? childs.filter((c) => !(c instanceof TextNode && c.val === "")) : childs;
|
|
1477
1463
|
}
|
|
1478
1464
|
|
|
1479
1465
|
class NodeEvents {
|
|
@@ -1490,12 +1476,11 @@ class NodeEvents {
|
|
|
1490
1476
|
}
|
|
1491
1477
|
getHandlersFor(eventName) {
|
|
1492
1478
|
let r = null;
|
|
1493
|
-
for (const handler of this.handlers)
|
|
1479
|
+
for (const handler of this.handlers)
|
|
1494
1480
|
if (handler.handlesEventName(eventName)) {
|
|
1495
1481
|
r ??= [];
|
|
1496
1482
|
r.push(handler);
|
|
1497
1483
|
}
|
|
1498
|
-
}
|
|
1499
1484
|
return r;
|
|
1500
1485
|
}
|
|
1501
1486
|
}
|
|
@@ -1530,7 +1515,10 @@ function compileModifiers(eventName, names) {
|
|
|
1530
1515
|
return w(this, f, args, ctx);
|
|
1531
1516
|
};
|
|
1532
1517
|
}
|
|
1533
|
-
var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, _parser = null, 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,
|
|
1518
|
+
var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, _parser = null, 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) => {
|
|
1519
|
+
const node = n instanceof FragmentNode ? n.childs[0] : n;
|
|
1520
|
+
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
1521
|
+
}, 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;
|
|
1534
1522
|
var init_anode = __esm(() => {
|
|
1535
1523
|
init_attribute();
|
|
1536
1524
|
init_path();
|
|
@@ -1559,8 +1547,8 @@ var init_anode = __esm(() => {
|
|
|
1559
1547
|
}
|
|
1560
1548
|
return false;
|
|
1561
1549
|
}
|
|
1562
|
-
condenseWhiteSpace() {
|
|
1563
|
-
this.val =
|
|
1550
|
+
condenseWhiteSpace(replacement = "") {
|
|
1551
|
+
this.val = replacement;
|
|
1564
1552
|
}
|
|
1565
1553
|
isConstant() {
|
|
1566
1554
|
return true;
|
|
@@ -1629,9 +1617,9 @@ var init_anode = __esm(() => {
|
|
|
1629
1617
|
return ANode.fromDOM(nodes[0] ?? new px.Text(""), px);
|
|
1630
1618
|
}
|
|
1631
1619
|
static fromDOM(node, px) {
|
|
1632
|
-
if (px.
|
|
1620
|
+
if (node instanceof px.Text)
|
|
1633
1621
|
return new TextNode(node.textContent);
|
|
1634
|
-
else if (px.
|
|
1622
|
+
else if (node instanceof px.Comment)
|
|
1635
1623
|
return new CommentNode(node.textContent);
|
|
1636
1624
|
const { childNodes, attributes: attrs, tagName: tag } = node;
|
|
1637
1625
|
const childs = new Array(childNodes.length);
|
|
@@ -1677,7 +1665,7 @@ var init_anode = __esm(() => {
|
|
|
1677
1665
|
if (textChild)
|
|
1678
1666
|
childs.unshift(new RenderTextNode(null, textChild));
|
|
1679
1667
|
const domChilds = tag !== "PRE" ? condenseChildsWhites(childs) : childs;
|
|
1680
|
-
return wrap(new DomNode(tag
|
|
1668
|
+
return wrap(new DomNode(tag, nAttrs, domChilds), px, wrappers);
|
|
1681
1669
|
}
|
|
1682
1670
|
return new CommentNode(`Error: InvalidTagName ${tag}`);
|
|
1683
1671
|
}
|
|
@@ -1697,9 +1685,9 @@ var init_anode = __esm(() => {
|
|
|
1697
1685
|
if (this.px.isInsideMacro(name))
|
|
1698
1686
|
throw new Error(`Recursive macro expansion: ${name}`);
|
|
1699
1687
|
const macro = scope.lookupMacro(name);
|
|
1700
|
-
if (macro === null)
|
|
1688
|
+
if (macro === null)
|
|
1701
1689
|
this.node = new CommentNode(`bad macro: ${name}`);
|
|
1702
|
-
|
|
1690
|
+
else {
|
|
1703
1691
|
const vars = { ...macro.defaults, ...attrs };
|
|
1704
1692
|
this.node = macro.expand(this.px.enterMacro(name, vars, slots));
|
|
1705
1693
|
for (const key in this.dataAttrs)
|
|
@@ -1853,6 +1841,7 @@ var init_anode = __esm(() => {
|
|
|
1853
1841
|
scope: ScopeNode,
|
|
1854
1842
|
"push-view": PushViewNameNode
|
|
1855
1843
|
};
|
|
1844
|
+
HTML_BLOCK_TAGS = new Set(_htmlBlockTags.split(","));
|
|
1856
1845
|
isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1857
1846
|
fwdCtrl = fwdIfCtxPred(({ e }) => isMac && e.metaKey || e.ctrlKey);
|
|
1858
1847
|
fwdMeta = fwdIfCtxPred(({ e }) => e.metaKey);
|
|
@@ -1870,10 +1859,8 @@ var init_anode = __esm(() => {
|
|
|
1870
1859
|
|
|
1871
1860
|
// src/cache.js
|
|
1872
1861
|
class NullDomCache {
|
|
1873
|
-
get(
|
|
1874
|
-
set(
|
|
1875
|
-
get2(_k1, _k2, _cacheKey) {}
|
|
1876
|
-
set2(_k1, _k2, _cacheKey, _v) {}
|
|
1862
|
+
get(_keys, _cacheKey) {}
|
|
1863
|
+
set(_keys, _cacheKey, _v) {}
|
|
1877
1864
|
evict() {
|
|
1878
1865
|
return { hit: 0, miss: 0, badKey: 0 };
|
|
1879
1866
|
}
|
|
@@ -1882,7 +1869,7 @@ class NullDomCache {
|
|
|
1882
1869
|
class WeakMapDomCache {
|
|
1883
1870
|
constructor() {
|
|
1884
1871
|
this.hit = this.miss = this.badKey = 0;
|
|
1885
|
-
this.
|
|
1872
|
+
this.keysByLen = new Map;
|
|
1886
1873
|
}
|
|
1887
1874
|
_returnValue(r) {
|
|
1888
1875
|
if (r === undefined)
|
|
@@ -1891,41 +1878,51 @@ class WeakMapDomCache {
|
|
|
1891
1878
|
this.hit += 1;
|
|
1892
1879
|
return r;
|
|
1893
1880
|
}
|
|
1894
|
-
get(
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
cur
|
|
1901
|
-
|
|
1902
|
-
|
|
1881
|
+
get(keys, cacheKey) {
|
|
1882
|
+
const len = keys.length;
|
|
1883
|
+
let cur = this.keysByLen.get(len);
|
|
1884
|
+
if (!cur)
|
|
1885
|
+
return this._returnValue(undefined);
|
|
1886
|
+
for (let i = 0;i < len - 1; i++) {
|
|
1887
|
+
cur = cur.get(keys[i]);
|
|
1888
|
+
if (!cur)
|
|
1889
|
+
return this._returnValue(undefined);
|
|
1890
|
+
}
|
|
1891
|
+
return this._returnValue(cur.get(keys[len - 1])?.[cacheKey]);
|
|
1892
|
+
}
|
|
1893
|
+
set(keys, cacheKey, v) {
|
|
1894
|
+
const len = keys.length;
|
|
1895
|
+
let cur = this.keysByLen.get(len);
|
|
1896
|
+
if (!cur) {
|
|
1897
|
+
cur = new WeakMap;
|
|
1898
|
+
this.keysByLen.set(len, cur);
|
|
1899
|
+
}
|
|
1900
|
+
for (let i = 0;i < len - 1; i++) {
|
|
1901
|
+
const key = keys[i];
|
|
1902
|
+
let next = cur.get(key);
|
|
1903
|
+
if (!next) {
|
|
1904
|
+
if (typeof key !== "object") {
|
|
1905
|
+
this.badKey += 1;
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1908
|
+
next = new WeakMap;
|
|
1909
|
+
cur.set(key, next);
|
|
1910
|
+
}
|
|
1911
|
+
cur = next;
|
|
1912
|
+
}
|
|
1913
|
+
const lastKey = keys[len - 1];
|
|
1914
|
+
const leaf = cur.get(lastKey);
|
|
1915
|
+
if (leaf)
|
|
1916
|
+
leaf[cacheKey] = v;
|
|
1917
|
+
else if (typeof lastKey === "object")
|
|
1918
|
+
cur.set(lastKey, { [cacheKey]: v });
|
|
1903
1919
|
else
|
|
1904
1920
|
this.badKey += 1;
|
|
1905
1921
|
}
|
|
1906
|
-
get2(k1, k2, cacheKey) {
|
|
1907
|
-
return this._returnValue(this.map.get(k1)?.get?.(k2)?.[cacheKey]);
|
|
1908
|
-
}
|
|
1909
|
-
set2(k1, k2, cacheKey, v) {
|
|
1910
|
-
const cur1 = this.map.get(k1);
|
|
1911
|
-
if (cur1) {
|
|
1912
|
-
const cur = cur1.get(k2);
|
|
1913
|
-
if (cur)
|
|
1914
|
-
cur[cacheKey] = v;
|
|
1915
|
-
else
|
|
1916
|
-
cur1.set(k2, { [cacheKey]: v });
|
|
1917
|
-
} else if (typeof k1 === "object" && typeof k2 === "object") {
|
|
1918
|
-
const cur = new WeakMap;
|
|
1919
|
-
cur.set(k2, { [cacheKey]: v });
|
|
1920
|
-
this.map.set(k1, cur);
|
|
1921
|
-
} else {
|
|
1922
|
-
this.badKey += 1;
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
1922
|
evict() {
|
|
1926
1923
|
const { hit, miss, badKey } = this;
|
|
1927
1924
|
this.hit = this.miss = this.badKey = 0;
|
|
1928
|
-
this.
|
|
1925
|
+
this.keysByLen = new Map;
|
|
1929
1926
|
return { hit, miss, badKey };
|
|
1930
1927
|
}
|
|
1931
1928
|
}
|
|
@@ -2047,8 +2044,8 @@ class ComponentStack {
|
|
|
2047
2044
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
2048
2045
|
}
|
|
2049
2046
|
}
|
|
2050
|
-
function defaultOnStackEnter(
|
|
2051
|
-
return
|
|
2047
|
+
function defaultOnStackEnter() {
|
|
2048
|
+
return null;
|
|
2052
2049
|
}
|
|
2053
2050
|
var init_components = __esm(() => {
|
|
2054
2051
|
init_attribute();
|
|
@@ -2466,7 +2463,7 @@ class Stack {
|
|
|
2466
2463
|
this.ctx = ctx;
|
|
2467
2464
|
}
|
|
2468
2465
|
_enrichOnEnter() {
|
|
2469
|
-
return this.comps.getOnEnterFor(this.it).call(this.it
|
|
2466
|
+
return this.withDynamicBindings(this.comps.getOnEnterFor(this.it).call(this.it));
|
|
2470
2467
|
}
|
|
2471
2468
|
upToFrameBinds() {
|
|
2472
2469
|
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
@@ -2481,7 +2478,8 @@ class Stack {
|
|
|
2481
2478
|
enter(it, bindings = {}, isFrame = true) {
|
|
2482
2479
|
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
2483
2480
|
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
2484
|
-
|
|
2481
|
+
const stack = new Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
2482
|
+
return isFrame ? stack._enrichOnEnter() : stack;
|
|
2485
2483
|
}
|
|
2486
2484
|
pushViewName(name) {
|
|
2487
2485
|
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
@@ -2489,17 +2487,26 @@ class Stack {
|
|
|
2489
2487
|
return new Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
2490
2488
|
}
|
|
2491
2489
|
withDynamicBindings(dynamics) {
|
|
2490
|
+
if (dynamics == null || dynamics.length === 0)
|
|
2491
|
+
return this;
|
|
2492
2492
|
const dynObj = {};
|
|
2493
2493
|
const comp = this.comps.getCompFor(this.it);
|
|
2494
2494
|
for (const dynName of dynamics)
|
|
2495
2495
|
comp.dynamic[dynName].evalAndBind(this, dynObj);
|
|
2496
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
2497
2496
|
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
2497
|
+
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
2498
2498
|
return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
2499
2499
|
}
|
|
2500
|
+
_pushDynBindValuesToArray(arr, dyns) {
|
|
2501
|
+
for (const k in dyns)
|
|
2502
|
+
arr.push(this._lookupDynamicWithDynVal(dyns[k]));
|
|
2503
|
+
}
|
|
2504
|
+
_lookupDynamicWithDynVal(d) {
|
|
2505
|
+
return lookup(this.dynBinds, d.getSymbol(this)) ?? d.val.eval(this);
|
|
2506
|
+
}
|
|
2500
2507
|
lookupDynamic(name) {
|
|
2501
2508
|
const d = this.comps.getCompFor(this.it)?.dynamic[name];
|
|
2502
|
-
return d ?
|
|
2509
|
+
return d ? this._lookupDynamicWithDynVal(d) : null;
|
|
2503
2510
|
}
|
|
2504
2511
|
lookupBind(name) {
|
|
2505
2512
|
return lookup(this.binds, name);
|
|
@@ -2982,23 +2989,20 @@ function morphNode(domNode, source, target, opts) {
|
|
|
2982
2989
|
domNode.data = target.text;
|
|
2983
2990
|
return domNode;
|
|
2984
2991
|
}
|
|
2985
|
-
if (type === 1 && source.
|
|
2992
|
+
if (type === 1 && source.isSameKind(target)) {
|
|
2986
2993
|
const propsDiff = diffProps(source.attrs, target.attrs);
|
|
2987
2994
|
const isSelect = source.tag === "SELECT";
|
|
2988
2995
|
if (propsDiff) {
|
|
2989
2996
|
if (isSelect && "value" in propsDiff) {
|
|
2990
2997
|
const { value: _v, ...rest } = propsDiff;
|
|
2991
2998
|
applyProperties(domNode, rest, source.attrs);
|
|
2992
|
-
} else
|
|
2999
|
+
} else
|
|
2993
3000
|
applyProperties(domNode, propsDiff, source.attrs);
|
|
2994
|
-
}
|
|
2995
3001
|
}
|
|
2996
|
-
if (!target.attrs.dangerouslySetInnerHTML)
|
|
3002
|
+
if (!target.attrs.dangerouslySetInnerHTML)
|
|
2997
3003
|
morphChildren(domNode, source.childs, target.childs, opts);
|
|
2998
|
-
|
|
2999
|
-
if (isSelect && target.attrs.value !== undefined) {
|
|
3004
|
+
if (isSelect && target.attrs.value !== undefined)
|
|
3000
3005
|
applyProperties(domNode, { value: target.attrs.value }, source.attrs);
|
|
3001
|
-
}
|
|
3002
3006
|
return domNode;
|
|
3003
3007
|
}
|
|
3004
3008
|
if (type === 11) {
|
|
@@ -3077,23 +3081,20 @@ function morphChildren(parentDom, oldChilds, newChilds, opts) {
|
|
|
3077
3081
|
if (!used[i] && domNodes[i].parentNode === parentDom)
|
|
3078
3082
|
parentDom.removeChild(domNodes[i]);
|
|
3079
3083
|
}
|
|
3080
|
-
function render(vnode, container, options) {
|
|
3081
|
-
const cached = renderCache.get(container);
|
|
3084
|
+
function render(vnode, container, options, prev) {
|
|
3082
3085
|
const isFragment = vnode instanceof VFragment;
|
|
3083
|
-
if (
|
|
3084
|
-
const oldDom = isFragment ? container :
|
|
3085
|
-
const newDom = morphNode(oldDom,
|
|
3086
|
-
|
|
3087
|
-
return newDom;
|
|
3086
|
+
if (prev && prev.vnode instanceof VFragment === isFragment) {
|
|
3087
|
+
const oldDom = isFragment ? container : prev.dom;
|
|
3088
|
+
const newDom = morphNode(oldDom, prev.vnode, vnode, options);
|
|
3089
|
+
return { vnode, dom: isFragment ? container : newDom };
|
|
3088
3090
|
}
|
|
3089
|
-
renderCache.delete(container);
|
|
3090
3091
|
const domNode = vnode.toDom(options);
|
|
3091
3092
|
container.replaceChildren(domNode);
|
|
3092
|
-
|
|
3093
|
-
return domNode;
|
|
3093
|
+
return { vnode, dom: isFragment ? container : domNode };
|
|
3094
3094
|
}
|
|
3095
3095
|
function h(tagName, properties, children) {
|
|
3096
|
-
const
|
|
3096
|
+
const c = tagName.charCodeAt(0);
|
|
3097
|
+
const tag = c >= 97 && c <= 122 ? tagName.toUpperCase() : tagName;
|
|
3097
3098
|
const props = {};
|
|
3098
3099
|
let key, namespace;
|
|
3099
3100
|
if (properties) {
|
|
@@ -3121,7 +3122,7 @@ function h(tagName, properties, children) {
|
|
|
3121
3122
|
addChild(normalizedChildren, children);
|
|
3122
3123
|
return new VNode(tag, props, normalizedChildren, key, namespace);
|
|
3123
3124
|
}
|
|
3124
|
-
var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a"), isObject = (v) => v !== null && typeof v === "object", prototypesDiffer = (a, b) => Object.getPrototypeOf(a) !== Object.getPrototypeOf(b), getKey = (child) => child instanceof VNode ? child.key : undefined, isIterable = (obj) => obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function", VText, VComment, VFragment, VNode
|
|
3125
|
+
var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a"), isObject = (v) => v !== null && typeof v === "object", prototypesDiffer = (a, b) => Object.getPrototypeOf(a) !== Object.getPrototypeOf(b), getKey = (child) => child instanceof VNode ? child.key : undefined, isIterable = (obj) => obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function", VText, VComment, VFragment, VNode;
|
|
3125
3126
|
var init_vdom = __esm(() => {
|
|
3126
3127
|
VText = class VText extends VBase {
|
|
3127
3128
|
constructor(text) {
|
|
@@ -3185,10 +3186,13 @@ var init_vdom = __esm(() => {
|
|
|
3185
3186
|
get nodeType() {
|
|
3186
3187
|
return 1;
|
|
3187
3188
|
}
|
|
3189
|
+
isSameKind(other) {
|
|
3190
|
+
return this.tag === other.tag && this.namespace === other.namespace && this.key === other.key;
|
|
3191
|
+
}
|
|
3188
3192
|
isEqualTo(other) {
|
|
3189
3193
|
if (this === other)
|
|
3190
3194
|
return true;
|
|
3191
|
-
if (!(other instanceof VNode) || this.
|
|
3195
|
+
if (!(other instanceof VNode) || !this.isSameKind(other) || this.childs.length !== other.childs.length) {
|
|
3192
3196
|
return false;
|
|
3193
3197
|
}
|
|
3194
3198
|
if (this.attrs !== other.attrs) {
|
|
@@ -3216,7 +3220,6 @@ var init_vdom = __esm(() => {
|
|
|
3216
3220
|
return node;
|
|
3217
3221
|
}
|
|
3218
3222
|
};
|
|
3219
|
-
renderCache = new WeakMap;
|
|
3220
3223
|
});
|
|
3221
3224
|
|
|
3222
3225
|
// src/app.js
|
|
@@ -3239,6 +3242,7 @@ class App {
|
|
|
3239
3242
|
};
|
|
3240
3243
|
this._compiled = false;
|
|
3241
3244
|
this._renderOpts = { document: rootNode.ownerDocument };
|
|
3245
|
+
this._renderState = null;
|
|
3242
3246
|
}
|
|
3243
3247
|
get state() {
|
|
3244
3248
|
return this.transactor.state;
|
|
@@ -3345,7 +3349,10 @@ class App {
|
|
|
3345
3349
|
render() {
|
|
3346
3350
|
const root = this.state.val;
|
|
3347
3351
|
const stack = this.makeStack(root);
|
|
3348
|
-
|
|
3352
|
+
const { renderer, rootNode, _renderOpts, _renderState } = this;
|
|
3353
|
+
const newState = render(renderer.renderRoot(stack, root), rootNode, _renderOpts, _renderState);
|
|
3354
|
+
this._renderState = newState;
|
|
3355
|
+
return newState.dom;
|
|
3349
3356
|
}
|
|
3350
3357
|
onChange(callback) {
|
|
3351
3358
|
this.transactor.state.onChange(callback);
|
|
@@ -7716,7 +7723,7 @@ class Renderer {
|
|
|
7716
7723
|
renderToDOM(stack, val) {
|
|
7717
7724
|
const rootNode = document.createElement("div");
|
|
7718
7725
|
const rOpts = { document };
|
|
7719
|
-
render(h("
|
|
7726
|
+
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
7720
7727
|
return rootNode.childNodes[0];
|
|
7721
7728
|
}
|
|
7722
7729
|
renderToString(stack, val, cleanAttrs = true) {
|
|
@@ -7740,13 +7747,15 @@ class Renderer {
|
|
|
7740
7747
|
}
|
|
7741
7748
|
_rValComp(stack, val, comp, nid, key, viewName) {
|
|
7742
7749
|
const cacheKey = `${viewName ?? stack.viewsId ?? ""}${nid}-${key}`;
|
|
7743
|
-
const
|
|
7750
|
+
const cachePath = [val];
|
|
7751
|
+
stack._pushDynBindValuesToArray(cachePath, comp.dynamic);
|
|
7752
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
7744
7753
|
if (cachedNode)
|
|
7745
7754
|
return cachedNode;
|
|
7746
7755
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
7747
7756
|
const meta = this._renderMetadata({ $: "Comp", nid });
|
|
7748
7757
|
const dom = new VFragment([meta, this.renderView(view, stack)]);
|
|
7749
|
-
this.cache.set(
|
|
7758
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
7750
7759
|
return dom;
|
|
7751
7760
|
}
|
|
7752
7761
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
@@ -7758,8 +7767,7 @@ class Renderer {
|
|
|
7758
7767
|
const iterData = loopWith.call(stack.it, seq);
|
|
7759
7768
|
this.getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
7760
7769
|
if (filter.call(stack.it, key, value, iterData)) {
|
|
7761
|
-
const
|
|
7762
|
-
const dom = this.renderIt(newStack, nodeId, key, viewName);
|
|
7770
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), nodeId, key, viewName);
|
|
7763
7771
|
this.pushEachEntry(r, nodeId, attrName, key, dom);
|
|
7764
7772
|
}
|
|
7765
7773
|
});
|
|
@@ -7772,25 +7780,19 @@ class Renderer {
|
|
|
7772
7780
|
const it = stack.it;
|
|
7773
7781
|
this.getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
7774
7782
|
if (filter.call(it, key, value, iterData)) {
|
|
7783
|
+
const cachePath = enricher ? [it, value] : [value];
|
|
7775
7784
|
const bindings = { key, value };
|
|
7776
7785
|
const cacheKey = `${nid}-${key}`;
|
|
7777
|
-
|
|
7778
|
-
if (enricher) {
|
|
7786
|
+
if (enricher)
|
|
7779
7787
|
enricher.call(it, bindings, key, value, iterData);
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
cachedNode = this.cache.get(value, cacheKey);
|
|
7783
|
-
if (cachedNode) {
|
|
7788
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
7789
|
+
if (cachedNode)
|
|
7784
7790
|
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
7785
|
-
|
|
7791
|
+
else {
|
|
7792
|
+
const dom = this.renderView(view, stack.enter(value, bindings, false));
|
|
7793
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
7794
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
7786
7795
|
}
|
|
7787
|
-
const newStack = stack.enter(value, bindings, false);
|
|
7788
|
-
const dom = this.renderView(view, newStack);
|
|
7789
|
-
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
7790
|
-
if (enricher)
|
|
7791
|
-
this.cache.set2(it, value, cacheKey, dom);
|
|
7792
|
-
else
|
|
7793
|
-
this.cache.set(value, cacheKey, dom);
|
|
7794
7796
|
}
|
|
7795
7797
|
});
|
|
7796
7798
|
return r;
|
|
@@ -8069,9 +8071,6 @@ MODULE CONVENTION
|
|
|
8069
8071
|
|
|
8070
8072
|
export function getRoot() // optional; returned by info
|
|
8071
8073
|
|
|
8072
|
-
The legacy \`getStoryBookSection()\` name fails fast with
|
|
8073
|
-
EXAMPLES_SHAPE_MISMATCH — rename it to \`getExamples\`.
|
|
8074
|
-
|
|
8075
8074
|
COMMANDS (require <module-path>)
|
|
8076
8075
|
info
|
|
8077
8076
|
Summarize which getX() exports are present and count components,
|