Skip to content

feat(style): support CSS attribute selector operators in includesAttrSelector#2201

Open
roli-lpci wants to merge 1 commit into
svg:mainfrom
roli-lpci:fix/attr-selector-operators
Open

feat(style): support CSS attribute selector operators in includesAttrSelector#2201
roli-lpci wants to merge 1 commit into
svg:mainfrom
roli-lpci:fix/attr-selector-operators

Conversation

@roli-lpci
Copy link
Copy Markdown

Summary

Resolves #2145.

includesAttrSelector previously only checked whether an attribute name was referenced in a CSS selector, ignoring the selector's operator and value. This caused SVGO to conservatively keep attributes even when the CSS selector would not actually match the element's attribute value.

Note: I noticed @viralcodex expressed interest in this issue. If they're still working on a solution, happy to close this PR.

Changes

  • Added matchesAttrAction() helper that evaluates all CSS attribute selector operators (=, ^=, $=, *=, ~=, |=, exists) against an element's actual attribute value
  • Added attrValue parameter to includesAttrSelector() — when provided, the selector's operator is evaluated against the element's real value instead of assuming a match
  • Updated call sites in removeUnknownsAndDefaults and inlineStyles plugins to pass the element's attribute value
  • Backward-compatible: when attrValue is not provided, the function retains its existing conservative behavior

Example (from the issue)

<!-- CSS: [preserveAspectRatio^="y"] { fill: yellow; } -->
<!-- Element: preserveAspectRatio="xMidYMid meet" -->
<!-- ^= "y" does NOT match "xMidYMid meet", so the default attribute is now safely removed -->

Test Coverage

  • 13 new unit tests for includesAttrSelector covering all 7 operator types, edge cases (empty values, comma-separated selectors), backward compatibility, and the exact issue example
  • 2 new plugin fixture tests for removeUnknownsAndDefaults (operator non-match allows removal; operator match keeps attribute)
  • All 496 existing tests continue to pass

…Selector

Previously, `includesAttrSelector` only checked if an attribute name was
referenced in a CSS selector, ignoring the selector's operator and value.
This caused SVGO to conservatively keep attributes even when the CSS
selector would not actually match the element's attribute value.

Add a new `attrValue` parameter that, when provided, evaluates the CSS
attribute selector operator (`=`, `^=`, `$=`, `*=`, `~=`, `|=`, exists)
against the element's actual attribute value. This allows plugins to
safely remove attributes when the selector would not match.

Updated call sites in `removeUnknownsAndDefaults` and `inlineStyles`
plugins to pass the element's attribute value for smarter matching.

Closes svg#2145

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

includesAttrSelector: support different equality checks in attribute selectors too

1 participant