Repository navigation
fix(attributes): use CSS whitespace for token matching - #1911
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
[Medium impact] The PR appears safe to merge.
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All five cases pass on master, where `\s` already splits on them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NBSP, EM SPACE and VT all reach the same character class, so one case covers the path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="test/attributes.ts">
<violation number="1" location="test/attributes.ts:14">
P2: This test now exercises only NBSP, so a regression that treats TAB, LF, FF, CR, or SPACE as token content would pass the suite. Retain a parameterized assertion for all five CSS separators.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
| it("should keep non-CSS whitespace inside a token", () => { | ||
| const token = "foo\u{A0}bar"; | ||
| const document = parseDocument(`<i class="${token}"></i>`); | ||
| expect(CSSselect.selectAll("[class~=foo]", document)).toHaveLength( | ||
| 0, | ||
| ); | ||
| expect(CSSselect.selectAll("[class~=bar]", document)).toHaveLength( | ||
| 0, | ||
| ); | ||
| expect( | ||
| CSSselect.selectAll(`[class~="${token}"]`, document), | ||
| ).toStrictEqual(document.children); | ||
| expect( | ||
| CSSselect.selectAll( | ||
| `[class~="${token.toUpperCase()}" i]`, | ||
| document, | ||
| ), | ||
| ).toStrictEqual(document.children); | ||
| }); |
There was a problem hiding this comment.
P2: This test now exercises only NBSP, so a regression that treats TAB, LF, FF, CR, or SPACE as token content would pass the suite. Retain a parameterized assertion for all five CSS separators.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At test/attributes.ts, line 14:
<comment>This test now exercises only NBSP, so a regression that treats TAB, LF, FF, CR, or SPACE as token content would pass the suite. Retain a parameterized assertion for all five CSS separators.</comment>
<file context>
@@ -11,46 +11,25 @@ const domChilds = dom.children as Element[];
- ).toBe(boolbase.falseFunc);
- },
- );
+ it("should keep non-CSS whitespace inside a token", () => {
+ const token = "foo\u{A0}bar";
+ const document = parseDocument(`<i class="${token}"></i>`);
</file context>
| it("should keep non-CSS whitespace inside a token", () => { | |
| const token = "foo\u{A0}bar"; | |
| const document = parseDocument(`<i class="${token}"></i>`); | |
| expect(CSSselect.selectAll("[class~=foo]", document)).toHaveLength( | |
| 0, | |
| ); | |
| expect(CSSselect.selectAll("[class~=bar]", document)).toHaveLength( | |
| 0, | |
| ); | |
| expect( | |
| CSSselect.selectAll(`[class~="${token}"]`, document), | |
| ).toStrictEqual(document.children); | |
| expect( | |
| CSSselect.selectAll( | |
| `[class~="${token.toUpperCase()}" i]`, | |
| document, | |
| ), | |
| ).toStrictEqual(document.children); | |
| }); | |
| it("should keep non-CSS whitespace inside a token", () => { | |
| const token = "foo\u{A0}bar"; | |
| const document = parseDocument(`<i class="${token}"></i>`); | |
| expect(CSSselect.selectAll("[class~=foo]", document)).toHaveLength( | |
| 0, | |
| ); | |
| expect(CSSselect.selectAll("[class~=bar]", document)).toHaveLength( | |
| 0, | |
| ); | |
| expect( | |
| CSSselect.selectAll(`[class~="${token}"]`, document), | |
| ).toStrictEqual(document.children); | |
| expect( | |
| CSSselect.selectAll( | |
| `[class~="${token.toUpperCase()}" i]`, | |
| document, | |
| ), | |
| ).toStrictEqual(document.children); | |
| }); | |
| it.each(["\t", "\n", "\f", "\r", " "])( | |
| "should split tokens on CSS whitespace %j", | |
| (space) => { | |
| const document = parseDocument( | |
| `<i class="foo${space}bar"></i>`, | |
| ); | |
| expect( | |
| CSSselect.selectAll("[class~=foo]", document), | |
| ).toStrictEqual(document.children); | |
| expect( | |
| CSSselect.selectAll("[class~=bar]", document), | |
| ).toStrictEqual(document.children); | |
| expect( | |
| CSSselect._compileUnsafe(`[class~="foo${space}bar"]`), | |
| ).toBe(boolbase.falseFunc); | |
| }, | |
| ); |
There was a problem hiding this comment.
Intentional: the five-separator rows all pass on master (\s already splits on them), so they don't test this change; splitting on spaces stays covered by the existing ~= tests ([data-foo~=IT i], the nwmatcher [class~=…] cases). The remaining NBSP row is the one that fails without the fix.
🤖 Generated with Claude Code, using Opus 5.5.
[class~=foo]currently matchesclass="foo\u00a0bar", while[class~="foo\u00a0bar"]cannot match the complete token. JavaScript\sincludes NBSP, EM SPACE and vertical tab; CSS uses only TAB, LF, FF, CR and SPACE as whitespace (Selectors §3.7, attribute selectors).Use those five characters for both the
~=selector-value check and attribute token boundaries. The tests cover non-CSS whitespace as token content, case-insensitive matching, and all five CSS separators.Validation: the new suite fails in three cases before the change;
npm testpasses with 225 tests and one existing skipped test, including ESLint, TypeScript and Biome checks.npm run buildandgit diff --checkpass.Prepared and tested with OpenAI Codex assistance. This covers token whitespace; the separate empty-value issue already has PR #1810.
Summary by CodeRabbit