import React , { useEffect , useState } from "react" ; import * as Sentry from "@sentry/gatsby" ; import GuideGrid from "./guideGrid" ; import { PageContext } from "./basePage" ; type Item = { title ? : string ; url ? : string ; items : Item [ ] ; } ; const getHeadings = ( element ) : Item [ ] => { const levels = [ 2 , 3 ] ; const headingSelector = levels . map ( level => `h${ level }` ) . join ( `, ` ) ; const htmlNodes = Array . from ( element . querySelectorAll ( headingSelector ) ) ; const headings = [ ] ; const tree = [ ] ; let lastDepth = null ; htmlNodes . forEach ( ( node , i ) => { if ( ! node . id ) return ; const item = { items : [ ] , url : `#${ node . id }` , title : node . innerText , } ; const depth = Number ( node . nodeName [ 1 ] ) ; if ( ! lastDepth ) { headings . push ( item ) ; tree . push ( item ) ; } else if ( lastDepth === depth ) { if ( tree . length === 1 ) { headings . push ( item ) ; } else { tree [ tree . length - 2 ] . items . push ( item ) ; } tree [ tree . length - 1 ] = item ; } else if ( depth > lastDepth ) { tree [ tree . length - 1 ] . items . push ( item ) ; tree . push ( item ) ; } else if ( depth < lastDepth ) { tree . pop ( ) ; if ( tree . length === 1 ) { headings . push ( item ) ; } else { tree [ tree . length - 2 ] . items . push ( item ) ; } tree [ tree . length - 1 ] = item ; } lastDepth = depth ; } ) ; return headings ; } ; type Props = { contentRef : React . RefObject < HTMLElement > ; pageContext ? : PageContext ; } ; export default ( { contentRef , pageContext } ) => { const [ items , setItems ] = useState < Item [ ] > ( null ) ; const { platform } = pageContext ; useEffect ( ( ) => { if ( ! items && contentRef . current ) { try { setItems ( getHeadings ( contentRef . current ) ) ; } catch ( err ) { Sentry . captureException ( err ) ; setItems ( [ ] ) ; } } } ) ; if ( ! items || ! items . length ) return null ; const recurse = items => items . map ( i => { if ( ! i . title ) return recurse ( i . items ) ; return ( < li className = "toc-entry" key = { i . url } > < a href = { i . url } > { i . title } < /a> { i . items && < ul > { recurse ( i . items ) } < /ul>} < /li>); } ) ; return ( < div className = "doc-toc" > < div className = "doc-toc-title" > < h6 > On this page < /h6> < /div> < ul className = "section-nav" > { recurse ( items ) } < /ul> { platform && ( < > < div className = "doc-toc-title" > < h6 > Related Guides < /h6> < /div> < GuideGrid platform = { platform . name } className = "section-nav" / > < />)} < /div>); } ;