blob: 23acac6fbeeef98ce1d07f101b7060e438167dcb [file] [log] [blame]
import { defineConfig, type Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import fs from 'fs'
import fse from 'fs-extra'
const SUPPORTED_LANGUAGES: string[] = ['en', 'zh'];
const OUTPUT_DIR: string = 'app';
// Custom plugin to handle HTML output for different languages
function createHtmlOutputPlugin(): Plugin {
return {
name: 'html-output-plugin',
enforce: 'post',
apply: 'build',
closeBundle: async () => {
const distDir = path.resolve(__dirname, 'dist');
const publicDir = path.resolve(__dirname, 'public');
// Create language directories if they don't exist
for (const lang of SUPPORTED_LANGUAGES) {
const langDir = path.join(OUTPUT_DIR, lang);
const assetDir = path.join(langDir, 'theme-builder');
const themesDir = path.join(assetDir, 'themes');
// Ensure directories exist and clean any existing assets
await fse.ensureDir(langDir);
await fse.ensureDir(assetDir);
// Clean up existing JS and CSS files before copying new ones
const existingFiles = await fse.readdir(assetDir);
for (const file of existingFiles) {
if (file.endsWith('.js') || file.endsWith('.css')) {
await fse.remove(path.join(assetDir, file));
}
}
await fse.ensureDir(themesDir);
// Find JS and CSS files in the dist directory
const files = await fse.readdir(distDir);
const jsFiles = files.filter(file => file.endsWith('.js'));
const cssFiles = files.filter(file => file.endsWith('.css'));
// Read the HTML file to extract scripts and links to include in body.html
if (fs.existsSync(path.join(distDir, 'index.html'))) {
const htmlContent = await fse.readFile(path.join(distDir, 'index.html'), 'utf-8');
// Extract only the content within the body tag
let bodyContent = htmlContent.match(/<body[^>]*>([\s\S]*)<\/body>/i)?.[1] || '';
// Get all script and link tags from head
const headScripts = (htmlContent.match(/<script[^>]*src="\.\/([^"]+)"[^>]*><\/script>/g) || [])
.map(script => script.replace(/src="\.\//g, 'src="theme-builder/'));
const headLinks = (htmlContent.match(/<link[^>]*href="\.\/([^"]+)"[^>]*>/g) || [])
.map(link => link.replace(/href="\.\//g, 'href="theme-builder/'));
// Create a complete body.html with necessary script and link tags
let finalContent = [...headLinks, ...headScripts, bodyContent.trim()].join('\n');
// Replace any references to themes in the content
finalContent = finalContent.replace(/(['"])\.?\/themes\//g, '$1./theme-builder/themes/');
// Write the content to body.html
await fse.writeFile(path.join(langDir, 'body.html'), finalContent);
}
// Copy JS and CSS files to the theme-builder directory
for (const jsFile of jsFiles) {
await fse.copy(
path.join(distDir, jsFile),
path.join(assetDir, jsFile)
);
}
for (const cssFile of cssFiles) {
await fse.copy(
path.join(distDir, cssFile),
path.join(assetDir, cssFile)
);
}
// Copy themes from public directory
if (fs.existsSync(path.join(publicDir, 'themes'))) {
await fse.copy(
path.join(publicDir, 'themes'),
themesDir
);
}
}
// Clean up the original dist directory
await fse.remove(distDir);
}
};
}
// Custom plugin to rewrite theme paths in JS files
function createThemePathRewritePlugin(): Plugin {
return {
name: 'theme-path-rewrite',
transform(code, id) {
if (id.endsWith('.js') || id.endsWith('.ts')) {
// Replace theme path references
return code.replace(/(['"`])\.?\/themes\//g, '$1./theme-builder/themes/');
}
return code;
}
};
}
export default defineConfig({
plugins: [
vue({
template: {
transformAssetUrls: {
base: '/src',
includeAbsolute: false,
},
}
}),
createThemePathRewritePlugin(),
createHtmlOutputPlugin()
],
build: {
outDir: 'dist', // Temporary build directory
emptyOutDir: true,
assetsDir: '.', // This will ensure assets are placed at the root level of the output directory
rollupOptions: {
output: {
// Customize output file names
entryFileNames: '[name]-[hash].js',
chunkFileNames: '[name]-[hash].js',
assetFileNames: '[name]-[hash].[ext]'
}
}
},
base: './', // Make sure assets use relative paths
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}
});