// ==UserScript== // @name GitHub镜像 // @name:en GitHub Mirror // @description GitHub镜像,加速访问GitHub,支持Clone、Release、Raw、Zip加速。 // @description:en GitHub mirror. Accelerate access to GitHub. Support Clone, Release, RAW and ZIP acceleration. // @namespace https://github.com/HaleShaw // @version 1.4.0 // @author HaleShaw // @copyright 2021+, HaleShaw (https://github.com/HaleShaw) // @license AGPL-3.0-or-later // @homepage https://github.com/HaleShaw/TM-GitHubMirror // @supportURL https://github.com/HaleShaw/TM-GitHubMirror/issues // @contributionURL https://www.jianwudao.com/ // @icon https://github.githubassets.com/favicon.ico // @require https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js // @include *://github.com/* // @compatible Chrome // @run-at document-end // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @downloadURL https://update.greasyfork.icu/scripts/422802/GitHub%E9%95%9C%E5%83%8F.user.js // @updateURL https://update.greasyfork.icu/scripts/422802/GitHub%E9%95%9C%E5%83%8F.meta.js // ==/UserScript== // ==OpenUserJS== // @author HaleShaw // @collaborator HaleShaw // ==/OpenUserJS== (function () { ("use strict"); const style = ` /* The menu container */ .menuContainer { width: 600px; } .menuBlock { padding: 4px 0; color: #990000; } .menuLeftIcon{ margin-right:5px; } .menuButtonLabel{ margin-right: 2rem; } .menuButtonCheck{ vertical-align: text-bottom; margin: 0 3px; } .SelectMenu-list { padding: 0 16px; } .SelectMenu-list > a.SelectMenu-item { padding-left: 0; padding-right: 0; margin-top: 4px; } .clone { padding-left: 3px 12px !important; } .Box-body.download-box { border-bottom: none; width: 100%; text-align: right; padding: unset; } .Box-body.download-box > a { font-size: 11px; margin: 0 3px; padding: 0 6px; } `; const mirrors = [ { id: 0, name: "CnpmJS", url: "https://github.com.cnpmjs.org", description: "cnpmjs.org", }, { id: 1, name: "FastGit", url: "https://hub.fastgit.org", description: "KevinZonda", }, { id: 2, name: "FastGit", url: "https://download.fastgit.org", description: "KevinZonda", }, { id: 3, name: "FastGit", url: "https://raw.fastgit.org", description: "KevinZonda", }, { id: 4, name: "WuYanZheShui", url: "https://github.wuyanzheshui.workers.dev", description: "WuYanZheShui. Maximum of 100,000 calls per day", }, { id: 5, name: "RC1844", url: "https://github.rc1844.workers.dev", description: "RC1844. Maximum of 100,000 calls per day", }, { id: 6, name: "jsDelivr", url: "https://cdn.jsdelivr.net/gh", description: "The total file size of the current branch of the project cannot exceed 50MB", }, { id: 7, name: "IAPK", url: "https://github.iapk.cc", description: "IAPK", }, { id: 8, name: "Ecalose", url: "https://gh.haval.gq", description: "Ecalose. Maximum of 100,000 calls per day", }, { id: 9, name: "IAPK", url: "https://iapk.cc/github?url=https://github.com", description: "IAPK", }, { id: 10, name: "Statically", url: "https://cdn.staticaly.com/gh", description: "Only images and source code files are supported, and the file size is limited to 30MB", }, { id: 11, name: "Github 原生", url: "ssh://git@ssh.github.com:443/", description: "Github 官方提供的 443 端口的 SSH,适用于限制访问 22 端口的网络环境", }, { id: 12, name: "FastGit", url: "git@ssh.fastgit.org:", description: "FastGit 香港", }, ]; //添加对应索引即可使用 const cloneSet = [0, 1, 4]; const sshSet = [11, 12]; const browseSet = [0, 1, 4, 5, 7, 8]; const downloadSet = [2, 4, 5, 8, 9]; const rawSet = [3, 4, 5, 6, 8, 9, 10]; const messages = { en: { menuButton: { name: "CloneMirror", title: "Open List", header: "Quickly clone and Mirror sites", block: "Please do not login in the mirror site. I will not be responsible for any loss caused by this.", }, }, zh: { menuButton: { name: "克隆与镜像", title: "打开列表", header: "快速克隆与镜像站点", block: "请不要在镜像网站登录账号,若因此造成任何损失本人概不负责", }, }, }; const icons = { closeIcon: ` `, copyIcon: ` `, copiedIcon: ` `, }; const clonePrefix = "git clone "; const depthPrefix = "--depth=1 "; let message; let settingHtml; main(); $(document).on("pjax:success", function () { $("#mirror-menu").remove(); main(); }); function main() { GM_addStyle(style); logInfo(GM_info.script.name, GM_info.script.version); const prefix = getClonePrefix(); addMenu(prefix); setTimeout(() => { addHttpsClone(prefix); addSSHClone(prefix); addRawList(); }, 1000); if (isPC()) { addDownloadZip(); } // The Release page loads element dynamically. const callback = (mutationsList, observer) => { if (location.pathname.indexOf("/releases") === -1) return; for (const mutation of mutationsList) { for (const target of mutation.addedNodes) { if (target.nodeType !== 1) return; if ( target.tagName === "DIV" && target.dataset.viewComponent === "true" && target.classList[0] === "Box" ) addReleasesList(); } } }; const observer = new MutationObserver(callback); observer.observe(document, { childList: true, subtree: true }); } /** * Initialize setting. */ function initSetting() { let lang = GM_getValue("lang"); let clone = GM_getValue("clone"); let depth = GM_getValue("depth"); if (lang == undefined) { GM_setValue("lang", "zh"); } if (clone == undefined) { GM_setValue("clone", true); } if (depth == undefined) { GM_setValue("depth", true); } } function addMenu(prefix) { initSetting(); message = getMessage(true, true); settingHtml = getSettingHtml(); let menuButtonHtml = getMenuButtonPrefix() + getCloneList(prefix) + getBrowseList() + getMenuButtonSuffix(); $("div.d-flex.flex-wrap.flex-items-center.wb-break-word.f3.text-normal").append(menuButtonHtml); } function getMenuButtonPrefix() { return `
`; } function addSSHClone(prefix) { let sshGroup = document.querySelector('[role="tabpanel"]:nth-child(3) div.input-group'); if (!sshGroup) { return; } let inputs = sshGroup.querySelectorAll("input.clone"); if (inputs.length > 0) { return; } let defaultSsh = sshGroup.firstElementChild; const sshStr = defaultSsh.value; let hrefSplit = sshStr.split(":"); let groupHtml = ""; if (hrefSplit[0] != "git@github.com") { return; } defaultSsh.value = prefix + sshStr; defaultSsh.setAttribute("aria-label", prefix + sshStr); defaultSsh.className += " clone"; let button = sshGroup.querySelector("clipboard-copy"); button.setAttribute("value", prefix + sshStr); sshSet.forEach(id => { groupHtml += getCloneHtml(prefix + mirrors[id]["url"] + hrefSplit[1], mirrors[id]["name"]); }); sshGroup.insertAdjacentHTML("afterend", groupHtml); } /** * Get the clone command prefix. */ function getClonePrefix() { let prefix = ""; let clone = GM_getValue("clone"); let depth = GM_getValue("depth"); if (clone) { prefix += "git clone "; } if (depth) { prefix += "--depth=1 "; } return prefix; } /** * Get the clone button html string. * @param {String} url url. * @param {tip} tip tip. */ function getCloneHtml(url, tip) { return `