您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Replace old Imgur .webp links with clickable zoomable images, fallback & conversion, full-size zoom
// ==UserScript== // @name Imgur WebP Link Fix with Full-Size Zoom // @namespace Violentmonkey Scripts // @version 17.0 // @description Replace old Imgur .webp links with clickable zoomable images, fallback & conversion, full-size zoom // @match *://*.imgur.com/* // @grant none // ==/UserScript== (function() { 'use strict'; const fallbacks = [".jpg", ".png", ".gif"]; const cache = new Map(); const maxConcurrent = 4; let queue = []; let running = 0; function stripQuery(url) { return url.split("?")[0]; } function getFileId(url) { const match = url.match(/\/([a-zA-Z0-9]+)\.webp$/); return match ? match[1] : "imgur-fix"; } async function convertWebPtoPNG(url) { url = stripQuery(url); if (cache.has(url)) return cache.get(url); try { const response = await fetch(url); const blob = await response.blob(); const bitmap = await createImageBitmap(blob); const canvas = document.createElement("canvas"); canvas.width = bitmap.width; canvas.height = bitmap.height; const ctx = canvas.getContext("2d"); ctx.drawImage(bitmap, 0, 0); return new Promise(resolve => { canvas.toBlob(pngBlob => { const blobUrl = URL.createObjectURL(pngBlob); const fileId = getFileId(url); const result = { url: blobUrl, filename: fileId + ".png" }; cache.set(url, result); resolve(result); }, "image/png"); }); } catch (e) { console.error("WebP conversion failed:", e); return null; } } function enableZoom(img, originalUrl) { img.style.cursor = "zoom-in"; img.addEventListener("click", () => { const overlay = document.createElement("div"); overlay.style.position = "fixed"; overlay.style.top = "0"; overlay.style.left = "0"; overlay.style.width = "100%"; overlay.style.height = "100%"; overlay.style.background = "rgba(0,0,0,0.9)"; overlay.style.display = "flex"; overlay.style.justifyContent = "center"; overlay.style.alignItems = "center"; overlay.style.zIndex = "10000"; overlay.style.cursor = "zoom-out"; const zoomImg = document.createElement("img"); // Use the largest possible resolution by removing query strings or resizing zoomImg.src = originalUrl; zoomImg.style.maxWidth = "95%"; zoomImg.style.maxHeight = "95%"; zoomImg.style.boxShadow = "0 0 20px black"; overlay.appendChild(zoomImg); overlay.addEventListener("click", () => document.body.removeChild(overlay)); document.body.appendChild(overlay); }); } async function processLink(link) { if (link.dataset.webpProcessed) return; link.dataset.webpProcessed = "true"; let url = link.href; if (!url.endsWith(".webp")) return; url = stripQuery(url); const base = url.replace(/\.webp$/, ""); let finalUrl = null; for (const ext of fallbacks) { try { finalUrl = await new Promise(resolve => { const img = new Image(); const timer = setTimeout(() => resolve(null), 3000); img.onload = () => { clearTimeout(timer); resolve(base + ext); }; img.onerror = () => { clearTimeout(timer); resolve(null); }; img.src = base + ext; }); if (finalUrl) break; } catch {} } if (!finalUrl) { const result = await convertWebPtoPNG(url); if (result) finalUrl = result.url; } if (!finalUrl) return; // Replace link with img const img = document.createElement("img"); img.src = finalUrl; img.style.maxWidth = "100%"; img.style.marginTop = "4px"; link.parentNode.replaceChild(img, link); enableZoom(img, url); } function queueLink(link) { queue.push(link); processQueue(); } function processQueue() { if (running >= maxConcurrent || queue.length === 0) return; running++; const link = queue.shift(); processLink(link).finally(() => { running--; processQueue(); }); } function fixLinks() { document.querySelectorAll('a').forEach(link => { if (link.href && link.href.endsWith(".webp") && !link.dataset.webpProcessed) { queueLink(link); } }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", fixLinks); } else { fixLinks(); } new MutationObserver(fixLinks).observe(document.body, { childList: true, subtree: true }); })();