一键跳转到github的dev编辑器页面

一键跳转到github的dev编辑器页面!

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         一键跳转到github的dev编辑器页面
// @namespace    https://github.com/xxxily
// @homepage     https://github.com/xxxily
// @version      0.0.2
// @description  一键跳转到github的dev编辑器页面!
// @author       xxxily
// @match        https://github.com/*
// @run-at       document-start
// @license      MIT
// ==/UserScript==

/**
 * 元素监听器
 * @param selector -必选
 * @param fn -必选,元素存在时的回调
 * @param shadowRoot -可选 指定监听某个shadowRoot下面的DOM元素
 * 参考:https://javascript.ruanyifeng.com/dom/mutationobserver.html
 */
 function ready (selector, fn, shadowRoot) {
  const win = window
  const docRoot = shadowRoot || win.document.documentElement
  if (!docRoot) return false
  const MutationObserver = win.MutationObserver || win.WebKitMutationObserver
  const listeners = docRoot._MutationListeners || []

  function $ready (selector, fn) {
    // 储存选择器和回调函数
    listeners.push({
      selector: selector,
      fn: fn
    })

    /* 增加监听对象 */
    if (!docRoot._MutationListeners || !docRoot._MutationObserver) {
      docRoot._MutationListeners = listeners
      docRoot._MutationObserver = new MutationObserver(() => {
        for (let i = 0; i < docRoot._MutationListeners.length; i++) {
          const item = docRoot._MutationListeners[i]
          check(item.selector, item.fn)
        }
      })

      docRoot._MutationObserver.observe(docRoot, {
        childList: true,
        subtree: true
      })
    }

    // 检查节点是否已经在DOM中
    check(selector, fn)
  }

  function check (selector, fn) {
    const elements = docRoot.querySelectorAll(selector)
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i]
      element._MutationReadyList_ = element._MutationReadyList_ || []
      if (!element._MutationReadyList_.includes(fn)) {
        element._MutationReadyList_.push(fn)
        fn.call(element, element)
      }
    }
  }

  const selectorArr = Array.isArray(selector) ? selector : [selector]
  selectorArr.forEach(selector => $ready(selector, fn))
}

ready('a.btn', function (element) {
  if(!document.getElementById('goToDev') && element.innerText === 'Go to file'){
    const devBtn = document.createElement("a")
    devBtn.innerText = "Go to Dev"
    devBtn.id = "goToDev"
    devBtn.target = "_blank"
    devBtn.href = window.location.href.replace("github.com", "github.dev")
    devBtn.className = element.className
    element.parentNode.insertBefore(devBtn, element)
  }
})

// 旧的实现方式,需要document-end才能获取到元素,偶尔会有失败的情况,所以改成ready方式
// if(!document.getElementById('goToDev')){
//   const devBtn = document.createElement("a")
//   devBtn.innerText = "Go to Dev"
//   devBtn.id = "goToDev"
//   devBtn.target = "_blank"
//   devBtn.href = window.location.href.replace("github.com", "github.dev")

//   const btns = document.querySelectorAll("a.btn")
//   btns.forEach(btn => {
//     if(btn.innerText === "Go to file"){
//       devBtn.className = btn.className
//       btn.parentNode.insertBefore(devBtn, btn)
//     }
//   })
// }