mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-24 21:48:02 +02:00
feat(v2): allow home page for docs (#2652)
* feat(v2): allow home page for docs
* Refactor
* Remove debugging info 🤦♂️
* Add sort routes for first test case
* Sort child routes for consistency
This commit is contained in:
parent
393adc5324
commit
00a8e9e365
12 changed files with 264 additions and 61 deletions
|
@ -52,6 +52,15 @@ Object {
|
|||
|
||||
exports[`simple website content 2`] = `
|
||||
Array [
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"exact": true,
|
||||
"modules": Object {
|
||||
"content": "@site/docs/hello.md",
|
||||
"docsMetadata": "~docs/site-docs-hello-md-9df-base.json",
|
||||
},
|
||||
"path": "/docs",
|
||||
},
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"modules": Object {
|
||||
|
@ -107,6 +116,33 @@ Array [
|
|||
|
||||
exports[`versioned website content 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"exact": true,
|
||||
"modules": Object {
|
||||
"content": "@site/versioned_docs/version-1.0.1/hello.md",
|
||||
"docsMetadata": "~docs/site-versioned-docs-version-1-0-1-hello-md-0c7-base.json",
|
||||
},
|
||||
"path": "/docs",
|
||||
},
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"exact": true,
|
||||
"modules": Object {
|
||||
"content": "@site/versioned_docs/version-1.0.0/hello.md",
|
||||
"docsMetadata": "~docs/site-versioned-docs-version-1-0-0-hello-md-3ef-base.json",
|
||||
},
|
||||
"path": "/docs/1.0.0",
|
||||
},
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"exact": true,
|
||||
"modules": Object {
|
||||
"content": "@site/docs/hello.md",
|
||||
"docsMetadata": "~docs/site-docs-hello-md-9df-base.json",
|
||||
},
|
||||
"path": "/docs/next",
|
||||
},
|
||||
Object {
|
||||
"component": "@theme/DocPage",
|
||||
"modules": Object {
|
||||
|
|
|
@ -93,6 +93,7 @@ describe('simple website', () => {
|
|||
const plugin = pluginContentDocs(context, {
|
||||
path: pluginPath,
|
||||
sidebarPath,
|
||||
homePageId: 'hello',
|
||||
});
|
||||
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
|
||||
|
||||
|
@ -203,6 +204,9 @@ describe('simple website', () => {
|
|||
expect(baseMetadata.docsSidebars).toEqual(docsSidebars);
|
||||
expect(baseMetadata.permalinkToSidebar).toEqual(permalinkToSidebar);
|
||||
|
||||
// Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering
|
||||
sortConfig(routeConfigs);
|
||||
|
||||
expect(routeConfigs).not.toEqual([]);
|
||||
expect(routeConfigs).toMatchSnapshot();
|
||||
});
|
||||
|
@ -216,6 +220,7 @@ describe('versioned website', () => {
|
|||
const plugin = pluginContentDocs(context, {
|
||||
routeBasePath,
|
||||
sidebarPath,
|
||||
homePageId: 'hello',
|
||||
});
|
||||
const env = loadEnv(siteDir);
|
||||
const {docsDir: versionedDir} = env.versioning;
|
||||
|
|
|
@ -48,9 +48,12 @@ import {Configuration} from 'webpack';
|
|||
import {docsVersion} from './version';
|
||||
import {VERSIONS_JSON_FILE} from './constants';
|
||||
|
||||
const REVERSED_DOCS_HOME_PAGE_ID = '_index';
|
||||
|
||||
const DEFAULT_OPTIONS: PluginOptions = {
|
||||
path: 'docs', // Path to data on filesystem, relative to site dir.
|
||||
routeBasePath: 'docs', // URL Route.
|
||||
homePageId: REVERSED_DOCS_HOME_PAGE_ID, // Document id for docs home page.
|
||||
include: ['**/*.{md,mdx}'], // Extensions to include.
|
||||
sidebarPath: '', // Path to sidebar configuration for showing a list of markdown pages.
|
||||
docLayoutComponent: '@theme/DocPage',
|
||||
|
@ -313,28 +316,96 @@ export default function pluginContentDocs(
|
|||
const aliasedSource = (source: string) =>
|
||||
`~docs/${path.relative(dataDir, source)}`;
|
||||
|
||||
const createDocsBaseMetadata = (version?: string): DocsBaseMetadata => {
|
||||
const {docsSidebars, permalinkToSidebar, versionToSidebars} = content;
|
||||
const neededSidebars: Set<string> =
|
||||
versionToSidebars[version!] || new Set();
|
||||
|
||||
return {
|
||||
docsSidebars: version
|
||||
? pick(docsSidebars, Array.from(neededSidebars))
|
||||
: docsSidebars,
|
||||
permalinkToSidebar: version
|
||||
? pickBy(permalinkToSidebar, (sidebar) =>
|
||||
neededSidebars.has(sidebar),
|
||||
)
|
||||
: permalinkToSidebar,
|
||||
version,
|
||||
};
|
||||
};
|
||||
|
||||
const genRoutes = async (
|
||||
metadataItems: Metadata[],
|
||||
): Promise<RouteConfig[]> => {
|
||||
const routes = await Promise.all(
|
||||
metadataItems.map(async (metadataItem) => {
|
||||
await createData(
|
||||
// Note that this created data path must be in sync with
|
||||
// metadataPath provided to mdx-loader.
|
||||
`${docuHash(metadataItem.source)}.json`,
|
||||
JSON.stringify(metadataItem, null, 2),
|
||||
const routes: RouteConfig[] = [];
|
||||
|
||||
await metadataItems.forEach(async (metadataItem, i) => {
|
||||
const isDocsHomePage =
|
||||
metadataItem.id.substr(metadataItem.id.indexOf('/') + 1) ===
|
||||
options.homePageId;
|
||||
|
||||
if (isDocsHomePage) {
|
||||
const homeDocsRoutePath =
|
||||
routeBasePath === '' ? '/' : routeBasePath;
|
||||
const versionDocsPathPrefix =
|
||||
(metadataItem?.version === versioning.latestVersion
|
||||
? ''
|
||||
: metadataItem.version!) ?? '';
|
||||
|
||||
// To show the sidebar, get the sidebar key of available sibling item.
|
||||
metadataItem.sidebar = (
|
||||
metadataItems[i - 1] ?? metadataItems[i + 1]
|
||||
).sidebar;
|
||||
const docsBaseMetadata = createDocsBaseMetadata(
|
||||
metadataItem.version!,
|
||||
);
|
||||
docsBaseMetadata.isHomePage = true;
|
||||
docsBaseMetadata.homePagePath = normalizeUrl([
|
||||
baseUrl,
|
||||
homeDocsRoutePath,
|
||||
versionDocsPathPrefix,
|
||||
options.homePageId,
|
||||
]);
|
||||
const docsBaseMetadataPath = await createData(
|
||||
`${docuHash(metadataItem.source)}-base.json`,
|
||||
JSON.stringify(docsBaseMetadata, null, 2),
|
||||
);
|
||||
|
||||
return {
|
||||
// Add a route for docs home page.
|
||||
addRoute({
|
||||
path: normalizeUrl([
|
||||
baseUrl,
|
||||
homeDocsRoutePath,
|
||||
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.
|
||||
`${docuHash(metadataItem.source)}.json`,
|
||||
JSON.stringify(metadataItem, null, 2),
|
||||
);
|
||||
|
||||
// Do not create a route for a page created specifically for docs home page.
|
||||
if (metadataItem.id !== REVERSED_DOCS_HOME_PAGE_ID) {
|
||||
routes.push({
|
||||
path: metadataItem.permalink,
|
||||
component: docItemComponent,
|
||||
exact: true,
|
||||
modules: {
|
||||
content: metadataItem.source,
|
||||
},
|
||||
};
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return routes.sort((a, b) =>
|
||||
a.path > b.path ? 1 : b.path > a.path ? -1 : 0,
|
||||
|
@ -383,19 +454,7 @@ export default function pluginContentDocs(
|
|||
isLatestVersion ? '' : version,
|
||||
]);
|
||||
const docsBaseRoute = normalizeUrl([docsBasePermalink, ':route']);
|
||||
const neededSidebars: Set<string> =
|
||||
content.versionToSidebars[version] || new Set();
|
||||
const docsBaseMetadata: DocsBaseMetadata = {
|
||||
docsSidebars: pick(
|
||||
content.docsSidebars,
|
||||
Array.from(neededSidebars),
|
||||
),
|
||||
permalinkToSidebar: pickBy(
|
||||
content.permalinkToSidebar,
|
||||
(sidebar) => neededSidebars.has(sidebar),
|
||||
),
|
||||
version,
|
||||
};
|
||||
const docsBaseMetadata = createDocsBaseMetadata(version);
|
||||
|
||||
// We want latest version route config to be placed last in the
|
||||
// generated routeconfig. Otherwise, `/docs/next/foo` will match
|
||||
|
@ -410,16 +469,31 @@ export default function pluginContentDocs(
|
|||
);
|
||||
} else {
|
||||
const routes = await genRoutes(Object.values(content.docsMetadata));
|
||||
const docsBaseMetadata: DocsBaseMetadata = {
|
||||
docsSidebars: content.docsSidebars,
|
||||
permalinkToSidebar: content.permalinkToSidebar,
|
||||
};
|
||||
const docsBaseMetadata = createDocsBaseMetadata();
|
||||
|
||||
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath, ':route']);
|
||||
return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
|
||||
}
|
||||
},
|
||||
|
||||
async routesLoaded(routes) {
|
||||
const normalizedHomeDocsRoutePath = `/${options.routeBasePath}`;
|
||||
const homeDocsRoutes = routes.filter(
|
||||
(routeConfig) => routeConfig.path === normalizedHomeDocsRoutePath,
|
||||
);
|
||||
|
||||
// Remove the route for docs home page if there is a page with the same path (i.e. docs).
|
||||
if (homeDocsRoutes.length > 1) {
|
||||
const docsHomePageRouteIndex = routes.findIndex(
|
||||
(route) =>
|
||||
route.component === options.docLayoutComponent &&
|
||||
route.path === normalizedHomeDocsRoutePath,
|
||||
);
|
||||
|
||||
delete routes[docsHomePageRouteIndex!];
|
||||
}
|
||||
},
|
||||
|
||||
configureWebpack(_config, isServer, utils) {
|
||||
const {getBabelLoader, getCacheLoader} = utils;
|
||||
const {rehypePlugins, remarkPlugins} = options;
|
||||
|
|
|
@ -24,6 +24,7 @@ export interface PluginOptions extends MetadataOptions, PathOptions {
|
|||
remarkPlugins: ([Function, object] | Function)[];
|
||||
rehypePlugins: string[];
|
||||
admonitions: any;
|
||||
homePageId: string;
|
||||
}
|
||||
|
||||
export type SidebarItemDoc = {
|
||||
|
@ -160,6 +161,8 @@ export type DocsBaseMetadata = Pick<
|
|||
'docsSidebars' | 'permalinkToSidebar'
|
||||
> & {
|
||||
version?: string;
|
||||
isHomePage?: boolean;
|
||||
homePagePath?: string;
|
||||
};
|
||||
|
||||
export type VersioningEnv = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue