@meng-xi/vite-plugin 0.1.5 → 0.1.7
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 +33 -15
- package/README.md +33 -15
- package/dist/common/format/index.cjs +1 -1
- package/dist/common/format/index.d.cts +35 -1
- package/dist/common/format/index.d.mts +35 -1
- package/dist/common/format/index.d.ts +35 -1
- package/dist/common/format/index.mjs +1 -1
- package/dist/common/fs/index.cjs +1 -1
- package/dist/common/fs/index.d.cts +36 -1
- package/dist/common/fs/index.d.mts +36 -1
- package/dist/common/fs/index.d.ts +36 -1
- package/dist/common/fs/index.mjs +1 -1
- package/dist/common/html/index.cjs +2 -2
- package/dist/common/html/index.d.cts +17 -1
- package/dist/common/html/index.d.mts +17 -1
- package/dist/common/html/index.d.ts +17 -1
- package/dist/common/html/index.mjs +2 -2
- package/dist/common/index.cjs +1 -1
- package/dist/common/index.d.cts +4 -3
- package/dist/common/index.d.mts +4 -3
- package/dist/common/index.d.ts +4 -3
- 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 +5 -3
- package/dist/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- 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 +7 -5
- package/dist/plugins/autoImport/index.mjs +9 -7
- package/dist/plugins/buildProgress/index.cjs +2 -2
- package/dist/plugins/bundleAnalyzer/index.cjs +21 -21
- 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/envGuard/index.cjs +9 -9
- package/dist/plugins/envGuard/index.mjs +7 -7
- package/dist/plugins/faviconManager/index.cjs +1 -1
- package/dist/plugins/faviconManager/index.mjs +1 -1
- package/dist/plugins/generateRouter/index.cjs +5 -4
- package/dist/plugins/generateRouter/index.d.cts +33 -0
- package/dist/plugins/generateRouter/index.d.mts +33 -0
- package/dist/plugins/generateRouter/index.d.ts +33 -0
- package/dist/plugins/generateRouter/index.mjs +3 -2
- 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/index.cjs +1 -1
- package/dist/plugins/index.d.cts +1 -0
- package/dist/plugins/index.d.mts +1 -0
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.mjs +1 -1
- package/dist/plugins/loadingManager/index.cjs +5 -5
- package/dist/plugins/loadingManager/index.mjs +4 -4
- package/dist/plugins/versionUpdateChecker/index.cjs +4 -4
- package/dist/plugins/versionUpdateChecker/index.mjs +4 -4
- package/dist/shared/vite-plugin.CcvHfrL8.cjs +1 -0
- package/dist/shared/vite-plugin.CuXEJAWX.mjs +1 -0
- package/package.json +12 -2
- package/dist/shared/vite-plugin.BPFqtmWa.mjs +0 -1
- package/dist/shared/vite-plugin.CnOy46d3.cjs +0 -1
package/README-en.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
- **Ready to Use** - 12 practical plugins covering auto-import, build progress, bundle analysis & compression, file copying, environment variable validation, route generation, version management, HTML injection, favicon
|
|
19
19
|
management, global Loading, 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 Common utility modules supporting on-demand sub-path imports
|
|
21
|
+
- **Common Utility Library** - Built-in 7 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,7 @@ pnpm add @meng-xi/vite-plugin -D
|
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
43
|
import { defineConfig } from 'vite'
|
|
44
|
-
import { buildProgress, bundleAnalyzer, compressAssets, copyFile, envGuard, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager
|
|
44
|
+
import { autoImport, buildProgress, bundleAnalyzer, compressAssets, copyFile, envGuard, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
|
|
45
45
|
|
|
46
46
|
export default defineConfig({
|
|
47
47
|
plugins: [
|
|
@@ -70,9 +70,9 @@ export default defineConfig({
|
|
|
70
70
|
| [bundleAnalyzer](https://mengxi-studio.github.io/vite-plugin/en/plugins/bundle-analyzer.html) | Bundle volume analysis with JSON/HTML reports, gzip calculation, threshold alerts, and build diff |
|
|
71
71
|
| [compressAssets](https://mengxi-studio.github.io/vite-plugin/en/plugins/compress-assets.html) | Asset compression with gzip / brotli / both, concurrent compression and statistics report |
|
|
72
72
|
| [copyFile](https://mengxi-studio.github.io/vite-plugin/en/plugins/copy-file.html) | Copy files or directories after build, supports incremental copying |
|
|
73
|
-
| [envGuard](https://mengxi-studio.github.io/vite-plugin/en/plugins/)
|
|
73
|
+
| [envGuard](https://mengxi-studio.github.io/vite-plugin/en/plugins/env-guard.html) | Environment variable validation with type checking, range validation, custom rules and runtime guard |
|
|
74
74
|
| [faviconManager](https://mengxi-studio.github.io/vite-plugin/en/plugins/favicon-manager.html) | Manage website favicon link injection and file copying, supports string shorthand config |
|
|
75
|
-
| [generateRouter](https://mengxi-studio.github.io/vite-plugin/en/plugins/generate-router.html) | Auto-generate route config from pages.json (uni-app)
|
|
75
|
+
| [generateRouter](https://mengxi-studio.github.io/vite-plugin/en/plugins/generate-router.html) | Auto-generate route config and type declarations from pages.json (uni-app) |
|
|
76
76
|
| [generateVersion](https://mengxi-studio.github.io/vite-plugin/en/plugins/generate-version.html) | Auto-generate version numbers with file output and global variable injection |
|
|
77
77
|
| [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
78
|
| [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 |
|
|
@@ -132,19 +132,37 @@ export const myPlugin = createPluginFactory(MyPlugin)
|
|
|
132
132
|
Built-in general-purpose utility function library, organized by functional modules, supporting on-demand sub-path imports.
|
|
133
133
|
|
|
134
134
|
```typescript
|
|
135
|
-
|
|
136
|
-
import {
|
|
137
|
-
|
|
135
|
+
// Formatting: date params, template variable replacement, file size, date formatting
|
|
136
|
+
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize } from '@meng-xi/vite-plugin/common/format'
|
|
137
|
+
|
|
138
|
+
// File system: file copy, directory scan, safe write, change detection
|
|
139
|
+
import { copySourceToTarget, scanDirectory, writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
|
|
140
|
+
|
|
141
|
+
// HTML: tag injection, content sanitization, attribute escaping
|
|
142
|
+
import { injectBeforeTag, injectHeadAndBody, sanitizeContent, escapeHtmlAttr } from '@meng-xi/vite-plugin/common/html'
|
|
143
|
+
|
|
144
|
+
// Script generation: callback function wrapping
|
|
145
|
+
import { makeCallback } from '@meng-xi/vite-plugin/common/script'
|
|
146
|
+
|
|
147
|
+
// Terminal UI: ANSI color codes
|
|
148
|
+
import { ANSI } from '@meng-xi/vite-plugin/common/ui'
|
|
149
|
+
|
|
150
|
+
// Validation: chain validator, common validation functions
|
|
151
|
+
import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng-xi/vite-plugin/common/validation'
|
|
152
|
+
|
|
153
|
+
// Path: path normalization, extension filtering, path exclusion matching, pre-compression detection
|
|
154
|
+
import { normalizePath, isExtensionIncluded, isPathExcluded, isPreCompressed } from '@meng-xi/vite-plugin/common/path'
|
|
138
155
|
```
|
|
139
156
|
|
|
140
|
-
| Sub-path | Description
|
|
141
|
-
| -------------------------------------------------------------------------------------------- |
|
|
142
|
-
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/en/common/format.html) |
|
|
143
|
-
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/en/common/fs.html) | File
|
|
144
|
-
| [`common/html`](https://mengxi-studio.github.io/vite-plugin/en/common/html.html) | HTML injection
|
|
145
|
-
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/en/common/script.html) |
|
|
146
|
-
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/en/common/ui.html) | Terminal
|
|
147
|
-
| [`common/validation`](https://mengxi-studio.github.io/vite-plugin/en/common/validation.html) |
|
|
157
|
+
| Sub-path | Description |
|
|
158
|
+
| -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
159
|
+
| [`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 |
|
|
160
|
+
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/en/common/fs.html) | File/directory copy, directory scan, sync safe write, file change detection |
|
|
161
|
+
| [`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 |
|
|
162
|
+
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/en/common/script.html) | Callback body wrapping into safe function expressions (with try-catch) |
|
|
163
|
+
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/en/common/ui.html) | Terminal ANSI color code constants |
|
|
164
|
+
| [`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 |
|
|
165
|
+
| [`common/path`](https://mengxi-studio.github.io/vite-plugin/en/common/path.html) | Path normalization, extension filtering, path exclusion matching, pre-compression format detection |
|
|
148
166
|
|
|
149
167
|
## Sub-path Exports
|
|
150
168
|
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
- **开箱即用** - 12 个实用插件,覆盖自动导入、构建进度、产物分析与压缩、文件复制、环境变量校验、路由生成、版本管理、HTML 注入、图标管理、全局 Loading 等场景
|
|
19
19
|
- **插件开发框架** - 导出 BasePlugin、Logger、Validator 等核心组件,快速构建自定义 Vite 插件
|
|
20
|
-
- **通用工具库** - 内置 Common 工具模块,支持按需子路径导入
|
|
20
|
+
- **通用工具库** - 内置 7 大 Common 工具模块,支持按需子路径导入
|
|
21
21
|
- **类型安全** - 完整 TypeScript 类型定义与配置验证器
|
|
22
22
|
- **按需导入** - 支持子路径导出,减少打包体积
|
|
23
23
|
|
|
@@ -40,7 +40,7 @@ pnpm add @meng-xi/vite-plugin -D
|
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
import { defineConfig } from 'vite'
|
|
43
|
-
import { buildProgress, bundleAnalyzer, compressAssets, copyFile, envGuard, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager
|
|
43
|
+
import { autoImport, buildProgress, bundleAnalyzer, compressAssets, copyFile, envGuard, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
|
|
44
44
|
|
|
45
45
|
export default defineConfig({
|
|
46
46
|
plugins: [
|
|
@@ -69,9 +69,9 @@ export default defineConfig({
|
|
|
69
69
|
| [bundleAnalyzer](https://mengxi-studio.github.io/vite-plugin/plugins/bundle-analyzer.html) | 构建产物体积分析,支持 JSON/HTML 报告、gzip 计算、阈值告警和构建对比 |
|
|
70
70
|
| [compressAssets](https://mengxi-studio.github.io/vite-plugin/plugins/compress-assets.html) | 构建产物压缩,支持 gzip / brotli / both,并发压缩和统计报告 |
|
|
71
71
|
| [copyFile](https://mengxi-studio.github.io/vite-plugin/plugins/copy-file.html) | 构建完成后复制文件或目录,支持增量复制 |
|
|
72
|
-
| [envGuard](https://mengxi-studio.github.io/vite-plugin/plugins/)
|
|
72
|
+
| [envGuard](https://mengxi-studio.github.io/vite-plugin/plugins/env-guard.html) | 环境变量校验,支持类型检查、范围验证、自定义规则和运行时守卫 |
|
|
73
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
|
|
74
|
+
| [generateRouter](https://mengxi-studio.github.io/vite-plugin/plugins/generate-router.html) | 根据 pages.json 自动生成路由配置与类型声明(uni-app) |
|
|
75
75
|
| [generateVersion](https://mengxi-studio.github.io/vite-plugin/plugins/generate-version.html) | 自动生成版本号,支持文件输出和全局变量注入 |
|
|
76
76
|
| [htmlInject](https://mengxi-studio.github.io/vite-plugin/plugins/html-inject.html) | HTML 内容注入,支持多种位置、选择器定位、条件注入、模板变量和安全过滤 |
|
|
77
77
|
| [loadingManager](https://mengxi-studio.github.io/vite-plugin/plugins/loading-manager.html) | 全局 Loading 状态管理,支持请求拦截、防抖、过渡动画和白屏 Loading |
|
|
@@ -131,19 +131,37 @@ export const myPlugin = createPluginFactory(MyPlugin)
|
|
|
131
131
|
内置通用工具函数库,按功能模块组织,支持子路径按需导入。
|
|
132
132
|
|
|
133
133
|
```typescript
|
|
134
|
-
|
|
135
|
-
import {
|
|
136
|
-
|
|
134
|
+
// 格式化:日期参数、模板变量替换、文件大小、日期格式化
|
|
135
|
+
import { getDateFormatParams, parseTemplate, formatDate, formatFileSize } from '@meng-xi/vite-plugin/common/format'
|
|
136
|
+
|
|
137
|
+
// 文件系统:文件复制、目录扫描、安全写入、变更检测
|
|
138
|
+
import { copySourceToTarget, scanDirectory, writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
|
|
139
|
+
|
|
140
|
+
// HTML:标签注入、内容消毒、属性转义
|
|
141
|
+
import { injectBeforeTag, injectHeadAndBody, sanitizeContent, escapeHtmlAttr } from '@meng-xi/vite-plugin/common/html'
|
|
142
|
+
|
|
143
|
+
// 脚本生成:回调函数包装
|
|
144
|
+
import { makeCallback } from '@meng-xi/vite-plugin/common/script'
|
|
145
|
+
|
|
146
|
+
// 终端 UI:ANSI 颜色码
|
|
147
|
+
import { ANSI } from '@meng-xi/vite-plugin/common/ui'
|
|
148
|
+
|
|
149
|
+
// 参数验证:链式验证器、通用校验函数
|
|
150
|
+
import { Validator, validateGlobalName, validateNoScriptInTemplate } from '@meng-xi/vite-plugin/common/validation'
|
|
151
|
+
|
|
152
|
+
// 路径处理:路径规范化、扩展名过滤、路径排除匹配、预压缩检测
|
|
153
|
+
import { normalizePath, isExtensionIncluded, isPathExcluded, isPreCompressed } from '@meng-xi/vite-plugin/common/path'
|
|
137
154
|
```
|
|
138
155
|
|
|
139
|
-
| 子路径 | 描述
|
|
140
|
-
| ----------------------------------------------------------------------------------------- |
|
|
141
|
-
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/common/format.html) |
|
|
142
|
-
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/common/fs.html) |
|
|
143
|
-
| [`common/html`](https://mengxi-studio.github.io/vite-plugin/common/html.html) | HTML
|
|
144
|
-
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/common/script.html) |
|
|
145
|
-
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/common/ui.html) | 终端
|
|
146
|
-
| [`common/validation`](https://mengxi-studio.github.io/vite-plugin/common/validation.html) |
|
|
156
|
+
| 子路径 | 描述 |
|
|
157
|
+
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
158
|
+
| [`common/format`](https://mengxi-studio.github.io/vite-plugin/common/format.html) | 日期参数提取、模板变量替换 `{{key}}`、日期格式化 `{YYYY}`、文件大小格式化 |
|
|
159
|
+
| [`common/fs`](https://mengxi-studio.github.io/vite-plugin/common/fs.html) | 文件/目录复制、目录扫描、同步安全写入、文件变更检测 |
|
|
160
|
+
| [`common/html`](https://mengxi-studio.github.io/vite-plugin/common/html.html) | HTML 标签注入、双区域注入、内容安全消毒、HTML 属性值转义 |
|
|
161
|
+
| [`common/script`](https://mengxi-studio.github.io/vite-plugin/common/script.html) | 回调函数体包装为安全的函数表达式(含 try-catch) |
|
|
162
|
+
| [`common/ui`](https://mengxi-studio.github.io/vite-plugin/common/ui.html) | 终端 ANSI 颜色码常量 |
|
|
163
|
+
| [`common/validation`](https://mengxi-studio.github.io/vite-plugin/common/validation.html) | 链式配置验证器、全局名称校验、脚本检测、回调字段校验 |
|
|
164
|
+
| [`common/path`](https://mengxi-studio.github.io/vite-plugin/common/path.html) | 路径规范化、扩展名过滤、路径排除匹配、预压缩格式检测 |
|
|
147
165
|
|
|
148
166
|
## 子路径导出
|
|
149
167
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";function
|
|
1
|
+
"use strict";function t(e,r=2){return e.toString().padStart(r,"0")}function getDateFormatParams(e=new Date){return{YYYY:e.getFullYear().toString(),YY:e.getFullYear().toString().slice(-2),MM:t(e.getMonth()+1),DD:t(e.getDate()),HH:t(e.getHours()),mm:t(e.getMinutes()),ss:t(e.getSeconds()),SSS:t(e.getMilliseconds(),3),timestamp:e.getTime().toString()}}function parseTemplate(e,r){let o=e;for(const[n,a]of Object.entries(r)){const s=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=a.replace(/\$/g,"$$$$");o=o.replace(new RegExp(`\\{\\{${s}\\}\\}`,"g"),i)}return o}function formatDate(e,r){const o=getDateFormatParams(e);let n=r;for(const[a,s]of Object.entries(o))n=n.replace(new RegExp(`\\{${a}\\}`,"g"),s);return n}function formatFileSize(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(2)}MB`}exports.formatDate=formatDate,exports.formatFileSize=formatFileSize,exports.getDateFormatParams=getDateFormatParams,exports.parseTemplate=parseTemplate;
|
|
@@ -35,6 +35,40 @@ interface DateFormatOptions {
|
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
37
|
declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
38
|
+
/**
|
|
39
|
+
* 替换模板字符串中的变量占位符
|
|
40
|
+
*
|
|
41
|
+
* @param template - 包含 `{{key}}` 占位符的模板字符串
|
|
42
|
+
* @param values - 占位符键值映射,支持合并多组变量(后者覆盖前者)
|
|
43
|
+
* @returns 替换占位符后的字符串
|
|
44
|
+
*
|
|
45
|
+
* @description 将模板中的 `{{key}}` 占位符替换为对应的值。
|
|
46
|
+
* 键名中的正则特殊字符会被自动转义,值中的 `$` 也会被安全处理。
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* parseTemplate('Hello {{name}}!', { name: 'World' })
|
|
51
|
+
* // 'Hello World!'
|
|
52
|
+
*
|
|
53
|
+
* parseTemplate('{{YYYY}}-{{MM}}-{{DD}}', getDateFormatParams())
|
|
54
|
+
* // '2026-06-06'
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function parseTemplate(template: string, values: Record<string, string>): string;
|
|
58
|
+
/**
|
|
59
|
+
* 格式化日期字符串
|
|
60
|
+
*
|
|
61
|
+
* @param date - 日期对象
|
|
62
|
+
* @param format - 格式字符串,支持 `{YYYY}`、`{MM}`、`{DD}`、`{HH}`、`{mm}`、`{ss}` 等占位符
|
|
63
|
+
* @returns 格式化后的日期字符串
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* formatDate(new Date(), '{YYYY}-{MM}-{DD}T{HH}:{mm}:{ss}')
|
|
68
|
+
* // '2026-06-06T15:30:00'
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function formatDate(date: Date, format: string): string;
|
|
38
72
|
/**
|
|
39
73
|
* 将字节数格式化为人类可读的文件大小字符串
|
|
40
74
|
*
|
|
@@ -55,5 +89,5 @@ declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
|
55
89
|
*/
|
|
56
90
|
declare function formatFileSize(bytes: number): string;
|
|
57
91
|
|
|
58
|
-
export { formatFileSize, getDateFormatParams };
|
|
92
|
+
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
59
93
|
export type { DateFormatOptions };
|
|
@@ -35,6 +35,40 @@ interface DateFormatOptions {
|
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
37
|
declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
38
|
+
/**
|
|
39
|
+
* 替换模板字符串中的变量占位符
|
|
40
|
+
*
|
|
41
|
+
* @param template - 包含 `{{key}}` 占位符的模板字符串
|
|
42
|
+
* @param values - 占位符键值映射,支持合并多组变量(后者覆盖前者)
|
|
43
|
+
* @returns 替换占位符后的字符串
|
|
44
|
+
*
|
|
45
|
+
* @description 将模板中的 `{{key}}` 占位符替换为对应的值。
|
|
46
|
+
* 键名中的正则特殊字符会被自动转义,值中的 `$` 也会被安全处理。
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* parseTemplate('Hello {{name}}!', { name: 'World' })
|
|
51
|
+
* // 'Hello World!'
|
|
52
|
+
*
|
|
53
|
+
* parseTemplate('{{YYYY}}-{{MM}}-{{DD}}', getDateFormatParams())
|
|
54
|
+
* // '2026-06-06'
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function parseTemplate(template: string, values: Record<string, string>): string;
|
|
58
|
+
/**
|
|
59
|
+
* 格式化日期字符串
|
|
60
|
+
*
|
|
61
|
+
* @param date - 日期对象
|
|
62
|
+
* @param format - 格式字符串,支持 `{YYYY}`、`{MM}`、`{DD}`、`{HH}`、`{mm}`、`{ss}` 等占位符
|
|
63
|
+
* @returns 格式化后的日期字符串
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* formatDate(new Date(), '{YYYY}-{MM}-{DD}T{HH}:{mm}:{ss}')
|
|
68
|
+
* // '2026-06-06T15:30:00'
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function formatDate(date: Date, format: string): string;
|
|
38
72
|
/**
|
|
39
73
|
* 将字节数格式化为人类可读的文件大小字符串
|
|
40
74
|
*
|
|
@@ -55,5 +89,5 @@ declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
|
55
89
|
*/
|
|
56
90
|
declare function formatFileSize(bytes: number): string;
|
|
57
91
|
|
|
58
|
-
export { formatFileSize, getDateFormatParams };
|
|
92
|
+
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
59
93
|
export type { DateFormatOptions };
|
|
@@ -35,6 +35,40 @@ interface DateFormatOptions {
|
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
37
|
declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
38
|
+
/**
|
|
39
|
+
* 替换模板字符串中的变量占位符
|
|
40
|
+
*
|
|
41
|
+
* @param template - 包含 `{{key}}` 占位符的模板字符串
|
|
42
|
+
* @param values - 占位符键值映射,支持合并多组变量(后者覆盖前者)
|
|
43
|
+
* @returns 替换占位符后的字符串
|
|
44
|
+
*
|
|
45
|
+
* @description 将模板中的 `{{key}}` 占位符替换为对应的值。
|
|
46
|
+
* 键名中的正则特殊字符会被自动转义,值中的 `$` 也会被安全处理。
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* parseTemplate('Hello {{name}}!', { name: 'World' })
|
|
51
|
+
* // 'Hello World!'
|
|
52
|
+
*
|
|
53
|
+
* parseTemplate('{{YYYY}}-{{MM}}-{{DD}}', getDateFormatParams())
|
|
54
|
+
* // '2026-06-06'
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function parseTemplate(template: string, values: Record<string, string>): string;
|
|
58
|
+
/**
|
|
59
|
+
* 格式化日期字符串
|
|
60
|
+
*
|
|
61
|
+
* @param date - 日期对象
|
|
62
|
+
* @param format - 格式字符串,支持 `{YYYY}`、`{MM}`、`{DD}`、`{HH}`、`{mm}`、`{ss}` 等占位符
|
|
63
|
+
* @returns 格式化后的日期字符串
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* formatDate(new Date(), '{YYYY}-{MM}-{DD}T{HH}:{mm}:{ss}')
|
|
68
|
+
* // '2026-06-06T15:30:00'
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function formatDate(date: Date, format: string): string;
|
|
38
72
|
/**
|
|
39
73
|
* 将字节数格式化为人类可读的文件大小字符串
|
|
40
74
|
*
|
|
@@ -55,5 +89,5 @@ declare function getDateFormatParams(date?: Date): DateFormatOptions;
|
|
|
55
89
|
*/
|
|
56
90
|
declare function formatFileSize(bytes: number): string;
|
|
57
91
|
|
|
58
|
-
export { formatFileSize, getDateFormatParams };
|
|
92
|
+
export { formatDate, formatFileSize, getDateFormatParams, parseTemplate };
|
|
59
93
|
export type { DateFormatOptions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function t
|
|
1
|
+
function e(t,n=2){return t.toString().padStart(n,"0")}function g(t=new Date){return{YYYY:t.getFullYear().toString(),YY:t.getFullYear().toString().slice(-2),MM:e(t.getMonth()+1),DD:e(t.getDate()),HH:e(t.getHours()),mm:e(t.getMinutes()),ss:e(t.getSeconds()),SSS:e(t.getMilliseconds(),3),timestamp:t.getTime().toString()}}function c(t,n){let r=t;for(const[o,i]of Object.entries(n)){const a=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),s=i.replace(/\$/g,"$$$$");r=r.replace(new RegExp(`\\{\\{${a}\\}\\}`,"g"),s)}return r}function l(t,n){const r=g(t);let o=n;for(const[i,a]of Object.entries(r))o=o.replace(new RegExp(`\\{${i}\\}`,"g"),a);return o}function u(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(2)}MB`}export{l as formatDate,u as formatFileSize,g as getDateFormatParams,c as parseTemplate};
|
package/dist/common/fs/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const
|
|
1
|
+
"use strict";const s=require("fs"),u=require("path");function _interopDefaultCompat(t){return t&&typeof t=="object"&&"default"in t?t.default:t}const s__default=_interopDefaultCompat(s),u__default=_interopDefaultCompat(u),R=10;async function checkSourceExists(t){try{await s__default.promises.access(t,s__default.constants.F_OK)}catch(e){const i=e;throw i.code==="ENOENT"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${t}`):i.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${i.message}`)}}async function g(t){try{await s__default.promises.mkdir(t,{recursive:!0})}catch(e){const i=e;throw i.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${i.message}`)}}async function h(t,e){const i=await s__default.promises.readdir(t,{withFileTypes:!0}),r=[];for(const o of i){const c=u__default.join(t,o.name),l=o.isFile(),F=o.isDirectory();if(r.push({path:c,isFile:l,isDirectory:F}),F&&e){const p=await h(c,e);r.push(...p)}}return r}async function C(t,e){try{const[i,r]=await Promise.all([s__default.promises.stat(t),s__default.promises.stat(e)]);return i.mtimeMs>r.mtimeMs||i.size!==r.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 T(t,e,i){const r=[];let o=0;async function c(){for(;o<t.length;){const F=o++,p=await e(t[F]);r[F]=p}}const l=Array(Math.min(i,t.length)).fill(null).map(()=>c());return await Promise.all(l),r}async function copySourceToTarget(t,e,i){const r=Date.now(),{recursive:o,overwrite:c,incremental:l=!1,parallelLimit:F=R}=i;let p=0,w=0,f=0;if((await s__default.promises.stat(t)).isDirectory()){await g(e);const a=await h(t,o),E=a.filter(n=>n.isFile);f=a.filter(n=>n.isDirectory).length;const S=new Set;for(const n of E){const A=u__default.relative(t,n.path),d=u__default.dirname(u__default.join(e,A));S.add(d)}await Promise.all([...S].map(n=>g(n)));const x=await T(E,async n=>{const A=u__default.relative(t,n.path),d=u__default.join(e,A);let m=c;return m||(m=!await D(d)),l&&m&&(m=await C(n.path,d)),m?(await s__default.promises.copyFile(n.path,d),{copied:!0,skipped:!1}):{copied:!1,skipped:!0}},F);for(const n of x)n.copied&&p++,n.skipped&&w++}else{await g(u__default.dirname(e));let a=c;a||(a=!await D(e)),l&&a&&(a=await C(t,e)),a?(await s__default.promises.copyFile(t,e),p++):w++}const y=Date.now()-r;return{copiedFiles:p,skippedFiles:w,copiedDirs:f,executionTime:y}}async function writeFileContent(t,e){try{await s__default.promises.writeFile(t,e,"utf-8")}catch(i){const r=i;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 scanDirectory(t,e={}){const{includeExtensions:i=[],excludePatterns:r=[],filter:o}=e,c=[];async function l(F){const p=await s__default.promises.readdir(F,{withFileTypes:!0});for(const w of p){const f=u__default.join(F,w.name);if(w.isDirectory()){await l(f);continue}if(!w.isFile()||r.some(E=>E.startsWith("*")?f.endsWith(E.slice(1)):f.includes(E)))continue;const y=u__default.extname(w.name).toLowerCase();if(i.length>0&&!i.includes(y))continue;const a=await s__default.promises.stat(f);o&&!o(f,y,a.size)||c.push({filePath:f,size:a.size,extension:y})}}return await l(t),c}async function writeJsonReport(t,e,i=2){await writeFileContent(t,JSON.stringify(e,null,i))}function writeFileSyncSafely(t,e){const i=u__default.dirname(t);s__default.existsSync(i)||s__default.mkdirSync(i,{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}}exports.checkSourceExists=checkSourceExists,exports.copySourceToTarget=copySourceToTarget,exports.scanDirectory=scanDirectory,exports.shouldUpdateFileContent=shouldUpdateFileContent,exports.writeFileContent=writeFileContent,exports.writeFileSyncSafely=writeFileSyncSafely,exports.writeJsonReport=writeJsonReport;
|
|
@@ -125,6 +125,41 @@ declare function scanDirectory(dirPath: string, options?: ScanDirectoryOptions):
|
|
|
125
125
|
* ```
|
|
126
126
|
*/
|
|
127
127
|
declare function writeJsonReport(filePath: string, data: object, indent?: number): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* 同步写入文件内容,自动创建不存在的目录
|
|
130
|
+
*
|
|
131
|
+
* @param filePath 文件路径
|
|
132
|
+
* @param content 文件内容
|
|
133
|
+
*
|
|
134
|
+
* @description 同步写入文件,如果目标目录不存在会自动递归创建。
|
|
135
|
+
* 适用于构建钩子中需要同步写入的场景(如 `transform` 钩子)。
|
|
136
|
+
*
|
|
137
|
+
* @throws 当文件写入失败时(如权限不足),抛出 `NodeJS.ErrnoException`
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', 'declare global { ... }')
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* 检查文件内容是否需要更新(同步版本)
|
|
147
|
+
*
|
|
148
|
+
* @param filePath 文件路径
|
|
149
|
+
* @param newContent 新生成的文件内容
|
|
150
|
+
* @returns 如果需要更新返回 `true`,否则返回 `false`
|
|
151
|
+
*
|
|
152
|
+
* @description 对比现有文件内容与新生成的内容,
|
|
153
|
+
* 仅在内容发生变化时才需要写入,减少不必要的文件 IO 操作。
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* if (shouldUpdateFileContent('/project/src/auto-imports.d.ts', newContent)) {
|
|
158
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', newContent)
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
128
163
|
|
|
129
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, writeFileContent, writeJsonReport };
|
|
164
|
+
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
130
165
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
|
@@ -125,6 +125,41 @@ declare function scanDirectory(dirPath: string, options?: ScanDirectoryOptions):
|
|
|
125
125
|
* ```
|
|
126
126
|
*/
|
|
127
127
|
declare function writeJsonReport(filePath: string, data: object, indent?: number): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* 同步写入文件内容,自动创建不存在的目录
|
|
130
|
+
*
|
|
131
|
+
* @param filePath 文件路径
|
|
132
|
+
* @param content 文件内容
|
|
133
|
+
*
|
|
134
|
+
* @description 同步写入文件,如果目标目录不存在会自动递归创建。
|
|
135
|
+
* 适用于构建钩子中需要同步写入的场景(如 `transform` 钩子)。
|
|
136
|
+
*
|
|
137
|
+
* @throws 当文件写入失败时(如权限不足),抛出 `NodeJS.ErrnoException`
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', 'declare global { ... }')
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* 检查文件内容是否需要更新(同步版本)
|
|
147
|
+
*
|
|
148
|
+
* @param filePath 文件路径
|
|
149
|
+
* @param newContent 新生成的文件内容
|
|
150
|
+
* @returns 如果需要更新返回 `true`,否则返回 `false`
|
|
151
|
+
*
|
|
152
|
+
* @description 对比现有文件内容与新生成的内容,
|
|
153
|
+
* 仅在内容发生变化时才需要写入,减少不必要的文件 IO 操作。
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* if (shouldUpdateFileContent('/project/src/auto-imports.d.ts', newContent)) {
|
|
158
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', newContent)
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
128
163
|
|
|
129
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, writeFileContent, writeJsonReport };
|
|
164
|
+
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
130
165
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
|
@@ -125,6 +125,41 @@ declare function scanDirectory(dirPath: string, options?: ScanDirectoryOptions):
|
|
|
125
125
|
* ```
|
|
126
126
|
*/
|
|
127
127
|
declare function writeJsonReport(filePath: string, data: object, indent?: number): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* 同步写入文件内容,自动创建不存在的目录
|
|
130
|
+
*
|
|
131
|
+
* @param filePath 文件路径
|
|
132
|
+
* @param content 文件内容
|
|
133
|
+
*
|
|
134
|
+
* @description 同步写入文件,如果目标目录不存在会自动递归创建。
|
|
135
|
+
* 适用于构建钩子中需要同步写入的场景(如 `transform` 钩子)。
|
|
136
|
+
*
|
|
137
|
+
* @throws 当文件写入失败时(如权限不足),抛出 `NodeJS.ErrnoException`
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', 'declare global { ... }')
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
declare function writeFileSyncSafely(filePath: string, content: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* 检查文件内容是否需要更新(同步版本)
|
|
147
|
+
*
|
|
148
|
+
* @param filePath 文件路径
|
|
149
|
+
* @param newContent 新生成的文件内容
|
|
150
|
+
* @returns 如果需要更新返回 `true`,否则返回 `false`
|
|
151
|
+
*
|
|
152
|
+
* @description 对比现有文件内容与新生成的内容,
|
|
153
|
+
* 仅在内容发生变化时才需要写入,减少不必要的文件 IO 操作。
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* if (shouldUpdateFileContent('/project/src/auto-imports.d.ts', newContent)) {
|
|
158
|
+
* writeFileSyncSafely('/project/src/auto-imports.d.ts', newContent)
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare function shouldUpdateFileContent(filePath: string, newContent: string): boolean;
|
|
128
163
|
|
|
129
|
-
export { checkSourceExists, copySourceToTarget, scanDirectory, writeFileContent, writeJsonReport };
|
|
164
|
+
export { checkSourceExists, copySourceToTarget, scanDirectory, shouldUpdateFileContent, writeFileContent, writeFileSyncSafely, writeJsonReport };
|
|
130
165
|
export type { CopyOptions, CopyResult, ScanDirectoryOptions, ScannedFile };
|
package/dist/common/fs/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"fs";import F from"path";const B=10;async function k(t){try{await e.promises.access(t,e.constants.F_OK)}catch(u){const i=u;throw i.code==="ENOENT"?new Error(`\u590D\u5236\u6587\u4EF6\u5931\u8D25\uFF1A\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728 - ${t}`):i.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${i.message}`)}}async function D(t){try{await e.promises.mkdir(t,{recursive:!0})}catch(u){const i=u;throw i.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${i.message}`)}}async function C(t,u){const i=await e.promises.readdir(t,{withFileTypes:!0}),r=[];for(const n of i){const a=F.join(t,n.name),l=n.isFile(),c=n.isDirectory();if(r.push({path:a,isFile:l,isDirectory:c}),c&&u){const p=await C(a,u);r.push(...p)}}return r}async function S(t,u){try{const[i,r]=await Promise.all([e.promises.stat(t),e.promises.stat(u)]);return i.mtimeMs>r.mtimeMs||i.size!==r.size}catch{return!0}}async function x(t){try{return await e.promises.access(t,e.constants.F_OK),!0}catch{return!1}}async function v(t,u,i){const r=[];let n=0;async function a(){for(;n<t.length;){const c=n++,p=await u(t[c]);r[c]=p}}const l=Array(Math.min(i,t.length)).fill(null).map(()=>a());return await Promise.all(l),r}async function T(t,u,i){const r=Date.now(),{recursive:n,overwrite:a,incremental:l=!1,parallelLimit:c=B}=i;let p=0,E=0,w=0;if((await e.promises.stat(t)).isDirectory()){await D(u);const o=await C(t,n),f=o.filter(s=>s.isFile);w=o.filter(s=>s.isDirectory).length;const A=new Set;for(const s of f){const h=F.relative(t,s.path),y=F.dirname(F.join(u,h));A.add(y)}await Promise.all([...A].map(s=>D(s)));const $=await v(f,async s=>{const h=F.relative(t,s.path),y=F.join(u,h);let d=a;return d||(d=!await x(y)),l&&d&&(d=await S(s.path,y)),d?(await e.promises.copyFile(s.path,y),{copied:!0,skipped:!1}):{copied:!1,skipped:!0}},c);for(const s of $)s.copied&&p++,s.skipped&&E++}else{await D(F.dirname(u));let o=a;o||(o=!await x(u)),l&&o&&(o=await S(t,u)),o?(await e.promises.copyFile(t,u),p++):E++}const m=Date.now()-r;return{copiedFiles:p,skippedFiles:E,copiedDirs:w,executionTime:m}}async function g(t,u){try{await e.promises.writeFile(t,u,"utf-8")}catch(i){const r=i;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 z(t,u={}){const{includeExtensions:i=[],excludePatterns:r=[],filter:n}=u,a=[];async function l(c){const p=await e.promises.readdir(c,{withFileTypes:!0});for(const E of p){const w=F.join(c,E.name);if(E.isDirectory()){await l(w);continue}if(!E.isFile()||r.some(f=>f.startsWith("*")?w.endsWith(f.slice(1)):w.includes(f)))continue;const m=F.extname(E.name).toLowerCase();if(i.length>0&&!i.includes(m))continue;const o=await e.promises.stat(w);n&&!n(w,m,o.size)||a.push({filePath:w,size:o.size,extension:m})}}return await l(t),a}async function P(t,u,i=2){await g(t,JSON.stringify(u,null,i))}function j(t,u){const i=F.dirname(t);e.existsSync(i)||e.mkdirSync(i,{recursive:!0}),e.writeFileSync(t,u,"utf-8")}function O(t,u){if(!e.existsSync(t))return!0;try{return e.readFileSync(t,"utf-8")!==u}catch{return!0}}export{k as checkSourceExists,T as copySourceToTarget,z as scanDirectory,O as shouldUpdateFileContent,g as writeFileContent,j as writeFileSyncSafely,P as writeJsonReport};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const security=require("../../shared/vite-plugin.
|
|
2
|
-
${t}`),injected:!0}:{html:e,injected:!1}}function c(e,t,
|
|
1
|
+
"use strict";const security=require("../../shared/vite-plugin.CcvHfrL8.cjs");function injectBeforeTag(e,t,l){const n=new RegExp(t,"i");return n.test(e)?{html:e.replace(n,`${l}
|
|
2
|
+
${t}`),injected:!0}:{html:e,injected:!1}}function c(e,t,l){const n=injectBeforeTag(e,"</body>",t);if(n.injected)return{...n,usedFallback:!1};const s=injectBeforeTag(e,"</html>",t);return s.injected?{...s,usedFallback:!1}:{html:e+t,injected:!0,usedFallback:!0}}function injectHeadAndBody(e,t,l){let n=e,s=!1;if(t){const r=injectBeforeTag(n,"</head>",t);r.injected&&(n=r.html,s=!0)}const i=c(n,l);return{html:i.html,headInjected:s,bodyInjected:i.injected,usedFallback:i.usedFallback}}exports.escapeHtmlAttr=security.escapeHtmlAttr,exports.sanitizeContent=security.sanitizeContent,exports.injectBeforeTag=injectBeforeTag,exports.injectHeadAndBody=injectHeadAndBody;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { S as SecurityConfig, H as HtmlInjectResult, D as DualInjectResult } from '../../shared/vite-plugin.BI9taN75.cjs';
|
|
2
2
|
export { C as ConditionType, I as InjectCondition, a as InjectPosition, b as SelectorMatch } from '../../shared/vite-plugin.BI9taN75.cjs';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 转义 HTML 属性值中的特殊字符
|
|
6
|
+
*
|
|
7
|
+
* @param str - 需要转义的字符串
|
|
8
|
+
* @returns 转义后的安全字符串
|
|
9
|
+
*
|
|
10
|
+
* @description 将字符串中的 `&`、`"`、`'`、`<`、`>` 转义为对应的 HTML 实体,
|
|
11
|
+
* 防止在 HTML 属性值中注入恶意代码。
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* escapeHtmlAttr('hello "world" & <friends>')
|
|
16
|
+
* // 'hello "world" & <friends>'
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function escapeHtmlAttr(str: string): string;
|
|
4
20
|
/**
|
|
5
21
|
* 内容消毒规则选项
|
|
6
22
|
*/
|
|
@@ -43,5 +59,5 @@ declare function injectBeforeTag(html: string, tag: string, code: string): HtmlI
|
|
|
43
59
|
*/
|
|
44
60
|
declare function injectHeadAndBody(html: string, headCode: string | undefined, bodyCode: string): DualInjectResult;
|
|
45
61
|
|
|
46
|
-
export { DualInjectResult, HtmlInjectResult, SecurityConfig, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
62
|
+
export { DualInjectResult, HtmlInjectResult, SecurityConfig, escapeHtmlAttr, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
47
63
|
export type { SanitizeRuleOptions };
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { S as SecurityConfig, H as HtmlInjectResult, D as DualInjectResult } from '../../shared/vite-plugin.BI9taN75.mjs';
|
|
2
2
|
export { C as ConditionType, I as InjectCondition, a as InjectPosition, b as SelectorMatch } from '../../shared/vite-plugin.BI9taN75.mjs';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 转义 HTML 属性值中的特殊字符
|
|
6
|
+
*
|
|
7
|
+
* @param str - 需要转义的字符串
|
|
8
|
+
* @returns 转义后的安全字符串
|
|
9
|
+
*
|
|
10
|
+
* @description 将字符串中的 `&`、`"`、`'`、`<`、`>` 转义为对应的 HTML 实体,
|
|
11
|
+
* 防止在 HTML 属性值中注入恶意代码。
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* escapeHtmlAttr('hello "world" & <friends>')
|
|
16
|
+
* // 'hello "world" & <friends>'
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function escapeHtmlAttr(str: string): string;
|
|
4
20
|
/**
|
|
5
21
|
* 内容消毒规则选项
|
|
6
22
|
*/
|
|
@@ -43,5 +59,5 @@ declare function injectBeforeTag(html: string, tag: string, code: string): HtmlI
|
|
|
43
59
|
*/
|
|
44
60
|
declare function injectHeadAndBody(html: string, headCode: string | undefined, bodyCode: string): DualInjectResult;
|
|
45
61
|
|
|
46
|
-
export { DualInjectResult, HtmlInjectResult, SecurityConfig, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
62
|
+
export { DualInjectResult, HtmlInjectResult, SecurityConfig, escapeHtmlAttr, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
47
63
|
export type { SanitizeRuleOptions };
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { S as SecurityConfig, H as HtmlInjectResult, D as DualInjectResult } from '../../shared/vite-plugin.BI9taN75.js';
|
|
2
2
|
export { C as ConditionType, I as InjectCondition, a as InjectPosition, b as SelectorMatch } from '../../shared/vite-plugin.BI9taN75.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 转义 HTML 属性值中的特殊字符
|
|
6
|
+
*
|
|
7
|
+
* @param str - 需要转义的字符串
|
|
8
|
+
* @returns 转义后的安全字符串
|
|
9
|
+
*
|
|
10
|
+
* @description 将字符串中的 `&`、`"`、`'`、`<`、`>` 转义为对应的 HTML 实体,
|
|
11
|
+
* 防止在 HTML 属性值中注入恶意代码。
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* escapeHtmlAttr('hello "world" & <friends>')
|
|
16
|
+
* // 'hello "world" & <friends>'
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function escapeHtmlAttr(str: string): string;
|
|
4
20
|
/**
|
|
5
21
|
* 内容消毒规则选项
|
|
6
22
|
*/
|
|
@@ -43,5 +59,5 @@ declare function injectBeforeTag(html: string, tag: string, code: string): HtmlI
|
|
|
43
59
|
*/
|
|
44
60
|
declare function injectHeadAndBody(html: string, headCode: string | undefined, bodyCode: string): DualInjectResult;
|
|
45
61
|
|
|
46
|
-
export { DualInjectResult, HtmlInjectResult, SecurityConfig, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
62
|
+
export { DualInjectResult, HtmlInjectResult, SecurityConfig, escapeHtmlAttr, injectBeforeTag, injectHeadAndBody, sanitizeContent };
|
|
47
63
|
export type { SanitizeRuleOptions };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{s as sanitizeContent}from"../../shared/vite-plugin.
|
|
2
|
-
${t}`),injected:!0}:{html:e,injected:!1}}function
|
|
1
|
+
export{e as escapeHtmlAttr,s as sanitizeContent}from"../../shared/vite-plugin.CuXEJAWX.mjs";function a(e,t,l){const n=new RegExp(t,"i");return n.test(e)?{html:e.replace(n,`${l}
|
|
2
|
+
${t}`),injected:!0}:{html:e,injected:!1}}function r(e,t,l){const n=a(e,"</body>",t);if(n.injected)return{...n,usedFallback:!1};const c=a(e,"</html>",t);return c.injected?{...c,usedFallback:!1}:{html:e+t,injected:!0,usedFallback:!0}}function i(e,t,l){let n=e,c=!1;if(t){const s=a(n,"</head>",t);s.injected&&(n=s.html,c=!0)}const d=r(n,l);return{html:d.html,headInjected:c,bodyInjected:d.injected,usedFallback:d.usedFallback}}export{a as injectBeforeTag,i as injectHeadAndBody};
|