@meng-xi/vite-plugin 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,11 +1,43 @@
1
1
  import { Plugin } from 'vite';
2
2
 
3
+ /**
4
+ * 基础插件配置
5
+ *
6
+ * @interface BasePluginOptions
7
+ */
8
+ interface BasePluginOptions {
9
+ /**
10
+ * 是否启用插件
11
+ *
12
+ * @default true
13
+ */
14
+ enabled?: boolean;
15
+ /**
16
+ * 是否启用日志
17
+ *
18
+ * @default true
19
+ */
20
+ verbose?: boolean;
21
+ /**
22
+ * 错误处理策略
23
+ *
24
+ * @default 'throw'
25
+ */
26
+ errorStrategy?: 'throw' | 'log' | 'ignore';
27
+ }
28
+ /**
29
+ * 插件工厂函数类型
30
+ *
31
+ * @template T 插件配置类型,默认继承自 BasePluginOptions
32
+ */
33
+ type PluginFactory<T extends BasePluginOptions = BasePluginOptions> = (options?: T) => Plugin;
34
+
3
35
  /**
4
36
  * 复制文件插件的配置选项接口
5
37
  *
6
38
  * @interface CopyFileOptions
7
39
  */
8
- interface CopyFileOptions {
40
+ interface CopyFileOptions extends BasePluginOptions {
9
41
  /**
10
42
  * 源文件目录的路径
11
43
  *
@@ -21,38 +53,28 @@ interface CopyFileOptions {
21
53
  /**
22
54
  * 是否覆盖同名文件
23
55
  *
24
- * @defaultValue true
25
- * @example false
56
+ * @default true
26
57
  */
27
58
  overwrite?: boolean;
28
59
  /**
29
60
  * 是否支持递归复制
30
61
  *
31
- * @defaultValue true
32
- * @example false
62
+ * @default true
33
63
  */
34
64
  recursive?: boolean;
35
65
  /**
36
- * 是否显示详细日志
37
- *
38
- * @defaultValue true
39
- * @example false
40
- */
41
- verbose?: boolean;
42
- /**
43
- * 是否启用复制功能
66
+ * 是否启用增量复制
44
67
  *
45
- * @defaultValue true
46
- * @example false
68
+ * @default true
47
69
  */
48
- enabled?: boolean;
70
+ incremental?: boolean;
49
71
  }
50
72
 
51
73
  /**
52
74
  * 复制文件插件
53
75
  *
54
- * @param options - 配置参数
55
- * @returns 一个 Vite 插件实例
76
+ * @param {CopyFileOptions} options - 插件配置选项
77
+ * @returns {Plugin} 一个 Vite 插件实例
56
78
  *
57
79
  * @example
58
80
  * ```typescript
@@ -62,34 +84,24 @@ interface CopyFileOptions {
62
84
  * targetDir: 'dist/assets'
63
85
  * })
64
86
  *
65
- * // 自定义配置
87
+ * // 高级配置
66
88
  * copyFile({
67
89
  * sourceDir: 'src/static',
68
90
  * targetDir: 'dist/static',
69
91
  * overwrite: false,
92
+ * recursive: true,
93
+ * incremental: true,
94
+ * enabled: true,
70
95
  * verbose: true,
71
- * recursive: false
72
- * })
73
- *
74
- * // 根据环境启用
75
- * copyFile({
76
- * sourceDir: 'src/assets',
77
- * targetDir: 'dist/assets',
78
- * enabled: process.env.NODE_ENV === 'production'
79
- * })
80
- *
81
- * // 禁用复制功能
82
- * copyFile({
83
- * sourceDir: 'src/assets',
84
- * targetDir: 'dist/assets',
85
- * enabled: false
96
+ * errorStrategy: 'throw'
86
97
  * })
87
98
  * ```
88
99
  *
89
100
  * @remarks
90
- * 该插件会在 Vite 构建完成后执行,将指定源目录的所有文件和子目录复制到目标目录
101
+ * 该插件会在 Vite 构建完成后执行,将指定源目录的所有文件和子目录复制到目标目录。
102
+ * 支持增量复制、递归复制和覆盖控制等功能。
91
103
  */
92
- declare function copyFile(options: CopyFileOptions): Plugin;
104
+ declare const copyFile: PluginFactory<CopyFileOptions>;
93
105
 
94
106
  /**
95
107
  * 图标配置项接口
@@ -135,15 +147,13 @@ interface CopyOptions {
135
147
  /**
136
148
  * 是否覆盖同名文件
137
149
  *
138
- * @defaultValue true
139
- * @example false
150
+ * @default true
140
151
  */
141
152
  overwrite?: boolean;
142
153
  /**
143
154
  * 是否支持递归复制
144
155
  *
145
- * @defaultValue true
146
- * @example false
156
+ * @default true
147
157
  */
148
158
  recursive?: boolean;
149
159
  }
@@ -152,11 +162,11 @@ interface CopyOptions {
152
162
  *
153
163
  * @interface InjectIcoOptions
154
164
  */
155
- interface InjectIcoOptions {
165
+ interface InjectIcoOptions extends BasePluginOptions {
156
166
  /**
157
- * 图标文件的基础路径,默认为根路径 `/`
167
+ * 图标文件的基础路径,默认为根路径 '/'
158
168
  *
159
- * @defaultValue `/`
169
+ * @default '/'
160
170
  * @example '/assets'
161
171
  */
162
172
  base?: string;
@@ -183,20 +193,6 @@ interface InjectIcoOptions {
183
193
  * ]
184
194
  */
185
195
  icons?: Icon[];
186
- /**
187
- * 是否显示详细日志
188
- *
189
- * @defaultValue true
190
- * @example false
191
- */
192
- verbose?: boolean;
193
- /**
194
- * 是否启用图标注入和文件复制功能
195
- *
196
- * @defaultValue true
197
- * @example false
198
- */
199
- enabled?: boolean;
200
196
  /**
201
197
  * 图标文件复制配置选项
202
198
  *
@@ -207,76 +203,39 @@ interface InjectIcoOptions {
207
203
  }
208
204
 
209
205
  /**
210
- * 注入网站图标链接到 HTML 文件的头部
211
- *
212
- * @param options - 配置选项(字符串时视为 base)
213
- * @returns 一个 Vite 插件实例,用于在构建过程中修改 HTML 文件
206
+ * 创建注入图标插件实例
214
207
  *
208
+ * @export
209
+ * @param {string | InjectIcoOptions} [options] - 插件配置选项,可以是字符串形式的 base 路径或完整的配置对象
210
+ * @returns {Plugin} Vite 插件实例,用于在构建过程中注入图标链接到 HTML 文件
215
211
  * @example
216
212
  * ```typescript
217
213
  * // 基本使用
218
- * injectIco({ base: '/assets' })
219
- *
220
- * // 自定义图标
221
- * injectIco({
222
- * icons: [
223
- * { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
224
- * { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
225
- * { rel: 'icon', href: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' }
226
- * ]
227
- * })
228
- *
229
- * // 带文件复制功能(适用于 uni-app 等框架)
230
- * injectIco({
231
- * base: '/assets',
232
- * copyOptions: {
233
- * sourceDir: 'src/assets/icons',
234
- * targetDir: 'dist/assets/icons'
235
- * }
236
- * })
237
- *
238
- * // 带完整复制配置的使用
239
- * injectIco({
240
- * base: '/assets',
241
- * copyOptions: {
242
- * sourceDir: 'src/assets/icons',
243
- * targetDir: 'dist/assets/icons',
244
- * overwrite: false,
245
- * recursive: true
246
- * }
247
- * })
248
- *
249
- * // 关闭日志输出
250
- * injectIco({
251
- * base: '/assets',
252
- * verbose: false,
253
- * copyOptions: {
254
- * sourceDir: 'src/assets/icons',
255
- * targetDir: 'dist/assets/icons'
256
- * }
257
- * })
214
+ * injectIco() // 使用默认配置
258
215
  *
259
- * // 根据环境启用
260
- * injectIco({
261
- * base: '/assets',
262
- * enabled: process.env.NODE_ENV === 'production',
263
- * copyOptions: {
264
- * sourceDir: 'src/assets/icons',
265
- * targetDir: 'dist/assets/icons'
266
- * }
267
- * })
216
+ * // 使用字符串配置 base 路径
217
+ * injectIco('/assets')
268
218
  *
269
- * // 禁用插件
219
+ * // 使用完整配置
270
220
  * injectIco({
271
221
  * base: '/assets',
272
- * enabled: false,
222
+ * icons: [
223
+ * { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
224
+ * { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }
225
+ * ],
273
226
  * copyOptions: {
274
227
  * sourceDir: 'src/assets/icons',
275
228
  * targetDir: 'dist/assets/icons'
276
229
  * }
277
230
  * })
278
231
  * ```
232
+ * @remarks
233
+ * 该函数创建并返回一个 Vite 插件实例,该实例会在构建过程中:
234
+ * 1. 将图标链接注入到 HTML 文件的 `<head>` 标签中
235
+ * 2. 如果配置了 copyOptions,将图标文件复制到目标目录
236
+ *
237
+ * 支持自定义图标链接、图标数组配置以及图标文件复制功能。
279
238
  */
280
- declare function injectIco(options?: InjectIcoOptions | string): Plugin;
239
+ declare function injectIco(options?: string | InjectIcoOptions): Plugin;
281
240
 
282
241
  export { copyFile, injectIco };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,43 @@
1
1
  import { Plugin } from 'vite';
2
2
 
3
+ /**
4
+ * 基础插件配置
5
+ *
6
+ * @interface BasePluginOptions
7
+ */
8
+ interface BasePluginOptions {
9
+ /**
10
+ * 是否启用插件
11
+ *
12
+ * @default true
13
+ */
14
+ enabled?: boolean;
15
+ /**
16
+ * 是否启用日志
17
+ *
18
+ * @default true
19
+ */
20
+ verbose?: boolean;
21
+ /**
22
+ * 错误处理策略
23
+ *
24
+ * @default 'throw'
25
+ */
26
+ errorStrategy?: 'throw' | 'log' | 'ignore';
27
+ }
28
+ /**
29
+ * 插件工厂函数类型
30
+ *
31
+ * @template T 插件配置类型,默认继承自 BasePluginOptions
32
+ */
33
+ type PluginFactory<T extends BasePluginOptions = BasePluginOptions> = (options?: T) => Plugin;
34
+
3
35
  /**
4
36
  * 复制文件插件的配置选项接口
5
37
  *
6
38
  * @interface CopyFileOptions
7
39
  */
8
- interface CopyFileOptions {
40
+ interface CopyFileOptions extends BasePluginOptions {
9
41
  /**
10
42
  * 源文件目录的路径
11
43
  *
@@ -21,38 +53,28 @@ interface CopyFileOptions {
21
53
  /**
22
54
  * 是否覆盖同名文件
23
55
  *
24
- * @defaultValue true
25
- * @example false
56
+ * @default true
26
57
  */
27
58
  overwrite?: boolean;
28
59
  /**
29
60
  * 是否支持递归复制
30
61
  *
31
- * @defaultValue true
32
- * @example false
62
+ * @default true
33
63
  */
34
64
  recursive?: boolean;
35
65
  /**
36
- * 是否显示详细日志
37
- *
38
- * @defaultValue true
39
- * @example false
40
- */
41
- verbose?: boolean;
42
- /**
43
- * 是否启用复制功能
66
+ * 是否启用增量复制
44
67
  *
45
- * @defaultValue true
46
- * @example false
68
+ * @default true
47
69
  */
48
- enabled?: boolean;
70
+ incremental?: boolean;
49
71
  }
50
72
 
51
73
  /**
52
74
  * 复制文件插件
53
75
  *
54
- * @param options - 配置参数
55
- * @returns 一个 Vite 插件实例
76
+ * @param {CopyFileOptions} options - 插件配置选项
77
+ * @returns {Plugin} 一个 Vite 插件实例
56
78
  *
57
79
  * @example
58
80
  * ```typescript
@@ -62,34 +84,24 @@ interface CopyFileOptions {
62
84
  * targetDir: 'dist/assets'
63
85
  * })
64
86
  *
65
- * // 自定义配置
87
+ * // 高级配置
66
88
  * copyFile({
67
89
  * sourceDir: 'src/static',
68
90
  * targetDir: 'dist/static',
69
91
  * overwrite: false,
92
+ * recursive: true,
93
+ * incremental: true,
94
+ * enabled: true,
70
95
  * verbose: true,
71
- * recursive: false
72
- * })
73
- *
74
- * // 根据环境启用
75
- * copyFile({
76
- * sourceDir: 'src/assets',
77
- * targetDir: 'dist/assets',
78
- * enabled: process.env.NODE_ENV === 'production'
79
- * })
80
- *
81
- * // 禁用复制功能
82
- * copyFile({
83
- * sourceDir: 'src/assets',
84
- * targetDir: 'dist/assets',
85
- * enabled: false
96
+ * errorStrategy: 'throw'
86
97
  * })
87
98
  * ```
88
99
  *
89
100
  * @remarks
90
- * 该插件会在 Vite 构建完成后执行,将指定源目录的所有文件和子目录复制到目标目录
101
+ * 该插件会在 Vite 构建完成后执行,将指定源目录的所有文件和子目录复制到目标目录。
102
+ * 支持增量复制、递归复制和覆盖控制等功能。
91
103
  */
92
- declare function copyFile(options: CopyFileOptions): Plugin;
104
+ declare const copyFile: PluginFactory<CopyFileOptions>;
93
105
 
94
106
  /**
95
107
  * 图标配置项接口
@@ -135,15 +147,13 @@ interface CopyOptions {
135
147
  /**
136
148
  * 是否覆盖同名文件
137
149
  *
138
- * @defaultValue true
139
- * @example false
150
+ * @default true
140
151
  */
141
152
  overwrite?: boolean;
142
153
  /**
143
154
  * 是否支持递归复制
144
155
  *
145
- * @defaultValue true
146
- * @example false
156
+ * @default true
147
157
  */
148
158
  recursive?: boolean;
149
159
  }
@@ -152,11 +162,11 @@ interface CopyOptions {
152
162
  *
153
163
  * @interface InjectIcoOptions
154
164
  */
155
- interface InjectIcoOptions {
165
+ interface InjectIcoOptions extends BasePluginOptions {
156
166
  /**
157
- * 图标文件的基础路径,默认为根路径 `/`
167
+ * 图标文件的基础路径,默认为根路径 '/'
158
168
  *
159
- * @defaultValue `/`
169
+ * @default '/'
160
170
  * @example '/assets'
161
171
  */
162
172
  base?: string;
@@ -183,20 +193,6 @@ interface InjectIcoOptions {
183
193
  * ]
184
194
  */
185
195
  icons?: Icon[];
186
- /**
187
- * 是否显示详细日志
188
- *
189
- * @defaultValue true
190
- * @example false
191
- */
192
- verbose?: boolean;
193
- /**
194
- * 是否启用图标注入和文件复制功能
195
- *
196
- * @defaultValue true
197
- * @example false
198
- */
199
- enabled?: boolean;
200
196
  /**
201
197
  * 图标文件复制配置选项
202
198
  *
@@ -207,76 +203,39 @@ interface InjectIcoOptions {
207
203
  }
208
204
 
209
205
  /**
210
- * 注入网站图标链接到 HTML 文件的头部
211
- *
212
- * @param options - 配置选项(字符串时视为 base)
213
- * @returns 一个 Vite 插件实例,用于在构建过程中修改 HTML 文件
206
+ * 创建注入图标插件实例
214
207
  *
208
+ * @export
209
+ * @param {string | InjectIcoOptions} [options] - 插件配置选项,可以是字符串形式的 base 路径或完整的配置对象
210
+ * @returns {Plugin} Vite 插件实例,用于在构建过程中注入图标链接到 HTML 文件
215
211
  * @example
216
212
  * ```typescript
217
213
  * // 基本使用
218
- * injectIco({ base: '/assets' })
219
- *
220
- * // 自定义图标
221
- * injectIco({
222
- * icons: [
223
- * { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
224
- * { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
225
- * { rel: 'icon', href: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' }
226
- * ]
227
- * })
228
- *
229
- * // 带文件复制功能(适用于 uni-app 等框架)
230
- * injectIco({
231
- * base: '/assets',
232
- * copyOptions: {
233
- * sourceDir: 'src/assets/icons',
234
- * targetDir: 'dist/assets/icons'
235
- * }
236
- * })
237
- *
238
- * // 带完整复制配置的使用
239
- * injectIco({
240
- * base: '/assets',
241
- * copyOptions: {
242
- * sourceDir: 'src/assets/icons',
243
- * targetDir: 'dist/assets/icons',
244
- * overwrite: false,
245
- * recursive: true
246
- * }
247
- * })
248
- *
249
- * // 关闭日志输出
250
- * injectIco({
251
- * base: '/assets',
252
- * verbose: false,
253
- * copyOptions: {
254
- * sourceDir: 'src/assets/icons',
255
- * targetDir: 'dist/assets/icons'
256
- * }
257
- * })
214
+ * injectIco() // 使用默认配置
258
215
  *
259
- * // 根据环境启用
260
- * injectIco({
261
- * base: '/assets',
262
- * enabled: process.env.NODE_ENV === 'production',
263
- * copyOptions: {
264
- * sourceDir: 'src/assets/icons',
265
- * targetDir: 'dist/assets/icons'
266
- * }
267
- * })
216
+ * // 使用字符串配置 base 路径
217
+ * injectIco('/assets')
268
218
  *
269
- * // 禁用插件
219
+ * // 使用完整配置
270
220
  * injectIco({
271
221
  * base: '/assets',
272
- * enabled: false,
222
+ * icons: [
223
+ * { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
224
+ * { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }
225
+ * ],
273
226
  * copyOptions: {
274
227
  * sourceDir: 'src/assets/icons',
275
228
  * targetDir: 'dist/assets/icons'
276
229
  * }
277
230
  * })
278
231
  * ```
232
+ * @remarks
233
+ * 该函数创建并返回一个 Vite 插件实例,该实例会在构建过程中:
234
+ * 1. 将图标链接注入到 HTML 文件的 `<head>` 标签中
235
+ * 2. 如果配置了 copyOptions,将图标文件复制到目标目录
236
+ *
237
+ * 支持自定义图标链接、图标数组配置以及图标文件复制功能。
279
238
  */
280
- declare function injectIco(options?: InjectIcoOptions | string): Plugin;
239
+ declare function injectIco(options?: string | InjectIcoOptions): Plugin;
281
240
 
282
241
  export { copyFile, injectIco };
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
- import s from"fs";async function a(e){try{await s.promises.access(e,s.constants.F_OK)}catch(r){const u=r;throw u.code==="ENOENT"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${e}`):u.code==="EACCES"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6E90\u6587\u4EF6 - ${e}`):new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u68C0\u67E5\u6E90\u6587\u4EF6\u65F6\u51FA\u9519 - ${e}\uFF0C\u9519\u8BEF\uFF1A${u.message}`)}}async function D(e){try{await s.promises.mkdir(e,{recursive:!0})}catch(r){const u=r;throw u.code==="EACCES"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u521B\u5EFA\u76EE\u6807\u76EE\u5F55 - ${e}`):new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u521B\u5EFA\u76EE\u6807\u76EE\u5F55\u65F6\u51FA\u9519 - ${e}\uFF0C\u9519\u8BEF\uFF1A${u.message}`)}}async function C(e,r,u){try{await s.promises.cp(e,r,{recursive:u.recursive,force:u.overwrite})}catch(o){const F=o;throw F.code==="ENOENT"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u590D\u5236\u8FC7\u7A0B\u4E2D\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${e}`):F.code==="EACCES"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u590D\u5236\u8FC7\u7A0B\u4E2D\u6743\u9650\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u8BBF\u95EE\u6E90\u6587\u4EF6\u6216\u5199\u5165\u76EE\u6807\u76EE\u5F55 - ${e} -> ${r}`):F.code==="EPERM"?new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u590D\u5236\u8FC7\u7A0B\u4E2D\u64CD\u4F5C\u88AB\u62D2\u7EDD - ${e} -> ${r}`):new Error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u590D\u5236\u6587\u4EF6\u65F6\u51FA\u9519 - ${e} -> ${r}\uFF0C\u9519\u8BEF\uFF1A${F.message}`)}}function l(e){const r=[];if(e.link)return r.push(e.link),r;if(e.icons&&e.icons.length>0)r.push(...e.icons.map(u=>{let o=`<link rel="${u.rel}" href="${u.href}"`;return u.sizes&&(o+=` sizes="${u.sizes}"`),u.type&&(o+=` type="${u.type}"`),o+=" />",o}));else if(e.url)r.push(`<link rel="icon" href="${e.url}" />`);else{const u=e.base||"/",o=u.endsWith("/")?`${u}favicon.ico`:`${u}/favicon.ico`;r.push(`<link rel="icon" href="${o}" />`)}return r}function A(e){const{sourceDir:r,targetDir:u,overwrite:o=!0,recursive:F=!0,verbose:n=!0,enabled:E=!0}=e;return{name:"copy-file",enforce:"post",async writeBundle(){if(!E){n&&console.log(`\u2139 \u590D\u5236\u6587\u4EF6\u529F\u80FD\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u6267\u884C\uFF1A\u4ECE ${r} \u5230 ${u}`);return}try{await a(r),await D(u),await C(r,u,{recursive:F,overwrite:o}),n&&console.log(`\u2705 \u590D\u5236\u6587\u4EF6\u6210\u529F\uFF1A\u4ECE ${r} \u5230 ${u}`)}catch(t){throw n&&(t instanceof Error?console.error(t.message):console.error(`\u274C \u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u672A\u77E5\u9519\u8BEF - ${r} -> ${u}`,t)),t}}}}function $(e){const r=typeof e=="string"?{base:e}:e||{},{verbose:u=!0,enabled:o=!0}=r;return{name:"inject-ico",transformIndexHtml(F){if(!o)return u&&console.log("\u2139 inject-ico: \u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u56FE\u6807\u6CE8\u5165"),F;const n=l(r);if(n.length===0)return u&&console.log("\u2139 inject-ico: \u6CA1\u6709\u751F\u6210\u56FE\u6807\u6807\u7B7E\uFF0C\u8DF3\u8FC7\u6CE8\u5165"),F;let E=F;const t=E.indexOf("</head>");if(t!==-1){const i=n.join(`
1
+ import a from"fs";import p from"path";class C{libName="@meng-xi/vite-plugin";name;enabled;logTypes={info:{method:console.log,icon:"",color:"",reset:""},success:{method:console.log,icon:"\u2705",color:"\x1B[32m",reset:"\x1B[0m"},warn:{method:console.warn,icon:"\u26A0\uFE0F",color:"\x1B[33m",reset:"\x1B[0m"},error:{method:console.error,icon:"\u274C",color:"\x1B[31m",reset:"\x1B[0m"}};constructor(u){this.name=u.name,this.enabled=u.enabled??!1}formatPrefix(){let u=`[${this.libName}:${this.name}]`;return u=`[${new Date().toLocaleString()}] ${u}`,u}log(u,e,t){if(!this.enabled)return;const i=this.formatPrefix(),s=this.logTypes[u],{method:o,icon:l,color:F,reset:h}=s,E=l?`${l} ${i}`:i;o("=================================="),t!=null?o(F+E+h,F+e+h,t):o(F+E+h,F+e+h),o("==================================")}success(u,e){this.log("success",u,e)}info(u,e){this.log("info",u,e)}warn(u,e){this.log("warn",u,e)}error(u,e){this.log("error",u,e)}}async function m(r){try{await a.promises.access(r,a.constants.F_OK)}catch(u){const e=u;throw e.code==="ENOENT"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${r}`):e.code==="EACCES"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6E90\u6587\u4EF6 - ${r}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u68C0\u67E5\u6E90\u6587\u4EF6\u65F6\u51FA\u9519 - ${r}\uFF0C\u9519\u8BEF\uFF1A${e.message}`)}}async function B(r){try{await a.promises.mkdir(r,{recursive:!0})}catch(u){const e=u;throw e.code==="EACCES"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u521B\u5EFA\u76EE\u6807\u76EE\u5F55 - ${r}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u521B\u5EFA\u76EE\u6807\u76EE\u5F55\u65F6\u51FA\u9519 - ${r}\uFF0C\u9519\u8BEF\uFF1A${e.message}`)}}async function w(r,u){const e=await a.promises.readdir(r,{withFileTypes:!0});let t=[];for(const i of e){const s=p.join(r,i.name);if(i.isDirectory()){if(t.push(s),u){const o=await w(s,u);t=[...t,...o]}}else t.push(s)}return t}async function D(r,u){try{const e=await a.promises.stat(r),t=await a.promises.stat(u);return e.mtimeMs>t.mtimeMs||e.size!==t.size}catch{return!0}}async function y(r,u,e){const t=Date.now(),{recursive:i,overwrite:s,incremental:o=!1}=e;let l=0,F=0,h=0;if((await a.promises.stat(r)).isDirectory()){await B(u);const c=await w(r,i),b=(await Promise.all(c.map(async n=>{const f=await a.promises.stat(n);return{path:n,isFile:f.isFile()}}))).filter(n=>n.isFile).map(n=>n.path);for(const n of b){const f=p.relative(r,n),g=p.join(u,f);await B(p.dirname(g));let d=s;if(!d)try{await a.promises.access(g,a.constants.F_OK),d=!1}catch{d=!0}o&&d&&(d=await D(n,g)),d?(await a.promises.copyFile(n,g),l++):F++}h=(await Promise.all(c.map(async n=>{const f=await a.promises.stat(n);return{path:n,isDirectory:f.isDirectory()}}))).filter(n=>n.isDirectory).length}else{await B(p.dirname(u));let c=s;if(!c)try{await a.promises.access(u,a.constants.F_OK),c=!1}catch{c=!0}o&&c&&(c=await D(r,u)),c?(await a.promises.copyFile(r,u),l++):F++}const E=Date.now()-t;return{copiedFiles:l,skippedFiles:F,copiedDirs:h,executionTime:E}}function A(...r){const u={};for(const e of r)if(e)for(const t in e){const i=e[t],s=u[t];typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof s=="object"&&s!==null&&!Array.isArray(s)?u[t]=A(s,i):u[t]=i}return u}class ${options;currentField=null;errors=[];constructor(u){this.options=u}field(u){return this.currentField=u,this}required(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");return this.options[this.currentField]==null&&this.errors.push(`${this.currentField} \u662F\u5FC5\u586B\u5B57\u6BB5`),this}string(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const u=this.options[this.currentField];return u!=null&&typeof u!="string"&&this.errors.push(`${this.currentField} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u7C7B\u578B`),this}boolean(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const u=this.options[this.currentField];return u!=null&&typeof u!="boolean"&&this.errors.push(`${this.currentField} \u5FC5\u987B\u662F\u5E03\u5C14\u7C7B\u578B`),this}number(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const u=this.options[this.currentField];return u!=null&&typeof u!="number"&&this.errors.push(`${this.currentField} \u5FC5\u987B\u662F\u6570\u5B57\u7C7B\u578B`),this}array(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const u=this.options[this.currentField];return u!=null&&!Array.isArray(u)&&this.errors.push(`${this.currentField} \u5FC5\u987B\u662F\u6570\u7EC4\u7C7B\u578B`),this}object(){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const u=this.options[this.currentField];return u!=null&&typeof u!="object"&&!Array.isArray(u)&&this.errors.push(`${this.currentField} \u5FC5\u987B\u662F\u5BF9\u8C61\u7C7B\u578B`),this}default(u){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");return this.options[this.currentField]==null&&(this.options[this.currentField]=u),this}custom(u,e){if(!this.currentField)throw new Error("\u5FC5\u987B\u5148\u8C03\u7528 field() \u65B9\u6CD5\u6307\u5B9A\u8981\u9A8C\u8BC1\u7684\u5B57\u6BB5");const t=this.options[this.currentField];return t!=null&&!u(t)&&this.errors.push(e),this}validate(){if(this.errors.length>0)throw new Error(`\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25\uFF1A
2
+ ${this.errors.map(u=>`- ${u}`).join(`
3
+ `)}`);return this.options}}class v{options;logger;validator;viteConfig=null;constructor(u,e){this.options=this.mergeOptions(u),this.logger=this.initLogger(e),this.validator=new $(this.options),this.validateOptions()}mergeOptions(u){return A({enabled:!0,verbose:!0,errorStrategy:"throw"},u)}initLogger(u){return u instanceof C?u:new C({name:this.getPluginName(),enabled:this.options.verbose,...u})}validateOptions(){}getEnforce(){}onConfigResolved(u){this.viteConfig=u,this.logger.info("\u914D\u7F6E\u89E3\u6790\u5B8C\u6210\uFF0C\u63D2\u4EF6\u5DF2\u521D\u59CB\u5316")}async safeExecute(u,e){try{return await u()}catch(t){return this.handleError(t,e)}}handleError(u,e){let t=`${e}: `;switch(u instanceof Error?t+=u.message:typeof u=="string"?t+=u:t+=String(u),this.options.errorStrategy){case"throw":throw this.logger.error(t),u;case"log":case"ignore":this.logger.error(t);return;default:throw this.logger.error(t),u}}toPlugin(){const u={name:this.getPluginName(),enforce:this.getEnforce(),configResolved:e=>{this.options.enabled&&this.onConfigResolved(e)}};return this.addPluginHooks(u),u}}function x(r){return u=>{const e=u,t=new r(e),i=t.toPlugin();return i.pluginInstance=t,i}}let P=class extends v{validateOptions(){this.validator.field("sourceDir").required().string().custom(u=>u.trim()!=="","sourceDir \u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32").field("targetDir").required().string().custom(u=>u.trim()!=="","targetDir \u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32").field("overwrite").boolean().default(!0).field("recursive").boolean().default(!0).field("incremental").boolean().default(!0).validate()}getPluginName(){return"copy-file"}getEnforce(){return"post"}async copyFiles(){const{sourceDir:u,targetDir:e,overwrite:t=!0,recursive:i=!0,incremental:s=!0,enabled:o=!0}=this.options;if(!o){this.logger.info(`\u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u6267\u884C\uFF1A\u4ECE ${u} \u590D\u5236\u5230 ${e}`);return}await m(u);const l=await y(u,e,{recursive:i,overwrite:t,incremental:s});this.logger.success(`\u590D\u5236\u6587\u4EF6\u6210\u529F\uFF1A\u4ECE ${u} \u5230 ${e}`,`\u590D\u5236\u4E86 ${l.copiedFiles} \u4E2A\u6587\u4EF6\uFF0C\u8DF3\u8FC7\u4E86 ${l.skippedFiles} \u4E2A\u6587\u4EF6\uFF0C\u8017\u65F6 ${l.executionTime}ms`)}addPluginHooks(u){u.writeBundle=async()=>{await this.safeExecute(()=>this.copyFiles(),"\u590D\u5236\u6587\u4EF6")}}};const O=x(P);function k(r){const u=[];if(r.link)return u.push(r.link),u;if(r.icons&&r.icons.length>0)u.push(...r.icons.map(e=>{let t=`<link rel="${e.rel}" href="${e.href}"`;return e.sizes&&(t+=` sizes="${e.sizes}"`),e.type&&(t+=` type="${e.type}"`),t+=" />",t}));else if(r.url)u.push(`<link rel="icon" href="${r.url}" />`);else{const e=r.base||"/",t=e.endsWith("/")?`${e}favicon.ico`:`${e}/favicon.ico`;u.push(`<link rel="icon" href="${t}" />`)}return u}class T extends v{constructor(u){const e=typeof u=="string"?{base:u}:u||{};super(e)}validateOptions(){this.validator.field("base").string().default("/").field("url").string().field("link").string().field("icons").array(),this.options?.copyOptions&&(this.validator.field("copyOptions").object(),new $(this.options.copyOptions).field("sourceDir").required().string().field("targetDir").required().string().field("overwrite").boolean().default(!0).field("recursive").boolean().default(!0).validate()),this.validator.validate()}getPluginName(){return"inject-ico"}injectIcoTags(u){if(!this.options.enabled)return this.logger.info("\u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u56FE\u6807\u6CE8\u5165"),u;const e=k(this.options);if(e.length===0)return this.logger.info("\u6CA1\u6709\u751F\u6210\u56FE\u6807\u6807\u7B7E\uFF0C\u8DF3\u8FC7\u6CE8\u5165"),u;let t=u;const i=t.indexOf("</head>");if(i!==-1){const s=e.join(`
2
4
  `)+`
3
- `;E=E.substring(0,t)+i+E.substring(t),u&&(console.log(`\u2705 inject-ico: \u6210\u529F\u6CE8\u5165 ${n.length} \u4E2A\u56FE\u6807\u6807\u7B7E\u5230 HTML \u6587\u4EF6`),n.forEach(c=>{console.log(` - ${c}`)}))}else u&&console.warn("\u26A0 inject-ico: \u672A\u627E\u5230 </head> \u6807\u7B7E\uFF0C\u8DF3\u8FC7\u56FE\u6807\u6CE8\u5165");return E},async writeBundle(){if(!o){u&&console.log("\u2139 inject-ico: \u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u6587\u4EF6\u590D\u5236");return}const{copyOptions:F}=r;if(!F)return;const{sourceDir:n,targetDir:E,overwrite:t=!0,recursive:i=!0}=F;try{await a(n),await D(E),await C(n,E,{recursive:i,overwrite:t}),u&&console.log(`\u2705 inject-ico: \u56FE\u6807\u6587\u4EF6\u590D\u5236\u6210\u529F\uFF1A\u4ECE ${n} \u5230 ${E}`)}catch(c){throw u&&(c instanceof Error?console.error(c.message):console.error(`\u274C inject-ico: \u56FE\u6807\u6587\u4EF6\u590D\u5236\u5931\u8D25\uFF1A\u672A\u77E5\u9519\u8BEF - ${n} -> ${E}`,c)),c}}}}export{A as copyFile,$ as injectIco};
5
+ `;t=t.substring(0,i)+s+t.substring(i),this.logger.success(`\u6210\u529F\u6CE8\u5165 ${e.length} \u4E2A\u56FE\u6807\u6807\u7B7E\u5230 HTML \u6587\u4EF6`),e.forEach(o=>{this.logger.info(` - ${o}`)})}else this.logger.warn("\u672A\u627E\u5230 </head> \u6807\u7B7E\uFF0C\u8DF3\u8FC7\u56FE\u6807\u6CE8\u5165");return t}async copyFiles(){if(!this.options.enabled){this.logger.info("\u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u8DF3\u8FC7\u6587\u4EF6\u590D\u5236");return}const{copyOptions:u}=this.options;if(!u)return;const{sourceDir:e,targetDir:t,overwrite:i=!0,recursive:s=!0}=u;await m(e);const o=await y(e,t,{recursive:s,overwrite:i,incremental:!0});this.logger.success(`\u56FE\u6807\u6587\u4EF6\u590D\u5236\u6210\u529F\uFF1A\u4ECE ${e} \u5230 ${t}`,`\u590D\u5236\u4E86 ${o.copiedFiles} \u4E2A\u6587\u4EF6\uFF0C\u8DF3\u8FC7\u4E86 ${o.skippedFiles} \u4E2A\u6587\u4EF6\uFF0C\u8017\u65F6 ${o.executionTime}ms`)}addPluginHooks(u){u.transformIndexHtml=e=>this.injectIcoTags(e),u.writeBundle=async()=>{await this.safeExecute(()=>this.copyFiles(),"\u56FE\u6807\u6587\u4EF6\u590D\u5236")}}}function j(r){return new T(r).toPlugin()}export{O as copyFile,j as injectIco};
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@meng-xi/vite-plugin",
3
3
  "type": "module",
4
- "version": "0.0.1",
4
+ "version": "0.0.2",
5
5
  "private": false,
6
6
  "description": "一个为 Vite 提供的插件库",
7
- "readme": "README.md",
8
7
  "keywords": [
9
8
  "meng-xi",
10
9
  "vite",
@@ -18,15 +17,12 @@
18
17
  "require": "./dist/index.cjs",
19
18
  "import": "./dist/index.mjs",
20
19
  "types": "./dist/index.d.ts"
21
- },
22
- "./plugins/*": {
23
- "require": "./dist/plugins/*.cjs",
24
- "import": "./dist/plugins/*.mjs",
25
- "types": "./dist/plugins/*.d.ts"
26
20
  }
27
21
  },
28
22
  "files": [
29
- "dist"
23
+ "dist",
24
+ "README.md",
25
+ "README-en.md"
30
26
  ],
31
27
  "scripts": {
32
28
  "dev": "unbuild --watch",