import { defineConfig, type PluginOption } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' import fs from 'fs' // Copy translation catalogs (l10n/*.json, except the extractor-only // en.manual.json) into static/l10n/ so the core shell can fetch them at // /modules/{handle}/static/l10n/{locale}.json const copyL10nCatalogs = (): PluginOption => ({ name: 'copy-l10n-catalogs', apply: 'build', closeBundle() { const sourceDir = path.resolve(__dirname, 'l10n') const outDir = path.resolve(__dirname, 'static/l10n') if (!fs.existsSync(sourceDir)) return fs.mkdirSync(outDir, { recursive: true }) for (const file of fs.readdirSync(sourceDir)) { if (file.endsWith('.json') && !file.endsWith('.manual.json')) { fs.copyFileSync(path.join(sourceDir, file), path.join(outDir, file)) } } }, }) // Rewrite the __CSS_FILENAME_PLACEHOLDER__ export in main.ts with the actual // hashed stylesheet name, so the core loader can inject it const injectCssFilename = (): PluginOption => ({ name: 'inject-css-filename', enforce: 'post', generateBundle(_options, bundle) { const cssFile = Object.keys(bundle).find(name => name.endsWith('.css')) if (!cssFile) return for (const fileName of Object.keys(bundle)) { const chunk = bundle[fileName] if (chunk.type === 'chunk' && chunk.code.includes('__CSS_FILENAME_PLACEHOLDER__')) { chunk.code = chunk.code.replace(/__CSS_FILENAME_PLACEHOLDER__/g, `static/${cssFile}`) } } }, }) // https://vite.dev/config/ export default defineConfig({ plugins: [vue(), injectCssFilename(), copyL10nCatalogs()], resolve: { alias: { '@': path.resolve(__dirname, './src'), '@KTXC': path.resolve(__dirname, '../../core/src') }, }, build: { outDir: 'static', sourcemap: true, lib: { entry: path.resolve(__dirname, 'src/main.ts'), formats: ['es'], fileName: () => 'module.mjs', }, rollupOptions: { external: ['vue', 'vue-router', 'pinia', '@KTXC'], output: { paths: (id) => (id === '@KTXC' ? '/js/ktxc.mjs' : id), }, }, }, })