UNPKG

beathers

Version:

Beather is a lightweight SCSS library that serves as a comprehensive design system for your projects. It offers a structured and consistent approach to manage colors, fonts, and other design related variables, making it easier to maintain a cohesive visua

155 lines (154 loc) 6.14 kB
/* eslint-disable no-console */ import { exec } from 'child_process'; import fs from 'fs-extra'; import { fileURLToPath } from 'node:url'; import path from 'path'; import { promisify } from 'util'; import { promptInput } from '../commands/index.js'; import { BuildScssVariables, DeepMerge, LoadUserConfigs, ReadDefaultValues } from '../helpers/index.js'; const execAsync = promisify(exec); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const projectRoot = path.resolve(__dirname, '../..'); // Detect if running as installed package vs development const isInstalledPackage = projectRoot.includes('node_modules'); let packageRoot; let variablesPath; if (isInstalledPackage) { const userProjectRoot = process.cwd(); packageRoot = path.join(userProjectRoot, 'node_modules', 'beathers'); variablesPath = path.join(packageRoot, 'scss', '_variables.scss'); } else { packageRoot = projectRoot; // Write variables to src location for development builds variablesPath = path.join(projectRoot, 'scss', '_variables.scss'); } async function defaultTheme() { let values = null; try { values = await ReadDefaultValues([path.join(projectRoot, 'scss', 'settings', '_index.scss')], [ 'useMediaQueries', 'useFontFamilies', 'useFontFamiliesMediaQueries', 'useFontSizes', 'useFontSizesMediaQueries', 'useFontShapes', 'useFontShapesMediaQueries', 'useTextAligns', 'useTextAlignsMediaQueries', 'useTextTruncate', 'useTextTruncateMediaQueries', 'useColors', 'useColorsOpacities', 'useColorsLightMode', 'useColorsDarkMode', 'useCurrentColors', 'useRootColors', 'useGrid', 'useFlex', 'useGridMediaQueries', 'useWrappers', 'useShadows', 'useShadowsMediaQueries', 'useDisplays', 'useDisplaysMediaQueries', 'useOverflows', 'useOverflowsMediaQueries', 'useOpacities', 'useOpacitiesMediaQueries', 'useBlur', 'useBlurMediaQueries', 'useObjectFits', 'useObjectFitsMediaQueries', 'usePositions', 'usePositionsMediaQueries', 'useInsets', 'useInsetsMediaQueries', 'useSizes', 'useSizesMediaQueries', 'useGutters', 'useGuttersMediaQueries', 'useBorders', 'useBordersMediaQueries', 'useTextBorders', 'useTextBordersMediaQueries', 'useRadius', 'useRadiusMediaQueries', 'useGlass', ]); } catch (error) { console.error('❌ Failed to read default theme configuration:', error instanceof Error ? error.message : error); process.exit(1); } return values; } async function BuildTheme(customOutputPath) { try { console.log('📦 Loading theme configuration...'); const defaults = await defaultTheme(); const userConfigs = await LoadUserConfigs(); console.log('🔄 Building theme variables...'); const theme = DeepMerge(defaults, userConfigs); const variablesString = BuildScssVariables(theme, true); await fs.writeFile(variablesPath, variablesString, { flag: 'w' }); console.log(`✅ Theme variables generated`); console.log(''); console.log('🔨 Compiling SCSS to CSS...'); const userProjectRoot = process.cwd(); const scssSourcePath = path.join(packageRoot, 'scss'); const outputPath = path.join(userProjectRoot, customOutputPath); console.log(`📁 Output directory: \x1b[36m${outputPath}\x1b[0m`); await fs.ensureDir(outputPath); const buildCommand = `sass --style compressed --source-map --embed-sources --no-error-css "${scssSourcePath}":"${outputPath}"`; const { stdout } = await execAsync(buildCommand); console.log('✅ Theme compilation completed successfully!'); if (stdout) console.log('📋 Build details:', stdout.trim()); } catch (error) { console.error('❌ Failed to build theme:', error); throw error; } } export async function Build() { try { console.log('🎨 Building \x1b[36mBeathers\x1b[0m theme...'); const defaultOutputPath = 'public/css'; let outputPath = defaultOutputPath; try { // Try to load user config to get outputPath const userConfigs = await LoadUserConfigs(); if (userConfigs?.outputPath) { outputPath = userConfigs.outputPath; console.log(`📁 Using output path from config: \x1b[36m${outputPath}\x1b[0m`); } else { // No config file or no outputPath in config, ask user console.log('🏠 Where would you like to save the compiled CSS files?'); console.log(`💡 Default: \x1b[36m${defaultOutputPath}\x1b[0m (press Enter to use default)`); const customOutputPath = await promptInput('📁 Output path: '); outputPath = customOutputPath.trim() || defaultOutputPath; } } catch { // No config file exists, ask user console.log('🏠 Where would you like to save the compiled CSS files?'); console.log(`💡 Default: \x1b[36m${defaultOutputPath}\x1b[0m (press Enter to use default)`); const customOutputPath = await promptInput('📁 Output path: '); outputPath = customOutputPath.trim() || defaultOutputPath; } await BuildTheme(outputPath); } catch (error) { console.error('❌ Failed to build theme:', error); process.exit(1); } } if (import.meta.url === `file://${process.argv[1]}`) { Build().catch((error) => { console.error('❌ Build failed:', error); process.exit(1); }); }