8chan /pol/ URL Cleaner

Fixes URLs with (.) before TLDs on 8chan.moe and 8chan.se /pol/ board

  1. // ==UserScript==
  2. // @name 8chan /pol/ URL Cleaner
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Fixes URLs with (.) before TLDs on 8chan.moe and 8chan.se /pol/ board
  6. // @author Leafanon
  7. // @match https://8chan.moe/pol/res/*
  8. // @match https://8chan.se/pol/res/*
  9. // @grant none
  10. // @license MIT
  11.  
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Function to fix URLs in text content and href attributes
  18. function fixUrl(url) {
  19. return url.replace(/\(\.\)(org|com|net)/gi, '.$1');
  20. }
  21.  
  22. // Process all links on the page
  23. function processLinks() {
  24. const links = document.querySelectorAll('a[href*="(.)"]');
  25. links.forEach(link => {
  26. // Fix href attribute
  27. if (link.href.includes('(.)')) {
  28. link.href = fixUrl(link.href);
  29. }
  30. // Fix text content if it contains the same pattern
  31. if (link.textContent.includes('(.)')) {
  32. link.textContent = fixUrl(link.textContent);
  33. }
  34. });
  35.  
  36. // Also process text nodes that might contain these URLs but aren't links yet
  37. const walker = document.createTreeWalker(
  38. document.body,
  39. NodeFilter.SHOW_TEXT,
  40. null,
  41. false
  42. );
  43.  
  44. let node;
  45. while (node = walker.nextNode()) {
  46. if (node.nodeValue.includes('(.)') &&
  47. (node.nodeValue.includes('.com') || node.nodeValue.includes('.org') || node.nodeValue.includes('.net'))) {
  48. const parent = node.parentNode;
  49. if (parent.nodeName !== 'A' && parent.nodeName !== 'SCRIPT' && parent.nodeName !== 'STYLE') {
  50. const newValue = fixUrl(node.nodeValue);
  51. if (newValue !== node.nodeValue) {
  52. // Replace the text node with HTML that may contain links
  53. const temp = document.createElement('div');
  54. temp.innerHTML = newValue.replace(/(https?:\/\/[^\s]+)/g, '<a target="_blank" href="$1">$1</a>');
  55. parent.replaceChild(temp, node);
  56. }
  57. }
  58. }
  59. }
  60. }
  61.  
  62. // Run initially and also observe DOM changes for dynamically loaded content
  63. processLinks();
  64.  
  65. // Use MutationObserver to handle dynamically loaded content
  66. const observer = new MutationObserver(function(mutations) {
  67. mutations.forEach(function(mutation) {
  68. if (mutation.addedNodes.length) {
  69. processLinks();
  70. }
  71. });
  72. });
  73.  
  74. observer.observe(document.body, {
  75. childList: true,
  76. subtree: true
  77. });
  78. })();