Removes the style rules that no page of a site can match, keeping everything else byte for byte.
It borrows PurgeCSS's content rule: the default extractor "considers every word of a file as a
selector" (purgecss.com/extractors, web page read 2026-10-19), so a word that appears anywhere
keeps the rules that name it. It differs on purpose. PurgeCSS needs a safelist for what the
content never spells out, and this function has none: a rule stays whenever the scanner cannot
prove it unmatched, and tokens come from every page and script of the site, not from one build.
A style rule is removed when every selector of its list needs a class, id or type token that
tokens lacks. One selector that may match keeps the rule.
Type names compare in lowercase, and a class or id present in any ASCII case keeps a rule,
since a quirks-mode page matches them that way. html, body, *, &, attribute selectors, escaped and
non-ASCII identifiers and namespaced selectors never count against a rule.
Pseudo-classes and pseudo-elements are ignored with their arguments, so .a:hover needs a,
and anything inside :is, :where, :not and :has is never examined.
@media, @supports, @layer, @container and @scope are walked into and their shells
stay, even when emptied, because an empty @layer still orders layers. Every other at-rule
(@font-face, @keyframes, @import, @property, @page, @charset, @namespace,
@counter-style) is kept whole.
Rules are only removed, never reordered or rewritten, so the cascade of what remains is
unchanged. Whitespace before a removed rule goes with it.
When the scanner meets an unterminated comment, string or block, an unmatched closing bracket
or a stray declaration, it keeps the rest of the file as it was.
missing holds one absent token for each selector of each removed rule. A page whose tokens
contain none of them cannot match any removed rule.
Removes the style rules that no page of a site can match, keeping everything else byte for byte.
It borrows PurgeCSS's content rule: the default extractor "considers every word of a file as a selector" (purgecss.com/extractors, web page read 2026-10-19), so a word that appears anywhere keeps the rules that name it. It differs on purpose. PurgeCSS needs a
safelistfor what the content never spells out, and this function has none: a rule stays whenever the scanner cannot prove it unmatched, and tokens come from every page and script of the site, not from one build.tokenslacks. One selector that may match keeps the rule.html,body,*,&, attribute selectors, escaped and non-ASCII identifiers and namespaced selectors never count against a rule..a:hoverneedsa, and anything inside:is,:where,:notand:hasis never examined.@media,@supports,@layer,@containerand@scopeare walked into and their shells stay, even when emptied, because an empty@layerstill orders layers. Every other at-rule (@font-face,@keyframes,@import,@property,@page,@charset,@namespace,@counter-style) is kept whole.missingholds one absent token for each selector of each removed rule. A page whose tokens contain none of them cannot match any removed rule.