diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index d9161577f8..e6f886cbca 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -20,7 +20,8 @@ "fs-extra": "^8.1.0", "globby": "^10.0.1", "loader-utils": "^1.2.3", - "lodash.kebabcase": "^4.1.1" + "lodash.kebabcase": "^4.1.1", + "reading-time": "^1.2.0" }, "peerDependencies": { "@docusaurus/core": "^2.0.0", diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 917433244d..b96bdeb67a 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -51,6 +51,7 @@ describe('loadBlog', () => { ...{prevItem: undefined}, }).toEqual({ permalink: '/blog/2019/01/01/date-matter', + readingTime: 0.02, source: path.join('@site', pluginPath, 'date-matter.md'), title: 'date-matter', description: `date inside front matter`, @@ -68,6 +69,7 @@ describe('loadBlog', () => { .metadata, ).toEqual({ permalink: '/blog/2018/12/14/Happy-First-Birthday-Slash', + readingTime: 0.01, source: path.join( '@site', pluginPath, @@ -89,6 +91,7 @@ describe('loadBlog', () => { ...{prevItem: undefined}, }).toEqual({ permalink: noDatePermalink, + readingTime: 0.01, source: noDateSource, title: 'no date', description: `no date`, diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 22e1469178..863a3d2efc 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -8,6 +8,7 @@ import fs from 'fs-extra'; import globby from 'globby'; import path from 'path'; +import readingTime from 'reading-time'; import {Feed} from 'feed'; import {PluginOptions, BlogPost, DateLink} from './types'; import {parse, normalizeUrl, aliasedSitePath} from '@docusaurus/utils'; @@ -85,7 +86,7 @@ export async function generateBlogPosts( {siteConfig, siteDir}: LoadContext, options: PluginOptions, ) { - const {include, routeBasePath, truncateMarker} = options; + const {include, routeBasePath, truncateMarker, showReadingTime} = options; if (!fs.existsSync(blogDir)) { return []; @@ -144,6 +145,9 @@ export async function generateBlogPosts( date, tags: frontMatter.tags, title: frontMatter.title, + readingTime: showReadingTime + ? readingTime(content).minutes + : undefined, truncated: truncateMarker?.test(content) || false, }, }); diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 89c423ac88..8dd9cecd53 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -40,6 +40,7 @@ const DEFAULT_OPTIONS: PluginOptions = { blogPostComponent: '@theme/BlogPostPage', blogTagsListComponent: '@theme/BlogTagsListPage', blogTagsPostsComponent: '@theme/BlogTagsPostsPage', + showReadingTime: true, remarkPlugins: [], rehypePlugins: [], truncateMarker: //, // Regex. diff --git a/packages/docusaurus-plugin-content-blog/src/types.ts b/packages/docusaurus-plugin-content-blog/src/types.ts index 61b82f0358..174e67ad6e 100644 --- a/packages/docusaurus-plugin-content-blog/src/types.ts +++ b/packages/docusaurus-plugin-content-blog/src/types.ts @@ -31,6 +31,7 @@ export interface PluginOptions { remarkPlugins: string[]; rehypePlugins: string[]; truncateMarker: RegExp; + showReadingTime: boolean; feedOptions?: { type: FeedType; title?: string; @@ -77,6 +78,7 @@ export interface MetaData { date: Date; tags: (Tag | string)[]; title: string; + readingTime?: number; prevItem?: Paginator; nextItem?: Paginator; truncated: boolean; diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.js b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.js index 5640a85064..6dc0c05a19 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.js +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.js @@ -37,7 +37,7 @@ function BlogPostItem(props) { truncated, isBlogPostPage = false, } = props; - const {date, permalink, tags} = metadata; + const {date, permalink, tags, readingTime} = metadata; const {author, title} = frontMatter; const authorURL = frontMatter.author_url || frontMatter.authorURL; @@ -60,7 +60,8 @@ function BlogPostItem(props) {