Skip to content

Commit 58cbca4

Browse files
authored
Shadowroot support using getHTML (#1795)
* Shadowroot support using getHTML * Removing backward compatability for getInnerHTML * Removing checks for innerHTML * Adding back the backward compatability for tests * Fixing Test Coverage
1 parent 160670d commit 58cbca4

File tree

3 files changed

+24
-13
lines changed

3 files changed

+24
-13
lines changed

packages/dom/src/clone-dom.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ export function cloneNodeAndShadow(ctx) {
5454
clone.shadowRoot.innerHTML = '';
5555
} else {
5656
clone.attachShadow({
57-
mode: 'open'
57+
mode: 'open',
58+
serializable: true
5859
});
5960
}
6061
// clone dom elements
@@ -84,10 +85,20 @@ export function cloneNodeAndShadow(ctx) {
8485
* Use `getInnerHTML()` to serialize shadow dom as <template> tags. `innerHTML` and `outerHTML` don't do this. Buzzword: "declarative shadow dom"
8586
*/
8687
export function getOuterHTML(docElement) {
87-
// firefox doesn't serialize shadow DOM, we're awaiting API's by firefox to become ready and are not polyfilling it.
88-
if (!docElement.getInnerHTML) { return docElement.outerHTML; }
88+
// All major browsers in latest versions supports getHTML API to get serialized DOM
89+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getHTML
90+
// old firefox doesn't serialize shadow DOM, we're awaiting API's by firefox to become ready and are not polyfilling it.
91+
// new firefox from 128 onwards serializes it using getHTML
92+
/* istanbul ignore if: Only triggered in firefox <= 128 and tests runs on latest */
93+
if (!docElement.getHTML) { return docElement.outerHTML; }
8994
// chromium gives us declarative shadow DOM serialization API
90-
let innerHTML = docElement.getInnerHTML({ includeShadowRoots: true });
95+
let innerHTML = '';
96+
/* istanbul ignore else if: Only triggered in chrome <= 128 and tests runs on latest */
97+
if (docElement.getHTML) {
98+
innerHTML = docElement.getHTML({ serializableShadowRoots: true });
99+
} else if (docElement.getInnerHTML) {
100+
innerHTML = docElement.getInnerHTML({ includeShadowRoots: true });
101+
}
91102
docElement.textContent = '';
92103
// Note: Here we are specifically passing replacer function to avoid any replacements due to
93104
// special characters in client's dom like $&

packages/dom/test/serialize-css.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ describe('serializeCSSOM', () => {
118118
}]));
119119

120120
expect(resultShadowEl.innerHTML).toEqual([
121-
'<template shadowrootmode="open">',
121+
'<template shadowrootmode="open" shadowrootserializable="">',
122122
`<link rel="stylesheet" data-percy-adopted-stylesheets-serialized="true" href="${capture.resources[0].url}">`,
123123
'<p>Percy-0</p>',
124124
'</template>'
@@ -157,14 +157,14 @@ describe('serializeCSSOM', () => {
157157
const resultShadowElChild = $('#Percy-1')[0];
158158

159159
expect(resultShadowEl.innerHTML).toMatch([
160-
'<template shadowrootmode="open">',
160+
'<template shadowrootmode="open" shadowrootserializable="">',
161161
`<link rel="stylesheet" data-percy-adopted-stylesheets-serialized="true" href="${capture.resources[0].url}">`,
162162
'<p>Percy-0</p>',
163163
'</template>'
164164
].join(''));
165165

166166
expect(resultShadowElChild.innerHTML).toMatch([
167-
'<template shadowrootmode="open">',
167+
'<template shadowrootmode="open" shadowrootserializable="">',
168168
`<link rel="stylesheet" data-percy-adopted-stylesheets-serialized="true" href="${capture.resources[1].url}">`,
169169
`<link rel="stylesheet" data-percy-adopted-stylesheets-serialized="true" href="${capture.resources[0].url}">`,
170170
'<p>Percy-1</p>',

packages/dom/test/serialize-dom.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ describe('serializeDOM', () => {
125125
shadow.appendChild(paragraphEl);
126126

127127
const html = serializeDOM().html;
128-
expect(html).toMatch('<template shadowrootmode="open">');
128+
expect(html).toMatch('<template shadowrootmode="open" shadowrootserializable="">');
129129
expect(html).toMatch('Hey Percy!');
130130
});
131131

@@ -162,10 +162,10 @@ describe('serializeDOM', () => {
162162
const html = serializeDOM().html;
163163

164164
expect(html).toMatch(new RegExp([
165-
'<template shadowrootmode="open">',
165+
'<template shadowrootmode="open" shadowrootserializable="">',
166166
'<p>Percy-1</p>',
167167
'<div id="Percy-2" .*>',
168-
'<template shadowrootmode="open">',
168+
'<template shadowrootmode="open" shadowrootserializable="">',
169169
'<p>Percy-2</p>',
170170
'</template>'
171171
].join('')));
@@ -193,7 +193,7 @@ describe('serializeDOM', () => {
193193
el = newEl;
194194
matchRegex += [
195195
`<div id="Percy-${j}" .*>`,
196-
'<template shadowrootmode="open">',
196+
'<template shadowrootmode="open" shadowrootserializable="">',
197197
`<p>Percy-${j}</p>`
198198
].join('');
199199
}
@@ -218,7 +218,7 @@ describe('serializeDOM', () => {
218218
baseContent.appendChild(newEl);
219219
matchRegex += [
220220
`<div id="Percy-${j}" .*>`,
221-
'<template shadowrootmode="open">',
221+
'<template shadowrootmode="open" shadowrootserializable="">',
222222
`<p>Percy-${j}</p>`,
223223
'</template>',
224224
'</div>'
@@ -251,7 +251,7 @@ describe('serializeDOM', () => {
251251
constructor() {
252252
super();
253253
// Create a shadow root
254-
const shadow = this.shadowRoot || this.attachShadow({ mode: 'open' });
254+
const shadow = this.shadowRoot || this.attachShadow({ mode: 'open', serializable: true });
255255
const wrapper = document.createElement('h2');
256256
wrapper.innerText = 'Test';
257257
shadow.appendChild(wrapper);

0 commit comments

Comments
 (0)