Greasy Fork is available in English.

不要翻译github上的代码

避免google网页翻译github和npm站点中的代码

Version au 27/12/2019. Voir la dernière version.

// ==UserScript==
// @name         不要翻译github上的代码
// @namespace    http://floatsyi.com/
// @version      0.4.1
// @description  避免google网页翻译github和npm站点中的代码
// @author       floatsyi
// @license      MIT
// @include      *://github.com*
// @include      *://www.npmjs.com*
// @match        *://github.com*
// @match        *://www.npmjs.com*
// ==/UserScript==
/* jshint esversion: 6 */
;(function () {
  'use strict'
  // debug log
  const isDev = false
  const log = (...args) => {
    isDev && console.log(args)
  }
  const style = 'font-size: inherit;'
  const addCodeEle = function (ele) {
    ele.innerHTML = '<code class="doNotTranslate">' + ele.innerHTML + '</code>'
  }
  const hasCodeEleChild = function (ele) {
    return !!ele.querySelector('code')
  }
  const addPreEle = function (ele) {
    ele.innerHTML = `<pre style= "${style}"><code class="doNotTranslate" style="${style}">${
      ele.innerHTML
    }</code></pre>`
  }
  const hasPreEleChild = function (ele) {
    return !!ele.querySelector('code')
  }
  const _ = {}
  _.debounce = function (func, wait) {
    var lastCallTime
    var lastThis
    var lastArgs
    var timerId

    function startTimer (timerExpired, wait) {
      return setTimeout(timerExpired, wait)
    }

    function remainingWait (time) {
      const timeSinceLastCall = time - lastCallTime
      const timeWaiting = wait - timeSinceLastCall
      return timeWaiting
    }

    function shoudInvoking (time) {
      return lastCallTime !== undefined && time - lastCallTime >= wait
    }

    function timerExpired () {
      const time = Date.now()
      if (shoudInvoking(time)) {
        return invokeFunc()
      }
      timerId = startTimer(timerExpired, remainingWait(time))
    }

    function invokeFunc () {
      timerId = undefined
      const args = lastArgs
      const thisArg = lastThis
      let result = func.apply(thisArg, args)
      lastArgs = lastThis = undefined
      return result
    }

    function debounced (...args) {
      let time = Date.now()
      lastThis = this
      lastArgs = args
      lastCallTime = time
      if (timerId === undefined) {
        timerId = startTimer(timerExpired, wait)
      }
    }

    return debounced
  }

  const doNotTranslateFilenamesAndDirectories = () => {
    const fileAndDirectory = document.querySelectorAll(
      '.file-wrap .js-navigation-item .js-navigation-open'
    )
    ;[...fileAndDirectory].forEach(item => {
      if (!hasPreEleChild(item)) {
        addPreEle(item)
      }
    })
  }

  const doNotTranslateCodeContentPages = () => {
    const codeContainer = document.querySelector('.js-file-line-container')
    if (codeContainer) {
      const main = document.querySelector('main')
      if (main.parentNode.nodeName !== 'CODE') {
        main.parentNode.innerHTML = `<code>${main.parentNode.innerHTML}</code>`
      }
    }
  }

  const doNotTranslateTitle = () => {
    ;['1', '2', '3', '4', '5', '6'].forEach(item => {
      const itemEle = document.querySelectorAll(`h${item}`)
      // 没找到就退出
      if (!itemEle) return false
      ;[...itemEle].forEach(el => {
        // 如果是 issues 标题就退出
        if (el.classList.contains('gh-header-title')) return false
        if (!hasCodeEleChild(el)) addCodeEle(el)
      })
    })
  }

  const doNotTranslateCode = () => {
    const files = document.querySelectorAll('.file')
    const pres = document.querySelectorAll('pre')

    if (files.length > 0) {
      if (window.location.href.search(/.md/i) !== -1) {
        if (pres.length > 0) {
          pres.forEach(function (pre) {
            if (!hasCodeEleChild(pre)) addCodeEle(pre)
          })
        }
      } else {
        files.forEach(function (file) {
          if (!hasCodeEleChild(file)) addCodeEle(file)
        })
      }
    } else if (pres.length > 0) {
      pres.forEach(function (pre) {
        if (!hasCodeEleChild(pre)) addCodeEle(pre)
      })
    }
  }

  // 监听DOM变更
  const githubTV = document.querySelector('body')
  const npmTV = document.querySelector('body')
  const isGitHub =
    window.location.href.search(/github.com/i) !== -1 && !!githubTV
  const isNPM = window.location.href.search(/npmjs.com/i) !== -1 && !!npmTV

  const option = {
    childList: true,
    subtree: true
  }

  let time = 0

  const doNotTranslate = function (mutations, observer) {
    // 处于过于频繁的 DOM 变更时, 暂停监听 50ms, 并放弃累积的未处理的变更事件
    if (time >= 20) {
      observer.disconnect()
      observer.takeRecords()
      time = 0
      setTimeout(function () {
        isGitHub && observer.observe(githubTV, option)
        isNPM && observer.observe(npmTV, option)
      }, 50)
    }

    // 如果是编辑页就退出
    if (window.location.href.match('/edit/') !== null) return false

    // 不要翻译文件名与目录
    doNotTranslateFilenamesAndDirectories()
    // 不要翻译代码内容页
    doNotTranslateCodeContentPages()
    // 不要翻译代码
    doNotTranslateCode()
    // 不要翻译标题
    doNotTranslateTitle()

    time++
    log(`第${time}次执行: doNotTranslate`)
  }

  const MutationObserver =
    window.MutationObserver ||
    window.WebKitMutationObserver ||
    window.MozMutationObserver
  const mo = new MutationObserver(_.debounce(doNotTranslate, 50))
  isGitHub && mo.observe(githubTV, option)
  isNPM && mo.observe(npmTV, option)
})()