OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 } | 70 } |
71 | 71 |
72 _updateAllAnchorDecorations() { | 72 _updateAllAnchorDecorations() { |
73 for (var anchors of this._anchorsByTarget.values()) { | 73 for (var anchors of this._anchorsByTarget.values()) { |
74 for (var anchor of anchors) | 74 for (var anchor of anchors) |
75 Components.Linkifier._updateLinkDecorations(anchor); | 75 Components.Linkifier._updateLinkDecorations(anchor); |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 /** | 79 /** |
80 * @param {?Components.Linkifier.LinkHandler} handler | |
81 */ | |
82 static setLinkHandler(handler) { | |
83 Components.Linkifier._linkHandler = handler; | |
84 } | |
85 | |
86 /** | |
87 * @param {string} url | |
88 * @param {number=} lineNumber | |
89 * @return {boolean} | |
90 */ | |
91 static handleLink(url, lineNumber) { | |
92 if (!Components.Linkifier._linkHandler) | |
93 return false; | |
94 return Components.Linkifier._linkHandler.handleLink(url, lineNumber); | |
95 } | |
96 | |
97 /** | |
98 * @param {!Element} anchor | 80 * @param {!Element} anchor |
99 * @param {!Workspace.UILocation} uiLocation | 81 * @param {!Workspace.UILocation} uiLocation |
100 */ | 82 */ |
101 static _bindUILocation(anchor, uiLocation) { | 83 static _bindUILocation(anchor, uiLocation) { |
102 Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation; | 84 Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation; |
103 if (!uiLocation) | 85 if (!uiLocation) |
104 return; | 86 return; |
105 var uiSourceCode = uiLocation.uiSourceCode; | 87 var uiSourceCode = uiLocation.uiSourceCode; |
106 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors ]; | 88 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors ]; |
107 if (!sourceCodeAnchors) { | 89 if (!sourceCodeAnchors) { |
(...skipping 12 matching lines...) Expand all Loading... | |
120 return; | 102 return; |
121 | 103 |
122 var uiSourceCode = info.uiLocation.uiSourceCode; | 104 var uiSourceCode = info.uiLocation.uiSourceCode; |
123 info.uiLocation = null; | 105 info.uiLocation = null; |
124 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors ]; | 106 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors ]; |
125 if (sourceCodeAnchors) | 107 if (sourceCodeAnchors) |
126 sourceCodeAnchors.delete(anchor); | 108 sourceCodeAnchors.delete(anchor); |
127 } | 109 } |
128 | 110 |
129 /** | 111 /** |
130 * @param {!SDK.Target} target | |
131 * @param {string} scriptId | |
132 * @param {number} lineNumber | |
133 * @param {number=} columnNumber | |
134 * @return {string} | |
135 */ | |
136 static liveLocationText(target, scriptId, lineNumber, columnNumber) { | |
137 var debuggerModel = SDK.DebuggerModel.fromTarget(target); | |
138 if (!debuggerModel) | |
139 return ''; | |
140 var script = debuggerModel.scriptForId(scriptId); | |
141 if (!script) | |
142 return ''; | |
143 var location = /** @type {!SDK.DebuggerModel.Location} */ ( | |
144 debuggerModel.createRawLocation(script, lineNumber, columnNumber || 0)); | |
145 var uiLocation = | |
146 /** @type {!Workspace.UILocation} */ (Bindings.debuggerWorkspaceBinding. rawLocationToUILocation(location)); | |
147 return uiLocation.linkText(); | |
148 } | |
149 | |
150 /** | |
151 * @override | 112 * @override |
152 * @param {!SDK.Target} target | 113 * @param {!SDK.Target} target |
153 */ | 114 */ |
154 targetAdded(target) { | 115 targetAdded(target) { |
155 this._anchorsByTarget.set(target, []); | 116 this._anchorsByTarget.set(target, []); |
156 this._locationPoolByTarget.set(target, new Bindings.LiveLocationPool()); | 117 this._locationPoolByTarget.set(target, new Bindings.LiveLocationPool()); |
157 } | 118 } |
158 | 119 |
159 /** | 120 /** |
160 * @override | 121 * @override |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 | 420 |
460 /** | 421 /** |
461 * @param {!Event} event | 422 * @param {!Event} event |
462 */ | 423 */ |
463 static _handleClick(event) { | 424 static _handleClick(event) { |
464 var link = /** @type {!Element} */ (event.currentTarget); | 425 var link = /** @type {!Element} */ (event.currentTarget); |
465 event.consume(true); | 426 event.consume(true); |
466 if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.targe t))) | 427 if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.targe t))) |
467 return; | 428 return; |
468 var info = Components.Linkifier._linkInfo(link); | 429 var info = Components.Linkifier._linkInfo(link); |
469 if (info.uiLocation && | |
470 Components.openAnchorLocationRegistry.dispatch( | |
471 {url: info.uiLocation.uiSourceCode.url(), lineNumber: info.uiLocatio n.lineNumber})) | |
472 return; | |
473 if (info.url && Components.openAnchorLocationRegistry.dispatch({url: info.ur l, lineNumber: info.lineNumber})) | |
474 return; | |
475 if (info.revealable) { | 430 if (info.revealable) { |
lushnikov
2016/11/21 20:51:09
this changes the order: revealable now prevails ov
dgozman
2016/11/21 23:34:50
Fixed.
| |
476 Common.Revealer.reveal(info.revealable); | 431 Common.Revealer.reveal(info.revealable); |
477 return; | 432 return; |
478 } | 433 } |
479 var actions = Components.Linkifier._linkActions(link); | 434 var actions = Components.Linkifier._linkActions(link); |
480 if (actions.length) | 435 if (actions.length) |
481 actions[0].handler.call(null); | 436 actions[0].handler.call(null); |
482 } | 437 } |
483 | 438 |
484 /** | 439 /** |
440 * @return {!Common.Setting} | |
441 */ | |
442 static _linkHandlerSetting() { | |
443 if (!Components.Linkifier._linkHandlerSettingInstance) { | |
444 Components.Linkifier._linkHandlerSettingInstance = | |
445 Common.settings.createSetting('openLinkHandler', Common.UIString('auto ')); | |
446 } | |
447 return Components.Linkifier._linkHandlerSettingInstance; | |
448 } | |
449 | |
450 /** | |
451 * @param {!{title: string, handler: !Components.Linkifier.LinkHandler}} entry | |
452 */ | |
453 static registerLinkHandler(entry) { | |
454 Components.Linkifier._linkHandlers.push(entry); | |
455 self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._upda te(); | |
456 } | |
457 | |
458 /** | |
459 * @param {string} title | |
460 */ | |
461 static unregisterLinkHandler(title) { | |
462 Components.Linkifier._linkHandlers = Components.Linkifier._linkHandlers.filt er(entry => entry.title !== title); | |
caseq
2016/11/21 20:13:09
if we remove by title, this could as well be a map
dgozman
2016/11/21 23:34:50
Done.
| |
463 self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._upda te(); | |
464 } | |
465 | |
466 /** | |
485 * @param {?Element} link | 467 * @param {?Element} link |
486 * @return {!Array<{title: string, handler: function()}>} | 468 * @return {!Array<{title: string, handler: function()}>} |
487 */ | 469 */ |
488 static _linkActions(link) { | 470 static _linkActions(link) { |
489 var info = Components.Linkifier._linkInfo(link); | 471 var info = Components.Linkifier._linkInfo(link); |
490 if (info && info.revealable) | 472 if (info && info.revealable) |
491 return []; | 473 return []; |
474 | |
492 var url = ''; | 475 var url = ''; |
493 var uiLocation = null; | 476 var uiLocation = null; |
477 var lineNumber = info.lineNumber || 0; | |
lushnikov
2016/11/21 20:51:09
let's inline this to the use-site
uiLocation ? uiL
dgozman
2016/11/21 23:34:50
Done.
| |
494 if (info && info.uiLocation) { | 478 if (info && info.uiLocation) { |
495 uiLocation = info.uiLocation; | 479 uiLocation = info.uiLocation; |
496 url = uiLocation.uiSourceCode.contentURL(); | 480 url = uiLocation.uiSourceCode.contentURL(); |
481 lineNumber = uiLocation.lineNumber; | |
497 } else if (info && info.url) { | 482 } else if (info && info.url) { |
498 url = info.url; | 483 url = info.url; |
499 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); | 484 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); |
500 uiLocation = uiSourceCode ? uiSourceCode.uiLocation(info.lineNumber || 0, info.columnNumber || 0) : null; | 485 uiLocation = uiSourceCode ? uiSourceCode.uiLocation(info.lineNumber || 0, info.columnNumber || 0) : null; |
501 } else { | 486 } else { |
502 return []; | 487 return []; |
503 } | 488 } |
504 | 489 |
505 var result = []; | 490 var result = []; |
506 if (uiLocation) | 491 var resource = Bindings.resourceForURL(url); |
507 result.push({title: Common.UIString('Open'), handler: () => Common.Reveale r.reveal(uiLocation)}); | 492 var request = SDK.NetworkLog.requestForURL(url); |
493 var contentProvider = uiLocation ? uiLocation.uiSourceCode : resource; | |
508 | 494 |
509 var resource = Bindings.resourceForURL(url); | 495 if (contentProvider) { |
lushnikov
2016/11/21 20:51:09
let's move this to the end.
dgozman
2016/11/21 23:34:50
Done.
| |
496 for (var entry of Components.Linkifier._linkHandlers) { | |
497 var action = { | |
498 title: Common.UIString.capitalize('Open using %s', entry.title), | |
499 handler: entry.handler.bind(null, contentProvider, lineNumber) | |
500 }; | |
501 if (entry.title === Components.Linkifier._linkHandlerSetting().get()) | |
502 result.unshift(action); | |
503 else | |
504 result.push(action); | |
505 } | |
506 } | |
507 if (uiLocation) { | |
508 result.push({ | |
509 title: Common.UIString.capitalize('Open in Sources ^panel'), | |
510 handler: () => Common.Revealer.reveal(uiLocation) | |
511 }); | |
512 } | |
510 if (resource) { | 513 if (resource) { |
511 result.push({ | 514 result.push({ |
512 title: Common.UIString.capitalize('Open ^link in Application ^panel'), | 515 title: Common.UIString.capitalize('Open in Application ^panel'), |
513 handler: () => Common.Revealer.reveal(resource) | 516 handler: () => Common.Revealer.reveal(resource) |
514 }); | 517 }); |
515 } | 518 } |
516 | |
517 var request = SDK.NetworkLog.requestForURL(url); | |
518 if (request) { | 519 if (request) { |
519 result.push({ | 520 result.push({ |
520 title: Common.UIString.capitalize('Open ^request in Network ^panel'), | 521 title: Common.UIString.capitalize('Open in Network ^panel'), |
521 handler: () => Common.Revealer.reveal(request) | 522 handler: () => Common.Revealer.reveal(request) |
522 }); | 523 }); |
523 } | 524 } |
524 | |
525 if (resource || info.url) { | 525 if (resource || info.url) { |
526 result.push({title: UI.openLinkExternallyLabel(), handler: () => Inspector FrontendHost.openInNewTab(url)}); | 526 result.push({title: UI.openLinkExternallyLabel(), handler: () => Inspector FrontendHost.openInNewTab(url)}); |
527 result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFro ntendHost.copyText(url)}); | 527 result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFro ntendHost.copyText(url)}); |
528 } | 528 } |
529 | |
530 return result; | 529 return result; |
531 } | 530 } |
532 }; | 531 }; |
533 | 532 |
534 /** @type {!Set<!Components.Linkifier>} */ | 533 /** @type {!Set<!Components.Linkifier>} */ |
535 Components.Linkifier._instances = new Set(); | 534 Components.Linkifier._instances = new Set(); |
536 /** @type {?Components.LinkDecorator} */ | 535 /** @type {?Components.LinkDecorator} */ |
537 Components.Linkifier._decorator = null; | 536 Components.Linkifier._decorator = null; |
538 | 537 |
539 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); | 538 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); |
(...skipping 22 matching lines...) Expand all Loading... | |
562 Components.Linkifier.MaxLengthForDisplayedURLs = 150; | 561 Components.Linkifier.MaxLengthForDisplayedURLs = 150; |
563 | 562 |
564 /** | 563 /** |
565 * The maximum length before strings are considered too long for finding URLs. | 564 * The maximum length before strings are considered too long for finding URLs. |
566 * @const | 565 * @const |
567 * @type {number} | 566 * @type {number} |
568 */ | 567 */ |
569 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; | 568 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; |
570 | 569 |
571 /** | 570 /** |
572 * @interface | 571 * @typedef {function(!Common.ContentProvider, number)} |
573 */ | 572 */ |
574 Components.Linkifier.LinkHandler = function() {}; | 573 Components.Linkifier.LinkHandler; |
575 | 574 |
576 Components.Linkifier.LinkHandler.prototype = { | 575 /** @type {!Array<{title: string, handler: !Components.Linkifier.LinkHandler}>} */ |
577 /** | 576 Components.Linkifier._linkHandlers = []; |
578 * @param {string} url | |
579 * @param {number=} lineNumber | |
580 * @return {boolean} | |
581 */ | |
582 handleLink(url, lineNumber) {} | |
583 }; | |
584 | 577 |
585 /** | 578 /** |
586 * @extends {Common.EventTarget} | 579 * @extends {Common.EventTarget} |
587 * @interface | 580 * @interface |
588 */ | 581 */ |
589 Components.LinkDecorator = function() {}; | 582 Components.LinkDecorator = function() {}; |
590 | 583 |
591 Components.LinkDecorator.prototype = { | 584 Components.LinkDecorator.prototype = { |
592 /** | 585 /** |
593 * @param {!Workspace.UISourceCode} uiSourceCode | 586 * @param {!Workspace.UISourceCode} uiSourceCode |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 appendApplicableItems(event, contextMenu, target) { | 666 appendApplicableItems(event, contextMenu, target) { |
674 var targetNode = /** @type {!Node} */ (target); | 667 var targetNode = /** @type {!Node} */ (target); |
675 while (targetNode && !targetNode[Components.Linkifier._infoSymbol]) | 668 while (targetNode && !targetNode[Components.Linkifier._infoSymbol]) |
676 targetNode = targetNode.parentNodeOrShadowHost(); | 669 targetNode = targetNode.parentNodeOrShadowHost(); |
677 var link = /** @type {?Element} */ (targetNode); | 670 var link = /** @type {?Element} */ (targetNode); |
678 var actions = Components.Linkifier._linkActions(link); | 671 var actions = Components.Linkifier._linkActions(link); |
679 for (var action of actions) | 672 for (var action of actions) |
680 contextMenu.appendItem(action.title, action.handler); | 673 contextMenu.appendItem(action.title, action.handler); |
681 } | 674 } |
682 }; | 675 }; |
676 | |
677 /** | |
678 * @implements {UI.SettingUI} | |
679 * @unrestricted | |
680 */ | |
681 Components.Linkifier.LinkHandlerSettingUI = class { | |
caseq
2016/11/21 20:13:09
Does it really belong to Linkifier?
| |
682 constructor() { | |
683 this._element = createElementWithClass('select', 'chrome-select'); | |
684 this._element.addEventListener('change', this._onChange.bind(this), false); | |
685 this._update(); | |
686 } | |
687 | |
688 _update() { | |
689 this._element.removeChildren(); | |
690 var names = Components.Linkifier._linkHandlers.map(entry => entry.title); | |
691 names.unshift(Common.UIString('auto')); | |
692 for (var name of names) { | |
693 var option = createElement('option'); | |
694 option.textContent = name; | |
695 option.selected = name === Components.Linkifier._linkHandlerSetting().get( ); | |
696 this._element.appendChild(option); | |
697 } | |
698 this._element.disabled = names.length <= 1; | |
699 } | |
700 | |
701 /** | |
702 * @param {!Event} event | |
703 */ | |
704 _onChange(event) { | |
705 var value = event.target.value; | |
706 Components.Linkifier._linkHandlerSetting().set(value); | |
707 } | |
708 | |
709 /** | |
710 * @override | |
711 * @return {?Element} | |
712 */ | |
713 settingElement() { | |
714 return UI.SettingsUI.createCustomSetting(Common.UIString('Link handling:'), this._element); | |
715 } | |
716 }; | |
717 | |
718 /** | |
719 * @implements {UI.ContextMenu.Provider} | |
720 * @unrestricted | |
721 */ | |
722 Components.Linkifier.ContentProviderContextMenuProvider = class { | |
723 /** | |
724 * @override | |
725 * @param {!Event} event | |
726 * @param {!UI.ContextMenu} contextMenu | |
727 * @param {!Object} target | |
728 */ | |
729 appendApplicableItems(event, contextMenu, target) { | |
730 var contentProvider = /** @type {!Common.ContentProvider} */ (target); | |
731 if (!contentProvider.contentURL()) | |
732 return; | |
733 | |
734 contextMenu.appendItem( | |
735 UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(c ontentProvider.contentURL())); | |
736 for (var entry of Components.Linkifier._linkHandlers) { | |
737 contextMenu.appendItem( | |
738 Common.UIString.capitalize('Open using %s', entry.title), entry.handle r.bind(null, contentProvider, 0)); | |
739 } | |
740 if (contentProvider instanceof SDK.NetworkRequest) | |
741 return; | |
742 | |
743 contextMenu.appendItem( | |
744 UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(contentP rovider.contentURL())); | |
745 if (!contentProvider.contentType().isDocumentOrScriptOrStyleSheet()) | |
746 return; | |
747 | |
748 /** | |
749 * @param {boolean} forceSaveAs | |
750 * @param {?string} content | |
751 */ | |
752 function doSave(forceSaveAs, content) { | |
753 var url = contentProvider.contentURL(); | |
754 Workspace.fileManager.save(url, /** @type {string} */ (content), forceSave As); | |
755 Workspace.fileManager.close(url); | |
756 } | |
757 | |
758 /** | |
759 * @param {boolean} forceSaveAs | |
760 */ | |
761 function save(forceSaveAs) { | |
762 if (contentProvider instanceof Workspace.UISourceCode) { | |
763 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvid er); | |
764 if (forceSaveAs) | |
765 uiSourceCode.saveAs(); | |
766 else | |
767 uiSourceCode.commitWorkingCopy(); | |
768 return; | |
769 } | |
770 contentProvider.requestContent().then(doSave.bind(null, forceSaveAs)); | |
771 } | |
772 | |
773 contextMenu.appendSeparator(); | |
774 contextMenu.appendItem(Common.UIString('Save'), save.bind(null, false)); | |
775 | |
776 if (contentProvider instanceof Workspace.UISourceCode) { | |
777 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider ); | |
778 if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem && | |
779 uiSourceCode.project().type() !== Workspace.projectTypes.Snippets) | |
780 contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.b ind(null, true)); | |
781 } | |
782 } | |
783 }; | |
OLD | NEW |