mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 02:08:36 +02:00
test: improve test coverage (#6857)
This commit is contained in:
parent
edb4d00096
commit
f763ac13a9
22 changed files with 435 additions and 220 deletions
|
@ -22,6 +22,47 @@ Array [
|
|||
]
|
||||
`;
|
||||
|
||||
exports[`translateContent should fallback when translation is incomplete 1`] = `
|
||||
Object {
|
||||
"blogListPaginated": Array [
|
||||
Object {
|
||||
"items": Array [
|
||||
"hello",
|
||||
],
|
||||
"metadata": Object {
|
||||
"blogDescription": "Someone's random blog",
|
||||
"blogTitle": "My blog",
|
||||
"nextPage": null,
|
||||
"page": 1,
|
||||
"permalink": "/",
|
||||
"postsPerPage": 10,
|
||||
"previousPage": null,
|
||||
"totalCount": 1,
|
||||
"totalPages": 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
"blogPosts": Array [
|
||||
Object {
|
||||
"id": "hello",
|
||||
"metadata": Object {
|
||||
"date": 2021-07-19T00:00:00.000Z,
|
||||
"description": "/blog/2021/06/19/hello",
|
||||
"formattedDate": "June 19, 2021",
|
||||
"permalink": "/blog/2021/06/19/hello",
|
||||
"source": "/blog/2021/06/19/hello",
|
||||
"tags": Array [],
|
||||
"title": "Hello",
|
||||
"truncated": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"blogSidebarTitle": "All my posts",
|
||||
"blogTags": Object {},
|
||||
"blogTagsListPath": "/tags",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`translateContent should return translated loaded content matching snapshot 1`] = `
|
||||
Object {
|
||||
"blogListPaginated": Array [
|
||||
|
|
|
@ -77,6 +77,12 @@ describe('getContentTranslationFiles', () => {
|
|||
});
|
||||
|
||||
describe('translateContent', () => {
|
||||
test('should fallback when translation is incomplete', () => {
|
||||
expect(
|
||||
translateContent(sampleBlogContent, [{path: 'foo', content: {}}]),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should not translate anything if translation files are untranslated', () => {
|
||||
const translationFiles = getSampleTranslationFiles();
|
||||
expect(translateContent(sampleBlogContent, translationFiles)).toEqual(
|
||||
|
|
|
@ -53,9 +53,6 @@ export function translateContent(
|
|||
content: BlogContent,
|
||||
translationFiles: TranslationFiles,
|
||||
): BlogContent {
|
||||
if (translationFiles.length === 0) {
|
||||
return content;
|
||||
}
|
||||
const {content: optionsTranslations} = translationFiles[0]!;
|
||||
return {
|
||||
...content,
|
||||
|
|
|
@ -21,10 +21,6 @@ function getCategoryGeneratedIndexMetadata({
|
|||
}): CategoryGeneratedIndexMetadata {
|
||||
const {sidebarName, previous, next} =
|
||||
sidebarsUtils.getCategoryGeneratedIndexNavigation(category.link.permalink);
|
||||
if (!sidebarName) {
|
||||
throw new Error('unexpected');
|
||||
}
|
||||
|
||||
return {
|
||||
title: category.link.title ?? category.label,
|
||||
description: category.link.description,
|
||||
|
@ -32,7 +28,7 @@ function getCategoryGeneratedIndexMetadata({
|
|||
keywords: category.link.keywords,
|
||||
slug: category.link.slug,
|
||||
permalink: category.link.permalink,
|
||||
sidebar: sidebarName,
|
||||
sidebar: sidebarName!,
|
||||
previous: toNavigationLink(previous, docsById),
|
||||
next: toNavigationLink(next, docsById),
|
||||
};
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"foo": "bar"
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DefaultSidebarItemsGenerator generates complex nested sidebar 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"id": "intro",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "tutorial1",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "tutorial2",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Tutorials",
|
||||
"link": Object {
|
||||
"id": "tutorials-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"collapsed": false,
|
||||
"collapsible": undefined,
|
||||
"customProps": Object {
|
||||
"description": "foo",
|
||||
},
|
||||
"items": Array [
|
||||
Object {
|
||||
"className": "foo",
|
||||
"id": "guide1",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "nested-guide",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "SubGuides (metadata file label)",
|
||||
"link": Object {
|
||||
"description": "subguides-description",
|
||||
"slug": "subguides-generated-index-slug",
|
||||
"title": "subguides-title",
|
||||
"type": "generated-index",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"id": "guide2",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Guides",
|
||||
"link": Object {
|
||||
"id": "guides-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"id": "end",
|
||||
"type": "doc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DefaultSidebarItemsGenerator generates simple flat sidebar 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"id": "doc3",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc4",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc1",
|
||||
"label": "doc1 sidebar label",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc2",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc5",
|
||||
"type": "doc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DefaultSidebarItemsGenerator generates subfolder sidebar 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc8",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc7",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "subsubsubfolder3 (_category_.json label)",
|
||||
"link": Object {
|
||||
"id": "doc1",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"className": "bar",
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc6",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "subsubsubfolder2 (_category_.yml label)",
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"id": "doc1",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "doc4",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc5",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "subsubsubfolder",
|
||||
"type": "category",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DefaultSidebarItemsGenerator respects custom isCategoryIndex 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"id": "intro",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "tutorial1",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "tutorial2",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Tutorials",
|
||||
"link": Object {
|
||||
"id": "tutorials-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"className": "foo",
|
||||
"id": "guide1",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "guide2",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "not-guides-index",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Guides",
|
||||
"type": "category",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DefaultSidebarItemsGenerator uses explicit link over the index/readme.{md,mdx} naming convention 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "parent/doc2",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "parent/doc1",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Category label",
|
||||
"link": Object {
|
||||
"id": "parent/doc3",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
Object {
|
||||
"collapsed": undefined,
|
||||
"collapsible": undefined,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "parent/doc4",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "parent/doc6",
|
||||
"type": "doc",
|
||||
},
|
||||
Object {
|
||||
"id": "parent/doc5",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "Category 2 label",
|
||||
"type": "category",
|
||||
},
|
||||
]
|
||||
`;
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import {DefaultSidebarItemsGenerator} from '../generator';
|
||||
import type {Sidebar, SidebarItemsGenerator} from '../types';
|
||||
import type {SidebarItemsGenerator} from '../types';
|
||||
import {DefaultNumberPrefixParser} from '../../numberPrefix';
|
||||
import {isCategoryIndex} from '../../docs';
|
||||
|
||||
|
@ -104,13 +104,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'doc3'},
|
||||
{type: 'doc', id: 'doc4'},
|
||||
{type: 'doc', id: 'doc1', label: 'doc1 sidebar label'},
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{type: 'doc', id: 'doc5'},
|
||||
] as Sidebar);
|
||||
expect(sidebarSlice).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('generates complex nested sidebar', async () => {
|
||||
|
@ -214,49 +208,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'intro'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorials',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'tutorials-index',
|
||||
},
|
||||
items: [
|
||||
{type: 'doc', id: 'tutorial1'},
|
||||
{type: 'doc', id: 'tutorial2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Guides',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'guides-index',
|
||||
},
|
||||
customProps: {
|
||||
description: 'foo',
|
||||
},
|
||||
collapsed: false,
|
||||
items: [
|
||||
{type: 'doc', id: 'guide1', className: 'foo'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'SubGuides (metadata file label)',
|
||||
items: [{type: 'doc', id: 'nested-guide'}],
|
||||
link: {
|
||||
type: 'generated-index',
|
||||
slug: 'subguides-generated-index-slug',
|
||||
title: 'subguides-title',
|
||||
description: 'subguides-description',
|
||||
},
|
||||
},
|
||||
{type: 'doc', id: 'guide2'},
|
||||
],
|
||||
},
|
||||
{type: 'doc', id: 'end'},
|
||||
] as Sidebar);
|
||||
expect(sidebarSlice).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('generates subfolder sidebar', async () => {
|
||||
|
@ -352,33 +304,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{
|
||||
type: 'category',
|
||||
label: 'subsubsubfolder3 (_category_.json label)',
|
||||
link: {
|
||||
id: 'doc1',
|
||||
type: 'doc',
|
||||
},
|
||||
items: [
|
||||
{type: 'doc', id: 'doc8'},
|
||||
{type: 'doc', id: 'doc7'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'subsubsubfolder2 (_category_.yml label)',
|
||||
className: 'bar',
|
||||
items: [{type: 'doc', id: 'doc6'}],
|
||||
},
|
||||
{type: 'doc', id: 'doc1'},
|
||||
{type: 'doc', id: 'doc4'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'subsubsubfolder',
|
||||
items: [{type: 'doc', id: 'doc5'}],
|
||||
},
|
||||
] as Sidebar);
|
||||
expect(sidebarSlice).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('uses explicit link over the index/readme.{md,mdx} naming convention', async () => {
|
||||
|
@ -449,45 +375,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Category label',
|
||||
link: {
|
||||
id: 'parent/doc3',
|
||||
type: 'doc',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
id: 'parent/doc2',
|
||||
type: 'doc',
|
||||
},
|
||||
// doc1 is below doc2, because its file name is index.md
|
||||
{
|
||||
id: 'parent/doc1',
|
||||
type: 'doc',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Category 2 label',
|
||||
items: [
|
||||
{
|
||||
id: 'parent/doc4',
|
||||
type: 'doc',
|
||||
},
|
||||
{
|
||||
id: 'parent/doc6',
|
||||
type: 'doc',
|
||||
},
|
||||
{
|
||||
id: 'parent/doc5',
|
||||
type: 'doc',
|
||||
},
|
||||
],
|
||||
},
|
||||
] as Sidebar);
|
||||
expect(sidebarSlice).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('respects custom isCategoryIndex', async () => {
|
||||
|
@ -570,32 +458,49 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'intro'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorials',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'tutorials-index',
|
||||
expect(sidebarSlice).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('throws for unknown index link', async () => {
|
||||
const generateSidebar = () =>
|
||||
DefaultSidebarItemsGenerator({
|
||||
numberPrefixParser: DefaultNumberPrefixParser,
|
||||
isCategoryIndex,
|
||||
item: {
|
||||
type: 'autogenerated',
|
||||
dirName: '.',
|
||||
},
|
||||
items: [
|
||||
{type: 'doc', id: 'tutorial1'},
|
||||
{type: 'doc', id: 'tutorial2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Guides',
|
||||
items: [
|
||||
{type: 'doc', id: 'guide1', className: 'foo'},
|
||||
{type: 'doc', id: 'guide2'},
|
||||
version: {
|
||||
versionName: 'current',
|
||||
contentPath: '',
|
||||
},
|
||||
categoriesMetadata: {
|
||||
category: {
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'foo',
|
||||
},
|
||||
},
|
||||
},
|
||||
docs: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'not-guides-index',
|
||||
id: 'intro',
|
||||
unversionedId: 'intro',
|
||||
source: '@site/docs/category/intro.md',
|
||||
sourceDirName: 'category',
|
||||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
] as Sidebar);
|
||||
options: {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
},
|
||||
});
|
||||
|
||||
await expect(generateSidebar).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Can't find any doc with ID foo.
|
||||
Available doc IDs:
|
||||
- intro"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,7 +23,10 @@ describe('loadSidebars', () => {
|
|||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
version: {contentPath: 'docs/foo', contentPathLocalized: 'docs/foo'},
|
||||
version: {
|
||||
contentPath: path.join(fixtureDir, 'docs'),
|
||||
contentPathLocalized: path.join(fixtureDir, 'docs'),
|
||||
},
|
||||
categoryLabelSlugger: null,
|
||||
sidebarOptions: {sidebarCollapsed: true, sidebarCollapsible: true},
|
||||
};
|
||||
|
@ -107,4 +110,36 @@ describe('loadSidebars', () => {
|
|||
const result = await loadSidebars(sidebarPath, params);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('duplicate category metadata files', async () => {
|
||||
const sidebarPath = path.join(
|
||||
fixtureDir,
|
||||
'sidebars-collapsed-first-level.json',
|
||||
);
|
||||
const consoleWarnMock = jest
|
||||
.spyOn(console, 'warn')
|
||||
.mockImplementation(() => {});
|
||||
const consoleErrorMock = jest
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
await expect(() =>
|
||||
loadSidebars(sidebarPath, {
|
||||
...params,
|
||||
version: {
|
||||
contentPath: path.join(fixtureDir, 'invalid-docs'),
|
||||
contentPathLocalized: path.join(fixtureDir, 'invalid-docs'),
|
||||
},
|
||||
}),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not allowed"`);
|
||||
expect(consoleWarnMock).toBeCalledWith(
|
||||
expect.stringMatching(
|
||||
/.*\[WARNING].* There are more than one category metadata files for .*foo.*: foo\/_category_.json, foo\/_category_.yml. The behavior is undetermined./,
|
||||
),
|
||||
);
|
||||
expect(consoleErrorMock).toBeCalledWith(
|
||||
expect.stringMatching(
|
||||
/.*\[ERROR].* The docs sidebar category metadata file .*foo\/_category_.json.* looks invalid!/,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -60,9 +60,9 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|||
const doc = findDoc(docId);
|
||||
if (!doc) {
|
||||
throw new Error(
|
||||
`Can't find any doc with id=${docId}.\nAvailable doc ids:\n- ${Object.keys(
|
||||
docsById,
|
||||
).join('\n- ')}`,
|
||||
`Can't find any doc with ID ${docId}.
|
||||
Available doc IDs:
|
||||
- ${Object.keys(docsById).join('\n- ')}`,
|
||||
);
|
||||
}
|
||||
return doc;
|
||||
|
|
|
@ -258,11 +258,7 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
|
|||
const sidebarName = Object.entries(sidebarNameToNavigationItems).find(
|
||||
([, navigationItems]) =>
|
||||
navigationItems.find(isCurrentCategoryGeneratedIndexItem),
|
||||
)?.[0];
|
||||
|
||||
if (!sidebarName) {
|
||||
return emptySidebarNavigation();
|
||||
}
|
||||
)![0];
|
||||
const navigationItems = sidebarNameToNavigationItems[sidebarName]!;
|
||||
const currentItemIndex = navigationItems.findIndex(
|
||||
isCurrentCategoryGeneratedIndexItem,
|
||||
|
|
8
packages/docusaurus-types/src/index.d.ts
vendored
8
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -161,10 +161,7 @@ export type ImportedPresetModule = PresetModule & {
|
|||
default?: PresetModule;
|
||||
};
|
||||
|
||||
export type PresetConfig =
|
||||
| [string, Record<string, unknown>]
|
||||
| [string]
|
||||
| string;
|
||||
export type PresetConfig = string | [string, Record<string, unknown>];
|
||||
|
||||
export type HostPortCLIOptions = {
|
||||
host?: string;
|
||||
|
@ -356,9 +353,8 @@ export type ConfigurePostCssFn = Plugin<unknown>['configurePostCss'];
|
|||
export type PluginOptions = {id?: string} & Record<string, unknown>;
|
||||
|
||||
export type PluginConfig =
|
||||
| [string, PluginOptions]
|
||||
| [string]
|
||||
| string
|
||||
| [string, PluginOptions]
|
||||
| [PluginModule, PluginOptions]
|
||||
| PluginModule;
|
||||
|
||||
|
|
|
@ -55,7 +55,9 @@ function createPluginSchema(theme: boolean = false) {
|
|||
Joi.alternatives()
|
||||
.try(
|
||||
Joi.function(),
|
||||
Joi.array().ordered(Joi.function().required(), Joi.object().required()),
|
||||
Joi.array()
|
||||
.ordered(Joi.function().required(), Joi.object().required())
|
||||
.length(2),
|
||||
Joi.string(),
|
||||
Joi.array()
|
||||
.ordered(Joi.string().required(), Joi.object().required())
|
||||
|
|
|
@ -3,3 +3,7 @@ module.exports = function (context, options) {
|
|||
name: 'third-plugin',
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.validateThemeConfig = function ({validate, themeConfig}) {
|
||||
return {a: 1};
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@ describe('initPlugins', () => {
|
|||
expect(plugins[1].name).toBe('second-plugin');
|
||||
expect(plugins[2].name).toBe('third-plugin');
|
||||
expect(plugins[3].name).toBe('fourth-plugin');
|
||||
expect(context.siteConfig.themeConfig).toEqual({a: 1});
|
||||
});
|
||||
|
||||
test('plugins with bad values throw user-friendly error message', async () => {
|
||||
|
|
|
@ -89,7 +89,7 @@ export async function loadPlugins({
|
|||
// need to run in certain order or depend on others for data.
|
||||
const loadedPlugins: LoadedPlugin[] = await Promise.all(
|
||||
plugins.map(async (plugin) => {
|
||||
const content = plugin.loadContent ? await plugin.loadContent() : null;
|
||||
const content = await plugin.loadContent?.();
|
||||
return {...plugin, content};
|
||||
}),
|
||||
);
|
||||
|
@ -205,7 +205,7 @@ export async function loadPlugins({
|
|||
await Promise.all(
|
||||
contentLoadedTranslatedPlugins.map(async (plugin) => {
|
||||
if (!plugin.routesLoaded) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO remove this deprecated lifecycle soon
|
||||
|
@ -213,7 +213,7 @@ export async function loadPlugins({
|
|||
// TODO, 1 user reported usage of this lifecycle! https://github.com/facebook/docusaurus/issues/3918
|
||||
logger.error`Plugin code=${'routesLoaded'} lifecycle is deprecated. If you think we should keep this lifecycle, please report here: path=${'https://github.com/facebook/docusaurus/issues/3918'}`;
|
||||
|
||||
return plugin.routesLoaded(pluginsRouteConfigs);
|
||||
await plugin.routesLoaded(pluginsRouteConfigs);
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
@ -61,39 +61,29 @@ async function normalizePluginConfig(
|
|||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
// plugins: [
|
||||
// ['./plugin',options],
|
||||
// ]
|
||||
if (typeof pluginConfig[0] === 'string') {
|
||||
const pluginModuleImport = pluginConfig[0];
|
||||
const pluginPath = pluginRequire.resolve(pluginModuleImport);
|
||||
const pluginModule = importFresh<ImportedPluginModule>(pluginPath);
|
||||
return {
|
||||
plugin: pluginModule?.default ?? pluginModule,
|
||||
options: pluginConfig[1] ?? {},
|
||||
pluginModule: {
|
||||
path: pluginModuleImport,
|
||||
module: pluginModule,
|
||||
},
|
||||
};
|
||||
}
|
||||
// plugins: [
|
||||
// [function plugin() { },options],
|
||||
// ]
|
||||
if (typeof pluginConfig[0] === 'function') {
|
||||
return {
|
||||
plugin: pluginConfig[0],
|
||||
options: pluginConfig[1] ?? {},
|
||||
};
|
||||
}
|
||||
// plugins: [
|
||||
// ['./plugin',options],
|
||||
// ]
|
||||
if (typeof pluginConfig[0] === 'string') {
|
||||
const pluginModuleImport = pluginConfig[0];
|
||||
const pluginPath = pluginRequire.resolve(pluginModuleImport);
|
||||
const pluginModule = importFresh<ImportedPluginModule>(pluginPath);
|
||||
return {
|
||||
plugin: pluginModule?.default ?? pluginModule,
|
||||
options: pluginConfig[1],
|
||||
pluginModule: {
|
||||
path: pluginModuleImport,
|
||||
module: pluginModule,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unexpected: can't load plugin for following plugin config.\n${JSON.stringify(
|
||||
pluginConfig,
|
||||
)}`,
|
||||
);
|
||||
// plugins: [
|
||||
// [function plugin() { },options],
|
||||
// ]
|
||||
return {
|
||||
plugin: pluginConfig[0],
|
||||
options: pluginConfig[1],
|
||||
};
|
||||
}
|
||||
|
||||
export async function normalizePluginConfigs(
|
||||
|
@ -219,16 +209,9 @@ export default async function initPlugins({
|
|||
};
|
||||
}
|
||||
|
||||
const plugins: InitializedPlugin[] = (
|
||||
await Promise.all(
|
||||
pluginConfigsNormalized.map((pluginConfig) => {
|
||||
if (!pluginConfig) {
|
||||
return null;
|
||||
}
|
||||
return initializePlugin(pluginConfig);
|
||||
}),
|
||||
)
|
||||
).filter(<T>(item: T): item is Exclude<T, null> => Boolean(item));
|
||||
const plugins: InitializedPlugin[] = await Promise.all(
|
||||
pluginConfigsNormalized.map(initializePlugin),
|
||||
);
|
||||
|
||||
ensureUniquePluginInstanceIds(plugins);
|
||||
|
||||
|
|
|
@ -32,10 +32,8 @@ export default async function loadPresets(context: LoadContext): Promise<{
|
|||
let presetOptions = {};
|
||||
if (typeof presetItem === 'string') {
|
||||
presetModuleImport = presetItem;
|
||||
} else if (Array.isArray(presetItem)) {
|
||||
[presetModuleImport, presetOptions = {}] = presetItem;
|
||||
} else {
|
||||
throw new Error('Invalid presets format detected in config.');
|
||||
[presetModuleImport, presetOptions] = presetItem;
|
||||
}
|
||||
const presetName = resolveModuleName(
|
||||
presetModuleImport,
|
||||
|
|
0
packages/docusaurus/src/server/versions/__tests__/__fixtures__/dummy-plugin.js
generated
Normal file
0
packages/docusaurus/src/server/versions/__tests__/__fixtures__/dummy-plugin.js
generated
Normal file
|
@ -12,7 +12,7 @@ describe('getPluginVersion', () => {
|
|||
it('Can detect external packages plugins versions of correctly.', async () => {
|
||||
await expect(
|
||||
getPluginVersion(
|
||||
path.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
|
||||
path.join(__dirname, '__fixtures__/dummy-plugin.js'),
|
||||
// Make the plugin appear external.
|
||||
path.join(__dirname, '..', '..', '..', '..', '..', '..', 'website'),
|
||||
),
|
||||
|
@ -22,9 +22,9 @@ describe('getPluginVersion', () => {
|
|||
it('Can detect project plugins versions correctly.', async () => {
|
||||
await expect(
|
||||
getPluginVersion(
|
||||
path.join(__dirname, '..', '__fixtures__', 'dummy-plugin.js'),
|
||||
path.join(__dirname, '__fixtures__/dummy-plugin.js'),
|
||||
// Make the plugin appear project local.
|
||||
path.join(__dirname, '..', '__fixtures__'),
|
||||
path.join(__dirname, '__fixtures__'),
|
||||
),
|
||||
).resolves.toEqual({type: 'project'});
|
||||
});
|
||||
|
|
|
@ -22,11 +22,8 @@ export async function getPackageJsonVersion(
|
|||
async function getPackageJsonName(
|
||||
packageJsonPath: string,
|
||||
): Promise<string | undefined> {
|
||||
if (await fs.pathExists(packageJsonPath)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
|
||||
return require(packageJsonPath).name;
|
||||
}
|
||||
return undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
|
||||
return require(packageJsonPath).name;
|
||||
}
|
||||
|
||||
export async function getPluginVersion(
|
||||
|
|
Loading…
Add table
Reference in a new issue