@@ -170,3 +170,120 @@ export const generateOGImage = async (data: OGImageData): Promise<Buffer> => {
170170 const svg = await buildSVG ( data , font ) ;
171171 return sharp ( Buffer . from ( svg ) ) . png ( ) . toBuffer ( ) ;
172172} ;
173+
174+ export type IndexOGImageData = {
175+ siteTitle : string ;
176+ username : string ;
177+ language : Language ;
178+ reportCount : number ;
179+ } ;
180+
181+ const buildIndexSVG = async (
182+ data : IndexOGImageData ,
183+ font : ArrayBuffer ,
184+ ) : Promise < string > => {
185+ const element = {
186+ type : "div" ,
187+ props : {
188+ style : {
189+ display : "flex" ,
190+ flexDirection : "column" ,
191+ justifyContent : "space-between" ,
192+ width : "100%" ,
193+ height : "100%" ,
194+ padding : "80px 90px" ,
195+ background : "linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 100%)" ,
196+ color : "#e0e0e0" ,
197+ fontFamily : "OGFont" ,
198+ } ,
199+ children : [
200+ {
201+ type : "div" ,
202+ props : {
203+ style : { display : "flex" , flexDirection : "column" , gap : "24px" } ,
204+ children : [
205+ {
206+ type : "div" ,
207+ props : {
208+ style : {
209+ fontSize : "96px" ,
210+ fontWeight : 600 ,
211+ lineHeight : 1.1 ,
212+ letterSpacing : "-0.03em" ,
213+ color : "#ffffff" ,
214+ } ,
215+ children : data . siteTitle . replace ( / \n / g, " " ) ,
216+ } ,
217+ } ,
218+ {
219+ type : "div" ,
220+ props : {
221+ style : {
222+ fontSize : "40px" ,
223+ color : "rgba(255,255,255,0.5)" ,
224+ } ,
225+ children : `Weekly reports by @${ data . username } ` ,
226+ } ,
227+ } ,
228+ ] ,
229+ } ,
230+ } ,
231+ {
232+ type : "div" ,
233+ props : {
234+ style : {
235+ display : "flex" ,
236+ justifyContent : "space-between" ,
237+ alignItems : "flex-end" ,
238+ } ,
239+ children : [
240+ {
241+ type : "div" ,
242+ props : {
243+ style : { display : "flex" , gap : "8px" , alignItems : "baseline" } ,
244+ children : [
245+ {
246+ type : "span" ,
247+ props : {
248+ style : { color : "#39d353" , fontWeight : 600 , fontSize : "36px" } ,
249+ children : String ( data . reportCount ) ,
250+ } ,
251+ } ,
252+ {
253+ type : "span" ,
254+ props : {
255+ style : { color : "rgba(255,255,255,0.4)" , fontSize : "30px" } ,
256+ children : data . reportCount === 1 ? "report" : "reports" ,
257+ } ,
258+ } ,
259+ ] ,
260+ } ,
261+ } ,
262+ {
263+ type : "div" ,
264+ props : {
265+ style : { fontSize : "28px" , color : "rgba(255,255,255,0.3)" } ,
266+ children : "github-weekly-reporter" ,
267+ } ,
268+ } ,
269+ ] ,
270+ } ,
271+ } ,
272+ ] ,
273+ } ,
274+ } ;
275+
276+ return satori ( element as Parameters < typeof satori > [ 0 ] , {
277+ width : 1200 ,
278+ height : 630 ,
279+ fonts : [ { name : "OGFont" , data : font , weight : 600 , style : "normal" as const } ] ,
280+ } ) ;
281+ } ;
282+
283+ export const generateIndexOGImage = async (
284+ data : IndexOGImageData ,
285+ ) : Promise < Buffer > => {
286+ const font = loadFont ( data . language ) ;
287+ const svg = await buildIndexSVG ( data , font ) ;
288+ return sharp ( Buffer . from ( svg ) ) . png ( ) . toBuffer ( ) ;
289+ } ;
0 commit comments