fix: css faster color parsing

This commit is contained in:
Martin Guillon
2021-08-07 15:14:24 +02:00
parent e2f579aa1b
commit 2005bd5927
2 changed files with 19 additions and 68 deletions

View File

@ -4,7 +4,6 @@ import { getKnownColor } from '../color/known-colors';
export type Parsed<V> = { start: number; end: number; value: V }; export type Parsed<V> = { start: number; end: number; value: V };
// Values // Values
export type ARGB = number;
export type URL = string; export type URL = string;
export type Angle = number; export type Angle = number;
export interface Unit<T> { export interface Unit<T> {
@ -16,7 +15,7 @@ export type Percentage = Unit<'%'>;
export type LengthPercentage = Length | Percentage; export type LengthPercentage = Length | Percentage;
export type Keyword = string; export type Keyword = string;
export interface ColorStop { export interface ColorStop {
argb: ARGB; color: Color;
offset?: LengthPercentage; offset?: LengthPercentage;
} }
export interface LinearGradient { export interface LinearGradient {
@ -68,49 +67,31 @@ export function parseURL(text: string, start = 0): Parsed<URL> {
return { start, end, value }; return { start, end, value };
} }
const hexColorRegEx = /\s*#((?:[0-9A-F]{8})|(?:[0-9A-F]{6})|(?:[0-9A-F]{3}))\s*/giy; const hexColorRegEx = /\s*#((?:[0-9A-F]{8})|(?:[0-9A-F]{6})|(?:[0-9A-F]{4})|(?:[0-9A-F]{3}))\s*/giy;
export function parseHexColor(text: string, start = 0): Parsed<ARGB> { export function parseHexColor(text: string, start = 0): Parsed<Color> {
hexColorRegEx.lastIndex = start; hexColorRegEx.lastIndex = start;
const result = hexColorRegEx.exec(text); const result = hexColorRegEx.exec(text);
if (!result) { if (!result) {
return null; return null;
} }
const end = hexColorRegEx.lastIndex; const end = hexColorRegEx.lastIndex;
return { start, end, value: new Color('#'+ result[1]).argb }; return { start, end, value: new Color('#'+ result[1]) };
} }
function rgbaToArgbNumber(r: number, g: number, b: number, a = 1): number | undefined { const cssColorRegEx = /\s*((?:rgb|rgba|hsl|hsla|hsv|hsva)\([^\(\)]\))/gy;
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) { export function parseCssColor(text: string, start = 0): Parsed<Color> {
return Math.round(a * 0xff) * 0x01000000 + r * 0x010000 + g * 0x000100 + b; cssColorRegEx.lastIndex = start;
} else { const result = cssColorRegEx.exec(text);
return null;
}
}
const rgbColorRegEx = /\s*(rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\))/gy;
export function parseRGBColor(text: string, start = 0): Parsed<ARGB> {
rgbColorRegEx.lastIndex = start;
const result = rgbColorRegEx.exec(text);
if (!result) { if (!result) {
return null; return null;
} }
const end = rgbColorRegEx.lastIndex; const end = cssColorRegEx.lastIndex;
const value = result[1] && rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4])); try {
return { start, end, value: new Color(text) };
return { start, end, value }; } catch {
}
const rgbaColorRegEx = /\s*(rgba\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*,\s*([01]?\.?\d*)\s*\))/gy;
export function parseRGBAColor(text: string, start = 0): Parsed<ARGB> {
rgbaColorRegEx.lastIndex = start;
const result = rgbaColorRegEx.exec(text);
if (!result) {
return null; return null;
} }
const end = rgbaColorRegEx.lastIndex;
const value = rgbaToArgbNumber(parseInt(result[2]), parseInt(result[3]), parseInt(result[4]), parseFloat(result[5]));
return { start, end, value };
} }
export function convertHSLToRGBColor(hue: number, saturation: number, lightness: number): { r: number; g: number; b: number } { export function convertHSLToRGBColor(hue: number, saturation: number, lightness: number): { r: number; g: number; b: number } {
@ -151,49 +132,19 @@ export function convertHSLToRGBColor(hue: number, saturation: number, lightness:
}; };
} }
function hslaToArgbNumber(h: number, s: number, l: number, a = 1): number | undefined {
const { r, g, b } = convertHSLToRGBColor(h, s, l);
return rgbaToArgbNumber(r, g, b, a);
}
const hslColorRegEx = /\s*(hsl\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*\))/gy; export function parseColorKeyword(value, start: number, keyword = parseKeyword(value, start)): Parsed<Color> {
export function parseHSLColor(text: string, start = 0): Parsed<ARGB> {
hslColorRegEx.lastIndex = start;
const result = hslColorRegEx.exec(text);
if (!result) {
return null;
}
const end = hslColorRegEx.lastIndex;
const value = result[1] && hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
return { start, end, value };
}
const hslaColorRegEx = /\s*(hsla\(\s*([\d.]*)\s*,\s*([\d.]*)%\s*,\s*([\d.]*)%\s*,\s*([01]?\.?\d*)\s*\))/gy;
export function parseHSLAColor(text: string, start = 0): Parsed<ARGB> {
hslaColorRegEx.lastIndex = start;
const result = hslaColorRegEx.exec(text);
if (!result) {
return null;
}
const end = hslaColorRegEx.lastIndex;
const value = hslaToArgbNumber(parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]), parseFloat(result[5]));
return { start, end, value };
}
export function parseColorKeyword(value, start: number, keyword = parseKeyword(value, start)): Parsed<ARGB> {
const parseColor = keyword && getKnownColor(keyword.value); const parseColor = keyword && getKnownColor(keyword.value);
if (parseColor != null) { if (parseColor != null) {
const end = keyword.end; const end = keyword.end;
const value = parseColor; const value = parseColor;
return { start, end, value }; return { start, end, value: new Color(parseColor) };
} }
return null; return null;
} }
export function parseColor(value: string, start = 0, keyword = parseKeyword(value, start)): Parsed<ARGB> { export function parseColor(value: string, start = 0, keyword = parseKeyword(value, start)): Parsed<Color> {
return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseRGBColor(value, start) || parseRGBAColor(value, start) || parseHSLColor(value, start) || parseHSLAColor(value, start); return parseHexColor(value, start) || parseColorKeyword(value, start, keyword) || parseCssColor(value, start);
} }
const keywordRegEx = /\s*([a-z][\w\-]*)\s*/giy; const keywordRegEx = /\s*([a-z][\w\-]*)\s*/giy;
@ -549,11 +500,11 @@ export function parseColorStop(text: string, start = 0): Parsed<ColorStop> {
return { return {
start, start,
end, end,
value: { argb: color.value, offset: offset.value }, value: { color: color.value, offset: offset.value },
}; };
} }
return { start, end, value: { argb: color.value } }; return { start, end, value: { color: color.value } };
} }
const linearGradientStartRegEx = /\s*linear-gradient\s*/gy; const linearGradientStartRegEx = /\s*linear-gradient\s*/gy;

View File

@ -22,7 +22,7 @@ export class LinearGradient {
} }
return { return {
color: new Color(color.argb), color: color.color,
offset: offsetUnit, offset: offsetUnit,
}; };
}); });