Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Unified Diff: third_party/WebKit/Source/devtools/front_end/components/Linkifier.js

Issue 2512353002: [DevTools] Refactor Linkifier to unify link processing. (Closed)
Patch Set: rebased Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 a619cb3a3301f4017ec4e940c8600be582924cc6..9a2de9ec0458fb3b55c85074a1487b5c15d71824 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
@@ -95,46 +95,11 @@ Components.Linkifier = class {
}
/**
- * @param {!Object} revealable
- * @param {string} text
- * @param {string=} fallbackHref
- * @param {number=} fallbackLineNumber
- * @param {string=} title
- * @param {string=} classes
- * @return {!Element}
- */
- static linkifyUsingRevealer(revealable, text, fallbackHref, fallbackLineNumber, title, classes) {
- var a = createElement('a');
- a.className = (classes || '') + ' webkit-html-resource-link';
- a.textContent = text.trimMiddle(Components.Linkifier.MaxLengthForDisplayedURLs);
- a.title = title || text;
- if (fallbackHref) {
- a.href = fallbackHref;
- a.lineNumber = fallbackLineNumber;
- }
-
- /**
- * @param {!Event} event
- * @this {Object}
- */
- function clickHandler(event) {
- event.stopImmediatePropagation();
- event.preventDefault();
- if (fallbackHref && Components.Linkifier.handleLink(fallbackHref, fallbackLineNumber))
- return;
-
- Common.Revealer.reveal(this);
- }
- a.addEventListener('click', clickHandler.bind(revealable), false);
- return a;
- }
-
- /**
* @param {!Element} anchor
* @param {!Workspace.UILocation} uiLocation
*/
static _bindUILocation(anchor, uiLocation) {
- anchor[Components.Linkifier._uiLocationSymbol] = uiLocation;
+ Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation;
if (!uiLocation)
return;
var uiSourceCode = uiLocation.uiSourceCode;
@@ -150,11 +115,12 @@ Components.Linkifier = class {
* @param {!Element} anchor
*/
static _unbindUILocation(anchor) {
- if (!anchor[Components.Linkifier._uiLocationSymbol])
+ var info = Components.Linkifier._linkInfo(anchor);
+ if (!info.uiLocation)
return;
- var uiSourceCode = anchor[Components.Linkifier._uiLocationSymbol].uiSourceCode;
- anchor[Components.Linkifier._uiLocationSymbol] = null;
+ var uiSourceCode = info.uiLocation.uiSourceCode;
+ info.uiLocation = null;
var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors];
if (sourceCodeAnchors)
sourceCodeAnchors.delete(anchor);
@@ -199,16 +165,15 @@ Components.Linkifier = class {
locationPool.disposeAll();
var anchors = this._anchorsByTarget.remove(target);
for (var anchor of anchors) {
- delete anchor[Components.Linkifier._liveLocationSymbol];
+ var info = Components.Linkifier._linkInfo(anchor);
+ info.liveLocation = null;
Components.Linkifier._unbindUILocation(anchor);
- var fallbackAnchor = anchor[Components.Linkifier._fallbackAnchorSymbol];
- if (fallbackAnchor) {
- anchor.href = fallbackAnchor.href;
- anchor.lineNumber = fallbackAnchor.lineNumber;
- anchor.title = fallbackAnchor.title;
- anchor.className = fallbackAnchor.className;
- anchor.textContent = fallbackAnchor.textContent;
- delete anchor[Components.Linkifier._fallbackAnchorSymbol];
+ if (info.fallback) {
+ anchor.href = info.fallback.href;
+ anchor.title = info.fallback.title;
+ anchor.className = info.fallback.className;
+ anchor.textContent = info.fallback.textContent;
+ anchor[Components.Linkifier._infoSymbol] = info.fallback[Components.Linkifier._infoSymbol];
}
}
}
@@ -237,14 +202,16 @@ Components.Linkifier = class {
if (!rawLocation)
return fallbackAnchor;
- var anchor = this._createAnchor(classes);
- var liveLocation = Bindings.debuggerWorkspaceBinding.createLiveLocation(
+ var anchor = Components.Linkifier._createLink('', classes || '');
+ var info = Components.Linkifier._linkInfo(anchor);
+ info.enableDecorator = this._useLinkDecorator;
+ info.fallback = fallbackAnchor;
+ info.liveLocation = Bindings.debuggerWorkspaceBinding.createLiveLocation(
rawLocation, this._updateAnchor.bind(this, anchor),
/** @type {!Bindings.LiveLocationPool} */ (this._locationPoolByTarget.get(rawLocation.target())));
+
var anchors = /** @type {!Array<!Element>} */ (this._anchorsByTarget.get(rawLocation.target()));
anchors.push(anchor);
- anchor[Components.Linkifier._liveLocationSymbol] = liveLocation;
- anchor[Components.Linkifier._fallbackAnchorSymbol] = fallbackAnchor;
return anchor;
}
@@ -305,14 +272,16 @@ Components.Linkifier = class {
if (rawLocations.length === 0)
return fallbackAnchor;
- var anchor = this._createAnchor(classes);
- var liveLocation = Bindings.debuggerWorkspaceBinding.createStackTraceTopFrameLiveLocation(
+ var anchor = Components.Linkifier._createLink('', classes || '');
+ var info = Components.Linkifier._linkInfo(anchor);
+ info.enableDecorator = this._useLinkDecorator;
+ info.fallback = fallbackAnchor;
+ info.liveLocation = Bindings.debuggerWorkspaceBinding.createStackTraceTopFrameLiveLocation(
rawLocations, this._updateAnchor.bind(this, anchor),
/** @type {!Bindings.LiveLocationPool} */ (this._locationPoolByTarget.get(target)));
+
var anchors = /** @type {!Array<!Element>} */ (this._anchorsByTarget.get(target));
anchors.push(anchor);
- anchor[Components.Linkifier._liveLocationSymbol] = liveLocation;
- anchor[Components.Linkifier._fallbackAnchorSymbol] = fallbackAnchor;
return anchor;
}
@@ -322,13 +291,15 @@ Components.Linkifier = class {
* @return {!Element}
*/
linkifyCSSLocation(rawLocation, classes) {
- var anchor = this._createAnchor(classes);
- var liveLocation = Bindings.cssWorkspaceBinding.createLiveLocation(
+ var anchor = Components.Linkifier._createLink('', classes || '');
+ var info = Components.Linkifier._linkInfo(anchor);
+ info.enableDecorator = this._useLinkDecorator;
+ info.liveLocation = Bindings.cssWorkspaceBinding.createLiveLocation(
rawLocation, this._updateAnchor.bind(this, anchor),
/** @type {!Bindings.LiveLocationPool} */ (this._locationPoolByTarget.get(rawLocation.target())));
+
var anchors = /** @type {!Array<!Element>} */ (this._anchorsByTarget.get(rawLocation.target()));
anchors.push(anchor);
- anchor[Components.Linkifier._liveLocationSymbol] = liveLocation;
return anchor;
}
@@ -338,38 +309,12 @@ Components.Linkifier = class {
*/
disposeAnchor(target, anchor) {
Components.Linkifier._unbindUILocation(anchor);
- delete anchor[Components.Linkifier._fallbackAnchorSymbol];
- var liveLocation = anchor[Components.Linkifier._liveLocationSymbol];
- if (liveLocation)
- liveLocation.dispose();
- delete anchor[Components.Linkifier._liveLocationSymbol];
- }
-
- /**
- * @param {string=} classes
- * @return {!Element}
- */
- _createAnchor(classes) {
- var anchor = createElement('a');
- if (this._useLinkDecorator)
- anchor[Components.Linkifier._enableDecoratorSymbol] = true;
- anchor.className = (classes || '') + ' webkit-html-resource-link';
-
- /**
- * @param {!Event} event
- */
- function clickHandler(event) {
- var uiLocation = anchor[Components.Linkifier._uiLocationSymbol];
- if (!uiLocation)
- return;
-
- event.consume(true);
- if (Components.Linkifier.handleLink(uiLocation.uiSourceCode.url(), uiLocation.lineNumber))
- return;
- Common.Revealer.reveal(uiLocation);
+ var info = Components.Linkifier._linkInfo(anchor);
+ info.fallback = null;
+ if (info.liveLocation) {
+ info.liveLocation.dispose();
+ info.liveLocation = null;
}
- anchor.addEventListener('click', clickHandler, false);
- return anchor;
}
reset() {
@@ -415,20 +360,19 @@ Components.Linkifier = class {
* @param {!Element} anchor
*/
static _updateLinkDecorations(anchor) {
- if (!anchor[Components.Linkifier._enableDecoratorSymbol])
+ var info = Components.Linkifier._linkInfo(anchor);
+ if (!info || !info.enableDecorator)
return;
- var uiLocation = anchor[Components.Linkifier._uiLocationSymbol];
- if (!Components.Linkifier._decorator || !uiLocation)
+ if (!Components.Linkifier._decorator || !info.uiLocation)
return;
- var icon = anchor[Components.Linkifier._iconSymbol];
- if (icon)
- icon.remove();
- icon = Components.Linkifier._decorator.linkIcon(uiLocation.uiSourceCode);
+ if (info.icon)
+ anchor.removeChild(info.icon);
+ var icon = Components.Linkifier._decorator.linkIcon(info.uiLocation.uiSourceCode);
if (icon) {
icon.style.setProperty('margin-right', '2px');
anchor.insertBefore(icon, anchor.firstChild);
}
- anchor[Components.Linkifier._iconSymbol] = icon;
+ info.icon = icon;
}
/**
@@ -440,31 +384,77 @@ Components.Linkifier = class {
* @return {!Element}
*/
static linkifyURL(url, text, className, lineNumber, columnNumber) {
- if (!url) {
+ if (!url || url.trim().toLowerCase().startsWith('javascript:')) {
var element = createElementWithClass('span', className);
- element.textContent = text || Common.UIString('(unknown)');
+ element.textContent = text || url || Common.UIString('(unknown)');
return element;
}
var linkText = text || Bindings.displayNameForURL(url);
if (typeof lineNumber === 'number' && !text)
linkText += ':' + (lineNumber + 1);
+ var title = linkText !== url ? url : '';
+ var link = Components.Linkifier._createLink(linkText.trimMiddle(150), className || '', title, url);
+ var info = Components.Linkifier._linkInfo(link);
+ if (typeof lineNumber === 'number')
+ info.lineNumber = lineNumber;
+ if (typeof columnNumber === 'number')
+ info.columnNumber = columnNumber;
+ return link;
+ }
+ /**
+ * @param {!Object} revealable
+ * @param {string} text
+ * @param {string=} fallbackHref
+ * @return {!Element}
+ */
+ static linkifyRevealable(revealable, text, fallbackHref) {
+ var link = Components.Linkifier._createLink(
+ text.trimMiddle(Components.Linkifier.MaxLengthForDisplayedURLs), '', undefined, fallbackHref);
+ Components.Linkifier._linkInfo(link).revealable = revealable;
+ return link;
+ }
+
+ /**
+ * @param {string} text
+ * @param {string} className
+ * @param {string=} title
+ * @param {string=} href
+ * @returns{!Element}
+ */
+ static _createLink(text, className, title, href) {
var link = createElementWithClass('a', className);
- if (!url.trim().toLowerCase().startsWith('javascript:')) {
- link.href = url;
- link.classList.add('webkit-html-resource-link');
- link[Components.Linkifier._linkSymbol] = true;
- link.addEventListener('click', Components.Linkifier._handleClick, false);
- }
- link.title = linkText !== url ? url : '';
- link.textContent = linkText.trimMiddle(150);
- link.lineNumber = lineNumber;
- link.columnNumber = columnNumber;
+ link.classList.add('webkit-html-resource-link');
+ if (title)
+ link.title = title;
+ if (href)
+ link.href = href;
+ link.textContent = text;
+ link[Components.Linkifier._infoSymbol] = {
+ icon: null,
+ enableDecorator: false,
+ uiLocation: null,
+ liveLocation: null,
+ url: href || null,
+ lineNumber: null,
+ columnNumber: null,
+ revealable: null,
+ fallback: null
+ };
+ link.addEventListener('click', Components.Linkifier._handleClick, false);
return link;
}
/**
+ * @param {?Element} link
+ * @return {?Components._LinkInfo}
+ */
+ static _linkInfo(link) {
+ return /** @type {?Components._LinkInfo} */ (link ? link[Components.Linkifier._infoSymbol] || null : null);
+ }
+
+ /**
* @param {!Event} event
*/
static _handleClick(event) {
@@ -472,8 +462,17 @@ Components.Linkifier = class {
event.consume(true);
if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.target)))
return;
- if (Components.openAnchorLocationRegistry.dispatch({url: link.href, lineNumber: link.lineNumber}))
+ var info = Components.Linkifier._linkInfo(link);
+ if (info.uiLocation &&
+ Components.openAnchorLocationRegistry.dispatch(
+ {url: info.uiLocation.uiSourceCode.url(), lineNumber: info.uiLocation.lineNumber}))
+ return;
+ if (info.url && Components.openAnchorLocationRegistry.dispatch({url: info.url, lineNumber: info.lineNumber}))
return;
+ if (info.revealable) {
+ Common.Revealer.reveal(info.revealable);
+ return;
+ }
var actions = Components.Linkifier._linkActions(link);
if (actions.length)
actions[0].handler.call(null);
@@ -484,27 +483,29 @@ Components.Linkifier = class {
* @return {!Array<{title: string, handler: function()}>}
*/
static _linkActions(link) {
- var url = null;
+ var info = Components.Linkifier._linkInfo(link);
+ var result = [];
+ if (!info)
+ return result;
+
+ var url = '';
var uiLocation = null;
- var isLiveLink = false;
- if (link && link[Components.Linkifier._uiLocationSymbol]) {
- uiLocation = /** @type {!Workspace.UILocation} */ (link[Components.Linkifier._uiLocationSymbol]);
+ if (info.uiLocation) {
+ uiLocation = info.uiLocation;
url = uiLocation.uiSourceCode.contentURL();
- isLiveLink = true;
- } else if (link && link.href) {
- url = link.href;
+ } else if (info.url) {
+ url = info.url;
var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
- uiLocation = uiSourceCode ? uiSourceCode.uiLocation(link.lineNumber || 0, link.columnNumber || 0) : null;
- isLiveLink = false;
- } else {
- return [];
+ uiLocation = uiSourceCode ? uiSourceCode.uiLocation(info.lineNumber || 0, info.columnNumber || 0) : null;
}
- var result = [];
+ if (info.revealable)
+ result.push({title: Common.UIString('Reveal'), handler: () => Common.Revealer.reveal(info.revealable)});
+
if (uiLocation)
result.push({title: Common.UIString('Open'), handler: () => Common.Revealer.reveal(uiLocation)});
- var resource = Bindings.resourceForURL(url);
+ var resource = url ? Bindings.resourceForURL(url) : null;
if (resource) {
result.push({
title: Common.UIString.capitalize('Open ^link in Application ^panel'),
@@ -512,7 +513,7 @@ Components.Linkifier = class {
});
}
- var request = SDK.NetworkLog.requestForURL(url);
+ var request = url ? SDK.NetworkLog.requestForURL(url) : null;
if (request) {
result.push({
title: Common.UIString.capitalize('Open ^request in Network ^panel'),
@@ -520,7 +521,7 @@ Components.Linkifier = class {
});
}
- if (resource || !isLiveLink) {
+ if (resource || info.url) {
result.push({title: UI.openLinkExternallyLabel(), handler: () => InspectorFrontendHost.openInNewTab(url)});
result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFrontendHost.copyText(url)});
}
@@ -534,13 +535,23 @@ Components.Linkifier._instances = new Set();
/** @type {?Components.LinkDecorator} */
Components.Linkifier._decorator = null;
-Components.Linkifier._iconSymbol = Symbol('Linkifier.iconSymbol');
-Components.Linkifier._enableDecoratorSymbol = Symbol('Linkifier.enableIconsSymbol');
Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors');
-Components.Linkifier._uiLocationSymbol = Symbol('uiLocation');
-Components.Linkifier._fallbackAnchorSymbol = Symbol('fallbackAnchor');
-Components.Linkifier._liveLocationSymbol = Symbol('liveLocation');
-Components.Linkifier._linkSymbol = Symbol('Linkifier.link');
+Components.Linkifier._infoSymbol = Symbol('Linkifier.info');
+
+/**
+ * @typedef {{
+ * icon: ?UI.Icon,
+ * enableDecorator: boolean,
+ * uiLocation: ?Workspace.UILocation,
+ * liveLocation: ?Bindings.LiveLocation,
+ * url: ?string,
+ * lineNumber: ?number,
+ * columnNumber: ?number,
+ * revealable: ?Object,
+ * fallback: ?Element
+ * }}
+ */
+Components._LinkInfo;
/**
* The maximum number of characters to display in a URL.
@@ -660,8 +671,7 @@ Components.Linkifier.LinkContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, target) {
var targetNode = /** @type {!Node} */ (target);
- while (targetNode && !targetNode[Components.Linkifier._linkSymbol] &&
- !targetNode[Components.Linkifier._uiLocationSymbol])
+ while (targetNode && !targetNode[Components.Linkifier._infoSymbol])
targetNode = targetNode.parentNodeOrShadowHost();
var link = /** @type {?Element} */ (targetNode);
var actions = Components.Linkifier._linkActions(link);

Powered by Google App Engine
This is Rietveld 408576698