From 2ae0b893ef19336862d3a985444b0a559e6857f6 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 4 Dec 2024 16:12:46 -0500 Subject: [PATCH] add fix for !important --- packages/rrweb-snapshot/src/utils.ts | 7 +- .../test/__snapshots__/record.test.ts.snap | 103 ++++++++++++++++++ packages/rrweb/test/record.test.ts | 30 ++++- 3 files changed, 137 insertions(+), 3 deletions(-) diff --git a/packages/rrweb-snapshot/src/utils.ts b/packages/rrweb-snapshot/src/utils.ts index bd2b610861..7c026a8ce8 100644 --- a/packages/rrweb-snapshot/src/utils.ts +++ b/packages/rrweb-snapshot/src/utils.ts @@ -113,7 +113,12 @@ export function stringifyStylesheet(s: CSSStyleSheet): string | null { export function fixAllCssProperty(rule: CSSStyleRule) { let styles = ''; for (let i = 0; i < rule.style.length; i++) { - styles += `${rule.style[i]}:${rule.style.getPropertyValue(rule.style[i])};`; + const styleDeclaration = rule.style; + const attribute = styleDeclaration[i]; + const isImportant = styleDeclaration.getPropertyPriority(attribute); + styles += `${attribute}:${styleDeclaration.getPropertyValue(attribute)}${ + isImportant ? ` !important` : '' + };`; } return `${rule.selectorText} { ${styles} }`; diff --git a/packages/rrweb/test/__snapshots__/record.test.ts.snap b/packages/rrweb/test/__snapshots__/record.test.ts.snap index e4f5e0b2e4..00aae9cb0f 100644 --- a/packages/rrweb/test/__snapshots__/record.test.ts.snap +++ b/packages/rrweb/test/__snapshots__/record.test.ts.snap @@ -2428,6 +2428,109 @@ exports[`record captures stylesheets with \`blob:\` url 1`] = ` ]" `; +exports[`record handles \`!important\` with "all" CSS property 1`] = ` +"[ + { + \\"type\\": 4, + \\"data\\": { + \\"href\\": \\"about:blank\\", + \\"width\\": 1920, + \\"height\\": 1080 + } + }, + { + \\"type\\": 2, + \\"data\\": { + \\"node\\": { + \\"type\\": 0, + \\"childNodes\\": [ + { + \\"type\\": 1, + \\"name\\": \\"html\\", + \\"publicId\\": \\"\\", + \\"systemId\\": \\"\\", + \\"id\\": 2 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"html\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"head\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"style\\", + \\"attributes\\": { + \\"_cssText\\": \\".btn { all:unset !important;padding-top:10px !important;padding-right:15px !important;padding-bottom:10px !important;padding-left:15px !important; }\\" + }, + \\"childNodes\\": [], + \\"id\\": 5 + } + ], + \\"id\\": 4 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"body\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 7 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"input\\", + \\"attributes\\": { + \\"type\\": \\"text\\", + \\"size\\": \\"40\\" + }, + \\"childNodes\\": [], + \\"id\\": 8 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n \\\\n \\", + \\"id\\": 9 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"div\\", + \\"attributes\\": { + \\"style\\": \\"all: unset !important; padding: 8px 4px !important;\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"Button\\", + \\"id\\": 11 + } + ], + \\"id\\": 10 + } + ], + \\"id\\": 6 + } + ], + \\"id\\": 3 + } + ], + \\"id\\": 1 + }, + \\"initialOffset\\": { + \\"left\\": 0, + \\"top\\": 0 + } + } + } +]" +`; + exports[`record iframes captures stylesheet mutations in iframes 1`] = ` "[ { diff --git a/packages/rrweb/test/record.test.ts b/packages/rrweb/test/record.test.ts index 7f75b3e4e6..11c986ba1d 100644 --- a/packages/rrweb/test/record.test.ts +++ b/packages/rrweb/test/record.test.ts @@ -749,7 +749,6 @@ describe('record', function (this: ISuite) { document.head.appendChild(styleElement); const styleSheet = styleElement.sheet; - // begin: pre-serialization styleSheet.insertRule('.btn { all: unset; padding: 10px 15px; }'); record({ @@ -772,7 +771,6 @@ describe('record', function (this: ISuite) { document.head.appendChild(style2); const styleSheet = style2.sheet; - // begin: pre-serialization styleSheet.insertRule('.btn2 { all: unset; padding: 4px 8px; }'); }); ctx.page.on('console', (msg) => console.log('PAGE LOG:', msg.text())); @@ -809,6 +807,34 @@ describe('record', function (this: ISuite) { }); }); + it('handles `!important` with "all" CSS property', async () => { + await ctx.page.evaluate(() => { + const { record } = (window as unknown as IWindow).rrweb; + + const div = document.createElement('div'); + div.setAttribute( + 'style', + 'all: unset !important; padding: 8px 4px !important;', + ); + div.innerText = 'Button'; + document.body.appendChild(div); + + const styleElement = document.createElement('style'); + document.head.appendChild(styleElement); + + const styleSheet = styleElement.sheet; + styleSheet.insertRule( + '.btn { all: unset !important; padding: 10px 15px !important; }', + ); + + record({ + emit: (window as unknown as IWindow).emit, + }); + }); + await ctx.page.waitForTimeout(50); + assertSnapshot(ctx.events); + }); + describe('loading stylesheets', () => { let server: Server; let serverURL: string;