Skip to content

Commit

Permalink
refactor: generate image with sharp and convert enum to const
Browse files Browse the repository at this point in the history
  • Loading branch information
fpasquet committed Apr 14, 2024
1 parent ea996d0 commit 3d4725a
Show file tree
Hide file tree
Showing 41 changed files with 352 additions and 257 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ excerpt: >-
categories: []
cover:
path: /imgs/articles/2024-02-19-quelques-conseils-pour-optimiser-votre-environnement-de-travail-sous-linux/cover.jpg
position: top
authors:
- nicolas
keywords:
Expand Down
1 change: 1 addition & 0 deletions _tutorials/fr/2024-03-27-chromatic/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ excerpt: >-
Nous allons découvrir comment utiliser Chromatic en CI pour faire des tests de non régression visuelle et des tests d'interaction sur un Storybook pour être confiant à chaque nouvelle feature implémentée.
cover:
path: /imgs/tutorials/2024-03-27-chromatic/cover.jpg
position: top
categories:
- javascript
keywords:
Expand Down
4 changes: 2 additions & 2 deletions src/config/i18n/i18n.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { InitOptions } from 'i18next';

import { BASE_URL, DEFAULT_LANGUAGE, IS_DEBUG, LanguageEnum, LANGUAGES_AVAILABLE } from '@/constants';
import { BASE_URL, DEFAULT_LANGUAGE, IS_DEBUG, LANGUAGES, LANGUAGES_AVAILABLE } from '@/constants';

export const i18nConfig = {
load: 'languageOnly',
preload: LANGUAGES_AVAILABLE,
whitelist: LANGUAGES_AVAILABLE,
fallbackLng: IS_DEBUG ? LanguageEnum.DT : DEFAULT_LANGUAGE,
fallbackLng: IS_DEBUG ? LANGUAGES.DT : DEFAULT_LANGUAGE,
returnEmptyString: false,
defaultNS: 'messages',
ns: 'messages',
Expand Down
8 changes: 4 additions & 4 deletions src/config/router/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Params, RouteObject } from 'react-router';
import { Outlet } from 'react-router-dom';

import { LanguageEnum, LANGUAGES_AVAILABLE_WITH_DT, PATHS } from '@/constants';
import { LANGUAGES_AVAILABLE_WITH_DT, PATHS } from '@/constants';
import { AuthorPageContainer } from '@/containers/AuthorPageContainer';
import { CategoryPageContainer } from '@/containers/CategoryPageContainer';
import { HomePageContainer } from '@/containers/HomePageContainer';
Expand All @@ -16,7 +16,7 @@ import {
loadPostListPageData,
loadPostPageData,
} from '@/helpers/loaderDataHelper';
import { LayoutTemplateData } from '@/types';
import { LanguageType, LayoutTemplateData } from '@/types';

export const routes: RouteObject[] = [
{
Expand Down Expand Up @@ -50,8 +50,8 @@ export const routes: RouteObject[] = [
{
path: '/:lang/',
loader: ({ params }): Record<string, unknown> => {
const languages = LANGUAGES_AVAILABLE_WITH_DT as LanguageEnum[];
if (!languages.includes(params.lang as LanguageEnum)) {
const languages = LANGUAGES_AVAILABLE_WITH_DT as LanguageType[];
if (!languages.includes(params.lang as LanguageType)) {
throw new Error(`The \`${params.lang}\` language doesn't exist`);
}
return {};
Expand Down
4 changes: 2 additions & 2 deletions src/config/schemaValidation/AuthorDataValidationSchema.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { z } from 'zod';

import { ContentTypeEnum } from '@/constants';
import { MARKDOWN_CONTENT_TYPES } from '@/constants';

export const AuthorDataValidationSchema = z.object({
contentType: z.literal(ContentTypeEnum.AUTHOR),
contentType: z.literal(MARKDOWN_CONTENT_TYPES.AUTHOR),
username: z.string().regex(/^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/, 'Kebab case format not respected'),
name: z.string(),
twitter: z
Expand Down
14 changes: 9 additions & 5 deletions src/config/schemaValidation/PostDataSchemaValidation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { z } from 'zod';

import { CATEGORIES, ContentTypeEnum, LanguageEnum } from '@/constants';
import { CATEGORIES, IMAGE_POSITIONS, LANGUAGES, MARKDOWN_CONTENT_TYPES } from '@/constants';
import { intersection } from '@/helpers/objectHelper';

export const PostDataSchemaValidation = z.object({
contentType: z.enum([ContentTypeEnum.ARTICLE, ContentTypeEnum.TUTORIAL]),
lang: z.nativeEnum(LanguageEnum),
contentType: z.nativeEnum({
ARTICLE: MARKDOWN_CONTENT_TYPES.ARTICLE,
TUTORIAL: MARKDOWN_CONTENT_TYPES.TUTORIAL,
} as const),
lang: z.nativeEnum(LANGUAGES),
date: z.coerce.date().transform((date) => date.toISOString().slice(0, 10)),
slug: z.string().regex(/^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/, 'Kebab case format not respected'),
title: z.string(),
Expand All @@ -14,6 +17,7 @@ export const PostDataSchemaValidation = z.object({
cover: z
.object({
path: z.string(),
position: z.nativeEnum(IMAGE_POSITIONS).optional(),
alt: z.string(),
})
.optional(),
Expand Down Expand Up @@ -48,13 +52,13 @@ export const PostDataSchemaValidation = z.object({

export const ArticleDataSchemaValidation = PostDataSchemaValidation.merge(
z.object({
contentType: z.literal(ContentTypeEnum.ARTICLE),
contentType: z.literal(MARKDOWN_CONTENT_TYPES.ARTICLE),
})
);

export const TutorialDataSchemaValidation = PostDataSchemaValidation.merge(
z.object({
contentType: z.literal(ContentTypeEnum.TUTORIAL),
contentType: z.literal(MARKDOWN_CONTENT_TYPES.TUTORIAL),
steps: z.array(z.string()),
})
);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { z } from 'zod';

import { ContentTypeEnum } from '@/constants';
import { MARKDOWN_CONTENT_TYPES } from '@/constants';

export const TutorialStepDataValidationSchema = z.object({
contentType: z.literal(ContentTypeEnum.TUTORIAL_STEP),
contentType: z.literal(MARKDOWN_CONTENT_TYPES.TUTORIAL_STEP),
tutorial: z.string(),
slug: z.string(),
title: z.string(),
Expand Down
132 changes: 81 additions & 51 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getEnv } from '@/helpers/getEnvHelper';
import { DeviceType, ImageExtensionType, ImageFormatType } from '@/types';

export const IS_SSR = import.meta.env?.SSR ?? false;
export const IS_PRERENDER = import.meta.env?.MODE === 'prerender';
Expand All @@ -7,26 +8,25 @@ export const BASE_URL = import.meta.env?.BASE_URL || '/';

export const IS_DEBUG = getEnv<string>('VITE_IS_DEBUG') === 'true';

export enum LanguageEnum {
FR = 'fr',
EN = 'en',
DT = 'dt',
}
export const LANGUAGES = {
FR: 'fr',
EN: 'en',
DT: 'dt',
} as const;

export const LANGUAGES_AVAILABLE = [LanguageEnum.FR, LanguageEnum.EN] as const;
export const LANGUAGES_AVAILABLE_WITH_DT = IS_DEBUG ? [...LANGUAGES_AVAILABLE, LanguageEnum.DT] : LANGUAGES_AVAILABLE;
export const LANGUAGES_AVAILABLE = [LANGUAGES.FR, LANGUAGES.EN] as const;
export const LANGUAGES_AVAILABLE_WITH_DT = IS_DEBUG ? [...LANGUAGES_AVAILABLE, LANGUAGES.DT] : LANGUAGES_AVAILABLE;

export enum ContentTypeEnum {
ARTICLE = 'article',
TUTORIAL = 'tutorial',
TUTORIAL_STEP = 'tutorial-step',
AUTHOR = 'author',
}
export const MARKDOWN_CONTENT_TYPES = {
ARTICLE: 'article',
TUTORIAL: 'tutorial',
TUTORIAL_STEP: 'tutorial-step',
AUTHOR: 'author',
} as const;

export const CATEGORIES = ['javascript', 'php', 'agile', 'architecture'] as const;
export type CategoryEnum = (typeof CATEGORIES)[number];

export const DEFAULT_LANGUAGE = LanguageEnum.FR;
export const DEFAULT_LANGUAGE = LANGUAGES.FR;
export const NUMBER_OF_ITEMS_FOR_SEARCH = 6;
export const NUMBER_OF_ITEMS_PER_PAGE = 12;

Expand All @@ -51,53 +51,83 @@ export const GTM_ID = getEnv<string>('VITE_GTM_ID');

export const GOOGLE_SITE_VERIFICATION = getEnv<string>('VITE_GOOGLE_SITE_VERIFICATION');

export enum ImageFormatEnum {
HIGHLIGHTED_ARTICLE_POST_CARD_COVER = 'highlighted-article-post-card-cover',
HIGHLIGHTED_TUTORIAL_POST_CARD_COVER = 'highlighted-tutorial-post-card-cover',
POST_CARD_COVER = 'post-card-cover',
POST_COVER = 'post-cover',
}

export enum DeviceEnum {
MOBILE = 'mobile',
DESKTOP = 'desktop',
}

export const IMAGE_FORMATS: Record<DeviceEnum, Record<ImageFormatEnum, { width: number; height: number }>> = {
mobile: {
[ImageFormatEnum.HIGHLIGHTED_ARTICLE_POST_CARD_COVER]: {
width: 67,
height: 67,
},
[ImageFormatEnum.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER]: {
width: 328,
height: 130,
},
[ImageFormatEnum.POST_CARD_COVER]: {
width: 67,
height: 67,
},
[ImageFormatEnum.POST_COVER]: {
width: 330,
height: 160,
},
},
desktop: {
[ImageFormatEnum.HIGHLIGHTED_ARTICLE_POST_CARD_COVER]: {
export const IMAGE_FORMATS = {
HIGHLIGHTED_ARTICLE_POST_CARD_COVER: 'highlighted-article-post-card-cover',
HIGHLIGHTED_TUTORIAL_POST_CARD_COVER: 'highlighted-tutorial-post-card-cover',
POST_CARD_COVER: 'post-card-cover',
POST_COVER: 'post-cover',
} as const;

export const DEVICES = {
DESKTOP: 'desktop',
MOBILE: 'mobile',
} as const;

export const IMAGE_CONTENT_TYPES = {
jpeg: 'image/jpeg',
gif: 'image/gif',
webp: 'image/webp',
png: 'image/png',
avif: 'image/avif',
} as const;

export const IMAGE_POSITIONS = {
TOP: 'top',
RIGHT_AND_TOP: 'right top',
RIGHT: 'right',
RIGHT_BOTTOM: 'right bottom',
BOTTOM: 'bottom',
LEFT_AND_BOTTOM: 'left bottom',
LEFT: 'left',
LEFT_TOP: 'left top',
CENTER: 'center',
NORTH: 'north',
NORTHEAST: 'northeast',
EAST: 'east',
SOUTHEAST: 'southeast',
SOUTH: 'south',
SOUTHWEST: 'southwest',
WEST: 'west',
NORTHWEST: 'northwest',
} as const;

export const DEFAULT_EXTENSION_FOR_IMAGES: ImageExtensionType = 'avif';

export const SIZES_BY_IMAGE_FORMAT: Record<DeviceType, Record<ImageFormatType, { width: number; height: number }>> = {
[DEVICES.DESKTOP]: {
[IMAGE_FORMATS.HIGHLIGHTED_ARTICLE_POST_CARD_COVER]: {
width: 385,
height: 175,
},
[ImageFormatEnum.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER]: {
[IMAGE_FORMATS.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER]: {
width: 400,
height: 245,
},
[ImageFormatEnum.POST_CARD_COVER]: {
[IMAGE_FORMATS.POST_CARD_COVER]: {
width: 190,
height: 190,
},
[ImageFormatEnum.POST_COVER]: {
[IMAGE_FORMATS.POST_COVER]: {
width: 1200,
height: 330,
},
},
[DEVICES.MOBILE]: {
[IMAGE_FORMATS.HIGHLIGHTED_ARTICLE_POST_CARD_COVER]: {
width: 67,
height: 67,
},
[IMAGE_FORMATS.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER]: {
width: 328,
height: 130,
},
[IMAGE_FORMATS.POST_CARD_COVER]: {
width: 67,
height: 67,
},
[IMAGE_FORMATS.POST_COVER]: {
width: 330,
height: 160,
},
},
} as const;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Box, PostPageProps } from '@eleven-labs/design-system';
import React from 'react';
import { useTranslation } from 'react-i18next';

import { ContentTypeEnum } from '@/constants';
import { MARKDOWN_CONTENT_TYPES } from '@/constants';
import { slugify } from '@/helpers/stringHelper';
import { usePostPage } from '@/hooks/usePostPage';
import { ArticlePageData } from '@/types';
Expand All @@ -12,7 +12,7 @@ export const useArticlePageContainer = (article: ArticlePageData): PostPageProps
const postPage = usePostPage(article);

return {
variant: ContentTypeEnum.ARTICLE,
variant: MARKDOWN_CONTENT_TYPES.ARTICLE,
...postPage,
summary: {
title: t('pages.article.summary_card.title'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useLoaderData, useParams } from 'react-router-dom';

import { blogUrl } from '@/config/website';
import { ContentTypeEnum, DEFAULT_LANGUAGE, PATHS } from '@/constants';
import { DEFAULT_LANGUAGE, MARKDOWN_CONTENT_TYPES, PATHS } from '@/constants';
import { PostCardListContainer, PostCardListContainerProps } from '@/containers/PostCardListContainer';
import { TransWithHtml } from '@/containers/TransWithHtml';
import { generatePath } from '@/helpers/routerHelper';
Expand Down Expand Up @@ -40,7 +40,7 @@ export const useCategoryPageContainer = (): CategoryPageProps => {
title: <TransWithHtml i18nKey={`pages.category.${categoryName}.title`} onlyLineBreak />,
description: <TransWithHtml i18nKey={`pages.category.${categoryName}.description`} />,
},
categoryEndingBlock: !['all', ContentTypeEnum.TUTORIAL].includes(categoryName as string)
categoryEndingBlock: !['all', MARKDOWN_CONTENT_TYPES.TUTORIAL].includes(categoryName as string)
? {
title: <TransWithHtml i18nKey={`pages.category.${categoryName}.expertise.title`} onlyLineBreak />,
description: <TransWithHtml i18nKey={`pages.category.${categoryName}.expertise.description`} />,
Expand Down
16 changes: 8 additions & 8 deletions src/containers/HomePageContainer/useHomePageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useLoaderData } from 'react-router-dom';

import { blogUrl, websiteUrl } from '@/config/website';
import { ContentTypeEnum, DEFAULT_LANGUAGE, ImageFormatEnum, LanguageEnum, PATHS } from '@/constants';
import { DEFAULT_LANGUAGE, IMAGE_FORMATS, LANGUAGES, MARKDOWN_CONTENT_TYPES, PATHS } from '@/constants';
import { TransWithHtml } from '@/containers/TransWithHtml';
import { generatePath } from '@/helpers/routerHelper';
import { useNewsletterCard } from '@/hooks/useNewsletterCard';
Expand All @@ -22,21 +22,21 @@ export const useHomePageContainer = (): HomePageProps => {
posts: postListPageData.posts
.filter(
(post) =>
post.contentType === ContentTypeEnum.ARTICLE &&
(i18n.language === LanguageEnum.DT || post.lang === i18n.language)
post.contentType === MARKDOWN_CONTENT_TYPES.ARTICLE &&
(i18n.language === LANGUAGES.DT || post.lang === i18n.language)
)
.slice(0, 3),
imageFormatEnum: ImageFormatEnum.HIGHLIGHTED_ARTICLE_POST_CARD_COVER,
imageFormat: IMAGE_FORMATS.HIGHLIGHTED_ARTICLE_POST_CARD_COVER,
});
const lastTutorialsForCardList = usePostsForCardList({
posts: postListPageData.posts
.filter(
(post) =>
post.contentType === ContentTypeEnum.TUTORIAL &&
(i18n.language === LanguageEnum.DT || post.lang === i18n.language)
post.contentType === MARKDOWN_CONTENT_TYPES.TUTORIAL &&
(i18n.language === LANGUAGES.DT || post.lang === i18n.language)
)
.slice(0, 2),
imageFormatEnum: ImageFormatEnum.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER,
imageFormat: IMAGE_FORMATS.HIGHLIGHTED_TUTORIAL_POST_CARD_COVER,
});

useTitle(t('pages.home.seo.title'));
Expand Down Expand Up @@ -73,7 +73,7 @@ export const useHomePageContainer = (): HomePageProps => {
posts: lastTutorialsForCardList,
linkSeeMore: {
label: t('pages.home.last-tutorials-block.link-see-more'),
href: generatePath(PATHS.CATEGORY, { categoryName: ContentTypeEnum.TUTORIAL, lang: i18n.language }),
href: generatePath(PATHS.CATEGORY, { categoryName: MARKDOWN_CONTENT_TYPES.TUTORIAL, lang: i18n.language }),
},
}
: undefined,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PostCardListProps } from '@eleven-labs/design-system';

import { ImageFormatEnum, NUMBER_OF_ITEMS_PER_PAGE } from '@/constants';
import { IMAGE_FORMATS, NUMBER_OF_ITEMS_PER_PAGE } from '@/constants';
import { usePostsForCardList } from '@/hooks/usePostsForCardList';

import { PostCardListContainerProps } from './PostCardListContainer';
Expand All @@ -20,7 +20,7 @@ export const usePostCardListContainer = ({
isLoading,
numberOfItems: NUMBER_OF_ITEMS_PER_PAGE,
posts,
imageFormatEnum: ImageFormatEnum.POST_CARD_COVER,
imageFormat: IMAGE_FORMATS.POST_CARD_COVER,
});

return {
Expand Down

0 comments on commit 3d4725a

Please sign in to comment.