diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/index.test.ts index 58ab78b388..a4439a7cb6 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/index.test.ts @@ -28,14 +28,15 @@ describe('loadDocs', () => { path: pluginPath, sidebarPath, }); - const {docs: docsMetadata} = await plugin.loadContent(); + const {docsMetadata} = await plugin.loadContent(); expect(docsMetadata.hello).toEqual({ - category: 'Guides', id: 'hello', permalink: '/docs/hello', - previous: 'foo/baz', - previous_title: 'baz', + previous: { + title: 'baz', + permalink: '/docs/foo/baz', + }, sidebar: 'docs', source: path.join('@site', pluginPath, 'hello.md'), title: 'Hello, World !', @@ -43,10 +44,11 @@ describe('loadDocs', () => { }); expect(docsMetadata['foo/bar']).toEqual({ - category: 'Test', id: 'foo/bar', - next: 'foo/baz', - next_title: 'baz', + next: { + title: 'baz', + permalink: '/docs/foo/baz', + }, permalink: '/docs/foo/bar', sidebar: 'docs', source: path.join('@site', pluginPath, 'foo', 'bar.md'), diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/order.test.ts b/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/order.test.ts index db3ef1098c..1f237318b7 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/order.test.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/__tests__/order.test.ts @@ -43,36 +43,26 @@ describe('createOrder', () => { }); expect(result).toEqual({ doc1: { - category: 'Category1', - subCategory: 'Subcategory 1', next: 'doc2', previous: undefined, sidebar: 'docs', }, doc2: { - category: 'Category1', - subCategory: 'Subcategory 2', next: 'doc3', previous: 'doc1', sidebar: 'docs', }, doc3: { - category: 'Category2', - subCategory: undefined, next: 'doc4', previous: 'doc2', sidebar: 'docs', }, doc4: { - category: 'Category2', - subCategory: undefined, next: undefined, previous: 'doc3', sidebar: 'docs', }, doc5: { - category: 'Category1', - subCategory: undefined, next: undefined, previous: undefined, sidebar: 'otherDocs', @@ -103,36 +93,26 @@ describe('createOrder', () => { }); expect(result).toEqual({ doc1: { - category: 'Category1', - subCategory: undefined, next: 'doc2', previous: undefined, sidebar: 'docs', }, doc2: { - category: 'Category1', - subCategory: undefined, next: 'doc3', previous: 'doc1', sidebar: 'docs', }, doc3: { - category: 'Category2', - subCategory: undefined, next: 'doc4', previous: 'doc2', sidebar: 'docs', }, doc4: { - category: 'Category2', - subCategory: undefined, next: undefined, previous: 'doc3', sidebar: 'docs', }, doc5: { - category: 'Category1', - subCategory: undefined, next: undefined, previous: undefined, sidebar: 'otherDocs', @@ -164,22 +144,16 @@ describe('createOrder', () => { }); expect(result).toEqual({ doc1: { - category: 'Category1', - subCategory: undefined, next: undefined, previous: undefined, sidebar: 'docs', }, 'version-1.2.3-doc1': { - category: 'Category2', - subCategory: undefined, next: undefined, previous: 'version-1.2.3-doc2', sidebar: 'version-1.2.3-docs', }, 'version-1.2.3-doc2': { - category: 'Category1', - subCategory: undefined, next: 'version-1.2.3-doc1', previous: undefined, sidebar: 'version-1.2.3-docs', @@ -227,22 +201,16 @@ describe('createOrder', () => { }); expect(result).toEqual({ doc2: { - category: 'Category1', - subCategory: 'Subcategory 2', next: 'doc3', previous: undefined, sidebar: 'docs', }, doc3: { - category: 'Category2', - subCategory: undefined, next: undefined, previous: 'doc2', sidebar: 'docs', }, doc5: { - category: 'Category1', - subCategory: undefined, next: undefined, previous: undefined, sidebar: 'otherDocs', diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/index.ts b/packages/docusaurus-plugin-content-docs-legacy/src/index.ts index a3c0b6d467..790368818a 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/index.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/index.ts @@ -18,11 +18,17 @@ import { PluginOptions, Sidebar, Order, - Metadata, DocsMetadata, LoadedContent, SourceToPermalink, - PermalinkToId, + PermalinkToSidebar, + DocsSidebarItemCategory, + SidebarItemLink, + SidebarItemDoc, + SidebarItemCategory, + DocsSidebar, + DocsBaseMetadata, + MetadataRaw, } from './types'; import {Configuration} from 'webpack'; @@ -64,13 +70,15 @@ export default function pluginContentDocs( return null; } - const docsSidebars: Sidebar = loadSidebars(sidebarPath); + const loadedSidebars: Sidebar = loadSidebars(sidebarPath); // Build the docs ordering such as next, previous, category and sidebar. - const order: Order = createOrder(docsSidebars); + const order: Order = createOrder(loadedSidebars); // Prepare metadata container. - const docs: DocsMetadata = {}; + const docsMetadataRaw: { + [id: string]: MetadataRaw; + } = {}; // Metadata for default docs files. const docsFiles = await globby(include, { @@ -78,7 +86,7 @@ export default function pluginContentDocs( }); await Promise.all( docsFiles.map(async source => { - const metadata: Metadata = await processMetadata( + const metadata: MetadataRaw = await processMetadata( source, docsDir, order, @@ -86,36 +94,99 @@ export default function pluginContentDocs( routeBasePath, siteDir, ); - docs[metadata.id] = metadata; + docsMetadataRaw[metadata.id] = metadata; }), ); - // Get the titles of the previous and next ids so that we can use them. - Object.keys(docs).forEach(currentID => { - const previousID = idx(docs, [currentID, 'previous']); + // Construct docsMetadata + const docsMetadata: DocsMetadata = {}; + Object.keys(docsMetadataRaw).forEach(currentID => { + let previous; + let next; + const previousID = idx(docsMetadataRaw, [currentID, 'previous']); if (previousID) { - const previousTitle = idx(docs, [previousID, 'title']); - docs[currentID].previous_title = previousTitle || 'Previous'; + previous = { + title: idx(docsMetadataRaw, [previousID, 'title']) || 'Previous', + permalink: idx(docsMetadataRaw, [previousID, 'permalink']), + }; } - const nextID = idx(docs, [currentID, 'next']); + const nextID = idx(docsMetadataRaw, [currentID, 'next']); if (nextID) { - const nextTitle = idx(docs, [nextID, 'title']); - docs[currentID].next_title = nextTitle || 'Next'; + next = { + title: idx(docsMetadataRaw, [nextID, 'title']) || 'Next', + permalink: idx(docsMetadataRaw, [nextID, 'permalink']), + }; + } + docsMetadata[currentID] = { + ...docsMetadataRaw[currentID], + previous, + next, + }; + }); + + const permalinkToSidebar: PermalinkToSidebar = {}; + Object.values(docsMetadataRaw).forEach(({source, permalink, sidebar}) => { + sourceToPermalink[source] = permalink; + if (sidebar) { + permalinkToSidebar[permalink] = sidebar; } }); - const permalinkToId: PermalinkToId = {}; - Object.values(docs).forEach(({id, source, permalink}) => { - sourceToPermalink[source] = permalink; - permalinkToId[permalink] = id; - }); + const convertDocLink = (item: SidebarItemDoc): SidebarItemLink => { + const linkID = item.id; + const linkMetadata = docsMetadataRaw[linkID]; + + if (!linkMetadata) { + throw new Error( + `Improper sidebars file, document with id '${linkID}' not found.`, + ); + } + + return { + type: 'link', + label: linkMetadata.sidebar_label || linkMetadata.title, + href: linkMetadata.permalink, + }; + }; + + const normalizeCategory = ( + category: SidebarItemCategory, + ): DocsSidebarItemCategory => { + const items = category.items.map(item => { + switch (item.type) { + case 'category': + return normalizeCategory(item as SidebarItemCategory); + case 'ref': + case 'doc': + return convertDocLink(item as SidebarItemDoc); + case 'link': + break; + default: + throw new Error(`Unknown sidebar item type: ${item.type}`); + } + return item as SidebarItemLink; + }); + return {...category, items}; + }; + + // Transform the sidebar so that all sidebar item will be in the form of 'link' or 'category' only + // This is what will be passed as props to the UI component + const docsSidebars: DocsSidebar = Object.entries(loadedSidebars).reduce( + (acc: DocsSidebar, [sidebarId, sidebarItemCategories]) => { + acc[sidebarId] = sidebarItemCategories.map(sidebarItemCategory => + normalizeCategory(sidebarItemCategory), + ); + return acc; + }, + {}, + ); return { - docs, + docsMetadata, docsDir, docsSidebars, sourceToPermalink, - permalinkToId, + permalinkToSidebar, }; }, @@ -128,7 +199,7 @@ export default function pluginContentDocs( const {addRoute, createData} = actions; const routes = await Promise.all( - Object.values(content.docs).map(async metadataItem => { + Object.values(content.docsMetadata).map(async metadataItem => { const metadataPath = await createData( `${docuHash(metadataItem.permalink)}.json`, JSON.stringify(metadataItem, null, 2), @@ -145,13 +216,18 @@ export default function pluginContentDocs( }), ); + const docsBaseMetadata: DocsBaseMetadata = { + docsSidebars: content.docsSidebars, + permalinkToSidebar: content.permalinkToSidebar, + }; + const docsBaseRoute = normalizeUrl([ (context.siteConfig as DocusaurusConfig).baseUrl, routeBasePath, ]); - const docsMetadataPath = await createData( + const docsBaseMetadataPath = await createData( `${docuHash(docsBaseRoute)}.json`, - JSON.stringify(content, null, 2), + JSON.stringify(docsBaseMetadata, null, 2), ); addRoute({ @@ -159,7 +235,7 @@ export default function pluginContentDocs( component: docLayoutComponent, routes, modules: { - docsMetadata: docsMetadataPath, + docsMetadata: docsBaseMetadataPath, }, }); }, diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/metadata.ts b/packages/docusaurus-plugin-content-docs-legacy/src/metadata.ts index 8b9d8889f0..d148a48840 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/metadata.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/metadata.ts @@ -74,8 +74,6 @@ export default async function processMetadata( const {id} = metadata; if (order[id]) { metadata.sidebar = order[id].sidebar; - metadata.category = order[id].category; - metadata.subCategory = order[id].subCategory; if (order[id].next) { metadata.next = order[id].next; } diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/order.ts b/packages/docusaurus-plugin-content-docs-legacy/src/order.ts index a7ddfebb4e..8c9805d633 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/order.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/order.ts @@ -21,26 +21,12 @@ export default function createOrder(allSidebars: Sidebar = {}): Order { const sidebar = allSidebars[sidebarId]; const ids: string[] = []; - const categoryOrder: (string | undefined)[] = []; - const subCategoryOrder: (string | undefined)[] = []; - const indexItems = ({ - items, - categoryLabel, - subCategoryLabel, - }: { - items: SidebarItem[]; - categoryLabel?: string; - subCategoryLabel?: string; - }) => { + const indexItems = ({items}: {items: SidebarItem[]}) => { items.forEach(item => { switch (item.type) { case 'category': indexItems({ items: (item as SidebarItemCategory).items, - categoryLabel: - categoryLabel || (item as SidebarItemCategory).label, - subCategoryLabel: - categoryLabel && (item as SidebarItemCategory).label, }); break; case 'ref': @@ -49,8 +35,6 @@ export default function createOrder(allSidebars: Sidebar = {}): Order { break; case 'doc': ids.push((item as SidebarItemDoc).id); - categoryOrder.push(categoryLabel); - subCategoryOrder.push(subCategoryLabel); break; default: throw new Error( @@ -80,8 +64,6 @@ export default function createOrder(allSidebars: Sidebar = {}): Order { previous, next, sidebar: sidebarId, - category: categoryOrder[i], - subCategory: subCategoryOrder[i], }; } }); diff --git a/packages/docusaurus-plugin-content-docs-legacy/src/types.ts b/packages/docusaurus-plugin-content-docs-legacy/src/types.ts index b322108f85..96194af2e7 100644 --- a/packages/docusaurus-plugin-content-docs-legacy/src/types.ts +++ b/packages/docusaurus-plugin-content-docs-legacy/src/types.ts @@ -61,12 +61,20 @@ export interface Sidebar { [sidebarId: string]: SidebarItemCategory[]; } +export interface DocsSidebarItemCategory { + type: string; + label: string; + items: (SidebarItemLink | DocsSidebarItemCategory)[]; +} + +export interface DocsSidebar { + [sidebarId: string]: DocsSidebarItemCategory[]; +} + export interface OrderMetadata { previous?: string; next?: string; sidebar?: string; - category?: string; - subCategory?: string; } export interface Order { @@ -79,11 +87,18 @@ export interface MetadataRaw extends OrderMetadata { description: string; source: string; permalink: string; + sidebar_label?: string; + [key: string]: any; } -export interface Metadata extends MetadataRaw { - previous_title?: string; - next_title?: string; +export interface Paginator { + title: string; + permalink: string; +} + +export interface Metadata extends Omit { + previous?: Paginator; + next?: Paginator; } export interface DocsMetadata { @@ -94,14 +109,19 @@ export interface SourceToPermalink { [source: string]: string; } -export interface PermalinkToId { +export interface PermalinkToSidebar { [permalink: string]: string; } export interface LoadedContent { - docs: DocsMetadata; + docsMetadata: DocsMetadata; docsDir: string; docsSidebars: Sidebar; sourceToPermalink: SourceToPermalink; - permalinkToId: PermalinkToId; + permalinkToSidebar: PermalinkToSidebar; } + +export type DocsBaseMetadata = Pick< + LoadedContent, + 'docsSidebars' | 'permalinkToSidebar' +>; diff --git a/packages/docusaurus-theme-classic/src/theme/DocLegacyItem/index.js b/packages/docusaurus-theme-classic/src/theme/DocLegacyItem/index.js index 266152ca57..b6916a87b2 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocLegacyItem/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocLegacyItem/index.js @@ -8,6 +8,8 @@ import React from 'react'; import Head from '@docusaurus/Head'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import withBaseUrl from '@docusaurus/withBaseUrl'; import DocLegacyPaginator from '@theme/DocLegacyPaginator'; import styles from './styles.module.css'; @@ -29,12 +31,35 @@ function Headings({headings, isChild}) { } function DocLegacyItem(props) { - const {metadata, content: DocContent, docsMetadata} = props; + const {siteConfig = {}} = useDocusaurusContext(); + const {url: siteUrl} = siteConfig; + const {metadata, content: DocContent} = props; + const {description, title, permalink, image: metaImage} = metadata; return (
- {metadata && metadata.title && {metadata.title}} + {title && {title}} + {description && } + {description && ( + + )} + {metaImage && ( + + )} + {metaImage && ( + + )} + {metaImage && ( + + )} + {permalink && }
@@ -49,10 +74,7 @@ function DocLegacyItem(props) {
- +
diff --git a/packages/docusaurus-theme-classic/src/theme/DocLegacyPage/index.js b/packages/docusaurus-theme-classic/src/theme/DocLegacyPage/index.js index 057dea32e8..4db6a94063 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocLegacyPage/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocLegacyPage/index.js @@ -15,27 +15,20 @@ import MDXComponents from '@theme/MDXComponents'; function DocLegacyPage(props) { const {route, docsMetadata, location} = props; - const {permalinkToId} = docsMetadata; - const id = - permalinkToId[location.pathname] || - permalinkToId[location.pathname.replace(/\/$/, '')]; - const metadata = docsMetadata.docs[id] || {}; - const {sidebar, description, title, permalink, image} = metadata; + const {permalinkToSidebar, docsSidebars} = docsMetadata; + const sidebar = + permalinkToSidebar[location.pathname] || + permalinkToSidebar[location.pathname.replace(/\/$/, '')]; return ( - +
- +
- {renderRoutes(route.routes, {docsMetadata})} + {renderRoutes(route.routes)}
diff --git a/packages/docusaurus-theme-classic/src/theme/DocLegacyPaginator/index.js b/packages/docusaurus-theme-classic/src/theme/DocLegacyPaginator/index.js index 6f616b06e9..3b7a2a2671 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocLegacyPaginator/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocLegacyPaginator/index.js @@ -9,33 +9,28 @@ import React from 'react'; import Link from '@docusaurus/Link'; function DocLegacyPaginator(props) { - const { - docsMetadata: {docs}, - metadata, - } = props; + const {metadata} = props; return (