@vizejs/vite-plugin 0.100.0 → 0.101.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 +57 -535
- package/package.json +3 -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
2
|
import fs from "node:fs";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
-
import path from "node:path";
|
|
5
4
|
import * as native from "@vizejs/native";
|
|
6
|
-
import { classifyVitePluginRequest } from "@vizejs/native";
|
|
5
|
+
import { applyViteDefineReplacements, classifyVitePluginRequest, createViteBareImportBases, createViteBareImportCandidates, createViteVirtualId, detectViteHmrUpdateType, generateViteHmrCode, hasViteHmrChanges, isViteBareSpecifier, normalizeViteRequireBase, normalizeViteResolvedVuePath, resolveViteAliasRequest, resolveViteCssImports, resolveViteRelativeImport, resolveViteVuePath, rewriteViteDynamicTemplateImports, rewriteViteStaticAssetUrls, scopeViteCssForPipeline, shouldApplyViteDefineInVirtualModule, splitViteIdQuery, toViteBrowserImportPrefix } from "@vizejs/native";
|
|
7
6
|
import { CONFIG_FILE_NAMES, defineConfig, loadConfig } from "vize";
|
|
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 {
|
|
@@ -859,104 +477,35 @@ async function compileAll(state) {
|
|
|
859
477
|
//#endregion
|
|
860
478
|
//#region src/plugin/resolve.ts
|
|
861
479
|
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(":");
|
|
480
|
+
return resolveViteVuePath(state.root, id, importer);
|
|
890
481
|
}
|
|
482
|
+
const EMPTY_NATIVE_ALIAS_RULES = [];
|
|
891
483
|
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
|
-
}
|
|
484
|
+
return resolveViteAliasRequest(id, nativeCssAliasRules(state));
|
|
921
485
|
}
|
|
922
486
|
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
|
-
}
|
|
487
|
+
const { request, querySuffix } = splitViteIdQuery(id);
|
|
488
|
+
for (const candidate of createViteBareImportBases(state.root, importer)) try {
|
|
489
|
+
return `${createRequire(candidate).resolve(request)}${querySuffix}`;
|
|
490
|
+
} catch {}
|
|
935
491
|
return null;
|
|
936
492
|
}
|
|
937
493
|
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);
|
|
494
|
+
for (const candidate of createViteBareImportCandidates(id, nativeCssAliasRules(state), resolvedId)) {
|
|
947
495
|
const resolved = resolveBareImportWithNode(state, candidate, importer);
|
|
948
496
|
if (resolved) return resolved;
|
|
949
497
|
}
|
|
950
498
|
return null;
|
|
951
499
|
}
|
|
952
500
|
function normalizeResolvedVuePath(id) {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
501
|
+
return normalizeViteResolvedVuePath(id);
|
|
502
|
+
}
|
|
503
|
+
function nativeCssAliasRules(state) {
|
|
504
|
+
return state.cssAliasRules.length === 0 ? EMPTY_NATIVE_ALIAS_RULES : state.cssAliasRules.map(toNativeCssAliasRule);
|
|
956
505
|
}
|
|
957
506
|
async function resolveAliasedVueImport(ctx, state, id, importer, isSsrRequest, handleNodeModules) {
|
|
958
507
|
if (path.isAbsolute(id)) return null;
|
|
959
|
-
const viteImporter =
|
|
508
|
+
const viteImporter = normalizeViteRequireBase(importer) ?? importer;
|
|
960
509
|
const viteResolved = await ctx.resolve(id, viteImporter, { skipSelf: true });
|
|
961
510
|
const realPath = viteResolved ? normalizeResolvedVuePath(viteResolved.id) : null;
|
|
962
511
|
if (!realPath) return null;
|
|
@@ -995,8 +544,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
995
544
|
}
|
|
996
545
|
const cleanPath = id.slice(1);
|
|
997
546
|
if (cleanPath.startsWith("/") && !cleanPath.endsWith(".vue.ts")) {
|
|
998
|
-
const
|
|
999
|
-
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
547
|
+
const { request: pathPart, querySuffix } = splitViteIdQuery(cleanPath);
|
|
1000
548
|
state.logger.log(`resolveId: redirecting \0-prefixed non-vue ID to ${pathPart}${querySuffix}`);
|
|
1001
549
|
const redirected = pathPart + querySuffix;
|
|
1002
550
|
return isBuild ? classifyVitePluginRequest(redirected).normalizedFsId ?? redirected : redirected;
|
|
@@ -1035,7 +583,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1035
583
|
if (!id.endsWith(".vue")) {
|
|
1036
584
|
if (!id.startsWith("./") && !id.startsWith("../") && !id.startsWith("/")) {
|
|
1037
585
|
const aliasRequest = resolveAliasRequest(state, id);
|
|
1038
|
-
if (aliasRequest &&
|
|
586
|
+
if (aliasRequest && isViteBareSpecifier(aliasRequest)) {
|
|
1039
587
|
const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
|
|
1040
588
|
if (nodeResolved) {
|
|
1041
589
|
state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
|
|
@@ -1056,7 +604,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1056
604
|
state.logger.log(`resolveId: normalized bare ${id} to ${nodeResolved} via Node fallback`);
|
|
1057
605
|
return nodeResolved;
|
|
1058
606
|
}
|
|
1059
|
-
if (
|
|
607
|
+
if (isViteBareSpecifier(resolved.id)) return null;
|
|
1060
608
|
return resolved;
|
|
1061
609
|
}
|
|
1062
610
|
} catch {}
|
|
@@ -1065,7 +613,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1065
613
|
state.logger.log(`resolveId: resolved bare ${id} to ${nodeResolved} via Node fallback`);
|
|
1066
614
|
return nodeResolved;
|
|
1067
615
|
}
|
|
1068
|
-
if (aliasRequest && aliasRequest !== id && !
|
|
616
|
+
if (aliasRequest && aliasRequest !== id && !isViteBareSpecifier(aliasRequest)) {
|
|
1069
617
|
try {
|
|
1070
618
|
const resolved = await ctx.resolve(aliasRequest, cleanImporter, { skipSelf: true });
|
|
1071
619
|
if (resolved) {
|
|
@@ -1080,7 +628,7 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1080
628
|
state.logger.log(`resolveId: normalized aliased bare ${id} to ${nodeResolved} via Node fallback`);
|
|
1081
629
|
return nodeResolved;
|
|
1082
630
|
}
|
|
1083
|
-
if (
|
|
631
|
+
if (isViteBareSpecifier(resolved.id)) return null;
|
|
1084
632
|
return resolved;
|
|
1085
633
|
}
|
|
1086
634
|
} catch {}
|
|
@@ -1105,36 +653,10 @@ async function resolveIdHook(ctx, state, id, importer, options) {
|
|
|
1105
653
|
}
|
|
1106
654
|
} catch {}
|
|
1107
655
|
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
|
-
}
|
|
656
|
+
const resolved = resolveViteRelativeImport(id, cleanImporter);
|
|
657
|
+
if (resolved) {
|
|
658
|
+
state.logger.log(`resolveId: resolved relative ${id} to ${resolved}`);
|
|
659
|
+
return resolved;
|
|
1138
660
|
}
|
|
1139
661
|
}
|
|
1140
662
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.101.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.101.0",
|
|
37
37
|
"tinyglobby": "0.2.16",
|
|
38
|
-
"vize": "0.
|
|
38
|
+
"vize": "0.101.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "25.7.0",
|