@zenithbuild/runtime 0.6.17 → 0.7.1
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/hydrate.js +194 -18
- package/package.json +1 -1
package/dist/hydrate.js
CHANGED
|
@@ -15,6 +15,7 @@ const ALIAS_CONFLICT = Symbol('alias_conflict');
|
|
|
15
15
|
const ACTIVE_MARKER_CLASS = 'z-active';
|
|
16
16
|
const UNRESOLVED_LITERAL = Symbol('unresolved_literal');
|
|
17
17
|
const LEGACY_MARKUP_HELPER = 'html';
|
|
18
|
+
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
18
19
|
const BOOLEAN_ATTRIBUTES = new Set([
|
|
19
20
|
'disabled', 'checked', 'selected', 'readonly', 'multiple',
|
|
20
21
|
'hidden', 'autofocus', 'required', 'open'
|
|
@@ -161,8 +162,13 @@ export function hydrate(payload) {
|
|
|
161
162
|
}
|
|
162
163
|
const nodes = _resolveNodes(root, marker.selector, marker.index, marker.kind, marker.source);
|
|
163
164
|
markerNodesByIndex.set(marker.index, nodes);
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
try {
|
|
166
|
+
const value = _evaluateExpression(expressions[marker.index], stateValues, stateKeys, signalMap, componentBindings, params, ssrData, marker.kind, props, exprFns, marker, null);
|
|
167
|
+
_applyMarkerValue(nodes, marker, value);
|
|
168
|
+
}
|
|
169
|
+
catch (evalErr) {
|
|
170
|
+
throw evalErr;
|
|
171
|
+
}
|
|
166
172
|
}
|
|
167
173
|
for (let i = 0; i < expressions.length; i++) {
|
|
168
174
|
if (!markerIndices.has(i)) {
|
|
@@ -661,7 +667,9 @@ function _resolveComponentProps(propTable, signalMap, context = {}) {
|
|
|
661
667
|
return resolved;
|
|
662
668
|
}
|
|
663
669
|
function _resolveNodes(root, selector, index, kind, source = undefined) {
|
|
664
|
-
const nodes =
|
|
670
|
+
const nodes = selector.startsWith('comment:')
|
|
671
|
+
? _resolveCommentNodes(root, selector.slice('comment:'.length))
|
|
672
|
+
: root.querySelectorAll(selector);
|
|
665
673
|
if (!nodes || nodes.length === 0) {
|
|
666
674
|
const isRef = kind === 'ref';
|
|
667
675
|
throwZenithRuntimeError({
|
|
@@ -679,6 +687,23 @@ function _resolveNodes(root, selector, index, kind, source = undefined) {
|
|
|
679
687
|
}
|
|
680
688
|
return nodes;
|
|
681
689
|
}
|
|
690
|
+
function _resolveCommentNodes(root, markerText) {
|
|
691
|
+
const walkerRoot = root && root.nodeType === 9 && root.documentElement ? root.documentElement : root;
|
|
692
|
+
const doc = walkerRoot && walkerRoot.ownerDocument ? walkerRoot.ownerDocument : walkerRoot;
|
|
693
|
+
if (!walkerRoot || !doc || typeof doc.createTreeWalker !== 'function') {
|
|
694
|
+
return [];
|
|
695
|
+
}
|
|
696
|
+
const nodes = [];
|
|
697
|
+
const walker = doc.createTreeWalker(walkerRoot, NodeFilter.SHOW_COMMENT);
|
|
698
|
+
let current = walker.nextNode();
|
|
699
|
+
while (current) {
|
|
700
|
+
if (current.data === markerText) {
|
|
701
|
+
nodes.push(current);
|
|
702
|
+
}
|
|
703
|
+
current = walker.nextNode();
|
|
704
|
+
}
|
|
705
|
+
return nodes;
|
|
706
|
+
}
|
|
682
707
|
function _resolveExpressionSignalIndices(binding) {
|
|
683
708
|
if (!binding || typeof binding !== 'object') {
|
|
684
709
|
return [];
|
|
@@ -696,20 +721,25 @@ function _evaluateExpression(binding, stateValues, stateKeys, signalMap, compone
|
|
|
696
721
|
const fns = Array.isArray(exprFns) ? exprFns : [];
|
|
697
722
|
const fn = fns[binding.fn_index];
|
|
698
723
|
if (typeof fn === 'function') {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
724
|
+
try {
|
|
725
|
+
return fn({
|
|
726
|
+
signalMap,
|
|
727
|
+
params,
|
|
728
|
+
ssrData,
|
|
729
|
+
props: props || {},
|
|
730
|
+
componentBindings,
|
|
731
|
+
zenhtml: _zenhtml,
|
|
732
|
+
fragment(html) {
|
|
733
|
+
return {
|
|
734
|
+
__zenith_fragment: true,
|
|
735
|
+
html: html === null || html === undefined || html === false ? '' : String(html)
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
catch (fnErr) {
|
|
741
|
+
throw fnErr;
|
|
742
|
+
}
|
|
713
743
|
}
|
|
714
744
|
}
|
|
715
745
|
if (binding.signal_index !== null && binding.signal_index !== undefined) {
|
|
@@ -1438,6 +1468,10 @@ function _applyMarkerValue(nodes, marker, value) {
|
|
|
1438
1468
|
try {
|
|
1439
1469
|
const node = nodes[i];
|
|
1440
1470
|
if (marker.kind === 'text') {
|
|
1471
|
+
if (node && node.nodeType === 8) {
|
|
1472
|
+
_applyCommentMarkerValue(node, value, `${markerPath}.text`);
|
|
1473
|
+
continue;
|
|
1474
|
+
}
|
|
1441
1475
|
if (_isStructuralFragment(value)) {
|
|
1442
1476
|
_mountStructuralFragment(node, value, `${markerPath}.text`);
|
|
1443
1477
|
continue;
|
|
@@ -1474,6 +1508,33 @@ function _applyMarkerValue(nodes, marker, value) {
|
|
|
1474
1508
|
}
|
|
1475
1509
|
}
|
|
1476
1510
|
}
|
|
1511
|
+
function _applyCommentMarkerValue(anchor, value, rootPath) {
|
|
1512
|
+
if (_isStructuralFragment(value)) {
|
|
1513
|
+
_mountStructuralFragmentIntoCommentRange(anchor, value, rootPath);
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
const end = _clearCommentPlaceholderContent(anchor);
|
|
1517
|
+
const parent = end.parentNode;
|
|
1518
|
+
if (!parent) {
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
const html = _renderFragmentValue(value, rootPath);
|
|
1522
|
+
if (html !== null) {
|
|
1523
|
+
parent.insertBefore(_createContextualFragment(parent, html), end);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
const textNode = (parent.ownerDocument || document).createTextNode(_coerceText(value, rootPath));
|
|
1527
|
+
parent.insertBefore(textNode, end);
|
|
1528
|
+
}
|
|
1529
|
+
function _createContextualFragment(parent, html) {
|
|
1530
|
+
const doc = parent.ownerDocument || document;
|
|
1531
|
+
if (!doc || typeof doc.createRange !== 'function') {
|
|
1532
|
+
throw new Error('[Zenith Runtime] comment placeholder HTML rendering requires Range#createContextualFragment');
|
|
1533
|
+
}
|
|
1534
|
+
const range = doc.createRange();
|
|
1535
|
+
range.selectNode(parent);
|
|
1536
|
+
return range.createContextualFragment(html);
|
|
1537
|
+
}
|
|
1477
1538
|
function _isStructuralFragment(value) {
|
|
1478
1539
|
if (Array.isArray(value)) {
|
|
1479
1540
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -1484,6 +1545,116 @@ function _isStructuralFragment(value) {
|
|
|
1484
1545
|
}
|
|
1485
1546
|
return value && typeof value === 'object' && value.__zenith_fragment === true && typeof value.mount === 'function';
|
|
1486
1547
|
}
|
|
1548
|
+
function _ensureCommentPlaceholderEnd(anchor) {
|
|
1549
|
+
let end = anchor.__z_range_end || null;
|
|
1550
|
+
if (end && end.parentNode === anchor.parentNode) {
|
|
1551
|
+
return end;
|
|
1552
|
+
}
|
|
1553
|
+
const parent = anchor.parentNode;
|
|
1554
|
+
if (!parent) {
|
|
1555
|
+
return null;
|
|
1556
|
+
}
|
|
1557
|
+
end = (anchor.ownerDocument || document).createComment(`/ ${anchor.data}`);
|
|
1558
|
+
parent.insertBefore(end, anchor.nextSibling);
|
|
1559
|
+
anchor.__z_range_end = end;
|
|
1560
|
+
return end;
|
|
1561
|
+
}
|
|
1562
|
+
function _clearCommentPlaceholderContent(anchor) {
|
|
1563
|
+
if (anchor.__z_unmounts) {
|
|
1564
|
+
for (let i = 0; i < anchor.__z_unmounts.length; i++) {
|
|
1565
|
+
try {
|
|
1566
|
+
anchor.__z_unmounts[i]();
|
|
1567
|
+
}
|
|
1568
|
+
catch (e) { }
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
anchor.__z_unmounts = [];
|
|
1572
|
+
const end = _ensureCommentPlaceholderEnd(anchor);
|
|
1573
|
+
if (!end) {
|
|
1574
|
+
return anchor;
|
|
1575
|
+
}
|
|
1576
|
+
let current = anchor.nextSibling;
|
|
1577
|
+
while (current && current !== end) {
|
|
1578
|
+
const next = current.nextSibling;
|
|
1579
|
+
if (current.parentNode) {
|
|
1580
|
+
current.parentNode.removeChild(current);
|
|
1581
|
+
}
|
|
1582
|
+
current = next;
|
|
1583
|
+
}
|
|
1584
|
+
return end;
|
|
1585
|
+
}
|
|
1586
|
+
function _mountStructuralFragmentIntoCommentRange(anchor, value, rootPath = 'renderable') {
|
|
1587
|
+
const end = _clearCommentPlaceholderContent(anchor);
|
|
1588
|
+
const parent = end.parentNode;
|
|
1589
|
+
if (!parent) {
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
const doc = parent.ownerDocument || document;
|
|
1593
|
+
const newUnmounts = [];
|
|
1594
|
+
function insertHtml(html) {
|
|
1595
|
+
const fragment = _createContextualFragment(parent, html);
|
|
1596
|
+
const nodes = Array.from(fragment.childNodes);
|
|
1597
|
+
parent.insertBefore(fragment, end);
|
|
1598
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1599
|
+
const inserted = nodes[i];
|
|
1600
|
+
newUnmounts.push(() => {
|
|
1601
|
+
if (inserted.parentNode)
|
|
1602
|
+
inserted.parentNode.removeChild(inserted);
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
function mountItem(item, path) {
|
|
1607
|
+
if (Array.isArray(item)) {
|
|
1608
|
+
for (let i = 0; i < item.length; i++)
|
|
1609
|
+
mountItem(item[i], `${path}[${i}]`);
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
if (item && item.__zenith_fragment === true && typeof item.mount === 'function') {
|
|
1613
|
+
const fragment = doc.createDocumentFragment();
|
|
1614
|
+
item.mount(fragment);
|
|
1615
|
+
const nodes = Array.from(fragment.childNodes);
|
|
1616
|
+
parent.insertBefore(fragment, end);
|
|
1617
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1618
|
+
const inserted = nodes[i];
|
|
1619
|
+
newUnmounts.push(() => {
|
|
1620
|
+
if (inserted.parentNode)
|
|
1621
|
+
inserted.parentNode.removeChild(inserted);
|
|
1622
|
+
});
|
|
1623
|
+
}
|
|
1624
|
+
if (typeof item.unmount === 'function') {
|
|
1625
|
+
newUnmounts.push(item.unmount.bind(item));
|
|
1626
|
+
}
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
if (item && item.__zenith_fragment === true && typeof item.html === 'string') {
|
|
1630
|
+
insertHtml(item.html);
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
const text = _coerceText(item, path);
|
|
1634
|
+
if (text || text === '') {
|
|
1635
|
+
const textNode = doc.createTextNode(text);
|
|
1636
|
+
parent.insertBefore(textNode, end);
|
|
1637
|
+
newUnmounts.push(() => {
|
|
1638
|
+
if (textNode.parentNode)
|
|
1639
|
+
textNode.parentNode.removeChild(textNode);
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
try {
|
|
1644
|
+
mountItem(value, rootPath);
|
|
1645
|
+
}
|
|
1646
|
+
catch (error) {
|
|
1647
|
+
rethrowZenithRuntimeError(error, {
|
|
1648
|
+
phase: 'render',
|
|
1649
|
+
code: 'FRAGMENT_MOUNT_FAILED',
|
|
1650
|
+
message: 'Fragment mount failed',
|
|
1651
|
+
path: rootPath,
|
|
1652
|
+
hint: 'Verify fragment values and nested renderable arrays.',
|
|
1653
|
+
docsLink: DOCS_LINKS.markerTable
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1656
|
+
anchor.__z_unmounts = newUnmounts;
|
|
1657
|
+
}
|
|
1487
1658
|
function _mountStructuralFragment(container, value, rootPath = 'renderable') {
|
|
1488
1659
|
if (container.__z_unmounts) {
|
|
1489
1660
|
for (let i = 0; i < container.__z_unmounts.length; i++) {
|
|
@@ -1619,7 +1790,12 @@ function _applyAttribute(node, attrName, value) {
|
|
|
1619
1790
|
return;
|
|
1620
1791
|
}
|
|
1621
1792
|
if (attrName === 'class' || attrName === 'className') {
|
|
1622
|
-
|
|
1793
|
+
const classValue = value === null || value === undefined || value === false ? '' : String(value);
|
|
1794
|
+
if (node && node.namespaceURI === SVG_NAMESPACE && typeof node.setAttribute === 'function') {
|
|
1795
|
+
node.setAttribute('class', classValue);
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
node.className = classValue;
|
|
1623
1799
|
return;
|
|
1624
1800
|
}
|
|
1625
1801
|
if (attrName === 'style') {
|