A rewrite of Poly+, my quality-of-life browser extension for Polytoria. Built entirely fresh using the WXT extension framework, Typescript, and with added better overall code quality.
extension
1import config from "@/utils/config.json"; 2 3/** 4 * Detects any username mentions in a forum post and turns them into clickable links. 5 */ 6export function forumMentions() { 7 const textBlocks = document.querySelectorAll("p:not(.text-muted):not(.mb-0)"); 8 const regex = /@([\w.]+)/g; 9 10 textBlocks.forEach((text) => { 11 const walker = document.createTreeWalker(text, NodeFilter.SHOW_TEXT, null); 12 let node; 13 14 while ((node = walker.nextNode())) { 15 const fragment = document.createDocumentFragment(); 16 let lastIndex = 0; 17 let match; 18 19 while ((match = regex.exec(node.nodeValue!)) !== null) { 20 const username = match[1]; 21 const link = document.createElement("a"); 22 link.href = `/u/${username}`; 23 link.className = "polyplus-mention"; 24 link.textContent = match[0]; 25 26 fragment.appendChild( 27 document.createTextNode( 28 node.nodeValue!.substring(lastIndex, match.index), 29 ), 30 ); 31 fragment.appendChild(link); 32 lastIndex = match.index + match[0].length; 33 } 34 35 fragment.appendChild( 36 document.createTextNode(node.nodeValue!.substring(lastIndex)), 37 ); 38 node.parentNode!.replaceChild(fragment, node); 39 } 40 }); 41} 42 43export function generativeAI() { 44 for (const userID of config.users.generativeAI) { 45 const cards = document.querySelectorAll(".card"); 46 47 cards.forEach((card) => { 48 const user = card.querySelector(".forum-user-container"); 49 50 if (user) { 51 const link = user.querySelector(`[href^="/users/${userID}"]`); 52 53 if (link) { 54 const textBlock = card.querySelector(".user-forum-content"); 55 56 if (textBlock) { 57 const tag = document.createElement("span"); 58 tag.classList.add("badge", "bg-secondary"); 59 tag.innerText = 60 "This content may have been generated using AI. This information may not be factual."; 61 textBlock.appendChild(tag); 62 } 63 } 64 } 65 }); 66 } 67}