1
1
import type { RequestHandler } from '@builder.io/qwik-city' ;
2
- import { Resvg , initWasm } from '@resvg/resvg-wasm' ;
3
- import satori from 'satori' ;
4
-
5
- let wasmPromise : Promise < void > | undefined ;
2
+ import { ImageResponse , html } from 'og-img' ;
6
3
7
4
async function getFontData ( fileName : string ) {
8
5
const resposne = await fetch (
@@ -12,9 +9,10 @@ async function getFontData(fileName: string) {
12
9
}
13
10
14
11
export const onGet : RequestHandler = async ( { send, url } ) => {
15
- // Get title and description from search params
12
+ // Get data from search params
16
13
const title = url . searchParams . get ( 'title' ) ;
17
- const description = url . searchParams . get ( 'description' ) || 'valibot.dev' ;
14
+ const description = url . searchParams . get ( 'description' ) ;
15
+ const path = url . searchParams . get ( 'path' ) ;
18
16
19
17
// Create Lexend 400 font object
20
18
const lexend400 = {
@@ -40,131 +38,87 @@ export const onGet: RequestHandler = async ({ send, url }) => {
40
38
weight : 500 ,
41
39
} as const ;
42
40
43
- // Generate SVG string using Satori
44
- const svg = title
45
- ? // If title is available, return SVG with text
46
- await satori (
47
- {
48
- type : 'div' ,
49
- props : {
50
- tw : 'flex h-full w-full flex-col justify-between bg-gray-900 p-16' ,
51
- style : { fontFamily : 'Lexend' } ,
52
- children : [
53
- {
54
- type : 'div' ,
55
- props : {
56
- tw : 'flex items-center' ,
57
- children : [
58
- {
59
- type : 'img' ,
60
- props : {
61
- tw : 'w-16 h-16' ,
62
- src : `${
63
- import . meta. env . PUBLIC_WEBSITE_URL
64
- } /icon-192px.png`,
65
- } ,
66
- } ,
67
- {
68
- type : 'div' ,
69
- props : {
70
- tw : 'text-4xl font-medium text-slate-300 ml-4' ,
71
- style : { fontFamily : 'Lexend Exa' } ,
72
- children : 'Valibot' ,
73
- } ,
74
- } ,
75
- ] ,
76
- } ,
77
- } ,
78
- {
79
- type : 'div' ,
80
- props : {
81
- tw : 'flex flex-col' ,
82
- children : [
83
- {
84
- type : 'h1' ,
85
- props : {
86
- tw : 'max-w-[80%] text-6xl font-medium leading-normal text-slate-200' ,
87
- style : {
88
- overflow : 'hidden' ,
89
- textOverflow : 'ellipsis' ,
90
- whiteSpace : 'nowrap' ,
91
- } ,
92
- children : title ,
93
- } ,
94
- } ,
95
- {
96
- type : 'p' ,
97
- props : {
98
- tw : 'text-4xl text-slate-400 leading-loose' ,
99
- children :
100
- description . length > 110
101
- ? description . slice ( 0 , 110 ) . trimEnd ( ) + '...'
102
- : description ,
103
- } ,
104
- } ,
105
- ] ,
106
- } ,
107
- } ,
108
- ] ,
109
- } ,
110
- } ,
41
+ // If title is available, return image with text
42
+ if ( title ) {
43
+ send (
44
+ new ImageResponse (
45
+ html `
46
+ < div
47
+ tw ="flex h-full w-full flex-col justify-between bg-gray-900 p-16 "
48
+ style ="font-family: 'Lexend' "
49
+ >
50
+ < div tw ="flex items-center justify-between ">
51
+ < div tw ="flex items-center ">
52
+ < img
53
+ tw ="w-16 h-16 "
54
+ src ="${ import . meta. env . PUBLIC_WEBSITE_URL } /icon-192px.png "
55
+ />
56
+ < div
57
+ tw ="text-4xl font-medium text-slate-300 ml-4 "
58
+ style ="font-family: 'Lexend Exa' "
59
+ >
60
+ Valibot
61
+ </ div >
62
+ </ div >
63
+ < div
64
+ tw ="max-w-[50%] text-4xl text-slate-500 "
65
+ style ="overflow: hidden; text-overflow: ellipsis; white-space: nowrap "
66
+ >
67
+ valibot.dev${ path ? `/` + path : '' }
68
+ </ div >
69
+ </ div >
70
+ < div tw ="flex flex-col ">
71
+ < h1
72
+ tw ="max-w-[80%] text-6xl font-medium leading-normal text-slate-200 "
73
+ style ="overflow: hidden; text-overflow: ellipsis; white-space: nowrap "
74
+ >
75
+ ${ title }
76
+ </ h1 >
77
+ < p
78
+ tw ="text-4xl text-slate-400 leading-loose "
79
+ style ="${ description ? '' : 'display: none' } } "
80
+ >
81
+ ${ description
82
+ ? description . length > 110
83
+ ? description . slice ( 0 , 110 ) . trimEnd ( ) + '...'
84
+ : description
85
+ : '' }
86
+ </ p >
87
+ </ div >
88
+ </ div >
89
+ ` ,
111
90
{
112
91
width : 1200 ,
113
92
height : 630 ,
114
93
fonts : [ lexend400 , lexend500 , lexendExa500 ] ,
115
94
}
116
95
)
117
- : // Otherwise, return SVG with logo
118
- await satori (
119
- {
120
- type : 'div' ,
121
- props : {
122
- tw : 'flex h-full w-full items-center justify-center bg-gray-900' ,
123
- style : { fontFamily : 'Lexend Exa' } ,
124
- children : {
125
- type : 'div' ,
126
- props : {
127
- tw : 'flex items-center' ,
128
- children : [
129
- {
130
- type : 'img' ,
131
- props : {
132
- tw : 'w-36 h-36' ,
133
- src : `${
134
- import . meta. env . PUBLIC_WEBSITE_URL
135
- } /icon-192px.png`,
136
- } ,
137
- } ,
138
- {
139
- type : 'div' ,
140
- props : {
141
- tw : 'text-8xl font-medium text-slate-300 ml-10' ,
142
- children : 'Valibot' ,
143
- } ,
144
- } ,
145
- ] ,
146
- } ,
147
- } ,
148
- } ,
149
- } ,
96
+ ) ;
97
+
98
+ // Otherwise, return image just with logo
99
+ } else {
100
+ send (
101
+ new ImageResponse (
102
+ html `
103
+ < div
104
+ tw ="flex h-full w-full items-center justify-center bg-gray-900 "
105
+ style ="font-family: 'Lexend Exa' "
106
+ >
107
+ < div tw ="flex items-center ">
108
+ < img
109
+ tw ="w-36 h-36 "
110
+ src ="${ import . meta. env . PUBLIC_WEBSITE_URL } /icon-192px.png "
111
+ />
112
+ < div tw ="text-8xl font-medium text-slate-300 ml-10 "> Valibot</ div >
113
+ </ div >
114
+ </ div >
115
+ ` ,
150
116
{
151
117
width : 1200 ,
152
118
height : 630 ,
153
119
fonts : [ lexendExa500 ] ,
154
120
}
155
- ) ;
156
-
157
- // Lazy initialize WebAssembly module
158
- if ( ! wasmPromise ) {
159
- wasmPromise = initWasm (
160
- fetch ( 'https://unpkg.com/@resvg/resvg-wasm/index_bg.wasm' )
121
+ )
161
122
) ;
162
123
}
163
- await wasmPromise ;
164
-
165
- // Convert SVG string to PNG image
166
- const image = new Resvg ( svg ) . render ( ) . asPng ( ) ;
167
-
168
- // Send PNG image as response
169
- send ( new Response ( image , { headers : { 'content-type' : 'image/png' } } ) ) ;
170
124
} ;
0 commit comments