您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
MetaFilter: navigate through users' comments, and highlight comments by OP and yourself
当前为
// ==UserScript== // @name MeFi Navigator Redux // @namespace https://github.com/klipspringr/mefi-userscripts // @version 2025-03-29-a // @description MetaFilter: navigate through users' comments, and highlight comments by OP and yourself // @author Klipspringer // @supportURL https://github.com/klipspringr/mefi-userscripts // @license MIT // @match *://*.metafilter.com/* // @grant none // ==/UserScript== const SELF_HTML = '<span style="padding:0 4px;margin-left:4px;background-color:#C8E0A1;color:#000;font-size:0.8em;border-radius:2px;">me</span>'; const getCookie = (key) => { const s = RegExp(key + "=([^;]+)").exec(document.cookie); if (!s || !s[1]) return null; return decodeURIComponent(s[1]); }; const createLink = (href, content) => { const a = document.createElement("a"); a.setAttribute("href", href); a.textContent = content; return a; }; const markSelf = (targetNode) => targetNode.insertAdjacentHTML("afterend", SELF_HTML); const markOP = (targetNode) => { const wrapper = targetNode.parentNode.parentNode; wrapper.style["border-left"] = "5px solid #0004"; // 40% black wrapper.style["padding-left"] = "10px"; }; const processByline = ( bylineNode, user, anchor, anchors, firstRun, self = null, op = null ) => { if (firstRun || !bylineNode.hasAttribute("data-mfn-processed")) { if (self !== null && user === self) markSelf(bylineNode); if (op !== null && user === op) markOP(bylineNode); bylineNode.setAttribute("data-mfn-processed", ""); } if (anchors.length <= 1) return; const i = anchors.indexOf(anchor); const previous = anchors[i - 1]; const next = anchors[i + 1]; // if not first run, check for existing nav and remove it if exists if (!firstRun) bylineNode.parentNode.querySelector("span[data-mfn-nav]")?.remove(); const navigator = document.createElement("span"); navigator.setAttribute("data-mfn-nav", ""); const navigatorNodes = [" ["]; if (previous) navigatorNodes.push(createLink("#" + previous, "⮝")); navigatorNodes.push(anchors.length); if (next) navigatorNodes.push(createLink("#" + next, "⮟")); navigatorNodes.push("]"); navigator.append(...navigatorNodes); bylineNode.parentNode.append(navigator); }; const run = (firstRun = false) => { const start = performance.now(); const subsite = window.location.hostname.split(".")[0]; const self = getCookie("USER_NAME"); // post node: first smallcopy in div.copy (works on all subsites, 2025-03-29) const postNode = document.querySelector( "div.copy > span.smallcopy > a:first-child" ); const op = postNode.textContent; // initialise with post const bylines = [[op, "top", 0]]; const mapUsersAnchors = new Map([[op, ["top"]]]); // comment nodes: smallcopy children of div.comments (works on all subsites, 2025-03-29) const commentNodes = document.querySelectorAll( "div.comments > span.smallcopy > a:first-child" ); for (const node of commentNodes) { const user = node.textContent; const anchorElement = node.parentElement.parentElement.previousElementSibling; const anchor = anchorElement.getAttribute("name"); bylines.push([user, anchor]); const anchors = mapUsersAnchors.get(user) ?? []; mapUsersAnchors.set(user, anchors.concat(anchor)); } for (const [i, bylineNode] of [postNode, ...commentNodes].entries()) { processByline( bylineNode, bylines[i][0], bylines[i][1], mapUsersAnchors.get(bylines[i][0]), firstRun, self, subsite !== "ask" && i > 0 ? op : null // don't highlight OP on AskMe, as site already does ); } console.log( "mefi-navigator-redux", firstRun ? "first-run" : "new-comments", 1 + commentNodes.length, performance.now() - start ); }; (() => { if (!/^\/(\d|comments\.mefi)/.test(window.location.pathname)) return; const newCommentsElement = document.getElementById("newcomments"); if (newCommentsElement) { const observer = new MutationObserver(run); observer.observe(newCommentsElement, { childList: true }); } run(true); })();