tailwind-nextjs-blog/components/TOCInline.tsx

75 lines
1.6 KiB
TypeScript
Raw Normal View History

2022-10-17 23:37:01 +08:00
import { Toc } from 'types/Toc';
interface TOCInlineProps {
2022-10-17 23:37:01 +08:00
toc: Toc;
indentDepth?: number;
fromHeading?: number;
toHeading?: number;
asDisclosure?: boolean;
exclude?: string | string[];
}
2022-07-17 21:40:41 +08:00
/**
* 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 = '',
* }
2022-07-17 21:40:41 +08:00
*
*/
const TOCInline = ({
toc,
indentDepth = 3,
fromHeading = 1,
toHeading = 6,
asDisclosure = false,
exclude = '',
}: TOCInlineProps) => {
2022-07-17 21:40:41 +08:00
const re = Array.isArray(exclude)
? new RegExp('^(' + exclude.join('|') + ')$', 'i')
2022-10-17 23:37:01 +08:00
: new RegExp('^(' + exclude + ')$', 'i');
2022-07-17 21:40:41 +08:00
const filteredToc = toc.filter(
(heading) =>
2022-10-17 23:37:01 +08:00
heading.depth >= fromHeading &&
heading.depth <= toHeading &&
!re.test(heading.value)
);
2022-07-17 21:40:41 +08:00
const tocList = (
<ul>
{filteredToc.map((heading) => (
2022-10-17 23:37:01 +08:00
<li
key={heading.value}
className={`${heading.depth >= indentDepth && 'ml-6'}`}>
2022-07-17 21:40:41 +08:00
<a href={heading.url}>{heading.value}</a>
</li>
))}
</ul>
2022-10-17 23:37:01 +08:00
);
2022-07-17 21:40:41 +08:00
return (
<>
{asDisclosure ? (
<details open>
2022-10-17 23:37:01 +08:00
<summary className="ml-6 pt-2 pb-2 text-xl font-bold">
Table of Contents
</summary>
2022-07-17 21:40:41 +08:00
<div className="ml-6">{tocList}</div>
</details>
) : (
tocList
)}
</>
2022-10-17 23:37:01 +08:00
);
};
2022-07-17 21:40:41 +08:00
2022-10-17 23:37:01 +08:00
export default TOCInline;