⭐ Moe-Counter Compatible Website Hit Counter Written in Gleam mayu.due.moe
hit-counter svg moe
at main 369 lines 11 kB view raw
1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>Mayu</title> 7 </head> 8 9 <body> 10 <style> 11 @import url("https://fonts.googleapis.com/css2?family=Overpass:ital,wght@0,100..900;1,100..900&display=swap"); 12 @import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"); 13 14 body { 15 background-color: #0b1622; 16 color: rgb(159, 173, 189); 17 font-family: 18 Roboto, 19 -apple-system, 20 BlinkMacSystemFont, 21 Segoe UI, 22 Oxygen, 23 Ubuntu, 24 Cantarell, 25 Fira Sans, 26 Droid Sans, 27 Helvetica Neue, 28 sans-serif; 29 } 30 31 main { 32 background-color: #151f2e; 33 padding: 20px 35.4px; 34 border-radius: 4px; 35 display: flex; 36 gap: 80px; 37 max-width: 100%; 38 position: absolute; 39 top: 50%; 40 left: 50%; 41 transform: translate(-50%, -50%); 42 box-shadow: 43 0 0 8px -2px rgba(0, 0, 0, 0.1), 44 0 6px 20px -3px rgba(0, 0, 0, 0.2); 45 } 46 47 .example-image { 48 display: block; 49 margin: 10px 0; 50 width: 100%; 51 border-radius: 3px; 52 } 53 54 h2 { 55 font-size: 1rem; 56 font-weight: 500; 57 margin-bottom: 15px; 58 } 59 60 input, 61 select { 62 background-color: rgb(11, 22, 34); 63 color: rgb(159, 173, 189); 64 border-radius: 4px; 65 border: 0; 66 height: 40px; 67 padding: 0 15px; 68 line-height: 40px; 69 display: inline-block; 70 font-size: 0.9rem; 71 } 72 73 ::placeholder { 74 /* color: #9fadbd; */ 75 color: rgb(114, 138, 161); 76 } 77 78 select { 79 color: #9fadbd; 80 margin-bottom: 35%; 81 appearance: none; 82 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%239fadbd'%3E%3Cpath d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z'/%3E%3C/svg%3E"); 83 background-repeat: no-repeat; 84 background-position: right 0.75em top 50%; 85 background-size: 1.25em; 86 } 87 88 select:focus { 89 outline: none; 90 } 91 92 input:focus { 93 outline: none; 94 } 95 96 .label { 97 margin-top: -10px; 98 padding-bottom: 0px; 99 font-size: 0.9rem; 100 color: rgb(114, 138, 161); 101 font-weight: normal; 102 } 103 104 pre { 105 font-family: monospace; 106 } 107 108 .copy-codes { 109 background-color: #0f1926; 110 padding: 10px; 111 border-radius: 4px; 112 color: #9fadbd; 113 font-size: 0.9rem; 114 overflow-x: auto; 115 white-space: pre-wrap; 116 word-wrap: break-word; 117 max-width: 100%; 118 margin-top: 20px; 119 } 120 121 a { 122 color: rgb(61, 180, 242); 123 text-decoration: none; 124 } 125 126 p { 127 font-size: 0.9rem; 128 color: #9fadbd; 129 line-height: 1.4; 130 } 131 132 .attribution { 133 position: absolute; 134 bottom: 20px; 135 left: 35.4px; 136 } 137 138 .attribution-2 { 139 display: none; 140 } 141 142 .counter { 143 display: flex; 144 flex-direction: column; 145 justify-content: center; 146 } 147 148 @media (max-width: 768px) { 149 main { 150 flex-direction: column; 151 gap: 40px; 152 } 153 154 .attribution-1 { 155 display: none; 156 } 157 158 .attribution-2 { 159 display: block; 160 } 161 162 .attribution { 163 position: unset; 164 margin-top: 40px; 165 } 166 167 select { 168 margin-bottom: unset; 169 } 170 171 .mascot { 172 display: none; 173 visibility: hidden; 174 } 175 } 176 177 @media (min-width: 768px) { 178 .mascot { 179 position: fixed; 180 bottom: 0; 181 right: 20px; 182 width: 300px; 183 margin: 0; 184 border-radius: 0; 185 z-index: -1; 186 display: none; 187 } 188 } 189 190 .copy-codes-label { 191 font-size: 0.9rem; 192 color: rgb(114, 138, 161); 193 font-weight: normal; 194 margin-top: 20px; 195 margin-bottom: -10px; 196 } 197 198 @media (max-width: 768px) { 199 main { 200 padding: 10px 17.7px; 201 } 202 } 203 </style> 204 205 <main> 206 <div> 207 <h2>Username</h2> 208 209 <p class="label"> 210 Enter the username you'd like to use as the ID of your counter. 211 </p> 212 213 <input type="text" id="idInput" placeholder="demo" /> 214 215 <p></p> 216 217 <select id="themeSelect"> 218 <option value="asoul">A-SOUL</option> 219 <option value="gelbooru">Gelbooru</option> 220 <option value="moebooru">Moebooru</option> 221 <option value="rule34">Rule 34</option> 222 <option value="urushi">Urushi Yaotome</option> 223 <option value="lain">Lain Iwakura</option> 224 <option value="garukura">Girls Band Cry</option> 225 </select> 226 227 <p class="attribution attribution-1"> 228 Created by 229 <a href="https://anilist.co/user/fuwn/" target="_blank">@Fuwn</a> 230 231 <br /> 232 233 Source code available on 234 <a href="https://github.com/Fuwn/mayu" target="_blank">GitHub</a> 235 {{ MAYU_VERSION }} 236 </p> 237 </div> 238 239 <div class="counter"> 240 <img 241 id="example" 242 src="/get/@demo" 243 alt="Example counter" 244 class="example-image" 245 /> 246 247 <p class="copy-codes-label"> 248 Copy one of the image embed snippets below to paste into your 249 biography 250 </p> 251 252 <pre id="copy-codes" class="copy-codes"></pre> 253 254 <p class="attribution attribution-2"> 255 Created by 256 <a href="https://anilist.co/user/fuwn/" target="_blank">@Fuwn</a> 257 258 <br /> 259 260 Source code available on 261 <a href="https://github.com/Fuwn/mayu" target="_blank">GitHub</a> 262 {{ MAYU_VERSION }} 263 </p> 264 </div> 265 </main> 266 267 <img src="" alt="Mascot" class="mascot" title="Mascot" /> 268 269 <script> 270 const themeQueryParameter = new URLSearchParams( 271 window.location.search, 272 ).get("theme"); 273 const defaultConfiguration = { 274 id: new URLSearchParams(window.location.search).get("id") || "demo", 275 theme: themeQueryParameter || "asoul", 276 }; 277 let inputTimeout; 278 const idInput = document.getElementById("idInput"); 279 const themeSelect = document.getElementById("themeSelect"); 280 const image = document.getElementById("example"); 281 const copyCodesInput = document.getElementById("copy-codes"); 282 let inputValue = defaultConfiguration.id; 283 let themeValue = defaultConfiguration.theme; 284 const setCopyCodes = () => { 285 copyCodesInput.innerText = `![${inputValue}](${image.src})\n\n<img src="${image.src}" alt="${inputValue}" />`; 286 }; 287 const set = () => { 288 if (idInput.value !== "") { 289 inputValue = idInput.value; 290 } else { 291 inputValue = defaultConfiguration.id; 292 293 if (inputValue !== null && inputValue !== "demo") { 294 idInput.value = inputValue; 295 } 296 } 297 298 if (themeQueryParameter) { 299 themeValue = themeQueryParameter; 300 themeSelect.value = themeValue; 301 } else { 302 themeValue = themeSelect.value; 303 } 304 305 image.src = `/get/@${inputValue}?theme=${themeValue}&padding=6`; 306 307 setCopyCodes(); 308 }; 309 const mascots = [ 310 { name: "Akaza Akari", image: "https://i.imgur.com/efamPLp.png" }, 311 { name: "Akemi Homura", image: "https://i.imgur.com/8v6aSbV.png" }, 312 { name: "Akiyama Mio", image: "https://i.imgur.com/fgbEdWe.png" }, 313 { name: "Ali Baba", image: "https://i.imgur.com/FWC00jB.png" }, 314 { name: "Cirno", image: "https://i.imgur.com/u65u8oN.png" }, 315 { name: "Fubuki Atsuya", image: "https://i.imgur.com/97DaEBD.png" }, 316 { name: "Gasai Yuno", image: "https://i.imgur.com/BurJnOd.png" }, 317 { name: "Hatsune Miku", image: "https://i.imgur.com/HsqOvDJ.png" }, 318 { name: "Hirasawa Yui", image: "https://i.imgur.com/ZttwSus.png" }, 319 { 320 name: "Hitagi Senjougahara", 321 image: "https://i.imgur.com/ttQDirH.png", 322 }, 323 { name: "Horo", image: "https://i.imgur.com/4F6BAMZ.png" }, 324 { name: "Kaname Madoka", image: "https://i.imgur.com/TVlagl3.png" }, 325 { name: "Kikuchi Makoto", image: "https://i.imgur.com/aXVz09Y.png" }, 326 { name: "Kirisame Marisa", image: "https://i.imgur.com/MCvbGgt.png" }, 327 { name: "Kisaragi Chihaya", image: "https://i.imgur.com/4Hdd0R8.png" }, 328 { name: "Kousaka Kirino", image: "https://i.imgur.com/E0sdnuC.png" }, 329 { name: "Kurisu Makise", image: "https://i.imgur.com/pMNliiX.png" }, 330 { name: "Kuriyama Mirai", image: "https://i.imgur.com/TwcfQPD.png" }, 331 { name: "Kuroko no Basuke", image: "https://i.imgur.com/FNgiG0D.png" }, 332 { name: "Mashiro Shiina", image: "https://i.imgur.com/BxJylsO.png" }, 333 { name: "Mayoi Hachikuji", image: "https://i.imgur.com/Xgzke7s.png" }, 334 { name: "Miyamoto Konatsu", image: "https://i.imgur.com/GhwBI5n.png" }, 335 { name: "Nagase Iori", image: "https://i.imgur.com/SRWU4e1.png" }, 336 { name: "Nakano Azusa", image: "https://i.imgur.com/pfqZLHo.png" }, 337 { name: "Poko Fox", image: "https://i.imgur.com/OF68sMQ.png" }, 338 { name: "Remilia Scarlet", image: "https://i.imgur.com/3YSqyiI.png" }, 339 { name: "Ruri Gokou", image: "https://i.imgur.com/UtjqvU6.png" }, 340 { name: "Saber", image: "https://i.imgur.com/H7GtZ9j.png" }, 341 { name: "Shana", image: "https://i.imgur.com/MPD95PX.png" }, 342 { name: "Touwa Erio", image: "https://i.imgur.com/AFINQjc.png" }, 343 { name: "Yin", image: "https://i.imgur.com/rddrYFR.png" }, 344 { name: "Yoko Littner", image: "https://i.imgur.com/bEPA1rz.png" }, 345 { 346 name: "Yukinoshita Yukino", 347 image: "https://i.imgur.com/uu6Dh0I.png", 348 }, 349 { name: "Yuuki Asuna", image: "https://i.imgur.com/283FX36.png" }, 350 { name: "Yuzuki Yukari", image: "https://i.imgur.com/84HOYIc.png" }, 351 ]; 352 353 set(); 354 idInput.addEventListener("input", () => { 355 clearTimeout(inputTimeout); 356 357 inputTimeout = setTimeout(set, 500); 358 }); 359 themeSelect.addEventListener("change", set); 360 361 const randomMascot = mascots[Math.floor(Math.random() * mascots.length)]; 362 363 document.querySelector(".mascot").src = randomMascot.image; 364 document.querySelector(".mascot").alt = randomMascot.name; 365 document.querySelector(".mascot").title = randomMascot.name; 366 document.querySelector(".mascot").style.display = "block"; 367 </script> 368 </body> 369</html>