Skip to content

Commit

Permalink
extract TOCItemTree component
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber committed Apr 29, 2022
1 parent fe286f1 commit 34ba054
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 41 deletions.
13 changes: 13 additions & 0 deletions packages/docusaurus-theme-classic/src/theme-classic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,19 @@ declare module '@theme/TOCItems' {
export default function TOCItems(props: Props): JSX.Element;
}

declare module '@theme/TOCItems/Tree' {
import type {TOCTreeNode} from '@docusaurus/theme-common';

export interface Props {
readonly toc: readonly TOCTreeNode[];
readonly className: string;
readonly linkClassName: string | null;
readonly isChild?: boolean;
}

export default function TOCItems(props: Props): JSX.Element;
}

declare module '@theme/TOC' {
import type {TOCItem} from '@docusaurus/types';

Expand Down
46 changes: 46 additions & 0 deletions packages/docusaurus-theme-classic/src/theme/TOCItems/Tree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import type {Props} from '@theme/TOCItems/Tree';

// Recursive component rendering the toc tree
/* eslint-disable jsx-a11y/control-has-associated-label */
function TOCItemTree({
toc,
className,
linkClassName,
isChild,
}: Props): JSX.Element | null {
if (!toc.length) {
return null;
}
return (
<ul className={isChild ? undefined : className}>
{toc.map((heading) => (
<li key={heading.id}>
<a
href={`#${heading.id}`}
className={linkClassName ?? undefined}
// Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{__html: heading.value}}
/>
<TOCItemTree
isChild
toc={heading.children}
className={className}
linkClassName={linkClassName}
/>
</li>
))}
</ul>
);
}

// Memo only the tree root is enough
export default React.memo(TOCItemTree);
43 changes: 2 additions & 41 deletions packages/docusaurus-theme-classic/src/theme/TOCItems/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,14 @@

import React, {useMemo} from 'react';
import type {Props} from '@theme/TOCItems';
import TOCItemTree from '@theme/TOCItems/Tree';
import {
type TOCHighlightConfig,
type TOCTreeNode,
useThemeConfig,
useTOCHighlight,
useFilteredAndTreeifiedTOC,
} from '@docusaurus/theme-common';

// Recursive component rendering the toc tree
/* eslint-disable jsx-a11y/control-has-associated-label */
function TOCItemList({
toc,
className,
linkClassName,
isChild,
}: {
readonly toc: readonly TOCTreeNode[];
readonly className: string;
readonly linkClassName: string | null;
readonly isChild?: boolean;
}): JSX.Element | null {
if (!toc.length) {
return null;
}
return (
<ul className={isChild ? undefined : className}>
{toc.map((heading) => (
<li key={heading.id}>
<a
href={`#${heading.id}`}
className={linkClassName ?? undefined}
// Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{__html: heading.value}}
/>
<TOCItemList
isChild
toc={heading.children}
className={className}
linkClassName={linkClassName}
/>
</li>
))}
</ul>
);
}

export default function TOCItems({
toc,
className = 'table-of-contents table-of-contents__left-border',
Expand Down Expand Up @@ -90,7 +51,7 @@ export default function TOCItems({
useTOCHighlight(tocHighlightConfig);

return (
<TOCItemList
<TOCItemTree
toc={tocTree}
className={className}
linkClassName={linkClassName}
Expand Down

0 comments on commit 34ba054

Please sign in to comment.