@zubra/runtime 5.10.1 → 5.10.3
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/production/element.js +12 -5
- package/package.json +1 -1
- package/src/element.js +13 -6
- package/types/index.d.ts +2 -0
|
@@ -635,19 +635,26 @@ const loadRemark = () => (remarking ??= import('./remark.js').then(
|
|
|
635
635
|
(module) => (remarker = module),
|
|
636
636
|
() => (remarker = { remark: () => false }),
|
|
637
637
|
));
|
|
638
|
-
/**
|
|
639
|
-
|
|
638
|
+
/**
|
|
639
|
+
* Whether `root`'s server markup lost the comments `template` has (its top-level elements are
|
|
640
|
+
* there). A template that is only regions has none of its own: `roots`, from the compiler, names
|
|
641
|
+
* the elements its regions' blocks start with, and markup with none of them is the page's own
|
|
642
|
+
* content (text a framework gave it, say), which needs no check, so the element renders now.
|
|
643
|
+
*/
|
|
644
|
+
function lostComments(root, template, roots) {
|
|
640
645
|
if (!root || !hasContent(root) || !hasComment(template) || hasComment(root)) return false;
|
|
641
646
|
// The page's own children for a slot aren't server markup: the template's top-level elements
|
|
642
647
|
// must be there, in order.
|
|
643
648
|
const children = [...root.children];
|
|
644
649
|
let at = 0;
|
|
650
|
+
let elements = 0;
|
|
645
651
|
for (const node of positions(template.firstChild, null)) {
|
|
646
652
|
if (node.nodeType !== 1) continue;
|
|
647
653
|
while (at < children.length && children[at].localName !== node.localName) at++;
|
|
648
654
|
if (at++ >= children.length) return false;
|
|
655
|
+
elements++;
|
|
649
656
|
}
|
|
650
|
-
return true;
|
|
657
|
+
return elements || !roots ? true : children.some((child) => roots.includes(child.localName));
|
|
651
658
|
}
|
|
652
659
|
|
|
653
660
|
/** A range's shape: its top-level positions as tag names and region markers. */
|
|
@@ -1602,7 +1609,7 @@ export function $define(tag, definition) {
|
|
|
1602
1609
|
|
|
1603
1610
|
function defineElement(tag, definition) {
|
|
1604
1611
|
const { props = {}, shadow = false, form = false, events = [], styled = false, inPage = false } = definition;
|
|
1605
|
-
let { template = '', slots = [], styles = null, setup } = definition;
|
|
1612
|
+
let { roots, template = '', slots = [], styles = null, setup } = definition;
|
|
1606
1613
|
// On a server (no DOM), a stand-in with the same `zubra` description, so a module that imports a
|
|
1607
1614
|
// component loads there: adapters render the host tag, and `@zubra/runtime/server` renders it.
|
|
1608
1615
|
if (typeof HTMLElement === 'undefined') return serverElement(tag, { props, shadow, form, slots, events, styled });
|
|
@@ -1699,7 +1706,7 @@ function defineElement(tag, definition) {
|
|
|
1699
1706
|
if (root.adoptedStyleSheets && !(inPage && root === document)) adopt(root, ownSheets());
|
|
1700
1707
|
}
|
|
1701
1708
|
if (this.#scope) this.#scope.resume();
|
|
1702
|
-
else if (!remarker && lostComments(shadow ? this.shadowRoot : this, componentTemplate.content)) {
|
|
1709
|
+
else if (!remarker && lostComments(shadow ? this.shadowRoot : this, componentTemplate.content, roots)) {
|
|
1703
1710
|
// Server markup without its comments: start once the code that puts them back is here.
|
|
1704
1711
|
this.#starting ??= loadRemark().then(() => {
|
|
1705
1712
|
this.#starting = null;
|
package/package.json
CHANGED
package/src/element.js
CHANGED
|
@@ -654,19 +654,26 @@ const loadRemark = () => (remarking ??= import('./remark.js').then(
|
|
|
654
654
|
(module) => (remarker = module),
|
|
655
655
|
() => (remarker = { remark: () => false }),
|
|
656
656
|
));
|
|
657
|
-
/**
|
|
658
|
-
|
|
657
|
+
/**
|
|
658
|
+
* Whether `root`'s server markup lost the comments `template` has (its top-level elements are
|
|
659
|
+
* there). A template that is only regions has none of its own: `roots`, from the compiler, names
|
|
660
|
+
* the elements its regions' blocks start with, and markup with none of them is the page's own
|
|
661
|
+
* content (text a framework gave it, say), which needs no check, so the element renders now.
|
|
662
|
+
*/
|
|
663
|
+
function lostComments(root, template, roots) {
|
|
659
664
|
if (!root || !hasContent(root) || !hasComment(template) || hasComment(root)) return false;
|
|
660
665
|
// The page's own children for a slot aren't server markup: the template's top-level elements
|
|
661
666
|
// must be there, in order.
|
|
662
667
|
const children = [...root.children];
|
|
663
668
|
let at = 0;
|
|
669
|
+
let elements = 0;
|
|
664
670
|
for (const node of positions(template.firstChild, null)) {
|
|
665
671
|
if (node.nodeType !== 1) continue;
|
|
666
672
|
while (at < children.length && children[at].localName !== node.localName) at++;
|
|
667
673
|
if (at++ >= children.length) return false;
|
|
674
|
+
elements++;
|
|
668
675
|
}
|
|
669
|
-
return true;
|
|
676
|
+
return elements || !roots ? true : children.some((child) => roots.includes(child.localName));
|
|
670
677
|
}
|
|
671
678
|
|
|
672
679
|
/** A range's shape: its top-level positions as tag names and region markers. */
|
|
@@ -1635,7 +1642,7 @@ const HOT = Symbol('zubra.hot');
|
|
|
1635
1642
|
|
|
1636
1643
|
function defineElement(tag, definition) {
|
|
1637
1644
|
const { props = {}, shadow = false, form = false, events = [], styled = false, inPage = false } = definition;
|
|
1638
|
-
let { template = '', slots = [], styles = null, setup } = definition;
|
|
1645
|
+
let { roots, template = '', slots = [], styles = null, setup } = definition;
|
|
1639
1646
|
// On a server (no DOM), a stand-in with the same `zubra` description, so a module that imports a
|
|
1640
1647
|
// component loads there: adapters render the host tag, and `@zubra/runtime/server` renders it.
|
|
1641
1648
|
if (typeof HTMLElement === 'undefined') return serverElement(tag, { props, shadow, form, slots, events, styled });
|
|
@@ -1680,7 +1687,7 @@ function defineElement(tag, definition) {
|
|
|
1680
1687
|
/** Swap in a new version of the component (see above); false if its interface changed. */
|
|
1681
1688
|
static [HOT](next) {
|
|
1682
1689
|
if (shape(next) !== shape(definition)) return false;
|
|
1683
|
-
({ template = '', slots = [], setup } = next);
|
|
1690
|
+
({ roots, template = '', slots = [], setup } = next);
|
|
1684
1691
|
componentTemplate.content = blueprint({ template });
|
|
1685
1692
|
templateSignature = signature(childRange(componentTemplate.content));
|
|
1686
1693
|
const nextStyles = next.styles ?? null;
|
|
@@ -1760,7 +1767,7 @@ function defineElement(tag, definition) {
|
|
|
1760
1767
|
if (root.adoptedStyleSheets && !(inPage && root === document)) adopt(root, ownSheets());
|
|
1761
1768
|
}
|
|
1762
1769
|
if (this.#scope) this.#scope.resume();
|
|
1763
|
-
else if (!remarker && lostComments(shadow ? this.shadowRoot : this, componentTemplate.content)) {
|
|
1770
|
+
else if (!remarker && lostComments(shadow ? this.shadowRoot : this, componentTemplate.content, roots)) {
|
|
1764
1771
|
// Server markup without its comments: start once the code that puts them back is here.
|
|
1765
1772
|
this.#starting ??= loadRemark().then(() => {
|
|
1766
1773
|
this.#starting = null;
|
package/types/index.d.ts
CHANGED
|
@@ -184,6 +184,8 @@ export interface Definition {
|
|
|
184
184
|
form?: boolean;
|
|
185
185
|
slots?: string[];
|
|
186
186
|
events?: string[];
|
|
187
|
+
/** For a template that is only regions: the elements their blocks start with (server markup's top level). */
|
|
188
|
+
roots?: string[];
|
|
187
189
|
/** The component has a `<style>`. */
|
|
188
190
|
styled?: boolean;
|
|
189
191
|
/** Its stylesheet, when the module carries it (otherwise the bundler adds it to the page). */
|