Automatic URL Decoder

Декодирует все найденные на странице ссылки, похожие на "%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80", в удобочитаемое "привет мир"

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

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