From 493225a3c6b6c6493e3ed7e01d12dd1b2b6f95e6 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 Aug 2021 18:21:58 +0800 Subject: [PATCH] feat(plugin-blog): multi-authors support + authors.yml global configuration (#5396) * Complete function Signed-off-by: Josh-Cena * A lot of blank lines Signed-off-by: Josh-Cena * More lenient validation Signed-off-by: Josh-Cena * Remove or Signed-off-by: Josh-Cena * Simpler logic Signed-off-by: Josh-Cena * Expand docs Signed-off-by: Josh-Cena * Better docs Signed-off-by: Josh-Cena * Dogfood Signed-off-by: Josh-Cena * More writeup Signed-off-by: Josh-Cena * Polish Signed-off-by: Josh-Cena * Polish Signed-off-by: Josh-Cena * Move mergeAuthorMap to authors.ts Signed-off-by: Josh-Cena * Unbreak relative assets * Update docs * Clarify in docs * simplify feed authors * rename authorMap -> authorsMap * mergeAuthorsMap -> getBlogPostAuthors * website => 5 blog posts per page * improve authors map file * Extract new theme authors components + display in row * add comment for meta array syntaxes * blog => getPathsToWatch should watch authorsMap file * remove useless v1 blog FBID frontmatter * keep older frontmatter syntax for now * revert blog frontmatter * Better console message * better blog authors frontmatter impl * add multi authors to beta blog post + fix some authors margins * fix React key * Refactor: mdx loader should support a more flexible assets system (poc, not documented yet) * better display of blog post authors: adapt layout to authors count + add line clamp * smaller local image * fix blog feed tests * fix blog frontmatter tests + improve validation schema * add more frontmatter tests * add tests for getAuthorsMapFilePath * tests for validateAuthorsMapFile * add tests for readAuthorsMapFile * test getAuthorsMap * exhaustive tests for getBlogPostAuthors * fix remaining tests * missing blog plugin author tests * fix windows tests * improve blog multi-author's doc * Use new format in init template Signed-off-by: Josh-Cena * Improve error message Signed-off-by: Josh-Cena * update feed snapshot * blog authors: limit to 2 cols + fix margins for no authors * minor doc improvements * better init template blog posts, demonstrating Blog features * replace the legacy blog author frontmatter in remaining places * Prefer using clsx Signed-off-by: Josh-Cena * cleanup getColClassName * remove blog author name/title line-clamping Co-authored-by: slorber --- .gitignore | 1 + package.json | 1 + packages/docusaurus-init/README.md | 24 + ...-hola.md => 2019-05-28-first-blog-post.md} | 13 +- .../shared/blog/2019-05-29-hello-world.md | 17 - .../shared/blog/2019-05-29-long-blog-post.md | 44 ++ .../shared/blog/2019-05-30-welcome.md | 13 - .../shared/blog/2021-08-01-mdx-blog-post.mdx | 20 + .../docusaurus-plushie-banner.jpeg | Bin 0 -> 96122 bytes .../shared/blog/2021-08-26-welcome/index.md | 25 + .../templates/shared/blog/authors.yml | 17 + .../tutorial-basics/create-a-blog-post.md | 13 +- packages/docusaurus-mdx-loader/src/index.ts | 91 +-- .../docusaurus-plugin-content-blog/index.d.ts | 30 +- .../package.json | 1 + .../__fixtures__/authorsMapFiles/authors.json | 29 + .../__fixtures__/authorsMapFiles/authors.yml | 27 + .../authorsMapFiles/authorsBad1.json | 5 + .../authorsMapFiles/authorsBad1.yml | 3 + .../authorsMapFiles/authorsBad2.json | 3 + .../authorsMapFiles/authorsBad2.yml | 2 + .../authorsMapFiles/authorsBad3.json | 8 + .../authorsMapFiles/authorsBad3.yml | 3 + .../contentPathEmpty/empty | 0 .../contentPathJson1/authors.json | 0 .../contentPathJson2/authors.json | 0 .../sub/folder/authors.yml | 0 .../contentPathYml1/authors.yml | 0 .../contentPathYml2/authors.yml | 0 .../2018-12-14-Happy-First-Birthday-Slash.md | 3 + .../__fixtures__/website/blog/authors.yml | 4 + .../__fixtures__/website/blog/simple-slug.md | 4 + .../2018-12-14-Happy-First-Birthday-Slash.md | 3 + .../authors.yml | 5 + .../generateBlogFeed.test.ts.snap | 10 + .../src/__tests__/authors.test.ts | 608 ++++++++++++++++++ .../src/__tests__/blogFrontMatter.test.ts | 107 ++- .../src/__tests__/generateBlogFeed.test.ts | 2 + .../src/__tests__/index.test.ts | 50 +- .../src/authors.ts | 202 ++++++ .../src/blogFrontMatter.ts | 80 ++- .../src/blogUtils.ts | 22 +- .../src/index.ts | 46 +- .../src/pluginOptionSchema.ts | 2 + .../src/types.ts | 15 + .../src/__tests__/docFrontMatter.test.ts | 2 +- .../src/theme/BlogPostItem/index.tsx | 14 +- .../src/theme/BlogListPage/index.tsx | 2 +- .../src/theme/BlogPostAuthor/index.tsx | 49 ++ .../theme/BlogPostAuthor/styles.module.css | 12 + .../src/theme/BlogPostAuthors/index.tsx | 55 ++ .../src/theme/BlogPostItem/index.tsx | 44 +- .../src/theme/BlogPostPage/index.tsx | 29 +- .../src/theme/BlogTagsPostsPage/index.tsx | 2 +- .../docusaurus-theme-classic/src/types.d.ts | 29 +- .../validationSchemas.test.ts.snap | 2 +- .../src/validationSchemas.ts | 5 +- .../2020-08-03-second-blog-intro.md | 6 +- .../_blog tests/2021-08-22-no-author.md | 3 + .../2021-08-23-multiple-authors.md | 11 + website/_dogfooding/_blog tests/authors.yml | 6 + .../blog/2017-12-14-introducing-docusaurus.md | 6 +- ...0-How-I-Converted-Profilo-To-Docusaurus.md | 3 +- .../blog/2018-09-11-Towards-Docusaurus-2.md | 2 +- .../2018-12-14-Happy-First-Birthday-Slash.md | 9 +- .../blog/2019-12-30-docusaurus-2019-recap.md | 6 +- website/blog/2020-01-07-tribute-to-endi.md | 6 +- .../blog/2021-01-19-docusaurus-2020-recap.md | 6 +- .../2021-03-09-releasing-docusaurus-i18n.md | 6 +- .../img/author.jpeg | Bin 3993 -> 0 bytes .../img/slorber.png | Bin 0 -> 69275 bytes .../index.md | 12 +- website/blog/authors.yml | 26 + .../docs/api/plugins/plugin-content-blog.md | 40 +- website/docs/{blog.md => blog.mdx} | 202 +++++- website/docs/guides/docs/docs-introduction.md | 2 +- website/docs/installation.md | 2 +- website/docs/migration/migration-manual.md | 2 +- website/docusaurus.config.js | 2 +- 79 files changed, 1871 insertions(+), 285 deletions(-) rename packages/docusaurus-init/templates/shared/blog/{2019-05-28-hola.md => 2019-05-28-first-blog-post.md} (53%) delete mode 100644 packages/docusaurus-init/templates/shared/blog/2019-05-29-hello-world.md create mode 100644 packages/docusaurus-init/templates/shared/blog/2019-05-29-long-blog-post.md delete mode 100644 packages/docusaurus-init/templates/shared/blog/2019-05-30-welcome.md create mode 100644 packages/docusaurus-init/templates/shared/blog/2021-08-01-mdx-blog-post.mdx create mode 100644 packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg create mode 100644 packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/index.md create mode 100644 packages/docusaurus-init/templates/shared/blog/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathEmpty/empty create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson1/authors.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson2/authors.json create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathNestedYml/sub/folder/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml1/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml2/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts create mode 100644 packages/docusaurus-plugin-content-blog/src/authors.ts create mode 100644 packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/index.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/BlogPostAuthor/styles.module.css create mode 100644 packages/docusaurus-theme-classic/src/theme/BlogPostAuthors/index.tsx create mode 100644 website/_dogfooding/_blog tests/2021-08-22-no-author.md create mode 100644 website/_dogfooding/_blog tests/2021-08-23-multiple-authors.md create mode 100644 website/_dogfooding/_blog tests/authors.yml delete mode 100644 website/blog/2021-05-12-announcing-docusaurus-two-beta/img/author.jpeg create mode 100644 website/blog/2021-05-12-announcing-docusaurus-two-beta/img/slorber.png create mode 100644 website/blog/authors.yml rename website/docs/{blog.md => blog.mdx} (65%) diff --git a/.gitignore b/.gitignore index 202d5775b0..640b8f236a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ coverage .cache-loader types test-website +test-website-in-workspace packages/docusaurus/lib/ packages/docusaurus-*/lib/* diff --git a/package.json b/package.json index c6d8dab064..f163a5fefd 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "workspaces": [ "packages/*", "website", + "test-website-in-workspace", "packages/docusaurus-init/templates/*", "admin/new.docusaurus.io" ], diff --git a/packages/docusaurus-init/README.md b/packages/docusaurus-init/README.md index 27ce71c066..798fc6302c 100644 --- a/packages/docusaurus-init/README.md +++ b/packages/docusaurus-init/README.md @@ -5,3 +5,27 @@ Create Docusaurus apps easily. ## Usage Please see the [installation documentation](https://docusaurus.io/docs/installation). + +## For maintainers + +For Docusaurus maintainers, templates can be tested with: + +```bash +cd `git rev-parse --show-toplevel` # Back to repo root +rm -rf test-website +yarn docusaurus-init init test-website classic +cd test-website +yarn start +``` + +Note: `test-website` is not part of the workspace and use packages from npm. + +Use the following to test the templates against local packages: + +```bash +cd `git rev-parse --show-toplevel` # Back to repo root +rm -rf test-website-in-workspace +yarn docusaurus-init init test-website-in-workspace classic +cd test-website-in-workspace +yarn start +``` diff --git a/packages/docusaurus-init/templates/shared/blog/2019-05-28-hola.md b/packages/docusaurus-init/templates/shared/blog/2019-05-28-first-blog-post.md similarity index 53% rename from packages/docusaurus-init/templates/shared/blog/2019-05-28-hola.md rename to packages/docusaurus-init/templates/shared/blog/2019-05-28-first-blog-post.md index 4adbc327fc..02f3f81bd2 100644 --- a/packages/docusaurus-init/templates/shared/blog/2019-05-28-hola.md +++ b/packages/docusaurus-init/templates/shared/blog/2019-05-28-first-blog-post.md @@ -1,10 +1,11 @@ --- -slug: hola -title: Hola -author: Gao Wei -author_title: Docusaurus Core Team -author_url: https://github.com/wgao19 -author_image_url: https://avatars1.githubusercontent.com/u/2055384?v=4 +slug: first-blog-post +title: First Blog Post +authors: + name: Gao Wei + title: Docusaurus Core Team + url: https://github.com/wgao19 + image_url: https://github.com/wgao19.png tags: [hola, docusaurus] --- diff --git a/packages/docusaurus-init/templates/shared/blog/2019-05-29-hello-world.md b/packages/docusaurus-init/templates/shared/blog/2019-05-29-hello-world.md deleted file mode 100644 index 6fd208307b..0000000000 --- a/packages/docusaurus-init/templates/shared/blog/2019-05-29-hello-world.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -slug: hello-world -title: Hello -author: Endilie Yacop Sucipto -author_title: Maintainer of Docusaurus -author_url: https://github.com/endiliey -author_image_url: https://avatars1.githubusercontent.com/u/17883920?s=460&v=4 -tags: [hello, docusaurus] ---- - -Welcome to this blog. This blog is created with [**Docusaurus 2**](https://docusaurus.io/). - - - -This is a test post. - -A whole bunch of other information. diff --git a/packages/docusaurus-init/templates/shared/blog/2019-05-29-long-blog-post.md b/packages/docusaurus-init/templates/shared/blog/2019-05-29-long-blog-post.md new file mode 100644 index 0000000000..26ffb1b1f6 --- /dev/null +++ b/packages/docusaurus-init/templates/shared/blog/2019-05-29-long-blog-post.md @@ -0,0 +1,44 @@ +--- +slug: long-blog-post +title: Long Blog Post +authors: endi +tags: [hello, docusaurus] +--- + +This is the summary of a very long blog post, + +Use a `` comment to limit blog post size in the list view. + + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/packages/docusaurus-init/templates/shared/blog/2019-05-30-welcome.md b/packages/docusaurus-init/templates/shared/blog/2019-05-30-welcome.md deleted file mode 100644 index d35d57b7dc..0000000000 --- a/packages/docusaurus-init/templates/shared/blog/2019-05-30-welcome.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -slug: welcome -title: Welcome -author: Yangshun Tay -author_title: Front End Engineer @ Facebook -author_url: https://github.com/yangshun -author_image_url: https://avatars0.githubusercontent.com/u/1315101?s=400&v=4 -tags: [facebook, hello, docusaurus] ---- - -Blog features are powered by the blog plugin. Simply add files to the `blog` directory. It supports tags as well! - -Delete the whole directory if you don't want the blog features. As simple as that! diff --git a/packages/docusaurus-init/templates/shared/blog/2021-08-01-mdx-blog-post.mdx b/packages/docusaurus-init/templates/shared/blog/2021-08-01-mdx-blog-post.mdx new file mode 100644 index 0000000000..c04ebe323e --- /dev/null +++ b/packages/docusaurus-init/templates/shared/blog/2021-08-01-mdx-blog-post.mdx @@ -0,0 +1,20 @@ +--- +slug: mdx-blog-post +title: MDX Blog Post +authors: [slorber] +tags: [docusaurus] +--- + +Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). + +:::tip + +Use the power of React to create interactive blog posts. + +```js + +``` + + + +::: diff --git a/packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..11bda0928456b12f8e53d0ba5709212a4058d449 GIT binary patch literal 96122 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 literal 0 HcmV?d00001 diff --git a/packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/index.md b/packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/index.md new file mode 100644 index 0000000000..9455168f17 --- /dev/null +++ b/packages/docusaurus-init/templates/shared/blog/2021-08-26-welcome/index.md @@ -0,0 +1,25 @@ +--- +slug: welcome +title: Welcome +authors: [slorber, yangshun] +tags: [facebook, hello, docusaurus] +--- + +[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). + +Simply add Markdown files (or folders) to the `blog` directory. + +Regular blog authors can be added to `authors.yml`. + +The blog post date can be extracted from filenames, such as: + +- `2019-05-30-welcome.md` +- `2019-05-30-welcome/index.md` + +A blog post folder can be convenient to co-locate blog post images: + +![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) + +The blog supports tags as well! + +**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. diff --git a/packages/docusaurus-init/templates/shared/blog/authors.yml b/packages/docusaurus-init/templates/shared/blog/authors.yml new file mode 100644 index 0000000000..bcb2991563 --- /dev/null +++ b/packages/docusaurus-init/templates/shared/blog/authors.yml @@ -0,0 +1,17 @@ +endi: + name: Endilie Yacop Sucipto + title: Maintainer of Docusaurus + url: https://github.com/endiliey + image_url: https://github.com/endiliey.png + +yangshun: + name: Yangshun Tay + title: Front End Engineer @ Facebook + url: https://github.com/yangshun + image_url: https://github.com/yangshun.png + +slorber: + name: Sébastien Lorber + title: Docusaurus maintainer + url: https://sebastienlorber.com + image_url: https://github.com/slorber.png diff --git a/packages/docusaurus-init/templates/shared/docs/tutorial-basics/create-a-blog-post.md b/packages/docusaurus-init/templates/shared/docs/tutorial-basics/create-a-blog-post.md index d893e1c74f..0d50aaf316 100644 --- a/packages/docusaurus-init/templates/shared/docs/tutorial-basics/create-a-blog-post.md +++ b/packages/docusaurus-init/templates/shared/docs/tutorial-basics/create-a-blog-post.md @@ -14,10 +14,15 @@ Create a file at `blog/2021-02-28-greetings.md`: --- slug: greetings title: Greetings! -author: Steven Hansel -author_title: Docusaurus Contributor -author_url: https://github.com/ShinteiMai -author_image_url: https://github.com/ShinteiMai.png +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: [greetings] --- diff --git a/packages/docusaurus-mdx-loader/src/index.ts b/packages/docusaurus-mdx-loader/src/index.ts index cd02f41262..26f98c657a 100644 --- a/packages/docusaurus-mdx-loader/src/index.ts +++ b/packages/docusaurus-mdx-loader/src/index.ts @@ -53,43 +53,45 @@ async function readMetadataPath(metadataPath: string) { } } -// For some specific FrontMatter fields, we want to allow referencing local relative assets so that they enter the Webpack asset pipeline -// We don't do that for all frontMatters, only for the configured keys +// Converts assets an object with Webpack require calls code +// This is useful for mdx files to reference co-located assets using relative paths +// Those assets should enter the Webpack assets pipeline and be hashed +// For now, we only handle that for images and paths starting with ./ // {image: "./myImage.png"} => {image: require("./myImage.png")} -function createFrontMatterAssetsExportCode( - frontMatter: Record, - frontMatterAssetKeys: string[] = [], -) { - if (frontMatterAssetKeys.length === 0) { +function createAssetsExportCode(assets: Record) { + if (Object.keys(assets).length === 0) { return 'undefined'; } - function createFrontMatterAssetRequireCode(value: unknown) { + // TODO implementation can be completed/enhanced + function createAssetValueCode(assetValue: unknown): string | undefined { + if (Array.isArray(assetValue)) { + const arrayItemCodes = assetValue.map( + (item) => createAssetValueCode(item) ?? 'undefined', + ); + return `[${arrayItemCodes.join(', ')}]`; + } // Only process string values starting with ./ // We could enhance this logic and check if file exists on disc? - if (typeof value === 'string' && value.startsWith('./')) { + if (typeof assetValue === 'string' && assetValue.startsWith('./')) { // TODO do we have other use-cases than image assets? // Probably not worth adding more support, as we want to move to Webpack 5 new asset system (https://github.com/facebook/docusaurus/pull/4708) const inlineLoader = inlineMarkdownImageFileLoader; - return `require("${inlineLoader}${escapePath(value)}").default`; + return `require("${inlineLoader}${escapePath(assetValue)}").default`; } return undefined; } - const frontMatterAssetEntries = Object.entries(frontMatter).filter(([key]) => - frontMatterAssetKeys.includes(key), - ); + const assetEntries = Object.entries(assets); - const lines = frontMatterAssetEntries + const codeLines = assetEntries .map(([key, value]) => { - const assetRequireCode = createFrontMatterAssetRequireCode(value); + const assetRequireCode = createAssetValueCode(value); return assetRequireCode ? `"${key}": ${assetRequireCode},` : undefined; }) .filter(Boolean); - const exportValue = `{\n${lines.join('\n')}\n}`; - - return exportValue; + return `{\n${codeLines.join('\n')}\n}`; } const docusaurusMdxLoader: Loader = async function (fileString) { @@ -130,18 +132,9 @@ const docusaurusMdxLoader: Loader = async function (fileString) { return callback(err); } - let exportStr = ` -export const frontMatter = ${stringifyObject(frontMatter)}; -export const frontMatterAssets = ${createFrontMatterAssetsExportCode( - frontMatter, - reqOptions.frontMatterAssetKeys, - )}; -export const contentTitle = ${stringifyObject(contentTitle)};`; - // MDX partials are MDX files starting with _ or in a folder starting with _ // Partial are not expected to have an associated metadata file or frontmatter const isMDXPartial = options.isMDXPartial && options.isMDXPartial(filePath); - if (isMDXPartial && hasFrontMatter) { const errorMessage = `Docusaurus MDX partial files should not contain FrontMatter. Those partial files use the _ prefix as a convention by default, but this is configurable. @@ -158,26 +151,46 @@ ${JSON.stringify(frontMatter, null, 2)}`; } } - if (!isMDXPartial) { - // Read metadata for this MDX and export it. - if (options.metadataPath && typeof options.metadataPath === 'function') { - const metadataPath = options.metadataPath(filePath); - - if (metadataPath) { - const metadata = await readMetadataPath(metadataPath); - exportStr += `\nexport const metadata = ${metadata};`; - // Add as dependency of this loader result so that we can - // recompile if metadata is changed. - this.addDependency(metadataPath); + function getMetadataPath(): string | undefined { + if (!isMDXPartial) { + // Read metadata for this MDX and export it. + if (options.metadataPath && typeof options.metadataPath === 'function') { + return options.metadataPath(filePath); } } + return undefined; } + const metadataPath = getMetadataPath(); + if (metadataPath) { + this.addDependency(metadataPath); + } + + const metadataJsonString = metadataPath + ? await readMetadataPath(metadataPath) + : undefined; + + const metadata = metadataJsonString + ? JSON.parse(metadataJsonString) + : undefined; + + const assets = + reqOptions.createAssets && metadata + ? reqOptions.createAssets({frontMatter, metadata}) + : undefined; + + const exportsCode = ` +export const frontMatter = ${stringifyObject(frontMatter)}; +export const contentTitle = ${stringifyObject(contentTitle)}; +${metadataJsonString ? `export const metadata = ${metadataJsonString};` : ''} +${assets ? `export const assets = ${createAssetsExportCode(assets)};` : ''} +`; + const code = ` import React from 'react'; import { mdx } from '@mdx-js/react'; -${exportStr} +${exportsCode} ${result} `; diff --git a/packages/docusaurus-plugin-content-blog/index.d.ts b/packages/docusaurus-plugin-content-blog/index.d.ts index 5fa42268b5..e2e5d15c02 100644 --- a/packages/docusaurus-plugin-content-blog/index.d.ts +++ b/packages/docusaurus-plugin-content-blog/index.d.ts @@ -21,33 +21,10 @@ declare module '@theme/BlogSidebar' { } declare module '@theme/BlogPostPage' { - import type {FrontMatterTag} from '@docusaurus/utils'; import type {BlogSidebar} from '@theme/BlogSidebar'; - export type FrontMatter = { - /* eslint-disable camelcase */ - readonly title: string; - readonly author?: string; - readonly image?: string; - readonly tags?: readonly FrontMatterTag[]; - readonly keywords?: readonly string[]; - readonly author_url?: string; - readonly authorURL?: string; - readonly author_title?: string; - readonly authorTitle?: string; - readonly author_image_url?: string; - readonly authorImageURL?: string; - readonly hide_table_of_contents?: boolean; - /* eslint-enable camelcase */ - }; - - export type FrontMatterAssets = { - /* eslint-disable camelcase */ - readonly image?: string; - readonly author_image_url?: string; - readonly authorImageURL?: string; - /* eslint-enable camelcase */ - }; + export type FrontMatter = import('./src/blogFrontMatter').BlogPostFrontMatter; + export type Assets = import('./src/types').Assets; export type Metadata = { readonly title: string; @@ -60,6 +37,7 @@ declare module '@theme/BlogPostPage' { readonly truncated?: string; readonly nextItem?: {readonly title: string; readonly permalink: string}; readonly prevItem?: {readonly title: string; readonly permalink: string}; + readonly authors: import('./src/types').Author[]; readonly tags: readonly { readonly label: string; readonly permalink: string; @@ -68,7 +46,7 @@ declare module '@theme/BlogPostPage' { export type Content = { readonly frontMatter: FrontMatter; - readonly frontMatterAssets: FrontMatterAssets; + readonly assets: Assets; readonly metadata: Metadata; readonly toc: readonly TOCItem[]; (): JSX.Element; diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 417db325cb..c367508105 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -28,6 +28,7 @@ "feed": "^4.2.2", "fs-extra": "^10.0.0", "globby": "^11.0.2", + "js-yaml": "^4.0.0", "loader-utils": "^2.0.0", "lodash": "^4.17.20", "reading-time": "^1.3.0", diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.json new file mode 100644 index 0000000000..1cca9c9f0a --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.json @@ -0,0 +1,29 @@ +{ + "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/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml new file mode 100644 index 0000000000..5bce126cef --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml @@ -0,0 +1,27 @@ + +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/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json new file mode 100644 index 0000000000..bd2c8659fc --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json @@ -0,0 +1,5 @@ +{ + "slorber": { + "title": "Docusaurus maintainer" + } +} diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml new file mode 100644 index 0000000000..edd8e7ce7c --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml @@ -0,0 +1,3 @@ + +slorber: + title: Docusaurus maintainer diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json new file mode 100644 index 0000000000..40128533eb --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json @@ -0,0 +1,3 @@ +{ + "name": "Sébastien Lorber" +} diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml new file mode 100644 index 0000000000..b0a0c84088 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml @@ -0,0 +1,2 @@ + +name: Sébastien Lorber diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json new file mode 100644 index 0000000000..60f1312989 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json @@ -0,0 +1,8 @@ +[ + { + "name": "Sébastien Lorber" + }, + { + "name": "Joel Marcey" + } +] diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml new file mode 100644 index 0000000000..15d2d9a2ec --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml @@ -0,0 +1,3 @@ + +- name: Sébastien Lorber +- name: Joel Marcey diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathEmpty/empty b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathEmpty/empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson1/authors.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson1/authors.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson2/authors.json b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson2/authors.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathNestedYml/sub/folder/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathNestedYml/sub/folder/authors.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml1/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml1/authors.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml2/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml2/authors.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md index a66bb945bf..5a8f32cea1 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md @@ -1,5 +1,8 @@ --- title: Happy 1st Birthday Slash! +authors: + - name: Yangshun Tay + - slorber --- Happy birthday! diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/authors.yml new file mode 100644 index 0000000000..cb6c296b21 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/authors.yml @@ -0,0 +1,4 @@ + +slorber: + name: Sébastien Lorber + title: Docusaurus maintainer diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/simple-slug.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/simple-slug.md index 9bee9390a9..7bea4b3849 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/simple-slug.md +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/simple-slug.md @@ -2,6 +2,10 @@ slug: /simple/slug title: Simple Slug date: 2020-08-15 + +author: Sébastien Lorber +author_title: Docusaurus maintainer +author_url: https://sebastienlorber.com --- simple url slug diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md index 0f8fcd88e8..b015e77fb5 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md @@ -1,5 +1,8 @@ --- title: Happy 1st Birthday Slash! (translated) +authors: + - name: Yangshun Tay (translated) + - slorber --- Happy birthday! (translated) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml new file mode 100644 index 0000000000..f42af6257f --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml @@ -0,0 +1,5 @@ + + +slorber: + name: Sébastien Lorber (translated) + title: Docusaurus maintainer (translated) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap index 8d4ac07201..2d3b7db474 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap @@ -26,6 +26,10 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` 2020-08-15T00:00:00.000Z + + Sébastien Lorber + https://sebastienlorber.com + <![CDATA[draft]]> @@ -53,6 +57,12 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` 2018-12-14T00:00:00.000Z + + Yangshun Tay (translated) + + + Sébastien Lorber (translated) + " `; diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts new file mode 100644 index 0000000000..3275b57244 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -0,0 +1,608 @@ +/** + * 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 { + AuthorsMap, + getAuthorsMapFilePath, + validateAuthorsMapFile, + readAuthorsMapFile, + getAuthorsMap, + getBlogPostAuthors, +} from '../authors'; +import path from 'path'; + +describe('getBlogPostAuthors', () => { + test('can read no authors', () => { + expect( + getBlogPostAuthors({ + frontMatter: {}, + authorsMap: undefined, + }), + ).toEqual([]); + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [], + }, + authorsMap: undefined, + }), + ).toEqual([]); + }); + + test('can read author from legacy frontmatter', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + author: 'Sébastien Lorber', + }, + authorsMap: undefined, + }), + ).toEqual([{name: 'Sébastien Lorber'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + authorTitle: 'maintainer', + }, + authorsMap: undefined, + }), + ).toEqual([{title: 'maintainer'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + authorImageURL: 'https://github.com/slorber.png', + }, + authorsMap: undefined, + }), + ).toEqual([{imageURL: 'https://github.com/slorber.png'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + author: 'Sébastien Lorber', + author_title: 'maintainer1', + authorTitle: 'maintainer2', + author_image_url: 'https://github.com/slorber1.png', + authorImageURL: 'https://github.com/slorber2.png', + author_url: 'https://github.com/slorber1', + authorURL: 'https://github.com/slorber2', + }, + authorsMap: undefined, + }), + ).toEqual([ + { + name: 'Sébastien Lorber', + title: 'maintainer1', + imageURL: 'https://github.com/slorber1.png', + url: 'https://github.com/slorber1', + }, + ]); + }); + + test('can read authors string', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: {slorber: {name: 'Sébastien Lorber'}}, + }), + ).toEqual([{key: 'slorber', name: 'Sébastien Lorber'}]); + }); + + test('can read authors string[]', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: ['slorber', 'yangshun'], + }, + authorsMap: { + slorber: {name: 'Sébastien Lorber', title: 'maintainer'}, + yangshun: {name: 'Yangshun Tay'}, + }, + }), + ).toEqual([ + {key: 'slorber', name: 'Sébastien Lorber', title: 'maintainer'}, + {key: 'yangshun', name: 'Yangshun Tay'}, + ]); + }); + + test('can read authors Author', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: {name: 'Sébastien Lorber', title: 'maintainer'}, + }, + authorsMap: undefined, + }), + ).toEqual([{name: 'Sébastien Lorber', title: 'maintainer'}]); + }); + + test('can read authors Author[]', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [ + {name: 'Sébastien Lorber', title: 'maintainer'}, + {name: 'Yangshun Tay'}, + ], + }, + authorsMap: undefined, + }), + ).toEqual([ + {name: 'Sébastien Lorber', title: 'maintainer'}, + {name: 'Yangshun Tay'}, + ]); + }); + + test('can read authors complex (string | Author)[] setup with keys and local overrides', () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [ + 'slorber', + { + key: 'yangshun', + title: 'Yangshun title local override', + extra: 42, + }, + {name: 'Alexey'}, + ], + }, + authorsMap: { + slorber: {name: 'Sébastien Lorber', title: 'maintainer'}, + yangshun: {name: 'Yangshun Tay', title: 'Yangshun title original'}, + }, + }), + ).toEqual([ + {key: 'slorber', name: 'Sébastien Lorber', title: 'maintainer'}, + { + key: 'yangshun', + name: 'Yangshun Tay', + title: 'Yangshun title local override', + extra: 42, + }, + {name: 'Alexey'}, + ]); + }); + + test('throw when using author key with no authorsMap', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: undefined, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "Can't reference blog post authors by a key (such as 'slorber') because no authors map file could be loaded. + Please double-check your blog plugin config (in particular 'authorsMapPath'), ensure the file exists at the configured path, is not empty, and is valid!" + `); + }); + + test('throw when using author key with empty authorsMap', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: {}, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "Can't reference blog post authors by a key (such as 'slorber') because no authors map file could be loaded. + Please double-check your blog plugin config (in particular 'authorsMapPath'), ensure the file exists at the configured path, is not empty, and is valid!" + `); + }); + + test('throw when using bad author key in string', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: { + yangshun: {name: 'Yangshun Tay'}, + jmarcey: {name: 'Joel Marcey'}, + }, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "Blog author with key \\"slorber\\" not found in the authors map file. + Valid author keys are: + - yangshun + - jmarcey" + `); + }); + + test('throw when using bad author key in string[]', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: ['yangshun', 'jmarcey', 'slorber'], + }, + authorsMap: { + yangshun: {name: 'Yangshun Tay'}, + jmarcey: {name: 'Joel Marcey'}, + }, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "Blog author with key \\"slorber\\" not found in the authors map file. + Valid author keys are: + - yangshun + - jmarcey" + `); + }); + + test('throw when using bad author key in Author[].key', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: [{key: 'yangshun'}, {key: 'jmarcey'}, {key: 'slorber'}], + }, + authorsMap: { + yangshun: {name: 'Yangshun Tay'}, + jmarcey: {name: 'Joel Marcey'}, + }, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "Blog author with key \\"slorber\\" not found in the authors map file. + Valid author keys are: + - yangshun + - jmarcey" + `); + }); + + test('throw when mixing legacy/new authors frontmatter', () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: [{name: 'Sébastien Lorber'}], + author: 'Yangshun Tay', + }, + authorsMap: undefined, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "To declare blog post authors, use the 'authors' FrontMatter in priority. + Don't mix 'authors' with other existing 'author_*' FrontMatter. Choose one or the other, not both at the same time." + `); + + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: [{key: 'slorber'}], + author_title: 'legacy title', + }, + authorsMap: {slorber: {name: 'Sébastien Lorber'}}, + }), + ).toThrowErrorMatchingInlineSnapshot(` + "To declare blog post authors, use the 'authors' FrontMatter in priority. + Don't mix 'authors' with other existing 'author_*' FrontMatter. Choose one or the other, not both at the same time." + `); + }); +}); + +describe('readAuthorsMapFile', () => { + const fixturesDir = path.join(__dirname, '__fixtures__/authorsMapFiles'); + + test('read valid yml author file', async () => { + const filePath = path.join(fixturesDir, 'authors.yml'); + expect(await readAuthorsMapFile(filePath)).toBeDefined(); + }); + + test('read valid json author file', async () => { + const filePath = path.join(fixturesDir, 'authors.json'); + expect(await readAuthorsMapFile(filePath)).toBeDefined(); + }); + + test('read yml and json should lead to the same result', async () => { + const content1 = await readAuthorsMapFile( + path.join(fixturesDir, 'authors.yml'), + ); + const content2 = await readAuthorsMapFile( + path.join(fixturesDir, 'authors.json'), + ); + expect(content1).toEqual(content2); + }); + + test('fail to read invalid yml 1', async () => { + const filePath = path.join(fixturesDir, 'authorsBad1.yml'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"slorber.name\\" is required"`, + ); + }); + test('fail to read invalid json 1', async () => { + const filePath = path.join(fixturesDir, 'authorsBad1.json'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"slorber.name\\" is required"`, + ); + }); + + test('fail to read invalid yml 2', async () => { + const filePath = path.join(fixturesDir, 'authorsBad2.yml'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"name\\" must be of type object"`, + ); + }); + test('fail to read invalid json 2', async () => { + const filePath = path.join(fixturesDir, 'authorsBad2.json'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"name\\" must be of type object"`, + ); + }); + + test('fail to read invalid yml 3', async () => { + const filePath = path.join(fixturesDir, 'authorsBad3.yml'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"value\\" must be of type object"`, + ); + }); + test('fail to read invalid json 3', async () => { + const filePath = path.join(fixturesDir, 'authorsBad3.json'); + await expect( + readAuthorsMapFile(filePath), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"value\\" must be of type object"`, + ); + }); +}); +describe('getAuthorsMap', () => { + const fixturesDir = path.join(__dirname, '__fixtures__/authorsMapFiles'); + const contentPaths = { + contentPathLocalized: fixturesDir, + contentPath: fixturesDir, + }; + + test('getAuthorsMap can read yml file', async () => { + expect( + await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + }), + ).toBeDefined(); + }); + + test('getAuthorsMap can read json file', async () => { + expect( + await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.json', + }), + ).toBeDefined(); + }); + + test('getAuthorsMap can return undefined if yaml file not found', async () => { + expect( + await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors_does_not_exist.yml', + }), + ).toBeUndefined(); + }); +}); + +describe('validateAuthorsMapFile', () => { + test('accept valid authors map', () => { + const authorsMap: AuthorsMap = { + slorber: { + name: 'Sébastien Lorber', + title: 'maintainer', + url: 'https://sebastienlorber.com', + imageURL: 'https://github.com/slorber.png', + }, + yangshun: { + name: 'Yangshun Tay', + imageURL: 'https://github.com/yangshun.png', + randomField: 42, + }, + jmarcey: { + name: 'Joel', + title: 'creator of Docusaurus', + hello: new Date(), + }, + }; + expect(validateAuthorsMapFile(authorsMap)).toEqual(authorsMap); + }); + + test('rename snake case image_url to camelCase imageURL', () => { + const authorsMap: AuthorsMap = { + slorber: { + name: 'Sébastien Lorber', + image_url: 'https://github.com/slorber.png', + }, + }; + expect(validateAuthorsMapFile(authorsMap)).toEqual({ + slorber: { + name: 'Sébastien Lorber', + imageURL: 'https://github.com/slorber.png', + }, + }); + }); + + test('reject author without name', () => { + const authorsMap: AuthorsMap = { + slorber: { + image_url: 'https://github.com/slorber.png', + }, + }; + expect(() => + validateAuthorsMapFile(authorsMap), + ).toThrowErrorMatchingInlineSnapshot(`"\\"slorber.name\\" is required"`); + }); + + test('reject undefined author', () => { + expect(() => + validateAuthorsMapFile({ + slorber: undefined, + }), + ).toThrowErrorMatchingInlineSnapshot(`"\\"slorber\\" is required"`); + }); + + test('reject null author', () => { + expect(() => + validateAuthorsMapFile({ + slorber: null, + }), + ).toThrowErrorMatchingInlineSnapshot( + `"\\"slorber\\" must be of type object"`, + ); + }); + + test('reject array author', () => { + expect(() => + validateAuthorsMapFile({slorber: []}), + ).toThrowErrorMatchingInlineSnapshot( + `"\\"slorber\\" must be of type object"`, + ); + }); + + test('reject array content', () => { + expect(() => validateAuthorsMapFile([])).toThrowErrorMatchingInlineSnapshot( + // TODO improve this error message + `"\\"value\\" must be of type object"`, + ); + }); + + test('reject flat author', () => { + expect(() => + validateAuthorsMapFile({name: 'Sébastien'}), + ).toThrowErrorMatchingInlineSnapshot( + // TODO improve this error message + `"\\"name\\" must be of type object"`, + ); + }); + + test('reject non-map author', () => { + const authorsMap: AuthorsMap = { + // @ts-expect-error: for tests + slorber: [], + }; + expect(() => + validateAuthorsMapFile(authorsMap), + ).toThrowErrorMatchingInlineSnapshot( + `"\\"slorber\\" must be of type object"`, + ); + }); +}); + +describe('getAuthorsMapFilePath', () => { + const fixturesDir = path.join( + __dirname, + '__fixtures__/getAuthorsMapFilePath', + ); + const contentPathYml1 = path.join(fixturesDir, 'contentPathYml1'); + const contentPathYml2 = path.join(fixturesDir, 'contentPathYml2'); + const contentPathJson1 = path.join(fixturesDir, 'contentPathJson1'); + const contentPathJson2 = path.join(fixturesDir, 'contentPathJson2'); + const contentPathEmpty = path.join(fixturesDir, 'contentPathEmpty'); + const contentPathNestedYml = path.join(fixturesDir, 'contentPathNestedYml'); + + test('getAuthorsMapFilePath returns localized Yml path in priority', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.yml', + contentPaths: { + contentPathLocalized: contentPathYml1, + contentPath: contentPathYml2, + }, + }), + ).toEqual(path.join(contentPathYml1, 'authors.yml')); + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.yml', + contentPaths: { + contentPathLocalized: contentPathYml2, + contentPath: contentPathYml1, + }, + }), + ).toEqual(path.join(contentPathYml2, 'authors.yml')); + }); + + test('getAuthorsMapFilePath returns localized Json path in priority', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.json', + contentPaths: { + contentPathLocalized: contentPathJson1, + contentPath: contentPathJson2, + }, + }), + ).toEqual(path.join(contentPathJson1, 'authors.json')); + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.json', + contentPaths: { + contentPathLocalized: contentPathJson2, + contentPath: contentPathJson1, + }, + }), + ).toEqual(path.join(contentPathJson2, 'authors.json')); + }); + + test('getAuthorsMapFilePath returns unlocalized Yml path as fallback', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.yml', + contentPaths: { + contentPathLocalized: contentPathEmpty, + contentPath: contentPathYml2, + }, + }), + ).toEqual(path.join(contentPathYml2, 'authors.yml')); + }); + + test('getAuthorsMapFilePath returns unlocalized Json path as fallback', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.json', + contentPaths: { + contentPathLocalized: contentPathEmpty, + contentPath: contentPathJson1, + }, + }), + ).toEqual(path.join(contentPathJson1, 'authors.json')); + }); + + test('getAuthorsMapFilePath can return undefined (file not found)', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.json', + contentPaths: { + contentPathLocalized: contentPathEmpty, + contentPath: contentPathYml1, + }, + }), + ).toBeUndefined(); + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'authors.yml', + contentPaths: { + contentPathLocalized: contentPathEmpty, + contentPath: contentPathJson1, + }, + }), + ).toBeUndefined(); + }); + + test('getAuthorsMapFilePath can return nested path', async () => { + expect( + await getAuthorsMapFilePath({ + authorsMapPath: 'sub/folder/authors.yml', + contentPaths: { + contentPathLocalized: contentPathEmpty, + contentPath: contentPathNestedYml, + }, + }), + ).toEqual(path.join(contentPathNestedYml, 'sub/folder/authors.yml')); + }); +}); diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/blogFrontMatter.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/blogFrontMatter.test.ts index 86afc79f94..eca414be39 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/blogFrontMatter.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/blogFrontMatter.test.ts @@ -11,6 +11,8 @@ import { } from '../blogFrontMatter'; import escapeStringRegexp from 'escape-string-regexp'; +// TODO this abstraction reduce verbosity but it makes it harder to debug +// It would be preferable to just expose helper methods function testField(params: { fieldName: keyof BlogPostFrontMatter; validFrontMatters: BlogPostFrontMatter[]; @@ -99,7 +101,30 @@ describe('validateBlogPostFrontMatter id', () => { testField({ fieldName: 'id', validFrontMatters: [{id: '123'}, {id: 'id'}], - invalidFrontMatters: [[{id: ''}, 'is not allowed to be empty']], + invalidFrontMatters: [[{id: ''}, 'not allowed to be empty']], + }); +}); + +describe('validateBlogPostFrontMatter handles legacy/new author frontmatter', () => { + test('allow legacy author frontmatter', () => { + const frontMatter: BlogPostFrontMatter = { + author: 'Sebastien', + author_url: 'https://sebastienlorber.com', + author_title: 'maintainer', + author_image_url: 'https://github.com/slorber.png', + }; + expect(validateBlogPostFrontMatter(frontMatter)).toEqual(frontMatter); + }); + + test('allow new authors frontmatter', () => { + const frontMatter: BlogPostFrontMatter = { + authors: [ + 'slorber', + {name: 'Yangshun'}, + {key: 'JMarcey', title: 'creator', random: '42'}, + ], + }; + expect(validateBlogPostFrontMatter(frontMatter)).toEqual(frontMatter); }); }); @@ -107,21 +132,24 @@ describe('validateBlogPostFrontMatter author', () => { testField({ fieldName: 'author', validFrontMatters: [{author: '123'}, {author: 'author'}], - invalidFrontMatters: [[{author: ''}, 'is not allowed to be empty']], + invalidFrontMatters: [[{author: ''}, 'not allowed to be empty']], }); }); describe('validateBlogPostFrontMatter author_title', () => { testField({ fieldName: 'author_title', - validFrontMatters: [{author_title: '123'}, {author_title: 'author_title'}], - invalidFrontMatters: [[{author_title: ''}, 'is not allowed to be empty']], + validFrontMatters: [ + {author: '123', author_title: '123'}, + {author: '123', author_title: 'author_title'}, + ], + invalidFrontMatters: [[{author_title: ''}, 'not allowed to be empty']], }); testField({ fieldName: 'authorTitle', validFrontMatters: [{authorTitle: '123'}, {authorTitle: 'authorTitle'}], - invalidFrontMatters: [[{authorTitle: ''}, 'is not allowed to be empty']], + invalidFrontMatters: [[{authorTitle: ''}, 'not allowed to be empty']], }); }); @@ -136,7 +164,7 @@ describe('validateBlogPostFrontMatter author_url', () => { invalidFrontMatters: [ [ {author_url: ''}, - '"author_url" does not match any of the allowed types', + '"author_url" does not look like a valid url (value=\'\')', ], ], }); @@ -150,7 +178,10 @@ describe('validateBlogPostFrontMatter author_url', () => { ], invalidFrontMatters: [ - [{authorURL: ''}, '"authorURL" does not match any of the allowed types'], + [ + {authorURL: ''}, + '"authorURL" does not look like a valid url (value=\'\')', + ], ], }); }); @@ -166,7 +197,7 @@ describe('validateBlogPostFrontMatter author_image_url', () => { invalidFrontMatters: [ [ {author_image_url: ''}, - '"author_image_url" does not match any of the allowed types', + '"author_image_url" does not look like a valid url (value=\'\')', ], ], }); @@ -181,7 +212,55 @@ describe('validateBlogPostFrontMatter author_image_url', () => { invalidFrontMatters: [ [ {authorImageURL: ''}, - '"authorImageURL" does not match any of the allowed types', + '"authorImageURL" does not look like a valid url (value=\'\')', + ], + ], + }); +}); + +describe('validateBlogPostFrontMatter authors', () => { + testField({ + fieldName: 'author', + validFrontMatters: [ + {authors: []}, + {authors: 'authorKey'}, + {authors: ['authorKey1', 'authorKey2']}, + { + authors: { + name: 'Author Name', + imageURL: '/absolute', + }, + }, + { + authors: { + key: 'authorKey', + title: 'Author title', + }, + }, + { + authors: [ + 'authorKey1', + {key: 'authorKey3'}, + 'authorKey3', + {name: 'Author Name 4'}, + {key: 'authorKey5'}, + ], + }, + ], + + invalidFrontMatters: [ + [{authors: ''}, '"authors" is not allowed to be empty'], + [ + {authors: [undefined]}, + '"authors[0]" does not look like a valid blog post author. Please use an author key or an author object (with a key and/or name).', + ], + [ + {authors: [null]}, + '"authors[0]" does not look like a valid blog post author. Please use an author key or an author object (with a key and/or name).', + ], + [ + {authors: [{}]}, + '"authors[0]" does not look like a valid blog post author. Please use an author key or an author object (with a key and/or name).', ], ], }); @@ -200,7 +279,7 @@ describe('validateBlogPostFrontMatter slug', () => { {slug: '/api/plugins/@docusaurus/plugin-debug'}, {slug: '@site/api/asset/image.png'}, ], - invalidFrontMatters: [[{slug: ''}, 'is not allowed to be empty']], + invalidFrontMatters: [[{slug: ''}, 'not allowed to be empty']], }); }); @@ -219,7 +298,7 @@ describe('validateBlogPostFrontMatter image', () => { {image: '@site/api/asset/image.png'}, ], invalidFrontMatters: [ - [{image: ''}, '"image" does not match any of the allowed types'], + [{image: ''}, '"image" does not look like a valid url (value=\'\')'], ], }); }); @@ -236,7 +315,7 @@ describe('validateBlogPostFrontMatter tags', () => { ], invalidFrontMatters: [ [{tags: ''}, 'must be an array'], - [{tags: ['']}, 'is not allowed to be empty'], + [{tags: ['']}, 'not allowed to be empty'], ], // See https://github.com/facebook/docusaurus/issues/4642 convertibleFrontMatter: [ @@ -260,7 +339,7 @@ describe('validateBlogPostFrontMatter keywords', () => { ], invalidFrontMatters: [ [{keywords: ''}, 'must be an array'], - [{keywords: ['']}, 'is not allowed to be empty'], + [{keywords: ['']}, 'not allowed to be empty'], [{keywords: []}, 'does not contain 1 required value(s)'], ], }); @@ -304,9 +383,7 @@ describe('validateBlogPostFrontMatter date', () => { fieldName: 'date', validFrontMatters: [ {date: new Date('2020-01-01')}, - // @ts-expect-error: string for test {date: '2020-01-01'}, - // @ts-expect-error: string for test {date: '2020'}, ], invalidFrontMatters: [ diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts index a99b9c33aa..c21974fd1d 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts @@ -52,6 +52,7 @@ describe('blogFeed', () => { { path: 'invalid-blog-path', routeBasePath: 'blog', + authorsMapPath: 'authors.yml', include: ['*.md', '*.mdx'], feedOptions: { type: [feedType], @@ -85,6 +86,7 @@ describe('blogFeed', () => { { path: 'blog', routeBasePath: 'blog', + authorsMapPath: 'authors.yml', include: DEFAULT_OPTIONS.include, exclude: DEFAULT_OPTIONS.exclude, feedOptions: { 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 898efa421b..eee9cf72c3 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -14,6 +14,7 @@ import {DocusaurusConfig, LoadContext, I18n} from '@docusaurus/types'; import {PluginOptionSchema} from '../pluginOptionSchema'; import {PluginOptions, EditUrlFunction, BlogPost} from '../types'; import {Joi} from '@docusaurus/utils-validation'; +import {posixPath} from '@docusaurus/utils'; function findByTitle( blogPosts: BlogPost[], @@ -60,7 +61,7 @@ describe('loadBlog', () => { const BaseEditUrl = 'https://baseEditUrl.com/edit'; - const getBlogPosts = async ( + const getPlugin = async ( siteDir: string, pluginOptions: Partial = {}, i18n: I18n = DefaultI18N, @@ -71,7 +72,7 @@ describe('loadBlog', () => { baseUrl: '/', url: 'https://docusaurus.io', } as DocusaurusConfig; - const plugin = pluginContentBlog( + return pluginContentBlog( { siteDir, siteConfig, @@ -84,11 +85,32 @@ describe('loadBlog', () => { ...pluginOptions, }), ); - const {blogPosts} = (await plugin.loadContent!())!; + }; + const getBlogPosts = async ( + siteDir: string, + pluginOptions: Partial = {}, + i18n: I18n = DefaultI18N, + ) => { + const plugin = await getPlugin(siteDir, pluginOptions, i18n); + const {blogPosts} = (await plugin.loadContent!())!; return blogPosts; }; + test('getPathsToWatch', async () => { + const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const plugin = await getPlugin(siteDir); + const pathsToWatch = plugin.getPathsToWatch!(); + const relativePathsToWatch = pathsToWatch.map((p) => + posixPath(path.relative(siteDir, p)), + ); + expect(relativePathsToWatch).toEqual([ + 'blog/authors.yml', + 'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}', + 'blog/**/*.{md,mdx}', + ]); + }); + test('simple website', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); const blogPosts = await getBlogPosts(siteDir); @@ -103,6 +125,7 @@ describe('loadBlog', () => { source: path.posix.join('@site', PluginPath, 'date-matter.md'), title: 'date-matter', description: `date inside front matter`, + authors: [], date: new Date('2019-01-01'), formattedDate: 'January 1, 2019', prevItem: undefined, @@ -128,6 +151,16 @@ describe('loadBlog', () => { ), title: 'Happy 1st Birthday Slash! (translated)', description: `Happy birthday! (translated)`, + authors: [ + { + name: 'Yangshun Tay (translated)', + }, + { + key: 'slorber', + name: 'Sébastien Lorber (translated)', + title: 'Docusaurus maintainer (translated)', + }, + ], date: new Date('2018-12-14'), formattedDate: 'December 14, 2018', tags: [], @@ -148,6 +181,7 @@ describe('loadBlog', () => { source: path.posix.join('@site', PluginPath, 'complex-slug.md'), title: 'Complex Slug', description: `complex url slug`, + authors: [], prevItem: undefined, nextItem: { permalink: '/blog/simple/slug', @@ -169,6 +203,14 @@ describe('loadBlog', () => { source: path.posix.join('@site', PluginPath, 'simple-slug.md'), title: 'Simple Slug', description: `simple url slug`, + authors: [ + { + name: 'Sébastien Lorber', + title: 'Docusaurus maintainer', + url: 'https://sebastienlorber.com', + imageURL: undefined, + }, + ], prevItem: undefined, nextItem: { permalink: '/blog/draft', @@ -190,6 +232,7 @@ describe('loadBlog', () => { source: path.posix.join('@site', PluginPath, 'heading-as-title.md'), title: 'some heading', description: '', + authors: [], date: new Date('2019-01-02'), formattedDate: 'January 2, 2019', prevItem: undefined, @@ -325,6 +368,7 @@ describe('loadBlog', () => { source: noDateSource, title: 'no date', description: `no date`, + authors: [], date: noDateSourceBirthTime, formattedDate, tags: [], diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts new file mode 100644 index 0000000000..3bca2ebef3 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -0,0 +1,202 @@ +/** + * 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 fs from 'fs-extra'; +import chalk from 'chalk'; +import path from 'path'; +import {Author, BlogContentPaths} from './types'; +import {findFolderContainingFile} from '@docusaurus/utils'; +import {Joi, URISchema} from '@docusaurus/utils-validation'; +import { + BlogPostFrontMatter, + BlogPostFrontMatterAuthor, + BlogPostFrontMatterAuthors, +} from './blogFrontMatter'; +import {getContentPathList} from './blogUtils'; +import Yaml from 'js-yaml'; + +export type AuthorsMap = Record; + +const AuthorsMapSchema = Joi.object().pattern( + Joi.string(), + Joi.object({ + name: Joi.string().required(), + url: URISchema, + imageURL: URISchema, + title: Joi.string(), + }) + .rename('image_url', 'imageURL') + .unknown() + .required(), +); + +export function validateAuthorsMapFile(content: unknown): AuthorsMap { + return Joi.attempt(content, AuthorsMapSchema); +} + +export async function readAuthorsMapFile( + filePath: string, +): Promise { + if (await fs.pathExists(filePath)) { + const contentString = await fs.readFile(filePath, {encoding: 'utf8'}); + const parse = + filePath.endsWith('.yml') || filePath.endsWith('.yaml') + ? Yaml.load + : JSON.parse; + try { + const unsafeContent = parse(contentString); + return validateAuthorsMapFile(unsafeContent); + } catch (e) { + // TODO replace later by error cause: see https://v8.dev/features/error-cause + console.error(chalk.red('The author list file looks invalid!')); + throw e; + } + } + return undefined; +} + +type AuthorsMapParams = { + authorsMapPath: string; + contentPaths: BlogContentPaths; +}; + +export async function getAuthorsMapFilePath({ + authorsMapPath, + contentPaths, +}: AuthorsMapParams): Promise { + // Useful to load an eventually localize authors map + const contentPath = await findFolderContainingFile( + getContentPathList(contentPaths), + authorsMapPath, + ); + + if (contentPath) { + return path.join(contentPath, authorsMapPath); + } + + return undefined; +} + +export async function getAuthorsMap( + params: AuthorsMapParams, +): Promise { + const filePath = await getAuthorsMapFilePath(params); + if (!filePath) { + return undefined; + } + try { + return await readAuthorsMapFile(filePath); + } catch (e) { + // TODO replace later by error cause, see https://v8.dev/features/error-cause + console.error( + chalk.red(`Couldn't read blog authors map at path ${filePath}`), + ); + throw e; + } +} + +type AuthorsParam = { + frontMatter: BlogPostFrontMatter; + authorsMap: AuthorsMap | undefined; +}; + +// Legacy v1/early-v2 frontmatter fields +// We may want to deprecate those in favor of using only frontMatter.authors +function getFrontMatterAuthorLegacy( + frontMatter: BlogPostFrontMatter, +): BlogPostFrontMatterAuthor | undefined { + const name = frontMatter.author; + const title = frontMatter.author_title ?? frontMatter.authorTitle; + const url = frontMatter.author_url ?? frontMatter.authorURL; + const imageURL = frontMatter.author_image_url ?? frontMatter.authorImageURL; + + // Shouldn't we require at least an author name? + if (name || title || url || imageURL) { + return { + name, + title, + url, + imageURL, + }; + } + + return undefined; +} + +function normalizeFrontMatterAuthors( + frontMatterAuthors: BlogPostFrontMatterAuthors = [], +): BlogPostFrontMatterAuthor[] { + function normalizeAuthor( + authorInput: string | BlogPostFrontMatterAuthor, + ): BlogPostFrontMatterAuthor { + if (typeof authorInput === 'string') { + // Technically, we could allow users to provide an author's name here + // IMHO it's better to only support keys here + // Reason: a typo in a key would fallback to becoming a name and may end-up un-noticed + return {key: authorInput}; + } + return authorInput; + } + + return Array.isArray(frontMatterAuthors) + ? frontMatterAuthors.map(normalizeAuthor) + : [normalizeAuthor(frontMatterAuthors)]; +} + +function getFrontMatterAuthors(params: AuthorsParam): Author[] { + const {authorsMap} = params; + const frontMatterAuthors = normalizeFrontMatterAuthors( + params.frontMatter.authors, + ); + + function getAuthorsMapAuthor(key: string | undefined): Author | undefined { + if (key) { + if (!authorsMap || Object.keys(authorsMap).length === 0) { + throw new Error(`Can't reference blog post authors by a key (such as '${key}') because no authors map file could be loaded. +Please double-check your blog plugin config (in particular 'authorsMapPath'), ensure the file exists at the configured path, is not empty, and is valid!`); + } + const author = authorsMap[key]; + if (!author) { + throw Error(`Blog author with key "${key}" not found in the authors map file. +Valid author keys are: +${Object.keys(authorsMap) + .map((validKey) => `- ${validKey}`) + .join('\n')}`); + } + return author; + } + return undefined; + } + + function toAuthor(frontMatterAuthor: BlogPostFrontMatterAuthor): Author { + return { + // Author def from authorsMap can be locally overridden by frontmatter + ...getAuthorsMapAuthor(frontMatterAuthor.key), + ...frontMatterAuthor, + }; + } + + return frontMatterAuthors.map(toAuthor); +} + +export function getBlogPostAuthors(params: AuthorsParam): Author[] { + const authorLegacy = getFrontMatterAuthorLegacy(params.frontMatter); + const authors = getFrontMatterAuthors(params); + + if (authorLegacy) { + // Technically, we could allow mixing legacy/authors frontmatter, but do we really want to? + if (authors.length > 0) { + throw new Error( + `To declare blog post authors, use the 'authors' FrontMatter in priority. +Don't mix 'authors' with other existing 'author_*' FrontMatter. Choose one or the other, not both at the same time.`, + ); + } + return [authorLegacy]; + } + + return authors; +} diff --git a/packages/docusaurus-plugin-content-blog/src/blogFrontMatter.ts b/packages/docusaurus-plugin-content-blog/src/blogFrontMatter.ts index 4d0787d055..0ea91930a0 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogFrontMatter.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogFrontMatter.ts @@ -13,6 +13,30 @@ import { } from '@docusaurus/utils-validation'; import type {FrontMatterTag} from '@docusaurus/utils'; +export type BlogPostFrontMatterAuthor = Record & { + key?: string; + name?: string; + imageURL?: string; + url?: string; + title?: string; +}; + +// All the possible variants that the user can use for convenience +export type BlogPostFrontMatterAuthors = + | string + | BlogPostFrontMatterAuthor + | (string | BlogPostFrontMatterAuthor)[]; + +const BlogPostFrontMatterAuthorSchema = Joi.object({ + key: Joi.string(), + name: Joi.string(), + title: Joi.string(), + url: URISchema, + imageURL: Joi.string(), +}) + .or('key', 'name') + .rename('image_url', 'imageURL', {alias: true}); + export type BlogPostFrontMatter = { /* eslint-disable camelcase */ id?: string; @@ -23,22 +47,30 @@ export type BlogPostFrontMatter = { draft?: boolean; date?: Date | string; // Yaml automagically convert some string patterns as Date, but not all + authors?: BlogPostFrontMatterAuthors; + + // We may want to deprecate those older author frontmatter fields later: author?: string; author_title?: string; author_url?: string; author_image_url?: string; + /** @deprecated */ + authorTitle?: string; + /** @deprecated */ + authorURL?: string; + /** @deprecated */ + authorImageURL?: string; + image?: string; keywords?: string[]; hide_table_of_contents?: boolean; - - /** @deprecated */ - authorTitle?: string; - authorURL?: string; - authorImageURL?: string; /* eslint-enable camelcase */ }; +const FrontMatterAuthorErrorMessage = + '{{#label}} does not look like a valid blog post author. Please use an author key or an author object (with a key and/or name).'; + const BlogFrontMatterSchema = Joi.object({ id: Joi.string(), title: Joi.string().allow(''), @@ -47,28 +79,42 @@ const BlogFrontMatterSchema = Joi.object({ draft: Joi.boolean(), date: Joi.date().raw(), + // New multi-authors frontmatter: + authors: Joi.alternatives() + .try( + Joi.string(), + BlogPostFrontMatterAuthorSchema, + Joi.array() + .items(Joi.string(), BlogPostFrontMatterAuthorSchema) + .messages({ + 'array.sparse': FrontMatterAuthorErrorMessage, + 'array.includes': FrontMatterAuthorErrorMessage, + }), + ) + .messages({ + 'alternatives.match': FrontMatterAuthorErrorMessage, + }), + // Legacy author frontmatter author: Joi.string(), author_title: Joi.string(), author_url: URISchema, author_image_url: URISchema, - slug: Joi.string(), - image: URISchema, - keywords: Joi.array().items(Joi.string().required()), - hide_table_of_contents: Joi.boolean(), - - // TODO re-enable warnings later, our v1 blog posts use those older frontmatter fields + // TODO enable deprecation warnings later authorURL: URISchema, // .warning('deprecate.error', { alternative: '"author_url"'}), authorTitle: Joi.string(), // .warning('deprecate.error', { alternative: '"author_title"'}), authorImageURL: URISchema, // .warning('deprecate.error', { alternative: '"author_image_url"'}), -}) - .unknown() - .messages({ - 'deprecate.error': - '{#label} blog frontMatter field is deprecated. Please use {#alternative} instead.', - }); + + slug: Joi.string(), + image: URISchema, + keywords: Joi.array().items(Joi.string().required()), + hide_table_of_contents: Joi.boolean(), +}).messages({ + 'deprecate.error': + '{#label} blog frontMatter field is deprecated. Please use {#alternative} instead.', +}); export function validateBlogPostFrontMatter( frontMatter: Record, diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index f63527cf24..c26e0e4e8c 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -9,7 +9,7 @@ import fs from 'fs-extra'; import chalk from 'chalk'; import path from 'path'; import readingTime from 'reading-time'; -import {Feed} from 'feed'; +import {Feed, Author as FeedAuthor} from 'feed'; import {compact, keyBy, mapValues} from 'lodash'; import { PluginOptions, @@ -17,6 +17,7 @@ import { BlogContentPaths, BlogMarkdownLoaderOptions, BlogTags, + Author, } from './types'; import { parseMarkdownFile, @@ -32,6 +33,7 @@ import { } from '@docusaurus/utils'; import {LoadContext} from '@docusaurus/types'; import {validateBlogPostFrontMatter} from './blogFrontMatter'; +import {AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors'; export function truncate(fileString: string, truncateMarker: RegExp): string { return fileString.split(truncateMarker, 1).shift()!; @@ -135,10 +137,16 @@ export async function generateBlogFeed( copyright: feedOptions.copyright, }); + function toFeedAuthor(author: Author): FeedAuthor { + // TODO ask author emails? + // RSS feed requires email to render authors + return {name: author.name, link: author.url}; + } + blogPosts.forEach((post) => { const { id, - metadata: {title: metadataTitle, permalink, date, description}, + metadata: {title: metadataTitle, permalink, date, description, authors}, } = post; feed.addItem({ title: metadataTitle, @@ -146,6 +154,7 @@ export async function generateBlogFeed( link: normalizeUrl([siteUrl, permalink]), date, description, + author: authors.map(toFeedAuthor), }); }); @@ -167,6 +176,7 @@ async function processBlogSourceFile( contentPaths: BlogContentPaths, context: LoadContext, options: PluginOptions, + authorsMap?: AuthorsMap, ): Promise { const { siteConfig: {baseUrl}, @@ -258,6 +268,7 @@ async function processBlogSourceFile( } const tagsBasePath = normalizeUrl([baseUrl, options.routeBasePath, 'tags']); // make this configurable? + const authors = getBlogPostAuthors({authorsMap, frontMatter}); return { id: frontMatter.slug ?? title, @@ -272,6 +283,7 @@ async function processBlogSourceFile( tags: normalizeFrontMatterTags(tagsBasePath, frontMatter.tags), readingTime: showReadingTime ? readingTime(content).minutes : undefined, truncated: truncateMarker?.test(content) || false, + authors, }, }; } @@ -292,6 +304,11 @@ export async function generateBlogPosts( ignore: exclude, }); + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: options.authorsMapPath, + }); + const blogPosts: BlogPost[] = compact( await Promise.all( blogSourceFiles.map(async (blogSourceFile: string) => { @@ -301,6 +318,7 @@ export async function generateBlogPosts( contentPaths, context, options, + authorsMap, ); } catch (e) { console.error( diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 76134402ec..52bb3abe3e 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -32,9 +32,10 @@ import { BlogItemsToMetadata, TagsModule, BlogPaginated, - BlogPost, BlogContentPaths, BlogMarkdownLoaderOptions, + MetaData, + Assets, } from './types'; import {PluginOptionSchema} from './pluginOptionSchema'; import { @@ -54,6 +55,7 @@ import { getSourceToPermalink, getBlogTags, } from './blogUtils'; +import {BlogPostFrontMatter} from './blogFrontMatter'; export default function pluginContentBlog( context: LoadContext, @@ -95,12 +97,22 @@ export default function pluginContentBlog( name: 'docusaurus-plugin-content-blog', getPathsToWatch() { - const {include = []} = options; - return flatten( + const {include, authorsMapPath} = options; + const contentMarkdownGlobs = flatten( getContentPathList(contentPaths).map((contentPath) => { return include.map((pattern) => `${contentPath}/${pattern}`); }), ); + + // TODO: we should read this path in plugin! but plugins do not support async init for now :'( + // const authorsMapFilePath = await getAuthorsMapFilePath({authorsMapPath,contentPaths,}); + // simplified impl, better than nothing for now: + const authorsMapFilePath = path.join( + contentPaths.contentPath, + authorsMapPath, + ); + + return [authorsMapFilePath, ...contentMarkdownGlobs]; }, async getTranslationFiles() { @@ -117,11 +129,7 @@ export default function pluginContentBlog( blogSidebarTitle, } = options; - const blogPosts: BlogPost[] = await generateBlogPosts( - contentPaths, - context, - options, - ); + const blogPosts = await generateBlogPosts(contentPaths, context, options); if (!blogPosts.length) { return { @@ -454,12 +462,22 @@ export default function pluginContentBlog( // For blog posts a title in markdown is always removed // Blog posts title are rendered separately removeContentTitle: true, - // those frontMatter fields will be exported as "frontMatterAssets" and eventually be converted to require() calls for relative file paths - frontMatterAssetKeys: [ - 'image', - 'authorImageURL', - 'author_image_URL', - ], + + // Assets allow to convert some relative images paths to require() calls + createAssets: ({ + frontMatter, + metadata, + }: { + frontMatter: BlogPostFrontMatter; + metadata: MetaData; + }): Assets => { + return { + image: frontMatter.image, + authorsImageUrls: metadata.authors.map( + (author) => author.imageURL, + ), + }; + }, }, }, { diff --git a/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts b/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts index fe02b17d1e..90401e4b9d 100644 --- a/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts +++ b/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts @@ -38,6 +38,7 @@ export const DEFAULT_OPTIONS: PluginOptions = { routeBasePath: 'blog', path: 'blog', editLocalizedFiles: false, + authorsMapPath: 'authors.yml', }; export const PluginOptionSchema = Joi.object({ @@ -107,4 +108,5 @@ export const PluginOptionSchema = Joi.object({ }), language: Joi.string(), }).default(DEFAULT_OPTIONS.feedOptions), + authorsMapPath: Joi.string().default(DEFAULT_OPTIONS.authorsMapPath), }); diff --git a/packages/docusaurus-plugin-content-blog/src/types.ts b/packages/docusaurus-plugin-content-blog/src/types.ts index 43289dad4a..2f308e4630 100644 --- a/packages/docusaurus-plugin-content-blog/src/types.ts +++ b/packages/docusaurus-plugin-content-blog/src/types.ts @@ -58,6 +58,7 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions { editUrl?: string | EditUrlFunction; editLocalizedFiles?: boolean; admonitions: Record; + authorsMapPath: string; } export interface BlogTags { @@ -92,6 +93,14 @@ export interface BlogPaginated { items: string[]; } +// We allow passing custom fields to authors, e.g., twitter +export interface Author extends Record { + name?: string; + imageURL?: string; + url?: string; + title?: string; +} + export interface MetaData { permalink: string; source: string; @@ -105,6 +114,12 @@ export interface MetaData { nextItem?: Paginator; truncated: boolean; editUrl?: string; + authors: Author[]; +} + +export interface Assets { + image?: string; + authorsImageUrls: (string | undefined)[]; // Array of same size as the original MetaData.authors array } export interface Paginator { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docFrontMatter.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docFrontMatter.test.ts index f3997d6fcb..543316e077 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docFrontMatter.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docFrontMatter.test.ts @@ -151,7 +151,7 @@ describe('validateDocFrontMatter image', () => { {image: '../relative/image.png'}, ], invalidFrontMatters: [ - [{image: ''}, 'does not match any of the allowed types'], + [{image: ''}, '"image" does not look like a valid url (value=\'\')'], ], }); }); diff --git a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostItem/index.tsx b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostItem/index.tsx index f2fece5284..c2735c96e9 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostItem/index.tsx +++ b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostItem/index.tsx @@ -40,11 +40,7 @@ function BlogPostItem(props: Props): JSX.Element { } = props; const {date, readingTime, tags, permalink, editUrl} = metadata; - const {author, title} = frontMatter; - - const authorURL = frontMatter.author_url || frontMatter.authorURL; - const authorImageURL = - frontMatter.author_image_url || frontMatter.authorImageURL; + const {author, title, authorURL, authorImageURL} = frontMatter; const match = date.substring(0, 10).split('-'); const year = match[0]; @@ -56,13 +52,17 @@ function BlogPostItem(props: Props): JSX.Element {
{authorImageURL && ( - {author} + {author )}
{author && (
- + {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 && ( + + {name} + + )} + + { + // Note: only legacy author frontmatter allow empty name (not frontMatter.authors) + name && ( + + ) + } +
+ ); +} + +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 && ( - - )} -
+ ); }; 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 be9fdfdbf43914eb6dfe8d06911a2cc57cc92cb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3993 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 U!XZ|Y_!bLx@Vd^_J99MhKUx3=G5`Po 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 0000000000000000000000000000000000000000..a2959a335caf013bf9ca83aa8a17a79b183bc11a GIT binary patch literal 69275 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 pF)c7SEiyG!F*7string | 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.`,