nextjs+MDX渲染md文件并生成目录

一、效果展示

线上网站:点击体验
md文件

网页

二、需要使用的模块包

包名 作用
@mdx-js/react 用来渲染react组件
@next-mdx-remote 将字符串转换成html标签
@remark-slug 为html标签添加id(锚点跳转)
@mapbox/rehype-prism 添加代码高亮
@jsdevtools/rehype-toc 生成目录
@remark-gfm 渲染表格插件

三、使用方法

项目目录结构
1

1.在_app.js中导入mdx-js/react
import { MDXProvider } from '@mdx-js/react';
function MyApp({ Component, pageProps }) {// 定义 mdx 中语法的映射组件const components = {// img: props => <Image {...props}></Image>,h1: props => {return <h1><div id={props.id} className='relative -top-24 invisible' ></div><a href={'#' + props.id}>{props.children}</a></h1>},h2: props => {return <h2><div id={props.id} className='relative -top-24 invisible' ></div><a href={'#' + props.id}>{props.children}</a></h2>},h3: props => {return <h3><div id={props.id} className='relative -top-24 invisible' ></div><a href={'#' + props.id}>{props.children}</a></h3>},h4: props => {return <h4><div id={props.id} className='relative -top-24 invisible' ></div><a href={'#' + props.id}>{props.children}</a></h4>},wrapper: ({ children, ...props }) => {// console.log(children.map(child => child.props.mdxType))// console.log(React.Children.toArray(children), 999)// console.log(children)// console.log(props, 111)// if (props.layout) {//   return <main {...props} />// }return <>{children}</>}}return <MDXProvider components={components}><Component {...pageProps}/></MDXProvider>
}export default MyApp
2.在blog/[name].js中

2.1通过getStaticProps在服务器使用fs模块运行读取content文件目录下的md文件内容
2.2配置MDX各种插件
2.3在通过MDXRemote将文件内容渲染出来
2.4通过插件获取到元数据和目录
2.5在组件prop中获取到内容
2.6通过自定义组件TableContents生成自己的目录

import { serialize } from 'next-mdx-remote/serialize'
import { MDXRemote } from 'next-mdx-remote'
import Layout from "../../components/Layout";
import slug from 'remark-slug'
import remarkGfm from 'remark-gfm'
import rehypePrism from '@mapbox/rehype-prism'
import TableContents from '../../components/TableContents';
import React from 'react';// import { useInView } from 'react-intersection-observer';
export default function BlogPage(props) {const [id, setId] = React.useState(array[0])return (<div className="wrapper"><Layout href='/blog' full={true} theme={props.theme} setTheme={props.setTheme}>{/* <div>{props.source.frontmatter.title}</div> */}<div className='grid grid-cols-4 gap-6 relative'><div className='markdown xl:col-span-3 col-span-5 p-5 rounded-lg dark:bg-[#222222] box-shadow bg-white'><MDXRemote {...props.source} /></div><div className='xl:block hidden'><div className='sticky top-24 p-5 rounded-lg dark:bg-[#222222] box-shadow bg-white'><h3 className="text-xl text-gray-900 dark:text-gray-100 dark:opacity-90 font-bold pb-4">目录</h3><TableContents idTable={id} {...props.tocElement}></TableContents></div></div></div></Layout></div>)
}export async function getStaticProps(context) {// MDX text - can be from a local file, database, anywhereconst fs = require('fs')const path = require('path')const toc = require("@jsdevtools/rehype-toc");let tocElementconst { name } = context.paramslet source = String(fs.readFileSync(path.join(process.cwd(), 'src', 'content', name + '.md')))const mdxSource = await serialize(source, {scope: {},mdxOptions: {remarkPlugins: [slug, remarkGfm],rehypePlugins: [rehypePrism, [toc, {headings: ['h1', 'h2', 'h3', 'h4'],customizeTOC: (tocAll) => {tocElement = tocAllreturn false}}]],format: 'mdx'},parseFrontmatter: true})return { props: { source: mdxSource, tocElement: tocElement } }
}
export async function getStaticPaths() {return {paths: [],fallback: 'blocking'}
}

TableContents组件

//拼接字符串工具
import clsx from 'clsx'
import React from 'react'export default function TableContents(props) {switch (props.tagName) {case 'nav': {return (<nav {...props.properties}>{props.children.map((item, index) => {return <TableContents {...item} key={index} idTable={props.idTable} />})}</nav>)};case 'ol': {return (<ol {...props.properties}>{props.children.map((item, index) => {return <TableContents {...item} key={index} idTable={props.idTable} />})}</ol>)};case 'li': {return (<li {...props.properties}>{props.children.map((item, index) => {return <TableContents {...item} key={index} idTable={props.idTable} />})}</li>)};case 'a': {return (<a {...props.properties} className={clsx('block py-1 text-sm font-medium hover:text-[#428dcc] focus:outline-none dark:hover:text-gray-200 focus-visible:text-gray-700 dark:opacity-90 dark:focus-visible:text-gray-200 text-gray-400', props.properties.href == '#' + props.idTable && 'text-[#428dcc] dark:text-gray-200')}>{props.children.map((item, index) => {return <TableContents {...item} key={index} />})}</a>)};default: return (<>{props.value}</>)}
}
3.引入CSS样式

在_app.js中
markdown样式可自行设计
prism官网代码高亮样式点击链接下载

import '../styles/prism.css'
import '../styles/markdown.css'
4.项目源码链接github

nextjs+MDX渲染md文件并生成目录相关推荐

  1. md文件自动生成目录[docsify]

    1.下载该工具,配置文件路径,双击程序运行即可 下载地址 -----  Docsify:自动生成sidebar与子目录sidebar_Sidebar-互联网文档类资源-CSDN下载 2.运行结果 3. ...

  2. VuePress 开发技术文档网站,管理.md文件,生成静态网站

    目录 最终效果 开发流程 1. 新建文件夹  mydocs 2. 初始化项目 3. 安装 VuePress 4. 添加项目脚本 5. 添加 .md文件 6. 添加项目配置 7. 运行项目 参考资料 最 ...

  3. 文件夹文件自动生成目录的方法-保存到txt

    文件夹文件自动生成目录的方法-保存到txt 1.打开记事本: 2.复制以下内容: @echo off     dir /b /on >list.txt 3.另存为bat,类型ANSI

  4. .md文件自动生成项目目录结构

    自动生成项目目录结构 1)安装mddir (-g是全局安装,可以选择不全局安装,这里因为以后都要使用所以选择的全局安装) npm install mddir -g 2)cd 到你想生成目录的工程结构, ...

  5. md 文件使用html阅读,使用markdow-it渲染md文件为html页面

    前言:最近在写一些新闻资讯详情的页面,header组件.footer组件.目录组件都是固定的,只有新闻的内容是变化的.为了不去写重复的代码(有句话怎么说来着:战略上偷懒,战术上勤奋,就是这个意思),准 ...

  6. html 渲染md文件,markdown的学习和.md文件使用

    Markdown Table of Contents 标准 Markdown 标题 # H1 ## H2 ### H3 #### H4 ##### H5 ###### H6 另外, 对于 H1 和 H ...

  7. vue渲染.md文件

    1. 在package.json文件安装以下依赖,npm install "dependencies": {"github-markdown-css": &qu ...

  8. pdf文件如何生成目录 wps_wps制作pdf文档的详细方法

    一些用户在使用wps软件的时候,wps怎样制作pdf文档?你们知道怎么操作的吗?对此感兴趣的伙伴们可以去下文看看wps制作pdf文档的详细方法. wps制作pdf文档的详细方法 一.打开或生成原始文件 ...

  9. md文件语法及目录使用

    标题的使用 # ==<h1> ## <h2> ................ 空格的使用     换行的使用 ①段落换行  回车 ②普通换行  space +space+回车 ...

最新文章

  1. Android 应用进行性能分析/APP/系统性能分析
  2. 关于 TApplication 详解 三 ---- TComponent
  3. 在leangoo里怎么复制列表,删除列表,插入列表?
  4. 【Xmind】,让你的大脑解放出来
  5. mac 黑窗口连接mysql_Mac系统Python、PyCharm安装及使用方法详解
  6. Redis Sentinel 配置文件
  7. linux设置python3为默认python_Ubuntu 18.04将Python3设置为Python默认版本
  8. Jest + React Testing Library 单测总结
  9. 后台系统可扩展性学习笔记(十四)异步机制与MQ
  10. 【温故而知新-Javascript】使用canvas元素(第一部分)
  11. 【Python】AttributeError: 'Series' object has no attribute 'order'
  12. 光伏并网发电及低电压穿越技术
  13. 2012浙江大学光华法学院毕业典礼教师发言
  14. 谢晶:webpower中国区正在向“多渠道智能化营销”全面转型
  15. 企业云盘的作用不仅只是存储
  16. 拼多多店铺营业执照相关问题
  17. 从删库到跑路再到权限管理
  18. java.lang.NoClassDefFoundError: org/jdom2/JDOMException
  19. 数仓工具—Hive源码之SQL解析Antlr入门(7)
  20. 详解Ubuntu的网络配置

热门文章

  1. React学习资源汇总
  2. 使用UltraISO软碟通制作Win10PE启动U盘
  3. mysql数据库全局搜索_数据库全局搜索
  4. android多个广告sdk回调处理,Android逆向 今日头条的广告SDK分析
  5. python怎么利用数据成像_使用Python对大脑成像数据进行可视化分析
  6. linux配置SVN,添加用户,配置用户组的各个权限教程
  7. Laravel OAuth2 (二) ---配置与数据库设计
  8. QTableWidget表格控件的用法
  9. PT100(RTD)三线制四线制测量方案
  10. 关于线上支付的实现思想方法与例子