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 katalogu components if (existsSync('./components')) { copyDir('./components', join(DIST_DIR, 'components')); console.log(' ✓ Skopiowano components/'); } // Kopiowanie katalogu assets if (existsSync('./assets')) { copyDir('./assets', join(DIST_DIR, 'assets')); console.log(' ✓ Skopiowano assets/'); } // Kopiowanie wymaganych bibliotek z node_modules (potrzebne dla plików HTML z UMD React) const nodeModulesDest = join(DIST_DIR, 'node_modules'); // React const reactUmdSrc = './node_modules/react/umd'; const reactUmdDest = join(nodeModulesDest, 'react/umd'); if (existsSync(reactUmdSrc)) { copyDir(reactUmdSrc, reactUmdDest); console.log(' ✓ Skopiowano node_modules/react/umd/'); } // React-DOM const reactDomUmdSrc = './node_modules/react-dom/umd'; const reactDomUmdDest = join(nodeModulesDest, 'react-dom/umd'); if (existsSync(reactDomUmdSrc)) { copyDir(reactDomUmdSrc, reactDomUmdDest); console.log(' ✓ Skopiowano node_modules/react-dom/umd/'); } // Survey-React const surveyReactSrc = './node_modules/survey-react'; const surveyReactDest = join(nodeModulesDest, 'survey-react'); if (existsSync(surveyReactSrc)) { // Kopiowanie tylko niezbędnych plików mkdirSync(surveyReactDest, { recursive: true }); const surveyFiles = ['survey.react.min.js', 'survey.react.min.css']; surveyFiles.forEach(file => { const src = join(surveyReactSrc, file); if (existsSync(src)) { copyFileSync(src, join(surveyReactDest, file)); } }); console.log(' ✓ Skopiowano node_modules/survey-react/'); } 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));