diff --git a/src/@types/index.ts b/src/@types/index.ts index 79edc0e..6d04ee0 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -204,4 +204,8 @@ export type InputOptions = Partial< labUnit?: `${ColorUnitEnum}`, alphaUnit?: `${ColorUnitEnum}`; cmykFunction?: `${CMYKFunctionEnum}` +}; + +export type MatchOptions = { + [K in keyof Pick]: number; }; \ No newline at end of file diff --git a/src/color/utils.ts b/src/color/utils.ts index 898e5fd..b7ec4f5 100644 --- a/src/color/utils.ts +++ b/src/color/utils.ts @@ -1,27 +1,27 @@ import { + AnglesUnitEnum, CIELabObject, CIELabObjectGeneric, CIELabOutput, - CIELabRegExpMatchArray, + CMYKFunctionEnum, CMYKObject, CMYKObjectGeneric, - CMYKRegExpMatchArray, Color, ColorInput, ColorInputWithoutCMYK, ColorOutput, + ColorUnitEnum, HEXObject, HEXOutput, - HEXRegExpMatchArray, HSLObject, HSLObjectGeneric, HSLOutput, - HSLRegExpMatchArray, + InputOptions, + MatchOptions, Options, RGBObject, RGBObjectGeneric, RGBOutput, - RGBRegExpMatchArray, RGYBObject, RYBObject } from '@types'; @@ -30,27 +30,37 @@ import { ColorKeywords, ColorModel, COLORREGS, + COMMAS_AND_NEXT_CHARS, + DEFAULT_OPTIONS, ERRORS, HEX, Mix, MixString, PCENT, + SPACES, + TypeOf, VALID_COLOR_OBJECTS } from '#constants'; import { getBase125Number, getBase255Number, getCMYKNumber, - getDEC, getHEX, getOrderedArrayString, hasProp, minmax, + normalizeAlpha, normalizeHue, percent, - percentNumber, round } from '#helpers'; +import { + CIELabStringParser, + CMYKStringParser, + HEXStringParser, + HSLStringParser, + RGBStringParser +} from '#parsers'; import { cmykToRGB, hslToRGB, @@ -66,18 +76,6 @@ import { CSS } from '#color/css'; type HarmonyFunction = (color: HSLObject, mode: MixString) => HSLObject[]; -//---Normalize alpha -export const normalizeAlpha = (alpha: number | string | undefined | null): number => { - if (typeof alpha === 'string') { - if(PCENT.test(alpha)) { - alpha = percentNumber(alpha) / 100; - } else { - alpha = +alpha; - } - } - return (isNaN(+alpha) || alpha > 1) ? 1 : round(alpha); -}; - //---Harmony const harmony = ( color: HSLObject, @@ -182,75 +180,19 @@ export const getRGBObjectFromString = { const colorStr = !~COLOR_KEYS.indexOf(color) ? color : ColorKeywords[color as keyof typeof ColorKeywords]; - const match = colorStr.match(COLORREGS.HEX) as HEXRegExpMatchArray; - const groups = match.groups; - const object: RGBObject = { - R: getDEC(groups.r ?? groups.rr), - G: getDEC(groups.g ?? groups.gg), - B: getDEC(groups.b ?? groups.bb) - }; - const A = groups.a ?? groups.aa; - if (A !== undefined) { - object.A = getDEC(A) / 255; - } - return object; + return new HEXStringParser(colorStr).rgb; }, [ColorModel.RGB](color: string): RGBObject { - const match = color.match(COLORREGS.RGB) as RGBRegExpMatchArray; - const groups = match.groups; - const R = getBase255Number(groups.r_legacy ?? groups.r); - const G = getBase255Number(groups.g_legacy ?? groups.g); - const B = getBase255Number(groups.b_legacy ?? groups.b); - const A = groups.a_legacy ?? groups.a; - const object: RGBObject = { - R: Math.min(R, 255), - G: Math.min(G, 255), - B: Math.min(B, 255) - }; - if (A !== undefined) { - object.A = normalizeAlpha(A); - } - return object; + return new RGBStringParser(color).rgb; }, [ColorModel.HSL](color: string): RGBObject { - const match = color.match(COLORREGS.HSL) as HSLRegExpMatchArray; - const groups = match.groups; - const H = normalizeHue(groups.h_legacy ?? groups.h); - const S = percent(groups.s_legacy ?? groups.s); - const L = percent(groups.l_legacy ?? groups.l); - const A = groups.a_legacy ?? groups.a; - const RGB = hslToRGB(H, S, L); - if (A !== undefined) { - RGB.A = normalizeAlpha(A); - } - return RGB; + return new HSLStringParser(color).rgb; }, [ColorModel.CIELab](color: string): RGBObject { - const match = color.match(COLORREGS.CIELab) as CIELabRegExpMatchArray; - const groups = match.groups; - const L = percent(groups.L); - const a = getBase125Number(groups.a); - const b = getBase125Number(groups.b); - const A = groups.A; - const RGB = labToRgb(L, a, b); - if (A !== undefined) { - RGB.A = normalizeAlpha(A); - } - return RGB; + return new CIELabStringParser(color).rgb; }, [ColorModel.CMYK](color: string): RGBObject { - const match = color.match(COLORREGS.CMYK) as CMYKRegExpMatchArray; - const groups = match.groups; - const C = getCMYKNumber(groups.c_legacy ?? groups.c); - const M = getCMYKNumber(groups.m_legacy ?? groups.m); - const Y = getCMYKNumber(groups.y_legacy ?? groups.y); - const K = getCMYKNumber(groups.k_legacy ?? groups.k); - const A = groups.a_legacy ?? groups.a; - const RGB = cmykToRGB(C, M, Y, K); - if (A !== undefined) { - RGB.A = normalizeAlpha(A); - } - return RGB; + return new CMYKStringParser(color).rgb; } }; @@ -302,6 +244,148 @@ export const getRGBObjectFromObject = { } }; +export const getOptionsFromColorInput = (options: InputOptions, ...colors: ColorInput[]): Options => { + const cssColors: string[] = []; + const hslColors: AnglesUnitEnum[] = []; + const rgbColors: boolean[] = []; + const labColors: boolean[] = []; + const cmykColors: boolean[] = []; + const alphaValues: boolean[] = []; + const anglesUnitValues = Object.values(AnglesUnitEnum); + const colorUnitValues = Object.values(ColorUnitEnum); + const cmykFunctionValues = Object.values(CMYKFunctionEnum); + + const matchOptions: MatchOptions = { + legacyCSS: 0, + spacesAfterCommas: 0, + cmykFunction: 0 + }; + + for(const color of colors) { + + if (typeof color === 'string') { + + cssColors.push(color); + + if (color.includes(',')){ + matchOptions.legacyCSS ++; + const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS); + if ( + new Set(commasWithNextCharacter).size === 1 && + SPACES.test(commasWithNextCharacter[0].slice(1)) + ) { + matchOptions.spacesAfterCommas ++; + } + } + + if (HSLStringParser.test(color)) { + const parser = new HSLStringParser(color); + hslColors.push(parser.angleUnit); + alphaValues.push( + parser.hasPercentageAlpha + ); + continue; + } + + if (RGBStringParser.test(color)) { + const parser = new RGBStringParser(color); + rgbColors.push( + parser.hasPercentageValues + ); + alphaValues.push( + parser.hasPercentageAlpha + ); + continue; + } + + if (CIELabStringParser.test(color)) { + const parser = new CIELabStringParser(color); + labColors.push( + parser.hasPercentageValues + ); + alphaValues.push( + parser.hasPercentageAlpha + ); + continue; + } + + if (CMYKStringParser.test(color)) { + const parser = new CMYKStringParser(color); + cmykColors.push( + parser.hasPercentageValues + ); + if (color.startsWith('cmyk')) { + matchOptions.cmykFunction ++; + } + alphaValues.push( + parser.hasPercentageAlpha + ); + } + + } + + } + return { + decimals: typeof options.decimals === TypeOf.NUMBER + ? options.decimals + : DEFAULT_OPTIONS.decimals, + legacyCSS: typeof options.legacyCSS === TypeOf.BOOLEAN + ? options.legacyCSS + : Boolean( + cssColors.length && + matchOptions.legacyCSS === cssColors.length + ) || DEFAULT_OPTIONS.legacyCSS, + spacesAfterCommas: typeof options.spacesAfterCommas === TypeOf.BOOLEAN + ? options.spacesAfterCommas + : Boolean( + cssColors.length && + matchOptions.spacesAfterCommas === cssColors.length + ) || DEFAULT_OPTIONS.spacesAfterCommas, + anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit) + ? options.anglesUnit as AnglesUnitEnum + : ( + new Set(hslColors).size === 1 + ? hslColors[0] + : DEFAULT_OPTIONS.anglesUnit + ), + rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit) + ? options.rgbUnit as ColorUnitEnum + : ( + new Set(rgbColors).size === 1 && rgbColors[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.rgbUnit + ), + labUnit: options.labUnit && colorUnitValues.includes(options.labUnit) + ? options.labUnit as ColorUnitEnum + : ( + new Set(labColors).size === 1 && labColors[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.labUnit + ), + cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit) + ? options.cmykUnit as ColorUnitEnum + : ( + new Set(cmykColors).size === 1 && !cmykColors[0] + ? ColorUnitEnum.NONE + : DEFAULT_OPTIONS.cmykUnit + ), + alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit) + ? options.alphaUnit as ColorUnitEnum + : ( + new Set(alphaValues).size === 1 && alphaValues[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.alphaUnit + ), + cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction) + ? options.cmykFunction as CMYKFunctionEnum + : ( + cmykColors.length && cmykColors.length === matchOptions.cmykFunction + ? CMYKFunctionEnum.CMYK + : DEFAULT_OPTIONS.cmykFunction + ) + }; +}; + export const getRGBObject = (color: ColorInput, model: ColorModel = getColorModel(color)): RGBObject => { return typeof color === 'string' ? getRGBObjectFromString[model](color) diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 187720b..b0356de 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,21 +1,10 @@ import { AnglesUnitEnum, AngleUnitRegExpMatchArray, - CIELabRegExpMatchArray, - CMYKFunctionEnum, - CMYKRegExpMatchArray, - ColorInput, - ColorUnitEnum, - HSLRegExpMatchArray, InputOptions, - NumberOrString, - Options, - RGBRegExpMatchArray + NumberOrString } from '@types'; import { - COLORREGS, - COMMAS_AND_NEXT_CHARS, - DEFAULT_OPTIONS, Harmony, HarmonyString, HEX, @@ -23,9 +12,7 @@ import { MAX_DECIMALS, Mix, MixString, - PCENT, - SPACES, - TypeOf + PCENT } from '#constants'; //---Has property @@ -148,6 +135,18 @@ export const normalizeHue = (hue: number | string): number => { return hue; }; +//---Normalize alpha +export const normalizeAlpha = (alpha: number | string | undefined | null): number => { + if (typeof alpha === 'string') { + if(PCENT.test(alpha)) { + alpha = percentNumber(alpha) / 100; + } else { + alpha = +alpha; + } + } + return (isNaN(+alpha) || alpha > 1) ? 1 : round(alpha); +}; + export const translateDegrees = (degrees: number, units: AnglesUnitEnum): number => { let hue: number; @@ -171,181 +170,6 @@ export const translateDegrees = (degrees: number, units: AnglesUnitEnum): number return hue; }; -type MatchOptions = { - [K in keyof Pick]: number; -}; - -export const getOptionsFromColorInput = (options: InputOptions, ...colors: ColorInput[]): Options => { - const cssColors: string[] = []; - const hslColors: AnglesUnitEnum[] = []; - const rgbColors: boolean[] = []; - const labColors: boolean[] = []; - const cmykColors: boolean[] = []; - const alphaValues: boolean[] = []; - const anglesUnitValues = Object.values(AnglesUnitEnum); - const colorUnitValues = Object.values(ColorUnitEnum); - const cmykFunctionValues = Object.values(CMYKFunctionEnum); - - const matchOptions: MatchOptions = { - legacyCSS: 0, - spacesAfterCommas: 0, - cmykFunction: 0 - }; - - for(const color of colors) { - - if (typeof color === 'string') { - - cssColors.push(color); - - if (color.includes(',')){ - matchOptions.legacyCSS ++; - const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS); - if ( - new Set(commasWithNextCharacter).size === 1 && - SPACES.test(commasWithNextCharacter[0].slice(1)) - ) { - matchOptions.spacesAfterCommas ++; - } - } - - if (color.match(COLORREGS.HSL)) { - const match = color.match(COLORREGS.HSL) as HSLRegExpMatchArray; - const groups = match.groups; - const angle = groups.h_legacy ?? groups.h; - const alpha = groups.a_legacy ?? groups.a; - const angleUnitMatch = angle.match(HSL_HUE) as AngleUnitRegExpMatchArray; - const angleUnit = angleUnitMatch.groups.units; - hslColors.push( - angleUnit === '' - ? AnglesUnitEnum.NONE - : angleUnit as AnglesUnitEnum - ); - alphaValues.push( - PCENT.test(alpha) - ); - continue; - } - - if (COLORREGS.RGB.test(color)) { - const match = color.match(COLORREGS.RGB) as RGBRegExpMatchArray; - const groups = match.groups; - const R = groups.r_legacy ?? groups.r; - const G = groups.g_legacy ?? groups.g; - const B = groups.b_legacy ?? groups.b; - const A = groups.a_legacy ?? groups.a; - rgbColors.push( - PCENT.test(R) && - PCENT.test(G) && - PCENT.test(B) - ); - alphaValues.push( - PCENT.test(A) - ); - continue; - } - - if (COLORREGS.CIELab.test(color)) { - const match = color.match(COLORREGS.CIELab) as CIELabRegExpMatchArray; - const groups = match.groups; - const { L, a, b, A } = groups; - labColors.push( - PCENT.test(L) && - PCENT.test(a) && - PCENT.test(b) - ); - alphaValues.push( - PCENT.test(A) - ); - continue; - } - - if (color.match(COLORREGS.CMYK)) { - const match = color.match(COLORREGS.CMYK) as CMYKRegExpMatchArray; - const groups = match.groups; - const C = groups.c_legacy ?? groups.c; - const M = groups.m_legacy ?? groups.m; - const Y = groups.y_legacy ?? groups.y; - const K = groups.k_legacy ?? groups.k; - const A = groups.a_legacy ?? groups.a; - cmykColors.push( - PCENT.test(C) && - PCENT.test(M) && - PCENT.test(Y) && - PCENT.test(K) - ); - if (color.startsWith('cmyk')) { - matchOptions.cmykFunction ++; - } - alphaValues.push( - PCENT.test(A) - ); - } - - } - - } - return { - decimals: typeof options.decimals === TypeOf.NUMBER - ? options.decimals - : DEFAULT_OPTIONS.decimals, - legacyCSS: typeof options.legacyCSS === TypeOf.BOOLEAN - ? options.legacyCSS - : Boolean( - cssColors.length && - matchOptions.legacyCSS === cssColors.length - ) || DEFAULT_OPTIONS.legacyCSS, - spacesAfterCommas: typeof options.spacesAfterCommas === TypeOf.BOOLEAN - ? options.spacesAfterCommas - : Boolean( - cssColors.length && - matchOptions.spacesAfterCommas === cssColors.length - ) || DEFAULT_OPTIONS.spacesAfterCommas, - anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit) - ? options.anglesUnit as AnglesUnitEnum - : ( - new Set(hslColors).size === 1 - ? hslColors[0] - : DEFAULT_OPTIONS.anglesUnit - ), - rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit) - ? options.rgbUnit as ColorUnitEnum - : ( - new Set(rgbColors).size === 1 && rgbColors[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.rgbUnit - ), - labUnit: options.labUnit && colorUnitValues.includes(options.labUnit) - ? options.labUnit as ColorUnitEnum - : ( - new Set(labColors).size === 1 && labColors[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.labUnit - ), - cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit) - ? options.cmykUnit as ColorUnitEnum - : ( - new Set(cmykColors).size === 1 && !cmykColors[0] - ? ColorUnitEnum.NONE - : DEFAULT_OPTIONS.cmykUnit - ), - alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit) - ? options.alphaUnit as ColorUnitEnum - : ( - new Set(alphaValues).size === 1 && alphaValues[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.alphaUnit - ), - cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction) - ? options.cmykFunction as CMYKFunctionEnum - : ( - cmykColors.length && cmykColors.length === matchOptions.cmykFunction - ? CMYKFunctionEnum.CMYK - : DEFAULT_OPTIONS.cmykFunction - ) - }; -}; - export const isHarmony = (param: HarmonyString | MixString | InputOptions): param is HarmonyString => { return `${param}` in Harmony; }; diff --git a/src/index.ts b/src/index.ts index aec10a0..44296a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,7 +33,6 @@ import { import * as utils from '#color/utils'; import { CSS } from '#color/css'; import { - getOptionsFromColorInput, isHarmony, isMix, minmax, @@ -87,7 +86,7 @@ export class ColorTranslator { // Constructor public constructor(color: ColorInput, options: InputOptions = {}) { - this._options = getOptionsFromColorInput(options, color); + this._options = utils.getOptionsFromColorInput(options, color); this.rgb = utils.getRGBObject(color); this.updateHSL(); this.updateLab(); @@ -580,7 +579,7 @@ export class ColorTranslator { public static toRGB(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const rgb = getColorReturn( color, model, @@ -602,7 +601,7 @@ export class ColorTranslator { public static toRGBA(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const rgba = getColorReturn( color, model, @@ -624,7 +623,7 @@ export class ColorTranslator { public static toHSL(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const hsl = getColorReturn( color, model, @@ -646,7 +645,7 @@ export class ColorTranslator { public static toHSLA(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const hsla = getColorReturn( color, model, @@ -668,7 +667,7 @@ export class ColorTranslator { public static toCIELab(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const lab = getColorReturn( color, model, @@ -690,7 +689,7 @@ export class ColorTranslator { public static toCIELabA(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const lab = getColorReturn( color, model, @@ -712,7 +711,7 @@ export class ColorTranslator { public static toCMYK(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const cmyk = getColorReturn( color, model, @@ -734,7 +733,7 @@ export class ColorTranslator { public static toCMYKA(color: ColorInput, options: InputOptions = {}): string { const model = utils.getColorModel(color); - const detectedOptions = getOptionsFromColorInput(options, color); + const detectedOptions = utils.getOptionsFromColorInput(options, color); const cmyka = getColorReturn( color, model, @@ -854,7 +853,7 @@ export class ColorTranslator { .map((color: RGBObject): string => { return CSS.RGB( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -868,7 +867,7 @@ export class ColorTranslator { .map((color: RGBObject): string => { return CSS.RGB( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -936,7 +935,7 @@ export class ColorTranslator { .map((color: RGBObject): string => { return CSS.RGB( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -950,7 +949,7 @@ export class ColorTranslator { .map((color: RGBObject): string => { return CSS.RGB( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -1018,7 +1017,7 @@ export class ColorTranslator { .map((color: HSLObject) => { return CSS.HSL( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -1032,7 +1031,7 @@ export class ColorTranslator { .map((color: HSLObject) => { return CSS.HSL( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -1100,7 +1099,7 @@ export class ColorTranslator { .map((color: HSLObject): string => { return CSS.HSL( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -1114,7 +1113,7 @@ export class ColorTranslator { .map((color: HSLObject): string => { return CSS.HSL( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -1182,7 +1181,7 @@ export class ColorTranslator { .map((color: CIELabObject) => { return CSS.CIELab( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -1196,7 +1195,7 @@ export class ColorTranslator { .map((color: CIELabObject) => { return CSS.CIELab( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -1264,7 +1263,7 @@ export class ColorTranslator { .map((color: CIELabObject) => { return CSS.CIELab( color, - getOptionsFromColorInput(fourthParameter || {}, from, to) + utils.getOptionsFromColorInput(fourthParameter || {}, from, to) ); }); } @@ -1278,7 +1277,7 @@ export class ColorTranslator { .map((color: CIELabObject) => { return CSS.CIELab( color, - getOptionsFromColorInput(thirdParameter || {}, from, to) + utils.getOptionsFromColorInput(thirdParameter || {}, from, to) ); }); } @@ -1319,7 +1318,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1329,7 +1328,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1355,7 +1354,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1365,7 +1364,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1391,7 +1390,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1401,7 +1400,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1427,7 +1426,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1437,7 +1436,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1463,7 +1462,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1473,7 +1472,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1499,7 +1498,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1509,7 +1508,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1535,7 +1534,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1545,7 +1544,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1571,7 +1570,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1581,7 +1580,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1607,7 +1606,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1617,7 +1616,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1643,7 +1642,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1653,7 +1652,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1679,7 +1678,7 @@ export class ColorTranslator { colors, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1689,7 +1688,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1715,7 +1714,7 @@ export class ColorTranslator { colors, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, ...colors ) @@ -1725,7 +1724,7 @@ export class ColorTranslator { colors, Mix.ADDITIVE, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, ...colors ) @@ -1755,7 +1754,7 @@ export class ColorTranslator { color, secondParameter, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, color ) @@ -1765,7 +1764,7 @@ export class ColorTranslator { color, DEFAULT_SHADES_TINTS_STEPS, true, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, color ) @@ -1795,7 +1794,7 @@ export class ColorTranslator { color, secondParameter, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParameter || {}, color ) @@ -1805,7 +1804,7 @@ export class ColorTranslator { color, DEFAULT_SHADES_TINTS_STEPS, false, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParameter || {}, color ) @@ -1850,7 +1849,7 @@ export class ColorTranslator { isMix(thirdParam) ? thirdParam : Mix.ADDITIVE, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( isMix(thirdParam) ? (fourthParam || {}) : thirdParam || {}, @@ -1862,7 +1861,7 @@ export class ColorTranslator { Harmony.COMPLEMENTARY, color, secondParam, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( thirdParam as InputOptions || {}, color ) @@ -1872,7 +1871,7 @@ export class ColorTranslator { Harmony.COMPLEMENTARY, color, Mix.ADDITIVE, - getOptionsFromColorInput( + utils.getOptionsFromColorInput( secondParam || {}, color ) diff --git a/src/parsers/_CIELabStringParser.ts b/src/parsers/_CIELabStringParser.ts new file mode 100644 index 0000000..e65f082 --- /dev/null +++ b/src/parsers/_CIELabStringParser.ts @@ -0,0 +1,56 @@ +import { CIELabRegExpMatchArray, RGBObject } from '@types'; +import { COLORREGS, PCENT } from '#constants'; +import { + getBase125Number, + normalizeAlpha, + percent +} from '#helpers'; +import { labToRgb } from '#color/translators'; + +export class CIELabStringParser { + + constructor(colorString: string) { + const match = colorString.match(COLORREGS.CIELab) as CIELabRegExpMatchArray; + const groups = match.groups; + this._L = groups.L; + this._a = groups.a; + this._b = groups.b; + this._A = groups.A; + const rgb: RGBObject = labToRgb( + percent(this._L), + getBase125Number(this._a), + getBase125Number(this._b) + ); + if (this._A !== undefined) { + rgb.A = normalizeAlpha(this._A); + } + this._rgb = rgb; + } + + private _L: string; + private _a: string; + private _b: string; + private _A: string | undefined; + private _rgb: RGBObject; + + public get rgb(): RGBObject { + return this._rgb; + } + + public get hasPercentageValues(): boolean { + return ( + PCENT.test(this._L) && + PCENT.test(this._a) && + PCENT.test(this._b) + ); + } + + public get hasPercentageAlpha(): boolean { + return PCENT.test(this._A); + } + + static test(colorString: string): boolean { + return COLORREGS.CIELab.test(colorString); + } + +} \ No newline at end of file diff --git a/src/parsers/_CMYKStringParser.ts b/src/parsers/_CMYKStringParser.ts new file mode 100644 index 0000000..97531ee --- /dev/null +++ b/src/parsers/_CMYKStringParser.ts @@ -0,0 +1,57 @@ +import { CMYKRegExpMatchArray, RGBObject } from '@types'; +import { COLORREGS, PCENT } from '#constants'; +import { getCMYKNumber, normalizeAlpha } from '#helpers'; +import { cmykToRGB } from '#color/translators'; + +export class CMYKStringParser { + + constructor(colorString: string) { + const match = colorString.match(COLORREGS.CMYK) as CMYKRegExpMatchArray; + const groups = match.groups; + this._c = groups.c_legacy ?? groups.c; + this._m = groups.m_legacy ?? groups.m; + this._y = groups.y_legacy ?? groups.y; + this._k = groups.k_legacy ?? groups.k; + this._a = groups.a_legacy ?? groups.a; + const rgb: RGBObject = cmykToRGB( + getCMYKNumber(this._c), + getCMYKNumber(this._m), + getCMYKNumber(this._y), + getCMYKNumber(this._k) + ); + if (this._a !== undefined) { + rgb.A = normalizeAlpha(this._a); + } + this._rgb = rgb; + } + + private _c: string; + private _m: string; + private _y: string; + private _k: string; + private _a: string | undefined; + + private _rgb: RGBObject; + + public get rgb(): RGBObject { + return this._rgb; + } + + public get hasPercentageValues(): boolean { + return ( + PCENT.test(this._c) && + PCENT.test(this._m) && + PCENT.test(this._y) && + PCENT.test(this._k) + ); + } + + public get hasPercentageAlpha(): boolean { + return PCENT.test(this._a); + } + + static test(colorString: string): boolean { + return COLORREGS.CMYK.test(colorString); + } + +} \ No newline at end of file diff --git a/src/parsers/_HEXStringParser.ts b/src/parsers/_HEXStringParser.ts new file mode 100644 index 0000000..4b1649b --- /dev/null +++ b/src/parsers/_HEXStringParser.ts @@ -0,0 +1,35 @@ +import { RGBObject, HEXRegExpMatchArray } from '@types'; +import { COLORREGS } from '#constants'; +import { getDEC } from '#helpers'; + +export class HEXStringParser { + + constructor(colorString: string) { + const match = colorString.match(COLORREGS.HEX) as HEXRegExpMatchArray; + const groups = match.groups; + this._r = groups.r ?? groups.rr; + this._g = groups.g ?? groups.gg; + this._b = groups.b ?? groups.bb; + this._a = groups.a ?? groups.aa; + const rgb: RGBObject = { + R: getDEC(this._r), + G: getDEC(this._g), + B: getDEC(this._b) + }; + if (this._a !== undefined) { + rgb.A = getDEC(this._a) / 255; + } + this._rgb = rgb; + } + + private _r: string; + private _g: string; + private _b: string; + private _a: string | undefined; + private _rgb: RGBObject; + + public get rgb(): RGBObject { + return this._rgb; + } + +} \ No newline at end of file diff --git a/src/parsers/_HSLStringParser.ts b/src/parsers/_HSLStringParser.ts new file mode 100644 index 0000000..0d44301 --- /dev/null +++ b/src/parsers/_HSLStringParser.ts @@ -0,0 +1,65 @@ +import { + AnglesUnitEnum, + AngleUnitRegExpMatchArray, + HSLRegExpMatchArray, + RGBObject +} from '@types'; +import { + COLORREGS, + HSL_HUE, + PCENT +} from '#constants'; +import { + normalizeAlpha, + normalizeHue, + percent +} from '#helpers'; +import { hslToRGB } from '#color/translators'; + +export class HSLStringParser { + + constructor(colorString: string) { + const match = colorString.match(COLORREGS.HSL) as HSLRegExpMatchArray; + const groups = match.groups; + this._h = groups.h_legacy ?? groups.h; + this._s = groups.s_legacy ?? groups.s; + this._l = groups.l_legacy ?? groups.l; + this._a = groups.a_legacy ?? groups.a; + const rgb: RGBObject = hslToRGB( + normalizeHue(this._h), + percent(this._s), + percent(this._l) + ); + if (this._a !== undefined) { + rgb.A = normalizeAlpha(this._a); + } + this._rgb = rgb; + } + + private _h: string; + private _s: string; + private _l: string; + private _a: string | undefined; + private _rgb: RGBObject; + + public get rgb(): RGBObject { + return this._rgb; + } + + public get angleUnit(): AnglesUnitEnum { + const angleUnitMatch = this._h.match(HSL_HUE) as AngleUnitRegExpMatchArray; + const angleUnit = angleUnitMatch.groups.units; + return angleUnit === '' + ? AnglesUnitEnum.NONE + : angleUnit as AnglesUnitEnum; + } + + public get hasPercentageAlpha(): boolean { + return PCENT.test(this._a); + } + + static test(colorString: string): boolean { + return COLORREGS.HSL.test(colorString); + } + +} \ No newline at end of file diff --git a/src/parsers/_RGBStringParser.ts b/src/parsers/_RGBStringParser.ts new file mode 100644 index 0000000..0765c66 --- /dev/null +++ b/src/parsers/_RGBStringParser.ts @@ -0,0 +1,61 @@ +import { RGBObject, RGBRegExpMatchArray } from '@types'; +import { COLORREGS, PCENT } from '#constants'; +import { getBase255Number, normalizeAlpha } from '#helpers'; + +export class RGBStringParser { + + constructor(colorString: string) { + const BASE = 255; + const match = colorString.match(COLORREGS.RGB) as RGBRegExpMatchArray; + const groups = match.groups; + this._r = groups.r_legacy ?? groups.r; + this._g = groups.g_legacy ?? groups.g; + this._b = groups.b_legacy ?? groups.b; + this._a = groups.a_legacy ?? groups.a; + const rgb: RGBObject = { + R: Math.min( + getBase255Number(this._r), + BASE + ), + G: Math.min( + getBase255Number(this._g), + BASE + ), + B: Math.min( + getBase255Number(this._b), + BASE + ) + }; + if (this._a !== undefined) { + rgb.A = normalizeAlpha(this._a); + } + this._rgb = rgb; + } + + private _r: string; + private _g: string; + private _b: string; + private _a: string | undefined; + private _rgb: RGBObject; + + public get rgb(): RGBObject { + return this._rgb; + } + + public get hasPercentageValues(): boolean { + return ( + PCENT.test(this._r) && + PCENT.test(this._g) && + PCENT.test(this._b) + ); + } + + public get hasPercentageAlpha(): boolean { + return PCENT.test(this._a); + } + + static test(colorString: string): boolean { + return COLORREGS.RGB.test(colorString); + } + +} \ No newline at end of file diff --git a/src/parsers/index.ts b/src/parsers/index.ts new file mode 100644 index 0000000..c91fc30 --- /dev/null +++ b/src/parsers/index.ts @@ -0,0 +1,5 @@ +export { HEXStringParser } from './_HEXStringParser'; +export { RGBStringParser } from './_RGBStringParser'; +export { HSLStringParser } from './_HSLStringParser'; +export { CIELabStringParser } from './_CIELabStringParser'; +export { CMYKStringParser } from './_CMYKStringParser'; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7cfbba0..9004865 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,8 @@ "@types": ["@types"], "#helpers": ["helpers"], "#constants": ["constants"], - "#color/*": ["color/*"] + "#color/*": ["color/*"], + "#parsers": ["parsers"] } }, "include": ["src/**/*.ts"],