{authorImageURL && (
-
+
)}
{author && (
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
index 27d61f3186..2179aeaca3 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
@@ -38,7 +38,7 @@ function BlogListPage(props: Props): JSX.Element {
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx
new file mode 100644
index 0000000000..79f285f59f
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx
@@ -0,0 +1,49 @@
+/**
+ * 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 Link from '@docusaurus/Link';
+import type {Props} from '@theme/BlogPostAuthor';
+
+import styles from './styles.module.css';
+
+function BlogPostAuthor({author}: Props): JSX.Element {
+ const {name, title, url, imageURL} = author;
+ return (
+
+ {imageURL && (
+
+
+
+ )}
+
+ {
+ // Note: only legacy author frontmatter allow empty name (not frontMatter.authors)
+ name && (
+
+
+
+ {name}
+
+
+ {title && (
+
+ {title}
+
+ )}
+
+ )
+ }
+
+ );
+}
+
+export default BlogPostAuthor;
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/styles.module.css b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/styles.module.css
new file mode 100644
index 0000000000..aae60add2d
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/styles.module.css
@@ -0,0 +1,12 @@
+/**
+ * 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.
+ */
+
+.image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostAuthors/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthors/index.tsx
new file mode 100644
index 0000000000..0b091c1416
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostAuthors/index.tsx
@@ -0,0 +1,55 @@
+/**
+ * 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 type {Props} from '@theme/BlogPostAuthors';
+import BlogPostAuthor from '@theme/BlogPostAuthor';
+
+function getAuthorsPerLine(authorsCount: number): 1 | 2 {
+ switch (authorsCount) {
+ case 0:
+ case 1:
+ return 1;
+ default:
+ return 2;
+ }
+}
+
+function getColClassName(authorsCount: number): string {
+ switch (getAuthorsPerLine(authorsCount)) {
+ case 1:
+ return 'col--12';
+ case 2:
+ return 'col--6';
+ default:
+ throw Error('unexpected');
+ }
+}
+
+// Component responsible for the authors layout
+export default function BlogPostAuthors({authors, assets}: Props): JSX.Element {
+ const authorsCount = authors.length;
+ if (authorsCount === 0) {
+ return <>>;
+ }
+ return (
+
+ {authors.map((author, idx) => (
+
+
+
+ ))}
+
+ );
+}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx
index b8062a37c7..ae45640ef7 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx
@@ -18,6 +18,7 @@ import type {Props} from '@theme/BlogPostItem';
import styles from './styles.module.css';
import TagsListInline from '@theme/TagsListInline';
+import BlogPostAuthors from '@theme/BlogPostAuthors';
// Very simple pluralization: probably good enough for now
function useReadingTimePlural() {
@@ -45,7 +46,7 @@ function BlogPostItem(props: Props): JSX.Element {
const {
children,
frontMatter,
- frontMatterAssets,
+ assets,
metadata,
truncated,
isBlogPostPage = false,
@@ -58,18 +59,10 @@ function BlogPostItem(props: Props): JSX.Element {
readingTime,
title,
editUrl,
+ authors,
} = metadata;
- const {author} = frontMatter;
- const image = frontMatterAssets.image ?? frontMatter.image;
-
- const authorURL = frontMatter.author_url || frontMatter.authorURL;
- const authorTitle = frontMatter.author_title || frontMatter.authorTitle;
- const authorImageURL =
- frontMatterAssets.author_image_url ||
- frontMatterAssets.authorImageURL ||
- frontMatter.author_image_url ||
- frontMatter.authorImageURL;
+ const image = assets.image ?? frontMatter.image;
const renderPostHeader = () => {
const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
@@ -90,39 +83,14 @@ function BlogPostItem(props: Props): JSX.Element {
{formattedDate}
- {readingTime && (
+ {typeof readingTime !== 'undefined' && (
<>
{' · '}
{readingTimePlural(readingTime)}
>
)}
-
- {authorImageURL && (
-
-
-
- )}
- {author && (
-
-
-
- {author}
-
-
-
- {authorTitle && (
-
- {authorTitle}
-
- )}
-
- )}
-
+
);
};
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
index d6cf19c4c7..8cabdad67d 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
@@ -15,12 +15,19 @@ 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, date, tags} = metadata;
+ const {frontMatter, assets, metadata} = BlogPostContents;
+ const {
+ title,
+ description,
+ nextItem,
+ prevItem,
+ date,
+ tags,
+ authors,
+ } = metadata;
const {hide_table_of_contents: hideTableOfContents, keywords} = frontMatter;
- const image = frontMatterAssets.image ?? frontMatter.image;
- const authorURL = frontMatter.author_url || frontMatter.authorURL;
+ const image = assets.image ?? frontMatter.image;
return (
- {authorURL && }
+
+ {/* TODO double check those article metas array syntaxes, see https://ogp.me/#array */}
+ {authors.some((author) => author.url) && (
+ author.url)
+ .filter(Boolean)
+ .join(',')}
+ />
+ )}
{tags.length > 0 && (
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx
index e64a5efa59..cb304821c0 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx
@@ -71,7 +71,7 @@ function BlogTagsPostPage(props: Props): JSX.Element {
diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts
index a878b2cb93..e4dbbdba12 100644
--- a/packages/docusaurus-theme-classic/src/types.d.ts
+++ b/packages/docusaurus-theme-classic/src/types.d.ts
@@ -27,15 +27,11 @@ declare module '@theme/BlogListPaginator' {
}
declare module '@theme/BlogPostItem' {
- import type {
- FrontMatter,
- FrontMatterAssets,
- Metadata,
- } from '@theme/BlogPostPage';
+ import type {FrontMatter, Assets, Metadata} from '@theme/BlogPostPage';
export type Props = {
readonly frontMatter: FrontMatter;
- readonly frontMatterAssets: FrontMatterAssets;
+ readonly assets: Assets;
readonly metadata: Metadata;
readonly truncated?: string | boolean;
readonly isBlogPostPage?: boolean;
@@ -46,6 +42,27 @@ declare module '@theme/BlogPostItem' {
export default BlogPostItem;
}
+declare module '@theme/BlogPostAuthor' {
+ import type {Metadata} from '@theme/BlogPostPage';
+
+ export type Props = {
+ readonly author: Metadata['authors'][number];
+ };
+
+ export default function BlogPostAuthor(props: Props): JSX.Element;
+}
+
+declare module '@theme/BlogPostAuthors' {
+ import type {Metadata, Assets} from '@theme/BlogPostPage';
+
+ export type Props = {
+ readonly authors: Metadata['authors'];
+ readonly assets: Assets;
+ };
+
+ export default function BlogPostAuthors(props: Props): JSX.Element;
+}
+
declare module '@theme/BlogPostPaginator' {
type Item = {readonly title: string; readonly permalink: string};
diff --git a/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap b/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap
index 4d9ff283cd..bd89b0a59f 100644
--- a/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap
+++ b/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap
@@ -60,4 +60,4 @@ exports[`validation schemas RemarkPluginsSchema: for value=false 1`] = `"\\"valu
exports[`validation schemas RemarkPluginsSchema: for value=null 1`] = `"\\"value\\" must be an array"`;
-exports[`validation schemas URISchema: for value="spaces are invalid in a URL" 1`] = `"\\"value\\" does not match any of the allowed types"`;
+exports[`validation schemas URISchema: for value="spaces are invalid in a URL" 1`] = `"\\"value\\" does not look like a valid url (value='')"`;
diff --git a/packages/docusaurus-utils-validation/src/validationSchemas.ts b/packages/docusaurus-utils-validation/src/validationSchemas.ts
index 0496147b73..5812891d8c 100644
--- a/packages/docusaurus-utils-validation/src/validationSchemas.ts
+++ b/packages/docusaurus-utils-validation/src/validationSchemas.ts
@@ -44,7 +44,10 @@ export const URISchema = Joi.alternatives(
return helpers.error('any.invalid');
}
}),
-);
+).messages({
+ 'alternatives.match':
+ "{{#label}} does not look like a valid url (value='{{.value}}')",
+});
export const PathnameSchema = Joi.string()
.custom((val) => {
diff --git a/website/_dogfooding/_blog tests/2020-08-03-second-blog-intro.md b/website/_dogfooding/_blog tests/2020-08-03-second-blog-intro.md
index 77115e1275..25f84187c0 100644
--- a/website/_dogfooding/_blog tests/2020-08-03-second-blog-intro.md
+++ b/website/_dogfooding/_blog tests/2020-08-03-second-blog-intro.md
@@ -1,10 +1,6 @@
---
title: Using twice the blog plugin
-author: Sebastien Lorber
-authorURL: https://sebastienlorber.com
-authorImageURL: https://github.com/slorber.png
-authorFBID: 611217057
-authorTwitter: sebastienlorber
+authors: [slorber]
tags: [blog, docusaurus]
---
diff --git a/website/_dogfooding/_blog tests/2021-08-22-no-author.md b/website/_dogfooding/_blog tests/2021-08-22-no-author.md
new file mode 100644
index 0000000000..4be979f1f1
--- /dev/null
+++ b/website/_dogfooding/_blog tests/2021-08-22-no-author.md
@@ -0,0 +1,3 @@
+# Hmmm!
+
+This is a blog post from an anonymous author!
diff --git a/website/_dogfooding/_blog tests/2021-08-23-multiple-authors.md b/website/_dogfooding/_blog tests/2021-08-23-multiple-authors.md
new file mode 100644
index 0000000000..5777def030
--- /dev/null
+++ b/website/_dogfooding/_blog tests/2021-08-23-multiple-authors.md
@@ -0,0 +1,11 @@
+---
+authors:
+ - slorber
+ - name: Josh-Cena
+ image_url: https://avatars.githubusercontent.com/u/55398995?v=4
+ url: https://joshcena.com
+---
+
+# Multiple authors
+
+You can have multiple authors for one blog post!
diff --git a/website/_dogfooding/_blog tests/authors.yml b/website/_dogfooding/_blog tests/authors.yml
new file mode 100644
index 0000000000..fc6a50b90b
--- /dev/null
+++ b/website/_dogfooding/_blog tests/authors.yml
@@ -0,0 +1,6 @@
+slorber:
+ name: Sebastien Lorber
+ title: Docusaurus maintainer
+ url: https://sebastienlorber.com
+ image_url: https://github.com/slorber.png
+ twitter: sebastienlorber
diff --git a/website/blog/2017-12-14-introducing-docusaurus.md b/website/blog/2017-12-14-introducing-docusaurus.md
index 850e1c5993..872e5d637b 100644
--- a/website/blog/2017-12-14-introducing-docusaurus.md
+++ b/website/blog/2017-12-14-introducing-docusaurus.md
@@ -1,10 +1,6 @@
---
title: Introducing Docusaurus
-author: Joel Marcey
-authorURL: http://twitter.com/JoelMarcey
-authorImageURL: https://graph.facebook.com/611217057/picture/?height=200&width=200
-authorFBID: 611217057
-authorTwitter: JoelMarcey
+authors: JMarcey
tags: [documentation, blog, docusaurus]
---
diff --git a/website/blog/2018-04-30-How-I-Converted-Profilo-To-Docusaurus.md b/website/blog/2018-04-30-How-I-Converted-Profilo-To-Docusaurus.md
index 44b8e4bda0..cf42f021b6 100644
--- a/website/blog/2018-04-30-How-I-Converted-Profilo-To-Docusaurus.md
+++ b/website/blog/2018-04-30-How-I-Converted-Profilo-To-Docusaurus.md
@@ -2,8 +2,7 @@
title: How I Converted Profilo to Docusaurus in Under 2 Hours
author: Christine Abernathy
authorURL: http://twitter.com/abernathyca
-authorImageURL: https://graph.facebook.com/1424840234/picture/?height=200&width=200
-authorFBID: 1424840234
+authorImageURL: https://github.com/caabernathy.png
authorTwitter: abernathyca
tags: [profilo, adoption]
---
diff --git a/website/blog/2018-09-11-Towards-Docusaurus-2.md b/website/blog/2018-09-11-Towards-Docusaurus-2.md
index 905719b4cd..8f9c5c1355 100644
--- a/website/blog/2018-09-11-Towards-Docusaurus-2.md
+++ b/website/blog/2018-09-11-Towards-Docusaurus-2.md
@@ -3,7 +3,7 @@ title: Towards Docusaurus 2
author: Endilie Yacop Sucipto
authorTitle: Maintainer of Docusaurus
authorURL: https://github.com/endiliey
-authorImageURL: https://avatars1.githubusercontent.com/u/17883920?s=460&v=4
+authorImageURL: https://github.com/endiliey.png
authorTwitter: endiliey
tags: [new, adoption]
---
diff --git a/website/blog/2018-12-14-Happy-First-Birthday-Slash.md b/website/blog/2018-12-14-Happy-First-Birthday-Slash.md
index d44215ceb2..81c8f0289f 100644
--- a/website/blog/2018-12-14-Happy-First-Birthday-Slash.md
+++ b/website/blog/2018-12-14-Happy-First-Birthday-Slash.md
@@ -1,11 +1,8 @@
---
title: Happy 1st Birthday Slash!
-author: Joel Marcey
-authorTitle: Co-creator of Docusaurus
-authorURL: https://github.com/JoelMarcey
-authorImageURL: https://graph.facebook.com/611217057/picture/?height=200&width=200
-authorFBID: 611217057
-authorTwitter: JoelMarcey
+authors:
+ - key: JMarcey
+ title: Co-creator of Docusaurus
tags: [birth]
---
diff --git a/website/blog/2019-12-30-docusaurus-2019-recap.md b/website/blog/2019-12-30-docusaurus-2019-recap.md
index 850754a990..fb1cba3bbc 100644
--- a/website/blog/2019-12-30-docusaurus-2019-recap.md
+++ b/website/blog/2019-12-30-docusaurus-2019-recap.md
@@ -1,10 +1,6 @@
---
title: Docusaurus 2019 Recap
-author: Yangshun Tay
-authorTitle: Front End Engineer at Facebook
-authorURL: https://github.com/yangshun
-authorImageURL: https://avatars1.githubusercontent.com/u/1315101?s=460&v=4
-authorTwitter: yangshunz
+authors: yangshun
tags: [recap]
---
diff --git a/website/blog/2020-01-07-tribute-to-endi.md b/website/blog/2020-01-07-tribute-to-endi.md
index 5c03384ab8..3ebe100539 100644
--- a/website/blog/2020-01-07-tribute-to-endi.md
+++ b/website/blog/2020-01-07-tribute-to-endi.md
@@ -1,10 +1,6 @@
---
title: Tribute to Endi
-author: Joel Marcey
-authorTitle: Technical Lead and Developer Advocate at Facebook
-authorURL: https://github.com/JoelMarcey
-authorImageURL: https://graph.facebook.com/611217057/picture/?height=200&width=200
-authorTwitter: JoelMarcey
+authors: JMarcey
tags: [endi, tribute]
---
diff --git a/website/blog/2021-01-19-docusaurus-2020-recap.md b/website/blog/2021-01-19-docusaurus-2020-recap.md
index d40d416d34..85d252681f 100644
--- a/website/blog/2021-01-19-docusaurus-2020-recap.md
+++ b/website/blog/2021-01-19-docusaurus-2020-recap.md
@@ -1,10 +1,6 @@
---
title: Docusaurus 2020 Recap
-author: Sébastien Lorber
-authorTitle: Docusaurus maintainer
-authorURL: https://sebastienlorber.com
-authorImageURL: https://github.com/slorber.png
-authorTwitter: sebastienlorber
+authors: [slorber]
tags: [recap]
image: /img/docusaurus-2020-recap.png
---
diff --git a/website/blog/2021-03-09-releasing-docusaurus-i18n.md b/website/blog/2021-03-09-releasing-docusaurus-i18n.md
index 61e8cdcf65..719e99a075 100644
--- a/website/blog/2021-03-09-releasing-docusaurus-i18n.md
+++ b/website/blog/2021-03-09-releasing-docusaurus-i18n.md
@@ -1,10 +1,6 @@
---
title: Releasing Docusaurus i18n
-author: Sébastien Lorber
-authorTitle: Docusaurus maintainer
-authorURL: https://sebastienlorber.com
-authorImageURL: https://github.com/slorber.png
-authorTwitter: sebastienlorber
+authors: [slorber]
tags: [release, i18n]
image: /img/blog/2021-03-09-releasing-docusaurus-i18n/social-card.png
---
diff --git a/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/author.jpeg b/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/author.jpeg
deleted file mode 100644
index be9fdfdbf4..0000000000
Binary files a/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/author.jpeg and /dev/null differ
diff --git a/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/slorber.png b/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/slorber.png
new file mode 100644
index 0000000000..a2959a335c
Binary files /dev/null and b/website/blog/2021-05-12-announcing-docusaurus-two-beta/img/slorber.png differ
diff --git a/website/blog/2021-05-12-announcing-docusaurus-two-beta/index.md b/website/blog/2021-05-12-announcing-docusaurus-two-beta/index.md
index c25cc2f616..4d4be53bc8 100644
--- a/website/blog/2021-05-12-announcing-docusaurus-two-beta/index.md
+++ b/website/blog/2021-05-12-announcing-docusaurus-two-beta/index.md
@@ -1,10 +1,12 @@
---
title: Announcing Docusaurus 2 Beta
-author: Sébastien Lorber
-authorTitle: Docusaurus maintainer
-authorURL: https://sebastienlorber.com
-authorImageURL: ./img/author.jpeg
-authorTwitter: sebastienlorber
+authors:
+ - key: slorber
+ image_url: ./img/slorber.png
+ - JMarcey
+ - yangshun
+ - lex111
+
tags: [release, beta]
image: ./img/social-card.png
---
diff --git a/website/blog/authors.yml b/website/blog/authors.yml
new file mode 100644
index 0000000000..6303083427
--- /dev/null
+++ b/website/blog/authors.yml
@@ -0,0 +1,26 @@
+JMarcey:
+ name: Joel Marcey
+ title: Technical Lead & Developer Advocate at Facebook
+ url: http://twitter.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
+ twitter: JoelMarcey
+
+slorber:
+ name: Sébastien Lorber
+ title: Docusaurus maintainer
+ url: https://sebastienlorber.com
+ image_url: https://github.com/slorber.png
+ twitter: sebastienlorber
+
+yangshun:
+ name: Yangshun Tay
+ title: Front End Engineer at Facebook
+ url: https://github.com/yangshun
+ image_url: https://github.com/yangshun.png
+ twitter: yangshunz
+
+lex111:
+ name: Alexey Pyltsyn
+ title: Open-source enthusiast
+ url: https://github.com/lex111
+ image_url: https://github.com/lex111.png
diff --git a/website/docs/api/plugins/plugin-content-blog.md b/website/docs/api/plugins/plugin-content-blog.md
index efd3bf06a1..26ef631a62 100644
--- a/website/docs/api/plugins/plugin-content-blog.md
+++ b/website/docs/api/plugins/plugin-content-blog.md
@@ -4,7 +4,7 @@ title: '📦 plugin-content-blog'
slug: '/api/plugins/@docusaurus/plugin-content-blog'
---
-Provides the [Blog](blog.md) feature and is the default blog plugin for Docusaurus.
+Provides the [Blog](blog.mdx) feature and is the default blog plugin for Docusaurus.
## Installation {#installation}
@@ -28,7 +28,7 @@ Accepted fields:
| Name | Type | Default | Description |
| --- | --- | --- | --- |
-| `path` | `string` | `'blog'` | Path to data on filesystem relative to site dir. |
+| `path` | `string` | `'blog'` | Path to the blog content directory on the filesystem, relative to site dir. |
| `editUrl` | string | EditUrlFunction
| `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `blogTitle` | `string` | `'Blog'` | Blog page title for better SEO. |
@@ -49,6 +49,7 @@ Accepted fields:
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `truncateMarker` | `string` | `//` | Truncate marker, can be a regex or string. |
| `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. |
+| `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory specified with `path`. Can also be a `json` file. |
| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. If undefined, no rss feed will be generated. |
| `feedOptions.type` | 'rss' | 'atom' | 'all'
(or array of multiple options) | **Required** | Type of feed to be generated. |
| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. |
@@ -174,10 +175,11 @@ Accepted fields:
| Name | Type | Default | Description |
| --- | --- | --- | --- |
-| `author` | `string` | `undefined` | The author name to be displayed. |
-| `author_url` | `string` | `undefined` | The URL that the author's name will be linked to. This could be a GitHub, Twitter, Facebook profile URL, etc. |
-| `author_image_url` | `string` | `undefined` | The URL to the author's thumbnail image. |
-| `author_title` | `string` | `undefined` | A description of the author. |
+| `authors` | `Authors` | `undefined` | List of blog post authors (or unique author). Read the [`authors` guide](../../blog.mdx#blog-post-authors) for more explanations. Prefer `authors` over the `author_*` FrontMatter fields, even for single author blog posts. |
+| `author` | `string` | `undefined` | ⚠️ Prefer using `authors`. The blog post author's name. |
+| `author_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL that the author's name will be linked to. This could be a GitHub, Twitter, Facebook profile URL, etc. |
+| `author_image_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL to the author's thumbnail image. |
+| `author_title` | `string` | `undefined` | ⚠️ Prefer using `authors`. A description of the author. |
| `title` | `string` | Markdown title | The blog post title. |
| `date` | `string` | File name or file creation time | The blog post creation date. If not specified, this can be extracted from the file or folder name, e.g, `2021-04-15-blog-post.mdx`, `2021-04-15-blog-post/index.mdx`, `2021/04/15/blog-post.mdx`. Otherwise, it is the Markdown file creation time. |
| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. |
@@ -192,6 +194,20 @@ Accepted fields:
```typescript
type Tag = string | {label: string; permalink: string};
+
+// An author key references an author from the global plugin authors.yml file
+type AuthorKey = string;
+
+type Author = {
+ key?: AuthorKey;
+ name: string;
+ title?: string;
+ url?: string;
+ image_url?: string;
+};
+
+// The FrontMatter authors field allows various possible shapes
+type Authors = AuthorKey | Author | (AuthorKey | Author)[];
```
Example:
@@ -199,10 +215,13 @@ Example:
```yml
---
title: Welcome Docusaurus v2
-author: Joel Marcey
-author_title: Co-creator of Docusaurus 1
-author_url: https://github.com/JoelMarcey
-author_image_url: https://graph.facebook.com/611217057/picture/?height=200&width=200
+authors:
+ - slorber
+ - yangshun
+ - name: Joel Marcey
+ title: Co-creator of Docusaurus 1
+ url: https://github.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
tags: [hello, docusaurus-v2]
description: This is my first post on Docusaurus 2.
image: https://i.imgur.com/mErPwqL.png
@@ -228,6 +247,7 @@ Read the [i18n introduction](../../i18n/i18n-introduction.md) first.
website/i18n//docusaurus-plugin-content-blog
│
│ # translations for website/blog
+├── authors.yml
├── first-blog-post.md
├── second-blog-post.md
│
diff --git a/website/docs/blog.md b/website/docs/blog.mdx
similarity index 65%
rename from website/docs/blog.md
rename to website/docs/blog.mdx
index 8488920631..96dee72d9d 100644
--- a/website/docs/blog.md
+++ b/website/docs/blog.mdx
@@ -3,6 +3,9 @@ id: blog
title: Blog
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
The blog feature enables you to deploy in no time a full-featured blog.
:::info
@@ -36,17 +39,23 @@ module.exports = {
To publish in the blog, create a Markdown file within the blog directory.
-For example, create a file at `my-website/blog/2019-09-05-hello-docusaurus-v2.md`:
+For example, create a file at `website/blog/2019-09-05-hello-docusaurus-v2.md`:
-```yml
+```yml title="website/blog/2019-09-05-hello-docusaurus-v2.md"
---
title: Welcome Docusaurus v2
-author: Joel Marcey
-author_title: Co-creator of Docusaurus 1
-author_url: https://github.com/JoelMarcey
-author_image_url: https://graph.facebook.com/611217057/picture/?height=200&width=200
-tags: [hello, docusaurus-v2]
description: This is my first post on Docusaurus 2.
+slug: welcome-docusaurus-v2
+authors:
+ - name: Joel Marcey
+ title: Co-creator of Docusaurus 1
+ url: https://github.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
+ - name: Sébastien Lorber
+ title: Docusaurus maintainer
+ url: https://sebastienlorber.com
+ image_url: https://github.com/slorber.png
+tags: [hello, docusaurus-v2]
image: https://i.imgur.com/mErPwqL.png
hide_table_of_contents: false
---
@@ -158,9 +167,184 @@ module.exports = {
};
```
-:::note
+## Blog post authors {#blog-post-authors}
-Because the sidebar title is hard-coded in the configuration file, it is currently untranslatable.
+Use the `authors` FrontMatter field to declare blog post authors.
+
+### Inline authors {#inline-authors}
+
+Blog post authors can be declared directly inside the FrontMatter:
+
+````mdx-code-block
+
+
+
+```yml title="my-blog-post.md"
+---
+authors:
+ name: Joel Marcey
+ title: Co-creator of Docusaurus 1
+ url: https://github.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
+---
+```
+
+
+
+
+```yml title="my-blog-post.md"
+---
+authors:
+ - name: Joel Marcey
+ title: Co-creator of Docusaurus 1
+ url: https://github.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
+ - name: Sébastien Lorber
+ title: Docusaurus maintainer
+ url: https://sebastienlorber.com
+ image_url: https://github.com/slorber.png
+---
+```
+
+
+
+````
+
+:::tip
+
+This option works best to get started, or for casual, irregular authors.
+
+:::
+
+:::info
+
+Prefer usage of the `authors` FrontMatter, but the legacy `author_*` FrontMatter remains supported:
+
+```yml title="my-blog-post.md"
+---
+author: Joel Marcey
+author_title: Co-creator of Docusaurus 1
+author_url: https://github.com/JoelMarcey
+author_image_url: https://github.com/JoelMarcey.png
+---
+
+```
+
+:::
+
+### Global authors {#global-authors}
+
+For regular blog post authors, it can be tedious to maintain authors information inlined in each blog post.
+
+It is possible declare those authors globally in a configuration file:
+
+```yml title="website/blog/authors.yml"
+jmarcey:
+ name: Joel Marcey
+ title: Co-creator of Docusaurus 1
+ url: https://github.com/JoelMarcey
+ image_url: https://github.com/JoelMarcey.png
+
+slorber:
+ name: Sébastien Lorber
+ title: Docusaurus maintainer
+ url: https://sebastienlorber.com
+ image_url: https://github.com/slorber.png
+```
+
+:::tip
+
+Use the `authorsMapPath` plugin option to configure the path. JSON is also supported.
+
+:::
+
+In blog posts FrontMatter, you can reference the authors declared in the global configuration file:
+
+````mdx-code-block
+
+
+
+```yml title="my-blog-post.md"
+---
+authors: jmarcey
+---
+```
+
+
+
+
+```yml title="my-blog-post.md"
+---
+authors: [jmarcey, slorber]
+---
+```
+
+
+
+````
+
+:::info
+
+The `authors` system is very flexible and can suit more advanced use-case:
+
+
+ Mix inline authors and global authors
+
+You can use global authors most of the time, and still use inline authors:
+
+```yml title="my-blog-post.md"
+---
+authors:
+ - jmarcey
+ - slorber
+ - name: Inline Author name
+ title: Inline Author Title
+ url: https://github.com/inlineAuthor
+ image_url: https://github.com/inlineAuthor
+---
+
+```
+
+
+
+
+ Local override of global authors
+
+You can customize the global author's data on per-blog-post basis
+
+```yml title="my-blog-post.md"
+---
+authors:
+ - key: jmarcey
+ title: Joel Marcey's new title
+ - key: slorber
+ name: Sébastien Lorber's new name
+---
+
+```
+
+
+
+
+ Localize the author's configuration file
+
+The configuration file can be localized, just create a localized copy of it at:
+
+```bash
+website/i18n//docusaurus-plugin-content-blog/authors.yml
+```
+
+
:::
diff --git a/website/docs/guides/docs/docs-introduction.md b/website/docs/guides/docs/docs-introduction.md
index b2cd257e91..0612e7b089 100644
--- a/website/docs/guides/docs/docs-introduction.md
+++ b/website/docs/guides/docs/docs-introduction.md
@@ -81,6 +81,6 @@ You should delete the existing homepage at `./src/pages/index.js`, or else there
:::tip
-There's also a "blog-only mode" for those who only want to use the blog feature of Docusaurus 2. You can use the same method detailed above. Follow the setup instructions on [Blog-only mode](../../blog.md#blog-only-mode).
+There's also a "blog-only mode" for those who only want to use the blog feature of Docusaurus 2. You can use the same method detailed above. Follow the setup instructions on [Blog-only mode](../../blog.mdx#blog-only-mode).
:::
diff --git a/website/docs/installation.md b/website/docs/installation.md
index 8e99c39d00..c632bc83e6 100644
--- a/website/docs/installation.md
+++ b/website/docs/installation.md
@@ -90,7 +90,7 @@ my-website
### Project structure rundown {#project-structure-rundown}
-- `/blog/` - Contains the blog Markdown files. You can delete the directory if you do not want/need a blog. More details can be found in the [blog guide](blog.md)
+- `/blog/` - Contains the blog Markdown files. You can delete the directory if you do not want/need a blog. More details can be found in the [blog guide](blog.mdx)
- `/docs/` - Contains the Markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](./guides/docs/docs-markdown-features.mdx)
- `/src/` - Non-documentation files like pages or custom React components. You don't have to strictly put your non-documentation files in here but putting them under a centralized directory makes it easier to specify in case you need to do some sort of linting/processing
- `/src/pages` - Any files within this directory will be converted into a website page. More details can be found in the [pages guide](guides/creating-pages.md)
diff --git a/website/docs/migration/migration-manual.md b/website/docs/migration/migration-manual.md
index 5c477cf38e..e915c815e6 100644
--- a/website/docs/migration/migration-manual.md
+++ b/website/docs/migration/migration-manual.md
@@ -576,7 +576,7 @@ Refer to the [multi-language support code blocks](../guides/markdown-features/ma
The Docusaurus front matter fields for the blog have been changed from camelCase to snake_case to be consistent with the docs.
-The fields `authorFBID` and `authorTwitter` have been deprecated. They are only used for generating the profile image of the author which can be done via the `author_image_url` field.
+The fields `authorFBID` and `authorTwitter` have been deprecated. They are only used for generating the profile image of the author which can be done via the `authors` field.
## Deployment {#deployment}
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index fcd2e81eec..4c3a7a462e 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -270,7 +270,7 @@ const TwitterSvg =
}
return `https://github.com/facebook/docusaurus/edit/main/website/${blogDirPath}/${blogPath}`;
},
- postsPerPage: 3,
+ postsPerPage: 5,
feedOptions: {
type: 'all',
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`,