@meng-xi/vite-plugin 0.1.6 → 0.1.8
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/README-en.md +42 -16
- package/README.md +55 -29
- package/dist/common/concurrency/index.cjs +1 -0
- package/dist/common/concurrency/index.d.cts +26 -0
- package/dist/common/concurrency/index.d.mts +26 -0
- package/dist/common/concurrency/index.d.ts +26 -0
- package/dist/common/concurrency/index.mjs +1 -0
- package/dist/common/format/index.cjs +1 -1
- package/dist/common/format/index.d.cts +19 -1
- package/dist/common/format/index.d.mts +19 -1
- package/dist/common/format/index.d.ts +19 -1
- package/dist/common/format/index.mjs +1 -1
- package/dist/common/fs/index.cjs +1 -1
- package/dist/common/fs/index.d.cts +19 -1
- package/dist/common/fs/index.d.mts +19 -1
- package/dist/common/fs/index.d.ts +19 -1
- package/dist/common/fs/index.mjs +1 -1
- package/dist/common/index.cjs +1 -1
- package/dist/common/index.d.cts +4 -2
- package/dist/common/index.d.mts +4 -2
- package/dist/common/index.d.ts +4 -2
- package/dist/common/index.mjs +1 -1
- package/dist/common/path/index.cjs +1 -0
- package/dist/common/path/index.d.cts +103 -0
- package/dist/common/path/index.d.mts +103 -0
- package/dist/common/path/index.d.ts +103 -0
- package/dist/common/path/index.mjs +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/dist/plugins/assetManifest/index.cjs +1 -0
- package/dist/plugins/assetManifest/index.d.cts +162 -0
- package/dist/plugins/assetManifest/index.d.mts +162 -0
- package/dist/plugins/assetManifest/index.d.ts +162 -0
- package/dist/plugins/assetManifest/index.mjs +1 -0
- package/dist/plugins/autoImport/index.cjs +13 -13
- package/dist/plugins/autoImport/index.mjs +8 -8
- package/dist/plugins/bundleAnalyzer/index.cjs +1 -1
- package/dist/plugins/bundleAnalyzer/index.mjs +2 -2
- package/dist/plugins/compressAssets/index.cjs +1 -1
- package/dist/plugins/compressAssets/index.mjs +1 -1
- package/dist/plugins/copyFile/index.cjs +1 -1
- package/dist/plugins/copyFile/index.mjs +1 -1
- package/dist/plugins/envGuard/index.cjs +1 -1
- package/dist/plugins/envGuard/index.mjs +1 -1
- package/dist/plugins/faviconManager/index.cjs +1 -1
- package/dist/plugins/faviconManager/index.mjs +1 -1
- package/dist/plugins/generateRouter/index.cjs +3 -3
- package/dist/plugins/generateRouter/index.mjs +1 -1
- package/dist/plugins/generateVersion/index.cjs +1 -1
- package/dist/plugins/generateVersion/index.mjs +1 -1
- package/dist/plugins/htmlInject/index.cjs +7 -7
- package/dist/plugins/htmlInject/index.mjs +2 -2
- package/dist/plugins/imageOptimizer/index.cjs +5 -0
- package/dist/plugins/imageOptimizer/index.d.cts +242 -0
- package/dist/plugins/imageOptimizer/index.d.mts +242 -0
- package/dist/plugins/imageOptimizer/index.d.ts +242 -0
- package/dist/plugins/imageOptimizer/index.mjs +5 -0
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.d.cts +2 -0
- package/dist/plugins/index.d.mts +2 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.mjs +1 -1
- package/package.json +25 -1
package/README-en.md
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
-
- **Ready to Use** -
|
|
19
|
-
management, global Loading, and more
|
|
18
|
+
- **Ready to Use** - 13 practical plugins covering auto-import, build progress, bundle analysis & compression, file copying, environment variable validation, route generation, version management, HTML injection, favicon
|
|
19
|
+
management, global Loading, image optimization, and more
|
|
20
20
|
- **Plugin Development Framework** - Exports core components like BasePlugin, Logger, and Validator to quickly build custom Vite plugins
|
|
21
|
-
- **Common Utility Library** - Built-in
|
|
21
|
+
- **Common Utility Library** - Built-in 8 Common utility modules supporting on-demand sub-path imports
|
|
22
22
|
- **Type Safe** - Complete TypeScript type definitions with configuration validators
|
|
23
23
|
- **On-demand Import** - Supports sub-path exports to reduce bundle size
|
|
24
24
|
|
|
@@ -41,7 +41,21 @@ pnpm add @meng-xi/vite-plugin -D
|
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
43
|
import { defineConfig } from 'vite'
|
|
44
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
autoImport,
|
|
46
|
+
buildProgress,
|
|
47
|
+
bundleAnalyzer,
|
|
48
|
+
compressAssets,
|
|
49
|
+
copyFile,
|
|
50
|
+
envGuard,
|
|
51
|
+
generateRouter,
|
|
52
|
+
generateVersion,
|
|
53
|
+
versionUpdateChecker,
|
|
54
|
+
htmlInject,
|
|
55
|
+
faviconManager,
|
|
56
|
+
loadingManager,
|
|
57
|
+
imageOptimizer
|
|
58
|
+
} from '@meng-xi/vite-plugin'
|
|
45
59
|
|
|
46
60
|
export default defineConfig({
|
|
47
61
|
plugins: [
|
|
@@ -56,7 +70,8 @@ export default defineConfig({
|
|
|
56
70
|
versionUpdateChecker(),
|
|
57
71
|
htmlInject({ rules: [{ id: 'meta', content: '<meta name="description" content="My App">', position: 'head-end' }] }),
|
|
58
72
|
faviconManager('/assets'),
|
|
59
|
-
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
73
|
+
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' }),
|
|
74
|
+
imageOptimizer({ quality: { jpeg: 80, webp: 75 }, convertToWebp: { png: true } })
|
|
60
75
|
]
|
|
61
76
|
})
|
|
62
77
|
```
|
|
@@ -77,6 +92,7 @@ export default defineConfig({
|
|
|
77
92
|
| [htmlInject](https://mengxi-studio.github.io/vite-plugin/en/plugins/html-inject.html) | HTML content injection with multiple positions, selector targeting, conditional injection, template variables, and security filtering |
|
|
78
93
|
| [loadingManager](https://mengxi-studio.github.io/vite-plugin/en/plugins/loading-manager.html) | Global Loading state management with request interception, debounce, transition animations, and white-screen Loading |
|
|
79
94
|
| [versionUpdateChecker](https://mengxi-studio.github.io/vite-plugin/en/plugins/version-update-checker.html) | Runtime version update checking with multiple prompt styles and custom callbacks |
|
|
95
|
+
| [imageOptimizer](https://mengxi-studio.github.io/vite-plugin/en/plugins/image-optimizer.html) | Image optimization & format conversion, supports JPEG/PNG/WebP/AVIF/GIF/TIFF/SVG, concurrent processing and statistics report |
|
|
80
96
|
|
|
81
97
|
## Plugin Development Framework
|
|
82
98
|
|
|
@@ -132,10 +148,13 @@ export const myPlugin = createPluginFactory(MyPlugin)
|
|
|
132
148
|
Built-in general-purpose utility function library, organized by functional modules, supporting on-demand sub-path imports.
|
|
133
149
|
|
|
134
150
|
```typescript
|
|
135
|
-
// Formatting: date params, template variable replacement, file size, date formatting
|
|
136
|
-
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize } from '@meng-xi/vite-plugin/common/format'
|
|
151
|
+
// Formatting: date params, template variable replacement, file size, date formatting, compression ratio
|
|
152
|
+
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize, calcRatio } from '@meng-xi/vite-plugin/common/format'
|
|
137
153
|
|
|
138
|
-
//
|
|
154
|
+
// Concurrency: batch execution with concurrency limit
|
|
155
|
+
import { runWithConcurrency } from '@meng-xi/vite-plugin/common/concurrency'
|
|
156
|
+
|
|
157
|
+
// File system: file copy, directory scan, safe write, change detection, report path resolution
|
|
139
158
|
import { copySourceToTarget, scanDirectory, writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
|
|
140
159
|
|
|
141
160
|
// HTML: tag injection, content sanitization, attribute escaping
|
|
@@ -149,16 +168,21 @@ import { ANSI } from '@meng-xi/vite-plugin/common/ui'
|
|
|
149
168
|
|
|
150
169
|
// Validation: chain validator, common validation functions
|
|
151
170
|
import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng-xi/vite-plugin/common/validation'
|
|
171
|
+
|
|
172
|
+
// Path: path normalization, extension filtering, path exclusion matching, pre-compression detection
|
|
173
|
+
import { normalizePath, isExtensionIncluded, isPathExcluded, isPreCompressed } from '@meng-xi/vite-plugin/common/path'
|
|
152
174
|
```
|
|
153
175
|
|
|
154
|
-
| Sub-path
|
|
155
|
-
|
|
|
156
|
-
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/en/common/format.html)
|
|
157
|
-
| [`common/
|
|
158
|
-
| [`common/
|
|
159
|
-
| [`common/
|
|
160
|
-
| [`common/
|
|
161
|
-
| [`common/
|
|
176
|
+
| Sub-path | Description |
|
|
177
|
+
| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
178
|
+
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/en/common/format.html) | Date param extraction, template variable replacement `{{key}}`, date formatting `{YYYY}`, file size, compression ratio |
|
|
179
|
+
| [`common/concurrency`](https://mengxi-studio.github.io/vite-plugin/en/common/concurrency.html) | Batch async execution with concurrency limit |
|
|
180
|
+
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/en/common/fs.html) | File/directory copy, directory scan, sync safe write, file change detection |
|
|
181
|
+
| [`common/html`](https://mengxi-studio.github.io/vite-plugin/en/common/html.html) | HTML tag injection, dual-zone injection, content sanitization, HTML attribute value escaping |
|
|
182
|
+
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/en/common/script.html) | Callback body wrapping into safe function expressions (with try-catch) |
|
|
183
|
+
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/en/common/ui.html) | Terminal ANSI color code constants |
|
|
184
|
+
| [`common/validation`](https://mengxi-studio.github.io/vite-plugin/en/common/validation.html) | Chain-style config validator, global name validation, script detection, callback field validation |
|
|
185
|
+
| [`common/path`](https://mengxi-studio.github.io/vite-plugin/en/common/path.html) | Path normalization, extension filtering, path exclusion matching, pre-compression format detection |
|
|
162
186
|
|
|
163
187
|
## Sub-path Exports
|
|
164
188
|
|
|
@@ -170,6 +194,7 @@ import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng
|
|
|
170
194
|
| `@meng-xi/vite-plugin/plugins` | All plugins |
|
|
171
195
|
| `@meng-xi/vite-plugin/common` | All utility functions |
|
|
172
196
|
| `@meng-xi/vite-plugin/common/*` | Utility sub-modules |
|
|
197
|
+
| `@meng-xi/vite-plugin/common/concurrency` | Concurrency control utilities |
|
|
173
198
|
| `@meng-xi/vite-plugin/plugins/auto-import` | autoImport plugin |
|
|
174
199
|
| `@meng-xi/vite-plugin/plugins/build-progress` | buildProgress plugin |
|
|
175
200
|
| `@meng-xi/vite-plugin/plugins/bundle-analyzer` | bundleAnalyzer plugin |
|
|
@@ -182,6 +207,7 @@ import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng
|
|
|
182
207
|
| `@meng-xi/vite-plugin/plugins/html-inject` | htmlInject plugin |
|
|
183
208
|
| `@meng-xi/vite-plugin/plugins/loading-manager` | loadingManager plugin |
|
|
184
209
|
| `@meng-xi/vite-plugin/plugins/version-update-checker` | versionUpdateChecker plugin |
|
|
210
|
+
| `@meng-xi/vite-plugin/plugins/image-optimizer` | imageOptimizer plugin |
|
|
185
211
|
|
|
186
212
|
## License
|
|
187
213
|
|
package/README.md
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
## 特性
|
|
17
17
|
|
|
18
|
-
- **开箱即用** -
|
|
18
|
+
- **开箱即用** - 13 个实用插件,覆盖自动导入、构建进度、产物分析与压缩、文件复制、环境变量校验、路由生成、版本管理、HTML 注入、图标管理、全局 Loading、图片优化 等场景
|
|
19
19
|
- **插件开发框架** - 导出 BasePlugin、Logger、Validator 等核心组件,快速构建自定义 Vite 插件
|
|
20
|
-
- **通用工具库** - 内置
|
|
20
|
+
- **通用工具库** - 内置 8 大 Common 工具模块,支持按需子路径导入
|
|
21
21
|
- **类型安全** - 完整 TypeScript 类型定义与配置验证器
|
|
22
22
|
- **按需导入** - 支持子路径导出,减少打包体积
|
|
23
23
|
|
|
@@ -40,7 +40,21 @@ pnpm add @meng-xi/vite-plugin -D
|
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
import { defineConfig } from 'vite'
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
autoImport,
|
|
45
|
+
buildProgress,
|
|
46
|
+
bundleAnalyzer,
|
|
47
|
+
compressAssets,
|
|
48
|
+
copyFile,
|
|
49
|
+
envGuard,
|
|
50
|
+
generateRouter,
|
|
51
|
+
generateVersion,
|
|
52
|
+
versionUpdateChecker,
|
|
53
|
+
htmlInject,
|
|
54
|
+
faviconManager,
|
|
55
|
+
loadingManager,
|
|
56
|
+
imageOptimizer
|
|
57
|
+
} from '@meng-xi/vite-plugin'
|
|
44
58
|
|
|
45
59
|
export default defineConfig({
|
|
46
60
|
plugins: [
|
|
@@ -55,27 +69,29 @@ export default defineConfig({
|
|
|
55
69
|
versionUpdateChecker(),
|
|
56
70
|
htmlInject({ rules: [{ id: 'meta', content: '<meta name="description" content="My App">', position: 'head-end' }] }),
|
|
57
71
|
faviconManager('/assets'),
|
|
58
|
-
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
72
|
+
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' }),
|
|
73
|
+
imageOptimizer({ quality: { jpeg: 80, webp: 75 }, convertToWebp: { png: true } })
|
|
59
74
|
]
|
|
60
75
|
})
|
|
61
76
|
```
|
|
62
77
|
|
|
63
78
|
## 内置插件
|
|
64
79
|
|
|
65
|
-
| 插件 | 说明
|
|
66
|
-
| ------------------------------------------------------------------------------------------------------- |
|
|
67
|
-
| [autoImport](https://mengxi-studio.github.io/vite-plugin/plugins/auto-import.html) | 自动注入 import 语句,支持预设映射、目录扫描和 Vue 模板自动导入
|
|
68
|
-
| [buildProgress](https://mengxi-studio.github.io/vite-plugin/plugins/build-progress.html) | 终端实时构建进度条,支持 bar / spinner / minimal
|
|
69
|
-
| [bundleAnalyzer](https://mengxi-studio.github.io/vite-plugin/plugins/bundle-analyzer.html) | 构建产物体积分析,支持 JSON/HTML 报告、gzip 计算、阈值告警和构建对比
|
|
70
|
-
| [compressAssets](https://mengxi-studio.github.io/vite-plugin/plugins/compress-assets.html) | 构建产物压缩,支持 gzip / brotli / both,并发压缩和统计报告
|
|
71
|
-
| [copyFile](https://mengxi-studio.github.io/vite-plugin/plugins/copy-file.html) | 构建完成后复制文件或目录,支持增量复制
|
|
72
|
-
| [envGuard](https://mengxi-studio.github.io/vite-plugin/plugins/env-guard.html) | 环境变量校验,支持类型检查、范围验证、自定义规则和运行时守卫
|
|
73
|
-
| [faviconManager](https://mengxi-studio.github.io/vite-plugin/plugins/favicon-manager.html) | 管理网站图标链接注入和文件复制,支持字符串简写配置
|
|
74
|
-
| [generateRouter](https://mengxi-studio.github.io/vite-plugin/plugins/generate-router.html) | 根据 pages.json 自动生成路由配置与类型声明(uni-app)
|
|
75
|
-
| [generateVersion](https://mengxi-studio.github.io/vite-plugin/plugins/generate-version.html) | 自动生成版本号,支持文件输出和全局变量注入
|
|
76
|
-
| [htmlInject](https://mengxi-studio.github.io/vite-plugin/plugins/html-inject.html) | HTML 内容注入,支持多种位置、选择器定位、条件注入、模板变量和安全过滤
|
|
77
|
-
| [loadingManager](https://mengxi-studio.github.io/vite-plugin/plugins/loading-manager.html) | 全局 Loading 状态管理,支持请求拦截、防抖、过渡动画和白屏 Loading
|
|
78
|
-
| [versionUpdateChecker](https://mengxi-studio.github.io/vite-plugin/plugins/version-update-checker.html) | 运行时版本更新检查,支持多种提示样式和自定义回调
|
|
80
|
+
| 插件 | 说明 |
|
|
81
|
+
| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
82
|
+
| [autoImport](https://mengxi-studio.github.io/vite-plugin/plugins/auto-import.html) | 自动注入 import 语句,支持预设映射、目录扫描和 Vue 模板自动导入 |
|
|
83
|
+
| [buildProgress](https://mengxi-studio.github.io/vite-plugin/plugins/build-progress.html) | 终端实时构建进度条,支持 bar / spinner / minimal |
|
|
84
|
+
| [bundleAnalyzer](https://mengxi-studio.github.io/vite-plugin/plugins/bundle-analyzer.html) | 构建产物体积分析,支持 JSON/HTML 报告、gzip 计算、阈值告警和构建对比 |
|
|
85
|
+
| [compressAssets](https://mengxi-studio.github.io/vite-plugin/plugins/compress-assets.html) | 构建产物压缩,支持 gzip / brotli / both,并发压缩和统计报告 |
|
|
86
|
+
| [copyFile](https://mengxi-studio.github.io/vite-plugin/plugins/copy-file.html) | 构建完成后复制文件或目录,支持增量复制 |
|
|
87
|
+
| [envGuard](https://mengxi-studio.github.io/vite-plugin/plugins/env-guard.html) | 环境变量校验,支持类型检查、范围验证、自定义规则和运行时守卫 |
|
|
88
|
+
| [faviconManager](https://mengxi-studio.github.io/vite-plugin/plugins/favicon-manager.html) | 管理网站图标链接注入和文件复制,支持字符串简写配置 |
|
|
89
|
+
| [generateRouter](https://mengxi-studio.github.io/vite-plugin/plugins/generate-router.html) | 根据 pages.json 自动生成路由配置与类型声明(uni-app) |
|
|
90
|
+
| [generateVersion](https://mengxi-studio.github.io/vite-plugin/plugins/generate-version.html) | 自动生成版本号,支持文件输出和全局变量注入 |
|
|
91
|
+
| [htmlInject](https://mengxi-studio.github.io/vite-plugin/plugins/html-inject.html) | HTML 内容注入,支持多种位置、选择器定位、条件注入、模板变量和安全过滤 |
|
|
92
|
+
| [loadingManager](https://mengxi-studio.github.io/vite-plugin/plugins/loading-manager.html) | 全局 Loading 状态管理,支持请求拦截、防抖、过渡动画和白屏 Loading |
|
|
93
|
+
| [versionUpdateChecker](https://mengxi-studio.github.io/vite-plugin/plugins/version-update-checker.html) | 运行时版本更新检查,支持多种提示样式和自定义回调 |
|
|
94
|
+
| [imageOptimizer](https://mengxi-studio.github.io/vite-plugin/plugins/image-optimizer.html) | 图片优化压缩与格式转换,支持 JPEG/PNG/WebP/AVIF/GIF/TIFF/SVG,并发处理和统计报告 |
|
|
79
95
|
|
|
80
96
|
## 插件开发框架
|
|
81
97
|
|
|
@@ -131,10 +147,13 @@ export const myPlugin = createPluginFactory(MyPlugin)
|
|
|
131
147
|
内置通用工具函数库,按功能模块组织,支持子路径按需导入。
|
|
132
148
|
|
|
133
149
|
```typescript
|
|
134
|
-
//
|
|
135
|
-
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize } from '@meng-xi/vite-plugin/common/format'
|
|
150
|
+
// 格式化:日期参数、模板变量替换、文件大小、日期格式化、压缩率计算
|
|
151
|
+
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize, calcRatio } from '@meng-xi/vite-plugin/common/format'
|
|
136
152
|
|
|
137
|
-
//
|
|
153
|
+
// 并发控制:带并发限制的批量执行
|
|
154
|
+
import { runWithConcurrency } from '@meng-xi/vite-plugin/common/concurrency'
|
|
155
|
+
|
|
156
|
+
// 文件系统:文件复制、目录扫描、安全写入、变更检测、报告路径解析
|
|
138
157
|
import { copySourceToTarget, scanDirectory, writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
|
|
139
158
|
|
|
140
159
|
// HTML:标签注入、内容消毒、属性转义
|
|
@@ -148,16 +167,21 @@ import { ANSI } from '@meng-xi/vite-plugin/common/ui'
|
|
|
148
167
|
|
|
149
168
|
// 参数验证:链式验证器、通用校验函数
|
|
150
169
|
import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng-xi/vite-plugin/common/validation'
|
|
170
|
+
|
|
171
|
+
// 路径处理:路径规范化、扩展名过滤、路径排除匹配、预压缩检测
|
|
172
|
+
import { normalizePath, isExtensionIncluded, isPathExcluded, isPreCompressed } from '@meng-xi/vite-plugin/common/path'
|
|
151
173
|
```
|
|
152
174
|
|
|
153
|
-
| 子路径
|
|
154
|
-
|
|
|
155
|
-
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/common/format.html)
|
|
156
|
-
| [`common/
|
|
157
|
-
| [`common/
|
|
158
|
-
| [`common/
|
|
159
|
-
| [`common/
|
|
160
|
-
| [`common/
|
|
175
|
+
| 子路径 | 描述 |
|
|
176
|
+
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
177
|
+
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/common/format.html) | 日期参数提取、模板变量替换 `{{key}}`、日期格式化 `{YYYY}`、文件大小格式化、压缩率计算 |
|
|
178
|
+
| [`common/concurrency`](https://mengxi-studio.github.io/vite-plugin/common/concurrency.html) | 带并发限制的批量异步执行 |
|
|
179
|
+
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/common/fs.html) | 文件/目录复制、目录扫描、同步安全写入、文件变更检测 |
|
|
180
|
+
| [`common/html`](https://mengxi-studio.github.io/vite-plugin/common/html.html) | HTML 标签注入、双区域注入、内容安全消毒、HTML 属性值转义 |
|
|
181
|
+
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/common/script.html) | 回调函数体包装为安全的函数表达式(含 try-catch) |
|
|
182
|
+
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/common/ui.html) | 终端 ANSI 颜色码常量 |
|
|
183
|
+
| [`common/validation`](https://mengxi-studio.github.io/vite-plugin/common/validation.html) | 链式配置验证器、全局名称校验、脚本检测、回调字段校验 |
|
|
184
|
+
| [`common/path`](https://mengxi-studio.github.io/vite-plugin/common/path.html) | 路径规范化、扩展名过滤、路径排除匹配、预压缩格式检测 |
|
|
161
185
|
|
|
162
186
|
## 子路径导出
|
|
163
187
|
|
|
@@ -169,6 +193,7 @@ import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng
|
|
|
169
193
|
| `@meng-xi/vite-plugin/plugins` | 所有插件 |
|
|
170
194
|
| `@meng-xi/vite-plugin/common` | 所有工具函数 |
|
|
171
195
|
| `@meng-xi/vite-plugin/common/*` | 各工具子模块 |
|
|
196
|
+
| `@meng-xi/vite-plugin/common/concurrency` | 并发控制工具 |
|
|
172
197
|
| `@meng-xi/vite-plugin/plugins/auto-import` | autoImport 插件 |
|
|
173
198
|
| `@meng-xi/vite-plugin/plugins/build-progress` | buildProgress 插件 |
|
|
174
199
|
| `@meng-xi/vite-plugin/plugins/bundle-analyzer` | bundleAnalyzer 插件 |
|
|
@@ -181,6 +206,7 @@ import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng
|
|
|
181
206
|
| `@meng-xi/vite-plugin/plugins/html-inject` | htmlInject 插件 |
|
|
182
207
|
| `@meng-xi/vite-plugin/plugins/loading-manager` | loadingManager 插件 |
|
|
183
208
|
| `@meng-xi/vite-plugin/plugins/version-update-checker` | versionUpdateChecker 插件 |
|
|
209
|
+
| `@meng-xi/vite-plugin/plugins/image-optimizer` | imageOptimizer 插件 |
|
|
184
210
|
|
|
185
211
|
## License
|
|
186
212
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";async function runWithConcurrency(n,a,e){const t=[];let r=0;async function i(){for(;r<n.length;){const c=r++,o=await a(n[c]);t[c]=o}}const l=Array(Math.min(e,n.length)).fill(null).map(()=>i());return await Promise.all(l),t}exports.runWithConcurrency=runWithConcurrency;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带并发限制的批量执行
|
|
3
|
+
*
|
|
4
|
+
* @template T - 输入项类型
|
|
5
|
+
* @template R - 返回结果类型
|
|
6
|
+
* @param {T[]} items - 待处理项列表
|
|
7
|
+
* @param {(item: T) => Promise<R>} handler - 处理函数
|
|
8
|
+
* @param {number} concurrency - 最大并发数
|
|
9
|
+
* @returns {Promise<R[]>} 处理结果数组,顺序与输入项对应
|
|
10
|
+
*
|
|
11
|
+
* @description 使用工作池模式并发执行异步任务,结果顺序与输入项对应。
|
|
12
|
+
* 当并发数大于等于项数时,所有项同时执行;否则按并发数分批执行。
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const results = await runWithConcurrency(
|
|
17
|
+
* [1, 2, 3, 4, 5],
|
|
18
|
+
* async (n) => { await delay(100); return n * 2 },
|
|
19
|
+
* 2
|
|
20
|
+
* )
|
|
21
|
+
* // [2, 4, 6, 8, 10]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function runWithConcurrency<T, R>(items: T[], handler: (item: T) => Promise<R>, concurrency: number): Promise<R[]>;
|
|
25
|
+
|
|
26
|
+
export { runWithConcurrency };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带并发限制的批量执行
|
|
3
|
+
*
|
|
4
|
+
* @template T - 输入项类型
|
|
5
|
+
* @template R - 返回结果类型
|
|
6
|
+
* @param {T[]} items - 待处理项列表
|
|
7
|
+
* @param {(item: T) => Promise<R>} handler - 处理函数
|
|
8
|
+
* @param {number} concurrency - 最大并发数
|
|
9
|
+
* @returns {Promise<R[]>} 处理结果数组,顺序与输入项对应
|
|
10
|
+
*
|
|
11
|
+
* @description 使用工作池模式并发执行异步任务,结果顺序与输入项对应。
|
|
12
|
+
* 当并发数大于等于项数时,所有项同时执行;否则按并发数分批执行。
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const results = await runWithConcurrency(
|
|
17
|
+
* [1, 2, 3, 4, 5],
|
|
18
|
+
* async (n) => { await delay(100); return n * 2 },
|
|
19
|
+
* 2
|
|
20
|
+
* )
|
|
21
|
+
* // [2, 4, 6, 8, 10]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function runWithConcurrency<T, R>(items: T[], handler: (item: T) => Promise<R>, concurrency: number): Promise<R[]>;
|
|
25
|
+
|
|
26
|
+
export { runWithConcurrency };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带并发限制的批量执行
|
|
3
|
+
*
|
|
4
|
+
* @template T - 输入项类型
|
|
5
|
+
* @template R - 返回结果类型
|
|
6
|
+
* @param {T[]} items - 待处理项列表
|
|
7
|
+
* @param {(item: T) => Promise<R>} handler - 处理函数
|
|
8
|
+
* @param {number} concurrency - 最大并发数
|
|
9
|
+
* @returns {Promise<R[]>} 处理结果数组,顺序与输入项对应
|
|
10
|
+
*
|
|
11
|
+
* @description 使用工作池模式并发执行异步任务,结果顺序与输入项对应。
|
|
12
|
+
* 当并发数大于等于项数时,所有项同时执行;否则按并发数分批执行。
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const results = await runWithConcurrency(
|
|
17
|
+
* [1, 2, 3, 4, 5],
|
|
18
|
+
* async (n) => { await delay(100); return n * 2 },
|
|
19
|
+
* 2
|
|
20
|
+
* )
|
|
21
|
+
* // [2, 4, 6, 8, 10]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function runWithConcurrency<T, R>(items: T[], handler: (item: T) => Promise<R>, concurrency: number): Promise<R[]>;
|
|
25
|
+
|
|
26
|
+
export { runWithConcurrency };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
async function s(n,c,l){const t=[];let r=0;async function o(){for(;r<n.length;){const a=r++,i=await c(n[a]);t[a]=i}}const e=Array(Math.min(l,n.length)).fill(null).map(()=>o());return await Promise.all(e),t}export{s as runWithConcurrency};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";function t
|
|
1
|
+
"use strict";function r(t,e=2){return t.toString().padStart(e,"0")}function getDateFormatParams(t=new Date){return{YYYY:t.getFullYear().toString(),YY:t.getFullYear().toString().slice(-2),MM:r(t.getMonth()+1),DD:r(t.getDate()),HH:r(t.getHours()),mm:r(t.getMinutes()),ss:r(t.getSeconds()),SSS:r(t.getMilliseconds(),3),timestamp:t.getTime().toString()}}function parseTemplate(t,e){let o=t;for(const[n,a]of Object.entries(e)){const i=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),s=a.replace(/\$/g,"$$$$");o=o.replace(new RegExp(`\\{\\{${i}\\}\\}`,"g"),s)}return o}function formatDate(t,e){const o=getDateFormatParams(t);let n=e;for(const[a,i]of Object.entries(o))n=n.replace(new RegExp(`\\{${a}\\}`,"g"),i);return n}function formatFileSize(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(2)}MB`}function calcRatio(t,e){return t>0?Number(((1-e/t)*100).toFixed(1)):0}exports.calcRatio=calcRatio,exports.formatDate=formatDate,exports.formatFileSize=formatFileSize,exports.getDateFormatParams=getDateFormatParams,exports.parseTemplate=parseTemplate;
|
|
@@ -88,6 +88,24 @@ declare function formatDate(date: Date, format: string): string;
|
|
|
88
88
|
* ```
|
|
89
89
|
*/
|
|
90
90
|
declare function formatFileSize(bytes: number): string;
|
|
91
|
+
/**
|
|
92
|
+
* 计算压缩率百分比
|
|
93
|
+
*
|
|
94
|
+
* @param {number} originalSize - 原始大小(字节)
|
|
95
|
+
* @param {number} compressedSize - 压缩后大小(字节)
|
|
96
|
+
* @returns {number} 压缩率百分比(0-100),如 65.2 表示体积减少 65.2%
|
|
97
|
+
*
|
|
98
|
+
* @description 计算公式: (1 - compressedSize / originalSize) * 100,保留一位小数。
|
|
99
|
+
* 当 originalSize 为 0 时返回 0,避免除零错误。
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* calcRatio(10000, 6000) // 40.0
|
|
104
|
+
* calcRatio(10000, 10000) // 0
|
|
105
|
+
* calcRatio(0, 0) // 0
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function calcRatio(originalSize: number, compressedSize: number): number;
|
|
91
109
|
|
|
92
|
-
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
110
|
+
export { calcRatio, formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
93
111
|
export type { DateFormatOptions };
|
|
@@ -88,6 +88,24 @@ declare function formatDate(date: Date, format: string): string;
|
|
|
88
88
|
* ```
|
|
89
89
|
*/
|
|
90
90
|
declare function formatFileSize(bytes: number): string;
|
|
91
|
+
/**
|
|
92
|
+
* 计算压缩率百分比
|
|
93
|
+
*
|
|
94
|
+
* @param {number} originalSize - 原始大小(字节)
|
|
95
|
+
* @param {number} compressedSize - 压缩后大小(字节)
|
|
96
|
+
* @returns {number} 压缩率百分比(0-100),如 65.2 表示体积减少 65.2%
|
|
97
|
+
*
|
|
98
|
+
* @description 计算公式: (1 - compressedSize / originalSize) * 100,保留一位小数。
|
|
99
|
+
* 当 originalSize 为 0 时返回 0,避免除零错误。
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* calcRatio(10000, 6000) // 40.0
|
|
104
|
+
* calcRatio(10000, 10000) // 0
|
|
105
|
+
* calcRatio(0, 0) // 0
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function calcRatio(originalSize: number, compressedSize: number): number;
|
|
91
109
|
|
|
92
|
-
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
110
|
+
export { calcRatio, formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
93
111
|
export type { DateFormatOptions };
|
|
@@ -88,6 +88,24 @@ declare function formatDate(date: Date, format: string): string;
|
|
|
88
88
|
* ```
|
|
89
89
|
*/
|
|
90
90
|
declare function formatFileSize(bytes: number): string;
|
|
91
|
+
/**
|
|
92
|
+
* 计算压缩率百分比
|
|
93
|
+
*
|
|
94
|
+
* @param {number} originalSize - 原始大小(字节)
|
|
95
|
+
* @param {number} compressedSize - 压缩后大小(字节)
|
|
96
|
+
* @returns {number} 压缩率百分比(0-100),如 65.2 表示体积减少 65.2%
|
|
97
|
+
*
|
|
98
|
+
* @description 计算公式: (1 - compressedSize / originalSize) * 100,保留一位小数。
|
|
99
|
+
* 当 originalSize 为 0 时返回 0,避免除零错误。
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* calcRatio(10000, 6000) // 40.0
|
|
104
|
+
* calcRatio(10000, 10000) // 0
|
|
105
|
+
* calcRatio(0, 0) // 0
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function calcRatio(originalSize: number, compressedSize: number): number;
|
|
91
109
|
|
|
92
|
-
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
110
|
+
export { calcRatio, formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
93
111
|
export type { DateFormatOptions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function n(t,e=2){return t.toString().padStart(e,"0")}function c(t=new Date){return{YYYY:t.getFullYear().toString(),YY:t.getFullYear().toString().slice(-2),MM:n(t.getMonth()+1),DD:n(t.getDate()),HH:n(t.getHours()),mm:n(t.getMinutes()),ss:n(t.getSeconds()),SSS:n(t.getMilliseconds(),3),timestamp:t.getTime().toString()}}function u(t,e){let r=t;for(const[o,i]of Object.entries(e)){const a=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=i.replace(/\$/g,"$$$$");r=r.replace(new RegExp(`\\{\\{${a}\\}\\}`,"g"),g)}return r}function s(t,e){const r=c(t);let o=e;for(const[i,a]of Object.entries(r))o=o.replace(new RegExp(`\\{${i}\\}`,"g"),a);return o}function l(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(2)}MB`}function f(t,e){return t>0?Number(((1-e/t)*100).toFixed(1)):0}export{f as calcRatio,s as formatDate,l as formatFileSize,c as getDateFormatParams,u as parseTemplate};
|
package/dist/common/fs/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const s=require("fs"),
|
|
1
|
+
"use strict";const s=require("fs"),o=require("path"),common_concurrency_index=require("../concurrency/index.cjs");function _interopDefaultCompat(t){return t&&typeof t=="object"&&"default"in t?t.default:t}const s__default=_interopDefaultCompat(s),o__default=_interopDefaultCompat(o),R=10;async function checkSourceExists(t){try{await s__default.promises.access(t,s__default.constants.F_OK)}catch(e){const u=e;throw u.code==="ENOENT"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${t}`):u.code==="EACCES"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6E90\u6587\u4EF6 - ${t}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u68C0\u67E5\u6E90\u6587\u4EF6\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${u.message}`)}}async function g(t){try{await s__default.promises.mkdir(t,{recursive:!0})}catch(e){const u=e;throw u.code==="EACCES"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u521B\u5EFA\u76EE\u6807\u76EE\u5F55 - ${t}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u521B\u5EFA\u76EE\u6807\u76EE\u5F55\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${u.message}`)}}async function C(t,e){const u=await s__default.promises.readdir(t,{withFileTypes:!0}),n=[];for(const a of u){const F=o__default.join(t,a.name),p=a.isFile(),f=a.isDirectory();if(n.push({path:F,isFile:p,isDirectory:f}),f&&e){const w=await C(F,e);n.push(...w)}}return n}async function h(t,e){try{const[u,n]=await Promise.all([s__default.promises.stat(t),s__default.promises.stat(e)]);return u.mtimeMs>n.mtimeMs||u.size!==n.size}catch{return!0}}async function D(t){try{return await s__default.promises.access(t,s__default.constants.F_OK),!0}catch{return!1}}async function copySourceToTarget(t,e,u){const n=Date.now(),{recursive:a,overwrite:F,incremental:p=!1,parallelLimit:f=R}=u;let w=0,l=0,c=0;if((await s__default.promises.stat(t)).isDirectory()){await g(e);const i=await C(t,a),E=i.filter(r=>r.isFile);c=i.filter(r=>r.isDirectory).length;const x=new Set;for(const r of E){const A=o__default.relative(t,r.path),d=o__default.dirname(o__default.join(e,A));x.add(d)}await Promise.all([...x].map(r=>g(r)));const S=await common_concurrency_index.runWithConcurrency(E,async r=>{const A=o__default.relative(t,r.path),d=o__default.join(e,A);let m=F;return m||(m=!await D(d)),p&&m&&(m=await h(r.path,d)),m?(await s__default.promises.copyFile(r.path,d),{copied:!0,skipped:!1}):{copied:!1,skipped:!0}},f);for(const r of S)r.copied&&w++,r.skipped&&l++}else{await g(o__default.dirname(e));let i=F;i||(i=!await D(e)),p&&i&&(i=await h(t,e)),i?(await s__default.promises.copyFile(t,e),w++):l++}const y=Date.now()-n;return{copiedFiles:w,skippedFiles:l,copiedDirs:c,executionTime:y}}async function writeFileContent(t,e){try{await s__default.promises.writeFile(t,e,"utf-8")}catch(u){const n=u;throw n.code==="EACCES"?new Error(`\u5199\u5165\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u5199\u5165\u6587\u4EF6 - ${t}`):new Error(`\u5199\u5165\u6587\u4EF6\u5931\u8D25\uFF1A\u5199\u5165\u6587\u4EF6\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${n.message}`)}}async function scanDirectory(t,e={}){const{includeExtensions:u=[],excludePatterns:n=[],filter:a}=e,F=[];async function p(f){const w=await s__default.promises.readdir(f,{withFileTypes:!0});for(const l of w){const c=o__default.join(f,l.name);if(l.isDirectory()){await p(c);continue}if(!l.isFile()||n.some(E=>E.startsWith("*")?c.endsWith(E.slice(1)):c.includes(E)))continue;const y=o__default.extname(l.name).toLowerCase();if(u.length>0&&!u.includes(y))continue;const i=await s__default.promises.stat(c);a&&!a(c,y,i.size)||F.push({filePath:c,size:i.size,extension:y})}}return await p(t),F}async function writeJsonReport(t,e,u=2){await writeFileContent(t,JSON.stringify(e,null,u))}function writeFileSyncSafely(t,e){const u=o__default.dirname(t);s__default.existsSync(u)||s__default.mkdirSync(u,{recursive:!0}),s__default.writeFileSync(t,e,"utf-8")}function shouldUpdateFileContent(t,e){if(!s__default.existsSync(t))return!0;try{return s__default.readFileSync(t,"utf-8")!==e}catch{return!0}}function resolveReportPath(t,e){return e?o__default.isAbsolute(e)?e:o__default.join(t,e):null}exports.checkSourceExists=checkSourceExists,exports.copySourceToTarget=copySourceToTarget,exports.resolveReportPath=resolveReportPath,exports.scanDirectory=scanDirectory,exports.shouldUpdateFileContent=shouldUpdateFileContent,exports.writeFileContent=writeFileContent,exports.writeFileSyncSafely=writeFileSyncSafely,exports.writeJsonReport=writeJsonReport;
|
|
@@ -160,6 +160,24 @@ declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
|
160
160
|
* ```
|
|
161
161
|
*/
|
|
162
162
|
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* 解析报告输出路径
|
|
165
|
+
*
|
|
166
|
+
* @param {string} outDir - 构建输出目录路径
|
|
167
|
+
* @param {string | false} reportPath - 报告文件路径,为 false 时返回 null
|
|
168
|
+
* @returns {string | null} 解析后的绝对路径,reportPath 为 false 时返回 null
|
|
169
|
+
*
|
|
170
|
+
* @description 当 reportPath 为相对路径时,相对于 outDir 解析;
|
|
171
|
+
* 为绝对路径时直接使用;为 false 时返回 null。
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* resolveReportPath('dist', 'report.json') // 'dist/report.json'
|
|
176
|
+
* resolveReportPath('dist', '/tmp/r.json') // '/tmp/r.json'
|
|
177
|
+
* resolveReportPath('dist', false) // null
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function resolveReportPath(outDir: string, reportPath: string | false): string | null;
|
|
163
181
|
|
|
164
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
182
|
+
export { checkSourceExists, copySourceToTarget, resolveReportPath, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
165
183
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
|
@@ -160,6 +160,24 @@ declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
|
160
160
|
* ```
|
|
161
161
|
*/
|
|
162
162
|
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* 解析报告输出路径
|
|
165
|
+
*
|
|
166
|
+
* @param {string} outDir - 构建输出目录路径
|
|
167
|
+
* @param {string | false} reportPath - 报告文件路径,为 false 时返回 null
|
|
168
|
+
* @returns {string | null} 解析后的绝对路径,reportPath 为 false 时返回 null
|
|
169
|
+
*
|
|
170
|
+
* @description 当 reportPath 为相对路径时,相对于 outDir 解析;
|
|
171
|
+
* 为绝对路径时直接使用;为 false 时返回 null。
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* resolveReportPath('dist', 'report.json') // 'dist/report.json'
|
|
176
|
+
* resolveReportPath('dist', '/tmp/r.json') // '/tmp/r.json'
|
|
177
|
+
* resolveReportPath('dist', false) // null
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function resolveReportPath(outDir: string, reportPath: string | false): string | null;
|
|
163
181
|
|
|
164
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
182
|
+
export { checkSourceExists, copySourceToTarget, resolveReportPath, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
165
183
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
|
@@ -160,6 +160,24 @@ declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
|
160
160
|
* ```
|
|
161
161
|
*/
|
|
162
162
|
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* 解析报告输出路径
|
|
165
|
+
*
|
|
166
|
+
* @param {string} outDir - 构建输出目录路径
|
|
167
|
+
* @param {string | false} reportPath - 报告文件路径,为 false 时返回 null
|
|
168
|
+
* @returns {string | null} 解析后的绝对路径,reportPath 为 false 时返回 null
|
|
169
|
+
*
|
|
170
|
+
* @description 当 reportPath 为相对路径时,相对于 outDir 解析;
|
|
171
|
+
* 为绝对路径时直接使用;为 false 时返回 null。
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* resolveReportPath('dist', 'report.json') // 'dist/report.json'
|
|
176
|
+
* resolveReportPath('dist', '/tmp/r.json') // '/tmp/r.json'
|
|
177
|
+
* resolveReportPath('dist', false) // null
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function resolveReportPath(outDir: string, reportPath: string | false): string | null;
|
|
163
181
|
|
|
164
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
182
|
+
export { checkSourceExists, copySourceToTarget, resolveReportPath, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
165
183
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
package/dist/common/fs/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import i from"fs";import s from"path";import{runWithConcurrency as v}from"../concurrency/index.mjs";const B=10;async function k(t){try{await i.promises.access(t,i.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 - ${t}`):e.code==="EACCES"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u8BBF\u95EE\u6E90\u6587\u4EF6 - ${t}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u68C0\u67E5\u6E90\u6587\u4EF6\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${e.message}`)}}async function D(t){try{await i.promises.mkdir(t,{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 - ${t}`):new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u521B\u5EFA\u76EE\u6807\u76EE\u5F55\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${e.message}`)}}async function C(t,u){const e=await i.promises.readdir(t,{withFileTypes:!0}),r=[];for(const c of e){const F=s.join(t,c.name),E=c.isFile(),p=c.isDirectory();if(r.push({path:F,isFile:E,isDirectory:p}),p&&u){const w=await C(F,u);r.push(...w)}}return r}async function S(t,u){try{const[e,r]=await Promise.all([i.promises.stat(t),i.promises.stat(u)]);return e.mtimeMs>r.mtimeMs||e.size!==r.size}catch{return!0}}async function x(t){try{return await i.promises.access(t,i.constants.F_OK),!0}catch{return!1}}async function T(t,u,e){const r=Date.now(),{recursive:c,overwrite:F,incremental:E=!1,parallelLimit:p=B}=e;let w=0,l=0,a=0;if((await i.promises.stat(t)).isDirectory()){await D(u);const o=await C(t,c),f=o.filter(n=>n.isFile);a=o.filter(n=>n.isDirectory).length;const A=new Set;for(const n of f){const h=s.relative(t,n.path),y=s.dirname(s.join(u,h));A.add(y)}await Promise.all([...A].map(n=>D(n)));const g=await v(f,async n=>{const h=s.relative(t,n.path),y=s.join(u,h);let d=F;return d||(d=!await x(y)),E&&d&&(d=await S(n.path,y)),d?(await i.promises.copyFile(n.path,y),{copied:!0,skipped:!1}):{copied:!1,skipped:!0}},p);for(const n of g)n.copied&&w++,n.skipped&&l++}else{await D(s.dirname(u));let o=F;o||(o=!await x(u)),E&&o&&(o=await S(t,u)),o?(await i.promises.copyFile(t,u),w++):l++}const m=Date.now()-r;return{copiedFiles:w,skippedFiles:l,copiedDirs:a,executionTime:m}}async function $(t,u){try{await i.promises.writeFile(t,u,"utf-8")}catch(e){const r=e;throw r.code==="EACCES"?new Error(`\u5199\u5165\u6587\u4EF6\u5931\u8D25\uFF1A\u6CA1\u6709\u6743\u9650\u5199\u5165\u6587\u4EF6 - ${t}`):new Error(`\u5199\u5165\u6587\u4EF6\u5931\u8D25\uFF1A\u5199\u5165\u6587\u4EF6\u65F6\u51FA\u9519 - ${t}\uFF0C\u9519\u8BEF\uFF1A${r.message}`)}}async function j(t,u={}){const{includeExtensions:e=[],excludePatterns:r=[],filter:c}=u,F=[];async function E(p){const w=await i.promises.readdir(p,{withFileTypes:!0});for(const l of w){const a=s.join(p,l.name);if(l.isDirectory()){await E(a);continue}if(!l.isFile()||r.some(f=>f.startsWith("*")?a.endsWith(f.slice(1)):a.includes(f)))continue;const m=s.extname(l.name).toLowerCase();if(e.length>0&&!e.includes(m))continue;const o=await i.promises.stat(a);c&&!c(a,m,o.size)||F.push({filePath:a,size:o.size,extension:m})}}return await E(t),F}async function z(t,u,e=2){await $(t,JSON.stringify(u,null,e))}function P(t,u){const e=s.dirname(t);i.existsSync(e)||i.mkdirSync(e,{recursive:!0}),i.writeFileSync(t,u,"utf-8")}function O(t,u){if(!i.existsSync(t))return!0;try{return i.readFileSync(t,"utf-8")!==u}catch{return!0}}function N(t,u){return u?s.isAbsolute(u)?u:s.join(t,u):null}export{k as checkSourceExists,T as copySourceToTarget,N as resolveReportPath,j as scanDirectory,O as shouldUpdateFileContent,$ as writeFileContent,P as writeFileSyncSafely,z as writeJsonReport};
|
package/dist/common/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const common_format_index=require("./format/index.cjs"),common_fs_index=require("./fs/index.cjs"),common_html_index=require("./html/index.cjs"),common_script_index=require("./script/index.cjs"),common_ui_index=require("./ui/index.cjs"),validator=require("../shared/vite-plugin.Bcg6RW2N.cjs"),common_validation_index=require("./validation/index.cjs"),security=require("../shared/vite-plugin.CcvHfrL8.cjs");require("fs"),require("path"),exports.formatDate=common_format_index.formatDate,exports.formatFileSize=common_format_index.formatFileSize,exports.getDateFormatParams=common_format_index.getDateFormatParams,exports.parseTemplate=common_format_index.parseTemplate,exports.checkSourceExists=common_fs_index.checkSourceExists,exports.copySourceToTarget=common_fs_index.copySourceToTarget,exports.scanDirectory=common_fs_index.scanDirectory,exports.shouldUpdateFileContent=common_fs_index.shouldUpdateFileContent,exports.writeFileContent=common_fs_index.writeFileContent,exports.writeFileSyncSafely=common_fs_index.writeFileSyncSafely,exports.writeJsonReport=common_fs_index.writeJsonReport,exports.injectBeforeTag=common_html_index.injectBeforeTag,exports.injectHeadAndBody=common_html_index.injectHeadAndBody,exports.makeCallback=common_script_index.makeCallback,exports.ANSI=common_ui_index.ANSI,exports.Validator=validator.Validator,exports.validateCallbackFields=common_validation_index.validateCallbackFields,exports.validateGlobalName=common_validation_index.validateGlobalName,exports.validateNoScriptInTemplate=common_validation_index.validateNoScriptInTemplate,exports.escapeHtmlAttr=security.escapeHtmlAttr,exports.sanitizeContent=security.sanitizeContent;
|
|
1
|
+
"use strict";const common_concurrency_index=require("./concurrency/index.cjs"),common_format_index=require("./format/index.cjs"),common_fs_index=require("./fs/index.cjs"),common_html_index=require("./html/index.cjs"),common_path_index=require("./path/index.cjs"),common_script_index=require("./script/index.cjs"),common_ui_index=require("./ui/index.cjs"),validator=require("../shared/vite-plugin.Bcg6RW2N.cjs"),common_validation_index=require("./validation/index.cjs"),security=require("../shared/vite-plugin.CcvHfrL8.cjs");require("fs"),require("path"),exports.runWithConcurrency=common_concurrency_index.runWithConcurrency,exports.calcRatio=common_format_index.calcRatio,exports.formatDate=common_format_index.formatDate,exports.formatFileSize=common_format_index.formatFileSize,exports.getDateFormatParams=common_format_index.getDateFormatParams,exports.parseTemplate=common_format_index.parseTemplate,exports.checkSourceExists=common_fs_index.checkSourceExists,exports.copySourceToTarget=common_fs_index.copySourceToTarget,exports.resolveReportPath=common_fs_index.resolveReportPath,exports.scanDirectory=common_fs_index.scanDirectory,exports.shouldUpdateFileContent=common_fs_index.shouldUpdateFileContent,exports.writeFileContent=common_fs_index.writeFileContent,exports.writeFileSyncSafely=common_fs_index.writeFileSyncSafely,exports.writeJsonReport=common_fs_index.writeJsonReport,exports.injectBeforeTag=common_html_index.injectBeforeTag,exports.injectHeadAndBody=common_html_index.injectHeadAndBody,exports.isExtensionIncluded=common_path_index.isExtensionIncluded,exports.isPathExcluded=common_path_index.isPathExcluded,exports.isPreCompressed=common_path_index.isPreCompressed,exports.normalizePath=common_path_index.normalizePath,exports.makeCallback=common_script_index.makeCallback,exports.ANSI=common_ui_index.ANSI,exports.Validator=validator.Validator,exports.validateCallbackFields=common_validation_index.validateCallbackFields,exports.validateGlobalName=common_validation_index.validateGlobalName,exports.validateNoScriptInTemplate=common_validation_index.validateNoScriptInTemplate,exports.escapeHtmlAttr=security.escapeHtmlAttr,exports.sanitizeContent=security.sanitizeContent;
|