diff options
| -rw-r--r-- | next.config.js | 11 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | src/components/atoms/figure/figure.tsx | 2 | ||||
| -rw-r--r-- | src/components/atoms/heading/heading.tsx | 2 | ||||
| -rw-r--r-- | src/components/atoms/lists/list/list.tsx | 12 | ||||
| -rw-r--r-- | src/components/mdx.tsx | 90 | ||||
| m--------- | src/content | 0 | ||||
| -rw-r--r-- | src/pages/cv.tsx | 108 | ||||
| -rw-r--r-- | src/pages/index.tsx | 74 | ||||
| -rw-r--r-- | src/pages/mentions-legales.tsx | 18 | ||||
| -rw-r--r-- | src/pages/projets/[slug].tsx | 117 | ||||
| -rw-r--r-- | src/pages/projets/index.tsx | 9 |
12 files changed, 123 insertions, 321 deletions
diff --git a/next.config.js b/next.config.js index 8227603..6e404a5 100644 --- a/next.config.js +++ b/next.config.js @@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url'; import bundleAnalyzer from '@next/bundle-analyzer'; import nextMDX from '@next/mdx'; import rehypeSlug from 'rehype-slug'; +import { visit } from 'unist-util-visit'; const currentDir = dirname(fileURLToPath(import.meta.url)); @@ -161,11 +162,19 @@ const withBundleAnalyzer = bundleAnalyzer({ enabled: process.env.ANALYZE === 'true', }); +const overrideHTMLTags = () => (tree) => { + visit(tree, 'mdxJsxTextElement', (node) => { + if (node.data) { + delete node.data._mdxExplicitJsx; + } + }); +}; + const withMDX = nextMDX({ extension: /\.mdx?$/, options: { remarkPlugins: [], - rehypePlugins: [rehypeSlug], + rehypePlugins: [rehypeSlug, overrideHTMLTags], }, }); diff --git a/package.json b/package.json index 3d98086..6f39487 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "stylelint-config-standard": "^34.0.0", "stylelint-config-standard-scss": "^11.1.0", "typescript": "^5.2.2", + "unist-util-visit": "^5.0.0", "webpack": "^5.89.0" } } diff --git a/src/components/atoms/figure/figure.tsx b/src/components/atoms/figure/figure.tsx index 4dd5b10..7d63259 100644 --- a/src/components/atoms/figure/figure.tsx +++ b/src/components/atoms/figure/figure.tsx @@ -11,7 +11,7 @@ export type FigureProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & { /** * The contents (ie. an image, illustration, diagram, code snippet, etc.). */ - children: ReactNode; + children?: ReactNode; /** * A figure caption. */ diff --git a/src/components/atoms/heading/heading.tsx b/src/components/atoms/heading/heading.tsx index 6cdb578..d8c58d1 100644 --- a/src/components/atoms/heading/heading.tsx +++ b/src/components/atoms/heading/heading.tsx @@ -14,7 +14,7 @@ export type HeadingProps = HTMLAttributes<HTMLHeadingElement> & { /** * The heading body. */ - children: ReactNode; + children?: ReactNode; /** * Use an heading element or only its styles. * diff --git a/src/components/atoms/lists/list/list.tsx b/src/components/atoms/lists/list/list.tsx index 6e58433..61d2216 100644 --- a/src/components/atoms/lists/list/list.tsx +++ b/src/components/atoms/lists/list/list.tsx @@ -16,14 +16,14 @@ type UnorderedListProps = Omit<HTMLAttributes<HTMLUListElement>, 'children'>; type BaseListProps<O extends boolean, H extends boolean> = O extends true ? OrderedListProps : H extends true - ? OrderedListProps - : UnorderedListProps; + ? OrderedListProps + : UnorderedListProps; type AdditionalProps<O extends boolean, H extends boolean> = { /** - * An array of list items. + * The list items. */ - children: ReactNode; + children?: ReactNode; /** * Should the items marker be hidden? * @@ -109,8 +109,8 @@ const ListWithRef = <O extends boolean, H extends boolean>( O extends true ? HTMLOListElement : H extends true - ? HTMLOListElement - : HTMLUListElement + ? HTMLOListElement + : HTMLUListElement > ) => { const itemSpacing = spacing === null ? 0 : `var(--spacing-${spacing})`; diff --git a/src/components/mdx.tsx b/src/components/mdx.tsx new file mode 100644 index 0000000..f11dda5 --- /dev/null +++ b/src/components/mdx.tsx @@ -0,0 +1,90 @@ +import type { MDXComponents } from 'mdx/types'; +import NextImage from 'next/image'; +import type { AnchorHTMLAttributes, ImgHTMLAttributes, ReactNode } from 'react'; +import { Figure, Heading, Link, List, ListItem } from './atoms'; +import { Code, Grid } from './molecules'; + +const Anchor = ({ + children = '', + href = '', + hrefLang, + rel, + ...props +}: AnchorHTMLAttributes<HTMLAnchorElement>) => ( + <Link + {...props} + isExternal={rel?.includes('external')} + href={href} + lang={hrefLang} + rel={rel} + > + {children} + </Link> +); + +const Img = ({ + alt, + src, + height, + placeholder, + width, + ...props +}: ImgHTMLAttributes<HTMLImageElement>) => { + if (src) + return ( + <NextImage + {...props} + alt={alt ?? ''} + height={typeof height === 'string' ? Number(height) : height} + src={src} + width={typeof width === 'string' ? Number(width) : width} + /> + ); + + // eslint-disable-next-line @next/next/no-img-element + return <img {...props} alt={alt} height={height} src={src} width={width} />; +}; + +const Gallery = ({ children }: { children: ReactNode[] }) => ( + <Grid + // eslint-disable-next-line react/jsx-no-literals + gap="sm" + items={children.map((child, index) => { + return { id: `${index}`, item: child }; + })} + // eslint-disable-next-line react/jsx-no-literals + sizeMin="250px" + /> +); + +export const mdxComponents: MDXComponents = { + a: Anchor, + Code, + figure: ({ ref, ...props }) => <Figure {...props} />, + Figure, + Gallery, + h1: ({ ref, ...props }) => <Heading {...props} level={1} />, + h2: ({ ref, ...props }) => <Heading {...props} level={2} />, + h3: ({ ref, ...props }) => <Heading {...props} level={3} />, + h4: ({ ref, ...props }) => <Heading {...props} level={4} />, + h5: ({ ref, ...props }) => <Heading {...props} level={5} />, + h6: ({ ref, ...props }) => <Heading {...props} level={6} />, + img: Img, + li: ({ ref, ...props }) => <ListItem {...props} />, + Link, + ol: ({ ref, ...props }) => ( + <List + // eslint-disable-next-line react/jsx-no-literals + spacing="2xs" + {...props} + isOrdered + /> + ), + ul: ({ ref, ...props }) => ( + <List + // eslint-disable-next-line react/jsx-no-literals + spacing="2xs" + {...props} + /> + ), +}; diff --git a/src/content b/src/content -Subproject 5099889918cd056394e5bae8d5864b7c25ecaef +Subproject 6c0f2250ea956f9511fed8d2620466cb43d18d3 diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx index fd19a83..edf267d 100644 --- a/src/pages/cv.tsx +++ b/src/pages/cv.tsx @@ -1,30 +1,24 @@ /* eslint-disable max-statements */ -import type { MDXComponents } from 'mdx/types'; import type { GetStaticProps } from 'next'; import Head from 'next/head'; import NextImage from 'next/image'; import { useRouter } from 'next/router'; import Script from 'next/script'; -import React, { - type AnchorHTMLAttributes, - type HTMLAttributes, - type ReactNode, -} from 'react'; +import React, { type ReactNode } from 'react'; import { useIntl } from 'react-intl'; import { getLayout, Heading, ImageWidget, Link, - List, SocialMediaWidget, - ListItem, Page, PageHeader, PageSidebar, TocWidget, PageBody, } from '../components'; +import { mdxComponents } from '../components/mdx'; import CVContent, { data, meta } from '../content/pages/cv.mdx'; import type { NextPageWithLayout } from '../types'; import { CONFIG } from '../utils/config'; @@ -37,102 +31,6 @@ import { import { loadTranslation } from '../utils/helpers/server'; import { useBreadcrumb, useHeadingsTree } from '../utils/hooks'; -const ExternalLink = ({ - children = '', - href = '', - ...props -}: AnchorHTMLAttributes<HTMLAnchorElement>) => ( - <Link {...props} isExternal href={href}> - {children} - </Link> -); - -const H1 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={1}> - {children} - </Heading> -); - -const H2 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={2}> - {children} - </Heading> -); - -const H3 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={3}> - {children} - </Heading> -); - -const H4 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={4}> - {children} - </Heading> -); - -const H5 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={5}> - {children} - </Heading> -); - -const H6 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={6}> - {children} - </Heading> -); - -const OrderedList = ({ - children, - ...props -}: HTMLAttributes<HTMLUListElement>) => ( - <List {...props} isOrdered spacing="2xs"> - {children} - </List> -); - -const UnorderedList = ({ - children, - ...props -}: HTMLAttributes<HTMLUListElement>) => ( - <List {...props} spacing="2xs"> - {children} - </List> -); - -const components: MDXComponents = { - a: ExternalLink, - h1: H1, - h2: H2, - h3: H3, - h4: H4, - h5: H5, - h6: H6, - li: ({ ref, ...props }) => <ListItem {...props} />, - Link, - ol: OrderedList, - ul: UnorderedList, -}; - /** * CV page. */ @@ -258,7 +156,7 @@ const CVPage: NextPageWithLayout = () => { /> </PageSidebar> <PageBody ref={ref}> - <CVContent components={components} /> + <CVContent components={mdxComponents} /> </PageBody> <PageSidebar> <ImageWidget diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 81883fc..32c2e7f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,8 +1,7 @@ -/* eslint-disable max-statements */ import type { MDXComponents } from 'mdx/types'; import type { GetStaticProps } from 'next'; import Head from 'next/head'; -import NextImage, { type ImageProps as NextImageProps } from 'next/image'; +import NextImage from 'next/image'; import Script from 'next/script'; import type { FC, HTMLAttributes, ReactNode } from 'react'; import { useIntl } from 'react-intl'; @@ -14,11 +13,9 @@ import { CardHeader, CardMeta, CardTitle, - Figure, getLayout, Grid, type GridItem, - Heading, Icon, List, ListItem, @@ -27,6 +24,7 @@ import { Time, MetaItem, } from '../components'; +import { mdxComponents } from '../components/mdx'; import HomePageContent from '../content/pages/homepage.mdx'; import { getArticlesCard } from '../services/graphql'; import styles from '../styles/pages/home.module.scss'; @@ -46,66 +44,6 @@ const Column = ({ children, ...props }: HTMLAttributes<HTMLDivElement>) => ( <div {...props}>{children}</div> ); -const H1 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={1}> - {children} - </Heading> -); - -const H2 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={2}> - {children} - </Heading> -); - -const H3 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={3}> - {children} - </Heading> -); - -const H4 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={4}> - {children} - </Heading> -); - -const H5 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={5}> - {children} - </Heading> -); - -const H6 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={6}> - {children} - </Heading> -); - -const ResponsiveImage = (props: NextImageProps) => ( - <Figure> - <NextImage {...props} /> - </Figure> -); - /** * Retrieve a list of coding links. * @@ -368,17 +306,11 @@ const HomePage: NextPageWithLayout<HomeProps> = ({ recentPosts }) => { }; const components: MDXComponents = { + ...mdxComponents, CodingLinks, ColdarkRepos, Column, Grid: StyledGrid, - h1: H1, - h2: H2, - h3: H3, - h4: H4, - h5: H5, - h6: H6, - Image: ResponsiveImage, LibreLinks, MoreLinks, RecentPosts: getRecentPosts, diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx index e3aabc5..d5958a6 100644 --- a/src/pages/mentions-legales.tsx +++ b/src/pages/mentions-legales.tsx @@ -1,15 +1,11 @@ /* eslint-disable max-statements */ -import type { MDXComponents } from 'mdx/types'; import type { GetStaticProps } from 'next'; import Head from 'next/head'; -import NextImage, { type ImageProps as NextImageProps } from 'next/image'; import { useRouter } from 'next/router'; import Script from 'next/script'; import { useIntl } from 'react-intl'; import { getLayout, - Link, - Figure, Page, PageHeader, PageSidebar, @@ -17,6 +13,7 @@ import { Heading, PageBody, } from '../components'; +import { mdxComponents } from '../components/mdx'; import LegalNoticeContent, { meta } from '../content/pages/legal-notice.mdx'; import type { NextPageWithLayout } from '../types'; import { CONFIG } from '../utils/config'; @@ -29,17 +26,6 @@ import { import { loadTranslation } from '../utils/helpers/server'; import { useBreadcrumb, useHeadingsTree } from '../utils/hooks'; -const ResponsiveImage = (props: NextImageProps) => ( - <Figure> - <NextImage {...props} /> - </Figure> -); - -const components: MDXComponents = { - Image: ResponsiveImage, - Link, -}; - /** * Legal Notice page. */ @@ -119,7 +105,7 @@ const LegalNoticePage: NextPageWithLayout = () => { /> </PageSidebar> <PageBody ref={ref}> - <LegalNoticeContent components={components} /> + <LegalNoticeContent components={mdxComponents} /> </PageBody> </Page> ); diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx index 82d9149..2911951 100644 --- a/src/pages/projets/[slug].tsx +++ b/src/pages/projets/[slug].tsx @@ -3,22 +3,16 @@ import type { MDXComponents } from 'mdx/types'; import type { GetStaticPaths, GetStaticProps } from 'next'; import dynamic from 'next/dynamic'; import Head from 'next/head'; -import NextImage, { type ImageProps as NextImageProps } from 'next/image'; +import NextImage from 'next/image'; import { useRouter } from 'next/router'; import Script from 'next/script'; -import type { ComponentType, HTMLAttributes, ReactNode } from 'react'; +import type { ComponentType } from 'react'; import { useIntl } from 'react-intl'; import { - Code, getLayout, - Link, SharingWidget, Spinner, Heading, - List, - ListItem, - Figure, - Grid, ProjectOverview, type ProjectMeta, type Repository, @@ -28,6 +22,7 @@ import { TocWidget, PageBody, } from '../../components'; +import { mdxComponents } from '../../components/mdx'; import styles from '../../styles/pages/project.module.scss'; import type { NextPageWithLayout, ProjectPreview, Repos } from '../../types'; import { CONFIG } from '../../utils/config'; @@ -49,110 +44,6 @@ import { useHeadingsTree, } from '../../utils/hooks'; -const BorderedImage = (props: NextImageProps) => ( - <Figure hasBorders> - <NextImage {...props} /> - </Figure> -); - -const H1 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={1}> - {children} - </Heading> -); - -const H2 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={2}> - {children} - </Heading> -); - -const H3 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={3}> - {children} - </Heading> -); - -const H4 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={4}> - {children} - </Heading> -); - -const H5 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={5}> - {children} - </Heading> -); - -const H6 = ({ - children = '', - ...props -}: HTMLAttributes<HTMLHeadingElement>) => ( - <Heading {...props} level={6}> - {children} - </Heading> -); - -const OrderedList = ({ - children, - ...props -}: HTMLAttributes<HTMLUListElement>) => ( - <List {...props} isOrdered spacing="2xs"> - {children} - </List> -); - -const UnorderedList = ({ - children, - ...props -}: HTMLAttributes<HTMLUListElement>) => ( - <List {...props} spacing="2xs"> - {children} - </List> -); - -const Gallery = ({ children }: { children: ReactNode[] }) => ( - <Grid - gap="sm" - items={children.map((child, index) => { - return { id: `${index}`, item: child }; - })} - sizeMin="250px" - /> -); - -const components: MDXComponents = { - Code, - Gallery, - h1: H1, - h2: H2, - h3: H3, - h4: H4, - h5: H5, - h6: H6, - Image: BorderedImage, - li: ({ ref, ...props }) => <ListItem {...props} />, - Link, - ol: OrderedList, - ul: UnorderedList, -}; - type ProjectPageProps = { project: ProjectPreview; translation: Messages; @@ -326,7 +217,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { meta={overviewMeta} name={project.title} /> - <ProjectContent components={components} /> + <ProjectContent components={mdxComponents} /> </PageBody> <PageSidebar> <SharingWidget diff --git a/src/pages/projets/index.tsx b/src/pages/projets/index.tsx index 0b9a91c..fc6eb5f 100644 --- a/src/pages/projets/index.tsx +++ b/src/pages/projets/index.tsx @@ -1,5 +1,4 @@ /* eslint-disable max-statements */ -import type { MDXComponents } from 'mdx/types'; import type { GetStaticProps } from 'next'; import Head from 'next/head'; import NextImage from 'next/image'; @@ -16,13 +15,13 @@ import { getLayout, Grid, type GridItem, - Link, MetaList, MetaItem, Page, PageHeader, PageBody, } from '../../components'; +import { mdxComponents } from '../../components/mdx'; import PageContent, { meta } from '../../content/pages/projects.mdx'; import styles from '../../styles/pages/projects.module.scss'; import type { NextPageWithLayout, ProjectCard } from '../../types'; @@ -40,10 +39,6 @@ import { } from '../../utils/helpers/server'; import { useBreadcrumb } from '../../utils/hooks'; -const components: MDXComponents = { - Link, -}; - type ProjectsPageProps = { projects: ProjectCard[]; translation?: Messages; @@ -167,7 +162,7 @@ const ProjectsPage: NextPageWithLayout<ProjectsPageProps> = ({ projects }) => { /> <PageHeader heading={title} - intro={<PageContent components={components} />} + intro={<PageContent components={mdxComponents} />} /> <PageBody className={styles.body}> <Grid |
