最近在做一个的个人博客的 nextjs 项目使用到了掘金 md 编辑器这里记录下集成的过程
ByteMD 仓库 猛击访问 虽然已经好久没有更新了但是不影响使用该有的都有了
支持多种框架
支持多种插件
所有代码已上传 github 猛击访问
初始化一个 nextjs 项目
执行 npx create-next-app@latest
初始化一个 nextjs 项目
打开项目执行 npm run dev
启动项目看一下,一般都是没什么问题的
开始集成
安装掘金编辑器依赖
执行 npm i bytemd @bytemd/react
安装编辑器
执行 npm i @bytemd/plugin-mermaid @bytemd/plugin-medium-zoom @bytemd/plugin-math-ssr @bytemd/plugin-math @bytemd/plugin-highlight-ssr @bytemd/plugin-gfm @bytemd/plugin-gemoji @bytemd/plugin-frontmatter @bytemd/plugin-footnotes @bytemd/plugin-breaks
安装依赖
执行 npm i juejin-markdown-themes
安装掘金主题
执行 npm i sass
安装 sass 依赖后边需要使用 scss 来写样式
创建组件目录
在 app/components/bytemd
创建对应的文件夹
创建 plugins.ts
文件
plugins.ts
文件把所有的插件统一引入导出, 这里这样做的原因是会创建一个编辑器和预览组件统一导出后就不需要写两遍了
import breaks from '@bytemd/plugin-breaks'
import frontmatter from '@bytemd/plugin-frontmatter'
import gemoji from '@bytemd/plugin-gemoji'
import gfm from '@bytemd/plugin-gfm'
import highlightSsr from '@bytemd/plugin-highlight-ssr'
import mediumZoom from '@bytemd/plugin-medium-zoom'
import mermaid from '@bytemd/plugin-mermaid'
import footnotes from '@bytemd/plugin-footnotes'
import math from '@bytemd/plugin-math-ssr'
import mermaid_zhHans from '@bytemd/plugin-mermaid/lib/locales/zh_Hans.json'
import math_zhHans from '@bytemd/plugin-math/lib/locales/zh_Hans.json'
import gfm_zhHans from '@bytemd/plugin-gfm/lib/locales/zh_Hans.json'
const plugins = [
breaks(),
frontmatter(),
gemoji(),
gfm({ locale: gfm_zhHans }),
math({ locale: math_zhHans }),
highlightSsr(),
mermaid({ locale: mermaid_zhHans }),
mediumZoom(),
footnotes()
]
export default plugins
编辑器样式
在官方仓库没有找到预览的深色主题的样式,自己写了一下 猛击访问
创建 editor.scss
@import 'bytemd/dist/index.css';
@import 'juejin-markdown-themes/dist/juejin.css';
// @import 'highlight.js/styles/default.css';
@import 'highlight.js/styles/atom-one-dark.css'; // 代码高亮主题 掘金编辑器已经依赖这个 highlight.js 这里无需单独安装
// @import 'highlight.js/styles/a11y-dark.css';
.bytemd {
// 设置默认高度,防止内容过少时,高度不够显示
height: 100vh;
border: 0;
overflow: hidden;
}
创建 editor.tsx
编辑组件
'use client'
import './editor.scss' // 编辑器样式
import plugins from './plugins' // 引入统一导出的插件
import { Editor } from '@bytemd/react'
import zh_Hans from 'bytemd/locales/zh_Hans.json' // 中文语言包
interface UploadImage {
url: string,
alt: string,
title: string
}
// 上传图片
async function uploadImages(files: File[]) {
const resultData:UploadImage[] = []
for (const item of files) {
const formData = new FormData()
formData.append('file', item)
const res = await fetch('/api/upload', {
method: 'POST',
body: formData
})
const data = await res.json()
if (data?.code === 0) {
// 上传成功后安装指定格式返回
resultData.push({
url: data?.data,
alt: item.name,
title: item.name
})
}
}
return resultData
}
interface BytemdEditorProps {
content: string
setContent: (content: string) => void
}
export function BytemdEditor({ content, setContent }: BytemdEditorProps) {
return (
<Editor
value={content}
locale={zh_Hans}
plugins={plugins}
onChange={(v) => {
setContent(v)
}}
uploadImages={uploadImages}
/>
)
}
编辑器组件的使用
'use client'
import { useState } from 'react';
import { BytemdEditor } from './components/bytemd/editor'
export default function Home() {
const [content, setContent] = useState('')
return (
<BytemdEditor content={content} setContent={setContent}></BytemdEditor>
);
}
创建 viewer.tsx
预览组件
'use client'
import { Viewer } from '@bytemd/react'
import plugins from './plugins'
import './editor.scss'
import './dark-theme.scss'
export function BytemdViewer({ content }: { content: string }) {
return <Viewer value={content} plugins={plugins}></Viewer>
}
预览组件的使用
'use client'
import { useEffect, useState } from 'react';
import { BytemdViewer } from '../components/bytemd/viewer'
export default function Home() {
const [content, setContent] = useState('')
useEffect(() => {
fetch('/api/md').then((res) => res.json()).then(res => {
console.log(res)
setContent(res.content)
})
}, [])
return (
<div>
<div className='max-w-5xl mx-auto'>
<BytemdViewer content={content} ></BytemdViewer>
</div>
</div>
);
}
成果展示
可以看到与官方示例一样!
预览组件的渲染也符合预期
看下自定义的深色主题也还行
总结
本文实践了在 nextjs 中如何集成掘金的 bytemd 编辑器以及插件的集成
封装了一个编辑器组件和预览组件
因为官方没有提供深色主题所以还自行实现了深色主题的样式
预览组件的样式切换是通过引入不同的 css 来实现 juejin-markdown-themes
这个包提供一些已经定义好的主题