import { proxyUrlFor } from '../media/registry.ts'; import { anchorOf, type Media, type Post, type Segment } from '../types.ts'; import { html, raw, type Raw } from './html.ts'; import { badge, layout, originalUrlBlock } from './layout.ts'; import { linkify } from './text.ts'; function aspect(item: Media): string { return item.width && item.height ? `aspect-ratio: ${item.width} / ${item.height};` : ''; } function renderItem(item: Media, index: number): Raw { const src = proxyUrlFor(item); if (item.kind === 'video') { const poster = item.poster ? proxyUrlFor(item.poster) : undefined; return html`
${item.hls ? html`
Streaming format — plays natively in Safari.
` : ''}
`; } return html`
${item.alt ?? ''}
`; } function renderMedia(media: Media[]): Raw { if (media.length === 0) return html``; const many = media.length > 1; return html`
${many ? html`
1 / ${media.length}
` : ''}
${media.map((item, index) => renderItem(item, index))}
`; } function renderText(segment: Segment, post: Post): Raw { if (!segment.text) return html``; return html`
${linkify(segment.text, post.platform)}
`; } function renderWhen(postedAt: string | undefined): Raw { if (!postedAt) return html``; const date = new Date(postedAt); if (Number.isNaN(date.getTime())) return html``; return html``; } /** * One post in the chain. When there is only one, the wrapper is invisible; * when there are several, each is separated and the one that was actually * linked is marked, since it may not be the first. */ function renderSegment(segment: Segment, post: Post, threaded: boolean): Raw { const above = post.textPosition === 'above'; return html`
${threaded && segment.isAnchor ? html`

the post you followed

` : ''} ${above ? renderText(segment, post) : ''} ${renderMedia(segment.media)} ${above ? '' : renderText(segment, post)}
`; } export function renderPost(post: Post): string { const avatar = post.author.avatar ? proxyUrlFor(post.author.avatar) : undefined; const threaded = post.segments.length > 1; const anchor = anchorOf(post); const body = html`
${badge(post.platform, post.platformLabel)}
${avatar ? html`` : ''}
${post.author.displayName ? html`${post.author.displayName}` : ''} ${post.author.handle}
${post.segments.map((segment) => renderSegment(segment, post, threaded))}
`; const who = post.author.displayName ?? post.author.handle; return layout(`${who} on ${post.platformLabel}`, body); }