在Next.js中使用remark和PrismJS来突出显示Markdown中的代码

4

我希望在我的Next.js博客中包含PrismJS,以便突出显示.md文件中的代码。使用remarkremark-html在/lib/posts.js中处理markdown并将其作为HTML传递给react-markdown

// /lib/posts.js

export async function getPostData(id) {
  const fullPath = path.join(postsDirectory, `${id}.md`);
  const fileContents = fs.readFileSync(fullPath, "utf8");

  const matterResult = matter(fileContents);

  const processedContent = await remark()
    .use(html)
    .process(matterResult.content);
  const contentHtml = processedContent.toString();

  return {
    id,
    contentHtml,
    ...matterResult.data,
  };
}

内容Html是在[id].js中获取的,我使用ReactMarkdown进行渲染。在这里,我导入Prism并使用CodeBlock函数进行高亮显示。我在_app.js中导入prism.css,放在我的global.css旁边。

// /pages/_app.js

import Container from "../components/Container";
import "../styles/global.css";
import "../styles/prism.css";

export default ({ Component, pageProps }) => (
  <Container>
    <Component {...pageProps} />
  </Container>
);


// /pages/posts/[id].js

import { getAllPostIds, getPostData } from "../../lib/posts";
import ReactMarkdown from "react-markdown/with-html";
import Prism from "prismjs";

const CodeBlock = (language, values) => {
  return <Prism language={language}>{values}</Prism>;
};

export default function Post({ postData }) {
  return (
    <ReactMarkdown
      escapeHtml={false} // Dangerous if content is user-generated
      source={postData.contentHtml}
      renderers={{ code: CodeBlock }}
    />
  );
}

export async function getStaticPaths() {
  const paths = getAllPostIds();
  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps({ params }) {
  const postData = await getPostData(params.id);
  return {
    props: {
      postData,
    },
  };
}

当我手动输入URL并按回车时,它能正常工作。例如 https://nextjs-blog-ivory-nine.vercel.app/posts/first-next-js-blog-devdiary 但是当我从主页面https://nextjs-blog-ivory-nine.vercel.app导航到第一篇文章时,代码就无法高亮显示。 你有什么想法吗? 提前感谢!

你尝试过使用 prism-react-renderer 吗? - hangindev.com
2个回答

13

我有同样的问题,但是对于Python高亮显示无效。 - Rolly

4

假设您已经能够使用remark来使用markdown,但没有安装Prism。添加Prism可以通过以下几个步骤完成:

yarn add remark-prism

在静态渲染期间调用解析器。
import remark from 'remark'
import html from 'remark-html'
import prism from 'remark-prism';

// ...
const parser = remark().use(html).use(prism)

在HTML头部添加CSS。这个工作只是由用户浏览器完成的CSS。我使用了这个链接:https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-coy-without-shadows.min.css,但还有其他选项。

import Head from 'next/head'

const Article = ({post}: ArticleProps) => {

  return (
    <div>
      <Head>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-coy-without-shadows.min.css" rel="stylesheet" />
      </Head>
      <article className={article.blogpost}>
         {/* ... */}
      </article>
    </div>
  )
}

export default Article

请注意,添加.use(prism)会显著减慢SSR!这在开发模式下是一个问题,但在导出的HTML网站中不是。

2
在上面的示例中,请确保将 sanitize 设置为 false。remark().use(prism).use(html, { sanitize: false }).process(markdown) - mattferderer
1
这种方法在nextjs 13中无法与应用程序目录一起使用。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接