mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-18 02:32:28 +02:00
refactor(v2): add typing for docs plugin (#1811)
* refactor(v2): add typing for docs plugin * nits
This commit is contained in:
parent
f671e6b437
commit
1591128cdd
25 changed files with 304 additions and 131 deletions
|
@ -14,3 +14,4 @@ packages/docusaurus-utils/lib/
|
||||||
packages/docusaurus/lib/
|
packages/docusaurus/lib/
|
||||||
packages/docusaurus-init/lib/
|
packages/docusaurus-init/lib/
|
||||||
packages/docusaurus-plugin-content-blog/lib/
|
packages/docusaurus-plugin-content-blog/lib/
|
||||||
|
packages/docusaurus-plugin-content-docs-legacy/lib/
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@ packages/docusaurus-utils/lib/
|
||||||
packages/docusaurus/lib/
|
packages/docusaurus/lib/
|
||||||
packages/docusaurus-init/lib/
|
packages/docusaurus-init/lib/
|
||||||
packages/docusaurus-plugin-content-blog/lib/
|
packages/docusaurus-plugin-content-blog/lib/
|
||||||
|
packages/docusaurus-plugin-content-docs-legacy/lib/
|
||||||
|
|
|
@ -6,3 +6,4 @@ packages/docusaurus-utils/lib/
|
||||||
packages/docusaurus/lib/
|
packages/docusaurus/lib/
|
||||||
packages/docusaurus-init/lib/
|
packages/docusaurus-init/lib/
|
||||||
packages/docusaurus-plugin-content-blog/lib/
|
packages/docusaurus-plugin-content-blog/lib/
|
||||||
|
packages/docusaurus-plugin-content-docs-legacy/lib/
|
||||||
|
|
|
@ -18,6 +18,7 @@ module.exports = {
|
||||||
'/packages/docusaurus/lib',
|
'/packages/docusaurus/lib',
|
||||||
'/packages/docusaurus-utils/lib',
|
'/packages/docusaurus-utils/lib',
|
||||||
'/packages/docusaurus-plugin-content-blog/lib',
|
'/packages/docusaurus-plugin-content-blog/lib',
|
||||||
|
'/packages/docusaurus-plugin-content-docs-legacy/lib',
|
||||||
],
|
],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.[jt]sx?$': 'babel-jest',
|
'^.+\\.[jt]sx?$': 'babel-jest',
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"@types/fs-extra": "8.0.0",
|
"@types/fs-extra": "8.0.0",
|
||||||
"@types/inquirer": "^6.0.3",
|
"@types/inquirer": "^6.0.3",
|
||||||
"@types/jest": "^24.0.15",
|
"@types/jest": "^24.0.15",
|
||||||
|
"@types/loader-utils": "^1.1.3",
|
||||||
"@types/lodash": "^4.14.136",
|
"@types/lodash": "^4.14.136",
|
||||||
"@types/lodash.kebabcase": "^4.1.6",
|
"@types/lodash.kebabcase": "^4.1.6",
|
||||||
"@types/node": "^12.0.2",
|
"@types/node": "^12.0.2",
|
||||||
|
|
|
@ -2,17 +2,23 @@
|
||||||
"name": "@docusaurus/plugin-content-docs-legacy",
|
"name": "@docusaurus/plugin-content-docs-legacy",
|
||||||
"version": "2.0.0-alpha.25",
|
"version": "2.0.0-alpha.25",
|
||||||
"description": "Documentation plugin for legacy v1 Docusaurus docs",
|
"description": "Documentation plugin for legacy v1 Docusaurus docs",
|
||||||
"main": "src/index.js",
|
"main": "lib/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"tsc": "tsc"
|
||||||
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@docusaurus/types": "^2.0.0-alpha.25"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/mdx-loader": "^2.0.0-alpha.25",
|
"@docusaurus/mdx-loader": "^2.0.0-alpha.25",
|
||||||
"@docusaurus/utils": "^2.0.0-alpha.25",
|
"@docusaurus/utils": "^2.0.0-alpha.25",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"globby": "^10.0.1",
|
"globby": "^10.0.1",
|
||||||
"import-fresh": "^3.0.0",
|
"import-fresh": "^3.1.0",
|
||||||
"loader-utils": "^1.2.3"
|
"loader-utils": "^1.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import pluginContentDocs from '../index';
|
import pluginContentDocs from '../index';
|
||||||
|
import {LoadContext} from '@docusaurus/types';
|
||||||
|
|
||||||
describe('loadDocs', () => {
|
describe('loadDocs', () => {
|
||||||
test('simple website', async () => {
|
test('simple website', async () => {
|
||||||
|
@ -16,18 +17,16 @@ describe('loadDocs', () => {
|
||||||
baseUrl: '/',
|
baseUrl: '/',
|
||||||
url: 'https://docusaurus.io',
|
url: 'https://docusaurus.io',
|
||||||
};
|
};
|
||||||
|
const context = {
|
||||||
|
siteDir,
|
||||||
|
siteConfig,
|
||||||
|
} as LoadContext;
|
||||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||||
const pluginPath = 'docs';
|
const pluginPath = 'docs';
|
||||||
const plugin = pluginContentDocs(
|
const plugin = pluginContentDocs(context, {
|
||||||
{
|
path: 'docs',
|
||||||
siteDir,
|
sidebarPath,
|
||||||
siteConfig,
|
});
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
sidebarPath,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const {docs: docsMetadata} = await plugin.loadContent();
|
const {docs: docsMetadata} = await plugin.loadContent();
|
||||||
|
|
||||||
expect(docsMetadata.hello).toEqual({
|
expect(docsMetadata.hello).toEqual({
|
|
@ -5,38 +5,49 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const globby = require('globby');
|
import globby from 'globby';
|
||||||
const fs = require('fs');
|
import fs from 'fs-extra';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const {idx, normalizeUrl, docuHash} = require('@docusaurus/utils');
|
import {idx, normalizeUrl, docuHash} from '@docusaurus/utils';
|
||||||
|
|
||||||
const createOrder = require('./order');
|
import createOrder from './order';
|
||||||
const loadSidebars = require('./sidebars');
|
import loadSidebars from './sidebars';
|
||||||
const processMetadata = require('./metadata');
|
import processMetadata from './metadata';
|
||||||
|
import {LoadContext, Plugin, DocusaurusConfig} from '@docusaurus/types';
|
||||||
|
import {
|
||||||
|
PluginOptions,
|
||||||
|
Sidebar,
|
||||||
|
Order,
|
||||||
|
Metadata,
|
||||||
|
DocsMetadata,
|
||||||
|
LoadedContent,
|
||||||
|
SourceToPermalink,
|
||||||
|
PermalinkToId,
|
||||||
|
} from './types';
|
||||||
|
import {Configuration} from 'webpack';
|
||||||
|
|
||||||
const DEFAULT_OPTIONS = {
|
const DEFAULT_OPTIONS: PluginOptions = {
|
||||||
path: 'docs', // Path to data on filesystem, relative to site dir.
|
path: 'docs', // Path to data on filesystem, relative to site dir.
|
||||||
routeBasePath: 'docs', // URL Route.
|
routeBasePath: 'docs', // URL Route.
|
||||||
include: ['**/*.md', '**/*.mdx'], // Extensions to include.
|
include: ['**/*.md', '**/*.mdx'], // Extensions to include.
|
||||||
// TODO: Change format to array.
|
|
||||||
sidebarPath: '', // Path to sidebar configuration for showing a list of markdown pages.
|
sidebarPath: '', // Path to sidebar configuration for showing a list of markdown pages.
|
||||||
// TODO: Settle themeing.
|
|
||||||
docLayoutComponent: '@theme/DocLegacyPage',
|
docLayoutComponent: '@theme/DocLegacyPage',
|
||||||
docItemComponent: '@theme/DocLegacyItem',
|
docItemComponent: '@theme/DocLegacyItem',
|
||||||
remarkPlugins: [],
|
remarkPlugins: [],
|
||||||
rehypePlugins: [],
|
rehypePlugins: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function(context, opts) {
|
export default function pluginContentDocs(
|
||||||
|
context: LoadContext,
|
||||||
|
opts: Partial<PluginOptions>,
|
||||||
|
): Plugin<LoadedContent | null> {
|
||||||
const options = {...DEFAULT_OPTIONS, ...opts};
|
const options = {...DEFAULT_OPTIONS, ...opts};
|
||||||
const contentPath = path.resolve(context.siteDir, options.path);
|
const contentPath = path.resolve(context.siteDir, options.path);
|
||||||
let globalContents = {};
|
let sourceToPermalink: SourceToPermalink = {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'docusaurus-plugin-content-docs',
|
name: 'docusaurus-plugin-content-docs',
|
||||||
|
|
||||||
contentPath,
|
|
||||||
|
|
||||||
getPathsToWatch() {
|
getPathsToWatch() {
|
||||||
const {include = []} = options;
|
const {include = []} = options;
|
||||||
const globPattern = include.map(pattern => `${contentPath}/${pattern}`);
|
const globPattern = include.map(pattern => `${contentPath}/${pattern}`);
|
||||||
|
@ -53,13 +64,13 @@ module.exports = function(context, opts) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const docsSidebars = loadSidebars(sidebarPath);
|
const docsSidebars: 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 = createOrder(docsSidebars);
|
const order: Order = createOrder(docsSidebars);
|
||||||
|
|
||||||
// Prepare metadata container.
|
// Prepare metadata container.
|
||||||
const docs = {};
|
const docs: DocsMetadata = {};
|
||||||
|
|
||||||
// Metadata for default docs files.
|
// Metadata for default docs files.
|
||||||
const docsFiles = await globby(include, {
|
const docsFiles = await globby(include, {
|
||||||
|
@ -67,7 +78,7 @@ module.exports = function(context, opts) {
|
||||||
});
|
});
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
docsFiles.map(async source => {
|
docsFiles.map(async source => {
|
||||||
const metadata = await processMetadata(
|
const metadata: Metadata = await processMetadata(
|
||||||
source,
|
source,
|
||||||
docsDir,
|
docsDir,
|
||||||
order,
|
order,
|
||||||
|
@ -93,22 +104,19 @@ module.exports = function(context, opts) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const sourceToPermalink = {};
|
const permalinkToId: PermalinkToId = {};
|
||||||
const permalinkToId = {};
|
|
||||||
Object.values(docs).forEach(({id, source, permalink}) => {
|
Object.values(docs).forEach(({id, source, permalink}) => {
|
||||||
sourceToPermalink[source] = permalink;
|
sourceToPermalink[source] = permalink;
|
||||||
permalinkToId[permalink] = id;
|
permalinkToId[permalink] = id;
|
||||||
});
|
});
|
||||||
|
|
||||||
globalContents = {
|
return {
|
||||||
docs,
|
docs,
|
||||||
docsDir,
|
docsDir,
|
||||||
docsSidebars,
|
docsSidebars,
|
||||||
sourceToPermalink,
|
sourceToPermalink,
|
||||||
permalinkToId,
|
permalinkToId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalContents;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async contentLoaded({content, actions}) {
|
async contentLoaded({content, actions}) {
|
||||||
|
@ -138,7 +146,7 @@ module.exports = function(context, opts) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const docsBaseRoute = normalizeUrl([
|
const docsBaseRoute = normalizeUrl([
|
||||||
context.siteConfig.baseUrl,
|
(context.siteConfig as DocusaurusConfig).baseUrl,
|
||||||
routeBasePath,
|
routeBasePath,
|
||||||
]);
|
]);
|
||||||
const docsMetadataPath = await createData(
|
const docsMetadataPath = await createData(
|
||||||
|
@ -156,7 +164,8 @@ module.exports = function(context, opts) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
configureWebpack(config, isServer, {getBabelLoader, getCacheLoader}) {
|
configureWebpack(_, isServer, utils) {
|
||||||
|
const {getBabelLoader, getCacheLoader} = utils;
|
||||||
const {rehypePlugins, remarkPlugins} = options;
|
const {rehypePlugins, remarkPlugins} = options;
|
||||||
return {
|
return {
|
||||||
module: {
|
module: {
|
||||||
|
@ -179,15 +188,15 @@ module.exports = function(context, opts) {
|
||||||
options: {
|
options: {
|
||||||
siteConfig: context.siteConfig,
|
siteConfig: context.siteConfig,
|
||||||
siteDir: context.siteDir,
|
siteDir: context.siteDir,
|
||||||
docsDir: globalContents.docsDir,
|
docsDir: contentPath,
|
||||||
sourceToPermalink: globalContents.sourceToPermalink,
|
sourceToPermalink: sourceToPermalink,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
} as Configuration;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
}
|
|
@ -5,11 +5,12 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const {getOptions} = require('loader-utils');
|
import {getOptions} from 'loader-utils';
|
||||||
const {resolve} = require('url');
|
import {resolve} from 'url';
|
||||||
|
import {loader} from 'webpack';
|
||||||
|
|
||||||
module.exports = async function(fileString) {
|
export = function(fileString: string) {
|
||||||
const callback = this.async();
|
const callback = this.async();
|
||||||
const options = Object.assign({}, getOptions(this), {
|
const options = Object.assign({}, getOptions(this), {
|
||||||
filepath: this.resourcePath,
|
filepath: this.resourcePath,
|
||||||
|
@ -17,7 +18,7 @@ module.exports = async function(fileString) {
|
||||||
const {docsDir, siteDir, sourceToPermalink} = options;
|
const {docsDir, siteDir, sourceToPermalink} = options;
|
||||||
|
|
||||||
// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
|
// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
|
||||||
let sourceDir;
|
let sourceDir: string | undefined;
|
||||||
const thisSource = this.resourcePath;
|
const thisSource = this.resourcePath;
|
||||||
if (thisSource.startsWith(docsDir)) {
|
if (thisSource.startsWith(docsDir)) {
|
||||||
sourceDir = docsDir;
|
sourceDir = docsDir;
|
||||||
|
@ -44,7 +45,7 @@ module.exports = async function(fileString) {
|
||||||
// Replace it to correct html link.
|
// Replace it to correct html link.
|
||||||
const mdLink = mdMatch[1];
|
const mdLink = mdMatch[1];
|
||||||
const targetSource = `${sourceDir}/${mdLink}`;
|
const targetSource = `${sourceDir}/${mdLink}`;
|
||||||
const aliasedSource = source =>
|
const aliasedSource = (source: string) =>
|
||||||
`@site/${path.relative(siteDir, source)}`;
|
`@site/${path.relative(siteDir, source)}`;
|
||||||
const permalink =
|
const permalink =
|
||||||
sourceToPermalink[aliasedSource(resolve(thisSource, mdLink))] ||
|
sourceToPermalink[aliasedSource(resolve(thisSource, mdLink))] ||
|
||||||
|
@ -59,5 +60,5 @@ module.exports = async function(fileString) {
|
||||||
content = lines.join('\n');
|
content = lines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback(null, content);
|
return callback && callback(null, content);
|
||||||
};
|
} as loader.Loader;
|
|
@ -5,18 +5,20 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
import fs from 'fs-extra';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const {parse, normalizeUrl} = require('@docusaurus/utils');
|
import {parse, normalizeUrl} from '@docusaurus/utils';
|
||||||
|
import {Order, MetadataRaw} from './types';
|
||||||
|
import {DocusaurusConfig} from '@docusaurus/types';
|
||||||
|
|
||||||
module.exports = async function processMetadata(
|
export default async function processMetadata(
|
||||||
source,
|
source: string,
|
||||||
docsDir,
|
docsDir: string,
|
||||||
order,
|
order: Order,
|
||||||
siteConfig,
|
siteConfig: Partial<DocusaurusConfig>,
|
||||||
docsBasePath,
|
docsBasePath: string,
|
||||||
siteDir,
|
siteDir: string,
|
||||||
) {
|
): Promise<MetadataRaw> {
|
||||||
const filepath = path.join(docsDir, source);
|
const filepath = path.join(docsDir, source);
|
||||||
|
|
||||||
const fileString = await fs.readFile(filepath, 'utf-8');
|
const fileString = await fs.readFile(filepath, 'utf-8');
|
||||||
|
@ -82,5 +84,5 @@ module.exports = async function processMetadata(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata;
|
return metadata as MetadataRaw;
|
||||||
};
|
}
|
|
@ -5,24 +5,42 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Sidebar,
|
||||||
|
SidebarItem,
|
||||||
|
SidebarItemDoc,
|
||||||
|
SidebarItemCategory,
|
||||||
|
Order,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
// Build the docs meta such as next, previous, category and sidebar.
|
// Build the docs meta such as next, previous, category and sidebar.
|
||||||
module.exports = function createOrder(allSidebars = {}) {
|
export default function createOrder(allSidebars: Sidebar = {}): Order {
|
||||||
const order = {};
|
const order: Order = {};
|
||||||
|
|
||||||
Object.keys(allSidebars).forEach(sidebarId => {
|
Object.keys(allSidebars).forEach(sidebarId => {
|
||||||
const sidebar = allSidebars[sidebarId];
|
const sidebar = allSidebars[sidebarId];
|
||||||
|
|
||||||
const ids = [];
|
const ids: string[] = [];
|
||||||
const categoryOrder = [];
|
const categoryOrder: (string | undefined)[] = [];
|
||||||
const subCategoryOrder = [];
|
const subCategoryOrder: (string | undefined)[] = [];
|
||||||
const indexItems = ({items, categoryLabel, subCategoryLabel}) => {
|
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.items,
|
items: (item as SidebarItemCategory).items,
|
||||||
categoryLabel: categoryLabel || item.label,
|
categoryLabel:
|
||||||
subCategoryLabel: categoryLabel && item.label,
|
categoryLabel || (item as SidebarItemCategory).label,
|
||||||
|
subCategoryLabel:
|
||||||
|
categoryLabel && (item as SidebarItemCategory).label,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'ref':
|
case 'ref':
|
||||||
|
@ -30,7 +48,7 @@ module.exports = function createOrder(allSidebars = {}) {
|
||||||
// Refs and links should not be shown in navigation.
|
// Refs and links should not be shown in navigation.
|
||||||
break;
|
break;
|
||||||
case 'doc':
|
case 'doc':
|
||||||
ids.push(item.id);
|
ids.push((item as SidebarItemDoc).id);
|
||||||
categoryOrder.push(categoryLabel);
|
categoryOrder.push(categoryLabel);
|
||||||
subCategoryOrder.push(subCategoryLabel);
|
subCategoryOrder.push(subCategoryLabel);
|
||||||
break;
|
break;
|
||||||
|
@ -69,4 +87,4 @@ module.exports = function createOrder(allSidebars = {}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return order;
|
return order;
|
||||||
};
|
}
|
|
@ -5,16 +5,20 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const importFresh = require('import-fresh');
|
import importFresh from 'import-fresh';
|
||||||
|
import {
|
||||||
|
SidebarItemCategory,
|
||||||
|
Sidebar,
|
||||||
|
SidebarRaw,
|
||||||
|
SidebarItem,
|
||||||
|
SidebarItemCategoryRaw,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that item contains only allowed keys
|
* Check that item contains only allowed keys
|
||||||
*
|
|
||||||
* @param {Object} item
|
|
||||||
* @param {Array<string>} keys
|
|
||||||
*/
|
*/
|
||||||
function assertItem(item, keys) {
|
function assertItem(item: Object, keys: string[]): void {
|
||||||
const unknownKeys = Object.keys(item).filter(
|
const unknownKeys = Object.keys(item).filter(
|
||||||
key => !keys.includes(key) && key !== 'type',
|
key => !keys.includes(key) && key !== 'type',
|
||||||
);
|
);
|
||||||
|
@ -31,13 +35,11 @@ function assertItem(item, keys) {
|
||||||
/**
|
/**
|
||||||
* Normalizes recursively category and all its children. Ensures, that at the end
|
* Normalizes recursively category and all its children. Ensures, that at the end
|
||||||
* each item will be an object with the corresponding type
|
* each item will be an object with the corresponding type
|
||||||
*
|
|
||||||
* @param {Array<Object>} category
|
|
||||||
* @param {number} [level=0]
|
|
||||||
*
|
|
||||||
* @return {Array<Object>}
|
|
||||||
*/
|
*/
|
||||||
function normalizeCategory(category, level = 0) {
|
function normalizeCategory(
|
||||||
|
category: SidebarItemCategoryRaw,
|
||||||
|
level = 0,
|
||||||
|
): SidebarItemCategory {
|
||||||
if (level === 2) {
|
if (level === 2) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Can not process ${
|
`Can not process ${
|
||||||
|
@ -54,33 +56,32 @@ function normalizeCategory(category, level = 0) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = category.items.map(item => {
|
const items: SidebarItem[] = category.items.map(item => {
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
return {
|
||||||
|
type: 'doc',
|
||||||
|
id: item,
|
||||||
|
};
|
||||||
|
}
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'category':
|
case 'category':
|
||||||
return normalizeCategory(item, level + 1);
|
return normalizeCategory(item as SidebarItemCategoryRaw, level + 1);
|
||||||
case 'link':
|
case 'link':
|
||||||
assertItem(item, ['href', 'label']);
|
assertItem(item, ['href', 'label']);
|
||||||
break;
|
break;
|
||||||
case 'ref':
|
case 'ref':
|
||||||
assertItem(item, ['id', 'label']);
|
assertItem(item, ['id']);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (typeof item === 'string') {
|
|
||||||
return {
|
|
||||||
type: 'doc',
|
|
||||||
id: item,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type !== 'doc') {
|
if (item.type !== 'doc') {
|
||||||
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertItem(item, ['id', 'label']);
|
assertItem(item, ['id']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item as SidebarItem;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {...category, items};
|
return {...category, items};
|
||||||
|
@ -88,35 +89,36 @@ function normalizeCategory(category, level = 0) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts sidebars object to mapping to arrays of sidebar item objects
|
* Converts sidebars object to mapping to arrays of sidebar item objects
|
||||||
*
|
|
||||||
* @param {{[key: string]: Object}} sidebars
|
|
||||||
*
|
|
||||||
* @return {{[key: string]: Array<Object>}}
|
|
||||||
*/
|
*/
|
||||||
function normalizeSidebar(sidebars) {
|
function normalizeSidebar(sidebars: SidebarRaw): Sidebar {
|
||||||
return Object.entries(sidebars).reduce((acc, [sidebarId, sidebar]) => {
|
return Object.entries(sidebars).reduce(
|
||||||
let normalizedSidebar = sidebar;
|
(acc: Sidebar, [sidebarId, sidebar]) => {
|
||||||
|
let normalizedSidebar: SidebarItemCategoryRaw[];
|
||||||
|
|
||||||
if (!Array.isArray(sidebar)) {
|
if (!Array.isArray(sidebar)) {
|
||||||
// convert sidebar to a more generic structure
|
// convert sidebar to a more generic structure
|
||||||
normalizedSidebar = Object.entries(sidebar).map(([label, items]) => ({
|
normalizedSidebar = Object.entries(sidebar).map(([label, items]) => ({
|
||||||
type: 'category',
|
type: 'category',
|
||||||
label,
|
label,
|
||||||
items,
|
items,
|
||||||
}));
|
}));
|
||||||
}
|
} else {
|
||||||
|
normalizedSidebar = sidebar;
|
||||||
|
}
|
||||||
|
|
||||||
acc[sidebarId] = normalizedSidebar.map(item => normalizeCategory(item));
|
acc[sidebarId] = normalizedSidebar.map(item => normalizeCategory(item));
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function loadSidebars(sidebarPath) {
|
export default function loadSidebars(sidebarPath: string): Sidebar {
|
||||||
// We don't want sidebars to be cached because of hotreloading.
|
// We don't want sidebars to be cached because of hotreloading.
|
||||||
let allSidebars = {};
|
let allSidebars: SidebarRaw = {};
|
||||||
if (sidebarPath && fs.existsSync(sidebarPath)) {
|
if (sidebarPath && fs.existsSync(sidebarPath)) {
|
||||||
allSidebars = importFresh(sidebarPath);
|
allSidebars = importFresh(sidebarPath) as SidebarRaw;
|
||||||
}
|
}
|
||||||
return normalizeSidebar(allSidebars);
|
return normalizeSidebar(allSidebars);
|
||||||
};
|
}
|
105
packages/docusaurus-plugin-content-docs-legacy/src/types.ts
Normal file
105
packages/docusaurus-plugin-content-docs-legacy/src/types.ts
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
export interface PluginOptions {
|
||||||
|
path: string;
|
||||||
|
routeBasePath: string;
|
||||||
|
include: string[];
|
||||||
|
sidebarPath: string;
|
||||||
|
docLayoutComponent: string;
|
||||||
|
docItemComponent: string;
|
||||||
|
remarkPlugins: string[];
|
||||||
|
rehypePlugins: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SidebarItemDoc = {
|
||||||
|
type: string;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface SidebarItemLink {
|
||||||
|
type: string;
|
||||||
|
href: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarItemCategory {
|
||||||
|
type: string;
|
||||||
|
label: string;
|
||||||
|
items: SidebarItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarItemCategoryRaw {
|
||||||
|
type: string;
|
||||||
|
label: string;
|
||||||
|
items: SidebarItemRaw[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SidebarItem =
|
||||||
|
| SidebarItemDoc
|
||||||
|
| SidebarItemLink
|
||||||
|
| SidebarItemCategory;
|
||||||
|
export type SidebarItemRaw =
|
||||||
|
| string
|
||||||
|
| SidebarItemDoc
|
||||||
|
| SidebarItemLink
|
||||||
|
| SidebarItemCategoryRaw;
|
||||||
|
|
||||||
|
// Sidebar given by user that is not normalized yet. e.g: sidebars.json
|
||||||
|
export interface SidebarRaw {
|
||||||
|
[sidebarId: string]: {
|
||||||
|
[sidebarCategory: string]: SidebarItemRaw[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Sidebar {
|
||||||
|
[sidebarId: string]: SidebarItemCategory[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderMetadata {
|
||||||
|
previous?: string;
|
||||||
|
next?: string;
|
||||||
|
sidebar?: string;
|
||||||
|
category?: string;
|
||||||
|
subCategory?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Order {
|
||||||
|
[id: string]: OrderMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MetadataRaw extends OrderMetadata {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
source: string;
|
||||||
|
permalink: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Metadata extends MetadataRaw {
|
||||||
|
previous_title?: string;
|
||||||
|
next_title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocsMetadata {
|
||||||
|
[id: string]: Metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SourceToPermalink {
|
||||||
|
[source: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PermalinkToId {
|
||||||
|
[permalink: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadedContent {
|
||||||
|
docs: DocsMetadata;
|
||||||
|
docsDir: string;
|
||||||
|
docsSidebars: Sidebar;
|
||||||
|
sourceToPermalink: SourceToPermalink;
|
||||||
|
permalinkToId: PermalinkToId;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"incremental": true,
|
||||||
|
"tsBuildInfoFile": "./lib/.tsbuildinfo",
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "lib",
|
||||||
|
}
|
||||||
|
}
|
8
packages/docusaurus-types/src/index.d.ts
vendored
8
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -57,7 +57,7 @@ export interface PluginContentLoadedActions {
|
||||||
|
|
||||||
export interface Plugin<T> {
|
export interface Plugin<T> {
|
||||||
name: string;
|
name: string;
|
||||||
loadContent?(): T;
|
loadContent?(): Promise<T>;
|
||||||
contentLoaded?({
|
contentLoaded?({
|
||||||
content,
|
content,
|
||||||
actions,
|
actions,
|
||||||
|
@ -67,7 +67,11 @@ export interface Plugin<T> {
|
||||||
}): void;
|
}): void;
|
||||||
postBuild?(props: Props): void;
|
postBuild?(props: Props): void;
|
||||||
postStart?(props: Props): void;
|
postStart?(props: Props): void;
|
||||||
configureWebpack?(config: Configuration, isServer: boolean): Configuration;
|
configureWebpack?(
|
||||||
|
config: Configuration,
|
||||||
|
isServer: boolean,
|
||||||
|
utils: ConfigureWebpackUtils,
|
||||||
|
): Configuration;
|
||||||
getThemePath?(): string;
|
getThemePath?(): string;
|
||||||
getPathsToWatch?(): string[];
|
getPathsToWatch?(): string[];
|
||||||
getClientModules?(): string[];
|
getClientModules?(): string[];
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"globby": "^10.0.1",
|
"globby": "^10.0.1",
|
||||||
"html-webpack-plugin": "^4.0.0-beta.8",
|
"html-webpack-plugin": "^4.0.0-beta.8",
|
||||||
"import-fresh": "^3.0.0",
|
"import-fresh": "^3.1.0",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"mini-css-extract-plugin": "^0.8.0",
|
"mini-css-extract-plugin": "^0.8.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
|
|
@ -17,7 +17,7 @@ export async function swizzle(
|
||||||
themeName: string,
|
themeName: string,
|
||||||
componentName?: string,
|
componentName?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const plugin = importFresh(themeName);
|
const plugin: any = importFresh(themeName);
|
||||||
const pluginInstance = plugin({siteDir});
|
const pluginInstance = plugin({siteDir});
|
||||||
let fromPath = pluginInstance.getThemePath();
|
let fromPath = pluginInstance.getThemePath();
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ export function loadConfig(siteDir: string): DocusaurusConfig {
|
||||||
if (!fs.existsSync(configPath)) {
|
if (!fs.existsSync(configPath)) {
|
||||||
throw new Error(`${CONFIG_FILE_NAME} not found`);
|
throw new Error(`${CONFIG_FILE_NAME} not found`);
|
||||||
}
|
}
|
||||||
const loadedConfig = importFresh(configPath);
|
const loadedConfig = importFresh(configPath) as Partial<DocusaurusConfig>;
|
||||||
const missingFields = REQUIRED_FIELDS.filter(
|
const missingFields = REQUIRED_FIELDS.filter(
|
||||||
field => !_.has(loadedConfig, field),
|
field => !_.has(loadedConfig, field),
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,10 @@ export function loadConfig(siteDir: string): DocusaurusConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge default config with loaded config.
|
// Merge default config with loaded config.
|
||||||
const config: DocusaurusConfig = {...DEFAULT_CONFIG, ...loadedConfig};
|
const config: DocusaurusConfig = {
|
||||||
|
...DEFAULT_CONFIG,
|
||||||
|
...loadedConfig,
|
||||||
|
} as DocusaurusConfig;
|
||||||
|
|
||||||
// Don't allow unrecognized fields.
|
// Don't allow unrecognized fields.
|
||||||
const allowedFields = [...REQUIRED_FIELDS, ...OPTIONAL_FIELDS];
|
const allowedFields = [...REQUIRED_FIELDS, ...OPTIONAL_FIELDS];
|
||||||
|
|
|
@ -49,7 +49,7 @@ export async function loadPlugins({
|
||||||
}
|
}
|
||||||
|
|
||||||
// module is any valid module identifier - npm package or locally-resolved path.
|
// module is any valid module identifier - npm package or locally-resolved path.
|
||||||
const pluginModule = importFresh(pluginModuleImport);
|
const pluginModule: any = importFresh(pluginModuleImport);
|
||||||
return (pluginModule.default || pluginModule)(context, pluginOptions);
|
return (pluginModule.default || pluginModule)(context, pluginOptions);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,9 +32,11 @@ export function loadPresets(
|
||||||
} else if (Array.isArray(presetItem)) {
|
} else if (Array.isArray(presetItem)) {
|
||||||
presetModuleImport = presetItem[0];
|
presetModuleImport = presetItem[0];
|
||||||
presetOptions = presetItem[1] || {};
|
presetOptions = presetItem[1] || {};
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid presets format detected in config.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const presetModule = importFresh(presetModuleImport);
|
const presetModule: any = importFresh(presetModuleImport);
|
||||||
const preset: Preset = (presetModule.default || presetModule)(
|
const preset: Preset = (presetModule.default || presetModule)(
|
||||||
context,
|
context,
|
||||||
presetOptions,
|
presetOptions,
|
||||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -2494,6 +2494,14 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
|
||||||
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
|
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
|
||||||
|
|
||||||
|
"@types/loader-utils@^1.1.3":
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-1.1.3.tgz#82b9163f2ead596c68a8c03e450fbd6e089df401"
|
||||||
|
integrity sha512-euKGFr2oCB3ASBwG39CYJMR3N9T0nanVqXdiH7Zu/Nqddt6SmFRxytq/i2w9LQYNQekEtGBz+pE3qG6fQTNvRg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/webpack" "*"
|
||||||
|
|
||||||
"@types/lodash.kebabcase@^4.1.6":
|
"@types/lodash.kebabcase@^4.1.6":
|
||||||
version "4.1.6"
|
version "4.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.6.tgz#07b07aeca6c0647836de46f87a3cdfff72166c8e"
|
resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.6.tgz#07b07aeca6c0647836de46f87a3cdfff72166c8e"
|
||||||
|
@ -8126,10 +8134,10 @@ import-fresh@^2.0.0:
|
||||||
caller-path "^2.0.0"
|
caller-path "^2.0.0"
|
||||||
resolve-from "^3.0.0"
|
resolve-from "^3.0.0"
|
||||||
|
|
||||||
import-fresh@^3.0.0:
|
import-fresh@^3.1.0:
|
||||||
version "3.0.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390"
|
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118"
|
||||||
integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==
|
integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
parent-module "^1.0.0"
|
parent-module "^1.0.0"
|
||||||
resolve-from "^4.0.0"
|
resolve-from "^4.0.0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue