import crypto from 'node:crypto'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import pLimit from 'p-limit'; import { createThumbnailFromTemplate } from './template-thumbnail-utils.mjs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const limit = pLimit(4); function calcHash(content) { return crypto.createHash('md5').update(content, 'utf8').digest('hex'); } async function main() { const playgroundPath = path.resolve(__dirname, '..'); const templatesPath = path.join(playgroundPath, 'public', 'template-assets'); const hashMapPath = path.join(__dirname, 'thumbnail-hash-map.json'); let hashMap = {}; if (fs.existsSync(hashMapPath)) { try { hashMap = JSON.parse(fs.readFileSync(hashMapPath, 'utf-8')); } catch (error) { console.warn('Failed to parse thumbnail-hash-map.json. Initializing empty map.'); } } const dirs = fs .readdirSync(templatesPath, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) .map((dirent) => dirent.name); const processDir = async (dir) => { const templateJsonPath = path.join(templatesPath, dir, 'template.json'); if (!fs.existsSync(templateJsonPath)) { return; } const templateJsonStr = fs.readFileSync(templateJsonPath, 'utf-8'); const currentHash = calcHash(templateJsonStr); if (hashMap[dir] && hashMap[dir] === currentHash) { console.log(`No changes in ${dir}. Skipping thumbnail generation.`); return; } const thumbnailPngPath = path.join(templatesPath, dir, 'thumbnail.png'); await createThumbnailFromTemplate(templateJsonPath, thumbnailPngPath); hashMap[dir] = currentHash; console.log(`Generated thumbnail for ${dir}.`); }; await Promise.all(dirs.map((dir) => limit(() => processDir(dir)))); fs.writeFileSync(hashMapPath, JSON.stringify(hashMap, null, 2), 'utf-8'); console.log('Thumbnails generation process completed!'); } main().catch((err) => { console.error(err); process.exit(1); });