diff options
Diffstat (limited to 'bskyembed/snippet')
-rw-r--r-- | bskyembed/snippet/embed.ts | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/bskyembed/snippet/embed.ts b/bskyembed/snippet/embed.ts new file mode 100644 index 000000000..f2b9b442e --- /dev/null +++ b/bskyembed/snippet/embed.ts @@ -0,0 +1,90 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +interface Window { + bluesky: { + scan: (element?: Pick<Element, 'querySelectorAll'>) => void + } +} + +const EMBED_URL = 'https://embed.bsky.app' + +window.bluesky = window.bluesky || { + scan, +} + +/** + * Listen for messages from the Bluesky embed iframe and adjust the height of + * the iframe accordingly. + */ +window.addEventListener('message', event => { + if (event.origin !== EMBED_URL) { + return + } + + const id = (event.data as {id: string}).id + if (!id) { + return + } + + const embed = document.querySelector<HTMLIFrameElement>( + `[data-bluesky-id="${id}"]`, + ) + + if (!embed) { + return + } + + const height = (event.data as {height: number}).height + if (height) { + embed.style.height = `${height}px` + } +}) + +/** + * Scan the document for all elements with the data-bluesky-aturi attribute, + * and initialize them as Bluesky embeds. + * + * @param element Only scan this specific element @default document @optional + * @returns + */ +function scan(node = document) { + const embeds = node.querySelectorAll('[data-bluesky-uri]') + + for (let i = 0; i < embeds.length; i++) { + const id = String(Math.random()).slice(2) + + const embed = embeds[i] + const aturi = embed.getAttribute('data-bluesky-uri') + + if (!aturi) { + continue + } + + const iframe = document.createElement('iframe') + iframe.setAttribute('data-bluesky-id', id) + iframe.src = `${EMBED_URL}/embed/${aturi.slice('at://'.length)}?id=${id}` + iframe.width = '100%' + iframe.style.border = 'none' + iframe.style.display = 'block' + iframe.style.flexGrow = '1' + iframe.frameBorder = '0' + iframe.scrolling = 'no' + + const container = document.createElement('div') + container.style.maxWidth = '600px' + container.style.width = '100%' + container.style.marginTop = '10px' + container.style.marginBottom = '10px' + container.style.display = 'flex' + container.className = 'bluesky-embed' + + container.appendChild(iframe) + + embed.replaceWith(container) + } +} + +if (['interactive', 'complete'].indexOf(document.readyState) !== -1) { + scan() +} else { + document.addEventListener('DOMContentLoaded', () => scan()) +} |