Greasy Fork is available in English.
Adds thumbnails to the script list on Greasy Fork.
// ==UserScript==
// @name Greasy Fork Thumbnail Adder
// @name:ja Greasy Fork Thumbnail Adder
// @namespace http://tampermonkey.net/
// @version 0.6
// @description Adds thumbnails to the script list on Greasy Fork.
// @description:ja Greasy Forkのスクリプト一覧に、詳細ページから抽出したサムネイルを追加表示します。
// @author Gemini
// @match https://greasyfork.org/*scripts*
// @license MIT
// @grant GM_xmlhttpRequest
// @connect greasyfork.org
// @connect *
// ==/UserScript==
(function() {
'use strict';
const scriptList = document.querySelectorAll('ol#browse-script-list > li');
scriptList.forEach(li => {
const article = li.querySelector('article');
if (!article) return;
const link = article.querySelector('h2 > a');
if (!link) return;
article.style.position = 'relative';
article.style.paddingRight = '210px';
article.style.minHeight = '150px';
const scriptUrl = link.href;
GM_xmlhttpRequest({
method: "GET",
url: scriptUrl,
onload: function(response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, "text/html");
// ページ内のすべての画像を取得して、条件に合うものを探すにゃ
const allImgs = doc.querySelectorAll('#script-screenshots img, .step-content img, #additional-info img, article img');
let validImgSrc = "";
for (let img of allImgs) {
const isIcon = img.src.includes('avatar') || img.src.includes('logo') || img.src.includes('badge');
// 簡易的なサイズ判定
const isSmall = (img.width > 0 && img.width < 100) || (img.height > 0 && img.height < 100);
if (!isIcon && !isSmall) {
validImgSrc = img.src;
break;
}
}
// 個別ページに画像がない場合、OGPを最終手段にするにゃ
if (!validImgSrc) {
const ogImg = doc.querySelector('meta[property="og:image"]');
if (ogImg && !ogImg.content.includes('black-logo')) {
validImgSrc = ogImg.content;
}
}
if (validImgSrc) {
const thumbContainer = document.createElement('div');
thumbContainer.style.cssText = `
position: absolute;
top: 15px;
right: 15px;
width: 180px;
height: 135px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: #fff;
border: 1px solid #eee;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0,0,0,0.1); /* 影を小さく調整したにゃ */
z-index: 10;
`;
const img = document.createElement('img');
img.src = validImgSrc;
img.style.cssText = `
width: 100%;
height: 100%;
object-fit: contain;
background: #fafafa;
`;
thumbContainer.appendChild(img);
article.appendChild(thumbContainer);
}
}
});
});
})();