您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays the number of downloads for each asset on all GitHub release pages.
// ==UserScript== // @name GitHub Release Download Count // @namespace http://tampermonkey.net/ // @version 1.0 // @description Displays the number of downloads for each asset on all GitHub release pages. // @author OpenAI // @match https://github.com/* // @grant GM_xmlhttpRequest // @connect api.github.com // @license MIT // ==/UserScript== (function () { 'use strict'; // Retrieves the name of the repo const repoMatch = window.location.pathname.match(/^\/([^\/]+)\/([^\/]+)/); if (!repoMatch) return; const owner = repoMatch[1]; const repo = repoMatch[2]; // API call: up to 100 releases const apiUrl = `https://api.github.com/repos/${owner}/${repo}/releases?per_page=100`; // Main function function fetchReleasesAndInject() { GM_xmlhttpRequest({ method: 'GET', url: apiUrl, headers: { 'Accept': 'application/vnd.github+json', }, onload: function (response) { if (response.status !== 200) { console.warn('GitHub API error:', response.statusText); return; } try { const releases = JSON.parse(response.responseText); const counts = {}; releases.forEach(release => { release.assets.forEach(asset => { counts[asset.browser_download_url] = asset.download_count; }); }); insertCounts(counts); } catch (e) { console.error('Erreur parsing JSON:', e); } } }); } // Inject the counter function insertCounts(counts) { const links = document.querySelectorAll('a[href*="/download/"]'); links.forEach(link => { const url = link.href; const count = counts[url]; // Do not re-inject if already present if (count !== undefined && !link.parentElement.querySelector('.download-count')) { const countSpan = document.createElement('span'); countSpan.className = 'download-count'; countSpan.style.marginLeft = '10px'; countSpan.style.fontSize = 'smaller'; countSpan.style.color = '#6a737d'; countSpan.textContent = `(${count.toLocaleString()} downloads)`; link.parentElement.appendChild(countSpan); } }); } // Wait for the DOM to stabilize, also observe the “Show more” function waitAndObserve() { const observer = new MutationObserver((mutations) => { const hasNewDownloadLinks = [...mutations].some(m => [...m.addedNodes].some(node => node.nodeType === 1 && node.querySelector?.('a[href*="/download/"]') ) ); if (hasNewDownloadLinks) { fetchReleasesAndInject(); } }); observer.observe(document.body, { childList: true, subtree: true }); // Launch once after initial delay setTimeout(fetchReleasesAndInject, 1000); } waitAndObserve(); })();