import data from './data.json' with { type: "json" }; import gm from "gm"; import * as fs from "fs"; import archiver from 'archiver'; import * as path from "path"; import { fileURLToPath } from 'url'; const myGm = gm.subClass({imageMagick: true}); const VERSION = process.env.npm_package_version; const zipname = `pride-button-${VERSION}.zip`; const position = {x: 4, y: 2, gravity: "NorthEast"} const metadatas = [] function capitalizeFirstLetter(val) { return String(val).charAt(0).toUpperCase() + String(val).slice(1); } function createFilename(prideflag, text, now = false) { const adaptedText = text .replaceAll("⋅", "_") .replaceAll(" ", "_") .replaceAll("\n", '-') .normalize("NFD").replaceAll(/[\u0300-\u036f]/g, "") .replaceAll("&", "and") .replaceAll("+", "") .toLowerCase(); return `${prideflag.name.en.toLowerCase()}-${adaptedText}${now?'-now':''}.gif`; } function createButton(source, x, y, text, gravity) { const turnedText = text .replaceAll("⋅", "-") .toUpperCase(); return myGm(source) .font('./NFPixels-Regular.ttf', 10) .drawText(x-1, y, turnedText, gravity) .drawText(x+1, y, turnedText, gravity) .drawText(x, y+1, turnedText, gravity) .drawText(x, y-1, turnedText, gravity) .drawText(x-1, y-1, turnedText, gravity) .drawText(x+1, y+1, turnedText, gravity) .drawText(x-1, y+1, turnedText, gravity) .drawText(x+1, y-1, turnedText, gravity) .fill("#FFFFFF") .drawText(x, y, turnedText, gravity); }; function createMetadatas(prideflag, text, now = false) { const filename = createFilename(prideflag, text, now); const textForAlt = text.replaceAll("\n", " ").toLowerCase(); const alt = `Drapeau ${prideflag.name.fr.toLowerCase()} (${prideflag.alt.fr}) avec écrit "${textForAlt}${now?", now!": ""}"` const alten = `${capitalizeFirstLetter(prideflag.name.en)} flag (${prideflag.alt.en}) with written "${textForAlt}${now?", now!": ""}"` return {file:filename, alt:alt, localizedAlt:{en: alten, fr: alt}, text:textForAlt}; } // Prepare folders const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); fs.mkdirSync(path.join(__dirname, 'build'), { recursive: true }); fs.mkdirSync(path.join(__dirname, 'output'), { recursive: true }); fs.mkdirSync(path.join(__dirname, 'tmp'), { recursive: true }); // Start generating let count = 0; let flagCount = 0; const start = Date.now(); data.forEach(prideflag => { console.log(`- Creating flags for ${prideflag.name.en}`); const imageMetadata = {title:`Drapeau ${prideflag.name.fr.toLowerCase()} :`, list:[]}; prideflag.texts.forEach(text => { const metadatas = createMetadatas(prideflag, text, false) imageMetadata.list.push(metadatas); //console.log(`Creating button for text "${metadatas.text}" (${metadatas.file})`); createButton(prideflag.source, position.x, position.y, text, position.gravity) .write(`./output/${metadatas.file}`, function (err) { if (err) { console.error(err); throw err; }; }); count++; }) if (prideflag.textsNow) { prideflag.textsNow.forEach(text => { const metadatas = createMetadatas(prideflag, text, true) imageMetadata.list.push(metadatas); //console.log(`Creating button for text "${metadatas.text}" (${metadatas.file})`); createButton(prideflag.source, position.x+12, position.y, text, position.gravity) .write(`./tmp/${metadatas.file}`, function (err) { if (err) { console.error(err); throw err; }; }); setTimeout(() => { myGm(`./tmp/${metadatas.file}`) .composite("./sources/now.gif") .write(`./output/${metadatas.file}`, function (err) { if (err) { console.error(err); throw err; }; }); }, 100); count++; }) } flagCount++; metadatas.push(imageMetadata); }); fs.writeFile("./output/pridebuttons.json", JSON.stringify(metadatas), (err) => { if (err) { console.error(err); throw err; } }); // Zip the folder var output = fs.createWriteStream(`build/${zipname}`); var archive = archiver('zip'); var size = 0; output.on('close', function () { size = archive.pointer(); console.log('archiver has been finalized and the output file descriptor has closed.'); }); archive.on('error', function(err){ throw err; }); archive.pipe(output); // append files from a sub-directory, putting its contents at the root of archive archive.directory('output/', false); await archive.finalize(); // Show final result const millis = Date.now() - start; setTimeout(() => { console.log(""); console.log("-----------------------"); console.log(""); console.log(`Pride Button version ${VERSION}`); console.log(`Generation finished in ${millis / 1000}s`); console.log(`${flagCount} flags processed`); console.log(`${count} files generated`); console.log(`Archive name : ${zipname}`); console.log(`Archive size : ${size/1000} kB`); }, 500);