Update table of contents

This commit is contained in:
Defectink
2022-04-01 15:15:38 +08:00
parent d68b4523ef
commit 11fcb9677f
7 changed files with 71 additions and 39 deletions

View File

@ -2,13 +2,16 @@ import { AnchorHTMLAttributes } from 'react';
import cn from 'classnames';
import { FiExternalLink } from 'react-icons/fi';
interface Props extends AnchorHTMLAttributes<HTMLAnchorElement> {}
interface Props extends AnchorHTMLAttributes<HTMLAnchorElement> {
external?: boolean;
}
const Anchor = ({ children, ...rest }: Props) => {
const Anchor = ({ children, external = true, ...rest }: Props) => {
return (
<>
<a
{...rest}
target={external ? '_blank' : undefined}
className={cn(
'mx-[2px] text-teal-500 relative',
'before:left-0 before:top-[1px] before:block before:absolute',
@ -18,6 +21,7 @@ const Anchor = ({ children, ...rest }: Props) => {
)}
>
{children}
{external && <FiExternalLink className="inline ml-1 mb-[0.2rem]" />}
</a>
</>
);

View File

@ -0,0 +1,29 @@
import { FC } from 'react';
import { getHeadings } from 'lib/utils';
import Anchor from 'components/mdx/Anchor';
interface Props {
headings: ReturnType<typeof getHeadings>;
}
const PostTOC: FC<Props> = ({ headings }) => {
return (
<>
<h2>What&apos;s inside?</h2>
<ul className="pl-4 border-l-4 border-gray-300">
{headings?.map((h) => (
<>
<li>
<Anchor href={h.link} external={false}>
{h.text}
</Anchor>
</li>
</>
))}
</ul>
</>
);
};
export default PostTOC;

View File

@ -1,7 +1,9 @@
import { FC } from 'react';
import dynamic from 'next/dynamic';
import { MyMatters } from 'types';
// import { renderToString } from 'react-dom/server';
import { renderToString } from 'react-dom/server';
import { getHeadings } from 'lib/utils';
import PostTOC from 'components/post/PostTOC';
const Footer = dynamic(() => import('components/Footer'));
const HeadBar = dynamic(() => import('components/NavBar'));
@ -9,29 +11,8 @@ const HeadBar = dynamic(() => import('components/NavBar'));
interface Props extends MyMatters {}
const MainLayout: FC<Props> = ({ title, date, children }) => {
// const contentString = renderToString(children as any);
// const getHeadings = (source: string) => {
// const regex = /<h2>(.*?)<\/h2>/g;
// if (source.match(regex)) {
// return source.match(regex)?.map((heading) => {
// const headingText = heading.replace('<h2>', '').replace('</h2>', '');
// const link = '#' + headingText.replace(/ /g, '_').toLowerCase();
// return {
// text: headingText,
// link,
// };
// });
// }
// return [];
// };
// const headings = getHeadings(contentString);
// console.log(headings);
const contentString = renderToString(children as any);
const headings = getHeadings(contentString);
return (
<>
@ -43,6 +24,8 @@ const MainLayout: FC<Props> = ({ title, date, children }) => {
<time>{date}</time>
<PostTOC headings={headings} />
{children}
</article>
</main>

View File

@ -10,3 +10,30 @@ export const sortByDate = (
return 0;
}
};
/**
* Read post head to mark TOC
* @param source
* @returns
*/
export const getHeadings = (source: string) => {
const regex = /<h2 id="(.*?)">(.*?)<\/h2>/g;
const linkRegx = /id="(.*?)"/;
if (source.match(regex)) {
return source.match(regex)?.map((heading) => {
const headingText = heading
.replace(/<h2 id="(.*?)">/, '')
.replace(/<\/h2>/, '');
const link = '#' + heading.match(linkRegx)?.[1];
return {
text: headingText,
link,
};
});
}
return [];
};

View File

@ -1,7 +1,7 @@
import remarkFrontmatter from 'remark-frontmatter';
import mdx from '@next/mdx';
import rehypePrism from '@mapbox/rehype-prism';
import remarkToc from 'remark-toc';
// import remarkToc from 'remark-toc';
import composePlugins from 'next-compose-plugins';
import remarkGfm from 'remark-gfm';
import rehypeSlug from 'rehype-slug';
@ -12,7 +12,7 @@ const composedConfig = composePlugins([
options: {
remarkPlugins: [
remarkFrontmatter,
() => remarkToc({ maxDepth: 2 }),
// [remarkToc, { maxDepth: 2 }],
remarkGfm,
],
rehypePlugins: [rehypePrism, rehypeSlug],

View File

@ -14,8 +14,6 @@ export const meta = {
export default ({ children }) => <Layout {...meta}>{children}</Layout>;
## Table of contents
## Hello
This is my second post.

View File

@ -2,15 +2,6 @@
@apply text-lg leading-10;
}
/* For the table of content */
#article h2#table-of-contents + ul {
@apply border-l-4 border-gray-300;
@apply pl-4;
}
#article h2#table-of-contents:hover::before {
content: unset;
}
#article h1 {
font-weight: bold;
text-align: center;