11import type { RequestHandler } from './$types' ;
22import { Resvg } from '@cf-wasm/resvg' ;
33
4- let fontCache : Uint8Array | null = null ;
4+ let fontCacheRegular : Uint8Array | null = null ;
5+ let fontCacheBold : Uint8Array | null = null ;
56
6- async function loadFont ( ) : Promise < Uint8Array > {
7- if ( fontCache ) return fontCache ;
7+ async function loadFonts ( ) : Promise < Uint8Array [ ] > {
8+ if ( fontCacheRegular && fontCacheBold ) return [ fontCacheRegular , fontCacheBold ] ;
89
910 const css = await fetch (
1011 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&subset=latin' ,
@@ -16,12 +17,16 @@ async function loadFont(): Promise<Uint8Array> {
1617 }
1718 ) . then ( ( r ) => r . text ( ) ) ;
1819
19- const fontUrl = css . match ( / s r c : u r l \( ( .+ ?) \) f o r m a t \( ' ( o p e n t y p e | t r u e t y p e ) ' \) / ) ?. [ 1 ] ;
20- if ( ! fontUrl ) throw new Error ( 'Could not find font URL ' ) ;
20+ const fontUrls = [ ... css . matchAll ( / s r c : u r l \( ( .+ ?) \) f o r m a t \( ' t r u e t y p e ' \) / g ) ] . map ( ( m ) => m [ 1 ] ) ;
21+ if ( fontUrls . length === 0 ) throw new Error ( 'Could not find font URLs ' ) ;
2122
22- const fontBuffer = await fetch ( fontUrl ) . then ( ( r ) => r . arrayBuffer ( ) ) ;
23- fontCache = new Uint8Array ( fontBuffer ) ;
24- return fontCache ;
23+ const buffers = await Promise . all (
24+ fontUrls . map ( ( url ) => fetch ( url ) . then ( ( r ) => r . arrayBuffer ( ) ) . then ( ( b ) => new Uint8Array ( b ) ) )
25+ ) ;
26+
27+ fontCacheRegular = buffers [ 0 ] ;
28+ fontCacheBold = buffers [ 1 ] || buffers [ 0 ] ;
29+ return buffers ;
2530}
2631
2732function esc ( s : string ) : string {
@@ -158,7 +163,7 @@ export const GET: RequestHandler = async ({ params, platform }) => {
158163 const npm = rawPkgs . filter ( ( p ) => p . type === 'npm' ) ;
159164 const total = rawPkgs . length ;
160165
161- const fontData = await loadFont ( ) ;
166+ const fontBuffers = await loadFonts ( ) ;
162167
163168 const svg = buildSvg (
164169 config . name ,
@@ -174,9 +179,10 @@ export const GET: RequestHandler = async ({ params, platform }) => {
174179 const resvg = await Resvg . async ( svg , {
175180 fitTo : { mode : 'width' as const , value : 1200 } ,
176181 font : {
177- fontBuffers : [ fontData ] ,
182+ fontBuffers,
178183 defaultFontFamily : 'Inter' ,
179184 sansSerifFamily : 'Inter' ,
185+ monospaceFamily : 'Inter' ,
180186 defaultFontSize : 16
181187 }
182188 } ) ;
@@ -186,15 +192,19 @@ export const GET: RequestHandler = async ({ params, platform }) => {
186192 return new Response ( pngBuffer , {
187193 headers : {
188194 'Content-Type' : 'image/png' ,
189- 'Cache-Control' : 'public, max-age=86400, s-maxage=86400'
195+ 'Cache-Control' : 'public, max-age=60' ,
196+ 'X-Font-Count' : String ( fontBuffers . length ) ,
197+ 'X-Font-Size' : String ( fontBuffers [ 0 ] ?. length || 0 ) ,
198+ 'X-Svg-Length' : String ( svg . length )
190199 }
191200 } ) ;
192- } catch {
193- return new Response ( svg , {
194- headers : {
195- 'Content-Type' : 'image/svg+xml' ,
196- 'Cache-Control' : 'public, max-age=86400, s-maxage=86400'
201+ } catch ( e ) {
202+ return new Response (
203+ JSON . stringify ( { error : String ( e ) , stack : ( e as Error ) . stack } ) ,
204+ {
205+ status : 500 ,
206+ headers : { 'Content-Type' : 'application/json' }
197207 }
198- } ) ;
208+ ) ;
199209 }
200210} ;
0 commit comments