// ==UserScript== // @name GitHub Image Preview // @version 1.1.17 // @description A userscript that adds clickable image thumbnails // @license MIT // @author Rob Garrison // @namespace https://github.com/Mottie // @include https://github.com/* // @run-at document-idle // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @connect github.com // @connect githubusercontent.com // @require https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=597950 // @icon https://assets-cdn.github.com/pinned-octocat.svg // @downloadURL none // ==/UserScript== (() => { "use strict"; GM_addStyle(` table.files tr.ghip-image-previews, table.files.ghip-show-previews tbody tr.js-navigation-item { display:none; } table.files.ghip-show-previews tr.ghip-image-previews { display:table-row; } table.files.ghip-show-previews .ghip-non-image { height:80px; margin-top:15px; opacity:.2; } table.files.ghip-show-previews .image { position:relative; overflow:hidden; text-align:center; } .ghip-image-previews .image { padding:10px; } table.files.ghip-tiled .image { width:22.5%; height:180px; margin:12px !important; /* GitHub uses !important flags now :( */ } table.files.ghip-tiled .image .border-wrap img, .ghip-image-previews .border-wrap svg { max-height:130px; } table.files.ghip-fullw .image { width:97%; height:auto; } /* zoom doesn't work in Firefox, but "-moz-transform:scale(3);" doesn't limit the size of the image, so it overflows */ table.files.ghip-tiled .image:hover img:not(.ghip-non-image) { zoom:3; } .ghip-image-previews .border-wrap img, .ghip-image-previews .border-wrap svg { max-width:95%; } .ghip-image-previews .border-wrap h4 { white-space:nowrap; text-overflow:ellipsis; margin-bottom:5px; } .ghip-image-previews .border-wrap h4.ghip-file-name { overflow:hidden; } .btn.ghip-tiled > *, .btn.ghip-fullw > *, .ghip-image-previews iframe { pointer-events:none; vertical-align:baseline; } .image .ghip-file-type { font-size:30px; top:-1.8em; position:relative; z-index:2; } .ghip-content span.exploregrid-item .ghip-file-name { cursor:default; } /* override GitHub-Dark styles */ table.files img[src*='octocat-spinner'], img[src='/images/spinner.gif'] { width:auto !important; height:auto !important; } table.files td .simplified-path { color:#888 !important; } `); // supported img types const imgExt = /(png|jpg|jpeg|gif|tif|tiff|bmp|webp)$/i, svgExt = /svg$/i, folderIconClasses = ` .octicon-file-directory, .octicon-file-symlink-directory, .octicon-file-submodule`, tiled = ` `, fullWidth = ` `, imgTemplate = [ // not using backticks here "", "${image}", "" ].join(""), spanTemplate = [ "", "${image}", "" ].join(""); function addToggles() { if ($(".gh-img-preview")) { return; } const div = document.createElement("div"), btn = `btn btn-sm BtnGroup-item tooltipped tooltipped-n" aria-label="Show`; div.className = "BtnGroup float-right gh-img-preview"; div.innerHTML = ` `; $(".file-navigation").appendChild(div); $(".ghip-tiled", div).addEventListener("click", event => { openView("tiled", event); }); $(".ghip-fullw", div).addEventListener("click", event => { openView("fullw", event); }); } function setInitState() { const state = GM_getValue("gh-image-preview"); if (state) { openView(state); } } function openView(name, event) { const el = $(".ghip-" + name); if (el) { if (event) { el.classList.toggle("selected"); if (!el.classList.contains("selected")) { return showList(); } } showPreview(name); } } function showPreview(name) { buildPreviews(); const table = $("table.files"), selected = "ghip-" + name, notSelected = "ghip-" + (name === "fullw" ? "tiled" : "fullw"); table.classList.add("ghip-show-previews", selected); $(".btn." + selected).classList.add("selected"); table.classList.remove(notSelected); $(".btn." + notSelected).classList.remove("selected"); GM_setValue("gh-image-preview", name); } function showList() { $("table.files").classList.remove( "ghip-show-previews", "ghip-tiled", "ghip-fullw" ); $(".btn.ghip-tiled").classList.remove("selected"); $(".btn.ghip-fullw").classList.remove("selected"); GM_setValue("gh-image-preview", ""); } function buildPreviews() { let template, url, temp, noExt, fileName, imgs = "