mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-01 02:12:36 +02:00
feat(v2): support external links and linking to docs from other sidebars (#1052)
* feat(sidebar): support external links and linking to docs from other sidebars * Update styles.css
This commit is contained in:
parent
edde297504
commit
a2d3f26722
8 changed files with 466 additions and 139 deletions
32
v2/lib/theme/Sidebar/SidebarCategory.js
Normal file
32
v2/lib/theme/Sidebar/SidebarCategory.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import styles from './styles.css';
|
||||
|
||||
export default function SidebarCategory({
|
||||
label,
|
||||
items,
|
||||
subCategory,
|
||||
renderItem,
|
||||
}) {
|
||||
const Heading = subCategory ? 'h4' : 'h3';
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(styles.sidebarGroup, {
|
||||
[styles.sidebarSubGroup]: subCategory,
|
||||
})}
|
||||
key={label}>
|
||||
<Heading
|
||||
className={classnames(
|
||||
styles.sidebarItem,
|
||||
styles.sidebarGroupTitle,
|
||||
styles.sidebarGroupCategoryTitle,
|
||||
)}>
|
||||
{label}
|
||||
</Heading>
|
||||
|
||||
<ul className={styles.sidebarList}>{items.map(renderItem)}</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
24
v2/lib/theme/Sidebar/SidebarLink.js
Normal file
24
v2/lib/theme/Sidebar/SidebarLink.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import {NavLink} from 'react-router-dom';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import styles from './styles.css';
|
||||
|
||||
export default function SidebarLink({href, label}) {
|
||||
const isExternal = /^(https?:|\/\/)/.test(href);
|
||||
const Link = isExternal
|
||||
? // eslint-disable-next-line jsx-a11y/anchor-has-content
|
||||
({to, activeClassName, ...linkProps}) => <a {...linkProps} href={to} />
|
||||
: NavLink;
|
||||
|
||||
return (
|
||||
<li className={styles.sidebarListItem}>
|
||||
<Link
|
||||
activeClassName={styles.sidebarLinkActive}
|
||||
className={classnames(styles.sidebarLink, styles.sidebarItem)}
|
||||
to={href}>
|
||||
{label}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
}
|
|
@ -1,80 +1,63 @@
|
|||
import React from 'react';
|
||||
import {NavLink} from 'react-router-dom';
|
||||
|
||||
import classnames from 'classnames';
|
||||
|
||||
import SidebarLink from './SidebarLink';
|
||||
import SidebarCategory from './SidebarCategory';
|
||||
import styles from './styles.css';
|
||||
|
||||
function Sidebar(props) {
|
||||
const {metadata, docsSidebars, docsMetadatas} = props;
|
||||
const {sidebar, language} = metadata;
|
||||
if (!sidebar || !docsSidebars) {
|
||||
|
||||
if (!sidebar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const thisSidebar = docsSidebars[sidebar];
|
||||
|
||||
const renderItemLink = rawLinkID => {
|
||||
const linkID = (language ? `${language}-` : '') + rawLinkID;
|
||||
if (!thisSidebar) {
|
||||
throw new Error(`Can not find ${sidebar} config`);
|
||||
}
|
||||
|
||||
const convertDocLink = item => {
|
||||
const linkID = (language ? `${language}-` : '') + item.id;
|
||||
const linkMetadata = docsMetadatas[linkID];
|
||||
|
||||
if (!linkMetadata) {
|
||||
throw new Error(
|
||||
`Improper sidebars.json file, document with id '${linkID}' not found.`,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={styles.sidebarListItem} key={linkID}>
|
||||
<NavLink
|
||||
activeClassName={styles.sidebarLinkActive}
|
||||
className={classnames(styles.sidebarLink, styles.sidebarItem)}
|
||||
to={linkMetadata.permalink}>
|
||||
{linkMetadata.sidebar_label || linkMetadata.title}
|
||||
</NavLink>
|
||||
</li>
|
||||
);
|
||||
return {
|
||||
type: 'link',
|
||||
label: linkMetadata.sidebar_label || linkMetadata.title,
|
||||
href: linkMetadata.permalink,
|
||||
};
|
||||
};
|
||||
|
||||
const renderCategory = categoryName => {
|
||||
const category = thisSidebar[categoryName];
|
||||
return (
|
||||
<div className={styles.sidebarGroup} key={categoryName}>
|
||||
<h3
|
||||
className={classnames(
|
||||
styles.sidebarItem,
|
||||
styles.sidebarGroupTitle,
|
||||
styles.sidebarGroupCategoryTitle,
|
||||
)}>
|
||||
{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={classnames(
|
||||
styles.sidebarItem,
|
||||
styles.sidebarGroupTitle,
|
||||
styles.sidebarGroupSubcategorytitle,
|
||||
)}>
|
||||
{subCategoryName}
|
||||
</h4>
|
||||
<ul className={styles.sidebarList}>
|
||||
{category[subCategoryName].map(renderItemLink)}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
const renderItem = (item, {root} = {}) => {
|
||||
switch (item.type) {
|
||||
case 'category':
|
||||
return (
|
||||
<SidebarCategory
|
||||
{...item}
|
||||
key={item.label}
|
||||
subCategory={!root}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
);
|
||||
case 'link':
|
||||
return <SidebarLink {...item} key={item.href} />;
|
||||
case 'ref':
|
||||
default:
|
||||
return renderItem(convertDocLink(item));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
thisSidebar && (
|
||||
<div className={styles.sidebar}>
|
||||
{Object.keys(thisSidebar).map(renderCategory)}
|
||||
</div>
|
||||
)
|
||||
<div className={styles.sidebar}>
|
||||
{thisSidebar.map(item => renderItem(item, {root: true}))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.sidebarSubGroup {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.sidebarGroupTitle {
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue