import uncss from 'uncss'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; import * as globModule from 'glob'; import cleanCss from 'clean-css'; const CleanCSS = cleanCss; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const { glob } = globModule; // Find all CSS files in the static directory const findCssFiles = () => { const staticDir = path.join(__dirname, 'static'); const cssFiles = []; if (fs.existsSync(staticDir)) { // Look for CSS files in static/css and static/css/vendor const vendorFiles = glob.sync(path.join(staticDir, 'css', 'vendor', '*.css')); const regularFiles = glob.sync(path.join(staticDir, 'css', '*.css')); cssFiles.push(...vendorFiles, ...regularFiles); } return cssFiles; }; // Get all HTML files from the public directory const findHtmlFiles = () => { const publicDir = path.join(__dirname, 'public'); if (fs.existsSync(publicDir)) { return glob.sync(path.join(publicDir, '**', '*.html')); } return []; }; // Create a directory if it doesn't exist const ensureDir = (dir) => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } }; // Create the optimized directory const createOptimizedDir = () => { const optimizedDir = path.join(__dirname, 'public', 'css', 'optimized'); ensureDir(optimizedDir); return optimizedDir; }; // Process CSS files const processCssFiles = (cssFiles, htmlFiles) => { // If no HTML files found, exit if (htmlFiles.length === 0) { console.log('No HTML files found. Make sure to run Hugo build first.'); return; } // If no CSS files found, look in the public directory if (cssFiles.length === 0) { console.log('No CSS files found in static directory, looking in public directory...'); const publicCssDir = path.join(__dirname, 'public', 'css'); const publicVendorCssDir = path.join(publicCssDir, 'vendor'); if (fs.existsSync(publicVendorCssDir)) { const vendorFiles = glob.sync(path.join(publicVendorCssDir, '*.css')); cssFiles.push(...vendorFiles); } if (fs.existsSync(publicCssDir)) { const regularFiles = glob.sync(path.join(publicCssDir, '*.css')); cssFiles.push(...regularFiles); } } if (cssFiles.length === 0) { console.log('No CSS files found. Exiting.'); return; } console.log(`Found ${cssFiles.length} CSS files and ${htmlFiles.length} HTML files.`); // Options for uncss const options = { ignoreSheets: [/fonts.googleapis/], ignore: [ /\.video-js/, /\.vjs-/, /\.material-/, /\.mdl-/, /\.fa-/, /\.is-/, /\.has-/, // Add more selectors to ignore as needed ], timeout: 5000, report: true }; const optimizedDir = createOptimizedDir(); // Process each CSS file cssFiles.forEach((cssFile) => { console.log(`Processing ${cssFile}...`); const filename = path.basename(cssFile); const outputFile = path.join(optimizedDir, filename); // Process the CSS uncss(htmlFiles, { ...options, stylesheets: [cssFile] }, (error, output) => { if (error) { console.error(`Error processing ${cssFile}:`, error); return; } // Minify the CSS const minifier = new CleanCSS(); const minified = minifier.minify(output); // Write the output fs.writeFileSync(outputFile, minified.styles); // Report const originalSize = fs.statSync(cssFile).size; const optimizedSize = minified.styles.length; const savings = ((originalSize - optimizedSize) / originalSize * 100).toFixed(2); console.log(`${filename}: ${originalSize} bytes -> ${optimizedSize} bytes (${savings}% saved)`); }); }); }; // Main execution const htmlFiles = findHtmlFiles(); const cssFiles = findCssFiles(); processCssFiles(cssFiles, htmlFiles);