- Cleaned up import statements in options.ts for better organization. - Enhanced the init function to load settings with improved formatting. - Streamlined event listener attachments for buttons and inputs. - Improved the rendering functions for color and semantic grids. - Updated the parsePalette function in themeEngine.ts for better error handling and readability. - Refactored deriveSemanticTheme to enhance clarity and maintainability. - Adjusted tsconfig.json for better structure and readability. - Updated vite.config.ts to improve build process and maintain consistency.
109 lines
4.1 KiB
TypeScript
109 lines
4.1 KiB
TypeScript
import { defineConfig, build as viteBuild, type UserConfig } from 'vite';
|
|
import { resolve } from 'path';
|
|
import { readFileSync, writeFileSync, mkdirSync, cpSync, existsSync, rmSync } from 'fs';
|
|
|
|
/**
|
|
* Vite build config for the Gogh Theme Engine Chrome Extension.
|
|
*
|
|
* Chrome MV3 content scripts CANNOT use ES module imports.
|
|
* Service workers CAN if the manifest specifies "type": "module".
|
|
*
|
|
* Strategy:
|
|
* • content.ts → IIFE bundle (no imports, self-contained)
|
|
* • background.ts → ESM (manifest has "type": "module")
|
|
* • options/ → Standard Vite HTML entry
|
|
*
|
|
* We solve the code-splitting problem by using a custom plugin that
|
|
* rebuilds content.ts as a separate IIFE after the main build.
|
|
*/
|
|
|
|
function chromeExtensionPlugin() {
|
|
return {
|
|
name: 'chrome-extension-iife',
|
|
async closeBundle() {
|
|
// Rebuild content.ts as a standalone IIFE bundle
|
|
console.log('[chrome-ext] Rebuilding content.js as IIFE...');
|
|
await viteBuild({
|
|
configFile: false,
|
|
build: {
|
|
outDir: resolve(__dirname, 'dist'),
|
|
emptyOutDir: false, // Don't wipe the rest of the build
|
|
lib: {
|
|
entry: resolve(__dirname, 'src/content.ts'),
|
|
name: 'GoghContent',
|
|
formats: ['iife'],
|
|
fileName: () => 'content.js',
|
|
},
|
|
rollupOptions: {
|
|
output: {
|
|
// Ensure it overwrites the ESM version
|
|
inlineDynamicImports: true,
|
|
},
|
|
},
|
|
minify: false,
|
|
sourcemap: false,
|
|
target: 'chrome120',
|
|
},
|
|
logLevel: 'warn',
|
|
});
|
|
|
|
// Fix options HTML path
|
|
const wrongPath = resolve(__dirname, 'dist/src/options/options.html');
|
|
const correctDir = resolve(__dirname, 'dist/options');
|
|
const correctPath = resolve(correctDir, 'options.html');
|
|
|
|
if (existsSync(wrongPath) && !existsSync(correctPath)) {
|
|
mkdirSync(correctDir, { recursive: true });
|
|
const html = readFileSync(wrongPath, 'utf-8');
|
|
// Fix script paths — point to the options.js at dist root
|
|
const fixedHtml = html
|
|
.replace(/src="[^"]*options\.js"/g, 'src="../options.js"')
|
|
.replace(/src="\.\.\/\.\.\/options\.js"/g, 'src="../options.js"');
|
|
writeFileSync(correctPath, fixedHtml);
|
|
}
|
|
|
|
// Clean up the misplaced src/ directory in dist
|
|
const distSrc = resolve(__dirname, 'dist/src');
|
|
if (existsSync(distSrc)) {
|
|
rmSync(distSrc, { recursive: true, force: true });
|
|
}
|
|
|
|
// Clean up the chunks directory since content.js is now self-contained
|
|
// and background.js still needs its chunk import
|
|
console.log('[chrome-ext] Build complete.');
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
const isProd = mode === 'production';
|
|
|
|
return {
|
|
plugins: [chromeExtensionPlugin()],
|
|
build: {
|
|
outDir: 'dist',
|
|
emptyOutDir: true,
|
|
rollupOptions: {
|
|
input: {
|
|
background: resolve(__dirname, 'src/background.ts'),
|
|
content: resolve(__dirname, 'src/content.ts'),
|
|
options: resolve(__dirname, 'src/options/options.html'),
|
|
},
|
|
output: {
|
|
entryFileNames: '[name].js',
|
|
chunkFileNames: 'chunks/[name].js',
|
|
assetFileNames: 'assets/[name].[ext]',
|
|
},
|
|
},
|
|
minify: isProd ? 'esbuild' : false,
|
|
sourcemap: !isProd ? 'inline' : false,
|
|
target: 'chrome120',
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
'@': resolve(__dirname, 'src'),
|
|
},
|
|
},
|
|
};
|
|
});
|