vite-userscript-plugin 2.0.0 → 2.1.1

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
@@ -83,10 +83,12 @@ Details: [types/README.md](./types/README.md).
83
83
 
84
84
  `vite` prints `/{fileName}.dev.user.js` — install that URL once. HMR covers code and styles.
85
85
 
86
+ `server.file: true` skips HMR. The same `vite` watch-builds `{fileName}.user.js` (headed IIFE), `{fileName}.js`, and `{fileName}.proxy.user.js` (`@require file://` to the IIFE). Install the printed `/{fileName}.user.js` URL (Firefox-safe). The `Proxy` line is for managers that can poll `file://`. See [examples/serve-file](./examples/serve-file).
87
+
86
88
  > [!IMPORTANT]
87
89
  > Changing `@match`, `@grant`, or `@name` needs a reinstall.
88
90
 
89
- `vite build` writes `{fileName}.user.js` to `dist/`.
91
+ `vite build` writes `{fileName}.user.js` to `dist/`. One-shot builds do not emit the proxy.
90
92
 
91
93
  ## Multiple scripts
92
94
 
@@ -133,8 +135,9 @@ See [examples/sourcemap](./examples/sourcemap).
133
135
  | `entry` | — | Userscript entry. Required. |
134
136
  | `header` | — | Metablock. Required: `name`, `version`, `match`. |
135
137
  | `fileName` | sanitized `header.name` | Output base name (`{fileName}.user.js`). |
136
- | `server.open` | `false` | Open the `.dev.user.js` install URL when Vite starts. |
138
+ | `server.open` | `false` | Open the install target when Vite starts. HMR: `.dev.user.js`. `file`: `.user.js` URL. |
137
139
  | `server.prefix` | `'server:'` | Prefix for `@name` in serve mode. `false` disables it. |
140
+ | `server.file` | `false` | Watch-build `{fileName}.user.js` + `{fileName}.js` + `{fileName}.proxy.user.js`. Install `.user.js` (or the proxy if `file://` `@require` works). No HMR. |
138
141
  | `cssInject` | `'auto'` | How production CSS is injected. `'auto'` uses `GM_addStyle` or a `<style>` node. |
139
142
  | `align` | `1` | Extra spaces after the longest `@key`. `false` — one space. |
140
143
  | `generate` | — | Rewrite the generated metablock. |
@@ -158,6 +161,7 @@ In serve mode the header lists every grant. In production the plugin scans the b
158
161
  | [svelte](./examples/svelte) | SFC `<style>`. |
159
162
  | [multiple-entries](./examples/multiple-entries) | Two scripts. |
160
163
  | [sourcemap](./examples/sourcemap) | Inline map, HTML page, virtual module. |
164
+ | [serve-file](./examples/serve-file) | `server.file`, install `.user.js` or the proxy from the printed URLs. |
161
165
 
162
166
  ## FAQ
163
167
 
@@ -181,17 +185,22 @@ In serve mode the header lists every grant. In production the plugin scans the b
181
185
  ### `@run-at document-start` feels late in dev
182
186
 
183
187
  > [!NOTE]
184
- > Serve injects `type="module"` (async). Production is a synchronous IIFE unless you use top-level `await`.
188
+ > Serve injects `type="module"` (async). Production is a synchronous IIFE unless you use top-level `await`. `server.file` uses that IIFE in dev too.
189
+
190
+ ### `file://` `@require` is blocked
191
+
192
+ > [!NOTE]
193
+ > Firefox extensions cannot read `file://`. Install the printed `{fileName}.user.js` URL instead of the proxy. Tampermonkey on Chromium must allow local file access for the proxy `@require`. Violentmonkey can poll the local IIFE after you install the proxy.
185
194
 
186
195
  ## Migration from v1
187
196
 
188
197
  | v1 | v2 |
189
198
  | --- | --- |
190
- | `vite build --watch` | `vite` |
199
+ | `vite build --watch` | `vite` (HMR) or `vite` + `server.file` |
191
200
  | `esbuildTransformOptions` | removed |
192
201
  | `server.port` | Vite `server.port` |
193
202
  | minify on by default | off; set `build.minify` |
194
- | `*.proxy.user.js` + `file://` | `*.dev.user.js` from Vite |
203
+ | `*.proxy.user.js` + `file://` | `server.file: true`, or HMR `.dev.user.js` |
195
204
  | Vite 3–7 | Vite 8 |
196
205
  | `scripts` + shared `header` | `userscript([config, config, …])` |
197
206
  | `ScriptOptions` | removed |
package/dist/index.d.ts CHANGED
@@ -146,7 +146,8 @@ type HeaderConfig = {
146
146
  };
147
147
  interface ServerConfig {
148
148
  /**
149
- * Open the `.dev.user.js` install URL when the Vite server starts.
149
+ * Open the install target when Vite starts.
150
+ * HMR: `.dev.user.js` URL. `file`: `{fileName}.user.js` URL.
150
151
  *
151
152
  * @default false
152
153
  */
@@ -158,6 +159,14 @@ interface ServerConfig {
158
159
  * @default 'server:'
159
160
  */
160
161
  prefix?: string | false;
162
+ /**
163
+ * Watch-build into `outDir`: `{fileName}.user.js`, headerless `{fileName}.js`,
164
+ * and `{fileName}.proxy.user.js` with `@require file://` pointing at the IIFE.
165
+ * Install `/{fileName}.user.js` (Firefox-safe) or the proxy URL. No HMR for this script.
166
+ *
167
+ * @default false
168
+ */
169
+ file?: boolean;
161
170
  }
162
171
  type HeaderMode = 'serve' | 'build' | 'meta';
163
172
  interface HeaderGenerateContext {
@@ -229,6 +238,7 @@ interface ResolvedScript {
229
238
  server: {
230
239
  open: boolean;
231
240
  prefix: string | false;
241
+ file: boolean;
232
242
  };
233
243
  cssInject: CssInject;
234
244
  align: number | false;
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { basename, posix, relative, resolve, sep } from "node:path";
2
+ import { build } from "vite";
2
3
  import { Buffer } from "node:buffer";
3
- import { existsSync } from "node:fs";
4
- import openLink from "open";
4
+ import { pathToFileURL } from "node:url";
5
+ import { existsSync, readFileSync } from "node:fs";
5
6
  import { styleText } from "node:util";
7
+ import openLink from "open";
6
8
  //#region src/names.ts
7
9
  function sanitizeFileName(name) {
8
10
  return name.replace(/[<>:"/\\|?*\u0000-\u001F]+/g, "-").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "userscript";
@@ -326,6 +328,37 @@ function ensureIife(code) {
326
328
  return `(${/\bawait\b/.test(stripped) ? "async function" : "function"} () {\n${stripped}\n})();\n`;
327
329
  }
328
330
  //#endregion
331
+ //#region src/build/proxy.ts
332
+ function toFileRequireUrl(absPath) {
333
+ return pathToFileURL(absPath).href;
334
+ }
335
+ function toRequireList(value) {
336
+ if (value == null) return [];
337
+ return Array.isArray(value) ? value.map(String) : [String(value)];
338
+ }
339
+ function createWatchProxyHeader(script, jsAbsPath) {
340
+ const header = withServeGrants({ ...script.header });
341
+ return {
342
+ ...header,
343
+ require: [...toRequireList(header.require), toFileRequireUrl(jsAbsPath)]
344
+ };
345
+ }
346
+ function generateWatchProxy(script, jsAbsPath) {
347
+ return generateHeader(createWatchProxyHeader(script, jsAbsPath), {
348
+ align: script.align,
349
+ autoMetaUrls: false,
350
+ fileName: script.fileName,
351
+ generate: script.generate,
352
+ mode: "serve"
353
+ });
354
+ }
355
+ function toProxyFileName(fileName) {
356
+ return `${fileName}.proxy.user.js`;
357
+ }
358
+ function toRequireFileName(fileName) {
359
+ return `${fileName}.js`;
360
+ }
361
+ //#endregion
329
362
  //#region src/build/apply.ts
330
363
  function importedChunkIds(chunk) {
331
364
  return [...chunk.imports, ...chunk.dynamicImports ?? []];
@@ -373,10 +406,33 @@ function withSourceMaps(fileNames) {
373
406
  function findScriptForChunk(chunk, fileName, scripts) {
374
407
  return scripts.find((script) => chunk.name === script.fileName || fileName === `${script.fileName}.js` || fileName === `${script.fileName}.user.js`);
375
408
  }
409
+ function createHeadedUserscript(script, options) {
410
+ const headerConfig = withBuildGrants(script.header, options.wrapped, options.extraGrants);
411
+ const prefix = `${generateHeader(headerConfig, {
412
+ align: script.align,
413
+ autoMetaUrls: script.autoMetaUrls,
414
+ fileName: script.fileName,
415
+ generate: script.generate,
416
+ mode: "build"
417
+ })}\n\n`;
418
+ const nextFileName = `${script.fileName}.user.js`;
419
+ let nextCode = `${prefix}${options.code}`;
420
+ if (options.map) {
421
+ const wrapOffset = isAlreadyIife(stripSourceMappingUrl(options.body)) ? 0 : 1;
422
+ const lineOffset = countHeaderLines(prefix) + countHeaderLines(options.cssPrelude) + wrapOffset + countHeaderLines(options.inlined);
423
+ const map = stripVendorSourcesContent(offsetSourceMap(options.map, lineOffset, nextFileName));
424
+ nextCode = `${stripSourceMappingUrl(nextCode).replace(/\n+$/g, "\n")}//# sourceMappingURL=${toInlineSourceMappingUrl(map)}\n`;
425
+ }
426
+ return {
427
+ headerConfig,
428
+ code: nextCode.endsWith("\n") ? nextCode : `${nextCode}\n`
429
+ };
430
+ }
376
431
  function deleteBundleFiles(bundle, fileNames) {
377
432
  for (const fileName of fileNames) delete bundle[fileName];
378
433
  }
379
- function applyUserscriptBundle(bundle, config, emitMeta) {
434
+ function applyUserscriptBundle(bundle, config, context) {
435
+ const { emitFile } = context;
380
436
  const userscriptEntries = [];
381
437
  const otherEntryFiles = [];
382
438
  for (const [fileName, item] of Object.entries(bundle)) {
@@ -405,27 +461,36 @@ function applyUserscriptBundle(bundle, config, emitMeta) {
405
461
  const body = `${inlined}${chunk.code}`;
406
462
  const wrapped = ensureIife(body);
407
463
  const extraGrants = css && script.cssInject === "auto" ? ["GM_addStyle"] : [];
408
- const headerConfig = withBuildGrants(script.header, wrapped, extraGrants);
409
464
  const code = `${cssPrelude}${wrapped}`;
410
- const prefix = `${generateHeader(headerConfig, {
411
- align: script.align,
412
- autoMetaUrls: script.autoMetaUrls,
413
- fileName: script.fileName,
414
- generate: script.generate,
415
- mode: "build"
416
- })}\n\n`;
417
- const nextFileName = `${script.fileName}.user.js`;
418
- let nextCode = `${prefix}${code}`;
419
- if (chunk.map) {
420
- const wrapOffset = isAlreadyIife(stripSourceMappingUrl(body)) ? 0 : 1;
421
- const lineOffset = countHeaderLines(prefix) + countHeaderLines(cssPrelude) + wrapOffset + countHeaderLines(inlined);
422
- chunk.map = stripVendorSourcesContent(offsetSourceMap(chunk.map, lineOffset, nextFileName));
423
- nextCode = `${stripSourceMappingUrl(nextCode).replace(/\n+$/g, "\n")}//# sourceMappingURL=${toInlineSourceMappingUrl(chunk.map)}\n`;
424
- }
465
+ const emitFileProxy = Boolean(context.emitProxy && context.outDir && script.server.file);
425
466
  leftoverAssets.push(`${fileName}.map`);
426
- chunk.code = nextCode;
427
- chunk.fileName = nextFileName;
428
- if (script.metaFile) emitMeta(`${script.fileName}.meta.js`, generateHeader(headerConfig, {
467
+ const headed = createHeadedUserscript(script, {
468
+ body,
469
+ code,
470
+ cssPrelude,
471
+ extraGrants,
472
+ inlined,
473
+ map: chunk.map,
474
+ wrapped
475
+ });
476
+ if (emitFileProxy) {
477
+ const requireName = toRequireFileName(script.fileName);
478
+ let nextCode = code.endsWith("\n") ? code : `${code}\n`;
479
+ if (chunk.map) {
480
+ const wrapOffset = isAlreadyIife(stripSourceMappingUrl(body)) ? 0 : 1;
481
+ const lineOffset = countHeaderLines(cssPrelude) + wrapOffset + countHeaderLines(inlined);
482
+ chunk.map = stripVendorSourcesContent(offsetSourceMap(chunk.map, lineOffset, requireName));
483
+ nextCode = `${stripSourceMappingUrl(nextCode).replace(/\n+$/g, "\n")}//# sourceMappingURL=${toInlineSourceMappingUrl(chunk.map)}\n`;
484
+ }
485
+ chunk.code = nextCode;
486
+ chunk.fileName = requireName;
487
+ emitFile(toProxyFileName(script.fileName), `${generateWatchProxy(script, resolve(context.outDir, requireName))}\n`);
488
+ emitFile(`${script.fileName}.user.js`, headed.code);
489
+ continue;
490
+ }
491
+ chunk.code = headed.code;
492
+ chunk.fileName = `${script.fileName}.user.js`;
493
+ if (script.metaFile) emitFile(`${script.fileName}.meta.js`, generateHeader(headed.headerConfig, {
429
494
  align: script.align,
430
495
  autoMetaUrls: script.autoMetaUrls,
431
496
  fileName: script.fileName,
@@ -443,12 +508,16 @@ function applyUserscriptBundle(bundle, config, emitMeta) {
443
508
  const VIRTUAL_MODULE_ID = "virtual:vite-userscript-plugin";
444
509
  const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
445
510
  function createClientSnapshot(scripts, command) {
446
- const suffix = command === "serve" ? ".dev.user.js" : ".user.js";
447
- return scripts.map((script) => ({
448
- name: script.header.name,
449
- version: script.header.version,
450
- file: `${script.fileName}${suffix}`
451
- }));
511
+ return scripts.map((script) => {
512
+ let suffix = ".dev.user.js";
513
+ if (command === "build") suffix = ".user.js";
514
+ else if (script.server.file) suffix = ".user.js";
515
+ return {
516
+ name: script.header.name,
517
+ version: script.header.version,
518
+ file: `${script.fileName}${suffix}`
519
+ };
520
+ });
452
521
  }
453
522
  function renderVirtualModule(scripts) {
454
523
  return `export const scripts = ${JSON.stringify(scripts)}\n`;
@@ -540,7 +609,8 @@ function toResolvedScript(config) {
540
609
  header: config.header,
541
610
  server: {
542
611
  open: config.server?.open ?? false,
543
- prefix: config.server?.prefix ?? "server:"
612
+ prefix: config.server?.prefix ?? "server:",
613
+ file: config.server?.file ?? false
544
614
  },
545
615
  cssInject: config.cssInject ?? "auto",
546
616
  align: config.align ?? 1,
@@ -594,9 +664,13 @@ function shimModule(code, id) {
594
664
  }
595
665
  //#endregion
596
666
  //#region src/serve/logger.ts
597
- function formatInstallLine(installUrl) {
667
+ function formatInstallLine(installUrl, label = "Userscript") {
598
668
  const coloredUrl = styleText("cyan", installUrl.replace(/:(\d+)\//, (_match, port) => `:${styleText("bold", port)}/`));
599
- return ` ${styleText("green", "➜")} ${styleText("bold", "Userscript")}: ${coloredUrl}`;
669
+ const padded = label.padEnd(10);
670
+ return ` ${styleText("green", "➜")} ${styleText("bold", padded)}: ${coloredUrl}`;
671
+ }
672
+ function formatRebuildLine(elapsedMs) {
673
+ return `${styleText("green", "Userscript rebuilt")} ${styleText("dim", `(${elapsedMs}ms)`)}`;
600
674
  }
601
675
  function formatFaqHint() {
602
676
  return `${` ${styleText("green", "➜")} ${styleText("bold", "FAQ")}: `}${styleText("cyan", FAQ_URL)}\n`;
@@ -660,8 +734,19 @@ import ${JSON.stringify(entryPath)};
660
734
  function matchDevUserscript(url, fileName) {
661
735
  return (url.split("?")[0] ?? "") === `/${fileName}.dev.user.js`;
662
736
  }
663
- function toInstallUrl(origin, fileName) {
664
- return `${origin.replace(/\/$/, "")}/${fileName}.dev.user.js`;
737
+ function matchProxyUserscript(url, fileName) {
738
+ return (url.split("?")[0] ?? "") === `/${toProxyFileName(fileName)}`;
739
+ }
740
+ function matchFileUserscript(url, fileName) {
741
+ return (url.split("?")[0] ?? "") === `/${fileName}.user.js`;
742
+ }
743
+ function toInstallUrl(origin, fileName, kind = "dev") {
744
+ const names = {
745
+ dev: `${fileName}.dev.user.js`,
746
+ proxy: toProxyFileName(fileName),
747
+ user: `${fileName}.user.js`
748
+ };
749
+ return `${origin.replace(/\/$/, "")}/${names[kind]}`;
665
750
  }
666
751
  function toServeEntryPath(root, entry) {
667
752
  const absolute = resolve(root, entry);
@@ -713,7 +798,13 @@ function generateDevUserscript(options) {
713
798
  })}`;
714
799
  }
715
800
  function findDevScript(url, scripts) {
716
- return scripts.find((script) => matchDevUserscript(url, script.fileName));
801
+ return scripts.find((script) => !script.server.file && matchDevUserscript(url, script.fileName));
802
+ }
803
+ function findProxyScript(url, scripts) {
804
+ return scripts.find((script) => script.server.file && matchProxyUserscript(url, script.fileName));
805
+ }
806
+ function findFileUserscript(url, scripts) {
807
+ return scripts.find((script) => script.server.file && matchFileUserscript(url, script.fileName));
717
808
  }
718
809
  function createDevUserscript(options) {
719
810
  return generateDevUserscript({
@@ -760,6 +851,22 @@ function configureDevServer(server, resolved, reactPreamble) {
760
851
  writeScript(res, createReactBootstrapModule(entry));
761
852
  return;
762
853
  }
854
+ const fileScript = findFileUserscript(url, resolved.scripts);
855
+ if (fileScript) {
856
+ const userJsPath = resolve(server.config.root, server.config.build.outDir, `${fileScript.fileName}.user.js`);
857
+ try {
858
+ writeScript(res, readFileSync(userJsPath, "utf8"));
859
+ } catch {
860
+ res.statusCode = 404;
861
+ res.end();
862
+ }
863
+ return;
864
+ }
865
+ const proxyScript = findProxyScript(url, resolved.scripts);
866
+ if (proxyScript) {
867
+ writeScript(res, `${generateWatchProxy(proxyScript, resolve(server.config.root, server.config.build.outDir, toRequireFileName(proxyScript.fileName)))}\n`);
868
+ return;
869
+ }
763
870
  const script = findDevScript(url, resolved.scripts);
764
871
  if (!script) {
765
872
  next();
@@ -779,7 +886,14 @@ function configureDevServer(server, resolved, reactPreamble) {
779
886
  let origins = [];
780
887
  if (urls) origins = urls.local.length ? urls.local : urls.network;
781
888
  const printInstall = () => {
782
- for (const origin of origins) for (const script of resolved.scripts) info(formatInstallLine(toInstallUrl(origin, script.fileName)));
889
+ for (const origin of origins) for (const script of resolved.scripts) {
890
+ if (script.server.file) {
891
+ info(formatInstallLine(toInstallUrl(origin, script.fileName, "user")));
892
+ info(formatInstallLine(toInstallUrl(origin, script.fileName, "proxy"), "Proxy"));
893
+ continue;
894
+ }
895
+ info(formatInstallLine(toInstallUrl(origin, script.fileName)));
896
+ }
783
897
  info(formatFaqHint());
784
898
  };
785
899
  const logger = createAfterLocalLogger(info, urls?.local.length ?? 0, printInstall);
@@ -797,7 +911,7 @@ function configureDevServer(server, resolved, reactPreamble) {
797
911
  if (!toOpen.length) return;
798
912
  queueMicrotask(() => {
799
913
  const origin = resolveServerOrigin(server.resolvedUrls);
800
- for (const script of toOpen) openLink(toInstallUrl(origin, script.fileName));
914
+ for (const script of toOpen) openLink(toInstallUrl(origin, script.fileName, script.server.file ? "user" : "dev"));
801
915
  });
802
916
  });
803
917
  }
@@ -813,6 +927,68 @@ function UserscriptPlugin(config) {
813
927
  let resolved = resolvePluginConfig(config);
814
928
  let reactPreamble = false;
815
929
  let command = "serve";
930
+ let isWatch = false;
931
+ let mode = "production";
932
+ let outDir = "";
933
+ let fileWatchStarted = false;
934
+ const shouldEmitProxy = () => {
935
+ return isWatch || mode === "development";
936
+ };
937
+ const startFileWatchBuild = async (server) => {
938
+ if (command === "build" || fileWatchStarted) return;
939
+ fileWatchStarted = true;
940
+ const outDirAbs = resolve(server.config.root, server.config.build.outDir);
941
+ let firstBuild = true;
942
+ const run = async () => {
943
+ const isRebuild = !firstBuild;
944
+ const started = Date.now();
945
+ await build({
946
+ configFile: server.config.configFile ?? false,
947
+ root: server.config.root,
948
+ mode: server.config.mode,
949
+ logLevel: "silent",
950
+ clearScreen: false,
951
+ plugins: server.config.configFile ? void 0 : [UserscriptPlugin(config)],
952
+ build: {
953
+ outDir: server.config.build.outDir,
954
+ emptyOutDir: firstBuild,
955
+ minify: server.config.build.minify,
956
+ sourcemap: server.config.build.sourcemap,
957
+ write: true,
958
+ reportCompressedSize: false
959
+ }
960
+ });
961
+ firstBuild = false;
962
+ if (isRebuild) server.config.logger.info(formatRebuildLine(Date.now() - started), { timestamp: true });
963
+ };
964
+ try {
965
+ await run();
966
+ } catch (error) {
967
+ fileWatchStarted = false;
968
+ server.config.logger.error(`[${PLUGIN_NAME}] Failed to start file-mode watch build`);
969
+ server.config.logger.error(String(error));
970
+ return;
971
+ }
972
+ let timer;
973
+ const onChange = (file) => {
974
+ if (file.startsWith(outDirAbs)) return;
975
+ clearTimeout(timer);
976
+ timer = setTimeout(() => {
977
+ run().catch((error) => {
978
+ server.config.logger.error(String(error));
979
+ });
980
+ }, 80);
981
+ };
982
+ server.watcher.on("change", onChange);
983
+ server.watcher.on("add", onChange);
984
+ const closeServer = server.close.bind(server);
985
+ server.close = async () => {
986
+ server.watcher.off("change", onChange);
987
+ server.watcher.off("add", onChange);
988
+ clearTimeout(timer);
989
+ return closeServer();
990
+ };
991
+ };
816
992
  return [
817
993
  {
818
994
  name: `${PLUGIN_NAME}:config`,
@@ -870,6 +1046,7 @@ function UserscriptPlugin(config) {
870
1046
  apply: "serve",
871
1047
  configureServer(server) {
872
1048
  configureDevServer(server, resolved, reactPreamble);
1049
+ if (resolved.scripts.some((script) => script.server.file)) startFileWatchBuild(server);
873
1050
  }
874
1051
  },
875
1052
  {
@@ -887,13 +1064,23 @@ function UserscriptPlugin(config) {
887
1064
  name: `${PLUGIN_NAME}:build`,
888
1065
  apply: "build",
889
1066
  enforce: "post",
1067
+ configResolved(viteConfig) {
1068
+ isWatch = Boolean(viteConfig.build.watch);
1069
+ mode = viteConfig.mode;
1070
+ outDir = resolve(viteConfig.root, viteConfig.build.outDir);
1071
+ },
890
1072
  generateBundle(_options, bundle) {
891
- applyUserscriptBundle(bundle, resolved, (fileName, source) => {
892
- this.emitFile({
893
- type: "asset",
894
- fileName,
895
- source
896
- });
1073
+ isWatch = this.meta.watchMode || isWatch;
1074
+ applyUserscriptBundle(bundle, resolved, {
1075
+ emitFile: (fileName, source) => {
1076
+ this.emitFile({
1077
+ type: "asset",
1078
+ fileName,
1079
+ source
1080
+ });
1081
+ },
1082
+ emitProxy: shouldEmitProxy(),
1083
+ outDir
897
1084
  });
898
1085
  }
899
1086
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-userscript-plugin",
3
3
  "type": "module",
4
- "version": "2.0.0",
4
+ "version": "2.1.1",
5
5
  "author": {
6
6
  "name": "Vitalij Ryndin",
7
7
  "url": "https://github.com/crashmax-dev"