diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
index f3d93c0585..bca8c59199 100644
--- a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
+++ b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/__snapshots__/index.test.ts.snap
@@ -5,32 +5,26 @@ exports[`inline code should be escaped 1`] = `
{
value: '<Head />',
id: 'head-',
- children: [
- {
- value: '<Head>Test</Head>',
- id: 'headtesthead',
- children: [],
- level: 3
- }
- ],
level: 2
},
+ {
+ value: '<Head>Test</Head>',
+ id: 'headtesthead',
+ level: 3
+ },
{
value: '<div />',
id: 'div-',
- children: [],
level: 2
},
{
value: '<div> Test </div>',
id: 'div-test-div',
- children: [],
level: 2
},
{
value: '<div><i>Test</i></div>',
id: 'divitestidiv',
- children: [],
level: 2
}
];
@@ -52,32 +46,26 @@ exports[`non text phrasing content 1`] = `
{
value: 'Emphasis',
id: 'emphasis',
- children: [
- {
- value: 'Importance',
- id: 'importance',
- children: [],
- level: 3
- }
- ],
level: 2
},
+ {
+ value: 'Importance',
+ id: 'importance',
+ level: 3
+ },
{
value: 'Strikethrough',
id: 'strikethrough',
- children: [],
level: 2
},
{
value: 'HTML',
id: 'html',
- children: [],
level: 2
},
{
value: 'inline.code()',
id: 'inlinecode',
- children: [],
level: 2
}
];
diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/index.test.ts
index f3134ef5d4..daf2488705 100644
--- a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/index.test.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/index.test.ts
@@ -41,26 +41,21 @@ test('text content', async () => {
{
value: 'Endi',
id: 'endi',
- children: [],
level: 3
},
{
value: 'Endi',
id: 'endi-1',
- children: [
- {
- value: 'Yangshun',
- id: 'yangshun',
- children: [],
- level: 3
- }
- ],
level: 2
},
+ {
+ value: 'Yangshun',
+ id: 'yangshun',
+ level: 3
+ },
{
value: 'I ♥ unicode.',
id: 'i--unicode',
- children: [],
level: 2
}
];
@@ -91,21 +86,17 @@ test('should export even with existing name', async () => {
{
value: 'Thanos',
id: 'thanos',
- children: [],
level: 2
},
{
value: 'Tony Stark',
id: 'tony-stark',
- children: [
- {
- value: 'Avengers',
- id: 'avengers',
- children: [],
- level: 3
- }
- ],
level: 2
+ },
+ {
+ value: 'Avengers',
+ id: 'avengers',
+ level: 3
}
];
@@ -128,26 +119,21 @@ test('should export with custom name', async () => {
{
value: 'Endi',
id: 'endi',
- children: [],
level: 3
},
{
value: 'Endi',
id: 'endi-1',
- children: [
- {
- value: 'Yangshun',
- id: 'yangshun',
- children: [],
- level: 3
- }
- ],
level: 2
},
+ {
+ value: 'Yangshun',
+ id: 'yangshun',
+ level: 3
+ },
{
value: 'I ♥ unicode.',
id: 'i--unicode',
- children: [],
level: 2
}
];
@@ -182,21 +168,17 @@ test('should insert below imports', async () => {
{
value: 'Title',
id: 'title',
- children: [],
level: 2
},
{
value: 'Test',
id: 'test',
- children: [
- {
- value: 'Again',
- id: 'again',
- children: [],
- level: 3
- }
- ],
level: 2
+ },
+ {
+ value: 'Again',
+ id: 'again',
+ level: 3
}
];
diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/search.test.ts b/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/search.test.ts
deleted file mode 100644
index 900fbfad3f..0000000000
--- a/packages/docusaurus-mdx-loader/src/remark/toc/__tests__/search.test.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * 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 remark from 'remark';
-import mdx from 'remark-mdx';
-import search from '../search';
-import headings from '../../headings/index';
-
-const getHeadings = async (mdText: string) => {
- const node = remark().parse(mdText);
- const result = await remark().use(headings).use(mdx).run(node);
- return search(result);
-};
-
-test('should process all heading levels', async () => {
- const md = `
-# Alpha
-
-## Bravo
-
-### Charlie
-
-#### Delta
-
-##### Echo
-
-###### Foxtrot
-
- `;
-
- await expect(getHeadings(md)).resolves.toEqual([
- {
- children: [
- {
- children: [
- {
- children: [
- {
- children: [
- {
- children: [],
- id: 'foxtrot',
- level: 6,
- value: 'Foxtrot',
- },
- ],
- id: 'echo',
- level: 5,
- value: 'Echo',
- },
- ],
- id: 'delta',
- level: 4,
- value: 'Delta',
- },
- ],
- id: 'charlie',
- level: 3,
- value: 'Charlie',
- },
- ],
- id: 'bravo',
- level: 2,
- value: 'Bravo',
- },
- ]);
-});
-
-test('should process real-world well-formatted md', async () => {
- const md = `
-# title
-
-some text
-
-## section 1
-
-some text
-
-### subsection 1-1
-
-some text
-
-#### subsection 1-1-1
-
-some text
-
-#### subsection 1-1-2
-
-some text
-
-### subsection 1-2
-
-some text
-
-### subsection 1-3
-
-some text
-
-## section 2
-
-some text
-
-### subsection 2-1
-
-some text
-
-### subsection 2-1
-
-some text
-
-## section 3
-
-some text
-
-### subsection 3-1
-
-some text
-
-### subsection 3-2
-
-some text
-
- `;
-
- await expect(getHeadings(md)).resolves.toEqual([
- {
- children: [
- {
- children: [
- {
- children: [],
- id: 'subsection-1-1-1',
- level: 4,
- value: 'subsection 1-1-1',
- },
- {
- children: [],
- id: 'subsection-1-1-2',
- level: 4,
- value: 'subsection 1-1-2',
- },
- ],
- id: 'subsection-1-1',
- level: 3,
- value: 'subsection 1-1',
- },
- {children: [], id: 'subsection-1-2', level: 3, value: 'subsection 1-2'},
- {children: [], id: 'subsection-1-3', level: 3, value: 'subsection 1-3'},
- ],
- id: 'section-1',
- level: 2,
- value: 'section 1',
- },
- {
- children: [
- {children: [], id: 'subsection-2-1', level: 3, value: 'subsection 2-1'},
- {
- children: [],
- id: 'subsection-2-1-1',
- level: 3,
- value: 'subsection 2-1',
- },
- ],
- id: 'section-2',
- level: 2,
- value: 'section 2',
- },
- {
- children: [
- {children: [], id: 'subsection-3-1', level: 3, value: 'subsection 3-1'},
- {children: [], id: 'subsection-3-2', level: 3, value: 'subsection 3-2'},
- ],
- id: 'section-3',
- level: 2,
- value: 'section 3',
- },
- ]);
-});
diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/index.ts b/packages/docusaurus-mdx-loader/src/remark/toc/index.ts
index c5630b796b..80e92b4a6b 100644
--- a/packages/docusaurus-mdx-loader/src/remark/toc/index.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/toc/index.ts
@@ -9,10 +9,14 @@ import {parse, type ParserOptions} from '@babel/parser';
import type {Identifier} from '@babel/types';
import traverse from '@babel/traverse';
import stringifyObject from 'stringify-object';
-import search from './search';
-import type {Plugin, Transformer} from 'unified';
+import toString from 'mdast-util-to-string';
+import visit from 'unist-util-visit';
+import {toValue} from '../utils';
+
+import type {TOCItem} from '@docusaurus/types';
import type {Node, Parent} from 'unist';
-import type {Literal} from 'mdast';
+import type {Heading, Literal} from 'mdast';
+import type {Plugin, Transformer} from 'unified';
const parseOptions: ParserOptions = {
plugins: ['jsx'],
@@ -70,7 +74,22 @@ const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
const name = options.name || 'toc';
const transformer: Transformer = (node) => {
- const headings = search(node);
+ const headings: TOCItem[] = [];
+
+ visit(node, 'heading', (child: Heading, _index, parent) => {
+ const value = toString(child);
+
+ // depth:1 headings are titles and not included in the TOC
+ if (parent !== node || !value || child.depth < 2) {
+ return;
+ }
+
+ headings.push({
+ value: toValue(child),
+ id: child.data!.id as string,
+ level: child.depth,
+ });
+ });
const {children} = node as Parent;
const targetIndex = getOrCreateExistingTargetIndex(children, name);
diff --git a/packages/docusaurus-mdx-loader/src/remark/toc/search.ts b/packages/docusaurus-mdx-loader/src/remark/toc/search.ts
deleted file mode 100644
index ea8fc8b704..0000000000
--- a/packages/docusaurus-mdx-loader/src/remark/toc/search.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * 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 toString from 'mdast-util-to-string';
-import visit from 'unist-util-visit';
-import {toValue} from '../utils';
-import type {TOCItem} from '@docusaurus/types';
-import type {Node} from 'unist';
-import type {Heading} from 'mdast';
-
-// Intermediate interface for TOC algorithm
-interface SearchItem {
- node: TOCItem;
- level: number;
- parentIndex: number;
-}
-
-/**
- *
- * Generate a TOC AST from the raw Markdown contents
- */
-export default function search(node: Node): TOCItem[] {
- const headings: SearchItem[] = [];
-
- visit(node, 'heading', (child: Heading, _index, parent) => {
- const value = toString(child);
-
- // depth:1 headings are titles and not included in the TOC
- if (parent !== node || !value || child.depth < 2) {
- return;
- }
-
- headings.push({
- node: {
- value: toValue(child),
- id: child.data!.id as string,
- children: [],
- level: child.depth,
- },
- level: child.depth,
- parentIndex: -1,
- });
- });
-
- // Keep track of which previous index would be the current heading's direct
- // parent. Each entry is the last index of the `headings` array at heading
- // level . We will modify these indices as we iterate through all headings.
- // e.g. if an ### H3 was last seen at index 2, then prevIndexForLevel[3] === 2
- // indices 0 and 1 will remain unused.
- const prevIndexForLevel = Array(7).fill(-1);
-
- headings.forEach((curr, currIndex) => {
- // take the last seen index for each ancestor level. the highest
- // index will be the direct ancestor of the current heading.
- const ancestorLevelIndexes = prevIndexForLevel.slice(2, curr.level);
- curr.parentIndex = Math.max(...ancestorLevelIndexes);
- // mark that curr.level was last seen at the current index
- prevIndexForLevel[curr.level] = currIndex;
- });
-
- const rootNodeIndexes: number[] = [];
-
- // For a given parentIndex, add each Node into that parent's `children` array
- headings.forEach((heading, i) => {
- if (heading.parentIndex >= 0) {
- headings[heading.parentIndex].node.children.push(heading.node);
- } else {
- rootNodeIndexes.push(i);
- }
- });
-
- const toc = headings
- .filter((_, k) => rootNodeIndexes.includes(k)) // only return root nodes
- .map((heading) => heading.node); // only return Node, no metadata
- return toc;
-}
diff --git a/packages/docusaurus-theme-classic/src/theme/TOCItems/index.tsx b/packages/docusaurus-theme-classic/src/theme/TOCItems/index.tsx
index 18715350f3..b0bed7c2bd 100644
--- a/packages/docusaurus-theme-classic/src/theme/TOCItems/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/TOCItems/index.tsx
@@ -7,12 +7,12 @@
import React, {useMemo} from 'react';
import type {Props} from '@theme/TOCItems';
-import type {TOCItem} from '@docusaurus/types';
import {
type TOCHighlightConfig,
+ type TOCTreeNode,
useThemeConfig,
- useTOCFilter,
useTOCHighlight,
+ useFilteredAndTreeifiedTOC,
} from '@docusaurus/theme-common';
// Recursive component rendering the toc tree
@@ -23,7 +23,7 @@ function TOCItemList({
linkClassName,
isChild,
}: {
- readonly toc: readonly TOCItem[];
+ readonly toc: readonly TOCTreeNode[];
readonly className: string;
readonly linkClassName: string | null;
readonly isChild?: boolean;
@@ -70,7 +70,11 @@ export default function TOCItems({
const maxHeadingLevel =
maxHeadingLevelOption ?? themeConfig.tableOfContents.maxHeadingLevel;
- const tocFiltered = useTOCFilter({toc, minHeadingLevel, maxHeadingLevel});
+ const tocTree = useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel,
+ maxHeadingLevel,
+ });
const tocHighlightConfig: TOCHighlightConfig | undefined = useMemo(() => {
if (linkClassName && linkActiveClassName) {
@@ -87,7 +91,7 @@ export default function TOCItems({
return (
{
+describe('useFilteredAndTreeifiedTOC', () => {
test('filter a toc with all heading levels', () => {
const toc: TOCItem[] = [
{
id: 'alpha',
level: 1,
value: 'alpha',
- children: [
- {
- id: 'bravo',
- level: 2,
- value: 'Bravo',
- children: [
- {
- id: 'charlie',
- level: 3,
- value: 'Charlie',
- children: [
- {
- id: 'delta',
- level: 4,
- value: 'Delta',
- children: [
- {
- id: 'echo',
- level: 5,
- value: 'Echo',
- children: [
- {
- id: 'foxtrot',
- level: 6,
- value: 'Foxtrot',
- children: [],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
+ },
+ {
+ id: 'bravo',
+ level: 2,
+ value: 'Bravo',
+ },
+ {
+ id: 'charlie',
+ level: 3,
+ value: 'Charlie',
+ },
+ {
+ id: 'delta',
+ level: 4,
+ value: 'Delta',
+ },
+ {
+ id: 'echo',
+ level: 5,
+ value: 'Echo',
+ },
+ {
+ id: 'foxtrot',
+ level: 6,
+ value: 'Foxtrot',
},
];
- expect(filterTOC({toc, minHeadingLevel: 2, maxHeadingLevel: 2})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 2,
+ maxHeadingLevel: 2,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'bravo',
level: 2,
@@ -63,7 +61,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 3, maxHeadingLevel: 3})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 3,
+ maxHeadingLevel: 3,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'charlie',
level: 3,
@@ -72,7 +78,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 2, maxHeadingLevel: 3})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 2,
+ maxHeadingLevel: 3,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'bravo',
level: 2,
@@ -88,7 +102,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 2, maxHeadingLevel: 4})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 2,
+ maxHeadingLevel: 4,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'bravo',
level: 2,
@@ -121,24 +143,28 @@ describe('filterTOC', () => {
id: 'charlie',
level: 3,
value: 'Charlie',
- children: [],
},
{
id: 'bravo',
level: 2,
value: 'Bravo',
- children: [
- {
- id: 'delta',
- level: 4,
- value: 'Delta',
- children: [],
- },
- ],
+ },
+ {
+ id: 'delta',
+ level: 4,
+ value: 'Delta',
},
];
- expect(filterTOC({toc, minHeadingLevel: 2, maxHeadingLevel: 2})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 2,
+ maxHeadingLevel: 2,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'bravo',
level: 2,
@@ -147,7 +173,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 3, maxHeadingLevel: 3})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 3,
+ maxHeadingLevel: 3,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'charlie',
level: 3,
@@ -156,7 +190,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 4, maxHeadingLevel: 4})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 4,
+ maxHeadingLevel: 4,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'delta',
level: 4,
@@ -165,7 +207,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 2, maxHeadingLevel: 3})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 2,
+ maxHeadingLevel: 3,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'charlie',
level: 3,
@@ -180,7 +230,15 @@ describe('filterTOC', () => {
},
]);
- expect(filterTOC({toc, minHeadingLevel: 3, maxHeadingLevel: 4})).toEqual([
+ expect(
+ renderHook(() =>
+ useFilteredAndTreeifiedTOC({
+ toc,
+ minHeadingLevel: 3,
+ maxHeadingLevel: 4,
+ }),
+ ).result.current,
+ ).toEqual([
{
id: 'charlie',
level: 3,
diff --git a/packages/docusaurus-theme-common/src/utils/tocUtils.ts b/packages/docusaurus-theme-common/src/utils/tocUtils.ts
index 0e88c9fb4f..6f00ebc3db 100644
--- a/packages/docusaurus-theme-common/src/utils/tocUtils.ts
+++ b/packages/docusaurus-theme-common/src/utils/tocUtils.ts
@@ -8,18 +8,64 @@
import {useMemo} from 'react';
import type {TOCItem} from '@docusaurus/types';
-type FilterTOCParam = {
- toc: readonly TOCItem[];
- minHeadingLevel: number;
- maxHeadingLevel: number;
+export type TOCTreeNode = {
+ readonly value: string;
+ readonly id: string;
+ readonly level: number;
+ readonly children: readonly TOCTreeNode[];
};
-export function filterTOC({
+function treeifyTOC(flatTOC: readonly TOCItem[]): TOCTreeNode[] {
+ const headings = flatTOC.map((heading) => ({
+ ...heading,
+ parentIndex: -1,
+ children: [] as TOCTreeNode[],
+ }));
+
+ // Keep track of which previous index would be the current heading's direct
+ // parent. Each entry is the last index of the `headings` array at heading
+ // level . We will modify these indices as we iterate through all headings.
+ // e.g. if an ### H3 was last seen at index 2, then prevIndexForLevel[3] === 2
+ // indices 0 and 1 will remain unused.
+ const prevIndexForLevel = Array(7).fill(-1);
+
+ headings.forEach((curr, currIndex) => {
+ // take the last seen index for each ancestor level. the highest
+ // index will be the direct ancestor of the current heading.
+ const ancestorLevelIndexes = prevIndexForLevel.slice(2, curr.level);
+ curr.parentIndex = Math.max(...ancestorLevelIndexes);
+ // mark that curr.level was last seen at the current index
+ prevIndexForLevel[curr.level] = currIndex;
+ });
+
+ const rootNodes: TOCTreeNode[] = [];
+
+ // For a given parentIndex, add each Node into that parent's `children` array
+ headings.forEach((heading) => {
+ const {parentIndex, ...rest} = heading;
+ if (parentIndex >= 0) {
+ headings[parentIndex].children.push(rest);
+ } else {
+ rootNodes.push(rest);
+ }
+ });
+ return rootNodes;
+}
+
+export function useTreeifiedTOC(toc: TOCItem[]): readonly TOCTreeNode[] {
+ return useMemo(() => treeifyTOC(toc), [toc]);
+}
+
+function filterTOC({
toc,
minHeadingLevel,
maxHeadingLevel,
-}: FilterTOCParam): TOCItem[] {
- function isValid(item: TOCItem) {
+}: {
+ toc: readonly TOCTreeNode[];
+ minHeadingLevel: number;
+ maxHeadingLevel: number;
+}): TOCTreeNode[] {
+ function isValid(item: TOCTreeNode) {
return item.level >= minHeadingLevel && item.level <= maxHeadingLevel;
}
@@ -41,14 +87,22 @@ export function filterTOC({
});
}
-// Memoize potentially expensive filtering logic
-export function useTOCFilter({
+export function useFilteredAndTreeifiedTOC({
toc,
minHeadingLevel,
maxHeadingLevel,
-}: FilterTOCParam): readonly TOCItem[] {
+}: {
+ toc: readonly TOCItem[];
+ minHeadingLevel: number;
+ maxHeadingLevel: number;
+}): readonly TOCTreeNode[] {
return useMemo(
- () => filterTOC({toc, minHeadingLevel, maxHeadingLevel}),
+ () =>
+ // Note: we have to filter the TOC after it has been treeified. This is
+ // mostly to ensure that weird TOC structures preserve their semantics.
+ // For example, an h3-h2-h4 sequence should not be treeified as an h3 > h4
+ // hierarchy with min=3, max=4, but should rather be [h3, h4]
+ filterTOC({toc: treeifyTOC(toc), minHeadingLevel, maxHeadingLevel}),
[toc, minHeadingLevel, maxHeadingLevel],
);
}
diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts
index a33d8c5e81..f664c66c69 100644
--- a/packages/docusaurus-types/src/index.d.ts
+++ b/packages/docusaurus-types/src/index.d.ts
@@ -429,12 +429,11 @@ export interface ThemeConfigValidationContext {
themeConfig: Partial;
}
-export interface TOCItem {
+export type TOCItem = {
readonly value: string;
readonly id: string;
- readonly children: TOCItem[];
readonly level: number;
-}
+};
export type RouteChunksTree = {[x: string | number]: string | RouteChunksTree};
diff --git a/project-words.txt b/project-words.txt
index e3fa93bff9..940a50943f 100644
--- a/project-words.txt
+++ b/project-words.txt
@@ -246,6 +246,7 @@ stylelintrc
sublabel
sublicensable
sublist
+subsubsection
subpage
subroute
subroutes
@@ -260,6 +261,7 @@ toolset
toplevel
transifex
transpiles
+treeified
treeify
treosh
triaging
diff --git a/website/docs/cli.md b/website/docs/cli.md
index 5955f30f78..44980ef6c4 100644
--- a/website/docs/cli.md
+++ b/website/docs/cli.md
@@ -25,12 +25,6 @@ Once your website is bootstrapped, the website source will contain the Docusauru
}
```
-## Index {#index}
-
-import TOCInline from "@theme/TOCInline"
-
-
-
## Docusaurus CLI commands {#docusaurus-cli-commands}
Below is a list of Docusaurus CLI commands and their usages:
diff --git a/website/docs/configuration.md b/website/docs/configuration.md
index c91354a6e6..161882929c 100644
--- a/website/docs/configuration.md
+++ b/website/docs/configuration.md
@@ -17,7 +17,7 @@ However, it can be helpful if you have a high-level understanding of how the con
The high-level overview of Docusaurus configuration can be categorized into:
-
+
For exact reference to each of the configurable fields, you may refer to [**`docusaurus.config.js` API reference**](api/docusaurus.config.js.md).
diff --git a/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx b/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx
index c8a8eaf567..4a48251ac4 100644
--- a/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx
+++ b/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx
@@ -35,33 +35,30 @@ import TOCInline from '@theme/TOCInline';
## Custom table of contents {#custom-table-of-contents}
-The `toc` props is just a list of table of contents items:
+The `toc` prop is just a list of heading items:
```ts
type TOCItem = {
value: string;
id: string;
- children: TOCItem[];
level: number;
};
```
-You can create this TOC tree manually, or derive a new TOC tree from the `toc` variable:
+Note that the `toc` global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree.
```jsx
import TOCInline from '@theme/TOCInline';
node.level === 2 || node.level === 4)}
/>;
```
```mdx-code-block
-
+ node.level === 2 || node.level === 4)} />
```
@@ -81,14 +78,32 @@ Lorem ipsum
Lorem ipsum
+#### Example subsubsection 1 a I
+
+#### Example subsubsection 1 a II
+
+#### Example subsubsection 1 a III
+
### Example Subsection 1 b {#example-subsection-1-b}
Lorem ipsum
+#### Example subsubsection 1 b I
+
+#### Example subsubsection 1 b II
+
+#### Example subsubsection 1 b III
+
### Example Subsection 1 c {#example-subsection-1-c}
Lorem ipsum
+#### Example subsubsection 1 c I
+
+#### Example subsubsection 1 c II
+
+#### Example subsubsection 1 c III
+
## Example Section 2 {#example-section-2}
Lorem ipsum
@@ -97,14 +112,32 @@ Lorem ipsum
Lorem ipsum
+#### Example subsubsection 2 a I
+
+#### Example subsubsection 2 a II
+
+#### Example subsubsection 2 a III
+
### Example Subsection 2 b {#example-subsection-2-b}
Lorem ipsum
+#### Example subsubsection 2 b I
+
+#### Example subsubsection 2 b II
+
+#### Example subsubsection 2 b III
+
### Example Subsection 2 c {#example-subsection-2-c}
Lorem ipsum
+#### Example subsubsection 2 c I
+
+#### Example subsubsection 2 c II
+
+#### Example subsubsection 2 c III
+
## Example Section 3 {#example-section-3}
Lorem ipsum
@@ -113,10 +146,28 @@ Lorem ipsum
Lorem ipsum
+#### Example subsubsection 3 a I
+
+#### Example subsubsection 3 a II
+
+#### Example subsubsection 3 a III
+
### Example Subsection 3 b {#example-subsection-3-b}
Lorem ipsum
+#### Example subsubsection 3 b I
+
+#### Example subsubsection 3 b II
+
+#### Example subsubsection 3 b III
+
### Example Subsection 3 c {#example-subsection-3-c}
Lorem ipsum
+
+#### Example subsubsection 3 c I
+
+#### Example subsubsection 3 c II
+
+#### Example subsubsection 3 c III
diff --git a/website/versioned_docs/version-2.0.0-beta.14/cli.md b/website/versioned_docs/version-2.0.0-beta.14/cli.md
index 9ea0d48af1..a88cb82b04 100644
--- a/website/versioned_docs/version-2.0.0-beta.14/cli.md
+++ b/website/versioned_docs/version-2.0.0-beta.14/cli.md
@@ -25,12 +25,6 @@ Once your website is bootstrapped, the website source will contain the Docusauru
}
```
-## Index {#index}
-
-import TOCInline from "@theme/TOCInline"
-
-
-
## Docusaurus CLI commands {#docusaurus-cli-commands}
Below is a list of Docusaurus CLI commands and their usages:
diff --git a/website/versioned_docs/version-2.0.0-beta.14/configuration.md b/website/versioned_docs/version-2.0.0-beta.14/configuration.md
index c10a1692c9..00b42d0172 100644
--- a/website/versioned_docs/version-2.0.0-beta.14/configuration.md
+++ b/website/versioned_docs/version-2.0.0-beta.14/configuration.md
@@ -17,7 +17,7 @@ However, it can be helpful if you have a high-level understanding of how the con
The high-level overview of Docusaurus configuration can be categorized into:
-
+
For exact reference to each of the configurable fields, you may refer to [**`docusaurus.config.js` API reference**](api/docusaurus.config.js.md).
diff --git a/website/versioned_docs/version-2.0.0-beta.14/guides/markdown-features/markdown-features-inline-toc.mdx b/website/versioned_docs/version-2.0.0-beta.14/guides/markdown-features/markdown-features-inline-toc.mdx
index 3726f04842..d3ad685831 100644
--- a/website/versioned_docs/version-2.0.0-beta.14/guides/markdown-features/markdown-features-inline-toc.mdx
+++ b/website/versioned_docs/version-2.0.0-beta.14/guides/markdown-features/markdown-features-inline-toc.mdx
@@ -59,14 +59,6 @@ import TOCInline from '@theme/TOCInline';
/>;
```
-```mdx-code-block
-
-
-
-
-
-```
-
---
:::caution
diff --git a/website/versioned_docs/version-2.0.0-beta.15/cli.md b/website/versioned_docs/version-2.0.0-beta.15/cli.md
index a491f7f618..b2593ca4b0 100644
--- a/website/versioned_docs/version-2.0.0-beta.15/cli.md
+++ b/website/versioned_docs/version-2.0.0-beta.15/cli.md
@@ -25,12 +25,6 @@ Once your website is bootstrapped, the website source will contain the Docusauru
}
```
-## Index {#index}
-
-import TOCInline from "@theme/TOCInline"
-
-
-
## Docusaurus CLI commands {#docusaurus-cli-commands}
Below is a list of Docusaurus CLI commands and their usages:
diff --git a/website/versioned_docs/version-2.0.0-beta.15/configuration.md b/website/versioned_docs/version-2.0.0-beta.15/configuration.md
index c91354a6e6..161882929c 100644
--- a/website/versioned_docs/version-2.0.0-beta.15/configuration.md
+++ b/website/versioned_docs/version-2.0.0-beta.15/configuration.md
@@ -17,7 +17,7 @@ However, it can be helpful if you have a high-level understanding of how the con
The high-level overview of Docusaurus configuration can be categorized into:
-
+
For exact reference to each of the configurable fields, you may refer to [**`docusaurus.config.js` API reference**](api/docusaurus.config.js.md).
diff --git a/website/versioned_docs/version-2.0.0-beta.15/guides/markdown-features/markdown-features-inline-toc.mdx b/website/versioned_docs/version-2.0.0-beta.15/guides/markdown-features/markdown-features-inline-toc.mdx
index c8a8eaf567..bfdc6c1a6d 100644
--- a/website/versioned_docs/version-2.0.0-beta.15/guides/markdown-features/markdown-features-inline-toc.mdx
+++ b/website/versioned_docs/version-2.0.0-beta.15/guides/markdown-features/markdown-features-inline-toc.mdx
@@ -59,12 +59,6 @@ import TOCInline from '@theme/TOCInline';
/>;
```
-```mdx-code-block
-
-
-
-```
-
---
:::caution