Skip to content

Commit 7dfdff7

Browse files
committed
feat: major releases
1 parent d125240 commit 7dfdff7

File tree

7 files changed

+78
-66
lines changed

7 files changed

+78
-66
lines changed

README-zh.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
## 功能特点
66

7-
- 自动监听指定的文件夹以检测文件变化
8-
- 更新这些文件夹内的 `index.ts` 文件,写入正确的 `export` 语句
9-
- 可配置以忽略特定文件或文件夹
10-
- 支持 `ts | js` 的文件扩展名(默认为 `.ts`
11-
- 处理组件文件夹,并提供选项以指定组件文件夹。
7+
- 自动监听指定的文件夹以检测文件变化
8+
- 更新这些文件夹内的 `index.ts` 文件,写入正确的 `export` 语句
9+
- 可配置以忽略特定文件或文件夹
10+
- 支持 `ts | js` 的文件扩展名(默认为 `.ts`
11+
- 自定义导出格式
1212

1313
## 安装
1414

@@ -37,10 +37,14 @@ export default defineConfig({
3737

3838
plugins: [
3939
AutoExport({
40-
path: ['~/views/**/{components,hooks}/*', '~/hooks/*'], // 要监听的文件夹, 路径可以使用别名
41-
ignore: ['**/node_modules'], // 要忽略的文件夹或文件(可选)
42-
componentDirs: ['components'], // 处理的组件文件夹(可选)
43-
extname: 'ts', // 文件扩展名(默认为 'ts')'ts' | 'js'
40+
// 要监听的文件夹, 路径可以使用别名; 以 /* 结尾即可
41+
path: ['~/views/**/{components,hooks}/*', './src/hooks/*'],
42+
// 要忽略的文件夹或文件(可选)
43+
ignore: ['**/node_modules'],
44+
// 文件扩展名(默认为 'ts')'ts' | 'js'
45+
extname: 'ts',
46+
// 自定义导出格式
47+
formatter: (filename, extname) => `export * from './${filename}'`
4448
}),
4549
],
4650
});
@@ -61,16 +65,14 @@ module.exports = {
6165

6266
## 配置选项
6367

64-
- `path``string``string[]`):要监听变化的文件夹。可以是单个字符串或字符串数组
68+
- `path`(`string``string[]`): 要监听变化的文件夹。可以是单个字符串或字符串数组
6569
- 可以使用自己配置的路径别名
66-
- **要使用通配符匹配模式, 如: `~/views/**/{components,hooks}/*` 或者 `src/hooks/*.ts`**
67-
- `ignore``string[]`):在监听时要忽略的文件夹或文件。**(可选)**
70+
- **使用通配符匹配模式, 如: `~/views/**/{components,hooks}/*` 或者 `src/hooks/*.ts`**
71+
- `ignore`(`string[]`): 在监听时要忽略的文件夹或文件。**(可选)**
6872
-`path` 规则
69-
- `extname``string`):用于 `index` 文件的文件扩展名(默认为 `ts`
73+
- `extname`(`string`): 用于 `index` 文件的文件扩展名(默认为 `ts`
7074
- 支持 `ts | js`
71-
- `componentDirs``string[]`):要处理的组件文件夹。 **(可选)**
72-
- 比如以上的例子中传入的是 `componentDirs: ['components']`
73-
- 那么输出的 `export` 语句就是: `export { default as ZForm } from './z-form.vue'`
75+
- `formatter`(`(filename: string, extname: string) => string`): 自定义导出格式
7476

7577
## 错误处理
7678

@@ -79,7 +81,7 @@ module.exports = {
7981
- 因为只有这样才会表示监听某个文件夹内部文件
8082
- 如果路径不符合此规则,插件将抛出错误,并显示消息:`Path rule does not match. Please check the path format.`
8183
- 正确例子: `~/views/**/{components,hooks}/*` 或者 `src/hooks/*.ts`
82-
- `~` `Vite` 中配置的路径别名
84+
- `~` 是配置的路径别名
8385

8486
## 例子
8587

README.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Updates the `index.ts` file within those directories with the appropriate `export` statements.
1111
- Configurable to ignore specific files or directories.
1212
- Supports `ts | js` file extensions (default is `.ts`).
13-
- Handles component directories with options to specify component directories.
13+
- Custom export format.
1414

1515
## Installation
1616

@@ -39,10 +39,14 @@ export default defineConfig({
3939

4040
plugins: [
4141
AutoExport({
42-
path: ['~/views/**/{components,hooks}/*', '~/hooks/*'], // Directories to watch, paths can use aliases
43-
ignore: ['**/node_modules'], // Directories or files to ignore (optional)
44-
componentDirs: ['components'], // Component directories to handle (optional)
45-
extname: 'ts', // File extension (default is 'ts') `ts` | `js`
42+
// Directories to watch, paths can use aliases; It just needs to end with /*
43+
path: ['~/views/**/{components,hooks}/*', '~/hooks/*'],
44+
// Directories or files to ignore (optional)
45+
ignore: ['**/node_modules'],
46+
// File extension (default is 'ts') `ts` | `js`
47+
extname: 'ts',
48+
// Custom export format
49+
formatter: (filename, extname) => `export * from './${filename}'`
4650
}),
4751
],
4852
});
@@ -70,9 +74,7 @@ module.exports = {
7074
- Follows the same path rule as `path`.
7175
- `extname` (`string`): The file extension to use for the `index` files (default is `ts`).
7276
- support `ts | js`.
73-
- `componentDirs` (`string[]`): Component directories to handle. **(optional)**
74-
- For example, if you pass `componentDirs: ['components']`,
75-
- The generated `export` statement will be: `export { default as ZForm } from './z-form.vue'`.
77+
- `formatter`(`(filename: string, extname: string) => string`): Custom export format
7678

7779
## Error Handling
7880

@@ -81,7 +83,7 @@ module.exports = {
8183
- Because this is the only way to indicate monitoring files within a specific folder.
8284
- If the path does not match this rule, the plugin will throw an error with the message: `Path rule does not match. Please check the path format.`
8385
- Correct examples: `~/views/**/{components,hooks}/* or src/hooks/*.ts`
84-
- `~` is the path alias configured in `Vite`.
86+
- "~" is a configured path alias.
8587

8688
## Example
8789

playground/vite/vite.config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@ import { defineConfig } from 'vite'
22
import vue from '@vitejs/plugin-vue'
33
import AutoExport from 'unplugin-auto-export/vite'
44

5-
65
// https://vitejs.dev/config/
76
export default defineConfig({
87
plugins: [
98
vue(),
109
AutoExport({
1110
path: ['src/components/*'],
12-
componentDirs: ['components'],
1311
}),
1412
],
1513
})

playground/webpack/vue.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module.exports = defineConfig({
77
plugins: [
88
AutoExport({
99
path: ['src/components/*'],
10-
componentDirs: ['components'],
1110
}),
1211
],
1312
},

src/core/index.ts

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,49 @@ import fs from 'node:fs'
22
import path from 'node:path'
33
import chokidar from 'chokidar'
44
import type { Alias, AliasOptions } from 'vite'
5-
import type { Options } from '../types'
5+
import type { IOptions, TFileType } from '../types'
66
import { replacePath, throwError, toHump } from './utils'
77

8-
export function unpluginAutoExport(config: Options, alias: AliasOptions & Alias[]) {
8+
export function unpluginAutoExport(config: IOptions, alias: AliasOptions & Alias[]): chokidar.FSWatcher {
99
const reg = /\/\*(\.[\w\d]+)?$/
10+
const splitReg = /\.(?=[^\.]+$)/g
11+
const defaultOptions: IOptions = {
12+
path: [],
13+
ignore: [],
14+
extname: 'ts',
15+
}
16+
config = Object.assign(defaultOptions, config)
1017

1118
const handleDir = (_path: string) => {
12-
const { extname = 'ts', componentDirs = [] } = config
13-
const indexFileName = `index.${extname}`
19+
const { extname } = config
1420
const dirPath = path.dirname(_path)
21+
const indexFileName = `index.${extname}`
1522
const indexFilePath = `${dirPath}/${indexFileName}`
16-
const dir = dirPath.split('/').at(-1)!
17-
const isVue = componentDirs.includes(dir)
1823
const files = fs.readdirSync(dirPath).filter(e => e !== indexFileName && fs.statSync(`${dirPath}/${e}`).isFile())
1924
if (path.basename(_path) === indexFileName)
2025
return
21-
const indexFileContent
22-
= `${files
23-
.map((file) => {
24-
const basename = path.basename(file)
25-
const [filename] = basename.split('.')
26-
const s = isVue ? `{ default as ${toHump(filename)} }` : '*'
27-
const name = isVue ? basename : filename
28-
return `export ${s} from './${name}'`
29-
})
30-
.join('\n')}\n`
26+
const exportList = files
27+
.map((basename) => {
28+
const [filename, extname] = basename.split(splitReg) as [string, TFileType]
29+
if (config.formatter)
30+
return config.formatter(filename, extname)
31+
32+
switch (extname) {
33+
case 'vue':
34+
case 'json':
35+
return `export { default as ${toHump(filename)} } from './${filename}.${extname}'`
36+
case 'js':
37+
case 'ts':
38+
default:
39+
return `export * from './${filename}'`
40+
}
41+
}).join('\n')
42+
const indexFileContent = `${exportList || 'export {}'}\n`
3143
fs.writeFileSync(indexFilePath, indexFileContent)
3244
}
33-
const setupWatcher = (watcher: fs.FSWatcher) => {
34-
watcher.on('unlink', handleDir)
35-
watcher.on('add', handleDir)
36-
}
37-
const init = (path: string | string[], ignore: string[]) => {
38-
setupWatcher(chokidar.watch(path, { ignored: ignore }))
39-
}
40-
const handleAlias = () => {
45+
const init = () => {
4146
let path = config.path
42-
let ignore = config.ignore ?? []
47+
let ignore = config.ignore
4348
if (Array.isArray(path)) {
4449
!path.every(p => reg.test(p)) && throwError()
4550
path = path.map(e => replacePath(e, alias))
@@ -48,11 +53,14 @@ export function unpluginAutoExport(config: Options, alias: AliasOptions & Alias[
4853
!reg.test(path) && throwError()
4954
path = replacePath(path, alias)
5055
}
51-
!ignore.every(p => reg.test(p)) && throwError()
56+
!ignore?.every(p => reg.test(p)) && throwError()
5257
ignore = ignore?.map(e => replacePath(e, alias))
5358

54-
init(path, ignore)
59+
const watcher = chokidar.watch(path, { ignored: ignore })
60+
watcher.on('unlink', handleDir)
61+
watcher.on('add', handleDir)
62+
return watcher
5563
}
5664

57-
handleAlias()
65+
return init()
5866
}

src/index.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { UnpluginFactory } from 'unplugin'
22
import { createUnplugin } from 'unplugin'
33
import type { Alias, AliasOptions, ResolvedConfig } from 'vite'
4-
import type { Options } from './types'
5-
4+
import type chokidar from 'chokidar'
5+
import type { IOptions } from './types'
66
import { unpluginAutoExport } from './core'
77

8-
export const unpluginFactory: UnpluginFactory<Options | undefined> = options => ({
8+
let watcher: chokidar.FSWatcher | undefined
9+
export const unpluginFactory: UnpluginFactory<IOptions> = options => ({
910
name: 'unplugin-auto-export',
1011
// transformInclude(id) {
1112
// return id.endsWith('main.ts')
@@ -18,13 +19,13 @@ export const unpluginFactory: UnpluginFactory<Options | undefined> = options =>
1819
find: k,
1920
replacement: alias![k as keyof typeof alias],
2021
}))
21-
unpluginAutoExport(options!, aliasList)
22+
unpluginAutoExport(options, aliasList)
2223
},
2324
vite: {
25+
apply: 'serve',
2426
configResolved(config: ResolvedConfig) {
25-
if (config.env.PROD)
26-
return
27-
unpluginAutoExport(options!, config.resolve.alias)
27+
watcher?.close()
28+
watcher = unpluginAutoExport(options, config.resolve.alias)
2829
},
2930
},
3031
})

src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
export interface Options {
1+
export interface IOptions {
22
path: string | string[]
33
ignore?: string[]
44
extname?: 'ts' | 'js'
5-
componentDirs?: string[]
5+
formatter?: (filename: string, extname: string) => string
66
}
7+
8+
export type TFileType = 'ts' | 'js' | 'vue' | 'json'

0 commit comments

Comments
 (0)