($p['category'] ?? '') === $category)); } /** * Récupère un projet par son slug */ function getProjectBySlug(string $slug): ?array { foreach (getProjects() as $project) { if (($project['slug'] ?? '') === $slug) { return $project; } } return null; } /** * Récupère les technologies uniques de tous les projets */ function getAllTechnologies(): array { $technologies = []; foreach (getProjects() as $project) { foreach ($project['technologies'] ?? [] as $tech) { if (!in_array($tech, $technologies, true)) { $technologies[] = $tech; } } } sort($technologies); return $technologies; } /** * Helper pour afficher une image projet optimisée */ function projectImage(string $filename, string $alt, int $width, int $height, bool $lazy = true): string { $webp = $filename; $fallback = str_replace('.webp', '.jpg', $filename); $lazyAttr = $lazy ? 'loading="lazy"' : ''; $altEsc = htmlspecialchars($alt, ENT_QUOTES, 'UTF-8'); $webpEsc = htmlspecialchars($webp, ENT_QUOTES, 'UTF-8'); $fallbackEsc = htmlspecialchars($fallback, ENT_QUOTES, 'UTF-8'); return << {$altEsc} HTML; } /** * Compte les projets par technologie */ function getProjectCountByTech(): array { $projects = getProjects(); $count = []; foreach ($projects as $project) { foreach ($project['technologies'] ?? [] as $tech) { $count[$tech] = ($count[$tech] ?? 0) + 1; } } return $count; } /** * Récupère les projets utilisant une technologie */ function getProjectsByTech(string $tech): array { return array_values(array_filter(getProjects(), function ($project) use ($tech) { return in_array($tech, $project['technologies'] ?? [], true); })); } /** * Icônes d'outils */ function getToolIcon(string $icon): string { $icons = [ 'github' => '', 'vscode' => '', 'figma' => '', 'notion' => '', 'docker' => '', ]; return $icons[$icon] ?? '🛠'; }