@vizejs/rspack-plugin 0.22.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ubugeeei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,452 @@
1
+ # @vizejs/rspack-plugin
2
+
3
+ High-performance Rspack plugin for Vue SFC compilation powered by [Vize](https://github.com/ubugeeei/vize).
4
+
5
+ > [!NOTE]
6
+ > Rspack intentionally uses the dedicated `@vizejs/rspack-plugin` path instead of an `@vizejs/unplugin/rspack` export.
7
+ > Its loader chain, `experiments.css`, and HMR behavior need Rspack-specific handling.
8
+ >
9
+ > Non-Vite bundler integrations are still unstable.
10
+ > If you need rollup, webpack, or esbuild, use `@vizejs/unplugin` and test carefully before relying on it in production.
11
+
12
+ ## Features
13
+
14
+ - ⚡ **Blazing Fast** - Powered by Rust-based `@vizejs/native` compiler
15
+ - 🔄 **HMR Support** - Script/template hot reload via `module.hot` + `__VUE_HMR_RUNTIME__`, CSS Modules HMR with targeted rerender
16
+ - 🎨 **CSS Processing** - Support for both native CSS (`experiments.css`) and CssExtractRspackPlugin
17
+ - 📦 **CSS Modules** - First-class CSS Modules support with per-module HMR
18
+ - 🔗 **`<style src>` Support** - Resolves external style files with watch dependency tracking
19
+ - 🔧 **TypeScript** - Full TypeScript support with auto-detection and optional built-in TS stripping
20
+ - 🗄️ **Compilation Cache** - Content-hash based caching to skip re-compilation of unchanged files
21
+ - 🛠️ **Vue DevTools** - Exposes `__file` for component file path in development mode
22
+ - 🧩 **Custom Elements** - Auto-detect `.ce.vue` or configure via `customElement` option
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pnpm add -D @vizejs/rspack-plugin @rspack/core
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Auto Preset
33
+
34
+ Use `createVizeVueRules()` to generate `.vue` rules automatically.
35
+ If you don't call it, write rules manually.
36
+
37
+ ```javascript
38
+ // rspack.config.mjs
39
+ import { rspack } from "@rspack/core";
40
+ import { VizePlugin, createVizeVueRules } from "@vizejs/rspack-plugin";
41
+
42
+ const isProduction = process.env.NODE_ENV === "production";
43
+
44
+ export default {
45
+ mode: isProduction ? "production" : "development",
46
+
47
+ experiments: {
48
+ css: true,
49
+ },
50
+
51
+ module: {
52
+ rules: [
53
+ ...createVizeVueRules({
54
+ isProduction,
55
+ nativeCss: true,
56
+ typescript: true, // auto-add SWC post-processing to strip TS types
57
+ styleLanguages: ["scss", "sass", "less", "stylus", "styl"],
58
+ loaderOptions: {
59
+ include: [/src\/.*\.vue$/],
60
+ exclude: [/node_modules/],
61
+ sourceMap: !isProduction,
62
+ },
63
+ }),
64
+ ],
65
+ },
66
+
67
+ plugins: [
68
+ new VizePlugin({
69
+ isProduction,
70
+ include: [/src\/.*\.vue$/],
71
+ exclude: [/node_modules/],
72
+ css: { native: true },
73
+ }),
74
+ ],
75
+ };
76
+ ```
77
+
78
+ ### Option A: Native CSS (Recommended)
79
+
80
+ Uses Rspack's built-in `experiments.css` for optimal performance. CSS is processed by Rust-side LightningCSS.
81
+
82
+ ```javascript
83
+ // rspack.config.mjs
84
+ import { rspack } from "@rspack/core";
85
+ import { VizePlugin } from "@vizejs/rspack-plugin";
86
+ import path from "node:path";
87
+
88
+ const isProduction = process.env.NODE_ENV === "production";
89
+
90
+ export default {
91
+ mode: isProduction ? "production" : "development",
92
+
93
+ // Enable Rspack native CSS support
94
+ experiments: {
95
+ css: true,
96
+ },
97
+
98
+ module: {
99
+ rules: [
100
+ {
101
+ test: /\.vue$/,
102
+ oneOf: [
103
+ // CSS Modules (<style module>)
104
+ {
105
+ resourceQuery: /vue&type=style.*module/,
106
+ type: "css/module",
107
+ use: [
108
+ {
109
+ loader: "@vizejs/rspack-plugin/style-loader",
110
+ },
111
+ ],
112
+ },
113
+
114
+ // SCSS (<style lang="scss">)
115
+ {
116
+ resourceQuery: /vue&type=style.*lang=scss/,
117
+ type: "css/auto",
118
+ use: [
119
+ "sass-loader",
120
+ {
121
+ loader: "@vizejs/rspack-plugin/style-loader",
122
+ },
123
+ ],
124
+ },
125
+
126
+ // Regular CSS (<style>)
127
+ {
128
+ resourceQuery: /vue&type=style/,
129
+ type: "css/auto",
130
+ use: [
131
+ {
132
+ loader: "@vizejs/rspack-plugin/style-loader",
133
+ },
134
+ ],
135
+ },
136
+
137
+ // Main .vue file (compile SFC → JS)
138
+ {
139
+ use: [
140
+ {
141
+ loader: "@vizejs/rspack-plugin/loader",
142
+ options: {
143
+ include: [/src\/.*\.vue$/],
144
+ exclude: [/node_modules/],
145
+ sourceMap: !isProduction,
146
+ },
147
+ },
148
+ ],
149
+ },
150
+ ],
151
+ },
152
+ ],
153
+ },
154
+
155
+ plugins: [
156
+ new VizePlugin({
157
+ isProduction,
158
+ include: [/src\/.*\.vue$/],
159
+ exclude: [/node_modules/],
160
+ css: {
161
+ native: true,
162
+ },
163
+ }),
164
+ ],
165
+
166
+ resolve: {
167
+ alias: {
168
+ "@": path.resolve(import.meta.dirname, "src"),
169
+ },
170
+ },
171
+ };
172
+ ```
173
+
174
+ ### Option B: CssExtractRspackPlugin
175
+
176
+ Compatible with webpack ecosystem, suitable for projects requiring PostCSS plugin chains.
177
+
178
+ ```javascript
179
+ // rspack.config.mjs
180
+ import { rspack } from "@rspack/core";
181
+ import { VizePlugin } from "@vizejs/rspack-plugin";
182
+ import path from "node:path";
183
+
184
+ const isProduction = process.env.NODE_ENV === "production";
185
+
186
+ export default {
187
+ mode: isProduction ? "production" : "development",
188
+
189
+ module: {
190
+ rules: [
191
+ {
192
+ test: /\.vue$/,
193
+ oneOf: [
194
+ // SCSS style blocks
195
+ {
196
+ resourceQuery: /vue&type=style.*lang=scss/,
197
+ type: "javascript/auto",
198
+ use: [
199
+ isProduction
200
+ ? rspack.CssExtractRspackPlugin.loader
201
+ : "style-loader",
202
+ "css-loader",
203
+ "sass-loader",
204
+ {
205
+ loader: "@vizejs/rspack-plugin/style-loader",
206
+ },
207
+ ],
208
+ },
209
+
210
+ // Regular CSS style blocks
211
+ {
212
+ resourceQuery: /vue&type=style/,
213
+ type: "javascript/auto",
214
+ use: [
215
+ isProduction
216
+ ? rspack.CssExtractRspackPlugin.loader
217
+ : "style-loader",
218
+ {
219
+ loader: "css-loader",
220
+ options: {
221
+ modules: {
222
+ auto: (_resourcePath, resourceQuery) =>
223
+ typeof resourceQuery === "string" &&
224
+ resourceQuery.includes("module="),
225
+ },
226
+ },
227
+ },
228
+ {
229
+ loader: "@vizejs/rspack-plugin/style-loader",
230
+ },
231
+ ],
232
+ },
233
+
234
+ // Main .vue file
235
+ {
236
+ use: [
237
+ {
238
+ loader: "@vizejs/rspack-plugin/loader",
239
+ options: {
240
+ include: [/src\/.*\.vue$/],
241
+ exclude: [/node_modules/],
242
+ sourceMap: !isProduction,
243
+ },
244
+ },
245
+ ],
246
+ },
247
+ ],
248
+ },
249
+
250
+ // Regular CSS files (non-Vue)
251
+ {
252
+ test: /\.css$/,
253
+ type: "javascript/auto",
254
+ use: [
255
+ isProduction ? rspack.CssExtractRspackPlugin.loader : "style-loader",
256
+ "css-loader",
257
+ ],
258
+ },
259
+
260
+ // Regular SCSS files (non-Vue)
261
+ {
262
+ test: /\.scss$/,
263
+ type: "javascript/auto",
264
+ use: [
265
+ isProduction ? rspack.CssExtractRspackPlugin.loader : "style-loader",
266
+ "css-loader",
267
+ "sass-loader",
268
+ ],
269
+ },
270
+ ],
271
+ },
272
+
273
+ plugins: [
274
+ new VizePlugin({
275
+ isProduction,
276
+ include: [/src\/.*\.vue$/],
277
+ exclude: [/node_modules/],
278
+ }),
279
+
280
+ // CSS extraction (production only)
281
+ ...(isProduction
282
+ ? [
283
+ new rspack.CssExtractRspackPlugin({
284
+ filename: "styles/[name].[contenthash:8].css",
285
+ chunkFilename: "styles/[name].[contenthash:8].chunk.css",
286
+ }),
287
+ ]
288
+ : []),
289
+ ],
290
+
291
+ resolve: {
292
+ alias: {
293
+ "@": path.resolve(import.meta.dirname, "src"),
294
+ },
295
+ },
296
+ };
297
+ ```
298
+
299
+ ## API
300
+
301
+ ### VizePlugin
302
+
303
+ ```typescript
304
+ import { VizePlugin } from "@vizejs/rspack-plugin";
305
+
306
+ new VizePlugin({
307
+ isProduction: boolean; // Auto-detected from Rspack mode
308
+ include: string | RegExp | (string | RegExp)[]; // Filter watched .vue files
309
+ exclude: string | RegExp | (string | RegExp)[]; // Exclude watched .vue files
310
+ ssr: boolean; // Enable SSR mode (default: false)
311
+ sourceMap: boolean; // Enable source maps (default: true in dev)
312
+ vapor: boolean; // Enable Vapor mode (default: false, SFC-level not yet supported)
313
+ root: string; // Root directory (default: Rspack's root)
314
+ css: {
315
+ native: boolean; // Use experiments.css (default: false), warns if config mismatch
316
+ };
317
+ compilerOptions: {}; // Extra @vizejs/native compileSfc options
318
+ debug: boolean; // Enable debug logging (default: false)
319
+ });
320
+ // Debug logging uses Rspack's infrastructure logger.
321
+ // Control verbosity via `infrastructureLogging.level` in your rspack config.
322
+ ```
323
+
324
+ ### VizeLoader
325
+
326
+ ```typescript
327
+ // In rspack.config.js
328
+ {
329
+ loader: "@vizejs/rspack-plugin/loader",
330
+ options: {
331
+ include: string | RegExp | (string | RegExp)[]; // Safe compile allowlist
332
+ exclude: string | RegExp | (string | RegExp)[]; // Safe compile denylist
333
+ sourceMap: boolean; // Enable source maps (default: true)
334
+ ssr: boolean; // Enable SSR mode (default: false)
335
+ customElement: boolean | RegExp; // Custom element mode (default: /\.ce\.vue$/)
336
+ hotReload: boolean; // Enable HMR (default: true in dev, false in prod/SSR)
337
+ compilerOptions: { // Extra @vizejs/native compileSfc options
338
+ filename?: string;
339
+ sourceMap?: boolean;
340
+ ssr?: boolean;
341
+ isTs?: boolean; // Preserve TypeScript (auto-detected from <script lang="ts">)
342
+ scopeId?: string;
343
+ };
344
+ };
345
+ }
346
+ ```
347
+
348
+ If `include/exclude` filters out a `.vue` file matched by this loader rule, the loader emits a warning and passes through the source unchanged.
349
+ This avoids hard failures while still alerting you to mismatched rule/filter configuration.
350
+
351
+ Compilation errors cause the loader to fail immediately (`callback(error)`) instead of returning broken code.
352
+
353
+ ### VizeStyleLoader
354
+
355
+ ```typescript
356
+ // In rspack.config.js
357
+ {
358
+ loader: "@vizejs/rspack-plugin/style-loader",
359
+ options: {
360
+ native: boolean; // Using experiments.css (default: false)
361
+ };
362
+ }
363
+ ```
364
+
365
+ ### createVizeVueRules
366
+
367
+ ```typescript
368
+ import { createVizeVueRules } from "@vizejs/rspack-plugin";
369
+
370
+ const rules = createVizeVueRules({
371
+ isProduction: false,
372
+ nativeCss: true, // true: css/auto + css/module, false: css-loader chain
373
+ styleLanguages: ["scss", "sass", "less", "stylus", "styl"],
374
+ styleInjectLoader: "style-loader",
375
+ styleExtractLoader: undefined, // e.g. rspack.CssExtractRspackPlugin.loader
376
+ cssLoader: "css-loader",
377
+ loaderOptions: {
378
+ include: [/src\/.*\.vue$/],
379
+ exclude: [/node_modules/],
380
+ sourceMap: true,
381
+ },
382
+ styleLoaderOptions: {
383
+ native: true, // match nativeCss setting
384
+ },
385
+ typescript: true, // or a custom LoaderEntry
386
+ });
387
+ ```
388
+
389
+ ## Comparison
390
+
391
+ | Feature | Native CSS (`experiments.css`) | CssExtractRspackPlugin |
392
+ | ------------------ | ------------------------------ | ---------------------- |
393
+ | **CSS Engine** | Rust (LightningCSS) | JS (css-loader) |
394
+ | **CSS Extraction** | Rspack automatic | CssExtractRspackPlugin |
395
+ | **CSS Modules** | `type: 'css/module'` | css-loader config |
396
+ | **HMR** | Rspack native | style-loader |
397
+ | **Vendor Prefix** | LightningCSS built-in | Requires autoprefixer |
398
+ | **Performance** | **Excellent** (Rust) | Good (JS) |
399
+ | **Use Case** | **New projects** | webpack compatibility |
400
+
401
+ ## Known Limitations
402
+
403
+ ### HMR
404
+
405
+ Script and template changes trigger a component-level hot reload via `module.hot.accept()` + `__VUE_HMR_RUNTIME__.reload()`. CSS Module changes trigger a targeted rerender without full reload. Plain `<style>` HMR is handled natively by Rspack's CSS pipeline.
406
+
407
+ ### Path Resolution
408
+
409
+ Style imports injected by the main loader are normalized to resolver-friendly request paths.
410
+ In modern Rspack setups this avoids most absolute-path query edge cases, especially across platforms.
411
+
412
+ ### Diagnostics
413
+
414
+ Compiler diagnostics are emitted via loader APIs:
415
+
416
+ - Compile errors: `callback(error)` — fails the build immediately
417
+ - Compile warnings: `this.emitWarning(...)`
418
+ - Missing `<style src>` files: build error (fail fast, no silent style loss)
419
+ - Scoped CSS fallback: warning emitted once per file (deduplicated in watch mode)
420
+
421
+ Scoped preprocessor blocks such as `<style scoped lang="scss">` are currently rejected.
422
+ The fallback transformer only understands plain CSS selectors, so allowing SCSS/Less/Stylus here would silently produce incorrect scoped output.
423
+
424
+ ### Scoped CSS
425
+
426
+ Scoped CSS scope IDs are derived from the file's **relative path** (relative to Rspack's `rootContext`). In production builds, the file content is also mixed into the hash to prevent collisions across packages with identically-named files. This ensures consistent scope IDs across different machines for SSR hydration.
427
+
428
+ The current scoped CSS implementation uses a fallback regex transformer with the following limitations:
429
+
430
+ - ❌ No support for `:deep()`, `:global()`, `:slotted()` pseudo-classes
431
+ - ❌ No support for nested `@media` / `@supports` selectors
432
+ - ❌ May not handle CSS comments containing `{` or `,` correctly
433
+
434
+ **Recommendation**: This is an MVP implementation. For production-grade scoped CSS, consider waiting for native-side precise API support.
435
+
436
+ ### Source Maps
437
+
438
+ The current `@vizejs/native` NAPI does not yet return a source map field. The type definition reserves a `map?: string` field for forward-compatibility. Once the Rust side implements source map output, the loader will pass it to Rspack automatically.
439
+
440
+ ### TypeScript Output
441
+
442
+ `@vizejs/native compileSfc` preserves TypeScript syntax in its output (same behavior as `@vue/compiler-sfc`). A downstream transpiler is needed to strip type annotations:
443
+
444
+ - **Recommended**: Use `createVizeVueRules({ typescript: true })` to auto-add a `builtin:swc-loader` post-processing rule
445
+ - **Custom loader**: Pass a `LoaderEntry` — e.g. `typescript: "esbuild-loader"` or `typescript: { loader: "esbuild-loader", options: { ... } }`
446
+ - **Manual**: Add your own `enforce: "post"` rule for `.vue` files (exclude `type=style` requests)
447
+
448
+ The `isTs` option is auto-detected from `<script lang="ts">` and passed to the native compiler for correct parsing.
449
+
450
+ ## License
451
+
452
+ MIT
@@ -0,0 +1,7 @@
1
+ import { VizeLoaderOptions } from "./index-Crp9t5G9.js";
2
+ import { LoaderContext } from "@rspack/core";
3
+
4
+ //#region src/loader/index.d.ts
5
+
6
+ declare function vizeLoader(this: LoaderContext<VizeLoaderOptions>, source: string): void; //#endregion
7
+ export { vizeLoader as vizeLoader$1 };
@@ -0,0 +1,249 @@
1
+ //#region src/types/index.d.ts
2
+ /**
3
+ * Type definitions for @vizejs/rspack-plugin
4
+ * Copied and adapted from vite-plugin-vize
5
+ */
6
+ interface SfcCompileOptionsNapi {
7
+ filename?: string;
8
+ sourceMap?: boolean;
9
+ ssr?: boolean;
10
+ /** Preserve TypeScript in output when true */
11
+ isTs?: boolean;
12
+ /** Scope ID for scoped CSS (e.g., "data-v-abc123") */
13
+ scopeId?: string;
14
+ }
15
+ interface SfcCompileResultNapi {
16
+ code: string;
17
+ css?: string;
18
+ /** Source map JSON string (when implemented in @vizejs/native) */
19
+ map?: string;
20
+ errors: string[];
21
+ warnings: string[];
22
+ }
23
+ interface StyleBlockInfo {
24
+ /** Raw style content (uncompiled for preprocessor langs) */
25
+ content: string;
26
+ /** External style source path from `<style src="...">` */
27
+ src?: string | null;
28
+ /** Language of the style block (e.g., "css", "scss", "less", "sass", "stylus") */
29
+ lang: string | null;
30
+ /** Whether the style block has the scoped attribute */
31
+ scoped: boolean;
32
+ /** CSS Modules: true for unnamed `module`, or the binding name for `module="name"` */
33
+ module: boolean | string;
34
+ /** Index of this style block in the SFC */
35
+ index: number;
36
+ }
37
+ interface CustomBlockInfo {
38
+ /** Tag name of the custom block (e.g., "i18n", "docs") */
39
+ type: string;
40
+ /** Raw content of the custom block */
41
+ content: string;
42
+ /** External source path from `<block src="...">` */
43
+ src?: string | null;
44
+ /** All attributes on the custom block tag */
45
+ attrs: Record<string, string | true>;
46
+ /** Index of this custom block in the SFC */
47
+ index: number;
48
+ }
49
+ interface SfcSrcInfo {
50
+ /** Whether <script> has a src attribute */
51
+ scriptSrc?: string | null;
52
+ /** Whether <template> has a src attribute */
53
+ templateSrc?: string | null;
54
+ }
55
+ interface CompiledModule {
56
+ code: string;
57
+ css?: string;
58
+ errors: string[];
59
+ warnings: string[];
60
+ scopeId: string;
61
+ hasScoped: boolean;
62
+ /** Per-block style metadata extracted from the source SFC */
63
+ styles: StyleBlockInfo[];
64
+ /** Custom blocks extracted from the source SFC */
65
+ customBlocks: CustomBlockInfo[];
66
+ /** Whether this is a custom element SFC (e.g., .ce.vue) */
67
+ isCustomElement: boolean;
68
+ }
69
+ interface VizeLoaderOptions {
70
+ /**
71
+ * Enable source map generation
72
+ * @default true
73
+ */
74
+ sourceMap?: boolean;
75
+ /**
76
+ * Enable SSR mode
77
+ * @default false
78
+ */
79
+ ssr?: boolean;
80
+ /**
81
+ * Project root directory
82
+ */
83
+ root?: string;
84
+ /**
85
+ * Files to include in compilation (safe filter)
86
+ */
87
+ include?: string | RegExp | (string | RegExp)[];
88
+ /**
89
+ * Files to exclude from compilation (safe filter)
90
+ */
91
+ exclude?: string | RegExp | (string | RegExp)[];
92
+ /**
93
+ * Additional low-level compiler options passed to @vizejs/native compileSfc
94
+ */
95
+ compilerOptions?: SfcCompileOptionsNapi;
96
+ /**
97
+ * Transform Vue SFCs into custom elements.
98
+ * - `true`: all `*.vue` imports are converted into custom elements
99
+ * - `RegExp`: matched files are converted into custom elements
100
+ *
101
+ * @default /\.ce\.vue$/
102
+ */
103
+ customElement?: boolean | RegExp;
104
+ /**
105
+ * Enable HMR (Hot Module Replacement) for Vue SFCs.
106
+ * Set to `false` to explicitly disable HMR even in development mode.
107
+ *
108
+ * @default true (enabled in development, disabled in production/SSR)
109
+ */
110
+ hotReload?: boolean;
111
+ }
112
+ interface VizeStyleLoaderOptions {
113
+ /**
114
+ * Whether to use native CSS mode (experiments.css)
115
+ * In both modes, the loader outputs pure CSS
116
+ * @default false
117
+ */
118
+ native?: boolean;
119
+ }
120
+ type VizeStyleLanguage = "css" | "scss" | "sass" | "less" | "styl" | "stylus";
121
+ interface CreateVizeVueRulesOptions {
122
+ /**
123
+ * Production mode flag
124
+ * @default false
125
+ */
126
+ isProduction?: boolean;
127
+ /**
128
+ * Use Rspack native CSS pipeline (`experiments.css`)
129
+ * @default true
130
+ */
131
+ nativeCss?: boolean;
132
+ /**
133
+ * Extra languages to handle automatically in addition to `css`
134
+ * @default ["scss", "sass", "less", "stylus", "styl"]
135
+ */
136
+ styleLanguages?: VizeStyleLanguage[];
137
+ /**
138
+ * Loader entry for the main `.vue` compiler loader
139
+ * @default "@vizejs/rspack-plugin/loader"
140
+ */
141
+ vizeLoader?: string;
142
+ /**
143
+ * Loader entry for the `.vue` style extractor loader
144
+ * @default "@vizejs/rspack-plugin/style-loader"
145
+ */
146
+ vizeStyleLoader?: string;
147
+ /**
148
+ * Dev style injector / prod extractor loader entry used in non-native CSS mode
149
+ * @default "style-loader"
150
+ */
151
+ styleInjectLoader?: LoaderEntry;
152
+ /**
153
+ * Production CSS extractor loader entry used in non-native CSS mode
154
+ * (e.g. `rspack.CssExtractRspackPlugin.loader`)
155
+ */
156
+ styleExtractLoader?: LoaderEntry;
157
+ /**
158
+ * css-loader entry used in non-native CSS mode
159
+ * @default "css-loader"
160
+ */
161
+ cssLoader?: LoaderEntry;
162
+ /**
163
+ * Main vize loader options
164
+ */
165
+ loaderOptions?: VizeLoaderOptions;
166
+ /**
167
+ * Vize style loader options
168
+ */
169
+ styleLoaderOptions?: VizeStyleLoaderOptions;
170
+ /**
171
+ * Add a post-processing rule to strip TypeScript type annotations from
172
+ * the compiled `.vue` output.
173
+ *
174
+ * This is needed because `@vizejs/native compileSfc` preserves TypeScript
175
+ * syntax in its output (same as `@vue/compiler-sfc`), and a downstream
176
+ * transpiler must strip the types before the browser/runtime can execute it.
177
+ *
178
+ * - `true`: use Rspack built-in SWC loader (`builtin:swc-loader`)
179
+ * - `LoaderEntry`: use a custom loader (e.g. `esbuild-loader`)
180
+ * - `false` / omitted: no post-processing (user handles it separately)
181
+ *
182
+ * @default false
183
+ */
184
+ typescript?: boolean | LoaderEntry;
185
+ }
186
+ interface VizeRspackPluginOptions {
187
+ /**
188
+ * Files to include in compilation
189
+ * @default /\.vue$/
190
+ */
191
+ include?: string | RegExp | (string | RegExp)[];
192
+ /**
193
+ * Files to exclude from compilation
194
+ * @default /node_modules/
195
+ */
196
+ exclude?: string | RegExp | (string | RegExp)[];
197
+ /**
198
+ * Force production mode
199
+ * @default auto-detected from Rspack config
200
+ */
201
+ isProduction?: boolean;
202
+ /**
203
+ * Enable SSR mode
204
+ * @default false
205
+ */
206
+ ssr?: boolean;
207
+ /**
208
+ * Enable source map generation
209
+ * @default true in development, false in production
210
+ */
211
+ sourceMap?: boolean;
212
+ /**
213
+ * Enable Vapor mode compilation
214
+ * @default false
215
+ */
216
+ vapor?: boolean;
217
+ /**
218
+ * Root directory to scan for .vue files
219
+ * @default Rspack's root
220
+ */
221
+ root?: string;
222
+ /**
223
+ * CSS configuration
224
+ */
225
+ css?: {
226
+ /**
227
+ * Use Rspack native CSS processing (experiments.css)
228
+ * When enabled, no need for css-loader/style-loader/CssExtractRspackPlugin
229
+ * Handled by Rust-side LightningCSS, better performance
230
+ * @default false
231
+ */
232
+ native?: boolean;
233
+ };
234
+ /**
235
+ * Custom compiler options
236
+ */
237
+ compilerOptions?: SfcCompileOptionsNapi;
238
+ /**
239
+ * Enable debug logging
240
+ * @default false
241
+ */
242
+ debug?: boolean;
243
+ }
244
+ /** Loader entry: either a string (loader name/path) or an object with loader + options */
245
+ type LoaderEntry = string | {
246
+ loader: string;
247
+ options?: Record<string, unknown>;
248
+ }; //#endregion
249
+ export { CompiledModule, CreateVizeVueRulesOptions, CustomBlockInfo, LoaderEntry, SfcCompileOptionsNapi, SfcCompileResultNapi, SfcSrcInfo, StyleBlockInfo, VizeLoaderOptions, VizeRspackPluginOptions, VizeStyleLanguage, VizeStyleLoaderOptions };
@@ -0,0 +1,159 @@
1
+ import { CompiledModule, CreateVizeVueRulesOptions, CustomBlockInfo, LoaderEntry, SfcCompileOptionsNapi, SfcCompileResultNapi, SfcSrcInfo, StyleBlockInfo, VizeLoaderOptions, VizeRspackPluginOptions, VizeStyleLanguage, VizeStyleLoaderOptions } from "./index-Crp9t5G9.js";
2
+ import { vizeLoader$1 as vizeLoader } from "./index-C1nbpj8i.js";
3
+ import { vizeStyleLoader$1 as vizeStyleLoader } from "./style-loader-zO0F0c6t.js";
4
+ import { Compiler } from "@rspack/core";
5
+
6
+ //#region src/plugin/index.d.ts
7
+
8
+ declare class VizePlugin {
9
+ static readonly name = "VizePlugin";
10
+ private options;
11
+ constructor(options?: VizeRspackPluginOptions);
12
+ apply(compiler: Compiler): void;
13
+ private shouldHandleFile;
14
+ } //#endregion
15
+ //#region src/shared/utils.d.ts
16
+ /**
17
+ * Generate a unique scope ID for scoped CSS based on file path.
18
+ * Uses SHA256 hash and takes the first 8 characters.
19
+ *
20
+ * Uses relative path (when rootContext is provided) for cross-environment
21
+ * consistency (e.g. SSR hydration). In production, mixes source content
22
+ * into the hash to avoid collisions across packages with identically-named files.
23
+ */
24
+ declare function generateScopeId(filename: string, rootContext?: string, isProduction?: boolean, source?: string): string;
25
+ /**
26
+ * Extract style block metadata from a Vue SFC source string.
27
+ * Parses `<style>` tags to determine lang, scoped, and module attributes.
28
+ *
29
+ * Copied from vite-plugin-vize/src/compiler.ts
30
+ */
31
+ declare function extractStyleBlocks(source: string): StyleBlockInfo[];
32
+ /**
33
+ * Fallback scoped CSS transformer using simple regex.
34
+ *
35
+ * ⚠️ Known limitations:
36
+ * - Does not support @media / @supports nested selectors
37
+ * - Does not support Vue's :deep() / :global() / :slotted() pseudo-classes
38
+ * - Does not handle CSS comments containing { or ,
39
+ * - Does not support :root and other pseudo-class selectors
40
+ *
41
+ * Recommendation: This regex implementation is for MVP stage only;
42
+ * production-grade scoped semantics should use native-side precise API.
43
+ *
44
+ * Copied from rspack-plugin-design.md
45
+ */
46
+ declare function addScopeToCssFallback(css: string, scopeId: string): string;
47
+ /**
48
+ * Extract custom block metadata from a Vue SFC source string.
49
+ * Parses root-level tags that are not <script>, <template>, or <style>.
50
+ */
51
+ declare function extractCustomBlocks(source: string): CustomBlockInfo[];
52
+ /**
53
+ * Extract <script src> and <template src> references from an SFC source.
54
+ * Returns null for each if no src attribute is present.
55
+ */
56
+ declare function extractSrcInfo(source: string): SfcSrcInfo;
57
+ /**
58
+ * Replace <script src="..."> or <template src="..."> with inline content
59
+ * read from external files. This produces a self-contained SFC string
60
+ * that can be passed to compileSfc.
61
+ */
62
+ declare function inlineSrcBlocks(source: string, scriptContent: string | null, templateContent: string | null): string;
63
+ /**
64
+ * Create a conditional logger.
65
+ *
66
+ * Copied from vite-plugin-vize/src/transform.ts
67
+ */
68
+ declare function createLogger(debug: boolean): {
69
+ log: (...args: unknown[]) => false | void;
70
+ info: (...args: unknown[]) => void;
71
+ warn: (...args: unknown[]) => void;
72
+ error: (...args: unknown[]) => void;
73
+ };
74
+ /**
75
+ * Match a file path against include/exclude patterns.
76
+ * Used by both the main loader and the plugin for consistent filtering.
77
+ *
78
+ * Normalizes backslashes to forward slashes before matching,
79
+ * so patterns like /src\/.*\.vue$/ work on Windows.
80
+ */
81
+ declare function matchesPattern(file: string, pattern: string | RegExp | (string | RegExp)[] | undefined, defaultValue: boolean): boolean;
82
+
83
+ //#endregion
84
+ //#region src/shared/hotReload.d.ts
85
+ /**
86
+ * HMR (Hot Module Replacement) code generation for Vue SFC modules.
87
+ *
88
+ * Uses `module.hot` (Rspack/webpack CommonJS HMR API), NOT `import.meta.hot`.
89
+ * Reference: rspack-vue-loader's hotReload.ts
90
+ *
91
+ * __VUE_HMR_RUNTIME__ is injected into global scope by @vue/runtime-core.
92
+ */
93
+ /**
94
+ * Generate HMR boilerplate code for a compiled Vue SFC module.
95
+ *
96
+ * The generated code:
97
+ * 1. Assigns `__hmrId` to the component for Vue devtools
98
+ * 2. Calls `module.hot.accept()` to make the module self-accepting
99
+ * 3. Registers or reloads the component via `__VUE_HMR_RUNTIME__`
100
+ *
101
+ * @param id - Unique HMR identifier for this component (typically the scopeId hash)
102
+ */
103
+ declare function genHotReloadCode(id: string): string;
104
+
105
+ //#endregion
106
+ //#region src/shared/compiler.d.ts
107
+ /**
108
+ * Generate HMR code for a CSS Module import.
109
+ *
110
+ * When the CSS Module file changes, this code:
111
+ * 1. Updates the __cssModules binding with the new values
112
+ * 2. Triggers a Vue component rerender (NOT a full reload)
113
+ */
114
+ /**
115
+ * Clear the compilation cache. Exposed for testing and manual invalidation.
116
+ */
117
+ declare function clearCompilationCache(): void;
118
+ /**
119
+ * Compile a single .vue file.
120
+ *
121
+ * Adapted from vite-plugin-vize for Rspack loader scenario:
122
+ * - Uses content-hash based cache to skip re-compilation of unchanged files
123
+ * - Does not read file (source is passed as parameter)
124
+ * - Returns styles metadata for loader chain processing
125
+ */
126
+ declare function compileFile(filePath: string, source: string, options?: {
127
+ sourceMap?: boolean;
128
+ ssr?: boolean;
129
+ compilerOptions?: SfcCompileOptionsNapi;
130
+ isCustomElement?: boolean;
131
+ rootContext?: string;
132
+ isProduction?: boolean;
133
+ }): CompiledModule;
134
+ /**
135
+ * Generate output code with style imports and custom block imports injected.
136
+ *
137
+ * Key difference from Vite version:
138
+ * - Generates import statements with query parameters for style blocks
139
+ * - Rspack will route these to the appropriate style loader via resourceQuery matching
140
+ * - Injects `module.hot` based HMR code when `hmr` is enabled
141
+ */
142
+ declare function generateOutput(compiled: CompiledModule, options: {
143
+ requestPath: string;
144
+ /** Inject HMR boilerplate using `module.hot` (Rspack/webpack CJS API) */
145
+ hmr?: boolean;
146
+ /** Original file path (for __file exposure in dev mode) */
147
+ filePath?: string;
148
+ /** Whether this is a production build */
149
+ isProduction?: boolean;
150
+ /** Project root context (for computing relative __file path) */
151
+ rootContext?: string;
152
+ }): string;
153
+
154
+ //#endregion
155
+ //#region src/preset/rules.d.ts
156
+ declare function createVizeVueRules(options?: CreateVizeVueRulesOptions): Record<string, unknown>[];
157
+
158
+ //#endregion
159
+ export { CompiledModule, CreateVizeVueRulesOptions, CustomBlockInfo, LoaderEntry, SfcCompileOptionsNapi, SfcCompileResultNapi, SfcSrcInfo, StyleBlockInfo, VizeLoaderOptions, VizePlugin, VizeRspackPluginOptions, VizeStyleLanguage, VizeStyleLoaderOptions, addScopeToCssFallback, clearCompilationCache, compileFile, createLogger, createVizeVueRules, extractCustomBlocks, extractSrcInfo, extractStyleBlocks, genHotReloadCode, generateOutput, generateScopeId, inlineSrcBlocks, matchesPattern, vizeLoader, vizeStyleLoader };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{addScopeToCssFallback as e,createLogger as t,extractCustomBlocks as n,extractSrcInfo as r,extractStyleBlocks as i,generateScopeId as a,inlineSrcBlocks as o,matchesPattern as s}from"./utils-Cw44tFia.js";import{clearCompilationCache as c,compileFile as l,genHotReloadCode as u,generateOutput as d,vizeLoader as f}from"./loader-DyzGJOBD.js";import{vizeStyleLoader as p}from"./style-loader-DPvk-BhE.js";var m=class e{static name=`VizePlugin`;options;constructor(e={}){this.options=e}apply(t){let n=t.getInfrastructureLogger(e.name),r=this.options.isProduction??t.options.mode===`production`;this.options.vapor&&n.warn("Vapor mode is enabled but SFC-level Vapor compilation is not yet supported by @vizejs/native. Only `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` will be set. Track https://github.com/nicepkg/vize for updates.");let i=!!t.options.experiments?.css;this.options.css?.native&&!i&&n.warn("`css.native: true` is set but `experiments.css` is not enabled in rspack config.");let{DefinePlugin:a}=t.webpack,o=new Set;for(let e of t.options.plugins??[]){let t=e?.definitions;if(t)for(let e of Object.keys(t))o.add(e)}let s={};o.has(`__VUE_OPTIONS_API__`)||(s.__VUE_OPTIONS_API__=JSON.stringify(!0)),o.has(`__VUE_PROD_DEVTOOLS__`)||(s.__VUE_PROD_DEVTOOLS__=JSON.stringify(!r)),o.has(`__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`)||(s.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__=JSON.stringify(!r)),Object.keys(s).length>0&&new a(s).apply(t),r||t.hooks.watchRun.tap(e.name,e=>{let t=e.modifiedFiles,r=e.removedFiles;if(t)for(let e of t)e.endsWith(`.vue`)&&this.shouldHandleFile(e)&&n.debug(`Vue file changed: ${e}`);if(r)for(let e of r)e.endsWith(`.vue`)&&this.shouldHandleFile(e)&&n.debug(`Vue file removed: ${e}`)})}shouldHandleFile(e){return!(!s(e,this.options.include,!0)||s(e,this.options.exclude,!1))}};const h=[`scss`,`sass`,`less`,`stylus`,`styl`],g={scss:`sass-loader`,sass:`sass-loader`,less:`less-loader`,styl:`stylus-loader`,stylus:`stylus-loader`};function _(e={}){let{isProduction:t=!1,nativeCss:n=!0,styleLanguages:r=h,vizeLoader:i=`@vizejs/rspack-plugin/loader`,vizeStyleLoader:a=`@vizejs/rspack-plugin/style-loader`,styleInjectLoader:o=`style-loader`,styleExtractLoader:s,cssLoader:c=`css-loader`,loaderOptions:l,styleLoaderOptions:u,typescript:d=!1}=e,f=Array.from(new Set(r.filter(e=>e!==`css`))),p={loader:a,...u?{options:u}:{}},m=[];for(let e of f){let r=g[e];if(!r)continue;m.push(v({lang:e,module:!0,nativeCss:n,styleLoaderEntry:p,preprocessorLoader:r,isProduction:t,styleInjectLoader:o,styleExtractLoader:s,cssLoader:c}))}m.push(v({module:!0,nativeCss:n,styleLoaderEntry:p,isProduction:t,styleInjectLoader:o,styleExtractLoader:s,cssLoader:c}));for(let e of f){let r=g[e];if(!r)continue;m.push(v({lang:e,module:!1,nativeCss:n,styleLoaderEntry:p,preprocessorLoader:r,isProduction:t,styleInjectLoader:o,styleExtractLoader:s,cssLoader:c}))}return m.push(v({module:!1,nativeCss:n,styleLoaderEntry:p,isProduction:t,styleInjectLoader:o,styleExtractLoader:s,cssLoader:c})),m.push({use:[{loader:i,options:l}]}),[{test:/\.vue$/,oneOf:m},...d?[{test:/\.vue$/,resourceQuery:{not:[/type=/]},enforce:`post`,...d===!0?{loader:`builtin:swc-loader`,options:{jsc:{parser:{syntax:`typescript`}}}}:typeof d==`string`?{loader:d}:d,type:`javascript/auto`}]:[]]}function v(e){let{lang:t,module:n,nativeCss:r,styleLoaderEntry:i,preprocessorLoader:a,isProduction:o,styleInjectLoader:s,styleExtractLoader:c,cssLoader:l}=e,u=[`type=style`];n&&u.push(`module`),t&&u.push(`lang=${t}`);let d=new RegExp(u.map(e=>`(?=.*${e})`).join(``));if(r)return{resourceQuery:d,type:n?`css/module`:`css/auto`,use:a?[a,i]:[i]};let f=typeof l==`string`?{loader:l,options:{modules:{auto:(e,t)=>typeof t==`string`&&t.includes(`module=`)}}}:l;return{resourceQuery:d,type:`javascript/auto`,use:[o&&c?c:s,f,...a?[a]:[],i]}}export{m as VizePlugin,e as addScopeToCssFallback,c as clearCompilationCache,l as compileFile,t as createLogger,_ as createVizeVueRules,n as extractCustomBlocks,r as extractSrcInfo,i as extractStyleBlocks,u as genHotReloadCode,d as generateOutput,a as generateScopeId,o as inlineSrcBlocks,s as matchesPattern,f as vizeLoader,p as vizeStyleLoader};
@@ -0,0 +1,3 @@
1
+ import "../index-Crp9t5G9.js";
2
+ import { vizeLoader$1 as vizeLoader } from "../index-C1nbpj8i.js";
3
+ export { vizeLoader as default };
@@ -0,0 +1 @@
1
+ import"../utils-Cw44tFia.js";import{vizeLoader as e}from"../loader-DyzGJOBD.js";export{e as default};
@@ -0,0 +1,3 @@
1
+ import "../index-Crp9t5G9.js";
2
+ import { vizeStyleLoader$1 as vizeStyleLoader } from "../style-loader-zO0F0c6t.js";
3
+ export { vizeStyleLoader as default };
@@ -0,0 +1 @@
1
+ import"../utils-Cw44tFia.js";import{vizeStyleLoader as e}from"../style-loader-DPvk-BhE.js";export{e as default};
@@ -0,0 +1,22 @@
1
+ import{extractCustomBlocks as e,extractSrcInfo as t,extractStyleBlocks as n,generateScopeId as r,inlineSrcBlocks as i,matchesPattern as a}from"./utils-Cw44tFia.js";import{createHash as o}from"node:crypto";import s from"node:path";import c from"node:fs";import*as l from"@vizejs/native";function u(e){return`
2
+ /* hot reload */
3
+ if (module.hot) {
4
+ _sfc_main.__hmrId = "${e}"
5
+ const api = __VUE_HMR_RUNTIME__
6
+ module.hot.accept()
7
+ if (!api.createRecord('${e}', _sfc_main)) {
8
+ api.reload('${e}', _sfc_main)
9
+ }
10
+ }`}function d(e,t,n,r){return`
11
+ if (module.hot) {
12
+ module.hot.accept(${t}, () => {
13
+ _sfc_main.__cssModules[${JSON.stringify(r)}] = ${n}
14
+ __VUE_HMR_RUNTIME__.rerender("${e}")
15
+ })
16
+ }`}const{compileSfc:f}=l,p=new Map;function m(e){return o(`sha256`).update(e).digest(`hex`).slice(0,16)}function h(){p.clear()}function g(t,i,a={}){let o=a.compilerOptions?.isTs??/<script[^>]*\blang=["']ts["']/.test(i),s=a.ssr??a.compilerOptions?.ssr??!1,c=a.sourceMap??a.compilerOptions?.sourceMap??!0,l=a.isCustomElement??!1,u=a.rootContext??``,d=a.isProduction??!1,h=`${t}:ssr=${s}:ts=${o}:map=${c}:ce=${l}:root=${u}:prod=${d}`,g=m(i),_=p.get(h);if(_&&_.contentHash===g)return _.result;let v=r(t,a.rootContext,a.isProduction,i),y=/<style[^>]*\bscoped\b/.test(i),b={...a.compilerOptions,filename:t,sourceMap:a.sourceMap??a.compilerOptions?.sourceMap??!0,ssr:s,isTs:o,scopeId:y?`data-v-${v}`:void 0},x=f(i,b),S=n(i),C=e(i),w={code:x.code,css:x.css,errors:x.errors,warnings:x.warnings,scopeId:v,hasScoped:y,styles:S,customBlocks:C,isCustomElement:l};return w.errors.length===0&&p.set(h,{contentHash:g,result:w}),w}function _(e,t){let n=e.code,r=e.isCustomElement,i=/^export default /m,a=i.test(n),o=/\bconst\s+_sfc_main\s*=/.test(n);if(a&&!o?(n=n.replace(i,`const _sfc_main = `),e.hasScoped&&e.scopeId&&(n+=`\n_sfc_main.__scopeId = "data-v-${e.scopeId}";`),n+=`
17
+ export default _sfc_main;`):a&&o&&e.hasScoped&&e.scopeId&&(n=n.replace(/^export default _sfc_main/m,`_sfc_main.__scopeId = "data-v-${e.scopeId}";\nexport default _sfc_main`)),e.styles.length>0){if(r){let t=e.styles.some(e=>e.module);if(t)throw Error(`[vize] <style module> is not supported in custom elements mode.`)}let i=e.styles.filter(e=>e.module===!0).length;if(i>1)throw Error(`[vize] Found ${i} unnamed <style module> blocks. Only one unnamed <style module> is allowed per SFC. Use named modules instead: <style module="name">`);let a=e.styles.filter(e=>e.src||/\S/.test(e.content)),o=[],s=a.map(n=>{let i=[`vue`,`type=style`,`index=${n.index}`,`lang=${n.lang||`css`}`,...n.scoped?[`scoped=${e.scopeId}`]:[],...n.module?[`module=${typeof n.module==`string`?n.module:`true`}`]:[],...r?[`inline`]:[]],a=i.join(`&`),s=`${t.requestPath}?${a}`;if(r)return`import _style_${n.index} from ${JSON.stringify(s)};`;if(n.module){let e=typeof n.module==`string`?n.module:`$style`,t=`_cssModule_${n.index}`;return o.push({request:s,varName:t,bindingName:e}),`import ${t} from ${JSON.stringify(s)};`}return`import ${JSON.stringify(s)};`}).join(`
18
+ `);if(n=s+`
19
+ `+n,r){let e=a.map(e=>`_style_${e.index}`).join(`,`);n=n.replace(/^export default _sfc_main;/m,`_sfc_main.styles = [${e}];\nexport default _sfc_main;`)}if(!r&&o.length>0){let r=o.map(e=>`_sfc_main.__cssModules = _sfc_main.__cssModules || {};\n_sfc_main.__cssModules[${JSON.stringify(e.bindingName)}] = ${e.varName};`).join(`
20
+ `),i=t.hmr&&e.scopeId?o.map(t=>d(e.scopeId,JSON.stringify(t.request),t.varName,t.bindingName)).join(`
21
+ `):``;n=n.replace(/^export default _sfc_main;/m,`${r}\n${i}\nexport default _sfc_main;`)}}if(t.filePath&&!t.isProduction){let e=t.rootContext?s.relative(t.rootContext,t.filePath).replace(/\\/g,`/`):s.basename(t.filePath);n=n.replace(/^export default _sfc_main;/m,`_sfc_main.__file = ${JSON.stringify(e)};\nexport default _sfc_main;`)}if(t.hmr&&e.scopeId&&(n=n.replace(/^export default _sfc_main;/m,`${u(e.scopeId)}\nexport default _sfc_main;`)),e.customBlocks.length>0){let r=e.customBlocks.map((e,n)=>{let r=[`vue`,`type=${e.type}`,`index=${n}`,...e.src?[`src=true`]:[]];for(let[t,n]of Object.entries(e.attrs)){if(t===`src`)continue;n===!0?r.push(t):r.push(`${t}=${n}`)}let i=r.join(`&`),a=t.requestPath;return`import block${n} from ${JSON.stringify(`${a}?${i}`)};\nif (typeof block${n} === 'function') block${n}(_sfc_main);`}).join(`
22
+ `);n=n.replace(/^export default _sfc_main;/m,`${r}\nexport default _sfc_main;`)}return n}const v=/\.ce\.vue$/;function y(n){let r=this.async(),a=this.getOptions(),o=this.resourcePath,l=this.resourceQuery,u=S(this,o),d=this.mode===`production`||process.env.NODE_ENV===`production`,f=a.ssr??!1,p=!f&&!d&&a.hotReload!==!1;if(this.addDependency(o),l?.includes(`type=style`)){r(Error(`[vize] Main loader received style sub-request: ${o}${l}. Use module.rules[].oneOf with resourceQuery branches so style requests are handled by @vizejs/rspack-plugin/style-loader.`));return}if(l&&l.includes(`vue`)&&l.includes(`type=`)&&!l.includes(`type=style`)){let t=new URLSearchParams(l.slice(1)),i=t.get(`type`);if(i&&i!==`style`){let a=parseInt(t.get(`index`)||`0`,10),l=e(n),u=l[a];if(u){if(u.src){let e=s.resolve(s.dirname(o),u.src);this.addDependency(e);try{let t=c.readFileSync(e,`utf-8`);r(null,t)}catch{r(Error(`[vize] Custom block <${i} src="${u.src}"> not found (resolved: ${e}) in ${o}`))}return}r(null,u.content)}else r(null,``);return}}if(!b(o,a)){this.emitWarning(Error(`[vize] File is filtered out by loader options include/exclude: ${o}. Passing through source unchanged.`)),r(null,n);return}try{let e=x(o,a.customElement),l=t(n),f=n;if(l.scriptSrc){let e=s.resolve(s.dirname(o),l.scriptSrc);this.addDependency(e);try{let t=c.readFileSync(e,`utf-8`);f=i(f,t,null)}catch{r(Error(`[vize] <script src="${l.scriptSrc}"> not found (resolved: ${e}) in ${o}`));return}}if(l.templateSrc){let e=s.resolve(s.dirname(o),l.templateSrc);this.addDependency(e);try{let t=c.readFileSync(e,`utf-8`);f=i(f,null,t)}catch{r(Error(`[vize] <template src="${l.templateSrc}"> not found (resolved: ${e}) in ${o}`));return}}let m=g(o,f,{sourceMap:a.sourceMap??this.sourceMap??!0,ssr:a.ssr??!1,compilerOptions:a.compilerOptions,isCustomElement:e,rootContext:this.rootContext,isProduction:d});for(let e of m.warnings)this.emitWarning(Error(`[vize] ${e}`));if(m.errors.length>0){for(let e of m.errors)this.emitError(Error(`[vize] ${e}`));let e=m.errors.join(`\\n`);r(Error(`[vize] Compilation failed for ${o}:\n${e}`));return}let h=_(m,{requestPath:u,hmr:p,filePath:o,isProduction:d,rootContext:this.rootContext});r(null,h)}catch(e){r(e)}}function b(e,t){return!(!a(e,t.include,!0)||a(e,t.exclude,!1))}function x(e,t){return t===!0?!0:t===!1||t===void 0?v.test(e):t.test(e)}function S(e,t){let n=s.basename(t);return`./${n}`}export{h as clearCompilationCache,g as compileFile,u as genHotReloadCode,_ as generateOutput,y as vizeLoader};
@@ -0,0 +1 @@
1
+ import{addScopeToCssFallback as e,extractStyleBlocks as t}from"./utils-Cw44tFia.js";import n from"node:path";import r from"node:fs/promises";const i=new Set;function a(e){let i=this.async(),{resourceQuery:a,resourcePath:s}=this;if(!a){i(null,e);return}let c=new URLSearchParams(a.slice(1)),l=c.get(`type`);if(l!==`style`){i(null,e);return}let u=parseInt(c.get(`index`)||`0`,10),d=c.get(`scoped`);this.addDependency(s);let f=t(e),p=f[u];if(!p){this.emitError(Error(`[vize] Style block at index ${u} not found in ${s}`)),i(null,``);return}if(p.src){let e=n.resolve(n.dirname(s),p.src);this.addDependency(e),r.readFile(e,`utf-8`).then(e=>{let t=o(this,e,p.scoped,d,s);i(null,t)}).catch(()=>{this.emitWarning(Error(`[vize] <style src> target not found: ${p.src} (resolved: ${e}) in ${s}`)),i(null,``)});return}let m=o(this,p.content,p.scoped,d,s);i(null,m)}function o(t,n,r,a,o){return r&&a?(i.has(o)||(i.add(o),t.emitWarning(Error(`[vize] scoped CSS uses fallback transformer with limitations: no :deep()/:global()/:slotted(), no nested @media. File: ${o}`))),e(n,a)):n}export{a as vizeStyleLoader};
@@ -0,0 +1,7 @@
1
+ import { VizeStyleLoaderOptions } from "./index-Crp9t5G9.js";
2
+ import { LoaderContext } from "@rspack/core";
3
+
4
+ //#region src/loader/style-loader.d.ts
5
+
6
+ declare function vizeStyleLoader(this: LoaderContext<VizeStyleLoaderOptions>, source: string): void; //#endregion
7
+ export { vizeStyleLoader as vizeStyleLoader$1 };
@@ -0,0 +1,3 @@
1
+ import{createHash as e}from"node:crypto";import t from"node:path";function n(n,r,i,a){let o;if(r){let e=t.relative(r,n).replace(/^(\.\.[/\\])+/,``).replace(/\\/g,`/`);o=i&&a?e+`
2
+ `+a.replace(/\r\n/g,`
3
+ `):e}else o=n;let s=e(`sha256`).update(o).digest(`hex`);return s.slice(0,8)}function r(e){let t=[],n=/<style([^>]*)>([\s\S]*?)<\/style>/gi,r,i=0;for(;(r=n.exec(e))!==null;){let e=r[1],n=r[2],a=e.match(/\bsrc=["']([^"']+)["']/)?.[1]??null,o=e.match(/\blang=["']([^"']+)["']/)?.[1]??null,s=/\bscoped\b/.test(e),c=e.match(/\bmodule(?:=["']([^"']+)["'])?\b/),l=c?c[1]||!0:!1;t.push({content:n,src:a,lang:o,scoped:s,module:l,index:i}),i++}return t}function i(e,t){let n=`[data-v-${t}]`,r=``,i=0,o=0,s=0;for(;o<e.length;){let t=e[o];if(t===`{`){if(i===0){let t=e.slice(s,o);r+=a(t,n),r+=`{`}else r+=t;i++,o++,s=o}else t===`}`?(i--,r+=t,o++,s=o):(i>0&&(r+=t),o++)}return s<e.length&&i===0&&(r+=e.slice(s)),r}function a(e,t){let n=e.trim();return n.startsWith(`@`)?e:e.split(`,`).map(e=>{let n=e.trim();if(!n||n.startsWith(`@`))return e;let r=e.match(/^(\s*)/)?.[1]??``;return`${r}${n}${t}`}).join(`,`)}function o(e){let t=e.replace(/<(script|template|style)\b[^>]*>[\s\S]*?<\/\1>/gi,``),n=[],r=/<([a-z][a-z0-9-]*)([^>]*)>([\s\S]*?)<\/\1>/gi,i,a=0;for(;(i=r.exec(t))!==null;){let e=i[1],t=i[2],r=i[3],o=t.match(/\bsrc=["']([^"']+)["']/)?.[1]??null,c=s(t);n.push({type:e,content:r,src:o,attrs:c,index:a}),a++}return n}function s(e){let t={},n=/\b([a-z][a-z0-9-]*)(?:=["']([^"']*)["'])?/gi,r;for(;(r=n.exec(e))!==null;)t[r[1]]=r[2]??!0;return t}function c(e){let t=e.match(/<script([^>]*)>/i),n=e.match(/<template([^>]*)>/i),r=t?.[1]?.match(/\bsrc=["']([^"']+)["']/)?.[1]??null,i=n?.[1]?.match(/\bsrc=["']([^"']+)["']/)?.[1]??null;return{scriptSrc:r,templateSrc:i}}function l(e,t,n){let r=e;return t!==null&&(r=r.replace(/(<script)([^>]*)\bsrc=["'][^"']+["']([^>]*>)[\s\S]*?(<\/script>)/i,(e,n,r,i,a)=>{let o=(r+i).replace(/\bsrc=["'][^"']+["']\s*/g,``);return`${n}${o}\n${t}\n${a}`})),n!==null&&(r=r.replace(/(<template)([^>]*)\bsrc=["'][^"']+["']([^>]*>)[\s\S]*?(<\/template>)/i,(e,t,r,i,a)=>{let o=(r+i).replace(/\bsrc=["'][^"']+["']\s*/g,``);return`${t}${o}\n${n}\n${a}`})),r}function u(e){return{log:(...t)=>e&&console.log(`[vize:rspack]`,...t),info:(...e)=>console.log(`[vize:rspack]`,...e),warn:(...e)=>console.warn(`[vize:rspack]`,...e),error:(...e)=>console.error(`[vize:rspack]`,...e)}}function d(e,t,n){if(!t)return n;let r=e.replace(/\\/g,`/`),i=Array.isArray(t)?t:[t];return i.some(t=>typeof t==`string`?r.includes(t)||e.includes(t):t.test(r))}export{i as addScopeToCssFallback,u as createLogger,o as extractCustomBlocks,c as extractSrcInfo,r as extractStyleBlocks,n as generateScopeId,l as inlineSrcBlocks,d as matchesPattern};
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@vizejs/rspack-plugin",
3
+ "version": "0.22.0",
4
+ "description": "High-performance Rspack plugin for Vue SFC compilation powered by Vize",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./loader": {
18
+ "types": "./dist/loader/index.d.ts",
19
+ "import": "./dist/loader/index.js",
20
+ "default": "./dist/loader/index.js"
21
+ },
22
+ "./style-loader": {
23
+ "types": "./dist/loader/style-loader.d.ts",
24
+ "import": "./dist/loader/style-loader.js",
25
+ "default": "./dist/loader/style-loader.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "keywords": [
32
+ "rspack",
33
+ "vue",
34
+ "plugin",
35
+ "loader",
36
+ "sfc",
37
+ "compiler",
38
+ "native",
39
+ "fast"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/ubugeeei/vize",
44
+ "directory": "npm/rspack-vize-plugin"
45
+ },
46
+ "license": "MIT",
47
+ "dependencies": {
48
+ "@vizejs/native": "0.24.0"
49
+ },
50
+ "peerDependencies": {
51
+ "@rspack/core": ">=1.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@rspack/core": "^1.7.7",
55
+ "@types/node": "^22.0.0",
56
+ "tsdown": "^0.9.0",
57
+ "tsx": "^4.21.0",
58
+ "typescript": "~5.6.0"
59
+ },
60
+ "scripts": {
61
+ "build": "tsdown",
62
+ "dev": "tsdown --watch",
63
+ "lint": "oxlint --deny-warnings --type-aware --tsconfig tsconfig.json",
64
+ "lint:fix": "oxlint --type-aware --tsconfig tsconfig.json --fix",
65
+ "fmt": "oxfmt --write src tsdown.config.ts",
66
+ "fmt:check": "oxfmt src tsdown.config.ts",
67
+ "test": "pnpm build && node --import tsx --test src/*.test.ts src/**/*.test.ts",
68
+ "test:update": "pnpm build && node --import tsx --test --test-update-snapshots src/*.test.ts src/**/*.test.ts"
69
+ }
70
+ }