1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
function supportsDeclarativeShadowDOM() {
// eslint-disable-next-line no-prototype-builtins
return HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot');
}
function hydrateShadowDomPolyfill(template) {
const mode = template.getAttribute('shadowroot');
const delegatesFocus = !!template.getAttribute('shadowrootdelegatesfocus');
const host = template.parentNode;
const shadowRoot = host.attachShadow({ mode, delegatesFocus });
// expose closed shadow root for tests
if (mode === 'closed') {
host.closedShadowRoot = shadowRoot;
}
shadowRoot.appendChild(template.content);
template.remove();
}
function scanAndHydrateShadowDom(container) {
container
.querySelectorAll('template[shadowroot]')
.forEach(hydrateShadowDomPolyfill);
}
function defineCustomTestElement(win) {
// register custom element to expose closed shadow for tests
if (!win.customElements.get('test-shadow')) {
win.customElements.define(
'test-shadow',
class TestShadow extends win.HTMLElement {
constructor() {
super();
if (supportsDeclarativeShadowDOM()) {
// expose closed shadow root for tests
const { shadowRoot } = this.attachInternals();
if (shadowRoot.mode === 'closed') {
this.closedShadowRoot = shadowRoot;
}
} else {
// polyfill nested shadow hydration
const shadowRoot = this.shadowRoot || this.closedShadowRoot;
if (shadowRoot) {
scanAndHydrateShadowDom(shadowRoot);
}
}
}
}
);
}
}
exports.appendHTMLWithShadowRoots = function (
container,
content,
{ win, caseId } = {}
) {
win = win || window;
defineCustomTestElement(win);
// create dom fragments with shadow dom (if supported)
const fragment = new win.DOMParser().parseFromString(content, 'text/html', {
includeShadowRoots: true,
});
// append content
if (caseId) {
container.appendChild(fragment.querySelector('#' + caseId));
} else {
const nodes = fragment.children[0].children[1].children;
while (nodes.length) {
container.appendChild(nodes[0]);
}
}
// polyfill shadow hydration if not supported
if (supportsDeclarativeShadowDOM() === false) {
scanAndHydrateShadowDom(container);
}
};
|