code.gitea.io/gitea@v1.21.7/build/generate-images.js (about) 1 #!/usr/bin/env node 2 import imageminZopfli from 'imagemin-zopfli'; 3 import {optimize} from 'svgo'; 4 import {fabric} from 'fabric'; 5 import {readFile, writeFile} from 'node:fs/promises'; 6 7 function exit(err) { 8 if (err) console.error(err); 9 process.exit(err ? 1 : 0); 10 } 11 12 function loadSvg(svg) { 13 return new Promise((resolve) => { 14 fabric.loadSVGFromString(svg, (objects, options) => { 15 resolve({objects, options}); 16 }); 17 }); 18 } 19 20 async function generate(svg, path, {size, bg}) { 21 const outputFile = new URL(path, import.meta.url); 22 23 if (String(outputFile).endsWith('.svg')) { 24 const {data} = optimize(svg, { 25 plugins: [ 26 'preset-default', 27 'removeDimensions', 28 { 29 name: 'addAttributesToSVGElement', 30 params: {attributes: [{width: size}, {height: size}]} 31 }, 32 ], 33 }); 34 await writeFile(outputFile, data); 35 return; 36 } 37 38 const {objects, options} = await loadSvg(svg); 39 const canvas = new fabric.Canvas(); 40 canvas.setDimensions({width: size, height: size}); 41 const ctx = canvas.getContext('2d'); 42 ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1); 43 44 if (bg) { 45 canvas.add(new fabric.Rect({ 46 left: 0, 47 top: 0, 48 height: size * (1 / (size / options.height)), 49 width: size * (1 / (size / options.width)), 50 fill: 'white', 51 })); 52 } 53 54 canvas.add(fabric.util.groupSVGElements(objects, options)); 55 canvas.renderAll(); 56 57 let png = Buffer.from([]); 58 for await (const chunk of canvas.createPNGStream()) { 59 png = Buffer.concat([png, chunk]); 60 } 61 62 png = await imageminZopfli({more: true})(png); 63 await writeFile(outputFile, png); 64 } 65 66 async function main() { 67 const gitea = process.argv.slice(2).includes('gitea'); 68 const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8'); 69 const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8'); 70 71 await Promise.all([ 72 generate(logoSvg, '../public/assets/img/logo.svg', {size: 32}), 73 generate(logoSvg, '../public/assets/img/logo.png', {size: 512}), 74 generate(faviconSvg, '../public/assets/img/favicon.svg', {size: 32}), 75 generate(faviconSvg, '../public/assets/img/favicon.png', {size: 180}), 76 generate(logoSvg, '../public/assets/img/avatar_default.png', {size: 200}), 77 generate(logoSvg, '../public/assets/img/apple-touch-icon.png', {size: 180, bg: true}), 78 gitea && generate(logoSvg, '../public/assets/img/gitea.svg', {size: 32}), 79 ]); 80 } 81 82 main().then(exit).catch(exit);