Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): simplify plugin API, support route.props (experimental) #10042

Merged
merged 27 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
84ca226
poc of route.props API
slorber Apr 12, 2024
6cd53b2
add useful comments
slorber Apr 12, 2024
434e1d9
use aliased module prop name
slorber Apr 12, 2024
4f91166
update snapshots
slorber Apr 12, 2024
a9de0d0
remove log
slorber Apr 12, 2024
0b79ec8
convert more blog routes to use route props
slorber Apr 12, 2024
7609737
refactor: apply lint autofix
slorber Apr 12, 2024
598cdeb
refactor/simplify blog post routes
slorber Apr 12, 2024
4a4d50c
Merge remote-tracking branch 'origin/slorber/refactor-contentLoaded' …
slorber Apr 12, 2024
73b7999
fix little codegen bugs
slorber Apr 12, 2024
796cbcb
track more file sizes
slorber Apr 13, 2024
586e829
remove plugins from codegen routes
slorber Apr 15, 2024
c489321
ensure all registry paths are using aliased paths
slorber Apr 15, 2024
c7aee9d
simplify debug plugin
slorber Apr 15, 2024
d74c0ba
useless comment
slorber Apr 15, 2024
3bf9cb9
simplify docs plugin to use route props
slorber Apr 16, 2024
9c62098
Merge branch 'main' into slorber/refactor-contentLoaded
slorber Apr 16, 2024
fcd8220
useful comment
slorber Apr 16, 2024
ec80ac8
refactor pages plugin contentLoaded
slorber Apr 16, 2024
2b8727d
refactor pages loadContent
slorber Apr 16, 2024
1ee3553
fix docs test snapshots
slorber Apr 16, 2024
46bfb69
fix test TS
slorber Apr 16, 2024
07e0bef
fix snapshots
slorber Apr 16, 2024
f8774e8
createData should support object content
slorber Apr 16, 2024
a78b237
createData should support object content
slorber Apr 16, 2024
d1b7e26
remove unused pages webpack alias
slorber Apr 16, 2024
eeef26a
change a bit the props module path
slorber Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
build-script: build:website:en
clean-script: clear:website # see https://github.com/facebook/docusaurus/pull/6838
pattern: '{website/build/assets/js/main*js,website/build/assets/css/styles*css,website/.docusaurus/globalData.json,website/build/index.html,website/build/blog/index.html,website/build/blog/**/introducing-docusaurus/*,website/build/docs/index.html,website/build/docs/installation/index.html,website/build/tests/docs/index.html,website/build/tests/docs/standalone/index.html}'
pattern: '{website/build/assets/js/main*js,website/build/assets/css/styles*css,website/.docusaurus/globalData.json,website/.docusaurus/registry.js,website/.docusaurus/routes.js,website/.docusaurus/routesChunkNames.json,website/.docusaurus/site-metadata.json,website/.docusaurus/codeTranslations.json,website/.docusaurus/i18n.json,website/.docusaurus/docusaurus.config.mjs,website/build/index.html,website/build/blog/index.html,website/build/blog/**/introducing-docusaurus/*,website/build/docs/index.html,website/build/docs/installation/index.html,website/build/tests/docs/index.html,website/build/tests/docs/standalone/index.html}'
strip-hash: '\.([^;]\w{7})\.'
minimum-change-threshold: 30
compression: none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ exports[`translateContent falls back when translation is incomplete 1`] = `
"source": "/blog/2021/06/19/hello",
"tags": [],
"title": "Hello",
"unlisted": false,
},
},
],
Expand Down Expand Up @@ -99,6 +100,7 @@ exports[`translateContent returns translated loaded 1`] = `
"source": "/blog/2021/06/19/hello",
"tags": [],
"title": "Hello",
"unlisted": false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const sampleBlogPosts: BlogPost[] = [
hasTruncateMarker: true,
authors: [],
frontMatter: {},
unlisted: false,
},
content: '',
},
Expand Down
230 changes: 13 additions & 217 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
normalizeUrl,
docuHash,
aliasedSitePath,
aliasedSitePathToRelativePath,
getPluginI18nPath,
posixPath,
addTrailingPathSeparator,
Expand All @@ -32,24 +31,17 @@ import footnoteIDFixer from './remark/footnoteIDFixer';
import {translateContent, getTranslationFiles} from './translations';
import {createBlogFeedFiles} from './feed';

import {toTagProp, toTagsProp} from './props';
import {createAllRoutes} from './routes';
import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types';
import type {
LoadContext,
Plugin,
HtmlTags,
RouteMetadata,
} from '@docusaurus/types';
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
import type {
PluginOptions,
BlogPostFrontMatter,
BlogPostMetadata,
Assets,
BlogTag,
BlogTags,
BlogContent,
BlogPaginated,
BlogMetadata,
} from '@docusaurus/plugin-content-blog';

export default async function pluginContentBlog(
Expand Down Expand Up @@ -80,6 +72,9 @@ export default async function pluginContentBlog(
'docusaurus-plugin-content-blog',
);
const dataDir = path.join(pluginDataDirRoot, pluginId);
// TODO Docusaurus v4 breaking change
// module aliasing should be automatic
// we should never find local absolute FS paths in the codegen registry
const aliasedSource = (source: string) =>
`~blog/${posixPath(path.relative(pluginDataDirRoot, source))}`;

Expand Down Expand Up @@ -185,213 +180,14 @@ export default async function pluginContentBlog(
};
},

async contentLoaded({content: blogContents, actions}) {
const {
blogListComponent,
blogPostComponent,
blogTagsListComponent,
blogTagsPostsComponent,
blogArchiveComponent,
routeBasePath,
archiveBasePath,
blogTitle,
} = options;

const {addRoute, createData} = actions;
const {
blogSidebarTitle,
blogPosts,
blogListPaginated,
blogTags,
blogTagsListPath,
} = blogContents;

const listedBlogPosts = blogPosts.filter(shouldBeListed);

const blogItemsToMetadata: {[postId: string]: BlogPostMetadata} = {};

const sidebarBlogPosts =
options.blogSidebarCount === 'ALL'
? blogPosts
: blogPosts.slice(0, options.blogSidebarCount);

function blogPostItemsModule(items: string[]) {
return items.map((postId) => {
const blogPostMetadata = blogItemsToMetadata[postId]!;
return {
content: {
__import: true,
path: blogPostMetadata.source,
query: {
truncated: true,
},
},
};
});
}

if (archiveBasePath && listedBlogPosts.length) {
const archiveUrl = normalizeUrl([
baseUrl,
routeBasePath,
archiveBasePath,
]);
// Create a blog archive route
const archiveProp = await createData(
`${docuHash(archiveUrl)}.json`,
JSON.stringify({blogPosts: listedBlogPosts}, null, 2),
);
addRoute({
path: archiveUrl,
component: blogArchiveComponent,
exact: true,
modules: {
archive: aliasedSource(archiveProp),
},
});
}

// This prop is useful to provide the blog list sidebar
const sidebarProp = await createData(
// Note that this created data path must be in sync with
// metadataPath provided to mdx-loader.
`blog-post-list-prop-${pluginId}.json`,
JSON.stringify(
{
title: blogSidebarTitle,
items: sidebarBlogPosts.map((blogPost) => ({
title: blogPost.metadata.title,
permalink: blogPost.metadata.permalink,
unlisted: blogPost.metadata.unlisted,
})),
},
null,
2,
),
);

const blogMetadata: BlogMetadata = {
blogBasePath: normalizeUrl([baseUrl, routeBasePath]),
blogTitle,
};
const blogMetadataPath = await createData(
`blogMetadata-${pluginId}.json`,
JSON.stringify(blogMetadata, null, 2),
);

function createBlogPostRouteMetadata(
blogPostMeta: BlogPostMetadata,
): RouteMetadata {
return {
sourceFilePath: aliasedSitePathToRelativePath(blogPostMeta.source),
lastUpdatedAt: blogPostMeta.lastUpdatedAt,
};
}

// Create routes for blog entries.
await Promise.all(
blogPosts.map(async (blogPost) => {
const {id, metadata} = blogPost;
await createData(
// Note that this created data path must be in sync with
// metadataPath provided to mdx-loader.
`${docuHash(metadata.source)}.json`,
JSON.stringify(metadata, null, 2),
);

addRoute({
path: metadata.permalink,
component: blogPostComponent,
exact: true,
modules: {
sidebar: aliasedSource(sidebarProp),
content: metadata.source,
},
metadata: createBlogPostRouteMetadata(metadata),
context: {
blogMetadata: aliasedSource(blogMetadataPath),
},
});

blogItemsToMetadata[id] = metadata;
}),
);

// Create routes for blog's paginated list entries.
await Promise.all(
blogListPaginated.map(async (listPage) => {
const {metadata, items} = listPage;
const {permalink} = metadata;
const pageMetadataPath = await createData(
`${docuHash(permalink)}.json`,
JSON.stringify(metadata, null, 2),
);

addRoute({
path: permalink,
component: blogListComponent,
exact: true,
modules: {
sidebar: aliasedSource(sidebarProp),
items: blogPostItemsModule(items),
metadata: aliasedSource(pageMetadataPath),
},
});
}),
);

// Tags. This is the last part so we early-return if there are no tags.
if (Object.keys(blogTags).length === 0) {
return;
}

async function createTagsListPage() {
const tagsPropPath = await createData(
`${docuHash(`${blogTagsListPath}-tags`)}.json`,
JSON.stringify(toTagsProp({blogTags}), null, 2),
);
addRoute({
path: blogTagsListPath,
component: blogTagsListComponent,
exact: true,
modules: {
sidebar: aliasedSource(sidebarProp),
tags: aliasedSource(tagsPropPath),
},
});
}

async function createTagPostsListPage(tag: BlogTag): Promise<void> {
await Promise.all(
tag.pages.map(async (blogPaginated) => {
const {metadata, items} = blogPaginated;
const tagPropPath = await createData(
`${docuHash(metadata.permalink)}.json`,
JSON.stringify(toTagProp({tag, blogTagsListPath}), null, 2),
);

const listMetadataPath = await createData(
`${docuHash(metadata.permalink)}-list.json`,
JSON.stringify(metadata, null, 2),
);

addRoute({
path: metadata.permalink,
component: blogTagsPostsComponent,
exact: true,
modules: {
sidebar: aliasedSource(sidebarProp),
items: blogPostItemsModule(items),
tag: aliasedSource(tagPropPath),
listMetadata: aliasedSource(listMetadataPath),
},
});
}),
);
}

await createTagsListPage();
await Promise.all(Object.values(blogTags).map(createTagPostsListPage));
async contentLoaded({content, actions}) {
await createAllRoutes({
baseUrl,
content,
actions,
options,
aliasedSource,
});
},

translateContent({content, translationFiles}) {
Expand Down
Loading
Loading