import { Element } from "@opticss/element-analysis" ; import { TemplateAnalysis , TemplateTypes } from "@opticss/template-api" ; import { ChangeSelector , RemoveRule } from "../Actions" ; import { ParsedCssFile } from "../CssFile" ; import { Initializers } from "../initializers" ; import { ElementMatcher , matches } from "../Match" ; import { OptiCSSOptions } from "../OpticssOptions" ; import { OptimizationPass } from "../OptimizationPass" ; import { walkRules } from "../util/cssIntrospection" ; import { SingleFileOptimization } from "./Optimization" ; /**
 * Removed all rules in a single stylesheet that will never match any Selectables
 * discovered during analysis.
 */ export class RemoveUnusedStyles implements SingleFileOptimization { name = "removeUnusedStyles" ; initializers : Array < keyof Initializers > = [ ] ; param options constructor ( _options ) { } param analyses param file optimizeSingleFile ( pass , analyses , file ) { let elements = analyses . reduce ( ( elements , analysis ) => { elements . push ( ... analysis . elements ) ; return elements ; } , new Array < Element > ( ) ) ; walkRules ( file . content . root ! , ( node ) => { let parsedSelectors = pass . cache . getParsedSelectors ( node ) ; let reason = undefined ; let found = parsedSelectors . filter ( ( value ) => { return value . eachCompoundSelector ( ( selector ) => { let found = elements . find ( ( element ) => matches ( ElementMatcher . instance . matchSelectorComponent ( element , selector ) ) ) ; if ( ! found || selector === value . key ) { if ( ! found ) { reason = `no element found that matches ${ selector . toString ( true ) }` ; } return ! ! found ; } else { return ; } } ) ; } ) ; if ( found . length === 0 ) { pass . actions . perform ( new RemoveRule ( node , "removeUnusedStyles" , reason ! , pass . cache ) ) ; } else { if ( found . length < parsedSelectors . length ) { pass . actions . perform ( new ChangeSelector ( node , found . join ( ", " ) , "removeUnusedStyles" , reason ! , pass . cache ) ) ; } } } ) ; } }