import fs from 'fs'; const defaultConfig = { "domains": ["mempool.space"], "theme": "default", "enterprise": "mempool", "branding": { "name": "mempool", "title": "mempool", "site_id": 5, }, "meta": { "title": "mempool - Bitcoin Explorer", "description": "Explore the full Bitcoin ecosystem with The Mempool Open Source Project®. See the real-time status of your transactions, get network info, and more.", }, "unfurls": { "preview": { "src": "https://mempool.space/resources/previews/mempool-space-preview.jpg", "type": "image/jpeg", "width": "2000", "height": "1000" } } } function deepMerge(target, source) { for (const key in source) { if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { target[key] = target[key] || {}; deepMerge(target[key], source[key]); } else { target[key] = source[key]; } } return target; } function addDefaultsToConfig(config) { return deepMerge(structuredClone(defaultConfig), config); } function substitute(indexhtml, config) { let newhtml = indexhtml; // substitute title newhtml = newhtml.replace(/\<\!\-\- TITLE \-\-\>.*\<\!\-\- END TITLE \-\-\>/gis, `${config.meta.title}`); // substitute customization script newhtml = newhtml.replace(/\<\!\-\- CUSTOMIZATION \-\-\>.*\<\!\-\- END CUSTOMIZATION \-\-\>/gis, ``); // substitute meta tags newhtml = newhtml.replace(/\<\!\-\- META \-\-\>.*\<\!\-\- END META \-\-\>/gis, ` `); // substitute favicons newhtml = newhtml.replace(/\<\!\-\- FAVICONS -->.*\<\!\-\- END FAVICONS \-\-\>/gis, ` `); return newhtml; } async function run() { const servicesHost = process.argv[2] || 'http://localhost:9000'; const mempoolDir = process.argv[3] || '../'; console.log('fetching list of custom builds'); const customBuilds = await (await fetch(`${servicesHost}/api/v1/services/custom/list`)).json(); // fetch config for each custom build from `$SERVICES/api/v1/services/custom/config/` const customConfigs = await Promise.all(customBuilds.map(async (build) => { console.log(`fetching config for ${build} `); return addDefaultsToConfig(await (await fetch(`${servicesHost}/api/v1/services/custom/config/${build}`)).json()); })); // for each custom build config: let i = 0; for (const config of customConfigs) { console.log(`generating ${config.enterprise} build (${i + 1}/${customConfigs.length})`); const browserDir = `${mempoolDir}/frontend/dist/mempool/browser`; const locales = fs.readdirSync(browserDir) .filter(file => fs.statSync(`${browserDir}/${file}`).isDirectory()) .filter(file => fs.existsSync(`${browserDir}/${file}/index.html`)); // Process each locale's index.html for (const locale of locales) { const indexPath = `${browserDir}/${locale}/index.html`; const indexContent = fs.readFileSync(indexPath, 'utf-8').toString(); const processedHtml = substitute(indexContent, config); // Save processed HTML const outputPath = `${browserDir}/${locale}/index.${config.enterprise}.html`; fs.writeFileSync(outputPath, processedHtml); console.log(`updated index.${config.enterprise}.html for locale ${locale}`); } console.log(`finished generating ${config.enterprise} build`); i++; } console.log('finished updating custom builds'); } run();