您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes the HN UI even more compact than it is now.
// ==UserScript== // @name HN SuperCompact UI // @match https://news.ycombinator.com/* // @grant none // @version 1.14 // @author hncompact // @description Makes the HN UI even more compact than it is now. // @license MIT // @run-at document-end // @namespace https://greasyfork.org/users/1430513 // ==/UserScript== let POSTS_CSS = ` <style> .votelinks a { display:none } tr.submission a b { font-weight:normal; color:#f60; } tr.submission .votelinks { min-width:0 } tr.submission .votelinks center { min-width:1em } tr.submission.local .votelinks center::before { content:'*'; color:#6f0; } tr.submission + tr { display:none } tr.submission td:not(:last-child) { font-size:8pt; line-height:14pt; white-space:nowrap; text-align:right; vertical-align:top; } tr.submission td:first-child a:hover { text-decoration:underline } tr.submission .titleline .sitebit { display:none } </style> `; let COMMS_CSS = ` <style> tr.comtr .votelinks center font { display:none } tr.comtr .votelinks center { min-width:1em } tr.comtr .votelinks a { display:none } tr.comtr .reply a.downvote { display:none } tr.comtr .reply .expand:not(:empty) { margin-right:0.5em } tr.comtr .reply .expand { cursor:pointer; color:#fff; } tr.comtr .reply .expand b { font-weight:normal; color:#f60; } tr.comtr .reply .expand i { font-style:normal; color:#6f0; } tr.comtr:not(.coll) .reply * { font-size:8pt } tr.comtr:not(.coll) .reply > p > *:not(.expand) { opacity:0.5 } tr.comtr.recent .votelinks center::before { content:'*'; color:#6f0 !important; } tr.comtr .default > *:not(.comment) { display:none } tr.comtr .reply a { color:#444 } tr.comtr .reply .age a { text-decoration:none } tr.comtr a.hnuser { text-decoration:none } tr.comtr .navs *:not(.togg) { display:none } tr.comtr.coll .comment.noshow { display:inherit } tr.comtr.coll .comment.noshow .commtext { display:none } tr.comtr.coll .comment.noshow .reply > p > *:not(.comhead) { display:none } /* tr.compact .reply { display:none } */ </style> `; let $ = (s) => document.querySelector(s); let $$ = (s) => document.querySelectorAll(s); if ($$('tr.submission').length > 0) init(); else document.addEventListener("DOMContentLoaded", init); function init() { switch (location.pathname) { case '/': case '/news': document.head.insertAdjacentHTML('beforeend', POSTS_CSS); initPosts(); break; case '/item': document.head.insertAdjacentHTML('beforeend', COMMS_CSS); initComments(); break; } } function initPosts() { for (let tr of $$('tr.submission')) { //console.debug('tr.id=' + tr.id); let tr2 = tr.nextElementSibling; let subtext = tr2.textContent.trim(); let [,comms='0'] = subtext.match(/(\d+)\scomments/)||[]; let [,score='0'] = subtext.match(/(\d+)\spoints/)||[]; let [,time='0', units=''] = subtext.match(/(\d+)\s(\w+)\sago/)||[]; let td1 = tr.children[0]; td1.className = ''; td1.textContent = ''; let bcomms = document.createElement('b'); bcomms.textContent = comms; let link = tr2.querySelector('a:last-child'); link.remove(); link.textContent = ''; link.append(score, ':', bcomms); td1.append(link); //let span = document.createElement('span'); //span.className = 'comhead'; //span.append(' ', time, units[0]||''); //tr.querySelector('.titleline').append(span); for (let a of tr.querySelectorAll('.votelinks a')) a.remove(); if (units.match(/minute/)) tr.classList.add('recent'); if (!tr.querySelector('.sitebit')) tr.classList.add('local'); } } function initComments() { let postId = new URLSearchParams(location.search).get('id'); let lastVisit = +localStorage.getItem('lastseen' + postId); localStorage.setItem('lastseen' + postId, Date.now()/1000|0); for (let tr of $$('tr.comtr')) { let ind = tr.querySelector('.ind'); let d = +ind.getAttribute('indent') || 0; tr.setAttribute('d', d); //console.debug('tr.id=' + tr.id); let reply = tr.querySelector('.reply > p'); if (!reply) continue; for (let a of tr.querySelectorAll('.votelinks a')) { let va = a.querySelector('.votearrow'); let type = va ? va.getAttribute('title') : ''; a.textContent = type; a.classList.add(type); a.remove(); reply.append(a, ' '); } let comhead = tr.querySelector('.comhead'); comhead.remove(); reply.append(comhead); let age = reply.querySelector('.age'); if (age) { let title = age.getAttribute('title'); let time = +title?.split(' ')[1]; //age.querySelector('a').textContent = time + units[0]; if (lastVisit > 0 && time > 0 && time > lastVisit) tr.classList.add('recent'); } let navs = comhead.querySelector('.navs'); for (let node of navs ? navs.childNodes : []) if (node.nodeName == '#text') node.remove(); let collapse = navs && navs.querySelector('a.togg'); if (collapse && collapse.textContent.match(/^\[.\]$/)) collapse.textContent = '[ - ]'; let counter = document.createElement('u'); counter.classList.add('expand'); reply.prepend(counter); } $('.comment-tree').addEventListener('click', e => { let exp = e.target.closest('.expand'); if (!exp) return; let tr = exp.closest('tr.comtr'); toggleComment(tr); }); // update comment counters let stack = [$('tr.comtr')]; while (stack[0]) { let tr = stack[stack.length-1]; tr.imm = tr.imm || 0; tr.tot = tr.tot || 0; tr.new = tr.new || 0; let tr2 = tr.nextElementSibling; if (!tr2) break; let d = +tr.getAttribute('d') || 0; let d2 = tr2 ? +tr2.getAttribute('d') : -1; if (d2 <= d) { let tr0; do { let tr = stack.pop(); let exp = tr.querySelector('u.expand'); exp.textContent = ''; if (tr.tot > 0) { let b = document.createElement('b'); b.textContent = tr.imm; exp.append(tr.tot, ':', b); if (tr.new > 0) { let i = document.createElement('i'); i.textContent = tr.new; exp.append(':', i); } } tr0 = stack[stack.length-1]; // tr0 is the parent of tr if (tr0) { tr0.tot += tr.tot + 1; tr0.imm += +tr0.getAttribute('d') + 1 == +tr.getAttribute('d'); tr0.new += tr.new + tr.classList.contains('recent'); } } while (tr0 && d2 <= tr0.getAttribute('d')); } stack.push(tr2); } for (let tr of $$('.comment-tree tr.comtr[d="0"]')) toggleComment(tr); } function toggleComment(tr) { let d = +tr.getAttribute('d') || 0; let is_compact = tr.classList.toggle('compact'); let tr2 = tr.nextElementSibling; while (tr2 && tr2.getAttribute('d') > d) { let d2 = +tr2.getAttribute('d'); let hide = is_compact || d2 >= d + 2; //console.debug('tr#' + tr2.id, 'd=' + d2); tr2.classList.toggle('compact', !hide); tr2.classList.toggle('noshow', hide); tr2 = tr2.nextElementSibling; } }