Last active
September 5, 2022 15:56
-
-
Save mcasimir/9484b74819228deecc5cd330c108647c to your computer and use it in GitHub Desktop.
Lg colors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const { Command } = require('commander'); | |
const fs = require('fs'); | |
const colorConvert = require('color-convert'); | |
const colorDiff = require('color-diff'); | |
const isBinaryFileSync = require("isbinaryfile").isBinaryFileSync; | |
const chalk = require('chalk'); | |
const NAMED_COLOR_RE = /[^@\-.A-z0-9](aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgrey|lightgreen|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen)/ig; | |
const HEX_COLOR_RE = /#[0-9a-fA-F]{3,6}\b/g; | |
const HEX_COLOR_ALPHA_RE = /#[0-9a-fA-F]{8,8}\b/g; | |
const RGB_COLOR_RE = /[^.A-z0-9]rgba?\(/ig; | |
const rgbObject = ([R, G, B]) => ({R, G, B}); | |
const toRgb = (hex) => rgbObject(colorConvert.hex.rgb(hex)); | |
const toHex = ({R, G, B}) => '#' + colorConvert.rgb.hex([R, G, B]).toLowerCase(); | |
const palette = [ | |
'#FFFFFF', | |
'#001E2B', | |
'#112733', | |
'#1C2D38', | |
'#3D4F58', | |
'#5C6C75', | |
'#889397', | |
'#C1C7C6', | |
'#E8EDEB', | |
'#F9FBFA', | |
'#023430', | |
'#00684A', | |
'#00A35C', | |
'#00ED64', | |
'#71F6BA', | |
'#C0FAE6', | |
'#E3FCF7', | |
'#2D0B59', | |
'#5E0C9E', | |
'#B45AF2', | |
'#F1D4FD', | |
'#F9EBFF', | |
'#0C2657', | |
'#083C90', | |
'#1254B7', | |
'#016BF8', | |
'#0498EC', | |
'#C3E7FE', | |
'#E1F7FF', | |
'#4C2100', | |
'#944F01', | |
'#FFC010', | |
'#FFEC9E', | |
'#FEF7DB', | |
'#5B0000', | |
'#970606', | |
'#DB3030', | |
'#FF6960', | |
'#FFCDC7', | |
'#FFEAE5', | |
].map(toRgb); | |
function getUniqueMatches(txt, re) { | |
const colorsArray = [...txt.matchAll(re)] | |
.filter((matches) => matches.length) | |
.flatMap((match) => match[0]); | |
return [...new Set(colorsArray)]; | |
} | |
function getReplacements(txt) { | |
const colors = getUniqueMatches(txt, HEX_COLOR_RE) | |
.map(toRgb); | |
const entries = colors.map( | |
(c) => [toHex(c), toHex(colorDiff.closest(c, palette))] | |
); | |
return entries; | |
} | |
function outputTable(entries) { | |
const toTd = (hex) => `<td style="background-color:${hex}">${hex}</td>`; | |
const rows = entries.map(([from, to]) => `<tr>${toTd(from)}${toTd(to)}</tr>`).join('\n'); | |
const table = `<table>\n${rows}\n<table>`; | |
return `<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Document</title> | |
</head> | |
<body> | |
${table} | |
</body> | |
</html> | |
`; | |
} | |
const program = new Command(); | |
program.command('replace') | |
.argument('<path>', 'source file path') | |
.option('--dry-run') | |
.option('--verbose') | |
.action((filename, options) => { | |
const bytes = fs.readFileSync(filename); | |
const size = fs.lstatSync(filename).size; | |
if (isBinaryFileSync(bytes, size)) { | |
console.error(filename, 'is a binary file.'); | |
return; | |
} | |
if (options.verbose) { | |
console.debug('Replacing', filename); | |
} | |
const source = bytes.toString('utf-8'); | |
const namedColors = getUniqueMatches(source, NAMED_COLOR_RE); | |
if (namedColors.length) { | |
console.warn(filename, chalk.yellow('potential named colors found'), namedColors); | |
} | |
const rgbColors = getUniqueMatches(source, RGB_COLOR_RE); | |
if (rgbColors.length) { | |
console.warn(filename, chalk.yellow('potential rgb colors found')); | |
} | |
const transparentColors = getUniqueMatches(source, HEX_COLOR_ALPHA_RE); | |
if (transparentColors.length) { | |
console.warn(filename, chalk.yellow('potential transparent colors found'), [transparentColors]); | |
} | |
const entries = getReplacements(source); | |
let dest = source; | |
for (const [from, to] of entries) { | |
dest = dest.replaceAll(from, to); | |
dest = dest.replaceAll(from.toUpperCase(), to); | |
} | |
if (options.dryRun) { | |
// console.log(dest); | |
} else { | |
fs.writeFileSync(filename, dest); | |
} | |
}); | |
program.command('print') | |
.argument('<path>', 'source file path') | |
.option('--html') | |
.action((src, options) => { | |
const entries = getReplacements(fs.readFileSync(src, 'utf-8')); | |
if (options.html) { | |
console.log(outputTable(entries)); | |
} else { | |
console.log(JSON.stringify(Object.fromEntries(entries))); | |
} | |
}); | |
program.parse(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment