| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 CSSTracker.CSSTrackerView = class extends UI.VBox { | 5 CSSTracker.CSSTrackerView = class extends UI.VBox { |
| 6 constructor() { | 6 constructor() { |
| 7 super(true); | 7 super(true); |
| 8 | 8 |
| 9 this.registerRequiredCSS('css_tracker/cssTrackerView.css'); | 9 this.registerRequiredCSS('css_tracker/cssTrackerView.css'); |
| 10 | 10 |
| 11 var toolbarContainer = this.contentElement.createChild('div', 'css-tracker-t
oolbar-container'); | 11 var toolbarContainer = this.contentElement.createChild('div', 'css-tracker-t
oolbar-container'); |
| 12 var topToolbar = new UI.Toolbar('css-tracker-toolbar', toolbarContainer); | 12 var topToolbar = new UI.Toolbar('css-tracker-toolbar', toolbarContainer); |
| 13 | 13 |
| 14 this._recordButton = new UI.ToolbarToggle(Common.UIString('Start recording')
, | 14 this._recordButton = |
| 15 'largeicon-resume', | 15 new UI.ToolbarToggle(Common.UIString('Start recording'), 'largeicon-resu
me', 'largeicon-pause'); |
| 16 'largeicon-pause'); | |
| 17 this._recordButton.addEventListener(UI.ToolbarButton.Events.Click, () => thi
s._toggleRecording(!this._isRecording)); | 16 this._recordButton.addEventListener(UI.ToolbarButton.Events.Click, () => thi
s._toggleRecording(!this._isRecording)); |
| 18 topToolbar.appendToolbarItem(this._recordButton); | 17 topToolbar.appendToolbarItem(this._recordButton); |
| 19 | 18 |
| 20 var clearButton = new UI.ToolbarButton(Common.UIString('Clear all'), 'largei
con-clear'); | 19 var clearButton = new UI.ToolbarButton(Common.UIString('Clear all'), 'largei
con-clear'); |
| 21 clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._reset.bind
(this)); | 20 clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._reset.bind
(this)); |
| 22 topToolbar.appendToolbarItem(clearButton); | 21 topToolbar.appendToolbarItem(clearButton); |
| 23 | 22 |
| 24 this._cssResultsElement = this.contentElement.createChild('div', 'css-result
s'); | 23 this._cssResultsElement = this.contentElement.createChild('div', 'css-result
s'); |
| 25 this._progressElement = this._cssResultsElement.createChild('div', 'progress
-view'); | 24 this._progressElement = this._cssResultsElement.createChild('div', 'progress
-view'); |
| 26 this._treeOutline = new TreeOutlineInShadow(); | 25 this._treeOutline = new UI.TreeOutlineInShadow(); |
| 27 this._treeOutline.registerRequiredCSS('css_tracker/unusedRulesTree.css'); | 26 this._treeOutline.registerRequiredCSS('css_tracker/unusedRulesTree.css'); |
| 28 | 27 |
| 29 this._statusToolbarElement = this.contentElement.createChild('div', 'css-too
lbar-summary'); | 28 this._statusToolbarElement = this.contentElement.createChild('div', 'css-too
lbar-summary'); |
| 30 this._statusMessageElement = this._statusToolbarElement.createChild('div', '
css-message'); | 29 this._statusMessageElement = this._statusToolbarElement.createChild('div', '
css-message'); |
| 31 | 30 |
| 32 this._isRecording = false; | 31 this._isRecording = false; |
| 33 } | 32 } |
| 34 | 33 |
| 35 _reset() { | 34 _reset() { |
| 36 Workspace.workspace.uiSourceCodes().forEach( | 35 Workspace.workspace.uiSourceCodes().forEach( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 var url = this._urlForStyleSheetId(cssModel, rule.styleSheetId); | 97 var url = this._urlForStyleSheetId(cssModel, rule.styleSheetId); |
| 99 if (!url) | 98 if (!url) |
| 100 continue; | 99 continue; |
| 101 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); | 100 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); |
| 102 if (!uiSourceCode) | 101 if (!uiSourceCode) |
| 103 continue; | 102 continue; |
| 104 | 103 |
| 105 var gutterRange = Common.TextRange.fromObject(rule.range); | 104 var gutterRange = Common.TextRange.fromObject(rule.range); |
| 106 if (gutterRange.startColumn) | 105 if (gutterRange.startColumn) |
| 107 gutterRange.startColumn--; | 106 gutterRange.startColumn--; |
| 108 uiSourceCode.addDecoration(gutterRange, | 107 uiSourceCode.addDecoration(gutterRange, CSSTracker.CSSTrackerView.LineDe
corator.type, rule.wasUsed); |
| 109 CSSTracker.CSSTrackerView.LineDecorator.type, rule.wasUsed); | |
| 110 } | 108 } |
| 111 var percentUnused = Math.round(100 * unusedRulesCount / ruleUsageList.leng
th); | 109 var percentUnused = Math.round(100 * unusedRulesCount / ruleUsageList.leng
th); |
| 112 if (unusedRulesCount === 1) { | 110 if (unusedRulesCount === 1) { |
| 113 this._statusMessageElement.textContent = | 111 this._statusMessageElement.textContent = |
| 114 Common.UIString('%d CSS rule is not used. (%d%%)', unusedRulesCount
, percentUnused); | 112 Common.UIString('%d CSS rule is not used. (%d%%)', unusedRulesCount,
percentUnused); |
| 115 } else { | 113 } else { |
| 116 this._statusMessageElement.textContent = | 114 this._statusMessageElement.textContent = |
| 117 Common.UIString('%d CSS rules are not used. (%d%%)', unusedRulesCoun
t, percentUnused); | 115 Common.UIString('%d CSS rules are not used. (%d%%)', unusedRulesCoun
t, percentUnused); |
| 118 } | 116 } |
| 119 | 117 |
| 120 this._renderRuleUsage(cssModel, ruleUsageList); | 118 this._renderRuleUsage(cssModel, ruleUsageList); |
| 121 } | 119 } |
| 122 } | 120 } |
| 123 | 121 |
| 124 /** | 122 /** |
| 125 * @param {!Array<!SDK.CSSStyleSheetHeader>} styleSheetHeaders | 123 * @param {!Array<!SDK.CSSStyleSheetHeader>} styleSheetHeaders |
| 126 * @return {!Promise<!Array<!CSSTracker.ParsedStyleSheet>>} | 124 * @return {!Promise<!Array<!CSSTracker.ParsedStyleSheet>>} |
| 127 */ | 125 */ |
| 128 _parseStyleSheets(styleSheetHeaders) { | 126 _parseStyleSheets(styleSheetHeaders) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if (!rule.selector && !rule.wasUsed) | 194 if (!rule.selector && !rule.wasUsed) |
| 197 ++unattributedRulesCount; | 195 ++unattributedRulesCount; |
| 198 } | 196 } |
| 199 ruleList = ruleList.filter(rule => rule.selector); | 197 ruleList = ruleList.filter(rule => rule.selector); |
| 200 | 198 |
| 201 this._cssResultsElement.removeChildren(); | 199 this._cssResultsElement.removeChildren(); |
| 202 | 200 |
| 203 if (unattributedRulesCount) { | 201 if (unattributedRulesCount) { |
| 204 if (unattributedRulesCount === 1) { | 202 if (unattributedRulesCount === 1) { |
| 205 var removedStyleSheetStats = Common.UIString('1 unused rule in a removed
style sheet.'); | 203 var removedStyleSheetStats = Common.UIString('1 unused rule in a removed
style sheet.'); |
| 206 } | 204 } else { |
| 207 else { | |
| 208 var removedStyleSheetStats = | 205 var removedStyleSheetStats = |
| 209 Common.UIString('%d unused rules in removed style sheets.', unattrib
utedRulesCount); | 206 Common.UIString('%d unused rules in removed style sheets.', unattrib
utedRulesCount); |
| 210 } | 207 } |
| 211 var treeElement = new TreeElement(Common.UIString('Unknown style sheets'),
true); | 208 var treeElement = new UI.TreeElement(Common.UIString('Unknown style sheets
'), true); |
| 212 treeElement.toggleOnClick = true; | 209 treeElement.toggleOnClick = true; |
| 213 treeElement.selectable = false; | 210 treeElement.selectable = false; |
| 214 | 211 |
| 215 var stats = new TreeElement(removedStyleSheetStats, false); | 212 var stats = new UI.TreeElement(removedStyleSheetStats, false); |
| 216 stats.selectable = false; | 213 stats.selectable = false; |
| 217 treeElement.appendChild(stats); | 214 treeElement.appendChild(stats); |
| 218 this._treeOutline.appendChild(treeElement); | 215 this._treeOutline.appendChild(treeElement); |
| 219 } | 216 } |
| 220 | 217 |
| 221 if (!ruleList.length) | 218 if (!ruleList.length) |
| 222 return; | 219 return; |
| 223 | 220 |
| 224 this._cssResultsElement.appendChild(this._treeOutline.element); | 221 this._cssResultsElement.appendChild(this._treeOutline.element); |
| 225 | 222 |
| 226 var startPosition = 0; | 223 var startPosition = 0; |
| 227 for (var i = 1; i < ruleList.length; ++i) { | 224 for (var i = 1; i < ruleList.length; ++i) { |
| 228 if (ruleList[i].styleSheetId === ruleList[i - 1].styleSheetId) | 225 if (ruleList[i].styleSheetId === ruleList[i - 1].styleSheetId) |
| 229 continue; | 226 continue; |
| 230 | 227 |
| 231 var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].style
SheetId); | 228 var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].style
SheetId); |
| 232 var styleSheetTreeElement = | 229 var styleSheetTreeElement = |
| 233 new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, ruleList.slic
e(startPosition, i)); | 230 new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, ruleList.slic
e(startPosition, i)); |
| 234 this._treeOutline.appendChild(styleSheetTreeElement); | 231 this._treeOutline.appendChild(styleSheetTreeElement); |
| 235 | 232 |
| 236 startPosition = i; | 233 startPosition = i; |
| 237 } | 234 } |
| 238 var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].styleSh
eetId); | 235 var url = this._urlForStyleSheetId(cssModel, ruleList[startPosition].styleSh
eetId); |
| 239 var styleSheetTreeElement = | 236 var styleSheetTreeElement = new CSSTracker.CSSTrackerView.StyleSheetTreeElem
ent(url, ruleList.slice(startPosition)); |
| 240 new CSSTracker.CSSTrackerView.StyleSheetTreeElement(url, ruleList.slice(
startPosition)); | |
| 241 this._treeOutline.appendChild(styleSheetTreeElement); | 237 this._treeOutline.appendChild(styleSheetTreeElement); |
| 242 } | 238 } |
| 243 | 239 |
| 244 /** | 240 /** |
| 245 * @param {string} styleSheetId | 241 * @param {string} styleSheetId |
| 246 * @param {!SDK.CSSModel} cssModel | 242 * @param {!SDK.CSSModel} cssModel |
| 247 * @return {string} | 243 * @return {string} |
| 248 */ | 244 */ |
| 249 _urlForStyleSheetId(cssModel, styleSheetId) { | 245 _urlForStyleSheetId(cssModel, styleSheetId) { |
| 250 var styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId); | 246 var styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId); |
| 251 if (!styleSheetHeader) | 247 if (!styleSheetHeader) |
| 252 return ''; | 248 return ''; |
| 253 return styleSheetHeader.sourceURL; | 249 return styleSheetHeader.sourceURL; |
| 254 } | 250 } |
| 255 }; | 251 }; |
| 256 | 252 |
| 257 /** @typedef {{range: !Protocol.CSS.SourceRange, | 253 /** @typedef {{range: !Protocol.CSS.SourceRange, |
| 258 * selector: (string|undefined), | 254 * selector: (string|undefined), |
| 259 * styleSheetId: !Protocol.CSS.StyleSheetId, | 255 * styleSheetId: !Protocol.CSS.StyleSheetId, |
| 260 * wasUsed: boolean}} | 256 * wasUsed: boolean}} |
| 261 */ | 257 */ |
| 262 CSSTracker.RuleUsage; | 258 CSSTracker.RuleUsage; |
| 263 | 259 |
| 264 /** @typedef {{sourceURL: string, rules: !Array<!Common.FormatterWorkerPool.CSSS
tyleRule>}} */ | 260 /** @typedef {{sourceURL: string, rules: !Array<!Common.FormatterWorkerPool.CSSS
tyleRule>}} */ |
| 265 CSSTracker.ParsedStyleSheet; | 261 CSSTracker.ParsedStyleSheet; |
| 266 | 262 |
| 267 CSSTracker.CSSTrackerView._rulesShownAtOnce = 20; | 263 CSSTracker.CSSTrackerView._rulesShownAtOnce = 20; |
| 268 | 264 |
| 269 CSSTracker.CSSTrackerView.StyleSheetTreeElement = class extends TreeElement { | 265 CSSTracker.CSSTrackerView.StyleSheetTreeElement = class extends UI.TreeElement { |
| 270 /** | 266 /** |
| 271 * @param {string} url | 267 * @param {string} url |
| 272 * @param {!Array<!CSSTracker.RuleUsage>} ruleList | 268 * @param {!Array<!CSSTracker.RuleUsage>} ruleList |
| 273 */ | 269 */ |
| 274 constructor(url, ruleList) { | 270 constructor(url, ruleList) { |
| 275 super('', true); | 271 super('', true); |
| 276 | 272 |
| 277 this._uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); | 273 this._uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); |
| 278 | 274 |
| 279 /** @type {!Array<!CSSTracker.RuleUsage>} */ | 275 /** @type {!Array<!CSSTracker.RuleUsage>} */ |
| 280 this._unusedRules = ruleList.filter(rule => !rule.wasUsed); | 276 this._unusedRules = ruleList.filter(rule => !rule.wasUsed); |
| 281 | 277 |
| 282 var lastLineNumber = 0; | 278 var lastLineNumber = 0; |
| 283 for (var i = this._unusedRules.length - 1; i >= 0; --i) { | 279 for (var i = this._unusedRules.length - 1; i >= 0; --i) { |
| 284 if (this._unusedRules[i].range) { | 280 if (this._unusedRules[i].range) { |
| 285 lastLineNumber = this._unusedRules[i].range.startLine; | 281 lastLineNumber = this._unusedRules[i].range.startLine; |
| 286 break; | 282 break; |
| 287 } | 283 } |
| 288 } | 284 } |
| 289 this._numberOfSpaces = lastLineNumber.toString().length + 1; | 285 this._numberOfSpaces = lastLineNumber.toString().length + 1; |
| 290 | 286 |
| 291 this._percentUnused = Math.round(100 * this._unusedRules.length / ruleList.l
ength); | 287 this._percentUnused = Math.round(100 * this._unusedRules.length / ruleList.l
ength); |
| 292 | 288 |
| 293 this.toggleOnClick = true; | 289 this.toggleOnClick = true; |
| 294 this.selectable = false; | 290 this.selectable = false; |
| 295 | 291 |
| 296 /** @type {?TreeElement} */ | 292 /** @type {?UI.TreeElement} */ |
| 297 this._showAllRulesTreeElement = null; | 293 this._showAllRulesTreeElement = null; |
| 298 | 294 |
| 299 var title = createElementWithClass('div', 'rule-result'); | 295 var title = createElementWithClass('div', 'rule-result'); |
| 300 var titleText; | 296 var titleText; |
| 301 if (this._uiSourceCode) | 297 if (this._uiSourceCode) |
| 302 titleText = this._uiSourceCode.fullDisplayName(); | 298 titleText = this._uiSourceCode.fullDisplayName(); |
| 303 else | 299 else |
| 304 titleText = Common.UIString('Style Sheet was removed'); | 300 titleText = Common.UIString('Style Sheet was removed'); |
| 305 title.createChild('span', 'rule-result-file-name').textContent = titleText; | 301 title.createChild('span', 'rule-result-file-name').textContent = titleText; |
| 306 | 302 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 var anchor = Components.Linkifier.linkifyRevealable(this._uiSourceCode.uiL
ocation(lineNumber, columnNumber), ''); | 343 var anchor = Components.Linkifier.linkifyRevealable(this._uiSourceCode.uiL
ocation(lineNumber, columnNumber), ''); |
| 348 | 344 |
| 349 var lineNumberSpan = createElement('span'); | 345 var lineNumberSpan = createElement('span'); |
| 350 lineNumberSpan.classList.add('rule-match-line-number'); | 346 lineNumberSpan.classList.add('rule-match-line-number'); |
| 351 lineNumberSpan.textContent = numberToStringWithSpacesPadding(lineNumber +
1, this._numberOfSpaces); | 347 lineNumberSpan.textContent = numberToStringWithSpacesPadding(lineNumber +
1, this._numberOfSpaces); |
| 352 anchor.appendChild(lineNumberSpan); | 348 anchor.appendChild(lineNumberSpan); |
| 353 | 349 |
| 354 var contentSpan = anchor.createChild('span', 'rule-match-content'); | 350 var contentSpan = anchor.createChild('span', 'rule-match-content'); |
| 355 contentSpan.textContent = rule.selector; | 351 contentSpan.textContent = rule.selector; |
| 356 | 352 |
| 357 var ruleElement = new TreeElement(); | 353 var ruleElement = new UI.TreeElement(); |
| 358 ruleElement.selectable = true; | 354 ruleElement.selectable = true; |
| 359 this.appendChild(ruleElement); | 355 this.appendChild(ruleElement); |
| 360 ruleElement.listItemElement.className = 'rule-match source-code'; | 356 ruleElement.listItemElement.className = 'rule-match source-code'; |
| 361 ruleElement.listItemElement.appendChild(anchor); | 357 ruleElement.listItemElement.appendChild(anchor); |
| 362 } | 358 } |
| 363 } | 359 } |
| 364 | 360 |
| 365 /** | 361 /** |
| 366 * @param {number} startMatchIndex | 362 * @param {number} startMatchIndex |
| 367 */ | 363 */ |
| 368 _appendShowAllRulesButton(startMatchIndex) { | 364 _appendShowAllRulesButton(startMatchIndex) { |
| 369 var rulesLeftCount = this._unusedRules.length - startMatchIndex; | 365 var rulesLeftCount = this._unusedRules.length - startMatchIndex; |
| 370 var button = createTextButton('', this._showMoreRulesElementSelected.bind(th
is, startMatchIndex)); | 366 var button = UI.createTextButton('', this._showMoreRulesElementSelected.bind
(this, startMatchIndex)); |
| 371 button.textContent = Common.UIString('Show all rules (%d more).', rulesLeftC
ount); | 367 button.textContent = Common.UIString('Show all rules (%d more).', rulesLeftC
ount); |
| 372 this._showAllRulesTreeElement = new TreeElement(button); | 368 this._showAllRulesTreeElement = new UI.TreeElement(button); |
| 373 this._showAllRulesTreeElement.selectable = false; | 369 this._showAllRulesTreeElement.selectable = false; |
| 374 this.appendChild(this._showAllRulesTreeElement); | 370 this.appendChild(this._showAllRulesTreeElement); |
| 375 } | 371 } |
| 376 | 372 |
| 377 /** | 373 /** |
| 378 * @param {number} startMatchIndex | 374 * @param {number} startMatchIndex |
| 379 */ | 375 */ |
| 380 _showMoreRulesElementSelected(startMatchIndex) { | 376 _showMoreRulesElementSelected(startMatchIndex) { |
| 381 if (!this._showAllRulesTreeElement) | 377 if (!this._showAllRulesTreeElement) |
| 382 return; | 378 return; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 412 else | 408 else |
| 413 element.className = 'text-editor-css-rule-unused-marker'; | 409 element.className = 'text-editor-css-rule-unused-marker'; |
| 414 | 410 |
| 415 textEditor.setGutterDecoration(line, gutterType, element); | 411 textEditor.setGutterDecoration(line, gutterType, element); |
| 416 } | 412 } |
| 417 } | 413 } |
| 418 } | 414 } |
| 419 }; | 415 }; |
| 420 | 416 |
| 421 CSSTracker.CSSTrackerView.LineDecorator.type = 'coverage'; | 417 CSSTracker.CSSTrackerView.LineDecorator.type = 'coverage'; |
| OLD | NEW |