--- a/devtools/client/shared/output-parser.js
+++ b/devtools/client/shared/output-parser.js
@@ -58,16 +58,17 @@ const CSS_SHAPE_OUTSIDE_ENABLED_PREF = "
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._computedVariable = null;
this._onColorSwatchMouseDown = this._onColorSwatchMouseDown.bind(this);
this._onAngleSwatchMouseDown = this._onAngleSwatchMouseDown.bind(this);
this.cssColor4 = supportsCssColor4ColorFunction();
}
OutputParser.prototype = {
/**
@@ -198,17 +199,17 @@ OutputParser.prototype = {
* title. Eg. a span with "var(--var1)" as the textContent
* and a title for --var1 like "--var1 = 10" or
* "--var1 is not set".
*/
_parseVariable: function (initialToken, text, tokenStream, options) {
// Handle the "var(".
let varText = text.substring(initialToken.startOffset,
initialToken.endOffset);
- let variableNode = this._createNode("span", {}, varText);
+ let variableNode = this._createNode("span", {});
// Parse the first variable name within the parens of var().
let {tokens, functionData, sawComma, sawVariable} =
this._parseMatchingParens(text, tokenStream, options, true);
let result = sawVariable ? "" : functionData.join("");
// Display options for the first and second argument in the var().
@@ -220,49 +221,58 @@ OutputParser.prototype = {
// Get the variable value if it is in use.
if (tokens && tokens.length === 1) {
varValue = options.isVariableInUse(tokens[0].text);
}
// Get the variable name.
let varName = text.substring(tokens[0].startOffset, tokens[0].endOffset);
+ // Reset swatch variable
+ this._computedVariable = null;
+
+ // If we saw a ",", get the remainder with the correct highlighting.
+ let rest;
+ if (sawComma) {
+ // Parse the text up until the close paren, being sure to
+ // disable the special case for filter.
+ let subOptions = Object.assign({}, options);
+ subOptions.expectFilter = false;
+ let saveParsed = this.parsed;
+ this.parsed = [];
+ subOptions.expectVar = true;
+ rest = this._doParse(text, subOptions, tokenStream, true);
+ this.parsed = saveParsed;
+ }
+
if (typeof varValue === "string") {
// The variable value is valid, set the variable name's title of the first argument
// in var() to display the variable name and value.
firstOpts.title =
STYLE_INSPECTOR_L10N.getFormatStr("rule.variableValue", varName, varValue);
+ this._computedVariable = varValue;
secondOpts.class = options.unmatchedVariableClass;
} else {
// The variable name is not valid, mark it unmatched.
firstOpts.class = options.unmatchedVariableClass;
firstOpts.title = STYLE_INSPECTOR_L10N.getFormatStr("rule.variableUnset",
varName);
}
+ this._appendVariable(this._computedVariable, variableNode, options);
+ appendText(variableNode, varText);
variableNode.appendChild(this._createNode("span", firstOpts, result));
- // If we saw a ",", then append it and show the remainder using
- // the correct highlighting.
if (sawComma) {
variableNode.appendChild(this.doc.createTextNode(","));
-
- // Parse the text up until the close paren, being sure to
- // disable the special case for filter.
- let subOptions = Object.assign({}, options);
- subOptions.expectFilter = false;
- let saveParsed = this.parsed;
- this.parsed = [];
- let rest = this._doParse(text, subOptions, tokenStream, true);
- this.parsed = saveParsed;
-
let span = this._createNode("span", secondOpts);
span.appendChild(rest);
variableNode.appendChild(span);
}
+
variableNode.appendChild(this.doc.createTextNode(")"));
return variableNode;
},
/* eslint-disable complexity */
/**
* The workhorse for @see _parse. This parses some CSS text,
@@ -375,16 +385,29 @@ OutputParser.prototype = {
this._isDisplayGrid(text, token, options)) {
this._appendGrid(token.text, options);
} 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 {
+ if (options.expectVar) {
+ let variableNode = this._createNode("span", {});
+ if (text.substring(token.startOffset, token.endOffset).startsWith("--")) {
+ let val = options.isVariableInUse(text.substring(token.startOffset,
+ token.endOffset)) || null;
+ this._appendVariable(val, variableNode);
+ this.parsed.push(variableNode);
+ this._computedVariable = val;
+ } else {
+ this._computedVariable = text.substring(token.startOffset,
+ token.endOffset);
+ }
+ }
this._appendTextNode(text.substring(token.startOffset,
token.endOffset));
}
break;
case "id":
case "hash": {
let original = text.substring(token.startOffset, token.endOffset);
@@ -1178,16 +1201,33 @@ OutputParser.prototype = {
container.appendChild(value);
this.parsed.push(container);
} else {
this._appendTextNode(color);
}
},
+ _appendVariable: function (variable, node) {
+ let swatch;
+ if (variable === null) {
+ swatch = this._createNode("span", {
+ class: "ruleview-swatch ruleview-variableswatch-unmatched",
+ title: "Cannot be resolved"
+ });
+ } else {
+ swatch = this._createNode("span", {
+ class: "ruleview-swatch ruleview-variableswatch-matched",
+ title: variable
+ });
+ }
+ node.appendChild(swatch);
+ return node;
+ },
+
/**
* Wrap some existing nodes in a filter editor.
*
* @param {String} filters
* The full text of the "filter" property.
* @param {object} options
* The options object passed to parseCssProperty().
* @param {object} nodes
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -471,16 +471,29 @@
}
.ruleview-shape {
background: url("chrome://devtools/skin/images/tool-shadereditor.svg");
border-radius: 0;
background-size: 1em;
}
+/* Temporarily use meaningless svg, replace in future */
+.ruleview-variableswatch-matched {
+ background: url("chrome://devtools/skin/images/grid.svg");
+ border-radius: 0;
+}
+
+/* Temporarily use meaningless svg, replace in future */
+.ruleview-variableswatch-unmatched {
+ background: url("chrome://devtools/skin/images/tool-shadereditor.svg");
+ border-radius: 0;
+ background-size: 1em;
+}
+
.ruleview-shape-point.active {
background-color: var(--rule-highlight-background-color);
}
.ruleview-colorswatch::before {
content: '';
background-color: #eee;
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),