fix(v2): fix docs homepage permalink issues (#2905)

* better fixes for docs homepage

* fix tests

* create special route for docs homepage + cleanup existing code

* no need to create multiple docs parent paths

* useful comment

* add test for slug + doc home usage at the same time error

* remove confusing variable name

* fix tests by using same suffix as before for docs base metadata path

* metadata: use homePageId correctly for nested docs: the full docId (including /) should be used to compare against homePageId

* add folder/testNested test doc

* refactor a bit processMetadata, the home should be handled correctly for all versions

* Workaround to fix issue when parent layout route (DocPage) has same path as the child route (DocItem): see https://github.com/facebook/docusaurus/issues/2917

* revert homePageId

* remove test doc

* remove test doc

* add useful comment
This commit is contained in:
Sébastien Lorber 2020-06-17 14:54:08 +02:00 committed by GitHub
parent a3f54d747d
commit f6b1c85b01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 264 additions and 218 deletions

View file

@ -85,7 +85,9 @@ export default function pluginContentDocs(
context: LoadContext,
opts: Partial<PluginOptions>,
): Plugin<LoadedContent | null> {
const options = {...DEFAULT_OPTIONS, ...opts};
const options: PluginOptions = {...DEFAULT_OPTIONS, ...opts};
const homePageDocsRoutePath =
options.routeBasePath === '' ? '/' : options.routeBasePath;
if (options.admonitions) {
options.remarkPlugins = options.remarkPlugins.concat([
@ -112,24 +114,6 @@ export default function pluginContentDocs(
} = versioning;
const versionsNames = versions.map((version) => `version-${version}`);
// Docs home page.
const homePageDocsRoutePath =
options.routeBasePath === '' ? '/' : options.routeBasePath;
const isDocsHomePagePath = (permalink: string) => {
const documentIdMatch = new RegExp(
`^\/(?:${homePageDocsRoutePath}\/)?(?:(?:${versions.join(
'|',
)}|next)\/)?(.*)`,
'i',
).exec(permalink);
if (documentIdMatch) {
return documentIdMatch[1] === options.homePageId;
}
return false;
};
return {
name: 'docusaurus-plugin-content-docs',
@ -307,9 +291,7 @@ Available document ids=
return {
type: 'link',
label: sidebar_label || title,
href: isDocsHomePagePath(permalink)
? permalink.replace(`/${options.homePageId}`, '')
: permalink,
href: permalink,
};
};
@ -376,50 +358,8 @@ Available document ids=
const genRoutes = async (
metadataItems: Metadata[],
): Promise<RouteConfig[]> => {
const versionsRegex = new RegExp(versionsNames.join('|'), 'i');
const routes = await Promise.all(
metadataItems.map(async (metadataItem) => {
const isDocsHomePage =
metadataItem.id.replace(versionsRegex, '').replace(/^\//, '') ===
options.homePageId;
if (isDocsHomePage) {
const versionDocsPathPrefix =
(metadataItem?.version === versioning.latestVersion
? ''
: metadataItem.version!) ?? '';
const docsBaseMetadata = createDocsBaseMetadata(
metadataItem.version!,
);
docsBaseMetadata.isHomePage = true;
docsBaseMetadata.homePagePath = normalizeUrl([
baseUrl,
homePageDocsRoutePath,
versionDocsPathPrefix,
]);
const docsBaseMetadataPath = await createData(
`${docuHash(metadataItem.source)}-base.json`,
JSON.stringify(docsBaseMetadata, null, 2),
);
// Add a route for docs home page.
addRoute({
path: normalizeUrl([
baseUrl,
homePageDocsRoutePath,
versionDocsPathPrefix,
]),
component: docLayoutComponent,
exact: true,
modules: {
docsMetadata: aliasedSource(docsBaseMetadataPath),
content: metadataItem.source,
},
});
}
await createData(
// Note that this created data path must be in sync with
// metadataPath provided to mdx-loader.
@ -438,15 +378,14 @@ Available document ids=
}),
);
return (
routes
// Do not create a route for a document serve as docs home page.
// TODO: need way to do this filtering when generating routes for better perf.
.filter(({path}) => !isDocsHomePagePath(path))
.sort((a, b) => (a.path > b.path ? 1 : b.path > a.path ? -1 : 0))
return routes.sort((a, b) =>
a.path > b.path ? 1 : b.path > a.path ? -1 : 0,
);
};
// This is the base route of the document root (for a doc given version)
// (/docs, /docs/next, /docs/1.0 etc...)
// The component applies the layout and renders the appropriate doc
const addBaseRoute = async (
docsBaseRoute: string,
docsBaseMetadata: DocsBaseMetadata,
@ -454,14 +393,20 @@ Available document ids=
priority?: number,
) => {
const docsBaseMetadataPath = await createData(
`${docuHash(docsBaseRoute)}.json`,
`${docuHash(normalizeUrl([docsBaseRoute, ':route']))}.json`,
JSON.stringify(docsBaseMetadata, null, 2),
);
// Important: the layout component should not end with /,
// as it conflicts with the home doc
// Workaround fix for https://github.com/facebook/docusaurus/issues/2917
const path = docsBaseRoute === '/' ? '' : docsBaseRoute;
addRoute({
path: docsBaseRoute,
component: docLayoutComponent,
routes,
path,
exact: false, // allow matching /docs/* as well
component: docLayoutComponent, // main docs component (DocPage)
routes, // subroute for each doc
modules: {
docsMetadata: aliasedSource(docsBaseMetadataPath),
},
@ -499,21 +444,20 @@ Available document ids=
);
const isLatestVersion = version === versioning.latestVersion;
const docsBasePermalink = normalizeUrl([
const docsBaseRoute = normalizeUrl([
baseUrl,
routeBasePath,
isLatestVersion ? '' : version,
]);
const docsBaseRoute = normalizeUrl([docsBasePermalink, ':route']);
const docsBaseMetadata = createDocsBaseMetadata(version);
// We want latest version route config to be placed last in the
// generated routeconfig. Otherwise, `/docs/next/foo` will match
// `/docs/:route` instead of `/docs/next/:route`.
return addBaseRoute(
docsBaseRoute,
docsBaseMetadata,
routes,
// We want latest version route config to be placed last in the
// generated routeconfig. Otherwise, `/docs/next/foo` will match
// `/docs/:route` instead of `/docs/next/:route`.
isLatestVersion ? -1 : undefined,
);
}),
@ -521,8 +465,7 @@ Available document ids=
} else {
const routes = await genRoutes(Object.values(content.docsMetadata));
const docsBaseMetadata = createDocsBaseMetadata();
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath, ':route']);
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath]);
return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
}
},