mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-15 10:07:33 +02:00
feat(v2): inline table-of-contents + refactor TOC (#3904)
* Add TOCInline theme component * Add TOCInline theme component doc + migration guide * remove useless getPathsToWatch on classic theme * rename rightToc to toc * add temp theme-bootstrap TOCInline comp to fix build issue
This commit is contained in:
parent
b11c24b752
commit
41ef333e47
28 changed files with 206 additions and 36 deletions
|
@ -12,13 +12,13 @@ const emoji = require('remark-emoji');
|
||||||
const matter = require('gray-matter');
|
const matter = require('gray-matter');
|
||||||
const stringifyObject = require('stringify-object');
|
const stringifyObject = require('stringify-object');
|
||||||
const slug = require('./remark/slug');
|
const slug = require('./remark/slug');
|
||||||
const rightToc = require('./remark/rightToc');
|
const toc = require('./remark/toc');
|
||||||
const transformImage = require('./remark/transformImage');
|
const transformImage = require('./remark/transformImage');
|
||||||
const transformLinks = require('./remark/transformLinks');
|
const transformLinks = require('./remark/transformLinks');
|
||||||
|
|
||||||
const DEFAULT_OPTIONS = {
|
const DEFAULT_OPTIONS = {
|
||||||
rehypePlugins: [],
|
rehypePlugins: [],
|
||||||
remarkPlugins: [emoji, slug, rightToc],
|
remarkPlugins: [emoji, slug, toc],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async function docusaurusMdxLoader(fileString) {
|
module.exports = async function docusaurusMdxLoader(fileString) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`inline code should be escaped 1`] = `
|
exports[`inline code should be escaped 1`] = `
|
||||||
"export const rightToc = [
|
"export const toc = [
|
||||||
{
|
{
|
||||||
value: '<code><Head /></code>',
|
value: '<code><Head /></code>',
|
||||||
id: 'head-',
|
id: 'head-',
|
||||||
|
@ -43,7 +43,7 @@ exports[`inline code should be escaped 1`] = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`non text phrasing content 1`] = `
|
exports[`non text phrasing content 1`] = `
|
||||||
"export const rightToc = [
|
"export const toc = [
|
||||||
{
|
{
|
||||||
value: '<em>Emphasis</em>',
|
value: '<em>Emphasis</em>',
|
||||||
id: 'emphasis',
|
id: 'emphasis',
|
|
@ -1,4 +1,4 @@
|
||||||
export const rightToc = ['replaceMe'];
|
export const toc = ['replaceMe'];
|
||||||
|
|
||||||
## Thanos
|
## Thanos
|
||||||
|
|
|
@ -37,7 +37,7 @@ test('inline code should be escaped', async () => {
|
||||||
test('text content', async () => {
|
test('text content', async () => {
|
||||||
const result = await processFixture('just-content');
|
const result = await processFixture('just-content');
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"export const rightToc = [
|
"export const toc = [
|
||||||
{
|
{
|
||||||
value: 'Endi',
|
value: 'Endi',
|
||||||
id: 'endi',
|
id: 'endi',
|
||||||
|
@ -83,7 +83,7 @@ test('text content', async () => {
|
||||||
test('should export even with existing name', async () => {
|
test('should export even with existing name', async () => {
|
||||||
const result = await processFixture('name-exist');
|
const result = await processFixture('name-exist');
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"export const rightToc = [
|
"export const toc = [
|
||||||
{
|
{
|
||||||
value: 'Thanos',
|
value: 'Thanos',
|
||||||
id: 'thanos',
|
id: 'thanos',
|
||||||
|
@ -167,7 +167,7 @@ test('should insert below imports', async () => {
|
||||||
|
|
||||||
import somethingElse from 'something-else';
|
import somethingElse from 'something-else';
|
||||||
|
|
||||||
export const rightToc = [
|
export const toc = [
|
||||||
{
|
{
|
||||||
value: 'Title',
|
value: 'Title',
|
||||||
id: 'title',
|
id: 'title',
|
||||||
|
@ -200,7 +200,7 @@ test('should insert below imports', async () => {
|
||||||
test('empty headings', async () => {
|
test('empty headings', async () => {
|
||||||
const result = await processFixture('empty-headings');
|
const result = await processFixture('empty-headings');
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"export const rightToc = [];
|
"export const toc = [];
|
||||||
|
|
||||||
# Ignore this
|
# Ignore this
|
||||||
|
|
|
@ -59,7 +59,7 @@ const getOrCreateExistingTargetIndex = (children, name) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const plugin = (options = {}) => {
|
const plugin = (options = {}) => {
|
||||||
const name = options.name || 'rightToc';
|
const name = options.name || 'toc';
|
||||||
|
|
||||||
const transformer = (node) => {
|
const transformer = (node) => {
|
||||||
const headings = search(node);
|
const headings = search(node);
|
|
@ -11,7 +11,7 @@ const toString = require('mdast-util-to-string');
|
||||||
const visit = require('unist-util-visit');
|
const visit = require('unist-util-visit');
|
||||||
const {toValue} = require('../utils');
|
const {toValue} = require('../utils');
|
||||||
|
|
||||||
/** @typedef {import('@docusaurus/types').MarkdownRightTableOfContents} TOC */
|
/** @typedef {import('@docusaurus/types').TOCItem} TOC */
|
||||||
/** @typedef {import('unist').Node} Node */
|
/** @typedef {import('unist').Node} Node */
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -24,7 +24,7 @@ declare module '@theme/BlogSidebar' {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@theme/BlogPostPage' {
|
declare module '@theme/BlogPostPage' {
|
||||||
import type {MarkdownRightTableOfContents} from '@docusaurus/types';
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
import type {BlogSidebar} from '@theme/BlogSidebar';
|
import type {BlogSidebar} from '@theme/BlogSidebar';
|
||||||
|
|
||||||
export type FrontMatter = {
|
export type FrontMatter = {
|
||||||
|
@ -61,7 +61,7 @@ declare module '@theme/BlogPostPage' {
|
||||||
export type Content = {
|
export type Content = {
|
||||||
readonly frontMatter: FrontMatter;
|
readonly frontMatter: FrontMatter;
|
||||||
readonly metadata: Metadata;
|
readonly metadata: Metadata;
|
||||||
readonly rightToc: readonly MarkdownRightTableOfContents[];
|
readonly toc: readonly TOCItem[];
|
||||||
(): JSX.Element;
|
(): JSX.Element;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ declare module '@docusaurus/plugin-content-docs-types' {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@theme/DocItem' {
|
declare module '@theme/DocItem' {
|
||||||
import type {MarkdownRightTableOfContents} from '@docusaurus/types';
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
export type DocumentRoute = {
|
export type DocumentRoute = {
|
||||||
readonly component: () => JSX.Element;
|
readonly component: () => JSX.Element;
|
||||||
|
@ -80,7 +80,7 @@ declare module '@theme/DocItem' {
|
||||||
readonly content: {
|
readonly content: {
|
||||||
readonly frontMatter: FrontMatter;
|
readonly frontMatter: FrontMatter;
|
||||||
readonly metadata: Metadata;
|
readonly metadata: Metadata;
|
||||||
readonly rightToc: readonly MarkdownRightTableOfContents[];
|
readonly toc: readonly TOCItem[];
|
||||||
(): JSX.Element;
|
(): JSX.Element;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare module '@theme/MDXPage' {
|
declare module '@theme/MDXPage' {
|
||||||
import type {MarkdownRightTableOfContents} from '@docusaurus/types';
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
readonly content: {
|
readonly content: {
|
||||||
|
@ -17,7 +17,7 @@ declare module '@theme/MDXPage' {
|
||||||
readonly hide_table_of_contents?: string;
|
readonly hide_table_of_contents?: string;
|
||||||
};
|
};
|
||||||
readonly metadata: {readonly permalink: string};
|
readonly metadata: {readonly permalink: string};
|
||||||
readonly rightToc: readonly MarkdownRightTableOfContents[];
|
readonly toc: readonly TOCItem[];
|
||||||
(): JSX.Element;
|
(): JSX.Element;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
function TOCInline(_props: any): JSX.Element {
|
||||||
|
return <div>TODO bootstrap toc</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TOCInline;
|
|
@ -15,7 +15,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc --noEmit && yarn babel:lib && yarn babel:lib-next && yarn prettier",
|
"build": "tsc --noEmit && yarn babel:lib && yarn babel:lib-next && yarn prettier",
|
||||||
"watch": "yarn babel:lib --watch",
|
"watch": "concurrently -n \"lib,lib-next\" --kill-others \"yarn babel:lib --watch\" \"yarn babel:lib-next --watch\"",
|
||||||
"babel:lib": "cross-env BABEL_ENV=lib babel src -d lib --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
|
"babel:lib": "cross-env BABEL_ENV=lib babel src -d lib --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
|
||||||
"babel:lib-next": "cross-env BABEL_ENV=lib-next babel src -d lib-next --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
|
"babel:lib-next": "cross-env BABEL_ENV=lib-next babel src -d lib-next --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
|
||||||
"prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --write \"**/*.{js,ts}\""
|
"prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --write \"**/*.{js,ts}\""
|
||||||
|
|
|
@ -72,6 +72,16 @@ export default function docusaurusThemeClassic(
|
||||||
return {
|
return {
|
||||||
name: 'docusaurus-theme-classic',
|
name: 'docusaurus-theme-classic',
|
||||||
|
|
||||||
|
/*
|
||||||
|
Does not seem needed: webpack can already hot reload theme files
|
||||||
|
getPathsToWatch() {
|
||||||
|
return [
|
||||||
|
path.join(__dirname, '..', 'lib'),
|
||||||
|
path.join(__dirname, '..', 'lib-next'),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
getThemePath() {
|
getThemePath() {
|
||||||
return path.join(__dirname, '..', 'lib-next', 'theme');
|
return path.join(__dirname, '..', 'lib-next', 'theme');
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,9 +53,9 @@ function BlogPostPage(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
{!hideTableOfContents && BlogPostContents.rightToc && (
|
{!hideTableOfContents && BlogPostContents.toc && (
|
||||||
<div className="col col--2">
|
<div className="col col--2">
|
||||||
<TOC headings={BlogPostContents.rightToc} />
|
<TOC toc={BlogPostContents.toc} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -162,9 +162,9 @@ function DocItem(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!hideTableOfContents && DocContent.rightToc && (
|
{!hideTableOfContents && DocContent.toc && (
|
||||||
<div className="col col--3">
|
<div className="col col--3">
|
||||||
<TOC headings={DocContent.rightToc} />
|
<TOC toc={DocContent.toc} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -41,9 +41,9 @@ function MDXPage(props: Props): JSX.Element {
|
||||||
</MDXProvider>
|
</MDXProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!hideTableOfContents && MDXPageContent.rightToc && (
|
{!hideTableOfContents && MDXPageContent.toc && (
|
||||||
<div className="col col--2">
|
<div className="col col--2">
|
||||||
<TOC headings={MDXPageContent.rightToc} />
|
<TOC toc={MDXPageContent.toc} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,14 +10,21 @@ import clsx from 'clsx';
|
||||||
import useTOCHighlight from '@theme/hooks/useTOCHighlight';
|
import useTOCHighlight from '@theme/hooks/useTOCHighlight';
|
||||||
import type {TOCProps} from '@theme/TOC';
|
import type {TOCProps} from '@theme/TOC';
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
import {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
const LINK_CLASS_NAME = 'table-of-contents__link';
|
const LINK_CLASS_NAME = 'table-of-contents__link';
|
||||||
const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active';
|
const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active';
|
||||||
const TOP_OFFSET = 100;
|
const TOP_OFFSET = 100;
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||||
function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) {
|
function Headings({
|
||||||
if (!headings.length) {
|
toc,
|
||||||
|
isChild,
|
||||||
|
}: {
|
||||||
|
toc: readonly TOCItem[];
|
||||||
|
isChild?: boolean;
|
||||||
|
}) {
|
||||||
|
if (!toc.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -25,7 +32,7 @@ function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) {
|
||||||
className={
|
className={
|
||||||
isChild ? '' : 'table-of-contents table-of-contents__left-border'
|
isChild ? '' : 'table-of-contents table-of-contents__left-border'
|
||||||
}>
|
}>
|
||||||
{headings.map((heading) => (
|
{toc.map((heading) => (
|
||||||
<li key={heading.id}>
|
<li key={heading.id}>
|
||||||
<a
|
<a
|
||||||
href={`#${heading.id}`}
|
href={`#${heading.id}`}
|
||||||
|
@ -34,18 +41,18 @@ function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) {
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{__html: heading.value}}
|
dangerouslySetInnerHTML={{__html: heading.value}}
|
||||||
/>
|
/>
|
||||||
<Headings isChild headings={heading.children} />
|
<Headings isChild toc={heading.children} />
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TOC({headings}: TOCProps): JSX.Element {
|
function TOC({toc}: TOCProps): JSX.Element {
|
||||||
useTOCHighlight(LINK_CLASS_NAME, ACTIVE_LINK_CLASS_NAME, TOP_OFFSET);
|
useTOCHighlight(LINK_CLASS_NAME, ACTIVE_LINK_CLASS_NAME, TOP_OFFSET);
|
||||||
return (
|
return (
|
||||||
<div className={clsx(styles.tableOfContents, 'thin-scrollbar')}>
|
<div className={clsx(styles.tableOfContents, 'thin-scrollbar')}>
|
||||||
<Headings headings={headings} />
|
<Headings toc={toc} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 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 clsx from 'clsx';
|
||||||
|
import type {TOCProps} from '@theme/TOC';
|
||||||
|
import styles from './styles.module.css';
|
||||||
|
import {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
|
const LINK_CLASS_NAME = styles['table-of-contents__link--inline'];
|
||||||
|
|
||||||
|
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||||
|
function HeadingsInline({
|
||||||
|
toc,
|
||||||
|
isChild,
|
||||||
|
}: {
|
||||||
|
toc: readonly TOCItem[];
|
||||||
|
isChild?: boolean;
|
||||||
|
}) {
|
||||||
|
if (!toc.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ul className={isChild ? '' : 'table-of-contents'}>
|
||||||
|
{toc.map((heading) => (
|
||||||
|
<li key={heading.id}>
|
||||||
|
<a
|
||||||
|
href={`#${heading.id}`}
|
||||||
|
className={LINK_CLASS_NAME}
|
||||||
|
// Developer provided the HTML, so assume it's safe.
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
|
dangerouslySetInnerHTML={{__html: heading.value}}
|
||||||
|
/>
|
||||||
|
<HeadingsInline isChild toc={heading.children} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TOCInline({toc}: TOCProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className={clsx(styles.tableOfContentsInline)}>
|
||||||
|
<HeadingsInline toc={toc} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TOCInline;
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.tableOfContentsInline ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents__link--inline {
|
||||||
|
color: var(--ifm-toc-link-color);
|
||||||
|
}
|
15
packages/docusaurus-theme-classic/src/types.d.ts
vendored
15
packages/docusaurus-theme-classic/src/types.d.ts
vendored
|
@ -413,16 +413,27 @@ declare module '@theme/ThemeProvider' {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@theme/TOC' {
|
declare module '@theme/TOC' {
|
||||||
import type {MarkdownRightTableOfContents} from '@docusaurus/types';
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
export type TOCProps = {
|
export type TOCProps = {
|
||||||
readonly headings: readonly MarkdownRightTableOfContents[];
|
readonly toc: readonly TOCItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOC: (props: TOCProps) => JSX.Element;
|
const TOC: (props: TOCProps) => JSX.Element;
|
||||||
export default TOC;
|
export default TOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@theme/TOCInline' {
|
||||||
|
import type {TOCItem} from '@docusaurus/types';
|
||||||
|
|
||||||
|
export type TOCInlineProps = {
|
||||||
|
readonly toc: readonly TOCItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const TOCInline: (props: TOCInlineProps) => JSX.Element;
|
||||||
|
export default TOCInline;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '@theme/Toggle' {
|
declare module '@theme/Toggle' {
|
||||||
import {ComponentProps} from 'react';
|
import {ComponentProps} from 'react';
|
||||||
import ReactToggle from 'react-toggle';
|
import ReactToggle from 'react-toggle';
|
||||||
|
|
4
packages/docusaurus-types/src/index.d.ts
vendored
4
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -344,8 +344,8 @@ export interface ValidationSchema<T> {
|
||||||
append(data: any): ValidationSchema<T>;
|
append(data: any): ValidationSchema<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarkdownRightTableOfContents {
|
export interface TOCItem {
|
||||||
readonly value: string;
|
readonly value: string;
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly children: MarkdownRightTableOfContents[];
|
readonly children: TOCItem[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,12 @@ Once your website is bootstrapped, the website source will contain the Docusauru
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
import TOCInline from "@theme/TOCInline"
|
||||||
|
|
||||||
|
<TOCInline toc={toc[1].children}/>
|
||||||
|
|
||||||
## Docusaurus CLI commands
|
## Docusaurus CLI commands
|
||||||
|
|
||||||
Below is a list of Docusaurus CLI commands and their usages:
|
Below is a list of Docusaurus CLI commands and their usages:
|
||||||
|
|
|
@ -471,6 +471,61 @@ import TabItem from '@theme/TabItem';
|
||||||
<TabItem value="banana">This is a banana 🍌</TabItem>
|
<TabItem value="banana">This is a banana 🍌</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
## Inline table of contents
|
||||||
|
|
||||||
|
Each markdown document displays a tab of content on the top-right corner.
|
||||||
|
|
||||||
|
But it is also possible to display an inline table of contents directly inside a markdown document, thanks to MDX.
|
||||||
|
|
||||||
|
### Full table of contents
|
||||||
|
|
||||||
|
The `toc` variable is available in any MDX document, and contain all the top level headings of a MDX document.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import TOCInline from '@theme/TOCInline';
|
||||||
|
|
||||||
|
<TOCInline toc={toc} />;
|
||||||
|
```
|
||||||
|
|
||||||
|
import TOCInline from '@theme/TOCInline';
|
||||||
|
|
||||||
|
<BrowserWindow>
|
||||||
|
|
||||||
|
<TOCInline toc={toc} />
|
||||||
|
|
||||||
|
</BrowserWindow>
|
||||||
|
|
||||||
|
### Custom table of contents
|
||||||
|
|
||||||
|
The `toc` props is just a list of table of contents items:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type TOCItem = {
|
||||||
|
value: string;
|
||||||
|
id: string;
|
||||||
|
children: TOCItem[];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
You can create this TOC tree manually, or derive a new TOC tree from the `toc` variable:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import TOCInline from '@theme/TOCInline';
|
||||||
|
|
||||||
|
<TOCInline
|
||||||
|
toc={
|
||||||
|
// Only show 4th and 5th top-level heading
|
||||||
|
[toc[3], toc[4]]
|
||||||
|
}
|
||||||
|
/>;
|
||||||
|
```
|
||||||
|
|
||||||
|
<BrowserWindow>
|
||||||
|
|
||||||
|
<TOCInline toc={[toc[3], toc[4]]} />
|
||||||
|
|
||||||
|
</BrowserWindow>
|
||||||
|
|
||||||
## Callouts/admonitions
|
## Callouts/admonitions
|
||||||
|
|
||||||
In addition to the basic Markdown syntax, we use [remark-admonitions](https://github.com/elviswolcott/remark-admonitions) alongside MDX to add support for admonitions. Admonitions are wrapped by a set of 3 colons.
|
In addition to the basic Markdown syntax, we use [remark-admonitions](https://github.com/elviswolcott/remark-admonitions) alongside MDX to add support for admonitions. Admonitions are wrapped by a set of 3 colons.
|
||||||
|
|
|
@ -554,9 +554,9 @@ The following code could be helpful for migration of various pages:
|
||||||
|
|
||||||
## Content
|
## Content
|
||||||
|
|
||||||
### Remove AUTOGENERATED_TABLE_OF_CONTENTS
|
### Replace AUTOGENERATED_TABLE_OF_CONTENTS
|
||||||
|
|
||||||
This feature is deprecated. You may read more about it in [this issue](https://github.com/facebook/docusaurus/issues/1549). If you need the feature, use [remark-toc](https://github.com/remarkjs/remark-toc) instead and pass it to docs plugin's `remarkPlugins` option.
|
This feature is replaced by [inline table of content](../markdown-features.mdx#inline-table-of-contents)
|
||||||
|
|
||||||
### Update Markdown syntax to be MDX-compatible
|
### Update Markdown syntax to be MDX-compatible
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue