/** * Vite config for the Chrome extension. * Builds the extension into dist/ for loading as an unpacked extension. * * Usage: * npm run dev — watch mode, rebuild on change * npm run build — production build */ import { defineConfig } from 'vite'; import { resolve } from 'path'; import sharp from 'sharp'; import { copyFileSync, mkdirSync, writeFileSync } from 'fs'; export default defineConfig({ root: 'src', plugins: [ { name: 'generate-icons', async generateBundle() { const outDir = resolve(__dirname, 'dist'); mkdirSync(resolve(outDir, 'icons'), { recursive: true }); const sizes = [16, 48, 128]; const svgPath = resolve(__dirname, 'src/icons/icon.svg'); const outDirs = [ resolve(outDir, 'icons'), resolve(__dirname, 'icons'), ]; for (const size of sizes) { const buffer = await sharp(svgPath) .resize(size, size) .png() .toBuffer(); for (const dir of outDirs) { mkdirSync(dir, { recursive: true }); writeFileSync(resolve(dir, `icon${size}.png`), buffer); } } }, }, { name: 'copy-manifest', generateBundle() { const manifestPath = resolve(__dirname, 'manifest.json'); const outPath = resolve(__dirname, 'dist/manifest.json'); copyFileSync(manifestPath, outPath); }, }, ], build: { target: 'chrome110', outDir: '../dist', emptyOutdir: true, minify: false, rollupOptions: { input: { background: resolve(__dirname, 'src/background/background.js'), content: resolve(__dirname, 'src/content/content.js'), viewer: resolve(__dirname, 'src/viewer/viewer.html'), viewerIndex: resolve(__dirname, 'src/viewer/index.html'), interceptors: resolve(__dirname, 'src/inject/interceptors.js'), // NOTE: hlds is NOT built by Vite — copied from source as pure ES5 to avoid // esbuild injecting arrow functions (Chrome flags these as "ES module content" // in extension URLs, preventing window.Hls registration). }, output: { entryFileNames: '[name].js', chunkFileNames: 'chunks/[name].js', assetFileNames: '[name][extname]', }, }, modulePreload: { polyfill: false, }, }, });