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

fix(plugin-docs,theme): refactor docs plugin routes and component tree #7966

Merged
merged 15 commits into from
Aug 18, 2022

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('normalizeDocsPluginOptions', () => {
sidebarPath: 'my-sidebar', // Path to sidebar configuration for showing a list of markdown pages.
sidebarItemsGenerator: DefaultSidebarItemsGenerator,
numberPrefixParser: DefaultNumberPrefixParser,
docVersionLayoutComponent: '@theme/DocVersionPage',
docLayoutComponent: '@theme/DocPage',
docItemComponent: '@theme/DocItem',
docTagDocListComponent: '@theme/DocTagDocListPage',
Expand Down
110 changes: 11 additions & 99 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,18 @@ import {
addDocNavigation,
type DocEnv,
} from './docs';
import {readVersionsMetadata} from './versions';
import {readVersionsMetadata, toFullVersion} from './versions';
import {cliDocsVersionCommand} from './cli';
import {VERSIONS_JSON_FILE} from './constants';
import {toGlobalDataVersion} from './globalData';
import {toTagDocListProp} from './props';
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
import {
translateLoadedContent,
getLoadedContentTranslationFiles,
} from './translations';
import {getVersionTags} from './tags';
import {createVersionRoutes} from './routes';
import {createAllRoutes} from './routes';
import {createSidebarsUtils} from './sidebars/utils';

import type {
PropTagsListPage,
PluginOptions,
DocMetadataBase,
VersionMetadata,
Expand All @@ -55,7 +51,6 @@ import type {
SourceToPermalink,
DocFile,
DocsMarkdownOption,
VersionTag,
FullVersion,
} from './types';
import type {RuleSetRule} from 'webpack';
Expand Down Expand Up @@ -209,102 +204,19 @@ export default async function pluginContentDocs(
},

async contentLoaded({content, actions}) {
const {loadedVersions} = content;
const {
docLayoutComponent,
docItemComponent,
docCategoryGeneratedIndexComponent,
breadcrumbs,
} = options;
const {addRoute, createData, setGlobalData} = actions;
const versions: FullVersion[] = loadedVersions.map((version) => {
const sidebarsUtils = createSidebarsUtils(version.sidebars);
return {
...version,
sidebarsUtils,
categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
docs: version.docs,
sidebarsUtils,
}),
};
});

async function createVersionTagsRoutes(version: FullVersion) {
const versionTags = getVersionTags(version.docs);

// TODO tags should be a sub route of the version route
async function createTagsListPage() {
const tagsProp: PropTagsListPage['tags'] = Object.values(
versionTags,
).map((tagValue) => ({
label: tagValue.label,
permalink: tagValue.permalink,
count: tagValue.docIds.length,
}));

// Only create /tags page if there are tags.
if (tagsProp.length > 0) {
const tagsPropPath = await createData(
`${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
JSON.stringify(tagsProp, null, 2),
);
addRoute({
path: version.tagsPath,
exact: true,
component: options.docTagsListComponent,
modules: {
tags: aliasedSource(tagsPropPath),
},
});
}
}
const versions: FullVersion[] = content.loadedVersions.map(toFullVersion);

// TODO tags should be a sub route of the version route
async function createTagDocListPage(tag: VersionTag) {
const tagProps = toTagDocListProp({
allTagsPath: version.tagsPath,
tag,
docs: version.docs,
});
const tagPropPath = await createData(
`${docuHash(`tag-${tag.permalink}`)}.json`,
JSON.stringify(tagProps, null, 2),
);
addRoute({
path: tag.permalink,
component: options.docTagDocListComponent,
exact: true,
modules: {
tag: aliasedSource(tagPropPath),
},
});
}

await createTagsListPage();
await Promise.all(Object.values(versionTags).map(createTagDocListPage));
}

await Promise.all(
versions.map((version) =>
createVersionRoutes({
version,
docItemComponent,
docLayoutComponent,
docCategoryGeneratedIndexComponent,
pluginId,
aliasedSource,
actions,
}),
),
);

// TODO tags should be a sub route of the version route
await Promise.all(versions.map(createVersionTagsRoutes));
await createAllRoutes({
versions,
options,
actions,
aliasedSource,
});

setGlobalData({
actions.setGlobalData({
path: normalizeUrl([baseUrl, options.routeBasePath]),
versions: versions.map(toGlobalDataVersion),
breadcrumbs,
breadcrumbs: options.breadcrumbs,
});
},

Expand Down
4 changes: 4 additions & 0 deletions packages/docusaurus-plugin-content-docs/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
exclude: GlobExcludeDefault,
sidebarItemsGenerator: DefaultSidebarItemsGenerator,
numberPrefixParser: DefaultNumberPrefixParser,
docVersionLayoutComponent: '@theme/DocVersionPage',
docLayoutComponent: '@theme/DocPage',
docItemComponent: '@theme/DocItem',
docTagDocListComponent: '@theme/DocTagDocListPage',
Expand Down Expand Up @@ -104,6 +105,9 @@ const OptionsSchema = Joi.object<PluginOptions>({
}),
)
.default(() => DEFAULT_OPTIONS.numberPrefixParser),
docVersionLayoutComponent: Joi.string().default(
DEFAULT_OPTIONS.docVersionLayoutComponent,
),
docLayoutComponent: Joi.string().default(DEFAULT_OPTIONS.docLayoutComponent),
docItemComponent: Joi.string().default(DEFAULT_OPTIONS.docItemComponent),
docTagsListComponent: Joi.string().default(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,17 @@ declare module '@docusaurus/plugin-content-docs' {
*/
exclude: string[];
/**
* Root layout component of each doc page. Provides the version data
* context, and is not unmounted when switching docs.
* Parent layout component of all versioned docs pages:
* - docs pages with sidebars
* - tags pages
* Stays mounted when navigation between such pages.
*/
docVersionLayoutComponent: string;
/**
* Parent layout component of docs pages with sidebars:
* - regular docs pages
* - category generated index pages
* Stays mounted when navigation between such pages.
*/
docLayoutComponent: string;
/** Main doc container, with TOC, pagination, etc. */
Expand Down Expand Up @@ -610,14 +619,23 @@ declare module '@theme/DocBreadcrumbs' {
export default function DocBreadcrumbs(): JSX.Element;
}

declare module '@theme/DocPage' {
declare module '@theme/DocVersionPage' {
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs';
import type {RouteConfigComponentProps} from 'react-router-config';
import type {Required} from 'utility-types';

export interface Props extends Required<RouteConfigComponentProps, 'route'> {
readonly versionMetadata: PropVersionMetadata;
readonly version: PropVersionMetadata;
}

export default function DocPage(props: Props): JSX.Element;
}

declare module '@theme/DocPage' {
import type {RouteConfigComponentProps} from 'react-router-config';
import type {Required} from 'utility-types';

export interface Props extends Required<RouteConfigComponentProps, 'route'> {}

export default function DocPage(props: Props): JSX.Element;
}
13 changes: 12 additions & 1 deletion packages/docusaurus-plugin-content-docs/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import _ from 'lodash';
import {createDocsByIdIndex} from './docs';
import type {VersionTag} from './types';
import type {VersionTag, VersionTags} from './types';
import type {
SidebarItemDoc,
SidebarItem,
Expand All @@ -21,6 +21,7 @@ import type {
PropSidebarItemCategory,
PropTagDocList,
PropTagDocListDoc,
PropTagsListPage,
PropSidebarItemLink,
PropVersionDocs,
DocMetadata,
Expand Down Expand Up @@ -181,3 +182,13 @@ export function toTagDocListProp({
items: toDocListProp(),
};
}

export function toTagsListTagsProp(
versionTags: VersionTags,
): PropTagsListPage['tags'] {
return Object.values(versionTags).map((tagValue) => ({
label: tagValue.label,
permalink: tagValue.permalink,
count: tagValue.docIds.length,
}));
}