From 3aa9034bee8da21d9ba21a9a5d02eb18d3d9f8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Fri, 12 Jul 2024 17:20:59 +0800 Subject: [PATCH] fix: pure number format (#28) * fix: not prefix color type * fix: logic * chore: reorder for fast match --- src/FastColor.ts | 58 ++++++++++++++++++++++-------------- src/types.ts | 8 ++++- tests/css-rgb-syntax.test.ts | 9 ++++++ 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/FastColor.ts b/src/FastColor.ts index 1af27c5..59f6c2c 100644 --- a/src/FastColor.ts +++ b/src/FastColor.ts @@ -1,4 +1,4 @@ -import type { ColorInput, HSL, HSV, RGB } from './types'; +import type { ColorInput, HSL, HSV, OptionalA, RGB } from './types'; type ParseNumber = (num: number, txt: string, index: number) => number; @@ -76,15 +76,20 @@ export class FastColor { constructor(input: ColorInput) { if (typeof input === 'string') { - const trimed = input.trim(); - if (trimed[0] === '#') { - this.fromHexString(trimed); - } else if (trimed.startsWith('rgb')) { - this.fromRgbString(trimed); - } else if (trimed.startsWith('hsl')) { - this.fromHslString(trimed); - } else if (trimed.startsWith('hsv') || trimed.startsWith('hsb')) { - this.fromHsvString(trimed); + const trimStr = input.trim(); + + function matchPrefix(prefix: string) { + return trimStr.startsWith(prefix); + } + + if (/^#?[A-F\d]{3,8}$/i.test(trimStr)) { + this.fromHexString(trimStr); + } else if (matchPrefix('rgb')) { + this.fromRgbString(trimStr); + } else if (matchPrefix('hsl')) { + this.fromHslString(trimStr); + } else if (matchPrefix('hsv') || matchPrefix('hsb')) { + this.fromHsvString(trimStr); } } else if ('r' in input && 'g' in input && 'b' in input) { this.r = input.r; @@ -401,23 +406,32 @@ export class FastColor { return this._min; } - private fromHexString(trimed: string) { - if (trimed.length < 6) { + private fromHexString(trimStr: string) { + const withoutPrefix = trimStr.replace('#', ''); + + function connectNum(index1: number, index2?: number) { + return parseInt( + withoutPrefix[index1] + withoutPrefix[index2 || index1], + 16, + ); + } + + if (withoutPrefix.length < 6) { // #rgb or #rgba - this.r = parseInt(trimed[1] + trimed[1], 16); - this.g = parseInt(trimed[2] + trimed[2], 16); - this.b = parseInt(trimed[3] + trimed[3], 16); - this.a = trimed[4] ? parseInt(trimed[4] + trimed[4], 16) / 255 : 1; + this.r = connectNum(0); + this.g = connectNum(1); + this.b = connectNum(2); + this.a = withoutPrefix[3] ? connectNum(3) / 255 : 1; } else { // #rrggbb or #rrggbbaa - this.r = parseInt(trimed[1] + trimed[2], 16); - this.g = parseInt(trimed[3] + trimed[4], 16); - this.b = parseInt(trimed[5] + trimed[6], 16); - this.a = trimed[8] ? parseInt(trimed[7] + trimed[8], 16) / 255 : 1; + this.r = connectNum(0, 1); + this.g = connectNum(2, 3); + this.b = connectNum(4, 5); + this.a = withoutPrefix[6] ? connectNum(6, 7) / 255 : 1; } } - private fromHsl({ h, s, l, a }: HSL): void { + private fromHsl({ h, s, l, a }: OptionalA): void { this._h = h % 360; this._s = s; this._l = l; @@ -464,7 +478,7 @@ export class FastColor { this.b = Math.round((this.b + lightnessModification) * 255); } - private fromHsv({ h, s, v, a }: HSV): void { + private fromHsv({ h, s, v, a }: OptionalA): void { this._h = h % 360; this._s = s; this._v = v; diff --git a/src/types.ts b/src/types.ts index 16ae495..ef6194c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -19,4 +19,10 @@ export interface HSV { a: number; } -export type ColorInput = string | RGB | HSL | HSV; +export type OptionalA = Omit & { a?: number }; + +export type ColorInput = + | string + | OptionalA + | OptionalA + | OptionalA; diff --git a/tests/css-rgb-syntax.test.ts b/tests/css-rgb-syntax.test.ts index 564132b..6ccd33c 100644 --- a/tests/css-rgb-syntax.test.ts +++ b/tests/css-rgb-syntax.test.ts @@ -159,4 +159,13 @@ describe('css rgb() syntax', () => { a: 1, }); }); + + it('pure rbg', () => { + expect(new FastColor('FF00FF').toRgb()).toEqual({ + r: 255, + g: 0, + b: 255, + a: 1, + }); + }); });