mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
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:
parent
b842197ac6
commit
2bcac29cd4
38 changed files with 715 additions and 521 deletions
|
@ -21,21 +21,21 @@ import toc from './remark/toc';
|
||||||
import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks';
|
import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks';
|
||||||
import transformImage from './remark/transformImage';
|
import transformImage from './remark/transformImage';
|
||||||
import transformLinks from './remark/transformLinks';
|
import transformLinks from './remark/transformLinks';
|
||||||
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
|
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
||||||
import type {LoaderContext} from 'webpack';
|
import type {LoaderContext} from 'webpack';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loaders: {inlineMarkdownImageFileLoader},
|
loaders: {inlineMarkdownImageFileLoader},
|
||||||
} = getFileLoaderUtils();
|
} = getFileLoaderUtils();
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: RemarkAndRehypePluginOptions = {
|
const DEFAULT_OPTIONS: MDXOptions = {
|
||||||
rehypePlugins: [],
|
rehypePlugins: [],
|
||||||
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
|
remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc],
|
||||||
beforeDefaultRemarkPlugins: [],
|
beforeDefaultRemarkPlugins: [],
|
||||||
beforeDefaultRehypePlugins: [],
|
beforeDefaultRehypePlugins: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
type Options = RemarkAndRehypePluginOptions & {
|
type Options = MDXOptions & {
|
||||||
staticDirs: string[];
|
staticDirs: string[];
|
||||||
siteDir: string;
|
siteDir: string;
|
||||||
isMDXPartial?: (filePath: string) => boolean;
|
isMDXPartial?: (filePath: string) => boolean;
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
import type {Plugin} from 'unified';
|
import type {Plugin} from 'unified';
|
||||||
|
|
||||||
export type RemarkOrRehypePlugin =
|
export type MDXPlugin =
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
[Plugin<any[]>, any] | Plugin<any[]>;
|
[Plugin<any[]>, any] | Plugin<any[]>;
|
||||||
export type RemarkAndRehypePluginOptions = {
|
export type MDXOptions = {
|
||||||
remarkPlugins: RemarkOrRehypePlugin[];
|
remarkPlugins: MDXPlugin[];
|
||||||
rehypePlugins: RemarkOrRehypePlugin[];
|
rehypePlugins: MDXPlugin[];
|
||||||
beforeDefaultRemarkPlugins: RemarkOrRehypePlugin[];
|
beforeDefaultRemarkPlugins: MDXPlugin[];
|
||||||
beforeDefaultRehypePlugins: RemarkOrRehypePlugin[];
|
beforeDefaultRehypePlugins: MDXPlugin[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare module '@docusaurus/plugin-content-blog' {
|
declare module '@docusaurus/plugin-content-blog' {
|
||||||
import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
|
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
||||||
import type {FrontMatterTag} from '@docusaurus/utils';
|
import type {FrontMatterTag, Tag} from '@docusaurus/utils';
|
||||||
import type {Overwrite} from 'utility-types';
|
import type {Overwrite} from 'utility-types';
|
||||||
|
|
||||||
export interface Assets {
|
export interface Assets {
|
||||||
|
@ -81,10 +81,7 @@ declare module '@docusaurus/plugin-content-blog' {
|
||||||
* @see {@link BlogPostMetadata.tags}
|
* @see {@link BlogPostMetadata.tags}
|
||||||
*/
|
*/
|
||||||
tags?: FrontMatterTag[];
|
tags?: FrontMatterTag[];
|
||||||
/**
|
/** Custom slug appended after `/<baseUrl>/<routeBasePath>/` */
|
||||||
* Custom slug appended after /<baseUrl>/<routeBasePath>/
|
|
||||||
* @see {@link BlogPostMetadata.slug}
|
|
||||||
*/
|
|
||||||
slug?: string;
|
slug?: string;
|
||||||
/**
|
/**
|
||||||
* Marks the post as draft and excludes it from the production build.
|
* 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 */
|
/** @deprecated v1 legacy */
|
||||||
authorImageURL?: string;
|
authorImageURL?: string;
|
||||||
|
|
||||||
/**
|
/** Used in the head meta. Should use `assets.image` in priority. */
|
||||||
* @see {@link BlogPostMetadata.image}
|
|
||||||
*/
|
|
||||||
image?: string;
|
image?: string;
|
||||||
/**
|
/** Used in the head meta. */
|
||||||
* Used in the head meta
|
|
||||||
*/
|
|
||||||
keywords?: string[];
|
keywords?: string[];
|
||||||
/**
|
/** Hide the right TOC. */
|
||||||
* Hide the right TOC
|
|
||||||
*/
|
|
||||||
hide_table_of_contents?: boolean;
|
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;
|
toc_min_heading_level?: number;
|
||||||
/**
|
/** Maximum TOC heading level. Must be between 2 and 6. */
|
||||||
* Maximum TOC heading level
|
|
||||||
*/
|
|
||||||
toc_max_heading_level?: number;
|
toc_max_heading_level?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,9 +165,7 @@ declare module '@docusaurus/plugin-content-blog' {
|
||||||
| (string | BlogPostFrontMatterAuthor)[];
|
| (string | BlogPostFrontMatterAuthor)[];
|
||||||
|
|
||||||
export type BlogPostMetadata = {
|
export type BlogPostMetadata = {
|
||||||
/**
|
/** Path to the Markdown source, with `@site` alias. */
|
||||||
* Path to the Markdown source, with `@site` alias.
|
|
||||||
*/
|
|
||||||
readonly source: string;
|
readonly source: string;
|
||||||
/**
|
/**
|
||||||
* Used to generate the page h1 heading, tab title, and pagination title.
|
* 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`.
|
* render the date regardless of the existence of `Intl.DateTimeFormat`.
|
||||||
*/
|
*/
|
||||||
readonly formattedDate: string;
|
readonly formattedDate: string;
|
||||||
/**
|
/** Full link including base URL. */
|
||||||
* Full link including base URL.
|
|
||||||
*/
|
|
||||||
readonly permalink: string;
|
readonly permalink: string;
|
||||||
/**
|
/**
|
||||||
* Description used in the meta. Could be an empty string (empty content)
|
* 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.
|
* `assets.authorsImageUrls` on client side.
|
||||||
*/
|
*/
|
||||||
readonly authors: Author[];
|
readonly authors: Author[];
|
||||||
/**
|
/** Front matter, as-is. */
|
||||||
* Front matter, as-is.
|
|
||||||
*/
|
|
||||||
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
|
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
|
||||||
/**
|
/** Tags, normalized. */
|
||||||
* Tags, normalized.
|
readonly tags: Tag[];
|
||||||
*/
|
|
||||||
readonly tags: readonly {
|
|
||||||
readonly label: string;
|
|
||||||
readonly permalink: string;
|
|
||||||
}[];
|
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @returns The edit URL that's directly plugged into metadata.
|
* @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
|
* site path. Usually the same as `options.path` but can be localized
|
||||||
*/
|
*/
|
||||||
blogDirPath: string;
|
blogDirPath: string;
|
||||||
/**
|
/** Path to this post file, relative to `blogDirPath`. */
|
||||||
* Path to this post file, relative to `blogDirPath`
|
|
||||||
*/
|
|
||||||
blogPath: string;
|
blogPath: string;
|
||||||
/**
|
/** @see {@link BlogPostMetadata.permalink} */
|
||||||
* @see {@link BlogPostMetadata.permalink}
|
|
||||||
*/
|
|
||||||
permalink: string;
|
permalink: string;
|
||||||
/**
|
/** Locale name. */
|
||||||
* Locale name.
|
|
||||||
*/
|
|
||||||
locale: string;
|
locale: string;
|
||||||
}) => string | undefined;
|
}) => string | undefined;
|
||||||
|
|
||||||
|
@ -325,7 +298,7 @@ declare module '@docusaurus/plugin-content-blog' {
|
||||||
/**
|
/**
|
||||||
* Plugin options after normalization.
|
* Plugin options after normalization.
|
||||||
*/
|
*/
|
||||||
export type PluginOptions = RemarkAndRehypePluginOptions & {
|
export type PluginOptions = MDXOptions & {
|
||||||
/** Plugin ID. */
|
/** Plugin ID. */
|
||||||
id?: string;
|
id?: string;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -169,7 +169,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"isLast": true,
|
"isLast": true,
|
||||||
|
"label": "current label (translated)",
|
||||||
"mainDocId": "",
|
"mainDocId": "",
|
||||||
|
"path": "/docs/",
|
||||||
"routePriority": undefined,
|
"routePriority": undefined,
|
||||||
"sidebarFilePath": "any",
|
"sidebarFilePath": "any",
|
||||||
"sidebars": {
|
"sidebars": {
|
||||||
|
@ -221,9 +223,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"versionLabel": "current label (translated)",
|
|
||||||
"versionName": "current",
|
"versionName": "current",
|
||||||
"versionPath": "/docs/",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"contentPath": "any",
|
"contentPath": "any",
|
||||||
|
@ -311,7 +311,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"isLast": true,
|
"isLast": true,
|
||||||
|
"label": "2.0.0 label (translated)",
|
||||||
"mainDocId": "",
|
"mainDocId": "",
|
||||||
|
"path": "/docs/",
|
||||||
"routePriority": undefined,
|
"routePriority": undefined,
|
||||||
"sidebarFilePath": "any",
|
"sidebarFilePath": "any",
|
||||||
"sidebars": {
|
"sidebars": {
|
||||||
|
@ -363,9 +365,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"versionLabel": "2.0.0 label (translated)",
|
|
||||||
"versionName": "2.0.0",
|
"versionName": "2.0.0",
|
||||||
"versionPath": "/docs/",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"contentPath": "any",
|
"contentPath": "any",
|
||||||
|
@ -453,7 +453,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"isLast": true,
|
"isLast": true,
|
||||||
|
"label": "1.0.0 label (translated)",
|
||||||
"mainDocId": "",
|
"mainDocId": "",
|
||||||
|
"path": "/docs/",
|
||||||
"routePriority": undefined,
|
"routePriority": undefined,
|
||||||
"sidebarFilePath": "any",
|
"sidebarFilePath": "any",
|
||||||
"sidebars": {
|
"sidebars": {
|
||||||
|
@ -505,9 +507,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = `
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"versionLabel": "1.0.0 label (translated)",
|
|
||||||
"versionName": "1.0.0",
|
"versionName": "1.0.0",
|
||||||
"versionPath": "/docs/",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,14 @@ import {
|
||||||
import {loadSidebars} from '../sidebars';
|
import {loadSidebars} from '../sidebars';
|
||||||
import type {Sidebars} from '../sidebars/types';
|
import type {Sidebars} from '../sidebars/types';
|
||||||
import {readVersionsMetadata} from '../versions';
|
import {readVersionsMetadata} from '../versions';
|
||||||
import type {
|
import type {DocFile} from '../types';
|
||||||
DocFile,
|
|
||||||
DocMetadataBase,
|
|
||||||
VersionMetadata,
|
|
||||||
DocNavLink,
|
|
||||||
} from '../types';
|
|
||||||
import type {
|
import type {
|
||||||
MetadataOptions,
|
MetadataOptions,
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
EditUrlFunction,
|
EditUrlFunction,
|
||||||
|
DocMetadataBase,
|
||||||
|
VersionMetadata,
|
||||||
|
PropNavigationLink,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
import type {LoadContext} from '@docusaurus/types';
|
import type {LoadContext} from '@docusaurus/types';
|
||||||
import {DEFAULT_OPTIONS} from '../options';
|
import {DEFAULT_OPTIONS} from '../options';
|
||||||
|
@ -123,7 +121,11 @@ function createTestUtils({
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateNavigation(docFiles: DocFile[]): Promise<{
|
async function generateNavigation(docFiles: DocFile[]): Promise<{
|
||||||
pagination: {prev?: DocNavLink; next?: DocNavLink; id: string}[];
|
pagination: {
|
||||||
|
prev?: PropNavigationLink;
|
||||||
|
next?: PropNavigationLink;
|
||||||
|
id: string;
|
||||||
|
}[];
|
||||||
sidebars: Sidebars;
|
sidebars: Sidebars;
|
||||||
}> {
|
}> {
|
||||||
const rawDocs = docFiles.map((docFile) =>
|
const rawDocs = docFiles.map((docFile) =>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {validateDocFrontMatter} from '../frontMatter';
|
import {validateDocFrontMatter} from '../frontMatter';
|
||||||
import type {DocFrontMatter} from '../types';
|
import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
|
||||||
import escapeStringRegexp from 'escape-string-regexp';
|
import escapeStringRegexp from 'escape-string-regexp';
|
||||||
|
|
||||||
function testField(params: {
|
function testField(params: {
|
||||||
|
|
|
@ -12,9 +12,9 @@ describe('toGlobalDataVersion', () => {
|
||||||
expect(
|
expect(
|
||||||
toGlobalDataVersion({
|
toGlobalDataVersion({
|
||||||
versionName: 'current',
|
versionName: 'current',
|
||||||
versionLabel: 'Label',
|
label: 'Label',
|
||||||
isLast: true,
|
isLast: true,
|
||||||
versionPath: '/current',
|
path: '/current',
|
||||||
mainDocId: 'main',
|
mainDocId: 'main',
|
||||||
docs: [
|
docs: [
|
||||||
{
|
{
|
||||||
|
@ -86,9 +86,9 @@ describe('toGlobalDataVersion', () => {
|
||||||
sidebar: 'tutorial',
|
sidebar: 'tutorial',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
versionBanner: 'unreleased',
|
banner: 'unreleased',
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'current-cls',
|
className: 'current-cls',
|
||||||
tagsPath: '/current/tags',
|
tagsPath: '/current/tags',
|
||||||
contentPath: '',
|
contentPath: '',
|
||||||
contentPathLocalized: '',
|
contentPathLocalized: '',
|
||||||
|
|
|
@ -16,7 +16,7 @@ describe('toTagDocListProp', () => {
|
||||||
|
|
||||||
it('works', () => {
|
it('works', () => {
|
||||||
const tag: Tag = {
|
const tag: Tag = {
|
||||||
name: 'tag1',
|
label: 'tag1',
|
||||||
permalink: '/tag1',
|
permalink: '/tag1',
|
||||||
docIds: ['id1', 'id3'],
|
docIds: ['id1', 'id3'],
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ describe('toTagDocListProp', () => {
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
allTagsPath,
|
allTagsPath,
|
||||||
name: tag.name,
|
name: tag.label,
|
||||||
permalink: tag.permalink,
|
permalink: tag.permalink,
|
||||||
docs: [doc3, doc1], // docs sorted by title, ignore "id5" absence
|
docs: [doc3, doc1], // docs sorted by title, ignore "id5" absence
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* 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 {CURRENT_VERSION_NAME} from '../constants';
|
||||||
import {
|
import {
|
||||||
getLoadedContentTranslationFiles,
|
getLoadedContentTranslationFiles,
|
||||||
translateLoadedContent,
|
translateLoadedContent,
|
||||||
} from '../translations';
|
} from '../translations';
|
||||||
|
import type {DocMetadata} from '@docusaurus/plugin-content-docs';
|
||||||
import {updateTranslationFileMessages} from '@docusaurus/utils';
|
import {updateTranslationFileMessages} from '@docusaurus/utils';
|
||||||
|
|
||||||
function createSampleDoc(doc: Pick<DocMetadata, 'id'>): DocMetadata {
|
function createSampleDoc(doc: Pick<DocMetadata, 'id'>): DocMetadata {
|
||||||
|
@ -36,8 +37,8 @@ function createSampleVersion(
|
||||||
version: Pick<LoadedVersion, 'versionName'>,
|
version: Pick<LoadedVersion, 'versionName'>,
|
||||||
): LoadedVersion {
|
): LoadedVersion {
|
||||||
return {
|
return {
|
||||||
versionLabel: `${version.versionName} label`,
|
label: `${version.versionName} label`,
|
||||||
versionPath: '/docs/',
|
path: '/docs/',
|
||||||
mainDocId: '',
|
mainDocId: '',
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
sidebarFilePath: 'any',
|
sidebarFilePath: 'any',
|
||||||
|
@ -45,21 +46,11 @@ function createSampleVersion(
|
||||||
contentPath: 'any',
|
contentPath: 'any',
|
||||||
contentPathLocalized: 'any',
|
contentPathLocalized: 'any',
|
||||||
docs: [
|
docs: [
|
||||||
createSampleDoc({
|
createSampleDoc({id: 'doc1'}),
|
||||||
id: 'doc1',
|
createSampleDoc({id: 'doc2'}),
|
||||||
}),
|
createSampleDoc({id: 'doc3'}),
|
||||||
createSampleDoc({
|
createSampleDoc({id: 'doc4'}),
|
||||||
id: 'doc2',
|
createSampleDoc({id: 'doc5'}),
|
||||||
}),
|
|
||||||
createSampleDoc({
|
|
||||||
id: 'doc3',
|
|
||||||
}),
|
|
||||||
createSampleDoc({
|
|
||||||
id: 'doc4',
|
|
||||||
}),
|
|
||||||
createSampleDoc({
|
|
||||||
id: 'doc5',
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
sidebars: {
|
sidebars: {
|
||||||
docs: [
|
docs: [
|
||||||
|
|
|
@ -15,9 +15,11 @@ import {
|
||||||
} from '../versions';
|
} from '../versions';
|
||||||
import {DEFAULT_OPTIONS} from '../options';
|
import {DEFAULT_OPTIONS} from '../options';
|
||||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
||||||
import type {VersionMetadata} from '../types';
|
|
||||||
import type {I18n} from '@docusaurus/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 = {
|
const DefaultI18N: I18n = {
|
||||||
currentLocale: 'en',
|
currentLocale: 'en',
|
||||||
|
@ -85,12 +87,12 @@ describe('readVersionsMetadata', () => {
|
||||||
routePriority: -1,
|
routePriority: -1,
|
||||||
sidebarFilePath: undefined,
|
sidebarFilePath: undefined,
|
||||||
tagsPath: '/docs/tags',
|
tagsPath: '/docs/tags',
|
||||||
versionLabel: 'Next',
|
label: 'Next',
|
||||||
versionName: 'current',
|
versionName: 'current',
|
||||||
versionPath: '/docs',
|
path: '/docs',
|
||||||
versionBanner: null,
|
banner: null,
|
||||||
versionBadge: false,
|
badge: false,
|
||||||
versionClassName: 'docs-version-current',
|
className: 'docs-version-current',
|
||||||
};
|
};
|
||||||
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
|
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
|
||||||
}
|
}
|
||||||
|
@ -120,7 +122,7 @@ describe('readVersionsMetadata', () => {
|
||||||
expect(versionsMetadata).toEqual([
|
expect(versionsMetadata).toEqual([
|
||||||
{
|
{
|
||||||
...vCurrent,
|
...vCurrent,
|
||||||
versionPath: '/myBaseUrl/docs',
|
path: '/myBaseUrl/docs',
|
||||||
tagsPath: '/myBaseUrl/docs/tags',
|
tagsPath: '/myBaseUrl/docs/tags',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -148,13 +150,13 @@ describe('readVersionsMetadata', () => {
|
||||||
expect(versionsMetadata).toEqual([
|
expect(versionsMetadata).toEqual([
|
||||||
{
|
{
|
||||||
...vCurrent,
|
...vCurrent,
|
||||||
versionPath: '/myBaseUrl/docs/current-path',
|
path: '/myBaseUrl/docs/current-path',
|
||||||
versionLabel: 'current-label',
|
label: 'current-label',
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
sidebarFilePath: undefined,
|
sidebarFilePath: undefined,
|
||||||
tagsPath: '/myBaseUrl/docs/current-path/tags',
|
tagsPath: '/myBaseUrl/docs/current-path/tags',
|
||||||
versionEditUrl: undefined,
|
editUrl: undefined,
|
||||||
versionEditUrlLocalized: undefined,
|
editUrlLocalized: undefined,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -245,12 +247,12 @@ describe('readVersionsMetadata', () => {
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
|
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
|
||||||
tagsPath: '/docs/next/tags',
|
tagsPath: '/docs/next/tags',
|
||||||
versionLabel: 'Next',
|
label: 'Next',
|
||||||
versionName: 'current',
|
versionName: 'current',
|
||||||
versionPath: '/docs/next',
|
path: '/docs/next',
|
||||||
versionBanner: 'unreleased',
|
banner: 'unreleased',
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-current',
|
className: 'docs-version-current',
|
||||||
};
|
};
|
||||||
|
|
||||||
const v101: VersionMetadata = {
|
const v101: VersionMetadata = {
|
||||||
|
@ -269,12 +271,12 @@ describe('readVersionsMetadata', () => {
|
||||||
'versioned_sidebars/version-1.0.1-sidebars.json',
|
'versioned_sidebars/version-1.0.1-sidebars.json',
|
||||||
),
|
),
|
||||||
tagsPath: '/docs/tags',
|
tagsPath: '/docs/tags',
|
||||||
versionLabel: '1.0.1',
|
label: '1.0.1',
|
||||||
versionName: '1.0.1',
|
versionName: '1.0.1',
|
||||||
versionPath: '/docs',
|
path: '/docs',
|
||||||
versionBanner: null,
|
banner: null,
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-1.0.1',
|
className: 'docs-version-1.0.1',
|
||||||
};
|
};
|
||||||
|
|
||||||
const v100: VersionMetadata = {
|
const v100: VersionMetadata = {
|
||||||
|
@ -293,12 +295,12 @@ describe('readVersionsMetadata', () => {
|
||||||
'versioned_sidebars/version-1.0.0-sidebars.json',
|
'versioned_sidebars/version-1.0.0-sidebars.json',
|
||||||
),
|
),
|
||||||
tagsPath: '/docs/1.0.0/tags',
|
tagsPath: '/docs/1.0.0/tags',
|
||||||
versionLabel: '1.0.0',
|
label: '1.0.0',
|
||||||
versionName: '1.0.0',
|
versionName: '1.0.0',
|
||||||
versionPath: '/docs/1.0.0',
|
path: '/docs/1.0.0',
|
||||||
versionBanner: 'unmaintained',
|
banner: 'unmaintained',
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-1.0.0',
|
className: 'docs-version-1.0.0',
|
||||||
};
|
};
|
||||||
|
|
||||||
const vWithSlugs: VersionMetadata = {
|
const vWithSlugs: VersionMetadata = {
|
||||||
|
@ -317,12 +319,12 @@ describe('readVersionsMetadata', () => {
|
||||||
'versioned_sidebars/version-withSlugs-sidebars.json',
|
'versioned_sidebars/version-withSlugs-sidebars.json',
|
||||||
),
|
),
|
||||||
tagsPath: '/docs/withSlugs/tags',
|
tagsPath: '/docs/withSlugs/tags',
|
||||||
versionLabel: 'withSlugs',
|
label: 'withSlugs',
|
||||||
versionName: 'withSlugs',
|
versionName: 'withSlugs',
|
||||||
versionPath: '/docs/withSlugs',
|
path: '/docs/withSlugs',
|
||||||
versionBanner: 'unmaintained',
|
banner: 'unmaintained',
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-withSlugs',
|
className: 'docs-version-withSlugs',
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -393,27 +395,27 @@ describe('readVersionsMetadata', () => {
|
||||||
{
|
{
|
||||||
...vCurrent,
|
...vCurrent,
|
||||||
tagsPath: '/docs/current-path/tags',
|
tagsPath: '/docs/current-path/tags',
|
||||||
versionPath: '/docs/current-path',
|
path: '/docs/current-path',
|
||||||
versionBanner: 'unmaintained',
|
banner: 'unmaintained',
|
||||||
versionBadge: false,
|
badge: false,
|
||||||
versionClassName: 'custom-current-className',
|
className: 'custom-current-className',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v101,
|
...v101,
|
||||||
isLast: false,
|
isLast: false,
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
tagsPath: '/docs/1.0.1/tags',
|
tagsPath: '/docs/1.0.1/tags',
|
||||||
versionPath: '/docs/1.0.1',
|
path: '/docs/1.0.1',
|
||||||
versionBanner: 'unreleased',
|
banner: 'unreleased',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v100,
|
...v100,
|
||||||
isLast: true,
|
isLast: true,
|
||||||
routePriority: -1,
|
routePriority: -1,
|
||||||
tagsPath: '/docs/tags',
|
tagsPath: '/docs/tags',
|
||||||
versionLabel: '1.0.0-label',
|
label: '1.0.0-label',
|
||||||
versionPath: '/docs',
|
path: '/docs',
|
||||||
versionBanner: 'unreleased',
|
banner: 'unreleased',
|
||||||
},
|
},
|
||||||
vWithSlugs,
|
vWithSlugs,
|
||||||
]);
|
]);
|
||||||
|
@ -434,30 +436,30 @@ describe('readVersionsMetadata', () => {
|
||||||
expect(versionsMetadata).toEqual([
|
expect(versionsMetadata).toEqual([
|
||||||
{
|
{
|
||||||
...vCurrent,
|
...vCurrent,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/docs',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v101,
|
...v101,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.1',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v100,
|
...v100,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.0',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...vWithSlugs,
|
...vWithSlugs,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-withSlugs',
|
'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',
|
'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([
|
expect(versionsMetadata).toEqual([
|
||||||
{
|
{
|
||||||
...vCurrent,
|
...vCurrent,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/docs',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v101,
|
...v101,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/docs',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...v100,
|
...v100,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/docs',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...vWithSlugs,
|
...vWithSlugs,
|
||||||
versionEditUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/main/website/docs',
|
'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',
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -538,9 +540,9 @@ describe('readVersionsMetadata', () => {
|
||||||
isLast: true,
|
isLast: true,
|
||||||
routePriority: -1,
|
routePriority: -1,
|
||||||
tagsPath: '/docs/tags',
|
tagsPath: '/docs/tags',
|
||||||
versionPath: '/docs',
|
path: '/docs',
|
||||||
versionBanner: null,
|
banner: null,
|
||||||
versionBadge: false,
|
badge: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -679,12 +681,12 @@ describe('readVersionsMetadata', () => {
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
|
sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'),
|
||||||
tagsPath: '/communityBasePath/next/tags',
|
tagsPath: '/communityBasePath/next/tags',
|
||||||
versionLabel: 'Next',
|
label: 'Next',
|
||||||
versionName: 'current',
|
versionName: 'current',
|
||||||
versionPath: '/communityBasePath/next',
|
path: '/communityBasePath/next',
|
||||||
versionBanner: 'unreleased',
|
banner: 'unreleased',
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-current',
|
className: 'docs-version-current',
|
||||||
};
|
};
|
||||||
|
|
||||||
const v100: VersionMetadata = {
|
const v100: VersionMetadata = {
|
||||||
|
@ -703,12 +705,12 @@ describe('readVersionsMetadata', () => {
|
||||||
'community_versioned_sidebars/version-1.0.0-sidebars.json',
|
'community_versioned_sidebars/version-1.0.0-sidebars.json',
|
||||||
),
|
),
|
||||||
tagsPath: '/communityBasePath/tags',
|
tagsPath: '/communityBasePath/tags',
|
||||||
versionLabel: '1.0.0',
|
label: '1.0.0',
|
||||||
versionName: '1.0.0',
|
versionName: '1.0.0',
|
||||||
versionPath: '/communityBasePath',
|
path: '/communityBasePath',
|
||||||
versionBanner: null,
|
banner: null,
|
||||||
versionBadge: true,
|
badge: true,
|
||||||
versionClassName: 'docs-version-1.0.0',
|
className: 'docs-version-1.0.0',
|
||||||
};
|
};
|
||||||
|
|
||||||
return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100};
|
return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100};
|
||||||
|
@ -735,7 +737,7 @@ describe('readVersionsMetadata', () => {
|
||||||
|
|
||||||
expect(versionsMetadata).toEqual([
|
expect(versionsMetadata).toEqual([
|
||||||
// vCurrent removed
|
// vCurrent removed
|
||||||
{...v100, versionBadge: false},
|
{...v100, badge: false},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -753,9 +755,9 @@ describe('readVersionsMetadata', () => {
|
||||||
isLast: true,
|
isLast: true,
|
||||||
routePriority: -1,
|
routePriority: -1,
|
||||||
tagsPath: '/communityBasePath/tags',
|
tagsPath: '/communityBasePath/tags',
|
||||||
versionPath: '/communityBasePath',
|
path: '/communityBasePath',
|
||||||
versionBanner: null,
|
banner: null,
|
||||||
versionBadge: false,
|
badge: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* 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 {SidebarItemCategoryWithGeneratedIndex} from './sidebars/types';
|
||||||
import {type SidebarsUtils, toNavigationLink} from './sidebars/utils';
|
import {type SidebarsUtils, toNavigationLink} from './sidebars/utils';
|
||||||
import {createDocsByIdIndex} from './docs';
|
import {createDocsByIdIndex} from './docs';
|
||||||
|
@ -29,8 +32,10 @@ function getCategoryGeneratedIndexMetadata({
|
||||||
slug: category.link.slug,
|
slug: category.link.slug,
|
||||||
permalink: category.link.permalink,
|
permalink: category.link.permalink,
|
||||||
sidebar: sidebarName!,
|
sidebar: sidebarName!,
|
||||||
|
navigation: {
|
||||||
previous: toNavigationLink(previous, docsById),
|
previous: toNavigationLink(previous, docsById),
|
||||||
next: toNavigationLink(next, docsById),
|
next: toNavigationLink(next, docsById),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
aliasedSitePath,
|
aliasedSitePath,
|
||||||
getEditUrl,
|
getEditUrl,
|
||||||
getFolderContainingFile,
|
getFolderContainingFile,
|
||||||
|
getContentPathList,
|
||||||
normalizeUrl,
|
normalizeUrl,
|
||||||
parseMarkdownString,
|
parseMarkdownString,
|
||||||
posixPath,
|
posixPath,
|
||||||
|
@ -21,18 +22,9 @@ import {
|
||||||
import type {LoadContext} from '@docusaurus/types';
|
import type {LoadContext} from '@docusaurus/types';
|
||||||
|
|
||||||
import {getFileLastUpdate} from './lastUpdate';
|
import {getFileLastUpdate} from './lastUpdate';
|
||||||
import type {
|
import type {DocFile, LoadedVersion} from './types';
|
||||||
DocFile,
|
|
||||||
DocMetadataBase,
|
|
||||||
DocMetadata,
|
|
||||||
DocNavLink,
|
|
||||||
LastUpdateData,
|
|
||||||
VersionMetadata,
|
|
||||||
LoadedVersion,
|
|
||||||
} from './types';
|
|
||||||
import getSlug from './slug';
|
import getSlug from './slug';
|
||||||
import {CURRENT_VERSION_NAME} from './constants';
|
import {CURRENT_VERSION_NAME} from './constants';
|
||||||
import {getDocsDirPaths} from './versions';
|
|
||||||
import {stripPathNumberPrefixes} from './numberPrefix';
|
import {stripPathNumberPrefixes} from './numberPrefix';
|
||||||
import {validateDocFrontMatter} from './frontMatter';
|
import {validateDocFrontMatter} from './frontMatter';
|
||||||
import type {SidebarsUtils} from './sidebars/utils';
|
import type {SidebarsUtils} from './sidebars/utils';
|
||||||
|
@ -41,7 +33,11 @@ import type {
|
||||||
MetadataOptions,
|
MetadataOptions,
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
CategoryIndexMatcher,
|
CategoryIndexMatcher,
|
||||||
CategoryIndexMatcherParam,
|
DocMetadataBase,
|
||||||
|
DocMetadata,
|
||||||
|
PropNavigationLink,
|
||||||
|
LastUpdateData,
|
||||||
|
VersionMetadata,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
|
|
||||||
type LastUpdateOptions = Pick<
|
type LastUpdateOptions = Pick<
|
||||||
|
@ -85,7 +81,7 @@ export async function readDocFile(
|
||||||
options: LastUpdateOptions,
|
options: LastUpdateOptions,
|
||||||
): Promise<DocFile> {
|
): Promise<DocFile> {
|
||||||
const contentPath = await getFolderContainingFile(
|
const contentPath = await getFolderContainingFile(
|
||||||
getDocsDirPaths(versionMetadata),
|
getContentPathList(versionMetadata),
|
||||||
source,
|
source,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -213,7 +209,7 @@ function doProcessDocMetadata({
|
||||||
|
|
||||||
const description: string = frontMatter.description ?? excerpt ?? '';
|
const description: string = frontMatter.description ?? excerpt ?? '';
|
||||||
|
|
||||||
const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]);
|
const permalink = normalizeUrl([versionMetadata.path, docSlug]);
|
||||||
|
|
||||||
function getDocEditUrl() {
|
function getDocEditUrl() {
|
||||||
const relativeFilePath = path.relative(contentPath, filePath);
|
const relativeFilePath = path.relative(contentPath, filePath);
|
||||||
|
@ -232,8 +228,8 @@ function doProcessDocMetadata({
|
||||||
const isLocalized = contentPath === versionMetadata.contentPathLocalized;
|
const isLocalized = contentPath === versionMetadata.contentPathLocalized;
|
||||||
const baseVersionEditUrl =
|
const baseVersionEditUrl =
|
||||||
isLocalized && options.editLocalizedFiles
|
isLocalized && options.editLocalizedFiles
|
||||||
? versionMetadata.versionEditUrlLocalized
|
? versionMetadata.editUrlLocalized
|
||||||
: versionMetadata.versionEditUrl;
|
: versionMetadata.editUrl;
|
||||||
return getEditUrl(relativeFilePath, baseVersionEditUrl);
|
return getEditUrl(relativeFilePath, baseVersionEditUrl);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -304,7 +300,7 @@ export function addDocNavigation(
|
||||||
const toNavigationLinkByDocId = (
|
const toNavigationLinkByDocId = (
|
||||||
docId: string | null | undefined,
|
docId: string | null | undefined,
|
||||||
type: 'prev' | 'next',
|
type: 'prev' | 'next',
|
||||||
): DocNavLink | undefined => {
|
): PropNavigationLink | undefined => {
|
||||||
if (!docId) {
|
if (!docId) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -401,7 +397,7 @@ export function toCategoryIndexMatcherParam({
|
||||||
}: Pick<
|
}: Pick<
|
||||||
DocMetadataBase,
|
DocMetadataBase,
|
||||||
'source' | 'sourceDirName'
|
'source' | 'sourceDirName'
|
||||||
>): CategoryIndexMatcherParam {
|
>): Parameters<CategoryIndexMatcher>[0] {
|
||||||
// source + sourceDirName are always posix-style
|
// source + sourceDirName are always posix-style
|
||||||
return {
|
return {
|
||||||
fileName: path.posix.parse(source).name,
|
fileName: path.posix.parse(source).name,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
FrontMatterTOCHeadingLevels,
|
FrontMatterTOCHeadingLevels,
|
||||||
validateFrontMatter,
|
validateFrontMatter,
|
||||||
} from '@docusaurus/utils-validation';
|
} 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
|
// 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
|
// We don't want default values to magically appear in doc metadata and props
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import type {Sidebars} from './sidebars/types';
|
import type {Sidebars} from './sidebars/types';
|
||||||
import {createSidebarsUtils} from './sidebars/utils';
|
import {createSidebarsUtils} from './sidebars/utils';
|
||||||
|
import type {LoadedVersion} from './types';
|
||||||
import type {
|
import type {
|
||||||
CategoryGeneratedIndexMetadata,
|
CategoryGeneratedIndexMetadata,
|
||||||
DocMetadata,
|
DocMetadata,
|
||||||
LoadedVersion,
|
} from '@docusaurus/plugin-content-docs';
|
||||||
} from './types';
|
|
||||||
import type {
|
import type {
|
||||||
GlobalVersion,
|
GlobalVersion,
|
||||||
GlobalSidebar,
|
GlobalSidebar,
|
||||||
|
@ -65,9 +65,9 @@ function toGlobalSidebars(
|
||||||
export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
|
export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
|
||||||
return {
|
return {
|
||||||
name: version.versionName,
|
name: version.versionName,
|
||||||
label: version.versionLabel,
|
label: version.label,
|
||||||
isLast: version.isLast,
|
isLast: version.isLast,
|
||||||
path: version.versionPath,
|
path: version.path,
|
||||||
mainDocId: version.mainDocId,
|
mainDocId: version.mainDocId,
|
||||||
docs: version.docs
|
docs: version.docs
|
||||||
.map(toGlobalDataDoc)
|
.map(toGlobalDataDoc)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
normalizeUrl,
|
normalizeUrl,
|
||||||
docuHash,
|
docuHash,
|
||||||
aliasedSitePath,
|
aliasedSitePath,
|
||||||
|
getContentPathList,
|
||||||
reportMessage,
|
reportMessage,
|
||||||
posixPath,
|
posixPath,
|
||||||
addTrailingPathSeparator,
|
addTrailingPathSeparator,
|
||||||
|
@ -27,18 +28,14 @@ import {
|
||||||
addDocNavigation,
|
addDocNavigation,
|
||||||
getMainDocId,
|
getMainDocId,
|
||||||
} from './docs';
|
} from './docs';
|
||||||
import {getDocsDirPaths, readVersionsMetadata} from './versions';
|
import {readVersionsMetadata} from './versions';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
LoadedContent,
|
LoadedContent,
|
||||||
SourceToPermalink,
|
SourceToPermalink,
|
||||||
DocMetadataBase,
|
|
||||||
VersionMetadata,
|
|
||||||
LoadedVersion,
|
LoadedVersion,
|
||||||
DocFile,
|
DocFile,
|
||||||
DocsMarkdownOption,
|
DocsMarkdownOption,
|
||||||
VersionTag,
|
VersionTag,
|
||||||
DocFrontMatter,
|
|
||||||
} from './types';
|
} from './types';
|
||||||
import type {RuleSetRule} from 'webpack';
|
import type {RuleSetRule} from 'webpack';
|
||||||
import {cliDocsVersionCommand} from './cli';
|
import {cliDocsVersionCommand} from './cli';
|
||||||
|
@ -55,6 +52,9 @@ import {createVersionRoutes} from './routes';
|
||||||
import type {
|
import type {
|
||||||
PropTagsListPage,
|
PropTagsListPage,
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
|
DocMetadataBase,
|
||||||
|
VersionMetadata,
|
||||||
|
DocFrontMatter,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
import {createSidebarsUtils} from './sidebars/utils';
|
import {createSidebarsUtils} from './sidebars/utils';
|
||||||
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
|
import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
|
||||||
|
@ -114,7 +114,7 @@ export default async function pluginContentDocs(
|
||||||
function getVersionPathsToWatch(version: VersionMetadata): string[] {
|
function getVersionPathsToWatch(version: VersionMetadata): string[] {
|
||||||
const result = [
|
const result = [
|
||||||
...options.include.flatMap((pattern) =>
|
...options.include.flatMap((pattern) =>
|
||||||
getDocsDirPaths(version).map(
|
getContentPathList(version).map(
|
||||||
(docsDirPath) => `${docsDirPath}/${pattern}`,
|
(docsDirPath) => `${docsDirPath}/${pattern}`,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -228,7 +228,7 @@ export default async function pluginContentDocs(
|
||||||
const tagsProp: PropTagsListPage['tags'] = Object.values(
|
const tagsProp: PropTagsListPage['tags'] = Object.values(
|
||||||
versionTags,
|
versionTags,
|
||||||
).map((tagValue) => ({
|
).map((tagValue) => ({
|
||||||
name: tagValue.name,
|
name: tagValue.label,
|
||||||
permalink: tagValue.permalink,
|
permalink: tagValue.permalink,
|
||||||
count: tagValue.docIds.length,
|
count: tagValue.docIds.length,
|
||||||
}));
|
}));
|
||||||
|
@ -331,7 +331,7 @@ export default async function pluginContentDocs(
|
||||||
};
|
};
|
||||||
|
|
||||||
function createMDXLoaderRule(): RuleSetRule {
|
function createMDXLoaderRule(): RuleSetRule {
|
||||||
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
|
const contentDirs = versionsMetadata.flatMap(getContentPathList);
|
||||||
return {
|
return {
|
||||||
test: /\.mdx?$/i,
|
test: /\.mdx?$/i,
|
||||||
include: contentDirs
|
include: contentDirs
|
||||||
|
|
|
@ -12,9 +12,9 @@ import {linkify} from '../linkify';
|
||||||
import type {
|
import type {
|
||||||
DocsMarkdownOption,
|
DocsMarkdownOption,
|
||||||
SourceToPermalink,
|
SourceToPermalink,
|
||||||
VersionMetadata,
|
|
||||||
DocBrokenMarkdownLink,
|
DocBrokenMarkdownLink,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
import type {VersionMetadata} from '@docusaurus/plugin-content-docs';
|
||||||
import {VERSIONED_DOCS_DIR, CURRENT_VERSION_NAME} from '../../constants';
|
import {VERSIONED_DOCS_DIR, CURRENT_VERSION_NAME} from '../../constants';
|
||||||
|
|
||||||
function createFakeVersion({
|
function createFakeVersion({
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {DocsMarkdownOption} from '../types';
|
import type {DocsMarkdownOption} from '../types';
|
||||||
import {getDocsDirPaths} from '../versions';
|
import {replaceMarkdownLinks, getContentPathList} from '@docusaurus/utils';
|
||||||
import {replaceMarkdownLinks} from '@docusaurus/utils';
|
|
||||||
|
|
||||||
function getVersion(filePath: string, options: DocsMarkdownOption) {
|
function getVersion(filePath: string, options: DocsMarkdownOption) {
|
||||||
const versionFound = options.versionsMetadata.find((version) =>
|
const versionFound = options.versionsMetadata.find((version) =>
|
||||||
getDocsDirPaths(version).some((docsDirPath) =>
|
getContentPathList(version).some((docsDirPath) =>
|
||||||
filePath.startsWith(docsDirPath),
|
filePath.startsWith(docsDirPath),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,18 +6,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare module '@docusaurus/plugin-content-docs' {
|
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 {
|
export interface Assets {
|
||||||
image?: string;
|
image?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom callback for parsing number prefixes from file/folder names.
|
||||||
|
*/
|
||||||
export type NumberPrefixParser = (filename: string) => {
|
export type NumberPrefixParser = (filename: string) => {
|
||||||
|
/** file name without number prefix, without any other modification. */
|
||||||
filename: string;
|
filename: string;
|
||||||
|
/** The number prefix. Can be float, integer, negative, or anything. */
|
||||||
numberPrefix?: number;
|
numberPrefix?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CategoryIndexMatcherParam = {
|
export type CategoryIndexMatcher = (param: {
|
||||||
/** The file name, without extension */
|
/** The file name, without extension */
|
||||||
fileName: string;
|
fileName: string;
|
||||||
/**
|
/**
|
||||||
|
@ -27,110 +34,442 @@ declare module '@docusaurus/plugin-content-docs' {
|
||||||
directories: string[];
|
directories: string[];
|
||||||
/** The extension, with a leading dot */
|
/** The extension, with a leading dot */
|
||||||
extension: string;
|
extension: string;
|
||||||
};
|
}) => boolean;
|
||||||
export type CategoryIndexMatcher = (
|
|
||||||
param: CategoryIndexMatcherParam,
|
|
||||||
) => boolean;
|
|
||||||
|
|
||||||
export type EditUrlFunction = (editUrlParams: {
|
export type EditUrlFunction = (editUrlParams: {
|
||||||
|
/** Name of the version. */
|
||||||
version: string;
|
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;
|
versionDocsDirPath: string;
|
||||||
|
/** Path of the doc file, relative to `versionDocsDirPath`. */
|
||||||
docPath: string;
|
docPath: string;
|
||||||
|
/** @see {@link DocMetadata.permalink} */
|
||||||
permalink: string;
|
permalink: string;
|
||||||
|
/** Locale name. */
|
||||||
locale: string;
|
locale: string;
|
||||||
}) => string | undefined;
|
}) => string | undefined;
|
||||||
|
|
||||||
export type MetadataOptions = {
|
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;
|
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;
|
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;
|
editCurrentVersion: boolean;
|
||||||
|
/**
|
||||||
|
* The edit URL will target the localized file, instead of the original
|
||||||
|
* unlocalized file. Ignored when `editUrl` is a function.
|
||||||
|
*/
|
||||||
editLocalizedFiles: boolean;
|
editLocalizedFiles: boolean;
|
||||||
|
/** Whether to display the last date the doc was updated. */
|
||||||
showLastUpdateTime?: boolean;
|
showLastUpdateTime?: boolean;
|
||||||
|
/** Whether to display the author who last updated the doc. */
|
||||||
showLastUpdateAuthor?: boolean;
|
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;
|
numberPrefixParser: NumberPrefixParser;
|
||||||
|
/** Enable or disable the breadcrumbs on doc pages. */
|
||||||
breadcrumbs: boolean;
|
breadcrumbs: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PathOptions = {
|
export type PathOptions = {
|
||||||
|
/**
|
||||||
|
* Path to the docs content directory on the file system, relative to site
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
path: string;
|
path: string;
|
||||||
|
/**
|
||||||
|
* Path to sidebar configuration. Use `false` to disable sidebars, or
|
||||||
|
* `undefined` to create a fully autogenerated sidebar.
|
||||||
|
*/
|
||||||
sidebarPath?: string | false | undefined;
|
sidebarPath?: string | false | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO support custom version banner?
|
// TODO support custom version banner?
|
||||||
// {type: "error", content: "html content"}
|
// {type: "error", content: "html content"}
|
||||||
export type VersionBanner = 'unreleased' | 'unmaintained';
|
export type VersionBanner = 'unreleased' | 'unmaintained';
|
||||||
export type VersionOptions = {
|
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;
|
||||||
|
/** 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;
|
path?: string;
|
||||||
|
/** The label of the version to be used in badges, dropdowns, etc. */
|
||||||
label?: string;
|
label?: string;
|
||||||
|
/** The banner to show at the top of a doc of that version. */
|
||||||
banner?: 'none' | VersionBanner;
|
banner?: 'none' | VersionBanner;
|
||||||
|
/** Show a badge with the version label at the top of each doc. */
|
||||||
badge?: boolean;
|
badge?: boolean;
|
||||||
|
/** Add a custom class name to the <html> element of each doc. */
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
export type VersionsOptions = {
|
};
|
||||||
lastVersion?: string;
|
|
||||||
versions: {[versionName: string]: VersionOptions};
|
|
||||||
onlyIncludeVersions?: string[];
|
|
||||||
};
|
};
|
||||||
export type SidebarOptions = {
|
export type SidebarOptions = {
|
||||||
|
/**
|
||||||
|
* Whether sidebar categories are collapsible by default.
|
||||||
|
*
|
||||||
|
* @see https://docusaurus.io/docs/sidebar#collapsible-categories
|
||||||
|
*/
|
||||||
sidebarCollapsible: boolean;
|
sidebarCollapsible: boolean;
|
||||||
|
/**
|
||||||
|
* Whether sidebar categories are collapsed by default.
|
||||||
|
*
|
||||||
|
* @see https://docusaurus.io/docs/sidebar#expanded-categories-by-default
|
||||||
|
*/
|
||||||
sidebarCollapsed: boolean;
|
sidebarCollapsed: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginOptions = MetadataOptions &
|
export type PluginOptions = MetadataOptions &
|
||||||
PathOptions &
|
PathOptions &
|
||||||
VersionsOptions &
|
VersionsOptions &
|
||||||
RemarkAndRehypePluginOptions &
|
MDXOptions &
|
||||||
SidebarOptions & {
|
SidebarOptions & {
|
||||||
|
/** Plugin ID. */
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* Array of glob patterns matching Markdown files to be built, relative to
|
||||||
|
* the content path.
|
||||||
|
*/
|
||||||
include: string[];
|
include: string[];
|
||||||
|
/**
|
||||||
|
* Array of glob patterns matching Markdown files to be excluded. Serves
|
||||||
|
* as refinement based on the `include` option.
|
||||||
|
*/
|
||||||
exclude: string[];
|
exclude: string[];
|
||||||
|
/**
|
||||||
|
* Root layout component of each doc page. Provides the version data
|
||||||
|
* context, and is not unmounted when switching docs.
|
||||||
|
*/
|
||||||
docLayoutComponent: string;
|
docLayoutComponent: string;
|
||||||
|
/** Main doc container, with TOC, pagination, etc. */
|
||||||
docItemComponent: string;
|
docItemComponent: string;
|
||||||
|
/** Root component of the "docs containing tag X" page. */
|
||||||
docTagDocListComponent: string;
|
docTagDocListComponent: string;
|
||||||
|
/** Root component of the tags list page */
|
||||||
docTagsListComponent: string;
|
docTagsListComponent: string;
|
||||||
|
/** Root component of the generated category index page. */
|
||||||
docCategoryGeneratedIndexComponent: string;
|
docCategoryGeneratedIndexComponent: string;
|
||||||
admonitions: {[key: string]: unknown};
|
admonitions: {[key: string]: unknown};
|
||||||
disableVersioning: boolean;
|
|
||||||
includeCurrentVersion: boolean;
|
|
||||||
sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
|
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;
|
tagsBasePath: string;
|
||||||
};
|
};
|
||||||
export type Options = Partial<PluginOptions>;
|
export type Options = Partial<PluginOptions>;
|
||||||
export type SidebarsConfig = import('./sidebars/types').SidebarsConfig;
|
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 = {
|
export type PropNavigationLink = {
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly permalink: string;
|
readonly permalink: string;
|
||||||
};
|
};
|
||||||
export type PropNavigation = {
|
export type PropNavigation = {
|
||||||
|
/**
|
||||||
|
* Used in pagination. Content is just a subset of another doc's metadata.
|
||||||
|
*/
|
||||||
readonly previous?: PropNavigationLink;
|
readonly previous?: PropNavigationLink;
|
||||||
|
/**
|
||||||
|
* Used in pagination. Content is just a subset of another doc's metadata.
|
||||||
|
*/
|
||||||
readonly next?: PropNavigationLink;
|
readonly next?: PropNavigationLink;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PropVersionDoc = import('./sidebars/types').PropVersionDoc;
|
export type PropVersionDoc = Pick<
|
||||||
export type PropVersionDocs = import('./sidebars/types').PropVersionDocs;
|
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;
|
pluginId: string;
|
||||||
|
/** Name of this version. */
|
||||||
version: string;
|
version: string;
|
||||||
label: string;
|
/** Sidebars contained in this version. */
|
||||||
banner: VersionBanner | null;
|
|
||||||
badge: boolean;
|
|
||||||
className: string;
|
|
||||||
isLast: boolean;
|
|
||||||
docsSidebars: PropSidebars;
|
docsSidebars: PropSidebars;
|
||||||
|
/** Docs contained in this version. */
|
||||||
docs: PropVersionDocs;
|
docs: PropVersionDocs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PropCategoryGeneratedIndex = {
|
export type PropCategoryGeneratedIndex = Omit<
|
||||||
title: string;
|
CategoryGeneratedIndexMetadata,
|
||||||
description?: string;
|
'sidebar'
|
||||||
image?: string;
|
>;
|
||||||
keywords?: string | readonly string[];
|
|
||||||
slug: string;
|
|
||||||
permalink: string;
|
|
||||||
navigation: PropNavigation;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PropSidebarItemLink =
|
export type PropSidebarItemLink =
|
||||||
import('./sidebars/types').PropSidebarItemLink;
|
import('./sidebars/types').PropSidebarItemLink;
|
||||||
|
@ -169,9 +508,10 @@ declare module '@docusaurus/plugin-content-docs' {
|
||||||
declare module '@theme/DocItem' {
|
declare module '@theme/DocItem' {
|
||||||
import type {TOCItem} from '@docusaurus/types';
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
import type {
|
import type {
|
||||||
PropNavigationLink,
|
|
||||||
PropVersionMetadata,
|
PropVersionMetadata,
|
||||||
Assets,
|
Assets,
|
||||||
|
DocMetadata,
|
||||||
|
DocFrontMatter,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
|
|
||||||
export type DocumentRoute = {
|
export type DocumentRoute = {
|
||||||
|
@ -181,41 +521,12 @@ declare module '@theme/DocItem' {
|
||||||
readonly sidebar?: string;
|
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 {
|
export interface Props {
|
||||||
readonly route: DocumentRoute;
|
readonly route: DocumentRoute;
|
||||||
readonly versionMetadata: PropVersionMetadata;
|
readonly versionMetadata: PropVersionMetadata;
|
||||||
readonly content: {
|
readonly content: {
|
||||||
readonly frontMatter: FrontMatter;
|
readonly frontMatter: DocFrontMatter;
|
||||||
readonly metadata: Metadata;
|
readonly metadata: DocMetadata;
|
||||||
readonly toc: readonly TOCItem[];
|
readonly toc: readonly TOCItem[];
|
||||||
readonly contentTitle: string | undefined;
|
readonly contentTitle: string | undefined;
|
||||||
readonly assets: Assets;
|
readonly assets: Assets;
|
||||||
|
|
|
@ -5,13 +5,12 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* 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 {
|
import type {
|
||||||
SidebarItemDoc,
|
SidebarItemDoc,
|
||||||
SidebarItem,
|
SidebarItem,
|
||||||
SidebarItemCategory,
|
SidebarItemCategory,
|
||||||
SidebarItemCategoryLink,
|
SidebarItemCategoryLink,
|
||||||
PropVersionDocs,
|
|
||||||
} from './sidebars/types';
|
} from './sidebars/types';
|
||||||
import type {
|
import type {
|
||||||
PropSidebars,
|
PropSidebars,
|
||||||
|
@ -21,6 +20,8 @@ import type {
|
||||||
PropTagDocList,
|
PropTagDocList,
|
||||||
PropTagDocListDoc,
|
PropTagDocListDoc,
|
||||||
PropSidebarItemLink,
|
PropSidebarItemLink,
|
||||||
|
PropVersionDocs,
|
||||||
|
DocMetadata,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {createDocsByIdIndex} from './docs';
|
import {createDocsByIdIndex} from './docs';
|
||||||
|
@ -119,10 +120,10 @@ export function toVersionMetadataProp(
|
||||||
return {
|
return {
|
||||||
pluginId,
|
pluginId,
|
||||||
version: loadedVersion.versionName,
|
version: loadedVersion.versionName,
|
||||||
label: loadedVersion.versionLabel,
|
label: loadedVersion.label,
|
||||||
banner: loadedVersion.versionBanner,
|
banner: loadedVersion.banner,
|
||||||
badge: loadedVersion.versionBadge,
|
badge: loadedVersion.badge,
|
||||||
className: loadedVersion.versionClassName,
|
className: loadedVersion.className,
|
||||||
isLast: loadedVersion.isLast,
|
isLast: loadedVersion.isLast,
|
||||||
docsSidebars: toSidebarsProp(loadedVersion),
|
docsSidebars: toSidebarsProp(loadedVersion),
|
||||||
docs: toVersionDocsProp(loadedVersion),
|
docs: toVersionDocsProp(loadedVersion),
|
||||||
|
@ -153,7 +154,7 @@ export function toTagDocListProp({
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: tag.name,
|
name: tag.label,
|
||||||
permalink: tag.permalink,
|
permalink: tag.permalink,
|
||||||
docs: toDocListProp(),
|
docs: toDocListProp(),
|
||||||
allTagsPath,
|
allTagsPath,
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
|
|
||||||
import type {PluginContentLoadedActions, RouteConfig} from '@docusaurus/types';
|
import type {PluginContentLoadedActions, RouteConfig} from '@docusaurus/types';
|
||||||
import {docuHash, createSlugger} from '@docusaurus/utils';
|
import {docuHash, createSlugger} from '@docusaurus/utils';
|
||||||
|
import type {LoadedVersion} from './types';
|
||||||
import type {
|
import type {
|
||||||
CategoryGeneratedIndexMetadata,
|
CategoryGeneratedIndexMetadata,
|
||||||
DocMetadata,
|
DocMetadata,
|
||||||
LoadedVersion,
|
} from '@docusaurus/plugin-content-docs';
|
||||||
} from './types';
|
|
||||||
import type {PropCategoryGeneratedIndex} from '@docusaurus/plugin-content-docs';
|
|
||||||
import {toVersionMetadataProp} from './props';
|
import {toVersionMetadataProp} from './props';
|
||||||
import logger from '@docusaurus/logger';
|
import logger from '@docusaurus/logger';
|
||||||
|
|
||||||
|
@ -32,42 +31,19 @@ export async function createCategoryGeneratedIndexRoutes({
|
||||||
async function createCategoryGeneratedIndexRoute(
|
async function createCategoryGeneratedIndexRoute(
|
||||||
categoryGeneratedIndex: CategoryGeneratedIndexMetadata,
|
categoryGeneratedIndex: CategoryGeneratedIndexMetadata,
|
||||||
): Promise<RouteConfig> {
|
): Promise<RouteConfig> {
|
||||||
const {
|
const {sidebar, ...prop} = categoryGeneratedIndex;
|
||||||
sidebar,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
slug,
|
|
||||||
permalink,
|
|
||||||
previous,
|
|
||||||
next,
|
|
||||||
image,
|
|
||||||
keywords,
|
|
||||||
} = categoryGeneratedIndex;
|
|
||||||
|
|
||||||
const propFileName = slugs.slug(
|
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(
|
const propData = await actions.createData(
|
||||||
`${docuHash(`category/${propFileName}`)}.json`,
|
`${docuHash(`category/${propFileName}`)}.json`,
|
||||||
JSON.stringify(prop, null, 2),
|
JSON.stringify(prop, null, 2),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: permalink,
|
path: categoryGeneratedIndex.permalink,
|
||||||
component: docCategoryGeneratedIndexComponent,
|
component: docCategoryGeneratedIndexComponent,
|
||||||
exact: true,
|
exact: true,
|
||||||
modules: {
|
modules: {
|
||||||
|
@ -162,7 +138,7 @@ export async function createVersionRoutes({
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.addRoute({
|
actions.addRoute({
|
||||||
path: version.versionPath,
|
path: version.path,
|
||||||
// allow matching /docs/* as well
|
// allow matching /docs/* as well
|
||||||
exact: false,
|
exact: false,
|
||||||
// main docs component (DocPage)
|
// main docs component (DocPage)
|
||||||
|
|
|
@ -34,7 +34,7 @@ describe('postProcess', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
||||||
version: {versionPath: 'version'},
|
version: {path: 'version'},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ describe('postProcess', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
||||||
version: {versionPath: 'version'},
|
version: {path: 'version'},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}).toThrowErrorMatchingInlineSnapshot(
|
}).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
@ -78,7 +78,7 @@ describe('postProcess', () => {
|
||||||
|
|
||||||
{
|
{
|
||||||
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
||||||
version: {versionPath: 'version'},
|
version: {path: 'version'},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
|
@ -98,7 +98,7 @@ describe('postProcess', () => {
|
||||||
|
|
||||||
{
|
{
|
||||||
sidebarOptions: {sidebarCollapsed: false, sidebarCollapsible: false},
|
sidebarOptions: {sidebarCollapsed: false, sidebarCollapsible: false},
|
||||||
version: {versionPath: 'version'},
|
version: {path: 'version'},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
|
@ -117,7 +117,7 @@ describe('postProcess', () => {
|
||||||
|
|
||||||
{
|
{
|
||||||
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: false},
|
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: false},
|
||||||
version: {versionPath: 'version'},
|
version: {path: 'version'},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
|
|
|
@ -18,7 +18,7 @@ import type {
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {DefaultSidebarItemsGenerator} from '../generator';
|
import {DefaultSidebarItemsGenerator} from '../generator';
|
||||||
import {createSlugger} from '@docusaurus/utils';
|
import {createSlugger} from '@docusaurus/utils';
|
||||||
import type {VersionMetadata} from '../../types';
|
import type {VersionMetadata} from '@docusaurus/plugin-content-docs';
|
||||||
import {DefaultNumberPrefixParser} from '../../numberPrefix';
|
import {DefaultNumberPrefixParser} from '../../numberPrefix';
|
||||||
import {isCategoryIndex} from '../../docs';
|
import {isCategoryIndex} from '../../docs';
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,10 @@ import {
|
||||||
toNavigationLink,
|
toNavigationLink,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import type {Sidebar, Sidebars} from '../types';
|
import type {Sidebar, Sidebars} from '../types';
|
||||||
import type {DocMetadataBase, DocNavLink} from '../../types';
|
import type {
|
||||||
|
DocMetadataBase,
|
||||||
|
PropNavigationLink,
|
||||||
|
} from '@docusaurus/plugin-content-docs';
|
||||||
|
|
||||||
describe('createSidebarsUtils', () => {
|
describe('createSidebarsUtils', () => {
|
||||||
const sidebar1: Sidebar = [
|
const sidebar1: Sidebar = [
|
||||||
|
@ -618,7 +621,7 @@ describe('toDocNavigationLink', () => {
|
||||||
).toEqual({
|
).toEqual({
|
||||||
title: 'Doc Title',
|
title: 'Doc Title',
|
||||||
permalink: '/docPermalink',
|
permalink: '/docPermalink',
|
||||||
} as DocNavLink);
|
} as PropNavigationLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with pagination_label front matter', () => {
|
it('with pagination_label front matter', () => {
|
||||||
|
@ -635,7 +638,7 @@ describe('toDocNavigationLink', () => {
|
||||||
).toEqual({
|
).toEqual({
|
||||||
title: 'pagination_label',
|
title: 'pagination_label',
|
||||||
permalink: '/docPermalink',
|
permalink: '/docPermalink',
|
||||||
} as DocNavLink);
|
} as PropNavigationLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with sidebar_label front matter', () => {
|
it('with sidebar_label front matter', () => {
|
||||||
|
@ -652,7 +655,7 @@ describe('toDocNavigationLink', () => {
|
||||||
).toEqual({
|
).toEqual({
|
||||||
title: 'sidebar_label',
|
title: 'sidebar_label',
|
||||||
permalink: '/docPermalink',
|
permalink: '/docPermalink',
|
||||||
} as DocNavLink);
|
} as PropNavigationLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with pagination_label + sidebar_label front matter', () => {
|
it('with pagination_label + sidebar_label front matter', () => {
|
||||||
|
@ -670,7 +673,7 @@ describe('toDocNavigationLink', () => {
|
||||||
).toEqual({
|
).toEqual({
|
||||||
title: 'pagination_label',
|
title: 'pagination_label',
|
||||||
permalink: '/docPermalink',
|
permalink: '/docPermalink',
|
||||||
} as DocNavLink);
|
} as PropNavigationLink);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ function normalizeCategoryLink(
|
||||||
const getDefaultSlug = () =>
|
const getDefaultSlug = () =>
|
||||||
`/category/${params.categoryLabelSlugger.slug(category.label)}`;
|
`/category/${params.categoryLabelSlugger.slug(category.label)}`;
|
||||||
const slug = category.link.slug ?? getDefaultSlug();
|
const slug = category.link.slug ?? getDefaultSlug();
|
||||||
const permalink = normalizeUrl([params.version.versionPath, slug]);
|
const permalink = normalizeUrl([params.version.path, slug]);
|
||||||
return {
|
return {
|
||||||
...category.link,
|
...category.link,
|
||||||
slug,
|
slug,
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* 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 {
|
import type {
|
||||||
NormalizedSidebarItem,
|
NormalizedSidebarItem,
|
||||||
NormalizedSidebar,
|
NormalizedSidebar,
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {Optional, Required} from 'utility-types';
|
import type {Optional, Required} from 'utility-types';
|
||||||
import type {DocMetadataBase, VersionMetadata} from '../types';
|
|
||||||
import type {
|
import type {
|
||||||
NumberPrefixParser,
|
NumberPrefixParser,
|
||||||
SidebarOptions,
|
SidebarOptions,
|
||||||
CategoryIndexMatcher,
|
CategoryIndexMatcher,
|
||||||
|
DocMetadataBase,
|
||||||
|
VersionMetadata,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
import type {Slugger} from '@docusaurus/utils';
|
import type {Slugger} from '@docusaurus/utils';
|
||||||
|
|
||||||
|
@ -199,16 +200,6 @@ export type PropSidebarBreadcrumbsItem =
|
||||||
| PropSidebarItemLink
|
| PropSidebarItemLink
|
||||||
| PropSidebarItemCategory;
|
| PropSidebarItemCategory;
|
||||||
|
|
||||||
export type PropVersionDoc = {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
description?: string;
|
|
||||||
sidebar?: string;
|
|
||||||
};
|
|
||||||
export type PropVersionDocs = {
|
|
||||||
[docId: string]: PropVersionDoc;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CategoryMetadataFile = {
|
export type CategoryMetadataFile = {
|
||||||
label?: string;
|
label?: string;
|
||||||
position?: number;
|
position?: number;
|
||||||
|
@ -243,11 +234,20 @@ export type SidebarItemsGeneratorVersion = Pick<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type SidebarItemsGeneratorArgs = {
|
export type SidebarItemsGeneratorArgs = {
|
||||||
|
/** The sidebar item with type "autogenerated" to be transformed. */
|
||||||
item: SidebarItemAutogenerated;
|
item: SidebarItemAutogenerated;
|
||||||
|
/** Useful metadata for the version this sidebar belongs to. */
|
||||||
version: SidebarItemsGeneratorVersion;
|
version: SidebarItemsGeneratorVersion;
|
||||||
|
/** All the docs of that version (unfiltered). */
|
||||||
docs: SidebarItemsGeneratorDoc[];
|
docs: SidebarItemsGeneratorDoc[];
|
||||||
|
/** Number prefix parser configured for this plugin. */
|
||||||
numberPrefixParser: NumberPrefixParser;
|
numberPrefixParser: NumberPrefixParser;
|
||||||
|
/** The default category index matcher which you can override. */
|
||||||
isCategoryIndex: CategoryIndexMatcher;
|
isCategoryIndex: CategoryIndexMatcher;
|
||||||
|
/**
|
||||||
|
* key is the path relative to the doc content directory, value is the
|
||||||
|
* category metadata file's content.
|
||||||
|
*/
|
||||||
categoriesMetadata: {[filePath: string]: CategoryMetadataFile};
|
categoriesMetadata: {[filePath: string]: CategoryMetadataFile};
|
||||||
};
|
};
|
||||||
export type SidebarItemsGenerator = (
|
export type SidebarItemsGenerator = (
|
||||||
|
@ -258,6 +258,10 @@ export type SidebarItemsGenerator = (
|
||||||
// default sidebar gen logic
|
// default sidebar gen logic
|
||||||
// see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320
|
// see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320
|
||||||
export type SidebarItemsGeneratorOptionArgs = {
|
export type SidebarItemsGeneratorOptionArgs = {
|
||||||
|
/**
|
||||||
|
* Useful to re-use/enhance the default sidebar generation logic from
|
||||||
|
* Docusaurus.
|
||||||
|
*/
|
||||||
defaultSidebarItemsGenerator: SidebarItemsGenerator;
|
defaultSidebarItemsGenerator: SidebarItemsGenerator;
|
||||||
} & SidebarItemsGeneratorArgs;
|
} & SidebarItemsGeneratorArgs;
|
||||||
export type SidebarItemsGeneratorOption = (
|
export type SidebarItemsGeneratorOption = (
|
||||||
|
|
|
@ -21,7 +21,10 @@ import type {
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {toMessageRelativeFilePath} from '@docusaurus/utils';
|
import {toMessageRelativeFilePath} from '@docusaurus/utils';
|
||||||
import type {DocMetadataBase, DocNavLink} from '../types';
|
import type {
|
||||||
|
DocMetadataBase,
|
||||||
|
PropNavigationLink,
|
||||||
|
} from '@docusaurus/plugin-content-docs';
|
||||||
|
|
||||||
export function isCategoriesShorthand(
|
export function isCategoriesShorthand(
|
||||||
item: SidebarItemConfig,
|
item: SidebarItemConfig,
|
||||||
|
@ -346,7 +349,7 @@ Available document ids are:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink {
|
export function toDocNavigationLink(doc: DocMetadataBase): PropNavigationLink {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
permalink,
|
permalink,
|
||||||
|
@ -361,7 +364,7 @@ export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink {
|
||||||
export function toNavigationLink(
|
export function toNavigationLink(
|
||||||
navigationItem: SidebarNavigationItem | undefined,
|
navigationItem: SidebarNavigationItem | undefined,
|
||||||
docsById: {[docId: string]: DocMetadataBase},
|
docsById: {[docId: string]: DocMetadataBase},
|
||||||
): DocNavLink | undefined {
|
): PropNavigationLink | undefined {
|
||||||
function getDocById(docId: string) {
|
function getDocById(docId: string) {
|
||||||
const doc = docsById[docId];
|
const doc = docsById[docId];
|
||||||
if (!doc) {
|
if (!doc) {
|
||||||
|
|
|
@ -15,9 +15,11 @@ import {
|
||||||
DefaultNumberPrefixParser,
|
DefaultNumberPrefixParser,
|
||||||
stripPathNumberPrefixes,
|
stripPathNumberPrefixes,
|
||||||
} from './numberPrefix';
|
} from './numberPrefix';
|
||||||
import type {DocMetadataBase} from './types';
|
|
||||||
import {isCategoryIndex, toCategoryIndexMatcherParam} from './docs';
|
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({
|
export default function getSlug({
|
||||||
baseID,
|
baseID,
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {groupTaggedItems} from '@docusaurus/utils';
|
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';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export function getVersionTags(docs: DocMetadata[]): VersionTags {
|
export function getVersionTags(docs: DocMetadata[]): VersionTags {
|
||||||
const groups = groupTaggedItems(docs, (doc) => doc.tags);
|
const groups = groupTaggedItems(docs, (doc) => doc.tags);
|
||||||
return _.mapValues(groups, (group) => ({
|
return _.mapValues(groups, (group) => ({
|
||||||
name: group.tag.label,
|
label: group.tag.label,
|
||||||
docIds: group.items.map((item) => item.id),
|
docIds: group.items.map((item) => item.id),
|
||||||
permalink: group.tag.permalink,
|
permalink: group.tag.permalink,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -245,7 +245,7 @@ function translateSidebars(
|
||||||
function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles {
|
function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles {
|
||||||
const versionTranslations: TranslationFileContent = {
|
const versionTranslations: TranslationFileContent = {
|
||||||
'version.label': {
|
'version.label': {
|
||||||
message: version.versionLabel,
|
message: version.label,
|
||||||
description: `The label for version ${version.versionName}`,
|
description: `The label for version ${version.versionName}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -275,8 +275,7 @@ function translateVersion(
|
||||||
translationFiles[getVersionFileName(version.versionName)]!.content;
|
translationFiles[getVersionFileName(version.versionName)]!.content;
|
||||||
return {
|
return {
|
||||||
...version,
|
...version,
|
||||||
versionLabel:
|
label: versionTranslations['version.label']?.message ?? version.label,
|
||||||
versionTranslations['version.label']?.message ?? version.versionLabel,
|
|
||||||
sidebars: translateSidebars(version, versionTranslations),
|
sidebars: translateSidebars(version, versionTranslations),
|
||||||
// docs: translateDocs(version.docs, versionTranslations),
|
// docs: translateDocs(version.docs, versionTranslations),
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
/// <reference types="@docusaurus/module-type-aliases" />
|
/// <reference types="@docusaurus/module-type-aliases" />
|
||||||
|
|
||||||
import type {Sidebars} from './sidebars/types';
|
import type {Sidebars} from './sidebars/types';
|
||||||
|
import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils';
|
||||||
import type {
|
import type {
|
||||||
Tag,
|
VersionMetadata,
|
||||||
FrontMatterTag,
|
LastUpdateData,
|
||||||
BrokenMarkdownLink,
|
DocMetadata,
|
||||||
ContentPaths,
|
CategoryGeneratedIndexMetadata,
|
||||||
} from '@docusaurus/utils';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
import type {VersionBanner} from '@docusaurus/plugin-content-docs';
|
|
||||||
|
|
||||||
export type DocFile = {
|
export type DocFile = {
|
||||||
contentPath: string; // /!\ may be localized
|
contentPath: string; // /!\ may be localized
|
||||||
|
@ -24,106 +24,19 @@ export type DocFile = {
|
||||||
lastUpdate: LastUpdateData;
|
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 = {
|
export type SourceToPermalink = {
|
||||||
[source: string]: string;
|
[source: string]: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VersionTag = {
|
export type VersionTag = Tag & {
|
||||||
name: string; // normalized name/label of the tag
|
/** all doc ids having this tag. */
|
||||||
docIds: string[]; // all doc ids having this tag
|
docIds: string[];
|
||||||
permalink: string; // pathname of the tag
|
|
||||||
};
|
};
|
||||||
export type VersionTags = {
|
export type VersionTags = {
|
||||||
[key: string]: VersionTag;
|
[key: string]: VersionTag;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LoadedVersion = VersionMetadata & {
|
export type LoadedVersion = VersionMetadata & {
|
||||||
versionPath: string;
|
|
||||||
mainDocId: string;
|
mainDocId: string;
|
||||||
docs: DocMetadata[];
|
docs: DocMetadata[];
|
||||||
sidebars: Sidebars;
|
sidebars: Sidebars;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import type {VersionMetadata} from './types';
|
|
||||||
import {
|
import {
|
||||||
VERSIONS_JSON_FILE,
|
VERSIONS_JSON_FILE,
|
||||||
VERSIONED_DOCS_DIR,
|
VERSIONED_DOCS_DIR,
|
||||||
|
@ -17,8 +16,8 @@ import {
|
||||||
import type {
|
import type {
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
VersionBanner,
|
VersionBanner,
|
||||||
VersionOptions,
|
|
||||||
VersionsOptions,
|
VersionsOptions,
|
||||||
|
VersionMetadata,
|
||||||
} from '@docusaurus/plugin-content-docs';
|
} from '@docusaurus/plugin-content-docs';
|
||||||
|
|
||||||
import type {LoadContext} from '@docusaurus/types';
|
import type {LoadContext} from '@docusaurus/types';
|
||||||
|
@ -207,7 +206,12 @@ function getVersionEditUrls({
|
||||||
contentPath,
|
contentPath,
|
||||||
contentPathLocalized,
|
contentPathLocalized,
|
||||||
context: {siteDir, i18n},
|
context: {siteDir, i18n},
|
||||||
options: {id, path: currentVersionPath, editUrl, editCurrentVersion},
|
options: {
|
||||||
|
id,
|
||||||
|
path: currentVersionPath,
|
||||||
|
editUrl: editUrlOption,
|
||||||
|
editCurrentVersion,
|
||||||
|
},
|
||||||
}: {
|
}: {
|
||||||
contentPath: string;
|
contentPath: string;
|
||||||
contentPathLocalized: string;
|
contentPathLocalized: string;
|
||||||
|
@ -216,15 +220,11 @@ function getVersionEditUrls({
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
'id' | 'path' | 'editUrl' | 'editCurrentVersion'
|
'id' | 'path' | 'editUrl' | 'editCurrentVersion'
|
||||||
>;
|
>;
|
||||||
}): {versionEditUrl: string; versionEditUrlLocalized: string} | undefined {
|
}): Pick<VersionMetadata, 'editUrl' | 'editUrlLocalized'> {
|
||||||
if (!editUrl) {
|
// If the user is using the functional form of editUrl,
|
||||||
return undefined;
|
// she has total freedom and we can't compute a "version edit url"
|
||||||
}
|
if (!editUrlOption || typeof editUrlOption === 'function') {
|
||||||
|
return {editUrl: undefined, editUrlLocalized: 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const editDirPath = editCurrentVersion ? currentVersionPath : contentPath;
|
const editDirPath = editCurrentVersion ? currentVersionPath : contentPath;
|
||||||
|
@ -244,16 +244,16 @@ function getVersionEditUrls({
|
||||||
path.relative(siteDir, path.resolve(siteDir, editDirPathLocalized)),
|
path.relative(siteDir, path.resolve(siteDir, editDirPathLocalized)),
|
||||||
);
|
);
|
||||||
|
|
||||||
const versionEditUrl = normalizeUrl([editUrl, versionPathSegment]);
|
const editUrl = normalizeUrl([editUrlOption, versionPathSegment]);
|
||||||
|
|
||||||
const versionEditUrlLocalized = normalizeUrl([
|
const editUrlLocalized = normalizeUrl([
|
||||||
editUrl,
|
editUrlOption,
|
||||||
versionPathSegmentLocalized,
|
versionPathSegmentLocalized,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
versionEditUrl,
|
editUrl,
|
||||||
versionEditUrlLocalized,
|
editUrlLocalized,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,12 +370,12 @@ function createVersionMetadata({
|
||||||
}
|
}
|
||||||
const defaultVersionPathPart = getDefaultVersionPathPart();
|
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 versionPathPart = versionOptions.path ?? defaultVersionPathPart;
|
||||||
|
|
||||||
const versionPath = normalizeUrl([
|
const routePath = normalizeUrl([
|
||||||
context.baseUrl,
|
context.baseUrl,
|
||||||
options.routeBasePath,
|
options.routeBasePath,
|
||||||
versionPathPart,
|
versionPathPart,
|
||||||
|
@ -388,28 +388,27 @@ function createVersionMetadata({
|
||||||
options,
|
options,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Because /docs/:route` should always be after `/docs/versionName/:route`.
|
|
||||||
const routePriority = versionPathPart === '' ? -1 : undefined;
|
const routePriority = versionPathPart === '' ? -1 : undefined;
|
||||||
|
|
||||||
// the path that will be used to refer the docs tags
|
// the path that will be used to refer the docs tags
|
||||||
// example below will be using /docs/tags
|
// example below will be using /docs/tags
|
||||||
const tagsPath = normalizeUrl([versionPath, options.tagsBasePath]);
|
const tagsPath = normalizeUrl([routePath, options.tagsBasePath]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
versionName,
|
versionName,
|
||||||
versionLabel,
|
label,
|
||||||
versionPath,
|
path: routePath,
|
||||||
tagsPath,
|
tagsPath,
|
||||||
versionEditUrl: versionEditUrls?.versionEditUrl,
|
editUrl: versionEditUrls.editUrl,
|
||||||
versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized,
|
editUrlLocalized: versionEditUrls.editUrlLocalized,
|
||||||
versionBanner: getVersionBanner({
|
banner: getVersionBanner({
|
||||||
versionName,
|
versionName,
|
||||||
versionNames,
|
versionNames,
|
||||||
lastVersionName,
|
lastVersionName,
|
||||||
options,
|
options,
|
||||||
}),
|
}),
|
||||||
versionBadge: getVersionBadge({versionName, versionNames, options}),
|
badge: getVersionBadge({versionName, versionNames, options}),
|
||||||
versionClassName: getVersionClassName({versionName, options}),
|
className: getVersionClassName({versionName, options}),
|
||||||
isLast,
|
isLast,
|
||||||
routePriority,
|
routePriority,
|
||||||
sidebarFilePath,
|
sidebarFilePath,
|
||||||
|
@ -592,15 +591,3 @@ export async function readVersionsMetadata({
|
||||||
);
|
);
|
||||||
return versionsMetadata;
|
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];
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare module '@docusaurus/plugin-content-pages' {
|
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;
|
id?: string;
|
||||||
path: string;
|
path: string;
|
||||||
routeBasePath: string;
|
routeBasePath: string;
|
||||||
|
|
|
@ -5,6 +5,13 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* 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' {
|
declare module '@docusaurus/theme-classic' {
|
||||||
export type Options = {
|
export type Options = {
|
||||||
customCss?: string | string[];
|
customCss?: string | string[];
|
||||||
|
|
|
@ -47,7 +47,7 @@ function DocItemContent(props: Props): JSX.Element {
|
||||||
const {title} = metadata;
|
const {title} = metadata;
|
||||||
|
|
||||||
// We only add a title if:
|
// 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
|
// - the markdown content does not already contain a top-level h1 heading
|
||||||
const shouldAddTitle =
|
const shouldAddTitle =
|
||||||
!hideTitle && typeof DocContent.contentTitle === 'undefined';
|
!hideTitle && typeof DocContent.contentTitle === 'undefined';
|
||||||
|
|
11
packages/docusaurus-theme-classic/src/types.d.ts
vendored
11
packages/docusaurus-theme-classic/src/types.d.ts
vendored
|
@ -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" />
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <reference types="@docusaurus/theme-classic" />
|
/// <reference types="@docusaurus/theme-classic" />
|
||||||
|
/// <reference types="@docusaurus/module-type-aliases" />
|
||||||
|
|
||||||
declare module '@theme-init/CodeBlock' {
|
declare module '@theme-init/CodeBlock' {
|
||||||
import type CodeBlock, {Props as BaseProps} from '@theme/CodeBlock';
|
import type CodeBlock, {Props as BaseProps} from '@theme/CodeBlock';
|
||||||
|
|
|
@ -31,24 +31,23 @@ Accepted fields:
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `path` | `string` | `'docs'` | Path to data on filesystem relative to site dir. |
|
| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. |
|
||||||
| `breadcrumbs` | `boolean` | `true` | To enable or disable the breadcrumbs on docs pages. |
|
|
||||||
| `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. |
|
| `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. |
|
| `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. |
|
| `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. |
|
| `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`. |
|
| `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. |
|
| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
|
||||||
| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. |
|
| `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` (creates autogenerated sidebar) | Path to sidebar configuration. |
|
| `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) |
|
| `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) |
|
| `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) |
|
| `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. |
|
| `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. |
|
||||||
| `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page |
|
| `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. |
|
| `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. |
|
||||||
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
|
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
|
||||||
| `rehypePlugins` | `any[]` | `[]` | Rehype 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. |
|
| `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. |
|
| `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. |
|
| `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. |
|
| `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. |
|
| `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>
|
</APITable>
|
||||||
|
|
||||||
|
@ -78,15 +78,24 @@ type PrefixParser = (filename: string) => {
|
||||||
numberPrefix?: number;
|
numberPrefix?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CategoryIndexMatcher = (doc: {
|
type CategoryIndexMatcher = (param: {
|
||||||
|
/** The file name, without extension */
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
/**
|
||||||
|
* The list of directories, from lowest level to highest.
|
||||||
|
* If there's no dir name, directories is ['.']
|
||||||
|
*/
|
||||||
directories: string[];
|
directories: string[];
|
||||||
|
/** The extension, with a leading dot */
|
||||||
extension: string;
|
extension: string;
|
||||||
}) => boolean;
|
}) => boolean;
|
||||||
|
|
||||||
type SidebarGenerator = (generatorArgs: {
|
type SidebarGenerator = (generatorArgs: {
|
||||||
item: {type: 'autogenerated'; dirName: string}; // the sidebar item with type "autogenerated"
|
/** The sidebar item with type "autogenerated" to be transformed. */
|
||||||
version: {contentPath: string; versionName: string}; // the current version
|
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<{
|
docs: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -94,23 +103,40 @@ type SidebarGenerator = (generatorArgs: {
|
||||||
source: string;
|
source: string;
|
||||||
sourceDirName: string;
|
sourceDirName: string;
|
||||||
sidebarPosition?: number | undefined;
|
sidebarPosition?: number | undefined;
|
||||||
}>; // all the docs of that version (unfiltered)
|
}>;
|
||||||
numberPrefixParser: PrefixParser; // numberPrefixParser configured for this plugin
|
/** Number prefix parser 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
|
numberPrefixParser: PrefixParser;
|
||||||
isCategoryIndex: CategoryIndexMatcher; // the default category index matcher, that you can override
|
/** The default category index matcher which you can override. */
|
||||||
defaultSidebarItemsGenerator: SidebarGenerator; // useful to re-use/enhance default sidebar generation logic from Docusaurus
|
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[]>;
|
}) => Promise<SidebarItem[]>;
|
||||||
|
|
||||||
type Versions = Record<
|
type VersionsConfig = {
|
||||||
string, // the version's ID
|
[versionName: string]: {
|
||||||
{
|
/**
|
||||||
label: string; // the label of the version
|
* The base path of the version, will be appended to `baseUrl` +
|
||||||
path: string; // the route path of the version
|
* `routeBasePath`.
|
||||||
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
|
path?: string;
|
||||||
className; // add a custom className to the <html> element when browsing docs of that version
|
/** 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}
|
### Example configuration {#ex-config}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue