You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

generate-images.js 2.5KB

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