From 6d26f5cf3e971c79681717110f2e1ce69ebc193a Mon Sep 17 00:00:00 2001 From: sebastien Date: Wed, 14 Feb 2024 15:59:06 +0100 Subject: [PATCH] Add blog plugin useBlogMetadata() client hook + refactor to use it --- .../package.json | 16 +++++++++++-- .../src/client/index.ts | 20 ++++++++++++++++ .../src/index.ts | 5 +++- .../src/plugin-content-blog.d.ts | 22 +++--------------- .../tsconfig.client.json | 16 +++++++++++++ .../tsconfig.json | 3 ++- .../BlogPostPage/StructuredData/index.tsx | 5 ++-- .../src/theme/BlogPostPage/index.tsx | 6 +---- .../src/utils/structuredDataUtils.ts | 23 ++++++++----------- packages/docusaurus-types/src/routing.d.ts | 2 +- 10 files changed, 73 insertions(+), 45 deletions(-) create mode 100644 packages/docusaurus-plugin-content-blog/src/client/index.ts create mode 100644 packages/docusaurus-plugin-content-blog/tsconfig.client.json diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 81b398107e59..e01d774d0b91 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -4,9 +4,21 @@ "description": "Blog plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-blog.d.ts", + "exports": { + "./lib/*": "./lib/*", + "./src/*": "./src/*", + "./client": { + "type": "./lib/client/index.d.ts", + "default": "./lib/client/index.js" + }, + ".": { + "types": "./src/plugin-content-blog.d.ts", + "default": "./lib/index.js" + } + }, "scripts": { - "build": "tsc", - "watch": "tsc --watch", + "build": "tsc --build", + "watch": "tsc --build --watch", "test:generate-build-snap": "yarn docusaurus build src/__tests__/__fixtures__/website --out-dir build-snap && yarn rimraf src/__tests__/__fixtures__/website/.docusaurus && yarn rimraf src/__tests__/__fixtures__/website/build-snap/assets && git add src/__tests__/__fixtures__/website/build-snap" }, "repository": { diff --git a/packages/docusaurus-plugin-content-blog/src/client/index.ts b/packages/docusaurus-plugin-content-blog/src/client/index.ts new file mode 100644 index 000000000000..333ddc5a4d7b --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/client/index.ts @@ -0,0 +1,20 @@ +/** + * 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 useRouteContext from '@docusaurus/useRouteContext'; +import type {BlogMetadata} from '@docusaurus/plugin-content-blog'; + +export function useBlogMetadata(): BlogMetadata { + const routeContext = useRouteContext(); + const blogMetadata = routeContext?.data?.blogMetadata; + if (!blogMetadata) { + throw new Error( + "useBlogMetadata() can't be called on the current route because the blog metadata could not be found in route context", + ); + } + return blogMetadata as BlogMetadata; +} diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index bf7f72d71b6e..75f6edf0a3d0 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -42,6 +42,7 @@ import type { BlogTags, BlogContent, BlogPaginated, + BlogMetadata, } from '@docusaurus/plugin-content-blog'; export default async function pluginContentBlog( @@ -262,7 +263,7 @@ export default async function pluginContentBlog( { blogBasePath: normalizeUrl([baseUrl, routeBasePath]), blogTitle, - }, + } satisfies BlogMetadata, null, 2, ), @@ -286,6 +287,8 @@ export default async function pluginContentBlog( modules: { sidebar: aliasedSource(sidebarProp), content: metadata.source, + }, + context: { blogMetadata: aliasedSource(blogMetadataPath), }, }); diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts index a245fbcbd901..2a37d67dfe54 100644 --- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts +++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +/// + declare module '@docusaurus/plugin-content-blog' { import type {LoadedMDXContent} from '@docusaurus/mdx-loader'; import type {MDXOptions} from '@docusaurus/mdx-loader'; @@ -563,25 +565,7 @@ declare module '@theme/BlogPostPage/Metadata' { } declare module '@theme/BlogPostPage/StructuredData' { - import type { - BlogPostFrontMatter, - PropBlogPostContent, - BlogMetadata, - } from '@docusaurus/plugin-content-blog'; - - export type FrontMatter = BlogPostFrontMatter; - - export type Assets = PropBlogPostContent['assets']; - - export type Metadata = PropBlogPostContent['metadata']; - - export interface Props { - readonly assets: Assets; - readonly metadata: Metadata; - readonly blogMetadata: BlogMetadata; - } - - export default function BlogPostStructuredData(props: Props): JSX.Element; + export default function BlogPostStructuredData(): JSX.Element; } declare module '@theme/BlogListPage' { diff --git a/packages/docusaurus-plugin-content-blog/tsconfig.client.json b/packages/docusaurus-plugin-content-blog/tsconfig.client.json new file mode 100644 index 000000000000..5d06aa818c96 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/tsconfig.client.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "noEmit": false, + "composite": true, + "incremental": true, + "tsBuildInfoFile": "./lib/.tsbuildinfo-client", + "moduleResolution": "bundler", + "module": "esnext", + "target": "esnext", + "rootDir": "src", + "outDir": "lib" + }, + "include": ["src/client", "src/*.d.ts"], + "exclude": ["**/__tests__/**"] +} diff --git a/packages/docusaurus-plugin-content-blog/tsconfig.json b/packages/docusaurus-plugin-content-blog/tsconfig.json index e16d5c2c5d33..3936df64b7e4 100644 --- a/packages/docusaurus-plugin-content-blog/tsconfig.json +++ b/packages/docusaurus-plugin-content-blog/tsconfig.json @@ -1,5 +1,6 @@ { "extends": "../../tsconfig.json", + "references": [{"path": "./tsconfig.client.json"}], "compilerOptions": { "noEmit": false, "incremental": true, @@ -8,5 +9,5 @@ "outDir": "lib" }, "include": ["src"], - "exclude": ["**/__tests__/**"] + "exclude": ["src/client", "**/__tests__/**"] } diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx index 4aa9c33ab2fb..0041a7e88f3a 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx @@ -10,9 +10,8 @@ import { useBlogPostStructuredData, StructuredData, } from '@docusaurus/theme-common'; -import type {Props} from '@theme/BlogPostPage/StructuredData'; -export default function BlogPostStructuredData(props: Props): JSX.Element { - const structuredData = useBlogPostStructuredData(props); +export default function BlogPostStructuredData(): JSX.Element { + const structuredData = useBlogPostStructuredData(); return ; } diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx index 0d97a6386752..6d7ed51a7fd5 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx @@ -66,11 +66,7 @@ export default function BlogPostPage(props: Props): JSX.Element { ThemeClassNames.page.blogPostPage, )}> - + diff --git a/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts b/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts index 99743766c640..eb8cea1ad1b3 100644 --- a/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts @@ -7,8 +7,9 @@ import {useBaseUrlUtils, type BaseUrlUtils} from '@docusaurus/useBaseUrl'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {useBlogMetadata} from '@docusaurus/plugin-content-blog/client'; import type {Props as BlogListPageStructuredDataProps} from '@theme/BlogListPage/StructuredData'; -import type {Props as BlogPostPageStructuredDataProps} from '@theme/BlogPostPage/StructuredData'; +import {useBlogPost} from '../contexts/blogPost'; import type { Blog, BlogPosting, @@ -88,7 +89,7 @@ export function useBlogListPageStructuredData( const url = `${siteConfig.url}${permalink}`; // details on structured data support: https://schema.org/Blog - const blogStructuredData: WithContext = { + return { '@context': 'https://schema.org', '@type': 'Blog', '@id': url, @@ -99,16 +100,14 @@ export function useBlogListPageStructuredData( getBlogPost(blogItem.content, siteConfig, withBaseUrl), ), }; - - return blogStructuredData; } -export function useBlogPostStructuredData( - props: BlogPostPageStructuredDataProps, -): WithContext { +export function useBlogPostStructuredData(): WithContext { + const blogMetadata = useBlogMetadata(); + const {assets, metadata} = useBlogPost(); const {siteConfig} = useDocusaurusContext(); const {withBaseUrl} = useBaseUrlUtils(); - const {assets, metadata} = props; + const {date, title, description, frontMatter} = metadata; const image = assets.image ?? frontMatter.image; @@ -119,7 +118,7 @@ export function useBlogPostStructuredData( // details on structured data support: https://schema.org/BlogPosting // BlogPosting is one of the structured data types that Google explicitly // supports: https://developers.google.com/search/docs/appearance/structured-data/article#structured-data-type-definitions - const blogPostStructuredData: WithContext = { + return { '@context': 'https://schema.org', '@type': 'BlogPosting', '@id': url, @@ -134,12 +133,10 @@ export function useBlogPostStructuredData( ...(keywords ? {keywords} : {}), isPartOf: { '@type': 'Blog', - '@id': `${siteConfig.url}${props.blogMetadata.blogBasePath}`, - name: props.blogMetadata.blogTitle, + '@id': `${siteConfig.url}${blogMetadata.blogBasePath}`, + name: blogMetadata.blogTitle, }, }; - - return blogPostStructuredData; } /** @returns A {@link https://schema.org/Person} constructed from the {@link Author} */ diff --git a/packages/docusaurus-types/src/routing.d.ts b/packages/docusaurus-types/src/routing.d.ts index 7d1129c2a0a6..5c5ad90f1b4f 100644 --- a/packages/docusaurus-types/src/routing.d.ts +++ b/packages/docusaurus-types/src/routing.d.ts @@ -70,7 +70,7 @@ export type RouteContext = { /** * Plugin-specific context data. */ - data?: object | undefined; + data?: {[key: string]: unknown}; }; /**