From dffe102381033a2f4f0c7b3ac375fd1cf08dcc41 Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Fri, 15 Feb 2019 16:27:35 +0000 Subject: [PATCH 01/13] [docs] Fix fragment id for i18n --- docs/src/modules/components/AppTableOfContents.js | 15 ++++++++++++--- docs/translations/translations-fr.json | 1 + docs/translations/translations-zh.json | 1 + docs/translations/translations.json | 1 + .../src/MarkdownElement/MarkdownElement.js | 9 ++++++--- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 2c694cc9f7700b..1cca1fa30832ca 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -11,6 +11,8 @@ import { withStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import { textToHash } from '@material-ui/docs/MarkdownElement/MarkdownElement'; import Link from 'docs/src/modules/components/Link'; +import compose from 'docs/src/modules/utils/compose'; +import {connect} from 'react-redux'; let itemsCollector; const renderer = new marked.Renderer(); @@ -64,6 +66,7 @@ const styles = theme => ({ }, contents: { marginTop: theme.spacing(2), + paddingLeft: theme.spacing(1.5), }, ul: { padding: 0, @@ -216,7 +219,7 @@ class AppTableOfContents extends React.Component { }; render() { - const { classes } = this.props; + const { classes, t } = this.props; const { active } = this.state; return ( @@ -224,7 +227,7 @@ class AppTableOfContents extends React.Component { {this.itemsServer.length > 0 ? ( - Contents + {t('tableOfContents')} @@ -278,6 +281,12 @@ class AppTableOfContents extends React.Component { AppTableOfContents.propTypes = { classes: PropTypes.object.isRequired, contents: PropTypes.array.isRequired, + t: PropTypes.func.isRequired, }; -export default withStyles(styles)(AppTableOfContents); +export default compose( + connect(state => ({ + t: state.options.t, + })), + withStyles(styles), +)(AppTableOfContents); diff --git a/docs/translations/translations-fr.json b/docs/translations/translations-fr.json index 7892b767d6a4cc..7211b1a9ec6309 100644 --- a/docs/translations/translations-fr.json +++ b/docs/translations/translations-fr.json @@ -28,6 +28,7 @@ "thanks": "Merci !", "adTitle": "Cette annonce est conçu pour soutenir l'Open Source.", "editPage": "Aidez à traduire cette page", + "tableOfContents": "Matières", "component": "Kit de composants", "mdbProDescr": "Material Dashboard Pro React est un theme Admin Material-UI premium.", "mkProDescr": "Un theme de composants premium Material-UI basé sur Material Design.", diff --git a/docs/translations/translations-zh.json b/docs/translations/translations-zh.json index e8c6bbbe291657..eb310c3ff518c9 100644 --- a/docs/translations/translations-zh.json +++ b/docs/translations/translations-zh.json @@ -28,6 +28,7 @@ "thanks": "感谢!", "adTitle": "该广告旨在支持开源代码。", "editPage": "帮助改进此页面的翻译", + "tableOfContents": "目录", "component": "组件包", "mdbProDescr": "Material Dashboard Pro React 是一个专业版的 Material-UI 管理员主题。", "mkProDescr": "一个根据 Material Design 开发的超棒的 Material-UI 组件。", diff --git a/docs/translations/translations.json b/docs/translations/translations.json index ace4e58207e45b..cdb1ac2995ca37 100644 --- a/docs/translations/translations.json +++ b/docs/translations/translations.json @@ -30,6 +30,7 @@ "thanks": "Thank you!", "adTitle": "This ad is designed to support Open Source.", "editPage": "Edit this page", + "tableOfContents": "Contents", "component": "Component Kit", "mdbProDescr": "Material Dashboard Pro React is a premium Material-UI admin theme.", "mkProDescr": "A Badass Material-UI Kit based on Material Design.", diff --git a/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js b/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js index 0cee732e16dd92..826b98bd196121 100644 --- a/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js +++ b/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js @@ -19,11 +19,14 @@ marked.Lexer.prototype.lex = function lex(src) { const renderer = new marked.Renderer(); export function textToHash(text) { - return text + return encodeURI(text .toLowerCase() .replace(/=>|<| \/>||<\/code>/g, '') - .replace(/\W+/g, '-') - .replace(/-$/g, ''); + .replace(/\s+/g, '-') + // eslint-disable-next-line no-useless-escape, eslint bug? + .replace(/[!@#\$%\^&\*\(\)=_\+\[\]{}`~;:'"\|,\.<>\/\?]+/g, '') + .replace(/-$/g, '') + ) } renderer.heading = (text, level) => { From b47e172c766709c362ad683b3541d31fd5d6e0bd Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 00:45:32 +0000 Subject: [PATCH 02/13] Convert AppTableOfContents to hooks --- .../modules/components/AppTableOfContents.js | 320 +++++++++--------- 1 file changed, 154 insertions(+), 166 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 1cca1fa30832ca..1a7336cceeb235 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -1,6 +1,6 @@ /* eslint-disable react/no-danger */ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import marked from 'marked'; import warning from 'warning'; @@ -14,38 +14,6 @@ import Link from 'docs/src/modules/components/Link'; import compose from 'docs/src/modules/utils/compose'; import {connect} from 'react-redux'; -let itemsCollector; -const renderer = new marked.Renderer(); -renderer.heading = (text, level) => { - if (level === 2) { - itemsCollector.push({ - text, - level, - hash: textToHash(text), - children: [], - }); - } else if (level === 3) { - if (!itemsCollector[itemsCollector.length - 1]) { - throw new Error(`Missing parent level for: ${text}`); - } - - itemsCollector[itemsCollector.length - 1].children.push({ - text, - level, - hash: textToHash(text), - }); - } -}; - -function getItems(contents) { - itemsCollector = []; - marked(contents.join(''), { - renderer, - }); - - return itemsCollector; -} - const styles = theme => ({ root: { top: 70 + 29, @@ -81,12 +49,12 @@ const styles = theme => ({ '&:hover': { borderLeft: `4px solid ${ theme.palette.type === 'light' ? theme.palette.grey[200] : theme.palette.grey[900] - }`, + }`, }, '&$active': { borderLeft: `4px solid ${ theme.palette.type === 'light' ? theme.palette.grey[300] : theme.palette.grey[800] - }`, + }`, }, }, secondaryItem: { @@ -95,104 +63,84 @@ const styles = theme => ({ active: {}, }); -function checkDuplication(uniq, item) { - warning(!uniq[item.hash], `Table of content: duplicated \`${item.hash}\` item`); - - if (!uniq[item.hash]) { - uniq[item.hash] = true; - } -} - -class AppTableOfContents extends React.Component { - handleScroll = throttle(() => { - this.findActiveIndex(); - }, 166); // Corresponds to 10 frames at 60 Hz. - - clicked = false; +let itemsCollector; +const renderer = new marked.Renderer(); +renderer.heading = (text, level) => { + if (level === 2) { + itemsCollector.push({ + text, + level, + hash: textToHash(text), + children: [], + }); + } else if (level === 3) { + if (!itemsCollector[itemsCollector.length - 1]) { + throw new Error(`Missing parent level for: ${text}`); + } - constructor(props) { - super(); - this.itemsServer = getItems(props.contents); + itemsCollector[itemsCollector.length - 1].children.push({ + text, + level, + hash: textToHash(text), + }); } +}; - state = { - active: null, - }; - - componentDidMount() { - this.itemsClient = []; - const uniq = {}; +function getItems(contents) { + itemsCollector = []; + marked(contents.join(''), { + renderer, + }); - this.itemsServer.forEach(item2 => { - checkDuplication(uniq, item2); - this.itemsClient.push({ - ...item2, - node: document.getElementById(item2.hash), - }); + return itemsCollector; +} - if (item2.children.length > 0) { - item2.children.forEach(item3 => { - checkDuplication(uniq, item3); - this.itemsClient.push({ - ...item3, - node: document.getElementById(item3.hash), - }); - }); - } - }); - window.addEventListener('hashchange', this.handleHashChange); - } +function checkDuplication(uniq, item) { + warning(!uniq[item.hash], `Table of content: duplicated \`${item.hash}\` item`); - componentWillUnmount() { - this.handleScroll.cancel(); - clearTimeout(this.unsetClicked); - window.removeEventListener('hashchange', this.handleHashChange); + if (!uniq[item.hash]) { + uniq[item.hash] = true; } +} - // Update the active TOC entry if the hash changes through click on '#' icon - handleHashChange = () => { - const hash = window.location.hash.substring(1); +function AppTableOfContents(props) { + const [activeState, setActiveState] = useState(null); + const [itemsServerState, setItemsServerState] = useState([]); - if (this.state.active !== hash) { - this.setState({ - active: hash, - }); - } - }; + let clicked = false; + let unsetClicked; + let itemsClient = []; - findActiveIndex = () => { + const findActiveIndex = () => { // Don't set the active index based on scroll if a link was just clicked - if (this.clicked) { + if (clicked) { return; } let active; - - for (let i = this.itemsClient.length - 1; i >= 0; i -= 1) { + for (let i = itemsClient.length - 1; i >= 0; i -= 1) { // No hash if we're near the top of the page if (document.documentElement.scrollTop < 200) { active = { hash: null }; break; } - const item = this.itemsClient[i]; + const item = itemsClient[i]; warning(item.node, `Missing node on the item ${JSON.stringify(item, null, 2)}`); if ( item.node && item.node.offsetTop < - document.documentElement.scrollTop + document.documentElement.clientHeight / 8 + document.documentElement.scrollTop + document.documentElement.clientHeight / 8 ) { active = item; break; } } - if (active && this.state.active !== active.hash) { - this.setState({ - active: active.hash, - }); + if (active && activeState !== active.hash) { + setActiveState(active.hash); window.history.replaceState( null, @@ -204,78 +152,118 @@ class AppTableOfContents extends React.Component { } }; - handleClick = hash => () => { + // Update the active TOC entry if the hash changes through click on '#' icon + const handleHashChange = () => { + const hash = window.location.hash.substring(1); + + if (activeState !== hash) { + setActiveState(hash); + } + }; + + const handleScroll = throttle(() => { + findActiveIndex(); + }, 166); // Corresponds to 10 frames at 60 Hz. + + useEffect(() => { + setItemsServerState(getItems(props.contents)); + itemsClient = []; + const unique = {}; + + itemsServerState.forEach(item2 => { + checkDuplication(unique, item2); + itemsClient.push({ + ...item2, + node: document.getElementById(item2.hash), + }); + + if (item2.children.length > 0) { + item2.children.forEach(item3 => { + checkDuplication(unique, item3); + itemsClient.push({ + ...item3, + node: document.getElementById(item3.hash), + }); + }); + } + }); + + window.addEventListener('hashchange', handleHashChange); + + return function componentWillUnmount() { + handleScroll.cancel(); + clearTimeout(unsetClicked); + window.removeEventListener('hashchange', handleHashChange); + } + }); + + const handleClick = hash => () => { // Used to disable findActiveIndex if the page scrolls due to a click - this.clicked = true; - this.unsetClicked = setTimeout(() => { - this.clicked = false; + clicked = true; + unsetClicked = setTimeout(() => { + clicked = false; }, 1000); - if (this.state.active !== hash) { - this.setState({ - active: hash, - }); + if (activeState !== hash) { + setActiveState(hash); } }; - render() { - const { classes, t } = this.props; - const { active } = this.state; - - return ( - - ); - } + const { classes, t } = props; + + return ( + + ); } AppTableOfContents.propTypes = { From 0df0ef1f9673d26c197b6f9a42ce7354f5c4d4fa Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 01:11:37 +0000 Subject: [PATCH 03/13] add missing translations --- docs/translations/translations-de.json | 1 + docs/translations/translations-es.json | 1 + docs/translations/translations-ja.json | 1 + docs/translations/translations-pt.json | 1 + docs/translations/translations-ru.json | 1 + 5 files changed, 5 insertions(+) diff --git a/docs/translations/translations-de.json b/docs/translations/translations-de.json index b15e4e167f4823..745a7cd5d11f59 100644 --- a/docs/translations/translations-de.json +++ b/docs/translations/translations-de.json @@ -28,6 +28,7 @@ "thanks": "Vielen Dank!", "adTitle": "Diese Werbung soll Open Source unterstützen.", "editPage": "Helfen Sie, diese Seite zu übersetzen", + "tableOfContents": "Inhaltsverzeichnis", "component": "Komponenten-Kit", "mdbProDescr": "Material Dashboard Pro React is a Premium Material-UI Admin.", "mkProDescr": "EIn tolles Material-UI Kit basierend auf Material Design.", diff --git a/docs/translations/translations-es.json b/docs/translations/translations-es.json index c4e513fec08792..f75e73db28421d 100644 --- a/docs/translations/translations-es.json +++ b/docs/translations/translations-es.json @@ -28,6 +28,7 @@ "thanks": "¡Gracias!", "adTitle": "Este anuncio está diseñado para apoyar al Open Source.", "editPage": "Ayuda a traducir esta página", + "tableOfContents": "Tabla de Contenido", "component": "Kit de Componentes", "mdbProDescr": "Material Dashboard Pro React es un tema de administración premium de Material-UI.", "mkProDescr": "Un fantástico Kit con Material-UI basado en Material Design.", diff --git a/docs/translations/translations-ja.json b/docs/translations/translations-ja.json index e372954cc0c596..9cb9c758cb97bd 100644 --- a/docs/translations/translations-ja.json +++ b/docs/translations/translations-ja.json @@ -28,6 +28,7 @@ "thanks": "感謝します!", "adTitle": "この広告はオープンソースを支援するように設計されています。", "editPage": "このページの翻訳を手伝ってください", + "tableOfContents": "目次", "component": "コンポーネントキット", "mdbProDescr": "Material Dashboard Pro React is a Premium Material-UI Admin.", "mkProDescr": "Material Designによる最高にクールなMaterial-UI", diff --git a/docs/translations/translations-pt.json b/docs/translations/translations-pt.json index dc61a5275a1962..ce7793ec0f9ae7 100644 --- a/docs/translations/translations-pt.json +++ b/docs/translations/translations-pt.json @@ -28,6 +28,7 @@ "thanks": "Obrigado!", "adTitle": "Este anúncio é projetado para apoiar o Código Aberto.", "editPage": "Ajude a traduzir esta página", + "tableOfContents": "Índice", "component": "Kit de Componente", "mdbProDescr": "Material Dashboard Pro React is a Premium Material-UI Admin.", "mkProDescr": "Um badass Material-UI Kit baseado em Material Design.", diff --git a/docs/translations/translations-ru.json b/docs/translations/translations-ru.json index 7a8f1ca19d60d4..62f80ed25034d5 100644 --- a/docs/translations/translations-ru.json +++ b/docs/translations/translations-ru.json @@ -28,6 +28,7 @@ "thanks": "Спасибо!", "adTitle": "Эта реклама предназначена для поддержки Open Source.", "editPage": "Помогите перевести эту страницу", + "tableOfContents": "Содержание", "component": "Набор компонентов", "mdbProDescr": "Material Dashboard Pro React is a Premium Material-UI Admin.", "mkProDescr": "Badass Material-UI Kit основывается на Material Design.", From 88545b4269ddc9ae9f7e01da1219b32cbfb7cb93 Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 01:15:34 +0000 Subject: [PATCH 04/13] lint & prettier --- .../modules/components/AppTableOfContents.js | 10 +++++----- .../src/MarkdownElement/MarkdownElement.js | 17 +++++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 1a7336cceeb235..3b79e59ed38a0e 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -12,7 +12,7 @@ import Typography from '@material-ui/core/Typography'; import { textToHash } from '@material-ui/docs/MarkdownElement/MarkdownElement'; import Link from 'docs/src/modules/components/Link'; import compose from 'docs/src/modules/utils/compose'; -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; const styles = theme => ({ root: { @@ -49,12 +49,12 @@ const styles = theme => ({ '&:hover': { borderLeft: `4px solid ${ theme.palette.type === 'light' ? theme.palette.grey[200] : theme.palette.grey[900] - }`, + }`, }, '&$active': { borderLeft: `4px solid ${ theme.palette.type === 'light' ? theme.palette.grey[300] : theme.palette.grey[800] - }`, + }`, }, }, secondaryItem: { @@ -132,7 +132,7 @@ function AppTableOfContents(props) { if ( item.node && item.node.offsetTop < - document.documentElement.scrollTop + document.documentElement.clientHeight / 8 + document.documentElement.scrollTop + document.documentElement.clientHeight / 8 ) { active = item; break; @@ -194,7 +194,7 @@ function AppTableOfContents(props) { handleScroll.cancel(); clearTimeout(unsetClicked); window.removeEventListener('hashchange', handleHashChange); - } + }; }); const handleClick = hash => () => { diff --git a/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js b/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js index 826b98bd196121..d03b31a33ec358 100644 --- a/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js +++ b/packages/material-ui-docs/src/MarkdownElement/MarkdownElement.js @@ -19,14 +19,15 @@ marked.Lexer.prototype.lex = function lex(src) { const renderer = new marked.Renderer(); export function textToHash(text) { - return encodeURI(text - .toLowerCase() - .replace(/=>|<| \/>||<\/code>/g, '') - .replace(/\s+/g, '-') - // eslint-disable-next-line no-useless-escape, eslint bug? - .replace(/[!@#\$%\^&\*\(\)=_\+\[\]{}`~;:'"\|,\.<>\/\?]+/g, '') - .replace(/-$/g, '') - ) + return encodeURI( + text + .toLowerCase() + .replace(/=>|<| \/>||<\/code>/g, '') + .replace(/\s+/g, '-') + // eslint-disable-next-line no-useless-escape + .replace(/[!@#\$%\^&\*\(\)=_\+\[\]{}`~;:'"\|,\.<>\/\?]+/g, '') + .replace(/-$/g, ''), + ); } renderer.heading = (text, level) => { From efc8c7c2d9b434c0bcb2facfbd8464d77bd7c320 Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 01:50:58 +0000 Subject: [PATCH 05/13] order imports by specificity --- docs/src/modules/components/AppTableOfContents.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 3b79e59ed38a0e..e2eb3535cfe9bb 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -7,12 +7,12 @@ import warning from 'warning'; import throttle from 'lodash/throttle'; import EventListener from 'react-event-listener'; import clsx from 'clsx'; +import { connect } from 'react-redux'; import { withStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import { textToHash } from '@material-ui/docs/MarkdownElement/MarkdownElement'; import Link from 'docs/src/modules/components/Link'; import compose from 'docs/src/modules/utils/compose'; -import { connect } from 'react-redux'; const styles = theme => ({ root: { From 322c0e878a962e2f308868a3851283e0454d000d Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 13:27:43 +0000 Subject: [PATCH 06/13] React - no named imports --- docs/src/modules/components/AppTableOfContents.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index e2eb3535cfe9bb..e730fa01eda257 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -1,6 +1,6 @@ /* eslint-disable react/no-danger */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import marked from 'marked'; import warning from 'warning'; @@ -104,8 +104,8 @@ function checkDuplication(uniq, item) { } function AppTableOfContents(props) { - const [activeState, setActiveState] = useState(null); - const [itemsServerState, setItemsServerState] = useState([]); + const [activeState, setActiveState] = React.useState(null); + const [itemsServerState, setItemsServerState] = React.useState([]); let clicked = false; let unsetClicked; @@ -165,7 +165,7 @@ function AppTableOfContents(props) { findActiveIndex(); }, 166); // Corresponds to 10 frames at 60 Hz. - useEffect(() => { + React.useEffect(() => { setItemsServerState(getItems(props.contents)); itemsClient = []; const unique = {}; From 31a6fbc7bf2f52baf39f0dfda1b57cb37bae7030 Mon Sep 17 00:00:00 2001 From: Matthew Brookes Date: Sat, 16 Feb 2019 22:19:44 +0000 Subject: [PATCH 07/13] Memoize itemsServer --- .../modules/components/AppTableOfContents.js | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index e730fa01eda257..2fa9febc4093d2 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -103,13 +103,37 @@ function checkDuplication(uniq, item) { } } +function getItemsClient(itemsServer) { + const items = []; + const unique = {}; + + itemsServer.forEach(item2 => { + checkDuplication(unique, item2); + items.push({ + ...item2, + node: document.getElementById(item2.hash), + }); + + if (item2.children.length > 0) { + item2.children.forEach(item3 => { + checkDuplication(unique, item3); + items.push({ + ...item3, + node: document.getElementById(item3.hash), + }); + }); + } + }); + return items; +} + function AppTableOfContents(props) { + const { classes, contents, t } = props; const [activeState, setActiveState] = React.useState(null); - const [itemsServerState, setItemsServerState] = React.useState([]); - + const itemsServer = React.useMemo(() => getItems(contents), [contents]); + let itemsClient = []; let clicked = false; let unsetClicked; - let itemsClient = []; const findActiveIndex = () => { // Don't set the active index based on scroll if a link was just clicked @@ -166,27 +190,7 @@ function AppTableOfContents(props) { }, 166); // Corresponds to 10 frames at 60 Hz. React.useEffect(() => { - setItemsServerState(getItems(props.contents)); - itemsClient = []; - const unique = {}; - - itemsServerState.forEach(item2 => { - checkDuplication(unique, item2); - itemsClient.push({ - ...item2, - node: document.getElementById(item2.hash), - }); - - if (item2.children.length > 0) { - item2.children.forEach(item3 => { - checkDuplication(unique, item3); - itemsClient.push({ - ...item3, - node: document.getElementById(item3.hash), - }); - }); - } - }); + itemsClient = getItemsClient(itemsServer); window.addEventListener('hashchange', handleHashChange); @@ -209,18 +213,16 @@ function AppTableOfContents(props) { } }; - const { classes, t } = props; - return (