(
filepath: string,
classnameTransformer: StringTransformer,
)
| 271 | * ``` |
| 272 | */ |
| 273 | export async function filePathToClassnameDict( |
| 274 | filepath: string, |
| 275 | classnameTransformer: StringTransformer, |
| 276 | ): Promise<ClassnameDict> { |
| 277 | const content = fs.readFileSync(filepath, {encoding: 'utf8'}); |
| 278 | const EOL = getEOL(content); |
| 279 | const {ext} = path.parse(filepath); |
| 280 | |
| 281 | /** |
| 282 | * only load the parses once they are needed |
| 283 | */ |
| 284 | const parsers: Record<string, undefined | LazyLoadPostcssParser> = { |
| 285 | '.less': () => require('postcss-less'), |
| 286 | '.scss': () => require('postcss-scss'), |
| 287 | '.sass': () => require('postcss-sass'), |
| 288 | }; |
| 289 | |
| 290 | const getParser = parsers[ext]; |
| 291 | |
| 292 | /** |
| 293 | * Postcss does not expose this option though typescript types |
| 294 | * This is why we are doing this naughty thingy |
| 295 | */ |
| 296 | const hiddenOption = {hideNothingWarning: true} as Record<never, never>; |
| 297 | const postcssOptions: ProcessOptions = { |
| 298 | map: false, |
| 299 | from: filepath, |
| 300 | ...hiddenOption, |
| 301 | ...(typeof getParser === 'function' ? {parser: getParser()} : {}), |
| 302 | }; |
| 303 | |
| 304 | const ast = await PostcssInst.process(content, postcssOptions); |
| 305 | // TODO: root.walkRules and for each rule gather info about parents |
| 306 | const dict: ClassnameDict = {}; |
| 307 | |
| 308 | const visitedNodes = new Map<Node, {selectors: string[]}>([]); |
| 309 | const stack = [...ast.root.nodes]; |
| 310 | let commentStack: Comment[] = []; |
| 311 | |
| 312 | while (stack.length) { |
| 313 | const node = stack.shift(); |
| 314 | if (node === undefined) continue; |
| 315 | if (node.type === 'comment') { |
| 316 | commentStack.push(node); |
| 317 | continue; |
| 318 | } |
| 319 | if (node.type === 'atrule') { |
| 320 | if ( |
| 321 | AT_RULES_WITH_SELECTORS.has(node.name.toLowerCase()) && |
| 322 | node.nodes |
| 323 | ) { |
| 324 | stack.unshift(...node.nodes); |
| 325 | } |
| 326 | commentStack = []; |
| 327 | continue; |
| 328 | } |
| 329 | if (node.type !== 'rule') continue; |
| 330 |
no test coverage detected