docstodev 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +1 -1
  2. package/src/ai/analyzer.ts +3 -1
  3. package/src/analyzers/languageAnalyzer.ts +297 -5
  4. package/src/commands/generateSummary.ts +129 -39
  5. package/src/exporters/html.ts +134 -52
  6. package/.env +0 -1
  7. package/dist/ai/analyzer.d.ts +0 -3
  8. package/dist/ai/analyzer.d.ts.map +0 -1
  9. package/dist/ai/analyzer.js +0 -43
  10. package/dist/ai/analyzer.js.map +0 -1
  11. package/dist/analyzers/languageAnalyzer.d.ts +0 -18
  12. package/dist/analyzers/languageAnalyzer.d.ts.map +0 -1
  13. package/dist/analyzers/languageAnalyzer.js +0 -251
  14. package/dist/analyzers/languageAnalyzer.js.map +0 -1
  15. package/dist/cache/cacheManager.d.ts +0 -38
  16. package/dist/cache/cacheManager.d.ts.map +0 -1
  17. package/dist/cache/cacheManager.js +0 -141
  18. package/dist/cache/cacheManager.js.map +0 -1
  19. package/dist/cli/index.d.ts +0 -3
  20. package/dist/cli/index.d.ts.map +0 -1
  21. package/dist/cli/index.js +0 -316
  22. package/dist/cli/index.js.map +0 -1
  23. package/dist/commands/classify.d.ts +0 -2
  24. package/dist/commands/classify.d.ts.map +0 -1
  25. package/dist/commands/classify.js +0 -37
  26. package/dist/commands/classify.js.map +0 -1
  27. package/dist/commands/generateSummary.d.ts +0 -5
  28. package/dist/commands/generateSummary.d.ts.map +0 -1
  29. package/dist/commands/generateSummary.js +0 -54
  30. package/dist/commands/generateSummary.js.map +0 -1
  31. package/dist/commands/run.d.ts +0 -5
  32. package/dist/commands/run.d.ts.map +0 -1
  33. package/dist/commands/run.js +0 -326
  34. package/dist/commands/run.js.map +0 -1
  35. package/dist/exporters/html.d.ts +0 -6
  36. package/dist/exporters/html.d.ts.map +0 -1
  37. package/dist/exporters/html.js +0 -517
  38. package/dist/exporters/html.js.map +0 -1
  39. package/src/commands/classify.ts +0 -40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docstodev",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Solution d’automatisation de documentation technique intelligente avec IA",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -19,7 +19,9 @@ Instructions :
19
19
  - Vous allez recevoir une liste de fichiers, leurs rôles et leurs exports.
20
20
  - Pour chaque fichier, rédigez UNE SEULE phrase concise expliquant sa responsabilité métier.
21
21
  - Soyez pro, mais gardez votre touche amicale et votre pointe d'humour du Congo-Brazzaville.
22
- - Ne mentionnez pas de code technique (pas de "il y a une fonction X"), expliquez le BUT du fichier.
22
+ - mentionnez les imports, technique ( "il y a une fonction X"), expliquez le BUT du fichier.
23
+ - selon le nombre d'occurance précisez les couleurs qui reviennen souvent eu suggérez un design systèm , pallette de couleur.
24
+ - donnez une très bref description du but de l'ensemble du projet.
23
25
  `;
24
26
 
25
27
  try {
@@ -9,6 +9,7 @@ export interface FileAnalysisResult {
9
9
  types: string[];
10
10
  imports: Array<{ name: string; type: string; usage?: string | undefined }>;
11
11
  exports: string[];
12
+ structure?: Record<string, any>; // Pour les fichiers non-standards
12
13
  }
13
14
 
14
15
  // Analyseur TypeScript/JavaScript
@@ -25,7 +26,6 @@ class TSJSAnalyzer implements LanguageAnalyzer {
25
26
 
26
27
  const functions: string[] = [];
27
28
  const funcRegex = /(?:export\s+)?(?:async\s+)?function\s+([a-zA-Z0-9_]+)/g;
28
- // Resetting regex because of global flag
29
29
  funcRegex.lastIndex = 0;
30
30
  while ((match = funcRegex.exec(content)) !== null) {
31
31
  if (match[1]) functions.push(match[1]);
@@ -266,6 +266,282 @@ class RustAnalyzer implements LanguageAnalyzer {
266
266
  }
267
267
  }
268
268
 
269
+ // Analyseur HTML
270
+ class HTMLAnalyzer implements LanguageAnalyzer {
271
+ extensions = [".html", ".htm"];
272
+
273
+ analyzeFile(content: string): FileAnalysisResult {
274
+ const structure: Record<string, any> = {
275
+ tags: new Set<string>(),
276
+ ids: [] as string[],
277
+ classes: [] as string[],
278
+ scripts: [] as string[],
279
+ styles: [] as string[]
280
+ };
281
+
282
+ // Extraire les balises
283
+ const tagRegex = /<(\w+)/g;
284
+ let match: RegExpExecArray | null;
285
+ while ((match = tagRegex.exec(content)) !== null) {
286
+ if (match[1]) structure.tags.add(match[1].toLowerCase());
287
+ }
288
+
289
+ // Extraire les IDs
290
+ const idRegex = /id=["']([^"']+)["']/g;
291
+ while ((match = idRegex.exec(content)) !== null) {
292
+ if (match[1]) structure.ids.push(match[1]);
293
+ }
294
+
295
+ // Extraire les classes
296
+ const classRegex = /class=["']([^"']+)["']/g;
297
+ while ((match = classRegex.exec(content)) !== null) {
298
+ if (match[1]) {
299
+ structure.classes.push(...match[1].split(/\s+/).filter(Boolean));
300
+ }
301
+ }
302
+
303
+ // Extraire les scripts externes
304
+ const scriptRegex = /<script[^>]+src=["']([^"']+)["']/g;
305
+ while ((match = scriptRegex.exec(content)) !== null) {
306
+ if (match[1]) structure.scripts.push(match[1]);
307
+ }
308
+
309
+ // Extraire les stylesheets externes
310
+ const linkRegex = /<link[^>]+href=["']([^"']+\.css)["']/g;
311
+ while ((match = linkRegex.exec(content)) !== null) {
312
+ if (match[1]) structure.styles.push(match[1]);
313
+ }
314
+
315
+ structure.tags = Array.from(structure.tags);
316
+
317
+ return {
318
+ functions: [],
319
+ classes: structure.classes,
320
+ types: [],
321
+ imports: [
322
+ ...structure.scripts.map((s : string) => ({ name: s, type: 'Script' })),
323
+ ...structure.styles.map((s:string) => ({ name: s, type: 'Stylesheet' }))
324
+ ],
325
+ exports: [],
326
+ structure
327
+ };
328
+ }
329
+ }
330
+
331
+ // Analyseur CSS/SCSS/SASS
332
+ class CSSAnalyzer implements LanguageAnalyzer {
333
+ extensions = [".css", ".scss", ".sass", ".less"];
334
+
335
+ analyzeFile(content: string): FileAnalysisResult {
336
+ const structure: Record<string, any> = {
337
+ selectors: [] as string[],
338
+ ids: [] as string[],
339
+ classes: [] as string[],
340
+ variables: [] as string[],
341
+ mixins: [] as string[],
342
+ imports: [] as string[]
343
+ };
344
+
345
+ // Classes CSS
346
+ const classRegex = /\.([a-zA-Z0-9_-]+)/g;
347
+ let match: RegExpExecArray | null;
348
+ while ((match = classRegex.exec(content)) !== null) {
349
+ if (match[1] && !structure.classes.includes(match[1])) {
350
+ structure.classes.push(match[1]);
351
+ }
352
+ }
353
+
354
+ // IDs CSS
355
+ const idRegex = /#([a-zA-Z0-9_-]+)/g;
356
+ while ((match = idRegex.exec(content)) !== null) {
357
+ if (match[1] && !structure.ids.includes(match[1])) {
358
+ structure.ids.push(match[1]);
359
+ }
360
+ }
361
+
362
+ // Variables CSS/SCSS
363
+ const varRegex = /(?:--|\$)([a-zA-Z0-9_-]+)/g;
364
+ while ((match = varRegex.exec(content)) !== null) {
365
+ if (match[1] && !structure.variables.includes(match[1])) {
366
+ structure.variables.push(match[1]);
367
+ }
368
+ }
369
+
370
+ // Mixins SCSS
371
+ const mixinRegex = /@mixin\s+([a-zA-Z0-9_-]+)/g;
372
+ while ((match = mixinRegex.exec(content)) !== null) {
373
+ if (match[1]) structure.mixins.push(match[1]);
374
+ }
375
+
376
+ // Imports
377
+ const importRegex = /@import\s+['"]([^'"]+)['"]/g;
378
+ while ((match = importRegex.exec(content)) !== null) {
379
+ if (match[1]) structure.imports.push(match[1]);
380
+ }
381
+
382
+ return {
383
+ functions: structure.mixins,
384
+ classes: structure.classes,
385
+ types: [],
386
+ imports: structure.imports.map((i:string) => ({ name: i, type: 'CSS' })),
387
+ exports: [],
388
+ structure
389
+ };
390
+ }
391
+ }
392
+
393
+ // Analyseur PHP
394
+ class PHPAnalyzer implements LanguageAnalyzer {
395
+ extensions = [".php"];
396
+
397
+ analyzeFile(content: string): FileAnalysisResult {
398
+ const functions: string[] = [];
399
+ const funcRegex = /function\s+([a-zA-Z0-9_]+)\s*\(/g;
400
+ let match: RegExpExecArray | null;
401
+ while ((match = funcRegex.exec(content)) !== null) {
402
+ if (match[1]) functions.push(match[1]);
403
+ }
404
+
405
+ const classes: string[] = [];
406
+ const classRegex = /class\s+([a-zA-Z0-9_]+)/g;
407
+ while ((match = classRegex.exec(content)) !== null) {
408
+ if (match[1]) classes.push(match[1]);
409
+ }
410
+
411
+ const imports: Array<{ name: string; type: string; usage?: string | undefined }> = [];
412
+ const useRegex = /use\s+([a-zA-Z0-9_\\]+)/g;
413
+ while ((match = useRegex.exec(content)) !== null) {
414
+ if (match[1]) {
415
+ imports.push({ name: match[1], type: 'Composer' });
416
+ }
417
+ }
418
+
419
+ const requireRegex = /(?:require|include)(?:_once)?\s*['"]([^'"]+)['"]/g;
420
+ while ((match = requireRegex.exec(content)) !== null) {
421
+ if (match[1]) {
422
+ imports.push({ name: match[1], type: 'Local' });
423
+ }
424
+ }
425
+
426
+ return { functions, classes, types: [], imports, exports: [] };
427
+ }
428
+ }
429
+
430
+ // Analyseur Ruby
431
+ class RubyAnalyzer implements LanguageAnalyzer {
432
+ extensions = [".rb"];
433
+
434
+ analyzeFile(content: string): FileAnalysisResult {
435
+ const functions: string[] = [];
436
+ const funcRegex = /def\s+([a-zA-Z0-9_?!]+)/g;
437
+ let match: RegExpExecArray | null;
438
+ while ((match = funcRegex.exec(content)) !== null) {
439
+ if (match[1]) functions.push(match[1]);
440
+ }
441
+
442
+ const classes: string[] = [];
443
+ const classRegex = /class\s+([a-zA-Z0-9_]+)/g;
444
+ while ((match = classRegex.exec(content)) !== null) {
445
+ if (match[1]) classes.push(match[1]);
446
+ }
447
+
448
+ const imports: Array<{ name: string; type: string; usage?: string | undefined }> = [];
449
+ const requireRegex = /require\s+['"]([^'"]+)['"]/g;
450
+ while ((match = requireRegex.exec(content)) !== null) {
451
+ if (match[1]) {
452
+ imports.push({ name: match[1], type: 'Gem' });
453
+ }
454
+ }
455
+
456
+ return { functions, classes, types: [], imports, exports: [] };
457
+ }
458
+ }
459
+
460
+ // Analyseur SQL
461
+ class SQLAnalyzer implements LanguageAnalyzer {
462
+ extensions = [".sql"];
463
+
464
+ analyzeFile(content: string): FileAnalysisResult {
465
+ const structure: Record<string, any> = {
466
+ tables: [] as string[],
467
+ procedures: [] as string[],
468
+ functions: [] as string[],
469
+ views: [] as string[]
470
+ };
471
+
472
+ const tableRegex = /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([a-zA-Z0-9_]+)/gi;
473
+ let match: RegExpExecArray | null;
474
+ while ((match = tableRegex.exec(content)) !== null) {
475
+ if (match[1]) structure.tables.push(match[1]);
476
+ }
477
+
478
+ const procRegex = /CREATE\s+(?:OR\s+REPLACE\s+)?PROCEDURE\s+([a-zA-Z0-9_]+)/gi;
479
+ while ((match = procRegex.exec(content)) !== null) {
480
+ if (match[1]) structure.procedures.push(match[1]);
481
+ }
482
+
483
+ const funcRegex = /CREATE\s+(?:OR\s+REPLACE\s+)?FUNCTION\s+([a-zA-Z0-9_]+)/gi;
484
+ while ((match = funcRegex.exec(content)) !== null) {
485
+ if (match[1]) structure.functions.push(match[1]);
486
+ }
487
+
488
+ const viewRegex = /CREATE\s+(?:OR\s+REPLACE\s+)?VIEW\s+([a-zA-Z0-9_]+)/gi;
489
+ while ((match = viewRegex.exec(content)) !== null) {
490
+ if (match[1]) structure.views.push(match[1]);
491
+ }
492
+
493
+ return {
494
+ functions: structure.functions,
495
+ classes: structure.tables,
496
+ types: structure.views,
497
+ imports: [],
498
+ exports: [],
499
+ structure
500
+ };
501
+ }
502
+ }
503
+
504
+ // Analyseur par défaut pour tous les autres fichiers
505
+ class DefaultAnalyzer implements LanguageAnalyzer {
506
+ extensions = ["*"]; // Wildcard pour tous les fichiers
507
+
508
+ analyzeFile(content: string): FileAnalysisResult {
509
+ const lines = content.split(/\r?\n/);
510
+ const structure: Record<string, any> = {
511
+ lineCount: lines.length,
512
+ nonEmptyLines: lines.filter(l => l.trim().length > 0).length,
513
+ size: content.length,
514
+ hasCode: /[a-zA-Z0-9_]+\s*[=:({]/.test(content),
515
+ encoding: 'UTF-8'
516
+ };
517
+
518
+ // Détection basique de patterns communs
519
+ const patterns = {
520
+ functions: [] as string[],
521
+ variables: [] as string[],
522
+ comments: [] as string[]
523
+ };
524
+
525
+ // Détection générique de fonctions (pattern commun à beaucoup de langages)
526
+ const genericFuncRegex = /(?:function|func|def|fn|sub|procedure)\s+([a-zA-Z0-9_]+)/gi;
527
+ let match: RegExpExecArray | null;
528
+ while ((match = genericFuncRegex.exec(content)) !== null) {
529
+ if (match[1]) patterns.functions.push(match[1]);
530
+ }
531
+
532
+ structure.patterns = patterns;
533
+
534
+ return {
535
+ functions: patterns.functions,
536
+ classes: [],
537
+ types: [],
538
+ imports: [],
539
+ exports: [],
540
+ structure
541
+ };
542
+ }
543
+ }
544
+
269
545
  // Registry des analyseurs
270
546
  const analyzers: LanguageAnalyzer[] = [
271
547
  new TSJSAnalyzer(),
@@ -273,16 +549,32 @@ const analyzers: LanguageAnalyzer[] = [
273
549
  new JavaAnalyzer(),
274
550
  new CSharpAnalyzer(),
275
551
  new GoAnalyzer(),
276
- new RustAnalyzer()
552
+ new RustAnalyzer(),
553
+ new HTMLAnalyzer(),
554
+ new CSSAnalyzer(),
555
+ new PHPAnalyzer(),
556
+ new RubyAnalyzer(),
557
+ new SQLAnalyzer()
277
558
  ];
278
559
 
279
- export function getAnalyzer(filePath: string): LanguageAnalyzer | null {
560
+ const defaultAnalyzer = new DefaultAnalyzer();
561
+
562
+ export function getAnalyzer(filePath: string): LanguageAnalyzer {
280
563
  const lastDotIndex = filePath.lastIndexOf('.');
281
- if (lastDotIndex === -1) return null;
564
+ if (lastDotIndex === -1) return defaultAnalyzer;
565
+
282
566
  const ext = filePath.substring(lastDotIndex).toLowerCase();
283
- return analyzers.find(a => a.extensions.includes(ext)) || null;
567
+ return analyzers.find(a => a.extensions.includes(ext)) || defaultAnalyzer;
284
568
  }
285
569
 
286
570
  export function getSupportedExtensions(): string[] {
287
571
  return analyzers.flatMap(a => a.extensions);
572
+ }
573
+
574
+ export function isExplicitlySupported(filePath: string): boolean {
575
+ const lastDotIndex = filePath.lastIndexOf('.');
576
+ if (lastDotIndex === -1) return false;
577
+
578
+ const ext = filePath.substring(lastDotIndex).toLowerCase();
579
+ return analyzers.some(a => a.extensions.includes(ext));
288
580
  }
@@ -3,55 +3,145 @@
3
3
  import { writeFileSync, mkdirSync } from "node:fs";
4
4
  import path from "node:path";
5
5
 
6
+ interface SummaryData {
7
+ totalFiles: number;
8
+ sourceFiles?: number;
9
+ totalComplexity?: number;
10
+ avgComplexity?: number;
11
+ totalDeps?: number;
12
+ topLanguages?: { lang: string; count: number }[];
13
+ criticalFiles?: string[];
14
+ }
15
+
6
16
  /**
7
17
  * Génère un résumé global du projet avec un ton humain et bilingue.
8
18
  */
9
- export function generateSummary(docsDir: string, totalFiles: number, lang: "fr" | "en" = "fr") {
19
+ export function generateSummary(
20
+ docsDir: string,
21
+ data: SummaryData | number,
22
+ lang: "fr" | "en" = "fr"
23
+ ) {
10
24
  mkdirSync(docsDir, { recursive: true });
11
25
 
12
- const dateStr = new Date().toLocaleString();
13
-
14
- // Contenu bilingue avec un ton "Expert & Humain"
15
- const content = lang === "fr"
16
- ? `# 📊 Vue d'ensemble du Projet – DocsToDev
17
-
18
- > 📅 **Rapport généré le :** ${dateStr}
19
-
20
- ## 🚀 État des lieux
21
- Salut ! J'ai passé ton projet au peigne fin. Voici un résumé rapide de ce que j'ai trouvé :
22
- - **Volume traité :** ${totalFiles} fichiers analysés avec succès.
23
- - **Diagnostic :** La structure est claire et l'analyse est complète. ✅
24
-
25
- ## 🧭 Navigation Rapide
26
- Pour aller plus loin, tu peux consulter les documents suivants :
27
- - **[📂 Arborescence & Analyse](../docs/docs-to-dev.md)** : Pour comprendre la vocation de chaque fichier et les capacités du système.
28
- - **[💻 Code Source](../)** : Pour retourner explorer la racine de ton projet.
29
-
30
- ---
31
- *DocsToDev – Ton allié pour une documentation technique vivante et intelligente.*
32
- `
33
- : `# 📊 Project Overview – DocsToDev
26
+ // Support de l'ancien format (juste un nombre) et du nouveau format (objet complet)
27
+ const summaryData: SummaryData = typeof data === 'number'
28
+ ? { totalFiles: data }
29
+ : data;
34
30
 
35
- > 📅 **Generated on:** ${dateStr}
36
-
37
- ## 🚀 Project Status
38
- Hey! I've scanned your entire codebase. Here's a quick summary of the findings:
39
- - **Volume processed:** ${totalFiles} files successfully analyzed.
40
- - **Diagnosis:** The structure is clear and the analysis is complete. ✅
41
-
42
- ## 🧭 Quick Navigation
43
- To dive deeper, check out these documents:
44
- - **[📂 Tree & Analysis](../docs/docs-to-dev.md)**: Explore file purposes and system capabilities.
45
- - **[💻 Source Code](../)**: Head back to the project root.
46
-
47
- ---
48
- *DocsToDev – Your partner for living and intelligent technical documentation.*
49
- `;
31
+ const dateStr = new Date().toLocaleString(lang === "fr" ? "fr-FR" : "en-US", {
32
+ dateStyle: "full",
33
+ timeStyle: "short"
34
+ });
35
+
36
+ const t = lang === "fr" ? {
37
+ title: "📊 Vue d'ensemble du Projet – DocsToDev",
38
+ genOn: "Rapport généré le",
39
+ status: "🚀 État des lieux",
40
+ intro: "Salut ! J'ai passé ton projet au peigne fin. Voici un résumé rapide de ce que j'ai trouvé :",
41
+ volume: "Volume traité",
42
+ filesAnalyzed: "fichiers analysés avec succès",
43
+ sourceFiles: "fichiers sources détectés",
44
+ diagnosis: "Diagnostic",
45
+ structureClear: "La structure est claire et l'analyse est complète. ✅",
46
+ metrics: "📈 Métriques clés",
47
+ complexity: "Complexité totale",
48
+ avgComplexity: "Complexité moyenne",
49
+ dependencies: "Dépendances uniques",
50
+ topLangs: "🔤 Langages détectés",
51
+ criticalFiles: "⚠️ Fichiers critiques (haute complexité)",
52
+ navigation: "🧭 Navigation Rapide",
53
+ navDesc: "Pour aller plus loin, tu peux consulter les documents suivants :",
54
+ treeLink: "📂 Arborescence & Analyse",
55
+ treeDesc: "Pour comprendre la vocation de chaque fichier et les capacités du système.",
56
+ codeLink: "💻 Code Source",
57
+ codeDesc: "Pour retourner explorer la racine de ton projet.",
58
+ footer: "DocsToDev – Ton allié pour une documentation technique vivante et intelligente."
59
+ } : {
60
+ title: "📊 Project Overview – DocsToDev",
61
+ genOn: "Generated on",
62
+ status: "🚀 Project Status",
63
+ intro: "Hey! I've scanned your entire codebase. Here's a quick summary of the findings:",
64
+ volume: "Volume processed",
65
+ filesAnalyzed: "files successfully analyzed",
66
+ sourceFiles: "source files detected",
67
+ diagnosis: "Diagnosis",
68
+ structureClear: "The structure is clear and the analysis is complete. ✅",
69
+ metrics: "📈 Key Metrics",
70
+ complexity: "Total complexity",
71
+ avgComplexity: "Average complexity",
72
+ dependencies: "Unique dependencies",
73
+ topLangs: "🔤 Languages Detected",
74
+ criticalFiles: "⚠️ Critical Files (high complexity)",
75
+ navigation: "🧭 Quick Navigation",
76
+ navDesc: "To dive deeper, check out these documents:",
77
+ treeLink: "📂 Tree & Analysis",
78
+ treeDesc: "Explore file purposes and system capabilities.",
79
+ codeLink: "💻 Source Code",
80
+ codeDesc: "Head back to the project root.",
81
+ footer: "DocsToDev – Your partner for living and intelligent technical documentation."
82
+ };
83
+
84
+ let content = `# ${t.title}\n\n`;
85
+ content += `> 📅 **${t.genOn} :** ${dateStr}\n\n`;
86
+
87
+ content += `## ${t.status}\n`;
88
+ content += `${t.intro}\n`;
89
+ content += `- **${t.volume} :** ${summaryData.totalFiles} ${t.filesAnalyzed}.\n`;
90
+
91
+ if (summaryData.sourceFiles) {
92
+ content += `- **${t.sourceFiles} :** ${summaryData.sourceFiles} ${t.sourceFiles.toLowerCase()}.\n`;
93
+ }
94
+
95
+ content += `- **${t.diagnosis} :** ${t.structureClear}\n\n`;
96
+
97
+ // Métriques additionnelles si disponibles
98
+ if (summaryData.totalComplexity || summaryData.avgComplexity || summaryData.totalDeps) {
99
+ content += `## ${t.metrics}\n`;
100
+
101
+ if (summaryData.totalComplexity) {
102
+ content += `- **${t.complexity} :** ${summaryData.totalComplexity}\n`;
103
+ }
104
+
105
+ if (summaryData.avgComplexity) {
106
+ content += `- **${t.avgComplexity} :** ${summaryData.avgComplexity}\n`;
107
+ }
108
+
109
+ if (summaryData.totalDeps) {
110
+ content += `- **${t.dependencies} :** ${summaryData.totalDeps}\n`;
111
+ }
112
+
113
+ content += `\n`;
114
+ }
115
+
116
+ // Langages détectés
117
+ if (summaryData.topLanguages && summaryData.topLanguages.length > 0) {
118
+ content += `## ${t.topLangs}\n`;
119
+ summaryData.topLanguages.forEach(({ lang, count }) => {
120
+ content += `- **${lang}** : ${count} ${lang === "fr" ? "fichiers" : "files"}\n`;
121
+ });
122
+ content += `\n`;
123
+ }
124
+
125
+ // Fichiers critiques
126
+ if (summaryData.criticalFiles && summaryData.criticalFiles.length > 0) {
127
+ content += `## ${t.criticalFiles}\n`;
128
+ summaryData.criticalFiles.forEach(file => {
129
+ content += `- \`${file}\`\n`;
130
+ });
131
+ content += `\n`;
132
+ }
133
+
134
+ content += `## ${t.navigation}\n`;
135
+ content += `${t.navDesc}\n`;
136
+ content += `- **[${t.treeLink}](../docs/docs-to-dev.md)** : ${t.treeDesc}\n`;
137
+ content += `- **[${t.codeLink}](../)** : ${t.codeDesc}\n\n`;
138
+
139
+ content += `---\n`;
140
+ content += `*${t.footer}*\n`;
50
141
 
51
142
  const outputPath = path.join(docsDir, "summary.md");
52
143
  writeFileSync(outputPath, content);
53
144
 
54
- // Log de succès bilingue
55
145
  const successMsg = lang === "fr"
56
146
  ? `📑 Résumé humain généré avec succès : ${outputPath}`
57
147
  : `📑 Human-friendly summary successfully generated: ${outputPath}`;