Skip to content

Commit

Permalink
Support relative colors
Browse files Browse the repository at this point in the history
Fix #33
  • Loading branch information
asamuzaK committed Jan 5, 2025
1 parent 24137e3 commit 6de44eb
Show file tree
Hide file tree
Showing 9 changed files with 986 additions and 14 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"types": "types/index.d.ts",
"dependencies": {
"@csstools/css-calc": "^2.1.1",
"@csstools/css-color-parser": "^3.0.7",
"@csstools/css-parser-algorithms": "^3.0.4",
"@csstools/css-tokenizer": "^3.0.3",
"lru-cache": "^11.0.2"
},
Expand Down
10 changes: 5 additions & 5 deletions src/js/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { interpolateHue, roundToPrecision } from './util.js';
/* constants */
import {
ANGLE, CS_HUE_CAPT, CS_MIX, CS_RGB, CS_XYZ, FN_COLOR, FN_MIX, NONE, NUM, PCT,
SYN_COLOR_TYPE, SYN_FN_COLOR, SYN_HSL, SYN_HSL_LV3, SYN_LAB, SYN_LCH,
SYN_MIX, SYN_MIX_CAPT, SYN_RGB, SYN_RGB_LV3, VAL_COMP, VAL_SPEC
SYN_COLOR_TYPE, SYN_FN_COLOR, SYN_HSL, SYN_HSL_LV3, SYN_LCH, SYN_MIX,
SYN_MIX_CAPT, SYN_MOD, SYN_RGB_LV3, VAL_COMP, VAL_SPEC
} from './constant.js';
const VAL_MIX = 'mixValue';

Expand Down Expand Up @@ -115,12 +115,12 @@ const REG_CURRENT = /^currentColor$/i;
const REG_FN_COLOR = new RegExp(`^color\\(\\s*(${SYN_FN_COLOR})\\s*\\)$`);
const REG_HSL = new RegExp(`^hsla?\\(\\s*(${SYN_HSL}|${SYN_HSL_LV3})\\s*\\)$`);
const REG_HWB = new RegExp(`^hwb\\(\\s*(${SYN_HSL})\\s*\\)$`);
const REG_LAB = new RegExp(`^lab\\(\\s*(${SYN_LAB})\\s*\\)$`);
const REG_LAB = new RegExp(`^lab\\(\\s*(${SYN_MOD})\\s*\\)$`);
const REG_LCH = new RegExp(`^lch\\(\\s*(${SYN_LCH})\\s*\\)$`);
const REG_MIX = new RegExp(`^${SYN_MIX}$`);
const REG_MIX_CAPT = new RegExp(`^${SYN_MIX_CAPT}$`);
const REG_MIX_NEST = new RegExp(`${SYN_MIX}`, 'g');
const REG_OKLAB = new RegExp(`^oklab\\(\\s*(${SYN_LAB})\\s*\\)$`);
const REG_OKLAB = new RegExp(`^oklab\\(\\s*(${SYN_MOD})\\s*\\)$`);
const REG_OKLCH = new RegExp(`^oklch\\(\\s*(${SYN_LCH})\\s*\\)$`);
const REG_SPEC = /^(?:specifi|comput)edValue$/;

Expand Down Expand Up @@ -1076,7 +1076,7 @@ export const parseRgb = (value, opt = {}) => {
throw new TypeError(`${value} is not a string.`);
}
const { format } = opt;
const reg = new RegExp(`^rgba?\\(\\s*(${SYN_RGB}|${SYN_RGB_LV3})\\s*\\)$`);
const reg = new RegExp(`^rgba?\\(\\s*(${SYN_MOD}|${SYN_RGB_LV3})\\s*\\)$`);
if (!reg.test(value)) {
switch (format) {
case VAL_MIX: {
Expand Down
12 changes: 8 additions & 4 deletions src/js/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ export const NUM = `[+-]?(?:${_DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${_DIGIT})?`;
export const NONE = 'none';
export const PCT = `${NUM}%`;
export const SYN_FN_MATH = `^(?:${_MATH})\\($`;
export const SYN_FN_MATH_CALC = `^${_CALC}\\(|(?<=[*\\/\\s\\(])${_CALC}\\(`;
export const SYN_FN_MATH_CALC =
`^(?:${_CALC})\\(|(?<=[*\\/\\s\\(])(?:${_CALC})\\(`;
export const SYN_FN_MATH_VAR = `^(?:${_VAR})\\(`;
export const SYN_FN_VAR = '^var\\(|(?<=[*\\/\\s\\(])var\\(';

/* colors */
const _ALPHA = `(?:\\s*\\/\\s*(?:${NUM}|${PCT}|${NONE}))?`;
const _ALPHA_LV3 = `(?:\\s*,\\s*(?:${NUM}|${PCT}))?`;
const _COLOR_FUNC = '(?:ok)?l(?:ab|ch)|color|hsla?|hwb|rgba?';
const _COLOR_KEY = '[a-z]+|#[\\da-f]{3}|#[\\da-f]{4}|#[\\da-f]{6}|#[\\da-f]{8}';
const _CS_HUE = '(?:ok)?lch|hsl|hwb';
const _CS_HUE_ARC = '(?:de|in)creasing|longer|shorter';
const _NUM_ANGLE = `${NUM}(?:${ANGLE})?`;
Expand All @@ -43,17 +46,18 @@ export const CS_XYZ = 'xyz(?:-d(?:50|65))?';
export const CS_MIX = `${CS_HUE}|${CS_LAB}|${CS_SRGB}|${CS_XYZ}`;
export const FN_COLOR = 'color(';
export const FN_MIX = 'color-mix(';
export const FN_REL = `(?:${_COLOR_FUNC})\\(\\s*from\\s+`;
export const FN_VAR = 'var(';
export const SYN_FN_COLOR =
`(?:${CS_RGB}|${CS_XYZ})(?:\\s+${_NUM_PCT_NONE}){3}${_ALPHA}`;
export const SYN_FN_REL = `^${FN_REL}|(?<=[\\s])${FN_REL}`;
export const SYN_HSL = `${_NUM_ANGLE_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_HSL_LV3 = `${_NUM_ANGLE}(?:\\s*,\\s*${PCT}){2}${_ALPHA_LV3}`;
export const SYN_LAB = `${_NUM_PCT_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_LCH = `(?:${_NUM_PCT_NONE}\\s+){2}${_NUM_ANGLE_NONE}${_ALPHA}`;
export const SYN_RGB = `${_NUM_PCT_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_MOD = `${_NUM_PCT_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_RGB_LV3 =
`(?:${NUM}(?:\\s*,\\s*${NUM}){2}|${PCT}(?:\\s*,\\s*${PCT}){2})${_ALPHA_LV3}`;
export const SYN_COLOR_TYPE = `[a-z]+|#(?:[\\da-f]{3}|[\\da-f]{4}|[\\da-f]{6}|[\\da-f]{8})|hsla?\\(\\s*(?:${SYN_HSL}|${SYN_HSL_LV3})\\s*\\)|hwb\\(\\s*${SYN_HSL}\\s*\\)|rgba?\\(\\s*(?:${SYN_RGB}|${SYN_RGB_LV3})\\s*\\)|(?:ok)?lab\\(\\s*${SYN_LAB}\\s*\\)|(?:ok)?lch\\(\\s*${SYN_LCH}\\s*\\)|color\\(\\s*${SYN_FN_COLOR}\\s*\\)`;
export const SYN_COLOR_TYPE = `${_COLOR_KEY}|hsla?\\(\\s*${SYN_HSL_LV3}\\s*\\)|rgba?\\(\\s*${SYN_RGB_LV3}\\s*\\)|(?:hsla?|hwb)\\(\\s*${SYN_HSL}\\s*\\)|(?:(?:ok)?lab|rgba?)\\(\\s*${SYN_MOD}\\s*\\)|(?:ok)?lch\\(\\s*${SYN_LCH}\\s*\\)|color\\(\\s*${SYN_FN_COLOR}\\s*\\)`;
export const SYN_MIX_PART = `(?:${SYN_COLOR_TYPE})(?:\\s+${PCT})?`;
export const SYN_MIX = `color-mix\\(\\s*in\\s+(?:${CS_MIX})\\s*,\\s*${SYN_MIX_PART}\\s*,\\s*${SYN_MIX_PART}\\s*\\)`;
export const SYN_MIX_CAPT = `color-mix\\(\\s*in\\s+(${CS_MIX})\\s*,\\s*(${SYN_MIX_PART})\\s*,\\s*(${SYN_MIX_PART})\\s*\\)`;
12 changes: 9 additions & 3 deletions src/js/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ import {
import { isString } from './common.js';
import { cssCalc } from './css-calc.js';
import { cssVar } from './css-var.js';
import { resolveRelativeColor } from './relative-color.js';
import { resolve } from './resolve.js';
import { valueToJsonString } from './util.js';

/* constants */
import { SYN_FN_MATH_CALC, SYN_FN_VAR, VAL_COMP } from './constant.js';
import {
SYN_FN_MATH_CALC, SYN_FN_REL, SYN_FN_VAR, VAL_COMP
} from './constant.js';

/* regexp */
const REG_FN_MATH_CALC = new RegExp(SYN_FN_MATH_CALC);
const REG_FN_REL = new RegExp(SYN_FN_REL);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);

/* cached results */
Expand Down Expand Up @@ -60,10 +64,12 @@ export const preProcess = (value, opt = {}) => {
return null;
}
}
if (REG_FN_MATH_CALC.test(value)) {
if (REG_FN_REL.test(value)) {
value = resolveRelativeColor(value, opt);
} else if (REG_FN_MATH_CALC.test(value)) {
value = cssCalc(value, opt);
}
if (value.startsWith('color-mix')) {
if (value && value.startsWith('color-mix')) {
value = resolve(value, {
format: VAL_COMP
});
Expand Down
Loading

0 comments on commit 6de44eb

Please sign in to comment.