您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
GitHub UI enhancer w/ drag menu, fast downloads, dark mode override, and more. Author: Eliminater74 | MIT License
// ==UserScript== // @name GitHub Enhancer (Ultra Edition) // @namespace https://github.com/TamperMonkeyDevelopment/TamperMonkeyScripts // @version 3.0 // @description GitHub UI enhancer w/ drag menu, fast downloads, dark mode override, and more. Author: Eliminater74 | MIT License // @author Eliminater74 // @license MIT // @match https://github.com/* // @icon https://github.githubassets.com/favicons/favicon.svg // @homepage https://github.com/TamperMonkeyDevelopment/TamperMonkeyScripts // @supportURL https://github.com/TamperMonkeyDevelopment/TamperMonkeyScripts/issues // @grant none // ==/UserScript== (function () { 'use strict'; const defaultSettings = { highlightStalePRs: true, autoExpandDiffs: true, addFileSizeLabels: true, autoFocusSearch: true, showFastDownload: true, showFloatingMenu: true, themeMode: 'auto', pinnedRepos: [] }; const settingsKey = 'githubEnhancerSettings'; const settings = JSON.parse(localStorage.getItem(settingsKey)) || defaultSettings; const saveSettings = () => localStorage.setItem(settingsKey, JSON.stringify(settings)); const getCurrentRepo = () => location.pathname.split('/').slice(1, 3).join('/'); const debounce = (fn, delay = 300) => { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => fn.apply(this, args), delay); }; }; const highlightStalePRs = () => { document.querySelectorAll('relative-time').forEach(el => { const daysOld = (Date.now() - new Date(el.dateTime)) / (1000 * 60 * 60 * 24); if (daysOld > 7) { el.style.color = 'red'; el.style.fontWeight = 'bold'; } }); }; const expandDiffs = () => { document.querySelectorAll('button').forEach(btn => { const txt = btn.innerText.toLowerCase(); if (txt.includes('load diff') || txt.includes('show')) btn.click(); }); }; const collapseDiffs = () => { document.querySelectorAll('button[aria-label="Collapse file"]').forEach(btn => btn.click()); }; const showFileSizes = () => { document.querySelectorAll('a.js-navigation-open').forEach(el => { const row = el.closest('tr'); const sizeEl = row?.querySelector('td:last-child'); if (sizeEl && sizeEl.innerText.match(/[0-9.]+ (KB|MB)/) && !el.querySelector('.gh-size')) { const tag = document.createElement('span'); tag.className = 'gh-size'; tag.style.marginLeft = '6px'; tag.style.fontSize = 'smaller'; tag.style.color = '#888'; tag.textContent = `(${sizeEl.innerText.trim()})`; el.appendChild(tag); } }); }; const autoFocusSearch = () => { const input = document.querySelector('input.header-search-input'); if (input) input.focus(); }; const addFastDownloadButtons = () => { document.querySelectorAll('a.js-navigation-open').forEach(el => { const href = el.getAttribute('href'); if (href?.includes('/blob/') && !el.parentNode.querySelector('.gh-download-link')) { const rawURL = 'https://raw.githubusercontent.com' + href.replace('/blob', ''); const dl = document.createElement('a'); dl.href = rawURL; dl.textContent = ' ⬇'; dl.download = ''; dl.className = 'gh-download-link'; dl.style.marginLeft = '5px'; el.parentNode.appendChild(dl); } }); }; const applyDarkMode = () => { const theme = settings.themeMode; if (theme === 'auto') return; document.documentElement.setAttribute('data-color-mode', theme); document.documentElement.setAttribute('data-dark-theme', 'dark'); document.documentElement.setAttribute('data-light-theme', 'light'); }; const pinCurrentRepo = () => { const repo = getCurrentRepo(); if (repo && !settings.pinnedRepos.includes(repo)) { settings.pinnedRepos.push(repo); saveSettings(); updatePinnedList(); } }; const updatePinnedList = () => { const list = document.getElementById('gh-pinned-list'); if (!list) return; list.innerHTML = ''; settings.pinnedRepos.forEach(repo => { const li = document.createElement('li'); const a = document.createElement('a'); a.href = `https://github.com/${repo}`; a.textContent = repo; a.target = '_blank'; const del = document.createElement('button'); del.textContent = '❌'; del.style.marginLeft = '6px'; del.onclick = () => { settings.pinnedRepos = settings.pinnedRepos.filter(r => r !== repo); saveSettings(); updatePinnedList(); }; li.appendChild(a); li.appendChild(del); list.appendChild(li); }); }; const createFloatingMenu = () => { const gear = document.createElement('div'); gear.innerHTML = '⚙️'; Object.assign(gear.style, { position: 'fixed', bottom: '20px', right: '20px', fontSize: '22px', zIndex: '9999', cursor: 'pointer', userSelect: 'none' }); const panel = document.createElement('div'); panel.id = 'gh-enhancer-panel'; panel.style.cssText = ` position: fixed; bottom: 60px; right: 20px; z-index: 9999; background: #222; color: #fff; padding: 12px; border-radius: 10px; font-size: 14px; display: none; box-shadow: 0 0 12px rgba(0,0,0,0.6); transition: all 0.3s ease; `; const checkbox = (label, key) => { const row = document.createElement('div'); row.innerHTML = `<label><input type="checkbox" ${settings[key] ? 'checked' : ''}/> ${label}</label>`; row.querySelector('input').addEventListener('change', e => { settings[key] = e.target.checked; saveSettings(); }); return row; }; panel.appendChild(checkbox('Highlight stale PRs', 'highlightStalePRs')); panel.appendChild(checkbox('Auto-expand diffs', 'autoExpandDiffs')); panel.appendChild(checkbox('Show file sizes', 'addFileSizeLabels')); panel.appendChild(checkbox('Auto-focus search', 'autoFocusSearch')); panel.appendChild(checkbox('Fast downloads', 'showFastDownload')); const themeSelect = document.createElement('select'); ['auto', 'dark', 'light'].forEach(t => { const opt = document.createElement('option'); opt.value = t; opt.textContent = t.charAt(0).toUpperCase() + t.slice(1); themeSelect.appendChild(opt); }); themeSelect.value = settings.themeMode; themeSelect.onchange = () => { settings.themeMode = themeSelect.value; saveSettings(); applyDarkMode(); }; panel.appendChild(document.createElement('hr')); panel.appendChild(document.createTextNode('Theme:')); panel.appendChild(themeSelect); panel.appendChild(document.createElement('hr')); const pinBtn = document.createElement('button'); pinBtn.textContent = '📌 Pin This Repo'; pinBtn.onclick = pinCurrentRepo; panel.appendChild(pinBtn); const pinnedList = document.createElement('ul'); pinnedList.id = 'gh-pinned-list'; panel.appendChild(pinnedList); document.body.appendChild(gear); document.body.appendChild(panel); gear.onclick = () => panel.style.display = (panel.style.display === 'none') ? 'block' : 'none'; updatePinnedList(); }; const runEnhancements = () => { applyDarkMode(); if (settings.highlightStalePRs) highlightStalePRs(); if (settings.autoExpandDiffs) expandDiffs(); if (settings.addFileSizeLabels) showFileSizes(); if (settings.autoFocusSearch) autoFocusSearch(); if (settings.showFastDownload) addFastDownloadButtons(); }; const observer = new MutationObserver(debounce(runEnhancements)); observer.observe(document.body, { childList: true, subtree: true }); runEnhancements(); if (settings.showFloatingMenu) createFloatingMenu(); document.addEventListener('keydown', e => { if (e.altKey && e.key === 'g') document.getElementById('gh-enhancer-panel')?.click(); if (e.altKey && e.key === 'e') expandDiffs(); if (e.altKey && e.key === 'c') collapseDiffs(); }); })();