зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1302787 - Add a mode for css-color-4 color parser to accept the old style syntax only. r=tromey
--HG-- extra : rebase_source : 089e0201bfa832848b0230a44b19753a1b2206fd extra : histedit_source : 84e737082baf5c52e891187d9073202235f35e93
This commit is contained in:
Родитель
995689ff27
Коммит
b1c8f17089
|
@ -704,36 +704,54 @@ function expectSymbol(lexer, symbol) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const COLOR_COMPONENT_TYPE = {
|
||||
"integer": "integer",
|
||||
"number": "number",
|
||||
"percentage": "percentage",
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a <number> or a <percentage> color component. If |separator| is
|
||||
* provided (not an empty string ""), this function will also attempt to parse that
|
||||
* character after parsing the color component. The range of output component
|
||||
* value is [0, 1] if the "isPercentage" is true. Otherwise, the range is
|
||||
* [0, 255].
|
||||
* Parse a <integer> or a <number> or a <percentage> color component. If
|
||||
* |separator| is provided (not an empty string ""), this function will also
|
||||
* attempt to parse that character after parsing the color component. The range
|
||||
* of output component value is [0, 1] if the component type is percentage.
|
||||
* Otherwise, the range is [0, 255].
|
||||
*
|
||||
* @param {CSSLexer} lexer The lexer.
|
||||
* @param {Boolean} isPercentage The color component is <percentage> or not.
|
||||
* @param {COLOR_COMPONENT_TYPE} type The color component type.
|
||||
* @param {String} separator The separator.
|
||||
* @param {Array} colorArray [out] The parsed color component will push into this array.
|
||||
* @return {Boolean} Return false on error.
|
||||
*/
|
||||
function parseColorComponent(lexer, isPercentage, separator, colorArray) {
|
||||
function parseColorComponent(lexer, type, separator, colorArray) {
|
||||
let token = getToken(lexer);
|
||||
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isPercentage) {
|
||||
if (token.tokenType !== "percentage") {
|
||||
return false;
|
||||
}
|
||||
} else if (token.tokenType !== "number") {
|
||||
return false;
|
||||
switch (type) {
|
||||
case COLOR_COMPONENT_TYPE.integer:
|
||||
if (token.tokenType !== "number" || !token.isInteger) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case COLOR_COMPONENT_TYPE.number:
|
||||
if (token.tokenType !== "number") {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case COLOR_COMPONENT_TYPE.percentage:
|
||||
if (token.tokenType !== "percentage") {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid color component type.");
|
||||
}
|
||||
|
||||
let colorComponent = 0;
|
||||
if (isPercentage) {
|
||||
if (type === COLOR_COMPONENT_TYPE.percentage) {
|
||||
colorComponent = clamp(token.number, 0, 1);
|
||||
} else {
|
||||
colorComponent = clamp(token.number, 0, 255);
|
||||
|
@ -855,8 +873,9 @@ function parseHsl(lexer) {
|
|||
// version of parseColorComponent function for them. No need to check the
|
||||
// separator after 'lightness'. It will be checked in opacity value parsing.
|
||||
let separatorBeforeAlpha = hasComma ? commaSeparator : "/";
|
||||
if (parseColorComponent(lexer, true, hasComma ? commaSeparator : "", hsl) &&
|
||||
parseColorComponent(lexer, true, "", hsl) &&
|
||||
if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
hasComma ? commaSeparator : "", hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage, "", hsl) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, a)) {
|
||||
return [...hslToRGB(hsl), ...a];
|
||||
}
|
||||
|
@ -864,6 +883,59 @@ function parseHsl(lexer) {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to parse the color arguments of old style hsl()/hsla()
|
||||
* function.
|
||||
*
|
||||
* @param {CSSLexer} lexer The lexer.
|
||||
* @param {Boolean} hasAlpha The color function has alpha component or not.
|
||||
* @return {Array} An array of the form [r,g,b,a]; or null on error.
|
||||
*/
|
||||
function parseOldStyleHsl(lexer, hasAlpha) {
|
||||
// hsla() = hsla( <hue>, <saturation>, <lightness>, <alpha-value> )
|
||||
// hsl() = hsl( <hue>, <saturation>, <lightness> )
|
||||
//
|
||||
// <hue> = <number>
|
||||
// <alpha-value> = <number>
|
||||
|
||||
const commaSeparator = ",";
|
||||
const closeParen = ")";
|
||||
let hsl = [];
|
||||
let a = [];
|
||||
|
||||
// Parse hue.
|
||||
let token = getToken(lexer);
|
||||
if (!token || token.tokenType !== "number") {
|
||||
return null;
|
||||
}
|
||||
if (!expectSymbol(lexer, commaSeparator)) {
|
||||
return null;
|
||||
}
|
||||
let val = token.number / 360.0;
|
||||
hsl.push(val - Math.floor(val));
|
||||
|
||||
// Parse saturation, lightness and opacity.
|
||||
// The saturation and lightness are <percentage>, so reuse the <percentage>
|
||||
// version of parseColorComponent function for them. The opacity is <number>
|
||||
if (hasAlpha) {
|
||||
if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number,
|
||||
closeParen, a)) {
|
||||
return [...hslToRGB(hsl), ...a];
|
||||
}
|
||||
} else if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
closeParen, hsl)) {
|
||||
return [...hslToRGB(hsl), 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to parse the color arguments of rgb()/rgba() function.
|
||||
* rgb() and rgba() now are aliases.
|
||||
|
@ -888,10 +960,12 @@ function parseRgb(lexer) {
|
|||
return null;
|
||||
}
|
||||
unGetToken(lexer);
|
||||
let isPercentage = token.tokenType === "percentage";
|
||||
let type = (token.tokenType === "percentage") ?
|
||||
COLOR_COMPONENT_TYPE.percentage :
|
||||
COLOR_COMPONENT_TYPE.number;
|
||||
|
||||
// Parse R.
|
||||
if (!parseColorComponent(lexer, isPercentage, "", rgba)) {
|
||||
if (!parseColorComponent(lexer, type, "", rgba)) {
|
||||
return null;
|
||||
}
|
||||
let hasComma = expectSymbol(lexer, commaSeparator);
|
||||
|
@ -900,10 +974,10 @@ function parseRgb(lexer) {
|
|||
// No need to check the separator after 'B'. It will be checked in 'A' values
|
||||
// parsing.
|
||||
let separatorBeforeAlpha = hasComma ? commaSeparator : "/";
|
||||
if (parseColorComponent(lexer, isPercentage, hasComma ? commaSeparator : "", rgba) &&
|
||||
parseColorComponent(lexer, isPercentage, "", rgba) &&
|
||||
if (parseColorComponent(lexer, type, hasComma ? commaSeparator : "", rgba) &&
|
||||
parseColorComponent(lexer, type, "", rgba) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, rgba)) {
|
||||
if (isPercentage) {
|
||||
if (type === COLOR_COMPONENT_TYPE.percentage) {
|
||||
rgba[0] = Math.round(255 * rgba[0]);
|
||||
rgba[1] = Math.round(255 * rgba[1]);
|
||||
rgba[2] = Math.round(255 * rgba[2]);
|
||||
|
@ -914,15 +988,73 @@ function parseRgb(lexer) {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to parse the color arguments of old style rgb()/rgba()
|
||||
* function.
|
||||
*
|
||||
* @param {CSSLexer} lexer The lexer.
|
||||
* @param {Boolean} hasAlpha The color function has alpha component or not.
|
||||
* @return {Array} An array of the form [r,g,b,a]; or null on error.
|
||||
*/
|
||||
function parseOldStyleRgb(lexer, hasAlpha) {
|
||||
// rgba() = rgba( component#{3} , <alpha-value> )
|
||||
// rgb() = rgb( component#{3} )
|
||||
//
|
||||
// component = <integer> | <percentage>
|
||||
// <alpha-value> = <number>
|
||||
|
||||
const commaSeparator = ",";
|
||||
const closeParen = ")";
|
||||
let rgba = [];
|
||||
|
||||
let token = getToken(lexer);
|
||||
if (token.tokenType !== "percentage" &&
|
||||
(token.tokenType !== "number" || !token.isInteger)) {
|
||||
return null;
|
||||
}
|
||||
unGetToken(lexer);
|
||||
let type = (token.tokenType === "percentage") ?
|
||||
COLOR_COMPONENT_TYPE.percentage :
|
||||
COLOR_COMPONENT_TYPE.integer;
|
||||
|
||||
// Parse R. G, B and A.
|
||||
if (hasAlpha) {
|
||||
if (!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number,
|
||||
closeParen, rgba)) {
|
||||
return null;
|
||||
}
|
||||
} else if (!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, closeParen, rgba)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type === COLOR_COMPONENT_TYPE.percentage) {
|
||||
rgba[0] = Math.round(255 * rgba[0]);
|
||||
rgba[1] = Math.round(255 * rgba[1]);
|
||||
rgba[2] = Math.round(255 * rgba[2]);
|
||||
}
|
||||
if (!hasAlpha) {
|
||||
rgba.push(1);
|
||||
}
|
||||
|
||||
return rgba;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string representing a color to an object holding the
|
||||
* color's components. Any valid CSS color form can be passed in.
|
||||
*
|
||||
* @param {String} name the color
|
||||
* @param {Boolean} oldColorFunctionSyntax use old color function syntax or the
|
||||
* css-color-4 syntax
|
||||
* @return {Object} an object of the form {r, g, b, a}; or null if the
|
||||
* name was not a valid color
|
||||
*/
|
||||
function colorToRGBA(name) {
|
||||
function colorToRGBA(name, oldColorFunctionSyntax = true) {
|
||||
name = name.trim().toLowerCase();
|
||||
|
||||
if (name in cssColors) {
|
||||
|
@ -956,7 +1088,14 @@ function colorToRGBA(name) {
|
|||
|
||||
let hsl = func.text === "hsl" || func.text === "hsla";
|
||||
|
||||
let vals = hsl ? parseHsl(lexer) : parseRgb(lexer);
|
||||
let vals;
|
||||
if (oldColorFunctionSyntax) {
|
||||
let hasAlpha = (func.text === "rgba" || func.text === "hsla");
|
||||
vals = hsl ? parseOldStyleHsl(lexer, hasAlpha) : parseOldStyleRgb(lexer, hasAlpha);
|
||||
} else {
|
||||
vals = hsl ? parseHsl(lexer) : parseRgb(lexer);
|
||||
}
|
||||
|
||||
if (!vals) {
|
||||
return null;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче