mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-02 19:57:25 +02:00
feat(v2): enable subcategories (#1021)
* feat(v2): enable subcategories * nits * eslint issue https://github.com/prettier/prettier/issues/3734
This commit is contained in:
parent
954456088c
commit
f62029c30e
9 changed files with 150 additions and 43 deletions
|
@ -9,7 +9,7 @@ module.exports = {
|
||||||
jest: true,
|
jest: true,
|
||||||
node: true,
|
node: true,
|
||||||
},
|
},
|
||||||
extends: ['airbnb', 'prettier'],
|
extends: ['airbnb', 'prettier', 'prettier/react'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': OFF,
|
'no-console': OFF,
|
||||||
'func-names': OFF,
|
'func-names': OFF,
|
||||||
|
|
|
@ -151,6 +151,7 @@ module.exports = async function processMetadata(
|
||||||
if (order[id]) {
|
if (order[id]) {
|
||||||
metadata.sidebar = order[id].sidebar;
|
metadata.sidebar = order[id].sidebar;
|
||||||
metadata.category = order[id].category;
|
metadata.category = order[id].category;
|
||||||
|
metadata.subCategory = order[id].subCategory;
|
||||||
if (order[id].next) {
|
if (order[id].next) {
|
||||||
metadata.next_id = order[id].next;
|
metadata.next_id = order[id].next;
|
||||||
metadata.next = (language ? `${language}-` : '') + order[id].next;
|
metadata.next = (language ? `${language}-` : '') + order[id].next;
|
||||||
|
|
|
@ -9,11 +9,26 @@ module.exports = function createOrder(allSidebars = {}) {
|
||||||
|
|
||||||
let ids = [];
|
let ids = [];
|
||||||
const categoryOrder = [];
|
const categoryOrder = [];
|
||||||
|
const subCategoryOrder = [];
|
||||||
Object.keys(categories).forEach(category => {
|
Object.keys(categories).forEach(category => {
|
||||||
ids = ids.concat(categories[category]);
|
if (Array.isArray(categories[category])) {
|
||||||
// eslint-disable-next-line
|
ids = ids.concat(categories[category]);
|
||||||
for (let i = 0; i < categories[category].length; i++) {
|
|
||||||
categoryOrder.push(category);
|
// eslint-disable-next-line
|
||||||
|
for (let i = 0; i < categories[category].length; i++) {
|
||||||
|
categoryOrder.push(category);
|
||||||
|
subCategoryOrder.push(undefined);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object.keys(categories[category]).forEach(subCategory => {
|
||||||
|
ids = ids.concat(categories[category][subCategory]);
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
for (let i = 0; i < categories[category][subCategory].length; i++) {
|
||||||
|
categoryOrder.push(category);
|
||||||
|
subCategoryOrder.push(subCategory);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,6 +44,7 @@ module.exports = function createOrder(allSidebars = {}) {
|
||||||
next,
|
next,
|
||||||
sidebar,
|
sidebar,
|
||||||
category: categoryOrder[i],
|
category: categoryOrder[i],
|
||||||
|
subCategory: subCategoryOrder[i],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,37 +12,56 @@ function Sidebar(props) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const thisSidebar = docsSidebars[sidebar];
|
const thisSidebar = docsSidebars[sidebar];
|
||||||
|
|
||||||
|
const renderItemLink = rawLinkID => {
|
||||||
|
const linkID = (language ? `${language}-` : '') + rawLinkID;
|
||||||
|
const linkMetadata = docsMetadatas[linkID];
|
||||||
|
if (!linkMetadata) {
|
||||||
|
throw new Error(
|
||||||
|
`Improper sidebars.json file, document with id '${linkID}' not found.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const activeItem = linkID === thisID;
|
||||||
|
return (
|
||||||
|
<li key={linkID}>
|
||||||
|
<Link
|
||||||
|
className={classnames(styles.sidebarLink, {
|
||||||
|
[styles.sidebarLinkActive]: activeItem,
|
||||||
|
})}
|
||||||
|
to={linkMetadata.permalink}>
|
||||||
|
{linkMetadata.sidebar_label || linkMetadata.title}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderCategory = categoryName => {
|
||||||
|
const category = thisSidebar[categoryName];
|
||||||
|
return (
|
||||||
|
<div className={styles.sidebarGroup} key={categoryName}>
|
||||||
|
<h3 className={styles.sidebarGroupTitle}>{categoryName}</h3>
|
||||||
|
<ul className={styles.sidebarList}>
|
||||||
|
{Array.isArray(category)
|
||||||
|
? category.map(renderItemLink)
|
||||||
|
: Object.keys(category).map(subCategoryName => (
|
||||||
|
<div className={styles.sidebarSubGroup} key={subCategoryName}>
|
||||||
|
<h4 className={styles.sidebarSubGroupTitle}>
|
||||||
|
{subCategoryName}
|
||||||
|
</h4>
|
||||||
|
<ul className={styles.sidebarList}>
|
||||||
|
{category[subCategoryName].map(renderItemLink)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
thisSidebar && (
|
thisSidebar && (
|
||||||
<div className={styles.sidebar}>
|
<div className={styles.sidebar}>
|
||||||
{Object.keys(thisSidebar).map(categoryName => (
|
{Object.keys(thisSidebar).map(renderCategory)}
|
||||||
<div className={styles.sidebarGroup} key={categoryName}>
|
|
||||||
<h3 className={styles.sidebarGroupTitle}>{categoryName}</h3>
|
|
||||||
<ul className={styles.sidebarList}>
|
|
||||||
{thisSidebar[categoryName].map(rawLinkID => {
|
|
||||||
const linkID = (language ? `${language}-` : '') + rawLinkID;
|
|
||||||
const linkMetadata = docsMetadatas[linkID];
|
|
||||||
if (!linkMetadata) {
|
|
||||||
throw new Error(
|
|
||||||
`Improper sidebars.json file, document with id '${linkID}' not found.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const activeItem = linkID === thisID;
|
|
||||||
return (
|
|
||||||
<li key={linkID}>
|
|
||||||
<Link
|
|
||||||
className={classnames(styles.sidebarLink, {
|
|
||||||
[styles.sidebarLinkActive]: activeItem,
|
|
||||||
})}
|
|
||||||
to={linkMetadata.permalink}>
|
|
||||||
{linkMetadata.sidebar_label || linkMetadata.title}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,18 @@
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebarSubGroup {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebarSubGroupTitle {
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebarGroupTitle {
|
.sidebarGroupTitle {
|
||||||
|
font-size: 18px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.9.0",
|
||||||
"eslint-plugin-import": "^2.12.0",
|
"eslint-plugin-import": "^2.12.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.0.3",
|
"eslint-plugin-jsx-a11y": "^6.0.3",
|
||||||
"eslint-plugin-react": "^7.9.1",
|
"eslint-plugin-react": "^7.11.1",
|
||||||
"jest": "^23.4.2",
|
"jest": "^23.4.2",
|
||||||
"prettier": "^1.13.7"
|
"prettier": "^1.13.7"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,58 @@
|
||||||
import createOrder from '@lib/load/docs/order';
|
import createOrder from '@lib/load/docs/order';
|
||||||
|
|
||||||
describe('createOrder', () => {
|
describe('createOrder', () => {
|
||||||
test('should populate docs index from multiple sidebars', () => {
|
test('multiple sidebars with subcategory', () => {
|
||||||
|
const result = createOrder({
|
||||||
|
docs: {
|
||||||
|
Category1: {
|
||||||
|
'Subcategory 1': ['doc1'],
|
||||||
|
'Subcategory 2': ['doc2'],
|
||||||
|
},
|
||||||
|
Category2: ['doc3', 'doc4'],
|
||||||
|
},
|
||||||
|
otherDocs: {
|
||||||
|
Category1: ['doc5'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(result).toEqual({
|
||||||
|
doc1: {
|
||||||
|
category: 'Category1',
|
||||||
|
subCategory: 'Subcategory 1',
|
||||||
|
next: 'doc2',
|
||||||
|
previous: undefined,
|
||||||
|
sidebar: 'docs',
|
||||||
|
},
|
||||||
|
doc2: {
|
||||||
|
category: 'Category1',
|
||||||
|
subCategory: 'Subcategory 2',
|
||||||
|
next: 'doc3',
|
||||||
|
previous: 'doc1',
|
||||||
|
sidebar: 'docs',
|
||||||
|
},
|
||||||
|
doc3: {
|
||||||
|
category: 'Category2',
|
||||||
|
subCategory: undefined,
|
||||||
|
next: 'doc4',
|
||||||
|
previous: 'doc2',
|
||||||
|
sidebar: 'docs',
|
||||||
|
},
|
||||||
|
doc4: {
|
||||||
|
category: 'Category2',
|
||||||
|
subCategory: undefined,
|
||||||
|
next: undefined,
|
||||||
|
previous: 'doc3',
|
||||||
|
sidebar: 'docs',
|
||||||
|
},
|
||||||
|
doc5: {
|
||||||
|
category: 'Category1',
|
||||||
|
subCategory: undefined,
|
||||||
|
next: undefined,
|
||||||
|
previous: undefined,
|
||||||
|
sidebar: 'otherDocs',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('multiple sidebars without subcategory', () => {
|
||||||
const result = createOrder({
|
const result = createOrder({
|
||||||
docs: {
|
docs: {
|
||||||
Category1: ['doc1', 'doc2'],
|
Category1: ['doc1', 'doc2'],
|
||||||
|
@ -14,30 +65,35 @@ describe('createOrder', () => {
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc1: {
|
doc1: {
|
||||||
category: 'Category1',
|
category: 'Category1',
|
||||||
|
subCategory: undefined,
|
||||||
next: 'doc2',
|
next: 'doc2',
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc2: {
|
doc2: {
|
||||||
category: 'Category1',
|
category: 'Category1',
|
||||||
|
subCategory: undefined,
|
||||||
next: 'doc3',
|
next: 'doc3',
|
||||||
previous: 'doc1',
|
previous: 'doc1',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc3: {
|
doc3: {
|
||||||
category: 'Category2',
|
category: 'Category2',
|
||||||
|
subCategory: undefined,
|
||||||
next: 'doc4',
|
next: 'doc4',
|
||||||
previous: 'doc2',
|
previous: 'doc2',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc4: {
|
doc4: {
|
||||||
category: 'Category2',
|
category: 'Category2',
|
||||||
|
subCategory: undefined,
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: 'doc3',
|
previous: 'doc3',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
},
|
},
|
||||||
doc5: {
|
doc5: {
|
||||||
category: 'Category1',
|
category: 'Category1',
|
||||||
|
subCategory: undefined,
|
||||||
next: undefined,
|
next: undefined,
|
||||||
previous: undefined,
|
previous: undefined,
|
||||||
sidebar: 'otherDocs',
|
sidebar: 'otherDocs',
|
||||||
|
@ -45,7 +101,7 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should resolve docs from older versions', () => {
|
test('versioned sidebars', () => {
|
||||||
const result = createOrder({
|
const result = createOrder({
|
||||||
docs: {
|
docs: {
|
||||||
Category1: ['doc1'],
|
Category1: ['doc1'],
|
||||||
|
@ -58,18 +114,21 @@ describe('createOrder', () => {
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
doc1: {
|
doc1: {
|
||||||
category: 'Category1',
|
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',
|
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',
|
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',
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"docs": {
|
"docs": {
|
||||||
"Foo": [
|
"Foo": {
|
||||||
"foo/bar",
|
"bar": ["foo/bar"],
|
||||||
"foo/baz"
|
"baz": ["foo/baz"]
|
||||||
],
|
},
|
||||||
"Endi": [
|
"Endi": [
|
||||||
"docusaurus",
|
"docusaurus",
|
||||||
"highlight",
|
"highlight",
|
||||||
|
|
|
@ -2527,10 +2527,11 @@ eslint-plugin-jsx-a11y@^6.0.3:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
jsx-ast-utils "^2.0.1"
|
jsx-ast-utils "^2.0.1"
|
||||||
|
|
||||||
eslint-plugin-react@^7.9.1:
|
eslint-plugin-react@^7.11.1:
|
||||||
version "7.10.0"
|
version "7.11.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz#af5c1fef31c4704db02098f9be18202993828b50"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
array-includes "^3.0.3"
|
||||||
doctrine "^2.1.0"
|
doctrine "^2.1.0"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
jsx-ast-utils "^2.0.1"
|
jsx-ast-utils "^2.0.1"
|
||||||
|
|
Loading…
Add table
Reference in a new issue