在Next.js中让md文档转html后高亮代码块

1,821 阅读2分钟

最近是在使用Next.js搭建个人blog,遇到了这个问题。原本以为使用remark插件就能轻松的把md格式转换为html格式,并且代码块自动高亮显示呢。

然并没有。简单记录下最后的解决方式。

md转html

在lib的工具函数中,我引入了remark和html

import { remark } from "remark";
import html from "remark-html";

...
// Use remark to convert markdown into HTML string
const processedContent = await remark()
        .use(html)
        .use(codeblocks)
        .process(matterResult.content);
const contentHtml = processedContent.toString();

所以在文章详情的页面中,直接使用contentHtml。

export default function Post({ postData }) {

    return (
        <Layout>
            <Head>
                <title>{postData.title}</title>
            </Head>
            <div className="w-full mx-0 mt-6 overflow-scroll">
                {postData.title}
                <br />
                {postData.id}
                <br />
                <Date dateString={postData.date} />
                <br />
                <div
                    dangerouslySetInnerHTML={{ __html: postData.contentHtml }}
                />
            </div>
        </Layout>
    );
}

最后出来页面上出来的效果是这样的。。

image-20220330152436652.png

看上去简直像毛坯房!藍

应该是少了code block样式之类的东西,去remark的插件列表找了一下。尝试了几个插件后,都没有效果。

image-20220330153404440.png

一波google下来找到了**highlight.js**插件。用起来还挺简单。果断一波先一波import!

使用highlight.js

还是在上面的文章详情的页面中

import "highlight.js/styles/github.css"; // github样式文件
import hljs from "highlight.js/lib/core"; // highlight.js核心
import javascript from "highlight.js/lib/languages/javascript"; // 单独使用js部分

hljs.registerLanguage("jsx", javascript);
hljs.highlightAll();

command+s !!

廊廊廊

image-20220311104635569.png

解决报错

这里报错了,应该是hljs是直接作用在dom上而这个时候组件并没有渲染到页面上。顺着这个思路,想到加一个useEffect就好了。然后把hljs的调用放在useEffect中执行。最终效果如下。

image-20220330155257443.png

这样就解决了markdown转html后,代码块没有样式的问题。

最后附上这个页面的完整代码。

import Layout from "../../components/layout";
import { getAllPostIds, getPostData } from "../../lib/posts";
import Head from "next/head";
import Date from "../../components/date";
import "highlight.js/styles/github.css";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import { useEffect } from "react";

export default function Post({ postData }) {
    useEffect(() => {
        hljs.registerLanguage("jsx", javascript);
        hljs.highlightAll();
    });
    return (
        <Layout>
            <Head>
                <title>{postData.title}</title>
            </Head>
            <div className="w-full mx-0 mt-6 overflow-scroll">
                {postData.title}
                <br />
                {postData.id}
                <br />
                <Date dateString={postData.date} />
                <br />
                <div
                    dangerouslySetInnerHTML={{ __html: postData.contentHtml }}
                />
            </div>
        </Layout>
    );
}

export async function getStaticPaths() {
    // Return a list of possible value for id
    const paths = getAllPostIds();
    console.log("getStaticPaths", paths);
    return {
        paths,
        fallback: false,
    };
}

export async function getStaticProps({ params }) {
    // Fetch necessary data for the blog post using params.id
    const postData = await getPostData(params.id);
    return {
        props: {
            postData,
        },
    };
}