Last active
May 13, 2020 19:11
-
-
Save clshortfuse/acffca0a5f1412edcf9e132f33febe1c to your computer and use it in GitHub Desktop.
CSS Color 4 Verifier
This file contains hidden or 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
const RGB_FUNCTION = 'rgba?'; | |
const HSL_FUNCTION = 'hsla?'; | |
const HWB_FUNCTION = 'hwb'; | |
const CMYK_FUNCTION = 'device-cmyk'; | |
const LAB_FUNCTION = 'lab'; | |
const LCH_FUNCTION = 'lch'; | |
const GRAY_FUNCTION = 'gray'; | |
const COLOR_FUNCTION = 'color'; | |
const FUNCTION_START = '\\('; | |
/** https://www.w3.org/TR/css-syntax-3/#consume-function */ | |
const FUNCTION_END = /(\)|$)/.source; | |
/** https://www.w3.org/TR/css-syntax-3/#whitespace */ | |
const WHITESPACE = '\\s+'; | |
const COMMENT = /\/\*([^*]|\*(?!\/))*\*\//.source; | |
const OPTIONAL_WHITESPACE = `\\s*(${COMMENT})*\\s*`; | |
const COMMA = ','; | |
const SLASH = '\\/'; | |
const PERCENTAGE = '%'; | |
const OPTIONAL_PERCENTAGE = '%?'; | |
/** https://www.w3.org/TR/css3-values/#angle-value */ | |
const ANGLE_UNIT = '(deg|grad|rad|turn)'; | |
/** https://www.w3.org/TR/css3-values/#number-value */ | |
const NUMBER = /[+-]?((\d+)|(\d*\.\d+))(e[+-]?\d+)?/.source; | |
/** https://www.w3.org/TR/css-color-4/#named-colors */ | |
const NAMED_COLORS = [ | |
'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', 'darkgrey', 'darkkhaki', 'darkmagenta', | |
'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', | |
'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', | |
'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', | |
'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', | |
'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', | |
'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', | |
'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', | |
'lightskyblue', 'lightslategray', 'lightslategrey', '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', 'rebeccapurple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', | |
'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', | |
'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', | |
'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen']; | |
/** @type {RegExp} */ | |
let regExpCache = null; | |
/** @type {string} */ | |
let patternCache = null; | |
/** | |
* https://www.w3.org/TR/css-color-4/#hex-notation | |
* @param {number} digits | |
* @param {number=} maxDigits | |
* @return {string} | |
*/ | |
function getHexPattern(digits, maxDigits) { | |
return `#[A-F0-9]{${digits}${maxDigits > digits ? `,${maxDigits}` : ''}}`; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#rgb-functions | |
* @param {boolean} [commaless=false] | |
* @param {boolean} [percentages=false] | |
* @return {string} | |
*/ | |
function getRGBPattern(commaless, percentages) { | |
const optionalAlpha = [ | |
'(', | |
commaless ? SLASH : COMMA, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
RGB_FUNCTION, | |
FUNCTION_START, | |
'(', | |
OPTIONAL_WHITESPACE, NUMBER, percentages ? PERCENTAGE : '', OPTIONAL_WHITESPACE, | |
commaless ? WHITESPACE : COMMA, | |
')', | |
'{2}', | |
OPTIONAL_WHITESPACE, NUMBER, percentages ? PERCENTAGE : '', OPTIONAL_WHITESPACE, | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#the-hsl-notation | |
* @return {string} | |
*/ | |
function getHSLPattern() { | |
const optionalAlpha = [ | |
'(', | |
COMMA, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
HSL_FUNCTION, | |
FUNCTION_START, | |
OPTIONAL_WHITESPACE, NUMBER, ANGLE_UNIT, '?', OPTIONAL_WHITESPACE, | |
'(', | |
COMMA, | |
OPTIONAL_WHITESPACE, NUMBER, PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'{2}', | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#the-hsl-notation | |
* https://www.w3.org/TR/css-color-4/#the-hwb-notation | |
* @return {string} | |
*/ | |
function getCommalessHSLorHWBPattern() { | |
const optionalAlpha = [ | |
'(', | |
SLASH, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
'(', HSL_FUNCTION, '|', HWB_FUNCTION, ')', | |
FUNCTION_START, | |
OPTIONAL_WHITESPACE, NUMBER, ANGLE_UNIT, '?', OPTIONAL_WHITESPACE, | |
'(', | |
WHITESPACE, | |
OPTIONAL_WHITESPACE, NUMBER, PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'{2}', | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#cmyk-colors | |
* @return {string} | |
*/ | |
function getDeviceCMYKPattern() { | |
const optionalAlpha = [ | |
'(', | |
SLASH, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
// Needs recursion. Using loose check that will consume functions | |
const optionalFallback = [ | |
'(', | |
COMMA, | |
/([^()]*|\([^)]*\))*/.source, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
CMYK_FUNCTION, | |
FUNCTION_START, | |
'(', | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
WHITESPACE, | |
')', | |
'{3}', | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
optionalAlpha, | |
optionalFallback, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#funcdef-lab | |
* @return {string} | |
*/ | |
function getLabPattern() { | |
const optionalAlpha = [ | |
'(', | |
SLASH, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
LAB_FUNCTION, | |
FUNCTION_START, | |
'(', | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_WHITESPACE, | |
WHITESPACE, | |
')', | |
'{2}', | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_WHITESPACE, | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#funcdef-lch | |
* @return {string} | |
*/ | |
function getLCHPattern() { | |
const optionalAlpha = [ | |
'(', | |
SLASH, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
LCH_FUNCTION, | |
FUNCTION_START, | |
'(', | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_WHITESPACE, | |
WHITESPACE, | |
')', | |
'{2}', | |
OPTIONAL_WHITESPACE, NUMBER, ANGLE_UNIT, '?', OPTIONAL_WHITESPACE, | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#grays | |
* @return {string} | |
*/ | |
function getGrayPattern() { | |
const optionalAlpha = [ | |
'(', | |
SLASH, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_PERCENTAGE, OPTIONAL_WHITESPACE, | |
')', | |
'?', | |
].join(''); | |
const pattern = [ | |
GRAY_FUNCTION, | |
FUNCTION_START, | |
OPTIONAL_WHITESPACE, NUMBER, OPTIONAL_WHITESPACE, | |
WHITESPACE, | |
optionalAlpha, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#color-function | |
* @return {string} | |
*/ | |
function getColorPattern() { | |
// Loose check that consumes function | |
const pattern = [ | |
COLOR_FUNCTION, | |
FUNCTION_START, | |
/([^()]*|\([^)]*\))*/.source, | |
FUNCTION_END, | |
].join(''); | |
return pattern; | |
} | |
/** | |
* https://www.w3.org/TR/css-color-4/#resolving-color-values | |
* @return {string} | |
*/ | |
export function getRegexPattern() { | |
if (patternCache == null) { | |
const patterns = [ | |
'currentcolor', | |
'transparent', | |
...NAMED_COLORS, | |
// DEPRECATED_SYSTEM_COLORS | |
getHexPattern(3, 4), | |
getHexPattern(6), | |
getHexPattern(8), | |
getRGBPattern(false, false), | |
getRGBPattern(false, true), | |
getRGBPattern(true, false), | |
getRGBPattern(true, true), | |
getHSLPattern(), | |
getCommalessHSLorHWBPattern(), | |
getDeviceCMYKPattern(), | |
getLabPattern(), | |
getLCHPattern(), | |
getGrayPattern(), | |
getColorPattern(), | |
].join('|'); | |
patternCache = [ | |
'^', | |
OPTIONAL_WHITESPACE, | |
'(', | |
...patterns, | |
')', | |
OPTIONAL_WHITESPACE, | |
'$', | |
].join(''); | |
} | |
return patternCache; | |
} | |
/** @return {RegExp} */ | |
export function getRegExp() { | |
if (!regExpCache) { | |
regExpCache = RegExp(getRegexPattern(), 'i'); | |
} | |
return regExpCache; | |
} | |
/** | |
* @param {string} input | |
* @return {boolean} | |
*/ | |
export function test(input) { | |
return getRegExp().test(input); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment