Skip to content

Commit 97073bd

Browse files
committed
feat(icon): bundle content icons via icon:clientBundleIcons hook
The scan glob can't reach docs navigation icons (remote content under the .data dot-dir + .navigation.yml dotfiles), so they were runtime-fetched and flashed in on client-side navigation. Collect them from content at build time and inject into the client bundle.
1 parent a6337d5 commit 97073bd

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

nuxt.config.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,27 @@ export default defineNuxtConfig({
499499
}
500500
},
501501
hooks: {
502+
// Docs navigation icons come from content: local `content/**/.navigation.yml`
503+
// and remote docs cloned into `.data/content` (at `modules:done`, before this
504+
// hook runs). @nuxt/icon's scanner reaches neither — dotfiles and the `.data`
505+
// dot-dir are skipped under `dot:false` — so those icons would be fetched at
506+
// runtime and flash in on client-side navigation. Collect them here so they
507+
// land in the client bundle. Unknown matches are harmlessly logged as failed.
508+
'icon:clientBundleIcons': async (icons: Set<string>) => {
509+
const { glob } = await import('tinyglobby')
510+
const { readFile } = await import('node:fs/promises')
511+
const files = await glob(
512+
['content/**/*.{md,yml,yaml}', '.data/content/**/*.{md,yml,yaml}'],
513+
{ cwd: resolve('.'), absolute: true, dot: true }
514+
)
515+
const re = /i-(lucide|vscode-icons|simple-icons|heroicons|logos|octicon)-([a-z0-9-]+)/g
516+
await Promise.all(files.map(async (file) => {
517+
const code = await readFile(file, 'utf8').catch(() => '')
518+
for (const match of code.matchAll(re)) {
519+
icons.add(`${match[1]}:${match[2]}`)
520+
}
521+
}))
522+
},
502523
'content:file:beforeParse': async ({ file }) => {
503524
if (file.id.startsWith('docsv5/')) {
504525
file.body = file.body.replaceAll(/\(\/docs\/(?!\d\.x)/g, '(/docs/5.x/')
@@ -553,10 +574,11 @@ export default defineNuxtConfig({
553574
dir: resolve('./app/assets/icons')
554575
}],
555576
clientBundle: {
577+
// Scan app source (incl. `.ts` nav/config) for icons. Content icons
578+
// (incl. remote docs nav) are added via the `icon:clientBundleIcons`
579+
// hook below, since the scanner can't reach `.data` or dotfiles.
556580
scan: {
557-
// Default include adds nothing for `ts`; the explicit dot pattern is
558-
// required because `dot:false` makes `*.yml` skip `.navigation.yml`.
559-
globInclude: ['**/*.{vue,jsx,tsx,md,mdc,mdx,yml,yaml,ts}', '**/.*.{yml,yaml}']
581+
globInclude: ['**/*.{vue,jsx,tsx,md,mdc,mdx,yml,yaml,ts}']
560582
},
561583
includeCustomCollections: true
562584
}

0 commit comments

Comments
 (0)