diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/ToC/ToC.tsx | 31 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 2 | ||||
| -rw-r--r-- | src/pages/cv.tsx | 12 | ||||
| -rw-r--r-- | src/pages/mentions-legales.tsx | 12 | ||||
| -rw-r--r-- | src/ts/types/app.ts | 7 | ||||
| -rw-r--r-- | src/utils/hooks/useHeadingsTree.tsx | 8 |
6 files changed, 61 insertions, 11 deletions
diff --git a/src/components/ToC/ToC.tsx b/src/components/ToC/ToC.tsx new file mode 100644 index 0000000..e7aafa5 --- /dev/null +++ b/src/components/ToC/ToC.tsx @@ -0,0 +1,31 @@ +import { t } from '@lingui/macro'; +import { Heading } from '@ts/types/app'; +import { slugify } from '@utils/helpers/slugify'; +import useHeadingsTree from '@utils/hooks/useHeadingsTree'; + +const ToC = () => { + const headingsTree = useHeadingsTree('article'); + const title = t`Table of contents`; + + const getItems = (headings: Heading[]) => { + return headings.map((heading) => { + if (heading.id === slugify(title)) return; + + return ( + <li key={heading.id}> + <a href={`#${heading.id}`}>{heading.title}</a> + {heading.children.length > 0 && <ol>{getItems(heading.children)}</ol>} + </li> + ); + }); + }; + + return ( + <> + <h2>{title}</h2> + <ol>{getItems(headingsTree)}</ol> + </> + ); +}; + +export default ToC; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index 621b2e2..1fa65fa 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -3,6 +3,7 @@ import CommentsList from '@components/CommentsList/CommentsList'; import { getLayout } from '@components/Layouts/Layout'; import PostFooter from '@components/PostFooter/PostFooter'; import PostHeader from '@components/PostHeader/PostHeader'; +import ToC from '@components/ToC/ToC'; import { t } from '@lingui/macro'; import { getAllPostsSlug, getPostBySlug } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; @@ -39,6 +40,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => { title={title} thematics={thematics} /> + <ToC /> <div dangerouslySetInnerHTML={{ __html: content }}></div> <PostFooter subjects={subjects} /> <section> diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx index de63ec6..44d943c 100644 --- a/src/pages/cv.tsx +++ b/src/pages/cv.tsx @@ -1,4 +1,5 @@ import { getLayout } from '@components/Layouts/Layout'; +import ToC from '@components/ToC/ToC'; import { seo } from '@config/seo'; import { getPageByUri } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; @@ -17,9 +18,16 @@ const CV: NextPageWithLayout<PageProps> = ({ page }) => { <article> <header> <h1>{page.title}</h1> - <div dangerouslySetInnerHTML={{ __html: page.intro }}></div> + {page.content && ( + <div dangerouslySetInnerHTML={{ __html: page.intro }}></div> + )} </header> - <div dangerouslySetInnerHTML={{ __html: page.content }}></div> + <ToC /> + <div + dangerouslySetInnerHTML={{ + __html: page.content ? page.content : page.intro, + }} + ></div> </article> </> ); diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx index 6155132..41e9a0c 100644 --- a/src/pages/mentions-legales.tsx +++ b/src/pages/mentions-legales.tsx @@ -1,4 +1,5 @@ import { getLayout } from '@components/Layouts/Layout'; +import ToC from '@components/ToC/ToC'; import { seo } from '@config/seo'; import { getPageByUri } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; @@ -17,9 +18,16 @@ const LegalNotice: NextPageWithLayout<PageProps> = ({ page }) => { <article> <header> <h1>{page.title}</h1> - <div dangerouslySetInnerHTML={{ __html: page.intro }}></div> + {page.content && ( + <div dangerouslySetInnerHTML={{ __html: page.intro }}></div> + )} </header> - <div dangerouslySetInnerHTML={{ __html: page.content }}></div> + <ToC /> + <div + dangerouslySetInnerHTML={{ + __html: page.content ? page.content : page.intro, + }} + ></div> </article> </> ); diff --git a/src/ts/types/app.ts b/src/ts/types/app.ts index ba28416..e1d8917 100644 --- a/src/ts/types/app.ts +++ b/src/ts/types/app.ts @@ -76,6 +76,13 @@ export type Dates = { update: string; }; +export type Heading = { + depth: number; + id: string; + children: Heading[]; + title: string; +}; + export type PageInfo = { endCursor: string; hasNextPage: boolean; diff --git a/src/utils/hooks/useHeadingsTree.tsx b/src/utils/hooks/useHeadingsTree.tsx index 8bb70c8..94d3b4b 100644 --- a/src/utils/hooks/useHeadingsTree.tsx +++ b/src/utils/hooks/useHeadingsTree.tsx @@ -1,13 +1,7 @@ +import { Heading } from '@ts/types/app'; import { slugify } from '@utils/helpers/slugify'; import { useCallback, useEffect, useMemo, useState } from 'react'; -type Heading = { - depth: number; - id: string; - children: Heading[]; - title: string; -}; - const useHeadingsTree = (wrapper: string) => { const [headingsTree, setHeadingsTree] = useState<Heading[]>([]); const depths = useMemo(() => ['h2', 'h3', 'h4', 'h5', 'h6'], []); |
