@vizejs/vite-plugin 0.0.1-alpha.102 → 0.0.1-alpha.104
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.js +141 -15
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -118,6 +118,69 @@ ${output}`;
|
|
|
118
118
|
if (!isProduction && isDev && hasExportDefault) output += generateHmrCode(compiled.scopeId, hmrUpdateType ?? "full-reload");
|
|
119
119
|
return output;
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Resolve CSS @import statements by inlining the imported files,
|
|
123
|
+
* then resolve @custom-media definitions within the combined CSS.
|
|
124
|
+
*
|
|
125
|
+
* This is necessary because Vize embeds CSS as a JS string via
|
|
126
|
+
* document.createElement('style'), bypassing Vite's CSS pipeline.
|
|
127
|
+
*/
|
|
128
|
+
function resolveCssImports(css, importer, aliasRules, isDev, devUrlBase) {
|
|
129
|
+
const customMedia = new Map();
|
|
130
|
+
const importRegex = /^@import\s+(?:"([^"]+)"|'([^']+)');?\s*$/gm;
|
|
131
|
+
let result = css;
|
|
132
|
+
result = result.replace(importRegex, (_match, dqPath, sqPath) => {
|
|
133
|
+
const importPath = dqPath || sqPath;
|
|
134
|
+
if (!importPath) return _match;
|
|
135
|
+
const resolved = resolveCssPath(importPath, importer, aliasRules);
|
|
136
|
+
if (!resolved || !fs.existsSync(resolved)) return _match;
|
|
137
|
+
try {
|
|
138
|
+
const content = fs.readFileSync(resolved, "utf-8");
|
|
139
|
+
parseCustomMedia(content, customMedia);
|
|
140
|
+
return content;
|
|
141
|
+
} catch {
|
|
142
|
+
return _match;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
parseCustomMedia(result, customMedia);
|
|
146
|
+
result = result.replace(/^@custom-media\s+[^;]+;\s*$/gm, "");
|
|
147
|
+
if (customMedia.size > 0) for (const [name, query] of customMedia) {
|
|
148
|
+
const escaped = name.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
149
|
+
result = result.replace(new RegExp(`\\(${escaped}\\)`, "g"), query);
|
|
150
|
+
}
|
|
151
|
+
if (isDev) result = result.replace(/url\(\s*(["']?)([^"')]+)\1\s*\)/g, (_match, quote, urlPath) => {
|
|
152
|
+
const trimmed = urlPath.trim();
|
|
153
|
+
if (trimmed.startsWith("data:") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("/@fs/")) return _match;
|
|
154
|
+
const resolved = resolveCssPath(trimmed, importer, aliasRules);
|
|
155
|
+
if (resolved && fs.existsSync(resolved)) {
|
|
156
|
+
const normalized = resolved.replace(/\\/g, "/");
|
|
157
|
+
const base = devUrlBase ?? "/";
|
|
158
|
+
const prefix = base.endsWith("/") ? base : base + "/";
|
|
159
|
+
return `url("${prefix}@fs${normalized}")`;
|
|
160
|
+
}
|
|
161
|
+
return _match;
|
|
162
|
+
});
|
|
163
|
+
result = result.replace(/:deep\(([^()]*(?:\([^()]*\))*[^()]*)\)/g, "$1");
|
|
164
|
+
result = result.replace(/\n{3,}/g, "\n\n");
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
function parseCustomMedia(css, map) {
|
|
168
|
+
const re = /@custom-media\s+(--[\w-]+)\s+(.+?)\s*;/g;
|
|
169
|
+
let m;
|
|
170
|
+
while ((m = re.exec(css)) !== null) map.set(m[1], m[2]);
|
|
171
|
+
}
|
|
172
|
+
function resolveCssPath(importPath, importer, aliasRules) {
|
|
173
|
+
for (const rule of aliasRules) if (importPath.startsWith(rule.find)) {
|
|
174
|
+
const resolved = importPath.replace(rule.find, rule.replacement);
|
|
175
|
+
return path.resolve(resolved);
|
|
176
|
+
}
|
|
177
|
+
if (importPath.startsWith(".")) {
|
|
178
|
+
const dir = path.dirname(importer);
|
|
179
|
+
return path.resolve(dir, importPath);
|
|
180
|
+
}
|
|
181
|
+
if (path.isAbsolute(importPath)) return importPath;
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
121
184
|
|
|
122
185
|
//#endregion
|
|
123
186
|
//#region src/compiler.ts
|
|
@@ -323,18 +386,61 @@ function createLogger(debug) {
|
|
|
323
386
|
error: (...args) => console.error("[vize]", ...args)
|
|
324
387
|
};
|
|
325
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Built-in Vite/Vue/Nuxt define keys that are handled by Vite's own transform pipeline.
|
|
391
|
+
* These must NOT be replaced by the vize plugin because:
|
|
392
|
+
* 1. Nuxt runs both client and server Vite builds, each with different values
|
|
393
|
+
* (e.g., import.meta.server = true on server, false on client).
|
|
394
|
+
* 2. Vite's import.meta transform already handles these correctly per-environment.
|
|
395
|
+
*/
|
|
396
|
+
const BUILTIN_DEFINE_PREFIXES = [
|
|
397
|
+
"import.meta.server",
|
|
398
|
+
"import.meta.client",
|
|
399
|
+
"import.meta.dev",
|
|
400
|
+
"import.meta.test",
|
|
401
|
+
"import.meta.prerender",
|
|
402
|
+
"import.meta.env",
|
|
403
|
+
"import.meta.hot",
|
|
404
|
+
"__VUE_",
|
|
405
|
+
"__NUXT_",
|
|
406
|
+
"process.env"
|
|
407
|
+
];
|
|
408
|
+
function isBuiltinDefine(key) {
|
|
409
|
+
return BUILTIN_DEFINE_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix + ".") || key.startsWith(prefix + "_"));
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Apply Vite define replacements to code.
|
|
413
|
+
* Replaces keys like `import.meta.vfFeatures.photoSection` with their values.
|
|
414
|
+
* Uses word-boundary-aware matching to avoid replacing inside strings or partial matches.
|
|
415
|
+
*/
|
|
416
|
+
function applyDefineReplacements(code, defines) {
|
|
417
|
+
const sortedKeys = Object.keys(defines).sort((a, b) => b.length - a.length);
|
|
418
|
+
let result = code;
|
|
419
|
+
for (const key of sortedKeys) {
|
|
420
|
+
if (!result.includes(key)) continue;
|
|
421
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
422
|
+
const re = new RegExp(escaped + "(?![\\w$.])", "g");
|
|
423
|
+
result = result.replace(re, defines[key]);
|
|
424
|
+
}
|
|
425
|
+
return result;
|
|
426
|
+
}
|
|
326
427
|
function vize(options = {}) {
|
|
327
428
|
const cache = new Map();
|
|
328
429
|
const collectedCss = new Map();
|
|
329
430
|
let isProduction;
|
|
330
431
|
let root;
|
|
432
|
+
let clientViteBase = "/";
|
|
433
|
+
let serverViteBase = "/";
|
|
331
434
|
let server = null;
|
|
332
435
|
let filter;
|
|
333
436
|
let scanPatterns;
|
|
334
437
|
let ignorePatterns;
|
|
335
438
|
let mergedOptions;
|
|
336
439
|
let dynamicImportAliasRules = [];
|
|
440
|
+
let cssAliasRules = [];
|
|
337
441
|
let extractCss = false;
|
|
442
|
+
let clientViteDefine = {};
|
|
443
|
+
let serverViteDefine = {};
|
|
338
444
|
const logger = createLogger(options.debug ?? false);
|
|
339
445
|
async function compileAll() {
|
|
340
446
|
const startTime = performance.now();
|
|
@@ -356,7 +462,7 @@ function vize(options = {}) {
|
|
|
356
462
|
}
|
|
357
463
|
const result = compileBatch(fileContents, cache, { ssr: mergedOptions.ssr ?? false });
|
|
358
464
|
if (isProduction) {
|
|
359
|
-
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, fileResult.css);
|
|
465
|
+
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, resolveCssImports(fileResult.css, fileResult.path, cssAliasRules, false));
|
|
360
466
|
}
|
|
361
467
|
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
362
468
|
logger.info(`Pre-compilation complete: ${result.successCount} succeeded, ${result.failedCount} failed (${elapsed}ms, native batch: ${result.timeMs.toFixed(2)}ms)`);
|
|
@@ -386,15 +492,6 @@ function vize(options = {}) {
|
|
|
386
492
|
optimizeDeps: {
|
|
387
493
|
include: ["vue"],
|
|
388
494
|
exclude: ["virtual:vize-styles"],
|
|
389
|
-
esbuildOptions: { plugins: [{
|
|
390
|
-
name: "vize-externalize-vue",
|
|
391
|
-
setup(build) {
|
|
392
|
-
build.onResolve({ filter: /\.vue$/ }, (args) => ({
|
|
393
|
-
path: args.path,
|
|
394
|
-
external: true
|
|
395
|
-
}));
|
|
396
|
-
}
|
|
397
|
-
}] },
|
|
398
495
|
rolldownOptions: { external: [/\.vue$/] }
|
|
399
496
|
}
|
|
400
497
|
};
|
|
@@ -402,7 +499,19 @@ function vize(options = {}) {
|
|
|
402
499
|
async configResolved(resolvedConfig) {
|
|
403
500
|
root = options.root ?? resolvedConfig.root;
|
|
404
501
|
isProduction = options.isProduction ?? resolvedConfig.isProduction;
|
|
502
|
+
const isSsrBuild = !!resolvedConfig.build?.ssr;
|
|
503
|
+
if (isSsrBuild) serverViteBase = resolvedConfig.base ?? "/";
|
|
504
|
+
else clientViteBase = resolvedConfig.base ?? "/";
|
|
405
505
|
extractCss = isProduction;
|
|
506
|
+
const isSsr = !!resolvedConfig.build?.ssr;
|
|
507
|
+
const envDefine = {};
|
|
508
|
+
if (resolvedConfig.define) for (const [key, value] of Object.entries(resolvedConfig.define)) {
|
|
509
|
+
if (isBuiltinDefine(key)) continue;
|
|
510
|
+
if (typeof value === "string") envDefine[key] = value;
|
|
511
|
+
else envDefine[key] = JSON.stringify(value);
|
|
512
|
+
}
|
|
513
|
+
if (isSsr) serverViteDefine = envDefine;
|
|
514
|
+
else clientViteDefine = envDefine;
|
|
406
515
|
const configEnv = {
|
|
407
516
|
mode: resolvedConfig.mode,
|
|
408
517
|
command: resolvedConfig.command === "build" ? "build" : "serve",
|
|
@@ -444,6 +553,15 @@ function vize(options = {}) {
|
|
|
444
553
|
});
|
|
445
554
|
}
|
|
446
555
|
dynamicImportAliasRules.sort((a, b) => b.fromPrefix.length - a.fromPrefix.length);
|
|
556
|
+
cssAliasRules = [];
|
|
557
|
+
for (const alias of resolvedConfig.resolve.alias) {
|
|
558
|
+
if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
|
|
559
|
+
cssAliasRules.push({
|
|
560
|
+
find: alias.find,
|
|
561
|
+
replacement: alias.replacement
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
cssAliasRules.sort((a, b) => b.find.length - a.find.length);
|
|
447
565
|
filter = createFilter(mergedOptions.include, mergedOptions.exclude);
|
|
448
566
|
scanPatterns = mergedOptions.scanPatterns ?? ["**/*.vue"];
|
|
449
567
|
ignorePatterns = mergedOptions.ignorePatterns ?? [
|
|
@@ -604,7 +722,8 @@ function vize(options = {}) {
|
|
|
604
722
|
}
|
|
605
723
|
return null;
|
|
606
724
|
},
|
|
607
|
-
load(id) {
|
|
725
|
+
load(id, loadOptions) {
|
|
726
|
+
const currentBase = loadOptions?.ssr ? serverViteBase : clientViteBase;
|
|
608
727
|
if (id === RESOLVED_CSS_MODULE) {
|
|
609
728
|
const allCss = Array.from(collectedCss.values()).join("\n\n");
|
|
610
729
|
return allCss;
|
|
@@ -613,7 +732,7 @@ function vize(options = {}) {
|
|
|
613
732
|
const [filename] = id.split("?");
|
|
614
733
|
const realPath = isVizeVirtual(filename) ? fromVirtualId(filename) : filename;
|
|
615
734
|
const compiled = cache.get(realPath);
|
|
616
|
-
if (compiled?.css) return compiled.css;
|
|
735
|
+
if (compiled?.css) return resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase);
|
|
617
736
|
return "";
|
|
618
737
|
}
|
|
619
738
|
if (isVizeVirtual(id)) {
|
|
@@ -631,6 +750,10 @@ function vize(options = {}) {
|
|
|
631
750
|
});
|
|
632
751
|
}
|
|
633
752
|
if (compiled) {
|
|
753
|
+
if (compiled.css) compiled = {
|
|
754
|
+
...compiled,
|
|
755
|
+
css: resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase)
|
|
756
|
+
};
|
|
634
757
|
const output = rewriteStaticAssetUrls(rewriteDynamicTemplateImports(generateOutput(compiled, {
|
|
635
758
|
isProduction,
|
|
636
759
|
isDev: server !== null,
|
|
@@ -656,13 +779,16 @@ function vize(options = {}) {
|
|
|
656
779
|
}
|
|
657
780
|
return null;
|
|
658
781
|
},
|
|
659
|
-
async transform(code, id) {
|
|
782
|
+
async transform(code, id, options$1) {
|
|
660
783
|
if (isVizeVirtual(id)) {
|
|
661
784
|
const realPath = fromVirtualId(id);
|
|
662
785
|
try {
|
|
663
786
|
const result = await transformWithOxc(code, realPath, { lang: "ts" });
|
|
787
|
+
const defines = options$1?.ssr ? serverViteDefine : clientViteDefine;
|
|
788
|
+
let transformed = result.code;
|
|
789
|
+
if (Object.keys(defines).length > 0) transformed = applyDefineReplacements(transformed, defines);
|
|
664
790
|
return {
|
|
665
|
-
code:
|
|
791
|
+
code: transformed,
|
|
666
792
|
map: result.map
|
|
667
793
|
};
|
|
668
794
|
} catch (e) {
|
|
@@ -699,7 +825,7 @@ function vize(options = {}) {
|
|
|
699
825
|
data: {
|
|
700
826
|
id: newCompiled.scopeId,
|
|
701
827
|
type: "style-only",
|
|
702
|
-
css: newCompiled.css
|
|
828
|
+
css: resolveCssImports(newCompiled.css, file, cssAliasRules, true, clientViteBase)
|
|
703
829
|
}
|
|
704
830
|
});
|
|
705
831
|
return [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.104",
|
|
4
4
|
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"tinyglobby": "^0.2.0",
|
|
46
|
-
"@vizejs/native": "0.0.1-alpha.
|
|
46
|
+
"@vizejs/native": "0.0.1-alpha.104"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsdown",
|