Link Sanitizer

Clean up unnecessary hyperlink redirections and link shims

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

Advertisement:

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

Advertisement:

// ==UserScript==
// @name         Link Sanitizer
// @description  Clean up unnecessary hyperlink redirections and link shims
// @version      1.2.2
// @author       wespe <[email protected]>
// @license      WTFPL 2.0; http://www.wtfpl.net/about/
// @namespace    https://github.com/cloux
// @homepage     https://github.com/cloux/LinkSanitizer
// @supportURL   https://github.com/cloux/LinkSanitizer
// @icon         http://icons.iconarchive.com/icons/designbolts/seo/128/Natural-Link-icon.png
// @include      *
// @run-at       document-start
// ==/UserScript==

(function() {
  // Limit contentType to "text/plain" or "text/html"
  if ((document.contentType != undefined) && (document.contentType != "text/plain") && (document.contentType != "text/html")) {
    console.log("Hyperlink Sanitizer - Not loading for content type " + document.contentType);
    return;
  }

  // Sanitize single link
  function sanitize(weblink) {
    // skip non-http links
    if (! /^http/.test(weblink)) {
      return weblink;
    }
    // whitelisted services
    if ( /google\.[a-z]*\/(ServiceLogin|Logout|AccountChooser)/.test(weblink) // google login service
      || /^https:\/\/(translate|consent)\.google\./.test(weblink)             // google services
      || /^http.*(login|registration)[./?].*http/.test(weblink)               // aliexpress, heise.de
      || /\/oauth\?/.test(weblink)                                            // OAuth on aws.amazon.com
      || /\/sign-?in[/?]/.test(weblink)                                       // amazon.com, google, gmail
      || /^https?:\/\/downloads\.(sourceforge|sf)\.net\//.test(weblink)       // downloads.sourceforge.net
      || /^https?:\/\/(www\.)?facebook\.com\/sharer/.test(weblink)            // share on FB
      || /^https?:\/\/(www\.)?linkedin\.com\/share/.test(weblink)             // share on linkedin
      || /^https?:\/\/(www\.)?pinterest\.com\/pin\/create\//.test(weblink)    // pinterest post
      || /^https?:\/\/(www\.)?getpocket\.com\/save/.test(weblink)             // save link to pocket
      || /^https?:\/\/[a-z.]*archive\.org\//.test(weblink)                    // archive.org
      || /^https?:\/\/github\.com\//.test(weblink)                            // Github
      || /^https:\/\/id\.atlassian\.com\//.test(weblink)                      // Atlassian Login
      ) {
      return weblink;
    }
    var cleanlink = weblink.replace(/^..*(https?(%3A|:)[^\\()&]*).*/, '$1');
    cleanlink = cleanlink.replace(/%23/g, '#').replace(/%26/g, '&').replace(/%2F/g, '/').replace(/%3A/g, ':').replace(/%3D/g, '=').replace(/%3F/g, '?');
    // NOTE: %25 must be translated last
    cleanlink = cleanlink.replace(/%25/g, '%');
    return cleanlink;
  }

  // Sanitize all HREF links within document
  function sanitize_links() {
    for (var element of document.getElementsByTagName("a")) {
      if (typeof element.href === 'undefined') {
        continue;
      }
      var link = element.getAttribute('href');
      if (! /..https?(%3A|:)/.test(link)) {
        continue;
      }
      var sanitizedLink = sanitize(link);
      if (link != sanitizedLink) {
        console.log("Hyperlink: " + link);
        console.log("SANITIZED: " + sanitizedLink);
        element.setAttribute('href', sanitizedLink);
      }
    }
  }

  function mutation_callback(mutationsList) {
    for (var mutation of mutationsList) {
      if ((mutation.type == "attributes") || (mutation.type == "childList")) {
        sanitize_links();
        return;
      }
    }
  }

  function load_sanitizer() {
    sanitize_links();
    // Create an observer instance linked to the callback function
    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    var observer = new MutationObserver(mutation_callback);
    // Start observing added elements and changes of href attributes
    observer.observe(window.document.documentElement, { attributeFilter: [ "href" ], childList: true, subtree: true });
  }

  window.addEventListener("load", load_sanitizer);
})();