您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork镜像 is available in English.
12/8/2023, 9:09:51 PM
当前为
// ==UserScript== // @name GitHub: Redirect forked repo links to own repo // @namespace Violentmonkey Scripts // @match https://github.com/* // @grant none // @version 0.1.1 // @author CY Fung // @description 12/8/2023, 9:09:51 PM // @run-at document-start // @license MIT // ==/UserScript== /** * * This is to change links in markdown files from the original repo links to your forked repo links * **/ (() => { let rafPromise = null; const rafFn = (typeof webkitRequestAnimationFrame !== 'undefined' ? webkitRequestAnimationFrame : requestAnimationFrame).bind(window); // eslint-disable-line no-undef, no-constant-condition const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => { rafFn(hRes => { rafPromise = null; resolve(hRes); }); })); const matcher = h => typeof h == 'string' && h.length > 19 && h.startsWith('https://github.com/') && /^https\:\/\/github\.com\/([\w\d\-\.]+)\/([\w\d\-\.]+)/.exec(h); const pageInfo = { ready: false, matched: false, owner: '', repo: '', originalOwner: '', originalRepo: '', url: '', }; const PromiseExternal = ((resolve_, reject_) => { const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject }; return class PromiseExternal extends Promise { constructor(cb = h) { super(cb); if (cb === h) { /** @type {(value: any) => void} */ this.resolve = resolve_; /** @type {(reason?: any) => void} */ this.reject = reject_; } } }; })(); let pageOriginalP = new PromiseExternal(); document.addEventListener('DOMContentLoaded', () => { // Define the XPath expression var xpathExpression = "//span[contains(text(), 'forked from')]"; // Use document.evaluate to find the matching element var result = document.evaluate(xpathExpression, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); var spanElement = result.singleNodeValue; // Check if a matching element was found if (spanElement instanceof Element) { setTimeout(() => { const a = spanElement.querySelector('a[href]'); if (a) { const h = a.href; let m = matcher(h); if (m) { pageInfo.originalOwner = m[1]; pageInfo.originalRepo = m[2]; pageInfo.originalRepoUrl = `https://github.com/${pageInfo.originalOwner}/${pageInfo.originalRepo}/`; pageOriginalP.resolve(); } } }, 1); } }, false); let qk = 0; let ck = 0; const process = async () => { let qt = ++qk; await pageOriginalP.then(); if (qt !== qk) return; let ct = ++ck; await getRafPromise().then(); if (ct !== ck) return; for (const s of document.querySelectorAll(`a[href^="${pageInfo.originalRepoUrl}"]`)) { const h = s.getAttribute('href'); let m = matcher(h); if (m) { s.setAttribute('href', h.replace(`${pageInfo.originalRepoUrl}`, `${pageInfo.repoUrl}`)) } } } const mo = new MutationObserver((entries) => { if (!pageInfo.ready) { pageInfo.ready = true; let pageUrl = `${location.origin}${location.pathname}`; pageInfo.url = pageUrl; let m = matcher(pageUrl); if (m) { pageInfo.matched = true; pageInfo.owner = m[1]; pageInfo.repo = m[2]; pageInfo.repoUrl = `https://github.com/${pageInfo.owner}/${pageInfo.repo}/`; } } if (pageInfo.matched) { process(); } }); mo.observe(document, { subtree: true, childList: true }); })();