12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import { readFile } from "fs/promises";
- import { join, basename, dirname } from "path";
- import { LibraryFormats, Plugin, ResolvedConfig } from "vite";
- export interface UserScriptOptions {
- entry: string;
- format: LibraryFormats;
- name?: string;
- port?: number;
- cdn?: string;
- }
- export function UserScriptPlugin(options: UserScriptOptions): Plugin {
- let config: ResolvedConfig;
- return {
- name: "userscript",
- config() {
- const name = options.name ?? basename(dirname(options.entry));
- return {
- build: {
- lib: {
- name: name,
- formats: [options.format],
- entry: {
- [name]: options.entry
- }
- },
- rollupOptions: {
- output: {
- entryFileNames: "[name].user.js"
- }
- }
- }
- };
- },
- configResolved(resolvedConfig) {
- config = resolvedConfig;
- },
- async generateBundle(outputOptions, bundle) {
- for (const chunk of Object.values(bundle)) {
- if (chunk.type !== "chunk") continue;
- if (!chunk.isEntry) continue;
- if (!chunk.facadeModuleId) continue;
- const code = await readFile(chunk.facadeModuleId, { encoding: "utf8" });
- let header = "";
- for (const line of code.split("\n")) {
- if (!line.startsWith("//")) break;
- header += line + "\n";
- }
- let url = "";
- if (config.mode === "production") {
- if (options.cdn) url = `${options.cdn}${chunk.name}.user.js`;
- } else {
- if (options.port) url = `http://localhost:${join(options.port.toString(), config.build.outDir, chunk.name).replaceAll("\\", "/")}.user.js`;
- }
- if (url) {
- header = header.replaceAll(
- `// ==/UserScript==`,
- `// @downloadURL ${url}\n` +
- `// @updateURL ${url}\n` +
- `// ==/UserScript==`
- );
- }
- chunk.code = header + "\n" + chunk.code;
- }
- }
- };
- }
|