🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

Hacker News Tweaks (Modern)

Improve Hacker News readability with larger fonts, modern styling.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         Hacker News Tweaks (Modern)
// @namespace    HackerNewsReadabilityTweaks
// @homepage     https://github.com/Meekelis/Hacker-News-ReadabilityTweaks
// @version      1.0
// @description  Improve Hacker News readability with larger fonts, modern styling.
// @match        *://news.ycombinator.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=ycombinator.com
// @license      MIT
// @grant        none
// ==/UserScript==
(function() {
  'use strict';
  const css = `
    .comment-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0.5em 0;
      border-bottom: 1px solid #e1e1e1;
      background: #f9f9f9;
    }
    .comment-header__details {
      display: flex;
      gap: 0.5em;
      align-items: center;
    }
    .comment-header__username {
      font-weight: bold;
      color: #333;
      text-decoration: none;
    }
    .comment-header__timestamp a {
      color: #888;
      text-decoration: none;
    }
    .comment-header__actions {
      display: flex;
      gap: 0.5em;
      align-items: center;
    }
    .comment-header__link {
      font-size: 0.9em;
      color: #0077cc;
      text-decoration: none;
    }
    .comment-header__toggle {
      display: inline-block;
      width: 2em;
      text-align: center;
      background: none;
      border: none;
      color: #0077cc;
      cursor: pointer;
      font-size: 0.9em;
      line-height: 1;
    }
  `;
  const styleEl = document.createElement('style');
  styleEl.textContent = css;
  document.head.appendChild(styleEl);
  document.querySelectorAll('.comhead').forEach(comhead => {
    const origToggle = comhead.querySelector('a.togg');
    if (origToggle) { origToggle.style.display = 'none'; }
    const userEl = comhead.querySelector('a.hnuser');
    if (!userEl) return;
    const username = userEl.textContent.trim();
    const userHref = userEl.href;
    const ageEl = comhead.querySelector('.age');
    const ageLink = ageEl ? ageEl.querySelector('a') : null;
    const timestamp = ageLink ? ageLink.textContent.replace(/^on\s+/i, '').trim() : '';
    const timeHref = ageLink ? ageLink.href : '#';
    const datetime = ageEl ? ageEl.getAttribute('title') : '';
    let nextHref = '#';
    const navs = comhead.querySelector('.navs');
    if (navs) {
      const nextLink = Array.from(navs.querySelectorAll('a')).find(a => /next/i.test(a.textContent));
      if (nextLink) { nextHref = nextLink.href; }
    }
    const toggleId = origToggle ? origToggle.id : 'toggle';
    const newHeader = document.createElement('div');
    newHeader.className = 'comment-header';
    newHeader.innerHTML = `
      <div class="comment-header__details">
        <a href="${userHref}" class="comment-header__username" target="_blank" rel="noopener noreferrer">
          ${username}
        </a>
        <time datetime="${datetime}" class="comment-header__timestamp">
          <a href="${timeHref}" rel="noopener noreferrer">
            ${timestamp}
          </a>
        </time>
      </div>
      <div class="comment-header__actions">
        <a href="${nextHref}" class="comment-header__link" rel="noopener noreferrer">
          Next
        </a>
        <button class="comment-header__toggle" id="new-toggle-${toggleId}" aria-expanded="true">–</button>
      </div>
    `;
    comhead.innerHTML = '';
    comhead.appendChild(newHeader);
    const defaultCell = comhead.closest('td.default');
    if (!defaultCell) return;
    const commentText = defaultCell.querySelector('.comment');
    if (!commentText) return;
    const collapseBtn = newHeader.querySelector('.comment-header__toggle');
    collapseBtn.addEventListener('click', function(event) {
      event.preventDefault();
      const button = event.target;
      const commentRow = button.closest('.athing.comtr');
      if (!commentRow) return;
      const isCollapsed = button.textContent === '+';
      let nextSibling = commentRow.nextElementSibling;
      while (nextSibling && nextSibling.classList.contains('athing') && nextSibling.classList.contains('comtr')) {
        const indentOfSibling = parseInt(nextSibling.querySelector('.ind').getAttribute('indent') || '0', 10);
        const indentOfCurrent = parseInt(commentRow.querySelector('.ind').getAttribute('indent') || '0', 10);
        if (indentOfSibling > indentOfCurrent) {
          nextSibling.style.display = isCollapsed ? '' : 'none';
        } else { break; }
        nextSibling = nextSibling.nextElementSibling;
      }
      button.textContent = isCollapsed ? '–' : '+';
      button.setAttribute('aria-expanded', (!isCollapsed).toString());
    });
  });
})();
(function(){
  'use strict';
  const style1 = `
  <style>
    :root {
      --accent: #ff6600;
      --accent-light: rgba(255,102,0,0.1);
      --spacing: 0.5rem;
      --radius: 8px;
      --grey: #757575;
      --bg: #f9f9f9;
      --font-main: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
    }
    html, body, td, .title, .comment, .default { font-family: var(--font-main); }
    html, body { margin: 0; padding: 0; }
    body, td, .title, .pagetop, .comment { font-size: 1rem; line-height: 1.5; }
    .votelinks, html[op='news'] .title { vertical-align: inherit; }
    .comment-tree .votelinks,
    html[op='threads'] .votelinks,
    html[op='newcomments'] .votelinks { vertical-align: top; }
    span.titleline { font-size: 1rem; line-height: 1.2; margin: var(--spacing) 0; display: block; font-weight: bold; }
    html[op='item'] span.titleline { font-size: 1.0rem; }
    html[op='news'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='newest'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='ask'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='newcomments'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='shownew'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='submitted'] #hnmain>tbody>tr:nth-child(3)>td>table,
    html[op='favorites'] #hnmain>tbody>tr:nth-child(3)>td>table:nth-child(2),
    html[op='front'] #hnmain>tbody>tr:nth-child(3)>td>table:nth-child(2),
    html[op='show'] #hnmain>tbody>tr:nth-child(3)>td>table:nth-child(2) { margin-left: var(--spacing); }
    .sitebit.comhead { margin-left: var(--spacing); }
    .subtext, .subline { font-size: 0.75rem; }
    #hnmain { background: var(--bg); }
    #hnmain>tbody>tr:first-child>td { padding: var(--spacing); }
    #hnmain>tbody>tr:first-child>td>table>tbody>tr:first-child>td { padding-right: var(--spacing)!important; }
    .hnname { font-size: 1.4em; font-weight: bold; }
    .comment, .toptext { max-width: 40em; margin: auto; }
    .toptext, a, a:visited { color: #333; text-decoration: none; transition: color 0.2s; }
    input { padding: var(--spacing); }
    input, textarea { background: white; border: 1px solid var(--grey); padding: 6px; border-radius: var(--radius); transition: box-shadow 0.2s; }
    input:focus, textarea:focus { box-shadow: 0 0 5px var(--accent); }
    input[type="text"]:hover { text-decoration: none; }
    input[type='button'] { cursor: pointer; }
    .downvoted .commtext { color: var(--grey); }
    .quote { margin: 16px; border: 1px solid var(--accent-light); border-left: 6px solid var(--accent); padding: 16px; color: var(--grey); background: var(--accent-light); border-radius: var(--radius); font-size: 0.9em; }
    .hidden { display: none; }
    .showComment a, .hideComment, .hideComment:link, .hideComment:visited { color: var(--accent); text-decoration: underline; }
    .hideComment { margin-left: var(--spacing); }
    .votelinks { min-width: 32px; }
    .votearrow { background: var(--accent-light); border-radius: var(--radius); color: var(--accent); display: block; width: 24px; height: 24px; font-size: 16px; position: relative; top: 2px; transition: background 0.1s, color 0.2s; }
    .votearrow:hover { background: var(--accent); color: white; }
    .votearrow:after { content: "⇧"; }
    body:has(form[action="login"]) { padding: 32px; }
  </style>`;
  document.head.insertAdjacentHTML("beforeend", style1);
  const style2 = `
  <style>
    .modern-downvoted {
      background: linear-gradient(135deg, #eef6ff, #f7fbff);
      padding: 12px 16px;
      border-left: 4px solid #007BFF;
      border-radius: 4px;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      font-size: 16px;
      color: #333;
    }
    .modern-downvoted a {
      color: #007BFF;
      text-decoration: none;
      font-weight: 500;
    }
    .modern-downvoted a:hover {
      text-decoration: underline;
    }
    pre.modern-code {
      position: relative;
      background: #f7f7f7;
      color: #333;
      padding: 16px;
      border: 1px solid #ddd;
      border-radius: 4px;
      overflow: auto;
      font-family: 'Fira Code', Consolas, "Courier New", monospace;
      font-size: 15px;
      line-height: 1.6;
      margin-bottom: 1em;
    }
    pre.modern-code code {
      font-family: 'Fira Code', Consolas, "Courier New", monospace;
      color: inherit;
    }
    .copy-button {
      position: absolute;
      top: 8px;
      right: 8px;
      background: transparent;
      border: none;
      cursor: pointer;
      padding: 4px;
      transition: color 0.2s;
      color: #666;
    }
    .copy-button:hover {
      color: #000;
    }
    .copy-button.svg-icon {
      width: 20px;
      height: 20px;
      display: block;
    }
  </style>`;
  document.head.insertAdjacentHTML("beforeend", style2);
  document.querySelectorAll('.commtext a').forEach(link => {
    link.setAttribute('target', '_blank');
    link.setAttribute('rel', 'noopener noreferrer');
  });
  document.querySelectorAll('.commtext:not(.c00)').forEach(e => {
    e.parentElement.classList.add('downvoted');
  });
  const quotes = document.evaluate("//p[starts-with(., '>')] | //span[starts-with(., '>')]", document.body, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  for (let i = 0; i < quotes.snapshotLength; i++){
    let n = quotes.snapshotItem(i),
        t = Array.from(n.childNodes).find(x => x.nodeType === Node.TEXT_NODE);
    if (t){
      let p = document.createElement('p');
      p.className = 'quote';
      p.innerText = t.data.replace(">", "").trim();
      n.replaceChild(p, n.firstChild);
    } else {
      n.classList.add('quote');
      n.innerText = n.innerText.replace(">", "").trim();
    }
  }
  const copyIcon = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="svg-icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>`;
  const checkIcon = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="svg-icon"><path d="M20.285 5.715a1 1 0 00-1.414 0L9 15.586l-3.871-3.87a1 1 0 00-1.414 1.414l4.578 4.578a1 1 0 001.414 0l10.578-10.578a1 1 0 000-1.414z" fill="currentColor"/></svg>`;
  document.querySelectorAll('pre').forEach(block => {
    block.classList.add('modern-code');
    const btn = document.createElement('button');
    btn.className = 'copy-button svg-icon';
    btn.innerHTML = copyIcon;
    btn.addEventListener('click', () => {
      navigator.clipboard.writeText(block.innerText).then(() => {
        btn.classList.add('copied');
        btn.innerHTML = checkIcon;
        setTimeout(() => {
          btn.classList.remove('copied');
          btn.innerHTML = copyIcon;
        }, 2000);
      });
    });
    block.style.position = 'relative';
    block.appendChild(btn);
  });
  document.querySelectorAll('.comment.downvoted .commtext').forEach(e => {
    if (!e.querySelector('.modern-downvoted')) {
      const wrapper = document.createElement('div');
      wrapper.className = 'modern-downvoted';
      wrapper.innerHTML = e.innerHTML;
      e.innerHTML = '';
      e.appendChild(wrapper);
    }
  });
})();