|
| 1 | +import type { Plugin } from 'esbuild'; |
| 2 | + |
| 3 | +// CSS-specific minification for template literals |
| 4 | +function minifyCSS(css: string): string { |
| 5 | + // return css; |
| 6 | + return ( |
| 7 | + css |
| 8 | + // Remove all unnecessary whitespace |
| 9 | + .replace(/\s+/g, ' ') |
| 10 | + // Remove space around colons |
| 11 | + .replace(/\s*:\s*/g, ':') |
| 12 | + // Remove space around semicolons |
| 13 | + .replace(/\s*;\s*/g, ';') |
| 14 | + // Remove space around commas |
| 15 | + .replace(/\s*,\s*/g, ',') |
| 16 | + // Decimal optimization: 0.X → .X |
| 17 | + .replace(/\b0(\.\d+)/g, '$1') |
| 18 | + |
| 19 | + // Unit removal for zero values |
| 20 | + .replace(/\b0(px|em|rem|%|deg|s|ms|vh|vw|vmin|vmax)\b/g, '0') |
| 21 | + |
| 22 | + // Color optimizations |
| 23 | + .replace(/rgba\((\d+),(\d+),(\d+),0(\.\d+)\)/g, 'rgba($1,$2,$3,$4)') // Remove leading zero in alpha |
| 24 | + .replace(/#([0-9a-fA-F])\1([0-9a-fA-F])\2([0-9a-fA-F])\3/g, '#$1$2$3') // #aabbcc → #abc |
| 25 | + |
| 26 | + // Optimize empty content property |
| 27 | + .replace(/content\s*:\s*['"]['"];/g, 'content:"";') |
| 28 | + |
| 29 | + // Remove leading/trailing spaces |
| 30 | + .trim() |
| 31 | + ); |
| 32 | +} |
| 33 | + |
| 34 | +export const cssMinifierPlugin = (): Plugin => ({ |
| 35 | + name: 'css-minifier', |
| 36 | + setup(build) { |
| 37 | + if (build.initialOptions.write !== false) return; |
| 38 | + |
| 39 | + build.onEnd((result) => { |
| 40 | + result.outputFiles?.forEach((file, fileIndex, outputFiles) => { |
| 41 | + if (!/\.[mc]?js$/.test(file.path)) return; |
| 42 | + |
| 43 | + const content = new TextDecoder().decode(file.contents); |
| 44 | + |
| 45 | + // Find and minify CSS in template literals more aggressively |
| 46 | + const minified = content.replace( |
| 47 | + /`([^`]*(?:from|to|%|\{[^}]*\})[^`]*)`/g, |
| 48 | + (match, cssContent) => { |
| 49 | + // Only process if it looks like CSS (contains CSS keywords) |
| 50 | + if ( |
| 51 | + /(?:transform|opacity|width|height|background|animation|from|to|%|\{)/.test( |
| 52 | + cssContent |
| 53 | + ) |
| 54 | + ) { |
| 55 | + return '`' + minifyCSS(cssContent) + '`'; |
| 56 | + } |
| 57 | + return match; |
| 58 | + } |
| 59 | + ); |
| 60 | + |
| 61 | + outputFiles[fileIndex].contents = new TextEncoder().encode(minified); |
| 62 | + }); |
| 63 | + }); |
| 64 | + }, |
| 65 | +}); |
0 commit comments