Skip to content

Commit 76005bf

Browse files
refactor: generate SVG badge script
1 parent 8c90b81 commit 76005bf

File tree

5 files changed

+84
-142
lines changed

5 files changed

+84
-142
lines changed

monkeytype-data/badges.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"icon": "fa-laptop",
77
"color": "white",
88
"customStyle": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
9-
"background": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
109
"iconSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 512\" fill=\"\" width=\"12\" height=\"12\"><path d=\"M128 32C92.7 32 64 60.7 64 96V352h64V96H512V352h64V96c0-35.3-28.7-64-64-64H128zM19.2 384C8.6 384 0 392.6 0 403.2C0 445.6 34.4 480 76.8 480H563.2c42.4 0 76.8-34.4 76.8-76.8c0-10.6-8.6-19.2-19.2-19.2H19.2z\"/></svg>"
1110
},
1211
"2": {
@@ -16,7 +15,6 @@
1615
"icon": "fa-code",
1716
"color": "white",
1817
"customStyle": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
19-
"background": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
2018
"iconSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 512\" fill=\"\" width=\"12\" height=\"12\"><path d=\"M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z\"/></svg>"
2119
},
2220
"3": {
@@ -26,7 +24,6 @@
2624
"icon": "fa-hammer",
2725
"color": "white",
2826
"customStyle": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
29-
"background": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
3027
"iconSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 576 512\" fill=\"\" width=\"12\" height=\"12\"><path d=\"M413.5 237.5c-28.2 4.8-58.2-3.6-80-25.4l-38.1-38.1C280.4 159 272 138.8 272 117.6V105.5L192.3 62c-5.3-2.9-8.6-8.6-8.3-14.7s3.9-11.5 9.5-14l47.2-21C259.1 4.2 279 0 299.2 0h18.1c36.7 0 72 14 98.7 39.1l44.6 42c24.2 22.8 33.2 55.7 26.6 86L503 183l8-8c9.4-9.4 24.6-9.4 33.9 0l24 24c9.4 9.4 9.4 24.6 0 33.9l-88 88c-9.4 9.4-24.6 9.4-33.9 0l-24-24c-9.4-9.4-9.4-24.6 0-33.9l8-8-17.5-17.5zM27.4 377.1L260.9 182.6c3.5 4.9 7.5 9.6 11.8 14l38.1 38.1c6 6 12.4 11.2 19.2 15.7L134.9 484.6c-14.5 17.4-36 27.4-58.6 27.4C34.1 512 0 477.8 0 435.7c0-22.6 10.1-44.1 27.4-58.6z\"/></svg>"
3128
},
3229
"4": {
@@ -117,7 +114,6 @@
117114
"icon": "fa-rocket",
118115
"color": "white",
119116
"customStyle": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
120-
"background": "animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);",
121117
"iconSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" fill=\"\" width=\"12\" height=\"12\"><path d=\"M156.6 384.9L125.7 354c-8.5-8.5-11.5-20.8-7.7-32.2c3-8.9 7-20.5 11.8-33.8L24 288c-8.6 0-16.6-4.6-20.9-12.1s-4.2-16.7 .2-24.1l52.5-88.5c13-21.9 36.5-35.3 61.9-35.3l82.3 0c2.4-4 4.8-7.7 7.2-11.3C289.1-4.1 411.1-8.1 483.9 5.3c11.6 2.1 20.6 11.2 22.8 22.8c13.4 72.9 9.3 194.8-111.4 276.7c-3.5 2.4-7.3 4.8-11.3 7.2v82.3c0 25.4-13.4 49-35.3 61.9l-88.5 52.5c-7.4 4.4-16.6 4.5-24.1 .2s-12.1-12.2-12.1-20.9V380.8c-14.1 4.9-26.4 8.9-35.7 11.9c-11.2 3.6-23.4 .5-31.8-7.8zM384 168a40 40 0 1 0 0-80 40 40 0 1 0 0 80z\"/></svg>"
122118
},
123119
"14": {

public/script/generateSvg.js

Lines changed: 49 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,7 @@ const downloadUserImg = (url, path) => {
1414
});
1515
};
1616

17-
const formatTopPercentage = (lbRank) => {
18-
if (lbRank?.rank === undefined) return "-";
19-
if (lbRank?.count === undefined) return "-";
20-
if (lbRank.rank === 1) return "GOAT";
21-
let percentage = (lbRank.rank / lbRank.count) * 100;
22-
let formattedPercentage =
23-
percentage % 1 === 0 ? percentage.toString() : percentage.toFixed(2);
24-
return "Top " + formattedPercentage + "%";
25-
};
26-
27-
async function getOGSvg(userData, theme, badge) {
28-
const width = 500;
29-
const height = 200;
30-
const cssData = await getOutputCSS();
31-
17+
const getUserImg = async (userData, theme) => {
3218
let userImg;
3319
let defaultUserImg = `
3420
<div class="h-20 w-20 rounded-full">
@@ -66,29 +52,53 @@ async function getOGSvg(userData, theme, badge) {
6652
`;
6753
}
6854
}
55+
return userImg;
56+
};
6957

58+
const getUserBadge = (badge, theme) => {
7059
let userBadge = "";
7160
if (badge !== null) {
7261
let color;
7362
if (badge.color === "white") color = "white";
7463
else color = theme[badge.color];
7564

76-
let bgColor;
77-
let bgTailwindColor = "";
78-
if (badge.background === "animation: rgb-bg 10s linear infinite;")
79-
bgTailwindColor = "animate-rgb-bg";
80-
bgColor = theme[badge.background];
81-
8265
badge.iconSvg = badge.iconSvg.replace('fill=""', `fill="${color}"`);
8366
userBadge = `
84-
<div class="flex w-fit items-center justify-center rounded-md p-1 ${bgTailwindColor}" style="background: ${bgColor};">
67+
<div class="flex w-fit items-center justify-center rounded-md p-1${
68+
badge.customStyle ? " animate-rgb-bg" : ""
69+
}"
70+
${
71+
badge.background
72+
? 'style="background: ' + theme[badge.background] + ';"'
73+
: ""
74+
}>
8575
<div class="px-1">${badge.iconSvg}</div>
8676
<div class="px-1 align-middle font-mono text-xs" style="color: ${color};">
8777
${badge.name}
8878
</div>
8979
</div>
9080
`;
9181
}
82+
return userBadge;
83+
};
84+
85+
const formatTopPercentage = (lbRank) => {
86+
if (lbRank?.rank === undefined) return "-";
87+
if (lbRank?.count === undefined) return "-";
88+
if (lbRank.rank === 1) return "GOAT";
89+
let percentage = (lbRank.rank / lbRank.count) * 100;
90+
let formattedPercentage =
91+
percentage % 1 === 0 ? percentage.toString() : percentage.toFixed(2);
92+
return "Top " + formattedPercentage + "%";
93+
};
94+
95+
async function getOGSvg(userData, theme, badge) {
96+
const width = 500;
97+
const height = 200;
98+
const cssData = await getOutputCSS();
99+
100+
let userImg = await getUserImg(userData, theme);
101+
let userBadge = getUserBadge(badge, theme);
92102

93103
const svg = `
94104
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}"
@@ -146,66 +156,8 @@ async function getSvg(userData, theme, badge, leaderBoards, personalbests) {
146156
personalbests ? (height += 440) : (height += 0);
147157
const cssData = await getOutputCSS();
148158

149-
let userImg;
150-
let defaultUserImg = `
151-
<div class="h-20 w-20 rounded-full">
152-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="${theme.subColor}">
153-
<path
154-
d="M399 384.2C376.9 345.8 335.4 320 288 320H224c-47.4 0-88.9 25.8-111 64.2c35.2 39.2 86.2 63.8 143 63.8s107.8-24.7 143-63.8zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm256 16a72 72 0 1 0 0-144 72 72 0 1 0 0 144z" />
155-
</svg>
156-
</div>
157-
`;
158-
if (
159-
userData === null ||
160-
userData.discordId === undefined ||
161-
userData.discordAvatar === undefined
162-
) {
163-
userImg = defaultUserImg;
164-
} else {
165-
// Download the image and save it to a file
166-
const imagePath = `public/image/userImg/${userData.discordId}-${userData.discordAvatar}.png`;
167-
await downloadUserImg(
168-
`https://cdn.discordapp.com/avatars/${userData.discordId}/${userData.discordAvatar}.png?size=256`,
169-
imagePath,
170-
);
171-
172-
// Convert the image file to base64
173-
const imageData = fs.readFileSync(imagePath);
174-
const base64Image = imageData.toString("base64");
175-
176-
if (base64Image == "") {
177-
userImg = defaultUserImg;
178-
} else {
179-
userImg = `
180-
<div class="h-20 w-20 overflow-hidden rounded-full">
181-
<img src="data:image/png;base64,${base64Image}" width="80" height="80" />
182-
</div>
183-
`;
184-
}
185-
}
186-
187-
let userBadge = "";
188-
if (badge !== null) {
189-
let color;
190-
if (badge.color === "white") color = "white";
191-
else color = theme[badge.color];
192-
193-
let bgColor;
194-
let bgTailwindColor = "";
195-
if (badge.background === "animation: rgb-bg 10s linear infinite;")
196-
bgTailwindColor = "animate-rgb-bg";
197-
bgColor = theme[badge.background];
198-
199-
badge.iconSvg = badge.iconSvg.replace('fill=""', `fill="${color}"`);
200-
userBadge = `
201-
<div class="flex w-fit items-center justify-center rounded-md p-1 ${bgTailwindColor}" style="background: ${bgColor};">
202-
<div class="px-1">${badge.iconSvg}</div>
203-
<div class="px-1 align-middle font-mono text-xs" style="color: ${color};">
204-
${badge.name}
205-
</div>
206-
</div>
207-
`;
208-
}
159+
let userImg = await getUserImg(userData, theme);
160+
let userBadge = getUserBadge(badge, theme);
209161

210162
let leaderBoardHTML = "";
211163
if (leaderBoards == true) {
@@ -231,28 +183,21 @@ async function getSvg(userData, theme, badge, leaderBoards, personalbests) {
231183
let ordinalNumber60 = "";
232184

233185
try {
234-
if (
235-
allTimeLbs.time["15"]["english"]["rank"] === undefined ||
236-
allTimeLbs.time["15"]["english"]["rank"] === null
237-
) {
238-
rank15 = "-";
239-
} else {
240-
rank15 = allTimeLbs.time["15"]["english"]["rank"];
241-
}
242-
if (
243-
allTimeLbs.time["60"]["english"]["rank"] === undefined ||
244-
allTimeLbs.time["60"]["english"]["rank"] === null
245-
) {
246-
rank60 = "-";
247-
} else {
248-
rank60 = allTimeLbs.time["60"]["english"]["rank"];
249-
}
250-
ordinalNumber15 = ordinalNumber(
251-
allTimeLbs.time["15"]["english"]["rank"],
252-
);
253-
ordinalNumber60 = ordinalNumber(
254-
allTimeLbs.time["60"]["english"]["rank"],
255-
);
186+
const time15 = allTimeLbs.time["15"] || {};
187+
const time60 = allTimeLbs.time["60"] || {};
188+
189+
rank15 = !time15.english?.rank ? "-" : time15.english.rank;
190+
rank60 = !time60.english?.rank ? "-" : time60.english.rank;
191+
192+
ordinalNumber15 =
193+
typeof time15.english?.rank === "number"
194+
? ordinalNumber(time15.english.rank)
195+
: "-";
196+
197+
ordinalNumber60 =
198+
typeof time60.english?.rank === "number"
199+
? ordinalNumber(time60.english.rank)
200+
: "-";
256201
} catch (e) {
257202
console.log(e);
258203
console.log(userData);

public/script/monkeytypeData.js

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -124,30 +124,19 @@ async function getMonkeyTypeBadgesData() {
124124

125125
for (let i = 0; i < Object.keys(badgesData).length; i++) {
126126
let badge = badgesData[Object.keys(badgesData)[i]];
127-
if (badge.hasOwnProperty("customStyle")) {
128-
if (
129-
badge.customStyle ==
130-
"animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);"
131-
) {
132-
badge.color = "white";
133-
badge["background"] =
134-
"animation: rgb-bg 10s linear infinite; background: linear-gradient(45deg in hsl longer hue, hsl(330, 90%, 30%) 0%, hsl(250, 90%, 30%) 100%);";
135-
}
136-
} else {
137-
if (badge.color.includes("var")) {
138-
badge.color = badge.color
139-
.replace("var(--", "")
140-
.replace(")", "")
141-
.replace("-", "")
142-
.replace("c", "C");
143-
}
144-
if (badge.background.includes("var")) {
145-
badge.background = badge.background
146-
.replace("var(--", "")
147-
.replace(")", "")
148-
.replace("-", "")
149-
.replace("c", "C");
150-
}
127+
if (badge.color.includes("var")) {
128+
badge.color = badge.color
129+
.replace("var(--", "")
130+
.replace(")", "")
131+
.replace("-", "")
132+
.replace("c", "C");
133+
}
134+
if (badge.background && badge.background.includes("var")) {
135+
badge.background = badge.background
136+
.replace("var(--", "")
137+
.replace(")", "")
138+
.replace("-", "")
139+
.replace("c", "C");
151140
}
152141
const iconSvg = findIconDefinition({
153142
prefix: "fas",

public/style/output.css

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,10 @@ video {
534534
--tw-backdrop-sepia: ;
535535
}
536536

537+
.pointer-events-none {
538+
pointer-events: none;
539+
}
540+
537541
.static {
538542
position: static;
539543
}
@@ -566,6 +570,10 @@ video {
566570
top: 0px;
567571
}
568572

573+
.isolate {
574+
isolation: isolate;
575+
}
576+
569577
.z-10 {
570578
z-index: 10;
571579
}
@@ -622,6 +630,10 @@ video {
622630
margin-left: 1rem;
623631
}
624632

633+
.ml-6 {
634+
margin-left: 1.5rem;
635+
}
636+
625637
.mr-2 {
626638
margin-right: 0.5rem;
627639
}
@@ -670,10 +682,6 @@ video {
670682
margin-top: 2rem;
671683
}
672684

673-
.ml-6 {
674-
margin-left: 1.5rem;
675-
}
676-
677685
.block {
678686
display: block;
679687
}
@@ -870,7 +878,7 @@ video {
870878
}
871879

872880
.animate-rgb-bg {
873-
animation: rgb-bg 12s linear infinite;
881+
animation: rgb-bg 10s linear infinite;
874882
}
875883

876884
@keyframes spin {
@@ -1133,10 +1141,6 @@ video {
11331141
padding-top: 1rem;
11341142
}
11351143

1136-
.pl-3 {
1137-
padding-left: 0.75rem;
1138-
}
1139-
11401144
.text-left {
11411145
text-align: left;
11421146
}
@@ -1304,6 +1308,14 @@ video {
13041308
outline-style: solid;
13051309
}
13061310

1311+
.transition {
1312+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
1313+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
1314+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
1315+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1316+
transition-duration: 150ms;
1317+
}
1318+
13071319
.transition-opacity {
13081320
transition-property: opacity;
13091321
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);

tailwind.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module.exports = {
2121
38: "9.5rem",
2222
},
2323
animation: {
24-
"rgb-bg": "rgb-bg 12s linear infinite",
24+
"rgb-bg": "rgb-bg 10s linear infinite",
2525
},
2626
keyframes: {
2727
"rgb-bg": {

0 commit comments

Comments
 (0)