Advertisement
BigBisous

Linkify Plus

Dec 13th, 2016
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name        Linkify Plus
  3. // @version     2.1.4
  4. // @namespace   http://arantius.com/misc/greasemonkey/
  5. // @description Turn plain text URLs into links.    Supports http, https, ftp, email addresses.
  6. // @include     http*
  7. // @exclude     http://www.google.tld/search*
  8. // @exclude     https://www.google.tld/search*
  9. // @exclude     http://music.google.com/*
  10. // @exclude     https://music.google.com/*
  11. // @exclude     http://mail.google.com/*
  12. // @exclude     https://mail.google.com/*
  13. // @exclude     http://docs.google.com/*
  14. // @exclude     https://docs.google.com/*
  15. // @exclude     http://mxr.mozilla.org/*
  16. // ==/UserScript==
  17. //
  18. // Copyright (c) 2011, Anthony Lieuallen
  19. // All rights reserved.
  20. //
  21. // Redistribution and use in source and binary forms, with or without
  22. // modification, are permitted provided that the following conditions are met:
  23. //
  24. // * Redistributions of source code must retain the above copyright notice,
  25. //   this list of conditions and the following disclaimer.
  26. // * Redistributions in binary form must reproduce the above copyright notice,
  27. //   this list of conditions and the following disclaimer in the documentation
  28. //   and/or other materials provided with the distribution.
  29. // * Neither the name of Anthony Lieuallen nor the names of its contributors
  30. //   may be used to endorse or promote products derived from this software
  31. //   without specific prior written permission.
  32. //
  33. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  34. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  35. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  37. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  38. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  39. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  40. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  41. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  43. // POSSIBILITY OF SUCH DAMAGE.
  44. //
  45.  
  46. /*******************************************************************************
  47. Loosely based on the Linkify script located at:
  48.   http://downloads.mozdev.org/greasemonkey/linkify.user.js
  49.  
  50. Version history:
  51.  Version 2.1.4 (Aug 12, 2012):
  52.   - Bug fix for when (only some) nodes have been removed from the document.
  53.  Version 2.1.3 (Oct 24, 2011):
  54.   - More excludes.
  55.  Version 2.1.2:
  56.   - Some bug fixes.
  57.  Version 2.1.1:
  58.   - Ignore certain "highlighter" script containers.
  59.  Version 2.1:
  60.   - Rewrite the regular expression to be more readable.
  61.   - Fix trailing "." characters.
  62.  Version 2.0.3:
  63.   - Fix infinite recursion on X(HT)ML pages.
  64.  Version 2.0.2:
  65.   - Limit @include, for greater site/plugin compatibility.
  66.  Version 2.0.1:
  67.   - Fix aberrant 'mailto:' where it does not belong.
  68.  Version 2.0:
  69.   - Apply incrementally, so the browser does not hang on large pages.
  70.   - Continually apply to new content added to the page (i.e. AJAX).
  71.  Version 1.1.4:
  72.   - Basic "don't screw up xml pretty printing" exception case
  73.  Version 1.1.3:
  74.   - Include "+" in the username of email addresses.
  75.  Version 1.1.2:
  76.   - Include "." in the username of email addresses.
  77.  Version 1.1:
  78.   - Fixed a big that caused the first link in a piece of text to
  79.     be skipped (i.e. not linkified).
  80. *******************************************************************************/
  81.  
  82. var notInTags = [
  83.       'a', 'code', 'head', 'noscript', 'option', 'script', 'style',
  84.       'title', 'textarea'];
  85. var textNodeXpath =
  86.     ".//text()[not(ancestor::"+notInTags.join(') and not(ancestor::')+")]";
  87. // Built based on:
  88. //  - http://en.wikipedia.org/wiki/URI_scheme
  89. //  - http://www.regular-expressions.info/regexbuddy/email.html
  90. var urlRE = new RegExp(
  91.     '('
  92.     // leading scheme:// or "www."
  93.     + '\\b([a-z][-a-z0-9+.]+://|www\\.)'
  94.     // everything until non-URL character
  95.     + '[^\\s\'"<>()]+'
  96.     + '|'
  97.     // email
  98.     + '\\b[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}\\b'
  99.     + ')', 'gi');
  100. var queue = [];
  101.  
  102. /******************************************************************************/
  103.  
  104. linkifyContainer(document.body);
  105. document.body.addEventListener('DOMNodeInserted', function(event) {
  106.     linkifyContainer(event.target);
  107. }, false);
  108.  
  109. /******************************************************************************/
  110.  
  111. function linkifyContainer(container) {
  112.     // Prevent infinite recursion, in case X(HT)ML documents with namespaces
  113.     // break the XPath's attempt to do so.  (Don't evaluate spans we put our
  114.     // classname into.)
  115.     if (container.className && container.className.match(/\blinkifyplus\b/)) {
  116.       return;
  117.     }
  118.  
  119.     var xpathResult = document.evaluate(
  120.           textNodeXpath, container, null,
  121.           XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  122.  
  123.     var i = 0;
  124.     function continuation() {
  125.         var node = null, counter = 0;
  126.         while (node = xpathResult.snapshotItem(i++)) {
  127.           var parent = node.parentNode;
  128.           if (!parent) continue;
  129.  
  130.           // Skip styled <pre> -- often highlighted by script.
  131.           if ('PRE' == parent.tagName && parent.className) continue;
  132.          
  133.             linkifyTextNode(node);
  134.  
  135.             if (++counter > 50) {
  136.                 return setTimeout(continuation, 0);
  137.             }
  138.         }
  139.     }
  140.     setTimeout(continuation, 0);
  141. }
  142.  
  143. function linkifyTextNode(node) {
  144.     var i, l, m;
  145.     var txt = node.textContent;
  146.     var span = null;
  147.     var p = 0;
  148.     while (m = urlRE.exec(txt)) {
  149.         if (null == span) {
  150.             // Create a span to hold the new text with links in it.
  151.             span = document.createElement('span');
  152.             span.className = 'linkifyplus';
  153.         }
  154.  
  155.         //get the link without trailing dots
  156.         l = m[0].replace(/\.*$/, '');
  157.         var lLen = l.length;
  158.         //put in text up to the link
  159.         span.appendChild(document.createTextNode(txt.substring(p, m.index)));
  160.         //create a link and put it in the span
  161.         a = document.createElement('a');
  162.         a.className = 'linkifyplus';
  163.         a.appendChild(document.createTextNode(l));
  164.         if (l.indexOf(":/") < 0) {
  165.             if (l.indexOf("@") > 0) {
  166.                 l = "mailto:" + l;
  167.             } else {
  168.                 l = "http://" + l;
  169.           }
  170.         }
  171.         a.setAttribute('href', l);
  172.         span.appendChild(a);
  173.         //track insertion point
  174.         p = m.index+lLen;
  175.     }
  176.     if (span) {
  177.         //take the text after the last link
  178.         span.appendChild(document.createTextNode(txt.substring(p, txt.length)));
  179.         //replace the original text with the new span
  180.         try {
  181.             node.parentNode.replaceChild(span, node);
  182.         } catch (e) {
  183.             console.error(e);
  184.             console.log(node);
  185.         }
  186.     }
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement