1
+ // @ts -expect-error No types for sub-export `parse` and `walk`
1
2
import parse from 'css-tree/parser'
3
+ // @ts -expect-error No types for sub-export `parse` and `walk`
2
4
import walk from 'css-tree/walker'
5
+ // @ts -expect-error No types for sub-export `core`
3
6
import { calculate } from '@bramus/specificity/core'
4
7
import { isSupportsBrowserhack , isMediaBrowserhack } from './atrules/atrules.js'
5
8
import { getCombinators , getComplexity , isAccessibility , isPrefixed } from './selectors/utils.js'
@@ -46,6 +49,12 @@ let border_radius_properties = new KeywordSet([
46
49
'border-end-start-radius' ,
47
50
] )
48
51
52
+ /**
53
+ * Safe ratio calculation to avoid division by zero errors
54
+ * @param {number } part
55
+ * @param {number } total
56
+ * @returns {number }
57
+ */
49
58
function ratio ( part , total ) {
50
59
if ( total === 0 ) return 0
51
60
return part / total
@@ -79,7 +88,9 @@ export function analyze(css, options = {}) {
79
88
return stringifyNodePlain ( node ) . trim ( )
80
89
}
81
90
91
+ /** @param {import('css-tree').CssNode } node */
82
92
function stringifyNodePlain ( node ) {
93
+ /** @type {import('css-tree').CssNode as NonNullable<import('css-tree').CssNode['loc']> } */
83
94
let loc = node . loc
84
95
return css . substring ( loc . start . offset , loc . end . offset )
85
96
}
@@ -192,7 +203,7 @@ export function analyze(css, options = {}) {
192
203
let valueKeywords = new Collection ( useLocations )
193
204
let borderRadiuses = new ContextCollection ( useLocations )
194
205
195
- walk ( ast , function ( node ) {
206
+ walk ( ast , function ( /** @type { import('css-tree').CssNode } */ node ) {
196
207
switch ( node . type ) {
197
208
case Atrule : {
198
209
totalAtRules ++
@@ -203,10 +214,10 @@ export function analyze(css, options = {}) {
203
214
let descriptors = { }
204
215
205
216
if ( useLocations ) {
206
- fontfaces_with_loc . p ( node . loc . start . offset , node . loc )
217
+ fontfaces_with_loc . p ( node . loc ? .start . offset , node . loc )
207
218
}
208
219
209
- node . block . children . forEach ( descriptor => {
220
+ node . block ? .children . forEach ( descriptor => {
210
221
// Ignore 'Raw' nodes in case of CSS syntax errors
211
222
if ( descriptor . type === Declaration ) {
212
223
descriptors [ descriptor . property ] = stringifyNode ( descriptor . value )
@@ -228,15 +239,15 @@ export function analyze(css, options = {}) {
228
239
229
240
if ( atRuleName === 'media' ) {
230
241
medias . p ( preludeStr , loc )
231
- if ( isMediaBrowserhack ( prelude ) ) {
242
+ if ( prelude . type === 'AtrulePrelude' && isMediaBrowserhack ( prelude ) ) {
232
243
mediaBrowserhacks . p ( preludeStr , loc )
233
244
complexity ++
234
245
}
235
246
} else if ( atRuleName === 'supports' ) {
236
247
supports . p ( preludeStr , loc )
237
248
// TODO: analyze vendor prefixes in @supports
238
249
// TODO: analyze complexity of @supports 'declaration'
239
- if ( isSupportsBrowserhack ( prelude ) ) {
250
+ if ( prelude . type === 'AtrulePrelude' && isSupportsBrowserhack ( prelude ) ) {
240
251
supportsBrowserhacks . p ( preludeStr , loc )
241
252
complexity ++
242
253
}
@@ -276,7 +287,7 @@ export function analyze(css, options = {}) {
276
287
case Rule : {
277
288
let prelude = node . prelude
278
289
let block = node . block
279
- let preludeChildren = prelude . children
290
+ let preludeChildren = prelude . type === 'SelectorList' ? prelude . children : new Set ( )
280
291
let blockChildren = block . children
281
292
let numSelectors = preludeChildren ? preludeChildren . size : 0
282
293
let numDeclarations = blockChildren ? blockChildren . size : 0
@@ -355,7 +366,7 @@ export function analyze(css, options = {}) {
355
366
ids . p ( selector , node . loc )
356
367
}
357
368
358
- getCombinators ( node , function onCombinator ( combinator ) {
369
+ getCombinators ( node , function onCombinator ( /** @type { import('css-tree').Combinator } */ combinator ) {
359
370
combinators . p ( combinator . name , combinator . loc )
360
371
} )
361
372
@@ -546,7 +557,7 @@ export function analyze(css, options = {}) {
546
557
// no break here: potentially contains colors
547
558
}
548
559
549
- walk ( node , function ( valueNode ) {
560
+ walk ( node , function ( /** @type { import('css-tree').CssNode } */ valueNode ) {
550
561
let nodeName = valueNode . name
551
562
552
563
switch ( valueNode . type ) {
0 commit comments