diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-03-01 22:05:08 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-03-01 22:05:08 +0100 |
| commit | 8bd9784acdee6871ad70e86d0d7120299bf76969 (patch) | |
| tree | 9b81e0cd3ff881b2cbeb81f9f96b52b510d67646 /src | |
| parent | 21c228600a7a69cfea3b7d8af6838bcfda1d7399 (diff) | |
refactor: split posts meta into smaller components
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Layouts/Layout.tsx | 3 | ||||
| -rw-r--r-- | src/components/MetaItems/Author/Author.tsx | 20 | ||||
| -rw-r--r-- | src/components/MetaItems/CommentsCount/CommentsCount.tsx | 41 | ||||
| -rw-r--r-- | src/components/MetaItems/Dates/Dates.tsx | 56 | ||||
| -rw-r--r-- | src/components/MetaItems/MetaItem/MetaItem.module.scss | 18 | ||||
| -rw-r--r-- | src/components/MetaItems/MetaItem/MetaItem.tsx | 36 | ||||
| -rw-r--r-- | src/components/MetaItems/PostsCount/PostsCount.tsx | 27 | ||||
| -rw-r--r-- | src/components/MetaItems/ReadingTime/ReadingTime.tsx | 55 | ||||
| -rw-r--r-- | src/components/MetaItems/Thematics/Thematics.tsx | 42 | ||||
| -rw-r--r-- | src/components/MetaItems/Topics/Topics.tsx | 36 | ||||
| -rw-r--r-- | src/components/MetaItems/Website/Website.tsx | 20 | ||||
| -rw-r--r-- | src/components/MetaItems/index.tsx | 21 | ||||
| -rw-r--r-- | src/components/PostHeader/PostHeader.tsx | 16 | ||||
| -rw-r--r-- | src/components/PostMeta/PostMeta.module.scss | 21 | ||||
| -rw-r--r-- | src/components/PostMeta/PostMeta.tsx | 236 | ||||
| -rw-r--r-- | src/i18n/en.json | 102 | ||||
| -rw-r--r-- | src/i18n/fr.json | 102 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 4 | ||||
| -rw-r--r-- | src/ts/types/app.ts | 2 |
19 files changed, 515 insertions, 343 deletions
diff --git a/src/components/Layouts/Layout.tsx b/src/components/Layouts/Layout.tsx index 845d6fa..23c1d0e 100644 --- a/src/components/Layouts/Layout.tsx +++ b/src/components/Layouts/Layout.tsx @@ -19,9 +19,8 @@ const Layout = ({ isHome?: boolean; }) => { const intl = useIntl(); - const { locale } = useRouter(); + const { asPath, locale } = useRouter(); const ref = useRef<HTMLSpanElement>(null); - const { asPath } = useRouter(); useEffect(() => { ref.current?.focus(); diff --git a/src/components/MetaItems/Author/Author.tsx b/src/components/MetaItems/Author/Author.tsx new file mode 100644 index 0000000..c3d78c2 --- /dev/null +++ b/src/components/MetaItems/Author/Author.tsx @@ -0,0 +1,20 @@ +import { MetaKind } from '@ts/types/app'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const Author = ({ name, kind }: { name: string; kind: MetaKind }) => { + const intl = useIntl(); + + return ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Written by:', + description: 'Author: article author meta label', + })} + value={name} + kind={kind} + /> + ); +}; + +export default Author; diff --git a/src/components/MetaItems/CommentsCount/CommentsCount.tsx b/src/components/MetaItems/CommentsCount/CommentsCount.tsx new file mode 100644 index 0000000..bd1990d --- /dev/null +++ b/src/components/MetaItems/CommentsCount/CommentsCount.tsx @@ -0,0 +1,41 @@ +import { MetaKind } from '@ts/types/app'; +import { useRouter } from 'next/router'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const CommentsCount = ({ total, kind }: { total: number; kind: MetaKind }) => { + const intl = useIntl(); + const { asPath } = useRouter(); + + const isArticle = () => asPath.includes('/article/'); + + const getCommentsCount = () => { + return intl.formatMessage( + { + defaultMessage: + '{total, plural, =0 {No comments} one {# comment} other {# comments}}', + description: 'CommentsCount: comment count value', + }, + { total } + ); + }; + + return ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Comments:', + description: 'CommentsCount: comment count meta label', + })} + value={ + isArticle() ? ( + <a href="#comments">{getCommentsCount()}</a> + ) : ( + getCommentsCount() + ) + } + kind={kind} + /> + ); +}; + +export default CommentsCount; diff --git a/src/components/MetaItems/Dates/Dates.tsx b/src/components/MetaItems/Dates/Dates.tsx new file mode 100644 index 0000000..04dff3a --- /dev/null +++ b/src/components/MetaItems/Dates/Dates.tsx @@ -0,0 +1,56 @@ +import { MetaKind } from '@ts/types/app'; +import { settings } from '@utils/config'; +import { getFormattedDate } from '@utils/helpers/format'; +import { useRouter } from 'next/router'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const Dates = ({ + publication, + update, + kind, +}: { + publication: string; + update: string; + kind: MetaKind; +}) => { + const intl = useIntl(); + const { locale } = useRouter(); + const validLocale = locale ? locale : settings.locales.defaultLocale; + + const publicationDate = getFormattedDate(publication, validLocale); + const updateDate = getFormattedDate(update, validLocale); + + return ( + <> + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Published on:', + description: 'Dates: publication date meta label', + })} + values={[ + <time key={publication} dateTime={publication}> + {publicationDate} + </time>, + ]} + kind={kind} + /> + {publicationDate !== updateDate && ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Updated on:', + description: 'Dates: update date meta label', + })} + values={[ + <time key={update} dateTime={update}> + {updateDate} + </time>, + ]} + kind={kind} + /> + )} + </> + ); +}; + +export default Dates; diff --git a/src/components/MetaItems/MetaItem/MetaItem.module.scss b/src/components/MetaItems/MetaItem/MetaItem.module.scss new file mode 100644 index 0000000..0b159ca --- /dev/null +++ b/src/components/MetaItems/MetaItem/MetaItem.module.scss @@ -0,0 +1,18 @@ +.wrapper--article { + display: flex; + flex-flow: row wrap; +} + +.title--article { + margin-right: var(--spacing-2xs); + color: var(--color-fg-light); +} + +.body--article { + &:not(:first-of-type) { + &::before { + content: "/"; + margin: 0 var(--spacing-2xs); + } + } +} diff --git a/src/components/MetaItems/MetaItem/MetaItem.tsx b/src/components/MetaItems/MetaItem/MetaItem.tsx new file mode 100644 index 0000000..5c51283 --- /dev/null +++ b/src/components/MetaItems/MetaItem/MetaItem.tsx @@ -0,0 +1,36 @@ +import { MetaKind } from '@ts/types/app'; +import { ReactElement } from 'react'; +import styles from './MetaItem.module.scss'; + +const MetaItem = ({ + title, + value, + values, + info, + kind = 'list', +}: { + title: string; + value?: ReactElement | string; + values?: ReactElement[] | string[]; + info?: string; + kind: MetaKind; +}) => { + return ( + <div className={styles[`wrapper--${kind}`]}> + <dt className={styles[`title--${kind}`]}>{title}</dt> + {value && ( + <dd className={styles[`body--${kind}`]} title={info}> + {value} + </dd> + )} + {values && + values.map((currentValue, index) => ( + <dd key={index} className={styles[`body--${kind}`]} title={info}> + {currentValue} + </dd> + ))} + </div> + ); +}; + +export default MetaItem; diff --git a/src/components/MetaItems/PostsCount/PostsCount.tsx b/src/components/MetaItems/PostsCount/PostsCount.tsx new file mode 100644 index 0000000..9fb1784 --- /dev/null +++ b/src/components/MetaItems/PostsCount/PostsCount.tsx @@ -0,0 +1,27 @@ +import { MetaKind } from '@ts/types/app'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const PostsCount = ({ total, kind }: { total: number; kind: MetaKind }) => { + const intl = useIntl(); + + return ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Total:', + description: 'PostCount: total found articles meta label', + })} + value={intl.formatMessage( + { + defaultMessage: + '{total, plural, =0 {No articles} one {# article} other {# articles}}', + description: 'PostCount: total found articles', + }, + { total } + )} + kind={kind} + /> + ); +}; + +export default PostsCount; diff --git a/src/components/MetaItems/ReadingTime/ReadingTime.tsx b/src/components/MetaItems/ReadingTime/ReadingTime.tsx new file mode 100644 index 0000000..94215b3 --- /dev/null +++ b/src/components/MetaItems/ReadingTime/ReadingTime.tsx @@ -0,0 +1,55 @@ +import { MetaKind } from '@ts/types/app'; +import { useRouter } from 'next/router'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const ReadingTime = ({ + time, + words, + kind, +}: { + time: number; + words: number; + kind: MetaKind; +}) => { + const intl = useIntl(); + const { locale } = useRouter(); + + const getEstimation = () => { + if (time < 0) { + return intl.formatMessage({ + defaultMessage: 'less than 1 minute', + description: 'ReadingTime: Reading time value', + }); + } + + return intl.formatMessage( + { + defaultMessage: + '{time, plural, =0 {# minutes} one {# minute} other {# minutes}}', + description: 'ReadingTime: reading time value', + }, + { time } + ); + }; + + return ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Reading time:', + description: 'ReadingTime: reading time meta label', + })} + value={getEstimation()} + info={intl.formatMessage( + { + defaultMessage: `Approximately {number} words`, + description: 'ReadingTime: number of words', + }, + { number: words.toLocaleString(locale) } + )} + kind={kind} + /> + ); +}; + +export default ReadingTime; diff --git a/src/components/MetaItems/Thematics/Thematics.tsx b/src/components/MetaItems/Thematics/Thematics.tsx new file mode 100644 index 0000000..a127715 --- /dev/null +++ b/src/components/MetaItems/Thematics/Thematics.tsx @@ -0,0 +1,42 @@ +import { MetaKind } from '@ts/types/app'; +import { ThematicPreview } from '@ts/types/taxonomies'; +import Link from 'next/link'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const Thematics = ({ + list, + kind, +}: { + list: ThematicPreview[]; + kind: MetaKind; +}) => { + const intl = useIntl(); + + const getThematics = () => { + return list.map((thematic) => { + return ( + <Link key={thematic.databaseId} href={`/thematique/${thematic.slug}`}> + <a>{thematic.title}</a> + </Link> + ); + }); + }; + + return ( + <MetaItem + title={intl.formatMessage( + { + defaultMessage: + '{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}', + description: 'Thematics: thematics list meta label', + }, + { thematicsCount: list.length } + )} + values={getThematics()} + kind={kind} + /> + ); +}; + +export default Thematics; diff --git a/src/components/MetaItems/Topics/Topics.tsx b/src/components/MetaItems/Topics/Topics.tsx new file mode 100644 index 0000000..4f2dc1f --- /dev/null +++ b/src/components/MetaItems/Topics/Topics.tsx @@ -0,0 +1,36 @@ +import { MetaKind } from '@ts/types/app'; +import { TopicPreview } from '@ts/types/taxonomies'; +import Link from 'next/link'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const Topics = ({ list, kind }: { list: TopicPreview[]; kind: MetaKind }) => { + const intl = useIntl(); + + const getTopics = () => { + return list.map((topic) => { + return ( + <Link key={topic.databaseId} href={`/sujet/${topic.slug}`}> + <a>{topic.title}</a> + </Link> + ); + }); + }; + + return ( + <MetaItem + title={intl.formatMessage( + { + defaultMessage: + '{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}', + description: 'Topics: topics list meta label', + }, + { topicsCount: list.length } + )} + values={getTopics()} + kind={kind} + /> + ); +}; + +export default Topics; diff --git a/src/components/MetaItems/Website/Website.tsx b/src/components/MetaItems/Website/Website.tsx new file mode 100644 index 0000000..bcf3fc8 --- /dev/null +++ b/src/components/MetaItems/Website/Website.tsx @@ -0,0 +1,20 @@ +import { MetaKind } from '@ts/types/app'; +import { useIntl } from 'react-intl'; +import { MetaItem } from '..'; + +const Website = ({ url, kind }: { url: string; kind: MetaKind }) => { + const intl = useIntl(); + + return ( + <MetaItem + title={intl.formatMessage({ + defaultMessage: 'Website:', + description: 'Website: website meta label', + })} + value={<a href={url}>{url}</a>} + kind={kind} + /> + ); +}; + +export default Website; diff --git a/src/components/MetaItems/index.tsx b/src/components/MetaItems/index.tsx new file mode 100644 index 0000000..e90d5a6 --- /dev/null +++ b/src/components/MetaItems/index.tsx @@ -0,0 +1,21 @@ +import Author from './Author/Author'; +import CommentsCount from './CommentsCount/CommentsCount'; +import Dates from './Dates/Dates'; +import MetaItem from './MetaItem/MetaItem'; +import PostsCount from './PostsCount/PostsCount'; +import ReadingTime from './ReadingTime/ReadingTime'; +import Thematics from './Thematics/Thematics'; +import Topics from './Topics/Topics'; +import Website from './Website/Website'; + +export { + Author, + CommentsCount, + Dates, + MetaItem, + PostsCount, + ReadingTime, + Thematics, + Topics, + Website, +}; diff --git a/src/components/PostHeader/PostHeader.tsx b/src/components/PostHeader/PostHeader.tsx index f070583..c0a6b68 100644 --- a/src/components/PostHeader/PostHeader.tsx +++ b/src/components/PostHeader/PostHeader.tsx @@ -16,19 +16,6 @@ const PostHeader = ({ meta?: ArticleMeta; title: string; }) => { - const hasMeta = () => { - return ( - meta?.author || - meta?.commentCount || - meta?.dates || - meta?.readingTime || - meta?.results || - meta?.thematics || - meta?.website || - meta?.wordsCount - ); - }; - const getIntro = () => { if (React.isValidElement(intro)) { const Intro = () => intro; @@ -38,6 +25,7 @@ const PostHeader = ({ </div> ); } + return ( intro && ( <div @@ -59,7 +47,7 @@ const PostHeader = ({ )} {title} </h1> - {meta && hasMeta() && <PostMeta mode="single" meta={meta} />} + {meta && <PostMeta kind="article" meta={meta} />} {getIntro()} </div> </header> diff --git a/src/components/PostMeta/PostMeta.module.scss b/src/components/PostMeta/PostMeta.module.scss index 6f8e1c2..d438635 100644 --- a/src/components/PostMeta/PostMeta.module.scss +++ b/src/components/PostMeta/PostMeta.module.scss @@ -18,7 +18,7 @@ } } - &--single { + &--article { flex-flow: column wrap; margin: var(--spacing-sm) 0 0; @@ -27,24 +27,5 @@ font-size: var(--font-size-sm); } } - - .item { - display: flex; - flex-flow: row wrap; - } - - .term { - margin-right: var(--spacing-2xs); - color: var(--color-fg-light); - } - - .description { - &:not(:first-of-type) { - &::before { - content: "/"; - margin: 0 var(--spacing-2xs); - } - } - } } } diff --git a/src/components/PostMeta/PostMeta.tsx b/src/components/PostMeta/PostMeta.tsx index b951c44..e89e0e2 100644 --- a/src/components/PostMeta/PostMeta.tsx +++ b/src/components/PostMeta/PostMeta.tsx @@ -1,19 +1,24 @@ +import { + Author, + CommentsCount, + Dates, + PostsCount, + ReadingTime, + Thematics, + Topics, + Website, +} from '@components/MetaItems'; +import { MetaKind } from '@ts/types/app'; import { ArticleMeta } from '@ts/types/articles'; -import { settings } from '@utils/config'; -import { getFormattedDate } from '@utils/helpers/format'; -import Link from 'next/link'; import { useRouter } from 'next/router'; -import { useIntl } from 'react-intl'; import styles from './PostMeta.module.scss'; -type PostMetaMode = 'list' | 'single'; - const PostMeta = ({ meta, - mode = 'list', + kind = 'list', }: { meta: ArticleMeta; - mode?: PostMetaMode; + kind?: MetaKind; }) => { const { author, @@ -26,217 +31,34 @@ const PostMeta = ({ website, wordsCount, } = meta; - const intl = useIntl(); - const router = useRouter(); - const locale = router.locale ? router.locale : settings.locales.defaultLocale; - const isThematic = () => router.asPath.includes('/thematique/'); - const isArticle = () => router.asPath.includes('/article/'); - - const getTopics = () => { - return ( - topics && - topics.map((topic) => { - return ( - <dd key={topic.id} className={styles.description}> - <Link href={`/sujet/${topic.slug}`}> - <a>{topic.title}</a> - </Link> - </dd> - ); - }) - ); - }; - - const getThematics = () => { - return ( - thematics && - thematics.map((thematic) => { - return ( - <dd key={thematic.id} className={styles.description}> - <Link href={`/thematique/${thematic.slug}`}> - <a>{thematic.title}</a> - </Link> - </dd> - ); - }) - ); - }; - - const getCommentsCount = () => { - return intl.formatMessage( - { - defaultMessage: - '{commentCount, plural, =0 {No comments} one {# comment} other {# comments}}', - description: 'PostMeta: comment count value', - }, - { commentCount } - ); - }; - - const getReadingTime = () => { - if (!readingTime) return; - if (readingTime < 0) - return intl.formatMessage({ - defaultMessage: 'less than 1 minute', - description: 'PostMeta: Reading time value', - }); - return intl.formatMessage( - { - defaultMessage: - '{readingTime, plural, =0 {# minutes} one {# minute} other {# minutes}}', - description: 'PostMeta: reading time value', - }, - { readingTime } - ); - }; + const { asPath } = useRouter(); + const isThematic = () => asPath.includes('/thematique/'); - const getDates = () => { - if (!dates) return <></>; - - const publicationDate = getFormattedDate(dates.publication, locale); - const updateDate = getFormattedDate(dates.update, locale); - - return ( - <> - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Published on:', - description: 'PostMeta: publication date label', - })} - </dt> - <dd className={styles.description}> - <time dateTime={dates.publication}>{publicationDate}</time> - </dd> - </div> - {publicationDate !== updateDate && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Updated on:', - description: 'PostMeta: update date label', - })} - </dt> - <dd className={styles.description}> - <time dateTime={dates.update}>{updateDate}</time> - </dd> - </div> - )} - </> - ); - }; - - const wrapperClass = styles[`wrapper--${mode}`]; + const wrapperClass = styles[`wrapper--${kind}`]; return ( <dl className={wrapperClass}> - {author && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Written by:', - description: 'Article meta', - })} - </dt> - <dd className={styles.description}>{author.name}</dd> - </div> + {author && <Author name={author.name} kind={kind} />} + {dates && ( + <Dates + publication={dates.publication} + update={dates.update} + kind={kind} + /> )} - {getDates()} {readingTime !== undefined && wordsCount !== undefined && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Reading time:', - description: 'Article meta', - })} - </dt> - <dd - className={styles.description} - title={`Approximately ${wordsCount.toLocaleString(locale)} words`} - > - {getReadingTime()} - </dd> - </div> - )} - {results && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Total:', - description: 'Article meta', - })} - </dt> - <dd className={styles.description}> - {intl.formatMessage( - { - defaultMessage: - '{results, plural, =0 {No articles} one {# article} other {# articles}}', - description: 'PostMeta: total found articles', - }, - { results } - )} - </dd> - </div> + <ReadingTime time={readingTime} words={wordsCount} kind={kind} /> )} + {results && <PostsCount total={results} kind={kind} />} {!isThematic() && thematics && thematics.length > 0 && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage( - { - defaultMessage: - '{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}', - description: 'PostMeta: thematics list label', - }, - { thematicsCount: thematics.length } - )} - </dt> - {getThematics()} - </div> + <Thematics list={thematics} kind={kind} /> )} {isThematic() && topics && topics.length > 0 && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage( - { - defaultMessage: - '{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}', - description: 'PostMeta: topics list label', - }, - { topicsCount: topics.length } - )} - </dt> - {getTopics()} - </div> - )} - {website && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Website:', - description: 'PostMeta: website label', - })} - </dt> - <dd className={styles.description}> - <a href={website}>{website}</a> - </dd> - </div> + <Topics list={topics} kind={kind} /> )} + {website && <Website url={website} kind={kind} />} {commentCount !== undefined && ( - <div className={styles.item}> - <dt className={styles.term}> - {intl.formatMessage({ - defaultMessage: 'Comments:', - description: 'PostMeta: comment count label', - })} - </dt> - <dd className={styles.description}> - {isArticle() ? ( - <a href="#comments">{getCommentsCount()}</a> - ) : ( - getCommentsCount() - )} - </dd> - </div> + <CommentsCount total={commentCount} kind={kind} /> )} </dl> ); diff --git a/src/i18n/en.json b/src/i18n/en.json index 9164b83..4928516 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -3,10 +3,6 @@ "defaultMessage": "Others topics", "description": "TopicPage: topics list widget title" }, - "+COyEW": { - "defaultMessage": "{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}", - "description": "PostMeta: topics list label" - }, "+Dre5J": { "defaultMessage": "Open-source projects", "description": "CVPage: social media widget title" @@ -31,6 +27,10 @@ "defaultMessage": "Failed to load.", "description": "TopicsList: failed to load text" }, + "0pp/IQ": { + "defaultMessage": "{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}", + "description": "Topics: topics list meta label" + }, "0zBQpa": { "defaultMessage": "Message", "description": "ContactForm: message field label" @@ -47,6 +47,10 @@ "defaultMessage": "Published on:", "description": "RecentPosts: publication date label" }, + "1r4ujR": { + "defaultMessage": "{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}", + "description": "Thematics: thematics list meta label" + }, "2D9tB5": { "defaultMessage": "Topics", "description": "BlogPage: topics list widget title" @@ -67,10 +71,22 @@ "defaultMessage": "Page not found.", "description": "404Page: SEO - Meta description" }, + "4EMSLO": { + "defaultMessage": "{total, plural, =0 {No articles} one {# article} other {# articles}}", + "description": "PostCount: total found articles" + }, "4zAUSu": { "defaultMessage": "Legal notice - {websiteName}", "description": "LegalNoticePage: SEO - Page title" }, + "52Fev1": { + "defaultMessage": "Published on:", + "description": "Dates: publication date meta label" + }, + "6BRtAu": { + "defaultMessage": "Comments:", + "description": "CommentsCount: comment count meta label" + }, "6dXfvr": { "defaultMessage": "Table of Contents", "description": "ProjectPage: ToC sidebar aria-label" @@ -123,6 +139,10 @@ "defaultMessage": "Others formats", "description": "CVPage: cv preview widget title" }, + "C+r/LF": { + "defaultMessage": "Updated on:", + "description": "Dates: update date meta label" + }, "C/XGkH": { "defaultMessage": "Failed to load.", "description": "BlogPage: failed to load text" @@ -167,18 +187,6 @@ "defaultMessage": "All posts in {name}", "description": "TopicPage: posts list title" }, - "Fj8WFC": { - "defaultMessage": "{results, plural, =0 {No articles} one {# article} other {# articles}}", - "description": "PostMeta: total found articles" - }, - "FtokGF": { - "defaultMessage": "Updated on:", - "description": "PostMeta: update date label" - }, - "GUfnQ4": { - "defaultMessage": "Reading time:", - "description": "Article meta" - }, "GgIWnN": { "defaultMessage": "<a11y>Jump to </a11y>{title}", "description": "ToC: link" @@ -223,6 +231,10 @@ "defaultMessage": "Sidebar", "description": "ArticlePage: right sidebar aria-label" }, + "JsOoAW": { + "defaultMessage": "Website:", + "description": "Website: website meta label" + }, "KERk7L": { "defaultMessage": "Filter by:", "description": "BlogPage: sidebar title" @@ -247,10 +259,6 @@ "defaultMessage": "Projects", "description": "HomePage: link to projects" }, - "N7I4lC": { - "defaultMessage": "less than 1 minute", - "description": "PostMeta: Reading time value" - }, "N804XO": { "defaultMessage": "Topics", "description": "SearchPage: topics list widget title" @@ -287,10 +295,6 @@ "defaultMessage": "Email", "description": "CommentForm: Email field label" }, - "Ox/daH": { - "defaultMessage": "{commentCount, plural, =0 {No comments} one {# comment} other {# comments}}", - "description": "PostMeta: comment count value" - }, "P0I+Xm": { "defaultMessage": "Journal du hacker", "description": "Sharing: Journal du hacker" @@ -355,10 +359,6 @@ "defaultMessage": "Search", "description": "SearchPage: breadcrumb item" }, - "U++A+B": { - "defaultMessage": "{readingTime, plural, =0 {# minutes} one {# minute} other {# minutes}}", - "description": "PostMeta: reading time value" - }, "U+35YD": { "defaultMessage": "Search", "description": "SearchPage: page title" @@ -387,10 +387,6 @@ "defaultMessage": "Email", "description": "ContactForm: email field label" }, - "W2G95o": { - "defaultMessage": "Comments:", - "description": "PostMeta: comment count label" - }, "WGFOmA": { "defaultMessage": "Send", "description": "CommentForm: Send button" @@ -459,10 +455,6 @@ "defaultMessage": "{starsCount, plural, =0 {0 stars on Github} one {# star on Github} other {# stars on Github}}", "description": "ProjectSummary: technologies list label" }, - "agLf5v": { - "defaultMessage": "Website:", - "description": "PostMeta: website label" - }, "akSutM": { "defaultMessage": "Projects", "description": "MainNav: projects link" @@ -535,10 +527,6 @@ "defaultMessage": "Sidebar", "description": "TopicPage: right sidebar aria-label" }, - "fGnfqp": { - "defaultMessage": "Published on:", - "description": "PostMeta: publication date label" - }, "fOe8rH": { "defaultMessage": "Failed to load.", "description": "SearchPage: failed to load text" @@ -587,9 +575,9 @@ "defaultMessage": "Linux", "description": "HomePage: link to Linux thematic" }, - "jGqV2+": { + "jCyqZS": { "defaultMessage": "Written by:", - "description": "Article meta" + "description": "Author: article author meta label" }, "jN+dY5": { "defaultMessage": "Website", @@ -599,9 +587,13 @@ "defaultMessage": "Resume", "description": "MainNav: resume link" }, - "l0+ROl": { - "defaultMessage": "{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}", - "description": "PostMeta: thematics list label" + "k7/SkN": { + "defaultMessage": "Approximately {number} words", + "description": "ReadingTime: number of words" + }, + "lKGNKx": { + "defaultMessage": "{total, plural, =0 {No comments} one {# comment} other {# comments}}", + "description": "CommentsCount: comment count value" }, "lKZm9t": { "defaultMessage": "Email", @@ -619,6 +611,10 @@ "defaultMessage": "{title} preview", "description": "ProjectSummary: cover alt text" }, + "n0Gbod": { + "defaultMessage": "Reading time:", + "description": "ReadingTime: reading time meta label" + }, "nFMdWI": { "defaultMessage": "Dark Theme 🌙", "description": "Prism: toggle dark theme button text" @@ -643,6 +639,10 @@ "defaultMessage": "{count, plural, =0 {Technologies:} one {Technology:} other {Technologies:}}", "description": "ProjectPreview: technologies list label" }, + "p1zZ/Z": { + "defaultMessage": "Total:", + "description": "PostCount: total found articles meta label" + }, "pEtJik": { "defaultMessage": "Load more?", "description": "SearchPage: load more text" @@ -723,10 +723,6 @@ "defaultMessage": "Popularity:", "description": "ProjectSummary: popularity label" }, - "vhIggb": { - "defaultMessage": "Total:", - "description": "Article meta" - }, "vkF/RP": { "defaultMessage": "Web development", "description": "HomePage: link to web development thematic" @@ -747,10 +743,18 @@ "defaultMessage": "Free", "description": "HomePage: link to free thematic" }, + "wdqOpf": { + "defaultMessage": "{time, plural, =0 {# minutes} one {# minute} other {# minutes}}", + "description": "ReadingTime: reading time value" + }, "xC3Khf": { "defaultMessage": "Download <link>CV in PDF</link>", "description": "CVPreview: download as PDF link" }, + "ySsWZl": { + "defaultMessage": "less than 1 minute", + "description": "ReadingTime: Reading time value" + }, "yWjXRx": { "defaultMessage": "Legal notice", "description": "FooterNav: legal notice link" diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 478a9cf..645ffa9 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -3,10 +3,6 @@ "defaultMessage": "Autres sujets", "description": "TopicPage: topics list widget title" }, - "+COyEW": { - "defaultMessage": "{topicsCount, plural, =0 {Sujets :} one {Sujet :} other {Sujets :}}", - "description": "PostMeta: topics list label" - }, "+Dre5J": { "defaultMessage": "Projets open-source", "description": "CVPage: social media widget title" @@ -31,6 +27,10 @@ "defaultMessage": "Échec du chargement.", "description": "TopicsList: failed to load text" }, + "0pp/IQ": { + "defaultMessage": "{topicsCount, plural, =0 {Sujet :} one {Sujet :} other {Sujets :}}", + "description": "Topics: topics list meta label" + }, "0zBQpa": { "defaultMessage": "Message", "description": "ContactForm: message field label" @@ -47,6 +47,10 @@ "defaultMessage": "Publié le :", "description": "RecentPosts: publication date label" }, + "1r4ujR": { + "defaultMessage": "{thematicsCount, plural, =0 {Thématique :} one {Thématique :} other {Thématiques :}}", + "description": "Thematics: thematics list meta label" + }, "2D9tB5": { "defaultMessage": "Sujets", "description": "BlogPage: topics list widget title" @@ -67,10 +71,22 @@ "defaultMessage": "Page non trouvée.", "description": "404Page: SEO - Meta description" }, + "4EMSLO": { + "defaultMessage": "{total, plural, =0 {Aucun article} one {# article} other {# articles}}", + "description": "PostCount: total found articles" + }, "4zAUSu": { "defaultMessage": "Mentions légales - {websiteName}", "description": "LegalNoticePage: SEO - Page title" }, + "52Fev1": { + "defaultMessage": "Publié le :", + "description": "Dates: publication date meta label" + }, + "6BRtAu": { + "defaultMessage": "Commentaires :", + "description": "CommentsCount: comment count meta label" + }, "6dXfvr": { "defaultMessage": "Table des matières", "description": "ProjectPage: ToC sidebar aria-label" @@ -123,6 +139,10 @@ "defaultMessage": "Autres formats", "description": "CVPage: cv preview widget title" }, + "C+r/LF": { + "defaultMessage": "Mis à jour le :", + "description": "Dates: update date meta label" + }, "C/XGkH": { "defaultMessage": "Échec du chargement.", "description": "BlogPage: failed to load text" @@ -167,18 +187,6 @@ "defaultMessage": "Tous les articles dans {name}", "description": "TopicPage: posts list title" }, - "Fj8WFC": { - "defaultMessage": "{results, plural, =0 {Aucun article} one {# article} other {# articles}}", - "description": "PostMeta: total found articles" - }, - "FtokGF": { - "defaultMessage": "Mis à jour le :", - "description": "PostMeta: update date label" - }, - "GUfnQ4": { - "defaultMessage": "Temps de lecture :", - "description": "Article meta" - }, "GgIWnN": { "defaultMessage": "<a11y>Atteindre </a11y>{title}", "description": "ToC: link" @@ -223,6 +231,10 @@ "defaultMessage": "Barre latérale", "description": "ArticlePage: right sidebar aria-label" }, + "JsOoAW": { + "defaultMessage": "Site web :", + "description": "Website: website meta label" + }, "KERk7L": { "defaultMessage": "Filtrer par :", "description": "BlogPage: sidebar title" @@ -247,10 +259,6 @@ "defaultMessage": "Projets", "description": "HomePage: link to projects" }, - "N7I4lC": { - "defaultMessage": "moins d'une minute", - "description": "PostMeta: Reading time value" - }, "N804XO": { "defaultMessage": "Sujets", "description": "SearchPage: topics list widget title" @@ -287,10 +295,6 @@ "defaultMessage": "Email", "description": "CommentForm: Email field label" }, - "Ox/daH": { - "defaultMessage": "{commentCount, plural, =0 {Aucun commentaire} one {# commentaire} other {# commentaires}}", - "description": "PostMeta: comment count value" - }, "P0I+Xm": { "defaultMessage": "Journal du hacker", "description": "Sharing: Journal du hacker" @@ -355,10 +359,6 @@ "defaultMessage": "Recherche", "description": "SearchPage: breadcrumb item" }, - "U++A+B": { - "defaultMessage": "{readingTime, plural, =0 {# minute} one {# minute} other {# minutes}}", - "description": "PostMeta: reading time value" - }, "U+35YD": { "defaultMessage": "Recherche", "description": "SearchPage: page title" @@ -387,10 +387,6 @@ "defaultMessage": "Email", "description": "ContactForm: email field label" }, - "W2G95o": { - "defaultMessage": "Commentaires :", - "description": "PostMeta: comment count label" - }, "WGFOmA": { "defaultMessage": "Envoyer", "description": "CommentForm: Send button" @@ -459,10 +455,6 @@ "defaultMessage": "{starsCount, plural, =0 {0 étoile sur Github} one {# étoile sur Github} other {# étoiles sur Github}}", "description": "ProjectSummary: technologies list label" }, - "agLf5v": { - "defaultMessage": "Site web :", - "description": "PostMeta: website label" - }, "akSutM": { "defaultMessage": "Projets", "description": "MainNav: projects link" @@ -535,10 +527,6 @@ "defaultMessage": "Barre latérale", "description": "TopicPage: right sidebar aria-label" }, - "fGnfqp": { - "defaultMessage": "Publié le :", - "description": "PostMeta: publication date label" - }, "fOe8rH": { "defaultMessage": "Échec du chargement.", "description": "SearchPage: failed to load text" @@ -587,9 +575,9 @@ "defaultMessage": "Linux", "description": "HomePage: link to Linux thematic" }, - "jGqV2+": { + "jCyqZS": { "defaultMessage": "Écrit par :", - "description": "Article meta" + "description": "Author: article author meta label" }, "jN+dY5": { "defaultMessage": "Site web", @@ -599,9 +587,13 @@ "defaultMessage": "CV", "description": "MainNav: resume link" }, - "l0+ROl": { - "defaultMessage": "{thematicsCount, plural, =0 {Thématiques :} one {Thématique :} other {Thématiques :}}", - "description": "PostMeta: thematics list label" + "k7/SkN": { + "defaultMessage": "Environ {number} mots", + "description": "ReadingTime: number of words" + }, + "lKGNKx": { + "defaultMessage": "{total, plural, =0 {Aucun commentaire} one {# commentaire} other {# commentaires}}", + "description": "CommentsCount: comment count value" }, "lKZm9t": { "defaultMessage": "Email", @@ -619,6 +611,10 @@ "defaultMessage": "Aperçu de {title}", "description": "ProjectSummary: cover alt text" }, + "n0Gbod": { + "defaultMessage": "Temps de lecture :", + "description": "ReadingTime: reading time meta label" + }, "nFMdWI": { "defaultMessage": "Thème sombre 🌙", "description": "Prism: toggle dark theme button text" @@ -643,6 +639,10 @@ "defaultMessage": "{count, plural, =0 {Technologies :} one {Technologie :} other {Technologies :}}", "description": "ProjectPreview: technologies list label" }, + "p1zZ/Z": { + "defaultMessage": "Total :", + "description": "PostCount: total found articles meta label" + }, "pEtJik": { "defaultMessage": "En charger plus ?", "description": "SearchPage: load more text" @@ -723,10 +723,6 @@ "defaultMessage": "Popularité :", "description": "ProjectSummary: popularity label" }, - "vhIggb": { - "defaultMessage": "Total :", - "description": "Article meta" - }, "vkF/RP": { "defaultMessage": "Développement web", "description": "HomePage: link to web development thematic" @@ -747,10 +743,18 @@ "defaultMessage": "Libre", "description": "HomePage: link to free thematic" }, + "wdqOpf": { + "defaultMessage": "{time, plural, =0 {# minute} one {# minute} other {# minutes}}", + "description": "ReadingTime: reading time value" + }, "xC3Khf": { "defaultMessage": "Télécharger le <link>CV au format PDF</link>", "description": "CVPreview: download as PDF link" }, + "ySsWZl": { + "defaultMessage": "moins d'une minute", + "description": "ReadingTime: Reading time value" + }, "yWjXRx": { "defaultMessage": "Mentions légales", "description": "FooterNav: legal notice link" diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index 6d0ad5a..656f7c9 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -22,7 +22,7 @@ import { usePrismTheme } from '@utils/providers/prism'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import Prism from 'prismjs'; +import { highlightAll } from 'prismjs'; import { ParsedUrlQuery } from 'querystring'; import { useEffect } from 'react'; import { useIntl } from 'react-intl'; @@ -39,7 +39,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ useEffect(() => { addPrismClasses(); - Prism.highlightAll(); + highlightAll(); }); const { setCodeBlocks } = usePrismTheme(); diff --git a/src/ts/types/app.ts b/src/ts/types/app.ts index 0960cbd..444733c 100644 --- a/src/ts/types/app.ts +++ b/src/ts/types/app.ts @@ -99,6 +99,8 @@ export type Meta = { updatedOn: string; }; +export type MetaKind = 'article' | 'list'; + export type NoticeType = 'error' | 'info' | 'success' | 'warning'; export type PageInfo = { |
