import esbuild from 'esbuild'; import scss from 'esbuild-plugin-sass'; import { copyFileSync, mkdirSync, readdirSync, existsSync } from 'fs'; import { join, dirname } from 'path'; // Określenie platformy docelowej: firefox (domyślnie) lub chrome const TARGET = process.env.TARGET || 'firefox'; const IS_FIREFOX = TARGET === 'firefox'; const IS_CHROME = TARGET === 'chrome'; // Katalogi wyjściowe const DIST_DIR = IS_FIREFOX ? './dist-firefox' : './dist-chrome'; const LIB_DIR = join(DIST_DIR, 'lib'); console.log(`🎯 Budowanie dla: ${TARGET.toUpperCase()}`); console.log(`📁 Katalog wyjściowy: ${DIST_DIR}`); const watch = process.argv.includes('--watch') && { onRebuild(error) { if (error) console.error('[watch] budowanie nie powiodło się', error); else console.log('[watch] budowanie zakończone'); }, }; // Funkcja pomocnicza: rekurencyjne kopiowanie katalogów function copyDir(src, dest) { if (!existsSync(dest)) { mkdirSync(dest, { recursive: true }); } const entries = readdirSync(src, { withFileTypes: true }); for (const entry of entries) { const srcPath = join(src, entry.name); const destPath = join(dest, entry.name); if (entry.isDirectory()) { copyDir(srcPath, destPath); } else { copyFileSync(srcPath, destPath); } } } // Plugin: kopiowanie plików statycznych po zakończeniu budowania const copyStaticFiles = { name: 'copy-static-files', setup(build) { build.onEnd(() => { console.log('📋 Kopiowanie plików statycznych...'); // Kopiowanie manifestu (wybór na podstawie platformy docelowej) const manifestSrc = IS_FIREFOX ? './manifest.json' : './manifest-chrome.json'; const manifestDest = join(DIST_DIR, 'manifest.json'); mkdirSync(dirname(manifestDest), { recursive: true }); copyFileSync(manifestSrc, manifestDest); console.log(` ✓ Skopiowano ${manifestSrc} → ${manifestDest}`); // Kopiowanie katalogów statycznych for (const dir of ['components', 'assets']) { if (existsSync(`./${dir}`)) { copyDir(`./${dir}`, join(DIST_DIR, dir)); console.log(` ✓ Skopiowano ${dir}/`); } } // Kopiowanie wymaganych bibliotek z node_modules (potrzebne dla plików HTML z UMD React) const nodeModulesDest = join(DIST_DIR, 'node_modules'); const nodeDeps = [ { src: 'react/umd', dest: 'react/umd' }, { src: 'react-dom/umd', dest: 'react-dom/umd' }, { src: 'survey-react', dest: 'survey-react', files: ['survey.react.min.js', 'survey.react.min.css'] }, ]; for (const dep of nodeDeps) { const srcPath = `./node_modules/${dep.src}`; const destPath = join(nodeModulesDest, dep.dest); if (existsSync(srcPath)) { if (dep.files) { mkdirSync(destPath, { recursive: true }); dep.files.forEach(file => { const fileSrc = join(srcPath, file); if (existsSync(fileSrc)) copyFileSync(fileSrc, join(destPath, file)); }); } else { copyDir(srcPath, destPath); } console.log(` ✓ Skopiowano node_modules/${dep.src}/`); } } console.log(`✅ Budowanie dla ${TARGET.toUpperCase()} zakończone!`); }); }, }; // Zobacz: https://github.com/evanw/esbuild/issues/806#issuecomment-779138268 // Plugin pomijający importy React (używamy globalnych obiektów z UMD) let skipReactImports = { name: 'skipReactImports', setup(build) { build.onResolve({ filter: /^(react(-dom)?|survey-react)$/ }, (args) => { return { path: args.path, namespace: `globalExternal_${args.path}`, }; }); build.onLoad({ filter: /.*/, namespace: 'globalExternal_react' }, () => { return { contents: `module.exports = globalThis.React`, loader: 'js', }; }); build.onLoad({ filter: /.*/, namespace: 'globalExternal_react-dom' }, () => { return { contents: `module.exports = globalThis.ReactDOM`, loader: 'js', }; }); build.onLoad({ filter: /.*/, namespace: 'globalExternal_survey-react' }, () => { return { contents: `module.exports = globalThis.Survey`, loader: 'js', }; }); }, }; esbuild .build({ entryPoints: [ // JavaScript/TypeScript 'components/toolbar/toolbar.tsx', 'components/sidebar/sidebar.tsx', 'components/report-window/report-window.tsx', 'background.ts', 'diag.tsx', // Globalne style 'styles/global.scss', 'styles/fonts.scss', // Style komponentów (kompilowane osobno) 'components/toolbar/toolbar.scss', // 'components/sidebar/sidebar.scss', // 'components/report-window/report-window.scss', ], bundle: true, // minify: true, outdir: LIB_DIR, loader: { '.woff': 'file', '.woff2': 'file' }, plugins: [scss(), skipReactImports, copyStaticFiles], define: { PLUGIN_NAME: '"Rentgen"', PLUGIN_URL: '"https://addons.mozilla.org/pl/firefox/addon/rentgen/"', 'process.env.TARGET': JSON.stringify(TARGET), }, external: ['react', 'react-dom', 'survey-react'], watch, }) .then(() => console.log(`\n🎉 Dodatek dla ${TARGET.toUpperCase()} zbudowany pomyślnie!\n`)) .catch(() => process.exit(1));