blog/src/theme/BlogPostItem/index.tsx (95 lines of code) (raw):

/* eslint-disable import/no-extraneous-dependencies */ /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import React from 'react'; import clsx from 'clsx'; import { MDXProvider } from '@mdx-js/react'; import MDXComponents from '@theme/MDXComponents'; import { translate } from '@docusaurus/Translate'; import Link from '@docusaurus/Link'; import { useBaseUrlUtils } from '@docusaurus/useBaseUrl'; import { usePluralForm } from '@docusaurus/theme-common'; import EditThisPage from '@theme/EditThisPage'; import type { Props } from '@theme/BlogPostItem'; import TagsListInline from '@theme/TagsListInline'; import BlogPostAuthors from '@theme/BlogPostAuthors'; import styles from './styles.module.css'; // Very simple pluralization: probably good enough for now function useReadingTimePlural() { const { selectMessage } = usePluralForm(); return (readingTimeFloat: number) => { const readingTime = Math.ceil(readingTimeFloat); return selectMessage( readingTime, translate( { id: 'theme.blog.post.readingTime.plurals', description: 'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)', message: 'One min read|{readingTime} min read', }, { readingTime }, ), ); }; } const defaultImg = '/img/default-blog-header.jpg'; const BlogPostItem = (props: Props): JSX.Element => { const readingTimePlural = useReadingTimePlural(); const { withBaseUrl } = useBaseUrlUtils(); const { children, frontMatter, assets, metadata, truncated, isBlogPostPage = false, } = props; const { date, formattedDate, permalink, tags, readingTime, title, editUrl, authors, } = metadata; const image = assets.image ?? frontMatter.image ?? withBaseUrl(defaultImg, { absolute: true }); const renderPostHeader = () => { const TitleHeading = isBlogPostPage ? 'h1' : 'h2'; return ( <header> <TitleHeading className={styles.blogPostTitle} itemProp="headline"> {isBlogPostPage ? ( title ) : ( <Link itemProp="url" to={permalink}> {title} </Link> )} </TitleHeading> <div className={clsx(styles.blogPostData, 'margin-vert--md')}> <time dateTime={date} itemProp="datePublished"> {formattedDate} </time> {typeof readingTime !== 'undefined' && ( <> {' · '} {readingTimePlural(readingTime)} </> )} </div> <BlogPostAuthors authors={authors} assets={assets} /> </header> ); }; return ( <article className={!isBlogPostPage ? 'margin-bottom--xl' : undefined} itemProp="blogPost" itemScope itemType="http://schema.org/BlogPosting" > {renderPostHeader()} {image && <meta itemProp="image" content={withBaseUrl(image, { absolute: true })} />} <div className="markdown" itemProp="articleBody"> <MDXProvider components={MDXComponents}>{children}</MDXProvider> </div> {(tags.length > 0 || truncated) && ( <footer className={clsx('row docusaurus-mt-lg', { [styles.blogPostDetailsFull]: isBlogPostPage, })} > {tags.length > 0 && ( <div className={clsx('col', { 'col--9': !isBlogPostPage })}> <TagsListInline tags={tags} /> </div> )} {isBlogPostPage && editUrl && ( <div className="col margin-top--sm"> <EditThisPage editUrl={editUrl} /> </div> )} </footer> )} </article> ); }; export default BlogPostItem;