Skip to content

Instantly share code, notes, and snippets.

@Darep
Created May 6, 2025 19:18
Show Gist options
  • Save Darep/1063370b09c589866e63daa430ae8dae to your computer and use it in GitHub Desktop.
Save Darep/1063370b09c589866e63daa430ae8dae to your computer and use it in GitHub Desktop.
convert css file with hsl to oklch
/**
* Simple script to convert hsl() to oklch() in a CSS file.
* Used for converting shadcn theme from HSL to OKLCH during Tailwind v4 upgrade.
*
* IMPORTANT! DOES NOT CHANGE THE FILE IN PLACE! Only outputs the converted CSS to the console.
*
* Usage:
* npm install culori
* node hsl-to-oklch.js /home/user/projects/my-project/globals.css
**/
const fs = require('node:fs');
const culori = require('culori');
function processCssFile(filePath) {
try {
const cssContent = fs.readFileSync(filePath, 'utf8');
const lines = cssContent.split('\n');
const newLines = [];
const hslPattern = /hsl\([^)]+\)/;
console.log('Starting CSS processing...\n');
for (const line of lines) {
const match = line.match(hslPattern);
if (match) {
const colorInputString = match[0];
try {
const parsedColor = culori.parse(colorInputString);
if (parsedColor) {
const oklchColor = culori.oklch(parsedColor);
if (oklchColor) {
oklchColor.l = culori.round(5)(oklchColor.l);
oklchColor.c = culori.round(5)(oklchColor.c);
oklchColor.h = culori.round(5)(oklchColor.h);
oklchColor.a = oklchColor.a ? culori.round(3)(oklchColor.a) : undefined;
const oklchString = culori.formatCss(oklchColor);
const newLine = line.replace(
hslPattern,
oklchString,
);
newLines.push(newLine);
console.log(
`CONVERTED: "${line.trim()}" => "${newLine.trim()}"`,
);
} else {
console.warn(
`[WARN] Could not convert parsed color to OKLCH. Original HSL: "${colorInputString}", Line: "${line.trim()}"`,
);
newLines.push(line);
}
} else {
console.warn(
`[WARN] Culori could not parse as HSL. Input: "${colorInputString}", Line: "${line.trim()}"`,
);
newLines.push(line);
}
} catch (e) {
console.error(
`[ERROR] Processing line: "${line.trim()}". HSL input: "${colorInputString}". Error: ${e.message}`,
);
newLines.push(line);
}
} else {
newLines.push(line);
}
}
const newCssContent = newLines.join('\n');
console.log('\n\n--- Processed CSS Content (copy this to your file) ---\n');
console.log(newCssContent);
} catch (error) {
console.error(
`[FATAL ERROR] Processing CSS file ${filePath}: ${error.message}`,
);
process.exit(1);
}
}
if (require.main === module) {
const filePath = process.argv[2];
if (!filePath) {
console.error(
'ERROR: Please provide the path to the CSS file as an argument.',
);
console.log(`Usage: node ${process.argv[1]} <path-to-your-css-file.css>`);
process.exit(1);
}
processCssFile(filePath);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment