Skip to content

Commit

Permalink
fix: Incorrect parsing of functional pseudo class css selector (#169)
Browse files Browse the repository at this point in the history
This fixes a parsing issue of CSS selectors that use a functional pseudo
class with multiple arguments.

For example,

```
.foo:has(button,div) {}
```

Would get parsed as 2 selectors: `.foo:has(button` and `div)` - this
results in an invalid stylesheet and looks like the replay is broken.

---------

Co-authored-by: Ryan Albrecht <[email protected]>
  • Loading branch information
billyvg and ryan953 committed Apr 26, 2024
1 parent dcf058c commit 7e60935
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions packages/rrweb-snapshot/test/css.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,85 @@ li[attr="has,comma"] a:hover {
).toEqual(1);
});

it.each([
['.foo,.bar {}', ['.foo', '.bar']],
['.bar:has(:disabled) {}', ['.bar:has(:disabled)']],
['.bar:has(input, button) {}', ['.bar:has(input, button)']],
[
'.bar:has(input:is(:disabled),button:has(:disabled)) {}',
['.bar:has(input:is(:disabled),button:has(:disabled))'],
],
[
'.bar:has(div, input:is(:disabled), button) {}',
['.bar:has(div, input:is(:disabled), button)'],
],
[
'.bar:has(div, input:is(:disabled),button:has(:disabled,.baz)) {}',
['.bar:has(div, input:is(:disabled),button:has(:disabled,.baz))'],
],
[
'.bar:has(input), .foo:has(input, button), .baz {}',
['.bar:has(input)', '.foo:has(input, button)', '.baz'],
],
[
'.bar:has(input:is(:disabled),button:has(:disabled,.baz), div:has(:disabled,.baz)){color: red;}',
[
'.bar:has(input:is(:disabled),button:has(:disabled,.baz), div:has(:disabled,.baz))',
],
],
[
'.bar:has(:has(:has(a), :has(:has(:has(b, :has(a), c), e))), input:is(:disabled), button) {}',
[
'.bar:has(:has(:has(a), :has(:has(:has(b, :has(a), c), e))), input:is(:disabled), button)',
],
],
[
'.foo,.bar:has(input:is(:disabled)){color: red;}',
['.foo', '.bar:has(input:is(:disabled))'],
],
[
'.foo,.bar:has(input:is(:disabled),button:has(:disabled,.baz)){color: red;}',
['.foo', '.bar:has(input:is(:disabled),button:has(:disabled,.baz))'],
],
[
'.foo,.bar:has(input:is(:disabled),button:has(:disabled), div:has(:disabled,.baz)){color: red;}',
[
'.foo',
'.bar:has(input:is(:disabled),button:has(:disabled), div:has(:disabled,.baz))',
],
],
[
'.foo,.bar:has(input:is(:disabled),button:has(:disabled,.baz), div:has(:disabled,.baz)){color: red;}',
[
'.foo',
'.bar:has(input:is(:disabled),button:has(:disabled,.baz), div:has(:disabled,.baz))',
],
],
['.bar:has(:disabled), .foo {}', ['.bar:has(:disabled)', '.foo']],
[
'.bar:has(input:is(:disabled),.foo,button:is(:disabled)), .foo {}',
['.bar:has(input:is(:disabled),.foo,button:is(:disabled))', '.foo'],
],
[
'.bar:has(input:is(:disabled),.foo,button:is(:disabled)), .foo:has(input, button), .baz, {}',
[
'.bar:has(input:is(:disabled),.foo,button:is(:disabled))',
'.foo:has(input, button)',
'.baz',
],
],
])(
'can parse selector(s) with functional pseudo classes: %s',
(cssText, expected) => {
expect(
parse(
cssText,
// @ts-ignore
).stylesheet?.rules[0].selectors,
).toEqual(expected);
},
);

it('parses imports with quotes correctly', () => {
const out1 = escapeImportStatement({
cssText: `@import url("/foo.css;900;800"");`,
Expand Down

0 comments on commit 7e60935

Please sign in to comment.