Spaces:
Runtime error
Runtime error
| const fs = require('fs') | |
| const path = require('path') | |
| const mimeType = require('mime-types') | |
| const sizeOf = require('image-size') | |
| const { toFixed } = require('./index') | |
| const themePath = path.resolve(__dirname, '../assets/theme') | |
| const imgExts = ['.jpg', '.jpeg', '.png', '.gif', '.webp'] | |
| const themeList = {} | |
| fs.readdirSync(themePath).forEach(theme => { | |
| const currentThemePath = path.resolve(themePath, theme) | |
| // skip non-directory | |
| if (!fs.statSync(currentThemePath).isDirectory()) return | |
| if (!(theme in themeList)) themeList[theme] = {} | |
| const imgList = fs.readdirSync(currentThemePath) | |
| imgList.forEach(img => { | |
| // skip non-image files | |
| if (!imgExts.includes(path.extname(img).toLowerCase())) return | |
| const imgPath = path.resolve(currentThemePath, img) | |
| const char = path.parse(img).name | |
| const { width, height } = sizeOf(imgPath) | |
| themeList[theme][char] = { | |
| width, | |
| height, | |
| data: convertToDatauri(imgPath) | |
| } | |
| }) | |
| }) | |
| function convertToDatauri(path) { | |
| const mime = mimeType.lookup(path) | |
| const base64 = fs.readFileSync(path).toString('base64') | |
| return `data:${mime};base64,${base64}` | |
| } | |
| function getCountImage(params) { | |
| let { count, theme = 'moebooru', padding = 7, prefix = -1, offset = 0, align = 'top', scale = 1, pixelated = '1', darkmode = 'auto' } = params | |
| if (!(theme in themeList)) theme = 'moebooru' | |
| padding = parseInt(Number(padding), 10) | |
| offset = parseFloat(Number(offset), 10) | |
| scale = parseFloat(Number(scale), 10) | |
| // This is not the greatest way for generating an SVG but it'll do for now | |
| const countArray = count.toString().padStart(padding, '0').split('') | |
| // Add prefix if exist | |
| if (prefix >= 0) { | |
| countArray.unshift(...String(prefix).split('')) | |
| } | |
| // Add _start and _end if exist | |
| if (themeList[theme]['_start']) { | |
| countArray.unshift('_start') | |
| } | |
| if (themeList[theme]['_end']) { | |
| countArray.push('_end') | |
| } | |
| const uniqueChar = [...new Set(countArray)] | |
| let x = 0, y = 0 | |
| const defs = uniqueChar.reduce((ret, cur) => { | |
| let { width, height, data } = themeList[theme][cur] | |
| width *= scale | |
| height *= scale | |
| y = Math.max(y, height) | |
| ret = `${ret} | |
| <image id="${cur}" width="${toFixed(width, 5)}" height="${toFixed(height, 5)}" xlink:href="${data}" />` | |
| return ret | |
| }, '') | |
| const parts = countArray.reduce((ret, cur) => { | |
| let { width, height } = themeList[theme][cur] | |
| width *= scale | |
| height *= scale | |
| let yOffset = 0 | |
| if (align === 'center') { | |
| yOffset = (y - height) / 2 | |
| } else if (align === 'bottom') { | |
| yOffset = y - height | |
| } | |
| const image = `${ret} | |
| <use x="${toFixed(x, 5)}"${yOffset ? ` y="${toFixed(yOffset, 5)}"` : ''} xlink:href="#${cur}" />` | |
| x += width + offset | |
| return image | |
| }, '') | |
| // Fix the last image offset | |
| x -= offset | |
| const style = ` | |
| svg { | |
| ${pixelated === '1' ? 'image-rendering: pixelated;' : ''} | |
| ${darkmode === '1' ? 'filter: brightness(.6);' : ''} | |
| } | |
| ${darkmode === 'auto' ? `@media (prefers-color-scheme: dark) { svg { filter: brightness(.6); } }` : ''} | |
| ` | |
| return `<?xml version="1.0" encoding="UTF-8"?> | |
| <!-- Generated by https://github.com/journey-ad/Moe-Counter --> | |
| <svg viewBox="0 0 ${toFixed(x, 5)} ${toFixed(y, 5)}" width="${toFixed(x, 5)}" height="${toFixed(y, 5)}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | |
| <title>Moe Counter!</title> | |
| <style>${style}</style> | |
| <defs>${defs} | |
| </defs> | |
| <g>${parts} | |
| </g> | |
| </svg> | |
| ` | |
| } | |
| module.exports = { | |
| themeList, | |
| getCountImage | |
| } | |