@@ -90,8 +90,8 @@ function generateCard(array $stats, array $params = null): string
90
90
$ theme = getRequestedTheme ($ params ?? $ _REQUEST );
91
91
92
92
// get date format
93
- $ dateFormat = isset (($ params ?? $ _REQUEST )["date_format " ])
94
- ? ($ params ?? $ _REQUEST )["date_format " ]
93
+ $ dateFormat = isset (($ params ?? $ _REQUEST )["date_format " ])
94
+ ? ($ params ?? $ _REQUEST )["date_format " ]
95
95
: "M j[, Y] " ;
96
96
97
97
// total contributions
@@ -117,8 +117,7 @@ function generateCard(array $stats, array $params = null): string
117
117
$ longestStreakRange .= " - " . $ longestStreakEnd ;
118
118
}
119
119
120
- return "
121
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='isolation:isolate' viewBox='0 0 495 195' width='495px' height='195px'>
120
+ return "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='isolation:isolate' viewBox='0 0 495 195' width='495px' height='195px'>
122
121
<style>
123
122
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
124
123
@keyframes currstreak {
@@ -139,7 +138,7 @@ function generateCard(array $stats, array $params = null): string
139
138
<g clip-path='url(#_clipPath_OZGVUqgkTHHpPTYeqOmK3uLgktRVSwWw)'>
140
139
<g style='isolation:isolate'>
141
140
<path d='M 4.5 0 L 490.5 0 C 492.984 0 495 2.016 495 4.5 L 495 190.5 C 495 192.984 492.984 195 490.5 195 L 4.5 195 C 2.016 195 0 192.984 0 190.5 L 0 4.5 C 0 2.016 2.016 0 4.5 0 Z'
142
- style='stroke: {$ theme ["border " ]}; fill: {$ theme ["background " ]};stroke-miterlimit:10;rx: 4.5;'/>
141
+ style='stroke: {$ theme ["border " ]}; fill: {$ theme ["background " ]};stroke-miterlimit:10;rx: 4.5;'/>
143
142
</g>
144
143
<g style='isolation:isolate'>
145
144
<line x1='330' y1='28' x2='330' y2='170' vector-effect='non-scaling-stroke' stroke-width='1' stroke=' {$ theme ["stroke " ]}' stroke-linejoin='miter' stroke-linecap='square' stroke-miterlimit='3'/>
@@ -149,23 +148,23 @@ function generateCard(array $stats, array $params = null): string
149
148
<!-- Total Contributions Big Number -->
150
149
<g transform='translate(1,48)'>
151
150
<rect width='163' height='50' stroke='none' fill='none'></rect>
152
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["sideNums " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.6s;'>
151
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["sideNums " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.6s;'>
153
152
{$ totalContributions }
154
153
</text>
155
154
</g>
156
155
157
156
<!-- Total Contributions Label -->
158
157
<g transform='translate(1,84)'>
159
158
<rect width='163' height='50' stroke='none' fill='none'></rect>
160
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.7s;'>
159
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.7s;'>
161
160
Total Contributions
162
161
</text>
163
162
</g>
164
163
165
164
<!-- total contributions range -->
166
165
<g transform='translate(1,114)'>
167
166
<rect width='163' height='50' stroke='none' fill='none'></rect>
168
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.8s;'>
167
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 0.8s;'>
169
168
{$ totalContributionsRange }
170
169
</text>
171
170
</g>
@@ -174,70 +173,65 @@ function generateCard(array $stats, array $params = null): string
174
173
<!-- Current Streak Big Number -->
175
174
<g transform='translate(166,48)'>
176
175
<rect width='163' height='50' stroke='none' fill='none'></rect>
177
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["currStreakNum " ]};stroke:none;animation: currstreak 0.6s linear forwards;'>
176
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["currStreakNum " ]};stroke:none;animation: currstreak 0.6s linear forwards;'>
178
177
{$ currentStreak }
179
178
</text>
180
179
</g>
181
180
182
181
<!-- Current Streak Label -->
183
182
<g transform='translate(166,108)'>
184
183
<rect width='163' height='50' stroke='none' fill='none'></rect>
185
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:700;font-size:14px;font-style:normal;fill: {$ theme ["currStreakLabel " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 0.9s;'>
184
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:700;font-size:14px;font-style:normal;fill: {$ theme ["currStreakLabel " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 0.9s;'>
186
185
Current Streak
187
186
</text>
188
187
</g>
189
188
190
189
<!-- Current Streak Range -->
191
190
<g transform='translate(166,145)'>
192
191
<rect width='163' height='26' stroke='none' fill='none'></rect>
193
- <text x='81.5' y='13' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 0.9s;'>
192
+ <text x='81.5' y='21' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 0.9s;'>
194
193
{$ currentStreakRange }
195
194
</text>
196
195
</g>
197
196
198
- <!-- mask for background behind fire -->
199
- <defs>
200
- <mask id='cut-off-area'>
201
- <rect x='0' y='0' width='500' height='500' fill='white' />
202
- <ellipse cx='247.5' cy='31' rx='13' ry='18'/>
203
- </mask>
204
- </defs>
205
197
<!-- ring around number -->
206
- <circle cx='247.5' cy='71' r='40' mask='url(#cut-off-area)' style='fill:none;stroke: {$ theme ["ring " ]};stroke-width:5;opacity: 0; animation: fadein 0.5s linear forwards 0.4s;'></circle>
198
+ <circle cx='247.5' cy='71' r='40' style='fill:none;stroke: {$ theme ["ring " ]};stroke-width:5;opacity: 0; animation: fadein 0.5s linear forwards 0.4s;'></circle>
199
+ <ellipse cx='247.5' cy='32' rx='13' ry='18' fill=' {$ theme ["background " ]}' />
207
200
<!-- fire icon -->
208
201
<g style='opacity: 0; animation: fadein 0.5s linear forwards 0.6s;'>
209
202
<path d=' M 235.5 19.5 L 259.5 19.5 L 259.5 43.5 L 235.5 43.5 L 235.5 19.5 Z ' fill='none'/>
210
203
<path d=' M 249 20.17 C 249 20.17 249.74 22.82 249.74 24.97 C 249.74 27.03 248.39 28.7 246.33 28.7 C 244.26 28.7 242.7 27.03 242.7 24.97 L 242.73 24.61 C 240.71 27.01 239.5 30.12 239.5 33.5 C 239.5 37.92 243.08 41.5 247.5 41.5 C 251.92 41.5 255.5 37.92 255.5 33.5 C 255.5 28.11 252.91 23.3 249 20.17 Z M 247.21 38.5 C 245.43 38.5 243.99 37.1 243.99 35.36 C 243.99 33.74 245.04 32.6 246.8 32.24 C 248.57 31.88 250.4 31.03 251.42 29.66 C 251.81 30.95 252.01 32.31 252.01 33.7 C 252.01 36.35 249.86 38.5 247.21 38.5 Z ' fill=' {$ theme ["fire " ]}'/>
211
204
</g>
205
+
212
206
</g>
213
207
<g style='isolation:isolate'>
214
208
<!-- Longest Streak Big Number -->
215
209
<g transform='translate(331,48)'>
216
210
<rect width='163' height='50' stroke='none' fill='none'></rect>
217
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["sideNums " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 1.2s;'>
211
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:700;font-size:28px;font-style:normal;fill: {$ theme ["sideNums " ]};stroke:none; opacity: 0; animation: fadein 0.5s linear forwards 1.2s;'>
218
212
{$ longestStreak }
219
213
</text>
220
214
</g>
221
215
222
216
<!-- Longest Streak Label -->
223
217
<g transform='translate(331,84)'>
224
218
<rect width='163' height='50' stroke='none' fill='none'></rect>
225
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 1.3s;'>
219
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 1.3s;'>
226
220
Longest Streak
227
221
</text>
228
222
</g>
229
223
230
224
<!-- Longest Streak Range -->
231
225
<g transform='translate(331,114)'>
232
226
<rect width='163' height='50' stroke='none' fill='none'></rect>
233
- <text x='81.5' y='25' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 1.4s;'>
227
+ <text x='81.5' y='32' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:12px;font-style:normal;fill: {$ theme ["dates " ]};stroke:none;opacity: 0; animation: fadein 0.5s linear forwards 1.4s;'>
234
228
{$ longestStreakRange }
235
229
</text>
236
230
</g>
237
231
</g>
238
232
</g>
239
233
</svg>
240
- " ;
234
+ " ;
241
235
}
242
236
243
237
/**
@@ -253,8 +247,7 @@ function generateErrorCard(string $message, array $params = null): string
253
247
// get requested theme, use $_REQUEST if no params array specified
254
248
$ theme = getRequestedTheme ($ params ?? $ _REQUEST );
255
249
256
- return "
257
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='isolation:isolate' viewBox='0 0 495 195' width='495px' height='195px'>
250
+ return "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='isolation:isolate' viewBox='0 0 495 195' width='495px' height='195px'>
258
251
<style>
259
252
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
260
253
</style>
@@ -272,7 +265,7 @@ function generateErrorCard(string $message, array $params = null): string
272
265
<!-- Error Label -->
273
266
<g transform='translate(166,108)'>
274
267
<rect width='163' height='50' stroke='none' fill='none'></rect>
275
- <text x='81.5' y='50' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:" Open Sans" , Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none;'>
268
+ <text x='81.5' y='50' dy='0.25em' stroke-width='0' text-anchor='middle' style='font-family:Open Sans, Roboto, system-ui, sans-serif;font-weight:400;font-size:14px;font-style:normal;fill: {$ theme ["sideLabels " ]};stroke:none;'>
276
269
{$ message }
277
270
</text>
278
271
</g>
@@ -294,5 +287,49 @@ function generateErrorCard(string $message, array $params = null): string
294
287
</g>
295
288
</g>
296
289
</svg>
297
- " ;
290
+ " ;
291
+ }
292
+
293
+ /**
294
+ * Displays a card as an SVG image
295
+ *
296
+ * @param string $svg The SVG for the card to display
297
+ */
298
+ function echoAsSvg (string $ svg ): void {
299
+ // set content type to SVG image
300
+ header ("Content-Type: image/svg+xml " );
301
+
302
+ // echo SVG data for streak stats
303
+ echo $ svg ;
304
+ }
305
+
306
+ /**
307
+ * Displays a card as a PNG image
308
+ *
309
+ * @param string $svg The SVG for the card to display
310
+ *
311
+ * @throws ImagickException
312
+ */
313
+ function echoAsPng (string $ svg ): void {
314
+ // remove style and animations
315
+ $ svg = preg_replace ('/(<style>\X*<\/style>)/m ' , '' , $ svg );
316
+ $ svg = preg_replace ('/(opacity: 0;)/m ' , 'opacity: 1; ' , $ svg );
317
+ $ svg = preg_replace ('/(animation: fadein.*?;)/m ' , 'opacity: 1; ' , $ svg );
318
+ $ svg = preg_replace ('/(animation: currentstreak.*?;)/m ' , 'font-size: 28px; ' , $ svg );
319
+
320
+ // create canvas
321
+ $ imagick = new Imagick ();
322
+ $ imagick ->setBackgroundColor (new ImagickPixel ('transparent ' ));
323
+
324
+ // add svg image
325
+ $ imagick ->readImageBlob ($ svg );
326
+ $ imagick ->setImageFormat ('png ' );
327
+
328
+ // echo PNG data
329
+ header ('Content-Type: image/png ' );
330
+ echo $ imagick ->getImageBlob ();
331
+
332
+ // clean up memory
333
+ $ imagick ->clear ();
334
+ $ imagick ->destroy ();
298
335
}
0 commit comments