Skip to content

Commit 5408907

Browse files
fix: css syntax error: 'Unclosed string'
1 parent 76df979 commit 5408907

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

.changeset/smooth-ghosts-wonder.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rrweb/record": patch
3+
---
4+
5+
fix 'CssSyntaxError: Unclosed string' for invalid css rules

packages/rrweb-snapshot/src/utils.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ export function stringifyRule(rule: CSSRule, sheetHref: string | null): string {
150150
}
151151
return importStringified;
152152
} else {
153-
let ruleStringified = rule.cssText;
153+
// Removes incomprehensible empty .cssText rules
154+
// see https://github.com/rrweb-io/rrweb/issues/1734
155+
let ruleStringified = fixEmptyCssStyles(rule.cssText);
154156
if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {
155157
// Safari does not escape selectors with : properly
156158
// see https://bugs.webkit.org/show_bug.cgi?id=184604
@@ -169,6 +171,18 @@ export function fixSafariColons(cssStringified: string): string {
169171
return cssStringified.replace(regex, '$1\\$2');
170172
}
171173

174+
export function fixEmptyCssStyles(cssStringified: string) {
175+
const quickTestRegExp = /:\s*;/;
176+
177+
if (quickTestRegExp.test(cssStringified)) {
178+
// Remove e.g. "border-top-style: ;"
179+
const regex = /(?<=^|\{|\;)\s*[_a-zA-Z][_a-zA-Z0-9-]*:\s*;/gm;
180+
return cssStringified.replace(regex, '');
181+
}
182+
183+
return cssStringified;
184+
}
185+
172186
export function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
173187
return 'styleSheet' in rule;
174188
}

packages/rrweb-snapshot/test/utils.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
escapeImportStatement,
77
extractFileExtension,
88
fixSafariColons,
9+
fixEmptyCssStyles,
910
isNodeMetaEqual,
1011
stringifyStylesheet,
1112
} from '../src/utils';
@@ -282,6 +283,19 @@ describe('utils', () => {
282283
});
283284
});
284285

286+
describe('fixEmptyCssStyles', () => {
287+
it('removes empty css styles', () => {
288+
const input =
289+
'.cl { font-family: sans-serif; font-size: 13px; color: var(--bug-text); border-top-style: ; border-top-width: ; border-right-style: ; border-right-width: ; border-bottom-style: ; border-bottom-width: ; border-left-style: ; border-left-width: ; border-image-source: ; border-image-slice: ; border-image-width: ; border-image-outset: ; border-image-repeat: ; border-color: var(--bug-border); background-color: var(--bug-background-primary); }';
290+
291+
const out1 = fixEmptyCssStyles(input);
292+
293+
expect(out1).toEqual(
294+
'.cl { font-family: sans-serif; font-size: 13px; color: var(--bug-text); border-color: var(--bug-border); background-color: var(--bug-background-primary); }',
295+
);
296+
});
297+
});
298+
285299
describe('stringifyStylesheet', () => {
286300
it('returns null if rules are missing', () => {
287301
const mockSheet = {

0 commit comments

Comments
 (0)