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

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

Issue 2644753002: DevTools: untruncate links on copy (Closed)
Patch Set: ac Created 3 years, 7 months 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 unified diff | Download patch
OLDNEW
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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 * @param {!Element} anchor 296 * @param {!Element} anchor
297 * @param {!Bindings.LiveLocation} liveLocation 297 * @param {!Bindings.LiveLocation} liveLocation
298 */ 298 */
299 _updateAnchor(anchor, liveLocation) { 299 _updateAnchor(anchor, liveLocation) {
300 Components.Linkifier._unbindUILocation(anchor); 300 Components.Linkifier._unbindUILocation(anchor);
301 var uiLocation = liveLocation.uiLocation(); 301 var uiLocation = liveLocation.uiLocation();
302 if (!uiLocation) 302 if (!uiLocation)
303 return; 303 return;
304 304
305 Components.Linkifier._bindUILocation(anchor, uiLocation); 305 Components.Linkifier._bindUILocation(anchor, uiLocation);
306 var text = uiLocation.linkText(); 306 var text = uiLocation.linkText(true /* skipTrim */);
307 var info = Components.Linkifier._linkInfo(anchor); 307 Components.Linkifier._setTrimmedText(anchor, text, this._maxLength);
308 info.originalLinkText = text;
309 text = text.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, '$1\u2026');
310 if (this._maxLength)
311 text = text.trimMiddle(this._maxLength);
312 anchor.textContent = text;
313 308
314 var titleText = uiLocation.uiSourceCode.url(); 309 var titleText = uiLocation.uiSourceCode.url();
315 if (typeof uiLocation.lineNumber === 'number') 310 if (typeof uiLocation.lineNumber === 'number')
316 titleText += ':' + (uiLocation.lineNumber + 1); 311 titleText += ':' + (uiLocation.lineNumber + 1);
317 anchor.title = titleText; 312 anchor.title = titleText;
318 anchor.classList.toggle('webkit-html-blackbox-link', liveLocation.isBlackbox ed()); 313 anchor.classList.toggle('webkit-html-blackbox-link', liveLocation.isBlackbox ed());
319 Components.Linkifier._updateLinkDecorations(anchor); 314 Components.Linkifier._updateLinkDecorations(anchor);
320 } 315 }
321 316
322 /** 317 /**
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 * @param {boolean=} preventClick 384 * @param {boolean=} preventClick
390 * @returns{!Element} 385 * @returns{!Element}
391 */ 386 */
392 static _createLink(text, className, maxLength, title, href, preventClick) { 387 static _createLink(text, className, maxLength, title, href, preventClick) {
393 var link = createElementWithClass('span', className); 388 var link = createElementWithClass('span', className);
394 link.classList.add('devtools-link'); 389 link.classList.add('devtools-link');
395 if (title) 390 if (title)
396 link.title = title; 391 link.title = title;
397 if (href) 392 if (href)
398 link.href = href; 393 link.href = href;
399 link.textContent = text; 394 Components.Linkifier._setTrimmedText(link, text, maxLength);
400 if (maxLength)
401 link.textContent = link.textContent.trimMiddle(maxLength);
402 link[Components.Linkifier._infoSymbol] = { 395 link[Components.Linkifier._infoSymbol] = {
403 icon: null, 396 icon: null,
404 enableDecorator: false, 397 enableDecorator: false,
405 uiLocation: null, 398 uiLocation: null,
406 liveLocation: null, 399 liveLocation: null,
407 url: href || null, 400 url: href || null,
408 lineNumber: null, 401 lineNumber: null,
409 columnNumber: null, 402 columnNumber: null,
410 revealable: null, 403 revealable: null,
411 fallback: null, 404 fallback: null
412 originalLinkText: text
413 }; 405 };
414 if (!preventClick) 406 if (!preventClick)
415 link.addEventListener('click', Components.Linkifier._handleClick, false); 407 link.addEventListener('click', Components.Linkifier._handleClick, false);
416 else 408 else
417 link.classList.add('devtools-link-prevent-click'); 409 link.classList.add('devtools-link-prevent-click');
418 return link; 410 return link;
419 } 411 }
420 412
421 /** 413 /**
422 * @param {?Element} link 414 * @param {!Element} link
423 * @return {?string} 415 * @param {string} text
416 * @param {number=} maxLength
424 */ 417 */
425 static originalLinkText(link) { 418 static _setTrimmedText(link, text, maxLength) {
426 var info = this._linkInfo(link); 419 link.removeChildren();
427 return info ? info.originalLinkText : null; 420 if (maxLength && text.length > maxLength) {
421 var middleSplit = splitMiddle(text, maxLength);
422 appendTextWithoutHashes(middleSplit[0]);
423 appendHiddenText(middleSplit[1]);
424 appendTextWithoutHashes(middleSplit[2]);
425 } else {
426 appendTextWithoutHashes(text);
427 }
428
429 /**
430 * @param {string} string
431 */
432 function appendHiddenText(string) {
433 var ellipsisNode = link.createChild('span', 'devtools-link-ellipsis').crea teTextChild('\u2026');
434 ellipsisNode[Components.Linkifier._untruncatedNodeTextSymbol] = string;
435 }
436
437 /**
438 * @param {string} string
439 */
440 function appendTextWithoutHashes(string) {
441 var hashSplit = TextUtils.TextUtils.splitStringByRegexes(string, [/[a-f0-9 ]{20,}/g]);
442 for (var match of hashSplit) {
443 if (match.regexIndex === -1) {
444 link.createTextChild(match.value);
445 } else {
446 link.createTextChild(match.value.substring(0, 7));
447 appendHiddenText(match.value.substring(7));
448 }
449 }
450 }
451
452 /**
453 * @param {string} string
454 * @param {number} maxLength
455 * @return {!Array<string>}
456 */
457 function splitMiddle(string, maxLength) {
458 var leftIndex = Math.floor(maxLength / 2);
459 var rightIndex = string.length - Math.ceil(maxLength / 2) + 1;
460
461 // Do not truncate between characters that use multiple code points (emoji s).
462 if (string.codePointAt(rightIndex - 1) >= 0x10000) {
463 rightIndex++;
464 leftIndex++;
465 }
466 if (leftIndex > 0 && string.codePointAt(leftIndex - 1) >= 0x10000)
467 leftIndex--;
468 return [string.substring(0, leftIndex), string.substring(leftIndex, rightI ndex), string.substring(rightIndex)];
469 }
428 } 470 }
429 471
430 /** 472 /**
473 * @param {!Node} node
474 * @return {string}
475 */
476 static untruncatedNodeText(node) {
477 return node[Components.Linkifier._untruncatedNodeTextSymbol] || node.textCon tent;
478 }
479
480 /**
431 * @param {?Element} link 481 * @param {?Element} link
432 * @return {?Components._LinkInfo} 482 * @return {?Components._LinkInfo}
433 */ 483 */
434 static _linkInfo(link) { 484 static _linkInfo(link) {
435 return /** @type {?Components._LinkInfo} */ (link ? link[Components.Linkifie r._infoSymbol] || null : null); 485 return /** @type {?Components._LinkInfo} */ (link ? link[Components.Linkifie r._infoSymbol] || null : null);
436 } 486 }
437 487
438 /** 488 /**
439 * @param {!Event} event 489 * @param {!Event} event
440 */ 490 */
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 } 592 }
543 }; 593 };
544 594
545 /** @type {!Set<!Components.Linkifier>} */ 595 /** @type {!Set<!Components.Linkifier>} */
546 Components.Linkifier._instances = new Set(); 596 Components.Linkifier._instances = new Set();
547 /** @type {?Components.LinkDecorator} */ 597 /** @type {?Components.LinkDecorator} */
548 Components.Linkifier._decorator = null; 598 Components.Linkifier._decorator = null;
549 599
550 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); 600 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors');
551 Components.Linkifier._infoSymbol = Symbol('Linkifier.info'); 601 Components.Linkifier._infoSymbol = Symbol('Linkifier.info');
602 Components.Linkifier._untruncatedNodeTextSymbol = Symbol('Linkifier.untruncatedN odeText');
552 603
553 /** 604 /**
554 * @typedef {{ 605 * @typedef {{
555 * icon: ?UI.Icon, 606 * icon: ?UI.Icon,
556 * enableDecorator: boolean, 607 * enableDecorator: boolean,
557 * uiLocation: ?Workspace.UILocation, 608 * uiLocation: ?Workspace.UILocation,
558 * liveLocation: ?Bindings.LiveLocation, 609 * liveLocation: ?Bindings.LiveLocation,
559 * url: ?string, 610 * url: ?string,
560 * lineNumber: ?number, 611 * lineNumber: ?number,
561 * columnNumber: ?number, 612 * columnNumber: ?number,
562 * revealable: ?Object, 613 * revealable: ?Object,
563 * fallback: ?Element, 614 * fallback: ?Element
564 * originalLinkText: string
565 * }} 615 * }}
566 */ 616 */
567 Components._LinkInfo; 617 Components._LinkInfo;
568 618
569 /** 619 /**
570 * The maximum length before strings are considered too long for finding URLs. 620 * The maximum length before strings are considered too long for finding URLs.
571 * @const 621 * @const
572 * @type {number} 622 * @type {number}
573 */ 623 */
574 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; 624 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 contextMenu.appendSeparator(); 830 contextMenu.appendSeparator();
781 contextMenu.appendItem(Common.UIString('Save'), save.bind(null, false)); 831 contextMenu.appendItem(Common.UIString('Save'), save.bind(null, false));
782 832
783 if (contentProvider instanceof Workspace.UISourceCode) { 833 if (contentProvider instanceof Workspace.UISourceCode) {
784 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider ); 834 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider );
785 if (!uiSourceCode.project().canSetFileContent()) 835 if (!uiSourceCode.project().canSetFileContent())
786 contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.b ind(null, true)); 836 contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.b ind(null, true));
787 } 837 }
788 } 838 }
789 }; 839 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698