refactor(content-docs): deduplicate types, JSDoc for some APIs (#7027)

* refactor(content-docs): deduplicate types, JSDoc for some APIs

* little refactor
This commit is contained in:
Joshua Chen 2022-03-27 12:57:15 +08:00 committed by GitHub
parent b842197ac6
commit 2bcac29cd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 715 additions and 521 deletions

View file

@ -21,21 +21,21 @@ import toc from './remark/toc';
import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks';
import transformImage from './remark/transformImage';
import transformLinks from './remark/transformLinks';
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
import type {MDXOptions} from '@docusaurus/mdx-loader';
import type {LoaderContext} from 'webpack';
const {
loaders: {inlineMarkdownImageFileLoader},
} = getFileLoaderUtils();
const DEFAULT_OPTIONS: RemarkAndRehypePluginOptions = {
const DEFAULT_OPTIONS: MDXOptions = {
rehypePlugins: [],
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
beforeDefaultRemarkPlugins: [],
beforeDefaultRehypePlugins: [],
};
type Options = RemarkAndRehypePluginOptions & {
type Options = MDXOptions & {
staticDirs: string[];
siteDir: string;
isMDXPartial?: (filePath: string) => boolean;

View file

@ -7,12 +7,12 @@
import type {Plugin} from 'unified';
export type RemarkOrRehypePlugin =
export type MDXPlugin =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[Plugin<any[]>, any] | Plugin<any[]>;
export type RemarkAndRehypePluginOptions = {
remarkPlugins: RemarkOrRehypePlugin[];
rehypePlugins: RemarkOrRehypePlugin[];
beforeDefaultRemarkPlugins: RemarkOrRehypePlugin[];
beforeDefaultRehypePlugins: RemarkOrRehypePlugin[];
export type MDXOptions = {
remarkPlugins: MDXPlugin[];
rehypePlugins: MDXPlugin[];
beforeDefaultRemarkPlugins: MDXPlugin[];
beforeDefaultRehypePlugins: MDXPlugin[];
};

View file

@ -6,8 +6,8 @@
*/
declare module '@docusaurus/plugin-content-blog' {
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
import type {FrontMatterTag} from '@docusaurus/utils';
import type {MDXOptions} from '@docusaurus/mdx-loader';
import type {FrontMatterTag, Tag} from '@docusaurus/utils';
import type {Overwrite} from 'utility-types';
export interface Assets {
@ -81,10 +81,7 @@ declare module '@docusaurus/plugin-content-blog' {
* @see {@link BlogPostMetadata.tags}
*/
tags?: FrontMatterTag[];
/**
* Custom slug appended after /<baseUrl>/<routeBasePath>/
* @see {@link BlogPostMetadata.slug}
*/
/** Custom slug appended after `/<baseUrl>/<routeBasePath>/` */
slug?: string;
/**
* Marks the post as draft and excludes it from the production build.
@ -130,25 +127,18 @@ declare module '@docusaurus/plugin-content-blog' {
/** @deprecated v1 legacy */
authorImageURL?: string;
/**
* @see {@link BlogPostMetadata.image}
*/
/** Used in the head meta. Should use `assets.image` in priority. */
image?: string;
/**
* Used in the head meta
*/
/** Used in the head meta. */
keywords?: string[];
/**
* Hide the right TOC
*/
/** Hide the right TOC. */
hide_table_of_contents?: boolean;
/**
* Minimum TOC heading level
* Minimum TOC heading level. Must be between 2 and 6 and lower or equal to
* the max value.
*/
toc_min_heading_level?: number;
/**
* Maximum TOC heading level
*/
/** Maximum TOC heading level. Must be between 2 and 6. */
toc_max_heading_level?: number;
};
@ -175,9 +165,7 @@ declare module '@docusaurus/plugin-content-blog' {
| (string | BlogPostFrontMatterAuthor)[];
export type BlogPostMetadata = {
/**
* Path to the Markdown source, with `@site` alias.
*/
/** Path to the Markdown source, with `@site` alias. */
readonly source: string;
/**
* Used to generate the page h1 heading, tab title, and pagination title.
@ -193,9 +181,7 @@ declare module '@docusaurus/plugin-content-blog' {
* render the date regardless of the existence of `Intl.DateTimeFormat`.
*/
readonly formattedDate: string;
/**
* Full link including base URL.
*/
/** Full link including base URL. */
readonly permalink: string;
/**
* Description used in the meta. Could be an empty string (empty content)
@ -229,17 +215,10 @@ declare module '@docusaurus/plugin-content-blog' {
* `assets.authorsImageUrls` on client side.
*/
readonly authors: Author[];
/**
* Front matter, as-is.
*/
/** Front matter, as-is. */
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
/**
* Tags, normalized.
*/
readonly tags: readonly {
readonly label: string;
readonly permalink: string;
}[];
/** Tags, normalized. */
readonly tags: Tag[];
};
/**
* @returns The edit URL that's directly plugged into metadata.
@ -250,17 +229,11 @@ declare module '@docusaurus/plugin-content-blog' {
* site path. Usually the same as `options.path` but can be localized
*/
blogDirPath: string;
/**
* Path to this post file, relative to `blogDirPath`
*/
/** Path to this post file, relative to `blogDirPath`. */
blogPath: string;
/**
* @see {@link BlogPostMetadata.permalink}
*/
/** @see {@link BlogPostMetadata.permalink} */
permalink: string;
/**
* Locale name.
*/
/** Locale name. */
locale: string;
}) => string | undefined;
@ -325,7 +298,7 @@ declare module '@docusaurus/plugin-content-blog' {
/**
* Plugin options after normalization.
*/
export type PluginOptions = RemarkAndRehypePluginOptions & {
export type PluginOptions = MDXOptions & {
/** Plugin ID. */
id?: string;
/**

View file

@ -169,7 +169,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
"isLast": true,
"label": "current label (translated)",
"mainDocId": "",
"path": "/docs/",
"routePriority": undefined,
"sidebarFilePath": "any",
"sidebars": {
@ -221,9 +223,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
},
"versionLabel": "current label (translated)",
"versionName": "current",
"versionPath": "/docs/",
},
{
"contentPath": "any",
@ -311,7 +311,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
"isLast": true,
"label": "2.0.0 label (translated)",
"mainDocId": "",
"path": "/docs/",
"routePriority": undefined,
"sidebarFilePath": "any",
"sidebars": {
@ -363,9 +365,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
},
"versionLabel": "2.0.0 label (translated)",
"versionName": "2.0.0",
"versionPath": "/docs/",
},
{
"contentPath": "any",
@ -453,7 +453,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
"isLast": true,
"label": "1.0.0 label (translated)",
"mainDocId": "",
"path": "/docs/",
"routePriority": undefined,
"sidebarFilePath": "any",
"sidebars": {
@ -505,9 +507,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
},
],
},
"versionLabel": "1.0.0 label (translated)",
"versionName": "1.0.0",
"versionPath": "/docs/",
},
],
}

View file

@ -18,16 +18,14 @@ import {
import {loadSidebars} from '../sidebars';
import type {Sidebars} from '../sidebars/types';
import {readVersionsMetadata} from '../versions';
import type {
DocFile,
DocMetadataBase,
VersionMetadata,
DocNavLink,
} from '../types';
import type {DocFile} from '../types';
import type {
MetadataOptions,
PluginOptions,
EditUrlFunction,
DocMetadataBase,
VersionMetadata,
PropNavigationLink,
} from '@docusaurus/plugin-content-docs';
import type {LoadContext} from '@docusaurus/types';
import {DEFAULT_OPTIONS} from '../options';
@ -123,7 +121,11 @@ function createTestUtils({
}
async function generateNavigation(docFiles: DocFile[]): Promise<{
pagination: {prev?: DocNavLink; next?: DocNavLink; id: string}[];
pagination: {
prev?: PropNavigationLink;
next?: PropNavigationLink;
id: string;
}[];
sidebars: Sidebars;
}> {
const rawDocs = docFiles.map((docFile) =>

View file

@ -6,7 +6,7 @@
*/
import {validateDocFrontMatter} from '../frontMatter';
import type {DocFrontMatter} from '../types';
import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
import escapeStringRegexp from 'escape-string-regexp';
function testField(params: {

View file

@ -12,9 +12,9 @@ describe('toGlobalDataVersion', () => {
expect(
toGlobalDataVersion({
versionName: 'current',
versionLabel: 'Label',
label: 'Label',
isLast: true,
versionPath: '/current',
path: '/current',
mainDocId: 'main',
docs: [
{
@ -86,9 +86,9 @@ describe('toGlobalDataVersion', () => {
sidebar: 'tutorial',
},
],
versionBanner: 'unreleased',
versionBadge: true,
versionClassName: 'current-cls',
banner: 'unreleased',
badge: true,
className: 'current-cls',
tagsPath: '/current/tags',
contentPath: '',
contentPathLocalized: '',

View file

@ -16,7 +16,7 @@ describe('toTagDocListProp', () => {
it('works', () => {
const tag: Tag = {
name: 'tag1',
label: 'tag1',
permalink: '/tag1',
docIds: ['id1', 'id3'],
};
@ -54,7 +54,7 @@ describe('toTagDocListProp', () => {
expect(result).toEqual({
allTagsPath,
name: tag.name,
name: tag.label,
permalink: tag.permalink,
docs: [doc3, doc1], // docs sorted by title, ignore "id5" absence
});

View file

@ -5,12 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
import type {LoadedContent, DocMetadata, LoadedVersion} from '../types';
import type {LoadedContent, LoadedVersion} from '../types';
import {CURRENT_VERSION_NAME} from '../constants';
import {
getLoadedContentTranslationFiles,
translateLoadedContent,
} from '../translations';
import type {DocMetadata} from '@docusaurus/plugin-content-docs';
import {updateTranslationFileMessages} from '@docusaurus/utils';
function createSampleDoc(doc: Pick<DocMetadata, 'id'>): DocMetadata {
@ -36,8 +37,8 @@ function createSampleVersion(
version: Pick<LoadedVersion, 'versionName'>,
): LoadedVersion {
return {
versionLabel: `${version.versionName} label`,
versionPath: '/docs/',
label: `${version.versionName} label`,
path: '/docs/',
mainDocId: '',
routePriority: undefined,
sidebarFilePath: 'any',
@ -45,21 +46,11 @@ function createSampleVersion(
contentPath: 'any',
contentPathLocalized: 'any',
docs: [
createSampleDoc({
id: 'doc1',
}),
createSampleDoc({
id: 'doc2',
}),
createSampleDoc({
id: 'doc3',
}),
createSampleDoc({
id: 'doc4',
}),
createSampleDoc({
id: 'doc5',
}),
createSampleDoc({id: 'doc1'}),
createSampleDoc({id: 'doc2'}),
createSampleDoc({id: 'doc3'}),
createSampleDoc({id: 'doc4'}),
createSampleDoc({id: 'doc5'}),
],
sidebars: {
docs: [

View file

@ -15,9 +15,11 @@ import {
} from '../versions';
import {DEFAULT_OPTIONS} from '../options';
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
import type {VersionMetadata} from '../types';
import type {I18n} from '@docusaurus/types';
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
import type {
PluginOptions,
VersionMetadata,
} from '@docusaurus/plugin-content-docs';
const DefaultI18N: I18n = {
currentLocale: 'en',
@ -85,12 +87,12 @@ describe('readVersionsMetadata', () => {
routePriority: -1,
sidebarFilePath: undefined,
tagsPath: '/docs/tags',
versionLabel: 'Next',
label: 'Next',
versionName: 'current',
versionPath: '/docs',
versionBanner: null,
versionBadge: false,
versionClassName: 'docs-version-current',
path: '/docs',
banner: null,
badge: false,
className: 'docs-version-current',
};
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
}
@ -120,7 +122,7 @@ describe('readVersionsMetadata', () => {
expect(versionsMetadata).toEqual([
{
...vCurrent,
versionPath: '/myBaseUrl/docs',
path: '/myBaseUrl/docs',
tagsPath: '/myBaseUrl/docs/tags',
},
]);
@ -148,13 +150,13 @@ describe('readVersionsMetadata', () => {
expect(versionsMetadata).toEqual([
{
...vCurrent,
versionPath: '/myBaseUrl/docs/current-path',
versionLabel: 'current-label',
path: '/myBaseUrl/docs/current-path',
label: 'current-label',
routePriority: undefined,
sidebarFilePath: undefined,
tagsPath: '/myBaseUrl/docs/current-path/tags',
versionEditUrl: undefined,
versionEditUrlLocalized: undefined,
editUrl: undefined,
editUrlLocalized: undefined,
},
]);
});
@ -245,12 +247,12 @@ describe('readVersionsMetadata', () => {
routePriority: undefined,
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
tagsPath: '/docs/next/tags',
versionLabel: 'Next',
label: 'Next',
versionName: 'current',
versionPath: '/docs/next',
versionBanner: 'unreleased',
versionBadge: true,
versionClassName: 'docs-version-current',
path: '/docs/next',
banner: 'unreleased',
badge: true,
className: 'docs-version-current',
};
const v101: VersionMetadata = {
@ -269,12 +271,12 @@ describe('readVersionsMetadata', () => {
'versioned_sidebars/version-1.0.1-sidebars.json',
),
tagsPath: '/docs/tags',
versionLabel: '1.0.1',
label: '1.0.1',
versionName: '1.0.1',
versionPath: '/docs',
versionBanner: null,
versionBadge: true,
versionClassName: 'docs-version-1.0.1',
path: '/docs',
banner: null,
badge: true,
className: 'docs-version-1.0.1',
};
const v100: VersionMetadata = {
@ -293,12 +295,12 @@ describe('readVersionsMetadata', () => {
'versioned_sidebars/version-1.0.0-sidebars.json',
),
tagsPath: '/docs/1.0.0/tags',
versionLabel: '1.0.0',
label: '1.0.0',
versionName: '1.0.0',
versionPath: '/docs/1.0.0',
versionBanner: 'unmaintained',
versionBadge: true,
versionClassName: 'docs-version-1.0.0',
path: '/docs/1.0.0',
banner: 'unmaintained',
badge: true,
className: 'docs-version-1.0.0',
};
const vWithSlugs: VersionMetadata = {
@ -317,12 +319,12 @@ describe('readVersionsMetadata', () => {
'versioned_sidebars/version-withSlugs-sidebars.json',
),
tagsPath: '/docs/withSlugs/tags',
versionLabel: 'withSlugs',
label: 'withSlugs',
versionName: 'withSlugs',
versionPath: '/docs/withSlugs',
versionBanner: 'unmaintained',
versionBadge: true,
versionClassName: 'docs-version-withSlugs',
path: '/docs/withSlugs',
banner: 'unmaintained',
badge: true,
className: 'docs-version-withSlugs',
};
return {
@ -393,27 +395,27 @@ describe('readVersionsMetadata', () => {
{
...vCurrent,
tagsPath: '/docs/current-path/tags',
versionPath: '/docs/current-path',
versionBanner: 'unmaintained',
versionBadge: false,
versionClassName: 'custom-current-className',
path: '/docs/current-path',
banner: 'unmaintained',
badge: false,
className: 'custom-current-className',
},
{
...v101,
isLast: false,
routePriority: undefined,
tagsPath: '/docs/1.0.1/tags',
versionPath: '/docs/1.0.1',
versionBanner: 'unreleased',
path: '/docs/1.0.1',
banner: 'unreleased',
},
{
...v100,
isLast: true,
routePriority: -1,
tagsPath: '/docs/tags',
versionLabel: '1.0.0-label',
versionPath: '/docs',
versionBanner: 'unreleased',
label: '1.0.0-label',
path: '/docs',
banner: 'unreleased',
},
vWithSlugs,
]);
@ -434,30 +436,30 @@ describe('readVersionsMetadata', () => {
expect(versionsMetadata).toEqual([
{
...vCurrent,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
},
{
...v101,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.1',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.1',
},
{
...v100,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.0',
},
{
...vWithSlugs,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-withSlugs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-withSlugs',
},
]);
@ -479,30 +481,30 @@ describe('readVersionsMetadata', () => {
expect(versionsMetadata).toEqual([
{
...vCurrent,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
},
{
...v101,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
},
{
...v100,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
},
{
...vWithSlugs,
versionEditUrl:
editUrl:
'https://github.com/facebook/docusaurus/edit/main/website/docs',
versionEditUrlLocalized:
editUrlLocalized:
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
},
]);
@ -538,9 +540,9 @@ describe('readVersionsMetadata', () => {
isLast: true,
routePriority: -1,
tagsPath: '/docs/tags',
versionPath: '/docs',
versionBanner: null,
versionBadge: false,
path: '/docs',
banner: null,
badge: false,
},
]);
});
@ -679,12 +681,12 @@ describe('readVersionsMetadata', () => {
routePriority: undefined,
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
tagsPath: '/communityBasePath/next/tags',
versionLabel: 'Next',
label: 'Next',
versionName: 'current',
versionPath: '/communityBasePath/next',
versionBanner: 'unreleased',
versionBadge: true,
versionClassName: 'docs-version-current',
path: '/communityBasePath/next',
banner: 'unreleased',
badge: true,
className: 'docs-version-current',
};
const v100: VersionMetadata = {
@ -703,12 +705,12 @@ describe('readVersionsMetadata', () => {
'community_versioned_sidebars/version-1.0.0-sidebars.json',
),
tagsPath: '/communityBasePath/tags',
versionLabel: '1.0.0',
label: '1.0.0',
versionName: '1.0.0',
versionPath: '/communityBasePath',
versionBanner: null,
versionBadge: true,
versionClassName: 'docs-version-1.0.0',
path: '/communityBasePath',
banner: null,
badge: true,
className: 'docs-version-1.0.0',
};
return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100};
@ -735,7 +737,7 @@ describe('readVersionsMetadata', () => {
expect(versionsMetadata).toEqual([
// vCurrent removed
{...v100, versionBadge: false},
{...v100, badge: false},
]);
});
@ -753,9 +755,9 @@ describe('readVersionsMetadata', () => {
isLast: true,
routePriority: -1,
tagsPath: '/communityBasePath/tags',
versionPath: '/communityBasePath',
versionBanner: null,
versionBadge: false,
path: '/communityBasePath',
banner: null,
badge: false,
},
]);
});

View file

@ -5,7 +5,10 @@
* LICENSE file in the root directory of this source tree.
*/
import type {CategoryGeneratedIndexMetadata, DocMetadataBase} from './types';
import type {
CategoryGeneratedIndexMetadata,
DocMetadataBase,
} from '@docusaurus/plugin-content-docs';
import type {SidebarItemCategoryWithGeneratedIndex} from './sidebars/types';
import {type SidebarsUtils, toNavigationLink} from './sidebars/utils';
import {createDocsByIdIndex} from './docs';
@ -29,8 +32,10 @@ function getCategoryGeneratedIndexMetadata({
slug: category.link.slug,
permalink: category.link.permalink,
sidebar: sidebarName!,
previous: toNavigationLink(previous, docsById),
next: toNavigationLink(next, docsById),
navigation: {
previous: toNavigationLink(previous, docsById),
next: toNavigationLink(next, docsById),
},
};
}

View file

@ -12,6 +12,7 @@ import {
aliasedSitePath,
getEditUrl,
getFolderContainingFile,
getContentPathList,
normalizeUrl,
parseMarkdownString,
posixPath,
@ -21,18 +22,9 @@ import {
import type {LoadContext} from '@docusaurus/types';
import {getFileLastUpdate} from './lastUpdate';
import type {
DocFile,
DocMetadataBase,
DocMetadata,
DocNavLink,
LastUpdateData,
VersionMetadata,
LoadedVersion,
} from './types';
import type {DocFile, LoadedVersion} from './types';
import getSlug from './slug';
import {CURRENT_VERSION_NAME} from './constants';
import {getDocsDirPaths} from './versions';
import {stripPathNumberPrefixes} from './numberPrefix';
import {validateDocFrontMatter} from './frontMatter';
import type {SidebarsUtils} from './sidebars/utils';
@ -41,7 +33,11 @@ import type {
MetadataOptions,
PluginOptions,
CategoryIndexMatcher,
CategoryIndexMatcherParam,
DocMetadataBase,
DocMetadata,
PropNavigationLink,
LastUpdateData,
VersionMetadata,
} from '@docusaurus/plugin-content-docs';
type LastUpdateOptions = Pick<
@ -85,7 +81,7 @@ export async function readDocFile(
options: LastUpdateOptions,
): Promise<DocFile> {
const contentPath = await getFolderContainingFile(
getDocsDirPaths(versionMetadata),
getContentPathList(versionMetadata),
source,
);
@ -213,7 +209,7 @@ function doProcessDocMetadata({
const description: string = frontMatter.description ?? excerpt ?? '';
const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]);
const permalink = normalizeUrl([versionMetadata.path, docSlug]);
function getDocEditUrl() {
const relativeFilePath = path.relative(contentPath, filePath);
@ -232,8 +228,8 @@ function doProcessDocMetadata({
const isLocalized = contentPath === versionMetadata.contentPathLocalized;
const baseVersionEditUrl =
isLocalized && options.editLocalizedFiles
? versionMetadata.versionEditUrlLocalized
: versionMetadata.versionEditUrl;
? versionMetadata.editUrlLocalized
: versionMetadata.editUrl;
return getEditUrl(relativeFilePath, baseVersionEditUrl);
}
return undefined;
@ -304,7 +300,7 @@ export function addDocNavigation(
const toNavigationLinkByDocId = (
docId: string | null | undefined,
type: 'prev' | 'next',
): DocNavLink | undefined => {
): PropNavigationLink | undefined => {
if (!docId) {
return undefined;
}
@ -401,7 +397,7 @@ export function toCategoryIndexMatcherParam({
}: Pick<
DocMetadataBase,
'source' | 'sourceDirName'
>): CategoryIndexMatcherParam {
>): Parameters<CategoryIndexMatcher>[0] {
// source + sourceDirName are always posix-style
return {
fileName: path.posix.parse(source).name,

View file

@ -12,7 +12,7 @@ import {
FrontMatterTOCHeadingLevels,
validateFrontMatter,
} from '@docusaurus/utils-validation';
import type {DocFrontMatter} from './types';
import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
// NOTE: we don't add any default value on purpose here
// We don't want default values to magically appear in doc metadata and props

View file

@ -8,11 +8,11 @@
import _ from 'lodash';
import type {Sidebars} from './sidebars/types';
import {createSidebarsUtils} from './sidebars/utils';
import type {LoadedVersion} from './types';
import type {
CategoryGeneratedIndexMetadata,
DocMetadata,
LoadedVersion,
} from './types';
} from '@docusaurus/plugin-content-docs';
import type {
GlobalVersion,
GlobalSidebar,
@ -65,9 +65,9 @@ function toGlobalSidebars(
export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
return {
name: version.versionName,
label: version.versionLabel,
label: version.label,
isLast: version.isLast,
path: version.versionPath,
path: version.path,
mainDocId: version.mainDocId,
docs: version.docs
.map(toGlobalDataDoc)

View file

@ -11,6 +11,7 @@ import {
normalizeUrl,
docuHash,
aliasedSitePath,
getContentPathList,
reportMessage,
posixPath,
addTrailingPathSeparator,
@ -27,18 +28,14 @@ import {
addDocNavigation,
getMainDocId,
} from './docs';
import {getDocsDirPaths, readVersionsMetadata} from './versions';
import {readVersionsMetadata} from './versions';
import type {
LoadedContent,
SourceToPermalink,
DocMetadataBase,
VersionMetadata,
LoadedVersion,
DocFile,
DocsMarkdownOption,
VersionTag,
DocFrontMatter,
} from './types';
import type {RuleSetRule} from 'webpack';
import {cliDocsVersionCommand} from './cli';
@ -55,6 +52,9 @@ import {createVersionRoutes} from './routes';
import type {
PropTagsListPage,
PluginOptions,
DocMetadataBase,
VersionMetadata,
DocFrontMatter,
} from '@docusaurus/plugin-content-docs';
import {createSidebarsUtils} from './sidebars/utils';
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
@ -114,7 +114,7 @@ export default async function pluginContentDocs(
function getVersionPathsToWatch(version: VersionMetadata): string[] {
const result = [
...options.include.flatMap((pattern) =>
getDocsDirPaths(version).map(
getContentPathList(version).map(
(docsDirPath) => `${docsDirPath}/${pattern}`,
),
),
@ -228,7 +228,7 @@ export default async function pluginContentDocs(
const tagsProp: PropTagsListPage['tags'] = Object.values(
versionTags,
).map((tagValue) => ({
name: tagValue.name,
name: tagValue.label,
permalink: tagValue.permalink,
count: tagValue.docIds.length,
}));
@ -331,7 +331,7 @@ export default async function pluginContentDocs(
};
function createMDXLoaderRule(): RuleSetRule {
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
const contentDirs = versionsMetadata.flatMap(getContentPathList);
return {
test: /\.mdx?$/i,
include: contentDirs

View file

@ -12,9 +12,9 @@ import {linkify} from '../linkify';
import type {
DocsMarkdownOption,
SourceToPermalink,
VersionMetadata,
DocBrokenMarkdownLink,
} from '../../types';
import type {VersionMetadata} from '@docusaurus/plugin-content-docs';
import {VERSIONED_DOCS_DIR, CURRENT_VERSION_NAME} from '../../constants';
function createFakeVersion({

View file

@ -6,12 +6,11 @@
*/
import type {DocsMarkdownOption} from '../types';
import {getDocsDirPaths} from '../versions';
import {replaceMarkdownLinks} from '@docusaurus/utils';
import {replaceMarkdownLinks, getContentPathList} from '@docusaurus/utils';
function getVersion(filePath: string, options: DocsMarkdownOption) {
const versionFound = options.versionsMetadata.find((version) =>
getDocsDirPaths(version).some((docsDirPath) =>
getContentPathList(version).some((docsDirPath) =>
filePath.startsWith(docsDirPath),
),
);

View file

@ -6,18 +6,25 @@
*/
declare module '@docusaurus/plugin-content-docs' {
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
import type {MDXOptions} from '@docusaurus/mdx-loader';
import type {ContentPaths, Tag, FrontMatterTag} from '@docusaurus/utils';
import type {Required} from 'utility-types';
export interface Assets {
image?: string;
}
/**
* Custom callback for parsing number prefixes from file/folder names.
*/
export type NumberPrefixParser = (filename: string) => {
/** file name without number prefix, without any other modification. */
filename: string;
/** The number prefix. Can be float, integer, negative, or anything. */
numberPrefix?: number;
};
export type CategoryIndexMatcherParam = {
export type CategoryIndexMatcher = (param: {
/** The file name, without extension */
fileName: string;
/**
@ -27,110 +34,442 @@ declare module '@docusaurus/plugin-content-docs' {
directories: string[];
/** The extension, with a leading dot */
extension: string;
};
export type CategoryIndexMatcher = (
param: CategoryIndexMatcherParam,
) => boolean;
}) => boolean;
export type EditUrlFunction = (editUrlParams: {
/** Name of the version. */
version: string;
/**
* Path of the version's root content path, relative to the site directory.
* Usually the same as `options.path` but can be localized or versioned.
*/
versionDocsDirPath: string;
/** Path of the doc file, relative to `versionDocsDirPath`. */
docPath: string;
/** @see {@link DocMetadata.permalink} */
permalink: string;
/** Locale name. */
locale: string;
}) => string | undefined;
export type MetadataOptions = {
/**
* URL route for the docs section of your site. **DO NOT** include a
* trailing slash. Use `/` for shipping docs without base path.
*/
routeBasePath: string;
/**
* Base URL to edit your site. The final URL is computed by `editUrl +
* relativeDocPath`. Using a function allows more nuanced control for each
* file. Omitting this variable entirely will disable edit links.
*/
editUrl?: string | EditUrlFunction;
/**
* The edit URL will always target the current version doc instead of older
* versions. Ignored when `editUrl` is a function.
*/
editCurrentVersion: boolean;
/**
* The edit URL will target the localized file, instead of the original
* unlocalized file. Ignored when `editUrl` is a function.
*/
editLocalizedFiles: boolean;
/** Whether to display the last date the doc was updated. */
showLastUpdateTime?: boolean;
/** Whether to display the author who last updated the doc. */
showLastUpdateAuthor?: boolean;
/**
* Custom parsing logic to extract number prefixes from file names. Use
* `false` to disable this behavior and leave the docs untouched, and `true`
* to use the default parser.
*
* @param filename One segment of the path, without any slashes.
* @see https://docusaurus.io/docs/sidebar#using-number-prefixes
*/
numberPrefixParser: NumberPrefixParser;
/** Enable or disable the breadcrumbs on doc pages. */
breadcrumbs: boolean;
};
export type PathOptions = {
/**
* Path to the docs content directory on the file system, relative to site
* directory.
*/
path: string;
/**
* Path to sidebar configuration. Use `false` to disable sidebars, or
* `undefined` to create a fully autogenerated sidebar.
*/
sidebarPath?: string | false | undefined;
};
// TODO support custom version banner?
// {type: "error", content: "html content"}
export type VersionBanner = 'unreleased' | 'unmaintained';
export type VersionOptions = {
path?: string;
label?: string;
banner?: 'none' | VersionBanner;
badge?: boolean;
className?: string;
};
export type VersionsOptions = {
/**
* The version navigated to in priority and displayed by default for docs
* navbar items.
*
* @see https://docusaurus.io/docs/versioning#terminology
*/
lastVersion?: string;
versions: {[versionName: string]: VersionOptions};
/** Only include a subset of all available versions. */
onlyIncludeVersions?: string[];
/**
* Explicitly disable versioning even when multiple versions exist. This
* will make the site only include the current version. Will error if
* `includeCurrentVersion: false` and `disableVersioning: true`.
*/
disableVersioning: boolean;
/** Include the current version of your docs. */
includeCurrentVersion: boolean;
/** Independent customization of each version's properties. */
versions: {
[versionName: string]: {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | VersionBanner;
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Add a custom class name to the <html> element of each doc. */
className?: string;
};
};
};
export type SidebarOptions = {
/**
* Whether sidebar categories are collapsible by default.
*
* @see https://docusaurus.io/docs/sidebar#collapsible-categories
*/
sidebarCollapsible: boolean;
/**
* Whether sidebar categories are collapsed by default.
*
* @see https://docusaurus.io/docs/sidebar#expanded-categories-by-default
*/
sidebarCollapsed: boolean;
};
export type PluginOptions = MetadataOptions &
PathOptions &
VersionsOptions &
RemarkAndRehypePluginOptions &
MDXOptions &
SidebarOptions & {
/** Plugin ID. */
id: string;
/**
* Array of glob patterns matching Markdown files to be built, relative to
* the content path.
*/
include: string[];
/**
* Array of glob patterns matching Markdown files to be excluded. Serves
* as refinement based on the `include` option.
*/
exclude: string[];
/**
* Root layout component of each doc page. Provides the version data
* context, and is not unmounted when switching docs.
*/
docLayoutComponent: string;
/** Main doc container, with TOC, pagination, etc. */
docItemComponent: string;
/** Root component of the "docs containing tag X" page. */
docTagDocListComponent: string;
/** Root component of the tags list page */
docTagsListComponent: string;
/** Root component of the generated category index page. */
docCategoryGeneratedIndexComponent: string;
admonitions: {[key: string]: unknown};
disableVersioning: boolean;
includeCurrentVersion: boolean;
sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
/**
* URL route for the tags section of your doc version. Will be appended to
* `routeBasePath`. **DO NOT** include a trailing slash.
*/
tagsBasePath: string;
};
export type Options = Partial<PluginOptions>;
export type SidebarsConfig = import('./sidebars/types').SidebarsConfig;
export type VersionMetadata = ContentPaths & {
/** A name like `1.0.0`. Acquired from `versions.json`. */
versionName: string;
/** Like `Version 1.0.0`. Can be configured through `versions.label`. */
label: string;
/**
* Version's base path in the form of `/<baseUrl>/<routeBasePath>/1.0.0`.
* Can be configured through `versions.path`.
*/
path: string;
/** Tags base path in the form of `<versionPath>/tags`. */
tagsPath: string;
/**
* The base URL to which the doc file path will be appended. Will be
* `undefined` if `editUrl` is `undefined` or a function.
*/
editUrl?: string | undefined;
/**
* The base URL to which the localized doc file path will be appended. Will
* be `undefined` if `editUrl` is `undefined` or a function.
*/
editUrlLocalized?: string | undefined;
/**
* "unmaintained" is the version before latest; "unreleased" is the version
* after latest. `null` is the latest version without a banner. Can be
* configured with `versions.banner`: `banner: "none"` will be transformed
* to `null` here.
*/
banner: VersionBanner | null;
/** Show a badge with the version label at the top of each doc. */
badge: boolean;
/** Add a custom class name to the <html> element of each doc. */
className: string;
/**
* Whether this version is the "last" version. Can be configured with
* `lastVersion` option.
*/
isLast: boolean;
/**
* Like `versioned_sidebars/1.0.0.json`. Versioned sidebars file may be
* nonexistent since we don't create empty files.
*/
sidebarFilePath: string | false | undefined;
/**
* Will be -1 for the latest docs, and `undefined` for everything else.
* Because `/docs/foo` should always be after `/docs/<versionName>/foo`.
*/
routePriority: number | undefined;
};
export type DocFrontMatter = {
/**
* The last part of the doc ID (will be refactored in the future to be the
* full ID instead)
* @see {@link DocMetadata.id}
*/
id?: string;
/**
* Will override the default title collected from h1 heading.
* @see {@link DocMetadata.title}
*/
title?: string;
/**
* Front matter tags, unnormalized.
* @see {@link DocMetadata.tags}
*/
tags?: FrontMatterTag[];
/**
* If there isn't a Markdown h1 heading (which, if there is, we don't
* remove), this front matter will cause the front matter title to not be
* displayed in the doc page.
*/
hide_title?: boolean;
/** Hide the TOC on the right. */
hide_table_of_contents?: boolean;
/** Used in the head meta. */
keywords?: string[];
/** Used in the head meta. Should use `assets.image` in priority. */
image?: string;
/**
* Will override the default excerpt.
* @see {@link DocMetadata.description}
*/
description?: string;
/**
* Custom slug appended after /<baseUrl>/<routeBasePath>/<versionPath>
* @see {@link DocMetadata.slug}
*/
slug?: string;
/** Customizes the sidebar label for this doc. Will default to its title. */
sidebar_label?: string;
/**
* Controls the position of a doc inside the generated sidebar slice when
* using autogenerated sidebar items.
*
* @see https://docusaurus.io/docs/sidebar#autogenerated-sidebar-metadata
*/
sidebar_position?: number;
/**
* Gives the corresponding sidebar label a special class name when using
* autogenerated sidebars.
*/
sidebar_class_name?: string;
/**
* Will be propagated to the final sidebars data structure. Useful if you
* have swizzled sidebar-related code or simply querying doc data through
* sidebars.
*/
sidebar_custom_props?: {[key: string]: unknown};
/**
* Changes the sidebar association of the current doc. Use `null` to make
* the current doc not associated to any sidebar.
*/
displayed_sidebar?: string | null;
/**
* Customizes the pagination label for this doc. Will default to the sidebar
* label.
*/
pagination_label?: string;
/** Overrides the default URL computed for this doc. */
custom_edit_url?: string | null;
/**
* Whether number prefix parsing is disabled on this doc.
* @see https://docusaurus.io/docs/sidebar#using-number-prefixes
*/
parse_number_prefixes?: boolean;
/**
* Minimum TOC heading level. Must be between 2 and 6 and lower or equal to
* the max value.
*/
toc_min_heading_level?: number;
/** Maximum TOC heading level. Must be between 2 and 6. */
toc_max_heading_level?: number;
/**
* The ID of the documentation you want the "Next" pagination to link to.
* Use `null` to disable showing "Next" for this page.
* @see {@link DocMetadata.next}
*/
pagination_next?: string | null;
/**
* The ID of the documentation you want the "Previous" pagination to link
* to. Use `null` to disable showing "Previous" for this page.
* @see {@link DocMetadata.prev}
*/
pagination_prev?: string | null;
};
export type LastUpdateData = {
/** A timestamp in **seconds**, directly acquired from `git log`. */
lastUpdatedAt?: number;
/** `lastUpdatedAt` formatted as a date according to the current locale. */
formattedLastUpdatedAt?: string;
/** The author's name directly acquired from `git log`. */
lastUpdatedBy?: string;
};
export type DocMetadataBase = LastUpdateData & {
// TODO
/**
* Legacy versioned ID. Will be refactored in the future to be unversioned.
*/
id: string;
// TODO
/**
* Unversioned ID. Should be preferred everywhere over `id` until the latter
* is refactored.
*/
unversionedId: string;
/** The name of the version this doc belongs to. */
version: string;
/**
* Used to generate the page h1 heading, tab title, and pagination title.
*/
title: string;
/**
* Description used in the meta. Could be an empty string (empty content)
*/
description: string;
/** Path to the Markdown source, with `@site` alias. */
source: string;
/**
* Posix path relative to the content path. Can be `"."`.
* e.g. "folder/subfolder/subsubfolder"
*/
sourceDirName: string;
/** `permalink` without base URL or version path. */
slug: string;
/** Full URL to this doc, with base URL and version path. */
permalink: string;
/**
* Position in an autogenerated sidebar slice, acquired through front matter
* or number prefix.
*/
sidebarPosition?: number;
/**
* Acquired from the options; can be customized with front matter.
* `custom_edit_url` will always lead to it being null, but you should treat
* `undefined` and `null` as equivalent.
*/
editUrl?: string | null;
/** Tags, normalized. */
tags: Tag[];
/** Front matter, as-is. */
frontMatter: DocFrontMatter & {[key: string]: unknown};
};
export type DocMetadata = DocMetadataBase &
PropNavigation & {
/** Name of the sidebar this doc is associated with. */
sidebar?: string;
};
export type CategoryGeneratedIndexMetadata = Required<
Omit<
import('./sidebars/types').SidebarItemCategoryLinkGeneratedIndex,
'type'
>,
'title'
> & {
navigation: PropNavigation;
/**
* Name of the sidebar this doc is associated with. Unlike
* `DocMetadata.sidebar`, this will always be defined, because a generated
* index can only be generated from a category.
*/
sidebar: string;
};
export type PropNavigationLink = {
readonly title: string;
readonly permalink: string;
};
export type PropNavigation = {
/**
* Used in pagination. Content is just a subset of another doc's metadata.
*/
readonly previous?: PropNavigationLink;
/**
* Used in pagination. Content is just a subset of another doc's metadata.
*/
readonly next?: PropNavigationLink;
};
export type PropVersionDoc = import('./sidebars/types').PropVersionDoc;
export type PropVersionDocs = import('./sidebars/types').PropVersionDocs;
export type PropVersionDoc = Pick<
DocMetadata,
'id' | 'title' | 'description' | 'sidebar'
>;
export type PropVersionMetadata = {
export type PropVersionDocs = {
[docId: string]: PropVersionDoc;
};
export type PropVersionMetadata = Pick<
VersionMetadata,
'label' | 'banner' | 'badge' | 'className' | 'isLast'
> & {
/** ID of the docs plugin this version belongs to. */
pluginId: string;
/** Name of this version. */
version: string;
label: string;
banner: VersionBanner | null;
badge: boolean;
className: string;
isLast: boolean;
/** Sidebars contained in this version. */
docsSidebars: PropSidebars;
/** Docs contained in this version. */
docs: PropVersionDocs;
};
export type PropCategoryGeneratedIndex = {
title: string;
description?: string;
image?: string;
keywords?: string | readonly string[];
slug: string;
permalink: string;
navigation: PropNavigation;
};
export type PropCategoryGeneratedIndex = Omit<
CategoryGeneratedIndexMetadata,
'sidebar'
>;
export type PropSidebarItemLink =
import('./sidebars/types').PropSidebarItemLink;
@ -169,9 +508,10 @@ declare module '@docusaurus/plugin-content-docs' {
declare module '@theme/DocItem' {
import type {TOCItem} from '@docusaurus/types';
import type {
PropNavigationLink,
PropVersionMetadata,
Assets,
DocMetadata,
DocFrontMatter,
} from '@docusaurus/plugin-content-docs';
export type DocumentRoute = {
@ -181,41 +521,12 @@ declare module '@theme/DocItem' {
readonly sidebar?: string;
};
export type FrontMatter = {
readonly id: string;
readonly title: string;
readonly image?: string;
readonly keywords?: readonly string[];
readonly hide_title?: boolean;
readonly hide_table_of_contents?: boolean;
readonly toc_min_heading_level?: number;
readonly toc_max_heading_level?: number;
};
export type Metadata = {
readonly unversionedId?: string;
readonly description?: string;
readonly title?: string;
readonly permalink?: string;
readonly editUrl?: string;
readonly lastUpdatedAt?: number;
readonly formattedLastUpdatedAt?: string;
readonly lastUpdatedBy?: string;
readonly version?: string;
readonly previous?: PropNavigationLink;
readonly next?: PropNavigationLink;
readonly tags: readonly {
readonly label: string;
readonly permalink: string;
}[];
};
export interface Props {
readonly route: DocumentRoute;
readonly versionMetadata: PropVersionMetadata;
readonly content: {
readonly frontMatter: FrontMatter;
readonly metadata: Metadata;
readonly frontMatter: DocFrontMatter;
readonly metadata: DocMetadata;
readonly toc: readonly TOCItem[];
readonly contentTitle: string | undefined;
readonly assets: Assets;

View file

@ -5,13 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/
import type {LoadedVersion, VersionTag, DocMetadata} from './types';
import type {LoadedVersion, VersionTag} from './types';
import type {
SidebarItemDoc,
SidebarItem,
SidebarItemCategory,
SidebarItemCategoryLink,
PropVersionDocs,
} from './sidebars/types';
import type {
PropSidebars,
@ -21,6 +20,8 @@ import type {
PropTagDocList,
PropTagDocListDoc,
PropSidebarItemLink,
PropVersionDocs,
DocMetadata,
} from '@docusaurus/plugin-content-docs';
import _ from 'lodash';
import {createDocsByIdIndex} from './docs';
@ -119,10 +120,10 @@ export function toVersionMetadataProp(
return {
pluginId,
version: loadedVersion.versionName,
label: loadedVersion.versionLabel,
banner: loadedVersion.versionBanner,
badge: loadedVersion.versionBadge,
className: loadedVersion.versionClassName,
label: loadedVersion.label,
banner: loadedVersion.banner,
badge: loadedVersion.badge,
className: loadedVersion.className,
isLast: loadedVersion.isLast,
docsSidebars: toSidebarsProp(loadedVersion),
docs: toVersionDocsProp(loadedVersion),
@ -153,7 +154,7 @@ export function toTagDocListProp({
}
return {
name: tag.name,
name: tag.label,
permalink: tag.permalink,
docs: toDocListProp(),
allTagsPath,

View file

@ -7,12 +7,11 @@
import type {PluginContentLoadedActions, RouteConfig} from '@docusaurus/types';
import {docuHash, createSlugger} from '@docusaurus/utils';
import type {LoadedVersion} from './types';
import type {
CategoryGeneratedIndexMetadata,
DocMetadata,
LoadedVersion,
} from './types';
import type {PropCategoryGeneratedIndex} from '@docusaurus/plugin-content-docs';
} from '@docusaurus/plugin-content-docs';
import {toVersionMetadataProp} from './props';
import logger from '@docusaurus/logger';
@ -32,42 +31,19 @@ export async function createCategoryGeneratedIndexRoutes({
async function createCategoryGeneratedIndexRoute(
categoryGeneratedIndex: CategoryGeneratedIndexMetadata,
): Promise<RouteConfig> {
const {
sidebar,
title,
description,
slug,
permalink,
previous,
next,
image,
keywords,
} = categoryGeneratedIndex;
const {sidebar, ...prop} = categoryGeneratedIndex;
const propFileName = slugs.slug(
`${version.versionPath}-${categoryGeneratedIndex.sidebar}-category-${categoryGeneratedIndex.title}`,
`${version.path}-${categoryGeneratedIndex.sidebar}-category-${categoryGeneratedIndex.title}`,
);
const prop: PropCategoryGeneratedIndex = {
title,
description,
slug,
permalink,
image,
keywords,
navigation: {
previous,
next,
},
};
const propData = await actions.createData(
`${docuHash(`category/${propFileName}`)}.json`,
JSON.stringify(prop, null, 2),
);
return {
path: permalink,
path: categoryGeneratedIndex.permalink,
component: docCategoryGeneratedIndexComponent,
exact: true,
modules: {
@ -162,7 +138,7 @@ export async function createVersionRoutes({
}
actions.addRoute({
path: version.versionPath,
path: version.path,
// allow matching /docs/* as well
exact: false,
// main docs component (DocPage)

View file

@ -34,7 +34,7 @@ describe('postProcess', () => {
},
{
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
version: {versionPath: 'version'},
version: {path: 'version'},
},
);
@ -53,7 +53,7 @@ describe('postProcess', () => {
},
{
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
version: {versionPath: 'version'},
version: {path: 'version'},
},
);
}).toThrowErrorMatchingInlineSnapshot(
@ -78,7 +78,7 @@ describe('postProcess', () => {
{
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
version: {versionPath: 'version'},
version: {path: 'version'},
},
),
).toMatchSnapshot();
@ -98,7 +98,7 @@ describe('postProcess', () => {
{
sidebarOptions: {sidebarCollapsed: false, sidebarCollapsible: false},
version: {versionPath: 'version'},
version: {path: 'version'},
},
),
).toMatchSnapshot();
@ -117,7 +117,7 @@ describe('postProcess', () => {
{
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: false},
version: {versionPath: 'version'},
version: {path: 'version'},
},
),
).toMatchSnapshot();

View file

@ -18,7 +18,7 @@ import type {
} from '../types';
import {DefaultSidebarItemsGenerator} from '../generator';
import {createSlugger} from '@docusaurus/utils';
import type {VersionMetadata} from '../../types';
import type {VersionMetadata} from '@docusaurus/plugin-content-docs';
import {DefaultNumberPrefixParser} from '../../numberPrefix';
import {isCategoryIndex} from '../../docs';

View file

@ -16,7 +16,10 @@ import {
toNavigationLink,
} from '../utils';
import type {Sidebar, Sidebars} from '../types';
import type {DocMetadataBase, DocNavLink} from '../../types';
import type {
DocMetadataBase,
PropNavigationLink,
} from '@docusaurus/plugin-content-docs';
describe('createSidebarsUtils', () => {
const sidebar1: Sidebar = [
@ -618,7 +621,7 @@ describe('toDocNavigationLink', () => {
).toEqual({
title: 'Doc Title',
permalink: '/docPermalink',
} as DocNavLink);
} as PropNavigationLink);
});
it('with pagination_label front matter', () => {
@ -635,7 +638,7 @@ describe('toDocNavigationLink', () => {
).toEqual({
title: 'pagination_label',
permalink: '/docPermalink',
} as DocNavLink);
} as PropNavigationLink);
});
it('with sidebar_label front matter', () => {
@ -652,7 +655,7 @@ describe('toDocNavigationLink', () => {
).toEqual({
title: 'sidebar_label',
permalink: '/docPermalink',
} as DocNavLink);
} as PropNavigationLink);
});
it('with pagination_label + sidebar_label front matter', () => {
@ -670,7 +673,7 @@ describe('toDocNavigationLink', () => {
).toEqual({
title: 'pagination_label',
permalink: '/docPermalink',
} as DocNavLink);
} as PropNavigationLink);
});
});

View file

@ -26,7 +26,7 @@ function normalizeCategoryLink(
const getDefaultSlug = () =>
`/category/${params.categoryLabelSlugger.slug(category.label)}`;
const slug = category.link.slug ?? getDefaultSlug();
const permalink = normalizeUrl([params.version.versionPath, slug]);
const permalink = normalizeUrl([params.version.path, slug]);
return {
...category.link,
slug,

View file

@ -5,7 +5,10 @@
* LICENSE file in the root directory of this source tree.
*/
import type {DocMetadataBase, VersionMetadata} from '../types';
import type {
DocMetadataBase,
VersionMetadata,
} from '@docusaurus/plugin-content-docs';
import type {
NormalizedSidebarItem,
NormalizedSidebar,

View file

@ -6,11 +6,12 @@
*/
import type {Optional, Required} from 'utility-types';
import type {DocMetadataBase, VersionMetadata} from '../types';
import type {
NumberPrefixParser,
SidebarOptions,
CategoryIndexMatcher,
DocMetadataBase,
VersionMetadata,
} from '@docusaurus/plugin-content-docs';
import type {Slugger} from '@docusaurus/utils';
@ -199,16 +200,6 @@ export type PropSidebarBreadcrumbsItem =
| PropSidebarItemLink
| PropSidebarItemCategory;
export type PropVersionDoc = {
id: string;
title: string;
description?: string;
sidebar?: string;
};
export type PropVersionDocs = {
[docId: string]: PropVersionDoc;
};
export type CategoryMetadataFile = {
label?: string;
position?: number;
@ -243,11 +234,20 @@ export type SidebarItemsGeneratorVersion = Pick<
>;
export type SidebarItemsGeneratorArgs = {
/** The sidebar item with type "autogenerated" to be transformed. */
item: SidebarItemAutogenerated;
/** Useful metadata for the version this sidebar belongs to. */
version: SidebarItemsGeneratorVersion;
/** All the docs of that version (unfiltered). */
docs: SidebarItemsGeneratorDoc[];
/** Number prefix parser configured for this plugin. */
numberPrefixParser: NumberPrefixParser;
/** The default category index matcher which you can override. */
isCategoryIndex: CategoryIndexMatcher;
/**
* key is the path relative to the doc content directory, value is the
* category metadata file's content.
*/
categoriesMetadata: {[filePath: string]: CategoryMetadataFile};
};
export type SidebarItemsGenerator = (
@ -258,6 +258,10 @@ export type SidebarItemsGenerator = (
// default sidebar gen logic
// see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320
export type SidebarItemsGeneratorOptionArgs = {
/**
* Useful to re-use/enhance the default sidebar generation logic from
* Docusaurus.
*/
defaultSidebarItemsGenerator: SidebarItemsGenerator;
} & SidebarItemsGeneratorArgs;
export type SidebarItemsGeneratorOption = (

View file

@ -21,7 +21,10 @@ import type {
import _ from 'lodash';
import {toMessageRelativeFilePath} from '@docusaurus/utils';
import type {DocMetadataBase, DocNavLink} from '../types';
import type {
DocMetadataBase,
PropNavigationLink,
} from '@docusaurus/plugin-content-docs';
export function isCategoriesShorthand(
item: SidebarItemConfig,
@ -346,7 +349,7 @@ Available document ids are:
};
}
export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink {
export function toDocNavigationLink(doc: DocMetadataBase): PropNavigationLink {
const {
title,
permalink,
@ -361,7 +364,7 @@ export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink {
export function toNavigationLink(
navigationItem: SidebarNavigationItem | undefined,
docsById: {[docId: string]: DocMetadataBase},
): DocNavLink | undefined {
): PropNavigationLink | undefined {
function getDocById(docId: string) {
const doc = docsById[docId];
if (!doc) {

View file

@ -15,9 +15,11 @@ import {
DefaultNumberPrefixParser,
stripPathNumberPrefixes,
} from './numberPrefix';
import type {DocMetadataBase} from './types';
import {isCategoryIndex, toCategoryIndexMatcherParam} from './docs';
import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
import type {
NumberPrefixParser,
DocMetadataBase,
} from '@docusaurus/plugin-content-docs';
export default function getSlug({
baseID,

View file

@ -6,13 +6,14 @@
*/
import {groupTaggedItems} from '@docusaurus/utils';
import type {VersionTags, DocMetadata} from './types';
import type {VersionTags} from './types';
import type {DocMetadata} from '@docusaurus/plugin-content-docs';
import _ from 'lodash';
export function getVersionTags(docs: DocMetadata[]): VersionTags {
const groups = groupTaggedItems(docs, (doc) => doc.tags);
return _.mapValues(groups, (group) => ({
name: group.tag.label,
label: group.tag.label,
docIds: group.items.map((item) => item.id),
permalink: group.tag.permalink,
}));

View file

@ -245,7 +245,7 @@ function translateSidebars(
function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles {
const versionTranslations: TranslationFileContent = {
'version.label': {
message: version.versionLabel,
message: version.label,
description: `The label for version ${version.versionName}`,
},
};
@ -275,8 +275,7 @@ function translateVersion(
translationFiles[getVersionFileName(version.versionName)]!.content;
return {
...version,
versionLabel:
versionTranslations['version.label']?.message ?? version.versionLabel,
label: versionTranslations['version.label']?.message ?? version.label,
sidebars: translateSidebars(version, versionTranslations),
// docs: translateDocs(version.docs, versionTranslations),
};

View file

@ -8,13 +8,13 @@
/// <reference types="@docusaurus/module-type-aliases" />
import type {Sidebars} from './sidebars/types';
import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils';
import type {
Tag,
FrontMatterTag,
BrokenMarkdownLink,
ContentPaths,
} from '@docusaurus/utils';
import type {VersionBanner} from '@docusaurus/plugin-content-docs';
VersionMetadata,
LastUpdateData,
DocMetadata,
CategoryGeneratedIndexMetadata,
} from '@docusaurus/plugin-content-docs';
export type DocFile = {
contentPath: string; // /!\ may be localized
@ -24,106 +24,19 @@ export type DocFile = {
lastUpdate: LastUpdateData;
};
export type VersionMetadata = ContentPaths & {
versionName: string; // 1.0.0
versionLabel: string; // Version 1.0.0
versionPath: string; // /baseUrl/docs/1.0.0
tagsPath: string;
versionEditUrl?: string | undefined;
versionEditUrlLocalized?: string | undefined;
versionBanner: VersionBanner | null;
versionBadge: boolean;
versionClassName: string;
isLast: boolean;
sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json
routePriority: number | undefined; // -1 for the latest docs
};
export type LastUpdateData = {
lastUpdatedAt?: number;
formattedLastUpdatedAt?: string;
lastUpdatedBy?: string;
};
export type DocFrontMatter = {
// Front matter uses snake case
id?: string;
title?: string;
tags?: FrontMatterTag[];
hide_title?: boolean;
hide_table_of_contents?: boolean;
keywords?: string[];
image?: string;
description?: string;
slug?: string;
sidebar_label?: string;
sidebar_position?: number;
sidebar_class_name?: string;
sidebar_custom_props?: {[key: string]: unknown};
displayed_sidebar?: string | null;
pagination_label?: string;
custom_edit_url?: string | null;
parse_number_prefixes?: boolean;
toc_min_heading_level?: number;
toc_max_heading_level?: number;
pagination_next?: string | null;
pagination_prev?: string | null;
};
export type DocMetadataBase = LastUpdateData & {
id: string; // TODO legacy versioned id => try to remove
unversionedId: string; // TODO new unversioned id => try to rename to "id"
version: string;
title: string;
description: string;
source: string; // @site aliased posix source => "@site/docs/folder/subFolder/subSubFolder/myDoc.md"
sourceDirName: string; // posix path relative to the versioned docs folder (can be ".") => "folder/subFolder/subSubFolder"
slug: string;
permalink: string;
sidebarPosition?: number;
editUrl?: string | null;
tags: Tag[];
frontMatter: DocFrontMatter & {[key: string]: unknown};
};
export type DocNavLink = {
title: string;
permalink: string;
};
export type DocMetadata = DocMetadataBase & {
sidebar?: string;
previous?: DocNavLink;
next?: DocNavLink;
};
export type CategoryGeneratedIndexMetadata = {
title: string;
description?: string;
slug: string;
permalink: string;
sidebar: string;
previous?: DocNavLink;
next?: DocNavLink;
image?: string;
keywords?: string | readonly string[];
};
export type SourceToPermalink = {
[source: string]: string;
};
export type VersionTag = {
name: string; // normalized name/label of the tag
docIds: string[]; // all doc ids having this tag
permalink: string; // pathname of the tag
export type VersionTag = Tag & {
/** all doc ids having this tag. */
docIds: string[];
};
export type VersionTags = {
[key: string]: VersionTag;
};
export type LoadedVersion = VersionMetadata & {
versionPath: string;
mainDocId: string;
docs: DocMetadata[];
sidebars: Sidebars;

View file

@ -7,7 +7,6 @@
import path from 'path';
import fs from 'fs-extra';
import type {VersionMetadata} from './types';
import {
VERSIONS_JSON_FILE,
VERSIONED_DOCS_DIR,
@ -17,8 +16,8 @@ import {
import type {
PluginOptions,
VersionBanner,
VersionOptions,
VersionsOptions,
VersionMetadata,
} from '@docusaurus/plugin-content-docs';
import type {LoadContext} from '@docusaurus/types';
@ -207,7 +206,12 @@ function getVersionEditUrls({
contentPath,
contentPathLocalized,
context: {siteDir, i18n},
options: {id, path: currentVersionPath, editUrl, editCurrentVersion},
options: {
id,
path: currentVersionPath,
editUrl: editUrlOption,
editCurrentVersion,
},
}: {
contentPath: string;
contentPathLocalized: string;
@ -216,15 +220,11 @@ function getVersionEditUrls({
PluginOptions,
'id' | 'path' | 'editUrl' | 'editCurrentVersion'
>;
}): {versionEditUrl: string; versionEditUrlLocalized: string} | undefined {
if (!editUrl) {
return undefined;
}
// if the user is using the functional form of editUrl,
// he has total freedom and we can't compute a "version edit url"
if (typeof editUrl === 'function') {
return undefined;
}): Pick<VersionMetadata, 'editUrl' | 'editUrlLocalized'> {
// If the user is using the functional form of editUrl,
// she has total freedom and we can't compute a "version edit url"
if (!editUrlOption || typeof editUrlOption === 'function') {
return {editUrl: undefined, editUrlLocalized: undefined};
}
const editDirPath = editCurrentVersion ? currentVersionPath : contentPath;
@ -244,16 +244,16 @@ function getVersionEditUrls({
path.relative(siteDir, path.resolve(siteDir, editDirPathLocalized)),
);
const versionEditUrl = normalizeUrl([editUrl, versionPathSegment]);
const editUrl = normalizeUrl([editUrlOption, versionPathSegment]);
const versionEditUrlLocalized = normalizeUrl([
editUrl,
const editUrlLocalized = normalizeUrl([
editUrlOption,
versionPathSegmentLocalized,
]);
return {
versionEditUrl,
versionEditUrlLocalized,
editUrl,
editUrlLocalized,
};
}
@ -370,12 +370,12 @@ function createVersionMetadata({
}
const defaultVersionPathPart = getDefaultVersionPathPart();
const versionOptions: VersionOptions = options.versions[versionName] ?? {};
const versionOptions = options.versions[versionName] ?? {};
const versionLabel = versionOptions.label ?? defaultVersionLabel;
const label = versionOptions.label ?? defaultVersionLabel;
const versionPathPart = versionOptions.path ?? defaultVersionPathPart;
const versionPath = normalizeUrl([
const routePath = normalizeUrl([
context.baseUrl,
options.routeBasePath,
versionPathPart,
@ -388,28 +388,27 @@ function createVersionMetadata({
options,
});
// Because /docs/:route` should always be after `/docs/versionName/:route`.
const routePriority = versionPathPart === '' ? -1 : undefined;
// the path that will be used to refer the docs tags
// example below will be using /docs/tags
const tagsPath = normalizeUrl([versionPath, options.tagsBasePath]);
const tagsPath = normalizeUrl([routePath, options.tagsBasePath]);
return {
versionName,
versionLabel,
versionPath,
label,
path: routePath,
tagsPath,
versionEditUrl: versionEditUrls?.versionEditUrl,
versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized,
versionBanner: getVersionBanner({
editUrl: versionEditUrls.editUrl,
editUrlLocalized: versionEditUrls.editUrlLocalized,
banner: getVersionBanner({
versionName,
versionNames,
lastVersionName,
options,
}),
versionBadge: getVersionBadge({versionName, versionNames, options}),
versionClassName: getVersionClassName({versionName, options}),
badge: getVersionBadge({versionName, versionNames, options}),
className: getVersionClassName({versionName, options}),
isLast,
routePriority,
sidebarFilePath,
@ -592,15 +591,3 @@ export async function readVersionsMetadata({
);
return versionsMetadata;
}
// order matter!
// Read in priority the localized path, then the unlocalized one
// We want the localized doc to "override" the unlocalized one
export function getDocsDirPaths(
versionMetadata: Pick<
VersionMetadata,
'contentPath' | 'contentPathLocalized'
>,
): [string, string] {
return [versionMetadata.contentPathLocalized, versionMetadata.contentPath];
}

View file

@ -6,9 +6,9 @@
*/
declare module '@docusaurus/plugin-content-pages' {
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
import type {MDXOptions} from '@docusaurus/mdx-loader';
export type PluginOptions = RemarkAndRehypePluginOptions & {
export type PluginOptions = MDXOptions & {
id?: string;
path: string;
routeBasePath: string;

View file

@ -5,6 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference types="@docusaurus/module-type-aliases" />
/// <reference types="@docusaurus/plugin-content-docs" />
/// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="@docusaurus/plugin-content-pages" />
declare module '@docusaurus/theme-classic' {
export type Options = {
customCss?: string | string[];

View file

@ -47,7 +47,7 @@ function DocItemContent(props: Props): JSX.Element {
const {title} = metadata;
// We only add a title if:
// - user asks to hide it with front matter
// - user doesn't ask to hide it with front matter
// - the markdown content does not already contain a top-level h1 heading
const shouldAddTitle =
!hideTitle && typeof DocContent.contentTitle === 'undefined';

View file

@ -1,11 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="@docusaurus/module-type-aliases" />
/// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="@docusaurus/plugin-content-docs" />
/// <reference types="@docusaurus/plugin-content-pages" />

View file

@ -6,6 +6,7 @@
*/
/// <reference types="@docusaurus/theme-classic" />
/// <reference types="@docusaurus/module-type-aliases" />
declare module '@theme-init/CodeBlock' {
import type CodeBlock, {Props as BaseProps} from '@theme/CodeBlock';

View file

@ -31,24 +31,23 @@ Accepted fields:
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'docs'` | Path to data on filesystem relative to site dir. |
| `breadcrumbs` | `boolean` | `true` | To enable or disable the breadcrumbs on docs pages. |
| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. |
| `editUrl` | <code>string \| EditUrlFunction</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. |
| `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. |
| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. |
| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. |
| `sidebarPath` | <code>false \| string</code> | `undefined` (creates autogenerated sidebar) | Path to sidebar configuration. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. |
| `sidebarPath` | <code>false \| string</code> | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. |
| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) |
| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) |
| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` by real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) |
| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) |
| `numberPrefixParser` | <code>boolean \| PrefixParser</code> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) |
| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root Layout component of each doc page. |
| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root layout component of each doc page. Provides the version data context, and is not unmounted when switching docs. |
| `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. |
| `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page |
| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag" page. |
| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag X" page. |
| `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. |
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. |
@ -56,11 +55,12 @@ Accepted fields:
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the doc. |
| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the doc was updated. |
| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even with versions. This will make the site only include the current version. |
| `breadcrumbs` | `boolean` | `true` | Enable or disable the breadcrumbs on doc pages. |
| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even when multiple versions exist. This will make the site only include the current version. Will error if `includeCurrentVersion: false` and `disableVersioning: true`. |
| `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. |
| `lastVersion` | `string` | First version in `versions.json` | Set the version navigated to in priority and displayed by default for docs navbar items. |
| `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. |
| `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. |
| `versions` | `Versions` | `{}` | Independent customization of each version's properties. |
| `versions` | `VersionsConfig` | `{}` | Independent customization of each version's properties. |
</APITable>
@ -78,15 +78,24 @@ type PrefixParser = (filename: string) => {
numberPrefix?: number;
};
type CategoryIndexMatcher = (doc: {
type CategoryIndexMatcher = (param: {
/** The file name, without extension */
fileName: string;
/**
* The list of directories, from lowest level to highest.
* If there's no dir name, directories is ['.']
*/
directories: string[];
/** The extension, with a leading dot */
extension: string;
}) => boolean;
type SidebarGenerator = (generatorArgs: {
item: {type: 'autogenerated'; dirName: string}; // the sidebar item with type "autogenerated"
version: {contentPath: string; versionName: string}; // the current version
/** The sidebar item with type "autogenerated" to be transformed. */
item: {type: 'autogenerated'; dirName: string};
/** Useful metadata for the version this sidebar belongs to. */
version: {contentPath: string; versionName: string};
/** All the docs of that version (unfiltered). */
docs: Array<{
id: string;
title: string;
@ -94,23 +103,40 @@ type SidebarGenerator = (generatorArgs: {
source: string;
sourceDirName: string;
sidebarPosition?: number | undefined;
}>; // all the docs of that version (unfiltered)
numberPrefixParser: PrefixParser; // numberPrefixParser configured for this plugin
categoriesMetadata: Record<string, CategoryMetadata>; // key is the path relative to the doc directory, value is the category metadata file's content
isCategoryIndex: CategoryIndexMatcher; // the default category index matcher, that you can override
defaultSidebarItemsGenerator: SidebarGenerator; // useful to re-use/enhance default sidebar generation logic from Docusaurus
}>;
/** Number prefix parser configured for this plugin. */
numberPrefixParser: PrefixParser;
/** The default category index matcher which you can override. */
isCategoryIndex: CategoryIndexMatcher;
/**
* key is the path relative to the doc content directory, value is the
* category metadata file's content.
*/
categoriesMetadata: {[filePath: string]: CategoryMetadata};
/**
* Useful to re-use/enhance the default sidebar generation logic from
* Docusaurus.
*/
defaultSidebarItemsGenerator: SidebarGenerator;
}) => Promise<SidebarItem[]>;
type Versions = Record<
string, // the version's ID
{
label: string; // the label of the version
path: string; // the route path of the version
banner: 'none' | 'unreleased' | 'unmaintained'; // the banner to show at the top of a doc of that version
badge: boolean; // show a badge with the version name at the top of a doc of that version
className; // add a custom className to the <html> element when browsing docs of that version
}
>;
type VersionsConfig = {
[versionName: string]: {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | 'unreleased' | 'unmaintained';
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Add a custom class name to the <html> element of each doc */
className?: string;
};
};
```
### Example configuration {#ex-config}