docstodev 1.0.2 → 1.1.1
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.
- package/dist/ai/analyzer.d.ts.map +1 -1
- package/dist/ai/analyzer.js +3 -1
- package/dist/ai/analyzer.js.map +1 -1
- package/dist/analyzers/languageAnalyzer.d.ts +3 -1
- package/dist/analyzers/languageAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/languageAnalyzer.js +266 -4
- package/dist/analyzers/languageAnalyzer.js.map +1 -1
- package/dist/commands/generateSummary.d.ts +14 -1
- package/dist/commands/generateSummary.d.ts.map +1 -1
- package/dist/commands/generateSummary.js +101 -39
- package/dist/commands/generateSummary.js.map +1 -1
- package/dist/exporters/html.d.ts.map +1 -1
- package/dist/exporters/html.js +130 -51
- package/dist/exporters/html.js.map +1 -1
- package/package.json +1 -1
- package/src/ai/analyzer.ts +3 -1
- package/src/analyzers/languageAnalyzer.ts +297 -5
- package/src/commands/generateSummary.ts +129 -39
- package/src/exporters/html.ts +134 -52
- package/.env +0 -1
- package/dist/commands/classify.d.ts +0 -2
- package/dist/commands/classify.d.ts.map +0 -1
- package/dist/commands/classify.js +0 -37
- package/dist/commands/classify.js.map +0 -1
- package/src/commands/classify.ts +0 -40
|
@@ -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(
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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}`;
|
package/src/exporters/html.ts
CHANGED
|
@@ -55,10 +55,10 @@ export function exportToHTML(
|
|
|
55
55
|
if (
|
|
56
56
|
processed.match(/^[│├└─\s]+/) ||
|
|
57
57
|
processed.includes("/") ||
|
|
58
|
-
processed.match(/\.(ts|js|py|java|cs|go|rs|tsx|jsx)$/)
|
|
58
|
+
processed.match(/\.(ts|js|py|java|cs|go|rs|tsx|jsx|html|css|php|rb|sql)$/)
|
|
59
59
|
) {
|
|
60
|
-
const hasFile = processed.match(/\.(ts|js|py|java|cs|go|rs|tsx|jsx)$/);
|
|
61
|
-
const fileMatch = hasFile ? processed.match(/([\w-]+\.(ts|js|py|java|cs|go|rs|tsx|jsx))/)?.[0] : null;
|
|
60
|
+
const hasFile = processed.match(/\.(ts|js|py|java|cs|go|rs|tsx|jsx|html|css|php|rb|sql)$/);
|
|
61
|
+
const fileMatch = hasFile ? processed.match(/([\w-]+\.(ts|js|py|java|cs|go|rs|tsx|jsx|html|css|php|rb|sql))/)?.[0] : null;
|
|
62
62
|
|
|
63
63
|
let treeLine = line
|
|
64
64
|
.replace(/├─/g, '<span class="branch">├─</span>')
|
|
@@ -104,10 +104,9 @@ export function exportToHTML(
|
|
|
104
104
|
|
|
105
105
|
if (inSection) htmlResult += "</section>";
|
|
106
106
|
|
|
107
|
-
//
|
|
107
|
+
// Nettoyer et valider les graphes Mermaid
|
|
108
|
+
const cleanMermaidGraph = sanitizeMermaidGraph(mermaidGraph || "graph TD\n Root[Projet]");
|
|
108
109
|
const hierarchyGraph = fileTree ? generateHierarchyGraph(fileTree) : getDefaultHierarchyGraph();
|
|
109
|
-
|
|
110
|
-
// Générer le flux de données (peut être personnalisé selon les imports/exports)
|
|
111
110
|
const dataFlowGraph = generateDataFlowGraph();
|
|
112
111
|
|
|
113
112
|
const html = `<!DOCTYPE html>
|
|
@@ -115,10 +114,38 @@ export function exportToHTML(
|
|
|
115
114
|
<head>
|
|
116
115
|
<meta charset="UTF-8">
|
|
117
116
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
118
|
-
<title>DocsToDev – Rapport Technique</title>
|
|
117
|
+
<title>DocsToDev – ${lang === 'fr' ? 'Rapport Technique' : 'Technical Report'}</title>
|
|
119
118
|
|
|
120
119
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400&family=Fira+Code&display=swap" rel="stylesheet">
|
|
121
|
-
<script
|
|
120
|
+
<script type="module">
|
|
121
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
|
122
|
+
|
|
123
|
+
mermaid.initialize({
|
|
124
|
+
startOnLoad: true,
|
|
125
|
+
theme: document.documentElement.dataset.theme === "dark" ? "dark" : "default",
|
|
126
|
+
securityLevel: 'loose',
|
|
127
|
+
logLevel: 'error',
|
|
128
|
+
themeVariables: {
|
|
129
|
+
darkMode: document.documentElement.dataset.theme === "dark",
|
|
130
|
+
background: "transparent",
|
|
131
|
+
primaryColor: "#58a6ff",
|
|
132
|
+
primaryTextColor: "#c9d1d9",
|
|
133
|
+
primaryBorderColor: "#30363d",
|
|
134
|
+
lineColor: "#8b949e",
|
|
135
|
+
secondaryColor: "#161b22",
|
|
136
|
+
tertiaryColor: "#0d1117",
|
|
137
|
+
fontSize: "14px",
|
|
138
|
+
fontFamily: "Inter, sans-serif"
|
|
139
|
+
},
|
|
140
|
+
flowchart: {
|
|
141
|
+
useMaxWidth: true,
|
|
142
|
+
htmlLabels: true,
|
|
143
|
+
curve: 'basis'
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
window.mermaid = mermaid;
|
|
148
|
+
</script>
|
|
122
149
|
|
|
123
150
|
<style>
|
|
124
151
|
:root[data-theme="dark"] {
|
|
@@ -250,6 +277,8 @@ h3 {
|
|
|
250
277
|
border: 1px solid var(--border);
|
|
251
278
|
background: var(--card);
|
|
252
279
|
padding: 1.5rem;
|
|
280
|
+
min-height: 300px;
|
|
281
|
+
position: relative;
|
|
253
282
|
}
|
|
254
283
|
|
|
255
284
|
.graph-title {
|
|
@@ -261,6 +290,12 @@ h3 {
|
|
|
261
290
|
font-size: 0.85rem;
|
|
262
291
|
}
|
|
263
292
|
|
|
293
|
+
.mermaid-wrapper {
|
|
294
|
+
width: 100%;
|
|
295
|
+
overflow-x: auto;
|
|
296
|
+
overflow-y: hidden;
|
|
297
|
+
}
|
|
298
|
+
|
|
264
299
|
.component {
|
|
265
300
|
border: 1px solid var(--border);
|
|
266
301
|
background: var(--card);
|
|
@@ -372,7 +407,25 @@ mark {
|
|
|
372
407
|
|
|
373
408
|
.mermaid {
|
|
374
409
|
background: transparent;
|
|
375
|
-
|
|
410
|
+
display: flex;
|
|
411
|
+
justify-content: center;
|
|
412
|
+
align-items: center;
|
|
413
|
+
min-height: 200px;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.mermaid svg {
|
|
417
|
+
max-width: 100%;
|
|
418
|
+
height: auto;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.error-message {
|
|
422
|
+
color: #f85149;
|
|
423
|
+
padding: 1rem;
|
|
424
|
+
background: rgba(248, 81, 73, 0.1);
|
|
425
|
+
border: 1px solid rgba(248, 81, 73, 0.3);
|
|
426
|
+
border-radius: 4px;
|
|
427
|
+
font-family: "Fira Code", monospace;
|
|
428
|
+
font-size: 0.9rem;
|
|
376
429
|
}
|
|
377
430
|
|
|
378
431
|
@media print {
|
|
@@ -425,23 +478,29 @@ mark {
|
|
|
425
478
|
<div class="graphs-grid">
|
|
426
479
|
<div class="graph-container">
|
|
427
480
|
<div class="graph-title">${lang === 'fr' ? 'Graphe des dépendances' : 'Dependency Graph'}</div>
|
|
428
|
-
<div class="mermaid">
|
|
429
|
-
|
|
481
|
+
<div class="mermaid-wrapper">
|
|
482
|
+
<pre class="mermaid">
|
|
483
|
+
${cleanMermaidGraph}
|
|
484
|
+
</pre>
|
|
430
485
|
</div>
|
|
431
486
|
</div>
|
|
432
487
|
|
|
433
488
|
<div class="graph-container">
|
|
434
489
|
<div class="graph-title">${lang === 'fr' ? 'Structure du projet' : 'Project Structure'}</div>
|
|
435
|
-
<div class="mermaid">
|
|
490
|
+
<div class="mermaid-wrapper">
|
|
491
|
+
<pre class="mermaid">
|
|
436
492
|
${hierarchyGraph}
|
|
493
|
+
</pre>
|
|
437
494
|
</div>
|
|
438
495
|
</div>
|
|
439
496
|
</div>
|
|
440
497
|
|
|
441
498
|
<div class="graph-container" style="margin-bottom: 3rem;">
|
|
442
499
|
<div class="graph-title">${lang === 'fr' ? 'Flux de données' : 'Data Flow'}</div>
|
|
443
|
-
<div class="mermaid">
|
|
500
|
+
<div class="mermaid-wrapper">
|
|
501
|
+
<pre class="mermaid">
|
|
444
502
|
${dataFlowGraph}
|
|
503
|
+
</pre>
|
|
445
504
|
</div>
|
|
446
505
|
</div>
|
|
447
506
|
|
|
@@ -450,34 +509,12 @@ ${dataFlowGraph}
|
|
|
450
509
|
</div>
|
|
451
510
|
|
|
452
511
|
<script>
|
|
453
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
454
|
-
if (window.mermaid) {
|
|
455
|
-
mermaid.initialize({
|
|
456
|
-
startOnLoad: true,
|
|
457
|
-
theme: document.documentElement.dataset.theme === "dark" ? "dark" : "default",
|
|
458
|
-
themeVariables: {
|
|
459
|
-
darkMode: document.documentElement.dataset.theme === "dark",
|
|
460
|
-
background: "transparent",
|
|
461
|
-
primaryColor: "#58a6ff",
|
|
462
|
-
primaryTextColor: "#c9d1d9",
|
|
463
|
-
primaryBorderColor: "#30363d",
|
|
464
|
-
lineColor: "#8b949e",
|
|
465
|
-
secondaryColor: "#161b22",
|
|
466
|
-
tertiaryColor: "#0d1117"
|
|
467
|
-
}
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
|
|
472
512
|
function toggleTheme() {
|
|
473
513
|
const root = document.documentElement;
|
|
474
514
|
const next = root.dataset.theme === "dark" ? "light" : "dark";
|
|
475
515
|
root.dataset.theme = next;
|
|
476
516
|
localStorage.setItem("theme", next);
|
|
477
|
-
|
|
478
|
-
if (window.mermaid) {
|
|
479
|
-
location.reload();
|
|
480
|
-
}
|
|
517
|
+
location.reload();
|
|
481
518
|
}
|
|
482
519
|
|
|
483
520
|
document.documentElement.dataset.theme = localStorage.getItem("theme") || "dark";
|
|
@@ -493,12 +530,26 @@ document.getElementById("search").addEventListener("input", e => {
|
|
|
493
530
|
return;
|
|
494
531
|
}
|
|
495
532
|
|
|
496
|
-
const regex = new RegExp("(" + term.replace(/[
|
|
533
|
+
const regex = new RegExp("(" + term.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&") + ")", "gi");
|
|
497
534
|
container.innerHTML = originalHTML.replace(regex, "<mark>$1</mark>");
|
|
498
535
|
|
|
499
536
|
const first = container.querySelector("mark");
|
|
500
537
|
if (first) first.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
501
538
|
});
|
|
539
|
+
|
|
540
|
+
// Gestion d'erreur Mermaid
|
|
541
|
+
window.addEventListener('load', () => {
|
|
542
|
+
setTimeout(() => {
|
|
543
|
+
document.querySelectorAll('.mermaid').forEach(el => {
|
|
544
|
+
if (!el.querySelector('svg') && !el.querySelector('.error-message')) {
|
|
545
|
+
const errorMsg = document.createElement('div');
|
|
546
|
+
errorMsg.className = 'error-message';
|
|
547
|
+
errorMsg.textContent = '${lang === 'fr' ? 'Erreur de rendu du graphe' : 'Graph rendering error'}';
|
|
548
|
+
el.appendChild(errorMsg);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}, 3000);
|
|
552
|
+
});
|
|
502
553
|
</script>
|
|
503
554
|
|
|
504
555
|
</body>
|
|
@@ -507,20 +558,46 @@ document.getElementById("search").addEventListener("input", e => {
|
|
|
507
558
|
writeFileSync(path.join(docsDir, "report.html"), html);
|
|
508
559
|
}
|
|
509
560
|
|
|
561
|
+
function sanitizeMermaidGraph(graph: string): string {
|
|
562
|
+
// Nettoyer les caractères problématiques
|
|
563
|
+
let cleaned = graph
|
|
564
|
+
.replace(/[""]/g, '"')
|
|
565
|
+
.replace(/['']/g, "'")
|
|
566
|
+
.replace(/\u00A0/g, ' ') // Espaces insécables
|
|
567
|
+
.trim();
|
|
568
|
+
|
|
569
|
+
// Vérifier que le graphe a une déclaration valide
|
|
570
|
+
if (!cleaned.match(/^(graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|gantt|pie|erDiagram)/)) {
|
|
571
|
+
cleaned = "graph TD\n " + cleaned;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Limiter la complexité si trop de nœuds
|
|
575
|
+
const lines = cleaned.split('\n');
|
|
576
|
+
if (lines.length > 50) {
|
|
577
|
+
cleaned = lines.slice(0, 50).join('\n') + '\n More["..."]';
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return cleaned;
|
|
581
|
+
}
|
|
582
|
+
|
|
510
583
|
function generateHierarchyGraph(tree: TreeStructure, maxDepth = 3): string {
|
|
511
584
|
let graph = "graph TD\n";
|
|
512
585
|
let nodeId = 0;
|
|
513
586
|
const nodeMap = new Map<string, string>();
|
|
514
587
|
|
|
588
|
+
function sanitizeLabel(label: string): string {
|
|
589
|
+
return label.replace(/["\[\]]/g, '');
|
|
590
|
+
}
|
|
591
|
+
|
|
515
592
|
function traverse(obj: TreeStructure, parentId: string | null, depth: number, prefix = ""): void {
|
|
516
593
|
if (depth > maxDepth) return;
|
|
517
594
|
|
|
518
|
-
const entries = Object.entries(obj).slice(0,
|
|
595
|
+
const entries = Object.entries(obj).slice(0, 10); // Limiter pour lisibilité
|
|
519
596
|
|
|
520
597
|
entries.forEach(([key, value]) => {
|
|
521
598
|
const currentId = `node${nodeId++}`;
|
|
522
599
|
const isFolder = value && typeof value === 'object' && Object.keys(value).length > 0;
|
|
523
|
-
const label = isFolder ? `${key}/` : key;
|
|
600
|
+
const label = sanitizeLabel(isFolder ? `${key}/` : key);
|
|
524
601
|
|
|
525
602
|
nodeMap.set(currentId, label);
|
|
526
603
|
graph += ` ${currentId}["${label}"]\n`;
|
|
@@ -529,30 +606,35 @@ function generateHierarchyGraph(tree: TreeStructure, maxDepth = 3): string {
|
|
|
529
606
|
graph += ` ${parentId} --> ${currentId}\n`;
|
|
530
607
|
}
|
|
531
608
|
|
|
532
|
-
if (isFolder && value) {
|
|
609
|
+
if (isFolder && value && depth < maxDepth) {
|
|
533
610
|
traverse(value, currentId, depth + 1, prefix + key + "/");
|
|
534
611
|
}
|
|
535
612
|
});
|
|
536
613
|
}
|
|
537
614
|
|
|
538
|
-
|
|
539
|
-
|
|
615
|
+
try {
|
|
616
|
+
traverse(tree, null, 0);
|
|
617
|
+
return graph || getDefaultHierarchyGraph();
|
|
618
|
+
} catch (e) {
|
|
619
|
+
console.error("Error generating hierarchy graph:", e);
|
|
620
|
+
return getDefaultHierarchyGraph();
|
|
621
|
+
}
|
|
540
622
|
}
|
|
541
623
|
|
|
542
624
|
function getDefaultHierarchyGraph(): string {
|
|
543
625
|
return `graph TD
|
|
544
|
-
A[Root] --> B[src]
|
|
545
|
-
A --> C[config]
|
|
546
|
-
B --> D[components]
|
|
547
|
-
B --> E[utils]
|
|
548
|
-
B --> F[services]`;
|
|
626
|
+
A["Root"] --> B["src"]
|
|
627
|
+
A --> C["config"]
|
|
628
|
+
B --> D["components"]
|
|
629
|
+
B --> E["utils"]
|
|
630
|
+
B --> F["services"]`;
|
|
549
631
|
}
|
|
550
632
|
|
|
551
633
|
function generateDataFlowGraph(): string {
|
|
552
634
|
return `graph LR
|
|
553
|
-
A[Input] --> B[Analyzer]
|
|
554
|
-
B --> C[Parser]
|
|
555
|
-
C --> D[Generator]
|
|
556
|
-
D --> E[Exporter]
|
|
557
|
-
E --> F[Output]`;
|
|
635
|
+
A["Input"] --> B["Analyzer"]
|
|
636
|
+
B --> C["Parser"]
|
|
637
|
+
C --> D["Generator"]
|
|
638
|
+
D --> E["Exporter"]
|
|
639
|
+
E --> F["Output"]`;
|
|
558
640
|
}
|
package/.env
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
GROQ_API_KEY=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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,IAAI,GAAG,IAAW,GAAG,MAAM,CAoCjG"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Emplacement absolu : M:\workspace\extensions\docstodev\src\commands\classify.ts
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
export function determineRole(filePath, content, lang = "fr") {
|
|
4
|
-
const fileName = path.basename(filePath).toLowerCase();
|
|
5
|
-
const ext = path.extname(filePath);
|
|
6
|
-
const roles = {
|
|
7
|
-
fr: {
|
|
8
|
-
cli: "Lanceur CLI",
|
|
9
|
-
logic: "Logique Métier / Service",
|
|
10
|
-
ui: "Interface Utilisateur (UI)",
|
|
11
|
-
api: "Point d'Entrée API",
|
|
12
|
-
config: "Configuration Système",
|
|
13
|
-
unknown: "Inconnu"
|
|
14
|
-
},
|
|
15
|
-
en: {
|
|
16
|
-
cli: "CLI Entry Point",
|
|
17
|
-
logic: "Business Logic / Service",
|
|
18
|
-
ui: "User Interface (UI)",
|
|
19
|
-
api: "API Endpoint",
|
|
20
|
-
config: "System Configuration",
|
|
21
|
-
unknown: "Unknown"
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
const t = roles[lang];
|
|
25
|
-
if (filePath.includes("cli") || fileName === "index.ts")
|
|
26
|
-
return t.cli;
|
|
27
|
-
if (filePath.includes("commands") || content.includes("export function"))
|
|
28
|
-
return t.logic;
|
|
29
|
-
if (content.includes("react") || ext === ".tsx")
|
|
30
|
-
return t.ui;
|
|
31
|
-
if (content.includes("NextResponse") || filePath.includes("api/"))
|
|
32
|
-
return t.api;
|
|
33
|
-
if (fileName.includes("config") || ext === ".json")
|
|
34
|
-
return t.config;
|
|
35
|
-
return t.unknown;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=classify.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe,EAAE,OAAoB,IAAI;IACrF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG;QACV,EAAE,EAAE;YACA,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,0BAA0B;YACjC,EAAE,EAAE,4BAA4B;YAChC,GAAG,EAAE,oBAAoB;YACzB,MAAM,EAAE,uBAAuB;YAC/B,OAAO,EAAE,SAAS;SACrB;QACD,EAAE,EAAE;YACA,GAAG,EAAE,iBAAiB;YACtB,KAAK,EAAE,0BAA0B;YACjC,EAAE,EAAE,qBAAqB;YACzB,GAAG,EAAE,cAAc;YACnB,MAAM,EAAE,sBAAsB;YAC9B,OAAO,EAAE,SAAS;SACrB;KACJ,CAAC;IAEF,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAEtB,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC;IAEtE,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC;IAEzF,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAE7D,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC;IAEhF,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,KAAK,OAAO;QAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IAEpE,OAAO,CAAC,CAAC,OAAO,CAAC;AACrB,CAAC"}
|
package/src/commands/classify.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// Emplacement absolu : M:\workspace\extensions\docstodev\src\commands\classify.ts
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
export function determineRole(filePath: string, content: string, lang: "fr" | "en" = "fr"): string {
|
|
5
|
-
const fileName = path.basename(filePath).toLowerCase();
|
|
6
|
-
const ext = path.extname(filePath);
|
|
7
|
-
|
|
8
|
-
const roles = {
|
|
9
|
-
fr: {
|
|
10
|
-
cli: "Lanceur CLI",
|
|
11
|
-
logic: "Logique Métier / Service",
|
|
12
|
-
ui: "Interface Utilisateur (UI)",
|
|
13
|
-
api: "Point d'Entrée API",
|
|
14
|
-
config: "Configuration Système",
|
|
15
|
-
unknown: "Inconnu"
|
|
16
|
-
},
|
|
17
|
-
en: {
|
|
18
|
-
cli: "CLI Entry Point",
|
|
19
|
-
logic: "Business Logic / Service",
|
|
20
|
-
ui: "User Interface (UI)",
|
|
21
|
-
api: "API Endpoint",
|
|
22
|
-
config: "System Configuration",
|
|
23
|
-
unknown: "Unknown"
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const t = roles[lang];
|
|
28
|
-
|
|
29
|
-
if (filePath.includes("cli") || fileName === "index.ts") return t.cli;
|
|
30
|
-
|
|
31
|
-
if (filePath.includes("commands") || content.includes("export function")) return t.logic;
|
|
32
|
-
|
|
33
|
-
if (content.includes("react") || ext === ".tsx") return t.ui;
|
|
34
|
-
|
|
35
|
-
if (content.includes("NextResponse") || filePath.includes("api/")) return t.api;
|
|
36
|
-
|
|
37
|
-
if (fileName.includes("config") || ext === ".json") return t.config;
|
|
38
|
-
|
|
39
|
-
return t.unknown;
|
|
40
|
-
}
|