UNPKG

@ordojs/cli

Version:

Command-line interface for OrdoJS framework

383 lines • 17.1 kB
/** * @fileoverview CSS Framework Integration Command for OrdoJS CLI * Handles integration of CSS frameworks like Tailwind CSS */ import { Command } from 'commander'; import { promises as fs } from 'fs'; import path from 'path'; import { OrdoJSCSSFrameworkIntegration } from '../../core/src/compiler/css-framework-integration.js'; import { CLIError, ErrorType } from '../utils/error.js'; import { logger } from '../utils/logger.js'; /** * Register CSS framework integration command */ export function registerCSSFrameworkCommand(program) { const cssFrameworkCommand = program .command('css-framework') .description('Integrate CSS frameworks with OrdoJS') .option('-f, --framework <framework>', 'CSS framework to integrate (tailwind, bootstrap, bulma, foundation, custom)', 'tailwind') .option('-o, --output <dir>', 'Output directory for generated files', './') .option('--no-purge', 'Disable CSS purging (keep all unused classes)') .option('--content <paths>', 'Content paths for purging (comma-separated)', './src/**/*.ordo') .option('--custom-css <path>', 'Custom CSS file path (for custom framework)') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .option('--postcss-plugins <plugins>', 'Additional PostCSS plugins (comma-separated)') .action(async (options) => { await cssFrameworkCommand(options); }); // Add subcommands for specific frameworks cssFrameworkCommand .command('tailwind') .description('Integrate Tailwind CSS') .option('-o, --output <dir>', 'Output directory', './') .option('--no-purge', 'Disable CSS purging') .option('--content <paths>', 'Content paths for purging', './src/**/*.ordo') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .action(async (options) => { await integrateTailwind(options); }); cssFrameworkCommand .command('bootstrap') .description('Integrate Bootstrap CSS') .option('-o, --output <dir>', 'Output directory', './') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .action(async (options) => { await integrateBootstrap(options); }); cssFrameworkCommand .command('bulma') .description('Integrate Bulma CSS') .option('-o, --output <dir>', 'Output directory', './') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .action(async (options) => { await integrateBulma(options); }); cssFrameworkCommand .command('foundation') .description('Integrate Foundation CSS') .option('-o, --output <dir>', 'Output directory', './') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .action(async (options) => { await integrateFoundation(options); }); cssFrameworkCommand .command('custom') .description('Integrate custom CSS framework') .requiredOption('-c, --css-file <path>', 'Path to custom CSS file') .option('-o, --output <dir>', 'Output directory', './') .option('--no-minify', 'Disable CSS minification') .option('--source-maps', 'Generate source maps') .action(async (options) => { await integrateCustom(options); }); } /** * Main CSS framework integration command */ async function cssFrameworkCommand(options) { logger.info(`Integrating ${options.framework} CSS framework...`); try { // Validate framework const validFrameworks = ['tailwind', 'bootstrap', 'bulma', 'foundation', 'custom']; if (!validFrameworks.includes(options.framework)) { throw new CLIError(`Invalid CSS framework: ${options.framework}`, ErrorType.VALIDATION, 'CSS-001', [`Valid frameworks: ${validFrameworks.join(', ')}`]); } // Parse content paths const contentPaths = options.content.split(',').map(p => p.trim()); // Parse PostCSS plugins const postcssPlugins = options.postcssPlugins?.split(',').map(p => p.trim()) || []; // Create integration options const integrationOptions = { framework: options.framework, includeFrameworkCSS: true, customCSSPath: options.customCss, purgeUnused: options.purge, contentPaths, generateSourceMaps: options.sourceMaps, minify: options.minify, postcss: { plugins: postcssPlugins, options: {} } }; // Initialize CSS framework integration const integration = new OrdoJSCSSFrameworkIntegration(integrationOptions); // Integrate the framework const result = await integration.integrate(); if (!result.success) { throw new CLIError(`CSS framework integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-002'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); // Generate configuration files const configFiles = await integration.generateConfigFiles(options.output); // Generate package.json dependencies const dependencies = integration.generateDependencies(); // Display results logger.success(`āœ… ${options.framework} CSS framework integrated successfully!`); logger.info(`šŸ“ CSS file: ${cssPath}`); if (configFiles.length > 0) { logger.info('šŸ“ Configuration files:'); configFiles.forEach(file => logger.info(` - ${file}`)); } if (Object.keys(dependencies).length > 0) { logger.info('šŸ“¦ Required dependencies:'); Object.entries(dependencies).forEach(([pkg, version]) => { logger.info(` - ${pkg}: ${version}`); }); } // Display usage instructions displayUsageInstructions(options.framework, cssPath); } catch (error) { if (error instanceof CLIError) { logger.error(`${error.type.toUpperCase()} ERROR: ${error.message}`); if (error.code) { logger.error(`Error code: ${error.code}`); } if (error.suggestions && error.suggestions.length > 0) { logger.info('Suggestions:'); error.suggestions.forEach(suggestion => { logger.info(` - ${suggestion}`); }); } } else { logger.error(`CSS framework integration failed: ${error instanceof Error ? error.message : String(error)}`); } process.exit(1); } } /** * Integrate Tailwind CSS */ async function integrateTailwind(options) { logger.info('Integrating Tailwind CSS...'); const contentPaths = options.content.split(',').map(p => p.trim()); const integration = new OrdoJSCSSFrameworkIntegration({ framework: 'tailwind', purgeUnused: options.purge, contentPaths, minify: options.minify, generateSourceMaps: options.sourceMaps }); const result = await integration.integrate(); if (!result.success) { throw new CLIError(`Tailwind CSS integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-003'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); // Generate configuration files const configFiles = await integration.generateConfigFiles(options.output); // Generate dependencies const dependencies = integration.generateDependencies(); logger.success('āœ… Tailwind CSS integrated successfully!'); logger.info(`šŸ“ CSS file: ${cssPath}`); logger.info('šŸ“ Configuration files:'); configFiles.forEach(file => logger.info(` - ${file}`)); logger.info('šŸ“¦ Required dependencies:'); Object.entries(dependencies).forEach(([pkg, version]) => { logger.info(` - ${pkg}: ${version}`); }); displayUsageInstructions('tailwind', cssPath); } /** * Integrate Bootstrap CSS */ async function integrateBootstrap(options) { logger.info('Integrating Bootstrap CSS...'); const integration = new OrdoJSCSSFrameworkIntegration({ framework: 'bootstrap', minify: options.minify, generateSourceMaps: options.sourceMaps }); const result = await integration.integrate(); if (!result.success) { throw new CLIError(`Bootstrap CSS integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-004'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); // Generate dependencies const dependencies = integration.generateDependencies(); logger.success('āœ… Bootstrap CSS integrated successfully!'); logger.info(`šŸ“ CSS file: ${cssPath}`); logger.info('šŸ“¦ Required dependencies:'); Object.entries(dependencies).forEach(([pkg, version]) => { logger.info(` - ${pkg}: ${version}`); }); displayUsageInstructions('bootstrap', cssPath); } /** * Integrate Bulma CSS */ async function integrateBulma(options) { logger.info('Integrating Bulma CSS...'); const integration = new OrdoJSCSSFrameworkIntegration({ framework: 'bulma', minify: options.minify, generateSourceMaps: options.sourceMaps }); const result = await integration.integrate(); if (!result.success) { throw new CLIError(`Bulma CSS integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-005'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); // Generate dependencies const dependencies = integration.generateDependencies(); logger.success('āœ… Bulma CSS integrated successfully!'); logger.info(`šŸ“ CSS file: ${cssPath}`); logger.info('šŸ“¦ Required dependencies:'); Object.entries(dependencies).forEach(([pkg, version]) => { logger.info(` - ${pkg}: ${version}`); }); displayUsageInstructions('bulma', cssPath); } /** * Integrate Foundation CSS */ async function integrateFoundation(options) { logger.info('Integrating Foundation CSS...'); const integration = new OrdoJSCSSFrameworkIntegration({ framework: 'foundation', minify: options.minify, generateSourceMaps: options.sourceMaps }); const result = await integration.integrate(); if (!result.success) { throw new CLIError(`Foundation CSS integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-006'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); // Generate dependencies const dependencies = integration.generateDependencies(); logger.success('āœ… Foundation CSS integrated successfully!'); logger.info(`šŸ“ CSS file: ${cssPath}`); logger.info('šŸ“¦ Required dependencies:'); Object.entries(dependencies).forEach(([pkg, version]) => { logger.info(` - ${pkg}: ${version}`); }); displayUsageInstructions('foundation', cssPath); } /** * Integrate custom CSS framework */ async function integrateCustom(options) { logger.info('Integrating custom CSS framework...'); // Check if custom CSS file exists try { await fs.access(options.cssFile); } catch (error) { throw new CLIError(`Custom CSS file not found: ${options.cssFile}`, ErrorType.VALIDATION, 'CSS-007', ['Check if the file exists and the path is correct']); } const integration = new OrdoJSCSSFrameworkIntegration({ framework: 'custom', customCSSPath: options.cssFile, minify: options.minify, generateSourceMaps: options.sourceMaps }); const result = await integration.integrate(); if (!result.success) { throw new CLIError(`Custom CSS integration failed: ${result.errors?.join(', ')}`, ErrorType.COMPILATION, 'CSS-008'); } // Create output directory await fs.mkdir(options.output, { recursive: true }); // Write CSS file const cssPath = path.join(options.output, result.cssPath); await fs.mkdir(path.dirname(cssPath), { recursive: true }); await fs.writeFile(cssPath, result.css); logger.success('āœ… Custom CSS framework integrated successfully!'); logger.info(`šŸ“ CSS file: ${cssPath}`); logger.info(`šŸ“ Source file: ${options.cssFile}`); displayUsageInstructions('custom', cssPath); } /** * Display usage instructions for the integrated framework */ function displayUsageInstructions(framework, cssPath) { logger.info('\nšŸ“– Usage Instructions:'); switch (framework) { case 'tailwind': logger.info('1. Include the CSS file in your HTML:'); logger.info(` <link rel="stylesheet" href="${cssPath}">`); logger.info('\n2. Use Tailwind classes in your OrdoJS components:'); logger.info(' <div class="bg-blue-500 text-white p-4 rounded-lg">'); logger.info(' Hello Tailwind!'); logger.info(' </div>'); logger.info('\n3. Install required dependencies:'); logger.info(' npm install tailwindcss @tailwindcss/forms @tailwindcss/typography autoprefixer postcss'); logger.info('\n4. Run the build process to purge unused CSS:'); logger.info(' ordojs build src/app.ordo --minify'); break; case 'bootstrap': logger.info('1. Include the CSS file in your HTML:'); logger.info(` <link rel="stylesheet" href="${cssPath}">`); logger.info('\n2. Use Bootstrap classes in your OrdoJS components:'); logger.info(' <div class="container">'); logger.info(' <div class="row">'); logger.info(' <div class="col-md-6">Bootstrap content</div>'); logger.info(' </div>'); logger.info(' </div>'); logger.info('\n3. Install Bootstrap:'); logger.info(' npm install bootstrap'); break; case 'bulma': logger.info('1. Include the CSS file in your HTML:'); logger.info(` <link rel="stylesheet" href="${cssPath}">`); logger.info('\n2. Use Bulma classes in your OrdoJS components:'); logger.info(' <div class="container">'); logger.info(' <div class="columns">'); logger.info(' <div class="column">Bulma content</div>'); logger.info(' </div>'); logger.info(' </div>'); logger.info('\n3. Install Bulma:'); logger.info(' npm install bulma'); break; case 'foundation': logger.info('1. Include the CSS file in your HTML:'); logger.info(` <link rel="stylesheet" href="${cssPath}">`); logger.info('\n2. Use Foundation classes in your OrdoJS components:'); logger.info(' <div class="grid-container">'); logger.info(' <div class="grid-x">'); logger.info(' <div class="cell medium-6">Foundation content</div>'); logger.info(' </div>'); logger.info(' </div>'); logger.info('\n3. Install Foundation:'); logger.info(' npm install foundation-sites'); break; case 'custom': logger.info('1. Include the CSS file in your HTML:'); logger.info(` <link rel="stylesheet" href="${cssPath}">`); logger.info('\n2. Use your custom CSS classes in OrdoJS components'); logger.info('\n3. The custom CSS has been integrated with OrdoJS'); break; } logger.info('\nšŸŽØ You can now use the CSS framework classes in your OrdoJS components!'); } //# sourceMappingURL=css-framework.js.map