From 76a8d5f38a3049e20c010784867c6ed94083a6da Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Wed, 26 Jan 2022 23:54:15 +0800 Subject: [PATCH] fix(content-blog): generate feed by reading build output (#6454) --- .../package.json | 2 + .../14/Happy-First-Birthday-Slash/index.html | 18 +++ .../build-snap/blog/archive/index.html | 18 +++ .../build-snap/blog/date-matter/index.html | 18 +++ .../blog/heading-as-title/index.html | 18 +++ .../blog/hey/my super path/héllô/index.html | 18 +++ .../website/build-snap/blog/index.html | 19 +++ .../build-snap/blog/mdx-blog-post/index.html | 19 +++ .../blog/mdx-require-blog-post/index.html | 18 +++ .../build-snap/blog/simple/slug/index.html | 18 +++ .../build-snap/blog/tags/birthday/index.html | 18 +++ .../build-snap/blog/tags/complex/index.html | 18 +++ .../build-snap/blog/tags/date/index.html | 18 +++ .../website/build-snap/blog/tags/index.html | 18 +++ .../__tests__/__snapshots__/feed.test.ts.snap | 59 ++------ .../src/__tests__/feed.test.ts | 14 +- .../src/feed.ts | 42 +++--- .../src/index.ts | 8 +- .../docusaurus-theme-classic/package.json | 1 + .../src/theme/BlogPostItem/index.tsx | 7 +- packages/docusaurus-types/src/index.d.ts | 2 +- packages/docusaurus-utils-common/src/index.ts | 1 + .../src/__tests__/mdxUtils.test.ts | 133 ------------------ packages/docusaurus-utils/src/index.ts | 34 ++++- packages/docusaurus-utils/src/mdxUtils.ts | 32 ----- packages/docusaurus/src/commands/build.ts | 7 +- .../docs/api/plugin-methods/lifecycle-apis.md | 1 + yarn.lock | 34 ++++- 28 files changed, 364 insertions(+), 249 deletions(-) create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/2018/12/14/Happy-First-Birthday-Slash/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/archive/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/date-matter/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/heading-as-title/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/hey/my super path/héllô/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-blog-post/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-require-blog-post/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/simple/slug/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/birthday/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/complex/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/date/index.html create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/index.html delete mode 100644 packages/docusaurus-utils/src/__tests__/mdxUtils.test.ts delete mode 100644 packages/docusaurus-utils/src/mdxUtils.ts diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 3abd1efc99..5c5dd3543f 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -22,7 +22,9 @@ "@docusaurus/logger": "2.0.0-beta.14", "@docusaurus/mdx-loader": "2.0.0-beta.14", "@docusaurus/utils": "2.0.0-beta.14", + "@docusaurus/utils-common": "2.0.0-beta.14", "@docusaurus/utils-validation": "2.0.0-beta.14", + "cheerio": "^1.0.0-rc.10", "feed": "^4.2.2", "fs-extra": "^10.0.0", "lodash": "^4.17.20", diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/2018/12/14/Happy-First-Birthday-Slash/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/2018/12/14/Happy-First-Birthday-Slash/index.html new file mode 100644 index 0000000000..1a3b803a8f --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/2018/12/14/Happy-First-Birthday-Slash/index.html @@ -0,0 +1,18 @@ + + + + + + + +Happy 1st Birthday Slash! | My Site + + + + +
+
Skip to main content
+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/archive/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/archive/index.html new file mode 100644 index 0000000000..403fe3174d --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/archive/index.html @@ -0,0 +1,18 @@ + + + + + + + +Archive | My Site + + + + +
+
Skip to main content
+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/date-matter/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/date-matter/index.html new file mode 100644 index 0000000000..f56293ab02 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/date-matter/index.html @@ -0,0 +1,18 @@ + + + + + + + +date-matter | My Site + + + + +
+
Skip to main content
+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/heading-as-title/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/heading-as-title/index.html new file mode 100644 index 0000000000..8e699a3d2d --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/heading-as-title/index.html @@ -0,0 +1,18 @@ + + + + + + + +some heading | My Site + + + + +
+
Skip to main content
+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/hey/my super path/héllô/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/hey/my super path/héllô/index.html new file mode 100644 index 0000000000..99bfcb770a --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/hey/my super path/héllô/index.html @@ -0,0 +1,18 @@ + + + + + + + +Complex Slug | My Site + + + + +
+
Skip to main content
+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/index.html new file mode 100644 index 0000000000..b0ba576b63 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/index.html @@ -0,0 +1,19 @@ + + + + + + + +Blog | My Site + + + + +
+
Skip to main content

· One min read

HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link +image

· One min read

date inside front matter

+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-blog-post/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-blog-post/index.html new file mode 100644 index 0000000000..921732b877 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-blog-post/index.html @@ -0,0 +1,19 @@ + + + + + + + +Full Blog Sample | My Site + + + + +
+
Skip to main content

Full Blog Sample

· One min read

HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link +image

+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-require-blog-post/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-require-blog-post/index.html new file mode 100644 index 0000000000..8d0ac938d8 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/mdx-require-blog-post/index.html @@ -0,0 +1,18 @@ + + + + + + + +MDX Blog Sample with require calls | My Site + + + + +
+
Skip to main content

MDX Blog Sample with require calls

· One min read

Test MDX with require calls

+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/simple/slug/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/simple/slug/index.html new file mode 100644 index 0000000000..1dd47a9943 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/simple/slug/index.html @@ -0,0 +1,18 @@ + + + + + + + +Simple Slug | My Site + + + + +
+
Skip to main content
+ + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/birthday/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/birthday/index.html new file mode 100644 index 0000000000..f9820c0f21 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/birthday/index.html @@ -0,0 +1,18 @@ + + + + + + + +One post tagged with "birthday" | My Site + + + + +
+
Skip to main content

One post tagged with "birthday"

View All Tags
+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/complex/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/complex/index.html new file mode 100644 index 0000000000..c8b5017f1a --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/complex/index.html @@ -0,0 +1,18 @@ + + + + + + + +One post tagged with "complex" | My Site + + + + +
+
Skip to main content

One post tagged with "complex"

View All Tags
+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/date/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/date/index.html new file mode 100644 index 0000000000..1878e30260 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/date/index.html @@ -0,0 +1,18 @@ + + + + + + + +2 posts tagged with "date" | My Site + + + + +
+
Skip to main content

2 posts tagged with "date"

View All Tags
+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/index.html b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/index.html new file mode 100644 index 0000000000..292400b08f --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/tags/index.html @@ -0,0 +1,18 @@ + + + + + + + +Tags | My Site + + + + +
+
Skip to main content
+ + + + \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap index 6c5dd55354..28d2e5b294 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap @@ -2,9 +2,7 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` Array [ - Array [ - "build/blog/atom.xml", - " + " https://docusaurus.io/myBaseUrl/blog Hello Blog @@ -20,6 +18,7 @@ Array [ 2021-03-06T00:00:00.000Z + Test MDX with require calls

]]>
<![CDATA[Full Blog Sample]]> @@ -27,8 +26,8 @@ Array [ 2021-03-05T00:00:00.000Z - HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link -\\"image\\"/

]]>
+ HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link +\\"image\\"

]]>
<![CDATA[Complex Slug]]> @@ -52,14 +51,6 @@ Array [ https://sebastienlorber.com - - <![CDATA[draft]]> - /draft - - 2020-02-27T00:00:00.000Z - - this post should not be published yet

]]>
-
<![CDATA[some heading]]> /heading-as-title @@ -81,7 +72,7 @@ Array [ 2018-12-14T00:00:00.000Z - Happy birthday! (translated)

]]>
+ Happy birthday!

]]>
Yangshun Tay (translated) @@ -90,15 +81,12 @@ Array [
", - ], ] `; exports[`blogFeed json shows feed item for each post 1`] = ` Array [ - Array [ - "build/blog/feed.json", - "{ + "{ \\"version\\": \\"https://jsonfeed.org/version/1\\", \\"title\\": \\"Hello Blog\\", \\"home_page_url\\": \\"https://docusaurus.io/myBaseUrl/blog\\", @@ -106,6 +94,7 @@ Array [ \\"items\\": [ { \\"id\\": \\"/mdx-require-blog-post\\", + \\"content_html\\": \\"

Test MDX with require calls

\\", \\"url\\": \\"https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post\\", \\"title\\": \\"MDX Blog Sample with require calls\\", \\"summary\\": \\"Test MDX with require calls\\", @@ -114,7 +103,7 @@ Array [ }, { \\"id\\": \\"/mdx-blog-post\\", - \\"content_html\\": \\"

HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5

Normal Text Italics Text Bold Text

link\\\\n\\\\\\"image\\\\\\"/

\\", + \\"content_html\\": \\"

HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5

Normal Text Italics Text Bold Text

link\\\\n\\\\\\"image\\\\\\"

\\", \\"url\\": \\"https://docusaurus.io/myBaseUrl/blog/mdx-blog-post\\", \\"title\\": \\"Full Blog Sample\\", \\"summary\\": \\"HTML Heading 1\\", @@ -146,15 +135,6 @@ Array [ }, \\"tags\\": [] }, - { - \\"id\\": \\"/draft\\", - \\"content_html\\": \\"

this post should not be published yet

\\", - \\"url\\": \\"https://docusaurus.io/myBaseUrl/blog/draft\\", - \\"title\\": \\"draft\\", - \\"summary\\": \\"this post should not be published yet\\", - \\"date_modified\\": \\"2020-02-27T00:00:00.000Z\\", - \\"tags\\": [] - }, { \\"id\\": \\"/heading-as-title\\", \\"content_html\\": \\"\\", @@ -176,7 +156,7 @@ Array [ }, { \\"id\\": \\"/2018/12/14/Happy-First-Birthday-Slash\\", - \\"content_html\\": \\"

Happy birthday! (translated)

\\", + \\"content_html\\": \\"

Happy birthday!

\\", \\"url\\": \\"https://docusaurus.io/myBaseUrl/blog/2018/12/14/Happy-First-Birthday-Slash\\", \\"title\\": \\"Happy 1st Birthday Slash! (translated)\\", \\"summary\\": \\"Happy birthday! (translated)\\", @@ -188,15 +168,12 @@ Array [ } ] }", - ], ] `; exports[`blogFeed rss shows feed item for each post 1`] = ` Array [ - Array [ - "build/blog/rss.xml", - " + " Hello Blog @@ -212,6 +189,7 @@ Array [ /mdx-require-blog-post Sat, 06 Mar 2021 00:00:00 GMT + Test MDX with require calls

]]>
<![CDATA[Full Blog Sample]]> @@ -219,8 +197,8 @@ Array [ /mdx-blog-post Fri, 05 Mar 2021 00:00:00 GMT - HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link -\\"image\\"/

]]>
+ HTML Heading 1

HTML Heading 2

HTML Paragraph

Import DOM

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
  • list1
  • list2
  • list3
  • list1
  • list2
  • list3

Normal Text Italics Text Bold Text

link +\\"image\\"

]]>
<![CDATA[Complex Slug]]> @@ -240,14 +218,6 @@ Array [ simple url slug

]]>
- - <![CDATA[draft]]> - https://docusaurus.io/myBaseUrl/blog/draft - /draft - Thu, 27 Feb 2020 00:00:00 GMT - - this post should not be published yet

]]>
-
<![CDATA[some heading]]> https://docusaurus.io/myBaseUrl/blog/heading-as-title @@ -269,10 +239,9 @@ Array [ /2018/12/14/Happy-First-Birthday-Slash Fri, 14 Dec 2018 00:00:00 GMT - Happy birthday! (translated)

]]>
+ Happy birthday!

]]>
", - ], ] `; diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index d6d5d1f2d3..bd77b29115 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -44,10 +44,10 @@ async function testGenerateFeeds( ); await createBlogFeedFiles({ - blogPosts, + blogPosts: blogPosts.filter((post) => !post.metadata.frontMatter.draft), options, siteConfig: context.siteConfig, - outDir: 'build', + outDir: context.outDir, }); } @@ -64,12 +64,14 @@ describe('blogFeed', () => { url: 'https://docusaurus.io', favicon: 'image/favicon.ico', }; + const outDir = path.join(siteDir, 'build-snap'); await testGenerateFeeds( { siteDir, siteConfig, i18n: DefaultI18N, + outDir, } as LoadContext, { path: 'invalid-blog-path', @@ -92,7 +94,7 @@ describe('blogFeed', () => { test('shows feed item for each post', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); - const generatedFilesDir = path.resolve(siteDir, '.docusaurus'); + const outDir = path.join(siteDir, 'build-snap'); const siteConfig = { title: 'Hello', baseUrl: '/myBaseUrl/', @@ -100,12 +102,14 @@ describe('blogFeed', () => { favicon: 'image/favicon.ico', }; + // Build is quite difficult to mock, so we built the blog beforehand and + // copied the output to the fixture... await testGenerateFeeds( { siteDir, siteConfig, - generatedFilesDir, i18n: DefaultI18N, + outDir, } as LoadContext, { path: 'blog', @@ -123,7 +127,7 @@ describe('blogFeed', () => { } as PluginOptions, ); - expect(fsMock.mock.calls).toMatchSnapshot(); + expect(fsMock.mock.calls.map((call) => call[1])).toMatchSnapshot(); fsMock.mockClear(); }); }); diff --git a/packages/docusaurus-plugin-content-blog/src/feed.ts b/packages/docusaurus-plugin-content-blog/src/feed.ts index 20f9a109a5..1357135e60 100644 --- a/packages/docusaurus-plugin-content-blog/src/feed.ts +++ b/packages/docusaurus-plugin-content-blog/src/feed.ts @@ -7,7 +7,13 @@ import {Feed, type Author as FeedAuthor, type Item as FeedItem} from 'feed'; import type {BlogPost} from './types'; -import {normalizeUrl, mdxToHtml, posixPath} from '@docusaurus/utils'; +import { + normalizeUrl, + posixPath, + mapAsyncSequential, + readOutputHTMLFile, +} from '@docusaurus/utils'; +import cheerio from 'cheerio'; import type {DocusaurusConfig} from '@docusaurus/types'; import path from 'path'; import fs from 'fs-extra'; @@ -16,28 +22,18 @@ import type { PluginOptions, Author, } from '@docusaurus/plugin-content-blog'; - -// TODO this is temporary until we handle mdxToHtml better -// It's hard to convert reliably JSX/require calls to an html feed content -// See https://github.com/facebook/docusaurus/issues/5664 -function mdxToFeedContent(mdxContent: string): string | undefined { - try { - return mdxToHtml(mdxContent); - } catch (e) { - // TODO will we need a plugin option to configure how to handle such an error - // Swallow the error on purpose for now, until we understand better the problem space - return undefined; - } -} +import {blogPostContainerID} from '@docusaurus/utils-common'; async function generateBlogFeed({ blogPosts, options, siteConfig, + outDir, }: { blogPosts: BlogPost[]; options: PluginOptions; siteConfig: DocusaurusConfig; + outDir: string; }): Promise { if (!blogPosts.length) { return null; @@ -66,7 +62,7 @@ async function generateBlogFeed({ return {name: author.name, link: author.url}; } - blogPosts.forEach((post) => { + await mapAsyncSequential(blogPosts, async (post) => { const { id, metadata: { @@ -79,6 +75,13 @@ async function generateBlogFeed({ }, } = post; + const content = await readOutputHTMLFile( + permalink.replace(siteConfig.baseUrl, ''), + outDir, + siteConfig.trailingSlash, + ); + const $ = cheerio.load(content); + const feedItem: FeedItem = { title: metadataTitle, id, @@ -87,7 +90,7 @@ async function generateBlogFeed({ description, // Atom feed demands the "term", while other feeds use "name" category: tags.map((tag) => ({name: tag.label, term: tag.label})), - content: mdxToFeedContent(post.content), + content: $(`#${blogPostContainerID}`).html()!, }; // json1() method takes the first item of authors array @@ -145,7 +148,12 @@ export async function createBlogFeedFiles({ siteConfig: DocusaurusConfig; outDir: string; }): Promise { - const feed = await generateBlogFeed({blogPosts, options, siteConfig}); + const feed = await generateBlogFeed({ + blogPosts, + options, + siteConfig, + outDir, + }); const feedTypes = options.feedOptions.type; if (!feed || !feedTypes) { diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index c21cfe4a85..14729a2fad 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -36,7 +36,6 @@ import {PluginOptionSchema} from './pluginOptionSchema'; import type { LoadContext, ConfigureWebpackUtils, - Props, Plugin, HtmlTags, OptionValidationContext, @@ -512,14 +511,11 @@ export default async function pluginContentBlog( }; }, - async postBuild({outDir}: Props) { + async postBuild({outDir, content}) { if (!options.feedOptions.type) { return; } - - // TODO: we shouldn't need to re-read the posts here! - // postBuild should receive loadedContent - const blogPosts = await generateBlogPosts(contentPaths, context, options); + const {blogPosts} = content; if (!blogPosts.length) { return; } diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 1dafae9093..5a74747c45 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -28,6 +28,7 @@ "@docusaurus/theme-common": "2.0.0-beta.14", "@docusaurus/theme-translations": "2.0.0-beta.14", "@docusaurus/utils": "2.0.0-beta.14", + "@docusaurus/utils-common": "2.0.0-beta.14", "@docusaurus/utils-validation": "2.0.0-beta.14", "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx index 2d98e1909f..dd9c870a80 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx @@ -12,6 +12,7 @@ import Translate, {translate} from '@docusaurus/Translate'; import Link from '@docusaurus/Link'; import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; import {usePluralForm} from '@docusaurus/theme-common'; +import {blogPostContainerID} from '@docusaurus/utils-common'; import MDXComponents from '@theme/MDXComponents'; import EditThisPage from '@theme/EditThisPage'; import type {Props} from '@theme/BlogPostItem'; @@ -102,7 +103,11 @@ function BlogPostItem(props: Props): JSX.Element { )} -
+
{children}
diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index d2fe18dab0..bb5d564a12 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -258,7 +258,7 @@ export interface Plugin { actions: PluginContentLoadedActions; }) => Promise; routesLoaded?: (routes: RouteConfig[]) => void; // TODO remove soon, deprecated (alpha-60) - postBuild?: (props: Props) => void; + postBuild?: (props: Props & {content: Content}) => Promise; postStart?: (props: Props) => void; // TODO refactor the configureWebpack API surface: use an object instead of multiple params (requires breaking change) configureWebpack?: ( diff --git a/packages/docusaurus-utils-common/src/index.ts b/packages/docusaurus-utils-common/src/index.ts index 204a13ebf5..6d7fb91b4f 100644 --- a/packages/docusaurus-utils-common/src/index.ts +++ b/packages/docusaurus-utils-common/src/index.ts @@ -5,5 +5,6 @@ * LICENSE file in the root directory of this source tree. */ +export const blogPostContainerID = 'post-content'; export {default as applyTrailingSlash} from './applyTrailingSlash'; export type {ApplyTrailingSlashParams} from './applyTrailingSlash'; diff --git a/packages/docusaurus-utils/src/__tests__/mdxUtils.test.ts b/packages/docusaurus-utils/src/__tests__/mdxUtils.test.ts deleted file mode 100644 index 15e63d1322..0000000000 --- a/packages/docusaurus-utils/src/__tests__/mdxUtils.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -/** - * 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 {mdxToHtml} from '../mdxUtils'; - -describe('mdxToHtml', () => { - test('work with simple markdown', () => { - const mdxString = ` -# title - -title text **bold** - -## subtitle - -subtitle text *italic* - -> Quote - - `; - - expect(mdxToHtml(mdxString)).toMatchInlineSnapshot( - `"

title

title text bold

subtitle

subtitle text italic

Quote

"`, - ); - }); - - test('work with MDX imports', () => { - const mdxString = ` -# title - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -text - - `; - - expect(mdxToHtml(mdxString)).toMatchInlineSnapshot( - `"

title

text

"`, - ); - }); - - test('work with MDX exports', () => { - const mdxString = ` -# title - -export const someExport = 42 - -export const MyLocalComponent = () => "result" - -export const toc = [ - {id: "title",label: "title"} -] - -text - - - `; - - expect(mdxToHtml(mdxString)).toMatchInlineSnapshot( - `"

title

text

"`, - ); - }); - - test('work with MDX Tabs', () => { - const mdxString = ` -# title - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - This is an apple 🍎 - - - This is an orange 🍊 - - - -text - - - `; - - // TODO this is not an ideal behavior! - // There is a warning "Component TabItem was not imported, exported, or provided by MDXProvider as global scope" - // Theme + MDX config should provide a list of React components to put in MDX scope - expect(mdxToHtml(mdxString)).toMatchInlineSnapshot( - `"

title

This is an apple 🍎
This is an orange 🍊

text

"`, - ); - }); - - test('work with MDX Tabs with ```mdx-code-block', () => { - const mdxString = ` -# title - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -\`\`\`mdx-code-block - - - This is an apple 🍎 - - - This is an orange 🍊 - - -\`\`\` - -text - - `; - - // TODO bad behavior! - // ```mdx-code-block should be unwrapped and inner MDX content should be evaluated - expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(` - "

title

<Tabs>
-        <TabItem value="apple" label="Apple">
-          This is an apple 🍎
-        </TabItem>
-        <TabItem value="orange" label="Orange">
-          This is an orange 🍊
-        </TabItem>
-      </Tabs>
-      

text

" - `); - }); -}); diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index e0ca7f81ec..bb0cffa266 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -23,7 +23,6 @@ import {simpleHash, docuHash} from './hashUtils'; import {DEFAULT_PLUGIN_ID} from './constants'; export * from './constants'; -export * from './mdxUtils'; export * from './urlUtils'; export * from './tags'; export * from './markdownParser'; @@ -210,6 +209,39 @@ export function getPluginI18nPath({ ); } +/** + * @param permalink The URL that the HTML file corresponds to, without base URL + * @param outDir Full path to the output directory + * @param trailingSlash The site config option. If provided, only one path will be read. + * @returns This returns a buffer, which you have to decode string yourself if + * needed. (Not always necessary since the output isn't for human consumption + * anyways, and most HTML manipulation libs accept buffers) + */ +export async function readOutputHTMLFile( + permalink: string, + outDir: string, + trailingSlash: boolean | undefined, +): Promise { + const withTrailingSlashPath = path.join(outDir, permalink, 'index.html'); + const withoutTrailingSlashPath = path.join(outDir, `${permalink}.html`); + if (trailingSlash) { + return fs.readFile(withTrailingSlashPath); + } else if (trailingSlash === false) { + return fs.readFile(withoutTrailingSlashPath); + } else { + const HTMLPath = await findAsyncSequential( + [withTrailingSlashPath, withoutTrailingSlashPath], + fs.pathExists, + ); + if (!HTMLPath) { + throw new Error( + `Expected output HTML file to be found at ${withTrailingSlashPath}`, + ); + } + return fs.readFile(HTMLPath); + } +} + export async function mapAsyncSequential( array: T[], action: (t: T) => Promise, diff --git a/packages/docusaurus-utils/src/mdxUtils.ts b/packages/docusaurus-utils/src/mdxUtils.ts deleted file mode 100644 index a8028896fc..0000000000 --- a/packages/docusaurus-utils/src/mdxUtils.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 ReactDOMServer from 'react-dom/server'; -import MDX from '@mdx-js/runtime'; -import removeImports from 'remark-mdx-remove-imports'; -import removeExports from 'remark-mdx-remove-exports'; - -/** - * Transform mdx text to plain html text - * Initially created to convert MDX blog posts to HTML for the RSS feed - * without import/export nodes - * - * TODO not ideal implementation, won't work well with MDX elements! - * TODO theme+global site config should be able to declare MDX comps in scope for rendering the RSS feeds - * see also https://github.com/facebook/docusaurus/issues/4625 - */ -export function mdxToHtml( - mdxStr: string, - // TODO allow providing components/scope here, see https://github.com/mdx-js/mdx/tree/v1.6.13/packages/runtime -): string { - return ReactDOMServer.renderToString( - React.createElement(MDX, {remarkPlugins: [removeImports, removeExports]}, [ - mdxStr, - ]), - ); -} diff --git a/packages/docusaurus/src/commands/build.ts b/packages/docusaurus/src/commands/build.ts index cdb99a2cd8..2f7d64c7d7 100644 --- a/packages/docusaurus/src/commands/build.ts +++ b/packages/docusaurus/src/commands/build.ts @@ -176,7 +176,7 @@ async function buildLocale({ if (configureWebpack) { clientConfig = applyConfigureWebpack( - configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`. // TODO remove this implicit api: inject in callback instead + configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`. clientConfig, false, props.siteConfig.webpack?.jsLoader, @@ -184,7 +184,7 @@ async function buildLocale({ ); serverConfig = applyConfigureWebpack( - configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`. // TODO remove this implicit api: inject in callback instead + configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`. serverConfig, true, props.siteConfig.webpack?.jsLoader, @@ -220,7 +220,8 @@ async function buildLocale({ if (!plugin.postBuild) { return; } - await plugin.postBuild(props); + // The plugin may reference `this`. We manually bind it again to prevent any bugs. + await plugin.postBuild({...props, content: plugin.content}); }), ); diff --git a/website/docs/api/plugin-methods/lifecycle-apis.md b/website/docs/api/plugin-methods/lifecycle-apis.md index ea06de717d..e4cb3d211e 100644 --- a/website/docs/api/plugin-methods/lifecycle-apis.md +++ b/website/docs/api/plugin-methods/lifecycle-apis.md @@ -281,6 +281,7 @@ interface Props { postBodyTags: string; routesPaths: string[]; plugins: Plugin[]; + content: Content; } ``` diff --git a/yarn.lock b/yarn.lock index d0a9d8ebed..f35378b92a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6047,6 +6047,17 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +cheerio-select@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" + integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== + dependencies: + css-select "^4.1.3" + css-what "^5.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + domutils "^2.7.0" + cheerio@^0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" @@ -6069,6 +6080,19 @@ cheerio@^0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" +cheerio@^1.0.0-rc.10: + version "1.0.0-rc.10" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" + integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== + dependencies: + cheerio-select "^1.5.0" + dom-serializer "^1.3.2" + domhandler "^4.2.0" + htmlparser2 "^6.1.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + tslib "^2.2.0" + chokidar@^3.0.2, chokidar@^3.4.0, chokidar@^3.4.2, chokidar@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" @@ -7117,7 +7141,7 @@ css-what@2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -css-what@^5.1.0: +css-what@^5.0.1, css-what@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== @@ -7757,7 +7781,7 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" -dom-serializer@^1.0.1: +dom-serializer@^1.0.1, dom-serializer@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== @@ -7826,7 +7850,7 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.5.2, domutils@^2.8.0: +domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -14544,7 +14568,7 @@ parse-url@^6.0.0: parse-path "^4.0.0" protocols "^1.4.0" -parse5-htmlparser2-tree-adapter@^6.0.0: +parse5-htmlparser2-tree-adapter@^6.0.0, parse5-htmlparser2-tree-adapter@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== @@ -18450,7 +18474,7 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1: +tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==