// ==UserScript== // @name huggingface与hf-mirror相互跳转 // @namespace http://tampermonkey.net/ // @version 1.9 // @description 在 Hugging Face 和 hf-mirror.com 的 blob 和 tree 页面添加相互跳转链接,并优化下载,包括 tree 页面文件行镜像下载按钮 // @author flyway // @match https://huggingface.co/*/blob/* // @match https://hf-mirror.com/*/blob/* // @match https://huggingface.co/* // @match https://hf-mirror.com/* // @grant none // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/530508/huggingface%E4%B8%8Ehf-mirror%E7%9B%B8%E4%BA%92%E8%B7%B3%E8%BD%AC.user.js // @updateURL https://update.greasyfork.icu/scripts/530508/huggingface%E4%B8%8Ehf-mirror%E7%9B%B8%E4%BA%92%E8%B7%B3%E8%BD%AC.meta.js // ==/UserScript== (function() { 'use strict'; var currentUrl = window.location.href; var isMirrorPage = currentUrl.includes('hf-mirror.com'); var isBlobPage = currentUrl.includes('/blob/'); var isTreePage = currentUrl.includes('/tree/main'); // 为 blob 页面添加下载链接(仅 Hugging Face 添加,镜像站无内容) function addBlobLinks() { var messageDiv = document.querySelector('div.p-4.py-8.text-center'); if (messageDiv && !messageDiv.querySelector('.custom-links')) { var newP = document.createElement('p'); newP.className = 'custom-links'; newP.style.marginTop = '20px'; if (isMirrorPage) { // 镜像站的 blob 页面不添加任何内容 return; } else { var downloadLink = document.querySelector('a[href*="/resolve/"]'); if (downloadLink) { var originalDownloadUrl = downloadLink.href; var urlObj = new URL(originalDownloadUrl); var mirrorDownloadUrl = urlObj.origin.replace('huggingface.co', 'hf-mirror.com') + urlObj.pathname; var downloadLinkMirror = document.createElement('a'); downloadLinkMirror.href = mirrorDownloadUrl; downloadLinkMirror.textContent = '使用 hf-mirror 下载'; downloadLinkMirror.style.color = 'green'; downloadLinkMirror.style.textDecoration = 'underline'; // 添加下划线 downloadLinkMirror.style.marginRight = '10px'; downloadLinkMirror.target = '_blank'; downloadLinkMirror.rel = 'noopener noreferrer'; newP.appendChild(downloadLinkMirror); } } messageDiv.appendChild(newP); } } // 为 tree 和 blob 页面添加 tab-alternate 样式的跳转链接 function addTabLink() { var tabContainer = document.querySelector('div.-mb-px.flex.h-12.items-center.overflow-x-auto.overflow-y-hidden'); if (tabContainer && !tabContainer.querySelector('.custom-tab')) { var jumpLink = document.createElement('a'); jumpLink.className = 'tab-alternate custom-tab'; if (isMirrorPage) { jumpLink.href = currentUrl.replace('hf-mirror.com', 'huggingface.co'); jumpLink.textContent = '切换到 huggingface 页面'; jumpLink.style.color = 'orange'; } else { jumpLink.href = currentUrl.replace('huggingface.co', 'hf-mirror.com'); jumpLink.textContent = '切换到 hf-mirror 页面'; jumpLink.style.color = 'green'; } jumpLink.style.marginLeft = '10px'; tabContainer.appendChild(jumpLink); } } // 为 tree 页面文件行添加绿色 hf-mirror 下载按钮 function addTreeDownloadButtons() { if (!isTreePage || isMirrorPage) return; // 仅在 Hugging Face 的 tree 页面执行 var fileLinks = document.querySelectorAll('a.group.col-span-4.flex.items-center.justify-self-end.truncate.text-right.font-mono.text-\\[0\\.8rem\\].leading-6.text-gray-400.md\\:col-span-3.lg\\:col-span-2.xl\\:pr-10[href*="/resolve/"]'); fileLinks.forEach(function(link) { if (!link.querySelector('.custom-mirror-download')) { console.log('Found file link:', link.href); var originalHref = link.href; var mirrorHref = originalHref.replace('huggingface.co', 'hf-mirror.com').split('?')[0]; // 为原始下载按钮添加独立 hover 样式 var originalDownloadBtn = link.querySelector('div.group-hover\\:shadow-xs.ml-2.flex.h-5.w-5'); if (originalDownloadBtn) { originalDownloadBtn.className = 'ml-2 flex h-5 w-5 items-center justify-center rounded-sm border text-gray-500 hover:bg-gray-50 hover:text-gray-800 dark:border-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-300 xl:ml-4'; } // 添加绿色 hf-mirror 下载按钮 var mirrorDownloadBtn = document.createElement('div'); mirrorDownloadBtn.className = 'ml-2 flex h-5 w-5 items-center justify-center rounded-sm border text-green-500 hover:bg-gray-50 hover:text-green-800 dark:border-gray-800 dark:hover:bg-gray-800 dark:hover:text-green-300 xl:ml-4 custom-mirror-download'; mirrorDownloadBtn.innerHTML = ''; link.appendChild(mirrorDownloadBtn); console.log('Added mirror download button to:', link.href); } }); } // 初始执行 if (isBlobPage) addBlobLinks(); addTabLink(); addTreeDownloadButtons(); // 使用 MutationObserver 监听 DOM 变化 var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (isBlobPage) addBlobLinks(); addTabLink(); addTreeDownloadButtons(); }); }); observer.observe(document.body, { childList: true, subtree: true }); window.addEventListener('load', function() { if (isBlobPage) addBlobLinks(); addTabLink(); addTreeDownloadButtons(); }); })();