Skip to content

Commit bbb5f9a

Browse files
committed
add config & update script
1 parent 97a4cf8 commit bbb5f9a

3 files changed

Lines changed: 807 additions & 813 deletions

File tree

config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"USERNAME": "FabioDevCode",
3+
"TITLE": "Langages Utilisés",
4+
"BG_COLOR": "#202830",
5+
"BORDER_COLOR": "#151B23",
6+
"TITLE_COLOR": "#D1D7E0",
7+
"TEXT_COLOR": "#D1D7E0",
8+
"PERCENT_COLOR": "#9298A1"
9+
}

generate-stats.js

Lines changed: 145 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,167 @@
11
const fs = require('fs');
22

33
// Configuration
4-
const USERNAME = 'FabioDevCode';
4+
const CONFIG = JSON.parse(fs.readFileSync('config.json', 'utf8'));;
55

6-
// Thème de couleur
7-
const BG_COLOR = '#202830';
8-
const BORDER_COLOR = '#151B23';
9-
const TITLE_COLOR = '#D1D7E0';
10-
const TEXT_COLOR = '#D1D7E0';
11-
const PERCENT_COLOR = '#9298A1';
12-
13-
// Couleurs officielles GitHub
6+
// Couleurs officielles GitHub (NE PAS MODIFIER)
147
const LANGUAGE_COLORS = JSON.parse(fs.readFileSync('github_colors.json', 'utf8'));
158

169
async function fetchGitHubStats(username, token) {
17-
console.log(`📊 Récupération des stats pour ${username}...`);
18-
19-
const headers = {
20-
'Authorization': `token ${token}`,
21-
'Accept': 'application/vnd.github.v3+json'
22-
};
23-
24-
try {
25-
const reposResponse = await fetch(
26-
`https://api.github.com/users/${username}/repos?per_page=100&type=owner`,
27-
{ headers }
28-
);
29-
30-
if (!reposResponse.ok) {
31-
throw new Error(`GitHub API error: ${reposResponse.status}`);
32-
}
33-
34-
const repos = await reposResponse.json();
35-
console.log(`✅ ${repos.length} repositories trouvés`);
36-
37-
// Compter les lignes de code par langage
38-
const languageStats = {};
39-
40-
for (const repo of repos) {
41-
if (!repo.fork && repo.language) {
42-
const langResponse = await fetch(repo.languages_url, { headers });
43-
const languages = await langResponse.json();
44-
45-
for (const [lang, bytes] of Object.entries(languages)) {
46-
languageStats[lang] = (languageStats[lang] || 0) + bytes;
47-
}
48-
}
49-
}
50-
51-
console.log(`📝 ${Object.keys(languageStats).length} langages différents détectés`);
52-
return languageStats;
53-
54-
} catch (error) {
55-
console.error('❌ Erreur:', error.message);
56-
throw error;
57-
}
10+
console.log(`📊 Récupération des stats pour ${username}...`);
11+
12+
const headers = {
13+
'Authorization': `token ${token}`,
14+
'Accept': 'application/vnd.github.v3+json'
15+
};
16+
17+
try {
18+
const reposResponse = await fetch(
19+
`https://api.github.com/users/${username}/repos?per_page=100&type=owner`,
20+
{ headers }
21+
);
22+
23+
if (!reposResponse.ok) {
24+
throw new Error(`GitHub API error: ${reposResponse.status}`);
25+
}
26+
27+
const repos = await reposResponse.json();
28+
console.log(`✅ ${repos.length} repositories trouvés`);
29+
30+
// Compter les lignes de code par langage
31+
const languageStats = {};
32+
33+
for (const repo of repos) {
34+
if (!repo.fork && repo.language) {
35+
const langResponse = await fetch(repo.languages_url, { headers });
36+
const languages = await langResponse.json();
37+
38+
for (const [lang, bytes] of Object.entries(languages)) {
39+
languageStats[lang] = (languageStats[lang] || 0) + bytes;
40+
}
41+
}
42+
}
43+
44+
console.log(`📝 ${Object.keys(languageStats).length} langages différents détectés`);
45+
return languageStats;
46+
} catch (error) {
47+
console.error('❌ Erreur:', error.message);
48+
throw error;
49+
}
5850
}
5951

6052
function getLanguageColor(language) {
61-
return LANGUAGE_COLORS[language] || '#858585';
53+
return LANGUAGE_COLORS[language] || '#858585';
6254
}
6355

6456
function generateSVG(languageStats, topN = 5) {
65-
// Trier et limiter
66-
const sortedLangs = Object.entries(languageStats)
67-
.sort((a, b) => b[1] - a[1])
68-
.slice(0, topN);
69-
70-
if (sortedLangs.length === 0) {
71-
return generateEmptySVG(topN);
72-
}
73-
74-
const totalBytes = sortedLangs.reduce((sum, [, bytes]) => sum + bytes, 0);
75-
76-
// Calculer les pourcentages
77-
const langData = sortedLangs.map(([lang, bytes]) => ({
78-
name: lang,
79-
bytes: bytes,
80-
percentage: (bytes / totalBytes * 100).toFixed(1),
81-
color: getLanguageColor(lang)
82-
}));
83-
84-
// Générer la barre de progression
85-
let currentX = 10;
86-
const barHeight = 12;
87-
const barY = 50;
88-
const barSegments = langData.map(lang => {
89-
const width = (lang.percentage / 100) * 400;
90-
const segment = `<rect x="${currentX}" y="${barY}" width="${width}" height="${barHeight}" fill="${lang.color}"/>`;
91-
currentX += width;
92-
return segment;
93-
}).join('');
94-
95-
// Générer la légende
96-
let legendY = 85;
97-
const legendItems = langData.map(lang => {
98-
const item = `
99-
<g>
100-
<circle cx="20" cy="${legendY}" r="5" fill="${lang.color}"/>
101-
<text x="35" y="${legendY + 4}" font-size="14" fill="${TEXT_COLOR}">${lang.name}</text>
102-
<text x="380" y="${legendY + 4}" font-size="14" fill="${PERCENT_COLOR}" text-anchor="end">${lang.percentage}%</text>
103-
</g>
104-
`;
105-
legendY += 25;
106-
return item;
107-
}).join('');
108-
109-
const height = 70 + (topN * 25) + 20;
110-
111-
return `<?xml version="1.0" encoding="UTF-8"?>
112-
<svg width="420" height="${height}" xmlns="http://www.w3.org/2000/svg">
113-
<defs>
114-
<style>
115-
@import url('https://fonts.googleapis.com/css2?family=Segoe+UI:wght@400;500;600&amp;display=swap');
116-
* { font-family: 'Segoe UI', Ubuntu, sans-serif; }
117-
</style>
118-
</defs>
119-
120-
<!-- Background -->
121-
<rect width="420" height="${height}" fill="${BG_COLOR}" rx="10" stroke="${BORDER_COLOR}" stroke-width="1"/>
122-
123-
<!-- Title -->
124-
<text x="210" y="30" font-size="18" fill="${TITLE_COLOR}" font-weight="600" text-anchor="middle">
125-
Top Langages
126-
</text>
127-
128-
<!-- Progress Bar Container -->
129-
<rect x="10" y="${barY}" width="400" height="${barHeight}" fill="#161b2200" rx="6"/>
130-
131-
<!-- Progress Bar Segments -->
132-
${barSegments}
133-
134-
<!-- Legend -->
135-
${legendItems}
136-
</svg>`;
57+
// Trier et limiter
58+
const sortedLangs = Object.entries(languageStats)
59+
.sort((a, b) => b[1] - a[1])
60+
.slice(0, topN);
61+
62+
if (sortedLangs.length === 0) {
63+
return generateEmptySVG(topN);
64+
}
65+
66+
const totalBytes = sortedLangs.reduce((sum, [, bytes]) => sum + bytes, 0);
67+
68+
// Calculer les pourcentages
69+
const langData = sortedLangs.map(([lang, bytes]) => ({
70+
name: lang,
71+
bytes: bytes,
72+
percentage: (bytes / totalBytes * 100).toFixed(1),
73+
color: getLanguageColor(lang)
74+
}));
75+
76+
// Générer la barre de progression
77+
let currentX = 10;
78+
const barHeight = 12;
79+
const barY = 50;
80+
const barSegments = langData.map(lang => {
81+
const width = (lang.percentage / 100) * 400;
82+
const segment = `<rect x="${currentX}" y="${barY}" width="${width}" height="${barHeight}" fill="${lang.color}"/>`;
83+
currentX += width;
84+
return segment;
85+
}).join('');
86+
87+
// Générer la légende
88+
let legendY = 85;
89+
const legendItems = langData.map(lang => {
90+
const item = `
91+
<g>
92+
<circle cx="20" cy="${legendY}" r="5" fill="${lang.color}"/>
93+
<text x="35" y="${legendY + 4}" font-size="14" fill="${CONFIG.TEXT_COLOR}">${lang.name}</text>
94+
<text x="380" y="${legendY + 4}" font-size="14" fill="${CONFIG.PERCENT_COLOR}" text-anchor="end">${lang.percentage}%</text>
95+
</g>
96+
`;
97+
legendY += 25;
98+
return item;
99+
}).join('');
100+
101+
const height = 70 + (topN * 25) + 20;
102+
103+
return `<?xml version="1.0" encoding="UTF-8"?>
104+
<svg width="420" height="${height}" xmlns="http://www.w3.org/2000/svg">
105+
<defs>
106+
<style>
107+
@import url('https://fonts.googleapis.com/css2?family=Segoe+UI:wght@400;500;600&amp;display=swap');
108+
* { font-family: 'Segoe UI', Ubuntu, sans-serif; }
109+
</style>
110+
</defs>
111+
112+
<!-- Background -->
113+
<rect width="420" height="${height}" fill="${CONFIG.BG_COLOR}" rx="10" stroke="${CONFIG.BORDER_COLOR}" stroke-width="1"/>
114+
115+
<!-- Title -->
116+
<text x="210" y="30" font-size="18" fill="${CONFIG.TITLE_COLOR}" font-weight="600" text-anchor="middle">
117+
${CONFIG.TITLE}
118+
</text>
119+
120+
<!-- Progress Bar Segments -->
121+
${barSegments}
122+
123+
<!-- Legend -->
124+
${legendItems}
125+
</svg>`;
137126
}
138127

139128
function generateEmptySVG(topN) {
140-
return `<?xml version="1.0" encoding="UTF-8"?>
141-
<svg width="420" height="150" xmlns="http://www.w3.org/2000/svg">
142-
<rect width="420" height="150" fill="#0d1117" rx="10"/>
143-
<text x="210" y="75" font-size="16" fill="#8b949e" text-anchor="middle">
144-
Aucune donnée disponible
145-
</text>
146-
</svg>`;
129+
return `<?xml version="1.0" encoding="UTF-8"?>
130+
<svg width="420" height="150" xmlns="http://www.w3.org/2000/svg">
131+
<rect width="420" height="150" fill="#0d1117" rx="10"/>
132+
<text x="210" y="75" font-size="16" fill="#8b949e" text-anchor="middle">
133+
Aucune donnée disponible
134+
</text>
135+
</svg>`;
147136
}
148137

149138
async function main() {
150-
const token = process.env.GITHUB_TOKEN;
151-
152-
if (!token) {
153-
console.error('❌ GITHUB_TOKEN non défini !');
154-
process.exit(1);
155-
}
156-
157-
try {
158-
const languageStats = await fetchGitHubStats(USERNAME, token);
159-
160-
// Générer plusieurs versions
161-
const variants = [4, 5, 6, 7, 8];
162-
163-
console.log('\n📸 Génération des images SVG...');
164-
variants.forEach(n => {
165-
const svg = generateSVG(languageStats, n);
166-
const filename = `stats-top${n}.svg`;
167-
fs.writeFileSync(filename, svg);
168-
console.log(` ✅ ${filename}`);
169-
});
170-
171-
// Générer aussi une version "default" (top 5)
172-
const defaultSvg = generateSVG(languageStats, 5);
173-
fs.writeFileSync('stats.svg', defaultSvg);
174-
console.log(' ✅ stats.svg (default)');
175-
console.log('\n🎉 Toutes les images ont été générées avec succès !');
176-
} catch (error) {
177-
console.error('❌ Erreur lors de la génération:', error);
178-
process.exit(1);
179-
}
139+
const token = process.env.GITHUB_TOKEN;
140+
141+
if (!token) {
142+
console.error('❌ GITHUB_TOKEN non défini !');
143+
process.exit(1);
144+
}
145+
146+
try {
147+
const languageStats = await fetchGitHubStats(CONFIG.USERNAME, token);
148+
149+
// Générer plusieurs versions
150+
const variants = [2, 4, 5, 6, 7, 8];
151+
152+
console.log('\n📸 Génération des images SVG...');
153+
variants.forEach(n => {
154+
const svg = generateSVG(languageStats, n);
155+
const filename = `stats/stats-top${n}.svg`;
156+
fs.writeFileSync(filename, svg);
157+
console.log(` ✅ ${filename}`);
158+
});
159+
160+
console.log('\n🎉 Toutes les images ont été générées avec succès !');
161+
} catch (error) {
162+
console.error('❌ Erreur lors de la génération:', error);
163+
process.exit(1);
164+
}
180165
}
181166

182167
main();

0 commit comments

Comments
 (0)