Fix: Capture css background-clip: text with browser prefix (#1047)
This commit is contained in:
@@ -24,10 +24,38 @@ export function isNativeShadowDom(shadowRoot: ShadowRoot) {
|
|||||||
return Object.prototype.toString.call(shadowRoot) === '[object ShadowRoot]';
|
return Object.prototype.toString.call(shadowRoot) === '[object ShadowRoot]';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Browsers sometimes destructively modify the css rules they receive.
|
||||||
|
* This function tries to rectify the modifications the browser made to make it more cross platform compatible.
|
||||||
|
* @param cssText - output of `CSSStyleRule.cssText`
|
||||||
|
* @returns `cssText` with browser inconsistencies fixed.
|
||||||
|
*/
|
||||||
|
function fixBrowserCompatibilityIssuesInCSS(cssText: string): string {
|
||||||
|
/**
|
||||||
|
* Chrome outputs `-webkit-background-clip` as `background-clip` in `CSSStyleRule.cssText`.
|
||||||
|
* But then Chrome ignores `background-clip` as css input.
|
||||||
|
* Re-introduce `-webkit-background-clip` to fix this issue.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
cssText.includes(' background-clip: text;') &&
|
||||||
|
!cssText.includes(' -webkit-background-clip: text;')
|
||||||
|
) {
|
||||||
|
cssText = cssText.replace(
|
||||||
|
' background-clip: text;',
|
||||||
|
' -webkit-background-clip: text; background-clip: text;',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return cssText;
|
||||||
|
}
|
||||||
|
|
||||||
export function getCssRulesString(s: CSSStyleSheet): string | null {
|
export function getCssRulesString(s: CSSStyleSheet): string | null {
|
||||||
try {
|
try {
|
||||||
const rules = s.rules || s.cssRules;
|
const rules = s.rules || s.cssRules;
|
||||||
return rules ? Array.from(rules).map(getCssRuleString).join('') : null;
|
return rules
|
||||||
|
? fixBrowserCompatibilityIssuesInCSS(
|
||||||
|
Array.from(rules).map(getCssRuleString).join(''),
|
||||||
|
)
|
||||||
|
: null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,20 @@ exports[`integration tests [html file]: about-mozilla.html 1`] = `
|
|||||||
</p></body></html>"
|
</p></body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`integration tests [html file]: background-clip-text.html 1`] = `
|
||||||
|
"<!DOCTYPE html><html lang=\\"en\\"><head>
|
||||||
|
<meta charset=\\"UTF-8\\" />
|
||||||
|
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"IE=edge\\" />
|
||||||
|
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style id=\\"dynamic-style\\">p { border-width: 0.8em; border-color: darkviolet; border-image: initial; border-style: dotted double; margin: 1em 0px; padding: 1.4em; background: linear-gradient(60deg, red, yellow, red, yellow, red); font: 900 1.2em sans-serif; text-decoration: underline; }.text { -webkit-background-clip: text; background-clip: text; color: rgba(0, 0, 0, 0.2); }</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class=\\"text\\">The background is clipped to the foreground text.</p>
|
||||||
|
<noscript>SCRIPT_PLACEHOLDER</noscript>
|
||||||
|
</body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`integration tests [html file]: basic.html 1`] = `
|
exports[`integration tests [html file]: basic.html 1`] = `
|
||||||
"<!DOCTYPE html><html lang=\\"en\\"><head>
|
"<!DOCTYPE html><html lang=\\"en\\"><head>
|
||||||
<meta charset=\\"UTF-8\\" />
|
<meta charset=\\"UTF-8\\" />
|
||||||
@@ -330,6 +344,25 @@ exports[`integration tests [html file]: picture.html 1`] = `
|
|||||||
</body></html>"
|
</body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`integration tests [html file]: picture-blob.html 1`] = `
|
||||||
|
"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\"><html xmlns=\\"http://www.w3.org/1999/xhtml\\"><head></head><body>
|
||||||
|
<img src=\\"\\" alt=\\"This is a robot\\" />
|
||||||
|
|
||||||
|
<noscript>SCRIPT_PLACEHOLDER</noscript></body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`integration tests [html file]: picture-blob-in-frame.html 1`] = `
|
||||||
|
"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\"><html xmlns=\\"http://www.w3.org/1999/xhtml\\"><head></head><body>
|
||||||
|
<iframe></iframe>
|
||||||
|
</body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`integration tests [html file]: picture-in-frame.html 1`] = `
|
||||||
|
"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\"><html xmlns=\\"http://www.w3.org/1999/xhtml\\"><head></head><body>
|
||||||
|
<iframe></iframe>
|
||||||
|
</body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`integration tests [html file]: preload.html 1`] = `
|
exports[`integration tests [html file]: preload.html 1`] = `
|
||||||
"<!DOCTYPE html><html lang=\\"en\\"><head>
|
"<!DOCTYPE html><html lang=\\"en\\"><head>
|
||||||
<meta charset=\\"UTF-8\\" />
|
<meta charset=\\"UTF-8\\" />
|
||||||
|
|||||||
33
packages/rrweb-snapshot/test/html/background-clip-text.html
Normal file
33
packages/rrweb-snapshot/test/html/background-clip-text.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style id="dynamic-style"></style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="text">The background is clipped to the foreground text.</p>
|
||||||
|
<script>
|
||||||
|
const style = document.getElementById('dynamic-style');
|
||||||
|
style.sheet.insertRule(`p {
|
||||||
|
border: 0.8em darkviolet;
|
||||||
|
border-style: dotted double;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 1.4em;
|
||||||
|
background: linear-gradient(60deg, red, yellow, red, yellow, red);
|
||||||
|
font: 900 1.2em sans-serif;
|
||||||
|
text-decoration: underline;
|
||||||
|
}`);
|
||||||
|
style.sheet.insertRule(
|
||||||
|
`.text {
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
color: rgba(0, 0, 0, 0.2);
|
||||||
|
}`,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -276,6 +276,23 @@ iframe.contentDocument.querySelector('center').clientHeight
|
|||||||
assert(snapshot.includes('"rr_dataURL"'));
|
assert(snapshot.includes('"rr_dataURL"'));
|
||||||
assert(snapshot.includes('data:image/webp;base64,'));
|
assert(snapshot.includes('data:image/webp;base64,'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should save background-clip: text; as the more compatible -webkit-background-clip: test;', async () => {
|
||||||
|
const page: puppeteer.Page = await browser.newPage();
|
||||||
|
await page.goto(`http://localhost:3030/html/background-clip-text.html`, {
|
||||||
|
waitUntil: 'load',
|
||||||
|
});
|
||||||
|
await waitForRAF(page); // wait for page to render
|
||||||
|
await page.evaluate(`${code}
|
||||||
|
window.snapshot = rrweb.snapshot(document, {
|
||||||
|
inlineStylesheet: true,
|
||||||
|
})`);
|
||||||
|
await page.waitFor(100);
|
||||||
|
const snapshot = (await page.evaluate(
|
||||||
|
'JSON.stringify(window.snapshot, null, 2);',
|
||||||
|
)) as string;
|
||||||
|
assert(snapshot.includes('-webkit-background-clip: text;'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('iframe integration tests', function (this: ISuite) {
|
describe('iframe integration tests', function (this: ISuite) {
|
||||||
|
|||||||
Reference in New Issue
Block a user