Skip to content

Commit aa4bc3e

Browse files
authored
feat: add excludeNames option (#788)
1 parent 7d89295 commit aa4bc3e

10 files changed

+58
-53
lines changed

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ Components({
358358
extensions: ['vue'],
359359

360360
// Glob patterns to match file names to be detected as components.
361-
// When specified, the `dirs` and `extensions` options will be ignored.
361+
// When specified, the `dirs`, `extensions`, and `directoryAsNamespace` options will be ignored.
362362
// If you want to exclude components being registered, use negative globs with leading `!`.
363363
globs: ['src/components/*.{vue}'],
364364

@@ -398,10 +398,14 @@ Components({
398398
allowOverrides: false,
399399

400400
// Filters for transforming targets (components to insert the auto import)
401-
// Note these are NOT about including/excluding components registered - use `globs` for that
401+
// Note these are NOT about including/excluding components registered - use `globs` or `excludeNames` for that
402402
include: [/\.vue$/, /\.vue\?vue/],
403403
exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/],
404404

405+
// Filters for component names that will not be imported
406+
// Use for globally imported async components or other conflicts that the plugin cannot detect
407+
excludeNames: [/^Async.+/],
408+
405409
// Vue version of project. It will detect automatically if not specified.
406410
// Acceptable value: 2 | 2.7 | 3
407411
version: 2.7,

src/core/context.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { UpdatePayload, ViteDevServer } from 'vite'
66
import { slash, throttle, toArray } from '@antfu/utils'
77
import type { ComponentInfo, Options, ResolvedOptions, Transformer } from '../types'
88
import { DIRECTIVE_IMPORT_PREFIX } from './constants'
9-
import { getNameFromFilePath, matchGlobs, normalizeComponentInfo, parseId, pascalCase, resolveAlias } from './utils'
9+
import { getNameFromFilePath, isExclude, matchGlobs, normalizeComponentInfo, parseId, pascalCase, resolveAlias } from './utils'
1010
import { resolveOptions } from './options'
1111
import { searchComponents } from './fs/glob'
1212
import { writeDeclaration } from './declaration'
@@ -203,6 +203,10 @@ export class Context {
203203
.from(this._componentPaths)
204204
.forEach((path) => {
205205
const name = pascalCase(getNameFromFilePath(path, this.options))
206+
if (isExclude(name, this.options.excludeNames)) {
207+
debug.components('exclude', name)
208+
return
209+
}
206210
if (this._componentNameMap[name] && !this.options.allowOverrides) {
207211
console.warn(`[unplugin-vue-components] component "${name}"(${path}) has naming conflicts with other components, ignored.`)
208212
return

src/core/options.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getPackageInfoSync, isPackageExists } from 'local-pkg'
44
import type { ComponentResolver, ComponentResolverObject, Options, ResolvedOptions } from '../types'
55
import { detectTypeImports } from './type-imports/detect'
66

7-
export const defaultOptions: Omit<Required<Options>, 'include' | 'exclude' | 'transformer' | 'globs' | 'directives' | 'types' | 'version'> = {
7+
export const defaultOptions: Omit<Required<Options>, 'include' | 'exclude' | 'excludeNames' | 'transformer' | 'globs' | 'directives' | 'types' | 'version'> = {
88
dirs: 'src/components',
99
extensions: 'vue',
1010
deep: true,

src/core/resolvers/_utils.ts

-18
This file was deleted.

src/core/resolvers/arco.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import Debug from 'debug'
22
import type { ComponentInfo, ComponentResolver } from '../../types'
3-
import { kebabCase, pascalCase } from '../utils'
4-
import { isExclude } from './_utils'
3+
import { isExclude, kebabCase, pascalCase } from '../utils'
54

65
const debug = Debug('unplugin-vue-components:resolvers:arco')
76

src/core/resolvers/layui-vue.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { FilterPattern } from '@rollup/pluginutils'
2+
import { isExclude } from '../utils'
13
import type { ComponentInfo, ComponentResolver, SideEffectsInfo } from '../../types'
24

35
const matchComponents = [
@@ -95,7 +97,7 @@ export interface LayuiVueResolverOptions {
9597
* exclude components that do not require automatic import
9698
*
9799
*/
98-
exclude?: Array<string | RegExp>
100+
exclude?: FilterPattern
99101
}
100102

101103
const layuiRE = /^Lay[A-Z]/
@@ -132,7 +134,7 @@ function getSideEffects(importName: string, options: LayuiVueResolverOptions): S
132134
function resolveComponent(importName: string, options: LayuiVueResolverOptions): ComponentInfo | undefined {
133135
let name: string | undefined
134136

135-
if (options.exclude && isExclude(importName, options.exclude))
137+
if (isExclude(importName, options.exclude))
136138
return undefined
137139

138140
if (options.resolveIcons && importName.match(iconsRE)) {
@@ -152,14 +154,6 @@ function resolveComponent(importName: string, options: LayuiVueResolverOptions):
152154
: undefined
153155
}
154156

155-
function isExclude(name: string, exclude: Array<string | RegExp>): boolean {
156-
for (const item of exclude) {
157-
if (name === item || name.match(item))
158-
return true
159-
}
160-
return false
161-
}
162-
163157
/**
164158
* Resolver for layui-vue
165159
*

src/core/resolvers/tdesign.ts

+4-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import type { FilterPattern } from '@rollup/pluginutils'
12
import type { ComponentResolver } from '../../types'
3+
import { isExclude } from '../utils'
24

35
export interface TDesignResolverOptions {
46
/**
@@ -23,7 +25,7 @@ export interface TDesignResolverOptions {
2325
* exclude component name, if match do not resolve the name
2426
*
2527
*/
26-
exclude?: string | RegExp | (string | RegExp)[]
28+
exclude?: FilterPattern
2729
}
2830

2931
export function TDesignResolver(options: TDesignResolverOptions = {}): ComponentResolver {
@@ -34,7 +36,7 @@ export function TDesignResolver(options: TDesignResolverOptions = {}): Component
3436
const { library = 'vue', exclude } = options
3537
const importFrom = options.esm ? '/esm' : ''
3638

37-
if (options.exclude && isExclude(name, exclude))
39+
if (isExclude(name, exclude))
3840
return
3941

4042
if (options.resolveIcons && name.match(/[a-z]Icon$/)) {
@@ -55,19 +57,3 @@ export function TDesignResolver(options: TDesignResolverOptions = {}): Component
5557
},
5658
}
5759
}
58-
59-
function isExclude(name: string, exclude: string | RegExp | (string | RegExp)[] | undefined): boolean {
60-
if (typeof exclude === 'string')
61-
return name === exclude
62-
63-
if (exclude instanceof RegExp)
64-
return !!name.match(exclude)
65-
66-
if (Array.isArray(exclude)) {
67-
for (const item of exclude) {
68-
if (name === item || name.match(item))
69-
return true
70-
}
71-
}
72-
return false
73-
}

src/core/utils.ts

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
getPackageInfo,
77
isPackageExists,
88
} from 'local-pkg'
9+
import type { FilterPattern } from '@rollup/pluginutils'
910
import type { ComponentInfo, ImportInfo, ImportInfoLegacy, Options, ResolvedOptions } from '../types'
1011
import type { Context } from './context'
1112
import { DISABLE_COMMENT } from './constants'
@@ -222,3 +223,22 @@ export function shouldTransform(code: string) {
222223
return false
223224
return true
224225
}
226+
227+
export function isExclude(name: string, exclude?: FilterPattern): boolean {
228+
if (!exclude)
229+
return false
230+
231+
if (typeof exclude === 'string')
232+
return name === exclude
233+
234+
if (exclude instanceof RegExp)
235+
return !!name.match(exclude)
236+
237+
if (Array.isArray(exclude)) {
238+
for (const item of exclude) {
239+
if (name === item || name.match(item))
240+
return true
241+
}
242+
}
243+
return false
244+
}

src/types.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ export interface Options {
7171
*/
7272
exclude?: FilterPattern
7373

74+
/**
75+
* RegExp or string to match component names that will NOT be imported
76+
*/
77+
excludeNames?: FilterPattern
78+
7479
/**
7580
* Relative paths to the directory to search for components.
7681
* @default 'src/components'
@@ -86,7 +91,7 @@ export interface Options {
8691
/**
8792
* Glob patterns to match file names to be detected as components.
8893
*
89-
* When specified, the `dirs` and `extensions` options will be ignored.
94+
* When specified, the `dirs`, `extensions`, and `directoryAsNamespace` options will be ignored.
9095
*/
9196
globs?: string | string[]
9297

test/search.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,15 @@ describe('search', () => {
6969

7070
expect(cleanup(ctx.componentNameMap).map(i => i.as)).not.toEqual(expect.arrayContaining(['Book']))
7171
})
72+
73+
it('should excludeNames', () => {
74+
const ctx = new Context({
75+
dirs: ['src/components'],
76+
excludeNames: ['Book'],
77+
})
78+
ctx.setRoot(root)
79+
ctx.searchGlob()
80+
81+
expect(cleanup(ctx.componentNameMap).map(i => i.as)).not.toEqual(expect.arrayContaining(['Book']))
82+
})
7283
})

0 commit comments

Comments
 (0)