feat: add more options to toc component and docs
This commit is contained in:
		| @@ -31,7 +31,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea | ||||
|  | ||||
| - Easy styling customization with [Tailwind 2.0](https://blog.tailwindcss.com/tailwindcss-v2) and primary color attribute | ||||
| - Near perfect lighthouse score - [Lighthouse report](https://www.webpagetest.org/result/210111_DiC1_08f3670c3430bf4a9b76fc3b927716c5/) | ||||
| - Lightweight, 38kB first load JS, uses Preact in production build | ||||
| - Lightweight, 39kB first load JS, uses Preact in production build | ||||
| - Mobile-friendly view | ||||
| - Light and dark theme | ||||
| - Supports [plausible](https://plausible.io/), [simple analytics](https://simpleanalytics.com/) and google analytics | ||||
| @@ -43,6 +43,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea | ||||
| - Support for tags - each unique tag will be its own page | ||||
| - Support for multiple authors | ||||
| - Blog templates | ||||
| - TOC component | ||||
| - Support for nested routing of blog posts | ||||
| - Supports [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus | ||||
| - Projects page | ||||
|   | ||||
| @@ -1,17 +1,63 @@ | ||||
| const TOCInline = ({ toc, indentDepth = 3 }) => { | ||||
| /** | ||||
|  * @typedef TocHeading | ||||
|  * @prop {string} value | ||||
|  * @prop {number} depth | ||||
|  * @prop {string} url | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Generates an inline table of contents | ||||
|  * Exclude titles matching this string (new RegExp('^(' + string + ')$', 'i')). | ||||
|  * If an array is passed the array gets joined with a pipe (new RegExp('^(' + array.join('|') + ')$', 'i')). | ||||
|  * | ||||
|  * @param {{ | ||||
|  *  toc: TocHeading[], | ||||
|  *  indentDepth?: number, | ||||
|  *  fromHeading?: number, | ||||
|  *  toHeading?: number, | ||||
|  *  asDisclosure?: boolean, | ||||
|  *  exclude?: string|string[] | ||||
|  * }} props | ||||
|  * | ||||
|  */ | ||||
| const TOCInline = ({ | ||||
|   toc, | ||||
|   indentDepth = 3, | ||||
|   fromHeading = 1, | ||||
|   toHeading = 6, | ||||
|   asDisclosure = false, | ||||
|   exclude = '', | ||||
| }) => { | ||||
|   const re = Array.isArray(exclude) | ||||
|     ? new RegExp('^(' + exclude.join('|') + ')$', 'i') | ||||
|     : new RegExp('^(' + exclude + ')$', 'i') | ||||
|  | ||||
|   const filteredToc = toc.filter( | ||||
|     (heading) => | ||||
|       heading.depth >= fromHeading && heading.depth <= toHeading ** !re.test(heading.value) | ||||
|   ) | ||||
|  | ||||
|   const tocList = ( | ||||
|     <ul> | ||||
|       {filteredToc.map((heading) => ( | ||||
|         <li key={heading.value} className={`${heading.depth >= indentDepth && 'ml-6'}`}> | ||||
|           <a href={heading.url}>{heading.value}</a> | ||||
|         </li> | ||||
|       ))} | ||||
|     </ul> | ||||
|   ) | ||||
|  | ||||
|   return ( | ||||
|     <details open> | ||||
|       <summary className="pt-2 pb-2 ml-6 text-xl font-bold">Table of Contents</summary> | ||||
|       <div className="ml-6"> | ||||
|         <ul> | ||||
|           {toc.map((heading) => ( | ||||
|             <li key={heading.value} className={`${heading.depth >= indentDepth && 'ml-6'}`}> | ||||
|               <a href={heading.url}>{heading.value}</a> | ||||
|             </li> | ||||
|           ))} | ||||
|         </ul> | ||||
|       </div> | ||||
|     </details> | ||||
|     <> | ||||
|       {asDisclosure ? ( | ||||
|         <details open> | ||||
|           <summary className="pt-2 pb-2 ml-6 text-xl font-bold">Table of Contents</summary> | ||||
|           <div className="ml-6">{tocList}</div> | ||||
|         </details> | ||||
|       ) : ( | ||||
|         tocList | ||||
|       )} | ||||
|     </> | ||||
|   ) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| --- | ||||
| title: 'Introducing Tailwind Nextjs Starter Blog' | ||||
| date: '2021-01-12' | ||||
| lastmod: '2021-08-02' | ||||
| lastmod: '2021-08-07' | ||||
| tags: ['next-js', 'tailwind', 'guide'] | ||||
| draft: false | ||||
| summary: 'Looking for a performant, out of the box template, with all the best in web technology to support your blogging needs? Checkout the Tailwind Nextjs Starter Blog template.' | ||||
| @@ -36,7 +36,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea | ||||
|  | ||||
| - Easy styling customization with [Tailwind 2.0](https://blog.tailwindcss.com/tailwindcss-v2) and primary color attribute | ||||
| - Near perfect lighthouse score - [Lighthouse report](https://www.webpagetest.org/result/210111_DiC1_08f3670c3430bf4a9b76fc3b927716c5/) | ||||
| - Lightweight, 38kB first load JS, uses Preact in production build | ||||
| - Lightweight, 39kB first load JS, uses Preact in production build | ||||
| - Mobile-friendly view | ||||
| - Light and dark theme | ||||
| - Supports [plausible](https://plausible.io/), [simple analytics](https://simpleanalytics.com/) and google analytics | ||||
| @@ -48,6 +48,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea | ||||
| - Support for tags - each unique tag will be its own page | ||||
| - Support for multiple authors | ||||
| - Blog templates | ||||
| - TOC component | ||||
| - Support for nested routing of blog posts | ||||
| - Supports [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus | ||||
| - Projects page | ||||
|   | ||||
| @@ -1,28 +1,19 @@ | ||||
| --- | ||||
| title: 'New features in v1' | ||||
| date: '2021-07-28' | ||||
| date: '2021-08-07' | ||||
| tags: ['next-js', 'tailwind', 'guide'] | ||||
| draft: false | ||||
| summary: 'An overview of the new features released in v1 - code block copy, multiple authors, frontmatter layout and more' | ||||
| layout: PostSimple | ||||
| --- | ||||
|  | ||||
| <TOCInline toc={props.toc} /> | ||||
|  | ||||
| ## Overview | ||||
|  | ||||
| A post on the new features introduced in v1.0. New features: | ||||
|  | ||||
| - [Theme colors](#theme-colors) | ||||
| - [Xdm MDX compiler](#xdm-mdx-compiler) | ||||
| - [Layouts](#layouts) | ||||
| - [Multiple authors](#multiple-authors) | ||||
| - [Analytics](#analytics) | ||||
| - [Blog comments system](#blog-comments-system) | ||||
| - [Copy button for code blocks](#copy-button-for-code-blocks) | ||||
| - [Line highlighting and line numbers](#line-highlighting-and-line-numbers) | ||||
| <TOCInline toc={props.toc} exclude="Overview" toHeading={2} /> | ||||
|  | ||||
| First load JS decreased from 43kB to 38kB despite all the new features added! | ||||
| First load JS decreased from 43kB to 39kB despite all the new features added! | ||||
|  | ||||
| See [upgrade guide](#upgrade-guide) below if you are migrating from v0 version of the template. | ||||
|  | ||||
| @@ -77,6 +68,30 @@ Components which require external image loaders would require additional esbuild | ||||
| Components which are dependent on global application state on lifecycle like the Nextjs `Link` component would also not work with this setup as each mdx file is built indepedently. | ||||
| For such cases, it is better to use component substitution. | ||||
|  | ||||
| ## Table of contents component | ||||
|  | ||||
| Inspired by [Docusaurus](https://docusaurus.io/docs/next/markdown-features/inline-toc) and Gatsby's [gatsby-remark-table-of-contents](https://www.gatsbyjs.com/plugins/gatsby-remark-table-of-contents/), | ||||
| the `toc` variable containing all the top level headings of the document is passed to the MDX file and can be styled accordingly. | ||||
| To make generating a TOC simple, you can use the existing `TOCInline` component. | ||||
|  | ||||
| For example, the TOC in this post was generated with the following code: | ||||
|  | ||||
| ```js | ||||
| <TOCInline toc={props.toc} exclude="Overview" toHeading={2} /> | ||||
| ``` | ||||
|  | ||||
| You can customise the headings to be generated by configuring the `fromHeading` and `toHeading` props as well as exclude particular headings | ||||
| by passing a string or a string array. By default, all headings that are of depth 3 or smaller are indented. This can be configured by changing the `indentDepth` property. | ||||
| A `asDisclosure` prop can be used to render the TOC within an expandable disclosure element. | ||||
|  | ||||
| Here's the full TOC rendered in a disclosure element. | ||||
|  | ||||
| ```js | ||||
| <TOCInline toc={props.toc} asDisclosure /> | ||||
| ``` | ||||
|  | ||||
| <TOCInline toc={props.toc} asDisclosure /> | ||||
|  | ||||
| ## Layouts | ||||
|  | ||||
| You can map mdx blog content to layout components by configuring the frontmatter field. For example, this post is written with the new `PostSimple` layout! | ||||
|   | ||||
		Reference in New Issue
	
	Block a user