Abstraction's End
home page
original site
twitter
thoughts
about
Linked TOC

Here are some scripts I've created to restyle, reformat, and add additional function to various websites. Code coloring via code-prettify. I still need to add a bunch of scripts to this page, and figure out how to make the lines break.

Tampermonkey

Scripts for use with Tampermonkey (website, Firefox addon), or similar monkeys.

Whenever you hover over a link to an Arxiv abstract, Wikipedia article, or LessWrong post in any page, this script creates a pop-up that allows you to preview the link. Arxiv previews give the paper's title, authors, and abstract, along with a link to the PDF; Wikipedia previews give the introductory section of the article; LessWrong previews just embed the whole entire articleLW articles don't come with summaries or abstracts, so I just used their API to get the whole article. One issue with this is that the browser wants to use the current page's CSS to style the HTML in the article (w/o which HTML you wouldn't have lists, blockquotes, math, and so on); I've only provided a moderate level of insulation from this, so previews may look slightly different from website to website, which is sometimes better (e.g. font consistency) and sometimes worse (e.g. spacing issues)..
Link to script
Note: because cross-site requests are generally a security risk, Tampermonkey intercepts calls and ask you to allow or deny them. Click 'Always Allow' the first time you hover over a link from each of these three domains, and it won't bother you again.
Test it here:

Twitter to Nitter Button

Twitter pages refresh themselves if you leave them inactive for some time and then go back; it's a very irritating 'feature' that causes me to lose my place, and the "reduce motion" fix doesn't work on desktop. This script adds a button to the top left of Twitter pages which opens the tweet currently being viewed on Nitter, a site with the same UI but no auto-refresh.

// ==UserScript==
// @name         Twitter to Nitter Button
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Adds a button to view Twitter links on Nitter
// @author       Mariven
// @match        https://twitter.com/*
// @grant        none
// ==/UserScript==

(function() {
	'use strict';

	// Create button element
	const button = document.createElement('button');
	button.innerHTML = "<img src='https://nitter.net/logo.png' style='height:20px;width:20px;'></img>";
	button.style.position = 'fixed';
	button.style.top = '10px';
	button.style.left = '10px';
	button.style.padding = '5px';
	button.style.display = 'flex';
	button.style.alignItems = 'center';
	button.style.zIndex = 9999; // To ensure the button appears on top of other elements
	button.style.background = 'transparent';
	button.style.color = '#4a4a4a';
	button.style.border = '1px solid #ff6c60';
	button.style.borderRadius = '12px';
	button.style.cursor = 'pointer';

	// Add event listener for click event
	button.addEventListener('click', function() {
		// Replace 'twitter.com' with 'nitter.net' in the current URL
		const newUrl = window.location.href.replace('twitter.com', 'nitter.net');
		window.location.href = newUrl;
	});

	// Add button to body
	document.body.appendChild(button);
})();

Glowfic Page Stitcher

Stitches pages on Glowfic and Project Lawful threads together, so it's not necessary to constantly click the next page, but appends page and post links to each post so it's still easy to link to them. Won't activate on the first page of a thread unless you add ?page=1 to the URL (example), but will activate on subsequent pages.

// ==UserScript==
// @name         Glowfic Page Stitcher
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Appends all subsequent pages of a glowfic thread to the displayed page
// @author       Mariven
// @match        https://www.projectlawful.com/posts/*?page=*
// @match        https://*glowfic.com/posts/*?page=*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=projectlawful.com
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // Replace this with the selector for your content section
    const contentSectionSelector = '#content';
    const postNumber = window.location.href.match(/[0-9]{2,9}/)[0];
    const startingPage = parseInt(window.location.href.match(/page=(\d+)/)[1]);
    // Function to fetch and append content from the next page
    function appendContentFromPage(pageNumber) {
        const baseUrl = window.location.href.replace(/\?page=\d+$/, '');
        const prev = `${baseUrl}?page=${pageNumber-1}`;
        const url = `${baseUrl}?page=${pageNumber}`;
        const lastPage = parseInt($('div.normal-pagination a:nth-last-child(2)')[0].firstChild.data);
        $("div.post-edit-box > a[href^='/replies/']:not(.post-history, .appended)").each(
            function(){
                $(this).replaceWith('<a href="'+prev+'" class="appended">page '+(pageNumber-1)+'</a>, '+'<a href="'+$(this).attr('href')+'" class="appended">post '+$(this).attr('href').slice(-7)+'</a>');});
        $("div.centered.margin-10").each(function(){this.style.display="none";});
        if (pageNumber > lastPage) {
            return;
        }
        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            onload: function(response) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(response.responseText, 'text/html');
                const contentSection = doc.querySelector(contentSectionSelector);
                if (contentSection) {
                    const postContainers = contentSection.querySelectorAll('div.post-container.post-reply');
                    if (postContainers.length > 0) {
                        const mainContentSection = document.querySelector(contentSectionSelector);
                        postContainers.forEach(postContainer => {
                            mainContentSection.appendChild(postContainer);
                        });
                        appendContentFromPage(pageNumber + 1);
                    }
                }
            },
            onerror: function() {
                console.error('Error fetching content from page:', pageNumber);
            }
        });
    }
    // Start appending content from the second page
    appendContentFromPage(startingPage+1);
    console.log("External links:");
    Array.prototype.forEach.call($("div.post-content a:not(.appended)").map(function(){return $(this).attr("href");}), (a)=>(console.log(a)));
})();

CSS

You can inject custom stylesheets into selected websites with add-ons like Stylus (Firefox, Chrome).


Slate Star Codex

Makes the content take up most of the page, and makes the comments much more compact. Could use some aesthetic tweaks.

div.comment-author {
    line-height: 1em;
    display: inline-block;
}
div.comment-meta {
    display: inline-block;
    margin: 0;
}
.new-text {
    display: none;
}
#comments .commentlist li.comment {
    line-height: 1.6em;
    margin: 0px;
    border-top: 1px solid #0004;
    border-radius: 2px;
    margin-bottom: -12px;
}

#comments .commentlist li.comment .commentholder {
    border: none;
    border-radius: 0; 
    
    border-top-right-radius: 2px; 
    border-right: 1px solid #0004; 
    background: transparent;
}

ul.children {
    border-left: 1px dotted #0003;
    border-top-left-radius: 2px;
}

div.reply a {
    text-decoration: none !important;
}

#primary {
    display: none;
}

#pjgm-wrap {
    max-width: unset;
    margin-top: 0px;
}

#pjgm-header {
    border-radius: 0px;
}

OpenAI Chat

Makes code boxes visually nicer, and removes their language names.

main div.group > div {
    max-width: 67%;
}

main div.group > div div.markdown pre code {
    filter: brightness(120%) contrast(160%) saturate(160%);   
}

main div.group > div div.markdown pre > div:first-child > div:first-child { 
    /* don't show 'Copy Code' block if not hovering over code block */
    /* display: none; */
    position: absolute; 
    right: 0;
    background-color: transparent; 
}

main div.group > div div.markdown pre > div:first-child > div:first-child > span:first-child { 
    /* don't show language name, since always either obvious or irrelevant/wrong */
    display: none;
}

Twitter

Hides the "For You" tab. I find that I keep clicking it out of idle curiosity and getting pulled into a sea of garbage, and this short-circuits that problem. It keeps the (now double-width) Following tab out of spite, but you can remove it entirely with the rule div[role="tablist"] {display: none;}.

div[role="tablist"] div:first-child a {
    display: none; 
}
div[role="tablist"] div:first-child {
    flex-grow: 0;
}