-
-
Save alternayte/cf4a0bf7ab214f8a8fc05d085367bce6 to your computer and use it in GitHub Desktop.
React Markdown TOC Proof-of-Concept
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| This is based on an idea for building a table of contents on top of | |
| React Markdown using a custom renderer. The original conversation is at | |
| https://github.com/remarkjs/react-markdown/issues/48 | |
| */ | |
| import React from "react"; | |
| import ReactMarkdown from "react-markdown"; | |
| import { Row, Col, Container } from "react-bootstrap"; | |
| import { HeadingProps } from "react-markdown/lib/ast-to-react"; | |
| const markdown: string = require("~static/docs/markdown.md"); | |
| export default function Documentation() { | |
| const toc: { | |
| level: number, | |
| id: string, | |
| title: string, | |
| }[] = []; | |
| // Magic. | |
| const addToTOC = ({children, ...props}: React.PropsWithChildren<HeadingProps>) => { | |
| const level = Number(props.node.tagName.match(/h(\d)/)?.slice(1)); | |
| if (level && children && typeof children[0] === "string") { | |
| const id = children[0].toLowerCase().replace(/[^a-z0-9]+/g, "-"); | |
| toc.push({ | |
| level, | |
| id, | |
| title: children[0], | |
| }); | |
| return React.createElement( | |
| props.node.tagName, {id}, children | |
| ) | |
| } else { | |
| return React.createElement(props.node.tagName, props, children); | |
| } | |
| }; | |
| function TOC() { | |
| return ( | |
| <ul className="table-of-contents"> | |
| {toc.map(({level, id, title}) => ( | |
| <li key={id} className={`toc-entry-level-${level}`}> | |
| <a href={`#${id}`}>{title}</a> | |
| </li> | |
| ))} | |
| </ul> | |
| ); | |
| } | |
| return ( | |
| <Container> | |
| <Row> | |
| <Col md="9" className="wall-of-text"> | |
| <ReactMarkdown | |
| components={{ | |
| h2: addToTOC, | |
| h3: addToTOC, | |
| h4: addToTOC, | |
| h5: addToTOC, | |
| h6: addToTOC, | |
| }} | |
| > | |
| {markdown} | |
| </ReactMarkdown> | |
| </Col> | |
| <Col md="3"> | |
| {/* More magic. */} | |
| <TOC /> | |
| </Col> | |
| </Row> | |
| </Container> | |
| ); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment