@meng-xi/vite-plugin 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";const common_fs_index=require("./common/fs/index.cjs"),common_format_index=require("./common/format/index.cjs"),common_html_index=require("./common/html/index.cjs"),common_object_index=require("./common/object/index.cjs"),common_script_index=require("./common/script/index.cjs"),validator=require("./shared/vite-plugin.Bcg6RW2N.cjs"),common_validation_index=require("./common/validation/index.cjs"),factory_index=require("./factory/index.cjs"),logger_index=require("./logger/index.cjs"),plugins_buildProgress_index=require("./plugins/buildProgress/index.cjs"),plugins_copyFile_index=require("./plugins/copyFile/index.cjs"),plugins_faviconManager_index=require("./plugins/faviconManager/index.cjs"),plugins_generateRouter_index=require("./plugins/generateRouter/index.cjs"),plugins_generateVersion_index=require("./plugins/generateVersion/index.cjs"),plugins_htmlInject_index=require("./plugins/htmlInject/index.cjs"),plugins_loadingManager_index=require("./plugins/loadingManager/index.cjs"),plugins_versionUpdateChecker_index=require("./plugins/versionUpdateChecker/index.cjs");require("fs"),require("path"),require("crypto"),require("node:path"),exports.checkSourceExists=common_fs_index.checkSourceExists,exports.copySourceToTarget=common_fs_index.copySourceToTarget,exports.ensureTargetDir=common_fs_index.ensureTargetDir,exports.fileExists=common_fs_index.fileExists,exports.readDirRecursive=common_fs_index.readDirRecursive,exports.readFileContent=common_fs_index.readFileContent,exports.readFileSync=common_fs_index.readFileSync,exports.runWithConcurrency=common_fs_index.runWithConcurrency,exports.shouldUpdateFile=common_fs_index.shouldUpdateFile,exports.writeFileContent=common_fs_index.writeFileContent,exports.escapeHtmlAttr=common_format_index.escapeHtmlAttr,exports.formatDate=common_format_index.formatDate,exports.generateRandomHash=common_format_index.generateRandomHash,exports.getDateFormatParams=common_format_index.getDateFormatParams,exports.padNumber=common_format_index.padNumber,exports.parseTemplate=common_format_index.parseTemplate,exports.stripJsonComments=common_format_index.stripJsonComments,exports.toCamelCase=common_format_index.toCamelCase,exports.toPascalCase=common_format_index.toPascalCase,exports.injectBeforeTag=common_html_index.injectBeforeTag,exports.injectBeforeTagWithFallback=common_html_index.injectBeforeTagWithFallback,exports.injectHeadAndBody=common_html_index.injectHeadAndBody,exports.injectHtmlByPriority=common_html_index.injectHtmlByPriority,exports.deepMerge=common_object_index.deepMerge,exports.containsScriptTag=common_script_index.containsScriptTag,exports.makeCallback=common_script_index.makeCallback,exports.validateIdentifierName=common_script_index.validateIdentifierName,exports.Validator=validator.Validator,exports.validateCallbackFields=common_validation_index.validateCallbackFields,exports.validateEnumValue=common_validation_index.validateEnumValue,exports.validateGlobalName=common_validation_index.validateGlobalName,exports.validateNestedDuration=common_validation_index.validateNestedDuration,exports.validateNoScriptInTemplate=common_validation_index.validateNoScriptInTemplate,exports.validateNonNegativeNumber=common_validation_index.validateNonNegativeNumber,exports.BasePlugin=factory_index.BasePlugin,exports.createPluginFactory=factory_index.createPluginFactory,exports.Logger=logger_index.Logger,exports.buildProgress=plugins_buildProgress_index.buildProgress,exports.copyFile=plugins_copyFile_index.copyFile,exports.faviconManager=plugins_faviconManager_index.faviconManager,exports.generateRouter=plugins_generateRouter_index.generateRouter,exports.generateVersion=plugins_generateVersion_index.generateVersion,exports.htmlInject=plugins_htmlInject_index.htmlInject,exports.loadingManager=plugins_loadingManager_index.loadingManager,exports.versionUpdateChecker=plugins_versionUpdateChecker_index.versionUpdateChecker;
1
+ "use strict";const common_fs_index=require("./common/fs/index.cjs"),common_format_index=require("./common/format/index.cjs"),common_html_index=require("./common/html/index.cjs"),common_object_index=require("./common/object/index.cjs"),common_script_index=require("./common/script/index.cjs"),validator=require("./shared/vite-plugin.Bcg6RW2N.cjs"),common_validation_index=require("./common/validation/index.cjs"),factory_index=require("./factory/index.cjs"),logger_index=require("./logger/index.cjs"),plugins_buildProgress_index=require("./plugins/buildProgress/index.cjs"),plugins_compressAssets_index=require("./plugins/compressAssets/index.cjs"),plugins_copyFile_index=require("./plugins/copyFile/index.cjs"),plugins_faviconManager_index=require("./plugins/faviconManager/index.cjs"),plugins_generateRouter_index=require("./plugins/generateRouter/index.cjs"),plugins_generateVersion_index=require("./plugins/generateVersion/index.cjs"),plugins_htmlInject_index=require("./plugins/htmlInject/index.cjs"),plugins_loadingManager_index=require("./plugins/loadingManager/index.cjs"),plugins_versionUpdateChecker_index=require("./plugins/versionUpdateChecker/index.cjs");require("fs"),require("path"),require("crypto"),require("node:zlib"),require("node:fs"),require("node:stream/promises"),require("node:path"),exports.checkSourceExists=common_fs_index.checkSourceExists,exports.copySourceToTarget=common_fs_index.copySourceToTarget,exports.ensureTargetDir=common_fs_index.ensureTargetDir,exports.fileExists=common_fs_index.fileExists,exports.readDirRecursive=common_fs_index.readDirRecursive,exports.readFileContent=common_fs_index.readFileContent,exports.readFileSync=common_fs_index.readFileSync,exports.runWithConcurrency=common_fs_index.runWithConcurrency,exports.shouldUpdateFile=common_fs_index.shouldUpdateFile,exports.writeFileContent=common_fs_index.writeFileContent,exports.escapeHtmlAttr=common_format_index.escapeHtmlAttr,exports.formatDate=common_format_index.formatDate,exports.generateRandomHash=common_format_index.generateRandomHash,exports.getDateFormatParams=common_format_index.getDateFormatParams,exports.padNumber=common_format_index.padNumber,exports.parseTemplate=common_format_index.parseTemplate,exports.stripJsonComments=common_format_index.stripJsonComments,exports.toCamelCase=common_format_index.toCamelCase,exports.toPascalCase=common_format_index.toPascalCase,exports.injectBeforeTag=common_html_index.injectBeforeTag,exports.injectBeforeTagWithFallback=common_html_index.injectBeforeTagWithFallback,exports.injectHeadAndBody=common_html_index.injectHeadAndBody,exports.injectHtmlByPriority=common_html_index.injectHtmlByPriority,exports.deepMerge=common_object_index.deepMerge,exports.containsScriptTag=common_script_index.containsScriptTag,exports.makeCallback=common_script_index.makeCallback,exports.validateIdentifierName=common_script_index.validateIdentifierName,exports.Validator=validator.Validator,exports.validateCallbackFields=common_validation_index.validateCallbackFields,exports.validateEnumValue=common_validation_index.validateEnumValue,exports.validateGlobalName=common_validation_index.validateGlobalName,exports.validateNestedDuration=common_validation_index.validateNestedDuration,exports.validateNoScriptInTemplate=common_validation_index.validateNoScriptInTemplate,exports.validateNonNegativeNumber=common_validation_index.validateNonNegativeNumber,exports.BasePlugin=factory_index.BasePlugin,exports.createPluginFactory=factory_index.createPluginFactory,exports.Logger=logger_index.Logger,exports.buildProgress=plugins_buildProgress_index.buildProgress,exports.compressAssets=plugins_compressAssets_index.compressAssets,exports.copyFile=plugins_copyFile_index.copyFile,exports.faviconManager=plugins_faviconManager_index.faviconManager,exports.generateRouter=plugins_generateRouter_index.generateRouter,exports.generateVersion=plugins_generateVersion_index.generateVersion,exports.htmlInject=plugins_htmlInject_index.htmlInject,exports.loadingManager=plugins_loadingManager_index.loadingManager,exports.versionUpdateChecker=plugins_versionUpdateChecker_index.versionUpdateChecker;
package/dist/index.d.cts CHANGED
@@ -8,6 +8,7 @@ export { validateCallbackFields, validateEnumValue, validateGlobalName, validate
8
8
  export { BasePlugin, BasePluginOptions, OptionsNormalizer, PluginFactory, PluginWithInstance, createPluginFactory } from './factory/index.cjs';
9
9
  export { L as Logger, P as PluginLogger } from './shared/vite-plugin.CLr0ttuO.cjs';
10
10
  export { BuildPhase, BuildProgressOptions, ProgressFormat, ProgressTheme, buildProgress } from './plugins/buildProgress/index.cjs';
11
+ export { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary, compressAssets } from './plugins/compressAssets/index.cjs';
11
12
  export { CopyFileOptions, copyFile } from './plugins/copyFile/index.cjs';
12
13
  export { FaviconManagerOptions, Icon, faviconManager } from './plugins/faviconManager/index.cjs';
13
14
  export { GenerateRouterOptions, NameStrategy, OutputFormat, RouteConfig, RouteMeta, UniAppPageConfig, UniAppPagesJson, UniAppTabBarConfig, generateRouter } from './plugins/generateRouter/index.cjs';
package/dist/index.d.mts CHANGED
@@ -8,6 +8,7 @@ export { validateCallbackFields, validateEnumValue, validateGlobalName, validate
8
8
  export { BasePlugin, BasePluginOptions, OptionsNormalizer, PluginFactory, PluginWithInstance, createPluginFactory } from './factory/index.mjs';
9
9
  export { L as Logger, P as PluginLogger } from './shared/vite-plugin.CLr0ttuO.mjs';
10
10
  export { BuildPhase, BuildProgressOptions, ProgressFormat, ProgressTheme, buildProgress } from './plugins/buildProgress/index.mjs';
11
+ export { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary, compressAssets } from './plugins/compressAssets/index.mjs';
11
12
  export { CopyFileOptions, copyFile } from './plugins/copyFile/index.mjs';
12
13
  export { FaviconManagerOptions, Icon, faviconManager } from './plugins/faviconManager/index.mjs';
13
14
  export { GenerateRouterOptions, NameStrategy, OutputFormat, RouteConfig, RouteMeta, UniAppPageConfig, UniAppPagesJson, UniAppTabBarConfig, generateRouter } from './plugins/generateRouter/index.mjs';
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { validateCallbackFields, validateEnumValue, validateGlobalName, validate
8
8
  export { BasePlugin, BasePluginOptions, OptionsNormalizer, PluginFactory, PluginWithInstance, createPluginFactory } from './factory/index.js';
9
9
  export { L as Logger, P as PluginLogger } from './shared/vite-plugin.CLr0ttuO.js';
10
10
  export { BuildPhase, BuildProgressOptions, ProgressFormat, ProgressTheme, buildProgress } from './plugins/buildProgress/index.js';
11
+ export { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary, compressAssets } from './plugins/compressAssets/index.js';
11
12
  export { CopyFileOptions, copyFile } from './plugins/copyFile/index.js';
12
13
  export { FaviconManagerOptions, Icon, faviconManager } from './plugins/faviconManager/index.js';
13
14
  export { GenerateRouterOptions, NameStrategy, OutputFormat, RouteConfig, RouteMeta, UniAppPageConfig, UniAppPagesJson, UniAppTabBarConfig, generateRouter } from './plugins/generateRouter/index.js';
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export{checkSourceExists,copySourceToTarget,ensureTargetDir,fileExists,readDirRecursive,readFileContent,readFileSync,runWithConcurrency,shouldUpdateFile,writeFileContent}from"./common/fs/index.mjs";export{escapeHtmlAttr,formatDate,generateRandomHash,getDateFormatParams,padNumber,parseTemplate,stripJsonComments,toCamelCase,toPascalCase}from"./common/format/index.mjs";export{injectBeforeTag,injectBeforeTagWithFallback,injectHeadAndBody,injectHtmlByPriority}from"./common/html/index.mjs";export{deepMerge}from"./common/object/index.mjs";export{containsScriptTag,makeCallback,validateIdentifierName}from"./common/script/index.mjs";export{V as Validator}from"./shared/vite-plugin.DcExl6jd.mjs";export{validateCallbackFields,validateEnumValue,validateGlobalName,validateNestedDuration,validateNoScriptInTemplate,validateNonNegativeNumber}from"./common/validation/index.mjs";export{BasePlugin,createPluginFactory}from"./factory/index.mjs";export{Logger}from"./logger/index.mjs";export{buildProgress}from"./plugins/buildProgress/index.mjs";export{copyFile}from"./plugins/copyFile/index.mjs";export{faviconManager}from"./plugins/faviconManager/index.mjs";export{generateRouter}from"./plugins/generateRouter/index.mjs";export{generateVersion}from"./plugins/generateVersion/index.mjs";export{htmlInject}from"./plugins/htmlInject/index.mjs";export{loadingManager}from"./plugins/loadingManager/index.mjs";export{versionUpdateChecker}from"./plugins/versionUpdateChecker/index.mjs";import"fs";import"path";import"crypto";import"node:path";
1
+ export{checkSourceExists,copySourceToTarget,ensureTargetDir,fileExists,readDirRecursive,readFileContent,readFileSync,runWithConcurrency,shouldUpdateFile,writeFileContent}from"./common/fs/index.mjs";export{escapeHtmlAttr,formatDate,generateRandomHash,getDateFormatParams,padNumber,parseTemplate,stripJsonComments,toCamelCase,toPascalCase}from"./common/format/index.mjs";export{injectBeforeTag,injectBeforeTagWithFallback,injectHeadAndBody,injectHtmlByPriority}from"./common/html/index.mjs";export{deepMerge}from"./common/object/index.mjs";export{containsScriptTag,makeCallback,validateIdentifierName}from"./common/script/index.mjs";export{V as Validator}from"./shared/vite-plugin.DcExl6jd.mjs";export{validateCallbackFields,validateEnumValue,validateGlobalName,validateNestedDuration,validateNoScriptInTemplate,validateNonNegativeNumber}from"./common/validation/index.mjs";export{BasePlugin,createPluginFactory}from"./factory/index.mjs";export{Logger}from"./logger/index.mjs";export{buildProgress}from"./plugins/buildProgress/index.mjs";export{compressAssets}from"./plugins/compressAssets/index.mjs";export{copyFile}from"./plugins/copyFile/index.mjs";export{faviconManager}from"./plugins/faviconManager/index.mjs";export{generateRouter}from"./plugins/generateRouter/index.mjs";export{generateVersion}from"./plugins/generateVersion/index.mjs";export{htmlInject}from"./plugins/htmlInject/index.mjs";export{loadingManager}from"./plugins/loadingManager/index.mjs";export{versionUpdateChecker}from"./plugins/versionUpdateChecker/index.mjs";import"fs";import"path";import"crypto";import"node:zlib";import"node:fs";import"node:stream/promises";import"node:path";
@@ -0,0 +1 @@
1
+ "use strict";const factory_index=require("../../factory/index.cjs"),node_zlib=require("node:zlib"),node_fs=require("node:fs"),promises=require("node:stream/promises"),o=require("node:path"),common_fs_index=require("../../common/fs/index.cjs");require("../../logger/index.cjs"),require("../../common/object/index.cjs"),require("../../shared/vite-plugin.Bcg6RW2N.cjs"),require("fs"),require("path");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const o__default=_interopDefaultCompat(o);async function compressFileGzip(e,t,i){const s=(await node_fs.promises.stat(e)).size,a=node_zlib.createGzip({level:i});await promises.pipeline(node_fs.createReadStream(e),a,node_fs.createWriteStream(t));const r=(await node_fs.promises.stat(t)).size;return{file:e,originalSize:s,compressedSize:r,ratio:s>0?Number(((1-r/s)*100).toFixed(1)):0,algorithm:"gzip"}}async function compressFileBrotli(e,t,i){const s=(await node_fs.promises.stat(e)).size,a=node_zlib.createBrotliCompress({params:{[node_zlib.constants.BROTLI_PARAM_QUALITY]:i}});await promises.pipeline(node_fs.createReadStream(e),a,node_fs.createWriteStream(t));const r=(await node_fs.promises.stat(t)).size;return{file:e,originalSize:s,compressedSize:r,ratio:s>0?Number(((1-r/s)*100).toFixed(1)):0,algorithm:"brotli"}}async function compressFile(e,t,i,s){const a=e+(t==="gzip"?".gz":".br");return t==="gzip"?compressFileGzip(e,a,i):compressFileBrotli(e,a,s)}function shouldCompressFile(e,t,i,s){const a=e.replace(/\\/g,"/");if(i<s.threshold||s.excludeExtensions.length>0&&s.excludeExtensions.includes(t)||s.includeExtensions.length>0&&!s.includeExtensions.includes(t))return!1;if(s.excludePaths.length>0)for(const r of s.excludePaths){const l=r.replace(/\\/g,"/");if(a.startsWith(l)||a.includes(l))return!1}return!(t===".gz"||t===".br")}async function scanDirectory(e,t){const i=[];async function s(a){const r=await node_fs.promises.readdir(a,{withFileTypes:!0});for(const l of r){const u=o__default.join(a,l.name);if(l.isDirectory())await s(u);else if(l.isFile()){const n=await node_fs.promises.stat(u),c=o__default.relative(e,u),m=o__default.extname(l.name).toLowerCase();shouldCompressFile(c,m,n.size,t)&&i.push({filePath:u,relativePath:c,size:n.size,ext:m})}}}return await s(e),i}function buildSummary(e,t){const i=e.reduce((r,l)=>r+l.originalSize,0),s=e.reduce((r,l)=>r+l.compressedSize,0),a=i>0?Number(((1-s/i)*100).toFixed(1)):0;return{totalFiles:e.length,totalOriginalSize:i,totalCompressedSize:s,totalRatio:a,gzipFiles:e.filter(r=>r.algorithm==="gzip").length,brotliFiles:e.filter(r=>r.algorithm==="brotli").length,executionTime:t,stats:e}}function formatFileSize(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(2)}MB`}async function writeReport(e,t,i){if(!t)return;const s=o__default.isAbsolute(t)?t:o__default.join(e,t),a={timestamp:new Date().toISOString(),summary:{totalFiles:i.totalFiles,totalOriginalSize:i.totalOriginalSize,totalCompressedSize:i.totalCompressedSize,totalRatio:i.totalRatio,gzipFiles:i.gzipFiles,brotliFiles:i.brotliFiles,executionTime:i.executionTime},files:i.stats.map(r=>({file:r.file,originalSize:r.originalSize,compressedSize:r.compressedSize,ratio:r.ratio,algorithm:r.algorithm}))};await common_fs_index.writeFileContent(s,JSON.stringify(a,null,2))}async function deleteOriginalFiles(e){const t=[...new Set(e.map(i=>i.file))];for(const i of t)try{await node_fs.promises.unlink(i)}catch{}}class y extends factory_index.BasePlugin{allStats=[];summary=null;getDefaultOptions(){return{algorithm:"gzip",threshold:1024,deleteOriginalFile:!1,includeExtensions:[".js",".css",".html",".svg",".json",".xml",".txt"],excludeExtensions:[],excludePaths:[],compressionLevel:9,brotliQuality:11,reportOutput:"compress-report.json",parallelLimit:10}}validateOptions(){this.validator.field("algorithm").enum(["gzip","brotli","both"]).field("threshold").number().minValue(0).field("deleteOriginalFile").boolean().field("includeExtensions").array().field("excludeExtensions").array().field("excludePaths").array().field("compressionLevel").number().minValue(1).maxValue(9).field("brotliQuality").number().minValue(1).maxValue(11).field("reportOutput").custom(t=>t===!1||typeof t=="string","reportOutput \u5FC5\u987B\u4E3A false \u6216\u5B57\u7B26\u4E32\u8DEF\u5F84").field("parallelLimit").number().minValue(1).maxValue(50).validate()}getPluginName(){return"compress-assets"}getEnforce(){return"post"}addPluginHooks(t){t.writeBundle=async()=>{await this.safeExecute(()=>this.compressAllFiles(),"\u538B\u7F29\u6784\u5EFA\u4EA7\u7269")}}async compressAllFiles(){if(!this.viteConfig)return;const t=this.viteConfig.build.outDir,i=Date.now();this.logger.info(`\u5F00\u59CB\u626B\u63CF\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55: ${t}`);const s=await scanDirectory(t,this.options);if(s.length===0){this.logger.info("\u672A\u627E\u5230\u9700\u8981\u538B\u7F29\u7684\u6587\u4EF6");return}this.logger.info(`\u53D1\u73B0 ${s.length} \u4E2A\u5F85\u538B\u7F29\u6587\u4EF6`),this.allStats=[];const a=this.options.algorithm==="both"?["gzip","brotli"]:[this.options.algorithm];for(const l of a){const u=await common_fs_index.runWithConcurrency(s,async n=>compressFile(n.filePath,l,this.options.compressionLevel,this.options.brotliQuality),this.options.parallelLimit);this.allStats.push(...u)}const r=Date.now()-i;this.summary=buildSummary(this.allStats,r),this.options.deleteOriginalFile&&(await deleteOriginalFiles(this.allStats),this.logger.info("\u5DF2\u5220\u9664\u539F\u59CB\u6587\u4EF6\uFF0C\u4EC5\u4FDD\u7559\u538B\u7F29\u7248\u672C")),this.options.reportOutput&&(await writeReport(t,this.options.reportOutput,this.summary),this.logger.info(`\u538B\u7F29\u62A5\u544A\u5DF2\u751F\u6210: ${this.options.reportOutput}`)),this.logSummary()}logSummary(){if(!this.summary)return;const{totalFiles:t,totalOriginalSize:i,totalCompressedSize:s,totalRatio:a,executionTime:r}=this.summary;this.logger.success(`\u538B\u7F29\u5B8C\u6210: ${t} \u4E2A\u6587\u4EF6`,`\u539F\u59CB\u4F53\u79EF: ${formatFileSize(i)} \u2192 \u538B\u7F29\u540E: ${formatFileSize(s)}\uFF0C\u538B\u7F29\u7387: ${a}%\uFF0C\u8017\u65F6: ${r}ms`);const l=[...this.allStats].sort((u,n)=>n.ratio-u.ratio).slice(0,5);if(l.length>0){this.logger.info("\u538B\u7F29\u7387 Top 5:");for(const u of l)this.logger.info(` ${u.algorithm.toUpperCase().padEnd(6)} ${u.ratio}% ${formatFileSize(u.originalSize)} \u2192 ${formatFileSize(u.compressedSize)}`)}}getStats(){return[...this.allStats]}getSummary(){return this.summary}}const compressAssets=factory_index.createPluginFactory(y);exports.compressAssets=compressAssets;
@@ -0,0 +1,132 @@
1
+ import { BasePluginOptions, PluginFactory } from '../../factory/index.cjs';
2
+ import 'vite';
3
+ import '../../shared/vite-plugin.CLr0ttuO.cjs';
4
+ import '../../shared/vite-plugin.DRRlWY8P.cjs';
5
+
6
+ /**
7
+ * 压缩算法类型
8
+ *
9
+ * @typedef {('gzip' | 'brotli' | 'both')} CompressAlgorithm
10
+ * @description 支持的压缩算法:
11
+ * - `gzip`: 使用 gzip 压缩,输出 `.gz` 文件
12
+ * - `brotli`: 使用 brotli 压缩,输出 `.br` 文件
13
+ * - `both`: 同时生成 gzip 和 brotli 两种压缩文件
14
+ */
15
+ type CompressAlgorithm = 'gzip' | 'brotli' | 'both';
16
+ /**
17
+ * 单个文件的压缩统计信息
18
+ *
19
+ * @interface CompressStats
20
+ * @description 记录单个文件经过压缩后的详细统计数据
21
+ */
22
+ interface CompressStats {
23
+ /** 原始文件路径 */
24
+ file: string;
25
+ /** 原始文件大小(字节) */
26
+ originalSize: number;
27
+ /** 压缩后文件大小(字节) */
28
+ compressedSize: number;
29
+ /** 压缩率百分比(0-100),如 75.3 表示压缩后体积减少 75.3% */
30
+ ratio: number;
31
+ /** 使用的压缩算法 */
32
+ algorithm: 'gzip' | 'brotli';
33
+ }
34
+ /**
35
+ * 压缩操作的汇总统计信息
36
+ *
37
+ * @interface CompressSummary
38
+ * @description 包含整个压缩操作的总体统计数据,用于报告生成和日志输出
39
+ */
40
+ interface CompressSummary {
41
+ /** 压缩的文件总数 */
42
+ totalFiles: number;
43
+ /** 所有文件的原始大小总和(字节) */
44
+ totalOriginalSize: number;
45
+ /** 所有文件的压缩后大小总和(字节) */
46
+ totalCompressedSize: number;
47
+ /** 总体压缩率百分比 */
48
+ totalRatio: number;
49
+ /** 使用 gzip 压缩的文件数量 */
50
+ gzipFiles: number;
51
+ /** 使用 brotli 压缩的文件数量 */
52
+ brotliFiles: number;
53
+ /** 压缩操作总耗时(毫秒) */
54
+ executionTime: number;
55
+ /** 每个文件的详细压缩统计 */
56
+ stats: CompressStats[];
57
+ }
58
+ /**
59
+ * 构建产物压缩插件的配置选项
60
+ *
61
+ * @interface CompressAssetsOptions
62
+ * @extends {BasePluginOptions}
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * compressAssets({
67
+ * algorithm: 'both',
68
+ * threshold: 2048,
69
+ * compressionLevel: 9,
70
+ * brotliQuality: 11,
71
+ * reportOutput: 'compress-report.json'
72
+ * })
73
+ * ```
74
+ */
75
+ interface CompressAssetsOptions extends BasePluginOptions {
76
+ /** 压缩算法,支持 gzip、brotli 或同时使用两者 */
77
+ algorithm?: CompressAlgorithm;
78
+ /** 最小压缩阈值(字节),小于此大小的文件将被跳过 */
79
+ threshold?: number;
80
+ /** 是否在压缩后删除原始文件,仅保留压缩版本 */
81
+ deleteOriginalFile?: boolean;
82
+ /** 需要压缩的文件扩展名列表,如 ['.js', '.css', '.html'] */
83
+ includeExtensions?: string[];
84
+ /** 需要排除的文件扩展名列表,优先级高于 includeExtensions */
85
+ excludeExtensions?: string[];
86
+ /** 需要排除的路径前缀列表,匹配到的路径下的文件将跳过压缩 */
87
+ excludePaths?: string[];
88
+ /** gzip 压缩级别,范围 1-9,1 最快压缩率最低,9 最慢压缩率最高 */
89
+ compressionLevel?: number;
90
+ /** brotli 崩质量参数,范围 1-11,1 最快质量最低,11 最慢质量最高 */
91
+ brotliQuality?: number;
92
+ /** 压缩报告输出路径,设为 false 则不生成报告 */
93
+ reportOutput?: string | false;
94
+ /** 并发压缩的最大文件数,控制同时进行压缩操作的文件数量 */
95
+ parallelLimit?: number;
96
+ }
97
+
98
+ /**
99
+ * 创建构建产物压缩插件
100
+ *
101
+ * @function compressAssets
102
+ * @param {Partial<CompressAssetsOptions>} [options] - 插件配置选项
103
+ * @returns {Plugin} Vite 插件实例
104
+ *
105
+ * @description 在 Vite 构建完成后自动压缩输出目录中的文件,
106
+ * 支持 gzip 和 brotli 两种压缩算法,可配置压缩级别、文件过滤规则、
107
+ * 并发数量等参数,并生成压缩统计报告。
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // vite.config.ts
112
+ * import { compressAssets } from '@meng-xi/vite-plugin'
113
+ *
114
+ * export default defineConfig({
115
+ * plugins: [
116
+ * compressAssets({
117
+ * algorithm: 'both',
118
+ * threshold: 2048,
119
+ * deleteOriginalFile: false,
120
+ * compressionLevel: 9,
121
+ * brotliQuality: 11,
122
+ * reportOutput: 'compress-report.json',
123
+ * parallelLimit: 10
124
+ * })
125
+ * ]
126
+ * })
127
+ * ```
128
+ */
129
+ declare const compressAssets: PluginFactory<CompressAssetsOptions, CompressAssetsOptions>;
130
+
131
+ export { compressAssets };
132
+ export type { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary };
@@ -0,0 +1,132 @@
1
+ import { BasePluginOptions, PluginFactory } from '../../factory/index.mjs';
2
+ import 'vite';
3
+ import '../../shared/vite-plugin.CLr0ttuO.mjs';
4
+ import '../../shared/vite-plugin.DRRlWY8P.mjs';
5
+
6
+ /**
7
+ * 压缩算法类型
8
+ *
9
+ * @typedef {('gzip' | 'brotli' | 'both')} CompressAlgorithm
10
+ * @description 支持的压缩算法:
11
+ * - `gzip`: 使用 gzip 压缩,输出 `.gz` 文件
12
+ * - `brotli`: 使用 brotli 压缩,输出 `.br` 文件
13
+ * - `both`: 同时生成 gzip 和 brotli 两种压缩文件
14
+ */
15
+ type CompressAlgorithm = 'gzip' | 'brotli' | 'both';
16
+ /**
17
+ * 单个文件的压缩统计信息
18
+ *
19
+ * @interface CompressStats
20
+ * @description 记录单个文件经过压缩后的详细统计数据
21
+ */
22
+ interface CompressStats {
23
+ /** 原始文件路径 */
24
+ file: string;
25
+ /** 原始文件大小(字节) */
26
+ originalSize: number;
27
+ /** 压缩后文件大小(字节) */
28
+ compressedSize: number;
29
+ /** 压缩率百分比(0-100),如 75.3 表示压缩后体积减少 75.3% */
30
+ ratio: number;
31
+ /** 使用的压缩算法 */
32
+ algorithm: 'gzip' | 'brotli';
33
+ }
34
+ /**
35
+ * 压缩操作的汇总统计信息
36
+ *
37
+ * @interface CompressSummary
38
+ * @description 包含整个压缩操作的总体统计数据,用于报告生成和日志输出
39
+ */
40
+ interface CompressSummary {
41
+ /** 压缩的文件总数 */
42
+ totalFiles: number;
43
+ /** 所有文件的原始大小总和(字节) */
44
+ totalOriginalSize: number;
45
+ /** 所有文件的压缩后大小总和(字节) */
46
+ totalCompressedSize: number;
47
+ /** 总体压缩率百分比 */
48
+ totalRatio: number;
49
+ /** 使用 gzip 压缩的文件数量 */
50
+ gzipFiles: number;
51
+ /** 使用 brotli 压缩的文件数量 */
52
+ brotliFiles: number;
53
+ /** 压缩操作总耗时(毫秒) */
54
+ executionTime: number;
55
+ /** 每个文件的详细压缩统计 */
56
+ stats: CompressStats[];
57
+ }
58
+ /**
59
+ * 构建产物压缩插件的配置选项
60
+ *
61
+ * @interface CompressAssetsOptions
62
+ * @extends {BasePluginOptions}
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * compressAssets({
67
+ * algorithm: 'both',
68
+ * threshold: 2048,
69
+ * compressionLevel: 9,
70
+ * brotliQuality: 11,
71
+ * reportOutput: 'compress-report.json'
72
+ * })
73
+ * ```
74
+ */
75
+ interface CompressAssetsOptions extends BasePluginOptions {
76
+ /** 压缩算法,支持 gzip、brotli 或同时使用两者 */
77
+ algorithm?: CompressAlgorithm;
78
+ /** 最小压缩阈值(字节),小于此大小的文件将被跳过 */
79
+ threshold?: number;
80
+ /** 是否在压缩后删除原始文件,仅保留压缩版本 */
81
+ deleteOriginalFile?: boolean;
82
+ /** 需要压缩的文件扩展名列表,如 ['.js', '.css', '.html'] */
83
+ includeExtensions?: string[];
84
+ /** 需要排除的文件扩展名列表,优先级高于 includeExtensions */
85
+ excludeExtensions?: string[];
86
+ /** 需要排除的路径前缀列表,匹配到的路径下的文件将跳过压缩 */
87
+ excludePaths?: string[];
88
+ /** gzip 压缩级别,范围 1-9,1 最快压缩率最低,9 最慢压缩率最高 */
89
+ compressionLevel?: number;
90
+ /** brotli 崩质量参数,范围 1-11,1 最快质量最低,11 最慢质量最高 */
91
+ brotliQuality?: number;
92
+ /** 压缩报告输出路径,设为 false 则不生成报告 */
93
+ reportOutput?: string | false;
94
+ /** 并发压缩的最大文件数,控制同时进行压缩操作的文件数量 */
95
+ parallelLimit?: number;
96
+ }
97
+
98
+ /**
99
+ * 创建构建产物压缩插件
100
+ *
101
+ * @function compressAssets
102
+ * @param {Partial<CompressAssetsOptions>} [options] - 插件配置选项
103
+ * @returns {Plugin} Vite 插件实例
104
+ *
105
+ * @description 在 Vite 构建完成后自动压缩输出目录中的文件,
106
+ * 支持 gzip 和 brotli 两种压缩算法,可配置压缩级别、文件过滤规则、
107
+ * 并发数量等参数,并生成压缩统计报告。
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // vite.config.ts
112
+ * import { compressAssets } from '@meng-xi/vite-plugin'
113
+ *
114
+ * export default defineConfig({
115
+ * plugins: [
116
+ * compressAssets({
117
+ * algorithm: 'both',
118
+ * threshold: 2048,
119
+ * deleteOriginalFile: false,
120
+ * compressionLevel: 9,
121
+ * brotliQuality: 11,
122
+ * reportOutput: 'compress-report.json',
123
+ * parallelLimit: 10
124
+ * })
125
+ * ]
126
+ * })
127
+ * ```
128
+ */
129
+ declare const compressAssets: PluginFactory<CompressAssetsOptions, CompressAssetsOptions>;
130
+
131
+ export { compressAssets };
132
+ export type { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary };
@@ -0,0 +1,132 @@
1
+ import { BasePluginOptions, PluginFactory } from '../../factory/index.js';
2
+ import 'vite';
3
+ import '../../shared/vite-plugin.CLr0ttuO.js';
4
+ import '../../shared/vite-plugin.DRRlWY8P.js';
5
+
6
+ /**
7
+ * 压缩算法类型
8
+ *
9
+ * @typedef {('gzip' | 'brotli' | 'both')} CompressAlgorithm
10
+ * @description 支持的压缩算法:
11
+ * - `gzip`: 使用 gzip 压缩,输出 `.gz` 文件
12
+ * - `brotli`: 使用 brotli 压缩,输出 `.br` 文件
13
+ * - `both`: 同时生成 gzip 和 brotli 两种压缩文件
14
+ */
15
+ type CompressAlgorithm = 'gzip' | 'brotli' | 'both';
16
+ /**
17
+ * 单个文件的压缩统计信息
18
+ *
19
+ * @interface CompressStats
20
+ * @description 记录单个文件经过压缩后的详细统计数据
21
+ */
22
+ interface CompressStats {
23
+ /** 原始文件路径 */
24
+ file: string;
25
+ /** 原始文件大小(字节) */
26
+ originalSize: number;
27
+ /** 压缩后文件大小(字节) */
28
+ compressedSize: number;
29
+ /** 压缩率百分比(0-100),如 75.3 表示压缩后体积减少 75.3% */
30
+ ratio: number;
31
+ /** 使用的压缩算法 */
32
+ algorithm: 'gzip' | 'brotli';
33
+ }
34
+ /**
35
+ * 压缩操作的汇总统计信息
36
+ *
37
+ * @interface CompressSummary
38
+ * @description 包含整个压缩操作的总体统计数据,用于报告生成和日志输出
39
+ */
40
+ interface CompressSummary {
41
+ /** 压缩的文件总数 */
42
+ totalFiles: number;
43
+ /** 所有文件的原始大小总和(字节) */
44
+ totalOriginalSize: number;
45
+ /** 所有文件的压缩后大小总和(字节) */
46
+ totalCompressedSize: number;
47
+ /** 总体压缩率百分比 */
48
+ totalRatio: number;
49
+ /** 使用 gzip 压缩的文件数量 */
50
+ gzipFiles: number;
51
+ /** 使用 brotli 压缩的文件数量 */
52
+ brotliFiles: number;
53
+ /** 压缩操作总耗时(毫秒) */
54
+ executionTime: number;
55
+ /** 每个文件的详细压缩统计 */
56
+ stats: CompressStats[];
57
+ }
58
+ /**
59
+ * 构建产物压缩插件的配置选项
60
+ *
61
+ * @interface CompressAssetsOptions
62
+ * @extends {BasePluginOptions}
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * compressAssets({
67
+ * algorithm: 'both',
68
+ * threshold: 2048,
69
+ * compressionLevel: 9,
70
+ * brotliQuality: 11,
71
+ * reportOutput: 'compress-report.json'
72
+ * })
73
+ * ```
74
+ */
75
+ interface CompressAssetsOptions extends BasePluginOptions {
76
+ /** 压缩算法,支持 gzip、brotli 或同时使用两者 */
77
+ algorithm?: CompressAlgorithm;
78
+ /** 最小压缩阈值(字节),小于此大小的文件将被跳过 */
79
+ threshold?: number;
80
+ /** 是否在压缩后删除原始文件,仅保留压缩版本 */
81
+ deleteOriginalFile?: boolean;
82
+ /** 需要压缩的文件扩展名列表,如 ['.js', '.css', '.html'] */
83
+ includeExtensions?: string[];
84
+ /** 需要排除的文件扩展名列表,优先级高于 includeExtensions */
85
+ excludeExtensions?: string[];
86
+ /** 需要排除的路径前缀列表,匹配到的路径下的文件将跳过压缩 */
87
+ excludePaths?: string[];
88
+ /** gzip 压缩级别,范围 1-9,1 最快压缩率最低,9 最慢压缩率最高 */
89
+ compressionLevel?: number;
90
+ /** brotli 崩质量参数,范围 1-11,1 最快质量最低,11 最慢质量最高 */
91
+ brotliQuality?: number;
92
+ /** 压缩报告输出路径,设为 false 则不生成报告 */
93
+ reportOutput?: string | false;
94
+ /** 并发压缩的最大文件数,控制同时进行压缩操作的文件数量 */
95
+ parallelLimit?: number;
96
+ }
97
+
98
+ /**
99
+ * 创建构建产物压缩插件
100
+ *
101
+ * @function compressAssets
102
+ * @param {Partial<CompressAssetsOptions>} [options] - 插件配置选项
103
+ * @returns {Plugin} Vite 插件实例
104
+ *
105
+ * @description 在 Vite 构建完成后自动压缩输出目录中的文件,
106
+ * 支持 gzip 和 brotli 两种压缩算法,可配置压缩级别、文件过滤规则、
107
+ * 并发数量等参数,并生成压缩统计报告。
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // vite.config.ts
112
+ * import { compressAssets } from '@meng-xi/vite-plugin'
113
+ *
114
+ * export default defineConfig({
115
+ * plugins: [
116
+ * compressAssets({
117
+ * algorithm: 'both',
118
+ * threshold: 2048,
119
+ * deleteOriginalFile: false,
120
+ * compressionLevel: 9,
121
+ * brotliQuality: 11,
122
+ * reportOutput: 'compress-report.json',
123
+ * parallelLimit: 10
124
+ * })
125
+ * ]
126
+ * })
127
+ * ```
128
+ */
129
+ declare const compressAssets: PluginFactory<CompressAssetsOptions, CompressAssetsOptions>;
130
+
131
+ export { compressAssets };
132
+ export type { CompressAlgorithm, CompressAssetsOptions, CompressStats, CompressSummary };
@@ -0,0 +1 @@
1
+ import{createPluginFactory as d,BasePlugin as z}from"../../factory/index.mjs";import{createGzip as S,createBrotliCompress as y,constants as x}from"node:zlib";import{promises as u,createReadStream as h,createWriteStream as f}from"node:fs";import{pipeline as F}from"node:stream/promises";import m from"node:path";import{writeFileContent as E,runWithConcurrency as w}from"../../common/fs/index.mjs";import"../../logger/index.mjs";import"../../common/object/index.mjs";import"../../shared/vite-plugin.DcExl6jd.mjs";import"fs";import"path";async function B(i,t,e){const s=(await u.stat(i)).size,r=S({level:e});await F(h(i),r,f(t));const o=(await u.stat(t)).size;return{file:i,originalSize:s,compressedSize:o,ratio:s>0?Number(((1-o/s)*100).toFixed(1)):0,algorithm:"gzip"}}async function b(i,t,e){const s=(await u.stat(i)).size,r=y({params:{[x.BROTLI_PARAM_QUALITY]:e}});await F(h(i),r,f(t));const o=(await u.stat(t)).size;return{file:i,originalSize:s,compressedSize:o,ratio:s>0?Number(((1-o/s)*100).toFixed(1)):0,algorithm:"brotli"}}async function C(i,t,e,s){const r=i+(t==="gzip"?".gz":".br");return t==="gzip"?B(i,r,e):b(i,r,s)}function O(i,t,e,s){const r=i.replace(/\\/g,"/");if(e<s.threshold||s.excludeExtensions.length>0&&s.excludeExtensions.includes(t)||s.includeExtensions.length>0&&!s.includeExtensions.includes(t))return!1;if(s.excludePaths.length>0)for(const o of s.excludePaths){const l=o.replace(/\\/g,"/");if(r.startsWith(l)||r.includes(l))return!1}return!(t===".gz"||t===".br")}async function A(i,t){const e=[];async function s(r){const o=await u.readdir(r,{withFileTypes:!0});for(const l of o){const a=m.join(r,l.name);if(l.isDirectory())await s(a);else if(l.isFile()){const n=await u.stat(a),p=m.relative(i,a),g=m.extname(l.name).toLowerCase();O(p,g,n.size,t)&&e.push({filePath:a,relativePath:p,size:n.size,ext:g})}}}return await s(i),e}function D(i,t){const e=i.reduce((o,l)=>o+l.originalSize,0),s=i.reduce((o,l)=>o+l.compressedSize,0),r=e>0?Number(((1-s/e)*100).toFixed(1)):0;return{totalFiles:i.length,totalOriginalSize:e,totalCompressedSize:s,totalRatio:r,gzipFiles:i.filter(o=>o.algorithm==="gzip").length,brotliFiles:i.filter(o=>o.algorithm==="brotli").length,executionTime:t,stats:i}}function c(i){return i<1024?`${i}B`:i<1024*1024?`${(i/1024).toFixed(1)}KB`:`${(i/(1024*1024)).toFixed(2)}MB`}async function v(i,t,e){if(!t)return;const s=m.isAbsolute(t)?t:m.join(i,t),r={timestamp:new Date().toISOString(),summary:{totalFiles:e.totalFiles,totalOriginalSize:e.totalOriginalSize,totalCompressedSize:e.totalCompressedSize,totalRatio:e.totalRatio,gzipFiles:e.gzipFiles,brotliFiles:e.brotliFiles,executionTime:e.executionTime},files:e.stats.map(o=>({file:o.file,originalSize:o.originalSize,compressedSize:o.compressedSize,ratio:o.ratio,algorithm:o.algorithm}))};await E(s,JSON.stringify(r,null,2))}async function P(i){const t=[...new Set(i.map(e=>e.file))];for(const e of t)try{await u.unlink(e)}catch{}}class $ extends z{allStats=[];summary=null;getDefaultOptions(){return{algorithm:"gzip",threshold:1024,deleteOriginalFile:!1,includeExtensions:[".js",".css",".html",".svg",".json",".xml",".txt"],excludeExtensions:[],excludePaths:[],compressionLevel:9,brotliQuality:11,reportOutput:"compress-report.json",parallelLimit:10}}validateOptions(){this.validator.field("algorithm").enum(["gzip","brotli","both"]).field("threshold").number().minValue(0).field("deleteOriginalFile").boolean().field("includeExtensions").array().field("excludeExtensions").array().field("excludePaths").array().field("compressionLevel").number().minValue(1).maxValue(9).field("brotliQuality").number().minValue(1).maxValue(11).field("reportOutput").custom(t=>t===!1||typeof t=="string","reportOutput \u5FC5\u987B\u4E3A false \u6216\u5B57\u7B26\u4E32\u8DEF\u5F84").field("parallelLimit").number().minValue(1).maxValue(50).validate()}getPluginName(){return"compress-assets"}getEnforce(){return"post"}addPluginHooks(t){t.writeBundle=async()=>{await this.safeExecute(()=>this.compressAllFiles(),"\u538B\u7F29\u6784\u5EFA\u4EA7\u7269")}}async compressAllFiles(){if(!this.viteConfig)return;const t=this.viteConfig.build.outDir,e=Date.now();this.logger.info(`\u5F00\u59CB\u626B\u63CF\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55: ${t}`);const s=await A(t,this.options);if(s.length===0){this.logger.info("\u672A\u627E\u5230\u9700\u8981\u538B\u7F29\u7684\u6587\u4EF6");return}this.logger.info(`\u53D1\u73B0 ${s.length} \u4E2A\u5F85\u538B\u7F29\u6587\u4EF6`),this.allStats=[];const r=this.options.algorithm==="both"?["gzip","brotli"]:[this.options.algorithm];for(const l of r){const a=await w(s,async n=>C(n.filePath,l,this.options.compressionLevel,this.options.brotliQuality),this.options.parallelLimit);this.allStats.push(...a)}const o=Date.now()-e;this.summary=D(this.allStats,o),this.options.deleteOriginalFile&&(await P(this.allStats),this.logger.info("\u5DF2\u5220\u9664\u539F\u59CB\u6587\u4EF6\uFF0C\u4EC5\u4FDD\u7559\u538B\u7F29\u7248\u672C")),this.options.reportOutput&&(await v(t,this.options.reportOutput,this.summary),this.logger.info(`\u538B\u7F29\u62A5\u544A\u5DF2\u751F\u6210: ${this.options.reportOutput}`)),this.logSummary()}logSummary(){if(!this.summary)return;const{totalFiles:t,totalOriginalSize:e,totalCompressedSize:s,totalRatio:r,executionTime:o}=this.summary;this.logger.success(`\u538B\u7F29\u5B8C\u6210: ${t} \u4E2A\u6587\u4EF6`,`\u539F\u59CB\u4F53\u79EF: ${c(e)} \u2192 \u538B\u7F29\u540E: ${c(s)}\uFF0C\u538B\u7F29\u7387: ${r}%\uFF0C\u8017\u65F6: ${o}ms`);const l=[...this.allStats].sort((a,n)=>n.ratio-a.ratio).slice(0,5);if(l.length>0){this.logger.info("\u538B\u7F29\u7387 Top 5:");for(const a of l)this.logger.info(` ${a.algorithm.toUpperCase().padEnd(6)} ${a.ratio}% ${c(a.originalSize)} \u2192 ${c(a.compressedSize)}`)}}getStats(){return[...this.allStats]}getSummary(){return this.summary}}const L=d($);export{L as compressAssets};
@@ -1,7 +1,7 @@
1
- "use strict";const factory_index=require("../../factory/index.cjs"),common_script_index=require("../../common/script/index.cjs"),r=require("node:path");require("../../logger/index.cjs"),require("../../common/object/index.cjs"),require("../../shared/vite-plugin.Bcg6RW2N.cjs");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const r__default=_interopDefaultCompat(r),g$1=["script","iframe","object","embed","applet","form","input","textarea","select","button"],b=["onclick","ondblclick","onmouseover","onmouseout","onmousemove","onmousedown","onmouseup","onkeydown","onkeyup","onkeypress","onload","onerror","onfocus","onblur","onsubmit","onchange","oninput","oncontextmenu","ondrag","ondrop","onanimationend","ontransitionend"];function validateRules(e){if(!e.rules||!Array.isArray(e.rules))throw new Error("rules \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");if(e.rules.length===0)throw new Error("rules \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4");for(let t=0;t<e.rules.length;t++)m(e.rules[t],t)}function m(e,t){if(!e.content||typeof e.content!="string")throw new Error(`rules[${t}].content \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);if(!e.position||typeof e.position!="string")throw new Error(`rules[${t}].position \u5FC5\u987B\u662F\u6709\u6548\u7684\u6CE8\u5165\u4F4D\u7F6E`);const n=["head-start","head-end","body-start","body-end","before-selector","after-selector","replace-selector"];if(!n.includes(e.position))throw new Error(`rules[${t}].position \u5FC5\u987B\u662F ${n.join(", ")} \u4E4B\u4E00`);if(e.position.includes("selector")&&!e.selector)throw new Error(`rules[${t}].position \u4E3A "${e.position}" \u65F6\uFF0Cselector \u4E3A\u5FC5\u586B\u9879`);if(e.priority!==void 0&&(typeof e.priority!="number"||e.priority<0))throw new Error(`rules[${t}].priority \u5FC5\u987B\u662F\u975E\u8D1F\u6570`);e.condition&&y(e.condition,t)}function y(e,t){if(!e)return;const n=["env","file-contains","custom"];if(!n.includes(e.type))throw new Error(`rules[${t}].condition.type \u5FC5\u987B\u662F ${n.join(", ")} \u4E4B\u4E00`);if(e.type==="custom"&&typeof e.value!="function")throw new Error(`rules[${t}].condition.type \u4E3A "custom" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u51FD\u6570`);if(e.type!=="custom"&&typeof e.value!="string")throw new Error(`rules[${t}].condition.type \u4E3A "${e.type}" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`)}function validateSecurityConfig(e){if(e){if(e.blockedTags&&!Array.isArray(e.blockedTags))throw new Error("security.blockedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(e.allowedTags&&!Array.isArray(e.allowedTags))throw new Error("security.allowedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(e.blockedAttributes&&!Array.isArray(e.blockedAttributes))throw new Error("security.blockedAttributes \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4")}}function validateAll(e){validateRules(e),validateSecurityConfig(e.security)}function sanitizeContent(e,t,n,i){const c=n?.blockDangerousTags!==!1,o=n?.blockDangerousAttributes!==!1,s=n?.blockedTags||g$1,f=n?.allowedTags,a=n?.blockedAttributes||b;let l=e;if(c){const E=f?s.filter(d=>!f.includes(d)):s;if(common_script_index.containsScriptTag(e))if(t.allowScriptInjection)i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5DF2\u542F\u7528\u811A\u672C\u6CE8\u5165(allowScriptInjection=true)\uFF0C\u8BF7\u786E\u4FDD\u6CE8\u5165\u5185\u5BB9\u6765\u6E90\u53EF\u4FE1\u3002\u6CE8\u5165\u811A\u672C\u53EF\u80FD\u5E26\u6765 XSS \u653B\u51FB\u98CE\u9669\u3002`);else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B <script> \u6807\u7B7E\uFF0C\u9ED8\u8BA4\u88AB\u963B\u6B62\u3002\u5982\u9700\u6CE8\u5165\u811A\u672C\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);for(const d of E){if(d==="script")continue;const F=new RegExp(`<${d}\\b[^>]*>[\\s\\S]*?<\\/${d}>`,"gi"),h=new RegExp(`<${d}\\b[^>]*/?>`,"gi");if(F.test(l)||h.test(l))if(t.allowScriptInjection){i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${d}>\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${d}>\u3002\u5982\u9700\u6CE8\u5165\u6B64\u6807\u7B7E\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true \u6216\u5728 security.allowedTags \u4E2D\u6DFB\u52A0 "${d}"`);l=l.replace(F,""),l=l.replace(h,"")}}if(o)for(const E of a){const d=new RegExp(`\\s${E}\\s*=\\s*["'][^"']*["']`,"gi");if(d.test(l))if(t.allowScriptInjection){i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5305\u542B\u5371\u9669\u5C5E\u6027 ${E}\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u5371\u9669\u5C5E\u6027 ${E}\u3002\u5982\u9700\u6CE8\u5165\u6B64\u5C5E\u6027\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);l=l.replace(d,"")}return l}function g(e,t,n){if(n==="regex"){try{const c=new RegExp(t),o=e.match(c);if(o&&o.index!==void 0)return{index:o.index,length:o[0].length}}catch{return null}return null}const i=e.indexOf(t);return i===-1?null:{index:i,length:t.length}}function applyTemplateVars(e,t,n){let i=e;const c={...n,...t};for(const[o,s]of Object.entries(c)){const f=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=s.replace(/\$/g,"$$$$");i=i.replace(new RegExp(`\\{\\{${f}\\}\\}`,"g"),a)}return i}function evaluateCondition(e,t){let n=!1;switch(e.type){case"env":{const i=e.value,c=process.env[i];n=!!c&&c!=="false"&&c!=="0";break}case"file-contains":{const i=e.value;n=t.includes(i);break}case"custom":{const i=e.value;try{n=!!i()}catch{n=!1}break}}return e.negate?!n:n}function sortRulesByPriority(e){return[...e].sort((t,n)=>(t.priority??100)-(n.priority??100))}function injectAtPosition(e,t,n,i,c){switch(n){case"head-start":{const o=e.match(/<head\b[^>]*>/i);if(!o)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 <head> \u6807\u7B7E"};const s=(o.index??0)+o[0].length;return{html:e.slice(0,s)+`
2
- `+t+e.slice(s),injected:!0}}case"head-end":{const o=e.match(/<\/head\s*>/i);if(!o)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 </head> \u6807\u7B7E"};const s=o.index;return{html:e.slice(0,s)+t+`
3
- `+e.slice(s),injected:!0}}case"body-start":{const o=e.match(/<body\b[^>]*>/i);if(!o)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 <body> \u6807\u7B7E"};const s=(o.index??0)+o[0].length;return{html:e.slice(0,s)+`
4
- `+t+e.slice(s),injected:!0}}case"body-end":{const o=e.match(/<\/body\s*>/i);if(!o)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 </body> \u6807\u7B7E"};const s=o.index;return{html:e.slice(0,s)+t+`
5
- `+e.slice(s),injected:!0}}case"before-selector":{if(!i)return{html:e,injected:!1,reason:"before-selector \u9700\u8981 selector \u53C2\u6570"};const o=g(e,i,c);return o?{html:e.slice(0,o.index)+t+`
6
- `+e.slice(o.index),injected:!0}:{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`}}case"after-selector":{if(!i)return{html:e,injected:!1,reason:"after-selector \u9700\u8981 selector \u53C2\u6570"};const o=g(e,i,c);if(!o)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`};const s=o.index+o.length;return{html:e.slice(0,s)+`
7
- `+t+e.slice(s),injected:!0}}case"replace-selector":{if(!i)return{html:e,injected:!1,reason:"replace-selector \u9700\u8981 selector \u53C2\u6570"};const o=g(e,i,c);if(!o)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`};const s=o.index+o.length;return{html:e.slice(0,o.index)+t+e.slice(s),injected:!0}}default:return{html:e,injected:!1,reason:`\u4E0D\u652F\u6301\u7684\u6CE8\u5165\u4F4D\u7F6E: ${n}`}}}function processRules(e,t,n,i,c){let o=e;const s=[],f=sortRulesByPriority(t);for(const a of f){const l={ruleId:a.id||"unnamed",position:a.position,selector:a.selector,injected:!1,timestamp:Date.now()};if(a.condition&&!evaluateCondition(a.condition,o)){l.injected=!1,l.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",s.push(l);continue}let E=applyTemplateVars(a.content,a.templateVars,n);try{E=sanitizeContent(E,a,i,c)}catch(F){l.injected=!1,l.reason=F.message,s.push(l),c?.warn(`\u89C4\u5219 "${a.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${F.message}`);continue}const d=injectAtPosition(o,E,a.position,a.selector,a.selectorMatch);o=d.html,l.injected=d.injected,l.reason=d.reason,s.push(l)}return{html:o,logs:s}}class u extends factory_index.BasePlugin{injectionLogs=[];getDefaultOptions(){return{targetFile:"index.html",logInjection:!0,security:{blockDangerousTags:!0,blockDangerousAttributes:!0}}}validateOptions(){this.validator.field("targetFile").string().field("rules").required().field("logInjection").boolean().validate(),validateAll(this.options)}getPluginName(){return"html-inject"}isTargetFile(t,n){if(n==="index.html")return t.endsWith("index.html")||t.endsWith("index.htm");const i=n.replace(/\\/g,"/"),c=t.replace(/\\/g,"/");return c.endsWith(i)?!0:r__default.basename(c)===r__default.basename(i)}addPluginHooks(t){t.transformIndexHtml={order:"post",handler:(n,i)=>{const c=i.filename||"",o=this.options.targetFile||"index.html";if(!this.isTargetFile(c,o))return n;const s={warn:a=>this.logger.warn(a)},f=processRules(n,this.options.rules,this.options.templateVars,this.options.security,s);return this.injectionLogs=f.logs,this.options.logInjection&&this.logInjectionResults(f.logs),f.html}},t.buildEnd=()=>{this.options.logInjection&&this.injectionLogs.length>0&&this.logger.info(`\u6CE8\u5165\u5B8C\u6210\uFF0C\u5171\u5904\u7406 ${this.injectionLogs.length} \u6761\u89C4\u5219`)}}logInjectionResults(t){for(const n of t)n.injected?this.logger.success(`\u89C4\u5219 "${n.ruleId}" \u6CE8\u5165\u6210\u529F (\u4F4D\u7F6E: ${n.position}${n.selector?`, \u9009\u62E9\u5668: ${n.selector}`:""})`):this.logger.warn(`\u89C4\u5219 "${n.ruleId}" \u6CE8\u5165\u5931\u8D25: ${n.reason||"\u672A\u77E5\u539F\u56E0"}`)}getInjectionLogs(){return[...this.injectionLogs]}}const htmlInject=factory_index.createPluginFactory(u);exports.htmlInject=htmlInject;
1
+ "use strict";const factory_index=require("../../factory/index.cjs"),common_script_index=require("../../common/script/index.cjs"),o=require("node:path");require("../../logger/index.cjs"),require("../../common/object/index.cjs"),require("../../shared/vite-plugin.Bcg6RW2N.cjs");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const o__default=_interopDefaultCompat(o),g$1=["script","iframe","object","embed","applet","form","input","textarea","select","button"],b=["onclick","ondblclick","onmouseover","onmouseout","onmousemove","onmousedown","onmouseup","onkeydown","onkeyup","onkeypress","onload","onerror","onfocus","onblur","onsubmit","onchange","oninput","oncontextmenu","ondrag","ondrop","onanimationend","ontransitionend"];function validateRules(e){if(!e.rules||!Array.isArray(e.rules))throw new Error("rules \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");if(e.rules.length===0)throw new Error("rules \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4");for(let t=0;t<e.rules.length;t++)m(e.rules[t],t)}function m(e,t){if(!e.content||typeof e.content!="string")throw new Error(`rules[${t}].content \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);if(!e.position||typeof e.position!="string")throw new Error(`rules[${t}].position \u5FC5\u987B\u662F\u6709\u6548\u7684\u6CE8\u5165\u4F4D\u7F6E`);const n=["head-start","head-end","body-start","body-end","before-selector","after-selector","replace-selector"];if(!n.includes(e.position))throw new Error(`rules[${t}].position \u5FC5\u987B\u662F ${n.join(", ")} \u4E4B\u4E00`);if(e.position.includes("selector")&&!e.selector)throw new Error(`rules[${t}].position \u4E3A "${e.position}" \u65F6\uFF0Cselector \u4E3A\u5FC5\u586B\u9879`);if(e.priority!==void 0&&(typeof e.priority!="number"||e.priority<0))throw new Error(`rules[${t}].priority \u5FC5\u987B\u662F\u975E\u8D1F\u6570`);e.condition&&y(e.condition,t)}function y(e,t){if(!e)return;const n=["env","file-contains","custom"];if(!n.includes(e.type))throw new Error(`rules[${t}].condition.type \u5FC5\u987B\u662F ${n.join(", ")} \u4E4B\u4E00`);if(e.type==="custom"&&typeof e.value!="function")throw new Error(`rules[${t}].condition.type \u4E3A "custom" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u51FD\u6570`);if(e.type!=="custom"&&typeof e.value!="string")throw new Error(`rules[${t}].condition.type \u4E3A "${e.type}" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`)}function validateSecurityConfig(e){if(e){if(e.blockedTags&&!Array.isArray(e.blockedTags))throw new Error("security.blockedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(e.allowedTags&&!Array.isArray(e.allowedTags))throw new Error("security.allowedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(e.blockedAttributes&&!Array.isArray(e.blockedAttributes))throw new Error("security.blockedAttributes \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4")}}function validateAll(e){validateRules(e),validateSecurityConfig(e.security)}function sanitizeContent(e,t,n,i){const c=n?.blockDangerousTags!==!1,r=n?.blockDangerousAttributes!==!1,s=n?.blockedTags||g$1,f=n?.allowedTags,a=n?.blockedAttributes||b;let l=e;if(c){const E=f?s.filter(d=>!f.includes(d)):s;if(common_script_index.containsScriptTag(e))if(t.allowScriptInjection)i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5DF2\u542F\u7528\u811A\u672C\u6CE8\u5165(allowScriptInjection=true)\uFF0C\u8BF7\u786E\u4FDD\u6CE8\u5165\u5185\u5BB9\u6765\u6E90\u53EF\u4FE1\u3002\u6CE8\u5165\u811A\u672C\u53EF\u80FD\u5E26\u6765 XSS \u653B\u51FB\u98CE\u9669\u3002`);else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B <script> \u6807\u7B7E\uFF0C\u9ED8\u8BA4\u88AB\u963B\u6B62\u3002\u5982\u9700\u6CE8\u5165\u811A\u672C\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);for(const d of E){if(d==="script")continue;const F=new RegExp(`<${d}\\b[^>]*>[\\s\\S]*?<\\/${d}>`,"gi"),h=new RegExp(`<${d}\\b[^>]*/?>`,"gi");if(F.test(l)||h.test(l))if(t.allowScriptInjection){i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${d}>\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${d}>\u3002\u5982\u9700\u6CE8\u5165\u6B64\u6807\u7B7E\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true \u6216\u5728 security.allowedTags \u4E2D\u6DFB\u52A0 "${d}"`);l=l.replace(F,""),l=l.replace(h,"")}}if(r)for(const E of a){const d=new RegExp(`\\s${E}\\s*=\\s*["'][^"']*["']`,"gi");if(d.test(l))if(t.allowScriptInjection){i?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${t.id||"unnamed"}" \u5305\u542B\u5371\u9669\u5C5E\u6027 ${E}\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${t.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u5371\u9669\u5C5E\u6027 ${E}\u3002\u5982\u9700\u6CE8\u5165\u6B64\u5C5E\u6027\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);l=l.replace(d,"")}return l}function g(e,t,n){if(n==="regex"){try{const c=new RegExp(t),r=e.match(c);if(r&&r.index!==void 0)return{index:r.index,length:r[0].length}}catch{return null}return null}const i=e.indexOf(t);return i===-1?null:{index:i,length:t.length}}function applyTemplateVars(e,t,n){let i=e;const c={...n,...t};for(const[r,s]of Object.entries(c)){const f=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=s.replace(/\$/g,"$$$$");i=i.replace(new RegExp(`\\{\\{${f}\\}\\}`,"g"),a)}return i}function evaluateCondition(e,t){let n=!1;switch(e.type){case"env":{const i=e.value,c=process.env[i];n=!!c&&c!=="false"&&c!=="0";break}case"file-contains":{const i=e.value;n=t.includes(i);break}case"custom":{const i=e.value;try{n=!!i()}catch{n=!1}break}}return e.negate?!n:n}function sortRulesByPriority(e){return[...e].sort((t,n)=>(t.priority??100)-(n.priority??100))}function injectAtPosition(e,t,n,i,c){switch(n){case"head-start":{const r=e.match(/<head\b[^>]*>/i);if(!r)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 <head> \u6807\u7B7E"};const s=(r.index??0)+r[0].length;return{html:e.slice(0,s)+`
2
+ `+t+e.slice(s),injected:!0}}case"head-end":{const r=e.match(/<\/head\s*>/i);if(!r)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 </head> \u6807\u7B7E"};const s=r.index;return{html:e.slice(0,s)+t+`
3
+ `+e.slice(s),injected:!0}}case"body-start":{const r=e.match(/<body\b[^>]*>/i);if(!r)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 <body> \u6807\u7B7E"};const s=(r.index??0)+r[0].length;return{html:e.slice(0,s)+`
4
+ `+t+e.slice(s),injected:!0}}case"body-end":{const r=e.match(/<\/body\s*>/i);if(!r)return{html:e,injected:!1,reason:"\u672A\u627E\u5230 </body> \u6807\u7B7E"};const s=r.index;return{html:e.slice(0,s)+t+`
5
+ `+e.slice(s),injected:!0}}case"before-selector":{if(!i)return{html:e,injected:!1,reason:"before-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,i,c);return r?{html:e.slice(0,r.index)+t+`
6
+ `+e.slice(r.index),injected:!0}:{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`}}case"after-selector":{if(!i)return{html:e,injected:!1,reason:"after-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,i,c);if(!r)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`};const s=r.index+r.length;return{html:e.slice(0,s)+`
7
+ `+t+e.slice(s),injected:!0}}case"replace-selector":{if(!i)return{html:e,injected:!1,reason:"replace-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,i,c);if(!r)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${i}"`};const s=r.index+r.length;return{html:e.slice(0,r.index)+t+e.slice(s),injected:!0}}default:return{html:e,injected:!1,reason:`\u4E0D\u652F\u6301\u7684\u6CE8\u5165\u4F4D\u7F6E: ${n}`}}}function processRules(e,t,n,i,c){let r=e;const s=[],f=sortRulesByPriority(t);for(const a of f){const l={ruleId:a.id||"unnamed",position:a.position,selector:a.selector,injected:!1,timestamp:Date.now()};if(a.condition&&!evaluateCondition(a.condition,r)){l.injected=!1,l.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",s.push(l);continue}let E=applyTemplateVars(a.content,a.templateVars,n);try{E=sanitizeContent(E,a,i,c)}catch(F){l.injected=!1,l.reason=F.message,s.push(l),c?.warn(`\u89C4\u5219 "${a.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${F.message}`);continue}const d=injectAtPosition(r,E,a.position,a.selector,a.selectorMatch);r=d.html,l.injected=d.injected,l.reason=d.reason,s.push(l)}return{html:r,logs:s}}class u extends factory_index.BasePlugin{injectionLogs=[];getDefaultOptions(){return{targetFile:"index.html",logInjection:!0,security:{blockDangerousTags:!0,blockDangerousAttributes:!0}}}validateOptions(){this.validator.field("targetFile").string().field("rules").required().field("logInjection").boolean().validate(),validateAll(this.options)}getPluginName(){return"html-inject"}isTargetFile(t,n){if(n==="index.html")return t.endsWith("index.html")||t.endsWith("index.htm");const i=n.replace(/\\/g,"/"),c=t.replace(/\\/g,"/");return c.endsWith(i)?!0:o__default.basename(c)===o__default.basename(i)}addPluginHooks(t){t.transformIndexHtml={order:"post",handler:(n,i)=>{const c=i.filename||"",r=this.options.targetFile||"index.html";if(!this.isTargetFile(c,r))return n;const s={warn:a=>this.logger.warn(a)},f=processRules(n,this.options.rules,this.options.templateVars,this.options.security,s);return this.injectionLogs=f.logs,this.options.logInjection&&this.logInjectionResults(f.logs),f.html}},t.buildEnd=()=>{this.options.logInjection&&this.injectionLogs.length>0&&this.logger.info(`\u6CE8\u5165\u5B8C\u6210\uFF0C\u5171\u5904\u7406 ${this.injectionLogs.length} \u6761\u89C4\u5219`)}}logInjectionResults(t){for(const n of t)n.injected?this.logger.success(`\u89C4\u5219 "${n.ruleId}" \u6CE8\u5165\u6210\u529F (\u4F4D\u7F6E: ${n.position}${n.selector?`, \u9009\u62E9\u5668: ${n.selector}`:""})`):this.logger.warn(`\u89C4\u5219 "${n.ruleId}" \u6CE8\u5165\u5931\u8D25: ${n.reason||"\u672A\u77E5\u539F\u56E0"}`)}getInjectionLogs(){return[...this.injectionLogs]}}const htmlInject=factory_index.createPluginFactory(u);exports.htmlInject=htmlInject;
@@ -1,7 +1,7 @@
1
- import{createPluginFactory as p,BasePlugin as g}from"../../factory/index.mjs";import{containsScriptTag as B}from"../../common/script/index.mjs";import h from"node:path";import"../../logger/index.mjs";import"../../common/object/index.mjs";import"../../shared/vite-plugin.DcExl6jd.mjs";const m=["script","iframe","object","embed","applet","form","input","textarea","select","button"],C=["onclick","ondblclick","onmouseover","onmouseout","onmousemove","onmousedown","onmouseup","onkeydown","onkeyup","onkeypress","onload","onerror","onfocus","onblur","onsubmit","onchange","oninput","oncontextmenu","ondrag","ondrop","onanimationend","ontransitionend"];function w(u){if(!u.rules||!Array.isArray(u.rules))throw new Error("rules \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");if(u.rules.length===0)throw new Error("rules \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4");for(let e=0;e<u.rules.length;e++)y(u.rules[e],e)}function y(u,e){if(!u.content||typeof u.content!="string")throw new Error(`rules[${e}].content \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);if(!u.position||typeof u.position!="string")throw new Error(`rules[${e}].position \u5FC5\u987B\u662F\u6709\u6548\u7684\u6CE8\u5165\u4F4D\u7F6E`);const t=["head-start","head-end","body-start","body-end","before-selector","after-selector","replace-selector"];if(!t.includes(u.position))throw new Error(`rules[${e}].position \u5FC5\u987B\u662F ${t.join(", ")} \u4E4B\u4E00`);if(u.position.includes("selector")&&!u.selector)throw new Error(`rules[${e}].position \u4E3A "${u.position}" \u65F6\uFF0Cselector \u4E3A\u5FC5\u586B\u9879`);if(u.priority!==void 0&&(typeof u.priority!="number"||u.priority<0))throw new Error(`rules[${e}].priority \u5FC5\u987B\u662F\u975E\u8D1F\u6570`);u.condition&&j(u.condition,e)}function j(u,e){if(!u)return;const t=["env","file-contains","custom"];if(!t.includes(u.type))throw new Error(`rules[${e}].condition.type \u5FC5\u987B\u662F ${t.join(", ")} \u4E4B\u4E00`);if(u.type==="custom"&&typeof u.value!="function")throw new Error(`rules[${e}].condition.type \u4E3A "custom" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u51FD\u6570`);if(u.type!=="custom"&&typeof u.value!="string")throw new Error(`rules[${e}].condition.type \u4E3A "${u.type}" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`)}function b(u){if(u){if(u.blockedTags&&!Array.isArray(u.blockedTags))throw new Error("security.blockedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(u.allowedTags&&!Array.isArray(u.allowedTags))throw new Error("security.allowedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(u.blockedAttributes&&!Array.isArray(u.blockedAttributes))throw new Error("security.blockedAttributes \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4")}}function $(u){w(u),b(u.security)}function A(u,e,t,r){const i=t?.blockDangerousTags!==!1,n=t?.blockDangerousAttributes!==!1,o=t?.blockedTags||m,a=t?.allowedTags,l=t?.blockedAttributes||C;let s=u;if(i){const d=a?o.filter(c=>!a.includes(c)):o;if(B(u))if(e.allowScriptInjection)r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5DF2\u542F\u7528\u811A\u672C\u6CE8\u5165(allowScriptInjection=true)\uFF0C\u8BF7\u786E\u4FDD\u6CE8\u5165\u5185\u5BB9\u6765\u6E90\u53EF\u4FE1\u3002\u6CE8\u5165\u811A\u672C\u53EF\u80FD\u5E26\u6765 XSS \u653B\u51FB\u98CE\u9669\u3002`);else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B <script> \u6807\u7B7E\uFF0C\u9ED8\u8BA4\u88AB\u963B\u6B62\u3002\u5982\u9700\u6CE8\u5165\u811A\u672C\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);for(const c of d){if(c==="script")continue;const f=new RegExp(`<${c}\\b[^>]*>[\\s\\S]*?<\\/${c}>`,"gi"),F=new RegExp(`<${c}\\b[^>]*/?>`,"gi");if(f.test(s)||F.test(s))if(e.allowScriptInjection){r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${c}>\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${c}>\u3002\u5982\u9700\u6CE8\u5165\u6B64\u6807\u7B7E\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true \u6216\u5728 security.allowedTags \u4E2D\u6DFB\u52A0 "${c}"`);s=s.replace(f,""),s=s.replace(F,"")}}if(n)for(const d of l){const c=new RegExp(`\\s${d}\\s*=\\s*["'][^"']*["']`,"gi");if(c.test(s))if(e.allowScriptInjection){r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5305\u542B\u5371\u9669\u5C5E\u6027 ${d}\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u5371\u9669\u5C5E\u6027 ${d}\u3002\u5982\u9700\u6CE8\u5165\u6B64\u5C5E\u6027\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);s=s.replace(c,"")}return s}function E(u,e,t){if(t==="regex"){try{const i=new RegExp(e),n=u.match(i);if(n&&n.index!==void 0)return{index:n.index,length:n[0].length}}catch{return null}return null}const r=u.indexOf(e);return r===-1?null:{index:r,length:e.length}}function D(u,e,t){let r=u;const i={...t,...e};for(const[n,o]of Object.entries(i)){const a=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=o.replace(/\$/g,"$$$$");r=r.replace(new RegExp(`\\{\\{${a}\\}\\}`,"g"),l)}return r}function x(u,e){let t=!1;switch(u.type){case"env":{const r=u.value,i=process.env[r];t=!!i&&i!=="false"&&i!=="0";break}case"file-contains":{const r=u.value;t=e.includes(r);break}case"custom":{const r=u.value;try{t=!!r()}catch{t=!1}break}}return u.negate?!t:t}function k(u){return[...u].sort((e,t)=>(e.priority??100)-(t.priority??100))}function v(u,e,t,r,i){switch(t){case"head-start":{const n=u.match(/<head\b[^>]*>/i);if(!n)return{html:u,injected:!1,reason:"\u672A\u627E\u5230 <head> \u6807\u7B7E"};const o=(n.index??0)+n[0].length;return{html:u.slice(0,o)+`
1
+ import{createPluginFactory as p,BasePlugin as g}from"../../factory/index.mjs";import{containsScriptTag as B}from"../../common/script/index.mjs";import h from"node:path";import"../../logger/index.mjs";import"../../common/object/index.mjs";import"../../shared/vite-plugin.DcExl6jd.mjs";const m=["script","iframe","object","embed","applet","form","input","textarea","select","button"],C=["onclick","ondblclick","onmouseover","onmouseout","onmousemove","onmousedown","onmouseup","onkeydown","onkeyup","onkeypress","onload","onerror","onfocus","onblur","onsubmit","onchange","oninput","oncontextmenu","ondrag","ondrop","onanimationend","ontransitionend"];function w(u){if(!u.rules||!Array.isArray(u.rules))throw new Error("rules \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");if(u.rules.length===0)throw new Error("rules \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4");for(let e=0;e<u.rules.length;e++)y(u.rules[e],e)}function y(u,e){if(!u.content||typeof u.content!="string")throw new Error(`rules[${e}].content \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);if(!u.position||typeof u.position!="string")throw new Error(`rules[${e}].position \u5FC5\u987B\u662F\u6709\u6548\u7684\u6CE8\u5165\u4F4D\u7F6E`);const t=["head-start","head-end","body-start","body-end","before-selector","after-selector","replace-selector"];if(!t.includes(u.position))throw new Error(`rules[${e}].position \u5FC5\u987B\u662F ${t.join(", ")} \u4E4B\u4E00`);if(u.position.includes("selector")&&!u.selector)throw new Error(`rules[${e}].position \u4E3A "${u.position}" \u65F6\uFF0Cselector \u4E3A\u5FC5\u586B\u9879`);if(u.priority!==void 0&&(typeof u.priority!="number"||u.priority<0))throw new Error(`rules[${e}].priority \u5FC5\u987B\u662F\u975E\u8D1F\u6570`);u.condition&&j(u.condition,e)}function j(u,e){if(!u)return;const t=["env","file-contains","custom"];if(!t.includes(u.type))throw new Error(`rules[${e}].condition.type \u5FC5\u987B\u662F ${t.join(", ")} \u4E4B\u4E00`);if(u.type==="custom"&&typeof u.value!="function")throw new Error(`rules[${e}].condition.type \u4E3A "custom" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u51FD\u6570`);if(u.type!=="custom"&&typeof u.value!="string")throw new Error(`rules[${e}].condition.type \u4E3A "${u.type}" \u65F6\uFF0Cvalue \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`)}function $(u){if(u){if(u.blockedTags&&!Array.isArray(u.blockedTags))throw new Error("security.blockedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(u.allowedTags&&!Array.isArray(u.allowedTags))throw new Error("security.allowedTags \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");if(u.blockedAttributes&&!Array.isArray(u.blockedAttributes))throw new Error("security.blockedAttributes \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4")}}function b(u){w(u),$(u.security)}function A(u,e,t,r){const i=t?.blockDangerousTags!==!1,n=t?.blockDangerousAttributes!==!1,o=t?.blockedTags||m,a=t?.allowedTags,l=t?.blockedAttributes||C;let s=u;if(i){const d=a?o.filter(c=>!a.includes(c)):o;if(B(u))if(e.allowScriptInjection)r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5DF2\u542F\u7528\u811A\u672C\u6CE8\u5165(allowScriptInjection=true)\uFF0C\u8BF7\u786E\u4FDD\u6CE8\u5165\u5185\u5BB9\u6765\u6E90\u53EF\u4FE1\u3002\u6CE8\u5165\u811A\u672C\u53EF\u80FD\u5E26\u6765 XSS \u653B\u51FB\u98CE\u9669\u3002`);else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B <script> \u6807\u7B7E\uFF0C\u9ED8\u8BA4\u88AB\u963B\u6B62\u3002\u5982\u9700\u6CE8\u5165\u811A\u672C\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);for(const c of d){if(c==="script")continue;const f=new RegExp(`<${c}\\b[^>]*>[\\s\\S]*?<\\/${c}>`,"gi"),F=new RegExp(`<${c}\\b[^>]*/?>`,"gi");if(f.test(s)||F.test(s))if(e.allowScriptInjection){r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${c}>\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u88AB\u963B\u6B62\u7684\u6807\u7B7E <${c}>\u3002\u5982\u9700\u6CE8\u5165\u6B64\u6807\u7B7E\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true \u6216\u5728 security.allowedTags \u4E2D\u6DFB\u52A0 "${c}"`);s=s.replace(f,""),s=s.replace(F,"")}}if(n)for(const d of l){const c=new RegExp(`\\s${d}\\s*=\\s*["'][^"']*["']`,"gi");if(c.test(s))if(e.allowScriptInjection){r?.warn(`[\u5B89\u5168\u8B66\u544A] \u89C4\u5219 "${e.id||"unnamed"}" \u5305\u542B\u5371\u9669\u5C5E\u6027 ${d}\uFF0C\u5DF2\u901A\u8FC7 allowScriptInjection \u8DF3\u8FC7\u5B89\u5168\u68C0\u67E5\uFF0C\u8BF7\u786E\u4FDD\u5185\u5BB9\u53EF\u4FE1\u3002`);continue}else throw new Error(`\u89C4\u5219 "${e.id||"unnamed"}" \u7684\u5185\u5BB9\u5305\u542B\u5371\u9669\u5C5E\u6027 ${d}\u3002\u5982\u9700\u6CE8\u5165\u6B64\u5C5E\u6027\uFF0C\u8BF7\u8BBE\u7F6E allowScriptInjection: true`);s=s.replace(c,"")}return s}function E(u,e,t){if(t==="regex"){try{const i=new RegExp(e),n=u.match(i);if(n&&n.index!==void 0)return{index:n.index,length:n[0].length}}catch{return null}return null}const r=u.indexOf(e);return r===-1?null:{index:r,length:e.length}}function D(u,e,t){let r=u;const i={...t,...e};for(const[n,o]of Object.entries(i)){const a=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=o.replace(/\$/g,"$$$$");r=r.replace(new RegExp(`\\{\\{${a}\\}\\}`,"g"),l)}return r}function x(u,e){let t=!1;switch(u.type){case"env":{const r=u.value,i=process.env[r];t=!!i&&i!=="false"&&i!=="0";break}case"file-contains":{const r=u.value;t=e.includes(r);break}case"custom":{const r=u.value;try{t=!!r()}catch{t=!1}break}}return u.negate?!t:t}function k(u){return[...u].sort((e,t)=>(e.priority??100)-(t.priority??100))}function v(u,e,t,r,i){switch(t){case"head-start":{const n=u.match(/<head\b[^>]*>/i);if(!n)return{html:u,injected:!1,reason:"\u672A\u627E\u5230 <head> \u6807\u7B7E"};const o=(n.index??0)+n[0].length;return{html:u.slice(0,o)+`
2
2
  `+e+u.slice(o),injected:!0}}case"head-end":{const n=u.match(/<\/head\s*>/i);if(!n)return{html:u,injected:!1,reason:"\u672A\u627E\u5230 </head> \u6807\u7B7E"};const o=n.index;return{html:u.slice(0,o)+e+`
3
3
  `+u.slice(o),injected:!0}}case"body-start":{const n=u.match(/<body\b[^>]*>/i);if(!n)return{html:u,injected:!1,reason:"\u672A\u627E\u5230 <body> \u6807\u7B7E"};const o=(n.index??0)+n[0].length;return{html:u.slice(0,o)+`
4
4
  `+e+u.slice(o),injected:!0}}case"body-end":{const n=u.match(/<\/body\s*>/i);if(!n)return{html:u,injected:!1,reason:"\u672A\u627E\u5230 </body> \u6807\u7B7E"};const o=n.index;return{html:u.slice(0,o)+e+`
5
5
  `+u.slice(o),injected:!0}}case"before-selector":{if(!r)return{html:u,injected:!1,reason:"before-selector \u9700\u8981 selector \u53C2\u6570"};const n=E(u,r,i);return n?{html:u.slice(0,n.index)+e+`
6
6
  `+u.slice(n.index),injected:!0}:{html:u,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${r}"`}}case"after-selector":{if(!r)return{html:u,injected:!1,reason:"after-selector \u9700\u8981 selector \u53C2\u6570"};const n=E(u,r,i);if(!n)return{html:u,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${r}"`};const o=n.index+n.length;return{html:u.slice(0,o)+`
7
- `+e+u.slice(o),injected:!0}}case"replace-selector":{if(!r)return{html:u,injected:!1,reason:"replace-selector \u9700\u8981 selector \u53C2\u6570"};const n=E(u,r,i);if(!n)return{html:u,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${r}"`};const o=n.index+n.length;return{html:u.slice(0,n.index)+e+u.slice(o),injected:!0}}default:return{html:u,injected:!1,reason:`\u4E0D\u652F\u6301\u7684\u6CE8\u5165\u4F4D\u7F6E: ${t}`}}}function I(u,e,t,r,i){let n=u;const o=[],a=k(e);for(const l of a){const s={ruleId:l.id||"unnamed",position:l.position,selector:l.selector,injected:!1,timestamp:Date.now()};if(l.condition&&!x(l.condition,n)){s.injected=!1,s.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",o.push(s);continue}let d=D(l.content,l.templateVars,t);try{d=A(d,l,r,i)}catch(f){s.injected=!1,s.reason=f.message,o.push(s),i?.warn(`\u89C4\u5219 "${l.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${f.message}`);continue}const c=v(n,d,l.position,l.selector,l.selectorMatch);n=c.html,s.injected=c.injected,s.reason=c.reason,o.push(s)}return{html:n,logs:o}}class T extends g{injectionLogs=[];getDefaultOptions(){return{targetFile:"index.html",logInjection:!0,security:{blockDangerousTags:!0,blockDangerousAttributes:!0}}}validateOptions(){this.validator.field("targetFile").string().field("rules").required().field("logInjection").boolean().validate(),$(this.options)}getPluginName(){return"html-inject"}isTargetFile(e,t){if(t==="index.html")return e.endsWith("index.html")||e.endsWith("index.htm");const r=t.replace(/\\/g,"/"),i=e.replace(/\\/g,"/");return i.endsWith(r)?!0:h.basename(i)===h.basename(r)}addPluginHooks(e){e.transformIndexHtml={order:"post",handler:(t,r)=>{const i=r.filename||"",n=this.options.targetFile||"index.html";if(!this.isTargetFile(i,n))return t;const o={warn:l=>this.logger.warn(l)},a=I(t,this.options.rules,this.options.templateVars,this.options.security,o);return this.injectionLogs=a.logs,this.options.logInjection&&this.logInjectionResults(a.logs),a.html}},e.buildEnd=()=>{this.options.logInjection&&this.injectionLogs.length>0&&this.logger.info(`\u6CE8\u5165\u5B8C\u6210\uFF0C\u5171\u5904\u7406 ${this.injectionLogs.length} \u6761\u89C4\u5219`)}}logInjectionResults(e){for(const t of e)t.injected?this.logger.success(`\u89C4\u5219 "${t.ruleId}" \u6CE8\u5165\u6210\u529F (\u4F4D\u7F6E: ${t.position}${t.selector?`, \u9009\u62E9\u5668: ${t.selector}`:""})`):this.logger.warn(`\u89C4\u5219 "${t.ruleId}" \u6CE8\u5165\u5931\u8D25: ${t.reason||"\u672A\u77E5\u539F\u56E0"}`)}getInjectionLogs(){return[...this.injectionLogs]}}const S=p(T);export{S as htmlInject};
7
+ `+e+u.slice(o),injected:!0}}case"replace-selector":{if(!r)return{html:u,injected:!1,reason:"replace-selector \u9700\u8981 selector \u53C2\u6570"};const n=E(u,r,i);if(!n)return{html:u,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${r}"`};const o=n.index+n.length;return{html:u.slice(0,n.index)+e+u.slice(o),injected:!0}}default:return{html:u,injected:!1,reason:`\u4E0D\u652F\u6301\u7684\u6CE8\u5165\u4F4D\u7F6E: ${t}`}}}function I(u,e,t,r,i){let n=u;const o=[],a=k(e);for(const l of a){const s={ruleId:l.id||"unnamed",position:l.position,selector:l.selector,injected:!1,timestamp:Date.now()};if(l.condition&&!x(l.condition,n)){s.injected=!1,s.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",o.push(s);continue}let d=D(l.content,l.templateVars,t);try{d=A(d,l,r,i)}catch(f){s.injected=!1,s.reason=f.message,o.push(s),i?.warn(`\u89C4\u5219 "${l.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${f.message}`);continue}const c=v(n,d,l.position,l.selector,l.selectorMatch);n=c.html,s.injected=c.injected,s.reason=c.reason,o.push(s)}return{html:n,logs:o}}class T extends g{injectionLogs=[];getDefaultOptions(){return{targetFile:"index.html",logInjection:!0,security:{blockDangerousTags:!0,blockDangerousAttributes:!0}}}validateOptions(){this.validator.field("targetFile").string().field("rules").required().field("logInjection").boolean().validate(),b(this.options)}getPluginName(){return"html-inject"}isTargetFile(e,t){if(t==="index.html")return e.endsWith("index.html")||e.endsWith("index.htm");const r=t.replace(/\\/g,"/"),i=e.replace(/\\/g,"/");return i.endsWith(r)?!0:h.basename(i)===h.basename(r)}addPluginHooks(e){e.transformIndexHtml={order:"post",handler:(t,r)=>{const i=r.filename||"",n=this.options.targetFile||"index.html";if(!this.isTargetFile(i,n))return t;const o={warn:l=>this.logger.warn(l)},a=I(t,this.options.rules,this.options.templateVars,this.options.security,o);return this.injectionLogs=a.logs,this.options.logInjection&&this.logInjectionResults(a.logs),a.html}},e.buildEnd=()=>{this.options.logInjection&&this.injectionLogs.length>0&&this.logger.info(`\u6CE8\u5165\u5B8C\u6210\uFF0C\u5171\u5904\u7406 ${this.injectionLogs.length} \u6761\u89C4\u5219`)}}logInjectionResults(e){for(const t of e)t.injected?this.logger.success(`\u89C4\u5219 "${t.ruleId}" \u6CE8\u5165\u6210\u529F (\u4F4D\u7F6E: ${t.position}${t.selector?`, \u9009\u62E9\u5668: ${t.selector}`:""})`):this.logger.warn(`\u89C4\u5219 "${t.ruleId}" \u6CE8\u5165\u5931\u8D25: ${t.reason||"\u672A\u77E5\u539F\u56E0"}`)}getInjectionLogs(){return[...this.injectionLogs]}}const S=p(T);export{S as htmlInject};
@@ -1 +1 @@
1
- "use strict";const plugins_buildProgress_index=require("./buildProgress/index.cjs"),plugins_copyFile_index=require("./copyFile/index.cjs"),plugins_faviconManager_index=require("./faviconManager/index.cjs"),plugins_generateRouter_index=require("./generateRouter/index.cjs"),plugins_generateVersion_index=require("./generateVersion/index.cjs"),plugins_htmlInject_index=require("./htmlInject/index.cjs"),plugins_loadingManager_index=require("./loadingManager/index.cjs"),plugins_versionUpdateChecker_index=require("./versionUpdateChecker/index.cjs");require("../factory/index.cjs"),require("../logger/index.cjs"),require("../common/object/index.cjs"),require("../shared/vite-plugin.Bcg6RW2N.cjs"),require("../common/fs/index.cjs"),require("fs"),require("path"),require("../common/html/index.cjs"),require("../common/format/index.cjs"),require("crypto"),require("../common/script/index.cjs"),require("node:path"),require("../common/validation/index.cjs"),exports.buildProgress=plugins_buildProgress_index.buildProgress,exports.copyFile=plugins_copyFile_index.copyFile,exports.faviconManager=plugins_faviconManager_index.faviconManager,exports.generateRouter=plugins_generateRouter_index.generateRouter,exports.generateVersion=plugins_generateVersion_index.generateVersion,exports.htmlInject=plugins_htmlInject_index.htmlInject,exports.loadingManager=plugins_loadingManager_index.loadingManager,exports.versionUpdateChecker=plugins_versionUpdateChecker_index.versionUpdateChecker;
1
+ "use strict";const plugins_buildProgress_index=require("./buildProgress/index.cjs"),plugins_compressAssets_index=require("./compressAssets/index.cjs"),plugins_copyFile_index=require("./copyFile/index.cjs"),plugins_faviconManager_index=require("./faviconManager/index.cjs"),plugins_generateRouter_index=require("./generateRouter/index.cjs"),plugins_generateVersion_index=require("./generateVersion/index.cjs"),plugins_htmlInject_index=require("./htmlInject/index.cjs"),plugins_loadingManager_index=require("./loadingManager/index.cjs"),plugins_versionUpdateChecker_index=require("./versionUpdateChecker/index.cjs");require("../factory/index.cjs"),require("../logger/index.cjs"),require("../common/object/index.cjs"),require("../shared/vite-plugin.Bcg6RW2N.cjs"),require("node:zlib"),require("node:fs"),require("node:stream/promises"),require("node:path"),require("../common/fs/index.cjs"),require("fs"),require("path"),require("../common/html/index.cjs"),require("../common/format/index.cjs"),require("crypto"),require("../common/script/index.cjs"),require("../common/validation/index.cjs"),exports.buildProgress=plugins_buildProgress_index.buildProgress,exports.compressAssets=plugins_compressAssets_index.compressAssets,exports.copyFile=plugins_copyFile_index.copyFile,exports.faviconManager=plugins_faviconManager_index.faviconManager,exports.generateRouter=plugins_generateRouter_index.generateRouter,exports.generateVersion=plugins_generateVersion_index.generateVersion,exports.htmlInject=plugins_htmlInject_index.htmlInject,exports.loadingManager=plugins_loadingManager_index.loadingManager,exports.versionUpdateChecker=plugins_versionUpdateChecker_index.versionUpdateChecker;