mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-24 14:36:59 +02:00
fix(content-blog): generate feed by reading build output (#6454)
This commit is contained in:
parent
ebd5340205
commit
76a8d5f38a
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
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
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
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue