@vizejs/vite-plugin 0.100.0 → 0.103.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.d.mts +7 -0
- package/dist/index.mjs +163 -622
- package/package.json +6 -3
package/dist/index.d.mts
CHANGED
|
@@ -620,6 +620,13 @@ interface DynamicImportAliasRule {
|
|
|
620
620
|
}
|
|
621
621
|
//#endregion
|
|
622
622
|
//#region src/transform.d.ts
|
|
623
|
+
/**
|
|
624
|
+
* Rewrite static asset URLs in compiled template output.
|
|
625
|
+
*
|
|
626
|
+
* Transforms property values like `src: "@/assets/logo.svg"` into import
|
|
627
|
+
* statements hoisted to the top of the module, so Vite's module resolution
|
|
628
|
+
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
629
|
+
*/
|
|
623
630
|
declare function rewriteStaticAssetUrls(code: string, aliasRules: DynamicImportAliasRule[]): string;
|
|
624
631
|
//#endregion
|
|
625
632
|
//#region src/plugin/index.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import fs from "node:fs";
|
|
3
2
|
import { createHash } from "node:crypto";
|
|
4
|
-
import path from "node:path";
|
|
5
3
|
import * as native from "@vizejs/native";
|
|
6
|
-
import { classifyVitePluginRequest } from "@vizejs/native";
|
|
4
|
+
import { applyViteDefineReplacements, chunkVitePrecompileFiles, classifyVitePluginRequest, createViteBareImportBases, createViteBareImportCandidates, createViteVirtualId, detectViteHmrUpdateType, diffVitePrecompileFiles, generateViteHmrCode, hasViteHmrChanges, isViteBareSpecifier, normalizeViteCssModuleFilename, normalizeViteDevMiddlewareUrl, normalizeVitePrecompileBatchSize, normalizeViteRequireBase, normalizeViteResolvedVuePath, resolveViteAliasRequest, resolveViteCssImports, resolveViteRelativeImport, resolveViteVuePath, rewriteViteDynamicTemplateImports, rewriteViteStaticAssetUrls, scopeViteCssForPipeline, shouldApplyViteDefineInVirtualModule, splitViteIdQuery, toViteBrowserImportPrefix } from "@vizejs/native";
|
|
7
5
|
import { CONFIG_FILE_NAMES, defineConfig, loadConfig } from "vize";
|
|
6
|
+
import fs from "node:fs";
|
|
8
7
|
import { glob } from "tinyglobby";
|
|
8
|
+
import path from "node:path";
|
|
9
9
|
import { pathToFileURL } from "node:url";
|
|
10
10
|
import { transformWithOxc } from "vite";
|
|
11
11
|
//#region src/hmr.ts
|
|
12
|
-
function didHashChange(prevHash, nextHash) {
|
|
13
|
-
return prevHash !== nextHash;
|
|
14
|
-
}
|
|
15
12
|
function hasHmrChanges(prev, next) {
|
|
16
|
-
|
|
17
|
-
return didHashChange(prev.scriptHash, next.scriptHash) || didHashChange(prev.templateHash, next.templateHash) || didHashChange(prev.styleHash, next.styleHash);
|
|
13
|
+
return hasViteHmrChanges(toHmrHashes(prev), toHmrHashes(next));
|
|
18
14
|
}
|
|
19
15
|
/**
|
|
20
16
|
* Detect the type of HMR update needed based on content hash changes.
|
|
@@ -24,362 +20,44 @@ function hasHmrChanges(prev, next) {
|
|
|
24
20
|
* @returns The type of HMR update needed
|
|
25
21
|
*/
|
|
26
22
|
function detectHmrUpdateType(prev, next) {
|
|
27
|
-
|
|
28
|
-
if (didHashChange(prev.scriptHash, next.scriptHash)) return "full-reload";
|
|
29
|
-
const templateChanged = didHashChange(prev.templateHash, next.templateHash);
|
|
30
|
-
if (didHashChange(prev.styleHash, next.styleHash) && !templateChanged) return "style-only";
|
|
31
|
-
if (templateChanged) return "template-only";
|
|
32
|
-
return "full-reload";
|
|
23
|
+
return detectViteHmrUpdateType(toHmrHashes(prev), toHmrHashes(next));
|
|
33
24
|
}
|
|
34
25
|
/**
|
|
35
26
|
* Generate HMR-aware code output based on update type.
|
|
36
27
|
*/
|
|
37
28
|
function generateHmrCode(scopeId, updateType) {
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
47
|
-
const updateType = updated.__hmrUpdateType || 'full-reload';
|
|
48
|
-
if (updateType === 'template-only') {
|
|
49
|
-
__VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render);
|
|
50
|
-
} else {
|
|
51
|
-
__VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
import.meta.hot.on('vize:update', (data) => {
|
|
57
|
-
if (data.id !== _sfc_main.__hmrId) return;
|
|
58
|
-
|
|
59
|
-
if (data.type === 'style-only') {
|
|
60
|
-
// Update styles without remounting component
|
|
61
|
-
const styleId = 'vize-style-' + _sfc_main.__hmrId;
|
|
62
|
-
const styleEl = document.getElementById(styleId);
|
|
63
|
-
if (styleEl && data.css) {
|
|
64
|
-
styleEl.textContent = data.css;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
70
|
-
__VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main);
|
|
71
|
-
}
|
|
72
|
-
}`;
|
|
29
|
+
return generateViteHmrCode(scopeId, updateType);
|
|
30
|
+
}
|
|
31
|
+
function toHmrHashes(module) {
|
|
32
|
+
return module ? {
|
|
33
|
+
scriptHash: module.scriptHash,
|
|
34
|
+
templateHash: module.templateHash,
|
|
35
|
+
styleHash: module.styleHash
|
|
36
|
+
} : void 0;
|
|
73
37
|
}
|
|
74
38
|
//#endregion
|
|
75
39
|
//#region src/utils/css.ts
|
|
76
|
-
const deepSelectorPattern = /:deep\(([^()]*(?:\([^()]*\))*[^()]*)\)/;
|
|
77
|
-
const globalSelectorPattern = /:global\(([^()]*(?:\([^()]*\))*[^()]*)\)/g;
|
|
78
|
-
const recursiveAtRules = new Set([
|
|
79
|
-
"@container",
|
|
80
|
-
"@layer",
|
|
81
|
-
"@media",
|
|
82
|
-
"@supports"
|
|
83
|
-
]);
|
|
84
40
|
function scopeCssForPipeline(css, scopeId) {
|
|
85
|
-
return
|
|
41
|
+
return scopeViteCssForPipeline(css, scopeId);
|
|
86
42
|
}
|
|
87
43
|
/**
|
|
88
44
|
* Resolve CSS @import statements by inlining the imported files,
|
|
89
45
|
* then resolve @custom-media definitions within the combined CSS.
|
|
90
|
-
*
|
|
91
|
-
* This is necessary because Vize embeds CSS as a JS string via
|
|
92
|
-
* document.createElement('style'), bypassing Vite's CSS pipeline.
|
|
93
46
|
*/
|
|
94
47
|
function resolveCssImports(css, importer, aliasRules, isDev, devUrlBase) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return _match;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
parseCustomMedia(result, customMedia);
|
|
112
|
-
result = result.replace(/^@custom-media\s+[^;]+;\s*$/gm, "");
|
|
113
|
-
if (customMedia.size > 0) for (const [name, query] of customMedia) {
|
|
114
|
-
const escaped = name.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
115
|
-
result = result.replace(new RegExp(`\\(${escaped}\\)`, "g"), query);
|
|
116
|
-
}
|
|
117
|
-
if (isDev) result = result.replace(/url\(\s*(["']?)([^"')]+)\1\s*\)/g, (_match, quote, urlPath) => {
|
|
118
|
-
const trimmed = urlPath.trim();
|
|
119
|
-
if (trimmed.startsWith("data:") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("/@fs/")) return _match;
|
|
120
|
-
const resolved = resolveCssPath(trimmed, importer, aliasRules);
|
|
121
|
-
if (resolved && fs.existsSync(resolved)) {
|
|
122
|
-
const normalized = resolved.replace(/\\/g, "/");
|
|
123
|
-
const base = devUrlBase ?? "/";
|
|
124
|
-
return `url("${base.endsWith("/") ? base : base + "/"}@fs${normalized}")`;
|
|
125
|
-
}
|
|
126
|
-
return _match;
|
|
127
|
-
});
|
|
128
|
-
result = result.replace(new RegExp(deepSelectorPattern.source, "g"), "$1");
|
|
129
|
-
result = result.replace(/\n{3,}/g, "\n\n");
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
function transformCssBlock(css, scopeId) {
|
|
133
|
-
let output = "";
|
|
134
|
-
let cursor = 0;
|
|
135
|
-
while (cursor < css.length) {
|
|
136
|
-
const brace = findNextTopLevelBrace(css, cursor);
|
|
137
|
-
if (brace === -1) {
|
|
138
|
-
output += css.slice(cursor);
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
const end = findMatchingBrace(css, brace);
|
|
142
|
-
if (end === -1) {
|
|
143
|
-
output += css.slice(cursor);
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
const header = css.slice(cursor, brace);
|
|
147
|
-
const body = css.slice(brace + 1, end);
|
|
148
|
-
const leadingLength = header.search(/\S/);
|
|
149
|
-
const leading = leadingLength === -1 ? header : header.slice(0, leadingLength);
|
|
150
|
-
const statement = leadingLength === -1 ? "" : header.slice(leadingLength);
|
|
151
|
-
output += leading;
|
|
152
|
-
if (statement.trimStart().startsWith("@")) {
|
|
153
|
-
output += statement;
|
|
154
|
-
output += "{";
|
|
155
|
-
output += shouldRecurseAtRule(statement) ? transformCssBlock(body, scopeId) : body;
|
|
156
|
-
output += "}";
|
|
157
|
-
} else {
|
|
158
|
-
output += scopeSelectorList(statement, scopeId);
|
|
159
|
-
output += "{";
|
|
160
|
-
output += body;
|
|
161
|
-
output += "}";
|
|
162
|
-
}
|
|
163
|
-
cursor = end + 1;
|
|
164
|
-
}
|
|
165
|
-
return output;
|
|
166
|
-
}
|
|
167
|
-
function shouldRecurseAtRule(statement) {
|
|
168
|
-
const name = statement.trimStart().split(/\s+/, 1)[0];
|
|
169
|
-
return name !== void 0 && recursiveAtRules.has(name);
|
|
170
|
-
}
|
|
171
|
-
function findNextTopLevelBrace(css, start) {
|
|
172
|
-
let parenDepth = 0;
|
|
173
|
-
let bracketDepth = 0;
|
|
174
|
-
let quote = null;
|
|
175
|
-
let inComment = false;
|
|
176
|
-
for (let index = start; index < css.length; index += 1) {
|
|
177
|
-
const char = css[index];
|
|
178
|
-
const next = css[index + 1];
|
|
179
|
-
if (inComment) {
|
|
180
|
-
if (char === "*" && next === "/") {
|
|
181
|
-
inComment = false;
|
|
182
|
-
index += 1;
|
|
183
|
-
}
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
if (quote !== null) {
|
|
187
|
-
if (char === "\\") index += 1;
|
|
188
|
-
else if (char === quote) quote = null;
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (char === "/" && next === "*") {
|
|
192
|
-
inComment = true;
|
|
193
|
-
index += 1;
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
if (char === "'" || char === "\"") {
|
|
197
|
-
quote = char;
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
if (char === "(") parenDepth += 1;
|
|
201
|
-
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
202
|
-
else if (char === "[") bracketDepth += 1;
|
|
203
|
-
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
204
|
-
else if (char === "{" && parenDepth === 0 && bracketDepth === 0) return index;
|
|
205
|
-
}
|
|
206
|
-
return -1;
|
|
207
|
-
}
|
|
208
|
-
function findMatchingBrace(css, start) {
|
|
209
|
-
let depth = 0;
|
|
210
|
-
let quote = null;
|
|
211
|
-
let inComment = false;
|
|
212
|
-
for (let index = start; index < css.length; index += 1) {
|
|
213
|
-
const char = css[index];
|
|
214
|
-
const next = css[index + 1];
|
|
215
|
-
if (inComment) {
|
|
216
|
-
if (char === "*" && next === "/") {
|
|
217
|
-
inComment = false;
|
|
218
|
-
index += 1;
|
|
219
|
-
}
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
if (quote !== null) {
|
|
223
|
-
if (char === "\\") index += 1;
|
|
224
|
-
else if (char === quote) quote = null;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (char === "/" && next === "*") {
|
|
228
|
-
inComment = true;
|
|
229
|
-
index += 1;
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
if (char === "'" || char === "\"") {
|
|
233
|
-
quote = char;
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
if (char === "{") depth += 1;
|
|
237
|
-
else if (char === "}") {
|
|
238
|
-
depth -= 1;
|
|
239
|
-
if (depth === 0) return index;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return -1;
|
|
243
|
-
}
|
|
244
|
-
function scopeSelectorList(selectorList, scopeId) {
|
|
245
|
-
return splitSelectorList(selectorList).map((selector) => scopeSelector(selector, scopeId)).join(",");
|
|
246
|
-
}
|
|
247
|
-
function splitSelectorList(selectorList) {
|
|
248
|
-
const selectors = [];
|
|
249
|
-
let start = 0;
|
|
250
|
-
let parenDepth = 0;
|
|
251
|
-
let bracketDepth = 0;
|
|
252
|
-
let quote = null;
|
|
253
|
-
for (let index = 0; index < selectorList.length; index += 1) {
|
|
254
|
-
const char = selectorList[index];
|
|
255
|
-
if (quote !== null) {
|
|
256
|
-
if (char === "\\") index += 1;
|
|
257
|
-
else if (char === quote) quote = null;
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
if (char === "'" || char === "\"") {
|
|
261
|
-
quote = char;
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
if (char === "(") parenDepth += 1;
|
|
265
|
-
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
266
|
-
else if (char === "[") bracketDepth += 1;
|
|
267
|
-
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
268
|
-
else if (char === "," && parenDepth === 0 && bracketDepth === 0) {
|
|
269
|
-
selectors.push(selectorList.slice(start, index));
|
|
270
|
-
start = index + 1;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
selectors.push(selectorList.slice(start));
|
|
274
|
-
return selectors;
|
|
275
|
-
}
|
|
276
|
-
function scopeSelector(selector, scopeId) {
|
|
277
|
-
const leadingLength = selector.search(/\S/);
|
|
278
|
-
if (leadingLength === -1) return selector;
|
|
279
|
-
const leading = selector.slice(0, leadingLength);
|
|
280
|
-
const trailingLength = selector.match(/\s*$/)?.[0].length ?? 0;
|
|
281
|
-
const bodyEnd = trailingLength === 0 ? selector.length : selector.length - trailingLength;
|
|
282
|
-
const trailing = selector.slice(bodyEnd);
|
|
283
|
-
let body = selector.slice(leadingLength, bodyEnd).replace(globalSelectorPattern, "$1");
|
|
284
|
-
const deep = body.match(deepSelectorPattern);
|
|
285
|
-
if (deep?.index !== void 0) {
|
|
286
|
-
const before = body.slice(0, deep.index).trimEnd();
|
|
287
|
-
const inner = deep[1] ?? "";
|
|
288
|
-
const after = body.slice(deep.index + deep[0].length);
|
|
289
|
-
body = `${before.length === 0 ? `[${scopeId}]` : addScopeToSelectorEnd(before, scopeId)} ${inner}${after}`;
|
|
290
|
-
} else body = addScopeToSelectorEnd(body, scopeId);
|
|
291
|
-
return leading + body + trailing;
|
|
292
|
-
}
|
|
293
|
-
function addScopeToSelectorEnd(selector, scopeId) {
|
|
294
|
-
const targetStart = findLastCompoundStart(selector);
|
|
295
|
-
const beforeTarget = selector.slice(0, targetStart);
|
|
296
|
-
const target = selector.slice(targetStart);
|
|
297
|
-
const insertAt = findScopeInsertPosition(target);
|
|
298
|
-
return `${beforeTarget}${target.slice(0, insertAt)}[${scopeId}]${target.slice(insertAt)}`;
|
|
299
|
-
}
|
|
300
|
-
function findLastCompoundStart(selector) {
|
|
301
|
-
let parenDepth = 0;
|
|
302
|
-
let bracketDepth = 0;
|
|
303
|
-
let quote = null;
|
|
304
|
-
for (let index = selector.length - 1; index >= 0; index -= 1) {
|
|
305
|
-
const char = selector[index];
|
|
306
|
-
if (quote !== null) {
|
|
307
|
-
if (char === quote) quote = null;
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
if (char === "'" || char === "\"") {
|
|
311
|
-
quote = char;
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
if (char === ")") parenDepth += 1;
|
|
315
|
-
else if (char === "(" && parenDepth > 0) parenDepth -= 1;
|
|
316
|
-
else if (char === "]") bracketDepth += 1;
|
|
317
|
-
else if (char === "[" && bracketDepth > 0) bracketDepth -= 1;
|
|
318
|
-
else if (parenDepth === 0 && bracketDepth === 0 && (char === ">" || char === "+" || char === "~")) return index + 1;
|
|
319
|
-
else if (parenDepth === 0 && bracketDepth === 0 && /\s/.test(char)) {
|
|
320
|
-
while (index > 0 && /\s/.test(selector[index - 1])) index -= 1;
|
|
321
|
-
return index + 1;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
return 0;
|
|
325
|
-
}
|
|
326
|
-
function findScopeInsertPosition(target) {
|
|
327
|
-
let parenDepth = 0;
|
|
328
|
-
let bracketDepth = 0;
|
|
329
|
-
let quote = null;
|
|
330
|
-
for (let index = 0; index < target.length; index += 1) {
|
|
331
|
-
const char = target[index];
|
|
332
|
-
if (quote !== null) {
|
|
333
|
-
if (char === "\\") index += 1;
|
|
334
|
-
else if (char === quote) quote = null;
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
if (char === "'" || char === "\"") {
|
|
338
|
-
quote = char;
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
if (char === "(") parenDepth += 1;
|
|
342
|
-
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
343
|
-
else if (char === "[") bracketDepth += 1;
|
|
344
|
-
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
345
|
-
else if (char === ":" && parenDepth === 0 && bracketDepth === 0) return index;
|
|
346
|
-
}
|
|
347
|
-
return target.length;
|
|
348
|
-
}
|
|
349
|
-
function parseCustomMedia(css, map) {
|
|
350
|
-
const re = /@custom-media\s+(--[\w-]+)\s+(.+?)\s*;/g;
|
|
351
|
-
let m;
|
|
352
|
-
while ((m = re.exec(css)) !== null) map.set(m[1], m[2]);
|
|
353
|
-
}
|
|
354
|
-
function resolveCssPath(importPath, importer, aliasRules) {
|
|
355
|
-
for (const rule of aliasRules) {
|
|
356
|
-
const resolved = resolveAliasPath(importPath, rule);
|
|
357
|
-
if (resolved !== null) return path.resolve(resolved);
|
|
358
|
-
}
|
|
359
|
-
if (importPath.startsWith(".")) {
|
|
360
|
-
const dir = path.dirname(importer);
|
|
361
|
-
return path.resolve(dir, importPath);
|
|
362
|
-
}
|
|
363
|
-
if (path.isAbsolute(importPath)) return importPath;
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
function resolveAliasPath(importPath, rule) {
|
|
367
|
-
if (typeof rule.find !== "string") {
|
|
368
|
-
const pattern = stableAliasPattern$1(rule.find);
|
|
369
|
-
return pattern.test(importPath) ? importPath.replace(pattern, rule.replacement) : null;
|
|
370
|
-
}
|
|
371
|
-
const suffix = matchedAliasSuffix(importPath, rule.find);
|
|
372
|
-
if (suffix !== null) return path.join(rule.replacement, suffix);
|
|
373
|
-
return null;
|
|
374
|
-
}
|
|
375
|
-
function stableAliasPattern$1(pattern) {
|
|
376
|
-
return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
|
|
377
|
-
}
|
|
378
|
-
function matchedAliasSuffix(importPath, find) {
|
|
379
|
-
if (importPath === find) return "";
|
|
380
|
-
const prefix = find.endsWith("/") ? find : `${find}/`;
|
|
381
|
-
if (!importPath.startsWith(prefix)) return null;
|
|
382
|
-
return importPath.slice(prefix.length);
|
|
48
|
+
return resolveViteCssImports(css, importer, aliasRules.map(toNativeCssAliasRule), isDev, devUrlBase);
|
|
49
|
+
}
|
|
50
|
+
function toNativeCssAliasRule(rule) {
|
|
51
|
+
return typeof rule.find === "string" ? {
|
|
52
|
+
find: rule.find,
|
|
53
|
+
replacement: rule.replacement,
|
|
54
|
+
isRegex: false
|
|
55
|
+
} : {
|
|
56
|
+
find: rule.find.source,
|
|
57
|
+
replacement: rule.replacement,
|
|
58
|
+
isRegex: true,
|
|
59
|
+
flags: rule.find.flags.replace(/[gy]/g, "")
|
|
60
|
+
};
|
|
383
61
|
}
|
|
384
62
|
//#endregion
|
|
385
63
|
//#region src/utils/index.ts
|
|
@@ -508,29 +186,16 @@ ${output}`;
|
|
|
508
186
|
}
|
|
509
187
|
return output;
|
|
510
188
|
}
|
|
511
|
-
const VIZE_SSR_PREFIX$1 = "\0vize-ssr:";
|
|
512
189
|
const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
|
|
513
190
|
/** Create a virtual module ID from a real .vue file path */
|
|
514
191
|
function toVirtualId(realPath, ssr = false) {
|
|
515
|
-
return
|
|
516
|
-
}
|
|
517
|
-
function escapeRegExp(value) {
|
|
518
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
192
|
+
return createViteVirtualId(realPath, ssr);
|
|
519
193
|
}
|
|
520
194
|
function toBrowserImportPrefix(replacement) {
|
|
521
|
-
|
|
522
|
-
if (normalized.startsWith("/@fs/")) return normalized;
|
|
523
|
-
if (path.isAbsolute(replacement) && fs.existsSync(replacement)) return `/@fs${normalized}`;
|
|
524
|
-
return normalized;
|
|
195
|
+
return toViteBrowserImportPrefix(replacement);
|
|
525
196
|
}
|
|
526
197
|
function rewriteDynamicTemplateImports(code, aliasRules) {
|
|
527
|
-
|
|
528
|
-
for (const rule of aliasRules) {
|
|
529
|
-
const pattern = new RegExp(`\\bimport\\s*\\(\\s*\`${escapeRegExp(rule.fromPrefix)}`, "g");
|
|
530
|
-
rewritten = rewritten.replace(pattern, `import(/* @vite-ignore */ \`${rule.toPrefix}`);
|
|
531
|
-
}
|
|
532
|
-
rewritten = rewritten.replace(/\bimport\s*\(\s*`/g, "import(/* @vite-ignore */ `");
|
|
533
|
-
return rewritten;
|
|
198
|
+
return rewriteViteDynamicTemplateImports(code, aliasRules);
|
|
534
199
|
}
|
|
535
200
|
//#endregion
|
|
536
201
|
//#region src/transform.ts
|
|
@@ -547,53 +212,11 @@ function rewriteDynamicTemplateImports(code, aliasRules) {
|
|
|
547
212
|
* statements hoisted to the top of the module, so Vite's module resolution
|
|
548
213
|
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
549
214
|
*/
|
|
550
|
-
const SCRIPT_EXTENSIONS = /\.(js|mjs|cjs|ts|mts|cts|jsx|tsx)$/i;
|
|
551
215
|
function rewriteStaticAssetUrls(code, aliasRules) {
|
|
552
|
-
|
|
553
|
-
const imports = [];
|
|
554
|
-
let counter = 0;
|
|
555
|
-
for (const rule of aliasRules) {
|
|
556
|
-
const pattern = new RegExp(`("?src"?\\s*:\\s*)(?:"(${escapeRegExp(rule.fromPrefix)}[^"]+)"|'(${escapeRegExp(rule.fromPrefix)}[^']+)')`, "g");
|
|
557
|
-
rewritten = rewritten.replace(pattern, (match, prefix, dqPath, sqPath) => {
|
|
558
|
-
const fullPath = dqPath || sqPath;
|
|
559
|
-
if (fullPath && SCRIPT_EXTENSIONS.test(fullPath)) return match;
|
|
560
|
-
const varName = `__vize_static_${counter++}`;
|
|
561
|
-
imports.push(`import ${varName} from ${JSON.stringify(fullPath)};`);
|
|
562
|
-
return `${prefix}${varName}`;
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
if (imports.length > 0) rewritten = imports.join("\n") + "\n" + rewritten;
|
|
566
|
-
return rewritten;
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Built-in Vite/Vue/Nuxt define keys that are normally handled by Vite's own
|
|
570
|
-
* transform pipeline.
|
|
571
|
-
*/
|
|
572
|
-
const BUILTIN_DEFINE_PREFIXES = [
|
|
573
|
-
"import.meta.server",
|
|
574
|
-
"import.meta.client",
|
|
575
|
-
"import.meta.dev",
|
|
576
|
-
"import.meta.test",
|
|
577
|
-
"import.meta.prerender",
|
|
578
|
-
"import.meta.env",
|
|
579
|
-
"import.meta.hot",
|
|
580
|
-
"__VUE_",
|
|
581
|
-
"__NUXT_",
|
|
582
|
-
"process.env"
|
|
583
|
-
];
|
|
584
|
-
const VIRTUAL_MODULE_DEFINE_KEYS = new Set([
|
|
585
|
-
"import.meta.server",
|
|
586
|
-
"import.meta.client",
|
|
587
|
-
"import.meta.dev",
|
|
588
|
-
"import.meta.test",
|
|
589
|
-
"import.meta.prerender"
|
|
590
|
-
]);
|
|
591
|
-
function isBuiltinDefine(key) {
|
|
592
|
-
return BUILTIN_DEFINE_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix + ".") || key.startsWith(prefix + "_"));
|
|
216
|
+
return rewriteViteStaticAssetUrls(code, aliasRules);
|
|
593
217
|
}
|
|
594
218
|
function shouldApplyDefineInVirtualModule(key) {
|
|
595
|
-
|
|
596
|
-
return !isBuiltinDefine(key);
|
|
219
|
+
return shouldApplyViteDefineInVirtualModule(key);
|
|
597
220
|
}
|
|
598
221
|
/**
|
|
599
222
|
* Apply Vite define replacements to code.
|
|
@@ -601,15 +224,10 @@ function shouldApplyDefineInVirtualModule(key) {
|
|
|
601
224
|
* Uses word-boundary-aware matching to avoid replacing inside strings or partial matches.
|
|
602
225
|
*/
|
|
603
226
|
function applyDefineReplacements(code, defines) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
609
|
-
const re = new RegExp(escaped + "(?![\\w$.])", "g");
|
|
610
|
-
result = result.replace(re, defines[key]);
|
|
611
|
-
}
|
|
612
|
-
return result;
|
|
227
|
+
return applyViteDefineReplacements(code, Object.entries(defines).map(([key, value]) => ({
|
|
228
|
+
key,
|
|
229
|
+
value
|
|
230
|
+
})));
|
|
613
231
|
}
|
|
614
232
|
function createLogger(debug) {
|
|
615
233
|
return {
|
|
@@ -648,6 +266,19 @@ function buildCompileBatchOptions(options) {
|
|
|
648
266
|
//#endregion
|
|
649
267
|
//#region src/compiler.ts
|
|
650
268
|
const { compileSfc, compileSfcBatchWithResults } = native;
|
|
269
|
+
var VizeSfcCompileError = class extends Error {
|
|
270
|
+
filePath;
|
|
271
|
+
diagnostics;
|
|
272
|
+
constructor(filePath, diagnostics) {
|
|
273
|
+
super(formatCompileErrorMessage(filePath, diagnostics));
|
|
274
|
+
this.name = "VizeSfcCompileError";
|
|
275
|
+
this.filePath = filePath;
|
|
276
|
+
this.diagnostics = diagnostics;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
function formatCompileErrorMessage(filePath, diagnostics) {
|
|
280
|
+
return `[vize] Compilation failed in ${filePath}:\n${diagnostics.map((diagnostic) => ` - ${diagnostic}`).join("\n")}`;
|
|
281
|
+
}
|
|
651
282
|
function normalizeStyleBlocks(styles) {
|
|
652
283
|
if (!styles) return [];
|
|
653
284
|
return styles.map((block) => ({
|
|
@@ -662,10 +293,7 @@ function compileFile(filePath, cache, options, source) {
|
|
|
662
293
|
const content = source ?? fs.readFileSync(filePath, "utf-8");
|
|
663
294
|
const scopeId = generateScopeId(filePath);
|
|
664
295
|
const result = compileSfc(content, buildCompileFileOptions(filePath, options));
|
|
665
|
-
if (result.errors.length > 0)
|
|
666
|
-
const errorMsg = result.errors.join("\n");
|
|
667
|
-
console.error(`[vize] Compilation error in ${filePath}:\n${errorMsg}`);
|
|
668
|
-
}
|
|
296
|
+
if (result.errors.length > 0) throw new VizeSfcCompileError(filePath, result.errors);
|
|
669
297
|
if (result.warnings.length > 0) result.warnings.forEach((warning) => {
|
|
670
298
|
console.warn(`[vize] Warning in ${filePath}: ${warning}`);
|
|
671
299
|
});
|
|
@@ -701,13 +329,15 @@ function compileBatch(files, cache, options) {
|
|
|
701
329
|
macroArtifacts: fileResult.macroArtifacts ?? [],
|
|
702
330
|
styles: normalizeStyleBlocks(fileResult.styles)
|
|
703
331
|
});
|
|
704
|
-
if (fileResult.errors.length > 0) console.error(
|
|
332
|
+
if (fileResult.errors.length > 0) console.error(formatCompileErrorMessage(fileResult.path, fileResult.errors));
|
|
705
333
|
if (fileResult.warnings.length > 0) fileResult.warnings.forEach((warning) => {
|
|
706
334
|
console.warn(`[vize] Warning in ${fileResult.path}: ${warning}`);
|
|
707
335
|
});
|
|
708
336
|
}
|
|
709
337
|
return result;
|
|
710
338
|
}
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/plugin/precompile.ts
|
|
711
341
|
const DEFAULT_PRECOMPILE_IGNORE_PATTERNS = [
|
|
712
342
|
"node_modules/**",
|
|
713
343
|
"dist/**",
|
|
@@ -717,46 +347,29 @@ const DEFAULT_PRECOMPILE_IGNORE_PATTERNS = [
|
|
|
717
347
|
".nitro/**",
|
|
718
348
|
"coverage/**"
|
|
719
349
|
];
|
|
720
|
-
function hasFileMetadataChanged(previous, next) {
|
|
721
|
-
return previous === void 0 || previous.mtimeMs !== next.mtimeMs || previous.size !== next.size;
|
|
722
|
-
}
|
|
723
350
|
function diffPrecompileFiles(files, currentMetadata, previousMetadata) {
|
|
724
|
-
|
|
725
|
-
const seenFiles = new Set(files);
|
|
726
|
-
for (const file of files) {
|
|
727
|
-
const metadata = currentMetadata.get(file);
|
|
728
|
-
if (!metadata || hasFileMetadataChanged(previousMetadata.get(file), metadata)) changedFiles.push(file);
|
|
729
|
-
}
|
|
730
|
-
const deletedFiles = [];
|
|
731
|
-
for (const file of previousMetadata.keys()) if (!seenFiles.has(file)) deletedFiles.push(file);
|
|
732
|
-
return {
|
|
733
|
-
changedFiles,
|
|
734
|
-
deletedFiles
|
|
735
|
-
};
|
|
351
|
+
return diffVitePrecompileFiles([...files], toNativePrecompileMetadataEntries(currentMetadata), toNativePrecompileMetadataEntries(previousMetadata));
|
|
736
352
|
}
|
|
737
353
|
function normalizePrecompileBatchSize(value) {
|
|
738
|
-
|
|
739
|
-
return Math.max(1, Math.floor(value));
|
|
354
|
+
return normalizeVitePrecompileBatchSize(value);
|
|
740
355
|
}
|
|
741
356
|
function chunkPrecompileFiles(files, batchSize, options = {}) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
let currentBytes = 0;
|
|
747
|
-
for (const file of files) {
|
|
748
|
-
const fileBytes = Math.max(0, options.metadata?.get(file)?.size ?? 0);
|
|
749
|
-
if (current.length > 0 && (current.length >= normalizedBatchSize || currentBytes + fileBytes > maxBytes)) {
|
|
750
|
-
chunks.push(current);
|
|
751
|
-
current = [];
|
|
752
|
-
currentBytes = 0;
|
|
753
|
-
}
|
|
754
|
-
current.push(file);
|
|
755
|
-
currentBytes += fileBytes;
|
|
756
|
-
}
|
|
757
|
-
if (current.length > 0) chunks.push(current);
|
|
758
|
-
return chunks;
|
|
357
|
+
return chunkVitePrecompileFiles([...files], batchSize, {
|
|
358
|
+
maxBytes: options.maxBytes,
|
|
359
|
+
metadata: options.metadata ? toNativePrecompileMetadataEntries(options.metadata) : void 0
|
|
360
|
+
});
|
|
759
361
|
}
|
|
362
|
+
function toNativePrecompileMetadataEntries(metadata) {
|
|
363
|
+
const entries = [];
|
|
364
|
+
for (const [path, value] of metadata) entries.push({
|
|
365
|
+
path,
|
|
366
|
+
mtimeMs: value.mtimeMs,
|
|
367
|
+
size: value.size
|
|
368
|
+
});
|
|
369
|
+
return entries;
|
|
370
|
+
}
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/plugin/state.ts
|
|
760
373
|
function getEnvironmentCache(state, ssr) {
|
|
761
374
|
return ssr ? state.ssrCache : state.cache;
|
|
762
375
|
}
|
|
@@ -815,6 +428,7 @@ async function compileAll(state) {
|
|
|
815
428
|
let successCount = 0;
|
|
816
429
|
let failedCount = 0;
|
|
817
430
|
let nativeTimeMs = 0;
|
|
431
|
+
const precompileFailures = [];
|
|
818
432
|
const chunks = chunkPrecompileFiles(changedFiles, state.precompileBatchSize, { metadata: currentMetadata });
|
|
819
433
|
for (const chunk of chunks) {
|
|
820
434
|
const fileContents = [];
|
|
@@ -829,6 +443,7 @@ async function compileAll(state) {
|
|
|
829
443
|
state.cache.delete(file);
|
|
830
444
|
state.collectedCss.delete(file);
|
|
831
445
|
state.precompileMetadata.delete(file);
|
|
446
|
+
precompileFailures.push(`[vize] Failed to read ${file}: ${formatUnknownError$1(e)}`);
|
|
832
447
|
state.logger.error(`Failed to read ${file}:`, e);
|
|
833
448
|
}
|
|
834
449
|
if (fileContents.length === 0) continue;
|
|
@@ -837,8 +452,9 @@ async function compileAll(state) {
|
|
|
837
452
|
vapor: state.mergedOptions.vapor ?? false,
|
|
838
453
|
customRenderer: state.mergedOptions.customRenderer ?? false
|
|
839
454
|
});
|
|
840
|
-
|
|
841
|
-
failedCount +=
|
|
455
|
+
const chunkFailedCount = result.results.filter((fileResult) => fileResult.errors.length > 0).length;
|
|
456
|
+
failedCount += chunkFailedCount;
|
|
457
|
+
successCount += result.results.length - chunkFailedCount;
|
|
842
458
|
nativeTimeMs += result.timeMs;
|
|
843
459
|
for (const fileResult of result.results) {
|
|
844
460
|
const metadata = currentMetadata.get(fileResult.path);
|
|
@@ -846,6 +462,7 @@ async function compileAll(state) {
|
|
|
846
462
|
state.cache.delete(fileResult.path);
|
|
847
463
|
state.collectedCss.delete(fileResult.path);
|
|
848
464
|
state.precompileMetadata.delete(fileResult.path);
|
|
465
|
+
precompileFailures.push(formatCompileErrorMessage(fileResult.path, fileResult.errors));
|
|
849
466
|
continue;
|
|
850
467
|
}
|
|
851
468
|
if (metadata) state.precompileMetadata.set(fileResult.path, metadata);
|
|
@@ -855,108 +472,52 @@ async function compileAll(state) {
|
|
|
855
472
|
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
856
473
|
const batchLabel = chunks.length === 1 ? "batch" : "batches";
|
|
857
474
|
state.logger.info(`Pre-compilation complete: ${successCount} recompiled, ${cachedFileCount} reused, ${failedCount} failed (${elapsed}ms, native ${batchLabel}: ${nativeTimeMs.toFixed(2)}ms)`);
|
|
475
|
+
if (failedCount > 0) {
|
|
476
|
+
const details = precompileFailures.length > 0 ? `\n\n${precompileFailures.join("\n\n")}` : "";
|
|
477
|
+
throw new Error(`[vize] Pre-compilation failed for ${failedCount} file(s).${details}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
function formatUnknownError$1(error) {
|
|
481
|
+
return error instanceof Error ? error.message : String(error);
|
|
858
482
|
}
|
|
859
483
|
//#endregion
|
|
860
484
|
//#region src/plugin/resolve.ts
|
|
861
485
|
function resolveVuePath(state, id, importer) {
|
|
862
|
-
|
|
863
|
-
if (id.startsWith("/@fs/")) resolved = id.slice(4);
|
|
864
|
-
else if (id.startsWith("/") && !fs.existsSync(id)) resolved = path.resolve(state.root, id.slice(1));
|
|
865
|
-
else if (path.isAbsolute(id)) resolved = id;
|
|
866
|
-
else if (importer) {
|
|
867
|
-
const importerRequest = classifyVitePluginRequest(importer);
|
|
868
|
-
const realImporter = importerRequest.vizeVirtualPath ?? importerRequest.strippedVirtualPath ?? importer;
|
|
869
|
-
resolved = path.resolve(path.dirname(realImporter), id);
|
|
870
|
-
} else resolved = path.resolve(state.root, id);
|
|
871
|
-
if (!path.isAbsolute(resolved)) resolved = path.resolve(state.root, resolved);
|
|
872
|
-
return path.normalize(resolved);
|
|
873
|
-
}
|
|
874
|
-
function normalizeRequireBase(importer) {
|
|
875
|
-
if (!importer) return null;
|
|
876
|
-
let normalized = importer;
|
|
877
|
-
const request = classifyVitePluginRequest(normalized);
|
|
878
|
-
if (request.vizeVirtualPath) normalized = request.vizeVirtualPath;
|
|
879
|
-
else if (request.isMacroVirtualId) normalized = request.strippedVirtualPath ?? "";
|
|
880
|
-
return normalized.split("?")[0] ?? null;
|
|
881
|
-
}
|
|
882
|
-
function splitIdQuery(id) {
|
|
883
|
-
const queryStart = id.indexOf("?");
|
|
884
|
-
if (queryStart === -1) return [id, ""];
|
|
885
|
-
return [id.slice(0, queryStart), id.slice(queryStart)];
|
|
886
|
-
}
|
|
887
|
-
function isBareSpecifier(id) {
|
|
888
|
-
const [request] = splitIdQuery(id);
|
|
889
|
-
return request !== "" && !request.startsWith("./") && !request.startsWith("../") && !request.startsWith("/") && !request.startsWith("\0") && !request.includes(":");
|
|
486
|
+
return resolveViteVuePath(state.root, id, importer);
|
|
890
487
|
}
|
|
488
|
+
const EMPTY_NATIVE_ALIAS_RULES = [];
|
|
891
489
|
function resolveAliasRequest(state, id) {
|
|
892
|
-
|
|
893
|
-
for (const rule of state.cssAliasRules) {
|
|
894
|
-
if (rule.find instanceof RegExp) {
|
|
895
|
-
const pattern = stableAliasPattern(rule.find);
|
|
896
|
-
if (pattern.test(request)) return request.replace(pattern, rule.replacement) + querySuffix;
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
899
|
-
if (request === rule.find) return rule.replacement + querySuffix;
|
|
900
|
-
const findPrefix = rule.find.endsWith("/") ? rule.find : rule.find + "/";
|
|
901
|
-
if (request.startsWith(findPrefix)) return (rule.replacement.endsWith("/") ? rule.replacement : rule.replacement + "/") + request.slice(findPrefix.length) + querySuffix;
|
|
902
|
-
}
|
|
903
|
-
return null;
|
|
904
|
-
}
|
|
905
|
-
function stableAliasPattern(pattern) {
|
|
906
|
-
return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
|
|
907
|
-
}
|
|
908
|
-
function pushPnpmHoistBases(candidates, start, isDirectory) {
|
|
909
|
-
if (!start) return;
|
|
910
|
-
let dir = isDirectory ? start : path.dirname(start);
|
|
911
|
-
for (;;) {
|
|
912
|
-
const pnpmHoist = path.join(dir, "node_modules", ".pnpm", "node_modules");
|
|
913
|
-
if (fs.existsSync(pnpmHoist)) {
|
|
914
|
-
candidates.push(path.join(pnpmHoist, "package.json"));
|
|
915
|
-
break;
|
|
916
|
-
}
|
|
917
|
-
const parent = path.dirname(dir);
|
|
918
|
-
if (parent === dir) break;
|
|
919
|
-
dir = parent;
|
|
920
|
-
}
|
|
490
|
+
return resolveViteAliasRequest(id, nativeCssAliasRules(state));
|
|
921
491
|
}
|
|
922
492
|
function resolveBareImportWithNode(state, id, importer) {
|
|
923
|
-
const
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
const seen = /* @__PURE__ */ new Set();
|
|
928
|
-
for (const candidate of candidates) {
|
|
929
|
-
if (seen.has(candidate)) continue;
|
|
930
|
-
seen.add(candidate);
|
|
931
|
-
try {
|
|
932
|
-
return `${createRequire(candidate).resolve(request)}${querySuffix}`;
|
|
933
|
-
} catch {}
|
|
934
|
-
}
|
|
493
|
+
const { request, querySuffix } = splitViteIdQuery(id);
|
|
494
|
+
for (const candidate of createViteBareImportBases(state.root, importer)) try {
|
|
495
|
+
return `${createRequire(candidate).resolve(request)}${querySuffix}`;
|
|
496
|
+
} catch {}
|
|
935
497
|
return null;
|
|
936
498
|
}
|
|
937
499
|
function resolveBareImportCandidatesWithNode(state, id, importer, resolvedId) {
|
|
938
|
-
const
|
|
939
|
-
resolvedId,
|
|
940
|
-
resolveAliasRequest(state, id),
|
|
941
|
-
id
|
|
942
|
-
].filter((candidate) => candidate != null && isBareSpecifier(candidate));
|
|
943
|
-
const seen = /* @__PURE__ */ new Set();
|
|
944
|
-
for (const candidate of candidates) {
|
|
945
|
-
if (seen.has(candidate)) continue;
|
|
946
|
-
seen.add(candidate);
|
|
500
|
+
for (const candidate of createViteBareImportCandidates(id, nativeCssAliasRules(state), resolvedId)) {
|
|
947
501
|
const resolved = resolveBareImportWithNode(state, candidate, importer);
|
|
948
502
|
if (resolved) return resolved;
|
|
949
503
|
}
|
|
950
504
|
return null;
|
|
951
505
|
}
|
|
952
506
|
function normalizeResolvedVuePath(id) {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
507
|
+
return normalizeViteResolvedVuePath(id);
|
|
508
|
+
}
|
|
509
|
+
function nativeCssAliasRules(state) {
|
|
510
|
+
return state.cssAliasRules.length === 0 ? EMPTY_NATIVE_ALIAS_RULES : state.cssAliasRules.map(toNativeCssAliasRule);
|
|
511
|
+
}
|
|
512
|
+
function isPotentialVizeResolveId(id) {
|
|
513
|
+
return id.startsWith("\0") || id.startsWith("vize:") || id.startsWith("/@fs") || id === "virtual:vize-styles" || id.endsWith(".vue") || id.includes(".vue?") || id.includes("?macro=true") || id.includes("?definePage");
|
|
514
|
+
}
|
|
515
|
+
function isPotentialVizeImporter(importer) {
|
|
516
|
+
return importer !== void 0 && (importer.startsWith("\0") || importer.startsWith("vize:"));
|
|
956
517
|
}
|
|
957
518
|
async function resolveAliasedVueImport(ctx, state, id, importer, isSsrRequest, handleNodeModules) {
|
|
958
519
|
if (path.isAbsolute(id)) return null;
|
|
959
|
-
const viteImporter =
|
|
520
|
+
const viteImporter = normalizeViteRequireBase(importer) ?? importer;
|
|
960
521
|
const viteResolved = await ctx.resolve(id, viteImporter, { skipSelf: true });
|
|
961
522
|
const realPath = viteResolved ? normalizeResolvedVuePath(viteResolved.id) : null;
|
|
962
523
|
if (!realPath) return null;
|
|
@@ -976,6 +537,7 @@ async function resolveAliasedVueImport(ctx, state, id, importer, isSsrRequest, h
|
|
|
976
537
|
return null;
|
|
977
538
|
}
|
|
978
539
|
async function resolveIdHook(ctx, state, id, importer, options) {
|
|
540
|
+
if (!isPotentialVizeResolveId(id) && !isPotentialVizeImporter(importer)) return null;
|
|
979
541
|
const isBuild = state.server === null;
|
|
980
542
|
const importerRequest = importer ? classifyVitePluginRequest(importer) : null;
|
|
981
543
|
const isSsrRequest = !!options?.ssr || (importerRequest?.isVizeSsrVirtual ?? false);
|
|
@@ -995,8 +557,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
995
557
|
}
|
|
996
558
|
const cleanPath = id.slice(1);
|
|
997
559
|
if (cleanPath.startsWith("/") && !cleanPath.endsWith(".vue.ts")) {
|
|
998
|
-
const
|
|
999
|
-
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
560
|
+
const { request: pathPart, querySuffix } = splitViteIdQuery(cleanPath);
|
|
1000
561
|
state.logger.log(`resolveId: redirecting \0-prefixed non-vue ID to ${pathPart}${querySuffix}`);
|
|
1001
562
|
const redirected = pathPart + querySuffix;
|
|
1002
563
|
return isBuild ? classifyVitePluginRequest(redirected).normalizedFsId ?? redirected : redirected;
|
|
@@ -1035,7 +596,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1035
596
|
if (!id.endsWith(".vue")) {
|
|
1036
597
|
if (!id.startsWith("./") && !id.startsWith("../") && !id.startsWith("/")) {
|
|
1037
598
|
const aliasRequest = resolveAliasRequest(state, id);
|
|
1038
|
-
if (aliasRequest &&
|
|
599
|
+
if (aliasRequest && isViteBareSpecifier(aliasRequest)) {
|
|
1039
600
|
const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
|
|
1040
601
|
if (nodeResolved) {
|
|
1041
602
|
state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
|
|
@@ -1051,12 +612,14 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1051
612
|
...resolved,
|
|
1052
613
|
id: normalizedFsId
|
|
1053
614
|
};
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
615
|
+
if (isViteBareSpecifier(resolved.id)) {
|
|
616
|
+
const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
|
|
617
|
+
if (nodeResolved) {
|
|
618
|
+
state.logger.log(`resolveId: normalized bare ${id} to ${nodeResolved} via Node fallback`);
|
|
619
|
+
return nodeResolved;
|
|
620
|
+
}
|
|
621
|
+
return null;
|
|
1058
622
|
}
|
|
1059
|
-
if (isBareSpecifier(resolved.id)) return null;
|
|
1060
623
|
return resolved;
|
|
1061
624
|
}
|
|
1062
625
|
} catch {}
|
|
@@ -1065,7 +628,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1065
628
|
state.logger.log(`resolveId: resolved bare ${id} to ${nodeResolved} via Node fallback`);
|
|
1066
629
|
return nodeResolved;
|
|
1067
630
|
}
|
|
1068
|
-
if (aliasRequest && aliasRequest !== id && !
|
|
631
|
+
if (aliasRequest && aliasRequest !== id && !isViteBareSpecifier(aliasRequest)) {
|
|
1069
632
|
try {
|
|
1070
633
|
const resolved = await ctx.resolve(aliasRequest, cleanImporter, { skipSelf: true });
|
|
1071
634
|
if (resolved) {
|
|
@@ -1075,12 +638,14 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1075
638
|
...resolved,
|
|
1076
639
|
id: normalizedFsId
|
|
1077
640
|
};
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
641
|
+
if (isViteBareSpecifier(resolved.id)) {
|
|
642
|
+
const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
|
|
643
|
+
if (nodeResolved) {
|
|
644
|
+
state.logger.log(`resolveId: normalized aliased bare ${id} to ${nodeResolved} via Node fallback`);
|
|
645
|
+
return nodeResolved;
|
|
646
|
+
}
|
|
647
|
+
return null;
|
|
1082
648
|
}
|
|
1083
|
-
if (isBareSpecifier(resolved.id)) return null;
|
|
1084
649
|
return resolved;
|
|
1085
650
|
}
|
|
1086
651
|
} catch {}
|
|
@@ -1105,36 +670,10 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1105
670
|
}
|
|
1106
671
|
} catch {}
|
|
1107
672
|
if (id.startsWith("./") || id.startsWith("../")) {
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
"",
|
|
1113
|
-
".ts",
|
|
1114
|
-
".tsx",
|
|
1115
|
-
".js",
|
|
1116
|
-
".jsx",
|
|
1117
|
-
".json"
|
|
1118
|
-
]) {
|
|
1119
|
-
const candidate = resolved + ext;
|
|
1120
|
-
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
1121
|
-
const finalPath = candidate + querySuffix;
|
|
1122
|
-
state.logger.log(`resolveId: resolved relative ${id} to ${finalPath}`);
|
|
1123
|
-
return finalPath;
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) for (const indexFile of [
|
|
1127
|
-
"/index.ts",
|
|
1128
|
-
"/index.tsx",
|
|
1129
|
-
"/index.js",
|
|
1130
|
-
"/index.jsx"
|
|
1131
|
-
]) {
|
|
1132
|
-
const candidate = resolved + indexFile;
|
|
1133
|
-
if (fs.existsSync(candidate)) {
|
|
1134
|
-
const finalPath = candidate + querySuffix;
|
|
1135
|
-
state.logger.log(`resolveId: resolved directory ${id} to ${finalPath}`);
|
|
1136
|
-
return finalPath;
|
|
1137
|
-
}
|
|
673
|
+
const resolved = resolveViteRelativeImport(id, cleanImporter);
|
|
674
|
+
if (resolved) {
|
|
675
|
+
state.logger.log(`resolveId: resolved relative ${id} to ${resolved}`);
|
|
676
|
+
return resolved;
|
|
1138
677
|
}
|
|
1139
678
|
}
|
|
1140
679
|
return null;
|
|
@@ -1223,6 +762,7 @@ function loadDefinePageMetaArtifact(state, realPath, ssr) {
|
|
|
1223
762
|
} : null;
|
|
1224
763
|
}
|
|
1225
764
|
function loadHook(state, id, loadOptions) {
|
|
765
|
+
if (id !== "\0vize:all-styles.css" && !id.startsWith("\0")) return null;
|
|
1226
766
|
const currentBase = loadOptions?.ssr ? state.serverViteBase : state.clientViteBase;
|
|
1227
767
|
const request = classifyVitePluginRequest(id);
|
|
1228
768
|
if (id === "\0vize:all-styles.css") {
|
|
@@ -1344,6 +884,7 @@ function loadHook(state, id, loadOptions) {
|
|
|
1344
884
|
return null;
|
|
1345
885
|
}
|
|
1346
886
|
async function transformHook(state, code, id, options) {
|
|
887
|
+
if (!id.startsWith("\0")) return null;
|
|
1347
888
|
const request = classifyVitePluginRequest(id);
|
|
1348
889
|
if (request.isVizeVirtual || request.isMacroVirtualId) {
|
|
1349
890
|
const realPath = request.isMacroVirtualId ? request.strippedVirtualPath ?? "" : request.vizeVirtualPath ?? "";
|
|
@@ -1361,17 +902,23 @@ async function transformHook(state, code, id, options) {
|
|
|
1361
902
|
};
|
|
1362
903
|
} catch (e) {
|
|
1363
904
|
state.logger.error(`transformWithOxc failed for ${realPath}:`, e);
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
code
|
|
1369
|
-
|
|
1370
|
-
|
|
905
|
+
let dumpPath = null;
|
|
906
|
+
try {
|
|
907
|
+
dumpPath = getOxcDumpPath(state.root, realPath);
|
|
908
|
+
fs.writeFileSync(dumpPath, code, "utf-8");
|
|
909
|
+
state.logger.error(`Dumped failing code to ${dumpPath}`);
|
|
910
|
+
} catch (dumpError) {
|
|
911
|
+
state.logger.error(`Failed to dump failing virtual module for ${realPath}:`, dumpError);
|
|
912
|
+
}
|
|
913
|
+
const message = [`[vize] Virtual module transform failed for ${realPath}: ${formatUnknownError(e)}`, dumpPath ? `Dumped failing code to ${dumpPath}` : null].filter(Boolean).join("\n");
|
|
914
|
+
throw new Error(message);
|
|
1371
915
|
}
|
|
1372
916
|
}
|
|
1373
917
|
return null;
|
|
1374
918
|
}
|
|
919
|
+
function formatUnknownError(error) {
|
|
920
|
+
return error instanceof Error ? error.message : String(error);
|
|
921
|
+
}
|
|
1375
922
|
//#endregion
|
|
1376
923
|
//#region src/plugin/hmr.ts
|
|
1377
924
|
async function handleHotUpdateHook(state, ctx) {
|
|
@@ -1564,6 +1111,28 @@ function patchUnoCssBridge(plugins) {
|
|
|
1564
1111
|
}
|
|
1565
1112
|
}
|
|
1566
1113
|
//#endregion
|
|
1114
|
+
//#region src/plugin/css-modules.ts
|
|
1115
|
+
function patchCssModuleGenerateScopedName(userConfig) {
|
|
1116
|
+
const cssModules = userConfig.css?.modules;
|
|
1117
|
+
if (!cssModules || typeof cssModules.generateScopedName !== "function") return;
|
|
1118
|
+
const origFn = cssModules.generateScopedName;
|
|
1119
|
+
cssModules.generateScopedName = function(name, filename, css) {
|
|
1120
|
+
return origFn.call(this, name, normalizeViteCssModuleFilename(filename), css);
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/plugin/dev-middleware.ts
|
|
1125
|
+
function installVirtualAssetMiddleware(devServer, state) {
|
|
1126
|
+
devServer.middlewares.use((req, _res, next) => {
|
|
1127
|
+
const rewrite = req.url ? normalizeViteDevMiddlewareUrl(req.url) : null;
|
|
1128
|
+
if (rewrite && fs.existsSync(rewrite.fsPath) && fs.statSync(rewrite.fsPath).isFile()) {
|
|
1129
|
+
state.logger.log(`middleware: rewriting ${req.url} -> ${rewrite.cleanedUrl}`);
|
|
1130
|
+
req.url = rewrite.cleanedUrl;
|
|
1131
|
+
}
|
|
1132
|
+
next();
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
//#endregion
|
|
1567
1136
|
//#region src/plugin/index.ts
|
|
1568
1137
|
function aliasSortKey(find) {
|
|
1569
1138
|
return typeof find === "string" ? find.length : find.source.length;
|
|
@@ -1599,18 +1168,7 @@ function vize(options = {}) {
|
|
|
1599
1168
|
name: "vite-plugin-vize",
|
|
1600
1169
|
enforce: "pre",
|
|
1601
1170
|
config(userConfig, env) {
|
|
1602
|
-
|
|
1603
|
-
if (cssModules && typeof cssModules.generateScopedName === "function") {
|
|
1604
|
-
const origFn = cssModules.generateScopedName;
|
|
1605
|
-
cssModules.generateScopedName = function(name, filename, css) {
|
|
1606
|
-
let clean = filename;
|
|
1607
|
-
const nulIdx = clean.indexOf("\0");
|
|
1608
|
-
if (nulIdx >= 0) clean = clean.slice(nulIdx + 1);
|
|
1609
|
-
clean = clean.replace(/\.module\.\w+$/, "").replace(/\.\w+$/, "");
|
|
1610
|
-
if (clean.includes("?")) clean = clean.split("?")[0];
|
|
1611
|
-
return origFn.call(this, name, clean, css);
|
|
1612
|
-
};
|
|
1613
|
-
}
|
|
1171
|
+
patchCssModuleGenerateScopedName(userConfig);
|
|
1614
1172
|
return {
|
|
1615
1173
|
// @vitejs/plugin-vue normally provides them; vize must do so as its replacement.
|
|
1616
1174
|
define: {
|
|
@@ -1701,24 +1259,7 @@ function vize(options = {}) {
|
|
|
1701
1259
|
},
|
|
1702
1260
|
configureServer(devServer) {
|
|
1703
1261
|
state.server = devServer;
|
|
1704
|
-
devServer
|
|
1705
|
-
if (req.url && req.url.includes("__x00__")) {
|
|
1706
|
-
const [urlPath, queryPart] = req.url.split("?");
|
|
1707
|
-
let cleanedPath = urlPath.replace(/__x00__/g, "");
|
|
1708
|
-
cleanedPath = cleanedPath.replace(/^\/@id\/\//, "/@fs/");
|
|
1709
|
-
if (cleanedPath.startsWith("/@fs/")) {
|
|
1710
|
-
const fsPath = cleanedPath.slice(4);
|
|
1711
|
-
if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile() && !fsPath.endsWith(".vue.ts")) {
|
|
1712
|
-
const cleaned = queryPart ? `${cleanedPath}?${queryPart}` : cleanedPath;
|
|
1713
|
-
if (cleaned !== req.url) {
|
|
1714
|
-
state.logger.log(`middleware: rewriting ${req.url} -> ${cleaned}`);
|
|
1715
|
-
req.url = cleaned;
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
next();
|
|
1721
|
-
});
|
|
1262
|
+
installVirtualAssetMiddleware(devServer, state);
|
|
1722
1263
|
},
|
|
1723
1264
|
async buildStart() {
|
|
1724
1265
|
if (!state.scanPatterns || state.scanPatterns.length === 0) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.103.0",
|
|
4
4
|
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@vizejs/native": "0.
|
|
36
|
+
"@vizejs/native": "0.103.0",
|
|
37
37
|
"tinyglobby": "0.2.16",
|
|
38
|
-
"vize": "0.
|
|
38
|
+
"vize": "0.103.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "25.7.0",
|
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"vite": "^8.0.0"
|
|
48
48
|
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22"
|
|
51
|
+
},
|
|
49
52
|
"scripts": {
|
|
50
53
|
"build": "vp pack",
|
|
51
54
|
"dev": "vp pack --watch",
|