您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
修正 Imgur 在 PTT 上的問題
当前为
// ==UserScript== // @name PTT Imgur Fix // @description 修正 Imgur 在 PTT 上的問題 // @namespace eight04.blogspot.com // @include https://www.ptt.cc/bbs/*.html // @include https://www.ptt.cc/man/*.html // @version 0.5.1 // @author eight // @homepage https://github.com/eight04/ptt-imgur-fix // @supportURL https://github.com/eight04/ptt-imgur-fix/issues // @license MIT // @compatible firefox // @compatible chrome // @run-at document-start // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @require https://greasyfork.org/scripts/7212-gm-config-eight-s-version/code/GM_config%20(eight's%20version).js?version=156587 // @connect imgur.com // ==/UserScript== /* global GM_config */ var config; GM_config.setup({ embedYoutube: { label: "Embed youtube video", type: "checkbox", default: true }, youtubeParameters: { label: "Youtube player parameters (e.g. rel=0&loop=1)", type: "text", default: "" }, embedImage: { label: "Embed image", type: "checkbox", default: true }, embedAlbum: { label: "Embed imgur album. The script would request imgur.com for album info", type: "checkbox", default: false }, albumMaxSize: { label: "Maximum number of images to load for an album", type: "number", default: 5 }, lazyLoad: { label: "Don't load images until scrolled into view", type: "checkbox", default: true } }, () => config = GM_config.get()); document.addEventListener("beforescriptexecute", e => { var url = new URL(e.target.src, location.href); if (url.hostname.endsWith("imgur.com")) { e.preventDefault(); } }); document.addEventListener("DOMContentLoaded", embedLinks); function embedLinks() { // remove old .richcontent var rich = document.querySelectorAll("#main-content .richcontent"); for (var node of rich) { node.parentNode.removeChild(node); } // embed links var links = document.querySelectorAll("#main-content a"), processed = new Set; for (var link of links) { if (processed.has(link) || !getLinkInfo(link).embedable) { continue; } var [links_, lineEnd] = findLinksInSameLine(link); links_.forEach(l => processed.add(l)); createRichContent(links_, lineEnd); } } function findLinksInSameLine(node) { var links = []; while (node) { if (node.nodeName == "A") { links.push(node); node = node.nextSibling || node.parentNode.nextSibling; continue; } if (node.nodeType == Node.TEXT_NODE && node.nodeValue.includes("\n")) { return [links, findLineEnd(node)]; } if (node.childNodes.length) { node = node.childNodes[0]; continue; } if (node.nextSibling) { node = node.nextSibling; continue; } if (node.parentNode.id != "main-content") { node = node.parentNode.nextSibling; continue; } throw new Error("Invalid article, missing new line?"); } } function findLineEnd(text) { var index = text.nodeValue.indexOf("\n"); if (index == text.nodeValue.length - 1) { while (text.parentNode.id != "main-content") { text = text.parentNode; } return text; } var pre = document.createTextNode(""); pre.nodeValue = text.nodeValue.slice(0, index + 1); text.nodeValue = text.nodeValue.slice(index + 1); text.parentNode.insertBefore(pre, text); return pre; } // insert richcontent brefore ref.nextSibling function createRichContent(links, ref) { // create our rich content for (var link of links) { var linkInfo = getLinkInfo(link); if (!linkInfo.embedable) { continue; } var richContent = document.createElement("div"); richContent.className = "richcontent ptt-imgur-fix"; const embed = createEmbed(linkInfo, richContent); if (typeof embed === "string") { richContent.innerHTML = embed; } else if (embed) { richContent.appendChild(embed); } const lazyTarget = richContent.querySelector("[data-src]"); if (lazyTarget) { if (config.lazyLoad) { setupLazyLoad(lazyTarget); } else { lazyTarget.src = lazyTarget.dataset.src; } } ref.parentNode.insertBefore(richContent, ref.nextSibling); ref = richContent; } } function setupLazyLoad(target) { const observer = new IntersectionObserver(entries => { for (const entry of entries) { if (entry.isIntersecting) { target.src = target.dataset.src; } else { const {offsetWidth, offsetHeight} = target; if (offsetWidth) { target.style.width = offsetWidth + "px"; target.style.height = offsetHeight + "px"; } target.src = ""; } } }); observer.observe(target); } function getLinkInfo(link) { return getUrlInfo(link.href); } function getUrlInfo(url) { var match; if ((match = url.match(/\/\/(?:[im]\.)?imgur\.com\/([a-z0-9]{2,})/i)) && match[1] != "gallery") { return { type: "imgur", id: match[1], url: url, embedable: config.embedImage }; } if ((match = url.match(/\/\/(?:[im]\.)?imgur\.com\/(?:a|gallery)\/([a-z0-9]{2,})/i))) { return { type: "imgur-album", id: match[1], url: url, embedable: config.embedAlbum }; } if ((match = url.match(/\/\/www\.youtube\.com\/watch?.*?v=([a-z0-9_-]{9,12})/i)) || (match = url.match(/\/\/(?:youtu\.be|www\.youtube\.com\/embed)\/([a-z0-9_-]{9,12})/i))) { return { type: "youtube", id: match[1], url: url, embedable: config.embedYoutube }; } if ((match = url.match(/\/\/pbs\.twimg\.com\/media\/([a-z0-9_-]+\.(?:jpg|png))/i))) { return { type: "twitter", id: match[1], url: url, embedable: config.embedImage }; } if ((match = url.match(/\/\/pbs\.twimg\.com\/media\/([a-z0-9_-]+)\?.*format=([\w]+)/i))) { return { type: "twitter", id: `${match[1]}.${match[2]}`, url: url, embedable: config.embedImage }; } if (/^[^?#]+\.(?:jpg|png|gif|jpeg)(?:$|[?#])/i.test(url)) { return { type: "image", id: null, url: url, embedable: config.embedImage }; } return { type: "url", id: null, url: url, embedable: false }; } function createEmbed(info, container) { if (info.type == "imgur") { return `<img referrerpolicy="no-referrer" data-src="//i.imgur.com/${info.id}.jpg">`; } if (info.type == "youtube") { return `<div class="resize-container"><div class="resize-content"><iframe class="youtube-player" type="text/html" data-src="//www.youtube.com/embed/${info.id}${config.youtubeParameters?`?${config.youtubeParameters}`:''}" frameborder="0" allowfullscreen></iframe></div></div>`; } if (info.type == "image") { return `<img referrerpolicy="no-referrer" data-src="${info.url}">`; } if (info.type == "twitter") { return `<img data-src="//pbs.twimg.com/media/${info.id}:orig">`; } if (info.type == "imgur-album") { container.textContent = "Loading album..."; GM_xmlhttpRequest({ method: "GET", url: info.url.replace("://m.", "://"), onload(response) { if (response.status < 200 || response.status >= 300) { container.textContent = `${response.status} ${response.statusText}`; return; } container.textContent = ""; const text = response.responseText; let match; let hashes; if ((match = text.match(/album_images":\{.+?(\[.+?\])/))) { hashes = JSON.parse(match[1]).map(i => i.hash); } else if ((match = text.match(/\bimage\s*:.+?hash":"([^"]+)/))) { hashes = [match[1]]; } if (!hashes) { throw new Error(`Can't find images for ${info.url} (${response.finalUrl})`); } let i = 0; const loadImages = (count = Infinity) => { let html = ""; for (; i < hashes.length && count--; i++) { html += `<div class="richcontent"><img referrerpolicy="no-referrer" src="//i.imgur.com/${hashes[i]}.jpg"></div>`; } container.insertAdjacentHTML("beforeend", html); }; loadImages(config.albumMaxSize); if (i < hashes.length) { const button = document.createElement("button"); button.textContent = `Load all images (${hashes.length - i} more)`; button.addEventListener('click', () => { button.remove(); loadImages(); }); container.appendChild(button); } } }); return; } throw new Error(`Invalid type: ${info.type}`); }