1(()=>{2 let g = window, d = document3 if (g.praseodymium) return4 let send = (el, type, detail)=>el.dispatchEvent(new CustomEvent("npr:" + type, {detail, cancelable:1, bubbles:1, composed:1}))5 let hexOf = (s)=>{6 if (/^[0-9a-f]{64}$/.test(s)) return s7 try { let x = neon.decode(s).data; return x.pubkey ?? x } catch {}8 }9 let npub = (pk)=>g.neon ? neon.encode("npub", pk) : pk10 let short = (pk)=>(pk = npub(pk)).slice(0, 10) + "…" + pk.slice(-4)11 // A 5x5 mirrored identicon, colored by the pubkey.12 let face = (pk)=>{13 let h = parseInt(pk.slice(0, 4), 16) % 360, p = ""14 for (let i = 0; i < 15; i++) if (parseInt(pk[i + 4], 16) & 1) p += `M${i % 3} ${i / 3 | 0}h1v1h-1zM${4 - i % 3} ${i / 3 | 0}h1v1h-1z`15 return "data:image/svg+xml," + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5 5"><rect width="5" height="5" fill="hsl(${h},40%,88%)"/><path fill="hsl(${h},45%,45%)" d="${p}"/></svg>`)16 }17 let f = (pk, field, tag, text = "")=>`<${tag} nrn-profile="${pk}" nrn-field="${field}" npr-part="${field}">${text}</${tag}>`18 let kinds = {19 card:(pk)=>`<img npr-avatar="${pk}" npr-part="avatar" alt="">${f(pk, "name", "b", short(pk))}${f(pk, "nip05", "span")}${f(pk, "about", "p")}<button npr-copy="${npub(pk)}" npr-part="copy">${short(pk)}</button>`,20 chip:(pk)=>`<img npr-avatar="${pk}" npr-part="avatar" alt="">${f(pk, "name", "b", short(pk))}`21 }22 let markup = (kind, pk)=>(pk = hexOf(pk)) && kinds[kind]?.(pk)23 let init = (el, kind)=>{24 let pk = hexOf(el.getAttribute("npr-" + kind))25 if (!pk || el.__npr == pk || el.closest("[npr-ignore]")) return26 if (kind == "avatar"){27 el.setAttribute("nrn-field", el.getAttribute("nrn-field") || "picture")28 el.setAttribute("nrn-profile", pk)29 if (!el.getAttribute("src") || el.__npr) el.src = face(pk)30 } else {31 let detail = {kind, pubkey:pk, html:kinds[kind](pk)}32 if (el.firstElementChild && !el.__npr || !send(el, "render", detail)) return33 el.innerHTML = detail.html34 }35 el.__npr = pk36 }37 let process = (n)=>{38 for (let k of ["card", "chip", "avatar"]){39 if (n.matches?.(`[npr-${k}]`)) init(n, k)40 n.querySelectorAll?.(`[npr-${k}]`).forEach((e)=>init(e, k))41 }42 }43 d.addEventListener("click", (evt)=>{44 let el = evt.target.closest?.("[npr-copy]"), detail = {text:el?.getAttribute("npr-copy")}45 if (el && send(el, "copy", detail)) navigator.clipboard.writeText(detail.text).then(()=>{46 el.setAttribute("npr-copied", "")47 clearTimeout(el.__nprT)48 el.__nprT = setTimeout(()=>el.removeAttribute("npr-copied"), g.nprCfg?.copied ?? 1500)49 send(el, "copied", detail)50 }, ()=>{})51 })52 // A picture that fails to load falls back to the identicon.53 d.addEventListener("error", (evt)=>{54 let el = evt.target, pk = el.matches?.("img[npr-avatar]") && hexOf(el.getAttribute("npr-avatar")), fb = pk && face(pk)55 if (fb && el.src != fb) el.src = fb56 }, 1)57 g.praseodymium = {markup, process, face}58 let mo = new MutationObserver((recs)=>recs.forEach((r)=>r.type == "attributes" ? process(r.target) : r.addedNodes.forEach(process)))59 let start = ()=>{60 mo.observe(d.documentElement, {childList:1, subtree:1, attributes:1, attributeFilter:["npr-card", "npr-chip", "npr-avatar"]})61 process(d.body)62 }63 d.readyState == "loading" ? d.addEventListener("DOMContentLoaded", start) : start()64})()