mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-20 20:46:58 +02:00
* feat: add all TOC levels to MDX loader * feat: add theme-level config for heading depth * test: add remark MDX loader test * fix: limit maxDepth validation to H2 - H6 * refactor: set default `maxDepth` using `joi` * refactor: `maxDepth` -> `maxHeadingLevel * refactor: invert underlying TOC depth API * refactor: make TOC algorithm level-aware * feat: add support for per-doc TOC heading levels * feat: support document-level heading levels for blog * fix: correct validation for toc level frontmatter * fix: ensure TOC doesn't generate redundant DOM * perf: simpler TOC heading search alg * docs: document heading level props for `TOCInline` * Update website/docs/guides/markdown-features/markdown-features-inline-toc.mdx Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * docs: fix docs (again) * create dedicated test file for heading searching logic: exhaustive tests will be simpler to write * toc search: add real-world test * fix test * add dogfooding tests for toc min/max * add test for min/max toc frontmatter * reverse min/max order * add theme minHeadingLevel + tests * simpler TOC rendering logic * simplify TOC implementation (temp, WIP) * reverse unnatural order for minHeadingLevel/maxHeadingLevel * add TOC dogfooding tests to all content plugins * expose toc min/max heading level frontmatter to all 3 content plugins * refactor blogLayout: accept toc ReactElement directly * move toc utils to theme-common * add tests for filterTOC * create new generic TOCItems component * useless css file copied * fix toc highlighting className conflicts * update doc * fix types Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Co-authored-by: slorber <lorber.sebastien@gmail.com>
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
/**
|
|
* 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, {useMemo} from 'react';
|
|
import type {TOCItemsProps} from '@theme/TOCItems';
|
|
import {TOCItem} from '@docusaurus/types';
|
|
import {
|
|
TOCHighlightConfig,
|
|
useThemeConfig,
|
|
useTOCFilter,
|
|
useTOCHighlight,
|
|
} from '@docusaurus/theme-common';
|
|
|
|
// Recursive component rendering the toc tree
|
|
/* eslint-disable jsx-a11y/control-has-associated-label */
|
|
function TOCItemList({
|
|
toc,
|
|
className = 'table-of-contents table-of-contents__left-border',
|
|
linkClassName = 'table-of-contents__link',
|
|
isChild,
|
|
}: {
|
|
readonly toc: readonly TOCItem[];
|
|
readonly className: string;
|
|
readonly linkClassName: string;
|
|
readonly isChild?: boolean;
|
|
}): JSX.Element | null {
|
|
if (!toc.length) {
|
|
return null;
|
|
}
|
|
return (
|
|
<ul className={isChild ? '' : className}>
|
|
{toc.map((heading) => (
|
|
<li key={heading.id}>
|
|
<a
|
|
href={`#${heading.id}`}
|
|
className={linkClassName}
|
|
// 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',
|
|
linkClassName = 'table-of-contents__link',
|
|
linkActiveClassName = undefined,
|
|
minHeadingLevel: minHeadingLevelOption,
|
|
maxHeadingLevel: maxHeadingLevelOption,
|
|
...props
|
|
}: TOCItemsProps): JSX.Element | null {
|
|
const themeConfig = useThemeConfig();
|
|
|
|
const minHeadingLevel =
|
|
minHeadingLevelOption ?? themeConfig.tableOfContents.minHeadingLevel;
|
|
const maxHeadingLevel =
|
|
maxHeadingLevelOption ?? themeConfig.tableOfContents.maxHeadingLevel;
|
|
|
|
const tocFiltered = useTOCFilter({toc, minHeadingLevel, maxHeadingLevel});
|
|
|
|
const tocHighlightConfig: TOCHighlightConfig | undefined = useMemo(() => {
|
|
if (linkClassName && linkActiveClassName) {
|
|
return {
|
|
linkClassName,
|
|
linkActiveClassName,
|
|
minHeadingLevel,
|
|
maxHeadingLevel,
|
|
};
|
|
}
|
|
return undefined;
|
|
}, [linkClassName, linkActiveClassName, minHeadingLevel, maxHeadingLevel]);
|
|
useTOCHighlight(tocHighlightConfig);
|
|
|
|
return (
|
|
<TOCItemList
|
|
toc={tocFiltered}
|
|
className={className}
|
|
linkClassName={linkClassName}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|