diff --git a/src/core/declaration.ts b/src/core/declaration.ts index 7259be71..cc2e35fa 100644 --- a/src/core/declaration.ts +++ b/src/core/declaration.ts @@ -38,6 +38,16 @@ export function parseDeclaration(code: string): DeclarationImports | undefined { return imports } +function addComponentPrefix(component: ComponentInfo, prefix?: string) { + if (!component.as || !prefix) + return component + + return { + ...component, + as: `${prefix}${component.as}`, + } +} + /** * Converts `ComponentInfo` to an array * @@ -72,11 +82,10 @@ export interface DeclarationImports { } export function getDeclarationImports(ctx: Context, filepath: string): DeclarationImports | undefined { + const prefixComponentNameMap = Object.values(ctx.componentNameMap).map(info => addComponentPrefix(info, ctx.options.prefix)) const component = stringifyComponentsInfo(filepath, [ - ...Object.values({ - ...ctx.componentNameMap, - ...ctx.componentCustomMap, - }), + ...Object.values(ctx.componentCustomMap), + ...prefixComponentNameMap, ...resolveTypeImports(ctx.options.types), ], ctx.options.importPathTransform) diff --git a/src/core/options.ts b/src/core/options.ts index 58ba6239..0ea67fb0 100644 --- a/src/core/options.ts +++ b/src/core/options.ts @@ -21,6 +21,8 @@ export const defaultOptions: Omit, 'include' | 'exclude' | 'ex importPathTransform: v => v, allowOverrides: false, + + prefix: '', } function normalizeResolvers(resolvers: (ComponentResolver | ComponentResolver[])[]): ComponentResolverObject[] { diff --git a/src/types.ts b/src/types.ts index ac17d1e3..bce2a70c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -114,6 +114,11 @@ export interface Options { */ directoryAsNamespace?: boolean + /** + * Generate components with prefix. + */ + prefix?: string + /** * Collapse same prefixes (camel-sensitive) of folders and components * to prevent duplication inside namespaced component name. diff --git a/test/__snapshots__/dts.test.ts.snap b/test/__snapshots__/dts.test.ts.snap index c1d09dda..1359bad0 100644 --- a/test/__snapshots__/dts.test.ts.snap +++ b/test/__snapshots__/dts.test.ts.snap @@ -36,6 +36,42 @@ declare module 'vue' { " `; +exports[`dts > generate components with prefix 1`] = ` +"/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +// biome-ignore lint: disable +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + CustomPrefixAvatar: typeof import('./examples/vite-vue3/src/components/global/avatar.vue')['default'] + CustomPrefixBook: typeof import('./examples/vite-vue3/src/components/book/index.vue')['default'] + CustomPrefixButton: typeof import('./examples/vite-vue3/src/components/ui/button.vue')['default'] + CustomPrefixCheckbox: typeof import('./examples/vite-vue3/src/components/ui/nested/checkbox.vue')['default'] + CustomPrefixCollapseFolderAndComponentFromRoot: typeof import('./examples/vite-vue3/src/components/collapse/collapseFolder/CollapseFolderAndComponentFromRoot.vue')['default'] + CustomPrefixComponentA: typeof import('./examples/vite-vue3/src/components/ComponentA.vue')['default'] + CustomPrefixComponentAsync: typeof import('./examples/vite-vue3/src/components/ComponentAsync.vue')['default'] + CustomPrefixComponentB: typeof import('./examples/vite-vue3/src/components/ComponentB.vue')['default'] + CustomPrefixComponentC: typeof import('./examples/vite-vue3/src/components/component-c.vue')['default'] + CustomPrefixComponentD: typeof import('./examples/vite-vue3/src/components/ComponentD.vue')['default'] + CustomPrefixFolderAndComponentPartially: typeof import('./examples/vite-vue3/src/components/collapse/collapseFolder/FolderAndComponentPartially.vue')['default'] + CustomPrefixKebabCaseCollapseFile: typeof import('./examples/vite-vue3/src/components/kebab-case/kebab-case-collapse/KebabCaseCollapseFile.vue')['default'] + CustomPrefixKebabCaseFile: typeof import('./examples/vite-vue3/src/components/kebab-case/KebabCaseFile.vue')['default'] + CustomPrefixRecursive: typeof import('./examples/vite-vue3/src/components/Recursive.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + TestComp: typeof import('test/component/TestComp')['default'] + } + export interface GlobalDirectives { + vLoading: typeof import('test/directive/Loading')['default'] + } +} +" +`; + exports[`dts > getDeclaration 1`] = ` "/* eslint-disable */ // @ts-nocheck diff --git a/test/dts.test.ts b/test/dts.test.ts index 9ddf0f5d..aa8715d1 100644 --- a/test/dts.test.ts +++ b/test/dts.test.ts @@ -5,6 +5,7 @@ import { describe, expect, it } from 'vitest' import { Context } from '../src/core/context' import { getDeclaration, parseDeclaration } from '../src/core/declaration' +const root = path.resolve(__dirname, '../examples/vite-vue3') const resolver: ComponentResolver[] = [ { type: 'component', @@ -189,4 +190,21 @@ declare module 'vue' { const imports = parseDeclaration(code) expect(imports).matchSnapshot() }) + + it('generate components with prefix', async () => { + const ctx = new Context({ + resolvers: resolver, + directives: true, + prefix: 'CustomPrefix', + dirs: ['src/components'], + }) + ctx.setRoot(root) + const code = ` +const _component_test_comp = _resolveComponent("test-comp") +const _directive_loading = _resolveDirective("loading")` + await ctx.transform(code, '') + + const declarations = getDeclaration(ctx, 'test.d.ts') + expect(declarations).toMatchSnapshot() + }) })