mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-14 17:47:40 +02:00
* feat: add metatags support for seo / blogposts
* feat: different implementation
* feat: use isBlogPostPage
* feat: implement in BlogPostPage-remove Seo changes
* Revert "feat: implement in BlogPostPage-remove Seo changes"
This reverts commit 1cba459b
* Move Seo to BlogPostPage + some fixes
* fix social preview asset
* Fix blog social image + improve a bit Seo setup
* fix bootstrap theme
Co-authored-by: John <john.reilly@investec.co.uk>
Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
69ec013248
commit
08597045ed
9 changed files with 90 additions and 72 deletions
|
@ -21,7 +21,7 @@ declare module '@theme/BlogSidebar' {
|
|||
}
|
||||
|
||||
declare module '@theme/BlogPostPage' {
|
||||
import type {TOCItem} from '@docusaurus/types';
|
||||
import type {FrontMatterTag} from '@docusaurus/utils';
|
||||
import type {BlogSidebar} from '@theme/BlogSidebar';
|
||||
|
||||
export type FrontMatter = {
|
||||
|
@ -29,7 +29,7 @@ declare module '@theme/BlogPostPage' {
|
|||
readonly title: string;
|
||||
readonly author?: string;
|
||||
readonly image?: string;
|
||||
readonly tags?: readonly string[];
|
||||
readonly tags?: readonly FrontMatterTag[];
|
||||
readonly keywords?: readonly string[];
|
||||
readonly author_url?: string;
|
||||
readonly authorURL?: string;
|
||||
|
|
|
@ -171,6 +171,7 @@ declare module '@theme/Seo' {
|
|||
readonly description?: string;
|
||||
readonly keywords?: readonly string[] | string;
|
||||
readonly image?: string;
|
||||
readonly children?: ReactNode;
|
||||
};
|
||||
|
||||
const Seo: (props: Props) => JSX.Element;
|
||||
|
|
|
@ -34,7 +34,7 @@ function Layout(props: Props): JSX.Element {
|
|||
const metaImage = image || defaultImage;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
metaImageUrl = metaImage as string;
|
||||
}
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ function Layout(props: Props): JSX.Element {
|
|||
const metaImage = image || defaultImage;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
metaImageUrl = metaImage as string;
|
||||
}
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import Link from '@docusaurus/Link';
|
|||
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
import {usePluralForm} from '@docusaurus/theme-common';
|
||||
import MDXComponents from '@theme/MDXComponents';
|
||||
import Seo from '@theme/Seo';
|
||||
import EditThisPage from '@theme/EditThisPage';
|
||||
import type {Props} from '@theme/BlogPostItem';
|
||||
|
||||
|
@ -60,7 +59,7 @@ function BlogPostItem(props: Props): JSX.Element {
|
|||
title,
|
||||
editUrl,
|
||||
} = metadata;
|
||||
const {author, keywords} = frontMatter;
|
||||
const {author} = frontMatter;
|
||||
|
||||
const image = frontMatterAssets.image ?? frontMatter.image;
|
||||
|
||||
|
@ -129,63 +128,56 @@ function BlogPostItem(props: Props): JSX.Element {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Seo {...{keywords, image}} />
|
||||
<article
|
||||
className={!isBlogPostPage ? 'margin-bottom--xl' : undefined}
|
||||
itemProp="blogPost"
|
||||
itemScope
|
||||
itemType="http://schema.org/BlogPosting">
|
||||
{renderPostHeader()}
|
||||
|
||||
<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})} />
|
||||
)}
|
||||
|
||||
{image && (
|
||||
<meta
|
||||
itemProp="image"
|
||||
content={withBaseUrl(image, {absolute: true})}
|
||||
/>
|
||||
)}
|
||||
<div className="markdown" itemProp="articleBody">
|
||||
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
|
||||
</div>
|
||||
|
||||
<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="col">
|
||||
<TagsListInline tags={tags} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(tags.length > 0 || truncated) && (
|
||||
<footer
|
||||
className={clsx('row docusaurus-mt-lg', {
|
||||
[styles.blogPostDetailsFull]: isBlogPostPage,
|
||||
})}>
|
||||
{tags.length > 0 && (
|
||||
<div className="col">
|
||||
<TagsListInline tags={tags} />
|
||||
</div>
|
||||
)}
|
||||
{isBlogPostPage && editUrl && (
|
||||
<div className="col margin-top--sm">
|
||||
<EditThisPage editUrl={editUrl} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isBlogPostPage && editUrl && (
|
||||
<div className="col margin-top--sm">
|
||||
<EditThisPage editUrl={editUrl} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isBlogPostPage && truncated && (
|
||||
<div className="col text--right">
|
||||
<Link
|
||||
to={metadata.permalink}
|
||||
aria-label={`Read more about ${title}`}>
|
||||
<b>
|
||||
<Translate
|
||||
id="theme.blog.post.readMore"
|
||||
description="The label used in blog post item excerpts to link to full blog posts">
|
||||
Read More
|
||||
</Translate>
|
||||
</b>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</footer>
|
||||
)}
|
||||
</article>
|
||||
</>
|
||||
{!isBlogPostPage && truncated && (
|
||||
<div className="col text--right">
|
||||
<Link
|
||||
to={metadata.permalink}
|
||||
aria-label={`Read more about ${title}`}>
|
||||
<b>
|
||||
<Translate
|
||||
id="theme.blog.post.readMore"
|
||||
description="The label used in blog post item excerpts to link to full blog posts">
|
||||
Read More
|
||||
</Translate>
|
||||
</b>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</footer>
|
||||
)}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Seo from '@theme/Seo';
|
||||
import BlogLayout from '@theme/BlogLayout';
|
||||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
|
@ -15,13 +16,14 @@ import {ThemeClassNames} from '@docusaurus/theme-common';
|
|||
function BlogPostPage(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents, sidebar} = props;
|
||||
const {frontMatter, frontMatterAssets, metadata} = BlogPostContents;
|
||||
const {title, description, nextItem, prevItem} = metadata;
|
||||
const {hide_table_of_contents: hideTableOfContents} = frontMatter;
|
||||
const {title, description, nextItem, prevItem, date, tags} = metadata;
|
||||
const {hide_table_of_contents: hideTableOfContents, keywords} = frontMatter;
|
||||
|
||||
const image = frontMatterAssets.image ?? frontMatter.image;
|
||||
const authorURL = frontMatter.author_url || frontMatter.authorURL;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
title={title}
|
||||
description={description}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogPostPage}
|
||||
sidebar={sidebar}
|
||||
|
@ -30,6 +32,24 @@ function BlogPostPage(props: Props): JSX.Element {
|
|||
? BlogPostContents.toc
|
||||
: undefined
|
||||
}>
|
||||
<Seo
|
||||
// TODO refactor needed: it's a bit annoying but Seo MUST be inside BlogLayout
|
||||
// otherwise default image (set by BlogLayout) would shadow the custom blog post image
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
{authorURL && <meta property="article:author" content={authorURL} />}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</Seo>
|
||||
|
||||
<BlogPostItem
|
||||
frontMatter={frontMatter}
|
||||
frontMatterAssets={frontMatterAssets}
|
||||
|
@ -37,6 +57,7 @@ function BlogPostPage(props: Props): JSX.Element {
|
|||
isBlogPostPage>
|
||||
<BlogPostContents />
|
||||
</BlogPostItem>
|
||||
|
||||
{(nextItem || prevItem) && (
|
||||
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||
)}
|
||||
|
|
|
@ -104,13 +104,14 @@ export default function LayoutHead(props: Props): JSX.Element {
|
|||
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
|
||||
<title>{pageTitle}</title>
|
||||
<meta property="og:title" content={pageTitle} />
|
||||
{image ||
|
||||
(defaultImage && (
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
))}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</Head>
|
||||
|
||||
<Seo {...{description, keywords, image}} />
|
||||
{/* image can override the default image */}
|
||||
{defaultImage && <Seo image={defaultImage} />}
|
||||
{image && <Seo image={image} />}
|
||||
|
||||
<Seo description={description} keywords={keywords} />
|
||||
|
||||
<CanonicalUrlHeaders />
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import {useThemeConfig, useTitleFormatter} from '@docusaurus/theme-common';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import {useTitleFormatter} from '@docusaurus/theme-common';
|
||||
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
|
||||
import type {Props} from '@theme/Seo';
|
||||
|
||||
|
@ -17,10 +17,11 @@ export default function Seo({
|
|||
description,
|
||||
keywords,
|
||||
image,
|
||||
children,
|
||||
}: Props): JSX.Element {
|
||||
const {image: defaultImage} = useThemeConfig();
|
||||
const pageTitle = useTitleFormatter(title);
|
||||
const pageImage = useBaseUrl(image || defaultImage, {absolute: true});
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const pageImage = image ? withBaseUrl(image, {absolute: true}) : undefined;
|
||||
|
||||
return (
|
||||
<Head>
|
||||
|
@ -41,6 +42,8 @@ export default function Seo({
|
|||
|
||||
{pageImage && <meta property="og:image" content={pageImage} />}
|
||||
{pageImage && <meta name="twitter:image" content={pageImage} />}
|
||||
|
||||
{children}
|
||||
</Head>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ export type ThemeConfig = {
|
|||
prism: PrismConfig;
|
||||
footer?: Footer;
|
||||
hideableSidebar: boolean;
|
||||
image: string;
|
||||
image?: string;
|
||||
metadatas: Array<Record<string, string>>;
|
||||
sidebarCollapsible: boolean;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue