// ==UserScript== // @name MeFi Neater Bylines // @namespace https://github.com/klipspringr/mefi-userscripts // @version 2025-08-29-a // @description MetaFilter: neaten up comment bylines // @author Klipspringer // @supportURL https://github.com/klipspringr/mefi-userscripts // @license MIT // @match *://*.metafilter.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @downloadURL https://raw.githubusercontent.com/klipspringr/mefi-userscripts/main/mefi-replace-quote-label.user.js // @updateURL https://raw.githubusercontent.com/klipspringr/mefi-userscripts/main/mefi-replace-quote-label.user.js // ==/UserScript== ;(async () => { "use strict" if ( !/^\/(\d|comments\.mefi)/.test(window.location.pathname) || /rss$/.test(window.location.pathname) ) return const KEY_CUSTOM_LABEL = "custom-quote-button-label" const SVG_REPLY = `` const SVG_USE_REPLY = `` const getSetting = async (key, def = "") => { const value = await GM_getValue(key, def) return String(value) } const handleEditLabel = async () => { const existing = await GM_getValue(KEY_CUSTOM_LABEL, "") const edited = prompt( "Quote button label (leave blank for reply arrow):", String(existing) ) await GM_setValue(KEY_CUSTOM_LABEL, edited || "") await modifyQuoteButtons() } GM_registerMenuCommand("Edit quote button", handleEditLabel) const modifyQuoteButtons = async () => { const start = performance.now() const customLabel = await getSetting(KEY_CUSTOM_LABEL, "") const label = customLabel || SVG_USE_REPLY const nodes = document.querySelectorAll("a.quotebutton") nodes.forEach((node) => { // replace quote button content node.innerHTML = label if (node.hasAttribute("data-mrql-moved")) return // move quote button to before flag button node.parentNode.parentNode .querySelector("span[id^='flag']") ?.before(node.parentNode) // mark as done so we don't pick this up again node.setAttribute("data-mrql-moved", "") }) console.log( "mefi-replace-quote-label", nodes.length, Math.round(performance.now() - start) + "ms" ) } document.body.insertAdjacentHTML("beforeend", SVG_REPLY) // MefiQuote listens for the "mefi-comments" event, but: // (a) my event listener wasn't picking that up for some reason; and // (b) there could be timing issues as MefiQuote needs to complete its work first // hence using MutationObserver instead. const newCommentsElement = document.getElementById("newcomments") if (newCommentsElement) { const observer = new MutationObserver(() => modifyQuoteButtons()) observer.observe(newCommentsElement, { childList: true }) } modifyQuoteButtons() })()