Changeset 248279 in webkit
- Timestamp:
- Aug 5, 2019, 4:40:40 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 6 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/inspector/css/resolve-variable-value-expected.txt (added)
-
LayoutTests/inspector/css/resolve-variable-value.html (added)
-
Source/WebInspectorUI/ChangeLog (modified) (1 diff)
-
Source/WebInspectorUI/UserInterface/Models/CSSKeywordCompletions.js (modified) (2 diffs)
-
Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js (modified) (1 diff)
-
Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js (modified) (10 diffs)
-
Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r248276 r248279 1 2019-08-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Styles: variable swatch not shown for var() with a fallback 4 https://bugs.webkit.org/show_bug.cgi?id=200237 5 6 Reviewed by Joseph Pecoraro. 7 8 * inspector/css/resolve-variable-value.html: Added. 9 * inspector/css/resolve-variable-value-expected.txt: Added. 10 1 11 2019-08-05 Chris Dumez <cdumez@apple.com> 2 12 -
trunk/Source/WebInspectorUI/ChangeLog
r248274 r248279 1 2019-08-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Styles: variable swatch not shown for var() with a fallback 4 https://bugs.webkit.org/show_bug.cgi?id=200237 5 6 Reviewed by Joseph Pecoraro. 7 8 * UserInterface/Views/SpreadsheetStyleProperty.js: 9 (WI.SpreadsheetStyleProperty.prototype._createInlineSwatch): 10 (WI.SpreadsheetStyleProperty.prototype._replaceSpecialTokens): Added. 11 (WI.SpreadsheetStyleProperty.prototype._addGradientTokens): 12 (WI.SpreadsheetStyleProperty.prototype._addColorTokens): 13 (WI.SpreadsheetStyleProperty.prototype._addTimingFunctionTokens): 14 (WI.SpreadsheetStyleProperty.prototype._addVariableTokens): 15 Check to see if there's a fallback value in the `var()` and tokenize it if there is. Mark 16 the property as invalid if the `var()` doesn't end up resolving to anything. 17 18 * UserInterface/Views/InlineSwatch.js: 19 (WI.InlineSwatch): 20 (WI.InlineSwatch.prototype.get value): 21 (WI.InlineSwatch.prototype._updateSwatch): 22 (WI.InlineSwatch.prototype._handleContextMenuEvent): 23 (WI.InlineSwatch.prototype._getNextValidHEXFormat.hexMatchesCurrentColor): 24 (WI.InlineSwatch.prototype._getNextValidHEXFormat): 25 Allow the `value` to be a function. In that case, use the getter `this.value` instead of the 26 value `this._value` directly so that the function is invoked. 27 This is needed for variable swatches because the fallback value could change after the 28 swatch has been created (e.g. another swatch in a CSS property value that just modifies the 29 text, rather than re-renders the entire CSS property value). 30 31 * UserInterface/Models/CSSStyleDeclaration.js: 32 (WI.CSSStyleDeclaration.prototype.resolveVariableValue): Added. 33 Follow the variable chain until an ultimate value is reached. 34 35 * UserInterface/Models/CSSKeywordCompletions.js: 36 (WI.CSSKeywordCompletions.isColorAwareProperty): 37 (WI.CSSKeywordCompletions.isTimingFunctionAwareProperty): Added. 38 Limit `cubic-bezier` and `spring` tokens to only be shown for timing function properties. 39 1 40 2019-08-05 Devin Rousso <drousso@apple.com> 2 41 -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSKeywordCompletions.js
r247928 r248279 76 76 WI.CSSKeywordCompletions.isColorAwareProperty = function(name) 77 77 { 78 if ( name in WI.CSSKeywordCompletions._colorAwareProperties)78 if (WI.CSSKeywordCompletions._colorAwareProperties.has(name)) 79 79 return true; 80 80 81 81 let isNotPrefixed = name.charAt(0) !== "-"; 82 if (isNotPrefixed && ("-webkit-" + name) in WI.CSSKeywordCompletions._colorAwareProperties)82 if (isNotPrefixed && WI.CSSKeywordCompletions._colorAwareProperties.has("-webkit-" + name)) 83 83 return true; 84 84 85 85 if (name.endsWith("color")) 86 return true; 87 88 return false; 89 }; 90 91 WI.CSSKeywordCompletions.isTimingFunctionAwareProperty = function(name) 92 { 93 if (WI.CSSKeywordCompletions._timingFunctionAwareProperties.has(name)) 94 return true; 95 96 let isNotPrefixed = name.charAt(0) !== "-"; 97 if (isNotPrefixed && WI.CSSKeywordCompletions._timingFunctionAwareProperties.has("-webkit-" + name)) 86 98 return true; 87 99 … … 303 315 ]; 304 316 305 WI.CSSKeywordCompletions._colorAwareProperties = [ 306 "background", "background-color", "background-image", "border", "border-color", "border-top", "border-right", "border-bottom", 307 "border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "box-shadow", "color", 308 "fill", "outline", "outline-color", "stroke", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color", 309 "text-shadow", "text-underline", "text-underline-color", "-webkit-box-shadow", "-webkit-column-rule", "-webkit-column-rule-color", 310 "-webkit-text-emphasis", "-webkit-text-emphasis-color", "-webkit-text-fill-color", "-webkit-text-stroke", "-webkit-text-stroke-color", 311 "-webkit-text-decoration-color", 317 WI.CSSKeywordCompletions._colorAwareProperties = new Set([ 318 "background", 319 "background-color", 320 "background-image", 321 "border", 322 "border-color", 323 "border-bottom", 324 "border-bottom-color", 325 "border-left", 326 "border-left-color", 327 "border-right", 328 "border-right-color", 329 "border-top", 330 "border-top-color", 331 "box-shadow", "-webkit-box-shadow", 332 "color", 333 "column-rule", "-webkit-column-rule", 334 "column-rule-color", "-webkit-column-rule-color", 335 "fill", 336 "outline", 337 "outline-color", 338 "stroke", 339 "text-decoration-color", "-webkit-text-decoration-color", 340 "text-emphasis", "-webkit-text-emphasis", 341 "text-emphasis-color", "-webkit-text-emphasis-color", 342 "text-line-through", 343 "text-line-through-color", 344 "text-overline", 345 "text-overline-color", 346 "text-shadow", 347 "text-underline", 348 "text-underline-color", 349 "-webkit-text-fill-color", 350 "-webkit-text-stroke", 351 "-webkit-text-stroke-color", 312 352 313 353 // iOS Properties 314 "-webkit-tap-highlight-color" 315 ].keySet(); 354 "-webkit-tap-highlight-color", 355 ]); 356 357 WI.CSSKeywordCompletions._timingFunctionAwareProperties = new Set([ 358 "animation", "-webkit-animation", 359 "animation-timing-function", "-webkit-animation-timing-function", 360 "transition", "-webkit-transition", 361 "transition-timing-function", "-webkit-transition-timing-function", 362 ]); 316 363 317 364 WI.CSSKeywordCompletions._propertyKeywordMap = { -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js
r248202 r248279 349 349 } 350 350 351 resolveVariableValue(text) 352 { 353 const invalid = Symbol("invalid"); 354 355 let checkTokens = (tokens) => { 356 let startIndex = NaN; 357 let openParenthesis = 0; 358 for (let i = 0; i < tokens.length; i++) { 359 let token = tokens[i]; 360 if (token.value === "var" && token.type && token.type.includes("atom")) { 361 if (isNaN(startIndex)) { 362 startIndex = i; 363 openParenthesis = 0; 364 } 365 continue; 366 } 367 368 if (isNaN(startIndex)) 369 continue; 370 371 if (token.value === "(") { 372 ++openParenthesis; 373 continue; 374 } 375 376 if (token.value === ")") { 377 --openParenthesis; 378 if (openParenthesis > 0) 379 continue; 380 381 let variableTokens = tokens.slice(startIndex, i + 1); 382 startIndex = NaN; 383 384 let variableNameIndex = variableTokens.findIndex((token) => token.value.startsWith("--") && /\bvariable-2\b/.test(token.type)); 385 if (variableNameIndex === -1) 386 continue; 387 388 let variableProperty = this.propertyForName(variableTokens[variableNameIndex].value, true); 389 if (variableProperty) 390 return variableProperty.value.trim(); 391 392 let fallbackStartIndex = variableTokens.findIndex((value, j) => j > variableNameIndex + 1 && /\bm-css\b/.test(value.type)); 393 if (fallbackStartIndex === -1) 394 return invalid; 395 396 let fallbackTokens = variableTokens.slice(fallbackStartIndex, i); 397 return checkTokens(fallbackTokens) || fallbackTokens.reduce((accumulator, token) => accumulator + token.value, "").trim(); 398 } 399 } 400 return null; 401 }; 402 403 let resolved = checkTokens(WI.tokenizeCSSValue(text)); 404 return resolved === invalid ? null : resolved; 405 } 406 351 407 newBlankProperty(propertyIndex) 352 408 { -
trunk/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js
r242602 r248279 91 91 get value() 92 92 { 93 if (typeof this._value === "function") 94 return this._value(); 93 95 return this._value; 94 96 } … … 138 140 _updateSwatch(dontFireEvents) 139 141 { 142 let value = this.value; 143 140 144 if (this._type === WI.InlineSwatch.Type.Color || this._type === WI.InlineSwatch.Type.Gradient) 141 this._swatchInnerElement.style.background = this._value ? this._value.toString() : null;145 this._swatchInnerElement.style.background = value ? value.toString() : null; 142 146 else if (this._type === WI.InlineSwatch.Type.Image) 143 this._swatchInnerElement.style.setProperty("background-image", `url(${ this._value.src})`);147 this._swatchInnerElement.style.setProperty("background-image", `url(${value.src})`); 144 148 145 149 if (!dontFireEvents) 146 this.dispatchEventToListeners(WI.InlineSwatch.Event.ValueChanged, {value : this._value});150 this.dispatchEventToListeners(WI.InlineSwatch.Event.ValueChanged, {value}); 147 151 } 148 152 … … 151 155 event.stop(); 152 156 153 if (event.shiftKey && this._value) { 157 let value = this.value; 158 159 if (event.shiftKey && value) { 154 160 if (this._type === WI.InlineSwatch.Type.Color) { 155 let nextFormat = this._value.nextFormat();161 let nextFormat = value.nextFormat(); 156 162 console.assert(nextFormat); 157 163 if (nextFormat) { 158 this._value.format = nextFormat;164 value.format = nextFormat; 159 165 this._updateSwatch(); 160 166 } … … 172 178 if (this._valueEditor) 173 179 return; 180 181 if (!value) 182 value = this._fallbackValue(); 174 183 175 184 let bounds = WI.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect()); … … 221 230 222 231 case WI.InlineSwatch.Type.Image: 223 this._valueEditor = {}; 224 this._valueEditor.element = document.createElement("img"); 225 this._valueEditor.element.src = this._value.src; 226 this._valueEditor.element.classList.add("show-grid"); 227 this._valueEditor.element.style.setProperty("max-width", "50vw"); 228 this._valueEditor.element.style.setProperty("max-height", "50vh"); 232 if (value.src) { 233 this._valueEditor = {}; 234 this._valueEditor.element = document.createElement("img"); 235 this._valueEditor.element.src = value.src; 236 this._valueEditor.element.classList.add("show-grid"); 237 this._valueEditor.element.style.setProperty("max-width", "50vw"); 238 this._valueEditor.element.style.setProperty("max-height", "50vh"); 239 } 229 240 break; 230 241 } … … 238 249 this.dispatchEventToListeners(WI.InlineSwatch.Event.Activated); 239 250 240 let value = this._value || this._fallbackValue();241 251 switch (this._type) { 242 252 case WI.InlineSwatch.Type.Color: … … 295 305 _handleContextMenuEvent(event) 296 306 { 297 if (!this._value) 307 let value = this.value; 308 if (!value) 298 309 return; 299 310 300 311 let contextMenu = WI.ContextMenu.createFromEvent(event); 301 312 302 if ( this._value.isKeyword() && this._value.format !== WI.Color.Format.Keyword) {313 if (value.isKeyword() && value.format !== WI.Color.Format.Keyword) { 303 314 contextMenu.appendItem(WI.UIString("Format: Keyword"), () => { 304 this._value.format = WI.Color.Format.Keyword;315 value.format = WI.Color.Format.Keyword; 305 316 this._updateSwatch(); 306 317 }); … … 310 321 if (hexInfo) { 311 322 contextMenu.appendItem(hexInfo.title, () => { 312 this._value.format = hexInfo.format;313 this._updateSwatch(); 314 }); 315 } 316 317 if ( this._value.simple && this._value.format !== WI.Color.Format.HSL) {323 value.format = hexInfo.format; 324 this._updateSwatch(); 325 }); 326 } 327 328 if (value.simple && value.format !== WI.Color.Format.HSL) { 318 329 contextMenu.appendItem(WI.UIString("Format: HSL"), () => { 319 this._value.format = WI.Color.Format.HSL;320 this._updateSwatch(); 321 }); 322 } else if ( this._value.format !== WI.Color.Format.HSLA) {330 value.format = WI.Color.Format.HSL; 331 this._updateSwatch(); 332 }); 333 } else if (value.format !== WI.Color.Format.HSLA) { 323 334 contextMenu.appendItem(WI.UIString("Format: HSLA"), () => { 324 this._value.format = WI.Color.Format.HSLA;325 this._updateSwatch(); 326 }); 327 } 328 329 if ( this._value.simple && this._value.format !== WI.Color.Format.RGB) {335 value.format = WI.Color.Format.HSLA; 336 this._updateSwatch(); 337 }); 338 } 339 340 if (value.simple && value.format !== WI.Color.Format.RGB) { 330 341 contextMenu.appendItem(WI.UIString("Format: RGB"), () => { 331 this._value.format = WI.Color.Format.RGB;332 this._updateSwatch(); 333 }); 334 } else if ( this._value.format !== WI.Color.Format.RGBA) {342 value.format = WI.Color.Format.RGB; 343 this._updateSwatch(); 344 }); 345 } else if (value.format !== WI.Color.Format.RGBA) { 335 346 contextMenu.appendItem(WI.UIString("Format: RGBA"), () => { 336 this._value.format = WI.Color.Format.RGBA;347 value.format = WI.Color.Format.RGBA; 337 348 this._updateSwatch(); 338 349 }); … … 345 356 return false; 346 357 358 let value = this.value; 359 347 360 function hexMatchesCurrentColor(hexInfo) { 348 361 let nextIsSimple = hexInfo.format === WI.Color.Format.ShortHEX || hexInfo.format === WI.Color.Format.HEX; 349 if (nextIsSimple && ! this._value.simple)362 if (nextIsSimple && !value.simple) 350 363 return false; 351 364 352 365 let nextIsShort = hexInfo.format === WI.Color.Format.ShortHEX || hexInfo.format === WI.Color.Format.ShortHEXAlpha; 353 if (nextIsShort && ! this._value.canBeSerializedAsShortHEX())366 if (nextIsShort && !value.canBeSerializedAsShortHEX()) 354 367 return false; 355 368 … … 376 389 ]; 377 390 378 let currentColorIsHEX = hexFormats.some((info) => info.format === this._value.format);391 let currentColorIsHEX = hexFormats.some((info) => info.format === value.format); 379 392 380 393 for (let i = 0; i < hexFormats.length; ++i) { 381 if (currentColorIsHEX && this._value.format !== hexFormats[i].format)394 if (currentColorIsHEX && value.format !== hexFormats[i].format) 382 395 continue; 383 396 384 397 for (let j = ~~currentColorIsHEX; j < hexFormats.length; ++j) { 385 398 let nextIndex = (i + j) % hexFormats.length; 386 if (hexMatchesCurrentColor .call(this,hexFormats[nextIndex]))399 if (hexMatchesCurrentColor(hexFormats[nextIndex])) 387 400 return hexFormats[nextIndex]; 388 401 } -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js
r247760 r248279 448 448 let tokens = WI.tokenizeCSSValue(value); 449 449 450 if (this._property.enabled) { 451 // FIXME: <https://webkit.org/b/178636> Web Inspector: Styles: Make inline widgets work with CSS functions (var(), calc(), etc.) 452 453 // CSS variables may contain color - display color picker for them. 454 if (this._property.variable || WI.CSSKeywordCompletions.isColorAwareProperty(this._property.name)) { 455 tokens = this._addGradientTokens(tokens); 456 tokens = this._addColorTokens(tokens); 457 } 458 tokens = this._addTimingFunctionTokens(tokens, "cubic-bezier"); 459 tokens = this._addTimingFunctionTokens(tokens, "spring"); 460 tokens = this._addVariableTokens(tokens); 461 } 450 if (this._property.enabled) 451 tokens = this._replaceSpecialTokens(tokens); 462 452 463 453 tokens = tokens.map((token) => { … … 494 484 } 495 485 496 _createInlineSwatch(type, text, valueObject)486 _createInlineSwatch(type, contents, valueObject) 497 487 { 498 488 let tokenElement = document.createElement("span"); 499 489 let innerElement = document.createElement("span"); 500 innerElement.textContent = text; 490 for (let item of contents) { 491 if (item instanceof Node) 492 innerElement.appendChild(item); 493 else if (typeof item === "object") 494 innerElement.append(item.value); 495 else 496 innerElement.append(item); 497 } 501 498 502 499 let readOnly = !this._isEditable(); … … 515 512 }, this); 516 513 514 if (type === WI.InlineSwatch.Type.Variable) { 515 swatch.value = () => { 516 return this._property.ownerStyle.nodeStyles.computedStyle.resolveVariableValue(innerElement.textContent); 517 }; 518 } 519 517 520 if (this._delegate && typeof this._delegate.stylePropertyInlineSwatchActivated === "function") { 518 521 swatch.addEventListener(WI.InlineSwatch.Event.Activated, () => { … … 530 533 531 534 return tokenElement; 535 } 536 537 _replaceSpecialTokens(tokens) 538 { 539 // FIXME: <https://webkit.org/b/178636> Web Inspector: Styles: Make inline widgets work with CSS functions (var(), calc(), etc.) 540 541 tokens = this._addVariableTokens(tokens); 542 543 if (this._property.variable || WI.CSSKeywordCompletions.isColorAwareProperty(this._property.name)) { 544 tokens = this._addGradientTokens(tokens); 545 tokens = this._addColorTokens(tokens); 546 } 547 548 if (this._property.variable || WI.CSSKeywordCompletions.isTimingFunctionAwareProperty(this._property.name)) { 549 tokens = this._addTimingFunctionTokens(tokens, "cubic-bezier"); 550 tokens = this._addTimingFunctionTokens(tokens, "spring"); 551 } 552 553 return tokens; 532 554 } 533 555 … … 557 579 let gradient = WI.Gradient.fromString(text); 558 580 if (gradient) 559 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Gradient, text, gradient));581 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Gradient, rawTokens, gradient)); 560 582 else 561 583 newTokens.push(...rawTokens); … … 576 598 let color = WI.Color.fromString(text); 577 599 if (color) 578 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Color, text, color));600 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Color, rawTokens, color)); 579 601 else 580 602 newTokens.push(...rawTokens); … … 643 665 644 666 if (valueObject) 645 newTokens.push(this._createInlineSwatch(inlineSwatchType, text, valueObject));667 newTokens.push(this._createInlineSwatch(inlineSwatchType, rawTokens, valueObject)); 646 668 else 647 669 newTokens.push(...rawTokens); … … 664 686 let token = tokens[i]; 665 687 if (token.value === "var" && token.type && token.type.includes("atom")) { 666 startIndex = i; 667 openParenthesis = 0; 688 if (isNaN(startIndex)) { 689 startIndex = i; 690 openParenthesis = 0; 691 } 668 692 } else if (token.value === "(" && !isNaN(startIndex)) 669 693 ++openParenthesis; … … 674 698 675 699 let rawTokens = tokens.slice(startIndex, i + 1); 676 let tokenValues = rawTokens.map((token) => token.value); 677 let variableName = tokenValues.find((value, i) => value.startsWith("--") && /\bvariable-2\b/.test(rawTokens[i].type)); 678 679 const dontCreateIfMissing = true; 680 let variableProperty = this._property.ownerStyle.nodeStyles.computedStyle.propertyForName(variableName, dontCreateIfMissing); 681 if (variableProperty) { 682 let valueObject = variableProperty.value.trim(); 683 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Variable, tokenValues.join(""), valueObject)); 700 let variableNameIndex = rawTokens.findIndex((token) => token.value.startsWith("--") && /\bvariable-2\b/.test(token.type)); 701 if (variableNameIndex !== -1) { 702 let contents = []; 703 let fallbackStartIndex = rawTokens.findIndex((value, i) => i > variableNameIndex + 1 && /\bm-css\b/.test(value.type)); 704 if (fallbackStartIndex !== -1) { 705 contents = contents.concat(rawTokens.slice(0, fallbackStartIndex)); 706 contents = contents.concat(this._replaceSpecialTokens(rawTokens.slice(fallbackStartIndex, i))); 707 } else 708 contents = contents.concat(rawTokens.slice(0, i)); 709 contents.push(token); 710 711 let text = rawTokens.reduce((accumulator, token) => accumulator + token.value, ""); 712 if (this._property.ownerStyle.nodeStyles.computedStyle.resolveVariableValue(text)) 713 newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Variable, contents)); 714 else 715 newTokens = newTokens.concat(contents); 684 716 } else { 685 717 this._hasInvalidVariableValue = true;
Note:
See TracChangeset
for help on using the changeset viewer.