Automatic URL Decoder

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

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

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