diff options
Diffstat (limited to '')
-rwxr-xr-x | tools/generate-images.js | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/tools/generate-images.js b/tools/generate-images.js new file mode 100755 index 0000000..0bd3af2 --- /dev/null +++ b/tools/generate-images.js @@ -0,0 +1,79 @@ +#!/usr/bin/env node +import imageminZopfli from 'imagemin-zopfli'; // eslint-disable-line i/no-unresolved +import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node'; // eslint-disable-line i/no-unresolved +import {optimize} from 'svgo'; +import {readFile, writeFile} from 'node:fs/promises'; +import {argv, exit} from 'node:process'; + +function doExit(err) { + if (err) console.error(err); + exit(err ? 1 : 0); +} + +async function generate(svg, path, {size, bg}) { + const outputFile = new URL(path, import.meta.url); + + if (String(outputFile).endsWith('.svg')) { + const {data} = optimize(svg, { + plugins: [ + 'preset-default', + 'removeDimensions', + { + name: 'addAttributesToSVGElement', + params: {attributes: [{width: size}, {height: size}]}, + }, + ], + }); + await writeFile(outputFile, data); + return; + } + + const {objects, options} = await loadSVGFromString(svg); + const canvas = new Canvas(); + canvas.setDimensions({width: size, height: size}); + const ctx = canvas.getContext('2d'); + ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1); + + if (bg) { + canvas.add(new Rect({ + left: 0, + top: 0, + height: size * (1 / (size / options.height)), + width: size * (1 / (size / options.width)), + fill: 'white', + })); + } + + canvas.add(util.groupSVGElements(objects, options)); + canvas.renderAll(); + + let png = Buffer.from([]); + for await (const chunk of canvas.createPNGStream()) { + png = Buffer.concat([png, chunk]); + } + + png = await imageminZopfli({more: true})(png); + await writeFile(outputFile, png); +} + +async function main() { + const gitea = argv.slice(2).includes('gitea'); + const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8'); + const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8'); + + await Promise.all([ + generate(logoSvg, '../public/assets/img/logo.svg', {size: 32}), + generate(logoSvg, '../public/assets/img/logo.png', {size: 512}), + generate(faviconSvg, '../public/assets/img/favicon.svg', {size: 32}), + generate(faviconSvg, '../public/assets/img/favicon.png', {size: 180}), + generate(logoSvg, '../public/assets/img/avatar_default.png', {size: 200}), + generate(logoSvg, '../public/assets/img/apple-touch-icon.png', {size: 180, bg: true}), + gitea && generate(logoSvg, '../public/assets/img/gitea.svg', {size: 32}), + ]); +} + +try { + doExit(await main()); +} catch (err) { + doExit(err); +} |