1- // src /scan-icons.js
1+ // scripts /scan-icons.js
22import fs from "fs"
33import path from "path"
44import * as babel from "@babel/core"
55import traverseImport from "@babel/traverse"
66import * as t from "@babel/types"
7+ import { IMPORT_NAME } from "./config.js"
8+
79const traverse = traverseImport . default
8- const iconNames = new Set ( )
10+ const ICONS = new Set ( )
11+ const ROOT = path . join ( process . cwd ( ) , "app" ) // or "src"
912
10- function walk ( dir ) {
11- for ( const file of fs . readdirSync ( dir ) ) {
12- const full = path . join ( dir , file )
13+ // walk all TSX/JSX files
14+ function collect ( dir ) {
15+ for ( const f of fs . readdirSync ( dir ) ) {
16+ const full = path . join ( dir , f )
1317 if ( fs . statSync ( full ) . isDirectory ( ) ) {
14- walk ( full )
15- } else if ( full . endsWith ( ".tsx" ) ) {
16- const code = fs . readFileSync ( full , "utf8" )
17- const ast = babel . parseSync ( code , {
18+ collect ( full )
19+ } else if ( / \. [ j t ] s x $ / . test ( full ) ) {
20+ const src = fs . readFileSync ( full , "utf8" )
21+ const ast = babel . parseSync ( src , {
1822 filename : full ,
1923 presets : [
2024 [ "@babel/preset-typescript" , { isTSX : true , allExtensions : true } ] ,
2125 [ "@babel/preset-react" , { runtime : "automatic" } ] ,
2226 ] ,
2327 sourceType : "module" ,
2428 } )
25- if ( ! ast ) continue
26-
2729 traverse ( ast , {
28- JSXElement ( path ) {
29- const opening = path . node . openingElement
30- const name = opening . name
31- // here we find all the elements that are named "Icon" or return
32- if ( ! t . isJSXIdentifier ( name ) || name . name !== "Icon" ) return
33-
34- for ( const attr of opening . attributes ) {
35- // here we find all the attributes that are named "name" and are a string literal
36- if ( t . isJSXAttribute ( attr ) && t . isJSXIdentifier ( attr . name , { name : "name" } ) ) {
37- iconNames . add ( attr . value . value )
30+ ImportDeclaration ( path ) {
31+ const from = path . node . source . value
32+ // adjust this to match your icon lib path
33+ if ( from === IMPORT_NAME ) {
34+ for ( const spec of path . node . specifiers ) {
35+ if ( t . isImportSpecifier ( spec ) ) {
36+ ICONS . add ( spec . imported . name )
37+ }
3838 }
3939 }
4040 } ,
@@ -43,11 +43,9 @@ function walk(dir) {
4343 }
4444}
4545
46- const rootDir = "app" // or "src" or whatever your root is
47- const currentDir = process . cwd ( )
48- walk ( path . join ( currentDir , rootDir ) )
46+ collect ( ROOT )
4947
50- const output = [ ... iconNames ] . sort ( )
51- console . log ( "output: " , output )
52- fs . writeFileSync ( "scripts/used-icons.js" , `export const ICONS = ${ JSON . stringify ( output , null , 2 ) } ` )
53- console . log ( `✅ Found ${ output . length } used icons` )
48+ // write the result for build-sprite to consume
49+ const list = [ ... ICONS ] . sort ( )
50+ fs . writeFileSync ( "scripts/used-icons.js" , `export const ICONS = ${ JSON . stringify ( list , null , 2 ) } ; ` )
51+ console . log ( `✅ Found ${ list . length } icons:` , list )
0 commit comments