fix(attributes): `[attr~=""]` with an empty value matches nothing

UR
4mo ago
+12-1

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.