From f00471ae34013bcbf79fae9f580b9316d6187746 Mon Sep 17 00:00:00 2001 From: IlyaL Date: Mon, 24 Feb 2025 20:22:56 +0800 Subject: [PATCH 1/2] feat: add options --- .gitignore | 1 + examples/vite-vue2/vite.config.ts | 1 + examples/vite-vue3/vite.config.ts | 1 + src/types.ts | 10 ++++++++++ 4 files changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index bbae2f96..bd89a7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules .DS_Store dist .idea +.unimport-components.json components.d.ts diff --git a/examples/vite-vue2/vite.config.ts b/examples/vite-vue2/vite.config.ts index 148b1ac9..24e876ee 100644 --- a/examples/vite-vue2/vite.config.ts +++ b/examples/vite-vue2/vite.config.ts @@ -8,6 +8,7 @@ const config: UserConfig = { Components({ transformer: 'vue2', dts: 'src/components.d.ts', + dumpUnimportComponents: true, }), ], build: { diff --git a/examples/vite-vue3/vite.config.ts b/examples/vite-vue3/vite.config.ts index 926eae87..478ae759 100644 --- a/examples/vite-vue3/vite.config.ts +++ b/examples/vite-vue3/vite.config.ts @@ -37,6 +37,7 @@ const config: UserConfig = { componentPrefix: 'i', }), ], + dumpUnimportComponents: true, }), ], build: { diff --git a/src/types.ts b/src/types.ts index ceaa3549..6815374e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -198,6 +198,16 @@ export interface Options { * Vue version of project. It will detect automatically if not specified. */ version?: 2 | 2.7 | 3 + + /** + * Save unimport components into a JSON file for other tools to consume. + * Provide a filepath to save the JSON file. + * + * When set to `true`, it will save to `./.unimport-components.json` + * + * @default false + */ + dumpUnimportComponents?: boolean | string } export type ResolvedOptions = Omit< From b7a55a187cbc1454db9bf6cee563298ceb5c6ecb Mon Sep 17 00:00:00 2001 From: IlyaL Date: Mon, 24 Feb 2025 21:09:43 +0800 Subject: [PATCH 2/2] feat: generate components json --- src/core/context.ts | 27 +++++++++++++++++++++++++-- src/core/declaration.ts | 19 +++++++++++++++++++ src/core/unplugin.ts | 6 ++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/core/context.ts b/src/core/context.ts index 1e40f340..2c007c7e 100644 --- a/src/core/context.ts +++ b/src/core/context.ts @@ -6,7 +6,7 @@ import process from 'node:process' import { slash, throttle, toArray } from '@antfu/utils' import Debug from 'debug' import { DIRECTIVE_IMPORT_PREFIX } from './constants' -import { writeDeclaration } from './declaration' +import { writeComponentsJson, writeDeclaration } from './declaration' import { searchComponents } from './fs/glob' import { resolveOptions } from './options' import transformer from './transformer' @@ -34,12 +34,23 @@ export class Context { root = process.cwd() sourcemap: string | boolean = true alias: Record = {} + dumpUnimportComponentsPath: string | undefined constructor( private rawOptions: Options, ) { this.options = resolveOptions(rawOptions, this.root) this.generateDeclaration = throttle(500, this._generateDeclaration.bind(this), { noLeading: false }) + + if (this.options.dumpUnimportComponents) { + const dumpUnimportComponents = this.options.dumpUnimportComponents === true + ? './.unimport-components.json' + : this.options.dumpUnimportComponents ?? false + + this.dumpUnimportComponentsPath = dumpUnimportComponents + this.generateComponentsJson = throttle(500, this._generateComponentsJson.bind(this), { noLeading: false }) + } + this.setTransformer(this.options.transformer) } @@ -287,7 +298,7 @@ export class Context { if (!this.options.dts) return - debug.declaration('generating') + debug.declaration('generating dts') return writeDeclaration(this, this.options.dts, removeUnused) } @@ -295,6 +306,18 @@ export class Context { this._generateDeclaration(removeUnused) } + _generateComponentsJson(removeUnused = !this._server) { + if (!Object.keys(this._componentNameMap).length) + return + + debug.components('generating components.json') + return writeComponentsJson(this, removeUnused) + } + + generateComponentsJson(removeUnused = !this._server): void { + this._generateComponentsJson(removeUnused) + } + get componentNameMap() { return this._componentNameMap } diff --git a/src/core/declaration.ts b/src/core/declaration.ts index 99a5945e..0d5c0d03 100644 --- a/src/core/declaration.ts +++ b/src/core/declaration.ts @@ -156,3 +156,22 @@ export async function writeDeclaration(ctx: Context, filepath: string, removeUnu if (code !== originalContent) await writeFile(filepath, code) } + +export async function writeComponentsJson(ctx: Context, _removeUnused = false) { + if (!ctx.dumpUnimportComponentsPath) + return + + const components = [ + ...Object.entries({ + ...ctx.componentNameMap, + ...ctx.componentCustomMap, + }).map(([_, { name, as, from }]) => ({ + name: name || 'default', + as, + from, + })), + ...resolveTypeImports(ctx.options.types), + ] + + await writeFile(ctx.dumpUnimportComponentsPath, JSON.stringify(components, null, 2)) +} diff --git a/src/core/unplugin.ts b/src/core/unplugin.ts index 5f07ad43..037bdc75 100644 --- a/src/core/unplugin.ts +++ b/src/core/unplugin.ts @@ -43,6 +43,7 @@ export default createUnplugin((options = {}) => { try { const result = await ctx.transform(code, id) ctx.generateDeclaration() + ctx.generateComponentsJson() return result } catch (e) { @@ -64,6 +65,11 @@ export default createUnplugin((options = {}) => { ctx.generateDeclaration() } + if (ctx.options.dumpUnimportComponents && ctx.dumpUnimportComponentsPath) { + if (!existsSync(ctx.dumpUnimportComponentsPath)) + ctx.generateComponentsJson() + } + if (config.build.watch && config.command === 'build') ctx.setupWatcher(chokidar.watch(ctx.options.globs)) },