summaryrefslogtreecommitdiffstats
path: root/build
diff options
context:
space:
mode:
Diffstat (limited to 'build')
-rwxr-xr-xbuild/generate-images.js80
1 files changed, 80 insertions, 0 deletions
diff --git a/build/generate-images.js b/build/generate-images.js
new file mode 100755
index 0000000000..7a00395a5b
--- /dev/null
+++ b/build/generate-images.js
@@ -0,0 +1,80 @@
+#!/usr/bin/env node
+'use strict';
+
+const imageminZopfli = require('imagemin-zopfli');
+const {fabric} = require('fabric');
+const {DOMParser, XMLSerializer} = require('xmldom');
+const {readFile, writeFile} = require('fs').promises;
+const {resolve} = require('path');
+
+function exit(err) {
+ if (err) console.error(err);
+ process.exit(err ? 1 : 0);
+}
+
+function loadSvg(svg) {
+ return new Promise((resolve) => {
+ fabric.loadSVGFromString(svg, (objects, options) => {
+ resolve({objects, options});
+ });
+ });
+}
+
+async function generate(svg, outputFile, {size, bg, removeDetail} = {}) {
+ const parser = new DOMParser();
+ const serializer = new XMLSerializer();
+ const document = parser.parseFromString(svg);
+
+ if (removeDetail) {
+ for (const el of Array.from(document.getElementsByTagName('g') || [])) {
+ for (const attribute of Array.from(el.attributes || [])) {
+ if (attribute.name === 'class' && attribute.value === 'detail-remove') {
+ el.parentNode.removeChild(el);
+ }
+ }
+ }
+ }
+
+ svg = serializer.serializeToString(document);
+
+ const {objects, options} = await loadSvg(svg);
+ const canvas = new fabric.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 fabric.Rect({
+ left: 0,
+ top: 0,
+ height: size * (1 / (size / options.height)),
+ width: size * (1 / (size / options.width)),
+ fill: 'white',
+ }));
+ }
+
+ canvas.add(fabric.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 svg = await readFile(resolve(__dirname, '../assets/logo.svg'), 'utf8');
+ await generate(svg, resolve(__dirname, '../public/img/gitea-lg.png'), {size: 880});
+ await generate(svg, resolve(__dirname, '../public/img/gitea-512.png'), {size: 512});
+ await generate(svg, resolve(__dirname, '../public/img/gitea-192.png'), {size: 192});
+ await generate(svg, resolve(__dirname, '../public/img/gitea-sm.png'), {size: 120});
+ await generate(svg, resolve(__dirname, '../public/img/avatar_default.png'), {size: 200});
+ await generate(svg, resolve(__dirname, '../public/img/favicon.png'), {size: 180, removeDetail: true});
+ await generate(svg, resolve(__dirname, '../public/img/apple-touch-icon.png'), {size: 180, bg: true});
+}
+
+main().then(exit).catch(exit);
+