Merge pull request #1377 from ae-utbm/fix-component-nesting

Fix component nesting bug
This commit is contained in:
2026-05-08 13:01:09 +02:00
committed by GitHub
3 changed files with 16 additions and 9 deletions
@@ -84,12 +84,8 @@ const refreshElement = <
return;
}
// This might be called at some bad timing
// This prevents crashes of the observer
if (element.refresh) {
element.refresh();
}
}
};
// Since we need to pause the observer, we make an helper to start it with consistent arguments
@@ -134,7 +130,7 @@ startObserver(observer);
export class LinkOnce extends elementOnce("link") {
getElementQuerySelector(): string {
// We get href from node.attributes instead of node.href to avoid getting the domain part
return `link[href='${this.node.attributes.getNamedItem("href")?.nodeValue}']`;
return `link[href='${this.node.attributes.getNamedItem("href").nodeValue}']`;
}
}
@@ -146,6 +142,6 @@ export class LinkOnce extends elementOnce("link") {
export class ScriptOnce extends inheritHtmlElement("script") {
getElementQuerySelector(): string {
// We get href from node.attributes instead of node.src to avoid getting the domain part
return `script[src='${this.node.attributes.getNamedItem("src")?.nodeValue}']`;
return `script[src='${this.node.attributes.getNamedItem("src").nodeValue}']`;
}
}
@@ -28,7 +28,7 @@ export class Tab extends HTMLElement {
return html`
<button
role="tab"
?aria-selected=${this.active}
?aria-selected="${this.active}"
class="tab-header clickable ${this.active ? "active" : ""}"
@click="${() => this.setActive(true)}"
>
@@ -40,7 +40,7 @@ export class Tab extends HTMLElement {
return html`
<section
class="tab-section"
?hidden=${!this.active}
?hidden="${!this.active}"
>
${unsafeHTML(this.getContentHtml())}
</section>
@@ -47,9 +47,18 @@ export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagNam
implements InheritedHtmlElement<K>
{
readonly inheritedTagName = tagName;
private readonly initializedAttribute = "component-initialized";
node: HTMLElementTagNameMap[K];
connectedCallback(autoAddNode?: boolean) {
// When nesting inherited elements, we might trigger the wrapping twice
// To avoid this, we tag a created element as initialized
// We then skip the initialization step and grab the inner content as the node
if (this.hasAttribute(this.initializedAttribute)) {
this.node = this.firstChild as HTMLElementTagNameMap[K];
return;
}
this.node = document.createElement(this.inheritedTagName);
const attributes: Attr[] = []; // We need to make a copy to delete while iterating
for (const attr of this.attributes) {
@@ -58,6 +67,8 @@ export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagNam
}
}
this.setAttribute(this.initializedAttribute, "");
// We move compatible attributes to the child element
// This avoids weird inconsistencies between attributes
// when we manipulate the dom in the future