feat: add more options to toc component and docs

This commit is contained in:
Timothy Lin 2021-08-07 23:49:56 +08:00
parent afbc2d9c66
commit 8023d60cdb
4 changed files with 91 additions and 28 deletions

View File

@ -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

View File

@ -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
)}
</>
)
}

View File

@ -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

View File

@ -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!