Automatic URL Decodeder

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

  1. // ==UserScript==
  2. // @name Automatic URL Decodeder
  3. // @namespace https://github.com/T1mL3arn
  4. // @description:ru Декодирует все найденные на странице ссылки, похожие на "%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80", в удобочитаемое "привет мир"
  5. // @description:en It decodes all cyrillic links on current page.
  6. // @match *://*/*
  7. // @version 1.0
  8. // @run-at document-end
  9. // @grant none
  10. // @license GPLv3
  11. // ==/UserScript==
  12.  
  13. let linkEreg = /(https|http|ftp|file):.+?(?=\s|$)/gi;
  14. let linkEregLocal = /(https|http|ftp|file):.+?(?=\s|$)/i;
  15. let obsOptions = { childList: true, subtree: true };
  16.  
  17. let underlineStyle = new Map([["border-bottom","2px solid currentColor"], ["margin-bottom", "-2px"]]);
  18. // set one of style from above to enable
  19. // custom style for fixed links
  20. let changedLinkStyle = null;
  21.  
  22. let obs = new MutationObserver((changes, obs) => {
  23. changes.forEach((change) => change.addedNodes.forEach((node) => fixLinks(node)) );
  24. });
  25. obs.observe(document.body, obsOptions);
  26.  
  27. function fixLinks(node) {
  28. if (node.nodeType === 3) {
  29. let content = node.textContent;
  30. if (content && content != '') {
  31. if (linkEregLocal.test(content)) {
  32. if (changedLinkStyle)
  33. replaceAndStyleLink(node);
  34. else {
  35. let decoded = content.replace(linkEreg, decodeURIComponent);
  36. if(decoded.length!=content.length)
  37. node.textContent = decoded;
  38. }
  39. }
  40. }
  41. } else if (node.childNodes && node.childNodes.length > 0) {
  42. node.childNodes.forEach(fixLinks);
  43. }
  44. }
  45.  
  46. function replaceAndStyleLink(node) {
  47. let match;
  48. let offset = 0;
  49. let sibling = node;
  50. let content = node.textContent;
  51. obs.disconnect();
  52. while ((match = linkEreg.exec(content)) != null) {
  53. let fullMatch = match[0];
  54. let decoded = decodeURIComponent(fullMatch);
  55. if (decoded.length != fullMatch.length) {
  56. let span = document.createElement('span');
  57.  
  58. changedLinkStyle.forEach((val, key) => span.style.setProperty(key, val));
  59. let range = document.createRange();
  60. range.setStart(sibling, linkEreg.lastIndex - match[0].length);
  61. range.setEnd(sibling, linkEreg.lastIndex);
  62. range.surroundContents(span);
  63. sibling = getNextTextSibling(span);
  64. content = sibling.textContent;
  65. span.textContent = decoded;
  66. linkEreg.lastIndex = 0;
  67.  
  68. if (sibling == null)
  69. break;
  70. }
  71. }
  72. obs.observe(document.body, obsOptions);
  73. }
  74.  
  75. function getNextTextSibling(node) {
  76. let next = node.nextSibling;
  77. while (next != null) {
  78. if (next.nodeType == 3)
  79. return next;
  80. else
  81. next = node.nextSibling;
  82. }
  83. return null;
  84. }
  85.  
  86. fixLinks(document.body);