diff --git a/toolkit/devtools/css-color.js b/toolkit/devtools/css-color.js index 45340bd7447b..561240cfe6e3 100644 --- a/toolkit/devtools/css-color.js +++ b/toolkit/devtools/css-color.js @@ -57,7 +57,8 @@ function CssColor(colorValue) { module.exports.colorUtils = { CssColor: CssColor, rgbToHsl: rgbToHsl, - setAlpha: setAlpha + setAlpha: setAlpha, + classifyColor: classifyColor }; /** @@ -74,7 +75,10 @@ CssColor.COLORUNIT = { CssColor.prototype = { _colorUnit: null, + // The value as-authored. authored: null, + // A lower-cased copy of |authored|. + lowerCased: null, get colorUnit() { if (this._colorUnit === null) { @@ -112,7 +116,7 @@ CssColor.prototype = { }, get specialValue() { - return SPECIALVALUES.has(this.authored) ? this.authored : null; + return SPECIALVALUES.has(this.lowerCased) ? this.authored : null; }, get name() { @@ -171,8 +175,8 @@ CssColor.prototype = { return invalidOrSpecialValue; } if (!this.hasAlpha) { - if (this.authored.startsWith("rgb(")) { - // The color is valid and begins with rgb(. Return the authored value. + if (this.lowerCased.startsWith("rgb(")) { + // The color is valid and begins with rgb(. return this.authored; } let tuple = this._getRGBATuple(); @@ -186,8 +190,8 @@ CssColor.prototype = { if (invalidOrSpecialValue !== false) { return invalidOrSpecialValue; } - if (this.authored.startsWith("rgba(")) { - // The color is valid and begins with rgba(. Return the authored value. + if (this.lowerCased.startsWith("rgba(")) { + // The color is valid and begins with rgba(. return this.authored; } let components = this._getRGBATuple(); @@ -202,8 +206,8 @@ CssColor.prototype = { if (invalidOrSpecialValue !== false) { return invalidOrSpecialValue; } - if (this.authored.startsWith("hsl(")) { - // The color is valid and begins with hsl(. Return the authored value. + if (this.lowerCased.startsWith("hsl(")) { + // The color is valid and begins with hsl(. return this.authored; } if (this.hasAlpha) { @@ -217,8 +221,8 @@ CssColor.prototype = { if (invalidOrSpecialValue !== false) { return invalidOrSpecialValue; } - if (this.authored.startsWith("hsla(")) { - // The color is valid and begins with hsla(. Return the authored value. + if (this.lowerCased.startsWith("hsla(")) { + // The color is valid and begins with hsla(. return this.authored; } if (this.hasAlpha) { @@ -256,7 +260,11 @@ CssColor.prototype = { * Any valid color string */ newColor: function(color) { - this.authored = color.toLowerCase(); + // Store a lower-cased version of the color to help with format + // testing. The original text is kept as well so it can be + // returned when needed. + this.lowerCased = color.toLowerCase(); + this.authored = color; return this; }, @@ -319,7 +327,7 @@ CssColor.prototype = { }, _hsl: function(maybeAlpha) { - if (this.authored.startsWith("hsl(") && maybeAlpha === undefined) { + if (this.lowerCased.startsWith("hsl(") && maybeAlpha === undefined) { // We can use it as-is. return this.authored; } @@ -415,6 +423,27 @@ function setAlpha(colorValue, alpha) { return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")"; } +/** + * Given a color, classify its type as one of the possible color + * units, as known by |CssColor.colorUnit|. + * + * @param {String} value + * The color, in any form accepted by CSS. + * @return {String} + * The color classification, one of "rgb", "hsl", "hex", or "name". + */ +function classifyColor(value) { + value = value.toLowerCase(); + if (value.startsWith("rgb(") || value.startsWith("rgba(")) { + return CssColor.COLORUNIT.rgb; + } else if (value.startsWith("hsl(") || value.startsWith("hsla(")) { + return CssColor.COLORUNIT.hsl; + } else if (/^#[0-9a-f]+$/.exec(value)) { + return CssColor.COLORUNIT.hex; + } + return CssColor.COLORUNIT.name; +} + loader.lazyGetter(this, "DOMUtils", function () { return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils); }); diff --git a/toolkit/devtools/tests/unit/test_cssColor.js b/toolkit/devtools/tests/unit/test_cssColor.js new file mode 100644 index 000000000000..b3e10a1c81ba --- /dev/null +++ b/toolkit/devtools/tests/unit/test_cssColor.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test classifyColor. + +"use strict"; + +const loader = new DevToolsLoader(); +const require = loader.require; +const {colorUtils} = require("devtools/css-color"); + +const CLASSIFY_TESTS = [ + { input: "rgb(255,0,192)", output: "rgb" }, + { input: "RGB(255,0,192)", output: "rgb" }, + { input: "rgba(255,0,192, 0.25)", output: "rgb" }, + { input: "hsl(5, 5, 5)", output: "hsl" }, + { input: "hsla(5, 5, 5, 0.25)", output: "hsl" }, + { input: "hSlA(5, 5, 5, 0.25)", output: "hsl" }, + { input: "#f0c", output: "hex" }, + { input: "#fe01cb", output: "hex" }, + { input: "#FE01CB", output: "hex" }, + { input: "blue", output: "name" }, + { input: "orange", output: "name" } +]; + +function run_test() { + for (let test of CLASSIFY_TESTS) { + let result = colorUtils.classifyColor(test.input); + equal(result, test.output, "test classifyColor(" + test.input + ")"); + } +} diff --git a/toolkit/devtools/tests/unit/xpcshell.ini b/toolkit/devtools/tests/unit/xpcshell.ini index 94340145804d..9a1eafa729e8 100644 --- a/toolkit/devtools/tests/unit/xpcshell.ini +++ b/toolkit/devtools/tests/unit/xpcshell.ini @@ -16,6 +16,7 @@ support-files = [test_defineLazyPrototypeGetter.js] [test_async-utils.js] [test_consoleID.js] +[test_cssColor.js] [test_prettifyCSS.js] [test_require_lazy.js] [test_require.js]