@vizejs/vite-plugin 0.206.0 → 0.210.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 CHANGED
@@ -56,6 +56,10 @@ interface CompilerConfig {
56
56
  * Enable Vapor mode compilation
57
57
  */
58
58
  vapor?: boolean;
59
+ /**
60
+ * Default output mode for .jsx/.tsx components without a "use vue:*" directive
61
+ */
62
+ jsxMode?: "vdom" | "vapor";
59
63
  /**
60
64
  * Treat lowercase non-HTML tags as custom renderer elements
61
65
  */
@@ -730,6 +734,14 @@ interface VizeOptions {
730
734
  * @default false
731
735
  */
732
736
  vapor?: boolean;
737
+ /**
738
+ * Default output mode for `.jsx`/`.tsx` components without a `"use vue:*"`
739
+ * directive. Distinct from `vapor` (which targets `.vue` SFCs): a project can
740
+ * keep SFCs on VDOM while defaulting JSX to Vapor, or vice versa. A
741
+ * per-component `"use vue:vapor"` / `"use vue:vdom"` directive overrides it.
742
+ * @default "vdom"
743
+ */
744
+ jsxMode?: "vdom" | "vapor";
733
745
  /**
734
746
  * Treat lowercase non-HTML tags as custom renderer elements instead of Vue components.
735
747
  * Useful for TresJS and other custom renderers.
package/dist/index.mjs CHANGED
@@ -94,6 +94,34 @@ function hasDelegatedStyles(compiled) {
94
94
  function supportsTemplateOnlyHmr(output) {
95
95
  return /(?:^|\n)(?:_sfc_main|__sfc__)\.render\s*=\s*render\b/m.test(output);
96
96
  }
97
+ /**
98
+ * Prepend a runtime `<style>` injection for plain CSS to a module's output.
99
+ *
100
+ * This is the same inline-CSS path plain SFC `<style>` blocks use in
101
+ * {@link generateOutput}: a guarded `document.createElement('style')` keyed by a
102
+ * stable id so the rule is injected once and idempotently. `styleKey` seeds the
103
+ * element id. Used for both SFC plain CSS and JSX `<style scoped>` CSS (#1495,
104
+ * #1533), whose content is already scope-rewritten by the compiler.
105
+ */
106
+ function prependInlineStyleInjection(output, css, styleKey) {
107
+ return `
108
+ export const __vize_css__ = ${JSON.stringify(css)};
109
+ const __vize_css_id__ = ${JSON.stringify(`vize-style-${styleKey}`)};
110
+ (function() {
111
+ if (typeof document !== 'undefined') {
112
+ let style = document.getElementById(__vize_css_id__);
113
+ if (!style) {
114
+ style = document.createElement('style');
115
+ style.id = __vize_css_id__;
116
+ style.textContent = __vize_css__;
117
+ document.head.appendChild(style);
118
+ } else {
119
+ style.textContent = __vize_css__;
120
+ }
121
+ }
122
+ })();
123
+ ${output}`;
124
+ }
97
125
  function insertAfterStaticImports(output, imports) {
98
126
  let insertAt = 0;
99
127
  for (const match of output.matchAll(/^import\b[^\n]*(?:\r?\n|$)/gm)) insertAt = (match.index ?? 0) + match[0].length;
@@ -172,23 +200,7 @@ function generateOutput(compiled, options) {
172
200
  const cssModuleSetup = moduleBindings.map((m) => `_sfc_main.__cssModules = _sfc_main.__cssModules || {};\n_sfc_main.__cssModules[${JSON.stringify(m.name)}] = ${m.bindingName};`).join("\n");
173
201
  output = output.replace(/^export default _sfc_main;?$/m, `${cssModuleSetup}\nexport default _sfc_main;`);
174
202
  }
175
- } else if (!ssr && compiled.css && !(isProduction && extractCss)) output = `
176
- export const __vize_css__ = ${JSON.stringify(compiled.css)};
177
- const __vize_css_id__ = ${JSON.stringify(`vize-style-${compiled.scopeId}`)};
178
- (function() {
179
- if (typeof document !== 'undefined') {
180
- let style = document.getElementById(__vize_css_id__);
181
- if (!style) {
182
- style = document.createElement('style');
183
- style.id = __vize_css_id__;
184
- style.textContent = __vize_css__;
185
- document.head.appendChild(style);
186
- } else {
187
- style.textContent = __vize_css__;
188
- }
189
- }
190
- })();
191
- ${output}`;
203
+ } else if (!ssr && compiled.css && !(isProduction && extractCss)) output = prependInlineStyleInjection(output, compiled.css, compiled.scopeId);
192
204
  if (!isProduction && isDev && hasExportDefault) {
193
205
  const effectiveHmrUpdateType = hmrUpdateType === "template-only" && !supportsTemplateOnlyHmr(output) ? "full-reload" : hmrUpdateType ?? "full-reload";
194
206
  output += generateHmrCode(compiled.scopeId, effectiveHmrUpdateType);
@@ -312,6 +324,7 @@ function buildCompileBatchOptions(options) {
312
324
  //#endregion
313
325
  //#region src/compiler.ts
314
326
  const { compileSfc, compileSfcBatchWithResults } = native;
327
+ const compileJsx = native.compileJsx;
315
328
  var VizeSfcCompileError = class extends Error {
316
329
  filePath;
317
330
  diagnostics;
@@ -405,6 +418,39 @@ function compileFile(filePath, cache, options, source) {
405
418
  return compiled;
406
419
  }
407
420
  /**
421
+ * Compile a `.jsx`/`.tsx` Vue component module to render code through Vize.
422
+ *
423
+ * Mirrors `compileFile` for SFCs but routes through the native `compileJsx`
424
+ * binding. The returned `code` is a self-contained module (the runtime-helper
425
+ * preamble is included, #1533), and `map` carries a v3 source map when
426
+ * `sourceMap` is requested. A component's `<style scoped>` CSS is surfaced
427
+ * (already scope-rewritten) and emitted through the same inline-injection path
428
+ * plain SFC `<style>` blocks use (#1495, #1533).
429
+ */
430
+ function compileJsxModule(filePath, source, options = {}) {
431
+ const result = compileJsx(source, {
432
+ filename: filePath,
433
+ lang: filePath.endsWith(".tsx") ? "tsx" : "jsx",
434
+ jsxMode: options.jsxMode,
435
+ vapor: options.vapor ?? false,
436
+ sourceMap: options.sourceMap ?? false
437
+ });
438
+ if (result.errors.length > 0) throw new VizeSfcCompileError(filePath, result.errors);
439
+ const css = (result.scopedStyles ?? []).map((style) => style.css).join("\n");
440
+ let code = result.code;
441
+ let map = result.map ?? null;
442
+ if (css && !options.ssr) {
443
+ const styleKey = result.scopedStyles[0].scopeId.replace(/^data-v-/, "");
444
+ code = prependInlineStyleInjection(code, css, styleKey);
445
+ map = null;
446
+ }
447
+ return {
448
+ code,
449
+ map,
450
+ warnings: result.warnings
451
+ };
452
+ }
453
+ /**
408
454
  * Batch compile multiple files in parallel using native Rust multithreading.
409
455
  * Returns per-file results with content hashes for HMR.
410
456
  */
@@ -1465,8 +1511,47 @@ function loadHook(state, id, loadOptions) {
1465
1511
  }
1466
1512
  return null;
1467
1513
  }
1514
+ function isJsxComponentPath(path) {
1515
+ return path.endsWith(".jsx") || path.endsWith(".tsx");
1516
+ }
1517
+ function shouldTransformJsxRequest(state, request) {
1518
+ if (!isJsxComponentPath(request.path)) return false;
1519
+ if (request.querySuffix) {
1520
+ const params = new URLSearchParams(request.querySuffix.slice(1));
1521
+ if (params.has("raw") || params.has("url") || params.has("worker") || params.has("sharedworker")) return false;
1522
+ }
1523
+ if (state.mergedOptions.exclude && !state.filter(request.path)) return false;
1524
+ return true;
1525
+ }
1526
+ /**
1527
+ * Route a raw `.jsx`/`.tsx` request through Vize's JSX compiler.
1528
+ *
1529
+ * Returns `undefined` when the request is not a JSX/TSX component (so the
1530
+ * caller falls through to the virtual-module pipeline), or a transform result
1531
+ * otherwise.
1532
+ */
1533
+ function transformJsxRequest(state, code, id, options) {
1534
+ const request = classifyVitePluginRequest(id);
1535
+ if (!shouldTransformJsxRequest(state, request)) return;
1536
+ const realPath = request.normalizedFsId ? classifyVitePluginRequest(request.normalizedFsId).path : request.path;
1537
+ const ssr = options?.ssr ?? false;
1538
+ const sourceMap = getCompileOptionsForRequest(state, ssr).sourceMap;
1539
+ const { code: compiled, map, warnings } = compileJsxModule(realPath, code, {
1540
+ jsxMode: state.mergedOptions.jsxMode,
1541
+ vapor: state.mergedOptions.vapor ?? false,
1542
+ ssr,
1543
+ sourceMap
1544
+ });
1545
+ for (const warning of warnings) state.logger.warn(`Warning in ${realPath}: ${warning}`);
1546
+ return {
1547
+ code: compiled,
1548
+ map: map ? JSON.parse(map) : null
1549
+ };
1550
+ }
1468
1551
  async function transformHook(state, code, id, options) {
1469
1552
  const pluginVisibleVirtualPath = fromPluginVisibleVirtualId(id);
1553
+ const jsxResult = transformJsxRequest(state, code, id, { ssr: options?.ssr });
1554
+ if (jsxResult !== void 0) return jsxResult;
1470
1555
  if (!id.startsWith("\0") && !pluginVisibleVirtualPath) return null;
1471
1556
  const request = classifyVitePluginRequest(id);
1472
1557
  if (request.isVizeVirtual || request.isMacroVirtualId || pluginVisibleVirtualPath) {
@@ -2012,6 +2097,7 @@ function vize(options = {}) {
2012
2097
  ssr: options.ssr ?? compilerConfig.ssr ?? false,
2013
2098
  sourceMap: options.sourceMap ?? compilerConfig.sourceMap,
2014
2099
  vapor: options.vapor ?? compilerConfig.vapor ?? false,
2100
+ jsxMode: options.jsxMode ?? compilerConfig.jsxMode,
2015
2101
  customRenderer: options.customRenderer ?? compilerConfig.customRenderer ?? false,
2016
2102
  templateSyntax,
2017
2103
  compatibility,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizejs/vite-plugin",
3
- "version": "0.206.0",
3
+ "version": "0.210.0",
4
4
  "description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
5
5
  "keywords": [
6
6
  "compiler",
@@ -39,9 +39,9 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@vizejs/native": "0.206.0",
42
+ "@vizejs/native": "0.210.0",
43
43
  "tinyglobby": "0.2.16",
44
- "vize": "0.206.0"
44
+ "vize": "0.210.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "25.9.2",