fix(attributes): `[attr~=""]` with an empty value matches nothing
Problem
The ~= (whitespace-separated "one of") attribute handler only short-circuits to boolbase.falseFunc when the value contains whitespace. An empty value falls through to the regex (?:^|\s)(?:$|\s), which matches an empty attribute — so [class~=""] wrongly selects elements with class="".
import * as CSSselect from "css-select";
import { parseDocument } from "htmlparser2";
const dom = parseDocument(`<i class=""></i>`);
CSSselect.selectAll('[class~=""]', dom); // ← returns the <i>, should be []
Expected behaviour
Per Selectors §6.3.2, an empty (or whitespace-containing) ~= value can never be a single token, so it represents nothing. Browsers agree — document.querySelectorAll('[class~=""]') returns nothing in Chrome.
This also makes ~= consistent with ^= / $= / *= (start / end / any), which already short-circuit empty values to falseFunc.
Change
Add value === "" to the existing short-circuit in the element (~=) handler, plus a test mirroring the existing empty-value tests for $= / *=.
🤖 Generated with Claude Code
Summary by CodeRabbit
-
Bug Fixes
- Fixed attribute selector matching to properly handle empty string values as non-matching cases.
-
Tests
- Added test coverage for attribute selectors with empty string values.