@vizejs/vite-plugin 0.70.0 → 0.71.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 +261 -11
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -72,6 +72,17 @@ if (import.meta.hot) {
|
|
|
72
72
|
}
|
|
73
73
|
//#endregion
|
|
74
74
|
//#region src/utils/css.ts
|
|
75
|
+
const deepSelectorPattern = /:deep\(([^()]*(?:\([^()]*\))*[^()]*)\)/;
|
|
76
|
+
const globalSelectorPattern = /:global\(([^()]*(?:\([^()]*\))*[^()]*)\)/g;
|
|
77
|
+
const recursiveAtRules = new Set([
|
|
78
|
+
"@container",
|
|
79
|
+
"@layer",
|
|
80
|
+
"@media",
|
|
81
|
+
"@supports"
|
|
82
|
+
]);
|
|
83
|
+
function scopeCssForPipeline(css, scopeId) {
|
|
84
|
+
return transformCssBlock(css, scopeId);
|
|
85
|
+
}
|
|
75
86
|
/**
|
|
76
87
|
* Resolve CSS @import statements by inlining the imported files,
|
|
77
88
|
* then resolve @custom-media definitions within the combined CSS.
|
|
@@ -113,10 +124,227 @@ function resolveCssImports(css, importer, aliasRules, isDev, devUrlBase) {
|
|
|
113
124
|
}
|
|
114
125
|
return _match;
|
|
115
126
|
});
|
|
116
|
-
result = result.replace(
|
|
127
|
+
result = result.replace(new RegExp(deepSelectorPattern.source, "g"), "$1");
|
|
117
128
|
result = result.replace(/\n{3,}/g, "\n\n");
|
|
118
129
|
return result;
|
|
119
130
|
}
|
|
131
|
+
function transformCssBlock(css, scopeId) {
|
|
132
|
+
let output = "";
|
|
133
|
+
let cursor = 0;
|
|
134
|
+
while (cursor < css.length) {
|
|
135
|
+
const brace = findNextTopLevelBrace(css, cursor);
|
|
136
|
+
if (brace === -1) {
|
|
137
|
+
output += css.slice(cursor);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
const end = findMatchingBrace(css, brace);
|
|
141
|
+
if (end === -1) {
|
|
142
|
+
output += css.slice(cursor);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
const header = css.slice(cursor, brace);
|
|
146
|
+
const body = css.slice(brace + 1, end);
|
|
147
|
+
const leadingLength = header.search(/\S/);
|
|
148
|
+
const leading = leadingLength === -1 ? header : header.slice(0, leadingLength);
|
|
149
|
+
const statement = leadingLength === -1 ? "" : header.slice(leadingLength);
|
|
150
|
+
output += leading;
|
|
151
|
+
if (statement.trimStart().startsWith("@")) {
|
|
152
|
+
output += statement;
|
|
153
|
+
output += "{";
|
|
154
|
+
output += shouldRecurseAtRule(statement) ? transformCssBlock(body, scopeId) : body;
|
|
155
|
+
output += "}";
|
|
156
|
+
} else {
|
|
157
|
+
output += scopeSelectorList(statement, scopeId);
|
|
158
|
+
output += "{";
|
|
159
|
+
output += body;
|
|
160
|
+
output += "}";
|
|
161
|
+
}
|
|
162
|
+
cursor = end + 1;
|
|
163
|
+
}
|
|
164
|
+
return output;
|
|
165
|
+
}
|
|
166
|
+
function shouldRecurseAtRule(statement) {
|
|
167
|
+
const name = statement.trimStart().split(/\s+/, 1)[0];
|
|
168
|
+
return name !== void 0 && recursiveAtRules.has(name);
|
|
169
|
+
}
|
|
170
|
+
function findNextTopLevelBrace(css, start) {
|
|
171
|
+
let parenDepth = 0;
|
|
172
|
+
let bracketDepth = 0;
|
|
173
|
+
let quote = null;
|
|
174
|
+
let inComment = false;
|
|
175
|
+
for (let index = start; index < css.length; index += 1) {
|
|
176
|
+
const char = css[index];
|
|
177
|
+
const next = css[index + 1];
|
|
178
|
+
if (inComment) {
|
|
179
|
+
if (char === "*" && next === "/") {
|
|
180
|
+
inComment = false;
|
|
181
|
+
index += 1;
|
|
182
|
+
}
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (quote !== null) {
|
|
186
|
+
if (char === "\\") index += 1;
|
|
187
|
+
else if (char === quote) quote = null;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (char === "/" && next === "*") {
|
|
191
|
+
inComment = true;
|
|
192
|
+
index += 1;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (char === "'" || char === "\"") {
|
|
196
|
+
quote = char;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (char === "(") parenDepth += 1;
|
|
200
|
+
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
201
|
+
else if (char === "[") bracketDepth += 1;
|
|
202
|
+
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
203
|
+
else if (char === "{" && parenDepth === 0 && bracketDepth === 0) return index;
|
|
204
|
+
}
|
|
205
|
+
return -1;
|
|
206
|
+
}
|
|
207
|
+
function findMatchingBrace(css, start) {
|
|
208
|
+
let depth = 0;
|
|
209
|
+
let quote = null;
|
|
210
|
+
let inComment = false;
|
|
211
|
+
for (let index = start; index < css.length; index += 1) {
|
|
212
|
+
const char = css[index];
|
|
213
|
+
const next = css[index + 1];
|
|
214
|
+
if (inComment) {
|
|
215
|
+
if (char === "*" && next === "/") {
|
|
216
|
+
inComment = false;
|
|
217
|
+
index += 1;
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (quote !== null) {
|
|
222
|
+
if (char === "\\") index += 1;
|
|
223
|
+
else if (char === quote) quote = null;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (char === "/" && next === "*") {
|
|
227
|
+
inComment = true;
|
|
228
|
+
index += 1;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (char === "'" || char === "\"") {
|
|
232
|
+
quote = char;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (char === "{") depth += 1;
|
|
236
|
+
else if (char === "}") {
|
|
237
|
+
depth -= 1;
|
|
238
|
+
if (depth === 0) return index;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return -1;
|
|
242
|
+
}
|
|
243
|
+
function scopeSelectorList(selectorList, scopeId) {
|
|
244
|
+
return splitSelectorList(selectorList).map((selector) => scopeSelector(selector, scopeId)).join(",");
|
|
245
|
+
}
|
|
246
|
+
function splitSelectorList(selectorList) {
|
|
247
|
+
const selectors = [];
|
|
248
|
+
let start = 0;
|
|
249
|
+
let parenDepth = 0;
|
|
250
|
+
let bracketDepth = 0;
|
|
251
|
+
let quote = null;
|
|
252
|
+
for (let index = 0; index < selectorList.length; index += 1) {
|
|
253
|
+
const char = selectorList[index];
|
|
254
|
+
if (quote !== null) {
|
|
255
|
+
if (char === "\\") index += 1;
|
|
256
|
+
else if (char === quote) quote = null;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (char === "'" || char === "\"") {
|
|
260
|
+
quote = char;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (char === "(") parenDepth += 1;
|
|
264
|
+
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
265
|
+
else if (char === "[") bracketDepth += 1;
|
|
266
|
+
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
267
|
+
else if (char === "," && parenDepth === 0 && bracketDepth === 0) {
|
|
268
|
+
selectors.push(selectorList.slice(start, index));
|
|
269
|
+
start = index + 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
selectors.push(selectorList.slice(start));
|
|
273
|
+
return selectors;
|
|
274
|
+
}
|
|
275
|
+
function scopeSelector(selector, scopeId) {
|
|
276
|
+
const leadingLength = selector.search(/\S/);
|
|
277
|
+
if (leadingLength === -1) return selector;
|
|
278
|
+
const leading = selector.slice(0, leadingLength);
|
|
279
|
+
const trailingLength = selector.match(/\s*$/)?.[0].length ?? 0;
|
|
280
|
+
const bodyEnd = trailingLength === 0 ? selector.length : selector.length - trailingLength;
|
|
281
|
+
const trailing = selector.slice(bodyEnd);
|
|
282
|
+
let body = selector.slice(leadingLength, bodyEnd).replace(globalSelectorPattern, "$1");
|
|
283
|
+
const deep = body.match(deepSelectorPattern);
|
|
284
|
+
if (deep?.index !== void 0) {
|
|
285
|
+
const before = body.slice(0, deep.index).trimEnd();
|
|
286
|
+
const inner = deep[1] ?? "";
|
|
287
|
+
const after = body.slice(deep.index + deep[0].length);
|
|
288
|
+
body = `${before.length === 0 ? `[${scopeId}]` : addScopeToSelectorEnd(before, scopeId)} ${inner}${after}`;
|
|
289
|
+
} else body = addScopeToSelectorEnd(body, scopeId);
|
|
290
|
+
return leading + body + trailing;
|
|
291
|
+
}
|
|
292
|
+
function addScopeToSelectorEnd(selector, scopeId) {
|
|
293
|
+
const targetStart = findLastCompoundStart(selector);
|
|
294
|
+
const beforeTarget = selector.slice(0, targetStart);
|
|
295
|
+
const target = selector.slice(targetStart);
|
|
296
|
+
const insertAt = findScopeInsertPosition(target);
|
|
297
|
+
return `${beforeTarget}${target.slice(0, insertAt)}[${scopeId}]${target.slice(insertAt)}`;
|
|
298
|
+
}
|
|
299
|
+
function findLastCompoundStart(selector) {
|
|
300
|
+
let parenDepth = 0;
|
|
301
|
+
let bracketDepth = 0;
|
|
302
|
+
let quote = null;
|
|
303
|
+
for (let index = selector.length - 1; index >= 0; index -= 1) {
|
|
304
|
+
const char = selector[index];
|
|
305
|
+
if (quote !== null) {
|
|
306
|
+
if (char === quote) quote = null;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (char === "'" || char === "\"") {
|
|
310
|
+
quote = char;
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
if (char === ")") parenDepth += 1;
|
|
314
|
+
else if (char === "(" && parenDepth > 0) parenDepth -= 1;
|
|
315
|
+
else if (char === "]") bracketDepth += 1;
|
|
316
|
+
else if (char === "[" && bracketDepth > 0) bracketDepth -= 1;
|
|
317
|
+
else if (parenDepth === 0 && bracketDepth === 0 && (char === ">" || char === "+" || char === "~")) return index + 1;
|
|
318
|
+
else if (parenDepth === 0 && bracketDepth === 0 && /\s/.test(char)) {
|
|
319
|
+
while (index > 0 && /\s/.test(selector[index - 1])) index -= 1;
|
|
320
|
+
return index + 1;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
function findScopeInsertPosition(target) {
|
|
326
|
+
let parenDepth = 0;
|
|
327
|
+
let bracketDepth = 0;
|
|
328
|
+
let quote = null;
|
|
329
|
+
for (let index = 0; index < target.length; index += 1) {
|
|
330
|
+
const char = target[index];
|
|
331
|
+
if (quote !== null) {
|
|
332
|
+
if (char === "\\") index += 1;
|
|
333
|
+
else if (char === quote) quote = null;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (char === "'" || char === "\"") {
|
|
337
|
+
quote = char;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (char === "(") parenDepth += 1;
|
|
341
|
+
else if (char === ")" && parenDepth > 0) parenDepth -= 1;
|
|
342
|
+
else if (char === "[") bracketDepth += 1;
|
|
343
|
+
else if (char === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
344
|
+
else if (char === ":" && parenDepth === 0 && bracketDepth === 0) return index;
|
|
345
|
+
}
|
|
346
|
+
return target.length;
|
|
347
|
+
}
|
|
120
348
|
function parseCustomMedia(css, map) {
|
|
121
349
|
const re = /@custom-media\s+(--[\w-]+)\s+(.+?)\s*;/g;
|
|
122
350
|
let m;
|
|
@@ -152,13 +380,16 @@ function needsPreprocessor(block) {
|
|
|
152
380
|
function isCssModule(block) {
|
|
153
381
|
return block.module !== false;
|
|
154
382
|
}
|
|
383
|
+
function needsCssPipeline(block) {
|
|
384
|
+
return block.content.includes("@apply");
|
|
385
|
+
}
|
|
155
386
|
/**
|
|
156
387
|
* Check if any style blocks in the compiled module require delegation to
|
|
157
|
-
* Vite's CSS pipeline (preprocessor or
|
|
388
|
+
* Vite's CSS pipeline (preprocessor, CSS Modules, or PostCSS transforms).
|
|
158
389
|
*/
|
|
159
390
|
function hasDelegatedStyles(compiled) {
|
|
160
391
|
if (!compiled.styles) return false;
|
|
161
|
-
return compiled.styles.some((s) => needsPreprocessor(s) || isCssModule(s));
|
|
392
|
+
return compiled.styles.some((s) => needsPreprocessor(s) || isCssModule(s) || needsCssPipeline(s));
|
|
162
393
|
}
|
|
163
394
|
function supportsTemplateOnlyHmr(output) {
|
|
164
395
|
return /(?:^|\n)(?:_sfc_main|__sfc__)\.render\s*=\s*render\b/m.test(output);
|
|
@@ -340,11 +571,8 @@ function rewriteStaticAssetUrls(code, aliasRules) {
|
|
|
340
571
|
return rewritten;
|
|
341
572
|
}
|
|
342
573
|
/**
|
|
343
|
-
* Built-in Vite/Vue/Nuxt define keys that are handled by Vite's own
|
|
344
|
-
*
|
|
345
|
-
* 1. Nuxt runs both client and server Vite builds, each with different values
|
|
346
|
-
* (e.g., import.meta.server = true on server, false on client).
|
|
347
|
-
* 2. Vite's import.meta transform already handles these correctly per-environment.
|
|
574
|
+
* Built-in Vite/Vue/Nuxt define keys that are normally handled by Vite's own
|
|
575
|
+
* transform pipeline.
|
|
348
576
|
*/
|
|
349
577
|
const BUILTIN_DEFINE_PREFIXES = [
|
|
350
578
|
"import.meta.server",
|
|
@@ -358,9 +586,20 @@ const BUILTIN_DEFINE_PREFIXES = [
|
|
|
358
586
|
"__NUXT_",
|
|
359
587
|
"process.env"
|
|
360
588
|
];
|
|
589
|
+
const VIRTUAL_MODULE_DEFINE_KEYS = new Set([
|
|
590
|
+
"import.meta.server",
|
|
591
|
+
"import.meta.client",
|
|
592
|
+
"import.meta.dev",
|
|
593
|
+
"import.meta.test",
|
|
594
|
+
"import.meta.prerender"
|
|
595
|
+
]);
|
|
361
596
|
function isBuiltinDefine(key) {
|
|
362
597
|
return BUILTIN_DEFINE_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix + ".") || key.startsWith(prefix + "_"));
|
|
363
598
|
}
|
|
599
|
+
function shouldApplyDefineInVirtualModule(key) {
|
|
600
|
+
if (VIRTUAL_MODULE_DEFINE_KEYS.has(key)) return true;
|
|
601
|
+
return !isBuiltinDefine(key);
|
|
602
|
+
}
|
|
364
603
|
/**
|
|
365
604
|
* Apply Vite define replacements to code.
|
|
366
605
|
* Replaces keys like `import.meta.vfFeatures.photoSection` with their values.
|
|
@@ -820,6 +1059,16 @@ function getOxcDumpPath(root, realPath) {
|
|
|
820
1059
|
fs.mkdirSync(dumpDir, { recursive: true });
|
|
821
1060
|
return path.join(dumpDir, `vize-oxc-error-${path.basename(realPath)}.ts`);
|
|
822
1061
|
}
|
|
1062
|
+
function getVirtualModuleDefines(state, ssr) {
|
|
1063
|
+
return {
|
|
1064
|
+
"import.meta.client": ssr ? "false" : "true",
|
|
1065
|
+
"import.meta.server": ssr ? "true" : "false",
|
|
1066
|
+
"import.meta.dev": state.isProduction ? "false" : "true",
|
|
1067
|
+
"import.meta.test": "false",
|
|
1068
|
+
"import.meta.prerender": "false",
|
|
1069
|
+
...ssr ? state.serverViteDefine : state.clientViteDefine
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
823
1072
|
function loadHook(state, id, loadOptions) {
|
|
824
1073
|
const currentBase = loadOptions?.ssr ? state.serverViteBase : state.clientViteBase;
|
|
825
1074
|
if (id === "\0vize:all-styles.css") return Array.from(state.collectedCss.values()).join("\n\n");
|
|
@@ -838,6 +1087,7 @@ function loadHook(state, id, loadOptions) {
|
|
|
838
1087
|
if (fallbackCompiled?.styles && blockIndex >= 0 && blockIndex < fallbackCompiled.styles.length) {
|
|
839
1088
|
const block = fallbackCompiled.styles[blockIndex];
|
|
840
1089
|
let styleContent = block.content;
|
|
1090
|
+
if (scoped && block.scoped && (!lang || lang === "css")) styleContent = scopeCssForPipeline(styleContent, scoped);
|
|
841
1091
|
if (scoped && block.scoped && lang && lang !== "css") {
|
|
842
1092
|
const lines = styleContent.split("\n");
|
|
843
1093
|
const hoisted = [];
|
|
@@ -936,9 +1186,9 @@ async function transformHook(state, code, id, options) {
|
|
|
936
1186
|
const realPath = isMacro ? id.slice(1).replace("?macro=true", "") : fromVirtualId(id);
|
|
937
1187
|
try {
|
|
938
1188
|
const result = await transformWithOxc(code, realPath, { lang: "ts" });
|
|
939
|
-
const defines = options?.ssr
|
|
1189
|
+
const defines = getVirtualModuleDefines(state, options?.ssr ?? false);
|
|
940
1190
|
let transformed = result.code;
|
|
941
|
-
|
|
1191
|
+
transformed = applyDefineReplacements(transformed, defines);
|
|
942
1192
|
return {
|
|
943
1193
|
code: transformed,
|
|
944
1194
|
map: result.map
|
|
@@ -1194,7 +1444,7 @@ function vize(options = {}) {
|
|
|
1194
1444
|
const isSsr = !!resolvedConfig.build?.ssr;
|
|
1195
1445
|
const envDefine = {};
|
|
1196
1446
|
if (resolvedConfig.define) for (const [key, value] of Object.entries(resolvedConfig.define)) {
|
|
1197
|
-
if (
|
|
1447
|
+
if (!shouldApplyDefineInVirtualModule(key)) continue;
|
|
1198
1448
|
if (typeof value === "string") envDefine[key] = value;
|
|
1199
1449
|
else envDefine[key] = JSON.stringify(value);
|
|
1200
1450
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.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.71.0",
|
|
37
37
|
"tinyglobby": "0.2.16",
|
|
38
|
-
"vize": "0.
|
|
38
|
+
"vize": "0.71.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "25.6.0",
|