@meng-xi/vite-plugin 0.1.0 → 0.1.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.
Files changed (110) hide show
  1. package/README-en.md +264 -533
  2. package/README.md +253 -522
  3. package/dist/common/format/index.cjs +1 -0
  4. package/dist/common/format/index.d.cts +156 -0
  5. package/dist/common/format/index.d.mts +156 -0
  6. package/dist/common/format/index.d.ts +156 -0
  7. package/dist/common/format/index.mjs +1 -0
  8. package/dist/common/fs/index.cjs +1 -0
  9. package/dist/common/fs/index.d.cts +150 -0
  10. package/dist/common/fs/index.d.mts +150 -0
  11. package/dist/common/fs/index.d.ts +150 -0
  12. package/dist/common/fs/index.mjs +1 -0
  13. package/dist/common/html/index.cjs +2 -0
  14. package/dist/common/html/index.d.cts +109 -0
  15. package/dist/common/html/index.d.mts +109 -0
  16. package/dist/common/html/index.d.ts +109 -0
  17. package/dist/common/html/index.mjs +2 -0
  18. package/dist/common/index.cjs +1 -1
  19. package/dist/common/index.d.cts +7 -417
  20. package/dist/common/index.d.mts +7 -417
  21. package/dist/common/index.d.ts +7 -417
  22. package/dist/common/index.mjs +1 -1
  23. package/dist/common/object/index.cjs +1 -0
  24. package/dist/common/object/index.d.cts +30 -0
  25. package/dist/common/object/index.d.mts +30 -0
  26. package/dist/common/object/index.d.ts +30 -0
  27. package/dist/common/object/index.mjs +1 -0
  28. package/dist/common/script/index.cjs +1 -0
  29. package/dist/common/script/index.d.cts +54 -0
  30. package/dist/common/script/index.d.mts +54 -0
  31. package/dist/common/script/index.d.ts +54 -0
  32. package/dist/common/script/index.mjs +1 -0
  33. package/dist/common/validation/index.cjs +1 -0
  34. package/dist/common/validation/index.d.cts +93 -0
  35. package/dist/common/validation/index.d.mts +93 -0
  36. package/dist/common/validation/index.d.ts +93 -0
  37. package/dist/common/validation/index.mjs +1 -0
  38. package/dist/factory/index.cjs +1 -1
  39. package/dist/factory/index.d.cts +1 -1
  40. package/dist/factory/index.d.mts +1 -1
  41. package/dist/factory/index.d.ts +1 -1
  42. package/dist/factory/index.mjs +1 -1
  43. package/dist/index.cjs +1 -1
  44. package/dist/index.d.cts +16 -3
  45. package/dist/index.d.mts +16 -3
  46. package/dist/index.d.ts +16 -3
  47. package/dist/index.mjs +1 -1
  48. package/dist/plugins/buildProgress/index.cjs +2 -0
  49. package/dist/plugins/buildProgress/index.d.cts +187 -0
  50. package/dist/plugins/buildProgress/index.d.mts +187 -0
  51. package/dist/plugins/buildProgress/index.d.ts +187 -0
  52. package/dist/plugins/buildProgress/index.mjs +2 -0
  53. package/dist/plugins/compressAssets/index.cjs +1 -0
  54. package/dist/plugins/compressAssets/index.d.cts +132 -0
  55. package/dist/plugins/compressAssets/index.d.mts +132 -0
  56. package/dist/plugins/compressAssets/index.d.ts +132 -0
  57. package/dist/plugins/compressAssets/index.mjs +1 -0
  58. package/dist/plugins/copyFile/index.cjs +1 -0
  59. package/dist/plugins/copyFile/index.d.cts +78 -0
  60. package/dist/plugins/copyFile/index.d.mts +78 -0
  61. package/dist/plugins/copyFile/index.d.ts +78 -0
  62. package/dist/plugins/copyFile/index.mjs +1 -0
  63. package/dist/plugins/faviconManager/index.cjs +1 -0
  64. package/dist/plugins/faviconManager/index.d.cts +143 -0
  65. package/dist/plugins/faviconManager/index.d.mts +143 -0
  66. package/dist/plugins/faviconManager/index.d.ts +143 -0
  67. package/dist/plugins/faviconManager/index.mjs +1 -0
  68. package/dist/plugins/generateRouter/index.cjs +35 -0
  69. package/dist/plugins/generateRouter/index.d.cts +215 -0
  70. package/dist/plugins/generateRouter/index.d.mts +215 -0
  71. package/dist/plugins/generateRouter/index.d.ts +215 -0
  72. package/dist/plugins/generateRouter/index.mjs +35 -0
  73. package/dist/plugins/generateVersion/index.cjs +1 -0
  74. package/dist/plugins/generateVersion/index.d.cts +184 -0
  75. package/dist/plugins/generateVersion/index.d.mts +184 -0
  76. package/dist/plugins/generateVersion/index.d.ts +184 -0
  77. package/dist/plugins/generateVersion/index.mjs +1 -0
  78. package/dist/plugins/htmlInject/index.cjs +7 -0
  79. package/dist/plugins/htmlInject/index.d.cts +278 -0
  80. package/dist/plugins/htmlInject/index.d.mts +278 -0
  81. package/dist/plugins/htmlInject/index.d.ts +278 -0
  82. package/dist/plugins/htmlInject/index.mjs +7 -0
  83. package/dist/plugins/index.cjs +1 -1
  84. package/dist/plugins/index.d.cts +11 -1714
  85. package/dist/plugins/index.d.mts +11 -1714
  86. package/dist/plugins/index.d.ts +11 -1714
  87. package/dist/plugins/index.mjs +1 -1
  88. package/dist/plugins/loadingManager/index.cjs +487 -0
  89. package/dist/plugins/loadingManager/index.d.cts +769 -0
  90. package/dist/plugins/loadingManager/index.d.mts +769 -0
  91. package/dist/plugins/loadingManager/index.d.ts +769 -0
  92. package/dist/plugins/loadingManager/index.mjs +487 -0
  93. package/dist/plugins/versionUpdateChecker/index.cjs +185 -0
  94. package/dist/plugins/versionUpdateChecker/index.d.cts +200 -0
  95. package/dist/plugins/versionUpdateChecker/index.d.mts +200 -0
  96. package/dist/plugins/versionUpdateChecker/index.d.ts +200 -0
  97. package/dist/plugins/versionUpdateChecker/index.mjs +185 -0
  98. package/dist/shared/vite-plugin.Bcg6RW2N.cjs +3 -0
  99. package/dist/shared/{vite-plugin.CiHfwMiN.d.ts → vite-plugin.DRRlWY8P.d.cts} +50 -0
  100. package/dist/shared/{vite-plugin.CiHfwMiN.d.cts → vite-plugin.DRRlWY8P.d.mts} +50 -0
  101. package/dist/shared/{vite-plugin.CiHfwMiN.d.mts → vite-plugin.DRRlWY8P.d.ts} +50 -0
  102. package/dist/shared/{vite-plugin.B88RyRN8.mjs → vite-plugin.DcExl6jd.mjs} +2 -2
  103. package/package.json +80 -3
  104. package/dist/shared/vite-plugin.CawoITTT.cjs +0 -1
  105. package/dist/shared/vite-plugin.D6Law9Ke.mjs +0 -706
  106. package/dist/shared/vite-plugin.D8L9KzuW.cjs +0 -706
  107. package/dist/shared/vite-plugin.DFjf9wFM.mjs +0 -2
  108. package/dist/shared/vite-plugin.DSb6XzBn.mjs +0 -1
  109. package/dist/shared/vite-plugin.IGZeStMa.cjs +0 -3
  110. package/dist/shared/vite-plugin.Tab4qcIM.cjs +0 -2
package/README-en.md CHANGED
@@ -15,7 +15,8 @@
15
15
 
16
16
  ## Features
17
17
 
18
- - **Ready to Use** - Provides 7 practical plugins covering build progress display, file copying, router generation, version management, version update checking, icon injection, and global Loading state management
18
+ - **Ready to Use** - Provides 9 practical plugins covering build progress display, build artifact compression, file copying, router generation, version management, version update checking, HTML injection, icon injection,
19
+ and global Loading state management
19
20
  - **Plugin Development Framework** - Exports core components like BasePlugin, Logger, Validator for building custom Vite plugins
20
21
  - **Complete Lifecycle** - Supports initialization, config resolution, destroy lifecycle management with automatic hook composition
21
22
  - **Type Safe** - Complete TypeScript type definitions with configuration validators ensuring parameter correctness
@@ -46,42 +47,21 @@ pnpm add @meng-xi/vite-plugin -D
46
47
 
47
48
  ```typescript
48
49
  import { defineConfig } from 'vite'
49
- import { buildProgress, copyFile, generateRouter, generateVersion, versionUpdateChecker, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
50
+ import { buildProgress, compressAssets, copyFile, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
50
51
 
51
52
  export default defineConfig({
52
53
  plugins: [
53
- // Build progress bar
54
54
  buildProgress(),
55
-
56
- // Copy files
57
- copyFile({
58
- sourceDir: 'src/assets',
59
- targetDir: 'dist/assets'
60
- }),
61
-
62
- // Generate router config (uni-app)
63
- generateRouter({
64
- pagesJsonPath: 'src/pages.json',
65
- outputPath: 'src/router.config.ts'
66
- }),
67
-
68
- // Generate version
69
- generateVersion({
70
- format: 'datetime',
71
- outputType: 'both'
72
- }),
73
-
74
- // Version update checker (works with generateVersion)
55
+ compressAssets({ algorithm: 'gzip' }),
56
+ copyFile({ sourceDir: 'src/assets', targetDir: 'dist/assets' }),
57
+ generateRouter({ pagesJsonPath: 'src/pages.json', outputPath: 'src/router.config.ts' }),
58
+ generateVersion({ format: 'datetime', outputType: 'both' }),
75
59
  versionUpdateChecker(),
76
-
77
- // Inject website icon (supports string shorthand)
60
+ htmlInject({
61
+ rules: [{ id: 'meta-description', content: '<meta name="description" content="My App">', position: 'head-end' }]
62
+ }),
78
63
  faviconManager('/assets'),
79
-
80
- // Global Loading state management
81
- loadingManager({
82
- defaultVisible: true,
83
- autoHideOn: 'DOMContentLoaded'
84
- })
64
+ loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
85
65
  ]
86
66
  })
87
67
  ```
@@ -95,22 +75,24 @@ import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
95
75
  import type { GenerateRouterOptions } from '@meng-xi/vite-plugin'
96
76
 
97
77
  const routerPlugin = generateRouter({ watch: true }) as PluginWithInstance<GenerateRouterOptions>
98
-
99
- // Access plugin internals via pluginInstance
100
78
  console.log(routerPlugin.pluginInstance?.options)
101
79
  ```
102
80
 
103
81
  ## Built-in Plugins
104
82
 
105
- | Plugin | Description |
106
- | -------------------- | ---------------------------------------------------------------------------------------- |
107
- | buildProgress | Real-time build progress bar in terminal, supports bar / spinner / minimal |
108
- | copyFile | Copy files or directories after build, supports incremental copying |
109
- | generateRouter | Auto-generate router config from pages.json (uni-app) |
110
- | generateVersion | Auto-generate version numbers, supports file output and global variable injection |
111
- | versionUpdateChecker | Runtime version update checking with multiple prompt styles and custom callbacks |
112
- | faviconManager | Manage website favicon links injection into HTML files, supports string shorthand config |
113
- | loadingManager | Global Loading state management with request interception and white-screen Loading |
83
+ | Plugin | Description |
84
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------- |
85
+ | buildProgress | Real-time build progress bar in terminal, supports bar / spinner / minimal |
86
+ | compressAssets | Compress build artifacts with gzip / brotli / both, concurrent compression and statistics report |
87
+ | copyFile | Copy files or directories after build, supports incremental copying |
88
+ | generateRouter | Auto-generate router config from pages.json (uni-app) |
89
+ | generateVersion | Auto-generate version numbers, supports file output and global variable injection |
90
+ | versionUpdateChecker | Runtime version update checking with multiple prompt styles and custom callbacks |
91
+ | htmlInject | HTML content injection with multiple positions, conditional injection, template variables, and security filtering |
92
+ | faviconManager | Manage website favicon links injection into HTML files, supports string shorthand config |
93
+ | loadingManager | Global Loading state management with request interception and white-screen Loading |
94
+
95
+ ---
114
96
 
115
97
  ### buildProgress
116
98
 
@@ -142,24 +124,10 @@ Display real-time build progress bar in terminal during Vite build, supporting t
142
124
  | moduleColor | `(text: string) => string` | Module name color |
143
125
 
144
126
  ```typescript
145
- // Default bar format
146
127
  buildProgress()
147
-
148
- // Spinner format
149
128
  buildProgress({ format: 'spinner' })
150
-
151
- // Minimal format
152
129
  buildProgress({ format: 'minimal' })
153
-
154
- // Custom appearance
155
- buildProgress({
156
- width: 40,
157
- completeChar: '■',
158
- incompleteChar: '□',
159
- clearOnComplete: false
160
- })
161
-
162
- // Custom color theme
130
+ buildProgress({ width: 40, completeChar: '■', incompleteChar: '□', clearOnComplete: false })
163
131
  buildProgress({
164
132
  theme: {
165
133
  completeColor: t => `\x1b[32m${t}\x1b[39m`,
@@ -171,6 +139,35 @@ buildProgress({
171
139
  })
172
140
  ```
173
141
 
142
+ ---
143
+
144
+ ### compressAssets
145
+
146
+ Automatically compress files in the output directory after Vite build, supporting both gzip and brotli compression algorithms.
147
+
148
+ | Option | Type | Default | Description |
149
+ | ------------------ | ---------------------------------- | ----------------------------------------------------------- | -------------------------------------------------- |
150
+ | algorithm | `'gzip'` \| `'brotli'` \| `'both'` | `'gzip'` | Compression algorithm |
151
+ | threshold | `number` | `1024` | Minimum compression threshold (bytes) |
152
+ | deleteOriginalFile | `boolean` | `false` | Whether to delete original files after compression |
153
+ | includeExtensions | `string[]` | `['.js', '.css', '.html', '.svg', '.json', '.xml', '.txt']` | File extensions to compress |
154
+ | excludeExtensions | `string[]` | `[]` | File extensions to exclude |
155
+ | excludePaths | `string[]` | `[]` | Path prefixes to exclude |
156
+ | compressionLevel | `number` | `9` | Gzip compression level (1-9) |
157
+ | brotliQuality | `number` | `11` | Brotli compression quality (1-11) |
158
+ | reportOutput | `string` \| `false` | `'compress-report.json'` | Compression report output path, false to skip |
159
+ | parallelLimit | `number` | `10` | Maximum concurrent file compression count |
160
+
161
+ ```typescript
162
+ compressAssets()
163
+ compressAssets({ algorithm: 'brotli' })
164
+ compressAssets({ algorithm: 'both', threshold: 2048, compressionLevel: 9, brotliQuality: 11 })
165
+ compressAssets({ deleteOriginalFile: true, reportOutput: 'compress-report.json' })
166
+ compressAssets({ includeExtensions: ['.js', '.css'], excludePaths: ['assets/images'], parallelLimit: 5 })
167
+ ```
168
+
169
+ ---
170
+
174
171
  ### copyFile
175
172
 
176
173
  Copy files or directories to specified locations after Vite build is completed, with `enforce: 'post'`.
@@ -184,21 +181,12 @@ Copy files or directories to specified locations after Vite build is completed,
184
181
  | incremental | `boolean` | `true` | Whether to enable incremental copying |
185
182
 
186
183
  ```typescript
187
- // Basic usage
188
- copyFile({
189
- sourceDir: 'src/assets',
190
- targetDir: 'dist/assets'
191
- })
192
-
193
- // Disable overwrite and incremental copy
194
- copyFile({
195
- sourceDir: 'src/static',
196
- targetDir: 'dist/static',
197
- overwrite: false,
198
- incremental: false
199
- })
184
+ copyFile({ sourceDir: 'src/assets', targetDir: 'dist/assets' })
185
+ copyFile({ sourceDir: 'src/static', targetDir: 'dist/static', overwrite: false, incremental: false })
200
186
  ```
201
187
 
188
+ ---
189
+
202
190
  ### generateRouter
203
191
 
204
192
  Automatically generate router configuration files based on uni-app project's `pages.json`.
@@ -216,38 +204,19 @@ Automatically generate router configuration files based on uni-app project's `pa
216
204
  | exportTypes | `boolean` | `true` | Whether to export type definitions |
217
205
  | preserveRouteChanges | `boolean` | `true` | Whether to preserve user modifications to routes |
218
206
 
219
- > Default `metaMapping` is `{ navigationBarTitleText: 'title', requireAuth: 'requireAuth' }`, automatically mapping page style fields to route meta. When `nameStrategy` is `'custom'`, `customNameGenerator` must be
220
- > provided.
207
+ > Default `metaMapping` is `{ navigationBarTitleText: 'title', requireAuth: 'requireAuth' }`. When `nameStrategy` is `'custom'`, `customNameGenerator` must be provided.
221
208
 
222
209
  ```typescript
223
- // Basic usage
224
210
  generateRouter()
225
-
226
- // Custom pages.json path
227
211
  generateRouter({ pagesJsonPath: 'pages.json' })
228
-
229
- // Output JavaScript file
230
212
  generateRouter({ outputFormat: 'js', outputPath: 'src/router.config.js' })
231
-
232
- // PascalCase naming strategy
233
213
  generateRouter({ nameStrategy: 'pascalCase' })
234
-
235
- // Custom route name generator
236
- generateRouter({
237
- nameStrategy: 'custom',
238
- customNameGenerator: path => `route_${path.replace(/\//g, '_')}`
239
- })
240
-
241
- // Custom meta mapping
242
- generateRouter({
243
- metaMapping: {
244
- navigationBarTitleText: 'title',
245
- requireAuth: 'requireAuth',
246
- customField: 'custom'
247
- }
248
- })
214
+ generateRouter({ nameStrategy: 'custom', customNameGenerator: path => `route_${path.replace(/\//g, '_')}` })
215
+ generateRouter({ metaMapping: { navigationBarTitleText: 'title', requireAuth: 'requireAuth', customField: 'custom' } })
249
216
  ```
250
217
 
218
+ ---
219
+
251
220
  ### generateVersion
252
221
 
253
222
  Automatically generate version numbers during the Vite build process.
@@ -287,34 +256,16 @@ Automatically generate version numbers during the Vite build process.
287
256
  > and timestamp.
288
257
 
289
258
  ```typescript
290
- // Timestamp format (default)
291
259
  generateVersion()
292
-
293
- // Date format
294
260
  generateVersion({ format: 'date' })
295
-
296
- // Semantic version format
297
261
  generateVersion({ format: 'semver', semverBase: '2.0.0', prefix: 'v' })
298
-
299
- // Custom format
300
- generateVersion({
301
- format: 'custom',
302
- customFormat: '{YYYY}.{MM}.{DD}-{hash}',
303
- hashLength: 6
304
- })
305
-
306
- // Inject into code
262
+ generateVersion({ format: 'custom', customFormat: '{YYYY}.{MM}.{DD}-{hash}', hashLength: 6 })
307
263
  generateVersion({ outputType: 'define', defineName: '__VERSION__' })
308
-
309
- // Both file output and code injection
310
- generateVersion({
311
- outputType: 'both',
312
- outputFile: 'build-info.json',
313
- defineName: '__BUILD_VERSION__',
314
- extra: { environment: 'production' }
315
- })
264
+ generateVersion({ outputType: 'both', outputFile: 'build-info.json', defineName: '__BUILD_VERSION__', extra: { environment: 'production' } })
316
265
  ```
317
266
 
267
+ ---
268
+
318
269
  ### versionUpdateChecker
319
270
 
320
271
  Periodically check for version changes at runtime and prompt users to refresh when a new version is detected. Typically used in conjunction with the `generateVersion` plugin.
@@ -347,130 +298,135 @@ Periodically check for version changes at runtime and prompt users to refresh wh
347
298
  > `{{newVersion}}`, `{{refreshButton}}`, `{{dismissButton}}` placeholders. Callbacks are provided as function body strings with available variables: `currentVersion`, `newVersion`.
348
299
 
349
300
  ```typescript
350
- // Basic usage (with generateVersion)
351
301
  generateVersion({ outputType: 'both' })
352
302
  versionUpdateChecker()
353
-
354
- // Read from version file only
355
303
  versionUpdateChecker({ versionSource: 'file' })
356
-
357
- // Custom check interval and prompt style
358
- versionUpdateChecker({
359
- checkInterval: 60000,
360
- promptStyle: 'banner'
361
- })
362
-
363
- // Toast-style prompt
304
+ versionUpdateChecker({ checkInterval: 60000, promptStyle: 'banner' })
364
305
  versionUpdateChecker({ promptStyle: 'toast' })
365
-
366
- // Custom prompt text
367
- versionUpdateChecker({
368
- promptMessage: 'System updated, refresh to experience new features',
369
- refreshButtonText: 'Update',
370
- dismissButtonText: 'Cancel'
371
- })
372
-
373
- // Custom callbacks
374
- versionUpdateChecker({
375
- onUpdateAvailable: 'console.log("New version:", newVersion); return true;',
376
- onRefresh: 'console.log("User chose to refresh");',
377
- onDismiss: 'console.log("User chose to dismiss");'
378
- })
379
-
380
- // Enable in development (for debugging)
306
+ versionUpdateChecker({ promptMessage: 'System updated, refresh to experience new features', refreshButtonText: 'Update', dismissButtonText: 'Cancel' })
307
+ versionUpdateChecker({ onUpdateAvailable: 'console.log("New version:", newVersion); return true;', onRefresh: 'console.log("User chose to refresh");', onDismiss: 'console.log("User chose to dismiss");' })
381
308
  versionUpdateChecker({ enableInDev: true })
382
309
  ```
383
310
 
384
- ### faviconManager
311
+ ---
312
+
313
+ ### htmlInject
314
+
315
+ Inject HTML content into target files during Vite build based on configurable rules, supporting multiple injection positions, conditional injection, template variable substitution, and security filtering.
316
+
317
+ **Injection positions:**
318
+
319
+ | Position | Description |
320
+ | ------------------ | ------------------------------------------ |
321
+ | `head-start` | Inject after the `<head>` tag opening |
322
+ | `head-end` | Inject before the `</head>` closing tag |
323
+ | `body-start` | Inject after the `<body>` tag opening |
324
+ | `body-end` | Inject before the `</body>` closing tag |
325
+ | `before-selector` | Inject before the selector-matched content |
326
+ | `after-selector` | Inject after the selector-matched content |
327
+ | `replace-selector` | Replace the selector-matched content |
328
+
329
+ | Option | Type | Default | Description |
330
+ | ------------ | ------------------------ | -------------- | ----------------------------------- |
331
+ | targetFile | `string` | `'index.html'` | Target HTML file path or filename |
332
+ | rules | `InjectRule[]` | - | Array of injection rules (required) |
333
+ | security | `SecurityConfig` | - | Security filtering configuration |
334
+ | templateVars | `Record<string, string>` | - | Global template variables |
335
+ | logInjection | `boolean` | `true` | Whether to output injection logs |
336
+
337
+ **InjectRule**
338
+
339
+ | Property | Type | Default | Description |
340
+ | -------------------- | ------------------------ | ---------- | --------------------------------------------------------- |
341
+ | id | `string` | - | Unique rule identifier |
342
+ | content | `string` | - | HTML content to inject |
343
+ | position | `InjectPosition` | - | Injection position |
344
+ | selector | `string` | - | Selector (required for selector-related positions) |
345
+ | selectorMatch | `'string'` \| `'regex'` | `'string'` | Selector matching mode |
346
+ | priority | `number` | `100` | Rule priority, lower values execute first |
347
+ | condition | `InjectCondition` | - | Injection condition |
348
+ | templateVars | `Record<string, string>` | - | Rule-level template variables, override global vars |
349
+ | allowScriptInjection | `boolean` | `false` | Whether to allow injecting dangerous content like scripts |
350
+
351
+ **SecurityConfig**
352
+
353
+ | Property | Type | Default | Description |
354
+ | ------------------------ | ---------- | ------- | --------------------------------- |
355
+ | blockDangerousTags | `boolean` | `true` | Block dangerous tags |
356
+ | blockDangerousAttributes | `boolean` | `true` | Block dangerous attributes |
357
+ | allowedTags | `string[]` | - | Whitelist of allowed tags |
358
+ | blockedTags | `string[]` | - | Custom list of blocked tags |
359
+ | blockedAttributes | `string[]` | - | Custom list of blocked attributes |
385
360
 
386
- Inject website icon links into the head of HTML files during the Vite build process. Supports string shorthand config.
361
+ ```typescript
362
+ htmlInject({
363
+ rules: [
364
+ { id: 'meta-description', content: '<meta name="description" content="{{appName}}">', position: 'head-end', templateVars: { appName: 'My Application' } },
365
+ { id: 'analytics', content: '<script src="/analytics.js"></script>', position: 'body-end', condition: { type: 'env', value: 'PRODUCTION' }, allowScriptInjection: true }
366
+ ]
367
+ })
368
+ ```
387
369
 
388
- | Option | Type | Default | Description |
389
- | ----------- | -------- | ------- | ------------------------------- |
390
- | base | `string` | `'/'` | Base path for icon files |
391
- | url | `string` | - | Complete URL for the icon |
392
- | link | `string` | - | Custom complete link tag HTML |
393
- | icons | `Icon[]` | - | Custom icon array |
394
- | copyOptions | `object` | - | Icon file copying configuration |
370
+ ---
395
371
 
396
- > Priority: `link` > `url` > `base`. When `link` is provided, custom HTML is injected directly; when `url` is provided, the complete URL is used; otherwise `base + '/favicon.ico'` is used.
372
+ ### faviconManager
397
373
 
398
- `Icon` interface definition:
374
+ Manage website favicon links injection into HTML files, supporting string shorthand config and icon file copying.
399
375
 
400
- | Property | Type | Required | Description |
401
- | -------- | -------- | -------- | ------------------ |
402
- | rel | `string` | Yes | Icon relation type |
403
- | href | `string` | Yes | Icon URL |
404
- | sizes | `string` | No | Icon sizes |
405
- | type | `string` | No | Icon MIME type |
376
+ | Option | Type | Default | Description |
377
+ | ----------- | -------- | ------- | ------------------------------------------------------ |
378
+ | base | `string` | `'/'` | Base path for icon files |
379
+ | url | `string` | - | Complete icon URL, takes precedence over base |
380
+ | link | `string` | - | Custom complete link tag HTML, highest priority |
381
+ | icons | `Icon[]` | - | Custom icon array, supports multiple formats and sizes |
382
+ | copyOptions | `object` | - | Icon file copy config (sourceDir, targetDir) |
406
383
 
407
- `copyOptions` interface definition:
384
+ **Icon**
408
385
 
409
- | Property | Type | Required | Default | Description |
410
- | --------- | --------- | -------- | ------- | --------------------------- |
411
- | sourceDir | `string` | Yes | - | Icon source directory |
412
- | targetDir | `string` | Yes | - | Icon target directory |
413
- | overwrite | `boolean` | No | `true` | Whether to overwrite files |
414
- | recursive | `boolean` | No | `true` | Whether to copy recursively |
386
+ | Property | Type | Description |
387
+ | -------- | -------- | ------------------ |
388
+ | rel | `string` | Icon relation type |
389
+ | href | `string` | Icon URL |
390
+ | sizes | `string` | Icon size |
391
+ | type | `string` | Icon MIME type |
415
392
 
416
393
  ```typescript
417
- // Use default config
418
394
  faviconManager()
419
-
420
- // String shorthand (set base path)
421
395
  faviconManager('/assets')
422
-
423
- // Custom icon array
424
396
  faviconManager({
425
397
  base: '/assets',
426
398
  icons: [
427
399
  { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
428
- { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
429
- { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }
400
+ { rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }
430
401
  ]
431
402
  })
432
-
433
- // Custom complete link tag
434
- faviconManager({
435
- link: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />'
436
- })
437
-
438
- // With file copying
439
- faviconManager({
440
- base: '/assets',
441
- copyOptions: {
442
- sourceDir: 'src/assets/icons',
443
- targetDir: 'dist/assets/icons'
444
- }
445
- })
403
+ faviconManager({ link: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />' })
404
+ faviconManager({ base: '/assets', copyOptions: { sourceDir: 'src/assets/icons', targetDir: 'dist/assets/icons' } })
446
405
  ```
447
406
 
407
+ ---
408
+
448
409
  ### loadingManager
449
410
 
450
- Inject global Loading state management with XHR/Fetch request interception, white-screen Loading, custom styles, and lifecycle callbacks.
451
-
452
- **Injection strategy:**
453
-
454
- - `defaultVisible: false` (default): All code (CSS + HTML + JS) is dynamically injected via JS before `</body>`
455
- - `defaultVisible: true`: CSS + HTML are injected as static tags before `</head>` (visible on white screen), JS is injected before `</body>`
456
-
457
- | Option | Type | Default | Description |
458
- | -------------- | ----------------------------------------------- | ----------------------- | ------------------------------------------------------- |
459
- | position | `'center'` \| `'top'` \| `'bottom'` | `'center'` | Loading display position |
460
- | defaultText | `string` | `'Loading...'` | Default display text |
461
- | spinnerType | `'spinner'` \| `'dots'` \| `'pulse'` \| `'bar'` | `'spinner'` | Spinner icon type |
462
- | style | `LoadingStyle` | - | Custom style configuration |
463
- | transition | `TransitionConfig` | `{ enabled: true }` | Transition animation configuration |
464
- | minDisplayTime | `MinDisplayTime` | `{ enabled: true }` | Minimum display time configuration |
465
- | delayShow | `DelayShow` | `{ enabled: true }` | Delayed show configuration |
466
- | debounceHide | `DebounceHide` | `{ enabled: false }` | Debounced hide configuration |
467
- | autoBind | `'fetch'` \| `'xhr'` \| `'all'` \| `'none'` | `'none'` | Auto-bind request interception mode |
468
- | requestFilter | `RequestFilter` | - | Request filter configuration |
469
- | globalName | `string` | `'__LOADING_MANAGER__'` | Global variable name injected into browser |
470
- | customTemplate | `string` | - | Custom HTML template (must include `data-loading-text`) |
471
- | defaultVisible | `boolean` | `false` | Whether initially visible (white-screen Loading) |
472
- | autoHideOn | `'DOMContentLoaded'` \| `'load'` \| `'manual'` | `'DOMContentLoaded'` | Auto-hide timing (requires `defaultVisible: true`) |
473
- | callbacks | `LoadingCallbacks` | - | Lifecycle callbacks |
411
+ Global Loading state management with request interception and white-screen Loading support.
412
+
413
+ | Option | Type | Default | Description |
414
+ | -------------- | ----------------------------------------------- | ----------------------- | ------------------------------------------ |
415
+ | position | `'center'` \| `'top'` \| `'bottom'` | `'center'` | Loading display position |
416
+ | defaultText | `string` | `'Loading...'` | Default display text |
417
+ | spinnerType | `'spinner'` \| `'dots'` \| `'pulse'` \| `'bar'` | `'spinner'` | Spinner icon type |
418
+ | autoBind | `'fetch'` \| `'xhr'` \| `'all'` \| `'none'` | `'none'` | Auto-bind request interception mode |
419
+ | globalName | `string` | `'__LOADING_MANAGER__'` | Global variable name injected into browser |
420
+ | defaultVisible | `boolean` | `false` | Loading DOM initial visibility state |
421
+ | autoHideOn | `'DOMContentLoaded'` \| `'load'` \| `'manual'` | `'DOMContentLoaded'` | Auto-hide timing |
422
+ | style | `LoadingStyle` | - | Custom style configuration |
423
+ | transition | `TransitionConfig` | - | Transition animation configuration |
424
+ | minDisplayTime | `MinDisplayTime` | - | Minimum display time configuration |
425
+ | delayShow | `DelayShow` | - | Delay show configuration |
426
+ | debounceHide | `DebounceHide` | - | Debounce hide configuration |
427
+ | requestFilter | `RequestFilter` | - | Request filter configuration |
428
+ | customTemplate | `string` | - | Custom HTML template |
429
+ | callbacks | `LoadingCallbacks` | - | Lifecycle callbacks |
474
430
 
475
431
  **LoadingStyle**
476
432
 
@@ -481,371 +437,146 @@ Inject global Loading state management with XHR/Fetch request interception, whit
481
437
  | spinnerSize | `string` | `'40px'` | Spinner icon size |
482
438
  | textColor | `string` | `'#333'` | Text color |
483
439
  | textSize | `string` | `'14px'` | Text size |
484
- | customClass | `string` | - | Custom CSS class name |
485
- | customStyle | `string` | - | Custom inline style |
486
440
  | zIndex | `number` | `9999` | z-index value |
487
441
  | pointerEvents | `boolean` | `true` | Whether to enable overlay pointer events |
488
- | backdropBlur | `boolean` | `false` | Whether to enable backdrop blur |
489
- | backdropBlurAmount | `number` | `4` | Backdrop blur amount (px) |
490
-
491
- **TransitionConfig**
492
-
493
- | Property | Type | Default | Description |
494
- | -------- | --------- | ------------ | ---------------------------- |
495
- | enabled | `boolean` | `true` | Whether to enable transition |
496
- | duration | `number` | `200` | Transition duration (ms) |
497
- | easing | `string` | `'ease-out'` | Easing function |
498
-
499
- **MinDisplayTime**
500
-
501
- | Property | Type | Default | Description |
502
- | -------- | --------- | ------- | --------------------------------------------------------- |
503
- | enabled | `boolean` | `true` | Whether to enable |
504
- | duration | `number` | `300` | Minimum display time (ms), prevents Loading from flashing |
505
-
506
- **DelayShow**
507
-
508
- | Property | Type | Default | Description |
509
- | -------- | --------- | ------- | ------------------------------------------------------------------------------ |
510
- | enabled | `boolean` | `true` | Whether to enable |
511
- | duration | `number` | `200` | Delay duration (ms); if request completes within this time, Loading won't show |
512
-
513
- **DebounceHide**
514
-
515
- | Property | Type | Default | Description |
516
- | -------- | --------- | ------- | ----------------------- |
517
- | enabled | `boolean` | `false` | Whether to enable |
518
- | duration | `number` | `100` | Debounce wait time (ms) |
519
-
520
- **RequestFilter**
521
-
522
- | Property | Type | Description |
523
- | ------------------ | ---------- | --------------------------------------------------------------------- |
524
- | excludeUrls | `RegExp[]` | Array of URL regex patterns to exclude |
525
- | includeUrls | `RegExp[]` | Array of URL regex patterns to include (higher priority than exclude) |
526
- | excludeMethods | `string[]` | Array of HTTP methods to exclude |
527
- | excludeUrlPrefixes | `string[]` | Array of URL prefixes to exclude (prefix matching, more efficient) |
528
-
529
- **LoadingCallbacks**
530
-
531
- Callbacks are provided as **function body strings** (injected into browser at build time, function references cannot be passed).
532
-
533
- | Property | Type | Description |
534
- | ------------ | -------- | ----------------------------------------------- |
535
- | onBeforeShow | `string` | Before show callback, `return false` to prevent |
536
- | onShow | `string` | After show callback |
537
- | onBeforeHide | `string` | Before hide callback, `return false` to prevent |
538
- | onHide | `string` | After hide callback |
539
- | onDestroy | `string` | On destroy callback |
540
-
541
- **LoadingManager API**
542
-
543
- Access via `window.__LOADING_MANAGER__`:
544
-
545
- | Method | Description |
546
- | -------------------------- | ------------------------------------------------------------------- |
547
- | `show(text?)` | Show Loading, optionally pass text |
548
- | `hide()` | Hide Loading (subject to min display time and debounce constraints) |
549
- | `forceHide()` | Force hide, ignoring min display time and debounce |
550
- | `toggle(text?)` | Toggle Loading show/hide state |
551
- | `updateText(text)` | Update text content |
552
- | `isVisible()` | Get whether Loading is currently visible |
553
- | `isPointerEventsEnabled()` | Get whether pointer events are currently enabled |
554
- | `enablePointerEvents()` | Enable overlay pointer events, intercept all clicks and scrolls |
555
- | `disablePointerEvents()` | Disable overlay pointer events, allow interaction passthrough |
556
- | `togglePointerEvents()` | Toggle overlay pointer events state |
557
- | `getPendingCount()` | Get the number of pending requests |
558
- | `destroy()` | Destroy instance, clean up DOM and restore original interceptors |
559
-
560
- ```typescript
561
- // White-screen Loading: visible on page load, auto-hide on DOMContentLoaded
562
- loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
563
-
564
- // White-screen Loading: auto-hide after all resources loaded
565
- loadingManager({ defaultVisible: true, autoHideOn: 'load' })
566
-
567
- // Vue/React SPA: visible on white screen, manually hide after framework renders
568
- loadingManager({ defaultVisible: true, autoHideOn: 'manual' })
569
- // In app entry: window.__LOADING_MANAGER__.hide()
570
-
571
- // Auto-intercept all requests
572
- loadingManager({ autoBind: 'all' })
573
-
574
- // Custom styles + request filtering
575
- loadingManager({
576
- style: { overlayColor: 'rgba(0,0,0,0.5)', spinnerColor: '#fff', backdropBlur: true },
577
- autoBind: 'fetch',
578
- requestFilter: { excludeUrls: [/\/api\/health/], excludeUrlPrefixes: ['http://localhost'] }
579
- })
442
+ | backdropBlur | `boolean` | `false` | Whether to enable background blur |
443
+ | backdropBlurAmount | `number` | `4` | Background blur amount (px) |
444
+ | customClass | `string` | - | Custom CSS class name |
445
+ | customStyle | `string` | - | Custom inline style string |
580
446
 
581
- // Debounced hide (prevent rapid flashing)
582
- loadingManager({ debounceHide: { enabled: true, duration: 100 } })
447
+ **Runtime API:**
583
448
 
584
- // Lifecycle callbacks
585
- loadingManager({
586
- callbacks: {
587
- onBeforeShow: 'if (shouldSkip) return false;',
588
- onShow: 'console.log("loading shown")',
589
- onBeforeHide: 'if (shouldKeepVisible) return false;',
590
- onHide: 'console.log("loading hidden")'
591
- }
592
- })
593
-
594
- // Manual control
595
- loadingManager()
596
- window.__LOADING_MANAGER__.show('Saving...')
449
+ ```typescript
450
+ window.__LOADING_MANAGER__.show('Loading...')
597
451
  window.__LOADING_MANAGER__.hide()
452
+ window.__LOADING_MANAGER__.forceHide()
598
453
  window.__LOADING_MANAGER__.toggle()
454
+ window.__LOADING_MANAGER__.updateText('Processing...')
455
+ window.__LOADING_MANAGER__.isVisible()
456
+ window.__LOADING_MANAGER__.getPendingCount()
457
+ window.__LOADING_MANAGER__.destroy()
458
+ window.__LOADING_MANAGER__.enablePointerEvents()
599
459
  window.__LOADING_MANAGER__.disablePointerEvents()
460
+ window.__LOADING_MANAGER__.togglePointerEvents()
461
+ window.__LOADING_MANAGER__.isPointerEventsEnabled()
600
462
  ```
601
463
 
602
- ## Common Utilities
603
-
604
- Exported via `@meng-xi/vite-plugin/common`, reusable in custom plugins:
605
-
606
464
  ```typescript
607
- import { deepMerge, formatDate, parseTemplate, toCamelCase, toPascalCase, stripJsonComments, generateRandomHash, Validator } from '@meng-xi/vite-plugin/common'
608
- import { readFileContent, writeFileContent, fileExists, copySourceToTarget } from '@meng-xi/vite-plugin/common'
609
- import { injectBeforeTag, injectHtmlByPriority } from '@meng-xi/vite-plugin/common'
610
- import { makeCallback, containsScriptTag, validateIdentifierName } from '@meng-xi/vite-plugin/common'
465
+ loadingManager()
466
+ loadingManager({ position: 'top', defaultText: 'Please wait...' })
467
+ loadingManager({ spinnerType: 'dots' })
468
+ loadingManager({ autoBind: 'fetch', requestFilter: { excludeUrls: [/\/api\/health/], excludeUrlPrefixes: ['http://localhost'] } })
469
+ loadingManager({ style: { overlayColor: 'rgba(0,0,0,0.5)', spinnerColor: '#ff6b6b', backdropBlur: true, backdropBlurAmount: 6 } })
470
+ loadingManager({ transition: { enabled: true, duration: 300, easing: 'cubic-bezier(0.4,0,0.2,1)' } })
471
+ loadingManager({ debounceHide: { enabled: true, duration: 100 } })
472
+ loadingManager({ callbacks: { onShow: 'console.log("loading shown")', onBeforeShow: 'return true', onHide: 'console.log("loading hidden")' } })
473
+ loadingManager({ customTemplate: '<div class="my-loader"><span data-loading-text></span></div>' })
474
+ loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
475
+ loadingManager({ defaultVisible: true, autoHideOn: 'manual' })
611
476
  ```
612
477
 
613
- | Function | Description |
614
- | -------------------------- | ----------------------------------------------------------------------------- |
615
- | `deepMerge()` | Deep merge objects (undefined skipped, arrays overwritten) |
616
- | `formatDate()` | Format date with `{YYYY}`, `{MM}`, `{DD}` etc. placeholders |
617
- | `parseTemplate()` | Parse template string, replace placeholders |
618
- | `toCamelCase()` | Convert to camelCase |
619
- | `toPascalCase()` | Convert to PascalCase |
620
- | `stripJsonComments()` | Remove comments from JSON string |
621
- | `generateRandomHash()` | Generate random hash string (1-64 characters) |
622
- | `readFileContent()` | Async read file content |
623
- | `writeFileContent()` | Async write file content |
624
- | `fileExists()` | Async check if file exists |
625
- | `copySourceToTarget()` | Copy files or directories with incremental copy and concurrency |
626
- | `injectBeforeTag()` | Inject code before a specified closing HTML tag |
627
- | `injectHtmlByPriority()` | Inject code into HTML by priority (`</head>` → `</body>` → `</html>`) |
628
- | `makeCallback()` | Wrap callback function body as safe function expression (with try-catch) |
629
- | `containsScriptTag()` | Detect if a string contains `<script>` tags |
630
- | `validateIdentifierName()` | Validate string as a legal JavaScript identifier, prevent prototype pollution |
478
+ ---
631
479
 
632
480
  ## Plugin Development Framework
633
481
 
634
- ### BasePlugin Core Concepts
635
-
636
- `BasePlugin` is the base class for all plugins, providing complete lifecycle management and development conventions:
637
-
638
- #### Lifecycle
639
-
640
- | Phase | Method | Description |
641
- | ----------------- | ------------------ | -------------------------------------------------------------- |
642
- | Initialization | `constructor` | Merge options, initialize logger and validator |
643
- | Config Resolution | `onConfigResolved` | Called when Vite config is resolved |
644
- | Hook Registration | `addPluginHooks` | Register Vite plugin hooks |
645
- | Destroy | `destroy` | Automatically called during `closeBundle` for resource cleanup |
646
-
647
- #### Automatic Hook Composition
648
-
649
- The `toPlugin()` method automatically composes the following hooks:
650
-
651
- - **configResolved** - Base class `onConfigResolved` runs first, then subclass hook
652
- - **closeBundle** - Subclass hook runs first, then base class `destroy`
482
+ ### BasePlugin
653
483
 
654
- > Subclasses don't need to manually register `closeBundle` hooks for cleanup just override the `destroy()` method.
655
-
656
- #### Required Methods
657
-
658
- | Method | Description |
659
- | ------------------------ | --------------------- |
660
- | `getPluginName()` | Return plugin name |
661
- | `addPluginHooks(plugin)` | Add Vite plugin hooks |
662
-
663
- #### Optional Methods
664
-
665
- | Method | Default Behavior | Description |
666
- | -------------------------- | ----------------- | ------------------------------------------- |
667
- | `getDefaultOptions()` | Returns `{}` | Provide plugin default options |
668
- | `validateOptions()` | No validation | Validate configuration parameters |
669
- | `getEnforce()` | `undefined` | Plugin execution order (`'pre'` / `'post'`) |
670
- | `onConfigResolved(config)` | Store config | Config resolved callback |
671
- | `destroy()` | Unregister logger | Cleanup logic when plugin is destroyed |
672
-
673
- #### Built-in Properties
674
-
675
- | Property | Type | Description |
676
- | ------------ | ------------------------ | ----------------------------- |
677
- | `options` | `Required<T>` | Merged complete configuration |
678
- | `logger` | `PluginLogger` | Plugin logger |
679
- | `validator` | `Validator<T>` | Configuration validator |
680
- | `viteConfig` | `ResolvedConfig \| null` | Resolved Vite configuration |
681
-
682
- #### Error Handling Strategy
683
-
684
- Control error behavior via the `errorStrategy` configuration option:
685
-
686
- - `'throw'` (default) - Log error and throw exception, halting the build
687
- - `'log'` - Log error but don't throw, continue execution
688
- - `'ignore'` - Log error but don't throw, continue execution
689
-
690
- Wrap error-prone operations with `safeExecute` / `safeExecuteSync`:
484
+ The base class for all built-in plugins, providing core functionality such as configuration management, logging, lifecycle management, and safe execution.
691
485
 
692
486
  ```typescript
693
- // Async safe execution
694
- const result = await this.safeExecute(async () => {
695
- return await someAsyncOperation()
696
- }, 'Execute async operation')
697
-
698
- // Sync safe execution
699
- const value = this.safeExecuteSync(() => {
700
- return someSyncOperation()
701
- }, 'Execute sync operation')
702
- ```
703
-
704
- ### createPluginFactory
705
-
706
- Create plugin factory functions with optional normalizer support:
707
-
708
- ```typescript
709
- // Basic usage
710
- const myPlugin = createPluginFactory(MyPlugin)
711
-
712
- // With normalizer (supports shorthand string config)
713
- const myPlugin = createPluginFactory(MyPlugin, opt => (typeof opt === 'string' ? { path: opt } : opt))
714
-
715
- // Usage with shorthand
716
- myPlugin('./custom-path')
717
- ```
718
-
719
- ### Validator
720
-
721
- Fluent configuration validator with chainable API:
722
-
723
- ```typescript
724
- import { Validator } from '@meng-xi/vite-plugin/common'
725
-
726
- const validator = new Validator(options)
727
- validator
728
- .field('sourceDir')
729
- .required()
730
- .string()
731
- .field('targetDir')
732
- .required()
733
- .string()
734
- .field('overwrite')
735
- .boolean()
736
- .default(true)
737
- .field('port')
738
- .number()
739
- .field('list')
740
- .array()
741
- .field('config')
742
- .object()
743
- .field('name')
744
- .custom(val => val.length > 0, 'name cannot be empty')
745
- .validate()
746
- ```
747
-
748
- | Method | Description |
749
- | ------------ | --------------------------------------------------------------- |
750
- | `field()` | Specify the field to validate |
751
- | `required()` | Mark field as required |
752
- | `string()` | Validate field value is a string type |
753
- | `boolean()` | Validate field value is a boolean type |
754
- | `number()` | Validate field value is a number type |
755
- | `array()` | Validate field value is an array type |
756
- | `object()` | Validate field value is an object type |
757
- | `default()` | Set default value for field (only when value is undefined/null) |
758
- | `custom()` | Validate field value with a custom function |
759
- | `validate()` | Execute validation, throws error on failure |
760
-
761
- ### Logger
762
-
763
- Global singleton log manager providing independent log control for each plugin:
764
-
765
- ```typescript
766
- import { Logger } from '@meng-xi/vite-plugin/logger'
767
-
768
- // Create logger (usually called automatically by BasePlugin)
769
- Logger.create({ name: 'my-plugin', enabled: true })
770
-
771
- // Unregister plugin log config (automatically called on plugin destroy)
772
- Logger.unregister('my-plugin')
773
-
774
- // Destroy singleton (for test scenarios)
775
- Logger.destroy()
776
- ```
777
-
778
- Log output format:
779
-
780
- ```
781
- ℹ️ [@meng-xi/vite-plugin:my-plugin] Info message
782
- ✅ [@meng-xi/vite-plugin:my-plugin] Success message
783
- ⚠️ [@meng-xi/vite-plugin:my-plugin] Warning message
784
- ❌ [@meng-xi/vite-plugin:my-plugin] Error message
785
- ```
786
-
787
- ### Custom Plugin Example
788
-
789
- ```typescript
790
- import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin'
791
- import type { BasePluginOptions, PluginWithInstance } from '@meng-xi/vite-plugin/factory'
487
+ import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
792
488
  import type { Plugin } from 'vite'
793
489
 
794
- interface MyPluginOptions extends BasePluginOptions {
795
- path: string
490
+ interface MyPluginOptions {
491
+ enabled?: boolean
492
+ message?: string
796
493
  }
797
494
 
798
495
  class MyPlugin extends BasePlugin<MyPluginOptions> {
799
- protected getDefaultOptions() {
800
- return { path: './default' }
496
+ protected getPluginName() {
497
+ return 'my-plugin'
801
498
  }
802
-
803
- protected validateOptions(): void {
804
- this.validator.field('path').required().string().validate()
499
+ protected getDefaultOptions() {
500
+ return { enabled: true, message: 'Hello' }
805
501
  }
806
-
807
- protected getPluginName(): string {
808
- return 'my-plugin'
502
+ protected validateOptions() {
503
+ this.validator.field('message').string().validate()
809
504
  }
810
-
811
- protected addPluginHooks(plugin: Plugin): void {
505
+ protected addPluginHooks(plugin: Plugin) {
812
506
  plugin.buildStart = () => {
813
- this.logger.info(`Plugin started with path: ${this.options.path}`)
507
+ this.logger.info(this.options.message)
814
508
  }
815
509
  }
816
-
817
- protected destroy(): void {
818
- super.destroy()
819
- // Custom cleanup logic, e.g. close connections, stop watchers
820
- }
821
510
  }
822
511
 
823
- // Basic usage
824
512
  export const myPlugin = createPluginFactory(MyPlugin)
825
-
826
- // With normalizer (supports shorthand string config)
827
- export const myPluginWithNormalizer = createPluginFactory(MyPlugin, opt => (typeof opt === 'string' ? { path: opt } : opt))
828
- // Usage with shorthand: myPluginWithNormalizer('./custom-path')
829
513
  ```
830
514
 
515
+ ### Core Components
516
+
517
+ | Component | Export Path | Description |
518
+ | --------------------- | ------------------------------ | ----------------------------------- |
519
+ | `BasePlugin` | `@meng-xi/vite-plugin/factory` | Plugin base class |
520
+ | `createPluginFactory` | `@meng-xi/vite-plugin/factory` | Plugin factory function creator |
521
+ | `PluginWithInstance` | `@meng-xi/vite-plugin/factory` | Plugin type with instance reference |
522
+ | `Logger` | `@meng-xi/vite-plugin/logger` | Log manager (singleton pattern) |
523
+ | `Validator` | `@meng-xi/vite-plugin/common` | Fluent API configuration validator |
524
+
525
+ ### Common Utilities
526
+
527
+ | Module | Export Path | Description |
528
+ | ---------- | ---------------------------------------- | ----------------------------------------------------------------- |
529
+ | format | `@meng-xi/vite-plugin/common/format` | Date formatting, name conversion, template parsing, HTML escaping |
530
+ | fs | `@meng-xi/vite-plugin/common/fs` | File copying, directory traversal, concurrency control |
531
+ | html | `@meng-xi/vite-plugin/common/html` | HTML injection (injectBeforeTag, injectHeadAndBody, etc.) |
532
+ | object | `@meng-xi/vite-plugin/common/object` | Deep merge objects |
533
+ | script | `@meng-xi/vite-plugin/common/script` | Callback wrapping, script tag detection, identifier validation |
534
+ | validation | `@meng-xi/vite-plugin/common/validation` | Global name validation, XSS prevention, enum validation, etc. |
535
+
536
+ ---
537
+
831
538
  ## Sub-path Exports
832
539
 
833
540
  Support importing modules on demand to reduce bundle size:
834
541
 
835
542
  ```typescript
836
- // Full import
837
- import { buildProgress, copyFile, loadingManager, BasePlugin, Logger } from '@meng-xi/vite-plugin'
543
+ import { buildProgress, copyFile, htmlInject, loadingManager, BasePlugin, Logger } from '@meng-xi/vite-plugin'
838
544
 
839
- // Module-level import
840
545
  import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
841
546
  import { Logger } from '@meng-xi/vite-plugin/logger'
842
- import { buildProgress, copyFile, generateRouter, loadingManager } from '@meng-xi/vite-plugin/plugins'
843
- import { Validator, readFileContent, writeFileContent } from '@meng-xi/vite-plugin/common'
547
+ import { buildProgress, compressAssets, copyFile, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin/plugins'
548
+ import { Validator, readFileContent, writeFileContent, injectHeadAndBody, deepMerge } from '@meng-xi/vite-plugin/common'
844
549
 
845
- // Type imports (on-demand type definitions from sub-paths)
846
550
  import type { PluginWithInstance, PluginFactory, BasePluginOptions } from '@meng-xi/vite-plugin/factory'
847
- import type { BuildProgressOptions, GenerateVersionOptions, VersionUpdateCheckerOptions, FaviconManagerOptions, LoadingManagerOptions, Icon } from '@meng-xi/vite-plugin/plugins'
848
- import type { DateFormatOptions } from '@meng-xi/vite-plugin/common'
551
+ import type { BuildProgressOptions, CompressAssetsOptions, GenerateVersionOptions, VersionUpdateCheckerOptions, HtmlInjectOptions, FaviconManagerOptions, LoadingManagerOptions } from '@meng-xi/vite-plugin/plugins'
552
+ import type { DateFormatOptions } from '@meng-xi/vite-plugin/common/format'
553
+ import type { HtmlInjectResult, DualInjectResult } from '@meng-xi/vite-plugin/common/html'
554
+ import type { CopyOptions, CopyResult } from '@meng-xi/vite-plugin/common/fs'
555
+ ```
556
+
557
+ **All available sub-paths:**
558
+
559
+ ```
560
+ @meng-xi/vite-plugin
561
+ @meng-xi/vite-plugin/factory
562
+ @meng-xi/vite-plugin/logger
563
+ @meng-xi/vite-plugin/plugins
564
+ @meng-xi/vite-plugin/plugins/build-progress
565
+ @meng-xi/vite-plugin/plugins/compress-assets
566
+ @meng-xi/vite-plugin/plugins/copy-file
567
+ @meng-xi/vite-plugin/plugins/favicon-manager
568
+ @meng-xi/vite-plugin/plugins/generate-router
569
+ @meng-xi/vite-plugin/plugins/generate-version
570
+ @meng-xi/vite-plugin/plugins/html-inject
571
+ @meng-xi/vite-plugin/plugins/loading-manager
572
+ @meng-xi/vite-plugin/plugins/version-update-checker
573
+ @meng-xi/vite-plugin/common
574
+ @meng-xi/vite-plugin/common/format
575
+ @meng-xi/vite-plugin/common/fs
576
+ @meng-xi/vite-plugin/common/html
577
+ @meng-xi/vite-plugin/common/object
578
+ @meng-xi/vite-plugin/common/script
579
+ @meng-xi/vite-plugin/common/validation
849
580
  ```
850
581
 
851
582
  ## Changelog