Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| index 97221657b101e52ec9c1174b31c44b5195f87c9a..96700c41aaa14845cefa0de285d5d7c835dc509f 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| @@ -42,10 +42,40 @@ WebInspector.Linkifier = class { |
| this._anchorsByTarget = new Map(); |
| /** @type {!Map<!WebInspector.Target, !WebInspector.LiveLocationPool>} */ |
| this._locationPoolByTarget = new Map(); |
| + WebInspector.Linkifier._instances.add(this); |
| WebInspector.targetManager.observeTargets(this); |
| } |
| /** |
| + * @param {!WebInspector.LinkifierIconProvider} iconProvider |
| + */ |
| + static registerIconProvider(iconProvider) { |
|
dgozman
2016/11/09 18:58:48
If you only support a single one, call it setDecor
lushnikov
2016/11/09 21:46:51
Done.
|
| + console.assert(!WebInspector.Linkifier._iconProvider, 'Cannot re-register icon provider.'); |
| + WebInspector.Linkifier._iconProvider = iconProvider; |
| + iconProvider.addEventListener(WebInspector.LinkifierIconProvider.Events.IconChanged, onIconChanged); |
| + for (var linkifier of WebInspector.Linkifier._instances) |
| + linkifier._updateAllAnchorIcons(); |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + function onIconChanged(event) { |
| + var uiSourceCode = /** @type {!WebInspector.UISourceCode} */(event.data); |
| + var anchors = uiSourceCode[WebInspector.Linkifier._sourceCodeAnchors] || []; |
| + for (var anchor of anchors) |
| + WebInspector.Linkifier._updateAnchorIcon(anchor); |
| + } |
| + } |
| + |
| + _updateAllAnchorIcons() { |
| + for (var target of this._anchorsByTarget.keysArray()) { |
| + var anchors = this._anchorsByTarget.get(target); |
| + for (var anchor of anchors) |
| + WebInspector.Linkifier._updateAnchorIcon(anchor); |
| + } |
| + } |
| + |
| + /** |
| * @param {?WebInspector.Linkifier.LinkHandler} handler |
| */ |
| static setLinkHandler(handler) { |
| @@ -81,6 +111,7 @@ WebInspector.Linkifier = class { |
| a.href = fallbackHref; |
| a.lineNumber = fallbackLineNumber; |
| } |
| + |
| /** |
| * @param {!Event} event |
| * @this {Object} |
| @@ -106,6 +137,36 @@ WebInspector.Linkifier = class { |
| } |
| /** |
| + * @param {!Element} anchor |
| + * @param {?WebInspector.UILocation} uiLocation |
| + */ |
| + static _bindAnchorToUILocation(anchor, uiLocation) { |
| + anchor[WebInspector.Linkifier._uiLocationSymbol] = uiLocation; |
| + if (!uiLocation) |
| + return; |
| + var uiSourceCode = uiLocation.uiSourceCode; |
| + var sourceCodeAnchors = uiSourceCode[WebInspector.Linkifier._sourceCodeAnchors]; |
| + if (!sourceCodeAnchors) { |
| + sourceCodeAnchors = new Set(); |
| + uiSourceCode[WebInspector.Linkifier._sourceCodeAnchors] = sourceCodeAnchors; |
| + } |
| + sourceCodeAnchors.add(anchor); |
| + } |
| + |
| + /** |
| + * @param {!Element} anchor |
| + */ |
| + static _unbindAnchorFromUILocation(anchor) { |
| + if (!anchor[WebInspector.Linkifier._uiLocationSymbol]) |
| + return; |
| + |
| + var uiSourceCode = anchor[WebInspector.Linkifier._uiLocationSymbol].uiSourceCode; |
| + var sourceCodeAnchors = uiSourceCode[WebInspector.Linkifier._sourceCodeAnchors]; |
| + if (sourceCodeAnchors) |
| + sourceCodeAnchors.delete(anchor); |
| + } |
| + |
| + /** |
| * @param {!WebInspector.Target} target |
| * @param {string} scriptId |
| * @param {number} lineNumber |
| @@ -145,6 +206,7 @@ WebInspector.Linkifier = class { |
| var anchors = this._anchorsByTarget.remove(target); |
| for (var anchor of anchors) { |
| delete anchor[WebInspector.Linkifier._liveLocationSymbol]; |
| + WebInspector.Linkifier._unbindAnchorFromUILocation(anchor); |
| var fallbackAnchor = anchor[WebInspector.Linkifier._fallbackAnchorSymbol]; |
| if (fallbackAnchor) { |
| anchor.href = fallbackAnchor.href; |
| @@ -266,7 +328,7 @@ WebInspector.Linkifier = class { |
| * @return {!Element} |
| */ |
| linkifyCSSLocation(rawLocation, classes) { |
| - var anchor = this._createAnchor(classes); |
| + var anchor = this._createAnchor(classes, true); |
|
dgozman
2016/11/09 18:58:48
This should be a parameter of linkifier.
lushnikov
2016/11/09 21:46:51
Done.
|
| var liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation( |
| rawLocation, this._updateAnchor.bind(this, anchor), |
| /** @type {!WebInspector.LiveLocationPool} */ (this._locationPoolByTarget.get(rawLocation.target()))); |
| @@ -281,7 +343,7 @@ WebInspector.Linkifier = class { |
| * @param {!Element} anchor |
| */ |
| disposeAnchor(target, anchor) { |
| - delete anchor[WebInspector.Linkifier._uiLocationSymbol]; |
| + WebInspector.Linkifier._unbindAnchorFromUILocation(anchor); |
| delete anchor[WebInspector.Linkifier._fallbackAnchorSymbol]; |
| var liveLocation = anchor[WebInspector.Linkifier._liveLocationSymbol]; |
| if (liveLocation) |
| @@ -291,10 +353,13 @@ WebInspector.Linkifier = class { |
| /** |
| * @param {string=} classes |
| + * @param {boolean=} enableIconDecorations |
| * @return {!Element} |
| */ |
| - _createAnchor(classes) { |
| + _createAnchor(classes, enableIconDecorations) { |
| var anchor = createElement('a'); |
| + if (enableIconDecorations) |
| + anchor[WebInspector.Linkifier._enableIconsSymbol] = true; |
| anchor.className = (classes || '') + ' webkit-html-resource-link'; |
| /** |
| @@ -325,6 +390,7 @@ WebInspector.Linkifier = class { |
| for (var target of this._anchorsByTarget.keysArray()) |
| this.targetRemoved(target); |
| WebInspector.targetManager.unobserveTargets(this); |
| + WebInspector.Linkifier._instances.delete(this); |
| } |
| /** |
| @@ -332,19 +398,12 @@ WebInspector.Linkifier = class { |
| * @param {!WebInspector.LiveLocation} liveLocation |
| */ |
| _updateAnchor(anchor, liveLocation) { |
| + WebInspector.Linkifier._unbindAnchorFromUILocation(anchor); |
| var uiLocation = liveLocation.uiLocation(); |
| + WebInspector.Linkifier._bindAnchorToUILocation(anchor, uiLocation); |
| if (!uiLocation) |
| return; |
| - anchor[WebInspector.Linkifier._uiLocationSymbol] = uiLocation; |
| - this._formatLiveAnchor(anchor, uiLocation, liveLocation.isBlackboxed()); |
| - } |
| - /** |
| - * @param {!Element} anchor |
| - * @param {!WebInspector.UILocation} uiLocation |
| - * @param {boolean} isBlackboxed |
| - */ |
| - _formatLiveAnchor(anchor, uiLocation, isBlackboxed) { |
| var text = uiLocation.linkText(); |
| text = text.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, '$1\u2026'); |
| if (this._maxLength) |
| @@ -355,11 +414,44 @@ WebInspector.Linkifier = class { |
| if (typeof uiLocation.lineNumber === 'number') |
| titleText += ':' + (uiLocation.lineNumber + 1); |
| anchor.title = titleText; |
| + anchor.classList.toggle('webkit-html-blackbox-link', liveLocation.isBlackboxed()); |
| + WebInspector.Linkifier._updateAnchorIcon(anchor); |
| + } |
| + |
| + /** |
| + * @param {!Element} anchor |
| + */ |
| + static _updateAnchorIcon(anchor) { |
| + if (!anchor[WebInspector.Linkifier._enableIconsSymbol]) |
| + return; |
| + var uiLocation = anchor[WebInspector.Linkifier._uiLocationSymbol]; |
| + if (!WebInspector.Linkifier._iconProvider || !uiLocation) |
| + return; |
| + var iconType = WebInspector.Linkifier._iconProvider.iconType(uiLocation.uiSourceCode); |
| + var icon = anchor.querySelector('span[is=ui-icon]'); |
| + if (!iconType) { |
| + if (icon) |
| + icon.setIconType(''); |
| + return; |
| + } |
| - anchor.classList.toggle('webkit-html-blackbox-link', isBlackboxed); |
| + if (!icon) { |
| + icon = WebInspector.Icon.create(iconType); |
| + icon.style.setProperty('margin-right', '2px'); |
| + anchor.insertBefore(icon, anchor.firstChild); |
| + } else { |
| + icon.setIconType(iconType); |
| + } |
| } |
| }; |
| +/** @type {!Set<!WebInspector.Linkifier>} */ |
| +WebInspector.Linkifier._instances = new Set(); |
| +/** @type {?WebInspector.LinkifierIconProvider} */ |
| +WebInspector.Linkifier._iconProvider = null; |
| + |
| +WebInspector.Linkifier._enableIconsSymbol = Symbol('Linkifier.enableIconsSymbol'); |
| +WebInspector.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); |
| WebInspector.Linkifier._uiLocationSymbol = Symbol('uiLocation'); |
| WebInspector.Linkifier._fallbackAnchorSymbol = Symbol('fallbackAnchor'); |
| WebInspector.Linkifier._liveLocationSymbol = Symbol('liveLocation'); |
| @@ -392,6 +484,23 @@ WebInspector.Linkifier.LinkHandler.prototype = { |
| handleLink: function(url, lineNumber) {} |
| }; |
| +/** |
| + * @extends {WebInspector.EventTarget} |
| + * @interface |
| + */ |
| +WebInspector.LinkifierIconProvider = function() {}; |
|
dgozman
2016/11/09 18:58:48
LinkDecorator
lushnikov
2016/11/09 21:46:51
Done.
|
| + |
| +WebInspector.LinkifierIconProvider.prototype = { |
| + /** |
| + * @param {!WebInspector.UISourceCode} uiSourceCode |
| + * @return {string} |
|
lushnikov
2016/11/09 18:23:28
it feels daunting to return a string here, but if
dgozman
2016/11/09 18:58:48
Let's go with WI.Icon.
lushnikov
2016/11/09 21:46:51
Done.
|
| + */ |
| + iconType: function(uiSourceCode) {} |
|
dgozman
2016/11/09 18:58:48
linkIcon
lushnikov
2016/11/09 21:46:51
Done.
|
| +}; |
| + |
| +WebInspector.LinkifierIconProvider.Events = { |
| + IconChanged: Symbol('IconChanged') |
|
dgozman
2016/11/09 18:58:48
LinkIconChanged
lushnikov
2016/11/09 21:46:51
Done.
|
| +}; |
| /** |
| * @param {string} string |