75 lines
1.6 KiB
TypeScript
75 lines
1.6 KiB
TypeScript
import { Toc } from 'types/Toc';
|
|
|
|
interface TOCInlineProps {
|
|
toc: Toc;
|
|
indentDepth?: number;
|
|
fromHeading?: number;
|
|
toHeading?: number;
|
|
asDisclosure?: boolean;
|
|
exclude?: string | string[];
|
|
}
|
|
|
|
/**
|
|
* Generates an inline table of contents
|
|
* Exclude titles matching this string (new RegExp('^(' + string + ')$', 'i')).
|
|
* If an array is passed the array gets joined with a pipe (new RegExp('^(' + array.join('|') + ')$', 'i')).
|
|
*
|
|
* @param {TOCInlineProps} {
|
|
* toc,
|
|
* indentDepth = 3,
|
|
* fromHeading = 1,
|
|
* toHeading = 6,
|
|
* asDisclosure = false,
|
|
* exclude = '',
|
|
* }
|
|
*
|
|
*/
|
|
const TOCInline = ({
|
|
toc,
|
|
indentDepth = 3,
|
|
fromHeading = 1,
|
|
toHeading = 6,
|
|
asDisclosure = false,
|
|
exclude = '',
|
|
}: TOCInlineProps) => {
|
|
const re = Array.isArray(exclude)
|
|
? new RegExp('^(' + exclude.join('|') + ')$', 'i')
|
|
: new RegExp('^(' + exclude + ')$', 'i');
|
|
|
|
const filteredToc = toc.filter(
|
|
(heading) =>
|
|
heading.depth >= fromHeading &&
|
|
heading.depth <= toHeading &&
|
|
!re.test(heading.value)
|
|
);
|
|
|
|
const tocList = (
|
|
<ul>
|
|
{filteredToc.map((heading) => (
|
|
<li
|
|
key={heading.value}
|
|
className={`${heading.depth >= indentDepth && 'ml-6'}`}>
|
|
<a href={heading.url}>{heading.value}</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
{asDisclosure ? (
|
|
<details open>
|
|
<summary className="ml-6 pt-2 pb-2 text-xl font-bold">
|
|
Table of Contents
|
|
</summary>
|
|
<div className="ml-6">{tocList}</div>
|
|
</details>
|
|
) : (
|
|
tocList
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default TOCInline;
|