@tbela99/css-parser
Version:
CSS parser for node and the browser
260 lines (257 loc) • 7.55 kB
JavaScript
import { COLORS_NAMES } from './utils/constants.js';
import { getComponents } from './utils/components.js';
import { color2srgbvalues, getNumber, getAngle } from './color.js';
import { EnumToken } from '../../ast/types.js';
import '../../ast/minify.js';
import '../../ast/walk.js';
import '../../parser/parse.js';
import { expandHexValue } from './hex.js';
import { lch2labvalues, Lab_to_sRGB, getLABComponents } from './lab.js';
import { OKLab_to_sRGB, getOKLABComponents } from './oklab.js';
import { getLCHComponents } from './lch.js';
import { getOKLCHComponents } from './oklch.js';
import { XYZ_to_lin_sRGB } from './xyz.js';
import '../sourcemap/lib/encode.js';
import '../../parser/utils/config.js';
// from https://www.w3.org/TR/css-color-4/#color-conversion-code
// srgb-linear -> srgb
// 0 <= r, g, b <= 1
function srgbvalues(token) {
switch (token.kin) {
case 'lit':
case 'hex':
return hex2srgb(token);
case 'rgb':
case 'rgba':
return rgb2srgb(token);
case 'hsl':
case 'hsla':
return hsl2srgb(token);
case 'hwb':
return hwb2srgb(token);
case 'lab':
return lab2srgb(token);
case 'lch':
return lch2srgb(token);
case 'oklab':
return oklab2srgb(token);
case 'oklch':
return oklch2srgb(token);
case 'color':
return color2srgbvalues(token);
}
return null;
}
function rgb2srgb(token) {
return getComponents(token).map((t, index) => index == 3 ? ((t.typ == EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t)) : (t.typ == EnumToken.PercentageTokenType ? 255 : 1) * getNumber(t) / 255);
}
function hex2srgb(token) {
const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
const rgb = [];
for (let i = 1; i < value.length; i += 2) {
rgb.push(parseInt(value.slice(i, i + 2), 16) / 255);
}
return rgb;
}
function xyz2srgb(x, y, z) {
// @ts-ignore
return lsrgb2srgbvalues(...XYZ_to_lin_sRGB(x, y, z));
}
function hwb2srgb(token) {
const { h: hue, s: white, l: black, a: alpha } = hslvalues(token);
const rgb = hsl2srgbvalues(hue, 1, .5);
for (let i = 0; i < 3; i++) {
rgb[i] *= (1 - white - black);
rgb[i] = rgb[i] + white;
}
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function hsl2srgb(token) {
let { h, s, l, a } = hslvalues(token);
return hsl2srgbvalues(h, s, l, a);
}
function cmyk2srgb(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const c = getNumber(t);
// @ts-ignore
t = components[1];
// @ts-ignore
const m = getNumber(t);
// @ts-ignore
t = components[2];
// @ts-ignore
const y = getNumber(t);
// @ts-ignore
t = components[3];
// @ts-ignore
const k = getNumber(t);
const rgb = [
1 - Math.min(1, c * (1 - k) + k),
1 - Math.min(1, m * (1 - k) + k),
1 - Math.min(1, y * (1 - k) + k)
];
// @ts-ignore
if (token.chi.length >= 9) {
// @ts-ignore
t = token.chi[8];
// @ts-ignore
rgb.push(getNumber(t));
}
return rgb;
}
function oklab2srgb(token) {
const [l, a, b, alpha] = getOKLABComponents(token);
const rgb = OKLab_to_sRGB(l, a, b);
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function oklch2srgb(token) {
const [l, c, h, alpha] = getOKLCHComponents(token);
// @ts-ignore
const rgb = OKLab_to_sRGB(...lch2labvalues(l, c, h));
if (alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function hslvalues(token) {
const components = getComponents(token);
let t;
// @ts-ignore
let h = getAngle(components[0]);
// @ts-ignore
t = components[1];
// @ts-ignore
let s = getNumber(t);
// @ts-ignore
t = components[2];
// @ts-ignore
let l = getNumber(t);
let a = null;
if (token.chi?.length == 4) {
// @ts-ignore
t = token.chi[3];
// @ts-ignore
a = getNumber(t);
}
return a == null ? { h, s, l } : { h, s, l, a };
}
function hsl2srgbvalues(h, s, l, a = null) {
let v = l <= .5 ? l * (1.0 + s) : l + s - l * s;
let r = l;
let g = l;
let b = l;
if (v > 0) {
let m = l + l - v;
let sv = (v - m) / v;
h *= 6.0;
let sextant = Math.floor(h);
let fract = h - sextant;
let vsf = v * sv * fract;
let mid1 = m + vsf;
let mid2 = v - vsf;
switch (sextant) {
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
const values = [r, g, b];
if (a != null && a != 1) {
values.push(a);
}
return values;
}
function lab2srgb(token) {
const [l, a, b, alpha] = getLABComponents(token);
const rgb = Lab_to_sRGB(l, a, b);
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function lch2srgb(token) {
// @ts-ignore
const [l, a, b, alpha] = lch2labvalues(...getLCHComponents(token));
// https://www.w3.org/TR/css-color-4/#lab-to-lch
const rgb = Lab_to_sRGB(l, a, b);
if (alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
// sRGB -> lRGB
function srgb2lsrgbvalues(r, g, b, a = null) {
// convert an array of linear-light sRGB values in the range 0.0-1.0
// to gamma corrected form
// https://en.wikipedia.org/wiki/SRGB
// Extended transfer function:
// For negative values, linear portion extends on reflection
// of axis, then uses reflected pow below that
const rgb = [r, g, b].map((val) => {
const abs = Math.abs(val);
if (abs <= 0.04045) {
return val / 12.92;
}
return (Math.sign(val) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4);
});
if (a != 1 && a != null) {
rgb.push(a);
}
return rgb;
}
function lsrgb2srgbvalues(r, g, b, alpha) {
// convert an array of linear-light sRGB values in the range 0.0-1.0
// to gamma corrected form
// https://en.wikipedia.org/wiki/SRGB
// Extended transfer function:
// For negative values, linear portion extends on reflection
// of axis, then uses reflected pow below that
const rgb = [r, g, b].map((val) => {
let abs = Math.abs(val);
if (Math.abs(val) > 0.0031308) {
return (Math.sign(val) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);
}
return 12.92 * val;
});
if (alpha != 1 && alpha != null) {
rgb.push(alpha);
}
return rgb;
}
export { cmyk2srgb, hex2srgb, hsl2srgb, hsl2srgbvalues, hslvalues, hwb2srgb, lab2srgb, lch2srgb, lsrgb2srgbvalues, oklab2srgb, oklch2srgb, rgb2srgb, srgb2lsrgbvalues, srgbvalues, xyz2srgb };