Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/common/CSSShadowModel.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/common/CSSShadowModel.js b/third_party/WebKit/Source/devtools/front_end/common/CSSShadowModel.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f81ecbf391d34a6b530d935d0730b7f695d028ee |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/common/CSSShadowModel.js |
| @@ -0,0 +1,327 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @constructor |
| + */ |
| +WebInspector.CSSShadowModel = function() |
| +{ |
| + this._inset = false; |
| + this._offsetX = WebInspector.CSSLength.zero(); |
| + this._offsetY = WebInspector.CSSLength.zero(); |
| + this._blurRadius = WebInspector.CSSLength.zero(); |
| + this._spreadRadius = WebInspector.CSSLength.zero(); |
| + this._color = /** @type {!WebInspector.Color} */ (WebInspector.Color.parse("black")); |
| + this._format = ["X", "Y"]; |
|
dgozman
2016/08/22 23:59:04
Use named constants here.
flandy
2016/08/23 00:16:53
Done.
|
| +} |
| + |
| +/** |
| + * @enum {string} |
| + */ |
| +WebInspector.CSSShadowModel.FormatParts = { |
|
dgozman
2016/08/22 23:59:04
FormatParts -> _Part
flandy
2016/08/23 00:16:53
Done.
|
| + Inset: "I", |
| + OffsetX: "X", |
| + OffsetY: "Y", |
| + BlurRadius: "B", |
| + SpreadRadius: "S", |
| + Color: "C" |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @return {!Array<!WebInspector.CSSShadowModel>} |
| + */ |
| +WebInspector.CSSShadowModel.parseTextShadow = function(text) |
| +{ |
| + return WebInspector.CSSShadowModel._parseShadow(text, false); |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @return {!Array<!WebInspector.CSSShadowModel>} |
| + */ |
| +WebInspector.CSSShadowModel.parseBoxShadow = function(text) |
| +{ |
| + return WebInspector.CSSShadowModel._parseShadow(text, true); |
| +} |
| + |
| +WebInspector.CSSShadowModel.prototype = { |
| + /** |
| + * @param {boolean} inset |
| + */ |
| + setInset: function(inset) |
| + { |
| + this._inset = inset; |
| + if (this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.Inset) === -1) |
| + this._format.unshift(WebInspector.CSSShadowModel.FormatParts.Inset); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} offsetX |
| + * @param {!WebInspector.CSSLength} offsetY |
| + */ |
| + setOffset: function(offsetX, offsetY) |
| + { |
| + this._offsetX = offsetX; |
| + this._offsetY = offsetY; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} blurRadius |
| + */ |
| + setBlurRadius: function(blurRadius) |
| + { |
| + this._blurRadius = blurRadius; |
| + if (this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.BlurRadius) === -1) { |
| + var yIndex = this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.OffsetY); |
| + this._format.splice(yIndex + 1, 0, WebInspector.CSSShadowModel.FormatParts.BlurRadius); |
| + } |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} spreadRadius |
| + */ |
| + setSpreadRadius: function(spreadRadius) |
| + { |
| + this._spreadRadius = spreadRadius; |
| + if (this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.SpreadRadius) === -1) { |
| + this.setBlurRadius(this._blurRadius); |
| + var blurIndex = this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.BlurRadius); |
| + this._format.splice(blurIndex + 1, 0, WebInspector.CSSShadowModel.FormatParts.SpreadRadius); |
| + } |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Color} color |
| + */ |
| + setColor: function(color) |
| + { |
| + this._color = color; |
| + if (this._format.indexOf(WebInspector.CSSShadowModel.FormatParts.Color) === -1) |
| + this._format.push(WebInspector.CSSShadowModel.FormatParts.Color); |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + inset: function() |
| + { |
| + return this._inset; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + offsetX: function() |
| + { |
| + return this._offsetX; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + offsetY: function() |
| + { |
| + return this._offsetY; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + blurRadius: function() |
| + { |
| + return this._blurRadius; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + spreadRadius: function() |
| + { |
| + return this._spreadRadius; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.Color} |
| + */ |
| + color: function() |
| + { |
| + return this._color; |
| + }, |
| + |
| + /** |
| + * @return {string} |
| + */ |
| + asCSSText: function() |
| + { |
| + var parts = []; |
| + for (var i = 0; i < this._format.length; i++) { |
| + var part = this._format[i]; |
| + if (part === WebInspector.CSSShadowModel.FormatParts.Inset && this._inset) |
| + parts.push("inset"); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.OffsetX) |
| + parts.push(this._offsetX.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.OffsetY) |
| + parts.push(this._offsetY.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.BlurRadius) |
| + parts.push(this._blurRadius.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.SpreadRadius) |
| + parts.push(this._spreadRadius.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.Color) |
| + parts.push(this._color.asString(this._color.format())); |
| + } |
| + return parts.join(" "); |
| + } |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @param {boolean} isBoxShadow |
| + * @return {!Array<!WebInspector.CSSShadowModel>} |
| + */ |
| +WebInspector.CSSShadowModel._parseShadow = function(text, isBoxShadow) |
| +{ |
| + var shadowTexts = []; |
| + // Split by commas that aren't inside of color values to get the individual shadow values. |
| + var splits = WebInspector.TextUtils.splitStringByRegexes(text, [WebInspector.Color.Regex, /,/g]); |
| + var currentIndex = 0; |
| + for (var i = 0; i < splits.length; i++) { |
| + if (splits[i].regexIndex === 1) { |
| + var comma = splits[i]; |
| + shadowTexts.push(text.substring(currentIndex, comma.position)); |
| + currentIndex = comma.position + 1; |
| + } |
| + } |
| + shadowTexts.push(text.substring(currentIndex, text.length)); |
| + |
| + var shadows = []; |
| + for (var i = 0; i < shadowTexts.length; i++) { |
| + var shadow = new WebInspector.CSSShadowModel(); |
| + shadow._format = []; |
| + var nextPartAllowed = true; |
| + var regexes = [/inset/gi, WebInspector.Color.Regex, WebInspector.CSSLength.Regex]; |
| + var results = WebInspector.TextUtils.splitStringByRegexes(shadowTexts[i], regexes); |
| + for (var j = 0; j < results.length; j++) { |
| + var result = results[j]; |
| + if (result.regexIndex === -1) { |
| + // Don't allow anything other than inset, color, length values, and whitespace. |
| + if (/\S/.test(result.value)) |
| + return []; |
| + // All parts must be separated by whitespace. |
| + nextPartAllowed = true; |
| + } else { |
| + if (!nextPartAllowed) |
| + return []; |
| + nextPartAllowed = false; |
| + |
| + if (result.regexIndex === 0) { |
| + shadow._inset = true; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.Inset); |
| + } else if (result.regexIndex === 1) { |
| + var color = WebInspector.Color.parse(result.value); |
| + if (!color) |
| + return []; |
| + shadow._color = color; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.Color); |
| + } else if (result.regexIndex === 2) { |
| + var length = WebInspector.CSSLength.parse(result.value); |
| + if (!length) |
| + return []; |
| + var previousPart = shadow._format.length > 0 ? shadow._format[shadow._format.length - 1] : ""; |
| + if (previousPart === WebInspector.CSSShadowModel.FormatParts.OffsetX) { |
| + shadow._offsetY = length; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.OffsetY); |
| + } else if (previousPart === WebInspector.CSSShadowModel.FormatParts.OffsetY) { |
| + shadow._blurRadius = length; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.BlurRadius); |
| + } else if (previousPart === WebInspector.CSSShadowModel.FormatParts.BlurRadius) { |
| + shadow._spreadRadius = length; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.SpreadRadius); |
| + } else { |
| + shadow._offsetX = length; |
| + shadow._format.push(WebInspector.CSSShadowModel.FormatParts.OffsetX); |
| + } |
| + } |
| + } |
| + } |
| + if (invalidCount(WebInspector.CSSShadowModel.FormatParts.OffsetX, 1, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.OffsetY, 1, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.Color, 0, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.BlurRadius, 0, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.Inset, 0, isBoxShadow ? 1 : 0) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.SpreadRadius, 0, isBoxShadow ? 1 : 0)) |
| + return []; |
| + shadows.push(shadow); |
| + } |
| + return shadows; |
| + |
| + /** |
| + * @param {string} part |
| + * @param {number} min |
| + * @param {number} max |
| + * @return {boolean} |
| + */ |
| + function invalidCount(part, min, max) |
| + { |
| + var count = 0; |
| + for (var i = 0; i < shadow._format.length; i++) { |
| + if (shadow._format[i] === part) |
| + count++; |
| + } |
| + return count < min || count > max; |
| + } |
| +} |
| + |
| +/** |
| + * @constructor |
| + * @param {number} amount |
| + * @param {string} unit |
| + */ |
| +WebInspector.CSSLength = function(amount, unit) |
| +{ |
| + this.amount = amount; |
| + this.unit = unit; |
| +} |
| + |
| +/** @type {!RegExp} */ |
| +WebInspector.CSSLength.Regex = (function() |
| +{ |
| + var number = "([+-]?(?:[0-9]*[.])?[0-9]+(?:[eE][+-]?[0-9]+)?)"; |
| + var unit = "(ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmax|vmin|vw)"; |
| + var zero = "[+-]?(?:0*[.])?0+(?:[eE][+-]?[0-9]+)?"; |
| + return new RegExp(number + unit + "|" + zero, "gi"); |
| +})(); |
| + |
| +/** |
| + * @param {string} text |
| + * @return {?WebInspector.CSSLength} |
| + */ |
| +WebInspector.CSSLength.parse = function(text) |
| +{ |
| + var lengthRegex = new RegExp("^(?:" + WebInspector.CSSLength.Regex.source + ")$", "i"); |
| + var match = text.match(lengthRegex) || []; |
|
dgozman
2016/08/22 23:59:04
I'd rather do
if (!match) return null;
if > 2 retu
flandy
2016/08/23 00:16:53
Done.
|
| + if (match.length > 2 && match[2]) |
| + return new WebInspector.CSSLength(parseFloat(match[1]), match[2]); |
| + else if (match.length > 0) |
| + return WebInspector.CSSLength.zero(); |
| + return null; |
| +} |
| + |
| +/** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| +WebInspector.CSSLength.zero = function() |
| +{ |
| + return new WebInspector.CSSLength(0, ""); |
| +} |
| + |
| +WebInspector.CSSLength.prototype = { |
| + /** |
| + * @return {string} |
| + */ |
| + asCSSText: function() |
| + { |
| + return this.amount + this.unit; |
| + } |
| +} |