@vizejs/vite-plugin 0.0.1-alpha.99 → 0.2.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.ts +25 -2
- package/dist/index.js +426 -80
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -459,6 +459,14 @@ interface VizeOptions {
|
|
|
459
459
|
* Custom config file path (overrides automatic search)
|
|
460
460
|
*/
|
|
461
461
|
configFile?: string;
|
|
462
|
+
/**
|
|
463
|
+
* Handle .vue files in node_modules (on-demand compilation).
|
|
464
|
+
* When true, vize will compile .vue files from node_modules that other plugins
|
|
465
|
+
* (like vite-plugin-vue-inspector) may import directly.
|
|
466
|
+
* Set to false if another Vue plugin (e.g. Nuxt) handles node_modules .vue files.
|
|
467
|
+
* @default true
|
|
468
|
+
*/
|
|
469
|
+
handleNodeModulesVue?: boolean;
|
|
462
470
|
/**
|
|
463
471
|
* Enable debug logging
|
|
464
472
|
* @default false
|
|
@@ -492,7 +500,22 @@ declare function loadConfig(root: string, options?: LoadConfigOptions): Promise<
|
|
|
492
500
|
* Used by musea() and other plugins to access the unified config.
|
|
493
501
|
*/
|
|
494
502
|
declare const vizeConfigStore: Map<string, VizeConfig>;
|
|
495
|
-
|
|
503
|
+
interface DynamicImportAliasRule {
|
|
504
|
+
fromPrefix: string;
|
|
505
|
+
toPrefix: string;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Rewrite static asset URLs in compiled template output.
|
|
509
|
+
*
|
|
510
|
+
* Transforms property values like `src: "@/assets/logo.svg"` into import
|
|
511
|
+
* statements hoisted to the top of the module, so Vite's module resolution
|
|
512
|
+
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
513
|
+
*/
|
|
514
|
+
declare function rewriteStaticAssetUrls(code: string, aliasRules: DynamicImportAliasRule[]): string;
|
|
515
|
+
declare const __internal: {
|
|
516
|
+
rewriteStaticAssetUrls: typeof rewriteStaticAssetUrls;
|
|
517
|
+
};
|
|
518
|
+
declare function vize(options?: VizeOptions): Plugin[];
|
|
496
519
|
|
|
497
520
|
//#endregion
|
|
498
|
-
export { CompiledModule, LoadConfigOptions, VizeConfig, VizeOptions, vize as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
|
521
|
+
export { CompiledModule, LoadConfigOptions, VizeConfig, VizeOptions, __internal, vize as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { transformWithOxc } from "vite";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
4
6
|
import { glob } from "tinyglobby";
|
|
5
7
|
import * as native from "@vizejs/native";
|
|
6
8
|
import { createHash } from "node:crypto";
|
|
@@ -96,7 +98,7 @@ function generateOutput(compiled, options) {
|
|
|
96
98
|
const cssCode = JSON.stringify(compiled.css);
|
|
97
99
|
const cssId = JSON.stringify(`vize-style-${compiled.scopeId}`);
|
|
98
100
|
output = `
|
|
99
|
-
const __vize_css__ = ${cssCode};
|
|
101
|
+
export const __vize_css__ = ${cssCode};
|
|
100
102
|
const __vize_css_id__ = ${cssId};
|
|
101
103
|
(function() {
|
|
102
104
|
if (typeof document !== 'undefined') {
|
|
@@ -116,6 +118,69 @@ ${output}`;
|
|
|
116
118
|
if (!isProduction && isDev && hasExportDefault) output += generateHmrCode(compiled.scopeId, hmrUpdateType ?? "full-reload");
|
|
117
119
|
return output;
|
|
118
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
|
+
}
|
|
119
184
|
|
|
120
185
|
//#endregion
|
|
121
186
|
//#region src/compiler.ts
|
|
@@ -250,9 +315,69 @@ async function loadConfigFile(configPath, env) {
|
|
|
250
315
|
* Used by musea() and other plugins to access the unified config.
|
|
251
316
|
*/
|
|
252
317
|
const vizeConfigStore = new Map();
|
|
253
|
-
const
|
|
318
|
+
const LEGACY_VIZE_PREFIX = "\0vize:";
|
|
254
319
|
const VIRTUAL_CSS_MODULE = "virtual:vize-styles";
|
|
255
320
|
const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
|
|
321
|
+
/** Check if a module ID is a vize-compiled virtual module */
|
|
322
|
+
function isVizeVirtual(id) {
|
|
323
|
+
return id.startsWith("\0") && id.endsWith(".vue.ts");
|
|
324
|
+
}
|
|
325
|
+
/** Create a virtual module ID from a real .vue file path */
|
|
326
|
+
function toVirtualId(realPath) {
|
|
327
|
+
return "\0" + realPath + ".ts";
|
|
328
|
+
}
|
|
329
|
+
/** Extract the real .vue file path from a virtual module ID */
|
|
330
|
+
function fromVirtualId(virtualId) {
|
|
331
|
+
return virtualId.slice(1, -3);
|
|
332
|
+
}
|
|
333
|
+
function escapeRegExp(value) {
|
|
334
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
335
|
+
}
|
|
336
|
+
function toBrowserImportPrefix(replacement) {
|
|
337
|
+
const normalized = replacement.replace(/\\/g, "/");
|
|
338
|
+
if (normalized.startsWith("/@fs/")) return normalized;
|
|
339
|
+
if (path.isAbsolute(replacement) && fs.existsSync(replacement)) return `/@fs${normalized}`;
|
|
340
|
+
return normalized;
|
|
341
|
+
}
|
|
342
|
+
function normalizeFsIdForBuild(id) {
|
|
343
|
+
const [pathPart, queryPart] = id.split("?");
|
|
344
|
+
if (!pathPart.startsWith("/@fs/")) return id;
|
|
345
|
+
const normalizedPath = pathPart.slice(4);
|
|
346
|
+
return queryPart ? `${normalizedPath}?${queryPart}` : normalizedPath;
|
|
347
|
+
}
|
|
348
|
+
function rewriteDynamicTemplateImports(code, aliasRules) {
|
|
349
|
+
let rewritten = code;
|
|
350
|
+
for (const rule of aliasRules) {
|
|
351
|
+
const pattern = new RegExp(`\\bimport\\s*\\(\\s*\`${escapeRegExp(rule.fromPrefix)}`, "g");
|
|
352
|
+
rewritten = rewritten.replace(pattern, `import(/* @vite-ignore */ \`${rule.toPrefix}`);
|
|
353
|
+
}
|
|
354
|
+
rewritten = rewritten.replace(/\bimport\s*\(\s*`/g, "import(/* @vite-ignore */ `");
|
|
355
|
+
return rewritten;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Rewrite static asset URLs in compiled template output.
|
|
359
|
+
*
|
|
360
|
+
* Transforms property values like `src: "@/assets/logo.svg"` into import
|
|
361
|
+
* statements hoisted to the top of the module, so Vite's module resolution
|
|
362
|
+
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
363
|
+
*/
|
|
364
|
+
function rewriteStaticAssetUrls(code, aliasRules) {
|
|
365
|
+
let rewritten = code;
|
|
366
|
+
const imports = [];
|
|
367
|
+
let counter = 0;
|
|
368
|
+
for (const rule of aliasRules) {
|
|
369
|
+
const pattern = new RegExp(`("?src"?\\s*:\\s*)(?:"(${escapeRegExp(rule.fromPrefix)}[^"]+)"|'(${escapeRegExp(rule.fromPrefix)}[^']+)')`, "g");
|
|
370
|
+
rewritten = rewritten.replace(pattern, (_match, prefix, dqPath, sqPath) => {
|
|
371
|
+
const fullPath = dqPath || sqPath;
|
|
372
|
+
const varName = `__vize_static_${counter++}`;
|
|
373
|
+
imports.push(`import ${varName} from ${JSON.stringify(fullPath)};`);
|
|
374
|
+
return `${prefix}${varName}`;
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
if (imports.length > 0) rewritten = imports.join("\n") + "\n" + rewritten;
|
|
378
|
+
return rewritten;
|
|
379
|
+
}
|
|
380
|
+
const __internal = { rewriteStaticAssetUrls };
|
|
256
381
|
function createLogger(debug) {
|
|
257
382
|
return {
|
|
258
383
|
log: (...args) => debug && console.log("[vize]", ...args),
|
|
@@ -261,18 +386,62 @@ function createLogger(debug) {
|
|
|
261
386
|
error: (...args) => console.error("[vize]", ...args)
|
|
262
387
|
};
|
|
263
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
|
+
}
|
|
264
427
|
function vize(options = {}) {
|
|
265
428
|
const cache = new Map();
|
|
266
|
-
const virtualToReal = new Map();
|
|
267
429
|
const collectedCss = new Map();
|
|
268
430
|
let isProduction;
|
|
269
431
|
let root;
|
|
432
|
+
let clientViteBase = "/";
|
|
433
|
+
let serverViteBase = "/";
|
|
270
434
|
let server = null;
|
|
271
435
|
let filter;
|
|
272
436
|
let scanPatterns;
|
|
273
437
|
let ignorePatterns;
|
|
274
438
|
let mergedOptions;
|
|
439
|
+
let initialized = false;
|
|
440
|
+
let dynamicImportAliasRules = [];
|
|
441
|
+
let cssAliasRules = [];
|
|
275
442
|
let extractCss = false;
|
|
443
|
+
let clientViteDefine = {};
|
|
444
|
+
let serverViteDefine = {};
|
|
276
445
|
const logger = createLogger(options.debug ?? false);
|
|
277
446
|
async function compileAll() {
|
|
278
447
|
const startTime = performance.now();
|
|
@@ -294,7 +463,7 @@ function vize(options = {}) {
|
|
|
294
463
|
}
|
|
295
464
|
const result = compileBatch(fileContents, cache, { ssr: mergedOptions.ssr ?? false });
|
|
296
465
|
if (isProduction) {
|
|
297
|
-
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, fileResult.css);
|
|
466
|
+
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, resolveCssImports(fileResult.css, fileResult.path, cssAliasRules, false));
|
|
298
467
|
}
|
|
299
468
|
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
300
469
|
logger.info(`Pre-compilation complete: ${result.successCount} succeeded, ${result.failedCount} failed (${elapsed}ms, native batch: ${result.timeMs.toFixed(2)}ms)`);
|
|
@@ -305,36 +474,45 @@ function vize(options = {}) {
|
|
|
305
474
|
else if (id.startsWith("/") && !fs.existsSync(id)) resolved = path.resolve(root, id.slice(1));
|
|
306
475
|
else if (path.isAbsolute(id)) resolved = id;
|
|
307
476
|
else if (importer) {
|
|
308
|
-
|
|
309
|
-
if (realImporter.endsWith(".vue.ts")) realImporter = realImporter.slice(0, -3);
|
|
477
|
+
const realImporter = isVizeVirtual(importer) ? fromVirtualId(importer) : importer;
|
|
310
478
|
resolved = path.resolve(path.dirname(realImporter), id);
|
|
311
479
|
} else resolved = path.resolve(root, id);
|
|
312
480
|
if (!path.isAbsolute(resolved)) resolved = path.resolve(root, resolved);
|
|
313
481
|
return path.normalize(resolved);
|
|
314
482
|
}
|
|
315
|
-
|
|
483
|
+
const mainPlugin = {
|
|
316
484
|
name: "vite-plugin-vize",
|
|
317
485
|
enforce: "pre",
|
|
318
|
-
config() {
|
|
319
|
-
return {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
rolldownOptions: { external: [/\.vue$/] }
|
|
332
|
-
} };
|
|
486
|
+
config(_, env) {
|
|
487
|
+
return {
|
|
488
|
+
define: {
|
|
489
|
+
__VUE_OPTIONS_API__: true,
|
|
490
|
+
__VUE_PROD_DEVTOOLS__: env.command === "serve",
|
|
491
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
|
|
492
|
+
},
|
|
493
|
+
optimizeDeps: {
|
|
494
|
+
include: ["vue"],
|
|
495
|
+
exclude: ["virtual:vize-styles"],
|
|
496
|
+
rolldownOptions: { external: [/\.vue$/] }
|
|
497
|
+
}
|
|
498
|
+
};
|
|
333
499
|
},
|
|
334
500
|
async configResolved(resolvedConfig) {
|
|
335
501
|
root = options.root ?? resolvedConfig.root;
|
|
336
502
|
isProduction = options.isProduction ?? resolvedConfig.isProduction;
|
|
503
|
+
const isSsrBuild = !!resolvedConfig.build?.ssr;
|
|
504
|
+
if (isSsrBuild) serverViteBase = resolvedConfig.base ?? "/";
|
|
505
|
+
else clientViteBase = resolvedConfig.base ?? "/";
|
|
337
506
|
extractCss = isProduction;
|
|
507
|
+
const isSsr = !!resolvedConfig.build?.ssr;
|
|
508
|
+
const envDefine = {};
|
|
509
|
+
if (resolvedConfig.define) for (const [key, value] of Object.entries(resolvedConfig.define)) {
|
|
510
|
+
if (isBuiltinDefine(key)) continue;
|
|
511
|
+
if (typeof value === "string") envDefine[key] = value;
|
|
512
|
+
else envDefine[key] = JSON.stringify(value);
|
|
513
|
+
}
|
|
514
|
+
if (isSsr) serverViteDefine = envDefine;
|
|
515
|
+
else clientViteDefine = envDefine;
|
|
338
516
|
const configEnv = {
|
|
339
517
|
mode: resolvedConfig.mode,
|
|
340
518
|
command: resolvedConfig.command === "build" ? "build" : "serve",
|
|
@@ -364,6 +542,27 @@ function vize(options = {}) {
|
|
|
364
542
|
scanPatterns: options.scanPatterns ?? viteConfig.scanPatterns,
|
|
365
543
|
ignorePatterns: options.ignorePatterns ?? viteConfig.ignorePatterns
|
|
366
544
|
};
|
|
545
|
+
dynamicImportAliasRules = [];
|
|
546
|
+
for (const alias of resolvedConfig.resolve.alias) {
|
|
547
|
+
if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
|
|
548
|
+
const fromPrefix = alias.find.endsWith("/") ? alias.find : `${alias.find}/`;
|
|
549
|
+
const replacement = toBrowserImportPrefix(alias.replacement);
|
|
550
|
+
const toPrefix = replacement.endsWith("/") ? replacement : `${replacement}/`;
|
|
551
|
+
dynamicImportAliasRules.push({
|
|
552
|
+
fromPrefix,
|
|
553
|
+
toPrefix
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
dynamicImportAliasRules.sort((a, b) => b.fromPrefix.length - a.fromPrefix.length);
|
|
557
|
+
cssAliasRules = [];
|
|
558
|
+
for (const alias of resolvedConfig.resolve.alias) {
|
|
559
|
+
if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
|
|
560
|
+
cssAliasRules.push({
|
|
561
|
+
find: alias.find,
|
|
562
|
+
replacement: alias.replacement
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
cssAliasRules.sort((a, b) => b.find.length - a.find.length);
|
|
367
566
|
filter = createFilter(mergedOptions.include, mergedOptions.exclude);
|
|
368
567
|
scanPatterns = mergedOptions.scanPatterns ?? ["**/*.vue"];
|
|
369
568
|
ignorePatterns = mergedOptions.ignorePatterns ?? [
|
|
@@ -371,118 +570,240 @@ function vize(options = {}) {
|
|
|
371
570
|
"dist/**",
|
|
372
571
|
".git/**"
|
|
373
572
|
];
|
|
573
|
+
initialized = true;
|
|
374
574
|
},
|
|
375
575
|
configureServer(devServer) {
|
|
376
576
|
server = devServer;
|
|
577
|
+
devServer.middlewares.use((req, _res, next) => {
|
|
578
|
+
if (req.url && req.url.includes("__x00__")) {
|
|
579
|
+
const [urlPath, queryPart] = req.url.split("?");
|
|
580
|
+
let cleanedPath = urlPath.replace(/__x00__/g, "");
|
|
581
|
+
cleanedPath = cleanedPath.replace(/^\/@id\/\//, "/@fs/");
|
|
582
|
+
if (cleanedPath.startsWith("/@fs/")) {
|
|
583
|
+
const fsPath = cleanedPath.slice(4);
|
|
584
|
+
if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile() && !fsPath.endsWith(".vue.ts")) {
|
|
585
|
+
const cleaned = queryPart ? `${cleanedPath}?${queryPart}` : cleanedPath;
|
|
586
|
+
if (cleaned !== req.url) {
|
|
587
|
+
logger.log(`middleware: rewriting ${req.url} → ${cleaned}`);
|
|
588
|
+
req.url = cleaned;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
next();
|
|
594
|
+
});
|
|
377
595
|
},
|
|
378
596
|
async buildStart() {
|
|
597
|
+
if (!scanPatterns) return;
|
|
379
598
|
await compileAll();
|
|
380
599
|
logger.log("Cache keys:", [...cache.keys()].slice(0, 3));
|
|
381
600
|
},
|
|
382
601
|
async resolveId(id, importer) {
|
|
383
|
-
|
|
602
|
+
const isBuild = server === null;
|
|
603
|
+
if (id.startsWith("\0")) {
|
|
604
|
+
if (isVizeVirtual(id)) return null;
|
|
605
|
+
if (id.startsWith(LEGACY_VIZE_PREFIX)) {
|
|
606
|
+
const rawPath = id.slice(LEGACY_VIZE_PREFIX.length);
|
|
607
|
+
const cleanPath$1 = rawPath.endsWith(".ts") ? rawPath.slice(0, -3) : rawPath;
|
|
608
|
+
if (!cleanPath$1.endsWith(".vue")) {
|
|
609
|
+
logger.log(`resolveId: redirecting legacy virtual ID to ${cleanPath$1}`);
|
|
610
|
+
return cleanPath$1;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
const cleanPath = id.slice(1);
|
|
614
|
+
if (cleanPath.startsWith("/") && !cleanPath.endsWith(".vue.ts")) {
|
|
615
|
+
const [pathPart, queryPart] = cleanPath.split("?");
|
|
616
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
617
|
+
logger.log(`resolveId: redirecting \0-prefixed non-vue ID to ${pathPart}${querySuffix}`);
|
|
618
|
+
const redirected = pathPart + querySuffix;
|
|
619
|
+
return isBuild ? normalizeFsIdForBuild(redirected) : redirected;
|
|
620
|
+
}
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
384
623
|
if (id.startsWith("vize:")) {
|
|
385
624
|
let realPath = id.slice(5);
|
|
386
625
|
if (realPath.endsWith(".ts")) realPath = realPath.slice(0, -3);
|
|
387
626
|
logger.log(`resolveId: redirecting stale vize: ID to ${realPath}`);
|
|
388
|
-
|
|
389
|
-
|
|
627
|
+
const resolved = await this.resolve(realPath, importer, { skipSelf: true });
|
|
628
|
+
if (resolved && isBuild && resolved.id.startsWith("/@fs/")) return {
|
|
629
|
+
...resolved,
|
|
630
|
+
id: normalizeFsIdForBuild(resolved.id)
|
|
631
|
+
};
|
|
632
|
+
return resolved;
|
|
390
633
|
}
|
|
391
634
|
if (id === VIRTUAL_CSS_MODULE) return RESOLVED_CSS_MODULE;
|
|
635
|
+
if (isBuild && id.startsWith("/@fs/")) return normalizeFsIdForBuild(id);
|
|
392
636
|
if (id.includes("?vue&type=style")) return id;
|
|
393
|
-
if (importer
|
|
394
|
-
const
|
|
395
|
-
const cleanImporter = realImporter.endsWith(".ts") ? realImporter.slice(0, -3) : realImporter;
|
|
637
|
+
if (importer && isVizeVirtual(importer)) {
|
|
638
|
+
const cleanImporter = fromVirtualId(importer);
|
|
396
639
|
logger.log(`resolveId from virtual: id=${id}, cleanImporter=${cleanImporter}`);
|
|
397
|
-
if (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
640
|
+
if (id.startsWith("#")) try {
|
|
641
|
+
return await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
642
|
+
} catch {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
if (!id.endsWith(".vue")) {
|
|
646
|
+
if (id.includes("/dist/") || id.includes("/lib/") || id.includes("/es/")) return null;
|
|
647
|
+
try {
|
|
648
|
+
const resolved = await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
649
|
+
if (resolved) {
|
|
650
|
+
logger.log(`resolveId: resolved ${id} to ${resolved.id} via Vite resolver`);
|
|
651
|
+
if (isBuild && resolved.id.startsWith("/@fs/")) return {
|
|
652
|
+
...resolved,
|
|
653
|
+
id: normalizeFsIdForBuild(resolved.id)
|
|
654
|
+
};
|
|
655
|
+
return resolved;
|
|
656
|
+
}
|
|
657
|
+
} catch {}
|
|
658
|
+
if (id.startsWith("./") || id.startsWith("../")) {
|
|
659
|
+
const [pathPart, queryPart] = id.split("?");
|
|
660
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
661
|
+
const resolved = path.resolve(path.dirname(cleanImporter), pathPart);
|
|
662
|
+
for (const ext of [
|
|
663
|
+
"",
|
|
664
|
+
".ts",
|
|
665
|
+
".tsx",
|
|
666
|
+
".js",
|
|
667
|
+
".jsx",
|
|
668
|
+
".json"
|
|
669
|
+
]) {
|
|
670
|
+
const candidate = resolved + ext;
|
|
671
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
672
|
+
const finalPath = candidate + querySuffix;
|
|
673
|
+
logger.log(`resolveId: resolved relative ${id} to ${finalPath}`);
|
|
674
|
+
return finalPath;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) for (const indexFile of [
|
|
678
|
+
"/index.ts",
|
|
679
|
+
"/index.tsx",
|
|
680
|
+
"/index.js",
|
|
681
|
+
"/index.jsx"
|
|
682
|
+
]) {
|
|
683
|
+
const candidate = resolved + indexFile;
|
|
684
|
+
if (fs.existsSync(candidate)) {
|
|
685
|
+
const finalPath = candidate + querySuffix;
|
|
686
|
+
logger.log(`resolveId: resolved directory ${id} to ${finalPath}`);
|
|
687
|
+
return finalPath;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
417
690
|
}
|
|
418
|
-
|
|
419
|
-
const resolved = await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
420
|
-
logger.log(`resolveId: resolved external ${id} to`, resolved?.id ?? "null");
|
|
421
|
-
return resolved;
|
|
691
|
+
return null;
|
|
422
692
|
}
|
|
423
693
|
}
|
|
424
694
|
if (id.endsWith(".vue")) {
|
|
425
|
-
|
|
695
|
+
const handleNodeModules = initialized ? mergedOptions.handleNodeModulesVue ?? true : true;
|
|
696
|
+
if (!handleNodeModules && id.includes("node_modules")) {
|
|
426
697
|
logger.log(`resolveId: skipping node_modules import ${id}`);
|
|
427
698
|
return null;
|
|
428
699
|
}
|
|
429
700
|
const resolved = resolveVuePath(id, importer);
|
|
430
|
-
|
|
701
|
+
const isNodeModulesPath = resolved.includes("node_modules");
|
|
702
|
+
if (!handleNodeModules && isNodeModulesPath) {
|
|
431
703
|
logger.log(`resolveId: skipping node_modules path ${resolved}`);
|
|
432
704
|
return null;
|
|
433
705
|
}
|
|
434
|
-
if (!filter(resolved)) {
|
|
706
|
+
if (filter && !isNodeModulesPath && !filter(resolved)) {
|
|
435
707
|
logger.log(`resolveId: skipping filtered path ${resolved}`);
|
|
436
708
|
return null;
|
|
437
709
|
}
|
|
438
710
|
const hasCache = cache.has(resolved);
|
|
439
711
|
const fileExists = fs.existsSync(resolved);
|
|
440
712
|
logger.log(`resolveId: id=${id}, resolved=${resolved}, hasCache=${hasCache}, fileExists=${fileExists}, importer=${importer ?? "none"}`);
|
|
441
|
-
if (hasCache || fileExists)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
713
|
+
if (hasCache || fileExists) return toVirtualId(resolved);
|
|
714
|
+
if (!fileExists && !path.isAbsolute(id)) {
|
|
715
|
+
const viteResolved = await this.resolve(id, importer, { skipSelf: true });
|
|
716
|
+
if (viteResolved && viteResolved.id.endsWith(".vue")) {
|
|
717
|
+
const realPath = viteResolved.id;
|
|
718
|
+
const isResolvedNodeModules = realPath.includes("node_modules");
|
|
719
|
+
if ((isResolvedNodeModules ? handleNodeModules : filter(realPath)) && (cache.has(realPath) || fs.existsSync(realPath))) {
|
|
720
|
+
logger.log(`resolveId: resolved via Vite fallback ${id} to ${realPath}`);
|
|
721
|
+
return toVirtualId(realPath);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
445
724
|
}
|
|
446
725
|
}
|
|
447
726
|
return null;
|
|
448
727
|
},
|
|
449
|
-
load(id) {
|
|
728
|
+
load(id, loadOptions) {
|
|
729
|
+
const currentBase = loadOptions?.ssr ? serverViteBase : clientViteBase;
|
|
450
730
|
if (id === RESOLVED_CSS_MODULE) {
|
|
451
731
|
const allCss = Array.from(collectedCss.values()).join("\n\n");
|
|
452
732
|
return allCss;
|
|
453
733
|
}
|
|
454
734
|
if (id.includes("?vue&type=style")) {
|
|
455
735
|
const [filename] = id.split("?");
|
|
456
|
-
const realPath = filename
|
|
736
|
+
const realPath = isVizeVirtual(filename) ? fromVirtualId(filename) : filename;
|
|
457
737
|
const compiled = cache.get(realPath);
|
|
458
|
-
if (compiled?.css) return compiled.css;
|
|
738
|
+
if (compiled?.css) return resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase);
|
|
459
739
|
return "";
|
|
460
740
|
}
|
|
461
|
-
if (id
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
741
|
+
if (isVizeVirtual(id)) {
|
|
742
|
+
const realPath = fromVirtualId(id);
|
|
743
|
+
if (!realPath.endsWith(".vue")) {
|
|
744
|
+
logger.log(`load: skipping non-vue virtual module ${realPath}`);
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
let compiled = cache.get(realPath);
|
|
748
|
+
if (!compiled && fs.existsSync(realPath)) {
|
|
749
|
+
logger.log(`load: on-demand compiling ${realPath}`);
|
|
750
|
+
compiled = compileFile(realPath, cache, {
|
|
751
|
+
sourceMap: mergedOptions?.sourceMap ?? !(isProduction ?? false),
|
|
752
|
+
ssr: mergedOptions?.ssr ?? false
|
|
753
|
+
});
|
|
754
|
+
}
|
|
465
755
|
if (compiled) {
|
|
466
|
-
|
|
756
|
+
if (compiled.css) compiled = {
|
|
757
|
+
...compiled,
|
|
758
|
+
css: resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase)
|
|
759
|
+
};
|
|
760
|
+
const output = rewriteStaticAssetUrls(rewriteDynamicTemplateImports(generateOutput(compiled, {
|
|
467
761
|
isProduction,
|
|
468
762
|
isDev: server !== null,
|
|
469
763
|
extractCss
|
|
470
|
-
});
|
|
764
|
+
}), dynamicImportAliasRules), dynamicImportAliasRules);
|
|
471
765
|
return {
|
|
472
766
|
code: output,
|
|
473
767
|
map: null
|
|
474
768
|
};
|
|
475
769
|
}
|
|
476
770
|
}
|
|
771
|
+
if (id.startsWith("\0")) {
|
|
772
|
+
const afterPrefix = id.startsWith(LEGACY_VIZE_PREFIX) ? id.slice(LEGACY_VIZE_PREFIX.length) : id.slice(1);
|
|
773
|
+
if (afterPrefix.includes("?commonjs-")) return null;
|
|
774
|
+
const [pathPart, queryPart] = afterPrefix.split("?");
|
|
775
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
776
|
+
const fsPath = pathPart.startsWith("/@fs/") ? pathPart.slice(4) : pathPart;
|
|
777
|
+
if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile()) {
|
|
778
|
+
const importPath = server === null ? `${pathToFileURL(fsPath).href}${querySuffix}` : "/@fs" + fsPath + querySuffix;
|
|
779
|
+
logger.log(`load: proxying \0-prefixed file ${id} → re-export from ${importPath}`);
|
|
780
|
+
return `export { default } from ${JSON.stringify(importPath)};\nexport * from ${JSON.stringify(importPath)};`;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
477
783
|
return null;
|
|
478
784
|
},
|
|
479
|
-
async transform(code, id) {
|
|
480
|
-
if (
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
785
|
+
async transform(code, id, options$1) {
|
|
786
|
+
if (isVizeVirtual(id)) {
|
|
787
|
+
const realPath = fromVirtualId(id);
|
|
788
|
+
try {
|
|
789
|
+
const result = await transformWithOxc(code, realPath, { lang: "ts" });
|
|
790
|
+
const defines = options$1?.ssr ? serverViteDefine : clientViteDefine;
|
|
791
|
+
let transformed = result.code;
|
|
792
|
+
if (Object.keys(defines).length > 0) transformed = applyDefineReplacements(transformed, defines);
|
|
793
|
+
return {
|
|
794
|
+
code: transformed,
|
|
795
|
+
map: result.map
|
|
796
|
+
};
|
|
797
|
+
} catch (e) {
|
|
798
|
+
logger.error(`transformWithOxc failed for ${realPath}:`, e);
|
|
799
|
+
const dumpPath = `/tmp/vize-oxc-error-${path.basename(realPath)}.ts`;
|
|
800
|
+
fs.writeFileSync(dumpPath, code, "utf-8");
|
|
801
|
+
logger.error(`Dumped failing code to ${dumpPath}`);
|
|
802
|
+
return {
|
|
803
|
+
code: "export default {}",
|
|
804
|
+
map: null
|
|
805
|
+
};
|
|
806
|
+
}
|
|
486
807
|
}
|
|
487
808
|
return null;
|
|
488
809
|
},
|
|
@@ -492,13 +813,13 @@ function vize(options = {}) {
|
|
|
492
813
|
const source = await read();
|
|
493
814
|
const prevCompiled = cache.get(file);
|
|
494
815
|
compileFile(file, cache, {
|
|
495
|
-
sourceMap: mergedOptions
|
|
496
|
-
ssr: mergedOptions
|
|
816
|
+
sourceMap: mergedOptions?.sourceMap ?? !isProduction,
|
|
817
|
+
ssr: mergedOptions?.ssr ?? false
|
|
497
818
|
}, source);
|
|
498
819
|
const newCompiled = cache.get(file);
|
|
499
820
|
const updateType = detectHmrUpdateType(prevCompiled, newCompiled);
|
|
500
821
|
logger.log(`Re-compiled: ${path.relative(root, file)} (${updateType})`);
|
|
501
|
-
const virtualId =
|
|
822
|
+
const virtualId = toVirtualId(file);
|
|
502
823
|
const modules = server$1.moduleGraph.getModulesByFile(virtualId) ?? server$1.moduleGraph.getModulesByFile(file);
|
|
503
824
|
if (updateType === "style-only" && newCompiled.css) {
|
|
504
825
|
server$1.ws.send({
|
|
@@ -507,7 +828,7 @@ function vize(options = {}) {
|
|
|
507
828
|
data: {
|
|
508
829
|
id: newCompiled.scopeId,
|
|
509
830
|
type: "style-only",
|
|
510
|
-
css: newCompiled.css
|
|
831
|
+
css: resolveCssImports(newCompiled.css, file, cssAliasRules, true, clientViteBase)
|
|
511
832
|
}
|
|
512
833
|
});
|
|
513
834
|
return [];
|
|
@@ -530,8 +851,33 @@ function vize(options = {}) {
|
|
|
530
851
|
}
|
|
531
852
|
}
|
|
532
853
|
};
|
|
854
|
+
let compilerSfc = null;
|
|
855
|
+
const loadCompilerSfc = () => {
|
|
856
|
+
if (!compilerSfc) try {
|
|
857
|
+
const require = createRequire(import.meta.url);
|
|
858
|
+
compilerSfc = require("@vue/compiler-sfc");
|
|
859
|
+
} catch {
|
|
860
|
+
compilerSfc = { parse: () => ({
|
|
861
|
+
descriptor: {},
|
|
862
|
+
errors: []
|
|
863
|
+
}) };
|
|
864
|
+
}
|
|
865
|
+
return compilerSfc;
|
|
866
|
+
};
|
|
867
|
+
const vueCompatPlugin = {
|
|
868
|
+
name: "vite:vue",
|
|
869
|
+
api: { get options() {
|
|
870
|
+
return {
|
|
871
|
+
compiler: loadCompilerSfc(),
|
|
872
|
+
isProduction: isProduction ?? false,
|
|
873
|
+
root: root ?? process.cwd(),
|
|
874
|
+
template: {}
|
|
875
|
+
};
|
|
876
|
+
} }
|
|
877
|
+
};
|
|
878
|
+
return [vueCompatPlugin, mainPlugin];
|
|
533
879
|
}
|
|
534
880
|
var src_default = vize;
|
|
535
881
|
|
|
536
882
|
//#endregion
|
|
537
|
-
export { src_default as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
|
883
|
+
export { __internal, src_default as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
5
|
"publishConfig": {
|
|
6
|
-
"provenance": true,
|
|
7
6
|
"access": "public"
|
|
8
7
|
},
|
|
9
8
|
"type": "module",
|
|
@@ -44,7 +43,7 @@
|
|
|
44
43
|
},
|
|
45
44
|
"dependencies": {
|
|
46
45
|
"tinyglobby": "^0.2.0",
|
|
47
|
-
"@vizejs/native": "0.0
|
|
46
|
+
"@vizejs/native": "0.2.0"
|
|
48
47
|
},
|
|
49
48
|
"scripts": {
|
|
50
49
|
"build": "tsdown",
|