Fix toc and heading

This commit is contained in:
Joshen Lim committed 2022-11-03 16:11:05 +07:00
1 parent af278ac579
commit dc9d1afbba
5 files changed
+69 -36

No files matched your search

@@ -1,11 +1,20 @@
export const getAnchor = (text: any): string | undefined => {
if (typeof text !== 'string') {
return undefined
} else {
if (typeof text === 'object') {
const formattedText = text.map((x) => {
if (typeof x !== 'string') {
return x.props.children
} else {
return x.trim()
}
})
return formattedText.join('-').toLowerCase()
} else if (typeof text === 'string') {
return text
.toLowerCase()
.replace(/[^a-z0-9 ]/g, '')
.replace(/[^a-z0-9- ]/g, '')
.replace(/[ ]/g, '-')
} else {
return undefined
}
}
@@ -13,7 +13,9 @@ const Heading = ({ tag, children }) => {
const link = `#${anchor}`
// check if current heading is in view, update TOC active item accordingly
const { ref, inView, entry } = useInView({
// [Joshen] Ideally we highlight the section in the TOC when it's at the top of the page
// much like when we click on the item in the TOC itself, the rootMargin fix is insufficient
const { ref } = useInView({
threshold: 1,
onChange: (inView, entry) => {
if (window.scrollY === 0) unHighlightSelectedTocItems()
@@ -0,0 +1,48 @@
import { FC } from 'react'
import { removeAnchor } from './CustomHTMLElements/CustomHTMLElements.utils'
interface TOCHeader {
id: number
lvl: number
seen: number
content: string
slug: string
}
interface Props {
toc: any
}
const formatSlug = (slug: string) => {
// [Joshen] We will still provide support for headers declared like this:
// ## REST API {#rest-api-overview}
// At least for now, this was a docusaurus thing.
if (slug.includes('#')) return slug.split('-#')[0]
return slug
}
const TableOfContents: FC<Props> = ({ toc }) => {
// [Joshen] markdown-toc doesn't seem to read maxdepth from the options passed in
// Our first level headers will be H2s (H1 is ignored), and we only show up to H3
return (
<ul className="toc-menu list-none pl-4 text-[0.8rem] grid gap-2 mt-1">
{(toc.json as TOCHeader[])
.filter((item) => item.lvl !== 1 && item.lvl <= 3)
.map((item: any, i: number) => {
return (
<li key={i} id={item.lvl} style={{ marginLeft: `${(item.lvl - 2) * 1}rem` }}>
<a
href={`#${formatSlug(item.slug)}`}
className="text-scale-1000 hover:text-brand-900 transition-colors"
>
{removeAnchor(item.content)}
</a>
</li>
)
})}
</ul>
)
}
export default TableOfContents
+3 -27
View File
@@ -3,6 +3,7 @@ import Head from 'next/head'
import NavBar from '../components/Navigation/NavBar'
import SideBar from '../components/Navigation/SideBar'
import Footer from '../components/Footer'
import TableOfContents from '~/components/TableOfContents'
interface Props {
meta: { title: string; description?: string; hide_table_of_contents?: boolean }
@@ -34,12 +35,6 @@ const Layout: FC<Props> = ({ meta, children, toc, menuItems, currentPage }) => {
<meta property="og:site_name" content={meta?.title} />
<meta property="og:description" content={meta?.description} />
<meta property="og:title" content={meta?.title} />
{/* <link
rel="preload"
href="https://unpkg.com/prismjs@0.0.1/themes/prism-okaidia.css"
as="script"
/> */}
{/* <link href={`https://unpkg.com/prismjs@0.0.1/themes/prism-${theme}.css`} rel="stylesheet" /> */}
</Head>
<main>
@@ -49,7 +44,7 @@ const Layout: FC<Props> = ({ meta, children, toc, menuItems, currentPage }) => {
<div className="docs-width grid grid-cols-12 gap-4 justify-between p-4 pb-8 w-full">
<div
className={`${
meta?.hide_table_of_contents ? 'col-span-10' : 'col-span-12 xl:col-span-9'
meta?.hide_table_of_contents ? 'col-span-10 2xl:col-span-8' : 'col-span-9'
} py-4 px-8`}
>
<article className="prose dark:prose-dark dark:bg-scale-200 width-full mt-8">
@@ -58,26 +53,7 @@ const Layout: FC<Props> = ({ meta, children, toc, menuItems, currentPage }) => {
</div>
{toc && !meta?.hide_table_of_contents && (
<div className="border-scale-400 dark:bg-scale-200 thin-scrollbar table-of-contents-height col-span-3 border-l px-2">
<ul className="toc-menu list-none pl-4 text-[0.8rem] grid gap-1 mt-1">
{toc.json
.filter((item) => item.lvl !== 1)
.map((item: any, i: number) => {
return (
<li
key={i}
className={`${item.lvl === 3 && i !== 0 ? 'ml-4' : ''}`}
id={item.lvl}
>
<a
className="text-scale-1000 hover:text-brand-900 transition-colors"
href={`#${item.slug}`}
>
{item.content}
</a>
</li>
)
})}
</ul>
<TableOfContents toc={toc} />
</div>
)}
</div>
+2 -4
View File
@@ -1,3 +1,4 @@
import toc from 'markdown-toc'
import { MDXProvider } from '@mdx-js/react'
import { useRouter } from 'next/router'
import { MDXRemote } from 'next-mdx-remote'
@@ -8,9 +9,6 @@ import { getPageType } from '../lib/helpers'
import { getAllDocs, getDocsBySlug } from '../lib/docs'
import Layout from '~/layouts/Default'
// table of contents extractor
const toc = require('markdown-toc')
interface Meta {
id: string
title: string
@@ -54,7 +52,7 @@ export async function getStaticProps({ params }: { params: { slug: string[] } })
props: {
...doc,
content,
toc: toc(doc.content, { maxdepth: 2 }),
toc: toc(doc.content, { maxdepth: 1, firsth1: false }),
},
}
}