-
Notifications
You must be signed in to change notification settings - Fork 6
/
og.ts
206 lines (176 loc) · 24.2 KB
/
og.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* Generate the open graph.
* It's highly inspired by the code from https://github.com/yuaanlin/yual.in/blob/main/pages/og_image/%5Bslug%5D.tsx
* The original open source code don't have any license.
* But I have get the approvement to use them here by asking the author https://twitter.com/yuaanlin.
*/
import { openGraphHeight, openGraphWidth } from '@/helpers/images';
import options from '@/options';
import { Canvas, GlobalFonts, type Image, loadImage, type SKRSContext2D } from '@napi-rs/canvas';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
const darkLogo = `<svg width="160px" height="160px" viewBox="0 0 300 300">
<g id="logo-dark" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(9, 16)">
<path d="M94.5479774,134.486962 C99.2907157,133.547617 103.46066,133.627395 107.053294,134.772127 C112.966407,136.656241 115.468525,138.552508 118.527601,142.942864 C120.544778,145.837896 122.197824,150.954965 123.547977,158.269051 C120.480628,159.074879 117.922174,159.051421 115.898234,158.066848 C112.281243,156.307314 108.930013,153.854322 104.030874,148.36204 C100.920908,144.875547 97.7620867,140.249025 94.5479774,134.486962 Z" id="font1-dot" fill="#E87777"></path>
<path d="M46.8422869,43.5778113 L57.1443602,56.2730781 C56.7735605,56.7561572 56.4130622,57.2126612 56.0629838,57.65605 C53.9299254,60.3576629 52.1719261,62.6165475 50.7441559,66.9195388 C50.4502647,67.8052636 50.1677524,68.619931 49.8923919,69.4140528 C49.8314037,69.5899391 49.7724657,69.7599129 49.7128765,69.9321459 L49.4613482,70.662537 L49.2935232,71.1557917 C47.9745439,75.1396843 46.9306321,78.9136477 45.656322,86.4265524 C45.5923165,86.803907 45.5308802,87.1721303 45.4724886,87.5306837 L45.2906471,88.64728 L46.4211204,88.6906833 C46.7672343,88.703972 47.114133,88.7250069 47.4615106,88.7540528 C52.0299366,89.1360406 56.2866289,90.8682914 59.6487574,93.2539327 C63.1178814,95.7154941 65.6686718,98.8706462 66.4517701,101.981914 C68.60611,110.541158 66.0929237,126.783437 64.8127236,135.185752 C64.5866135,136.670182 64.4272962,137.716618 64.3109454,138.547528 C64.2110444,139.260964 64.0963334,140.121689 63.9669251,141.092859 C63.5964104,143.873461 63.1062925,147.552582 62.4974582,151.2603 L62.3501742,152.143769 C62.3063655,152.402519 62.2619748,152.661094 62.2178889,152.914142 L62.0804882,153.690928 C62.0374659,153.930444 61.9945544,154.170039 61.9516883,154.409322 L61.8231614,155.125846 C60.9449348,160.010357 60.0584182,164.599705 58.601916,165.530233 C57.805445,166.039081 57.006599,166.319837 56.1912629,166.319837 C55.6983618,166.319837 55.2058376,166.218051 54.7107569,166.026725 L56.5363189,132.813886 L56.5363189,117.952805 C56.5363189,114.562057 55.0807514,109.453547 52.7326075,105.554166 C50.565461,101.955353 47.6610156,99.5848491 44.6855326,99.494663 C44.0984373,99.4768683 43.5116237,99.5447372 42.930147,99.691674 L42.6597517,101.122219 C42.2390935,103.347296 41.8463033,105.420982 41.4790073,107.360075 C38.7314734,121.865335 37.4066585,128.866917 36.514877,135.348104 L36.4075675,136.141324 L36.2550999,137.317585 C35.7432607,141.37236 35.3633024,145.499053 34.8715413,151.430142 L34.7754348,152.594528 C34.6778039,153.782228 34.5754009,155.041283 34.4664618,156.384181 C32.6370807,178.935067 32.6465327,193.41116 34.4758443,207.817687 C35.1130431,209.059087 35.4505578,209.4473 35.8461893,209.900621 C36.2628642,210.378055 36.7485755,210.934581 37.2492196,211.502852 L37.761254,212.081997 C38.7419113,213.186811 39.7007875,214.234846 40.2442178,214.749187 C57.1310783,230.732128 75.7119052,242.824647 105.765401,247.408667 C109.294776,247.946998 115.268279,248.495676 121.400226,248.890169 L122.660606,248.968948 L123.167339,248.999323 L124.173781,249.057433 C128.498158,249.300705 132.7267,249.451989 136.06598,249.461499 L136.820436,249.461154 C138.665307,249.453887 140.193882,249.398156 141.253804,249.284403 C158.756452,247.405975 178.012994,240.001867 190.196691,231.670191 L197.337908,245.093068 C181.039287,261.625357 151.989795,268.373466 127.523858,266.785601 C92.0463247,264.483072 59.2083357,249.636224 35.737857,225.385271 C13.7492289,202.665446 0,171.691228 0,135.084268 C0,95.9047997 4.92480232,78.9292586 16.5817116,61.5698853 L21.6734002,67.1219286 C22.224218,70.7987853 22.0831216,74.6092097 21.8833807,78.4096352 L21.7935543,80.068187 C21.6331516,82.9993195 21.4826699,85.9161104 21.5886642,88.7610078 L35.1115099,88.7610078 L35.4226052,87.0934405 C36.910092,79.119959 37.7288197,74.7309457 38.3192627,71.7947151 C38.6839117,69.9974911 38.9181738,68.9279254 39.1538244,67.9399317 L39.4405339,66.775326 C39.7212508,65.6782577 39.9575194,64.7967777 40.2489296,63.7094853 C41.5463253,58.868719 44.3586413,49.7909628 46.8422869,43.5778113 Z M33.4110834,99.2447984 C32.9875317,99.2197029 32.5537361,99.2253734 32.1108175,99.2620712 C31.510935,99.3117743 30.9369263,99.4148625 30.3913414,99.5700791 C25.0958359,101.076628 20.0066053,108.547117 16.272319,119.472516 C16.0174749,120.218113 15.7824956,120.88259 15.5482645,121.544999 L15.4289242,121.882749 C14.9704194,123.182325 14.4903225,124.576387 13.6539215,127.394135 C12.5972078,131.724203 11.9030411,138.422974 10.2648489,160.194842 C12.386381,169.475376 15.5860883,178.386831 20.1072374,187.207176 C21.5388579,190.000136 23.3581345,193.292493 25.1007851,196.220048 C25.8298233,197.444791 26.6085805,198.711777 27.3976596,199.960927 C28.1550483,201.15991 28.9313605,202.357364 29.6935857,203.499008 C29.5337319,202.098916 29.3818575,200.706731 29.2377218,199.323244 C29.0890396,197.896117 28.9465076,196.458236 28.8106055,195.010174 C27.142633,177.237618 26.7411971,160.786976 27.6100462,145.658204 C28.4790972,130.525914 30.2433482,115.92831 32.9037595,101.865512 C32.9930459,101.393549 33.083492,100.921394 33.1750978,100.449046 C33.2530331,100.047187 33.331695,99.6457716 33.4110834,99.2447984 Z M89.4808642,58.6801565 C92.0068614,60.3843231 94.7646457,62.2699999 97.7542322,64.3371648 C98.0082141,64.512782 98.2627902,64.6879201 98.5191904,64.8635207 L99.0239121,65.2081815 C101.346591,66.789757 103.575234,68.2464848 104.913699,69.1125503 L104.645529,70.5022078 L99.0735581,92.9668955 C107.177099,82.6114474 114.957818,77.4411893 122.619933,78.2505728 C123.659042,78.3603385 124.689583,78.4765651 125.704588,78.6202666 C126.032424,78.6666807 126.363407,78.712543 126.696954,78.7587574 C127.472499,78.8662125 128.254562,78.9745299 129.035845,79.0953064 L129.55599,79.1776545 C133.416424,79.8043464 137.445859,80.7765026 140.53886,83.8456905 C142.876704,86.1655353 144.634788,89.6681904 145.487457,94.9712293 C146.593454,101.849804 144.235271,113.304222 141.647049,126.076635 L141.534571,126.63173 C141.124865,128.653954 140.7099,130.706676 140.300599,132.779026 L140.028856,134.162543 C136.378889,152.855625 133.478955,172.801947 139.065486,185.579446 C142.741515,193.98725 145.865395,198.847806 148.446217,201.634068 C150.269872,203.60289 151.887994,204.619399 153.276765,205.141938 C155.503681,205.979836 157.247306,205.618131 158.574524,205.303093 C158.881949,205.228586 159.056948,205.170695 159.212486,205.170695 C160.681127,205.170695 163.524778,204.324138 167.729101,202.486963 C168.144678,207.413204 167.853549,211.559155 166.807717,214.918397 C166.490764,215.93646 166.402402,216.521637 165.756928,216.867816 C163.472619,218.09293 160.306731,217.452113 157.278843,216.690243 C152.044493,215.379504 144.939023,213.632045 138.897651,206.294504 C138.304468,205.574054 137.734642,204.888089 137.186589,204.228344 C131.79243,197.734936 128.584983,193.895563 125.971834,184.25501 C124.142417,177.505838 123.524386,172.576467 123.497998,164.345985 L123.497286,163.50831 C123.504175,158.688115 123.6948,152.764096 123.960373,144.828458 C124.418593,131.136286 126.448981,122.108357 127.95961,115.386576 C128.977339,110.858026 129.748333,107.328344 129.748333,104.145054 C129.748333,102.897969 129.91503,101.152569 130.088723,99.3175902 L130.149154,98.6785927 C130.379001,96.2395414 130.591136,93.7302671 130.508028,91.9489684 C130.467268,91.0753466 130.350362,90.3437209 130.173932,89.8038461 C129.805841,88.6774852 129.150822,88.1197233 128.495809,87.8557942 C126.138427,86.9059184 122.674207,87.6321829 118.991273,89.5849052 C114.720749,91.8491721 110.187542,95.5551461 107.434711,98.3185491 C100.842602,104.935973 99.7358106,106.580141 96.9290224,120.905406 C95.1829229,129.817136 93.1830672,156.132114 90.9546315,199.846258 C87.7558456,197.811765 85.423412,195.374821 83.9994149,192.497341 C81.1302113,186.699524 80.1373069,184.598991 78.579987,174.323917 C77.3820022,166.419708 78.014172,155.594277 78.3840357,149.179652 C78.510286,146.989852 78.60257,145.354355 78.60257,144.421556 C78.60257,140.648774 79.211373,130.740662 80.9674434,116.227783 C81.804359,109.311174 82.2813491,105.378398 82.8584727,101.608456 L82.9838112,100.802183 C83.5990451,96.9045868 84.3576676,92.9603216 85.7689204,85.832392 C87.4981236,77.0985643 88.7355384,68.0467944 89.4808642,58.6801565 Z" id="Down-circle-and-font1" fill="#FFFFFF"></path>
<path d="M125.96931,0 C165.244145,0 199.188759,18.6967659 222.566877,46.7852627 C242.044483,70.1873477 255.489726,99.1018141 256.986198,132.847566 C257.617886,147.092255 253.475262,164.752089 249.778592,178.724344 L241.782581,160.287368 C242.142102,159.030178 242.624586,157.42267 243.165601,155.619938 C243.757109,153.648959 244.40736,151.47963 245.046597,149.274558 L245.36469,148.170767 C246.750719,143.330945 248.015661,138.476921 248.372968,135.54866 C249.191574,128.839897 250.276891,109.397269 235.51671,78.7751477 C229.036129,65.330249 212.314365,47.0048462 198.630472,36.4489395 C184.941164,25.8888558 158.303936,18.5677961 131.15276,17.4481574 C105.814941,16.4032964 80.5800412,22.2630952 60.8430882,34.8694163 L56.8577885,21.1396695 C76.8094612,7.46418563 100.610421,0 125.96931,0 Z" id="Upper-circle" fill="#FFFFFF"></path>
<path d="M186.992625,127.949897 C192.185797,128.776084 196.740749,130.94293 200.085937,134.288118 C203.244467,137.446649 205.314771,141.65394 205.834511,146.739889 C206.384415,152.348905 204.936064,157.466847 202.146389,161.810588 C199.064207,166.609784 194.352759,170.465378 188.886854,173.016134 C186.790972,174.030354 184.17215,175.484367 182.282377,174.690964 C181.93939,174.521434 181.676586,174.298397 181.495225,174.036154 C181.301426,173.755924 181.20287,173.434686 181.183291,173.10673 C181.137511,172.339912 181.506314,171.539641 182.153845,171.039222 C183.468941,170.042294 184.824211,169.13691 186.16858,168.238124 C189.99904,165.677246 193.725348,163.152543 196.321816,158.925735 C199.140385,154.057975 199.551295,147.599676 196.920345,142.50754 C194.849421,138.451981 190.824509,136.579032 186.488388,135.971975 C186.089287,135.916101 185.689776,135.871263 185.291244,135.83899 C185.317716,136.232667 185.337391,136.618847 185.350326,136.996544 C185.573874,143.52416 183.96246,152.717552 179.867892,159.513863 C176.918756,164.408946 172.662059,168.072684 166.78035,168.363538 C163.750107,168.543859 161.062809,167.582154 158.987636,165.850722 C156.807138,164.031411 155.303845,161.371002 154.77513,158.312003 C153.230699,150.357067 155.614437,141.572966 161.076979,135.648701 C167.576646,128.762149 177.79698,126.481685 186.992625,127.949897 Z M180.383135,135.633276 C179.968245,135.653552 179.549932,135.684957 179.129408,135.727363 C174.040881,136.240492 169.591248,138.267306 166.39797,141.415608 C163.286957,144.482803 161.356895,148.615929 161.190324,153.488149 C161.138763,155.394962 161.72196,157.715934 162.997962,159.220474 C163.574847,159.900683 164.288243,160.422401 165.136865,160.706532 C165.893594,160.959895 166.763196,161.027651 167.770001,160.817758 C170.485546,160.20457 172.564408,157.647204 174.066709,155.349566 C177.587926,149.863086 179.320045,143.243049 180.219942,136.861961 C180.277448,136.454185 180.331959,136.044532 180.383135,135.633276 Z" id="font2" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M211.943573,193.818182 C212.16928,192.606061 211.717867,192 210.589333,192 L203.411857,192 C202.193041,192 201.786768,192.656566 202.102758,193.919192 C202.599313,195.737374 203.095868,197.858586 203.637564,200.282828 C203.863271,201.444444 204.540391,202 205.578642,202 L208.151699,202 C209.189951,202 209.912212,201.444444 210.228202,200.383838 C210.905322,198.262626 211.447018,196.090909 211.943573,193.818182 Z M202.085158,224.116095 C201.530414,224.07124 201.114355,224.205805 200.883212,224.474934 C199.819951,225.506596 199.172749,226 198.849148,226 L198.664234,225.955145 C197.554745,226 197,225.461741 197,224.430079 L197,210.525066 C197,209.493404 197.554745,209 198.618005,209 L214.428224,209 C215.491484,209 216,209.538259 216,210.569921 L216,224.430079 C216,225.461741 215.445255,226 214.381995,226 L214.289538,225.955145 C213.781022,225.91029 213.364964,225.82058 213.087591,225.596306 C211.839416,224.609499 211.145985,224.116095 211.007299,224.116095 L202.085158,224.116095 Z M235.413994,208.657957 C236.48688,210.695962 237,212.826603 237,215.0962 C237,217.551069 236.393586,219.357482 235.227405,220.515439 C234.014577,221.673397 232.148688,222.229216 229.676385,222.229216 L228.370262,222.229216 C227.344023,222.229216 226.737609,221.766033 226.504373,220.793349 C226.271137,219.68171 226.784257,219.125891 227.950437,219.125891 L228.090379,219.125891 C230.142857,219.125891 231.542274,218.847981 232.335277,218.245843 C233.12828,217.643705 233.501458,216.578385 233.501458,215.049881 C233.501458,211.390736 231.728863,207.916865 228.230321,204.628266 C227.437318,203.840855 227.297376,203.007126 227.810496,202.127078 C229.489796,199.209026 231.029155,196.013064 232.381924,192.631829 C232.848397,191.473872 232.475219,190.871734 231.215743,190.871734 L226.037901,190.871734 C224.965015,190.871734 224.405248,191.381235 224.405248,192.446556 L224.405248,225.425178 C224.405248,226.490499 223.845481,227 222.772595,227 L222.6793,226.953682 C221.559767,227 221,226.444181 221,225.332542 L221,189.62114 C221,188.555819 221.559767,188 222.632653,188 L235.040816,188 C236.020408,188 236.533528,188.416865 236.673469,189.250594 C236.766764,190.130641 236.580175,191.149644 236.113703,192.400238 C234.854227,195.688836 233.408163,198.83848 231.728863,201.849169 C231.215743,202.775534 231.402332,203.609264 232.195335,204.350356 C233.548105,205.647268 234.620991,207.083135 235.413994,208.657957 Z M198.772083,194.713948 C198.496287,193.770686 197.944695,193.276596 197.071341,193.186761 C196.106054,193.096927 195.600428,192.647754 195.46253,191.884161 C195.324632,190.851064 195.876224,190.312057 197.071341,190.312057 L203.414652,190.312057 C204.47187,190.312057 204.977497,189.77305 204.977497,188.739953 L204.977497,187.572104 C204.977497,186.539007 205.529089,186 206.586307,186 L206.90807,186 C207.965288,186 208.51688,186.539007 208.51688,187.572104 L208.51688,188.739953 C208.51688,189.77305 209.068473,190.312057 210.125691,190.312057 L216.974629,190.312057 C217.939915,190.312057 218.491507,190.761229 218.58344,191.614657 C218.675372,192.55792 218.261677,193.096927 217.296391,193.186761 C216.239172,193.276596 215.595648,193.770686 215.365818,194.713948 C214.860192,196.690307 214.308599,198.576832 213.711041,200.328605 C213.343313,201.496454 213.757007,202.080378 214.99809,202.080378 L217.388323,202.080378 C218.399575,202.080378 218.951168,202.529551 218.997134,203.427896 C219.0431,204.460993 218.537474,205 217.388323,205 L196.61168,205 C195.600428,205 195.048836,204.550827 195.00287,203.652482 C194.956904,202.619385 195.46253,202.080378 196.565714,202.080378 L199.04788,202.080378 C200.19703,202.080378 200.65669,201.541371 200.380894,200.463357 C199.875268,198.44208 199.369642,196.510638 198.772083,194.713948 Z M211.403042,222 C212.452471,222 213,221.43662 213,220.356808 L213,213.643192 C213,212.56338 212.452471,212 211.403042,212 L202.596958,212 C201.547529,212 201,212.56338 201,213.643192 L201,220.356808 C201,221.43662 201.547529,222 202.596958,222 L211.403042,222 Z" id="font3" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M257.384704,207.041597 C256.606856,208.420495 257.018658,209.086169 258.528597,208.991073 C261.685741,208.753332 265.025909,208.468043 268.549099,208.135205 C270.013282,207.992561 270.379328,207.421983 269.601481,206.42347 C267.862764,204.141157 266.764626,203 266.261313,203 L260.999406,203 C259.947024,203 259.169177,203.52303 258.665864,204.521542 C258.254062,205.424958 257.796505,206.233278 257.384704,207.041597 Z M247,193.409091 C247,194.454545 247.559068,195 248.630616,195 L273.369384,195 C274.440932,195 275,194.454545 275,193.409091 L275,192.545455 C275,191.5 274.440932,191 273.369384,191 L248.630616,191 C247.559068,191 247,191.5 247,192.545455 L247,193.409091 Z M243.985144,224.66586 C243.477744,225.815981 242.785835,225.90799 241.909417,225.033898 L241.724908,224.803874 C240.986872,224.113801 240.802363,223.239709 241.217509,222.273608 C243.385489,216.845036 244.446416,210.082324 244.446416,201.939467 L244.446416,189.610169 C244.446416,188.552058 244.999943,188 246.06087,188 L277.56578,188 C278.626707,188 279.180234,188.552058 279.180234,189.610169 L279.180234,195.912833 C279.180234,196.970944 278.672834,197.476998 277.611907,197.476998 L249.520413,197.476998 C248.459487,197.476998 247.90596,198.029056 247.90596,199.087167 L247.90596,199.179177 C247.90596,200.237288 248.459487,200.789346 249.520413,200.789346 L278.626707,200.789346 C279.503124,200.789346 280.056651,201.157385 280.195033,201.939467 C280.425669,202.997579 279.872142,203.549637 278.626707,203.549637 L274.198491,203.549637 C272.353401,203.549637 272.076638,204.193705 273.3682,205.527845 C275.259418,207.506053 277.150635,209.484262 278.949597,211.46247 C279.687633,212.290557 279.595379,213.026634 278.718961,213.670702 L278.672834,213.716707 C277.796416,214.31477 277.012253,214.176755 276.320344,213.348668 C275.905199,212.88862 275.490054,212.428571 275.074909,211.968523 C274.336873,211.186441 273.414328,210.818402 272.353401,210.956416 C270.18542,211.186441 268.34033,211.37046 266.910386,211.508475 C265.849459,211.600484 265.295932,212.198547 265.295932,213.256659 L265.295932,214.130751 C265.295932,215.188862 265.849459,215.74092 266.910386,215.74092 L276.689362,215.74092 C277.56578,215.74092 278.07318,216.108959 278.211562,216.845036 C278.442198,217.903148 277.888671,218.455206 276.643235,218.455206 L266.864259,218.455206 C265.803332,218.455206 265.295932,219.007264 265.295932,220.065375 L265.295932,221.583535 C265.295932,222.641646 265.803332,223.193705 266.864259,223.193705 L279.364743,223.193705 C280.333415,223.193705 280.840815,223.561743 280.979196,224.343826 C281.117578,225.447942 280.564051,226 279.364743,226 L247.39856,226 C246.476015,225.953995 245.968615,225.539952 245.830233,224.757869 C245.645724,223.699758 246.153124,223.193705 247.39856,223.193705 L260.175808,223.193705 C261.236734,223.193705 261.790261,222.641646 261.790261,221.583535 L261.790261,220.065375 C261.790261,219.007264 261.236734,218.455206 260.175808,218.455206 L250.396831,218.455206 C249.520413,218.455206 249.013014,218.087167 248.874632,217.35109 C248.643996,216.292978 249.197523,215.74092 250.442958,215.74092 L260.221935,215.74092 C261.282862,215.74092 261.790261,215.188862 261.790261,214.130751 L261.790261,213.532688 C261.790261,212.474576 261.236734,211.968523 260.175808,212.014528 C256.762391,212.244552 253.579611,212.428571 250.627467,212.520581 C249.75105,212.566586 249.197523,212.198547 248.966886,211.416465 C248.73625,210.358354 249.24365,209.806295 250.489085,209.760291 C250.350704,209.760291 250.535213,209.760291 251.042612,209.714286 C252.195794,209.668281 253.026084,209.208232 253.533484,208.288136 C254.087011,207.368039 254.640538,206.401937 255.194065,205.389831 C255.885974,204.1477 255.516956,203.549637 254.133138,203.549637 L249.520413,203.549637 C248.459487,203.549637 247.952087,204.193705 247.90596,205.48184 C247.767578,212.88862 246.429888,219.283293 243.985144,224.66586 Z" id="font4" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</svg>`;
const getStringWidth = (text: string, fontSize: number) => {
let result = 0;
for (let idx = 0; idx < text.length; idx++) {
if (text.charCodeAt(idx) > 255) {
result += fontSize;
} else {
result += fontSize * 0.5;
}
}
return result;
};
// Print text on SKRSContext with wrapping
const printAt = (
context: SKRSContext2D,
text: string,
x: number,
y: number,
lineHeight: number,
fitWidth: number,
fontSize: number,
) => {
// Avoid invalid fitWidth.
const width = fitWidth || 0;
if (width <= 0) {
context.fillText(text, x, y);
return;
}
for (let idx = 1; idx <= text.length; idx++) {
const str = text.substring(0, idx);
if (getStringWidth(str, fontSize) > width) {
context.fillText(text.substring(0, idx - 1), x, y);
printAt(context, text.substring(idx - 1), x, y + lineHeight, lineHeight, width, fontSize);
return;
}
}
context.fillText(text, x, y);
};
// Modified snippet from https://stackoverflow.com/questions/21961839/simulation-background-size-cover-in-canvas
const drawImageProp = (
ctx: SKRSContext2D,
img: Image,
x: number,
y: number,
w: number,
h: number,
offsetX: number,
offsetY: number,
) => {
// keep bounds [0.0, 1.0]
let ox = offsetX;
if (offsetX < 0) ox = 0;
if (offsetX > 1) ox = 1;
let oy = offsetY;
if (offsetY < 0) oy = 0;
if (offsetY > 1) oy = 1;
const iw = img.width;
const ih = img.height;
const r = Math.min(w / iw, h / ih);
// new prop.width
let nw = iw * r;
// new prop.height
let nh = ih * r;
let ar = 1;
// decide which gap to fill
if (nw < w) ar = w / nw;
if (Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh; // updated
nw *= ar;
nh *= ar;
// calc source rectangle
let cw = iw / (nw / w);
let ch = ih / (nh / h);
let cx = (iw - cw) * ox;
let cy = (ih - ch) * oy;
// make sure source rectangle is valid
if (cx < 0) cx = 0;
if (cy < 0) cy = 0;
if (cw > iw) cw = iw;
if (ch > ih) ch = ih;
// fill image in dest. rectangle
ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
};
const fetchCover = async (cover: string): Promise<Buffer> => {
if (cover.startsWith(options.assetsPrefix())) {
const coverPath = join(process.cwd(), 'public', cover.substring(options.assetsPrefix().length));
return await readFile(coverPath);
}
if (cover.startsWith('http')) {
return Buffer.from(await (await fetch(cover)).arrayBuffer());
}
const coverPath = join(process.cwd(), 'public', cover);
return await readFile(coverPath);
};
export interface OpenGraphProps {
title: string;
summary: string;
cover: string;
}
export const defaultOpenGraph = async (): Promise<Buffer> => {
return await fetchCover('/images/open-graph.png');
};
// Register the font if it doesn't exist
if (!GlobalFonts.has('OPPOSans')) {
const fontBuffer = await readFile(join(process.cwd(), '/src/assets/styles/opposans/opposans.ttf'));
GlobalFonts.register(fontBuffer, 'OPPOSans');
}
export const drawOpenGraph = async ({ title, summary, cover }: OpenGraphProps): Promise<Buffer> => {
// Fetch the cover image as the background
const coverImage = await loadImage(await fetchCover(cover));
// Generate the logo image
const logoImage = await loadImage(Buffer.from(darkLogo, 'utf-8'));
// Mark sure the summary length is small enough to fit in
const description = `${summary
.replace(/<[^>]+>/g, '')
.slice(0, 80)
.trim()} ...`;
// Start drawing the open graph
const canvas = new Canvas(openGraphWidth, openGraphHeight);
const ctx = canvas.getContext('2d');
drawImageProp(ctx, coverImage, 0, 0, openGraphWidth, openGraphHeight, 0.5, 0.5);
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.fillRect(0, 0, openGraphWidth, openGraphHeight);
ctx.save();
// Add website title
ctx.fillStyle = '#e0c2bb';
ctx.font = '800 64px OPPOSans';
printAt(ctx, options.title, 96, 180, 96, openGraphWidth, 64);
// Add website logo
ctx.drawImage(logoImage, 940, 120, 160, 160);
// Add article title
ctx.fillStyle = '#fff';
ctx.font = '800 48px OPPOSans';
printAt(ctx, title, 96, openGraphHeight / 2 - 64, 96, openGraphWidth - 192, 64);
// Add article summary
ctx.font = '800 36px OPPOSans';
ctx.fillStyle = 'rgba(255,255,255,0.5)';
printAt(ctx, description, 96, openGraphHeight - 200, 48, openGraphWidth - 192, 36);
ctx.restore();
const encodedImage = await canvas.encode('png');
return await compressImage(encodedImage);
};
const compressImage = async (buf: Buffer): Promise<Buffer> => {
const { default: sharp } = await import('sharp');
return await sharp(buf)
.png({
compressionLevel: 9,
adaptiveFiltering: true,
force: true,
palette: true,
quality: 75,
progressive: true,
})
.toBuffer();
};