@@ -127,17 +127,58 @@ async function parseCustomCollection(
127127
128128export async function discoverInstalledCollections ( nuxt : Nuxt ) : Promise < ServerBundleOptions [ 'collections' ] > {
129129 const paths = getResolvePaths ( nuxt )
130- const fullCollectionInstalled = hasFullCollection ( nuxt )
131- const collections = fullCollectionInstalled
132- ? collectionNames
133- : collectionNames . filter ( collection => isPackageExists ( '@iconify-json/' + collection , { paths } ) )
134- if ( fullCollectionInstalled )
135- logger . success ( `Nuxt Icon discovered local-installed ${ collections . length } collections (@iconify/json)` )
136- else if ( collections . length )
137- logger . success ( `Nuxt Icon discovered local-installed ${ collections . length } collections:` , collections . join ( ', ' ) )
138130
139- if ( fullCollectionInstalled )
131+ if ( hasFullCollection ( nuxt ) ) {
132+ logger . success ( `Nuxt Icon discovered local-installed ${ collectionNames . length } collections (@iconify/json)` )
140133 logger . warn ( 'Currently all iconify collections are included in the bundle, which might be inefficient, consider explicit name the collections you use in the `icon.serverBundle.collections` option' )
134+ return collectionNames
135+ }
136+
137+ // Find which `@iconify-json/*` packages are installed;
138+ // Special for Yarn PnP, which does not have a `node_modules` folder.
139+ const found = new Set < string > ( )
140+ if ( process . versions . pnp ) {
141+ for ( const collection of collectionNames ) {
142+ if ( isPackageExists ( '@iconify-json/' + collection , { paths } ) )
143+ found . add ( collection )
144+ }
145+ }
146+ else {
147+ await Promise . all ( iconifyScopeDirs ( paths ) . map ( async ( scope ) => {
148+ const entries = await fs . readdir ( scope ) . catch ( ( ) => [ ] as string [ ] )
149+ await Promise . all ( entries . map ( async ( name ) => {
150+ if ( name . startsWith ( '.' ) )
151+ return
152+ // A real Iconify collection package ships an `icons.json`.
153+ const hasIconsJson = await fs . access ( join ( scope , name , 'icons.json' ) ) . then ( ( ) => true , ( ) => false )
154+ if ( hasIconsJson )
155+ found . add ( name )
156+ } ) )
157+ } ) )
158+ }
159+
160+ const collections = collectionNames . filter ( collection => found . has ( collection ) )
161+ if ( collections . length )
162+ logger . success ( `Nuxt Icon discovered local-installed ${ collections . length } collections:` , collections . join ( ', ' ) )
141163
142164 return collections
143165}
166+
167+ /**
168+ * Returns the `@iconify-json` scope directory inside every `node_modules`,
169+ * deduped, walking up the tree like the Node resolver.
170+ */
171+ function iconifyScopeDirs ( paths : string [ ] ) : string [ ] {
172+ const dirs = new Set < string > ( )
173+ for ( const base of paths ) {
174+ let dir = base
175+ while ( true ) {
176+ dirs . add ( join ( dir , 'node_modules' , '@iconify-json' ) )
177+ const parent = join ( dir , '..' )
178+ if ( parent === dir )
179+ break
180+ dir = parent
181+ }
182+ }
183+ return [ ...dirs ]
184+ }
0 commit comments