Skip to content

Commit

Permalink
feat: add excludeNames option (#788)
Browse files Browse the repository at this point in the history
  • Loading branch information
KaelWD authored Aug 12, 2024
1 parent 7d89295 commit aa4bc3e
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 53 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ Components({
extensions: ['vue'],

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

Expand Down Expand Up @@ -398,10 +398,14 @@ Components({
allowOverrides: false,

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

// Filters for component names that will not be imported
// Use for globally imported async components or other conflicts that the plugin cannot detect
excludeNames: [/^Async.+/],

// Vue version of project. It will detect automatically if not specified.
// Acceptable value: 2 | 2.7 | 3
version: 2.7,
Expand Down
6 changes: 5 additions & 1 deletion src/core/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { UpdatePayload, ViteDevServer } from 'vite'
import { slash, throttle, toArray } from '@antfu/utils'
import type { ComponentInfo, Options, ResolvedOptions, Transformer } from '../types'
import { DIRECTIVE_IMPORT_PREFIX } from './constants'
import { getNameFromFilePath, matchGlobs, normalizeComponentInfo, parseId, pascalCase, resolveAlias } from './utils'
import { getNameFromFilePath, isExclude, matchGlobs, normalizeComponentInfo, parseId, pascalCase, resolveAlias } from './utils'
import { resolveOptions } from './options'
import { searchComponents } from './fs/glob'
import { writeDeclaration } from './declaration'
Expand Down Expand Up @@ -203,6 +203,10 @@ export class Context {
.from(this._componentPaths)
.forEach((path) => {
const name = pascalCase(getNameFromFilePath(path, this.options))
if (isExclude(name, this.options.excludeNames)) {
debug.components('exclude', name)
return
}
if (this._componentNameMap[name] && !this.options.allowOverrides) {
console.warn(`[unplugin-vue-components] component "${name}"(${path}) has naming conflicts with other components, ignored.`)
return
Expand Down
2 changes: 1 addition & 1 deletion src/core/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getPackageInfoSync, isPackageExists } from 'local-pkg'
import type { ComponentResolver, ComponentResolverObject, Options, ResolvedOptions } from '../types'
import { detectTypeImports } from './type-imports/detect'

export const defaultOptions: Omit<Required<Options>, 'include' | 'exclude' | 'transformer' | 'globs' | 'directives' | 'types' | 'version'> = {
export const defaultOptions: Omit<Required<Options>, 'include' | 'exclude' | 'excludeNames' | 'transformer' | 'globs' | 'directives' | 'types' | 'version'> = {
dirs: 'src/components',
extensions: 'vue',
deep: true,
Expand Down
18 changes: 0 additions & 18 deletions src/core/resolvers/_utils.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/core/resolvers/arco.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Debug from 'debug'
import type { ComponentInfo, ComponentResolver } from '../../types'
import { kebabCase, pascalCase } from '../utils'
import { isExclude } from './_utils'
import { isExclude, kebabCase, pascalCase } from '../utils'

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

Expand Down
14 changes: 4 additions & 10 deletions src/core/resolvers/layui-vue.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { FilterPattern } from '@rollup/pluginutils'
import { isExclude } from '../utils'
import type { ComponentInfo, ComponentResolver, SideEffectsInfo } from '../../types'

const matchComponents = [
Expand Down Expand Up @@ -95,7 +97,7 @@ export interface LayuiVueResolverOptions {
* exclude components that do not require automatic import
*
*/
exclude?: Array<string | RegExp>
exclude?: FilterPattern
}

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

if (options.exclude && isExclude(importName, options.exclude))
if (isExclude(importName, options.exclude))
return undefined

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

function isExclude(name: string, exclude: Array<string | RegExp>): boolean {
for (const item of exclude) {
if (name === item || name.match(item))
return true
}
return false
}

/**
* Resolver for layui-vue
*
Expand Down
22 changes: 4 additions & 18 deletions src/core/resolvers/tdesign.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { FilterPattern } from '@rollup/pluginutils'
import type { ComponentResolver } from '../../types'
import { isExclude } from '../utils'

export interface TDesignResolverOptions {
/**
Expand All @@ -23,7 +25,7 @@ export interface TDesignResolverOptions {
* exclude component name, if match do not resolve the name
*
*/
exclude?: string | RegExp | (string | RegExp)[]
exclude?: FilterPattern
}

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

if (options.exclude && isExclude(name, exclude))
if (isExclude(name, exclude))
return

if (options.resolveIcons && name.match(/[a-z]Icon$/)) {
Expand All @@ -55,19 +57,3 @@ export function TDesignResolver(options: TDesignResolverOptions = {}): Component
},
}
}

function isExclude(name: string, exclude: string | RegExp | (string | RegExp)[] | undefined): boolean {
if (typeof exclude === 'string')
return name === exclude

if (exclude instanceof RegExp)
return !!name.match(exclude)

if (Array.isArray(exclude)) {
for (const item of exclude) {
if (name === item || name.match(item))
return true
}
}
return false
}
20 changes: 20 additions & 0 deletions src/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getPackageInfo,
isPackageExists,
} from 'local-pkg'
import type { FilterPattern } from '@rollup/pluginutils'
import type { ComponentInfo, ImportInfo, ImportInfoLegacy, Options, ResolvedOptions } from '../types'
import type { Context } from './context'
import { DISABLE_COMMENT } from './constants'
Expand Down Expand Up @@ -222,3 +223,22 @@ export function shouldTransform(code: string) {
return false
return true
}

export function isExclude(name: string, exclude?: FilterPattern): boolean {
if (!exclude)
return false

if (typeof exclude === 'string')
return name === exclude

if (exclude instanceof RegExp)
return !!name.match(exclude)

if (Array.isArray(exclude)) {
for (const item of exclude) {
if (name === item || name.match(item))
return true
}
}
return false
}
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export interface Options {
*/
exclude?: FilterPattern

/**
* RegExp or string to match component names that will NOT be imported
*/
excludeNames?: FilterPattern

/**
* Relative paths to the directory to search for components.
* @default 'src/components'
Expand All @@ -86,7 +91,7 @@ export interface Options {
/**
* Glob patterns to match file names to be detected as components.
*
* When specified, the `dirs` and `extensions` options will be ignored.
* When specified, the `dirs`, `extensions`, and `directoryAsNamespace` options will be ignored.
*/
globs?: string | string[]

Expand Down
11 changes: 11 additions & 0 deletions test/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,15 @@ describe('search', () => {

expect(cleanup(ctx.componentNameMap).map(i => i.as)).not.toEqual(expect.arrayContaining(['Book']))
})

it('should excludeNames', () => {
const ctx = new Context({
dirs: ['src/components'],
excludeNames: ['Book'],
})
ctx.setRoot(root)
ctx.searchGlob()

expect(cleanup(ctx.componentNameMap).map(i => i.as)).not.toEqual(expect.arrayContaining(['Book']))
})
})

0 comments on commit aa4bc3e

Please sign in to comment.