the home site for me: also iteration 3 or 4 of my site
at main 1.7 kB view raw
1document.addEventListener("DOMContentLoaded", () => { 2 const content = document.querySelector("main"); 3 if (!content) return; 4 5 const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, { 6 acceptNode: (node) => { 7 // Skip code blocks, pre tags, and script/style tags 8 let parent = node.parentElement; 9 while (parent) { 10 const tag = parent.tagName.toLowerCase(); 11 if ( 12 tag === "code" || 13 tag === "pre" || 14 tag === "script" || 15 tag === "style" 16 ) { 17 return NodeFilter.FILTER_REJECT; 18 } 19 parent = parent.parentElement; 20 } 21 return NodeFilter.FILTER_ACCEPT; 22 }, 23 }); 24 25 const nodesToReplace = []; 26 while (walker.nextNode()) { 27 const node = walker.currentNode; 28 if (/:[\w-]+:/.test(node.textContent)) { 29 nodesToReplace.push(node); 30 } 31 } 32 33 nodesToReplace.forEach((node) => { 34 const frag = document.createDocumentFragment(); 35 const parts = node.textContent.split(/(:[\w-]+:)/); 36 37 parts.forEach((part) => { 38 if (/^:[\w-]+:$/.test(part)) { 39 const name = part.slice(1, -1); 40 41 const span = document.createElement("span"); 42 span.className = "emoji-inline--wrapper"; 43 44 const img = document.createElement("img"); 45 img.src = `https://cachet.dunkirk.sh/emojis/${name}/r`; 46 img.alt = part; 47 img.className = "emoji-inline"; 48 img.loading = "lazy"; 49 img.setAttribute("aria-label", `${name} emoji`); 50 51 // Fallback: if image fails to load, show original text 52 img.onerror = () => { 53 span.replaceWith(document.createTextNode(part)); 54 }; 55 56 span.appendChild(img); 57 frag.appendChild(span); 58 } else if (part) { 59 frag.appendChild(document.createTextNode(part)); 60 } 61 }); 62 63 node.replaceWith(frag); 64 }); 65});