Last active
March 21, 2024 13:05
-
-
Save MohamedElashri/beb6af8fce6c407ec35366518a2f59aa to your computer and use it in GitHub Desktop.
This is my standard userstyle for HN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Hacker News Comprehensive Enhancements (Light) | |
// @namespace http://melashri.net/hn | |
// @version 1.3 | |
// @description A comprehensive enhancement script for Hacker News | |
// @author melashri | |
// @match https://news.ycombinator.com/* | |
// @grant GM_addStyle | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
// --------------------------- | |
// Configuration Settings | |
// --------------------------- | |
const autoCollapse = false; // Enable/disable auto-collapse feature | |
const numberOfRoots = 5; // Number of root comments to display | |
const numberOfReplies = 3; // Number of replies to display | |
const numberOfRepliesOfReplies = 1; // Number of replies' replies to display | |
const FIX_NUMBERING = false; // Enable/disable re-numbering of posts after ad removal | |
// CSS Injection | |
// --------------------------- | |
// Inject custom CSS for various elements on the page | |
/// Global, Container, Text, Link, Header, News Listing Styles | |
const userStyleCSS = ` | |
/* Global Styles */ | |
body { | |
margin: 0 !important; | |
padding: 0 !important; | |
background: #bfcddb !important; /* Light blue background */ | |
} | |
/* Main Container Styles */ | |
#hnmain { | |
background: #fcfcfc !important; /* White background */ | |
max-width: 95% !important; /* Use max-width for scalability */ | |
box-shadow: 0px 0px 30px 3px rgba(7, 43, 132, .2) !important; /* Box shadow for depth */ | |
border-left: 1px solid #fff !important; | |
border-right: 1px solid #fff !important; | |
margin: 0 auto; /* Center the container */ | |
} | |
/* Responsive design for smaller screens */ | |
@media screen and (max-width: 600px) { | |
#hnmain { | |
width: 100% !important; /* Full width on small screens */ | |
box-shadow: none !important; /* Optional: remove shadow on small screens */ | |
} | |
} | |
/* Text and Link Styles */ | |
td { | |
color: #c40707 !important; /* Red text color for table data */ | |
} | |
/* Dead Links Styling */ | |
.dead a:link:hover, .dead a:visited { | |
background: #0d0d0d !important; /* Dark background for dead links */ | |
color: #fff !important; /* White text color for contrast */ | |
} | |
.dead a:link:hover::before { | |
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAMAAAAR8Wy4AAAATlBMVEX///9NTU38/PxjY2OVlZX5+fny8vLDw8Nzc3P29vbh4eHLy8uysrKmpqaKioqDg4Pm5uZVVVXV1dW8vLyPj495eXlra2ve3t7b29taWlqwMuwSAAAAk0lEQVQI1z2OVw7EMAhEsXHBvcROuf9FlzjZzAcSTwN6cEenXYg9Sngjp1jJfxDEmxNgtSI+O24g3Q0sPYCsNAxUrRkzUcbh+tDQGx3KyKKgJr+3E7oqNEtBHDNjUR3AGbM1EaO4tlMuK57cbSOYz8zbampIx6MdbEFrvVcBsw0ajktEqRNNtuI/nj0S+xm37pPSP4ZHBjEu/RG/AAAAAElFTkSuQmCC) !important; | |
background: #fff !important; | |
color: #fff !important; | |
padding: 3px 3px 2px 3px !important; | |
margin-right: 3px !important; | |
border: 1px solid #000 !important; | |
} | |
.dead a:link:hover::after { | |
content: "[DEAD LINK]"; | |
background: #939090 !important; | |
color: #fff !important; | |
padding: 0 4px !important; | |
} | |
/* Header Styling */ | |
#hnmain td[bgcolor="#ff6600"] { | |
background: linear-gradient(to top, rgba(232,228,221,1) 0%, rgba(243,239,237,1) 100%) !important; | |
padding: 3px 4px !important; | |
box-shadow: 0px 1px 1px 0px rgba(33, 33, 33, 0.2); | |
} | |
.pagetop a[href="news"] { | |
font-size: 133% !important; | |
text-shadow: -1px -1px 0 #fffbf3, 1px -1px 0 #fffbf3, -1px 1px 0 #fffbf3, 1px 1px 0 #fffbf3 !important; | |
} | |
/* Various Header Link Styles */ | |
.topsel a { | |
color: #f60 !important; | |
font-weight: bold !important; | |
} | |
.pagetop a:not(:first-child):hover { | |
text-decoration: underline !important; | |
} | |
.pagetop { | |
color: #620303 !important; | |
} | |
#hnmain td[bgcolor="#ffffaa"] * { | |
color: #000 !important; | |
} | |
/* Front Page News Listing Styles */ | |
.title:first-child { | |
padding-right: 8px !important; | |
padding-left: 8px !important; | |
color: #f60 !important; | |
font-size: 11px !important; | |
} | |
.title:not(:first-child) { | |
font-size: 16px !important; | |
font-family: "Verdana", "Lucida Grande", "Open Sans", "Bitstream Vera Sans", sans-serif !important; | |
padding-left: 8px !important; | |
} | |
.title:not(:first-child) > a { | |
border-bottom: 1px solid #620303 !important; | |
} | |
.title:not(:first-child) > a:hover { | |
text-decoration: underline !important; | |
border: none !important; | |
} | |
.title > a:visited { | |
color: #44010b !important; | |
} | |
.title .sitebit { | |
color: #44010b !important; | |
} | |
.subtext { | |
font-size: 11px !important; | |
color: #f60 !important; | |
padding-left: 8px !important; | |
} | |
tr[style="height:5px"] { | |
height: 16px !important; | |
} | |
.title > a[href^="news?p="] { | |
color: #7c500d !important; | |
} | |
/* Comment Section Styles */ | |
#hnmain > tbody > tr:first-child + tr + tr > td > table + br + br + table { | |
padding-right: 10px !important; | |
} | |
#hnmain > tbody > tr:first-child + tr + tr > td > table > tbody > tr:first-child > .title > a { | |
color: #c67d0f !important; | |
} | |
.comment { | |
font-family: "Lucida Grande", "Open Sans", "Bitstream Vera Sans", "Verdana", sans-serif !important; | |
font-size: 105% !important; | |
line-height: 1.5 !important; | |
} | |
.default { | |
padding: 10px 0 !important; | |
} | |
.default p { | |
margin-bottom: 6px !important; | |
} | |
.comment a { | |
text-decoration: none !important; | |
border-bottom: 1px solid #c40707 !important; | |
} | |
a[href^="reply"] { | |
background: linear-gradient(to top, rgba(232,228,221,1) 0%, rgba(243,239,237,1) 100%) !important; | |
padding: 2px 6px 3px 6px !important; | |
border-radius: 5px !important; | |
border: 2px solid #a07a42 !important; | |
text-shadow: 0px 1px 0px #ffffff; | |
} | |
a[href^="reply"]:hover { | |
background: linear-gradient(to bottom, rgba(232,228,221,1) 0%, rgba(243,239,237,1) 100%) !important; | |
padding: 2px 6px 3px 6px !important; | |
border-radius: 5px !important; | |
border: 2px solid #c67d0f !important; | |
text-shadow: 0px -1px 0px #ffffff; | |
} | |
.default .comhead { | |
opacity: 1 !important; | |
color: #f60 !important; | |
} | |
.default .comhead:hover { | |
opacity: 1 !important; | |
} | |
.comhead a[href^="user?"] { | |
font-weight: bold !important; | |
color: #f90 !important; | |
} | |
.comment pre { | |
max-width: 750px !important; | |
font-size: 12px !important; | |
} | |
#hnmain > tbody > tr:first-child + tr + tr > td > table + br + br + table .votearrow { | |
margin-top: 11px !important; | |
} | |
/* Dimmed Comment Styling */ | |
.c5a, .c73, .c82, .c88, .c9c, | |
.cae, .cbe, .cce, .cdd { | |
transition: color 0.5s !important; | |
} | |
.c5a:hover, .c73:hover, .c82:hover, .c88:hover, .c9c:hover, | |
.cae:hover, .cbe:hover, .cce:hover, .cdd:hover { | |
color: #000 !important; | |
} | |
/* Footer Styles */ | |
#hnmain > tbody > tr:last-child { | |
background: linear-gradient(to bottom, #fff 0%, #b9b2a7 100%) !important; | |
} | |
`; | |
// Custom CSS for quotes | |
const quoteCSS = ` | |
.quote { | |
border-left: 3px solid #ff6600; /* Hacker News orange color */ | |
padding: 6px 6px 6px 9px; | |
font-style: italic; | |
background-color: #fff3e0; /* Light orange background */ | |
border-radius: 5px; /* Example border radius */ | |
} | |
`; | |
// Custom CSS for vote arrows | |
const voteArrowCSS = ` | |
:root { | |
--colour-hn-orange: #ff6600; | |
--colour-hn-orange-pale: rgba(255, 102, 0, 0.05); | |
--colour-voted: #cccccc; /* Colour for voted arrows */ | |
--border-radius: 8px; | |
} | |
.votelinks { | |
min-width: 32px; | |
} | |
.votearrow { | |
background: var(--colour-hn-orange-pale); | |
border-radius: var(--border-radius); | |
color: var(--colour-hn-orange); | |
display: block; | |
width: 24px; | |
height: 24px; | |
font-size: 16px; | |
position: relative; | |
top: 2px; | |
cursor: pointer; /* Makes it clear that it's clickable */ | |
} | |
.votearrow:hover, .votearrow.voted { | |
background: var(--colour-hn-orange); | |
color: white; | |
} | |
.votearrow.voted { | |
background: var(--colour-voted); | |
color: var(--colour-hn-orange); | |
} | |
.votearrow:after { | |
content: "⇧"; | |
} | |
`; | |
// Additional CSS for hover effects | |
const fadeOnHoverCSS = ` | |
.verticalBar:hover { | |
background-color: gray !important; | |
} | |
`; | |
// --------------------------- | |
// Lists | |
// --------------------------- | |
const topics = [ | |
"Trump", "Governments", "Israel", "Biden", "Congress", "Sex", "Housing" , | |
"Court", "Israeli","Elite", "Musk", "Military", "Iran", "Iranian", "Boeing", | |
"artist", "artists", "emacs", "twitter", "antisemitism", "islam", "ukraine", | |
"north korea", "Tesla", "SpaceX", "DoD", "pantagon", "Matlab", "union", "unions", | |
"cats", "cat", "facebook", "tiktok", "snapchat","Java", "government","veto", | |
]; | |
const sites = [ | |
"foxnews.com", "bbc.co.uk", "bbc.com", "cnn.com", "economist.com","nbcnews.com", | |
]; | |
const users = [ | |
// **sanity** | |
"rendall", "usehackernews", "rewmie", "kaba0", "Natsu", | |
"dijit", "Aloisius", "josephcsible", "iddan", "deadbabe", | |
"Ferret7446", "johnwheeler", | |
// **Islamphopia** | |
"YZF", "throwaway5959", "rottencupcakes", "riku_iki", | |
"llimos", "physicles", "coryrc", "motoxpro", "hirako2000", | |
"richardfeynman", "vasilipupkin", "tptacek", "wonderwonder", "ericfrazier", | |
"weatherlite", "rrook", "wslh", "rythmshifter", "GuB-42", "elromulous", "AnimalMuppet", | |
"prmph", "readthenotes1","gruez", "me_me_me", "prmph", "slibhb", "xpl", "ekianjo", | |
"tekknik", "dijit", "sheff_ne", "Always_Anon", "llm_trw", "samsin", "numpad0", "screye", | |
"brink", "mschuster91", "GardenLetter27","xdennis","JumpCrisscross","tguvot","rickydroll", | |
"megaman821", "RoyTyrell", "bryanlarsen", "myth_drannon", "ftyhbhyjnjk", "nsguy", | |
"pvg","candiodari", | |
]; | |
const projects = [ | |
{ | |
name: "Archive.is", | |
url: "https://archive.is/", | |
}, | |
{ | |
name: "12ft.io", | |
url: "https://12ft.io/", | |
}, | |
{ | |
name: "Archive.org", | |
url: "https://web.archive.org/web/", | |
}, | |
]; | |
// source https://github.com/MostlyEmre/hn-anti-paywall | |
const paywalls = [ | |
"adweek.com","ad.nl","ambito.com","americanbanker.com","baltimoresun.com","barrons.com", | |
"bloomberg.com","bloombergquint.com","bndestem.nl","bostonglobe.com","bd.nl", "brisbanetimes.com.au", | |
"businessinsider.com","caixinglobal.com","centralwesterndaily.com.au","cen.acs.org","chicagotribune.com", | |
"corriere.it","chicagobusiness.com","dailypress.com","gelderlander.nl","groene.nl", | |
"demorgen.be","denverpost.com","speld.nl","destentor.nl","tijd.be", | |
"volkskrant.nl","df.cl","editorialedomani.it","dynamed.com","ed.nl", | |
"elmercurio.com","elmundo.es","elpais.com","elperiodico.com","elu24.ee", | |
"britannica.com","estadao.com.br","examiner.com.au","expansion.com", | |
"fnlondon.com","financialpost.com","ft.com","firstthings.com", | |
"foreignpolicy.com","fortune.com","genomeweb.com","glassdoor.com", | |
"globes.co.il","grubstreet.com","haaretz.com","haaretz.co.il","harpers.org","courant.com","hbr.org", | |
"hbrchina.org","heraldsun.com.au","fd.nl","historyextra.com","humo.be", | |
"ilmanifesto.it","inc.com","interest.co.nz","investorschronicle.co.uk", | |
"lanacion.com.ar","repubblica.it","lastampa.it","latercera.com", | |
"lavoixdunord.fr","lecho.be","ledevoir.com","leparisien.fr", | |
"lesechos.fr","loebclassics.com","lrb.co.uk","labusinessjournal.com","latimes.com", | |
"medium.com","medscape.com","mexiconewsdaily.com","sloanreview.mit.edu", | |
"technologyreview.com","mv-voice.com","nationalgeographic.com","nationalpost.com", | |
"nzz.ch","newstatesman.com","nydailynews.com","nymag.com", | |
"nzherald.co.nz","nrc.nl","ntnews.com.au","ocregister.com","orlandosentinel.com", | |
"paloaltoonline.com","parool.nl","postimees.ee","pzc.nl", | |
"qz.com","quora.com","gelocal.it","republic.ru","reuters.com","sandiegouniontribune.com", | |
"sfchronicle.com","scientificamerican.com","seekingalpha.com","slate.com", | |
"sofrep.com","startribune.com","statista.com","stuff.co.nz","\"sueddeutsche.de\"", | |
"sun-sentinel.com","techinasia.com","telegraaf.nl","time.com", | |
"adelaidenow.com.au","theadvocate.com.au","theage.com.au","the-american-interest.com", | |
"theathletic.com","theathletic.co.uk","theatlantic.com","afr.com","theaustralian.com.au", | |
"bizjournals.com","canberratimes.com.au","thecourier.com.au","couriermail.com.au", | |
"thecut.com","dailytelegraph.com.au","thediplomat.com","economist.com","theglobeandmail.com", | |
"theherald.com.au","thehindu.com","irishtimes.com","japantimes.co.jp","kansascity.com", | |
"themarker.com","mercurynews.com","themercury.com.au","mcall.com","thenation.com", | |
"thenational.scot","news-gazette.com","newyorker.com","nytimes.com", | |
"theolivepress.es","inquirer.com","thesaturdaypaper.com.au","seattletimes.com", | |
"spectator.com.au","spectator.co.uk","spectator.us","smh.com.au", | |
"telegraph.co.uk","thestar.com","wsj.com","washingtonpost.com","thewrap.com", | |
"the-tls.co.uk","towardsdatascience.com","trouw.nl","tubantia.nl","vanityfair.com", | |
"vn.nl","vulture.com","journalnow.com","wired.com","zeit.de" | |
]; | |
// --------------------------- | |
// Functions | |
// --------------------------- | |
// | |
// Function to find elements containing text starting with '>' | |
function findElementContentsStartingWithQuoteChar(elementNames) { | |
let nodes = []; | |
elementNames.forEach(elementName => { | |
const es = document.evaluate(`//${elementName}[contains(text(), '>')]`, document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); | |
for (let i = 0; i < es.snapshotLength; i++) { | |
nodes.push(es.snapshotItem(i)); | |
} | |
}); | |
return nodes; | |
} | |
// Function to apply custom styling to quotes | |
function applyCustomStylingToQuotes(nodes) { | |
nodes.forEach((n, index) => { | |
const textNode = Array.from(n.childNodes).find((n) => n.nodeType === Node.TEXT_NODE && n.textContent.trim().startsWith('>')); | |
if (textNode) { | |
const p = document.createElement('p'); | |
p.classList.add('quote'); | |
if (textNode.textContent.trim() === ">") { | |
const quotedContent = textNode.nextSibling; | |
p.innerHTML = quotedContent.innerHTML.trim(); | |
quotedContent.remove(); | |
} else { | |
p.innerHTML = textNode.textContent.replace(">", "").trim(); | |
} | |
n.replaceChild(p, textNode); | |
} | |
}); | |
} | |
// function to remove inline ads | |
function hideInlineAdsOnHN() { | |
// Select all posts (rows with class "athing") | |
let things = document.querySelectorAll("tr.athing"); | |
// Iterate over each post | |
for(let i = 0; i < things.length; i++) { | |
// Ensure the nextSibling exists and is the expected subtext row | |
if(things[i].nextSibling && things[i].nextSibling.querySelector("td.subtext")) { | |
// Check if the subtext row has exactly two child elements | |
if(things[i].nextSibling.querySelector("td.subtext").childElementCount == 2) { | |
// Hide the post row | |
things[i].style.display = "none"; | |
// Hide the subtext row | |
things[i].nextSibling.style.display = "none"; | |
// Check and hide the additional related element, which could be spacing or further details | |
// Make sure to safely check for the existence of next siblings to avoid errors | |
let possibleAdDetailsRow = things[i].nextSibling.nextSibling; | |
if(possibleAdDetailsRow && possibleAdDetailsRow.nextSibling) { | |
possibleAdDetailsRow.nextSibling.style.display = "none"; | |
} | |
} | |
} | |
} | |
} | |
// Helper function to determine if a row is a spacer | |
function isSpacerRow(row) { | |
// Implement logic to determine if a row is used as a spacer | |
// This can be based on class, style, or lack of certain elements | |
return row.style.height === "5px"; // To be fine tuned | |
} | |
// Helper function to determine if a row is a metadata row | |
function isMetadataRow(row) { | |
// Implement logic to determine if a row contains metadata | |
// This can be based on the presence of certain classes or specific text | |
// Adjust the condition based on the actual structure of the page | |
return row.querySelector('.subtext') !== null; | |
} | |
// Function to hide elements containing specific text | |
function hideElementsByText(selector, text, includeParent = false) { | |
const elements = document.querySelectorAll(selector); | |
const lowerCaseText = text.toLowerCase(); // Convert the text to lowercase | |
elements.forEach(el => { | |
if (el.textContent.toLowerCase().includes(lowerCaseText)) { | |
let elementToHide = includeParent ? el.closest('tr') : el; | |
if (elementToHide) { | |
// Hide the parent <tr> | |
let parentRow = elementToHide.closest('tr'); | |
if (parentRow) { | |
parentRow.style.display = 'none'; | |
// Hide the next sibling if it's a spacer or metadata row | |
let nextSiblingRow = parentRow.nextElementSibling; | |
if (nextSiblingRow && nextSiblingRow.tagName === "TR") { | |
if (isSpacerRow(nextSiblingRow) || isMetadataRow(nextSiblingRow)) { | |
nextSiblingRow.style.display = 'none'; | |
} | |
} | |
// Additionally, check for and hide a previous spacer if present | |
let previousSiblingRow = parentRow.previousElementSibling; | |
if (previousSiblingRow && previousSiblingRow.tagName === "TR") { | |
if (isSpacerRow(previousSiblingRow)) { | |
previousSiblingRow.style.display = 'none'; | |
} | |
} | |
} | |
} | |
} | |
}); | |
} | |
// Function to apply filters based on topics, sites, and users | |
function applyFilters() { | |
topics.forEach(topic => { | |
hideElementsByText('.title a', topic, true); | |
}); | |
sites.forEach(site => { | |
hideElementsByText('.title .sitebit', site, true); | |
}); | |
users.forEach(user => { | |
hideElementsByText('.comhead > a[href^="user?"]', user, true); | |
}); | |
} | |
// Function to bypass paywalls and add redirection | |
function passTheButter(node, paywalls, projects) { | |
// Check if node.nextSibling is an element and has querySelector | |
if (node.nextSibling && node.nextSibling.nodeType === Node.ELEMENT_NODE) { | |
let meta = node.nextSibling.querySelector(".subtext"); | |
// Additional check for meta existence | |
if (meta) { | |
let link = node.querySelector(".titleline a").href; | |
let domain = node.querySelector("span.sitestr") ? node.querySelector("span.sitestr").innerText : ""; | |
let paywall = paywalls.find((paywall) => domain.includes(paywall)); | |
if (paywall) { | |
let paywallSpan = document.createElement("span"); | |
paywallSpan.appendChild(document.createTextNode(" | 💰")); | |
projects.forEach((project) => { | |
const anchor = document.createElement("a"); | |
const line = document.createElement("span"); | |
line.textContent = " | "; | |
anchor.setAttribute("href", `${project.url}${link}`); | |
anchor.setAttribute("target", "_blank"); | |
anchor.setAttribute("rel", "noopener noreferrer"); | |
anchor.textContent = project.name; | |
paywallSpan.appendChild(line); | |
paywallSpan.appendChild(anchor); | |
}); | |
meta.appendChild(paywallSpan); | |
} | |
} else { | |
console.log("Meta element not found for node: ", node); | |
} | |
} else { | |
console.log("Unexpected node type or null nextSibling for node: ", node); | |
} | |
} | |
// Function to inject CSS into the document | |
function injectCSS(css) { | |
const style = document.createElement('style'); | |
style.type = 'text/css'; | |
style.appendChild(document.createTextNode(css)); | |
document.head.appendChild(style); | |
} | |
// --------------------------- | |
// Feature Implementations | |
// --------------------------- | |
// Highlight number of comments in bold | |
function highlightComments() { | |
let commentLinks = document.querySelectorAll("td.subtext > span.subline > a[href^='item?id']"); | |
for (let i = 0; i < commentLinks.length; i++) { | |
let commentMatch = commentLinks[i].innerHTML.match(/^([0-9]+)/); | |
if (commentMatch) { | |
let numComments = commentMatch[0]; | |
let plural = numComments > 1 ? "s" : ""; | |
commentLinks[i].innerHTML = `<span style="font-weight: bold; color: #c40707;">${numComments}</span> comment${plural}`; | |
} | |
} | |
} | |
// Highlight the submission author | |
function highlightSubmissionAuthor() { | |
// Check if the current page is a submission page and not running on iOS | |
if (window.location.href.includes('item?id=') && !/iPad|iPhone|iPod/.test(navigator.userAgent)) { | |
let originalPoster = document.querySelector('.hnuser'); | |
if (originalPoster) { | |
originalPoster = originalPoster.innerText; | |
GM_addStyle(` | |
a[href='user?id=${originalPoster}'] { | |
background: #e0f7fa !important; | |
color: #c40707 !important; | |
padding: 5px 10px !important; | |
border-radius: 10px !important; | |
font-weight: bold !important; | |
font-size: 12px !important; | |
} | |
`); | |
} | |
} | |
} | |
// Add click event to toggle the voted class on vote arrows | |
function addVoteArrowClickEvent() { | |
document.addEventListener('click', function(event) { | |
if (event.target.classList.contains('votearrow')) { | |
event.target.classList.toggle('voted'); | |
} | |
}, false); | |
} | |
// Function to toggle hiding a comment and all its sub-comments. | |
(function() { | |
// Pre-calculate and cache the comments length to avoid recalculating | |
const comments = document.querySelectorAll('.athing'); | |
const commentsLength = comments.length; | |
// Function to toggle comment visibility | |
const toggleComment = (comment, collapse) => { | |
const text = comment.querySelector('.comment'); | |
const displayStyle = text.style.display === '' ? 'none' : ''; | |
text.style.display = displayStyle; | |
// Update collapse button text | |
collapse.textContent = displayStyle === '' ? '[-]' : '[+]'; | |
}; | |
// Optimize by avoiding repeated DOM queries for the same elements | |
for (let i = 0; i < commentsLength; i++) { | |
const comment = comments[i]; | |
const indentImg = comment.querySelector('td.ind img'); | |
// Skip OP and comments without indentation | |
if (indentImg === null) continue; | |
const collapse = document.createElement('a'); | |
Object.assign(collapse.style, { cursor: 'pointer', marginRight: '5px', fontFamily: 'monospace' }); | |
collapse.className = 'addon-comment-collapse'; | |
collapse.textContent = '[-]'; | |
collapse.onclick = () => { | |
const originIndent = indentImg.width; | |
let minIgnoreIndent = Number.MAX_SAFE_INTEGER; | |
toggleComment(comment, collapse); // Toggle the clicked comment | |
for (let j = i + 1; j < commentsLength; j++) { | |
const nextComment = comments[j]; | |
const nextIndentImg = nextComment.querySelector('td.ind img'); | |
const indent = nextIndentImg ? nextIndentImg.width : 0; | |
if (indent <= originIndent) break; | |
if (indent >= minIgnoreIndent) continue; | |
nextComment.style.display = comment.querySelector('.comment').style.display; | |
const subCollapse = nextComment.querySelector('.addon-comment-collapse'); | |
if (subCollapse && subCollapse.textContent == '[+]') { | |
minIgnoreIndent = indent + 1; | |
} else { | |
minIgnoreIndent = Number.MAX_SAFE_INTEGER; | |
} | |
} | |
}; | |
const commentHead = comment.querySelector('.comhead'); | |
commentHead.insertBefore(collapse, commentHead.firstChild); | |
} | |
})(); | |
// --------------------------- | |
// Initialization | |
// --------------------------- | |
// Inject all custom CSS | |
injectCSS(userStyleCSS + quoteCSS + voteArrowCSS + fadeOnHoverCSS); | |
// Add bypass to submissions and links | |
let titles = document.querySelectorAll("table tr.athing"); | |
let postTitle = document.querySelector("tbody table.fatitem tr.athing"); | |
postTitle ? passTheButter(postTitle, paywalls, projects) : titles.forEach((title) => { | |
passTheButter(title, paywalls, projects); | |
}); | |
// Apply custom styling to quotes | |
const commentNodes = findElementContentsStartingWithQuoteChar(['span', 'p']); | |
applyCustomStylingToQuotes(commentNodes); | |
// Run the filter function on page load | |
applyFilters(); | |
// Remove job ads and renumber posts | |
hideInlineAdsOnHN(); | |
// Add event listeners and other initialization code | |
highlightComments(); | |
highlightSubmissionAuthor(); | |
addVoteArrowClickEvent(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment