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