UNPKG

nostr-web-components

Version:

collection of web components that provide quick access to basic nostr things

162 lines (161 loc) 4.93 kB
import { verifyEvent } from "@nostr/tools/pure"; import { decodeNostrURI, neventEncode, npubEncode } from "@nostr/tools/nip19"; import { normalizeURL } from "@nostr/tools/utils"; import * as nip10 from "@nostr/tools/nip10"; import { fetchNostrUser, getOutboxRelaysFor, pool } from "./nostr.js"; import { debounce, nostrLink, shorten, splitComma } from "./utils.js"; import { renderText } from "./text.js"; class NostrNote extends HTMLElement { static observedAttributes = ["ref", "event", "relays", "template"]; root; constructor() { super(); this.attachShadow({ mode: "open" }); const { shadowRoot } = this; this.root = document.createElement("div"); shadowRoot.appendChild(this.root); } connectedCallback() { setTimeout(() => { let template = this.getAttribute("template") ? document.getElementById(this.getAttribute("template")) : null; if (template) { this.root.appendChild(template.content.cloneNode(true)); } else { this.root.innerHTML = ` <div part="container"> <header part="header"> <a part="author-link"> <span part="author-name"></span> <span part="author-npub-short"></span> </a> <a part="parent-link" style="display: none"> <span part="parent">parent</span> </a> <a part="link"> <time part="date"></time> </a> </header> <div part="content"></div> </div> `; } this.set(); }, 1); } *queryPart(name) { let slotted = this.querySelectorAll(`[part="${name}"]`); for (let i = 0; i < slotted.length; i++) { yield slotted[i]; } let templated = this.root.querySelectorAll(`[part="${name}"]`); for (let i = 0; i < templated.length; i++) { yield templated[i]; } } attributeChangedCallback() { this.set(); } set = debounce(async () => { var evt = null; let eventj = this.getAttribute("event"); if (eventj) { evt = JSON.parse(eventj); if (evt) { if (!verifyEvent(evt)) { return; } } } if (!evt) { let ref = this.getAttribute("ref"); if (ref) { let { type, data } = decodeNostrURI(ref); if (type !== "nevent") { return; } let d = data; let relays = (d.relays || []).concat(splitComma(this.getAttribute("relays")).map(normalizeURL)); let filter = { ids: [d.id] }; if (d.author && relays.length === 0) relays = await getOutboxRelaysFor(d.author); evt = await pool.get(relays, filter); if (!evt && d.author) { relays = await getOutboxRelaysFor(d.author); evt = await pool.get(relays, filter); } } } if (!evt) { return; } let npub = npubEncode(evt.pubkey); for (let el of this.queryPart("author-link")) { el.href = nostrLink(npub); el.target = "_blank"; } for (let el of this.queryPart("author-npub")) { el.textContent = npub; } var nu = null; for (let el of this.queryPart("author-name")) { if (!nu) { nu = await fetchNostrUser(evt.pubkey, []); } el.textContent = nu.shortName; } for (let el of this.queryPart("author-npub-short")) { el.textContent = shorten(npub); } let thread = null; for (let el of this.queryPart("parent-link")) { if (!thread) thread = nip10.parse(evt); if (thread.reply) { el.href = nostrLink(neventEncode(thread.reply)); el.target = "_blank"; el.style.display = ""; } else { el.remove(); } } for (let el of this.queryPart("root-link")) { if (!thread) thread = nip10.parse(evt); if (thread.root) { el.href = nostrLink(neventEncode(thread.root)); el.target = "_blank"; } else { el.remove(); } } for (let el of this.queryPart("link")) { el.href = nostrLink( neventEncode({ id: evt.id, relays: Array.from(pool.seenOn.get(evt.id) || []).slice(0, 3).map((r) => r.url), author: evt.pubkey }) ); el.target = "_blank"; } for (let el of this.queryPart("date")) { let date = new Date(evt.created_at * 1e3); el.textContent = date.toLocaleString(); if (el.tagName === "TIME") { el.setAttribute("time", date.toISOString().substring(0, 23)); } } let contentWrapper = null; for (let el of this.queryPart("content")) { if (!contentWrapper) { contentWrapper = document.createElement("div"); el.appendChild(contentWrapper); } renderText(contentWrapper, evt.content); } }, 200); } window.customElements.define("nostr-note", NostrNote); export { NostrNote as default };