Text To link

Turn plain text URLs into clickable links

当前为 2018-02-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Text To link
  3. // @description Turn plain text URLs into clickable links
  4. // @description:zh 把文字链接转换为可点击链接
  5. // @author lkytal
  6. // @namespace Lkytal
  7. // @version 2.8.5
  8. // @homepage https://lkytal.github.io/
  9. // @homepageURL https://lkytal.github.io/coldfire/GM
  10. // @license LGPL
  11. // @include *
  12. // @exclude *pan.baidu.com/*
  13. // @exclude *renren.com/*
  14. // @exclude *exhentai.org/*
  15. // @exclude *music.google.com/*
  16. // @exclude *play.google.com/music/*
  17. // @exclude *mail.google.com/*
  18. // @exclude *docs.google.com/*
  19. // @exclude *www.google.*
  20. // @exclude *acid3.acidtests.org/*
  21. // @exclude *.163.com/*
  22. // @exclude *.alipay.com/*
  23. // @run-at document-end
  24. // @icon https://github.com/lkytal/GM/raw/master/icons/link.png
  25. // @grant unsafeWindow
  26. // @charset UTF-8
  27. // @supportURL https://github.com/lkytal/GM/issues
  28. // ==/UserScript==
  29.  
  30. "use strict";
  31. ;
  32. var clearLink, excludedTags, linkFilter, linkMixInit, linkPack, linkify, observePage, observer, setLink, urlPrefixes, url_regexp, xPath;
  33.  
  34. url_regexp = /((https?:\/\/|www\.)[\x21-\x7e]+[\w\/]|(\w[\w._-]+\.(com|cn|org|net|info|tv|cc|gov|edu))(\/[\x21-\x7e]*[\w\/])?|ed2k:\/\/[\x21-\x7e]+\|\/|thunder:\/\/[\x21-\x7e]+=)/gi;
  35.  
  36. urlPrefixes = ['http://', 'https://', 'ftp://', 'thunder://', 'ed2k://'];
  37.  
  38. clearLink = function (event) {
  39. var j, len, link, prefix, ref, url;
  40. link = (ref = event.originalTarget) != null ? ref : event.target;
  41. if (!(link != null && link.localName === "a" && link.className.indexOf("textToLink") !== -1)) {
  42. return;
  43. }
  44. url = link.getAttribute("href");
  45. //console.log url
  46. for (j = 0, len = urlPrefixes.length; j < len; j++) {
  47. prefix = urlPrefixes[j];
  48. if (url.indexOf(prefix) === 0) {
  49. return;
  50. }
  51. }
  52. return link.setAttribute("href", "http://" + url);
  53. };
  54.  
  55. document.addEventListener("mouseover", clearLink);
  56.  
  57. setLink = function (candidate) {
  58. var span, text;
  59. if (candidate == null || candidate.parentNode.className.indexOf("textToLink") !== -1 || candidate.nodeName === "#cdata-section") {
  60. return;
  61. }
  62. text = candidate.textContent.replace(url_regexp, '<a href="$1" target="_blank" class="textToLink">$1</a>');
  63. if (candidate.textContent.length === text.length) {
  64. return;
  65. }
  66. span = document.createElement("span");
  67. span.innerHTML = text;
  68. return candidate.parentNode.replaceChild(span, candidate);
  69. };
  70.  
  71. excludedTags = "a,svg,canvas,applet,input,button,area,pre,embed,frame,frameset,head,iframe,img,option,map,meta,noscript,object,script,style,textarea,code".split(",");
  72.  
  73. xPath = '//text()[not(ancestor::' + excludedTags.join(') and not(ancestor::') + ')]';
  74.  
  75. linkPack = function (result, start) {
  76. var i, j, k, ref, ref1, ref2, ref3, startTime;
  77. startTime = Date.now();
  78. while (start + 10000 < result.snapshotLength) {
  79. for (i = j = ref = start, ref1 = start + 10000; undefined !== 0 && (ref <= ref1 ? ref <= j && j <= ref1 : ref >= j && j >= ref1); i = ref <= ref1 ? ++j : --j) {
  80. setLink(result.snapshotItem(i));
  81. }
  82. start += 10000;
  83. if (Date.now() - startTime > 2500) {
  84. return;
  85. }
  86. }
  87. for (i = k = ref2 = start, ref3 = result.snapshotLength; undefined !== 0 && (ref2 <= ref3 ? ref2 <= k && k <= ref3 : ref2 >= k && k >= ref3); i = ref2 <= ref3 ? ++k : --k) {
  88. setLink(result.snapshotItem(i));
  89. }
  90. };
  91.  
  92. linkify = function (node) {
  93. var result;
  94. result = document.evaluate(xPath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  95. return linkPack(result, 0);
  96. };
  97.  
  98. linkFilter = function (node) {
  99. var j, len, tag;
  100. for (j = 0, len = excludedTags.length; j < len; j++) {
  101. tag = excludedTags[j];
  102. if (tag === node.parentNode.localName.toLowerCase()) {
  103. return NodeFilter.FILTER_REJECT;
  104. }
  105. }
  106. return NodeFilter.FILTER_ACCEPT;
  107. };
  108.  
  109. observePage = function (root) {
  110. var tW;
  111. tW = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { //+ NodeFilter.SHOW_ELEMENT,
  112. acceptNode: linkFilter
  113. }, false);
  114. while (tW.nextNode()) {
  115. setLink(tW.currentNode);
  116. }
  117. };
  118.  
  119. observer = new window.MutationObserver(function (mutations) {
  120. var Node, j, k, len, len1, mutation, ref;
  121. for (j = 0, len = mutations.length; j < len; j++) {
  122. mutation = mutations[j];
  123. if (mutation.type === "childList") {
  124. ref = mutation.addedNodes;
  125. for (k = 0, len1 = ref.length; k < len1; k++) {
  126. Node = ref[k];
  127. observePage(Node);
  128. }
  129. }
  130. }
  131. });
  132.  
  133. linkMixInit = function () {
  134. if (window !== window.top || window.document.title === "") {
  135. return;
  136. }
  137. //console.time('a')
  138. linkify(document.body);
  139. //console.timeEnd('a')
  140. return observer.observe(document.body, {
  141. childList: true,
  142. subtree: true
  143. });
  144. };
  145.  
  146. setTimeout(linkMixInit, 100);