前言✨
在开发博客的时候想找一个颜值、功能都强大的markdown编辑器,看了CSDN觉得ui太丑,看了简书的又感觉功能不够强大,然后看了掘金的编辑器感觉非常符合我的气质,后来去查了一下掘金用的编辑器叫Bytemd。
ByteMD 是一个使用 Svelte 构建的 Markdown 编辑器组件。它也可以用于其他库/框架,例如 React、Vue 和 Angular,是字节跳动团队开发维护的开源项目。
gitHub:github.com/bytedance/b…
官方示例:bytemd.netlify.app/
安装⚙
可以看到他有三个版本,由于我的博客是react开发的所以我需要安装@bytemd/react
$ yarn add @bytemd/react
插件介绍及使用💻
Bytemd目前有多种插件来增强优化markdown的能力如下:
首先要引入所需插件
import zhHans from 'bytemd/lib/locales/zh_Hans.json';// 中文插件
import gfm from '@bytemd/plugin-gfm';// 支持GFM
import highlight from '@bytemd/plugin-highlight';// 代码高亮
import 'highlight.js/styles/monokai-sublime.css';// 代码高亮的主题样式(可自选)
import frontmatter from '@bytemd/plugin-frontmatter';// 解析前题
import mediumZoom from '@bytemd/plugin-medium-zoom';// 缩放图片
定义插件
const plugins = [
gfm(), // GFM
highlight(), // 代码高亮
frontmatter(), // 解析前题
mediumZoom(), // 图片缩放
gemoji() // Gemoji短代码
];
在bytemd中使用
<Editor
locale={zhHans}
plugins={plugins}
value={props.value}
onChange={(v) => props.setValue(v)}
/>
增加图片上传功能🎨
uploadImages使用方法,需要return出数组
import { uploadImg } from '@/services/upload';// 接口地址
<Editor
value={props.value}
onChange={(v) => props.setValue(v)}
uploadImages={async (files: any) => {
let imgUrl = '';
let fromData = new FormData();
fromData.append('uploadImg', files[0]);
const res = await uploadImg(fromData);
if (res.code === 200) {
imgUrl = res.data;// 这里是上传成功后,服务端返回的图片地址
} else {
console.log(图片上传失败)
}
return [
{
title: files.map((i) => i.name),
url: imgUrl,
},
];
}}
/>
封装成react组件及使用🎈
封装index.tsx (完整代码)
import React from 'react';
import { Editor } from '@bytemd/react';
import zhHans from 'bytemd/lib/locales/zh_Hans.json';// 中文插件
import gfm from '@bytemd/plugin-gfm';// 支持GFM
import highlight from '@bytemd/plugin-highlight';// 代码高亮
import 'highlight.js/styles/monokai-sublime.css';// 代码高亮的主题样式(可自选)
import frontmatter from '@bytemd/plugin-frontmatter';// 解析前题
import mediumZoom from '@bytemd/plugin-medium-zoom';// 缩放图片
import { uploadImg } from '@/services/upload';
import { notification } from 'antd';
import 'bytemd/dist/index.min.css';// bytemd基础样式必须引入!!!
import 'juejin-markdown-themes/dist/juejin.min.css';// 掘金同款样式
interface EditorProps {
value: string;
setValue: any;
}
const plugins = [
gfm(), // GFM
highlight(), // 代码高亮
frontmatter(), // 解析前题
mediumZoom(), // 图片缩放
gemoji(), // Gemoji短代码
];
const Bytemd: React.FC<EditorProps> = (props) => {
return (
<>
<Editor
locale={zhHans}
plugins={plugins}
value={props.value}
onChange={(v) => props.setValue(v)}
uploadImages={async (files: any) => {
let imgUrl = '';
let fromData = new FormData();
fromData.append('uploadImg', files[0]);
const res = await uploadImg(fromData);
if (res && res.code === 200) {
imgUrl = res.data;// 这里是上传成功后,服务端返回的图片地址
} else {
notification.error({
message: '图片上传失败',
});
}
return [
{
title: files.map((i) => i.name),
url: imgUrl,
},
];
}}
/>
</>
);
};
export default Bytemd;
使用方式,articleDetail.tsx (精简代码)
import React, { useEffect, useState } from 'react';
import Bytemd from '@/components/Bytemd';// 引入组件
import {getArticleDetail } from '@/services/article';// 引入请求接口
const ArticleDetail: React.FC = () => {
// 单独存取markdown值,因为我们不仅有新增还有编辑文章的场景
const [value, setValue] = useState<string>('');
useEffect(() => {
getDetail();
}, []);
// 获取数据
const getDetail = async () => {
const res = await getArticleDetail({ id: query.id as string });
if (res.code === 200) {
setValue(res.data.content);// 赋值
}
};
return (
<Bytemd value={value || ''} setValue={setValue} />
)
}
export default ArticleDetail;