unplugin-version-injector 2.2.0 → 2.3.0

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.mjs CHANGED
@@ -93,18 +93,27 @@ function toScriptString(value) {
93
93
  var INJECTED_MARK = 'data-injected="unplugin-version-injector"';
94
94
  var HEADERS_INJECTED_MARK = 'data-injected="unplugin-version-injector-headers"';
95
95
  var HEADER_NAME_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
96
+ var DEFAULT_VERSION_HEADER = "X-Client-Version";
97
+ var DEFAULT_BUILD_TIME_HEADER = "X-Client-Build-Time";
96
98
  function normalizeRequestHeaders(opt) {
97
- var _a, _b, _c;
98
99
  if (!opt) return null;
99
100
  const o = typeof opt === "object" ? opt : {};
100
- const versionHeaderName = (_a = o.versionHeaderName) != null ? _a : "X-Client-Version";
101
- const buildTimeHeaderName = (_b = o.buildTimeHeaderName) != null ? _b : "X-Client-Build-Time";
102
- for (const h of [versionHeaderName, buildTimeHeaderName]) {
103
- if (!HEADER_NAME_RE.test(h)) {
104
- throw new Error(`[VersionInjector] invalid request header name: "${h}"`);
105
- }
106
- }
107
- return { versionHeaderName, buildTimeHeaderName, include: (_c = o.include) != null ? _c : [] };
101
+ const pickHeaderName = (value, fallback) => {
102
+ if (value == null) return fallback;
103
+ if (HEADER_NAME_RE.test(value)) return value;
104
+ console.warn(
105
+ `[VersionInjector] invalid request header name "${value}", falling back to "${fallback}"`
106
+ );
107
+ return fallback;
108
+ };
109
+ const include = (Array.isArray(o.include) ? o.include : []).filter(
110
+ (p) => typeof p === "string" || p instanceof RegExp
111
+ );
112
+ return {
113
+ versionHeaderName: pickHeaderName(o.versionHeaderName, DEFAULT_VERSION_HEADER),
114
+ buildTimeHeaderName: pickHeaderName(o.buildTimeHeaderName, DEFAULT_BUILD_TIME_HEADER),
115
+ include
116
+ };
108
117
  }
109
118
  function sanitizeHeaderValue(value) {
110
119
  return value.replace(/[^\t\x20-\x7E]/g, "").trim();
@@ -115,6 +124,7 @@ function serializeInclude(patterns) {
115
124
  );
116
125
  return `[${items.join(", ")}]`;
117
126
  }
127
+ var HEAD_OPEN_RE = /<head(\s[^>]*)?>/i;
118
128
  function createVersionInjector(options = {}) {
119
129
  const pkg = options.version && options.name ? { version: options.version, name: options.name } : getPackageVersion();
120
130
  const version = options.version || pkg.version;
@@ -122,25 +132,34 @@ function createVersionInjector(options = {}) {
122
132
  const formatDateOpt = options.formatDate;
123
133
  const formatDate2 = typeof formatDateOpt === "string" ? (date) => formatDate(date, formatDateOpt) : formatDateOpt != null ? formatDateOpt : defaultFormatDate;
124
134
  const headersConfig = normalizeRequestHeaders(options.requestHeaders);
135
+ let cachedBuildTime = null;
136
+ const getBuildTime = () => {
137
+ if (cachedBuildTime === null) cachedBuildTime = formatDate2(/* @__PURE__ */ new Date());
138
+ return cachedBuildTime;
139
+ };
140
+ const nonceAttr = options.nonce ? ` nonce="${escapeHtml(options.nonce)}"` : "";
125
141
  const metaTag = `<meta name="version" content="${escapeHtml(version)}">
126
142
  <meta name="project" content="${escapeHtml(name)}">
127
143
  `;
128
144
  const buildLogScript = (buildTime) => `
129
- <script ${INJECTED_MARK}>
145
+ <script${nonceAttr} ${INJECTED_MARK}>
130
146
  (function () {
131
- var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
132
- var bg = isDark ? '#ffffff' : '#1e1e1e';
133
- var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
134
- console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
135
- console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
147
+ try {
148
+ var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
149
+ var bg = isDark ? '#ffffff' : '#1e1e1e';
150
+ var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
151
+ console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
152
+ console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
153
+ } catch (e) {}
136
154
  })();
137
155
  </script>`;
138
156
  const buildHeaderScript = (buildTime, cfg) => {
139
157
  const versionValue = sanitizeHeaderValue(`${name}/${version}`);
140
158
  const buildValue = sanitizeHeaderValue(buildTime);
141
159
  return `
142
- <script ${HEADERS_INJECTED_MARK}>
160
+ <script${nonceAttr} ${HEADERS_INJECTED_MARK}>
143
161
  (function () {
162
+ try {
144
163
  if (window.__UVI_HEADERS_PATCHED__) return;
145
164
  window.__UVI_HEADERS_PATCHED__ = true;
146
165
  var VERSION_HEADER = ${toScriptString(cfg.versionHeaderName)};
@@ -164,13 +183,21 @@ function createVersionInjector(options = {}) {
164
183
  }
165
184
  }
166
185
 
186
+ function matchesPrefix(href, p) {
187
+ if (href.indexOf(p) !== 0) return false;
188
+ // \u524D\u7F00\u672C\u8EAB\u4EE5 / \u7ED3\u5C3E\uFF0C\u6216\u524D\u7F00\u540E\u7D27\u8DDF\u8FB9\u754C\u5B57\u7B26\uFF0C\u907F\u514D 'https://api.x.com' \u547D\u4E2D 'https://api.x.com.evil.com'
189
+ if (p.charAt(p.length - 1) === '/') return true;
190
+ var next = href.charAt(p.length);
191
+ return next === '' || next === '/' || next === '?' || next === '#';
192
+ }
193
+
167
194
  function shouldInject(url) {
168
195
  var u = resolveUrl(url == null ? '' : String(url));
169
196
  if (!u || (u.protocol !== 'http:' && u.protocol !== 'https:')) return false;
170
197
  if (u.protocol === location.protocol && u.host === location.host) return true;
171
198
  for (var i = 0; i < INCLUDE.length; i++) {
172
199
  var p = INCLUDE[i];
173
- if (typeof p === 'string' ? u.href.indexOf(p) === 0 : p.test(u.href)) return true;
200
+ if (typeof p === 'string' ? matchesPrefix(u.href, p) : p.test(u.href)) return true;
174
201
  }
175
202
  return false;
176
203
  }
@@ -219,29 +246,37 @@ function createVersionInjector(options = {}) {
219
246
  };
220
247
  }
221
248
  }
249
+ } catch (e) {}
222
250
  })();
223
251
  </script>`;
224
252
  };
225
253
  const processHtml = function processHtml2(html) {
226
- const buildTime = formatDate2(/* @__PURE__ */ new Date());
227
- if (!html.includes('<meta name="version"')) {
228
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
254
+ const original = html;
255
+ try {
256
+ const buildTime = getBuildTime();
257
+ if (!html.includes('<meta name="version"')) {
258
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
229
259
  ${metaTag}`);
230
- }
231
- if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
232
- const headerScript = buildHeaderScript(buildTime, headersConfig);
233
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
260
+ }
261
+ if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
262
+ const headerScript = buildHeaderScript(buildTime, headersConfig);
263
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
234
264
  ${headerScript}
235
265
  `);
236
- }
237
- if (options.log !== false && !html.includes(INJECTED_MARK)) {
238
- const logScript = buildLogScript(buildTime);
239
- html = html.replace(/<\/body>/i, () => ` ${logScript}
266
+ }
267
+ if (options.log !== false && !html.includes(INJECTED_MARK)) {
268
+ const logScript = buildLogScript(buildTime);
269
+ html = html.replace(/<\/body>/i, () => ` ${logScript}
240
270
  </body>`);
271
+ }
272
+ return html;
273
+ } catch (err) {
274
+ console.warn("[VersionInjector] injection failed, returning original HTML unchanged:", err);
275
+ return original;
241
276
  }
242
- return html;
243
277
  };
244
278
  processHtml.resetBuildTime = () => {
279
+ cachedBuildTime = null;
245
280
  };
246
281
  return processHtml;
247
282
  }
@@ -296,6 +331,10 @@ var unpluginFactory = (options = {}) => {
296
331
  const inject = createVersionInjector(options);
297
332
  return {
298
333
  name: PLUGIN_NAME,
334
+ // 每轮(重)构建开始时重置构建时间缓存:watch 重建刷新时间,同一次构建里 MPA 各页保持一致
335
+ buildStart() {
336
+ inject.resetBuildTime();
337
+ },
299
338
  vite: {
300
339
  transformIndexHtml(html) {
301
340
  return inject(html);
@@ -1,5 +1,5 @@
1
1
  import * as unplugin from 'unplugin';
2
- import { V as VersionInjectorOptions } from './types-Cc-nzIS0.mjs';
2
+ import { V as VersionInjectorOptions } from './types-CLRw9rBI.mjs';
3
3
 
4
4
  declare const _default: (options?: VersionInjectorOptions | undefined) => unplugin.RolldownPlugin<any> | unplugin.RolldownPlugin<any>[];
5
5
 
@@ -1,5 +1,5 @@
1
1
  import * as unplugin from 'unplugin';
2
- import { V as VersionInjectorOptions } from './types-Cc-nzIS0.js';
2
+ import { V as VersionInjectorOptions } from './types-CLRw9rBI.js';
3
3
 
4
4
  declare const _default: (options?: VersionInjectorOptions | undefined) => unplugin.RolldownPlugin<any> | unplugin.RolldownPlugin<any>[];
5
5
 
package/dist/rolldown.js CHANGED
@@ -100,18 +100,27 @@ function toScriptString(value) {
100
100
  var INJECTED_MARK = 'data-injected="unplugin-version-injector"';
101
101
  var HEADERS_INJECTED_MARK = 'data-injected="unplugin-version-injector-headers"';
102
102
  var HEADER_NAME_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
103
+ var DEFAULT_VERSION_HEADER = "X-Client-Version";
104
+ var DEFAULT_BUILD_TIME_HEADER = "X-Client-Build-Time";
103
105
  function normalizeRequestHeaders(opt) {
104
- var _a, _b, _c;
105
106
  if (!opt) return null;
106
107
  const o = typeof opt === "object" ? opt : {};
107
- const versionHeaderName = (_a = o.versionHeaderName) != null ? _a : "X-Client-Version";
108
- const buildTimeHeaderName = (_b = o.buildTimeHeaderName) != null ? _b : "X-Client-Build-Time";
109
- for (const h of [versionHeaderName, buildTimeHeaderName]) {
110
- if (!HEADER_NAME_RE.test(h)) {
111
- throw new Error(`[VersionInjector] invalid request header name: "${h}"`);
112
- }
113
- }
114
- return { versionHeaderName, buildTimeHeaderName, include: (_c = o.include) != null ? _c : [] };
108
+ const pickHeaderName = (value, fallback) => {
109
+ if (value == null) return fallback;
110
+ if (HEADER_NAME_RE.test(value)) return value;
111
+ console.warn(
112
+ `[VersionInjector] invalid request header name "${value}", falling back to "${fallback}"`
113
+ );
114
+ return fallback;
115
+ };
116
+ const include = (Array.isArray(o.include) ? o.include : []).filter(
117
+ (p) => typeof p === "string" || p instanceof RegExp
118
+ );
119
+ return {
120
+ versionHeaderName: pickHeaderName(o.versionHeaderName, DEFAULT_VERSION_HEADER),
121
+ buildTimeHeaderName: pickHeaderName(o.buildTimeHeaderName, DEFAULT_BUILD_TIME_HEADER),
122
+ include
123
+ };
115
124
  }
116
125
  function sanitizeHeaderValue(value) {
117
126
  return value.replace(/[^\t\x20-\x7E]/g, "").trim();
@@ -122,6 +131,7 @@ function serializeInclude(patterns) {
122
131
  );
123
132
  return `[${items.join(", ")}]`;
124
133
  }
134
+ var HEAD_OPEN_RE = /<head(\s[^>]*)?>/i;
125
135
  function createVersionInjector(options = {}) {
126
136
  const pkg = options.version && options.name ? { version: options.version, name: options.name } : getPackageVersion();
127
137
  const version = options.version || pkg.version;
@@ -129,25 +139,34 @@ function createVersionInjector(options = {}) {
129
139
  const formatDateOpt = options.formatDate;
130
140
  const formatDate2 = typeof formatDateOpt === "string" ? (date) => formatDate(date, formatDateOpt) : formatDateOpt != null ? formatDateOpt : defaultFormatDate;
131
141
  const headersConfig = normalizeRequestHeaders(options.requestHeaders);
142
+ let cachedBuildTime = null;
143
+ const getBuildTime = () => {
144
+ if (cachedBuildTime === null) cachedBuildTime = formatDate2(/* @__PURE__ */ new Date());
145
+ return cachedBuildTime;
146
+ };
147
+ const nonceAttr = options.nonce ? ` nonce="${escapeHtml(options.nonce)}"` : "";
132
148
  const metaTag = `<meta name="version" content="${escapeHtml(version)}">
133
149
  <meta name="project" content="${escapeHtml(name)}">
134
150
  `;
135
151
  const buildLogScript = (buildTime) => `
136
- <script ${INJECTED_MARK}>
152
+ <script${nonceAttr} ${INJECTED_MARK}>
137
153
  (function () {
138
- var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
139
- var bg = isDark ? '#ffffff' : '#1e1e1e';
140
- var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
141
- console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
142
- console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
154
+ try {
155
+ var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
156
+ var bg = isDark ? '#ffffff' : '#1e1e1e';
157
+ var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
158
+ console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
159
+ console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
160
+ } catch (e) {}
143
161
  })();
144
162
  </script>`;
145
163
  const buildHeaderScript = (buildTime, cfg) => {
146
164
  const versionValue = sanitizeHeaderValue(`${name}/${version}`);
147
165
  const buildValue = sanitizeHeaderValue(buildTime);
148
166
  return `
149
- <script ${HEADERS_INJECTED_MARK}>
167
+ <script${nonceAttr} ${HEADERS_INJECTED_MARK}>
150
168
  (function () {
169
+ try {
151
170
  if (window.__UVI_HEADERS_PATCHED__) return;
152
171
  window.__UVI_HEADERS_PATCHED__ = true;
153
172
  var VERSION_HEADER = ${toScriptString(cfg.versionHeaderName)};
@@ -171,13 +190,21 @@ function createVersionInjector(options = {}) {
171
190
  }
172
191
  }
173
192
 
193
+ function matchesPrefix(href, p) {
194
+ if (href.indexOf(p) !== 0) return false;
195
+ // \u524D\u7F00\u672C\u8EAB\u4EE5 / \u7ED3\u5C3E\uFF0C\u6216\u524D\u7F00\u540E\u7D27\u8DDF\u8FB9\u754C\u5B57\u7B26\uFF0C\u907F\u514D 'https://api.x.com' \u547D\u4E2D 'https://api.x.com.evil.com'
196
+ if (p.charAt(p.length - 1) === '/') return true;
197
+ var next = href.charAt(p.length);
198
+ return next === '' || next === '/' || next === '?' || next === '#';
199
+ }
200
+
174
201
  function shouldInject(url) {
175
202
  var u = resolveUrl(url == null ? '' : String(url));
176
203
  if (!u || (u.protocol !== 'http:' && u.protocol !== 'https:')) return false;
177
204
  if (u.protocol === location.protocol && u.host === location.host) return true;
178
205
  for (var i = 0; i < INCLUDE.length; i++) {
179
206
  var p = INCLUDE[i];
180
- if (typeof p === 'string' ? u.href.indexOf(p) === 0 : p.test(u.href)) return true;
207
+ if (typeof p === 'string' ? matchesPrefix(u.href, p) : p.test(u.href)) return true;
181
208
  }
182
209
  return false;
183
210
  }
@@ -226,29 +253,37 @@ function createVersionInjector(options = {}) {
226
253
  };
227
254
  }
228
255
  }
256
+ } catch (e) {}
229
257
  })();
230
258
  </script>`;
231
259
  };
232
260
  const processHtml = function processHtml2(html) {
233
- const buildTime = formatDate2(/* @__PURE__ */ new Date());
234
- if (!html.includes('<meta name="version"')) {
235
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
261
+ const original = html;
262
+ try {
263
+ const buildTime = getBuildTime();
264
+ if (!html.includes('<meta name="version"')) {
265
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
236
266
  ${metaTag}`);
237
- }
238
- if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
239
- const headerScript = buildHeaderScript(buildTime, headersConfig);
240
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
267
+ }
268
+ if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
269
+ const headerScript = buildHeaderScript(buildTime, headersConfig);
270
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
241
271
  ${headerScript}
242
272
  `);
243
- }
244
- if (options.log !== false && !html.includes(INJECTED_MARK)) {
245
- const logScript = buildLogScript(buildTime);
246
- html = html.replace(/<\/body>/i, () => ` ${logScript}
273
+ }
274
+ if (options.log !== false && !html.includes(INJECTED_MARK)) {
275
+ const logScript = buildLogScript(buildTime);
276
+ html = html.replace(/<\/body>/i, () => ` ${logScript}
247
277
  </body>`);
278
+ }
279
+ return html;
280
+ } catch (err) {
281
+ console.warn("[VersionInjector] injection failed, returning original HTML unchanged:", err);
282
+ return original;
248
283
  }
249
- return html;
250
284
  };
251
285
  processHtml.resetBuildTime = () => {
286
+ cachedBuildTime = null;
252
287
  };
253
288
  return processHtml;
254
289
  }
@@ -303,6 +338,10 @@ var unpluginFactory = (options = {}) => {
303
338
  const inject = createVersionInjector(options);
304
339
  return {
305
340
  name: PLUGIN_NAME,
341
+ // 每轮(重)构建开始时重置构建时间缓存:watch 重建刷新时间,同一次构建里 MPA 各页保持一致
342
+ buildStart() {
343
+ inject.resetBuildTime();
344
+ },
306
345
  vite: {
307
346
  transformIndexHtml(html) {
308
347
  return inject(html);
package/dist/rolldown.mjs CHANGED
@@ -93,18 +93,27 @@ function toScriptString(value) {
93
93
  var INJECTED_MARK = 'data-injected="unplugin-version-injector"';
94
94
  var HEADERS_INJECTED_MARK = 'data-injected="unplugin-version-injector-headers"';
95
95
  var HEADER_NAME_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
96
+ var DEFAULT_VERSION_HEADER = "X-Client-Version";
97
+ var DEFAULT_BUILD_TIME_HEADER = "X-Client-Build-Time";
96
98
  function normalizeRequestHeaders(opt) {
97
- var _a, _b, _c;
98
99
  if (!opt) return null;
99
100
  const o = typeof opt === "object" ? opt : {};
100
- const versionHeaderName = (_a = o.versionHeaderName) != null ? _a : "X-Client-Version";
101
- const buildTimeHeaderName = (_b = o.buildTimeHeaderName) != null ? _b : "X-Client-Build-Time";
102
- for (const h of [versionHeaderName, buildTimeHeaderName]) {
103
- if (!HEADER_NAME_RE.test(h)) {
104
- throw new Error(`[VersionInjector] invalid request header name: "${h}"`);
105
- }
106
- }
107
- return { versionHeaderName, buildTimeHeaderName, include: (_c = o.include) != null ? _c : [] };
101
+ const pickHeaderName = (value, fallback) => {
102
+ if (value == null) return fallback;
103
+ if (HEADER_NAME_RE.test(value)) return value;
104
+ console.warn(
105
+ `[VersionInjector] invalid request header name "${value}", falling back to "${fallback}"`
106
+ );
107
+ return fallback;
108
+ };
109
+ const include = (Array.isArray(o.include) ? o.include : []).filter(
110
+ (p) => typeof p === "string" || p instanceof RegExp
111
+ );
112
+ return {
113
+ versionHeaderName: pickHeaderName(o.versionHeaderName, DEFAULT_VERSION_HEADER),
114
+ buildTimeHeaderName: pickHeaderName(o.buildTimeHeaderName, DEFAULT_BUILD_TIME_HEADER),
115
+ include
116
+ };
108
117
  }
109
118
  function sanitizeHeaderValue(value) {
110
119
  return value.replace(/[^\t\x20-\x7E]/g, "").trim();
@@ -115,6 +124,7 @@ function serializeInclude(patterns) {
115
124
  );
116
125
  return `[${items.join(", ")}]`;
117
126
  }
127
+ var HEAD_OPEN_RE = /<head(\s[^>]*)?>/i;
118
128
  function createVersionInjector(options = {}) {
119
129
  const pkg = options.version && options.name ? { version: options.version, name: options.name } : getPackageVersion();
120
130
  const version = options.version || pkg.version;
@@ -122,25 +132,34 @@ function createVersionInjector(options = {}) {
122
132
  const formatDateOpt = options.formatDate;
123
133
  const formatDate2 = typeof formatDateOpt === "string" ? (date) => formatDate(date, formatDateOpt) : formatDateOpt != null ? formatDateOpt : defaultFormatDate;
124
134
  const headersConfig = normalizeRequestHeaders(options.requestHeaders);
135
+ let cachedBuildTime = null;
136
+ const getBuildTime = () => {
137
+ if (cachedBuildTime === null) cachedBuildTime = formatDate2(/* @__PURE__ */ new Date());
138
+ return cachedBuildTime;
139
+ };
140
+ const nonceAttr = options.nonce ? ` nonce="${escapeHtml(options.nonce)}"` : "";
125
141
  const metaTag = `<meta name="version" content="${escapeHtml(version)}">
126
142
  <meta name="project" content="${escapeHtml(name)}">
127
143
  `;
128
144
  const buildLogScript = (buildTime) => `
129
- <script ${INJECTED_MARK}>
145
+ <script${nonceAttr} ${INJECTED_MARK}>
130
146
  (function () {
131
- var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
132
- var bg = isDark ? '#ffffff' : '#1e1e1e';
133
- var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
134
- console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
135
- console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
147
+ try {
148
+ var isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
149
+ var bg = isDark ? '#ffffff' : '#1e1e1e';
150
+ var base = 'background: ' + bg + '; border-radius: 4px; padding: 4px; font-size: 12px;';
151
+ console.log('%c' + ${toScriptString(` ${name}@${version} `)}, base + ' color: #00c853;');
152
+ console.log('%c' + ${toScriptString(` Build Time: ${buildTime} `)}, base + ' color: #ffab00;');
153
+ } catch (e) {}
136
154
  })();
137
155
  </script>`;
138
156
  const buildHeaderScript = (buildTime, cfg) => {
139
157
  const versionValue = sanitizeHeaderValue(`${name}/${version}`);
140
158
  const buildValue = sanitizeHeaderValue(buildTime);
141
159
  return `
142
- <script ${HEADERS_INJECTED_MARK}>
160
+ <script${nonceAttr} ${HEADERS_INJECTED_MARK}>
143
161
  (function () {
162
+ try {
144
163
  if (window.__UVI_HEADERS_PATCHED__) return;
145
164
  window.__UVI_HEADERS_PATCHED__ = true;
146
165
  var VERSION_HEADER = ${toScriptString(cfg.versionHeaderName)};
@@ -164,13 +183,21 @@ function createVersionInjector(options = {}) {
164
183
  }
165
184
  }
166
185
 
186
+ function matchesPrefix(href, p) {
187
+ if (href.indexOf(p) !== 0) return false;
188
+ // \u524D\u7F00\u672C\u8EAB\u4EE5 / \u7ED3\u5C3E\uFF0C\u6216\u524D\u7F00\u540E\u7D27\u8DDF\u8FB9\u754C\u5B57\u7B26\uFF0C\u907F\u514D 'https://api.x.com' \u547D\u4E2D 'https://api.x.com.evil.com'
189
+ if (p.charAt(p.length - 1) === '/') return true;
190
+ var next = href.charAt(p.length);
191
+ return next === '' || next === '/' || next === '?' || next === '#';
192
+ }
193
+
167
194
  function shouldInject(url) {
168
195
  var u = resolveUrl(url == null ? '' : String(url));
169
196
  if (!u || (u.protocol !== 'http:' && u.protocol !== 'https:')) return false;
170
197
  if (u.protocol === location.protocol && u.host === location.host) return true;
171
198
  for (var i = 0; i < INCLUDE.length; i++) {
172
199
  var p = INCLUDE[i];
173
- if (typeof p === 'string' ? u.href.indexOf(p) === 0 : p.test(u.href)) return true;
200
+ if (typeof p === 'string' ? matchesPrefix(u.href, p) : p.test(u.href)) return true;
174
201
  }
175
202
  return false;
176
203
  }
@@ -219,29 +246,37 @@ function createVersionInjector(options = {}) {
219
246
  };
220
247
  }
221
248
  }
249
+ } catch (e) {}
222
250
  })();
223
251
  </script>`;
224
252
  };
225
253
  const processHtml = function processHtml2(html) {
226
- const buildTime = formatDate2(/* @__PURE__ */ new Date());
227
- if (!html.includes('<meta name="version"')) {
228
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
254
+ const original = html;
255
+ try {
256
+ const buildTime = getBuildTime();
257
+ if (!html.includes('<meta name="version"')) {
258
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
229
259
  ${metaTag}`);
230
- }
231
- if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
232
- const headerScript = buildHeaderScript(buildTime, headersConfig);
233
- html = html.replace(/<head[^>]*>/i, (match) => `${match}
260
+ }
261
+ if (headersConfig && !html.includes(HEADERS_INJECTED_MARK)) {
262
+ const headerScript = buildHeaderScript(buildTime, headersConfig);
263
+ html = html.replace(HEAD_OPEN_RE, (match) => `${match}
234
264
  ${headerScript}
235
265
  `);
236
- }
237
- if (options.log !== false && !html.includes(INJECTED_MARK)) {
238
- const logScript = buildLogScript(buildTime);
239
- html = html.replace(/<\/body>/i, () => ` ${logScript}
266
+ }
267
+ if (options.log !== false && !html.includes(INJECTED_MARK)) {
268
+ const logScript = buildLogScript(buildTime);
269
+ html = html.replace(/<\/body>/i, () => ` ${logScript}
240
270
  </body>`);
271
+ }
272
+ return html;
273
+ } catch (err) {
274
+ console.warn("[VersionInjector] injection failed, returning original HTML unchanged:", err);
275
+ return original;
241
276
  }
242
- return html;
243
277
  };
244
278
  processHtml.resetBuildTime = () => {
279
+ cachedBuildTime = null;
245
280
  };
246
281
  return processHtml;
247
282
  }
@@ -296,6 +331,10 @@ var unpluginFactory = (options = {}) => {
296
331
  const inject = createVersionInjector(options);
297
332
  return {
298
333
  name: PLUGIN_NAME,
334
+ // 每轮(重)构建开始时重置构建时间缓存:watch 重建刷新时间,同一次构建里 MPA 各页保持一致
335
+ buildStart() {
336
+ inject.resetBuildTime();
337
+ },
299
338
  vite: {
300
339
  transformIndexHtml(html) {
301
340
  return inject(html);
package/dist/rollup.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as rollup from 'rollup';
2
- import { V as VersionInjectorOptions } from './types-Cc-nzIS0.mjs';
2
+ import { V as VersionInjectorOptions } from './types-CLRw9rBI.mjs';
3
3
 
4
4
  declare const _default: (options?: VersionInjectorOptions | undefined) => rollup.Plugin<any> | rollup.Plugin<any>[];
5
5
 
package/dist/rollup.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as rollup from 'rollup';
2
- import { V as VersionInjectorOptions } from './types-Cc-nzIS0.js';
2
+ import { V as VersionInjectorOptions } from './types-CLRw9rBI.js';
3
3
 
4
4
  declare const _default: (options?: VersionInjectorOptions | undefined) => rollup.Plugin<any> | rollup.Plugin<any>[];
5
5