Automatic URL Decoder

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

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

  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
  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. changes.forEach((change) => change.addedNodes.forEach((node) => fixLinks(node)) );
  27. });
  28. obs.observe(document.body, obsOptions);
  29.  
  30. function fixLinks(node) {
  31. if (node.tagName != 'SCRIPT' && node.nodeType === 3) {
  32. let content = node.textContent;
  33. if (content && content != '') {
  34. if (linkEregLocal.test(content)) {
  35. if (changedLinkStyle)
  36. replaceAndStyleLink(node);
  37. else {
  38. let decoded = content.replace(linkEreg, decodeURIComponent);
  39. if(decoded.length!=content.length)
  40. node.textContent = decoded;
  41. }
  42. }
  43. }
  44. } else if (node.childNodes && node.childNodes.length > 0) {
  45. node.childNodes.forEach(fixLinks);
  46. }
  47. }
  48.  
  49. function replaceAndStyleLink(node) {
  50. let match;
  51. let offset = 0;
  52. let sibling = node;
  53. let content = node.textContent;
  54. obs.disconnect();
  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. obs.observe(document.body, obsOptions);
  76. }
  77.  
  78. function getNextTextSibling(node) {
  79. let next = node.nextSibling;
  80. while (next != null) {
  81. if (next.nodeType == 3)
  82. return next;
  83. else
  84. next = node.nextSibling;
  85. }
  86. return null;
  87. }
  88.  
  89. fixLinks(document.body);