| 142 | |
| 143 | const assetCache = new Map<string, Asset | undefined>(); |
| 144 | const loadDynamicAsset = ({ emoji }: { emoji?: EmojiType }) => { |
| 145 | const fn = async ( |
| 146 | code: keyof typeof languageFontMap | "emoji", |
| 147 | text: string, |
| 148 | ): Promise<Asset | undefined> => { |
| 149 | if (code === "emoji") { |
| 150 | // It's an emoji, load the image. |
| 151 | return ( |
| 152 | `data:image/svg+xml;base64,` + |
| 153 | btoa(await (await loadEmoji(getIconCode(text), emoji)).text()) |
| 154 | ); |
| 155 | } |
| 156 | |
| 157 | // Try to load from Google Fonts. |
| 158 | if (!languageFontMap[code]) code = "unknown"; |
| 159 | |
| 160 | try { |
| 161 | const data = await loadGoogleFont(languageFontMap[code], text); |
| 162 | |
| 163 | if (data) { |
| 164 | return { |
| 165 | name: `satori_${code}_fallback_${text}`, |
| 166 | data, |
| 167 | weight: 400, |
| 168 | style: "normal", |
| 169 | }; |
| 170 | } |
| 171 | } catch (e) { |
| 172 | console.error("Failed to load dynamic font for", text, ". Error:", e); |
| 173 | } |
| 174 | }; |
| 175 | |
| 176 | return async (...args: Parameters<typeof fn>) => { |
| 177 | const key = JSON.stringify(args); |
| 178 | const cache = assetCache.get(key); |
| 179 | if (cache) return cache; |
| 180 | |
| 181 | const asset = await fn(...args); |
| 182 | assetCache.set(key, asset); |
| 183 | return asset; |
| 184 | }; |
| 185 | }; |
| 186 | |
| 187 | export class ImageResponse extends Response { |
| 188 | constructor(element: ReactElement, options: ImageResponseOptions = {}) { |