refactor(v2): docs plugin refactor (#3245)

* safe refactorings

* safe refactors

* add code to read versions more generically

* refactor docs plugin

* refactors

* stable docs refactor

* progress on refactor

* stable docs refactor

* stable docs refactor

* stable docs refactor

* attempt to fix admonition :(

* configureWebpack docs: better typing

* more refactors

* rename cli

* refactor docs metadata processing => move to pure function

* stable docs refactor

* stable docs refactor

* named exports

* basic sidebars refactor

* add getElementsAround utils

* refactor sidebar + ordering/navigation logic

* stable retrocompatible refactor

* add proper versions metadata tests

* fix docs metadata tests

* fix docs tests

* fix test due to absolute path

* fix webpack tests

* refactor linkify + add broken markdown links warning

* fix DOM warning due to forwarding legacy prop to div element

* add todo
This commit is contained in:
Sébastien Lorber 2020-08-17 17:50:22 +02:00 committed by GitHub
parent d17df954b5
commit a4c8a7f55b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 3219 additions and 2724 deletions

View file

@ -6,7 +6,13 @@
*/
import path from 'path';
import loadSidebars from '../sidebars';
import {
loadSidebars,
collectSidebarDocItems,
collectSidebarsDocIds,
createSidebarsUtils,
} from '../sidebars';
import {Sidebar, Sidebars} from '../types';
/* eslint-disable global-require, import/no-dynamic-require */
@ -14,13 +20,13 @@ describe('loadSidebars', () => {
const fixtureDir = path.join(__dirname, '__fixtures__', 'sidebars');
test('sidebars with known sidebar item type', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars.json');
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
test('sidebars with deep level of category', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-category.js');
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
@ -30,8 +36,8 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-category-shorthand.js',
);
const sidebar1 = loadSidebars([sidebarPath1]);
const sidebar2 = loadSidebars([sidebarPath2]);
const sidebar1 = loadSidebars(sidebarPath1);
const sidebar2 = loadSidebars(sidebarPath2);
expect(sidebar1).toEqual(sidebar2);
});
@ -40,9 +46,7 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-category-wrong-items.json',
);
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Error loading {\\"type\\":\\"category\\",\\"label\\":\\"Category Label\\",\\"items\\":\\"doc1\\"}. \\"items\\" must be an array."`,
);
});
@ -52,9 +56,7 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-category-wrong-label.json',
);
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Error loading {\\"type\\":\\"category\\",\\"label\\":true,\\"items\\":[\\"doc1\\"]}. \\"label\\" must be a string."`,
);
});
@ -64,9 +66,7 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-doc-id-not-string.json',
);
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Error loading {\\"type\\":\\"doc\\",\\"id\\":[\\"doc1\\"]}. \\"id\\" must be a string."`,
);
});
@ -76,60 +76,75 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-first-level-not-category.js',
);
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
test('sidebars link', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-link.json');
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
test('sidebars link wrong label', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-link-wrong-label.json');
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Error loading {\\"type\\":\\"link\\",\\"label\\":false,\\"href\\":\\"https://github.com\\"}. \\"label\\" must be a string."`,
);
});
test('sidebars link wrong href', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-link-wrong-href.json');
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Error loading {\\"type\\":\\"link\\",\\"label\\":\\"GitHub\\",\\"href\\":[\\"example.com\\"]}. \\"href\\" must be a string."`,
);
});
test('sidebars with unknown sidebar item type', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-unknown-type.json');
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Unknown sidebar item type [superman]. Sidebar item={\\"type\\":\\"superman\\"} "`,
);
});
test('sidebars with known sidebar item type but wrong field', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-wrong-field.json');
expect(() =>
loadSidebars([sidebarPath]),
).toThrowErrorMatchingInlineSnapshot(
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
`"Unknown sidebar item keys: href. Item: {\\"type\\":\\"category\\",\\"label\\":\\"category\\",\\"href\\":\\"https://github.com\\"}"`,
);
});
test('no sidebars', () => {
const result = loadSidebars(null);
expect(result).toEqual({});
test('unexisting path', () => {
expect(() => loadSidebars('badpath')).toThrowErrorMatchingInlineSnapshot(
`"No sidebar file exist at path: badpath"`,
);
});
test('undefined path', () => {
expect(() =>
loadSidebars(
// @ts-expect-error: bad arg
undefined,
),
).toThrowErrorMatchingInlineSnapshot(
`"sidebarFilePath not provided: undefined"`,
);
});
test('null path', () => {
expect(() =>
loadSidebars(
// @ts-expect-error: bad arg
null,
),
).toThrowErrorMatchingInlineSnapshot(
`"sidebarFilePath not provided: null"`,
);
});
test('sidebars with category.collapsed property', async () => {
const sidebarPath = path.join(fixtureDir, 'sidebars-collapsed.json');
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
@ -138,7 +153,177 @@ describe('loadSidebars', () => {
fixtureDir,
'sidebars-collapsed-first-level.json',
);
const result = loadSidebars([sidebarPath]);
const result = loadSidebars(sidebarPath);
expect(result).toMatchSnapshot();
});
});
describe('collectSidebarDocItems', () => {
test('can collect recursively', async () => {
const sidebar: Sidebar = [
{
type: 'category',
collapsed: false,
label: 'Category1',
items: [
{
type: 'category',
collapsed: false,
label: 'Subcategory 1',
items: [{type: 'doc', id: 'doc1'}],
},
{
type: 'category',
collapsed: false,
label: 'Subcategory 2',
items: [
{type: 'doc', id: 'doc2'},
{
type: 'category',
collapsed: false,
label: 'Sub sub category 1',
items: [{type: 'doc', id: 'doc3'}],
},
],
},
],
},
{
type: 'category',
collapsed: false,
label: 'Category2',
items: [
{type: 'doc', id: 'doc4'},
{type: 'doc', id: 'doc5'},
],
},
];
expect(collectSidebarDocItems(sidebar).map((doc) => doc.id)).toEqual([
'doc1',
'doc2',
'doc3',
'doc4',
'doc5',
]);
});
});
describe('collectSidebarsDocItems', () => {
test('can collect sidebars doc items', async () => {
const sidebar1: Sidebar = [
{
type: 'category',
collapsed: false,
label: 'Category1',
items: [
{
type: 'category',
collapsed: false,
label: 'Subcategory 1',
items: [{type: 'doc', id: 'doc1'}],
},
{type: 'doc', id: 'doc2'},
],
},
];
const sidebar2: Sidebar = [
{
type: 'category',
collapsed: false,
label: 'Category2',
items: [
{type: 'doc', id: 'doc3'},
{type: 'doc', id: 'doc4'},
],
},
];
const sidebar3: Sidebar = [
{type: 'doc', id: 'doc5'},
{type: 'doc', id: 'doc6'},
];
expect(collectSidebarsDocIds({sidebar1, sidebar2, sidebar3})).toEqual({
sidebar1: ['doc1', 'doc2'],
sidebar2: ['doc3', 'doc4'],
sidebar3: ['doc5', 'doc6'],
});
});
});
describe('createSidebarsUtils', () => {
const sidebar1: Sidebar = [
{
type: 'category',
collapsed: false,
label: 'Category1',
items: [
{
type: 'category',
collapsed: false,
label: 'Subcategory 1',
items: [{type: 'doc', id: 'doc1'}],
},
{type: 'doc', id: 'doc2'},
],
},
];
const sidebar2: Sidebar = [
{
type: 'category',
collapsed: false,
label: 'Category2',
items: [
{type: 'doc', id: 'doc3'},
{type: 'doc', id: 'doc4'},
],
},
];
const sidebars: Sidebars = {sidebar1, sidebar2};
const {
getFirstDocIdOfFirstSidebar,
getSidebarNameByDocId,
getDocNavigation,
} = createSidebarsUtils(sidebars);
test('getSidebarNameByDocId', async () => {
expect(getFirstDocIdOfFirstSidebar()).toEqual('doc1');
});
test('getSidebarNameByDocId', async () => {
expect(getSidebarNameByDocId('doc1')).toEqual('sidebar1');
expect(getSidebarNameByDocId('doc2')).toEqual('sidebar1');
expect(getSidebarNameByDocId('doc3')).toEqual('sidebar2');
expect(getSidebarNameByDocId('doc4')).toEqual('sidebar2');
expect(getSidebarNameByDocId('doc5')).toEqual(undefined);
expect(getSidebarNameByDocId('doc6')).toEqual(undefined);
});
test('getDocNavigation', async () => {
expect(getDocNavigation('doc1')).toEqual({
sidebarName: 'sidebar1',
previousId: undefined,
nextId: 'doc2',
});
expect(getDocNavigation('doc2')).toEqual({
sidebarName: 'sidebar1',
previousId: 'doc1',
nextId: undefined,
});
expect(getDocNavigation('doc3')).toEqual({
sidebarName: 'sidebar2',
previousId: undefined,
nextId: 'doc4',
});
expect(getDocNavigation('doc4')).toEqual({
sidebarName: 'sidebar2',
previousId: 'doc3',
nextId: undefined,
});
});
});