@meng-xi/vite-plugin 0.1.3 → 0.1.4
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 +48 -774
- package/README.md +45 -769
- package/dist/common/html/index.cjs +2 -2
- package/dist/common/html/index.d.cts +268 -19
- package/dist/common/html/index.d.mts +268 -19
- package/dist/common/html/index.d.ts +268 -19
- package/dist/common/html/index.mjs +2 -2
- package/dist/common/index.cjs +1 -1
- package/dist/common/index.d.cts +4 -1
- package/dist/common/index.d.mts +4 -1
- package/dist/common/index.d.ts +4 -1
- package/dist/common/index.mjs +1 -1
- package/dist/common/ui/index.cjs +1 -0
- package/dist/common/ui/index.d.cts +132 -0
- package/dist/common/ui/index.d.mts +132 -0
- package/dist/common/ui/index.d.ts +132 -0
- package/dist/common/ui/index.mjs +1 -0
- package/dist/common/validation/index.cjs +1 -1
- package/dist/common/validation/index.d.cts +1 -0
- package/dist/common/validation/index.d.mts +1 -0
- package/dist/common/validation/index.d.ts +1 -0
- package/dist/common/validation/index.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/dist/plugins/buildProgress/index.cjs +2 -2
- package/dist/plugins/buildProgress/index.mjs +2 -2
- package/dist/plugins/copyFile/index.d.cts +20 -2
- package/dist/plugins/copyFile/index.d.mts +20 -2
- package/dist/plugins/copyFile/index.d.ts +20 -2
- package/dist/plugins/envGuard/index.cjs +67 -0
- package/dist/plugins/envGuard/index.d.cts +156 -0
- package/dist/plugins/envGuard/index.d.mts +156 -0
- package/dist/plugins/envGuard/index.d.ts +156 -0
- package/dist/plugins/envGuard/index.mjs +67 -0
- package/dist/plugins/faviconManager/index.cjs +1 -1
- package/dist/plugins/faviconManager/index.d.cts +43 -5
- package/dist/plugins/faviconManager/index.d.mts +43 -5
- package/dist/plugins/faviconManager/index.d.ts +43 -5
- package/dist/plugins/faviconManager/index.mjs +1 -1
- package/dist/plugins/generateRouter/index.d.cts +61 -14
- package/dist/plugins/generateRouter/index.d.mts +61 -14
- package/dist/plugins/generateRouter/index.d.ts +61 -14
- package/dist/plugins/generateVersion/index.d.cts +12 -0
- package/dist/plugins/generateVersion/index.d.mts +12 -0
- package/dist/plugins/generateVersion/index.d.ts +12 -0
- package/dist/plugins/htmlInject/index.cjs +1 -7
- package/dist/plugins/htmlInject/index.d.cts +49 -194
- package/dist/plugins/htmlInject/index.d.mts +49 -194
- package/dist/plugins/htmlInject/index.d.ts +49 -194
- package/dist/plugins/htmlInject/index.mjs +1 -7
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.d.cts +4 -1
- package/dist/plugins/index.d.mts +4 -1
- package/dist/plugins/index.d.ts +4 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/plugins/loadingManager/index.cjs +2 -2
- package/dist/plugins/loadingManager/index.mjs +1 -1
- package/dist/plugins/versionUpdateChecker/index.cjs +2 -2
- package/dist/plugins/versionUpdateChecker/index.mjs +3 -3
- package/dist/shared/vite-plugin.BCuhU1au.mjs +7 -0
- package/dist/shared/vite-plugin.BrI73DHA.cjs +7 -0
- package/dist/shared/vite-plugin.CmtcnItg.d.cts +261 -0
- package/dist/shared/vite-plugin.CmtcnItg.d.mts +261 -0
- package/dist/shared/vite-plugin.CmtcnItg.d.ts +261 -0
- package/dist/shared/vite-plugin.DnFDPjNf.mjs +1 -0
- package/dist/shared/vite-plugin.Dumot0up.mjs +1 -0
- package/dist/shared/vite-plugin.FfJ-Wwfu.d.cts +143 -0
- package/dist/shared/vite-plugin.FfJ-Wwfu.d.mts +143 -0
- package/dist/shared/vite-plugin.FfJ-Wwfu.d.ts +143 -0
- package/dist/shared/vite-plugin.soT9a-KD.cjs +1 -0
- package/dist/shared/vite-plugin.vwox4bU0.cjs +1 -0
- package/package.json +11 -1
|
@@ -46,6 +46,18 @@ interface VersionInfo {
|
|
|
46
46
|
* 自动生成版本号插件的配置选项接口
|
|
47
47
|
*
|
|
48
48
|
* @interface GenerateVersionOptions
|
|
49
|
+
* @extends {BasePluginOptions}
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* generateVersion({
|
|
54
|
+
* format: 'semver',
|
|
55
|
+
* semverBase: '2.0.0',
|
|
56
|
+
* outputType: 'both',
|
|
57
|
+
* prefix: 'v',
|
|
58
|
+
* extra: { environment: 'production' }
|
|
59
|
+
* })
|
|
60
|
+
* ```
|
|
49
61
|
*/
|
|
50
62
|
interface GenerateVersionOptions extends BasePluginOptions {
|
|
51
63
|
/**
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
"use strict";const factory_index=require("../../factory/index.cjs"),
|
|
2
|
-
`+t+e.slice(i),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 i=r.index;return{html:e.slice(0,i)+t+`
|
|
3
|
-
`+e.slice(i),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 i=(r.index??0)+r[0].length;return{html:e.slice(0,i)+`
|
|
4
|
-
`+t+e.slice(i),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 i=r.index;return{html:e.slice(0,i)+t+`
|
|
5
|
-
`+e.slice(i),injected:!0}}case"before-selector":{if(!o)return{html:e,injected:!1,reason:"before-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,o,s);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 "${o}"`}}case"after-selector":{if(!o)return{html:e,injected:!1,reason:"after-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,o,s);if(!r)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${o}"`};const i=r.index+r.length;return{html:e.slice(0,i)+`
|
|
7
|
-
`+t+e.slice(i),injected:!0}}case"replace-selector":{if(!o)return{html:e,injected:!1,reason:"replace-selector \u9700\u8981 selector \u53C2\u6570"};const r=g(e,o,s);if(!r)return{html:e,injected:!1,reason:`\u672A\u627E\u5230\u9009\u62E9\u5668 "${o}"`};const i=r.index+r.length;return{html:e.slice(0,r.index)+t+e.slice(i),injected:!0}}default:return{html:e,injected:!1,reason:`\u4E0D\u652F\u6301\u7684\u6CE8\u5165\u4F4D\u7F6E: ${n}`}}}function processRules(e,t,n,o,s){let r=e;const i=[],f=sortRulesByPriority(t);for(const l of f){const c={ruleId:l.id||"unnamed",position:l.position,selector:l.selector,injected:!1,timestamp:Date.now()};if(l.condition&&!evaluateCondition(l.condition,r)){c.injected=!1,c.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",i.push(c);continue}let E=applyTemplateVars(l.content,l.templateVars,n);try{E=sanitizeContent(E,l,o,s)}catch(F){c.injected=!1,c.reason=F.message,i.push(c),s?.warn(`\u89C4\u5219 "${l.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${F.message}`);continue}const d=injectAtPosition(r,E,l.position,l.selector,l.selectorMatch);r=d.html,c.injected=d.injected,c.reason=d.reason,i.push(c)}return{html:r,logs:i}}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 o=n.replace(/\\/g,"/"),s=t.replace(/\\/g,"/");return s.endsWith(o)?!0:a__default.basename(s)===a__default.basename(o)}addPluginHooks(t){t.transformIndexHtml={order:"post",handler:(n,o)=>{const s=o.filename||"",r=this.options.targetFile||"index.html";if(!this.isTargetFile(s,r))return n;const i={warn:l=>this.logger.warn(l)},f=processRules(n,this.options.rules,this.options.templateVars,this.options.security,i);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"),security=require("../../shared/vite-plugin.BrI73DHA.cjs"),a=require("node:path");require("../../logger/index.cjs"),require("../../common/object/index.cjs"),require("../../shared/vite-plugin.Bcg6RW2N.cjs"),require("../../common/script/index.cjs");function _interopDefaultCompat(e){return e&&typeof e=="object"&&"default"in e?e.default:e}const a__default=_interopDefaultCompat(a);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++)s(e.rules[t],t)}function s(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 o=["head-start","head-end","body-start","body-end","before-selector","after-selector","replace-selector"];if(!o.includes(e.position))throw new Error(`rules[${t}].position \u5FC5\u987B\u662F ${o.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&&c(e.condition,t)}function c(e,t){if(!e)return;const o=["env","file-contains","custom"];if(!o.includes(e.type))throw new Error(`rules[${t}].condition.type \u5FC5\u987B\u662F ${o.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 validateAll(e){validateRules(e),security.validateSecurityConfig(e.security)}function processRules(e,t,o,l,r){let d=e;const p=[],h=security.sortRulesByPriority(t);for(const n of h){const i={ruleId:n.id||"unnamed",position:n.position,selector:n.selector,injected:!1,timestamp:Date.now()};if(n.condition&&!security.evaluateCondition(n.condition,d)){i.injected=!1,i.reason="\u6761\u4EF6\u4E0D\u6EE1\u8DB3\uFF0C\u8DF3\u8FC7\u6CE8\u5165",p.push(i);continue}let g=security.applyTemplateVars(n.content,n.templateVars,o);try{g=security.sanitizeContent(g,n,l,r)}catch(F){i.injected=!1,i.reason=F.message,p.push(i),r?.warn(`\u89C4\u5219 "${n.id||"unnamed"}" \u5B89\u5168\u68C0\u67E5\u5931\u8D25: ${F.message}`);continue}const f=security.injectAtPosition(d,g,n.position,n.selector,n.selectorMatch);d=f.html,i.injected=f.injected,i.reason=f.reason,p.push(i)}return{html:d,logs:p}}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,o){if(o==="index.html")return t.endsWith("index.html")||t.endsWith("index.htm");const l=o.replace(/\\/g,"/"),r=t.replace(/\\/g,"/");return r.endsWith(l)?!0:a__default.basename(r)===a__default.basename(l)}addPluginHooks(t){t.transformIndexHtml={order:"post",handler:(o,l)=>{const r=l.filename||"",d=this.options.targetFile||"index.html";if(!this.isTargetFile(r,d))return o;const p={warn:n=>this.logger.warn(n)},h=processRules(o,this.options.rules,this.options.templateVars,this.options.security,p);return this.injectionLogs=h.logs,this.options.logInjection&&this.logInjectionResults(h.logs),h.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 o of t)o.injected?this.logger.success(`\u89C4\u5219 "${o.ruleId}" \u6CE8\u5165\u6210\u529F (\u4F4D\u7F6E: ${o.position}${o.selector?`, \u9009\u62E9\u5668: ${o.selector}`:""})`):this.logger.warn(`\u89C4\u5219 "${o.ruleId}" \u6CE8\u5165\u5931\u8D25: ${o.reason||"\u672A\u77E5\u539F\u56E0"}`)}getInjectionLogs(){return[...this.injectionLogs]}}const htmlInject=factory_index.createPluginFactory(u);exports.htmlInject=htmlInject;
|
|
@@ -1,239 +1,94 @@
|
|
|
1
1
|
import { BasePluginOptions, PluginFactory } from '../../factory/index.cjs';
|
|
2
|
+
import { a as InjectPosition, b as SelectorMatch, I as InjectCondition, S as SecurityConfig } from '../../shared/vite-plugin.FfJ-Wwfu.cjs';
|
|
2
3
|
import 'vite';
|
|
3
4
|
import '../../shared/vite-plugin.CLr0ttuO.cjs';
|
|
4
5
|
import '../../shared/vite-plugin.DRRlWY8P.cjs';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @description
|
|
10
|
-
* - 'string': 使用字符串精确匹配(默认)
|
|
11
|
-
* - 'regex': 使用正则表达式匹配,支持更灵活的模式
|
|
12
|
-
*/
|
|
13
|
-
type SelectorMatch = 'string' | 'regex';
|
|
14
|
-
/**
|
|
15
|
-
* HTML 内容注入位置
|
|
16
|
-
*
|
|
17
|
-
* @description
|
|
18
|
-
* - 'head-start': 注入到 `<head>` 标签开始之后
|
|
19
|
-
* - 'head-end': 注入到 `</head>` 标签之前
|
|
20
|
-
* - 'body-start': 注入到 `<body>` 标签开始之后
|
|
21
|
-
* - 'body-end': 注入到 `</body>` 标签之前
|
|
22
|
-
* - 'before-selector': 注入到指定选择器之前
|
|
23
|
-
* - 'after-selector': 注入到指定选择器之后
|
|
24
|
-
* - 'replace-selector': 替换指定选择器匹配的内容
|
|
25
|
-
*/
|
|
26
|
-
type InjectPosition = 'head-start' | 'head-end' | 'body-start' | 'body-end' | 'before-selector' | 'after-selector' | 'replace-selector';
|
|
27
|
-
/**
|
|
28
|
-
* 条件类型
|
|
29
|
-
*
|
|
30
|
-
* @description
|
|
31
|
-
* - 'env': 基于环境变量判断
|
|
32
|
-
* - 'file-contains': 基于 HTML 文件内容判断
|
|
33
|
-
* - 'custom': 基于自定义函数判断
|
|
34
|
-
*/
|
|
35
|
-
type ConditionType = 'env' | 'file-contains' | 'custom';
|
|
36
|
-
/**
|
|
37
|
-
* 注入条件接口
|
|
38
|
-
*
|
|
39
|
-
* @interface InjectCondition
|
|
40
|
-
* @description 定义内容注入的触发条件,支持环境变量检测、文件内容检测和自定义函数
|
|
41
|
-
*/
|
|
42
|
-
interface InjectCondition {
|
|
43
|
-
/**
|
|
44
|
-
* 条件类型
|
|
45
|
-
*/
|
|
46
|
-
type: ConditionType;
|
|
47
|
-
/**
|
|
48
|
-
* 条件值
|
|
49
|
-
*
|
|
50
|
-
* @description
|
|
51
|
-
* - 当 type 为 'env' 时,为环境变量名(字符串)
|
|
52
|
-
* - 当 type 为 'file-contains' 时,为要搜索的字符串(字符串)
|
|
53
|
-
* - 当 type 为 'custom' 时,为返回布尔值的判断函数
|
|
54
|
-
*/
|
|
55
|
-
value: string | ((...args: any[]) => boolean);
|
|
56
|
-
/**
|
|
57
|
-
* 是否对条件结果取反
|
|
58
|
-
*
|
|
59
|
-
* @default false
|
|
60
|
-
*/
|
|
61
|
-
negate?: boolean;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 注入规则接口
|
|
8
|
+
* HTML 注入规则接口
|
|
65
9
|
*
|
|
66
10
|
* @interface InjectRule
|
|
67
|
-
* @description 定义单条 HTML
|
|
11
|
+
* @description 定义单条 HTML 内容注入规则,包含注入内容、位置、条件和安全配置。
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* {
|
|
16
|
+
* id: 'meta-viewport',
|
|
17
|
+
* content: '<meta name="viewport" content="width=device-width">',
|
|
18
|
+
* position: 'head-end',
|
|
19
|
+
* priority: 10
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
68
22
|
*/
|
|
69
23
|
interface InjectRule {
|
|
70
|
-
/**
|
|
71
|
-
* 规则唯一标识符,用于日志记录和调试
|
|
72
|
-
*/
|
|
24
|
+
/** 规则唯一标识,用于日志输出和调试追踪 */
|
|
73
25
|
id?: string;
|
|
74
|
-
/**
|
|
75
|
-
* 要注入的 HTML 内容
|
|
76
|
-
*
|
|
77
|
-
* @example '<meta name="description" content="My App">'
|
|
78
|
-
*/
|
|
26
|
+
/** 要注入的 HTML 内容字符串,支持模板变量占位符 `{{varName}}` */
|
|
79
27
|
content: string;
|
|
80
|
-
/**
|
|
81
|
-
* 注入位置
|
|
82
|
-
*/
|
|
28
|
+
/** 注入位置,如 'head-start'、'head-end'、'body-start'、'body-end' 等 */
|
|
83
29
|
position: InjectPosition;
|
|
84
|
-
/**
|
|
85
|
-
* 选择器字符串,当 position 为 selector 相关位置时必填
|
|
86
|
-
*
|
|
87
|
-
* @description 当 selectorMatch 为 'string' 时,使用字符串精确匹配;
|
|
88
|
-
* 当 selectorMatch 为 'regex' 时,使用正则表达式匹配
|
|
89
|
-
*
|
|
90
|
-
* @example '<div id="app">'
|
|
91
|
-
*/
|
|
30
|
+
/** CSS 选择器,仅在 position 为 'before-selector' 或 'after-selector' 时需要 */
|
|
92
31
|
selector?: string;
|
|
93
|
-
/**
|
|
94
|
-
* 选择器匹配模式
|
|
95
|
-
*
|
|
96
|
-
* @default 'string'
|
|
97
|
-
*/
|
|
32
|
+
/** 选择器匹配模式,仅在指定 selector 时有效 */
|
|
98
33
|
selectorMatch?: SelectorMatch;
|
|
99
|
-
/**
|
|
100
|
-
* 规则优先级,数值越小优先级越高,越先执行
|
|
101
|
-
*
|
|
102
|
-
* @default 100
|
|
103
|
-
*/
|
|
34
|
+
/** 规则优先级,数值越大越先执行 */
|
|
104
35
|
priority?: number;
|
|
105
|
-
/**
|
|
106
|
-
* 注入条件,满足条件时才执行注入
|
|
107
|
-
*/
|
|
36
|
+
/** 条件注入配置,满足条件时才执行注入 */
|
|
108
37
|
condition?: InjectCondition;
|
|
109
|
-
/**
|
|
110
|
-
* 规则级模板变量,会覆盖全局模板变量
|
|
111
|
-
*
|
|
112
|
-
* @description 使用 `{{变量名}}` 语法在 content 中引用变量
|
|
113
|
-
*
|
|
114
|
-
* @example { greeting: 'Hello', name: 'World' }
|
|
115
|
-
*/
|
|
38
|
+
/** 规则级别的模板变量,会与全局 templateVars 合并 */
|
|
116
39
|
templateVars?: Record<string, string>;
|
|
117
|
-
/**
|
|
118
|
-
* 是否允许注入脚本等危险内容
|
|
119
|
-
*
|
|
120
|
-
* @default false
|
|
121
|
-
* @remarks 启用此选项将跳过安全检查,请确保注入内容来源可信
|
|
122
|
-
*/
|
|
40
|
+
/** 是否允许注入 `<script>` 标签,默认为 false 以防止 XSS 攻击 */
|
|
123
41
|
allowScriptInjection?: boolean;
|
|
124
42
|
}
|
|
125
|
-
/**
|
|
126
|
-
* 安全配置接口
|
|
127
|
-
*
|
|
128
|
-
* @interface SecurityConfig
|
|
129
|
-
* @description 控制 HTML 注入内容的安全过滤行为,防止 XSS 攻击
|
|
130
|
-
*/
|
|
131
|
-
interface SecurityConfig {
|
|
132
|
-
/**
|
|
133
|
-
* 是否阻止危险标签(script、iframe、object 等)
|
|
134
|
-
*
|
|
135
|
-
* @default true
|
|
136
|
-
*/
|
|
137
|
-
blockDangerousTags?: boolean;
|
|
138
|
-
/**
|
|
139
|
-
* 是否阻止危险属性(onclick、onload 等事件处理器)
|
|
140
|
-
*
|
|
141
|
-
* @default true
|
|
142
|
-
*/
|
|
143
|
-
blockDangerousAttributes?: boolean;
|
|
144
|
-
/**
|
|
145
|
-
* 允许通过的标签白名单,白名单中的标签不会被阻止
|
|
146
|
-
*
|
|
147
|
-
* @example ['iframe', 'object']
|
|
148
|
-
*/
|
|
149
|
-
allowedTags?: string[];
|
|
150
|
-
/**
|
|
151
|
-
* 自定义阻止标签列表,覆盖默认阻止列表
|
|
152
|
-
*
|
|
153
|
-
* @example ['div', 'span']
|
|
154
|
-
*/
|
|
155
|
-
blockedTags?: string[];
|
|
156
|
-
/**
|
|
157
|
-
* 自定义阻止属性列表,覆盖默认阻止列表
|
|
158
|
-
*
|
|
159
|
-
* @example ['data-custom', 'data-track']
|
|
160
|
-
*/
|
|
161
|
-
blockedAttributes?: string[];
|
|
162
|
-
}
|
|
163
43
|
/**
|
|
164
44
|
* 注入日志条目接口
|
|
165
45
|
*
|
|
166
46
|
* @interface InjectionLogEntry
|
|
167
|
-
* @description
|
|
47
|
+
* @description 记录单条注入规则的执行结果,用于调试和统计。
|
|
168
48
|
*/
|
|
169
49
|
interface InjectionLogEntry {
|
|
170
|
-
/**
|
|
171
|
-
* 规则标识符
|
|
172
|
-
*/
|
|
50
|
+
/** 规则标识 */
|
|
173
51
|
ruleId: string;
|
|
174
|
-
/**
|
|
175
|
-
* 注入位置
|
|
176
|
-
*/
|
|
52
|
+
/** 注入位置 */
|
|
177
53
|
position: InjectPosition;
|
|
178
|
-
/**
|
|
179
|
-
* 使用的选择器
|
|
180
|
-
*/
|
|
54
|
+
/** 使用的 CSS 选择器(如果有) */
|
|
181
55
|
selector?: string;
|
|
182
|
-
/**
|
|
183
|
-
* 是否注入成功
|
|
184
|
-
*/
|
|
56
|
+
/** 是否注入成功 */
|
|
185
57
|
injected: boolean;
|
|
186
|
-
/**
|
|
187
|
-
* 注入失败原因
|
|
188
|
-
*/
|
|
58
|
+
/** 注入失败原因(如果失败) */
|
|
189
59
|
reason?: string;
|
|
190
|
-
/**
|
|
191
|
-
* 日志时间戳
|
|
192
|
-
*/
|
|
60
|
+
/** 日志记录时间戳(毫秒) */
|
|
193
61
|
timestamp: number;
|
|
194
62
|
}
|
|
195
63
|
/**
|
|
196
|
-
* HTML
|
|
64
|
+
* HTML 内容注入插件的配置选项接口
|
|
197
65
|
*
|
|
198
66
|
* @interface HtmlInjectOptions
|
|
199
67
|
* @extends {BasePluginOptions}
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* htmlInject({
|
|
72
|
+
* targetFile: 'index.html',
|
|
73
|
+
* rules: [
|
|
74
|
+
* { content: '<meta name="description" content="My App">', position: 'head-end' }
|
|
75
|
+
* ],
|
|
76
|
+
* security: { blockDangerousTags: true },
|
|
77
|
+
* templateVars: { appName: 'My App' },
|
|
78
|
+
* logInjection: true
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
200
81
|
*/
|
|
201
82
|
interface HtmlInjectOptions extends BasePluginOptions {
|
|
202
|
-
/**
|
|
203
|
-
* 目标 HTML 文件路径或文件名
|
|
204
|
-
*
|
|
205
|
-
* @default 'index.html'
|
|
206
|
-
* @description 支持相对路径和文件名匹配,默认匹配所有 index.html 文件
|
|
207
|
-
*
|
|
208
|
-
* @example 'index.html'
|
|
209
|
-
* @example 'src/views/home.html'
|
|
210
|
-
*/
|
|
83
|
+
/** 目标 HTML 文件路径或文件名,默认为 'index.html' */
|
|
211
84
|
targetFile?: string;
|
|
212
|
-
/**
|
|
213
|
-
* 注入规则数组
|
|
214
|
-
*
|
|
215
|
-
* @description 定义要注入的 HTML 内容及其注入位置和条件,规则按 priority 升序执行
|
|
216
|
-
*/
|
|
85
|
+
/** 注入规则数组,至少包含一条规则 */
|
|
217
86
|
rules: InjectRule[];
|
|
218
|
-
/**
|
|
219
|
-
* 安全配置
|
|
220
|
-
*
|
|
221
|
-
* @description 控制注入内容的安全过滤行为,防止 XSS 攻击
|
|
222
|
-
*/
|
|
87
|
+
/** 安全过滤配置,控制危险标签和属性的过滤行为 */
|
|
223
88
|
security?: SecurityConfig;
|
|
224
|
-
/**
|
|
225
|
-
* 全局模板变量,可被规则级 templateVars 覆盖
|
|
226
|
-
*
|
|
227
|
-
* @description 使用 `{{变量名}}` 语法在 content 中引用变量
|
|
228
|
-
*
|
|
229
|
-
* @example { appName: 'My App', version: '1.0.0' }
|
|
230
|
-
*/
|
|
89
|
+
/** 全局模板变量映射,用于替换内容中的 `{{varName}}` 占位符 */
|
|
231
90
|
templateVars?: Record<string, string>;
|
|
232
|
-
/**
|
|
233
|
-
* 是否在控制台输出注入日志
|
|
234
|
-
*
|
|
235
|
-
* @default true
|
|
236
|
-
*/
|
|
91
|
+
/** 是否在控制台输出注入结果日志 */
|
|
237
92
|
logInjection?: boolean;
|
|
238
93
|
}
|
|
239
94
|
|
|
@@ -275,4 +130,4 @@ interface HtmlInjectOptions extends BasePluginOptions {
|
|
|
275
130
|
declare const htmlInject: PluginFactory<HtmlInjectOptions, HtmlInjectOptions>;
|
|
276
131
|
|
|
277
132
|
export { htmlInject };
|
|
278
|
-
export type {
|
|
133
|
+
export type { HtmlInjectOptions, InjectRule, InjectionLogEntry };
|
|
@@ -1,239 +1,94 @@
|
|
|
1
1
|
import { BasePluginOptions, PluginFactory } from '../../factory/index.mjs';
|
|
2
|
+
import { a as InjectPosition, b as SelectorMatch, I as InjectCondition, S as SecurityConfig } from '../../shared/vite-plugin.FfJ-Wwfu.mjs';
|
|
2
3
|
import 'vite';
|
|
3
4
|
import '../../shared/vite-plugin.CLr0ttuO.mjs';
|
|
4
5
|
import '../../shared/vite-plugin.DRRlWY8P.mjs';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @description
|
|
10
|
-
* - 'string': 使用字符串精确匹配(默认)
|
|
11
|
-
* - 'regex': 使用正则表达式匹配,支持更灵活的模式
|
|
12
|
-
*/
|
|
13
|
-
type SelectorMatch = 'string' | 'regex';
|
|
14
|
-
/**
|
|
15
|
-
* HTML 内容注入位置
|
|
16
|
-
*
|
|
17
|
-
* @description
|
|
18
|
-
* - 'head-start': 注入到 `<head>` 标签开始之后
|
|
19
|
-
* - 'head-end': 注入到 `</head>` 标签之前
|
|
20
|
-
* - 'body-start': 注入到 `<body>` 标签开始之后
|
|
21
|
-
* - 'body-end': 注入到 `</body>` 标签之前
|
|
22
|
-
* - 'before-selector': 注入到指定选择器之前
|
|
23
|
-
* - 'after-selector': 注入到指定选择器之后
|
|
24
|
-
* - 'replace-selector': 替换指定选择器匹配的内容
|
|
25
|
-
*/
|
|
26
|
-
type InjectPosition = 'head-start' | 'head-end' | 'body-start' | 'body-end' | 'before-selector' | 'after-selector' | 'replace-selector';
|
|
27
|
-
/**
|
|
28
|
-
* 条件类型
|
|
29
|
-
*
|
|
30
|
-
* @description
|
|
31
|
-
* - 'env': 基于环境变量判断
|
|
32
|
-
* - 'file-contains': 基于 HTML 文件内容判断
|
|
33
|
-
* - 'custom': 基于自定义函数判断
|
|
34
|
-
*/
|
|
35
|
-
type ConditionType = 'env' | 'file-contains' | 'custom';
|
|
36
|
-
/**
|
|
37
|
-
* 注入条件接口
|
|
38
|
-
*
|
|
39
|
-
* @interface InjectCondition
|
|
40
|
-
* @description 定义内容注入的触发条件,支持环境变量检测、文件内容检测和自定义函数
|
|
41
|
-
*/
|
|
42
|
-
interface InjectCondition {
|
|
43
|
-
/**
|
|
44
|
-
* 条件类型
|
|
45
|
-
*/
|
|
46
|
-
type: ConditionType;
|
|
47
|
-
/**
|
|
48
|
-
* 条件值
|
|
49
|
-
*
|
|
50
|
-
* @description
|
|
51
|
-
* - 当 type 为 'env' 时,为环境变量名(字符串)
|
|
52
|
-
* - 当 type 为 'file-contains' 时,为要搜索的字符串(字符串)
|
|
53
|
-
* - 当 type 为 'custom' 时,为返回布尔值的判断函数
|
|
54
|
-
*/
|
|
55
|
-
value: string | ((...args: any[]) => boolean);
|
|
56
|
-
/**
|
|
57
|
-
* 是否对条件结果取反
|
|
58
|
-
*
|
|
59
|
-
* @default false
|
|
60
|
-
*/
|
|
61
|
-
negate?: boolean;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 注入规则接口
|
|
8
|
+
* HTML 注入规则接口
|
|
65
9
|
*
|
|
66
10
|
* @interface InjectRule
|
|
67
|
-
* @description 定义单条 HTML
|
|
11
|
+
* @description 定义单条 HTML 内容注入规则,包含注入内容、位置、条件和安全配置。
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* {
|
|
16
|
+
* id: 'meta-viewport',
|
|
17
|
+
* content: '<meta name="viewport" content="width=device-width">',
|
|
18
|
+
* position: 'head-end',
|
|
19
|
+
* priority: 10
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
68
22
|
*/
|
|
69
23
|
interface InjectRule {
|
|
70
|
-
/**
|
|
71
|
-
* 规则唯一标识符,用于日志记录和调试
|
|
72
|
-
*/
|
|
24
|
+
/** 规则唯一标识,用于日志输出和调试追踪 */
|
|
73
25
|
id?: string;
|
|
74
|
-
/**
|
|
75
|
-
* 要注入的 HTML 内容
|
|
76
|
-
*
|
|
77
|
-
* @example '<meta name="description" content="My App">'
|
|
78
|
-
*/
|
|
26
|
+
/** 要注入的 HTML 内容字符串,支持模板变量占位符 `{{varName}}` */
|
|
79
27
|
content: string;
|
|
80
|
-
/**
|
|
81
|
-
* 注入位置
|
|
82
|
-
*/
|
|
28
|
+
/** 注入位置,如 'head-start'、'head-end'、'body-start'、'body-end' 等 */
|
|
83
29
|
position: InjectPosition;
|
|
84
|
-
/**
|
|
85
|
-
* 选择器字符串,当 position 为 selector 相关位置时必填
|
|
86
|
-
*
|
|
87
|
-
* @description 当 selectorMatch 为 'string' 时,使用字符串精确匹配;
|
|
88
|
-
* 当 selectorMatch 为 'regex' 时,使用正则表达式匹配
|
|
89
|
-
*
|
|
90
|
-
* @example '<div id="app">'
|
|
91
|
-
*/
|
|
30
|
+
/** CSS 选择器,仅在 position 为 'before-selector' 或 'after-selector' 时需要 */
|
|
92
31
|
selector?: string;
|
|
93
|
-
/**
|
|
94
|
-
* 选择器匹配模式
|
|
95
|
-
*
|
|
96
|
-
* @default 'string'
|
|
97
|
-
*/
|
|
32
|
+
/** 选择器匹配模式,仅在指定 selector 时有效 */
|
|
98
33
|
selectorMatch?: SelectorMatch;
|
|
99
|
-
/**
|
|
100
|
-
* 规则优先级,数值越小优先级越高,越先执行
|
|
101
|
-
*
|
|
102
|
-
* @default 100
|
|
103
|
-
*/
|
|
34
|
+
/** 规则优先级,数值越大越先执行 */
|
|
104
35
|
priority?: number;
|
|
105
|
-
/**
|
|
106
|
-
* 注入条件,满足条件时才执行注入
|
|
107
|
-
*/
|
|
36
|
+
/** 条件注入配置,满足条件时才执行注入 */
|
|
108
37
|
condition?: InjectCondition;
|
|
109
|
-
/**
|
|
110
|
-
* 规则级模板变量,会覆盖全局模板变量
|
|
111
|
-
*
|
|
112
|
-
* @description 使用 `{{变量名}}` 语法在 content 中引用变量
|
|
113
|
-
*
|
|
114
|
-
* @example { greeting: 'Hello', name: 'World' }
|
|
115
|
-
*/
|
|
38
|
+
/** 规则级别的模板变量,会与全局 templateVars 合并 */
|
|
116
39
|
templateVars?: Record<string, string>;
|
|
117
|
-
/**
|
|
118
|
-
* 是否允许注入脚本等危险内容
|
|
119
|
-
*
|
|
120
|
-
* @default false
|
|
121
|
-
* @remarks 启用此选项将跳过安全检查,请确保注入内容来源可信
|
|
122
|
-
*/
|
|
40
|
+
/** 是否允许注入 `<script>` 标签,默认为 false 以防止 XSS 攻击 */
|
|
123
41
|
allowScriptInjection?: boolean;
|
|
124
42
|
}
|
|
125
|
-
/**
|
|
126
|
-
* 安全配置接口
|
|
127
|
-
*
|
|
128
|
-
* @interface SecurityConfig
|
|
129
|
-
* @description 控制 HTML 注入内容的安全过滤行为,防止 XSS 攻击
|
|
130
|
-
*/
|
|
131
|
-
interface SecurityConfig {
|
|
132
|
-
/**
|
|
133
|
-
* 是否阻止危险标签(script、iframe、object 等)
|
|
134
|
-
*
|
|
135
|
-
* @default true
|
|
136
|
-
*/
|
|
137
|
-
blockDangerousTags?: boolean;
|
|
138
|
-
/**
|
|
139
|
-
* 是否阻止危险属性(onclick、onload 等事件处理器)
|
|
140
|
-
*
|
|
141
|
-
* @default true
|
|
142
|
-
*/
|
|
143
|
-
blockDangerousAttributes?: boolean;
|
|
144
|
-
/**
|
|
145
|
-
* 允许通过的标签白名单,白名单中的标签不会被阻止
|
|
146
|
-
*
|
|
147
|
-
* @example ['iframe', 'object']
|
|
148
|
-
*/
|
|
149
|
-
allowedTags?: string[];
|
|
150
|
-
/**
|
|
151
|
-
* 自定义阻止标签列表,覆盖默认阻止列表
|
|
152
|
-
*
|
|
153
|
-
* @example ['div', 'span']
|
|
154
|
-
*/
|
|
155
|
-
blockedTags?: string[];
|
|
156
|
-
/**
|
|
157
|
-
* 自定义阻止属性列表,覆盖默认阻止列表
|
|
158
|
-
*
|
|
159
|
-
* @example ['data-custom', 'data-track']
|
|
160
|
-
*/
|
|
161
|
-
blockedAttributes?: string[];
|
|
162
|
-
}
|
|
163
43
|
/**
|
|
164
44
|
* 注入日志条目接口
|
|
165
45
|
*
|
|
166
46
|
* @interface InjectionLogEntry
|
|
167
|
-
* @description
|
|
47
|
+
* @description 记录单条注入规则的执行结果,用于调试和统计。
|
|
168
48
|
*/
|
|
169
49
|
interface InjectionLogEntry {
|
|
170
|
-
/**
|
|
171
|
-
* 规则标识符
|
|
172
|
-
*/
|
|
50
|
+
/** 规则标识 */
|
|
173
51
|
ruleId: string;
|
|
174
|
-
/**
|
|
175
|
-
* 注入位置
|
|
176
|
-
*/
|
|
52
|
+
/** 注入位置 */
|
|
177
53
|
position: InjectPosition;
|
|
178
|
-
/**
|
|
179
|
-
* 使用的选择器
|
|
180
|
-
*/
|
|
54
|
+
/** 使用的 CSS 选择器(如果有) */
|
|
181
55
|
selector?: string;
|
|
182
|
-
/**
|
|
183
|
-
* 是否注入成功
|
|
184
|
-
*/
|
|
56
|
+
/** 是否注入成功 */
|
|
185
57
|
injected: boolean;
|
|
186
|
-
/**
|
|
187
|
-
* 注入失败原因
|
|
188
|
-
*/
|
|
58
|
+
/** 注入失败原因(如果失败) */
|
|
189
59
|
reason?: string;
|
|
190
|
-
/**
|
|
191
|
-
* 日志时间戳
|
|
192
|
-
*/
|
|
60
|
+
/** 日志记录时间戳(毫秒) */
|
|
193
61
|
timestamp: number;
|
|
194
62
|
}
|
|
195
63
|
/**
|
|
196
|
-
* HTML
|
|
64
|
+
* HTML 内容注入插件的配置选项接口
|
|
197
65
|
*
|
|
198
66
|
* @interface HtmlInjectOptions
|
|
199
67
|
* @extends {BasePluginOptions}
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* htmlInject({
|
|
72
|
+
* targetFile: 'index.html',
|
|
73
|
+
* rules: [
|
|
74
|
+
* { content: '<meta name="description" content="My App">', position: 'head-end' }
|
|
75
|
+
* ],
|
|
76
|
+
* security: { blockDangerousTags: true },
|
|
77
|
+
* templateVars: { appName: 'My App' },
|
|
78
|
+
* logInjection: true
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
200
81
|
*/
|
|
201
82
|
interface HtmlInjectOptions extends BasePluginOptions {
|
|
202
|
-
/**
|
|
203
|
-
* 目标 HTML 文件路径或文件名
|
|
204
|
-
*
|
|
205
|
-
* @default 'index.html'
|
|
206
|
-
* @description 支持相对路径和文件名匹配,默认匹配所有 index.html 文件
|
|
207
|
-
*
|
|
208
|
-
* @example 'index.html'
|
|
209
|
-
* @example 'src/views/home.html'
|
|
210
|
-
*/
|
|
83
|
+
/** 目标 HTML 文件路径或文件名,默认为 'index.html' */
|
|
211
84
|
targetFile?: string;
|
|
212
|
-
/**
|
|
213
|
-
* 注入规则数组
|
|
214
|
-
*
|
|
215
|
-
* @description 定义要注入的 HTML 内容及其注入位置和条件,规则按 priority 升序执行
|
|
216
|
-
*/
|
|
85
|
+
/** 注入规则数组,至少包含一条规则 */
|
|
217
86
|
rules: InjectRule[];
|
|
218
|
-
/**
|
|
219
|
-
* 安全配置
|
|
220
|
-
*
|
|
221
|
-
* @description 控制注入内容的安全过滤行为,防止 XSS 攻击
|
|
222
|
-
*/
|
|
87
|
+
/** 安全过滤配置,控制危险标签和属性的过滤行为 */
|
|
223
88
|
security?: SecurityConfig;
|
|
224
|
-
/**
|
|
225
|
-
* 全局模板变量,可被规则级 templateVars 覆盖
|
|
226
|
-
*
|
|
227
|
-
* @description 使用 `{{变量名}}` 语法在 content 中引用变量
|
|
228
|
-
*
|
|
229
|
-
* @example { appName: 'My App', version: '1.0.0' }
|
|
230
|
-
*/
|
|
89
|
+
/** 全局模板变量映射,用于替换内容中的 `{{varName}}` 占位符 */
|
|
231
90
|
templateVars?: Record<string, string>;
|
|
232
|
-
/**
|
|
233
|
-
* 是否在控制台输出注入日志
|
|
234
|
-
*
|
|
235
|
-
* @default true
|
|
236
|
-
*/
|
|
91
|
+
/** 是否在控制台输出注入结果日志 */
|
|
237
92
|
logInjection?: boolean;
|
|
238
93
|
}
|
|
239
94
|
|
|
@@ -275,4 +130,4 @@ interface HtmlInjectOptions extends BasePluginOptions {
|
|
|
275
130
|
declare const htmlInject: PluginFactory<HtmlInjectOptions, HtmlInjectOptions>;
|
|
276
131
|
|
|
277
132
|
export { htmlInject };
|
|
278
|
-
export type {
|
|
133
|
+
export type { HtmlInjectOptions, InjectRule, InjectionLogEntry };
|