@ordojs/cli
Version:
Command-line interface for OrdoJS framework
383 lines ⢠17.1 kB
JavaScript
/**
* @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