@@ -19,6 +19,10 @@ function parseFileName (filePath) {
1919 return path . resolve ( process . cwd ( ) , filePath )
2020}
2121
22+ function parseTokenList ( tokenString ) {
23+ return tokenString . split ( ',' ) . map ( token => token . trim ( ) . toLowerCase ( ) )
24+ }
25+
2226const STATUS_CODE = {
2327 ERROR : 111 ,
2428 OK : 0
@@ -33,6 +37,7 @@ commander
3337 . option ( '--verbose' , 'verbose/debugging output' )
3438 . option ( '--ignore-source-map' , 'disable loading the sourcemap if one is found' )
3539 . option ( '--cover-declarations' , 'try to cover CSS declarations as well as selectors (best-effort, difficult with sourcemaps)' )
40+ . option ( '--ignore-declarations [move-to,content]' , 'A comma-separated list of declarations to ignore' , parseTokenList )
3641 . parse ( process . argv )
3742
3843// Validate args
@@ -69,11 +74,24 @@ try {
6974}
7075
7176const cssRules = [ ]
77+ const cssDeclarations = { } // so it is serializable to the browser
78+
7279cssTree . walkRules ( ast , ( rule ) => {
7380 if ( rule . type === 'Atrule' ) {
7481 // ignore
7582 } else if ( rule . type === 'Rule' ) {
7683 const converted = rule . prelude . children . map ( ( selector ) => {
84+ rule . block . children . each ( declaration => {
85+ if ( commander . ignoreDeclarations . indexOf ( declaration . property . toLowerCase ( ) ) >= 0 ) {
86+ return // skip because it is ignored
87+ }
88+ // Append to a list of locations
89+ const key = cssTree . translate ( declaration )
90+ let locs = cssDeclarations [ key ]
91+ locs = locs || [ ]
92+ locs . push ( declaration . loc )
93+ cssDeclarations [ key ] = locs
94+ } )
7795 return cssTree . translate ( selector )
7896 } )
7997 cssRules . push ( converted )
@@ -152,7 +170,7 @@ async function runCoverage () {
152170 } )
153171
154172 log . debug ( `Calculating coverage` )
155- const coverageOutput = await page . evaluate ( cssRules => {
173+ const { matchedSelectors : coverageOutput , supportedDeclarations } = await page . evaluate ( ( cssRules , cssDeclarations ) => {
156174 // This is the meat of the code. It runs inside the browser
157175 console . log ( `Starting evaluation` )
158176 const rules = cssRules
@@ -165,7 +183,7 @@ async function runCoverage () {
165183 window . Sizzle . selectors . pseudos [ pseudo ] = function ( elem ) { return elem }
166184 } )
167185
168- const ret = [ ]
186+ const matchedSelectors = [ ]
169187 rules . forEach ( function ( selectors ) {
170188 console . log ( `Checking selector: "${ JSON . stringify ( selectors ) } "` )
171189
@@ -194,20 +212,30 @@ async function runCoverage () {
194212
195213 console . log ( `Found ${ count } matche(s)` )
196214
197- ret . push ( [ count , selectors ] )
215+ matchedSelectors . push ( [ count , selectors ] )
198216 } )
199217
200218 console . log ( `Finished checking selectors` )
201- return ret
202- } , cssRules )
219+
220+ console . log ( `Checking if declarations are understandable by the browser` )
221+ const supportedDeclarations = [ ]
222+ for ( const decl of cssDeclarations ) {
223+ if ( window . CSS . supports ( decl ) ) {
224+ supportedDeclarations . push ( decl )
225+ } else {
226+ console . warn ( `Unsupported declaration ${ decl } ` )
227+ }
228+ }
229+ return { matchedSelectors, supportedDeclarations }
230+ } , cssRules , Object . keys ( cssDeclarations ) )
203231
204232 log . debug ( 'Closing browser' )
205233 await browser . close ( )
206234
207235 log . debug ( 'Finished evaluating selectors' )
208236 log . info ( 'Generating LCOV string...' )
209237
210- const lcovStr = await generateLcovStr ( coverageOutput )
238+ const lcovStr = await generateLcovStr ( coverageOutput , supportedDeclarations )
211239 if ( commander . lcov ) {
212240 fs . writeFileSync ( commander . lcov , lcovStr )
213241 } else {
0 commit comments