Bug 1310681 - pass css-color-4 color function supporting info to devtool css OutputParser and SwatchColorPickerTooltip. r?tromey
Pass css-color-4 supporting status from css-property db to OutputParser and SwatchColorPickerTooltip.
MozReview-Commit-ID: N1ffWOlf9f
--- a/devtools/client/inspector/shared/tooltips-overlay.js
+++ b/devtools/client/inspector/shared/tooltips-overlay.js
@@ -83,17 +83,19 @@ TooltipsOverlay.prototype = {
this.previewTooltip.startTogglingOnHover(this.view.element,
this._onPreviewTooltipTargetHover.bind(this));
// MDN CSS help tooltip
this.cssDocs = new CssDocsTooltip(toolbox.doc);
if (this.isRuleView) {
// Color picker tooltip
- this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc, this.view.inspector);
+ this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc,
+ this.view.inspector,
+ this._cssProperties);
// Cubic bezier tooltip
this.cubicBezier = new SwatchCubicBezierTooltip(toolbox.doc);
// Filter editor tooltip
this.filterEditor = new SwatchFilterTooltip(toolbox.doc,
this._cssProperties.getValidityChecker(this.view.inspector.panelDoc));
}
this._isStarted = true;
--- a/devtools/client/shared/output-parser.js
+++ b/devtools/client/shared/output-parser.js
@@ -35,26 +35,31 @@ const CSS_GRID_ENABLED_PREF = "layout.cs
*
* @param {Document} document Used to create DOM nodes.
* @param {Function} supportsTypes - A function that returns a boolean when asked if a css
* property name supports a given css type.
* The function is executed like supportsType("color", CSS_TYPES.COLOR)
* where CSS_TYPES is defined in devtools/shared/css/properties-db.js
* @param {Function} isValidOnClient - A function that checks if a css property
* name/value combo is valid.
+ * @param {Function} supportsCssColor4ColorFunction - A function for checking
+ * the supporting of css-color-4 color function.
*/
-function OutputParser(document, {supportsType, isValidOnClient}) {
+function OutputParser(document,
+ {supportsType, isValidOnClient, supportsCssColor4ColorFunction}) {
this.parsed = [];
this.doc = document;
this.supportsType = supportsType;
this.isValidOnClient = isValidOnClient;
this.colorSwatches = new WeakMap();
this.angleSwatches = new WeakMap();
this._onColorSwatchMouseDown = this._onColorSwatchMouseDown.bind(this);
this._onAngleSwatchMouseDown = this._onAngleSwatchMouseDown.bind(this);
+
+ this.cssColor4 = supportsCssColor4ColorFunction();
}
OutputParser.prototype = {
/**
* Parse a CSS property value given a property name.
*
* @param {String} name
* CSS Property Name
@@ -181,47 +186,49 @@ OutputParser.prototype = {
}
++parenDepth;
} else {
let functionText = this._collectFunctionText(token, text,
tokenStream);
if (options.expectCubicBezier && token.text === "cubic-bezier") {
this._appendCubicBezier(functionText, options);
- } else if (colorOK() && colorUtils.isValidCSSColor(functionText)) {
+ } else if (colorOK() &&
+ colorUtils.isValidCSSColor(functionText, this.cssColor4)) {
this._appendColor(functionText, options);
} else {
this._appendTextNode(functionText);
}
}
break;
}
case "ident":
if (options.expectCubicBezier &&
BEZIER_KEYWORDS.indexOf(token.text) >= 0) {
this._appendCubicBezier(token.text, options);
} else if (Services.prefs.getBoolPref(CSS_GRID_ENABLED_PREF) &&
options.expectDisplay && token.text === "grid" &&
text === token.text) {
this._appendGrid(token.text, options);
- } else if (colorOK() && colorUtils.isValidCSSColor(token.text)) {
+ } else if (colorOK() &&
+ colorUtils.isValidCSSColor(token.text, this.cssColor4)) {
this._appendColor(token.text, options);
} else if (angleOK(token.text)) {
this._appendAngle(token.text, options);
} else {
this._appendTextNode(text.substring(token.startOffset,
token.endOffset));
}
break;
case "id":
case "hash": {
let original = text.substring(token.startOffset, token.endOffset);
- if (colorOK() && colorUtils.isValidCSSColor(original)) {
+ if (colorOK() && colorUtils.isValidCSSColor(original, this.cssColor4)) {
this._appendColor(original, options);
} else {
this._appendTextNode(original);
}
break;
}
case "dimension":
let value = text.substring(token.startOffset, token.endOffset);
@@ -387,17 +394,17 @@ OutputParser.prototype = {
*
* @param {String} color
* Color to append
* @param {Object} [options]
* Options object. For valid options and default values see
* _mergeOptions().
*/
_appendColor: function (color, options = {}) {
- let colorObj = new colorUtils.CssColor(color);
+ let colorObj = new colorUtils.CssColor(color, this.cssColor4);
if (this._isValidColor(colorObj)) {
let container = this._createNode("span", {
"data-color": color
});
if (options.colorSwatchClass) {
let swatch = this._createNode("span", {
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -23,28 +23,33 @@ const XHTML_NS = "http://www.w3.org/1999
* color picker.
*
* @param {Document} document
* The document to attach the SwatchColorPickerTooltip. This is either the toolbox
* document if the tooltip is a popup tooltip or the panel's document if it is an
* inline editor.
* @param {InspectorPanel} inspector
* The inspector panel, needed for the eyedropper.
+ * @param {Function} supportsCssColor4ColorFunction
+ * A function for checking the supporting of css-color-4 color function.
*/
-function SwatchColorPickerTooltip(document, inspector) {
+function SwatchColorPickerTooltip(document,
+ inspector,
+ {supportsCssColor4ColorFunction}) {
let stylesheet = "chrome://devtools/content/shared/widgets/spectrum.css";
SwatchBasedEditorTooltip.call(this, document, stylesheet);
this.inspector = inspector;
// Creating a spectrum instance. this.spectrum will always be a promise that
// resolves to the spectrum instance
this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
this._openEyeDropper = this._openEyeDropper.bind(this);
+ this.cssColor4 = supportsCssColor4ColorFunction();
}
SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
/**
* Fill the tooltip with a new instance of the spectrum color picker widget
* initialized with the given color, and return the instance of spectrum
*/
setColorPickerContent: function (color) {
@@ -152,24 +157,24 @@ SwatchColorPickerTooltip.prototype = Her
},
_onEyeDropperDone: function () {
this.eyedropperOpen = false;
this.activeSwatch = null;
},
_colorToRgba: function (color) {
- color = new colorUtils.CssColor(color);
+ color = new colorUtils.CssColor(color, this.cssColor4);
let rgba = color._getRGBATuple();
return [rgba.r, rgba.g, rgba.b, rgba.a];
},
_toDefaultType: function (color) {
let colorObj = new colorUtils.CssColor(color);
- colorObj.setAuthoredUnitFromColor(this._originalColor);
+ colorObj.setAuthoredUnitFromColor(this._originalColor, this.cssColor4);
return colorObj.toString();
},
destroy: function () {
SwatchBasedEditorTooltip.prototype.destroy.call(this);
this.inspector = null;
this.currentSwatchColor = null;
this.spectrum.off("changed", this._onSpectrumColorChange);
--- a/devtools/shared/css/color.js
+++ b/devtools/shared/css/color.js
@@ -23,16 +23,20 @@ const SPECIALVALUES = new Set([
]);
/**
* This module is used to convert between various color types.
*
* Usage:
* let {colorUtils} = require("devtools/shared/css/color");
* let color = new colorUtils.CssColor("red");
+ * // In order to support css-color-4 color function, pass true to the
+ * // second argument.
+ * // e.g.
+ * // let color = new colorUtils.CssColor("red", true);
*
* color.authored === "red"
* color.hasAlpha === false
* color.valid === true
* color.transparent === false // transparent has a special status.
* color.name === "red" // returns hex when no name available.
* color.hex === "#f00" // returns shortHex when available else returns
* longHex. If alpha channel is present then we
@@ -53,18 +57,19 @@ const SPECIALVALUES = new Set([
* color.toString() === "#f00"; // Outputs the color type determined in the
* COLOR_UNIT_PREF constant (above).
* // Color objects can be reused
* color.newColor("green") === "#0f0"; // true
*
* Valid values for COLOR_UNIT_PREF are contained in CssColor.COLORUNIT.
*/
-function CssColor(colorValue) {
+function CssColor(colorValue, supportsCssColor4ColorFunction = false) {
this.newColor(colorValue);
+ this.cssColor4 = supportsCssColor4ColorFunction;
}
module.exports.colorUtils = {
CssColor: CssColor,
rgbToHsl: rgbToHsl,
setAlpha: setAlpha,
classifyColor: classifyColor,
rgbToColorName: rgbToColorName,
@@ -87,16 +92,19 @@ CssColor.prototype = {
_colorUnit: null,
_colorUnitUppercase: false,
// The value as-authored.
authored: null,
// A lower-cased copy of |authored|.
lowerCased: null,
+ // Whether the value should be parsed using css-color-4 rules.
+ cssColor4: false,
+
_setColorUnitUppercase: function (color) {
// Specifically exclude the case where the color is
// case-insensitive. This makes it so that "#000" isn't
// considered "upper case" for the purposes of color cycling.
this._colorUnitUppercase = (color === color.toUpperCase()) &&
(color !== color.toLowerCase());
},
@@ -131,17 +139,17 @@ CssColor.prototype = {
get hasAlpha() {
if (!this.valid) {
return false;
}
return this._getRGBATuple().a !== 1;
},
get valid() {
- return isValidCSSColor(this.authored);
+ return isValidCSSColor(this.authored, this.cssColor4);
},
/**
* Return true for all transparent values e.g. rgba(0, 0, 0, 0).
*/
get transparent() {
try {
let tuple = this._getRGBATuple();
@@ -388,17 +396,17 @@ CssColor.prototype = {
return color;
},
/**
* Returns a RGBA 4-Tuple representation of a color or transparent as
* appropriate.
*/
_getRGBATuple: function () {
- let tuple = colorToRGBA(this.authored);
+ let tuple = colorToRGBA(this.authored, this.cssColor4);
tuple.a = parseFloat(tuple.a.toFixed(1));
return tuple;
},
_hsl: function (maybeAlpha) {
if (this.lowerCased.startsWith("hsl(") && maybeAlpha === undefined) {
@@ -476,21 +484,23 @@ function roundTo(number, digits) {
* Takes a color value of any type (hex, hsl, hsla, rgb, rgba)
* and an alpha value to generate an rgba string with the correct
* alpha value.
*
* @param {String} colorValue
* Color in the form of hex, hsl, hsla, rgb, rgba.
* @param {Number} alpha
* Alpha value for the color, between 0 and 1.
+ * @param {Boolean} useCssColor4ColorFunction
+ * use css-color-4 color function or not.
* @return {String}
* Converted color with `alpha` value in rgba form.
*/
-function setAlpha(colorValue, alpha) {
- let color = new CssColor(colorValue);
+function setAlpha(colorValue, alpha, useCssColor4ColorFunction = false) {
+ let color = new CssColor(colorValue, useCssColor4ColorFunction);
// Throw if the color supplied is not valid.
if (!color.valid) {
throw new Error("Invalid color.");
}
// If an invalid alpha valid, just set to 1.
if (!(alpha >= 0 && alpha <= 1)) {
@@ -1044,22 +1054,21 @@ function parseOldStyleRgb(lexer, hasAlph
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
+ * @param {Boolean} useCssColor4ColorFunction use css-color-4 color function or not.
* @return {Object} an object of the form {r, g, b, a}; or null if the
* name was not a valid color
*/
-function colorToRGBA(name, oldColorFunctionSyntax = true) {
+function colorToRGBA(name, useCssColor4ColorFunction = false) {
name = name.trim().toLowerCase();
if (name in cssColors) {
let result = cssColors[name];
return {r: result[0], g: result[1], b: result[2], a: result[3]};
} else if (name === "transparent") {
return {r: 0, g: 0, b: 0, a: 0};
} else if (name === "currentcolor") {
@@ -1084,17 +1093,17 @@ function colorToRGBA(name, oldColorFunct
if (!func || func.tokenType !== "function" ||
!expectedFunctions.includes(func.text)) {
return null;
}
let hsl = func.text === "hsl" || func.text === "hsla";
let vals;
- if (oldColorFunctionSyntax) {
+ if (!useCssColor4ColorFunction) {
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;
@@ -1105,13 +1114,14 @@ function colorToRGBA(name, oldColorFunct
return {r: vals[0], g: vals[1], b: vals[2], a: vals[3]};
}
/**
* Check whether a string names a valid CSS color.
*
* @param {String} name The string to check
+ * @param {Boolean} useCssColor4ColorFunction use css-color-4 color function or not.
* @return {Boolean} True if the string is a CSS color name.
*/
-function isValidCSSColor(name) {
- return colorToRGBA(name) !== null;
+function isValidCSSColor(name, useCssColor4ColorFunction = false) {
+ return colorToRGBA(name, useCssColor4ColorFunction) !== null;
}