#!/usr/bin/env node /** * create | delete | clone | rename — cohérence slides + portail (sync). */ import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { execFileSync } from 'node:child_process' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const root = path.resolve(__dirname, '..') function sync() { execFileSync(process.execPath, [path.join(root, 'tools', 'sync-portal.mjs')], { stdio: 'inherit', cwd: root, env: process.env, }) } function assertSlug(s, label = 'slug') { if (!s || typeof s !== 'string') throw new Error(`${label} manquant`) if (!/^[a-z0-9-]+$/.test(s)) throw new Error(`${label} invalide (a-z 0-9 -): ${s}`) if (s.length < 2) throw new Error(`${label} trop court`) if (s === 'portal') throw new Error('slug réservé') } const cmd = process.argv[2] const a = process.argv[3] const b = process.argv[4] try { if (cmd === 'create') { assertSlug(a) const dir = path.join(root, 'slides', a) if (fs.existsSync(dir)) throw new Error(`existe déjà: slides/${a}/`) fs.mkdirSync(dir, { recursive: true }) fs.writeFileSync( path.join(dir, 'meta.json'), JSON.stringify( { title: 'Nouvelle présentation', description: '', order: 99, tags: [], }, null, 2, ), 'utf8', ) fs.writeFileSync( path.join(dir, 'slides.md'), ['---', 'title: Nouvelle présentation', '---', '', '# Bienvenue', ''].join('\n'), 'utf8', ) sync() console.log(`[create] slides/${a}/ — lancez make run ou make build`) } else if (cmd === 'delete') { assertSlug(a) fs.rmSync(path.join(root, 'slides', a), { recursive: true, force: true }) fs.rmSync(path.join(root, `dist-${a}`), { recursive: true, force: true }) sync() console.log(`[delete] ${a} retiré`) } else if (cmd === 'clone') { assertSlug(a, 'source') assertSlug(b, 'dest') const src = path.join(root, 'slides', a) const dst = path.join(root, 'slides', b) if (!fs.existsSync(src)) throw new Error(`source absente: slides/${a}/`) if (fs.existsSync(dst)) throw new Error(`dest existe: slides/${b}/`) fs.cpSync(src, dst, { recursive: true }) const metaPath = path.join(dst, 'meta.json') const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')) meta.title = `${meta.title || a} (copie)` fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf8') sync() console.log(`[clone] ${a} → ${b} — build: node tools/build-deck.mjs ${b}`) } else if (cmd === 'rename') { assertSlug(a, 'ancien') assertSlug(b, 'nouveau') const src = path.join(root, 'slides', a) const dst = path.join(root, 'slides', b) if (!fs.existsSync(src)) throw new Error(`slides/${a}/ absent`) if (fs.existsSync(dst)) throw new Error(`slides/${b}/ existe déjà`) fs.renameSync(src, dst) const metaPath = path.join(dst, 'meta.json') const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')) delete meta.slug fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf8') const oldDist = path.join(root, `dist-${a}`) const newDist = path.join(root, `dist-${b}`) if (fs.existsSync(oldDist)) { fs.renameSync(oldDist, newDist) } sync() console.log(`[rename] ${a} → ${b}`) } else { console.error('usage: node tools/presentation-cli.mjs [args]') process.exit(1) } } catch (e) { console.error(String(e.message || e)) process.exit(1) }