UNPKG

flexcss-cli

Version:

The Flex CSS, what if we dont follow CSS's rules? No Identation.

128 lines (106 loc) 4.38 kB
#!/usr/bin/env node import { watchFile, readFileSync, writeFileSync } from "fs"; const staticKeywords = { "ghost": "background: #eee", "p-4": "font-size: 4rem", "fusion-gradient": "background: linear-gradient(135deg, #4776E6, #8E54E9)", "shadow-xl": "box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04)", "rounded": "border-radius: 50px" // So Cubes are not converted into Ovals. }; function convertPadding(n) { const map = { "1": "0.25rem", "2": "0.5rem", "3": "0.75rem", "4": "1rem" }; return map[n] || `${n}rem`; } function convertBlockContent(blockContent) { for (const key in staticKeywords) { const regex = new RegExp(`\\b${key}\\b`, 'g'); blockContent = blockContent.replace(regex, staticKeywords[key]); } blockContent = blockContent.replace(/\btxt-([0-9a-fA-F]{3,6})\b/g, (_, hex) => { return `color: #${hex}`; }); blockContent = blockContent.replace(/\bbg-([0-9a-fA-F]{3,6})\b/g, (_, hex) => { return `background-color: #${hex}`; }); blockContent = blockContent.replace(/\b([pm])-(\d+)\b/g, (_, type, num) => { const val = type === "p" ? convertPadding(num) : `${num}rem`; const prop = type === "p" ? "padding" : "margin"; return `${prop}: ${val}`; }); blockContent = blockContent.replace(/\b([pm][lrud])-(\d+)\b/g, (_, prop, num) => { const type = prop.startsWith("p") ? "padding" : "margin"; const dirMap = { l: "left", r: "right", u: "top", d: "bottom" }; const dir = dirMap[prop[1]]; return `${type}-${dir}: ${num}rem`; }); blockContent = blockContent.replace(/\b(hi|wi)-(\d+)([phwr])\b/g, (_, type, val, unit) => { const prop = type === "hi" ? "height" : "width"; const unitMap = { p: "px", h: "vh", w: "vw", r: "rem" }; return `${prop}: ${val}${unitMap[unit]}`; }); blockContent = blockContent.replace(/\bmax-(w|h)-(\d+)-([phwr])\b/g, (_, dim, val, unit) => { const prop = `max-${dim === "w" ? "width" : "height"}`; const unitMap = { p: "px", h: "vh", w: "vw", r: "rem" }; return `${prop}: ${val}${unitMap[unit]}`; }); return blockContent; } function autoSemicolonFix(content) { return content.replace(/([^\s;{}\n])\n/g, "$1;\n"); } function transpill(input, output) { let source = readFileSync(input, "utf-8"); let prepared = source.replaceAll(",", ";\n "); let transformed = prepared.replace(/([^{]+){([^}]+)}/g, (match, selector, block) => { const cleanedSelector = selector.trim(); // like #ghost-btn let blockContent = block.trim(); // like ghost; txt-fff; ... blockContent = convertBlockContent(blockContent); blockContent = autoSemicolonFix(blockContent); return `${cleanedSelector} {\n ${blockContent}\n}`; }); const result = `/* Compiled from ${input} */\n` + transformed; writeFileSync(output, result); console.log("✅ Done."); } //////////////////////////// // C L I // // Command Line Interface // // Don't touch me! // //////////////////////////// const args = process.argv.slice(2); const command = args[0]; if (command === "transpill") { const inputFile = args[1]; const outputIndex = args.indexOf("-o"); if (outputIndex === -1 || !args[outputIndex + 1]) { console.error("Error: Output file not specified with -o"); process.exit(1); } const outputFile = args[outputIndex + 1]; console.log("Transpilling..."); console.log("Input:", inputFile); console.log("Output:", outputFile); transpill(inputFile, outputFile); } else if (command === "watch") { const inputFile = args[1]; const outputIndex = args.indexOf("-o"); if (outputIndex === -1 || !args[outputIndex + 1]) { console.error("Error: Output file not specified with -o"); process.exit(1); } const outputFile = args[outputIndex + 1]; console.log(`Watching ${inputFile} for changes...`); transpill(inputFile, outputFile); // Initial run watchFile(inputFile, { interval: 500 }, () => { console.log(`[FlexCSS] Change detected. Re-transpilling...`); transpill(inputFile, outputFile); }); } else { console.error("Unknown command:", command); process.exit(1); }