summaryrefslogtreecommitdiffstats
path: root/tools/generate-images.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/generate-images.js')
-rwxr-xr-xtools/generate-images.js79
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);
+}