Ajout carrousel articles avec miniatures auto-générées

- Créer composant React ArticleCarousel avec lecture auto et boucle infinie
- Afficher 6 articles total : 3 articles blog et 3 pages docs, intercalés
- Ajouter badges colorés : bleu pour blog, vert foncé pour docs
- Implémenter plugin personnalisé pour récupérer et organiser articles
- Remplacer section fonctionnalités page d'accueil par nouveau carrousel
- Mettre à jour logo site et favicon avec logo vache (logo_vache.png)
- Ajouter traductions anglaises pour chaînes UI carrousel
This commit is contained in:
Tellsanguis 2025-12-03 21:32:31 +01:00
parent ba57296597
commit 461fc446ff
10 changed files with 911 additions and 55 deletions

View file

@ -0,0 +1,96 @@
/**
* Docusaurus plugin to gather recent blog posts and documentation pages
* for the ArticleCarousel component.
*
* This plugin creates a global data structure containing recent articles
* from both blog posts and documentation pages, sorted by date.
*/
module.exports = function pluginRecentArticles(context, options) {
return {
name: 'docusaurus-plugin-recent-articles',
async allContentLoaded({ actions, allContent }) {
const { setGlobalData } = actions;
try {
const blogArticles = [];
const docArticles = [];
// Access blog plugin data
const blogPlugin = allContent?.['docusaurus-plugin-content-blog'];
const blogContent = blogPlugin?.default;
if (blogContent?.blogPosts) {
blogContent.blogPosts.forEach((post) => {
blogArticles.push({
title: post.metadata.title,
permalink: post.metadata.permalink,
type: 'blog',
date: post.metadata.date,
});
});
}
// Access docs plugin data
const docsPlugin = allContent?.['docusaurus-plugin-content-docs'];
const docsContent = docsPlugin?.default;
if (docsContent?.loadedVersions) {
docsContent.loadedVersions.forEach((version) => {
if (version.docs) {
version.docs.forEach((doc) => {
// Skip index/category pages to focus on actual content
if (!doc.id.endsWith('/index') && !doc.id.includes('category')) {
docArticles.push({
title: doc.title,
permalink: doc.permalink,
type: 'doc',
// Docs don't have a publish date, use last updated time or current date
date: doc.lastUpdatedAt
? new Date(doc.lastUpdatedAt).toISOString()
: new Date().toISOString(),
});
}
});
}
});
}
// Sort each type by date (most recent first)
blogArticles.sort((a, b) => {
const dateA = new Date(a.date || 0);
const dateB = new Date(b.date || 0);
return dateB - dateA;
});
docArticles.sort((a, b) => {
const dateA = new Date(a.date || 0);
const dateB = new Date(b.date || 0);
return dateB - dateA;
});
// Take 3 most recent from each type
const recentBlog = blogArticles.slice(0, 3);
const recentDocs = docArticles.slice(0, 3);
// Intercalate blog and documentation articles: blog, doc, blog, doc, blog, doc
const articles = [];
for (let i = 0; i < Math.max(recentBlog.length, recentDocs.length); i++) {
if (i < recentBlog.length) {
articles.push(recentBlog[i]);
}
if (i < recentDocs.length) {
articles.push(recentDocs[i]);
}
}
// Store globally for use in React components
setGlobalData({ articles });
} catch (error) {
console.error('Error loading recent articles:', error);
setGlobalData({ articles: [] });
}
},
};
};