Skip to content

Instantly share code, notes, and snippets.

@Mariven
Created December 23, 2024 05:30
Show Gist options
  • Save Mariven/e76b52f8614a13ef6a941da9b29d147a to your computer and use it in GitHub Desktop.
Save Mariven/e76b52f8614a13ef6a941da9b29d147a to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Github Boilerplate File Shrinker
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author Mariven
// @match https://github.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=github.com
// @grant none
// ==/UserScript==
( function() { 'use strict';
let paths = {};
const // configurables
blacklist = [
// forbidden js files
/\.(conf|config)\.js$/i,
// forbidden filename prefixes
/^(tsconfig|gradle|build|mypy|pyright|pytest|jenkinsfile|gradlew?).*?\./i,
// forbidden dot prefixes
/^\.(vscode|aws|DS_Store|env|circleci|mailmap|cloudflare|nix|zed|cursor|.*?\.json)/i,
// forbidden folders
/^(target|build|dist|deploy|enterprise|node[-_]modules|tests|legal|nix|test|crates|tooling|jenkinsfile|gradlew|CVS|ci[-_]cd|db[-_]scripts|enterprise)(\/|$)/i,
// forbidden extensions
/\.(lock|toml|properties|example|plist|nix|yml|yaml|prisma|.*?lint)$/i,
// forbidden dot infixes
/^\..*?(ignore|rc|[-_](version|ci|cd)|config|git|flake|yarn|container|cargo|compose|workflow|pipeline|package|gradle|husky|mvn|svn|idea)/i,
// forbidden config files
/^(yarn|composer|tsconfig|livekit|renovate|azure-pipelines|github-workflows|docker-compose|appveyor|vercel|pom|mvn|settings|coverage|tox|Desktop|package(-lock)?)\.(lock|json|yaml|yml|xml|ini)$/i,
// forbidden config dotfiles
/^\.(travis|bitrise)\.(lock|json|yaml|yml)$/i,
// other
/^(?:CODE.?OF.?CONDUCT|LICENSE(.?MODEL)?|SECURITY|CONTRIBUTING|COPYING|MANIFEST|NOTICE|Makefile)(?:(\.|-)[a-zA-Z]+)?(?:(\.|-)[a-zA-Z]+)?$/i,
/^(docker|p(ip|roc)|gem)-?(file-?)?/i,
/^(thumbs|requirements)\.(db|txt)$/i,
].map(rx => new RegExp(rx)),
selectors = {
row: "tr[id^='folder-row'], table[aria-labelledby='folders-and-files']>tbody>tr",
title: ".react-directory-filename-cell",
icons: ".react-directory-filename-column svg",
blocks: ".react-directory-filename-column",
contents: ".react-directory-filename-column cell",
},
config = {
styles: {
row: {height: "20px", opacity: "0.5", fontSize: "0.7em"},
blocks: {height: "20px"},
icons: {scale: "0.8", height: "20px"},
title: {fontSize: "0.8em"}
},
hideCompletely: false,
};
const // utilities
get = (sel, el = document) => el.querySelector(sel),
getAll = (sel, el = document) => Array.from(el.querySelectorAll(sel)),
text = (sel, el = document) => el.querySelector(sel)?.innerText,
hyphenize = (str) => str.replaceAll(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
setStyleAttr = (el, key, val, important = false) => {
el.style.setProperty(hyphenize(key), val, important ? "important" : null);
el.style.cssText += `${hyphenize(key)}:${val}${important ? '!important' : ''};`;
},
forceStyle = (el, styleParams) => Object.entries(styleParams).forEach(([k, v]) => setStyleAttr(el, k, v, true)),
forceStyleSystem = (baseEl, styleTree) => {
styleTree.forEach(item => {
let els = item.selector
? (item.all ? getAll : (s,e)=>[get(s,e)])(item.selector, baseEl)
: [baseEl];
els.forEach(el => forceStyle(el, item.style));
});
},
isIgnorable = row => blacklist.some(rx => text(selectors.title, row)?.match(rx)),
processRow = row => forceStyleSystem(row, [
{selector: null , all: false, style: config.styles.row },
{selector: selectors.blocks, all: true , style: config.styles.blocks },
{selector: selectors.icons , all: true , style: config.styles.icons },
{selector: selectors.title , all: true , style: config.styles.title },
]);
function addStyles() {
// do the thing
getAll(selectors.row).filter(isIgnorable).forEach(processRow);
paths[window.location.pathname] = true;
}
function waitForContent(retries=10) {
// try { if (paths[window.location.pathname]) return; } catch{}
if (document.querySelector(selectors.row)) {
addStyles();
} else {
setTimeout(()=>waitForContent(retries-1), 250);
}
};
// set up observer
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
setTimeout(()=>waitForContent(10), 250);
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
waitForContent();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment