import fs from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..') const source = path.join(root, 'content/tutorials') const output = path.join(root, 'public/tutorials') let layout = await fs.readFile(path.join(root, 'resources/tutorials/layout.html'), 'utf8') if (process.argv.includes('--live-reload')) { layout = layout.replace('', `@if(in_array(request()->getHost(), ['localhost', '127.0.0.1'])) @endif `) } const registry = {} const views = path.join(root, 'resources/views/tutorials') await fs.mkdir(path.join(output, 'assets'), {recursive: true}) await fs.copyFile(path.join(root, 'resources/tutorials/tutorial.css'), path.join(output, 'assets/tutorial.css')) if (process.argv.includes('--live-reload')) await fs.copyFile(path.join(root, 'resources/tutorials/live-reload.js'), path.join(output, 'assets/live-reload.js')) for (const platform of await fs.readdir(source, {withFileTypes: true})) { if (!platform.isDirectory()) continue for (const client of await fs.readdir(path.join(source, platform.name), {withFileTypes: true})) { if (!client.isDirectory()) continue const folder = path.join(source, platform.name, client.name) const meta = JSON.parse(await fs.readFile(path.join(folder, 'meta.json'), 'utf8')) if (meta.platform !== platform.name || meta.client !== client.name || !/^[a-z0-9-]+$/.test(platform.name) || !/^[a-z0-9-]+$/.test(client.name)) throw new Error('Invalid tutorial location') const prefix = `/tutorials/${platform.name}/${client.name}` let body = await fs.readFile(path.join(folder, `${meta.language}.html`), 'utf8') for (const match of body.matchAll(/src="\.\/images\/([^"]+)"/g)) await fs.access(path.join(folder, 'images', match[1])) body = body.replaceAll('src="./images/', `src="${prefix}/images/`) const escape = value => value.replaceAll('&','&').replaceAll('<','<').replaceAll('"','"') const html = layout.replace('{{language}}', escape(meta.language)).replace('{{title}}', escape(meta.title)).replace('{{body}}', body).replaceAll('{{brand}}', '{{ $brand }}') await fs.mkdir(path.join(output, platform.name), {recursive:true}) await fs.mkdir(path.join(views, platform.name), {recursive:true}) await fs.writeFile(path.join(views, platform.name, `${client.name}.blade.php`), html) // Remove legacy static HTML so Laravel can inject the current configured name. await fs.rm(path.join(output, platform.name, `${client.name}.html`), {force:true}) await fs.cp(path.join(folder,'images'), path.join(output,platform.name,client.name,'images'),{recursive:true}) registry[platform.name] = prefix + '.html' } } const generated = path.join(root, 'stellar/src/generated') await fs.mkdir(generated,{recursive:true}) await fs.writeFile(path.join(generated,'tutorials.ts'), '// Generated by scripts/tutorials/build.mjs\nexport const tutorialPages: Record = '+JSON.stringify(registry,null,2)+'\n') console.log(`Built ${Object.keys(registry).length} independent tutorial page(s).`)