feat(v2): allow specifying TOC max depth (themeConfig + frontMatter) (#5578)

* 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>
This commit is contained in:
Erick Zhao 2021-09-29 02:19:11 -07:00 committed by GitHub
parent caba1e4908
commit c86dfbda61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1522 additions and 214 deletions

View file

@ -91,6 +91,10 @@ describe('themeConfig', () => {
},
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc. Built with Docusaurus.`,
},
tableOfContents: {
minHeadingLevel: 2,
maxHeadingLevel: 5,
},
};
expect(testValidateThemeConfig(userConfig)).toEqual({
...DEFAULT_CONFIG,
@ -453,3 +457,131 @@ describe('themeConfig', () => {
});
});
});
describe('themeConfig tableOfContents', () => {
test('toc undefined', () => {
const tableOfContents = undefined;
expect(testValidateThemeConfig({tableOfContents})).toEqual({
...DEFAULT_CONFIG,
tableOfContents: {
minHeadingLevel: DEFAULT_CONFIG.tableOfContents.minHeadingLevel,
maxHeadingLevel: DEFAULT_CONFIG.tableOfContents.maxHeadingLevel,
},
});
});
test('toc empty', () => {
const tableOfContents = {};
expect(testValidateThemeConfig({tableOfContents})).toEqual({
...DEFAULT_CONFIG,
tableOfContents: {
minHeadingLevel: DEFAULT_CONFIG.tableOfContents.minHeadingLevel,
maxHeadingLevel: DEFAULT_CONFIG.tableOfContents.maxHeadingLevel,
},
});
});
test('toc with min', () => {
const tableOfContents = {
minHeadingLevel: 3,
};
expect(testValidateThemeConfig({tableOfContents})).toEqual({
...DEFAULT_CONFIG,
tableOfContents: {
minHeadingLevel: 3,
maxHeadingLevel: DEFAULT_CONFIG.tableOfContents.maxHeadingLevel,
},
});
});
test('toc with max', () => {
const tableOfContents = {
maxHeadingLevel: 5,
};
expect(testValidateThemeConfig({tableOfContents})).toEqual({
...DEFAULT_CONFIG,
tableOfContents: {
minHeadingLevel: DEFAULT_CONFIG.tableOfContents.minHeadingLevel,
maxHeadingLevel: 5,
},
});
});
test('toc with min 2.5', () => {
const tableOfContents = {
minHeadingLevel: 2.5,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.minHeadingLevel\\" must be an integer"`,
);
});
test('toc with max 2.5', () => {
const tableOfContents = {
maxHeadingLevel: 2.5,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.maxHeadingLevel\\" must be an integer"`,
);
});
test('toc with min 1', () => {
const tableOfContents = {
minHeadingLevel: 1,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.minHeadingLevel\\" must be greater than or equal to 2"`,
);
});
test('toc with min 7', () => {
const tableOfContents = {
minHeadingLevel: 7,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.minHeadingLevel\\" must be less than or equal to ref:maxHeadingLevel"`,
);
});
test('toc with max 1', () => {
const tableOfContents = {
maxHeadingLevel: 1,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.maxHeadingLevel\\" must be greater than or equal to 2"`,
);
});
test('toc with max 7', () => {
const tableOfContents = {
maxHeadingLevel: 7,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.maxHeadingLevel\\" must be less than or equal to 6"`,
);
});
test('toc with bad min 5 + max 3', () => {
const tableOfContents = {
minHeadingLevel: 5,
maxHeadingLevel: 3,
};
expect(() =>
testValidateThemeConfig({tableOfContents}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"tableOfContents.minHeadingLevel\\" must be less than or equal to ref:maxHeadingLevel"`,
);
});
});