diff --git a/packages/docusaurus-mdx-loader/src/index.ts b/packages/docusaurus-mdx-loader/src/index.ts index ae3336d169a1..34cea4978d23 100644 --- a/packages/docusaurus-mdx-loader/src/index.ts +++ b/packages/docusaurus-mdx-loader/src/index.ts @@ -21,21 +21,21 @@ import toc from './remark/toc'; import unwrapMdxCodeBlocks from './remark/unwrapMdxCodeBlocks'; import transformImage from './remark/transformImage'; import transformLinks from './remark/transformLinks'; -import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader'; +import type {MDXOptions} from '@docusaurus/mdx-loader'; import type {LoaderContext} from 'webpack'; const { loaders: {inlineMarkdownImageFileLoader}, } = getFileLoaderUtils(); -const DEFAULT_OPTIONS: RemarkAndRehypePluginOptions = { +const DEFAULT_OPTIONS: MDXOptions = { rehypePlugins: [], remarkPlugins: [unwrapMdxCodeBlocks, emoji, headings, toc], beforeDefaultRemarkPlugins: [], beforeDefaultRehypePlugins: [], }; -type Options = RemarkAndRehypePluginOptions & { +type Options = MDXOptions & { staticDirs: string[]; siteDir: string; isMDXPartial?: (filePath: string) => boolean; diff --git a/packages/docusaurus-mdx-loader/src/mdx-loader.d.ts b/packages/docusaurus-mdx-loader/src/mdx-loader.d.ts index e1fff7113ef8..c84168aefdbd 100644 --- a/packages/docusaurus-mdx-loader/src/mdx-loader.d.ts +++ b/packages/docusaurus-mdx-loader/src/mdx-loader.d.ts @@ -7,12 +7,12 @@ import type {Plugin} from 'unified'; -export type RemarkOrRehypePlugin = +export type MDXPlugin = // eslint-disable-next-line @typescript-eslint/no-explicit-any [Plugin, any] | Plugin; -export type RemarkAndRehypePluginOptions = { - remarkPlugins: RemarkOrRehypePlugin[]; - rehypePlugins: RemarkOrRehypePlugin[]; - beforeDefaultRemarkPlugins: RemarkOrRehypePlugin[]; - beforeDefaultRehypePlugins: RemarkOrRehypePlugin[]; +export type MDXOptions = { + remarkPlugins: MDXPlugin[]; + rehypePlugins: MDXPlugin[]; + beforeDefaultRemarkPlugins: MDXPlugin[]; + beforeDefaultRehypePlugins: MDXPlugin[]; }; diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts index 10e4fd654752..e7fd5a65ab88 100644 --- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts +++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts @@ -6,8 +6,8 @@ */ declare module '@docusaurus/plugin-content-blog' { - import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader'; - import type {FrontMatterTag} from '@docusaurus/utils'; + import type {MDXOptions} from '@docusaurus/mdx-loader'; + import type {FrontMatterTag, Tag} from '@docusaurus/utils'; import type {Overwrite} from 'utility-types'; export interface Assets { @@ -81,10 +81,7 @@ declare module '@docusaurus/plugin-content-blog' { * @see {@link BlogPostMetadata.tags} */ tags?: FrontMatterTag[]; - /** - * Custom slug appended after /// - * @see {@link BlogPostMetadata.slug} - */ + /** Custom slug appended after `///` */ slug?: string; /** * Marks the post as draft and excludes it from the production build. @@ -130,25 +127,18 @@ declare module '@docusaurus/plugin-content-blog' { /** @deprecated v1 legacy */ authorImageURL?: string; - /** - * @see {@link BlogPostMetadata.image} - */ + /** Used in the head meta. Should use `assets.image` in priority. */ image?: string; - /** - * Used in the head meta - */ + /** Used in the head meta. */ keywords?: string[]; - /** - * Hide the right TOC - */ + /** Hide the right TOC. */ hide_table_of_contents?: boolean; /** - * Minimum TOC heading level + * Minimum TOC heading level. Must be between 2 and 6 and lower or equal to + * the max value. */ toc_min_heading_level?: number; - /** - * Maximum TOC heading level - */ + /** Maximum TOC heading level. Must be between 2 and 6. */ toc_max_heading_level?: number; }; @@ -175,9 +165,7 @@ declare module '@docusaurus/plugin-content-blog' { | (string | BlogPostFrontMatterAuthor)[]; export type BlogPostMetadata = { - /** - * Path to the Markdown source, with `@site` alias. - */ + /** Path to the Markdown source, with `@site` alias. */ readonly source: string; /** * Used to generate the page h1 heading, tab title, and pagination title. @@ -193,9 +181,7 @@ declare module '@docusaurus/plugin-content-blog' { * render the date regardless of the existence of `Intl.DateTimeFormat`. */ readonly formattedDate: string; - /** - * Full link including base URL. - */ + /** Full link including base URL. */ readonly permalink: string; /** * Description used in the meta. Could be an empty string (empty content) @@ -229,17 +215,10 @@ declare module '@docusaurus/plugin-content-blog' { * `assets.authorsImageUrls` on client side. */ readonly authors: Author[]; - /** - * Front matter, as-is. - */ + /** Front matter, as-is. */ readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown}; - /** - * Tags, normalized. - */ - readonly tags: readonly { - readonly label: string; - readonly permalink: string; - }[]; + /** Tags, normalized. */ + readonly tags: Tag[]; }; /** * @returns The edit URL that's directly plugged into metadata. @@ -250,17 +229,11 @@ declare module '@docusaurus/plugin-content-blog' { * site path. Usually the same as `options.path` but can be localized */ blogDirPath: string; - /** - * Path to this post file, relative to `blogDirPath` - */ + /** Path to this post file, relative to `blogDirPath`. */ blogPath: string; - /** - * @see {@link BlogPostMetadata.permalink} - */ + /** @see {@link BlogPostMetadata.permalink} */ permalink: string; - /** - * Locale name. - */ + /** Locale name. */ locale: string; }) => string | undefined; @@ -325,7 +298,7 @@ declare module '@docusaurus/plugin-content-blog' { /** * Plugin options after normalization. */ - export type PluginOptions = RemarkAndRehypePluginOptions & { + export type PluginOptions = MDXOptions & { /** Plugin ID. */ id?: string; /** diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap index 30c85bc511e0..a67e0081748c 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap @@ -169,7 +169,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], "isLast": true, + "label": "current label (translated)", "mainDocId": "", + "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", "sidebars": { @@ -221,9 +223,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], }, - "versionLabel": "current label (translated)", "versionName": "current", - "versionPath": "/docs/", }, { "contentPath": "any", @@ -311,7 +311,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], "isLast": true, + "label": "2.0.0 label (translated)", "mainDocId": "", + "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", "sidebars": { @@ -363,9 +365,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], }, - "versionLabel": "2.0.0 label (translated)", "versionName": "2.0.0", - "versionPath": "/docs/", }, { "contentPath": "any", @@ -453,7 +453,9 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], "isLast": true, + "label": "1.0.0 label (translated)", "mainDocId": "", + "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", "sidebars": { @@ -505,9 +507,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` }, ], }, - "versionLabel": "1.0.0 label (translated)", "versionName": "1.0.0", - "versionPath": "/docs/", }, ], } diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 730e3d787e54..b7aa5cfe178b 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -18,16 +18,14 @@ import { import {loadSidebars} from '../sidebars'; import type {Sidebars} from '../sidebars/types'; import {readVersionsMetadata} from '../versions'; -import type { - DocFile, - DocMetadataBase, - VersionMetadata, - DocNavLink, -} from '../types'; +import type {DocFile} from '../types'; import type { MetadataOptions, PluginOptions, EditUrlFunction, + DocMetadataBase, + VersionMetadata, + PropNavigationLink, } from '@docusaurus/plugin-content-docs'; import type {LoadContext} from '@docusaurus/types'; import {DEFAULT_OPTIONS} from '../options'; @@ -123,7 +121,11 @@ function createTestUtils({ } async function generateNavigation(docFiles: DocFile[]): Promise<{ - pagination: {prev?: DocNavLink; next?: DocNavLink; id: string}[]; + pagination: { + prev?: PropNavigationLink; + next?: PropNavigationLink; + id: string; + }[]; sidebars: Sidebars; }> { const rawDocs = docFiles.map((docFile) => diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts index 734e7e0bbf49..7e295afb0cb0 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts @@ -6,7 +6,7 @@ */ import {validateDocFrontMatter} from '../frontMatter'; -import type {DocFrontMatter} from '../types'; +import type {DocFrontMatter} from '@docusaurus/plugin-content-docs'; import escapeStringRegexp from 'escape-string-regexp'; function testField(params: { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts index 4c1cac6ecdcc..2c9a02966317 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts @@ -12,9 +12,9 @@ describe('toGlobalDataVersion', () => { expect( toGlobalDataVersion({ versionName: 'current', - versionLabel: 'Label', + label: 'Label', isLast: true, - versionPath: '/current', + path: '/current', mainDocId: 'main', docs: [ { @@ -86,9 +86,9 @@ describe('toGlobalDataVersion', () => { sidebar: 'tutorial', }, ], - versionBanner: 'unreleased', - versionBadge: true, - versionClassName: 'current-cls', + banner: 'unreleased', + badge: true, + className: 'current-cls', tagsPath: '/current/tags', contentPath: '', contentPathLocalized: '', diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts index 508913d6dd13..86bd7b88fc27 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts @@ -16,7 +16,7 @@ describe('toTagDocListProp', () => { it('works', () => { const tag: Tag = { - name: 'tag1', + label: 'tag1', permalink: '/tag1', docIds: ['id1', 'id3'], }; @@ -54,7 +54,7 @@ describe('toTagDocListProp', () => { expect(result).toEqual({ allTagsPath, - name: tag.name, + name: tag.label, permalink: tag.permalink, docs: [doc3, doc1], // docs sorted by title, ignore "id5" absence }); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts index b4ca8cf72b75..85af2ef203e0 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts @@ -5,12 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -import type {LoadedContent, DocMetadata, LoadedVersion} from '../types'; +import type {LoadedContent, LoadedVersion} from '../types'; import {CURRENT_VERSION_NAME} from '../constants'; import { getLoadedContentTranslationFiles, translateLoadedContent, } from '../translations'; +import type {DocMetadata} from '@docusaurus/plugin-content-docs'; import {updateTranslationFileMessages} from '@docusaurus/utils'; function createSampleDoc(doc: Pick): DocMetadata { @@ -36,8 +37,8 @@ function createSampleVersion( version: Pick, ): LoadedVersion { return { - versionLabel: `${version.versionName} label`, - versionPath: '/docs/', + label: `${version.versionName} label`, + path: '/docs/', mainDocId: '', routePriority: undefined, sidebarFilePath: 'any', @@ -45,21 +46,11 @@ function createSampleVersion( contentPath: 'any', contentPathLocalized: 'any', docs: [ - createSampleDoc({ - id: 'doc1', - }), - createSampleDoc({ - id: 'doc2', - }), - createSampleDoc({ - id: 'doc3', - }), - createSampleDoc({ - id: 'doc4', - }), - createSampleDoc({ - id: 'doc5', - }), + createSampleDoc({id: 'doc1'}), + createSampleDoc({id: 'doc2'}), + createSampleDoc({id: 'doc3'}), + createSampleDoc({id: 'doc4'}), + createSampleDoc({id: 'doc5'}), ], sidebars: { docs: [ diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts index 9e5f2e483160..5209f7dfea05 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts @@ -15,9 +15,11 @@ import { } from '../versions'; import {DEFAULT_OPTIONS} from '../options'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; -import type {VersionMetadata} from '../types'; import type {I18n} from '@docusaurus/types'; -import type {PluginOptions} from '@docusaurus/plugin-content-docs'; +import type { + PluginOptions, + VersionMetadata, +} from '@docusaurus/plugin-content-docs'; const DefaultI18N: I18n = { currentLocale: 'en', @@ -85,12 +87,12 @@ describe('readVersionsMetadata', () => { routePriority: -1, sidebarFilePath: undefined, tagsPath: '/docs/tags', - versionLabel: 'Next', + label: 'Next', versionName: 'current', - versionPath: '/docs', - versionBanner: null, - versionBadge: false, - versionClassName: 'docs-version-current', + path: '/docs', + banner: null, + badge: false, + className: 'docs-version-current', }; return {simpleSiteDir, defaultOptions, defaultContext, vCurrent}; } @@ -120,7 +122,7 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([ { ...vCurrent, - versionPath: '/myBaseUrl/docs', + path: '/myBaseUrl/docs', tagsPath: '/myBaseUrl/docs/tags', }, ]); @@ -148,13 +150,13 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([ { ...vCurrent, - versionPath: '/myBaseUrl/docs/current-path', - versionLabel: 'current-label', + path: '/myBaseUrl/docs/current-path', + label: 'current-label', routePriority: undefined, sidebarFilePath: undefined, tagsPath: '/myBaseUrl/docs/current-path/tags', - versionEditUrl: undefined, - versionEditUrlLocalized: undefined, + editUrl: undefined, + editUrlLocalized: undefined, }, ]); }); @@ -245,12 +247,12 @@ describe('readVersionsMetadata', () => { routePriority: undefined, sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'), tagsPath: '/docs/next/tags', - versionLabel: 'Next', + label: 'Next', versionName: 'current', - versionPath: '/docs/next', - versionBanner: 'unreleased', - versionBadge: true, - versionClassName: 'docs-version-current', + path: '/docs/next', + banner: 'unreleased', + badge: true, + className: 'docs-version-current', }; const v101: VersionMetadata = { @@ -269,12 +271,12 @@ describe('readVersionsMetadata', () => { 'versioned_sidebars/version-1.0.1-sidebars.json', ), tagsPath: '/docs/tags', - versionLabel: '1.0.1', + label: '1.0.1', versionName: '1.0.1', - versionPath: '/docs', - versionBanner: null, - versionBadge: true, - versionClassName: 'docs-version-1.0.1', + path: '/docs', + banner: null, + badge: true, + className: 'docs-version-1.0.1', }; const v100: VersionMetadata = { @@ -293,12 +295,12 @@ describe('readVersionsMetadata', () => { 'versioned_sidebars/version-1.0.0-sidebars.json', ), tagsPath: '/docs/1.0.0/tags', - versionLabel: '1.0.0', + label: '1.0.0', versionName: '1.0.0', - versionPath: '/docs/1.0.0', - versionBanner: 'unmaintained', - versionBadge: true, - versionClassName: 'docs-version-1.0.0', + path: '/docs/1.0.0', + banner: 'unmaintained', + badge: true, + className: 'docs-version-1.0.0', }; const vWithSlugs: VersionMetadata = { @@ -317,12 +319,12 @@ describe('readVersionsMetadata', () => { 'versioned_sidebars/version-withSlugs-sidebars.json', ), tagsPath: '/docs/withSlugs/tags', - versionLabel: 'withSlugs', + label: 'withSlugs', versionName: 'withSlugs', - versionPath: '/docs/withSlugs', - versionBanner: 'unmaintained', - versionBadge: true, - versionClassName: 'docs-version-withSlugs', + path: '/docs/withSlugs', + banner: 'unmaintained', + badge: true, + className: 'docs-version-withSlugs', }; return { @@ -393,27 +395,27 @@ describe('readVersionsMetadata', () => { { ...vCurrent, tagsPath: '/docs/current-path/tags', - versionPath: '/docs/current-path', - versionBanner: 'unmaintained', - versionBadge: false, - versionClassName: 'custom-current-className', + path: '/docs/current-path', + banner: 'unmaintained', + badge: false, + className: 'custom-current-className', }, { ...v101, isLast: false, routePriority: undefined, tagsPath: '/docs/1.0.1/tags', - versionPath: '/docs/1.0.1', - versionBanner: 'unreleased', + path: '/docs/1.0.1', + banner: 'unreleased', }, { ...v100, isLast: true, routePriority: -1, tagsPath: '/docs/tags', - versionLabel: '1.0.0-label', - versionPath: '/docs', - versionBanner: 'unreleased', + label: '1.0.0-label', + path: '/docs', + banner: 'unreleased', }, vWithSlugs, ]); @@ -434,30 +436,30 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([ { ...vCurrent, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/docs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current', }, { ...v101, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.1', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.1', }, { ...v100, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-1.0.0', }, { ...vWithSlugs, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-withSlugs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/version-withSlugs', }, ]); @@ -479,30 +481,30 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([ { ...vCurrent, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/docs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current', }, { ...v101, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/docs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current', }, { ...v100, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/docs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current', }, { ...vWithSlugs, - versionEditUrl: + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/docs', - versionEditUrlLocalized: + editUrlLocalized: 'https://github.com/facebook/docusaurus/edit/main/website/i18n/en/docusaurus-plugin-content-docs/current', }, ]); @@ -538,9 +540,9 @@ describe('readVersionsMetadata', () => { isLast: true, routePriority: -1, tagsPath: '/docs/tags', - versionPath: '/docs', - versionBanner: null, - versionBadge: false, + path: '/docs', + banner: null, + badge: false, }, ]); }); @@ -679,12 +681,12 @@ describe('readVersionsMetadata', () => { routePriority: undefined, sidebarFilePath: path.join(versionedSiteDir, 'sidebars.json'), tagsPath: '/communityBasePath/next/tags', - versionLabel: 'Next', + label: 'Next', versionName: 'current', - versionPath: '/communityBasePath/next', - versionBanner: 'unreleased', - versionBadge: true, - versionClassName: 'docs-version-current', + path: '/communityBasePath/next', + banner: 'unreleased', + badge: true, + className: 'docs-version-current', }; const v100: VersionMetadata = { @@ -703,12 +705,12 @@ describe('readVersionsMetadata', () => { 'community_versioned_sidebars/version-1.0.0-sidebars.json', ), tagsPath: '/communityBasePath/tags', - versionLabel: '1.0.0', + label: '1.0.0', versionName: '1.0.0', - versionPath: '/communityBasePath', - versionBanner: null, - versionBadge: true, - versionClassName: 'docs-version-1.0.0', + path: '/communityBasePath', + banner: null, + badge: true, + className: 'docs-version-1.0.0', }; return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100}; @@ -735,7 +737,7 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([ // vCurrent removed - {...v100, versionBadge: false}, + {...v100, badge: false}, ]); }); @@ -753,9 +755,9 @@ describe('readVersionsMetadata', () => { isLast: true, routePriority: -1, tagsPath: '/communityBasePath/tags', - versionPath: '/communityBasePath', - versionBanner: null, - versionBadge: false, + path: '/communityBasePath', + banner: null, + badge: false, }, ]); }); diff --git a/packages/docusaurus-plugin-content-docs/src/categoryGeneratedIndex.ts b/packages/docusaurus-plugin-content-docs/src/categoryGeneratedIndex.ts index b3785f6fe9ec..4c87e711a515 100644 --- a/packages/docusaurus-plugin-content-docs/src/categoryGeneratedIndex.ts +++ b/packages/docusaurus-plugin-content-docs/src/categoryGeneratedIndex.ts @@ -5,7 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -import type {CategoryGeneratedIndexMetadata, DocMetadataBase} from './types'; +import type { + CategoryGeneratedIndexMetadata, + DocMetadataBase, +} from '@docusaurus/plugin-content-docs'; import type {SidebarItemCategoryWithGeneratedIndex} from './sidebars/types'; import {type SidebarsUtils, toNavigationLink} from './sidebars/utils'; import {createDocsByIdIndex} from './docs'; @@ -29,8 +32,10 @@ function getCategoryGeneratedIndexMetadata({ slug: category.link.slug, permalink: category.link.permalink, sidebar: sidebarName!, - previous: toNavigationLink(previous, docsById), - next: toNavigationLink(next, docsById), + navigation: { + previous: toNavigationLink(previous, docsById), + next: toNavigationLink(next, docsById), + }, }; } diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 631daef5f73e..ee247ec0a97a 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -12,6 +12,7 @@ import { aliasedSitePath, getEditUrl, getFolderContainingFile, + getContentPathList, normalizeUrl, parseMarkdownString, posixPath, @@ -21,18 +22,9 @@ import { import type {LoadContext} from '@docusaurus/types'; import {getFileLastUpdate} from './lastUpdate'; -import type { - DocFile, - DocMetadataBase, - DocMetadata, - DocNavLink, - LastUpdateData, - VersionMetadata, - LoadedVersion, -} from './types'; +import type {DocFile, LoadedVersion} from './types'; import getSlug from './slug'; import {CURRENT_VERSION_NAME} from './constants'; -import {getDocsDirPaths} from './versions'; import {stripPathNumberPrefixes} from './numberPrefix'; import {validateDocFrontMatter} from './frontMatter'; import type {SidebarsUtils} from './sidebars/utils'; @@ -41,7 +33,11 @@ import type { MetadataOptions, PluginOptions, CategoryIndexMatcher, - CategoryIndexMatcherParam, + DocMetadataBase, + DocMetadata, + PropNavigationLink, + LastUpdateData, + VersionMetadata, } from '@docusaurus/plugin-content-docs'; type LastUpdateOptions = Pick< @@ -85,7 +81,7 @@ export async function readDocFile( options: LastUpdateOptions, ): Promise { const contentPath = await getFolderContainingFile( - getDocsDirPaths(versionMetadata), + getContentPathList(versionMetadata), source, ); @@ -213,7 +209,7 @@ function doProcessDocMetadata({ const description: string = frontMatter.description ?? excerpt ?? ''; - const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]); + const permalink = normalizeUrl([versionMetadata.path, docSlug]); function getDocEditUrl() { const relativeFilePath = path.relative(contentPath, filePath); @@ -232,8 +228,8 @@ function doProcessDocMetadata({ const isLocalized = contentPath === versionMetadata.contentPathLocalized; const baseVersionEditUrl = isLocalized && options.editLocalizedFiles - ? versionMetadata.versionEditUrlLocalized - : versionMetadata.versionEditUrl; + ? versionMetadata.editUrlLocalized + : versionMetadata.editUrl; return getEditUrl(relativeFilePath, baseVersionEditUrl); } return undefined; @@ -304,7 +300,7 @@ export function addDocNavigation( const toNavigationLinkByDocId = ( docId: string | null | undefined, type: 'prev' | 'next', - ): DocNavLink | undefined => { + ): PropNavigationLink | undefined => { if (!docId) { return undefined; } @@ -401,7 +397,7 @@ export function toCategoryIndexMatcherParam({ }: Pick< DocMetadataBase, 'source' | 'sourceDirName' ->): CategoryIndexMatcherParam { +>): Parameters[0] { // source + sourceDirName are always posix-style return { fileName: path.posix.parse(source).name, diff --git a/packages/docusaurus-plugin-content-docs/src/frontMatter.ts b/packages/docusaurus-plugin-content-docs/src/frontMatter.ts index fe53b0573dec..52e5af68b383 100644 --- a/packages/docusaurus-plugin-content-docs/src/frontMatter.ts +++ b/packages/docusaurus-plugin-content-docs/src/frontMatter.ts @@ -12,7 +12,7 @@ import { FrontMatterTOCHeadingLevels, validateFrontMatter, } from '@docusaurus/utils-validation'; -import type {DocFrontMatter} from './types'; +import type {DocFrontMatter} from '@docusaurus/plugin-content-docs'; // NOTE: we don't add any default value on purpose here // We don't want default values to magically appear in doc metadata and props diff --git a/packages/docusaurus-plugin-content-docs/src/globalData.ts b/packages/docusaurus-plugin-content-docs/src/globalData.ts index 302fb77328de..ebeb61c8228e 100644 --- a/packages/docusaurus-plugin-content-docs/src/globalData.ts +++ b/packages/docusaurus-plugin-content-docs/src/globalData.ts @@ -8,11 +8,11 @@ import _ from 'lodash'; import type {Sidebars} from './sidebars/types'; import {createSidebarsUtils} from './sidebars/utils'; +import type {LoadedVersion} from './types'; import type { CategoryGeneratedIndexMetadata, DocMetadata, - LoadedVersion, -} from './types'; +} from '@docusaurus/plugin-content-docs'; import type { GlobalVersion, GlobalSidebar, @@ -65,9 +65,9 @@ function toGlobalSidebars( export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion { return { name: version.versionName, - label: version.versionLabel, + label: version.label, isLast: version.isLast, - path: version.versionPath, + path: version.path, mainDocId: version.mainDocId, docs: version.docs .map(toGlobalDataDoc) diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 4b659f48fa57..ed35fa390c55 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -11,6 +11,7 @@ import { normalizeUrl, docuHash, aliasedSitePath, + getContentPathList, reportMessage, posixPath, addTrailingPathSeparator, @@ -27,18 +28,14 @@ import { addDocNavigation, getMainDocId, } from './docs'; -import {getDocsDirPaths, readVersionsMetadata} from './versions'; - +import {readVersionsMetadata} from './versions'; import type { LoadedContent, SourceToPermalink, - DocMetadataBase, - VersionMetadata, LoadedVersion, DocFile, DocsMarkdownOption, VersionTag, - DocFrontMatter, } from './types'; import type {RuleSetRule} from 'webpack'; import {cliDocsVersionCommand} from './cli'; @@ -55,6 +52,9 @@ import {createVersionRoutes} from './routes'; import type { PropTagsListPage, PluginOptions, + DocMetadataBase, + VersionMetadata, + DocFrontMatter, } from '@docusaurus/plugin-content-docs'; import {createSidebarsUtils} from './sidebars/utils'; import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex'; @@ -114,7 +114,7 @@ export default async function pluginContentDocs( function getVersionPathsToWatch(version: VersionMetadata): string[] { const result = [ ...options.include.flatMap((pattern) => - getDocsDirPaths(version).map( + getContentPathList(version).map( (docsDirPath) => `${docsDirPath}/${pattern}`, ), ), @@ -228,7 +228,7 @@ export default async function pluginContentDocs( const tagsProp: PropTagsListPage['tags'] = Object.values( versionTags, ).map((tagValue) => ({ - name: tagValue.name, + name: tagValue.label, permalink: tagValue.permalink, count: tagValue.docIds.length, })); @@ -331,7 +331,7 @@ export default async function pluginContentDocs( }; function createMDXLoaderRule(): RuleSetRule { - const contentDirs = versionsMetadata.flatMap(getDocsDirPaths); + const contentDirs = versionsMetadata.flatMap(getContentPathList); return { test: /\.mdx?$/i, include: contentDirs diff --git a/packages/docusaurus-plugin-content-docs/src/markdown/__tests__/linkify.test.ts b/packages/docusaurus-plugin-content-docs/src/markdown/__tests__/linkify.test.ts index c6e5bb9ac52b..f106ea6edb9d 100644 --- a/packages/docusaurus-plugin-content-docs/src/markdown/__tests__/linkify.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/markdown/__tests__/linkify.test.ts @@ -12,9 +12,9 @@ import {linkify} from '../linkify'; import type { DocsMarkdownOption, SourceToPermalink, - VersionMetadata, DocBrokenMarkdownLink, } from '../../types'; +import type {VersionMetadata} from '@docusaurus/plugin-content-docs'; import {VERSIONED_DOCS_DIR, CURRENT_VERSION_NAME} from '../../constants'; function createFakeVersion({ diff --git a/packages/docusaurus-plugin-content-docs/src/markdown/linkify.ts b/packages/docusaurus-plugin-content-docs/src/markdown/linkify.ts index 39e45e8f399e..704bcbd4974f 100644 --- a/packages/docusaurus-plugin-content-docs/src/markdown/linkify.ts +++ b/packages/docusaurus-plugin-content-docs/src/markdown/linkify.ts @@ -6,12 +6,11 @@ */ import type {DocsMarkdownOption} from '../types'; -import {getDocsDirPaths} from '../versions'; -import {replaceMarkdownLinks} from '@docusaurus/utils'; +import {replaceMarkdownLinks, getContentPathList} from '@docusaurus/utils'; function getVersion(filePath: string, options: DocsMarkdownOption) { const versionFound = options.versionsMetadata.find((version) => - getDocsDirPaths(version).some((docsDirPath) => + getContentPathList(version).some((docsDirPath) => filePath.startsWith(docsDirPath), ), ); diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index 7c807019c7ea..40aad894e8b6 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -6,18 +6,25 @@ */ declare module '@docusaurus/plugin-content-docs' { - import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader'; + import type {MDXOptions} from '@docusaurus/mdx-loader'; + import type {ContentPaths, Tag, FrontMatterTag} from '@docusaurus/utils'; + import type {Required} from 'utility-types'; export interface Assets { image?: string; } + /** + * Custom callback for parsing number prefixes from file/folder names. + */ export type NumberPrefixParser = (filename: string) => { + /** file name without number prefix, without any other modification. */ filename: string; + /** The number prefix. Can be float, integer, negative, or anything. */ numberPrefix?: number; }; - export type CategoryIndexMatcherParam = { + export type CategoryIndexMatcher = (param: { /** The file name, without extension */ fileName: string; /** @@ -27,110 +34,442 @@ declare module '@docusaurus/plugin-content-docs' { directories: string[]; /** The extension, with a leading dot */ extension: string; - }; - export type CategoryIndexMatcher = ( - param: CategoryIndexMatcherParam, - ) => boolean; + }) => boolean; export type EditUrlFunction = (editUrlParams: { + /** Name of the version. */ version: string; + /** + * Path of the version's root content path, relative to the site directory. + * Usually the same as `options.path` but can be localized or versioned. + */ versionDocsDirPath: string; + /** Path of the doc file, relative to `versionDocsDirPath`. */ docPath: string; + /** @see {@link DocMetadata.permalink} */ permalink: string; + /** Locale name. */ locale: string; }) => string | undefined; export type MetadataOptions = { + /** + * URL route for the docs section of your site. **DO NOT** include a + * trailing slash. Use `/` for shipping docs without base path. + */ routeBasePath: string; + /** + * Base URL to edit your site. The final URL is computed by `editUrl + + * relativeDocPath`. Using a function allows more nuanced control for each + * file. Omitting this variable entirely will disable edit links. + */ editUrl?: string | EditUrlFunction; + /** + * The edit URL will always target the current version doc instead of older + * versions. Ignored when `editUrl` is a function. + */ editCurrentVersion: boolean; + /** + * The edit URL will target the localized file, instead of the original + * unlocalized file. Ignored when `editUrl` is a function. + */ editLocalizedFiles: boolean; + /** Whether to display the last date the doc was updated. */ showLastUpdateTime?: boolean; + /** Whether to display the author who last updated the doc. */ showLastUpdateAuthor?: boolean; + /** + * Custom parsing logic to extract number prefixes from file names. Use + * `false` to disable this behavior and leave the docs untouched, and `true` + * to use the default parser. + * + * @param filename One segment of the path, without any slashes. + * @see https://docusaurus.io/docs/sidebar#using-number-prefixes + */ numberPrefixParser: NumberPrefixParser; + /** Enable or disable the breadcrumbs on doc pages. */ breadcrumbs: boolean; }; export type PathOptions = { + /** + * Path to the docs content directory on the file system, relative to site + * directory. + */ path: string; + /** + * Path to sidebar configuration. Use `false` to disable sidebars, or + * `undefined` to create a fully autogenerated sidebar. + */ sidebarPath?: string | false | undefined; }; // TODO support custom version banner? // {type: "error", content: "html content"} export type VersionBanner = 'unreleased' | 'unmaintained'; - export type VersionOptions = { - path?: string; - label?: string; - banner?: 'none' | VersionBanner; - badge?: boolean; - className?: string; - }; export type VersionsOptions = { + /** + * The version navigated to in priority and displayed by default for docs + * navbar items. + * + * @see https://docusaurus.io/docs/versioning#terminology + */ lastVersion?: string; - versions: {[versionName: string]: VersionOptions}; + /** Only include a subset of all available versions. */ onlyIncludeVersions?: string[]; + /** + * Explicitly disable versioning even when multiple versions exist. This + * will make the site only include the current version. Will error if + * `includeCurrentVersion: false` and `disableVersioning: true`. + */ + disableVersioning: boolean; + /** Include the current version of your docs. */ + includeCurrentVersion: boolean; + /** Independent customization of each version's properties. */ + versions: { + [versionName: string]: { + /** + * The base path of the version, will be appended to `baseUrl` + + * `routeBasePath`. + */ + path?: string; + /** The label of the version to be used in badges, dropdowns, etc. */ + label?: string; + /** The banner to show at the top of a doc of that version. */ + banner?: 'none' | VersionBanner; + /** Show a badge with the version label at the top of each doc. */ + badge?: boolean; + /** Add a custom class name to the element of each doc. */ + className?: string; + }; + }; }; export type SidebarOptions = { + /** + * Whether sidebar categories are collapsible by default. + * + * @see https://docusaurus.io/docs/sidebar#collapsible-categories + */ sidebarCollapsible: boolean; + /** + * Whether sidebar categories are collapsed by default. + * + * @see https://docusaurus.io/docs/sidebar#expanded-categories-by-default + */ sidebarCollapsed: boolean; }; export type PluginOptions = MetadataOptions & PathOptions & VersionsOptions & - RemarkAndRehypePluginOptions & + MDXOptions & SidebarOptions & { + /** Plugin ID. */ id: string; + /** + * Array of glob patterns matching Markdown files to be built, relative to + * the content path. + */ include: string[]; + /** + * Array of glob patterns matching Markdown files to be excluded. Serves + * as refinement based on the `include` option. + */ exclude: string[]; + /** + * Root layout component of each doc page. Provides the version data + * context, and is not unmounted when switching docs. + */ docLayoutComponent: string; + /** Main doc container, with TOC, pagination, etc. */ docItemComponent: string; + /** Root component of the "docs containing tag X" page. */ docTagDocListComponent: string; + /** Root component of the tags list page */ docTagsListComponent: string; + /** Root component of the generated category index page. */ docCategoryGeneratedIndexComponent: string; admonitions: {[key: string]: unknown}; - disableVersioning: boolean; - includeCurrentVersion: boolean; sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption; + /** + * URL route for the tags section of your doc version. Will be appended to + * `routeBasePath`. **DO NOT** include a trailing slash. + */ tagsBasePath: string; }; export type Options = Partial; 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 `///1.0.0`. + * Can be configured through `versions.path`. + */ + path: string; + /** Tags base path in the form of `/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 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//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 /// + * @see {@link DocMetadata.slug} + */ + slug?: string; + /** Customizes the sidebar label for this doc. Will default to its title. */ + sidebar_label?: string; + /** + * Controls the position of a doc inside the generated sidebar slice when + * using autogenerated sidebar items. + * + * @see https://docusaurus.io/docs/sidebar#autogenerated-sidebar-metadata + */ + sidebar_position?: number; + /** + * Gives the corresponding sidebar label a special class name when using + * autogenerated sidebars. + */ + sidebar_class_name?: string; + /** + * Will be propagated to the final sidebars data structure. Useful if you + * have swizzled sidebar-related code or simply querying doc data through + * sidebars. + */ + sidebar_custom_props?: {[key: string]: unknown}; + /** + * Changes the sidebar association of the current doc. Use `null` to make + * the current doc not associated to any sidebar. + */ + displayed_sidebar?: string | null; + /** + * Customizes the pagination label for this doc. Will default to the sidebar + * label. + */ + pagination_label?: string; + /** Overrides the default URL computed for this doc. */ + custom_edit_url?: string | null; + /** + * Whether number prefix parsing is disabled on this doc. + * @see https://docusaurus.io/docs/sidebar#using-number-prefixes + */ + parse_number_prefixes?: boolean; + /** + * Minimum TOC heading level. Must be between 2 and 6 and lower or equal to + * the max value. + */ + toc_min_heading_level?: number; + /** Maximum TOC heading level. Must be between 2 and 6. */ + toc_max_heading_level?: number; + /** + * The ID of the documentation you want the "Next" pagination to link to. + * Use `null` to disable showing "Next" for this page. + * @see {@link DocMetadata.next} + */ + pagination_next?: string | null; + /** + * The ID of the documentation you want the "Previous" pagination to link + * to. Use `null` to disable showing "Previous" for this page. + * @see {@link DocMetadata.prev} + */ + pagination_prev?: string | null; + }; + + export type LastUpdateData = { + /** A timestamp in **seconds**, directly acquired from `git log`. */ + lastUpdatedAt?: number; + /** `lastUpdatedAt` formatted as a date according to the current locale. */ + formattedLastUpdatedAt?: string; + /** The author's name directly acquired from `git log`. */ + lastUpdatedBy?: string; + }; + + export type DocMetadataBase = LastUpdateData & { + // TODO + /** + * Legacy versioned ID. Will be refactored in the future to be unversioned. + */ + id: string; + // TODO + /** + * Unversioned ID. Should be preferred everywhere over `id` until the latter + * is refactored. + */ + unversionedId: string; + /** The name of the version this doc belongs to. */ + version: string; + /** + * Used to generate the page h1 heading, tab title, and pagination title. + */ + title: string; + /** + * Description used in the meta. Could be an empty string (empty content) + */ + description: string; + /** Path to the Markdown source, with `@site` alias. */ + source: string; + /** + * Posix path relative to the content path. Can be `"."`. + * e.g. "folder/subfolder/subsubfolder" + */ + sourceDirName: string; + /** `permalink` without base URL or version path. */ + slug: string; + /** Full URL to this doc, with base URL and version path. */ + permalink: string; + /** + * Position in an autogenerated sidebar slice, acquired through front matter + * or number prefix. + */ + sidebarPosition?: number; + /** + * Acquired from the options; can be customized with front matter. + * `custom_edit_url` will always lead to it being null, but you should treat + * `undefined` and `null` as equivalent. + */ + editUrl?: string | null; + /** Tags, normalized. */ + tags: Tag[]; + /** Front matter, as-is. */ + frontMatter: DocFrontMatter & {[key: string]: unknown}; + }; + + export type DocMetadata = DocMetadataBase & + PropNavigation & { + /** Name of the sidebar this doc is associated with. */ + sidebar?: string; + }; + + export type CategoryGeneratedIndexMetadata = Required< + Omit< + import('./sidebars/types').SidebarItemCategoryLinkGeneratedIndex, + 'type' + >, + 'title' + > & { + navigation: PropNavigation; + /** + * Name of the sidebar this doc is associated with. Unlike + * `DocMetadata.sidebar`, this will always be defined, because a generated + * index can only be generated from a category. + */ + sidebar: string; + }; + export type PropNavigationLink = { readonly title: string; readonly permalink: string; }; export type PropNavigation = { + /** + * Used in pagination. Content is just a subset of another doc's metadata. + */ readonly previous?: PropNavigationLink; + /** + * Used in pagination. Content is just a subset of another doc's metadata. + */ readonly next?: PropNavigationLink; }; - export type PropVersionDoc = import('./sidebars/types').PropVersionDoc; - export type PropVersionDocs = import('./sidebars/types').PropVersionDocs; + export type PropVersionDoc = Pick< + DocMetadata, + 'id' | 'title' | 'description' | 'sidebar' + >; - export type PropVersionMetadata = { + export type PropVersionDocs = { + [docId: string]: PropVersionDoc; + }; + + export type PropVersionMetadata = Pick< + VersionMetadata, + 'label' | 'banner' | 'badge' | 'className' | 'isLast' + > & { + /** ID of the docs plugin this version belongs to. */ pluginId: string; + /** Name of this version. */ version: string; - label: string; - banner: VersionBanner | null; - badge: boolean; - className: string; - isLast: boolean; + /** Sidebars contained in this version. */ docsSidebars: PropSidebars; + /** Docs contained in this version. */ docs: PropVersionDocs; }; - export type PropCategoryGeneratedIndex = { - title: string; - description?: string; - image?: string; - keywords?: string | readonly string[]; - slug: string; - permalink: string; - navigation: PropNavigation; - }; + export type PropCategoryGeneratedIndex = Omit< + CategoryGeneratedIndexMetadata, + 'sidebar' + >; export type PropSidebarItemLink = import('./sidebars/types').PropSidebarItemLink; @@ -169,9 +508,10 @@ declare module '@docusaurus/plugin-content-docs' { declare module '@theme/DocItem' { import type {TOCItem} from '@docusaurus/types'; import type { - PropNavigationLink, PropVersionMetadata, Assets, + DocMetadata, + DocFrontMatter, } from '@docusaurus/plugin-content-docs'; export type DocumentRoute = { @@ -181,41 +521,12 @@ declare module '@theme/DocItem' { readonly sidebar?: string; }; - export type FrontMatter = { - readonly id: string; - readonly title: string; - readonly image?: string; - readonly keywords?: readonly string[]; - readonly hide_title?: boolean; - readonly hide_table_of_contents?: boolean; - readonly toc_min_heading_level?: number; - readonly toc_max_heading_level?: number; - }; - - export type Metadata = { - readonly unversionedId?: string; - readonly description?: string; - readonly title?: string; - readonly permalink?: string; - readonly editUrl?: string; - readonly lastUpdatedAt?: number; - readonly formattedLastUpdatedAt?: string; - readonly lastUpdatedBy?: string; - readonly version?: string; - readonly previous?: PropNavigationLink; - readonly next?: PropNavigationLink; - readonly tags: readonly { - readonly label: string; - readonly permalink: string; - }[]; - }; - export interface Props { readonly route: DocumentRoute; readonly versionMetadata: PropVersionMetadata; readonly content: { - readonly frontMatter: FrontMatter; - readonly metadata: Metadata; + readonly frontMatter: DocFrontMatter; + readonly metadata: DocMetadata; readonly toc: readonly TOCItem[]; readonly contentTitle: string | undefined; readonly assets: Assets; diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index 0a99bf8f5b7a..d25888db63a8 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -5,13 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -import type {LoadedVersion, VersionTag, DocMetadata} from './types'; +import type {LoadedVersion, VersionTag} from './types'; import type { SidebarItemDoc, SidebarItem, SidebarItemCategory, SidebarItemCategoryLink, - PropVersionDocs, } from './sidebars/types'; import type { PropSidebars, @@ -21,6 +20,8 @@ import type { PropTagDocList, PropTagDocListDoc, PropSidebarItemLink, + PropVersionDocs, + DocMetadata, } from '@docusaurus/plugin-content-docs'; import _ from 'lodash'; import {createDocsByIdIndex} from './docs'; @@ -119,10 +120,10 @@ export function toVersionMetadataProp( return { pluginId, version: loadedVersion.versionName, - label: loadedVersion.versionLabel, - banner: loadedVersion.versionBanner, - badge: loadedVersion.versionBadge, - className: loadedVersion.versionClassName, + label: loadedVersion.label, + banner: loadedVersion.banner, + badge: loadedVersion.badge, + className: loadedVersion.className, isLast: loadedVersion.isLast, docsSidebars: toSidebarsProp(loadedVersion), docs: toVersionDocsProp(loadedVersion), @@ -153,7 +154,7 @@ export function toTagDocListProp({ } return { - name: tag.name, + name: tag.label, permalink: tag.permalink, docs: toDocListProp(), allTagsPath, diff --git a/packages/docusaurus-plugin-content-docs/src/routes.ts b/packages/docusaurus-plugin-content-docs/src/routes.ts index ad7608f449dc..3ef6e60ba146 100644 --- a/packages/docusaurus-plugin-content-docs/src/routes.ts +++ b/packages/docusaurus-plugin-content-docs/src/routes.ts @@ -7,12 +7,11 @@ import type {PluginContentLoadedActions, RouteConfig} from '@docusaurus/types'; import {docuHash, createSlugger} from '@docusaurus/utils'; +import type {LoadedVersion} from './types'; import type { CategoryGeneratedIndexMetadata, DocMetadata, - LoadedVersion, -} from './types'; -import type {PropCategoryGeneratedIndex} from '@docusaurus/plugin-content-docs'; +} from '@docusaurus/plugin-content-docs'; import {toVersionMetadataProp} from './props'; import logger from '@docusaurus/logger'; @@ -32,42 +31,19 @@ export async function createCategoryGeneratedIndexRoutes({ async function createCategoryGeneratedIndexRoute( categoryGeneratedIndex: CategoryGeneratedIndexMetadata, ): Promise { - const { - sidebar, - title, - description, - slug, - permalink, - previous, - next, - image, - keywords, - } = categoryGeneratedIndex; + const {sidebar, ...prop} = categoryGeneratedIndex; const propFileName = slugs.slug( - `${version.versionPath}-${categoryGeneratedIndex.sidebar}-category-${categoryGeneratedIndex.title}`, + `${version.path}-${categoryGeneratedIndex.sidebar}-category-${categoryGeneratedIndex.title}`, ); - const prop: PropCategoryGeneratedIndex = { - title, - description, - slug, - permalink, - image, - keywords, - navigation: { - previous, - next, - }, - }; - const propData = await actions.createData( `${docuHash(`category/${propFileName}`)}.json`, JSON.stringify(prop, null, 2), ); return { - path: permalink, + path: categoryGeneratedIndex.permalink, component: docCategoryGeneratedIndexComponent, exact: true, modules: { @@ -162,7 +138,7 @@ export async function createVersionRoutes({ } actions.addRoute({ - path: version.versionPath, + path: version.path, // allow matching /docs/* as well exact: false, // main docs component (DocPage) diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts index 19cd6495831f..a1a8e56d8fd1 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts @@ -34,7 +34,7 @@ describe('postProcess', () => { }, { sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true}, - version: {versionPath: 'version'}, + version: {path: 'version'}, }, ); @@ -53,7 +53,7 @@ describe('postProcess', () => { }, { sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true}, - version: {versionPath: 'version'}, + version: {path: 'version'}, }, ); }).toThrowErrorMatchingInlineSnapshot( @@ -78,7 +78,7 @@ describe('postProcess', () => { { sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true}, - version: {versionPath: 'version'}, + version: {path: 'version'}, }, ), ).toMatchSnapshot(); @@ -98,7 +98,7 @@ describe('postProcess', () => { { sidebarOptions: {sidebarCollapsed: false, sidebarCollapsible: false}, - version: {versionPath: 'version'}, + version: {path: 'version'}, }, ), ).toMatchSnapshot(); @@ -117,7 +117,7 @@ describe('postProcess', () => { { sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: false}, - version: {versionPath: 'version'}, + version: {path: 'version'}, }, ), ).toMatchSnapshot(); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts index 1dad824917f9..500eefbfe1dd 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts @@ -18,7 +18,7 @@ import type { } from '../types'; import {DefaultSidebarItemsGenerator} from '../generator'; import {createSlugger} from '@docusaurus/utils'; -import type {VersionMetadata} from '../../types'; +import type {VersionMetadata} from '@docusaurus/plugin-content-docs'; import {DefaultNumberPrefixParser} from '../../numberPrefix'; import {isCategoryIndex} from '../../docs'; diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/utils.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/utils.test.ts index 540f379a7f06..7c2d4428c642 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/utils.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/utils.test.ts @@ -16,7 +16,10 @@ import { toNavigationLink, } from '../utils'; import type {Sidebar, Sidebars} from '../types'; -import type {DocMetadataBase, DocNavLink} from '../../types'; +import type { + DocMetadataBase, + PropNavigationLink, +} from '@docusaurus/plugin-content-docs'; describe('createSidebarsUtils', () => { const sidebar1: Sidebar = [ @@ -618,7 +621,7 @@ describe('toDocNavigationLink', () => { ).toEqual({ title: 'Doc Title', permalink: '/docPermalink', - } as DocNavLink); + } as PropNavigationLink); }); it('with pagination_label front matter', () => { @@ -635,7 +638,7 @@ describe('toDocNavigationLink', () => { ).toEqual({ title: 'pagination_label', permalink: '/docPermalink', - } as DocNavLink); + } as PropNavigationLink); }); it('with sidebar_label front matter', () => { @@ -652,7 +655,7 @@ describe('toDocNavigationLink', () => { ).toEqual({ title: 'sidebar_label', permalink: '/docPermalink', - } as DocNavLink); + } as PropNavigationLink); }); it('with pagination_label + sidebar_label front matter', () => { @@ -670,7 +673,7 @@ describe('toDocNavigationLink', () => { ).toEqual({ title: 'pagination_label', permalink: '/docPermalink', - } as DocNavLink); + } as PropNavigationLink); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts index 44c652fe1959..363c731696b9 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts @@ -26,7 +26,7 @@ function normalizeCategoryLink( const getDefaultSlug = () => `/category/${params.categoryLabelSlugger.slug(category.label)}`; const slug = category.link.slug ?? getDefaultSlug(); - const permalink = normalizeUrl([params.version.versionPath, slug]); + const permalink = normalizeUrl([params.version.path, slug]); return { ...category.link, slug, diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts index a4f55b6bf5d0..7e83dd08a921 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts @@ -5,7 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -import type {DocMetadataBase, VersionMetadata} from '../types'; +import type { + DocMetadataBase, + VersionMetadata, +} from '@docusaurus/plugin-content-docs'; import type { NormalizedSidebarItem, NormalizedSidebar, diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts index 50a1e6185c2c..9f4d68a3ae45 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts @@ -6,11 +6,12 @@ */ import type {Optional, Required} from 'utility-types'; -import type {DocMetadataBase, VersionMetadata} from '../types'; import type { NumberPrefixParser, SidebarOptions, CategoryIndexMatcher, + DocMetadataBase, + VersionMetadata, } from '@docusaurus/plugin-content-docs'; import type {Slugger} from '@docusaurus/utils'; @@ -199,16 +200,6 @@ export type PropSidebarBreadcrumbsItem = | PropSidebarItemLink | PropSidebarItemCategory; -export type PropVersionDoc = { - id: string; - title: string; - description?: string; - sidebar?: string; -}; -export type PropVersionDocs = { - [docId: string]: PropVersionDoc; -}; - export type CategoryMetadataFile = { label?: string; position?: number; @@ -243,11 +234,20 @@ export type SidebarItemsGeneratorVersion = Pick< >; export type SidebarItemsGeneratorArgs = { + /** The sidebar item with type "autogenerated" to be transformed. */ item: SidebarItemAutogenerated; + /** Useful metadata for the version this sidebar belongs to. */ version: SidebarItemsGeneratorVersion; + /** All the docs of that version (unfiltered). */ docs: SidebarItemsGeneratorDoc[]; + /** Number prefix parser configured for this plugin. */ numberPrefixParser: NumberPrefixParser; + /** The default category index matcher which you can override. */ isCategoryIndex: CategoryIndexMatcher; + /** + * key is the path relative to the doc content directory, value is the + * category metadata file's content. + */ categoriesMetadata: {[filePath: string]: CategoryMetadataFile}; }; export type SidebarItemsGenerator = ( @@ -258,6 +258,10 @@ export type SidebarItemsGenerator = ( // default sidebar gen logic // see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320 export type SidebarItemsGeneratorOptionArgs = { + /** + * Useful to re-use/enhance the default sidebar generation logic from + * Docusaurus. + */ defaultSidebarItemsGenerator: SidebarItemsGenerator; } & SidebarItemsGeneratorArgs; export type SidebarItemsGeneratorOption = ( diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts index 5caa93d94884..ee27177c1e4a 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts @@ -21,7 +21,10 @@ import type { import _ from 'lodash'; import {toMessageRelativeFilePath} from '@docusaurus/utils'; -import type {DocMetadataBase, DocNavLink} from '../types'; +import type { + DocMetadataBase, + PropNavigationLink, +} from '@docusaurus/plugin-content-docs'; export function isCategoriesShorthand( item: SidebarItemConfig, @@ -346,7 +349,7 @@ Available document ids are: }; } -export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink { +export function toDocNavigationLink(doc: DocMetadataBase): PropNavigationLink { const { title, permalink, @@ -361,7 +364,7 @@ export function toDocNavigationLink(doc: DocMetadataBase): DocNavLink { export function toNavigationLink( navigationItem: SidebarNavigationItem | undefined, docsById: {[docId: string]: DocMetadataBase}, -): DocNavLink | undefined { +): PropNavigationLink | undefined { function getDocById(docId: string) { const doc = docsById[docId]; if (!doc) { diff --git a/packages/docusaurus-plugin-content-docs/src/slug.ts b/packages/docusaurus-plugin-content-docs/src/slug.ts index 9de48aa13f28..4815e210b01d 100644 --- a/packages/docusaurus-plugin-content-docs/src/slug.ts +++ b/packages/docusaurus-plugin-content-docs/src/slug.ts @@ -15,9 +15,11 @@ import { DefaultNumberPrefixParser, stripPathNumberPrefixes, } from './numberPrefix'; -import type {DocMetadataBase} from './types'; import {isCategoryIndex, toCategoryIndexMatcherParam} from './docs'; -import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs'; +import type { + NumberPrefixParser, + DocMetadataBase, +} from '@docusaurus/plugin-content-docs'; export default function getSlug({ baseID, diff --git a/packages/docusaurus-plugin-content-docs/src/tags.ts b/packages/docusaurus-plugin-content-docs/src/tags.ts index 005b956bd804..1de963d81f56 100644 --- a/packages/docusaurus-plugin-content-docs/src/tags.ts +++ b/packages/docusaurus-plugin-content-docs/src/tags.ts @@ -6,13 +6,14 @@ */ import {groupTaggedItems} from '@docusaurus/utils'; -import type {VersionTags, DocMetadata} from './types'; +import type {VersionTags} from './types'; +import type {DocMetadata} from '@docusaurus/plugin-content-docs'; import _ from 'lodash'; export function getVersionTags(docs: DocMetadata[]): VersionTags { const groups = groupTaggedItems(docs, (doc) => doc.tags); return _.mapValues(groups, (group) => ({ - name: group.tag.label, + label: group.tag.label, docIds: group.items.map((item) => item.id), permalink: group.tag.permalink, })); diff --git a/packages/docusaurus-plugin-content-docs/src/translations.ts b/packages/docusaurus-plugin-content-docs/src/translations.ts index 40d9e24f0a6b..cc43d6b3f061 100644 --- a/packages/docusaurus-plugin-content-docs/src/translations.ts +++ b/packages/docusaurus-plugin-content-docs/src/translations.ts @@ -245,7 +245,7 @@ function translateSidebars( function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles { const versionTranslations: TranslationFileContent = { 'version.label': { - message: version.versionLabel, + message: version.label, description: `The label for version ${version.versionName}`, }, }; @@ -275,8 +275,7 @@ function translateVersion( translationFiles[getVersionFileName(version.versionName)]!.content; return { ...version, - versionLabel: - versionTranslations['version.label']?.message ?? version.versionLabel, + label: versionTranslations['version.label']?.message ?? version.label, sidebars: translateSidebars(version, versionTranslations), // docs: translateDocs(version.docs, versionTranslations), }; diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index 7da32a8a3691..909a200da7e4 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -8,13 +8,13 @@ /// import type {Sidebars} from './sidebars/types'; +import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils'; import type { - Tag, - FrontMatterTag, - BrokenMarkdownLink, - ContentPaths, -} from '@docusaurus/utils'; -import type {VersionBanner} from '@docusaurus/plugin-content-docs'; + VersionMetadata, + LastUpdateData, + DocMetadata, + CategoryGeneratedIndexMetadata, +} from '@docusaurus/plugin-content-docs'; export type DocFile = { contentPath: string; // /!\ may be localized @@ -24,106 +24,19 @@ export type DocFile = { lastUpdate: LastUpdateData; }; -export type VersionMetadata = ContentPaths & { - versionName: string; // 1.0.0 - versionLabel: string; // Version 1.0.0 - versionPath: string; // /baseUrl/docs/1.0.0 - tagsPath: string; - versionEditUrl?: string | undefined; - versionEditUrlLocalized?: string | undefined; - versionBanner: VersionBanner | null; - versionBadge: boolean; - versionClassName: string; - isLast: boolean; - sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json - routePriority: number | undefined; // -1 for the latest docs -}; - -export type LastUpdateData = { - lastUpdatedAt?: number; - formattedLastUpdatedAt?: string; - lastUpdatedBy?: string; -}; - -export type DocFrontMatter = { - // Front matter uses snake case - id?: string; - title?: string; - tags?: FrontMatterTag[]; - hide_title?: boolean; - hide_table_of_contents?: boolean; - keywords?: string[]; - image?: string; - description?: string; - slug?: string; - sidebar_label?: string; - sidebar_position?: number; - sidebar_class_name?: string; - sidebar_custom_props?: {[key: string]: unknown}; - displayed_sidebar?: string | null; - pagination_label?: string; - custom_edit_url?: string | null; - parse_number_prefixes?: boolean; - toc_min_heading_level?: number; - toc_max_heading_level?: number; - pagination_next?: string | null; - pagination_prev?: string | null; -}; - -export type DocMetadataBase = LastUpdateData & { - id: string; // TODO legacy versioned id => try to remove - unversionedId: string; // TODO new unversioned id => try to rename to "id" - version: string; - title: string; - description: string; - source: string; // @site aliased posix source => "@site/docs/folder/subFolder/subSubFolder/myDoc.md" - sourceDirName: string; // posix path relative to the versioned docs folder (can be ".") => "folder/subFolder/subSubFolder" - slug: string; - permalink: string; - sidebarPosition?: number; - editUrl?: string | null; - tags: Tag[]; - frontMatter: DocFrontMatter & {[key: string]: unknown}; -}; - -export type DocNavLink = { - title: string; - permalink: string; -}; - -export type DocMetadata = DocMetadataBase & { - sidebar?: string; - previous?: DocNavLink; - next?: DocNavLink; -}; - -export type CategoryGeneratedIndexMetadata = { - title: string; - description?: string; - slug: string; - permalink: string; - sidebar: string; - previous?: DocNavLink; - next?: DocNavLink; - image?: string; - keywords?: string | readonly string[]; -}; - export type SourceToPermalink = { [source: string]: string; }; -export type VersionTag = { - name: string; // normalized name/label of the tag - docIds: string[]; // all doc ids having this tag - permalink: string; // pathname of the tag +export type VersionTag = Tag & { + /** all doc ids having this tag. */ + docIds: string[]; }; export type VersionTags = { [key: string]: VersionTag; }; export type LoadedVersion = VersionMetadata & { - versionPath: string; mainDocId: string; docs: DocMetadata[]; sidebars: Sidebars; diff --git a/packages/docusaurus-plugin-content-docs/src/versions.ts b/packages/docusaurus-plugin-content-docs/src/versions.ts index 664118498155..7b06aa0e089c 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions.ts @@ -7,7 +7,6 @@ import path from 'path'; import fs from 'fs-extra'; -import type {VersionMetadata} from './types'; import { VERSIONS_JSON_FILE, VERSIONED_DOCS_DIR, @@ -17,8 +16,8 @@ import { import type { PluginOptions, VersionBanner, - VersionOptions, VersionsOptions, + VersionMetadata, } from '@docusaurus/plugin-content-docs'; import type {LoadContext} from '@docusaurus/types'; @@ -207,7 +206,12 @@ function getVersionEditUrls({ contentPath, contentPathLocalized, context: {siteDir, i18n}, - options: {id, path: currentVersionPath, editUrl, editCurrentVersion}, + options: { + id, + path: currentVersionPath, + editUrl: editUrlOption, + editCurrentVersion, + }, }: { contentPath: string; contentPathLocalized: string; @@ -216,15 +220,11 @@ function getVersionEditUrls({ PluginOptions, 'id' | 'path' | 'editUrl' | 'editCurrentVersion' >; -}): {versionEditUrl: string; versionEditUrlLocalized: string} | undefined { - if (!editUrl) { - return undefined; - } - - // if the user is using the functional form of editUrl, - // he has total freedom and we can't compute a "version edit url" - if (typeof editUrl === 'function') { - return undefined; +}): Pick { + // If the user is using the functional form of editUrl, + // she has total freedom and we can't compute a "version edit url" + if (!editUrlOption || typeof editUrlOption === 'function') { + return {editUrl: undefined, editUrlLocalized: undefined}; } const editDirPath = editCurrentVersion ? currentVersionPath : contentPath; @@ -244,16 +244,16 @@ function getVersionEditUrls({ path.relative(siteDir, path.resolve(siteDir, editDirPathLocalized)), ); - const versionEditUrl = normalizeUrl([editUrl, versionPathSegment]); + const editUrl = normalizeUrl([editUrlOption, versionPathSegment]); - const versionEditUrlLocalized = normalizeUrl([ - editUrl, + const editUrlLocalized = normalizeUrl([ + editUrlOption, versionPathSegmentLocalized, ]); return { - versionEditUrl, - versionEditUrlLocalized, + editUrl, + editUrlLocalized, }; } @@ -370,12 +370,12 @@ function createVersionMetadata({ } const defaultVersionPathPart = getDefaultVersionPathPart(); - const versionOptions: VersionOptions = options.versions[versionName] ?? {}; + const versionOptions = options.versions[versionName] ?? {}; - const versionLabel = versionOptions.label ?? defaultVersionLabel; + const label = versionOptions.label ?? defaultVersionLabel; const versionPathPart = versionOptions.path ?? defaultVersionPathPart; - const versionPath = normalizeUrl([ + const routePath = normalizeUrl([ context.baseUrl, options.routeBasePath, versionPathPart, @@ -388,28 +388,27 @@ function createVersionMetadata({ options, }); - // Because /docs/:route` should always be after `/docs/versionName/:route`. const routePriority = versionPathPart === '' ? -1 : undefined; // the path that will be used to refer the docs tags // example below will be using /docs/tags - const tagsPath = normalizeUrl([versionPath, options.tagsBasePath]); + const tagsPath = normalizeUrl([routePath, options.tagsBasePath]); return { versionName, - versionLabel, - versionPath, + label, + path: routePath, tagsPath, - versionEditUrl: versionEditUrls?.versionEditUrl, - versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized, - versionBanner: getVersionBanner({ + editUrl: versionEditUrls.editUrl, + editUrlLocalized: versionEditUrls.editUrlLocalized, + banner: getVersionBanner({ versionName, versionNames, lastVersionName, options, }), - versionBadge: getVersionBadge({versionName, versionNames, options}), - versionClassName: getVersionClassName({versionName, options}), + badge: getVersionBadge({versionName, versionNames, options}), + className: getVersionClassName({versionName, options}), isLast, routePriority, sidebarFilePath, @@ -592,15 +591,3 @@ export async function readVersionsMetadata({ ); return versionsMetadata; } - -// order matter! -// Read in priority the localized path, then the unlocalized one -// We want the localized doc to "override" the unlocalized one -export function getDocsDirPaths( - versionMetadata: Pick< - VersionMetadata, - 'contentPath' | 'contentPathLocalized' - >, -): [string, string] { - return [versionMetadata.contentPathLocalized, versionMetadata.contentPath]; -} diff --git a/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts b/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts index fabded2ba633..24fd413ca1f4 100644 --- a/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts +++ b/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts @@ -6,9 +6,9 @@ */ declare module '@docusaurus/plugin-content-pages' { - import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader'; + import type {MDXOptions} from '@docusaurus/mdx-loader'; - export type PluginOptions = RemarkAndRehypePluginOptions & { + export type PluginOptions = MDXOptions & { id?: string; path: string; routeBasePath: string; diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index bb3e03137640..04e8b6ccd92b 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -5,6 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +/* eslint-disable @typescript-eslint/triple-slash-reference */ + +/// +/// +/// +/// + declare module '@docusaurus/theme-classic' { export type Options = { customCss?: string | string[]; diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx index aa675efa2c9b..77265efccbd2 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx @@ -47,7 +47,7 @@ function DocItemContent(props: Props): JSX.Element { const {title} = metadata; // We only add a title if: - // - user asks to hide it with front matter + // - user doesn't ask to hide it with front matter // - the markdown content does not already contain a top-level h1 heading const shouldAddTitle = !hideTitle && typeof DocContent.contentTitle === 'undefined'; diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts deleted file mode 100644 index db5e128fd3d1..000000000000 --- a/packages/docusaurus-theme-classic/src/types.d.ts +++ /dev/null @@ -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. - */ - -/// -/// -/// -/// diff --git a/packages/docusaurus-theme-live-codeblock/src/types.d.ts b/packages/docusaurus-theme-live-codeblock/src/types.d.ts index df2fa7d2162a..9ae9bb21cef3 100644 --- a/packages/docusaurus-theme-live-codeblock/src/types.d.ts +++ b/packages/docusaurus-theme-live-codeblock/src/types.d.ts @@ -6,6 +6,7 @@ */ /// +/// declare module '@theme-init/CodeBlock' { import type CodeBlock, {Props as BaseProps} from '@theme/CodeBlock'; diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index cf69f8f8a220..7ef92f29f5b1 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -31,24 +31,23 @@ Accepted fields: | Name | Type | Default | Description | | --- | --- | --- | --- | -| `path` | `string` | `'docs'` | Path to data on filesystem relative to site dir. | -| `breadcrumbs` | `boolean` | `true` | To enable or disable the breadcrumbs on docs pages. | +| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. | | `editUrl` | string \| EditUrlFunction | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | | `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | | `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. | | `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. | | `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. | -| `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. | -| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. | -| `sidebarPath` | false \| string | `undefined` (creates autogenerated sidebar) | Path to sidebar configuration. | +| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | +| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | +| `sidebarPath` | false \| string | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | | `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) | | `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) | -| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` by real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | +| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | | `numberPrefixParser` | boolean \| PrefixParser | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | -| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root Layout component of each doc page. | +| `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root layout component of each doc page. Provides the version data context, and is not unmounted when switching docs. | | `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. | | `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page | -| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag" page. | +| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag X" page. | | `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. | | `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. | | `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. | @@ -56,11 +55,12 @@ Accepted fields: | `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | | `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the doc. | | `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the doc was updated. | -| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even with versions. This will make the site only include the current version. | +| `breadcrumbs` | `boolean` | `true` | Enable or disable the breadcrumbs on doc pages. | +| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even when multiple versions exist. This will make the site only include the current version. Will error if `includeCurrentVersion: false` and `disableVersioning: true`. | | `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. | -| `lastVersion` | `string` | First version in `versions.json` | Set the version navigated to in priority and displayed by default for docs navbar items. | +| `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. | | `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. | -| `versions` | `Versions` | `{}` | Independent customization of each version's properties. | +| `versions` | `VersionsConfig` | `{}` | Independent customization of each version's properties. | @@ -78,15 +78,24 @@ type PrefixParser = (filename: string) => { numberPrefix?: number; }; -type CategoryIndexMatcher = (doc: { +type CategoryIndexMatcher = (param: { + /** The file name, without extension */ fileName: string; + /** + * The list of directories, from lowest level to highest. + * If there's no dir name, directories is ['.'] + */ directories: string[]; + /** The extension, with a leading dot */ extension: string; }) => boolean; type SidebarGenerator = (generatorArgs: { - item: {type: 'autogenerated'; dirName: string}; // the sidebar item with type "autogenerated" - version: {contentPath: string; versionName: string}; // the current version + /** The sidebar item with type "autogenerated" to be transformed. */ + item: {type: 'autogenerated'; dirName: string}; + /** Useful metadata for the version this sidebar belongs to. */ + version: {contentPath: string; versionName: string}; + /** All the docs of that version (unfiltered). */ docs: Array<{ id: string; title: string; @@ -94,23 +103,40 @@ type SidebarGenerator = (generatorArgs: { source: string; sourceDirName: string; sidebarPosition?: number | undefined; - }>; // all the docs of that version (unfiltered) - numberPrefixParser: PrefixParser; // numberPrefixParser configured for this plugin - categoriesMetadata: Record; // key is the path relative to the doc directory, value is the category metadata file's content - isCategoryIndex: CategoryIndexMatcher; // the default category index matcher, that you can override - defaultSidebarItemsGenerator: SidebarGenerator; // useful to re-use/enhance default sidebar generation logic from Docusaurus + }>; + /** Number prefix parser configured for this plugin. */ + numberPrefixParser: PrefixParser; + /** The default category index matcher which you can override. */ + isCategoryIndex: CategoryIndexMatcher; + /** + * key is the path relative to the doc content directory, value is the + * category metadata file's content. + */ + categoriesMetadata: {[filePath: string]: CategoryMetadata}; + /** + * Useful to re-use/enhance the default sidebar generation logic from + * Docusaurus. + */ + defaultSidebarItemsGenerator: SidebarGenerator; }) => Promise; -type Versions = Record< - string, // the version's ID - { - label: string; // the label of the version - path: string; // the route path of the version - banner: 'none' | 'unreleased' | 'unmaintained'; // the banner to show at the top of a doc of that version - badge: boolean; // show a badge with the version name at the top of a doc of that version - className; // add a custom className to the element when browsing docs of that version - } ->; +type VersionsConfig = { + [versionName: string]: { + /** + * The base path of the version, will be appended to `baseUrl` + + * `routeBasePath`. + */ + path?: string; + /** The label of the version to be used in badges, dropdowns, etc. */ + label?: string; + /** The banner to show at the top of a doc of that version. */ + banner?: 'none' | 'unreleased' | 'unmaintained'; + /** Show a badge with the version label at the top of each doc. */ + badge?: boolean; + /** Add a custom class name to the element of each doc */ + className?: string; + }; +}; ``` ### Example configuration {#ex-config}