mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-07 14:17:16 +02:00
refactor(v2): better docs metadata (#1815)
This commit is contained in:
parent
a04bd440b4
commit
e7ba8af6d9
10 changed files with 185 additions and 149 deletions
|
@ -28,14 +28,15 @@ describe('loadDocs', () => {
|
||||||
path: pluginPath,
|
path: pluginPath,
|
||||||
sidebarPath,
|
sidebarPath,
|
||||||
});
|
});
|
||||||
const {docs: docsMetadata} = await plugin.loadContent();
|
const {docsMetadata} = await plugin.loadContent();
|
||||||
|
|
||||||
expect(docsMetadata.hello).toEqual({
|
expect(docsMetadata.hello).toEqual({
|
||||||
category: 'Guides',
|
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
permalink: '/docs/hello',
|
permalink: '/docs/hello',
|
||||||
previous: 'foo/baz',
|
previous: {
|
||||||
previous_title: 'baz',
|
title: 'baz',
|
||||||
|
permalink: '/docs/foo/baz',
|
||||||
|
},
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
source: path.join('@site', pluginPath, 'hello.md'),
|
source: path.join('@site', pluginPath, 'hello.md'),
|
||||||
title: 'Hello, World !',
|
title: 'Hello, World !',
|
||||||
|
@ -43,10 +44,11 @@ describe('loadDocs', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(docsMetadata['foo/bar']).toEqual({
|
expect(docsMetadata['foo/bar']).toEqual({
|
||||||
category: 'Test',
|
|
||||||
id: 'foo/bar',
|
id: 'foo/bar',
|
||||||
next: 'foo/baz',
|
next: {
|
||||||
next_title: 'baz',
|
title: 'baz',
|
||||||
|
permalink: '/docs/foo/baz',
|
||||||
|
},
|
||||||
permalink: '/docs/foo/bar',
|
permalink: '/docs/foo/bar',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
source: path.join('@site', pluginPath, 'foo', 'bar.md'),
|
source: path.join('@site', pluginPath, 'foo', 'bar.md'),
|
||||||
|
|
|
@ -43,36 +43,26 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc1: {
|
doc1: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: 'Subcategory 1',
|
|
||||||
next: 'doc2',
|
next: 'doc2',
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc2: {
|
doc2: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: 'Subcategory 2',
|
|
||||||
next: 'doc3',
|
next: 'doc3',
|
||||||
previous: 'doc1',
|
previous: 'doc1',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc3: {
|
doc3: {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: 'doc4',
|
next: 'doc4',
|
||||||
previous: 'doc2',
|
previous: 'doc2',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc4: {
|
doc4: {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: 'doc3',
|
previous: 'doc3',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc5: {
|
doc5: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'otherDocs',
|
sidebar: 'otherDocs',
|
||||||
|
@ -103,36 +93,26 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc1: {
|
doc1: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: 'doc2',
|
next: 'doc2',
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc2: {
|
doc2: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: 'doc3',
|
next: 'doc3',
|
||||||
previous: 'doc1',
|
previous: 'doc1',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc3: {
|
doc3: {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: 'doc4',
|
next: 'doc4',
|
||||||
previous: 'doc2',
|
previous: 'doc2',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc4: {
|
doc4: {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: 'doc3',
|
previous: 'doc3',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc5: {
|
doc5: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'otherDocs',
|
sidebar: 'otherDocs',
|
||||||
|
@ -164,22 +144,16 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc1: {
|
doc1: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
'version-1.2.3-doc1': {
|
'version-1.2.3-doc1': {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: 'version-1.2.3-doc2',
|
previous: 'version-1.2.3-doc2',
|
||||||
sidebar: 'version-1.2.3-docs',
|
sidebar: 'version-1.2.3-docs',
|
||||||
},
|
},
|
||||||
'version-1.2.3-doc2': {
|
'version-1.2.3-doc2': {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: 'version-1.2.3-doc1',
|
next: 'version-1.2.3-doc1',
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'version-1.2.3-docs',
|
sidebar: 'version-1.2.3-docs',
|
||||||
|
@ -227,22 +201,16 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc2: {
|
doc2: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: 'Subcategory 2',
|
|
||||||
next: 'doc3',
|
next: 'doc3',
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc3: {
|
doc3: {
|
||||||
category: 'Category2',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: 'doc2',
|
previous: 'doc2',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc5: {
|
doc5: {
|
||||||
category: 'Category1',
|
|
||||||
subCategory: undefined,
|
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'otherDocs',
|
sidebar: 'otherDocs',
|
||||||
|
|
|
@ -18,11 +18,17 @@ import {
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
Sidebar,
|
Sidebar,
|
||||||
Order,
|
Order,
|
||||||
Metadata,
|
|
||||||
DocsMetadata,
|
DocsMetadata,
|
||||||
LoadedContent,
|
LoadedContent,
|
||||||
SourceToPermalink,
|
SourceToPermalink,
|
||||||
PermalinkToId,
|
PermalinkToSidebar,
|
||||||
|
DocsSidebarItemCategory,
|
||||||
|
SidebarItemLink,
|
||||||
|
SidebarItemDoc,
|
||||||
|
SidebarItemCategory,
|
||||||
|
DocsSidebar,
|
||||||
|
DocsBaseMetadata,
|
||||||
|
MetadataRaw,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {Configuration} from 'webpack';
|
import {Configuration} from 'webpack';
|
||||||
|
|
||||||
|
@ -64,13 +70,15 @@ export default function pluginContentDocs(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const docsSidebars: Sidebar = loadSidebars(sidebarPath);
|
const loadedSidebars: Sidebar = loadSidebars(sidebarPath);
|
||||||
|
|
||||||
// Build the docs ordering such as next, previous, category and sidebar.
|
// Build the docs ordering such as next, previous, category and sidebar.
|
||||||
const order: Order = createOrder(docsSidebars);
|
const order: Order = createOrder(loadedSidebars);
|
||||||
|
|
||||||
// Prepare metadata container.
|
// Prepare metadata container.
|
||||||
const docs: DocsMetadata = {};
|
const docsMetadataRaw: {
|
||||||
|
[id: string]: MetadataRaw;
|
||||||
|
} = {};
|
||||||
|
|
||||||
// Metadata for default docs files.
|
// Metadata for default docs files.
|
||||||
const docsFiles = await globby(include, {
|
const docsFiles = await globby(include, {
|
||||||
|
@ -78,7 +86,7 @@ export default function pluginContentDocs(
|
||||||
});
|
});
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
docsFiles.map(async source => {
|
docsFiles.map(async source => {
|
||||||
const metadata: Metadata = await processMetadata(
|
const metadata: MetadataRaw = await processMetadata(
|
||||||
source,
|
source,
|
||||||
docsDir,
|
docsDir,
|
||||||
order,
|
order,
|
||||||
|
@ -86,36 +94,99 @@ export default function pluginContentDocs(
|
||||||
routeBasePath,
|
routeBasePath,
|
||||||
siteDir,
|
siteDir,
|
||||||
);
|
);
|
||||||
docs[metadata.id] = metadata;
|
docsMetadataRaw[metadata.id] = metadata;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the titles of the previous and next ids so that we can use them.
|
// Construct docsMetadata
|
||||||
Object.keys(docs).forEach(currentID => {
|
const docsMetadata: DocsMetadata = {};
|
||||||
const previousID = idx(docs, [currentID, 'previous']);
|
Object.keys(docsMetadataRaw).forEach(currentID => {
|
||||||
|
let previous;
|
||||||
|
let next;
|
||||||
|
const previousID = idx(docsMetadataRaw, [currentID, 'previous']);
|
||||||
if (previousID) {
|
if (previousID) {
|
||||||
const previousTitle = idx(docs, [previousID, 'title']);
|
previous = {
|
||||||
docs[currentID].previous_title = previousTitle || '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) {
|
if (nextID) {
|
||||||
const nextTitle = idx(docs, [nextID, 'title']);
|
next = {
|
||||||
docs[currentID].next_title = nextTitle || '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 = {};
|
const convertDocLink = (item: SidebarItemDoc): SidebarItemLink => {
|
||||||
Object.values(docs).forEach(({id, source, permalink}) => {
|
const linkID = item.id;
|
||||||
sourceToPermalink[source] = permalink;
|
const linkMetadata = docsMetadataRaw[linkID];
|
||||||
permalinkToId[permalink] = id;
|
|
||||||
});
|
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 {
|
return {
|
||||||
docs,
|
docsMetadata,
|
||||||
docsDir,
|
docsDir,
|
||||||
docsSidebars,
|
docsSidebars,
|
||||||
sourceToPermalink,
|
sourceToPermalink,
|
||||||
permalinkToId,
|
permalinkToSidebar,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -128,7 +199,7 @@ export default function pluginContentDocs(
|
||||||
const {addRoute, createData} = actions;
|
const {addRoute, createData} = actions;
|
||||||
|
|
||||||
const routes = await Promise.all(
|
const routes = await Promise.all(
|
||||||
Object.values(content.docs).map(async metadataItem => {
|
Object.values(content.docsMetadata).map(async metadataItem => {
|
||||||
const metadataPath = await createData(
|
const metadataPath = await createData(
|
||||||
`${docuHash(metadataItem.permalink)}.json`,
|
`${docuHash(metadataItem.permalink)}.json`,
|
||||||
JSON.stringify(metadataItem, null, 2),
|
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([
|
const docsBaseRoute = normalizeUrl([
|
||||||
(context.siteConfig as DocusaurusConfig).baseUrl,
|
(context.siteConfig as DocusaurusConfig).baseUrl,
|
||||||
routeBasePath,
|
routeBasePath,
|
||||||
]);
|
]);
|
||||||
const docsMetadataPath = await createData(
|
const docsBaseMetadataPath = await createData(
|
||||||
`${docuHash(docsBaseRoute)}.json`,
|
`${docuHash(docsBaseRoute)}.json`,
|
||||||
JSON.stringify(content, null, 2),
|
JSON.stringify(docsBaseMetadata, null, 2),
|
||||||
);
|
);
|
||||||
|
|
||||||
addRoute({
|
addRoute({
|
||||||
|
@ -159,7 +235,7 @@ export default function pluginContentDocs(
|
||||||
component: docLayoutComponent,
|
component: docLayoutComponent,
|
||||||
routes,
|
routes,
|
||||||
modules: {
|
modules: {
|
||||||
docsMetadata: docsMetadataPath,
|
docsMetadata: docsBaseMetadataPath,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,8 +74,6 @@ export default async function processMetadata(
|
||||||
const {id} = metadata;
|
const {id} = metadata;
|
||||||
if (order[id]) {
|
if (order[id]) {
|
||||||
metadata.sidebar = order[id].sidebar;
|
metadata.sidebar = order[id].sidebar;
|
||||||
metadata.category = order[id].category;
|
|
||||||
metadata.subCategory = order[id].subCategory;
|
|
||||||
if (order[id].next) {
|
if (order[id].next) {
|
||||||
metadata.next = order[id].next;
|
metadata.next = order[id].next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,26 +21,12 @@ export default function createOrder(allSidebars: Sidebar = {}): Order {
|
||||||
const sidebar = allSidebars[sidebarId];
|
const sidebar = allSidebars[sidebarId];
|
||||||
|
|
||||||
const ids: string[] = [];
|
const ids: string[] = [];
|
||||||
const categoryOrder: (string | undefined)[] = [];
|
const indexItems = ({items}: {items: SidebarItem[]}) => {
|
||||||
const subCategoryOrder: (string | undefined)[] = [];
|
|
||||||
const indexItems = ({
|
|
||||||
items,
|
|
||||||
categoryLabel,
|
|
||||||
subCategoryLabel,
|
|
||||||
}: {
|
|
||||||
items: SidebarItem[];
|
|
||||||
categoryLabel?: string;
|
|
||||||
subCategoryLabel?: string;
|
|
||||||
}) => {
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'category':
|
case 'category':
|
||||||
indexItems({
|
indexItems({
|
||||||
items: (item as SidebarItemCategory).items,
|
items: (item as SidebarItemCategory).items,
|
||||||
categoryLabel:
|
|
||||||
categoryLabel || (item as SidebarItemCategory).label,
|
|
||||||
subCategoryLabel:
|
|
||||||
categoryLabel && (item as SidebarItemCategory).label,
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'ref':
|
case 'ref':
|
||||||
|
@ -49,8 +35,6 @@ export default function createOrder(allSidebars: Sidebar = {}): Order {
|
||||||
break;
|
break;
|
||||||
case 'doc':
|
case 'doc':
|
||||||
ids.push((item as SidebarItemDoc).id);
|
ids.push((item as SidebarItemDoc).id);
|
||||||
categoryOrder.push(categoryLabel);
|
|
||||||
subCategoryOrder.push(subCategoryLabel);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -80,8 +64,6 @@ export default function createOrder(allSidebars: Sidebar = {}): Order {
|
||||||
previous,
|
previous,
|
||||||
next,
|
next,
|
||||||
sidebar: sidebarId,
|
sidebar: sidebarId,
|
||||||
category: categoryOrder[i],
|
|
||||||
subCategory: subCategoryOrder[i],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,12 +61,20 @@ export interface Sidebar {
|
||||||
[sidebarId: string]: SidebarItemCategory[];
|
[sidebarId: string]: SidebarItemCategory[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DocsSidebarItemCategory {
|
||||||
|
type: string;
|
||||||
|
label: string;
|
||||||
|
items: (SidebarItemLink | DocsSidebarItemCategory)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocsSidebar {
|
||||||
|
[sidebarId: string]: DocsSidebarItemCategory[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface OrderMetadata {
|
export interface OrderMetadata {
|
||||||
previous?: string;
|
previous?: string;
|
||||||
next?: string;
|
next?: string;
|
||||||
sidebar?: string;
|
sidebar?: string;
|
||||||
category?: string;
|
|
||||||
subCategory?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Order {
|
export interface Order {
|
||||||
|
@ -79,11 +87,18 @@ export interface MetadataRaw extends OrderMetadata {
|
||||||
description: string;
|
description: string;
|
||||||
source: string;
|
source: string;
|
||||||
permalink: string;
|
permalink: string;
|
||||||
|
sidebar_label?: string;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Metadata extends MetadataRaw {
|
export interface Paginator {
|
||||||
previous_title?: string;
|
title: string;
|
||||||
next_title?: string;
|
permalink: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Metadata extends Omit<MetadataRaw, 'previous' | 'next'> {
|
||||||
|
previous?: Paginator;
|
||||||
|
next?: Paginator;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DocsMetadata {
|
export interface DocsMetadata {
|
||||||
|
@ -94,14 +109,19 @@ export interface SourceToPermalink {
|
||||||
[source: string]: string;
|
[source: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PermalinkToId {
|
export interface PermalinkToSidebar {
|
||||||
[permalink: string]: string;
|
[permalink: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadedContent {
|
export interface LoadedContent {
|
||||||
docs: DocsMetadata;
|
docsMetadata: DocsMetadata;
|
||||||
docsDir: string;
|
docsDir: string;
|
||||||
docsSidebars: Sidebar;
|
docsSidebars: Sidebar;
|
||||||
sourceToPermalink: SourceToPermalink;
|
sourceToPermalink: SourceToPermalink;
|
||||||
permalinkToId: PermalinkToId;
|
permalinkToSidebar: PermalinkToSidebar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DocsBaseMetadata = Pick<
|
||||||
|
LoadedContent,
|
||||||
|
'docsSidebars' | 'permalinkToSidebar'
|
||||||
|
>;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Head from '@docusaurus/Head';
|
import Head from '@docusaurus/Head';
|
||||||
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
import withBaseUrl from '@docusaurus/withBaseUrl';
|
||||||
import DocLegacyPaginator from '@theme/DocLegacyPaginator';
|
import DocLegacyPaginator from '@theme/DocLegacyPaginator';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
@ -29,12 +31,35 @@ function Headings({headings, isChild}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function DocLegacyItem(props) {
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<Head>
|
||||||
{metadata && metadata.title && <title>{metadata.title}</title>}
|
{title && <title>{title}</title>}
|
||||||
|
{description && <meta name="description" content={description} />}
|
||||||
|
{description && (
|
||||||
|
<meta property="og:description" content={description} />
|
||||||
|
)}
|
||||||
|
{metaImage && (
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content={siteUrl + withBaseUrl(metaImage)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{metaImage && (
|
||||||
|
<meta
|
||||||
|
property="twitter:image"
|
||||||
|
content={siteUrl + withBaseUrl(metaImage)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{metaImage && (
|
||||||
|
<meta name="twitter:image:alt" content={`Image for ${title}`} />
|
||||||
|
)}
|
||||||
|
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
|
||||||
</Head>
|
</Head>
|
||||||
<div className="padding-vert--lg">
|
<div className="padding-vert--lg">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
@ -49,10 +74,7 @@ function DocLegacyItem(props) {
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<div className="margin-top--xl margin-bottom--lg">
|
<div className="margin-top--xl margin-bottom--lg">
|
||||||
<DocLegacyPaginator
|
<DocLegacyPaginator metadata={metadata} />
|
||||||
docsMetadata={docsMetadata}
|
|
||||||
metadata={metadata}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,27 +15,20 @@ import MDXComponents from '@theme/MDXComponents';
|
||||||
|
|
||||||
function DocLegacyPage(props) {
|
function DocLegacyPage(props) {
|
||||||
const {route, docsMetadata, location} = props;
|
const {route, docsMetadata, location} = props;
|
||||||
const {permalinkToId} = docsMetadata;
|
const {permalinkToSidebar, docsSidebars} = docsMetadata;
|
||||||
const id =
|
const sidebar =
|
||||||
permalinkToId[location.pathname] ||
|
permalinkToSidebar[location.pathname] ||
|
||||||
permalinkToId[location.pathname.replace(/\/$/, '')];
|
permalinkToSidebar[location.pathname.replace(/\/$/, '')];
|
||||||
const metadata = docsMetadata.docs[id] || {};
|
|
||||||
const {sidebar, description, title, permalink, image} = metadata;
|
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout noFooter>
|
||||||
noFooter
|
|
||||||
description={description}
|
|
||||||
title={title}
|
|
||||||
image={image}
|
|
||||||
permalink={permalink}>
|
|
||||||
<div className="container container--fluid">
|
<div className="container container--fluid">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col col--3">
|
<div className="col col--3">
|
||||||
<DocLegacySidebar docsMetadata={docsMetadata} sidebar={sidebar} />
|
<DocLegacySidebar docsSidebars={docsSidebars} sidebar={sidebar} />
|
||||||
</div>
|
</div>
|
||||||
<main className="col">
|
<main className="col">
|
||||||
<MDXProvider components={MDXComponents}>
|
<MDXProvider components={MDXComponents}>
|
||||||
{renderRoutes(route.routes, {docsMetadata})}
|
{renderRoutes(route.routes)}
|
||||||
</MDXProvider>
|
</MDXProvider>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,33 +9,28 @@ import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
|
||||||
function DocLegacyPaginator(props) {
|
function DocLegacyPaginator(props) {
|
||||||
const {
|
const {metadata} = props;
|
||||||
docsMetadata: {docs},
|
|
||||||
metadata,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="pagination-nav">
|
<nav className="pagination-nav">
|
||||||
<div className="pagination-nav__item">
|
<div className="pagination-nav__item">
|
||||||
{metadata.previous && docs[metadata.previous] && (
|
{metadata.previous && (
|
||||||
<Link
|
<Link
|
||||||
className="pagination-nav__link"
|
className="pagination-nav__link"
|
||||||
to={docs[metadata.previous].permalink}>
|
to={metadata.previous.permalink}>
|
||||||
<h5 className="pagination-nav__link--sublabel">Previous</h5>
|
<h5 className="pagination-nav__link--sublabel">Previous</h5>
|
||||||
<h4 className="pagination-nav__link--label">
|
<h4 className="pagination-nav__link--label">
|
||||||
« {metadata.previous_title}
|
« {metadata.previous.title}
|
||||||
</h4>
|
</h4>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="pagination-nav__item pagination-nav__item--next">
|
<div className="pagination-nav__item pagination-nav__item--next">
|
||||||
{metadata.next && docs[metadata.next] && (
|
{metadata.next && (
|
||||||
<Link
|
<Link className="pagination-nav__link" to={metadata.next.permalink}>
|
||||||
className="pagination-nav__link"
|
|
||||||
to={docs[metadata.next].permalink}>
|
|
||||||
<h5 className="pagination-nav__link--sublabel">Next</h5>
|
<h5 className="pagination-nav__link--sublabel">Next</h5>
|
||||||
<h4 className="pagination-nav__link--label">
|
<h4 className="pagination-nav__link--label">
|
||||||
{metadata.next_title} »
|
{metadata.next.title} »
|
||||||
</h4>
|
</h4>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -16,35 +16,18 @@ const MOBILE_TOGGLE_SIZE = 24;
|
||||||
|
|
||||||
function DocLegacySidebar(props) {
|
function DocLegacySidebar(props) {
|
||||||
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
||||||
const {docsMetadata, sidebar} = props;
|
const {docsSidebars, sidebar} = props;
|
||||||
|
|
||||||
if (!sidebar) {
|
if (!sidebar) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thisSidebar = docsMetadata.docsSidebars[sidebar];
|
const thisSidebar = docsSidebars[sidebar];
|
||||||
|
|
||||||
if (!thisSidebar) {
|
if (!thisSidebar) {
|
||||||
throw new Error(`Can not find ${sidebar} config`);
|
throw new Error(`Can not find ${sidebar} config`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertDocLink = item => {
|
|
||||||
const linkID = item.id;
|
|
||||||
const linkMetadata = docsMetadata.docs[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 renderItem = item => {
|
const renderItem = item => {
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'category':
|
case 'category':
|
||||||
|
@ -58,6 +41,7 @@ function DocLegacySidebar(props) {
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'link':
|
case 'link':
|
||||||
|
default:
|
||||||
return (
|
return (
|
||||||
<li className="menu__list-item" key={item.label}>
|
<li className="menu__list-item" key={item.label}>
|
||||||
<Link
|
<Link
|
||||||
|
@ -71,10 +55,6 @@ function DocLegacySidebar(props) {
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'ref':
|
|
||||||
default:
|
|
||||||
return renderItem(convertDocLink(item));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue