FuckShortenedUrl

Replace shortened URLs with real URLs

当前为 2021-02-21 提交的版本,查看 最新版本

// ==UserScript==
// @name         FuckShortenedUrl
// @namespace    http://tampermonkey.net/
// @version      0.11
// @description  Replace shortened URLs with real URLs
// @author       wtfjs
// @match        https://*.douban.com/*
// @match        https://*.zhihu.com/*
// @match        https://*.twitter.com/*
// @match        https://*.youtube.com/*
// @grant        none
// ==/UserScript==

;(function __FuckShortenedUrl() {
  var utils = {
    $: function $(selector, parent) {
      var _parent = parent || document
      return _parent.querySelector(selector)
    },

    $$: function $$(selector, parent) {
      var _parent = parent || document
      return _parent.querySelectorAll(selector)
    },

    forEachRight: function forEachRight(arr, fn, _this) {
      var __this = Object(_this || this)
      for (var i = (arr.length >>> 0) - 1; i >= 0; i -= 1) {
        var it = arr[i]
        var res = fn.call(__this, it, i, arr)
        if (res === false) {
          break;
        }
      }
    },

    concurrent: function concurrent(job) {
      var dispatch = window.requestIdleCallback || window.requestAnimationFrame || window.setTimeout
      dispatch(job)
    },

    isElement: function isElement(any) {
      return typeof any === "object" && any.nodeType === 1 // Node.ELEMENT_NODE
    }
  }

  var handlers = [
    [
      /zhihu\.com*/,
      function transform($link) {
        var re = /https?:\/\/link\.zhihu\.com\/\?target=(\S+)/
        var matches = re.exec($link.href) 
        if (matches) {
          var realUrl = window.decodeURIComponent(matches[1])
          $link.href = realUrl
        }
        return $link
      }
    ],
    [
      /douban\.com*/,
      function transform($link) {
        var re = /https?:\/\/douc\.cc/
        if (re.test($link.href)) {
          $link.textContent = $link.textContent.replace($link.href, $link.title)
          $link.href = $link.title
        }
        return $link
      }
    ],
    [
      /twitter\.com*/,
      function transform($link) {
        var re = /https?:\/\/t\.co/
        if (re.test($link.href)) {
          $link.href = $link.textContent.replace(/((\.\.\.)|(…))$/, '')
        }
        return $link
      }
    ],
    [
      /youtube\.com*/,
      function transform($link) {
        var re = /https?:\/\/(www\.)?youtube\.com\/redirect\?/
        if (re.test($link.href)) {
          var href = window.decodeURIComponent($link.href)
          var idx = href.indexOf("&q=")
          if (idx > -1) {
            $link.href = href.slice(idx + 3)
          }
        }
        return $link
      }
    ]
  ]

  function transformLinks($links, handler) {
    utils.forEachRight($links, function(it) {
      if (it) {
        utils.concurrent(
          function transform() {
            handler[1](it)
          }
        )
      }
    })
  }

  function createMutationCallback(handlerToUse) {
    return function onDomMutation(mutationList) {
      utils.forEachRight(mutationList, function(mutation) {
        var addedNodes = mutation.addedNodes
        if (addedNodes.length > 0) {
          var $newLinks = []

          utils.forEachRight(addedNodes, function filterElement(node) {
            if (utils.isElement(node)) {
              utils.forEachRight(utils.$$("a", node), function addNewLink($link) {
                $newLinks.push($link)
              })
            }
          })

          transformLinks($newLinks, handlerToUse)
        }
      })
    }
  }

  function start() {
    var hostname = window.location.hostname

    var handlerToUse = null
    while (handlers.length > 0) {
      var handler = handlers.pop()
      if (handler[0].test(hostname)) {
        handlerToUse = handler
        break;
      }
    }

    if (handlerToUse) {
      transformLinks(utils.$$("a"), handlerToUse)
      var observer = new MutationObserver(createMutationCallback(handlerToUse))
      observer.observe(document.body, {subtree: true, childList: true})
    }
  }

  start()
})()