Changeset 286844 in webkit
- Timestamp:
- Dec 10, 2021, 4:23:49 AM (5 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 1 added
- 10 edited
-
ChangeLog (modified) (1 diff)
-
UserInterface/Base/Main.js (modified) (2 diffs)
-
UserInterface/Controllers/CSSManager.js (modified) (3 diffs)
-
UserInterface/Controllers/CodeMirrorCompletionController.js (modified) (1 diff)
-
UserInterface/Main.html (modified) (1 diff)
-
UserInterface/Models/CSSCompletions.js (modified) (2 diffs)
-
UserInterface/Models/CSSKeywordCompletions.js (modified) (3 diffs)
-
UserInterface/Models/CSSPropertyNameCompletions.js (added)
-
UserInterface/Test.html (modified) (1 diff)
-
UserInterface/Test/Test.js (modified) (1 diff)
-
UserInterface/Views/SpreadsheetStyleProperty.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r286803 r286844 1 2021-12-10 Razvan Caliman <rcaliman@apple.com> 2 3 Web Inspector: Extract a specialized CSSNameCompletions from CSSCompletions 4 https://bugs.webkit.org/show_bug.cgi?id=233369 5 <rdar://83206520> 6 7 Reviewed by Devin Rousso. 8 9 `WI.CSSPropertyNameCompletions` is a long-lived object that holds the list of all CSS properties 10 supported by the target. It is instantiated only once on Web Inspector startup. 11 12 By contrast, `WI.CSSCompletions` is an object instantiated as often as needed with 13 lists of property values, CSS function values, etc. It holds the generic logic for 14 matching values against a given query. 15 16 The specialized logic for CSS property names was mixed-in with the generic logic in `WI.CSSCompletions`. 17 The main difference is in the format of the payload provided: 18 - an array of objects with key/value pairs for `WI.CSSPropertyNameCompletions`. 19 - an array of strings for general purpose `WI.CSSCompletions`. 20 21 This patch reduces the complexity in `WI.Completions`: 22 - moves the one-time initialization method to `WI.cssManager.initializeCSSCompletions`. 23 - simplifies `WI.Completions` constructor to expect just an array of strings. 24 - introduces `WI.CSSPropertyNameCompletions` as a sub-class of `WI.CSSCompletions` where its constructor 25 is specialized to handle the payload received from the backend. 26 - moves the `WI.CSSPropertyNameCompletions` instance to `WI.cssManager.cssPropertyNameCompletions`. 27 - removes unused accessors for navigating the list of matched completions. 28 29 * UserInterface/Base/Main.js: 30 (WI.performOneTimeFrontendInitializationsUsingTarget): 31 * UserInterface/Controllers/CSSManager.js: 32 (WI.CSSManager): 33 (WI.CSSManager.prototype.initializeCSSPropertyNameCompletions.): 34 (WI.CSSManager.prototype.initializeCSSPropertyNameCompletions): 35 Moved the initializiation method for objects used to get CSS completions 36 from `WI.CSSCompletions` with data from the backed to a more appropriate place. 37 38 (WI.CSSManager.prototype.get propertyNameCompletions): 39 * UserInterface/Controllers/CodeMirrorCompletionController.js: 40 (WI.CodeMirrorCompletionController.prototype._generateCSSCompletions): 41 * UserInterface/Main.html: 42 * UserInterface/Models/CSSCompletions.js: 43 (WI.CSSCompletions.prototype._firstIndexOfPrefix): 44 (WI.CSSCompletions): 45 (WI.CSSCompletions.initializeCSSCompletions.): Deleted. 46 (WI.CSSCompletions.initializeCSSCompletions.collectPropertyNameForCodeMirror): Deleted. 47 (WI.CSSCompletions.initializeCSSCompletions.propertiesCallback): Deleted. 48 (WI.CSSCompletions.initializeCSSCompletions.fontFamilyNamesCallback): Deleted. 49 (WI.CSSCompletions.initializeCSSCompletions): Deleted. 50 Moved to `WI.CSSManager`. 51 52 (WI.CSSCompletions.prototype.next): Deleted. 53 (WI.CSSCompletions.prototype.previous): Deleted. 54 (WI.CSSCompletions.prototype._closest): Deleted. 55 Removed unused methods for navigating the completions list. 56 This behavior is encapsulated in `WI.CompletionSuggestionsView`. 57 58 (WI.CSSCompletions.prototype.isValidPropertyName): Deleted. 59 Moved to `WI.CSSPropertyNameCompletions`. 60 61 * UserInterface/Models/CSSKeywordCompletions.js: 62 (WI.CSSKeywordCompletions.forPartialPropertyName): 63 * UserInterface/Models/CSSPropertyNameCompletions.js: Added. 64 (WI.CSSPropertyNameCompletions.prototype.isValidPropertyName): 65 (WI.CSSPropertyNameCompletions): 66 * UserInterface/Test.html: 67 * UserInterface/Test/Test.js: 68 (WI.performOneTimeFrontendInitializationsUsingTarget): 69 * UserInterface/Views/SpreadsheetStyleProperty.js: 70 (WI.SpreadsheetStyleProperty.prototype.updateStatus): 71 (WI.SpreadsheetStyleProperty.prototype._addCSSDocumentationButton): 72 1 73 2021-12-09 Brent Fulgham <bfulgham@apple.com> 2 74 -
trunk/Source/WebInspectorUI/UserInterface/Base/Main.js
r286329 r286844 624 624 if (!WI.__didPerformCSSInitialization && target.hasDomain("CSS")) { 625 625 WI.__didPerformCSSInitialization = true; 626 WI. CSSCompletions.initializeCSSCompletions(target);626 WI.cssManager.initializeCSSPropertyNameCompletions(target); 627 627 } 628 628 }; … … 811 811 812 812 if (WI.mainTarget.hasDomain("CSS")) 813 WI. CSSCompletions.initializeCSSCompletions(WI.assumingMainTarget());813 WI.cssManager.initializeCSSPropertyNameCompletions(WI.assumingMainTarget()); 814 814 815 815 if (WI.mainTarget.hasDomain("DOM")) -
trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js
r285502 r286844 49 49 this._defaultAppearance = null; 50 50 this._forcedAppearance = null; 51 52 this._propertyNameCompletions = null; 51 53 } 52 54 … … 57 59 if (target.hasDomain("CSS")) 58 60 target.CSSAgent.enable(); 61 } 62 63 initializeCSSPropertyNameCompletions(target) 64 { 65 console.assert(target.hasDomain("CSS")); 66 67 if (this._propertyNameCompletions) 68 return; 69 70 target.CSSAgent.getSupportedCSSProperties((error, cssProperties) => { 71 if (error) 72 return; 73 74 this._propertyNameCompletions = new WI.CSSPropertyNameCompletions(cssProperties); 75 76 WI.CSSKeywordCompletions.addCustomCompletions(cssProperties); 77 78 // CodeMirror is not included by tests so we shouldn't assume it always exists. 79 // If it isn't available we skip MIME type associations. 80 if (!window.CodeMirror) 81 return; 82 83 let propertyNamesForCodeMirror = {}; 84 let valueKeywordsForCodeMirror = {"inherit": true, "initial": true, "unset": true, "revert": true, "var": true, "env": true}; 85 let colorKeywordsForCodeMirror = {}; 86 87 function nameForCodeMirror(name) { 88 // CodeMirror parses the vendor prefix separate from the property or keyword name, 89 // so we need to strip vendor prefixes from our names. Also strip function parenthesis. 90 return name.replace(/^-[^-]+-/, "").replace(/\(\)$/, "").toLowerCase(); 91 } 92 93 for (let property of cssProperties) { 94 // Properties can also be value keywords, like when used in a transition. 95 // So we add them to both lists. 96 let codeMirrorPropertyName = nameForCodeMirror(property.name); 97 propertyNamesForCodeMirror[codeMirrorPropertyName] = true; 98 valueKeywordsForCodeMirror[codeMirrorPropertyName] = true; 99 } 100 101 for (let propertyName in WI.CSSKeywordCompletions._propertyKeywordMap) { 102 let keywords = WI.CSSKeywordCompletions._propertyKeywordMap[propertyName]; 103 for (let keyword of keywords) { 104 // Skip numbers, like the ones defined for font-weight. 105 if (keyword === WI.CSSKeywordCompletions.AllPropertyNamesPlaceholder || !isNaN(Number(keyword))) 106 continue; 107 valueKeywordsForCodeMirror[nameForCodeMirror(keyword)] = true; 108 } 109 } 110 111 for (let color of WI.CSSKeywordCompletions._colors) 112 colorKeywordsForCodeMirror[nameForCodeMirror(color)] = true; 113 114 function updateCodeMirrorCSSMode(mimeType) { 115 let modeSpec = CodeMirror.resolveMode(mimeType); 116 117 console.assert(modeSpec.propertyKeywords); 118 console.assert(modeSpec.valueKeywords); 119 console.assert(modeSpec.colorKeywords); 120 121 modeSpec.propertyKeywords = propertyNamesForCodeMirror; 122 modeSpec.valueKeywords = valueKeywordsForCodeMirror; 123 modeSpec.colorKeywords = colorKeywordsForCodeMirror; 124 125 CodeMirror.defineMIME(mimeType, modeSpec); 126 } 127 128 updateCodeMirrorCSSMode("text/css"); 129 updateCodeMirrorCSSMode("text/x-scss"); 130 }); 131 132 if (target.hasCommand("CSS.getSupportedSystemFontFamilyNames")) { 133 target.CSSAgent.getSupportedSystemFontFamilyNames((error, fontFamilyNames) =>{ 134 if (error) 135 return; 136 137 WI.CSSKeywordCompletions.addPropertyCompletionValues("font-family", fontFamilyNames); 138 WI.CSSKeywordCompletions.addPropertyCompletionValues("font", fontFamilyNames); 139 }); 140 } 59 141 } 60 142 … … 181 263 // Public 182 264 265 get propertyNameCompletions() { return this._propertyNameCompletions; } 266 183 267 get preferredColorFormat() 184 268 { -
trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js
r269023 r286844 628 628 629 629 // Complete property names. 630 return WI. CSSCompletions.cssNameCompletions.startsWith(this._prefix);630 return WI.cssManager.propertyNameCompletions.startsWith(this._prefix); 631 631 } 632 632 -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r286611 r286844 397 397 <script src="Models/CSSKeywordCompletions.js"></script> 398 398 <script src="Models/CSSProperty.js"></script> 399 <script src="Models/CSSPropertyNameCompletions.js"></script> 399 400 <script src="Models/CSSRule.js"></script> 400 401 <script src="Models/CSSSelector.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSCompletions.js
r286611 r286844 34 34 WI.CSSCompletions = class CSSCompletions 35 35 { 36 constructor(properties, acceptEmptyPrefix) 37 { 38 this._values = []; 39 40 // The `properties` parameter can be either a list of objects with 'name' / 'longhand' 41 // properties when initialized from the protocol for CSSCompletions.cssNameCompletions. 42 // Or it may just a list of strings when quickly initialized for other completion purposes. 43 if (properties.length && typeof properties[0] === "string") 44 this._values.pushAll(properties); 45 else { 46 for (var property of properties) { 47 var propertyName = property.name; 48 console.assert(propertyName); 49 50 this._values.push(propertyName); 51 52 let aliases = property.aliases; 53 if (aliases) 54 this._values.pushAll(aliases); 55 } 56 } 57 36 constructor(values, {acceptEmptyPrefix} = {}) 37 { 38 console.assert(Array.isArray(values), values); 39 console.assert(typeof values[0] === "string", "Expect an array of string values", values); 40 41 this._values = values.slice(); 58 42 this._values.sort(); 59 60 this._acceptEmptyPrefix = acceptEmptyPrefix; 43 this._acceptEmptyPrefix = !!acceptEmptyPrefix; 61 44 this._queryController = null; 62 45 } 63 46 64 47 // Static 65 66 static initializeCSSCompletions(target)67 {68 console.assert(target.hasDomain("CSS"));69 70 if (WI.CSSCompletions.cssNameCompletions)71 return;72 73 function propertiesCallback(error, cssProperties)74 {75 if (error)76 return;77 78 WI.CSSCompletions.cssNameCompletions = new WI.CSSCompletions(cssProperties, false);79 80 WI.CSSKeywordCompletions.addCustomCompletions(cssProperties);81 82 // CodeMirror is not included by tests so we shouldn't assume it always exists.83 // If it isn't available we skip MIME type associations.84 if (!window.CodeMirror)85 return;86 87 var propertyNamesForCodeMirror = {};88 var valueKeywordsForCodeMirror = {"inherit": true, "initial": true, "unset": true, "revert": true, "var": true, "env": true};89 var colorKeywordsForCodeMirror = {};90 91 function nameForCodeMirror(name)92 {93 // CodeMirror parses the vendor prefix separate from the property or keyword name,94 // so we need to strip vendor prefixes from our names. Also strip function parenthesis.95 return name.replace(/^-[^-]+-/, "").replace(/\(\)$/, "").toLowerCase();96 }97 98 function collectPropertyNameForCodeMirror(propertyName)99 {100 // Properties can also be value keywords, like when used in a transition.101 // So we add them to both lists.102 var codeMirrorPropertyName = nameForCodeMirror(propertyName);103 propertyNamesForCodeMirror[codeMirrorPropertyName] = true;104 valueKeywordsForCodeMirror[codeMirrorPropertyName] = true;105 }106 107 for (var property of cssProperties)108 collectPropertyNameForCodeMirror(property.name);109 110 for (var propertyName in WI.CSSKeywordCompletions._propertyKeywordMap) {111 var keywords = WI.CSSKeywordCompletions._propertyKeywordMap[propertyName];112 for (var i = 0; i < keywords.length; ++i) {113 // Skip numbers, like the ones defined for font-weight.114 if (keywords[i] === WI.CSSKeywordCompletions.AllPropertyNamesPlaceholder || !isNaN(Number(keywords[i])))115 continue;116 valueKeywordsForCodeMirror[nameForCodeMirror(keywords[i])] = true;117 }118 }119 120 WI.CSSKeywordCompletions._colors.forEach(function(colorName) {121 colorKeywordsForCodeMirror[nameForCodeMirror(colorName)] = true;122 });123 124 function updateCodeMirrorCSSMode(mimeType)125 {126 var modeSpec = CodeMirror.resolveMode(mimeType);127 128 console.assert(modeSpec.propertyKeywords);129 console.assert(modeSpec.valueKeywords);130 console.assert(modeSpec.colorKeywords);131 132 modeSpec.propertyKeywords = propertyNamesForCodeMirror;133 modeSpec.valueKeywords = valueKeywordsForCodeMirror;134 modeSpec.colorKeywords = colorKeywordsForCodeMirror;135 136 CodeMirror.defineMIME(mimeType, modeSpec);137 }138 139 updateCodeMirrorCSSMode("text/css");140 updateCodeMirrorCSSMode("text/x-scss");141 }142 143 function fontFamilyNamesCallback(error, fontFamilyNames)144 {145 if (error)146 return;147 148 WI.CSSKeywordCompletions.addPropertyCompletionValues("font-family", fontFamilyNames);149 WI.CSSKeywordCompletions.addPropertyCompletionValues("font", fontFamilyNames);150 }151 152 target.CSSAgent.getSupportedCSSProperties(propertiesCallback);153 if (target.hasCommand("CSS.getSupportedSystemFontFamilyNames"))154 target.CSSAgent.getSupportedSystemFontFamilyNames(fontFamilyNamesCallback);155 }156 48 157 49 static completeUnbalancedValue(value) … … 312 204 return foundIndex; 313 205 } 314 315 next(str, prefix)316 {317 return this._closest(str, prefix, 1);318 }319 320 previous(str, prefix)321 {322 return this._closest(str, prefix, -1);323 }324 325 _closest(str, prefix, shift)326 {327 if (!str)328 return "";329 330 var index = this._values.indexOf(str);331 if (index === -1)332 return "";333 334 if (!prefix) {335 index = (index + this._values.length + shift) % this._values.length;336 return this._values[index];337 }338 339 var propertiesWithPrefix = this.startsWith(prefix);340 var j = propertiesWithPrefix.indexOf(str);341 j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;342 return propertiesWithPrefix[j];343 }344 345 isValidPropertyName(name)346 {347 return this._values.includes(name);348 }349 206 }; 350 351 WI.CSSCompletions.cssNameCompletions = null;352 207 353 208 WI.CSSCompletions.lengthUnits = new Set([ -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSKeywordCompletions.js
r286803 r286844 42 42 43 43 if (!text.length && allowEmptyPrefix) 44 return {prefix: text, completions: WI. CSSCompletions.cssNameCompletions.values};44 return {prefix: text, completions: WI.cssManager.propertyNameCompletions.values}; 45 45 46 46 let completions; 47 47 if (useFuzzyMatching) 48 completions = WI. CSSCompletions.cssNameCompletions.executeQuery(text);48 completions = WI.cssManager.propertyNameCompletions.executeQuery(text); 49 49 else 50 completions = WI. CSSCompletions.cssNameCompletions.startsWith(text);50 completions = WI.cssManager.propertyNameCompletions.startsWith(text); 51 51 52 52 return {prefix: text, completions}; … … 171 171 } 172 172 173 if (acceptedKeywords.includes(WI.CSSKeywordCompletions.AllPropertyNamesPlaceholder) && WI. CSSCompletions.cssNameCompletions) {173 if (acceptedKeywords.includes(WI.CSSKeywordCompletions.AllPropertyNamesPlaceholder) && WI.cssManager.propertyNameCompletions) { 174 174 acceptedKeywords.remove(WI.CSSKeywordCompletions.AllPropertyNamesPlaceholder); 175 acceptedKeywords.pushAll(WI. CSSCompletions.cssNameCompletions.values);175 acceptedKeywords.pushAll(WI.cssManager.propertyNameCompletions.values); 176 176 } 177 177 178 return new WI.CSSCompletions(Array.from(new Set(acceptedKeywords)), true);178 return new WI.CSSCompletions(Array.from(new Set(acceptedKeywords)), {acceptEmptyPrefix: true}); 179 179 }; 180 180 … … 227 227 } 228 228 229 return new WI.CSSCompletions(suggestions, true);229 return new WI.CSSCompletions(suggestions, {acceptEmptyPrefix: true}); 230 230 }; 231 231 -
trunk/Source/WebInspectorUI/UserInterface/Test.html
r286611 r286844 133 133 <script src="Models/CSSKeywordCompletions.js"></script> 134 134 <script src="Models/CSSProperty.js"></script> 135 <script src="Models/CSSPropertyNameCompletions.js"></script> 135 136 <script src="Models/CSSRule.js"></script> 136 137 <script src="Models/CSSSelector.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Test/Test.js
r260847 r286844 126 126 if (!WI.__didPerformCSSInitialization && target.hasDomain("CSS")) { 127 127 WI.__didPerformCSSInitialization = true; 128 WI. CSSCompletions.initializeCSSCompletions(target);128 WI.cssManager.initializeCSSPropertyNameCompletions(target); 129 129 } 130 130 }; -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js
r286611 r286844 301 301 classNames.push("other-vendor"); 302 302 else if (this._hasInvalidVariableValue || (!this._property.valid && this._property.value !== "")) { 303 let propertyNameIsValid = false;304 if (WI.CSSCompletions.cssNameCompletions)305 propertyNameIsValid = WI.CSSCompletions.cssNameCompletions.isValidPropertyName(this._property.name);306 307 303 classNames.push("has-warning"); 308 304 309 if (! propertyNameIsValid) {305 if (!WI.cssManager.propertyNameCompletions?.isValidPropertyName(this._property.name)) { 310 306 classNames.push("invalid-name"); 311 307 elementTitle = WI.UIString("Unsupported property name"); … … 540 536 return; 541 537 542 if (!WI. CSSCompletions.cssNameCompletions.isValidPropertyName(this._property.name))538 if (!WI.cssManager.propertyNameCompletions?.isValidPropertyName(this._property.name)) 543 539 return; 544 540
Note:
See TracChangeset
for help on using the changeset viewer.