Correction erreurs TypeScript

This commit is contained in:
Jalil Arfaoui 2026-01-07 03:03:42 +01:00
parent dc3fb4f3d8
commit 030298d311
15 changed files with 2050 additions and 1929 deletions

3859
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@
"check": "biome check --apply-unsafe ." "check": "biome check --apply-unsafe ."
}, },
"devDependencies": { "devDependencies": {
"@astrojs/check": "^0.6.0", "@astrojs/check": "^0.9.4",
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"@biomejs/biome": "1.7.3", "@biomejs/biome": "1.7.3",
"@tailwindcss/typography": "^0.5.13", "@tailwindcss/typography": "^0.5.13",
@ -22,11 +22,7 @@
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "^5.4.5", "typescript": "^5.7.3",
"webdav": "^5.8.0" "webdav": "^5.8.0"
},
"dependencies": {
"@astrojs/check": "^0.9.2",
"typescript": "^5.5.4"
} }
} }

View file

@ -108,7 +108,7 @@ function getCurrentLocaleUrl(targetLocale: string): string {
</a> </a>
<div class="absolute left-0 hidden mt-2 bg-white dark:bg-neutral-900 rounded-lg shadow-lg group-hover:block"> <div class="absolute left-0 hidden mt-2 bg-white dark:bg-neutral-900 rounded-lg shadow-lg group-hover:block">
<div class="py-2"> <div class="py-2">
{menu.children.map((child) => { {menu.children?.map((child) => {
const childUrl = locale === 'fr' ? child.url : `/${locale}${child.url}`; const childUrl = locale === 'fr' ? child.url : `/${locale}${child.url}`;
return ( return (
<a <a

View file

@ -1,5 +1,5 @@
--- ---
import { Image } from 'astro:assets'; import { Picture } from 'astro:assets';
import ScrollIndicator from './ScrollIndicator.astro'; import ScrollIndicator from './ScrollIndicator.astro';
interface Props { interface Props {
@ -16,7 +16,7 @@ const { title, description, date, tags, coverImage, scrollTarget = '.info-sectio
{coverImage && ( {coverImage && (
<div class="hero-image"> <div class="hero-image">
<Image src={coverImage} alt={title} widths={[800, 1200, 1920]} formats={['webp', 'avif']} /> <Picture src={coverImage} alt={title} widths={[800, 1200, 1920]} formats={['webp']} />
<div class="hero-overlay"> <div class="hero-overlay">
<div class="hero-content"> <div class="hero-content">
<h1 class="album-title">{title}</h1> <h1 class="album-title">{title}</h1>

View file

@ -2,7 +2,7 @@
import CategoryNav from './CategoryNav.astro'; import CategoryNav from './CategoryNav.astro';
import ScrollIndicator from './ScrollIndicator.astro'; import ScrollIndicator from './ScrollIndicator.astro';
import Lightbox from './Lightbox.astro'; import Lightbox from './Lightbox.astro';
import { Image } from 'astro:assets'; import { Picture } from 'astro:assets';
import { getEntry } from 'astro:content'; import { getEntry } from 'astro:content';
const { category } = Astro.props; const { category } = Astro.props;
@ -51,7 +51,7 @@ const lightboxImages = images.map(img => ({
<!-- Image hero avec titre en overlay --> <!-- Image hero avec titre en overlay -->
<header class="hero-cover"> <header class="hero-cover">
<div class="hero-image"> <div class="hero-image">
{images[0] && <Image src={images[0].src} alt={images[0].alt} widths={[800, 1200, 1920]} formats={['webp', 'avif']} class="hero-bg" />} {images[0] && <Picture src={images[0].src} alt={images[0].alt} widths={[800, 1200, 1920]} formats={['webp']} class="hero-bg" />}
<div class="hero-overlay"> <div class="hero-overlay">
<div class="hero-content"> <div class="hero-content">
<h1 class="hero-title"> <h1 class="hero-title">
@ -71,11 +71,11 @@ const lightboxImages = images.map(img => ({
{images.map((image, index) => ( {images.map((image, index) => (
<div class="thumbnail-item"> <div class="thumbnail-item">
<a href="#" class="thumbnail-link" data-image-index={index}> <a href="#" class="thumbnail-link" data-image-index={index}>
<Image <Picture
src={image.src} src={image.src}
alt={image.alt} alt={image.alt}
widths={[300, 500, 800]} widths={[300, 500, 800]}
formats={['webp', 'avif']} formats={['webp']}
class="thumbnail-image" class="thumbnail-image"
loading={index < 12 ? 'eager' : 'lazy'} loading={index < 12 ? 'eager' : 'lazy'}
/> />
@ -97,8 +97,8 @@ let lastScrollY = window.scrollY;
let ticking = false; let ticking = false;
function updateNavVisibility() { function updateNavVisibility() {
const header = document.querySelector('.category-navigation'); const header = document.querySelector('.category-navigation') as HTMLElement | null;
const footer = document.querySelector('footer'); const footer = document.querySelector('footer') as HTMLElement | null;
const scrollY = window.scrollY; const scrollY = window.scrollY;
if (scrollY > lastScrollY && scrollY > 100) { if (scrollY > lastScrollY && scrollY > 100) {

View file

@ -75,19 +75,37 @@ const categoryLabels: Record<string, string> = {
</script> </script>
<script> <script>
declare global {
interface Window {
lightboxData?: {
images: { src: string; alt: string; title?: string; category?: string }[];
albumTitle: string;
showCategory: boolean;
category: string;
categoryLabels: Record<string, string>;
};
}
}
class Lightbox { class Lightbox {
images: { src: string; alt: string; title?: string; category?: string }[] = [];
currentIndex = 0;
lightbox: HTMLElement | null;
lightboxImage: HTMLImageElement | null;
lightboxTitle: HTMLElement | null;
lightboxCategory: HTMLElement | null;
lightboxCounter: HTMLElement | null;
albumTitle = '';
showCategory = false;
category = '';
categoryLabels: Record<string, string> = {};
constructor() { constructor() {
this.images = [];
this.currentIndex = 0;
this.lightbox = document.getElementById('lightbox'); this.lightbox = document.getElementById('lightbox');
this.lightboxImage = document.getElementById('lightbox-image'); this.lightboxImage = document.getElementById('lightbox-image') as HTMLImageElement | null;
this.lightboxTitle = document.getElementById('lightbox-title'); this.lightboxTitle = document.getElementById('lightbox-title');
this.lightboxCategory = document.getElementById('lightbox-category'); this.lightboxCategory = document.getElementById('lightbox-category');
this.lightboxCounter = document.getElementById('lightbox-counter'); this.lightboxCounter = document.getElementById('lightbox-counter');
this.albumTitle = '';
this.showCategory = false;
this.category = '';
this.categoryLabels = {};
this.init(); this.init();
} }

View file

@ -1,5 +1,5 @@
--- ---
import { Image } from 'astro:assets'; import { Picture } from 'astro:assets';
interface Props { interface Props {
images: { images: {
@ -15,11 +15,11 @@ const { images, columns = 5 } = Astro.props;
<div class="masonry-gallery" style={`--columns: ${columns}`}> <div class="masonry-gallery" style={`--columns: ${columns}`}>
{images.map((image, index) => ( {images.map((image, index) => (
<div class="gallery-item"> <div class="gallery-item">
<Image <Picture
src={image.src} src={image.src}
alt={image.alt} alt={image.alt}
widths={[300, 500, 800]} widths={[300, 500, 800]}
formats={['webp', 'avif']} formats={['webp']}
data-index={index} data-index={index}
loading={index < 12 ? 'eager' : 'lazy'} loading={index < 12 ? 'eager' : 'lazy'}
/> />

View file

@ -66,6 +66,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (scrollArrow) { if (scrollArrow) {
scrollArrow.addEventListener('click', () => { scrollArrow.addEventListener('click', () => {
const targetSelector = scrollArrow.getAttribute('data-target'); const targetSelector = scrollArrow.getAttribute('data-target');
if (!targetSelector) return;
const targetElement = document.querySelector(targetSelector); const targetElement = document.querySelector(targetSelector);
if (targetElement) { if (targetElement) {
targetElement.scrollIntoView({ targetElement.scrollIntoView({

View file

@ -1,5 +1,9 @@
--- ---
import { Image } from 'astro:assets'; import { Picture } from 'astro:assets';
interface Props {
images: { src: ImageMetadata; alt: string }[];
}
const { images = [] } = Astro.props; const { images = [] } = Astro.props;
--- ---
@ -11,11 +15,11 @@ const { images = [] } = Astro.props;
class={`slide ${index === 0 ? 'active' : ''}`} class={`slide ${index === 0 ? 'active' : ''}`}
data-index={index} data-index={index}
> >
<Image <Picture
src={image.src} src={image.src}
alt={image.alt} alt={image.alt}
widths={[800, 1200, 1920]} widths={[800, 1200, 1920]}
formats={['webp', 'avif']} formats={['webp']}
class="slide-image" class="slide-image"
loading={index < 3 ? 'eager' : 'lazy'} loading={index < 3 ? 'eager' : 'lazy'}
/> />

View file

@ -1,6 +1,6 @@
--- ---
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
const allPosts = await getCollection("post"); const allPosts = await getCollection("blog");
const { count } = Astro.props; const { count } = Astro.props;

View file

@ -0,0 +1,14 @@
---
title: Aria - a minimalist Astro homepage template
description: Aria is a template for Astro
date: 2024-06-06
category: pro
---
[![GitHub](https://github.html.zone/ccbikai/astro-aria)](https://github.com/ccbikai/astro-aria)
Aria is a template I found on [https://aria.devdojo.io/](https://aria.devdojo.io/). It's clean and beautiful, so I decided to use it for my own homepage and ported it to Astro.
It's already open source, so feel free to use it if you're interested.
<https://github.com/ccbikai/astro-aria>

View file

@ -1,19 +1,30 @@
import { defineCollection, z, type ImageFunction } from "astro:content"; import { defineCollection, z, type ImageFunction } from "astro:content";
const formatDate = (date: Date, lang: string = 'fr') => {
const locales: Record<string, string> = { fr: 'fr-FR', en: 'en-US', ar: 'ar-SA' };
return date.toLocaleDateString(locales[lang] || 'fr-FR', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
};
const blogCollection = defineCollection({ const blogCollection = defineCollection({
type: "content", type: "content",
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
date: z.date(), date: z.date(),
dateFormatted: z.string(),
category: z.enum(['pro', 'comedy', 'photo']), category: z.enum(['pro', 'comedy', 'photo']),
tags: z.array(z.string()).optional(), tags: z.array(z.string()).optional(),
image: z.string().optional(), image: z.string().optional(),
imageAlt: z.string().optional(), imageAlt: z.string().optional(),
draft: z.boolean().default(false), draft: z.boolean().default(false),
lang: z.enum(['fr', 'en', 'ar']).default('fr'), lang: z.enum(['fr', 'en', 'ar']).default('fr'),
}), }).transform((data) => ({
...data,
dateFormatted: formatDate(data.date, data.lang),
})),
}); });
const projectsCollection = defineCollection({ const projectsCollection = defineCollection({

View file

@ -16,7 +16,7 @@ export async function getStaticPaths() {
const { category } = Astro.params; const { category } = Astro.params;
const categoryLabels = { const categoryLabels: Record<string, string> = {
'blog': 'Blog', 'blog': 'Blog',
'portraits': 'Portraits', 'portraits': 'Portraits',
'places': 'Paysages', 'places': 'Paysages',
@ -28,7 +28,7 @@ const categoryLabels = {
'everyday': 'Quotidien' 'everyday': 'Quotidien'
}; };
const title = `Galerie ${categoryLabels[category] || category} - Jalil Arfaoui`; const title = `Galerie ${category ? categoryLabels[category] || category : ''} - Jalil Arfaoui`;
--- ---
<PhotoLayout title={title} enableScroll={true}> <PhotoLayout title={title} enableScroll={true}>

View file

@ -2,7 +2,7 @@
import PhotoLayout from '../../../layouts/PhotoLayout.astro'; import PhotoLayout from '../../../layouts/PhotoLayout.astro';
import CategoryNav from '../../../components/photo/CategoryNav.astro'; import CategoryNav from '../../../components/photo/CategoryNav.astro';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { Image } from 'astro:assets'; import { Picture } from 'astro:assets';
// Récupération des posts photo // Récupération des posts photo
const allPhotoBlogPosts = await getCollection('photoBlogPosts'); const allPhotoBlogPosts = await getCollection('photoBlogPosts');
@ -35,7 +35,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
<article class="featured-post"> <article class="featured-post">
<a href={`/photo/blog/${post.slug}`} class="post-link"> <a href={`/photo/blog/${post.slug}`} class="post-link">
<div class="post-image"> <div class="post-image">
{post.resolvedCoverImage && <Image src={post.resolvedCoverImage} alt={post.data.title} widths={[600, 900, 1200]} formats={['webp', 'avif']} />} {post.resolvedCoverImage && <Picture src={post.resolvedCoverImage} alt={post.data.title} widths={[600, 900, 1200]} formats={['webp']} />}
<div class="post-overlay"> <div class="post-overlay">
<div class="post-content"> <div class="post-content">
<span class="post-badge">À la une</span> <span class="post-badge">À la une</span>
@ -64,7 +64,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
{regularPosts.map(post => ( {regularPosts.map(post => (
<article class="post-item"> <article class="post-item">
<a href={`/photo/blog/${post.slug}`} class="post-link"> <a href={`/photo/blog/${post.slug}`} class="post-link">
{post.resolvedCoverImage && <Image src={post.resolvedCoverImage} alt={post.data.title} widths={[400, 600, 800]} formats={['webp', 'avif']} />} {post.resolvedCoverImage && <Picture src={post.resolvedCoverImage} alt={post.data.title} widths={[400, 600, 800]} formats={['webp']} />}
<div class="post-overlay"> <div class="post-overlay">
<div class="overlay-content"> <div class="overlay-content">
<h3 class="post-title">{post.data.title}</h3> <h3 class="post-title">{post.data.title}</h3>

View file

@ -2,7 +2,7 @@
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
export async function getStaticPaths() { export async function getStaticPaths() {
const postEntries = await getCollection("post"); const postEntries = await getCollection("blog");
return postEntries.map((entry) => ({ return postEntries.map((entry) => ({
params: { slug: entry.slug }, params: { slug: entry.slug },
props: { entry }, props: { entry },