#!/usr/bin/env node import * as fs from 'fs'; import * as path from 'path'; import { glob } from 'glob'; interface SidebarItem { type: 'doc' | 'category'; id?: string; label?: string; items?: SidebarItem[]; } interface SidebarConfig { [key: string]: SidebarItem[]; } class SidebarBuilder { private docsRoot: string; private domainOrder = ['overview', 'product', 'backend', 'frontend', 'rust', 'infra', 'security', 'ops', 'legal', 'misc']; constructor(docsRoot: string) { this.docsRoot = docsRoot; } async buildSidebars(): Promise { console.log('📚 Génération des sidebars...'); await this.buildSidebar('current'); await this.buildSidebar('vision'); console.log('✅ Sidebars générés avec succès!'); } private async buildSidebar(track: 'current' | 'vision'): Promise { const trackPath = path.join(this.docsRoot, track); const sidebarPath = path.join(trackPath, 'sidebars.js'); console.log(`📖 Génération de la sidebar pour ${track}...`); const sidebar: SidebarItem[] = []; // Ajouter la page overview const overviewPath = path.join(trackPath, 'overview.md'); if (fs.existsSync(overviewPath)) { sidebar.push({ type: 'doc', id: 'overview' }); } // Parcourir les domaines for (const domain of this.domainOrder) { const domainPath = path.join(trackPath, 'domains', domain); if (fs.existsSync(domainPath)) { const domainItems = await this.buildDomainSidebar(domainPath, domain); if (domainItems.length > 0) { sidebar.push({ type: 'category', label: this.getDomainLabel(domain), items: domainItems }); } } } // Générer le contenu JavaScript const sidebarContent = this.generateSidebarContent(sidebar, track); fs.writeFileSync(sidebarPath, sidebarContent); console.log(`✅ Sidebar ${track} générée: ${sidebarPath}`); } private async buildDomainSidebar(domainPath: string, domain: string): Promise { const items: SidebarItem[] = []; // Chercher tous les fichiers .md et .mdx const patterns = ['*.md', '*.mdx']; const allFiles: string[] = []; for (const pattern of patterns) { const files = await glob(pattern, { cwd: domainPath }); allFiles.push(...files); } // Trier les fichiers allFiles.sort((a, b) => { // Mettre les fichiers README en premier if (a.toLowerCase().includes('readme')) return -1; if (b.toLowerCase().includes('readme')) return 1; // Puis trier alphabétiquement return a.localeCompare(b); }); // Créer les items de sidebar for (const file of allFiles) { const filePath = path.join(domainPath, file); const content = fs.readFileSync(filePath, 'utf-8'); const frontmatter = this.extractFrontmatter(content); const slug = path.basename(file, path.extname(file)); items.push({ type: 'doc', id: `${domain}/${slug}`, label: frontmatter.sidebar_label || frontmatter.title || this.generateLabelFromFilename(file) }); } return items; } private extractFrontmatter(content: string): Record { const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/; const match = content.match(frontmatterRegex); if (!match) return {}; const frontmatterText = match[1]; const frontmatter: Record = {}; frontmatterText.split('\n').forEach(line => { const [key, ...valueParts] = line.split(':'); if (key && valueParts.length > 0) { const value = valueParts.join(':').trim(); frontmatter[key.trim()] = value.replace(/^["']|["']$/g, ''); } }); return frontmatter; } private generateLabelFromFilename(filename: string): string { const baseName = path.basename(filename, path.extname(filename)); return baseName .replace(/[-_]/g, ' ') .replace(/\b\w/g, l => l.toUpperCase()); } private getDomainLabel(domain: string): string { const labels: Record = { 'overview': '📋 Aperçu', 'product': '🎯 Produit', 'backend': '⚙️ Backend', 'frontend': '🎨 Frontend', 'rust': '🦀 Rust', 'infra': '🏗️ Infrastructure', 'security': '🔒 Sécurité', 'ops': '🔧 Opérations', 'legal': '📜 Légal', 'misc': '📁 Divers' }; return labels[domain] || domain; } private generateSidebarContent(sidebar: SidebarItem[], track: string): string { const sidebarJson = JSON.stringify(sidebar, null, 2); return `/** * @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} * Sidebar généré automatiquement pour ${track} * * Généré le: ${new Date().toISOString()} */ const sidebars = { ${track}Sidebar: ${sidebarJson} }; module.exports = sidebars; `; } async run(): Promise { console.log('📚 Démarrage de la génération des sidebars...'); try { await this.buildSidebars(); console.log('✅ Génération des sidebars terminée!'); } catch (error) { console.error('❌ Erreur lors de la génération des sidebars:', error); process.exit(1); } } } // Exécution du script if (require.main === module) { const docsRoot = process.argv[2] || path.join(__dirname, '..'); const builder = new SidebarBuilder(docsRoot); builder.run(); } export { SidebarBuilder };