fix(content-blog): generate feed by reading build output (#6454)

This commit is contained in:
Joshua Chen 2022-01-26 23:54:15 +08:00 committed by GitHub
parent ebd5340205
commit 76a8d5f38a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 364 additions and 249 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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();
});
});

View file

@ -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<Feed | null> {
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<void> {
const feed = await generateBlogFeed({blogPosts, options, siteConfig});
const feed = await generateBlogFeed({
blogPosts,
options,
siteConfig,
outDir,
});
const feedTypes = options.feedOptions.type;
if (!feed || !feedTypes) {

View file

@ -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;
}