Skip to content

fix: include Nuxt layers in icon scanner context.#505

Merged
antfu merged 3 commits into
nuxt:mainfrom
oyedejioyewole:fix/layer-aware-scanner
Jul 2, 2026
Merged

fix: include Nuxt layers in icon scanner context.#505
antfu merged 3 commits into
nuxt:mainfrom
oyedejioyewole:fix/layer-aware-scanner

Conversation

@oyedejioyewole

@oyedejioyewole oyedejioyewole commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🔗 Linked issue

This pull request resolves #358

📚 Description

  1. Icon scanning now iterates over nuxt.options._layers instead of only nuxt.options.rootDir
  2. nuxt.config in playground adds ../dummy layer for testing external layer resolution

@pkg-pr-new

pkg-pr-new Bot commented Jul 1, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/nuxt/icon/@nuxt/icon@505

commit: 86ce6bb

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 47cd9f5d-c3fb-4c97-81ca-cfb778bffd33

📥 Commits

Reviewing files that changed from the base of the PR and between 18f1ff2 and 86ce6bb.

📒 Files selected for processing (5)
  • playgrounds/dummy/app/components/DummyComponent.vue
  • playgrounds/dummy/nuxt.config.ts
  • playgrounds/nuxt/nuxt.config.ts
  • src/context.ts
  • src/core/scan.ts
💤 Files with no reviewable changes (2)
  • playgrounds/dummy/nuxt.config.ts
  • playgrounds/dummy/app/components/DummyComponent.vue
✅ Files skipped from review due to trivial changes (1)
  • playgrounds/nuxt/nuxt.config.ts

📝 Walkthrough

Walkthrough

This PR changes icon usage scanning to cover extended Nuxt layers rather than only the root directory. IconUsageScanner.scanFiles now accepts a string or array of directories, glob-searching each and merging results before reading files. NuxtIconModuleContext now passes each layer's cwd from nuxt.options._layers instead of rootDir. A new dummy Nuxt layer (config plus a component using Icon) is added, and the playground config extends it to exercise the change.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Context as NuxtIconModuleContext
  participant Scanner as IconUsageScanner
  participant FS as File System

  Context->>Scanner: scanFiles(layers.map(l => l.cwd), scannedIcons)
  loop for each layer cwd
    Scanner->>FS: glob(cwd)
  end
  Scanner->>Scanner: merge results into files Set
  loop for each file
    Scanner->>FS: read file
    Scanner->>Scanner: extractFromCode(content, set)
  end
  Scanner-->>Context: scannedIcons updated
Loading

Related issues: Addresses reported failure to scan icons referenced in non-component files (e.g., app.config.ts) within extended Nuxt layers, by broadening the scan to include each layer's working directory.

Suggested labels: bug, enhancement, playground

Suggested reviewers: antfu, danielroe

🐰 A dummy layer, plucked and grown,
Icons scanned in every zone,
No more root-bound, narrow view,
Now each layer's path shines through,
Carrots counted, glob by glob — done!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: scanning icon usage across Nuxt layers.
Description check ✅ Passed The description matches the code changes and mentions the layer-scanning fix plus the playground test layer.
Linked Issues check ✅ Passed The changes address #358 by scanning icon usage across Nuxt layer directories, which should cover layered app.config.ts files.
Out of Scope Changes check ✅ Passed The added playground layer and dummy component are test scaffolding for the layer-scanning fix, not unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/scan.ts (1)

53-65: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Parallelize per-layer globbing and dedupe files.

Sequential await per layer serializes I/O unnecessarily, and overlapping layer directories can cause the same file to be globbed (and later read) more than once.

♻️ Suggested refactor
-    const files = []
-
-    for (const layer of nuxt.options._layers) {
-      files.push(...await glob(
-        this.globInclude,
-        {
-          ignore: this.globExclude,
-          cwd: layer.cwd,
-          absolute: true,
-          expandDirectories: false,
-        },
-      ))
-    }
+    const fileResults = await Promise.all(
+      nuxt.options._layers.map(layer => glob(
+        this.globInclude,
+        {
+          ignore: this.globExclude,
+          cwd: layer.cwd,
+          absolute: true,
+          expandDirectories: false,
+        },
+      )),
+    )
+    const files = [...new Set(fileResults.flat())]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/scan.ts` around lines 53 - 65, Parallelize the per-layer globbing in the
scan logic by replacing the sequential await inside the nuxt.options._layers
loop with concurrent glob calls, then merge the results. In the scan flow around
the files collection in the scan routine, dedupe the combined paths before they
are returned or read so overlapping layer roots do not produce duplicates. Use
the existing globInclude, globExclude, and layer.cwd handling in the same scan
path so behavior stays unchanged apart from concurrency and deduplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dummy/app/components/Dummy.vue`:
- Around line 1-3: Fix the vue/multi-word-component-names lint failure by
renaming the single-word component used in Dummy.vue to a multi-word component
name. Update the component/file to a name like DummyIcon and adjust any
references so the template still renders the Icon correctly. If a single-word
name is truly intended, add the appropriate inline lint disable in the component
definition instead of leaving the current name unchanged.

---

Nitpick comments:
In `@src/scan.ts`:
- Around line 53-65: Parallelize the per-layer globbing in the scan logic by
replacing the sequential await inside the nuxt.options._layers loop with
concurrent glob calls, then merge the results. In the scan flow around the files
collection in the scan routine, dedupe the combined paths before they are
returned or read so overlapping layer roots do not produce duplicates. Use the
existing globInclude, globExclude, and layer.cwd handling in the same scan path
so behavior stays unchanged apart from concurrency and deduplication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc9b7134-17fc-4845-995a-940f6cd1d4e1

📥 Commits

Reviewing files that changed from the base of the PR and between fa3c999 and 5919361.

📒 Files selected for processing (4)
  • dummy/app/components/Dummy.vue
  • dummy/nuxt.config.ts
  • playground/nuxt.config.ts
  • src/scan.ts

Comment on lines +1 to +3
<template>
<Icon name="uil:0-plus" />
</template>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Fix lint failure: component name must be multi-word.

CI is failing due to vue/multi-word-component-names. Rename the component (and file) to a multi-word name, e.g. DummyIcon.vue, or add an inline disable if a single-word name is intentional.

🛠️ Suggested fix
-<template>
-  <Icon name="uil:0-plus" />
-</template>
+<!-- eslint-disable-next-line vue/multi-word-component-names -->
+<template>
+  <Icon name="uil:0-plus" />
+</template>

Or rename dummy/app/components/Dummy.vue to dummy/app/components/DummyIcon.vue and update any references.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<template>
<Icon name="uil:0-plus" />
</template>
<!-- eslint-disable-next-line vue/multi-word-component-names -->
<template>
<Icon name="uil:0-plus" />
</template>
🧰 Tools
🪛 ESLint

[error] 1-1: Component name "Dummy" should always be multi-word.

(vue/multi-word-component-names)

🪛 GitHub Actions: ci-main / 0_ci (ubuntu-latest, lts_).txt

[error] 1-1: ESLint (vue/multi-word-component-names): Component name "Dummy" should always be multi-word

🪛 GitHub Actions: ci-main / ci (ubuntu-latest, lts_)

[error] 1-1: ESLint (vue/multi-word-component-names): Component name "Dummy" should always be multi-word


[error] 1-1: Command failed: "npm run lint" (eslint .) reported 1 error

🪛 GitHub Check: ci (ubuntu-latest, lts/*)

[failure] 1-1:
Component name "Dummy" should always be multi-word

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dummy/app/components/Dummy.vue` around lines 1 - 3, Fix the
vue/multi-word-component-names lint failure by renaming the single-word
component used in Dummy.vue to a multi-word component name. Update the
component/file to a name like DummyIcon and adjust any references so the
template still renders the Icon correctly. If a single-word name is truly
intended, add the appropriate inline lint disable in the component definition
instead of leaving the current name unchanged.

Sources: Linters/SAST tools, Pipeline failures

@oyedejioyewole

oyedejioyewole commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

I've provided the link to a reproduction of the problem this PR fixes.

https://stackblitz.com/edit/nuxt-starter-8zyfrhuz

Summary
2 components use <Icon />, but icon.clientBundle.scan prioritises source files within the project root and ignores those in layers outside the project root folder.

@antfu
antfu merged commit 1345dc9 into nuxt:main Jul 2, 2026
5 checks passed
@oyedejioyewole
oyedejioyewole deleted the fix/layer-aware-scanner branch July 2, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scan doesn't work when extending a Layer

3 participants