| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 /** | |
| 5 * @unrestricted | |
| 6 */ | |
| 7 Common.CSSShadowModel = class { | |
| 8 /** | |
| 9 * @param {boolean} isBoxShadow | |
| 10 */ | |
| 11 constructor(isBoxShadow) { | |
| 12 this._isBoxShadow = isBoxShadow; | |
| 13 this._inset = false; | |
| 14 this._offsetX = Common.CSSLength.zero(); | |
| 15 this._offsetY = Common.CSSLength.zero(); | |
| 16 this._blurRadius = Common.CSSLength.zero(); | |
| 17 this._spreadRadius = Common.CSSLength.zero(); | |
| 18 this._color = /** @type {!Common.Color} */ (Common.Color.parse('black')); | |
| 19 this._format = [Common.CSSShadowModel._Part.OffsetX, Common.CSSShadowModel._
Part.OffsetY]; | |
| 20 } | |
| 21 | |
| 22 /** | |
| 23 * @param {string} text | |
| 24 * @return {!Array<!Common.CSSShadowModel>} | |
| 25 */ | |
| 26 static parseTextShadow(text) { | |
| 27 return Common.CSSShadowModel._parseShadow(text, false); | |
| 28 } | |
| 29 | |
| 30 /** | |
| 31 * @param {string} text | |
| 32 * @return {!Array<!Common.CSSShadowModel>} | |
| 33 */ | |
| 34 static parseBoxShadow(text) { | |
| 35 return Common.CSSShadowModel._parseShadow(text, true); | |
| 36 } | |
| 37 | |
| 38 /** | |
| 39 * @param {string} text | |
| 40 * @param {boolean} isBoxShadow | |
| 41 * @return {!Array<!Common.CSSShadowModel>} | |
| 42 */ | |
| 43 static _parseShadow(text, isBoxShadow) { | |
| 44 var shadowTexts = []; | |
| 45 // Split by commas that aren't inside of color values to get the individual
shadow values. | |
| 46 var splits = Common.TextUtils.splitStringByRegexes(text, [Common.Color.Regex
, /,/g]); | |
| 47 var currentIndex = 0; | |
| 48 for (var i = 0; i < splits.length; i++) { | |
| 49 if (splits[i].regexIndex === 1) { | |
| 50 var comma = splits[i]; | |
| 51 shadowTexts.push(text.substring(currentIndex, comma.position)); | |
| 52 currentIndex = comma.position + 1; | |
| 53 } | |
| 54 } | |
| 55 shadowTexts.push(text.substring(currentIndex, text.length)); | |
| 56 | |
| 57 var shadows = []; | |
| 58 for (var i = 0; i < shadowTexts.length; i++) { | |
| 59 var shadow = new Common.CSSShadowModel(isBoxShadow); | |
| 60 shadow._format = []; | |
| 61 var nextPartAllowed = true; | |
| 62 var regexes = [/inset/gi, Common.Color.Regex, Common.CSSLength.Regex]; | |
| 63 var results = Common.TextUtils.splitStringByRegexes(shadowTexts[i], regexe
s); | |
| 64 for (var j = 0; j < results.length; j++) { | |
| 65 var result = results[j]; | |
| 66 if (result.regexIndex === -1) { | |
| 67 // Don't allow anything other than inset, color, length values, and wh
itespace. | |
| 68 if (/\S/.test(result.value)) | |
| 69 return []; | |
| 70 // All parts must be separated by whitespace. | |
| 71 nextPartAllowed = true; | |
| 72 } else { | |
| 73 if (!nextPartAllowed) | |
| 74 return []; | |
| 75 nextPartAllowed = false; | |
| 76 | |
| 77 if (result.regexIndex === 0) { | |
| 78 shadow._inset = true; | |
| 79 shadow._format.push(Common.CSSShadowModel._Part.Inset); | |
| 80 } else if (result.regexIndex === 1) { | |
| 81 var color = Common.Color.parse(result.value); | |
| 82 if (!color) | |
| 83 return []; | |
| 84 shadow._color = color; | |
| 85 shadow._format.push(Common.CSSShadowModel._Part.Color); | |
| 86 } else if (result.regexIndex === 2) { | |
| 87 var length = Common.CSSLength.parse(result.value); | |
| 88 if (!length) | |
| 89 return []; | |
| 90 var previousPart = shadow._format.length > 0 ? shadow._format[shadow
._format.length - 1] : ''; | |
| 91 if (previousPart === Common.CSSShadowModel._Part.OffsetX) { | |
| 92 shadow._offsetY = length; | |
| 93 shadow._format.push(Common.CSSShadowModel._Part.OffsetY); | |
| 94 } else if (previousPart === Common.CSSShadowModel._Part.OffsetY) { | |
| 95 shadow._blurRadius = length; | |
| 96 shadow._format.push(Common.CSSShadowModel._Part.BlurRadius); | |
| 97 } else if (previousPart === Common.CSSShadowModel._Part.BlurRadius)
{ | |
| 98 shadow._spreadRadius = length; | |
| 99 shadow._format.push(Common.CSSShadowModel._Part.SpreadRadius); | |
| 100 } else { | |
| 101 shadow._offsetX = length; | |
| 102 shadow._format.push(Common.CSSShadowModel._Part.OffsetX); | |
| 103 } | |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 if (invalidCount(Common.CSSShadowModel._Part.OffsetX, 1, 1) || | |
| 108 invalidCount(Common.CSSShadowModel._Part.OffsetY, 1, 1) || | |
| 109 invalidCount(Common.CSSShadowModel._Part.Color, 0, 1) || | |
| 110 invalidCount(Common.CSSShadowModel._Part.BlurRadius, 0, 1) || | |
| 111 invalidCount(Common.CSSShadowModel._Part.Inset, 0, isBoxShadow ? 1 : 0
) || | |
| 112 invalidCount(Common.CSSShadowModel._Part.SpreadRadius, 0, isBoxShadow
? 1 : 0)) | |
| 113 return []; | |
| 114 shadows.push(shadow); | |
| 115 } | |
| 116 return shadows; | |
| 117 | |
| 118 /** | |
| 119 * @param {string} part | |
| 120 * @param {number} min | |
| 121 * @param {number} max | |
| 122 * @return {boolean} | |
| 123 */ | |
| 124 function invalidCount(part, min, max) { | |
| 125 var count = 0; | |
| 126 for (var i = 0; i < shadow._format.length; i++) { | |
| 127 if (shadow._format[i] === part) | |
| 128 count++; | |
| 129 } | |
| 130 return count < min || count > max; | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 /** | |
| 135 * @param {boolean} inset | |
| 136 */ | |
| 137 setInset(inset) { | |
| 138 this._inset = inset; | |
| 139 if (this._format.indexOf(Common.CSSShadowModel._Part.Inset) === -1) | |
| 140 this._format.unshift(Common.CSSShadowModel._Part.Inset); | |
| 141 } | |
| 142 | |
| 143 /** | |
| 144 * @param {!Common.CSSLength} offsetX | |
| 145 */ | |
| 146 setOffsetX(offsetX) { | |
| 147 this._offsetX = offsetX; | |
| 148 } | |
| 149 | |
| 150 /** | |
| 151 * @param {!Common.CSSLength} offsetY | |
| 152 */ | |
| 153 setOffsetY(offsetY) { | |
| 154 this._offsetY = offsetY; | |
| 155 } | |
| 156 | |
| 157 /** | |
| 158 * @param {!Common.CSSLength} blurRadius | |
| 159 */ | |
| 160 setBlurRadius(blurRadius) { | |
| 161 this._blurRadius = blurRadius; | |
| 162 if (this._format.indexOf(Common.CSSShadowModel._Part.BlurRadius) === -1) { | |
| 163 var yIndex = this._format.indexOf(Common.CSSShadowModel._Part.OffsetY); | |
| 164 this._format.splice(yIndex + 1, 0, Common.CSSShadowModel._Part.BlurRadius)
; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 /** | |
| 169 * @param {!Common.CSSLength} spreadRadius | |
| 170 */ | |
| 171 setSpreadRadius(spreadRadius) { | |
| 172 this._spreadRadius = spreadRadius; | |
| 173 if (this._format.indexOf(Common.CSSShadowModel._Part.SpreadRadius) === -1) { | |
| 174 this.setBlurRadius(this._blurRadius); | |
| 175 var blurIndex = this._format.indexOf(Common.CSSShadowModel._Part.BlurRadiu
s); | |
| 176 this._format.splice(blurIndex + 1, 0, Common.CSSShadowModel._Part.SpreadRa
dius); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 /** | |
| 181 * @param {!Common.Color} color | |
| 182 */ | |
| 183 setColor(color) { | |
| 184 this._color = color; | |
| 185 if (this._format.indexOf(Common.CSSShadowModel._Part.Color) === -1) | |
| 186 this._format.push(Common.CSSShadowModel._Part.Color); | |
| 187 } | |
| 188 | |
| 189 /** | |
| 190 * @return {boolean} | |
| 191 */ | |
| 192 isBoxShadow() { | |
| 193 return this._isBoxShadow; | |
| 194 } | |
| 195 | |
| 196 /** | |
| 197 * @return {boolean} | |
| 198 */ | |
| 199 inset() { | |
| 200 return this._inset; | |
| 201 } | |
| 202 | |
| 203 /** | |
| 204 * @return {!Common.CSSLength} | |
| 205 */ | |
| 206 offsetX() { | |
| 207 return this._offsetX; | |
| 208 } | |
| 209 | |
| 210 /** | |
| 211 * @return {!Common.CSSLength} | |
| 212 */ | |
| 213 offsetY() { | |
| 214 return this._offsetY; | |
| 215 } | |
| 216 | |
| 217 /** | |
| 218 * @return {!Common.CSSLength} | |
| 219 */ | |
| 220 blurRadius() { | |
| 221 return this._blurRadius; | |
| 222 } | |
| 223 | |
| 224 /** | |
| 225 * @return {!Common.CSSLength} | |
| 226 */ | |
| 227 spreadRadius() { | |
| 228 return this._spreadRadius; | |
| 229 } | |
| 230 | |
| 231 /** | |
| 232 * @return {!Common.Color} | |
| 233 */ | |
| 234 color() { | |
| 235 return this._color; | |
| 236 } | |
| 237 | |
| 238 /** | |
| 239 * @return {string} | |
| 240 */ | |
| 241 asCSSText() { | |
| 242 var parts = []; | |
| 243 for (var i = 0; i < this._format.length; i++) { | |
| 244 var part = this._format[i]; | |
| 245 if (part === Common.CSSShadowModel._Part.Inset && this._inset) | |
| 246 parts.push('inset'); | |
| 247 else if (part === Common.CSSShadowModel._Part.OffsetX) | |
| 248 parts.push(this._offsetX.asCSSText()); | |
| 249 else if (part === Common.CSSShadowModel._Part.OffsetY) | |
| 250 parts.push(this._offsetY.asCSSText()); | |
| 251 else if (part === Common.CSSShadowModel._Part.BlurRadius) | |
| 252 parts.push(this._blurRadius.asCSSText()); | |
| 253 else if (part === Common.CSSShadowModel._Part.SpreadRadius) | |
| 254 parts.push(this._spreadRadius.asCSSText()); | |
| 255 else if (part === Common.CSSShadowModel._Part.Color) | |
| 256 parts.push(this._color.asString(this._color.format())); | |
| 257 } | |
| 258 return parts.join(' '); | |
| 259 } | |
| 260 }; | |
| 261 | |
| 262 /** | |
| 263 * @enum {string} | |
| 264 */ | |
| 265 Common.CSSShadowModel._Part = { | |
| 266 Inset: 'I', | |
| 267 OffsetX: 'X', | |
| 268 OffsetY: 'Y', | |
| 269 BlurRadius: 'B', | |
| 270 SpreadRadius: 'S', | |
| 271 Color: 'C' | |
| 272 }; | |
| 273 | |
| 274 | |
| 275 /** | |
| 276 * @unrestricted | |
| 277 */ | |
| 278 Common.CSSLength = class { | |
| 279 /** | |
| 280 * @param {number} amount | |
| 281 * @param {string} unit | |
| 282 */ | |
| 283 constructor(amount, unit) { | |
| 284 this.amount = amount; | |
| 285 this.unit = unit; | |
| 286 } | |
| 287 | |
| 288 /** | |
| 289 * @param {string} text | |
| 290 * @return {?Common.CSSLength} | |
| 291 */ | |
| 292 static parse(text) { | |
| 293 var lengthRegex = new RegExp('^(?:' + Common.CSSLength.Regex.source + ')$',
'i'); | |
| 294 var match = text.match(lengthRegex); | |
| 295 if (!match) | |
| 296 return null; | |
| 297 if (match.length > 2 && match[2]) | |
| 298 return new Common.CSSLength(parseFloat(match[1]), match[2]); | |
| 299 return Common.CSSLength.zero(); | |
| 300 } | |
| 301 | |
| 302 /** | |
| 303 * @return {!Common.CSSLength} | |
| 304 */ | |
| 305 static zero() { | |
| 306 return new Common.CSSLength(0, ''); | |
| 307 } | |
| 308 | |
| 309 /** | |
| 310 * @return {string} | |
| 311 */ | |
| 312 asCSSText() { | |
| 313 return this.amount + this.unit; | |
| 314 } | |
| 315 }; | |
| 316 | |
| 317 /** @type {!RegExp} */ | |
| 318 Common.CSSLength.Regex = (function() { | |
| 319 var number = '([+-]?(?:[0-9]*[.])?[0-9]+(?:[eE][+-]?[0-9]+)?)'; | |
| 320 var unit = '(ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmax|vmin|vw)'; | |
| 321 var zero = '[+-]?(?:0*[.])?0+(?:[eE][+-]?[0-9]+)?'; | |
| 322 return new RegExp(number + unit + '|' + zero, 'gi'); | |
| 323 })(); | |
| OLD | NEW |