@vizejs/vite-plugin 0.59.0 → 0.60.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/README.md CHANGED
@@ -12,15 +12,10 @@ High-performance native Vite plugin for Vue SFC compilation powered by [Vize](ht
12
12
 
13
13
  ## Installation
14
14
 
15
- ```bash
16
- # npm
17
- npm install @vizejs/vite-plugin vize
18
-
19
- # pnpm
20
- pnpm add @vizejs/vite-plugin vize
15
+ Install `vp` once from the [Vite+ install guide](https://viteplus.dev/guide/install), then add the packages:
21
16
 
22
- # yarn
23
- yarn add @vizejs/vite-plugin vize
17
+ ```bash
18
+ vp install -D @vizejs/vite-plugin vize
24
19
  ```
25
20
 
26
21
  ## Usage
package/dist/index.d.mts CHANGED
@@ -16,6 +16,12 @@ interface CompilerConfig {
16
16
  * @default false
17
17
  */
18
18
  vapor?: boolean;
19
+ /**
20
+ * Treat lowercase non-HTML tags as custom renderer elements instead of Vue components.
21
+ * Useful for TresJS and other custom renderers.
22
+ * @default false
23
+ */
24
+ customRenderer?: boolean;
19
25
  /**
20
26
  * Enable SSR mode
21
27
  * @default false
@@ -529,6 +535,12 @@ interface VizeOptions {
529
535
  * @default false
530
536
  */
531
537
  vapor?: boolean;
538
+ /**
539
+ * Treat lowercase non-HTML tags as custom renderer elements instead of Vue components.
540
+ * Useful for TresJS and other custom renderers.
541
+ * @default false
542
+ */
543
+ customRenderer?: boolean;
532
544
  /**
533
545
  * Root directory to scan for .vue files
534
546
  * @default Vite's root
package/dist/index.mjs CHANGED
@@ -176,7 +176,7 @@ function createFilter(include, exclude) {
176
176
  };
177
177
  }
178
178
  function generateOutput(compiled, options) {
179
- const { isProduction, isDev, hmrUpdateType, extractCss, filePath } = options;
179
+ const { isProduction, isDev, ssr, hmrUpdateType, extractCss, filePath } = options;
180
180
  let output = compiled.code;
181
181
  const exportDefaultRegex = /^export default /m;
182
182
  const hasExportDefault = exportDefaultRegex.test(output);
@@ -233,9 +233,9 @@ function generateOutput(compiled, options) {
233
233
  });
234
234
  }
235
235
  const cssModuleSetup = moduleBindings.map((m) => `_sfc_main.__cssModules = _sfc_main.__cssModules || {};\n_sfc_main.__cssModules[${JSON.stringify(m.name)}] = ${m.bindingName};`).join("\n");
236
- output = output.replace(/^export default _sfc_main;/m, `${cssModuleSetup}\nexport default _sfc_main;`);
236
+ output = output.replace(/^export default _sfc_main;?$/m, `${cssModuleSetup}\nexport default _sfc_main;`);
237
237
  }
238
- } else if (compiled.css && !(isProduction && extractCss)) output = `
238
+ } else if (!ssr && compiled.css && !(isProduction && extractCss)) output = `
239
239
  export const __vize_css__ = ${JSON.stringify(compiled.css)};
240
240
  const __vize_css_id__ = ${JSON.stringify(`vize-style-${compiled.scopeId}`)};
241
241
  (function() {
@@ -262,8 +262,10 @@ const VIZE_SSR_PREFIX = "\0vize-ssr:";
262
262
  const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
263
263
  /** Check if a module ID is a vize-compiled virtual module */
264
264
  function isVizeVirtual(id) {
265
- const pathPart = id.startsWith("\0vize-ssr:") ? id.slice(10) : id.slice(1);
266
- return id.startsWith("\0") && pathPart.endsWith(".vue.ts");
265
+ return isVizeVirtualVueModuleId(id);
266
+ }
267
+ function isVizeVirtualVueModuleId(id) {
268
+ return id.startsWith("\0") && /\.vue\.ts(?:\?|$)/.test(id);
267
269
  }
268
270
  function isVizeSsrVirtual(id) {
269
271
  return id.startsWith(VIZE_SSR_PREFIX);
@@ -274,8 +276,11 @@ function toVirtualId(realPath, ssr = false) {
274
276
  }
275
277
  /** Extract the real .vue file path from a virtual module ID */
276
278
  function fromVirtualId(virtualId) {
277
- const prefix = isVizeSsrVirtual(virtualId) ? 10 : 1;
278
- return virtualId.slice(prefix, -3);
279
+ return normalizeVizeVirtualVueModuleId(virtualId).split("?")[0];
280
+ }
281
+ function normalizeVizeVirtualVueModuleId(id) {
282
+ const prefix = isVizeSsrVirtual(id) ? 10 : 1;
283
+ return id.slice(prefix).replace(/\.ts(?=\?|$)/, "");
279
284
  }
280
285
  function escapeRegExp(value) {
281
286
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -396,13 +401,15 @@ function buildCompileFileOptions(filePath, source, options) {
396
401
  sourceMap: options.sourceMap,
397
402
  ssr: options.ssr,
398
403
  vapor: options.vapor,
404
+ customRenderer: options.customRenderer ?? false,
399
405
  scopeId
400
406
  };
401
407
  }
402
408
  function buildCompileBatchOptions(options) {
403
409
  return {
404
410
  ssr: options.ssr,
405
- vapor: options.vapor
411
+ vapor: options.vapor,
412
+ customRenderer: options.customRenderer ?? false
406
413
  };
407
414
  }
408
415
  //#endregion
@@ -520,9 +527,15 @@ function getCompileOptionsForRequest(state, ssr) {
520
527
  return {
521
528
  sourceMap: state.mergedOptions?.sourceMap ?? !state.isProduction,
522
529
  ssr,
523
- vapor: !ssr && (state.mergedOptions?.vapor ?? false)
530
+ vapor: !ssr && (state.mergedOptions?.vapor ?? false),
531
+ customRenderer: state.mergedOptions?.customRenderer ?? false
524
532
  };
525
533
  }
534
+ function syncCollectedCssForFile(state, filePath, compiled) {
535
+ if (!compiled || !state.isProduction) return;
536
+ if (compiled.css && !hasDelegatedStyles(compiled)) state.collectedCss.set(filePath, resolveCssImports(compiled.css, filePath, state.cssAliasRules, false));
537
+ else state.collectedCss.delete(filePath);
538
+ }
526
539
  /**
527
540
  * Pre-compile all Vue files matching scan patterns.
528
541
  */
@@ -570,7 +583,8 @@ async function compileAll(state) {
570
583
  }
571
584
  const result = compileBatch(fileContents, state.cache, {
572
585
  ssr: false,
573
- vapor: state.mergedOptions.vapor ?? false
586
+ vapor: state.mergedOptions.vapor ?? false,
587
+ customRenderer: state.mergedOptions.customRenderer ?? false
574
588
  });
575
589
  for (const file of changedFiles) {
576
590
  state.collectedCss.delete(file);
@@ -585,10 +599,7 @@ async function compileAll(state) {
585
599
  continue;
586
600
  }
587
601
  if (metadata) state.precompileMetadata.set(fileResult.path, metadata);
588
- if (state.isProduction && fileResult.css) {
589
- const cached = state.cache.get(fileResult.path);
590
- if (cached && !hasDelegatedStyles(cached)) state.collectedCss.set(fileResult.path, resolveCssImports(fileResult.css, fileResult.path, state.cssAliasRules, false));
591
- }
602
+ syncCollectedCssForFile(state, fileResult.path, state.cache.get(fileResult.path));
592
603
  }
593
604
  const elapsed = (performance.now() - startTime).toFixed(2);
594
605
  state.logger.info(`Pre-compilation complete: ${result.successCount} recompiled, ${cachedFileCount} reused, ${result.failedCount} failed (${elapsed}ms, native batch: ${result.timeMs.toFixed(2)}ms)`);
@@ -881,6 +892,7 @@ function loadHook(state, id, loadOptions) {
881
892
  if (!compiled && fs.existsSync(realPath)) {
882
893
  state.logger.log(`load: on-demand compiling ${realPath}`);
883
894
  compiled = compileFile(realPath, cache, getCompileOptionsForRequest(state, isSsr));
895
+ syncCollectedCssForFile(state, realPath, compiled);
884
896
  }
885
897
  if (compiled) {
886
898
  const hasDelegated = hasDelegatedStyles(compiled);
@@ -892,6 +904,7 @@ function loadHook(state, id, loadOptions) {
892
904
  const output = rewriteStaticAssetUrls(rewriteDynamicTemplateImports(generateOutput(compiled, {
893
905
  isProduction: state.isProduction,
894
906
  isDev: state.server !== null && !isSsr,
907
+ ssr: isSsr,
895
908
  hmrUpdateType: pendingHmrUpdateType,
896
909
  extractCss: state.extractCss,
897
910
  filePath: realPath
@@ -1060,9 +1073,12 @@ function createPostTransformPlugin(state) {
1060
1073
  state.logger.log(`post-transform: compiling virtual SFC content from ${id}`);
1061
1074
  try {
1062
1075
  const isSsr = !!transformOptions?.ssr;
1063
- const result = await transformWithOxc(generateOutput(compileFile(id, getEnvironmentCache(state, isSsr), getCompileOptionsForRequest(state, isSsr), code), {
1076
+ const compiled = compileFile(id, getEnvironmentCache(state, isSsr), getCompileOptionsForRequest(state, isSsr), code);
1077
+ syncCollectedCssForFile(state, id, compiled);
1078
+ const result = await transformWithOxc(generateOutput(compiled, {
1064
1079
  isProduction: state.isProduction,
1065
1080
  isDev: state.server !== null,
1081
+ ssr: isSsr,
1066
1082
  extractCss: state.extractCss,
1067
1083
  filePath: id
1068
1084
  }), id, { lang: "ts" });
@@ -1082,6 +1098,39 @@ function createPostTransformPlugin(state) {
1082
1098
  };
1083
1099
  }
1084
1100
  //#endregion
1101
+ //#region src/plugin/unocss.ts
1102
+ const bridgePatched = Symbol("vize.unocssBridgePatched");
1103
+ const plainSsrPrefix = VIZE_SSR_PREFIX.slice(1);
1104
+ function stripBridgePrefix(id) {
1105
+ if (id.startsWith("\0vize-ssr:")) return id.slice(10);
1106
+ if (id.startsWith(plainSsrPrefix)) return id.slice(plainSsrPrefix.length);
1107
+ if (id.startsWith("\0")) return id.slice(1);
1108
+ return id;
1109
+ }
1110
+ function isUnoCssBridgeModuleId(id) {
1111
+ return /\.vue\.ts(?:\?|$)/.test(stripBridgePrefix(id));
1112
+ }
1113
+ function normalizeUnoCssBridgeModuleId(id) {
1114
+ return stripBridgePrefix(id).replace(/\.ts(?=\?|$)/, "");
1115
+ }
1116
+ function patchUnoCssBridge(plugins) {
1117
+ for (const plugin of plugins) {
1118
+ if (!plugin.name?.startsWith("unocss:") || typeof plugin.transform !== "function" || plugin[bridgePatched]) continue;
1119
+ const originalTransform = plugin.transform;
1120
+ const isExtractionOnly = plugin.name.startsWith("unocss:global");
1121
+ plugin.transform = function(code, id, ...args) {
1122
+ if (!isUnoCssBridgeModuleId(id)) return originalTransform.call(this, code, id, ...args);
1123
+ const normalizedId = normalizeUnoCssBridgeModuleId(id);
1124
+ let effectiveCode = code;
1125
+ if (isExtractionOnly) try {
1126
+ effectiveCode = `${code}\n${fs.readFileSync(normalizedId.split("?")[0], "utf-8")}`;
1127
+ } catch {}
1128
+ return originalTransform.call(this, effectiveCode, normalizedId, ...args);
1129
+ };
1130
+ plugin[bridgePatched] = true;
1131
+ }
1132
+ }
1133
+ //#endregion
1085
1134
  //#region src/plugin/index.ts
1086
1135
  function vize(options = {}) {
1087
1136
  const state = {
@@ -1177,6 +1226,7 @@ function vize(options = {}) {
1177
1226
  ssr: options.ssr ?? compilerConfig.ssr ?? false,
1178
1227
  sourceMap: options.sourceMap ?? compilerConfig.sourceMap,
1179
1228
  vapor: options.vapor ?? compilerConfig.vapor ?? false,
1229
+ customRenderer: options.customRenderer ?? compilerConfig.customRenderer ?? false,
1180
1230
  include: options.include ?? viteConfig.include,
1181
1231
  exclude: options.exclude ?? viteConfig.exclude,
1182
1232
  scanPatterns: options.scanPatterns ?? viteConfig.scanPatterns,
@@ -1210,6 +1260,7 @@ function vize(options = {}) {
1210
1260
  "dist/**",
1211
1261
  ".git/**"
1212
1262
  ];
1263
+ patchUnoCssBridge(resolvedConfig.plugins);
1213
1264
  state.initialized = true;
1214
1265
  },
1215
1266
  configureServer(devServer) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizejs/vite-plugin",
3
- "version": "0.59.0",
3
+ "version": "0.60.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.59.0",
36
+ "@vizejs/native": "0.60.0",
37
37
  "tinyglobby": "0.2.16",
38
- "vize": "0.59.0"
38
+ "vize": "0.60.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "25.6.0",
@@ -52,6 +52,6 @@
52
52
  "check": "vp check src vite.config.ts",
53
53
  "check:fix": "vp check --fix src vite.config.ts",
54
54
  "fmt": "vp fmt --write src vite.config.ts",
55
- "test": "node src/test.ts"
55
+ "test": "pnpm --dir ../vize-native build:debug && node src/test.ts"
56
56
  }
57
57
  }