@moontra/moonui-cli
Version:
CLI tool for MoonUI component library
138 lines (114 loc) • 3.75 kB
text/typescript
import fs from 'fs';
import path from 'path';
import type { Plugin } from 'vite';
import { generateThemeCSS } from '../utils/theme-generator';
export interface MoonUIThemePluginOptions {
/**
* Project root directory path
* @default process.cwd()
*/
projectRoot?: string;
/**
* Whether to log verbose output
* @default true
*/
verbose?: boolean;
/**
* CSS file ID to inject theme into
* @default 'virtual:moonui-theme.css'
*/
virtualId?: string;
}
/**
* Vite plugin for MoonUI theme injection
* Automatically generates and injects theme CSS based on moonui.config.js
*/
export function moonuiThemePlugin(options: MoonUIThemePluginOptions = {}): Plugin {
const virtualId = options.virtualId || 'virtual:moonui-theme.css';
const resolvedVirtualId = '\0' + virtualId;
const projectRoot = options.projectRoot || process.cwd();
const configPath = path.join(projectRoot, 'moonui.config.js');
let themeCSS: string | null = null;
function generateTheme(): string {
try {
// Check if config exists
if (!fs.existsSync(configPath)) {
console.warn('[MoonUI Vite] moonui.config.js not found. Using default theme.');
return generateThemeCSS({});
}
// Clear module cache to get fresh config
delete require.cache[configPath];
// Load the config
const config = require(configPath);
// Check if automatic CSS generation is enabled
if (config.build?.generateThemeCSS === false) {
return '';
}
// Generate theme CSS (now scoped to .moonui-theme class)
const css = generateThemeCSS(config.theme || {});
// Log success
if (options.verbose !== false) {
console.log('[MoonUI Vite] Theme CSS generated successfully (scoped to .moonui-theme)');
}
return css;
} catch (error) {
console.error('[MoonUI Vite] Error generating theme CSS:', error);
return '';
}
}
return {
name: 'moonui-theme',
// Handle virtual module
resolveId(id: string) {
if (id === virtualId) {
return resolvedVirtualId;
}
return null;
},
// Load virtual module content
load(id: string) {
if (id === resolvedVirtualId) {
if (!themeCSS) {
themeCSS = generateTheme();
}
return themeCSS;
}
return null;
},
// Handle HMR
handleHotUpdate({ file, server }: { file: string; server: any }) {
if (file === configPath) {
// Regenerate theme CSS
themeCSS = generateTheme();
// Trigger HMR for the virtual module
const module = server.moduleGraph.getModuleById(resolvedVirtualId);
if (module) {
server.reloadModule(module);
}
if (options.verbose !== false) {
console.log('[MoonUI Vite] Theme updated due to config change');
}
}
},
// Transform CSS imports to include virtual module
transform(code: string, id: string) {
// Only process CSS files
if (!id.endsWith('.css')) return null;
// Check if this is a main CSS file (e.g., index.css, app.css, global.css)
const isMainCSS = /\/(index|app|global|main|styles)\.css$/.test(id);
if (!isMainCSS) return null;
// Check if the virtual module is already imported
if (code.includes(virtualId)) return null;
// Add import at the beginning
const importStatement = `@import '${virtualId}';\n\n`;
return {
code: importStatement + code,
map: null
};
}
};
}
/**
* Default export for easier importing
*/
export default moonuiThemePlugin;