Files
archy/packages/app/src/composables/useImageFallback.ts
T

26 lines
1.3 KiB
TypeScript
Raw Normal View History

export function generatePosterFallback(title: string, year?: number): string {
const hue = [...title].reduce((acc, c) => acc + c.charCodeAt(0), 0) % 360
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342 513">
<rect width="342" height="513" fill="hsl(${hue}, 30%, 15%)"/>
<rect x="1" y="1" width="340" height="511" rx="8" fill="none" stroke="hsl(${hue}, 40%, 25%)" stroke-width="2"/>
<text x="171" y="230" text-anchor="middle" fill="hsl(${hue}, 50%, 70%)" font-family="system-ui" font-size="20" font-weight="600">
${escapeXml(title.length > 20 ? title.slice(0, 18) + '…' : title)}
</text>
${year ? `<text x="171" y="260" text-anchor="middle" fill="hsl(${hue}, 30%, 50%)" font-family="system-ui" font-size="14">${year}</text>` : ''}
<text x="171" y="290" text-anchor="middle" fill="hsl(${hue}, 20%, 35%)" font-size="40">🎬</text>
</svg>`
return `data:image/svg+xml,${encodeURIComponent(svg)}`
}
function escapeXml(s: string): string {
return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
}
export function handleImgError(e: Event, title: string, year?: number) {
const img = e.target as HTMLImageElement
if (!img.dataset.fallback) {
img.dataset.fallback = '1'
img.src = generatePosterFallback(title, year)
}
}