1 推荐md-editor-rt
说明文档地址:(imzbf.github.io/md-editor-r…)
github:(github.com/imzbf/md-ed…)
推荐理由:
- 一款很健全的markdown第三方库,文档说明详细
- 兼容react,typescript
- 虽然 star少,但是遇到问题作者还是很愿意回答
- 代码theme和预览theme还是很多可选友好的。
- 可拓展性强
2 文件上传下载
2.1 下载的解决方式
目前主流的上传下载后端接口都需要请求接口带token,内部的md转html我是没有过多的研究,所以我是让后端把下载接口加入白名单中,免去token认证,思路是利用markdown的链接,点击给a标签加入_black属性.
具体配置如下:
import { config } from 'md-editor-rt';
// 修改配置
config({
markdownItConfig(md) {
md.use(TargetBlankExtension);
},
});
const TargetBlankExtension = (md: markdownit) => {
const defaultRender =
md.renderer.rules.link_open ||
function (tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
const aIndex = tokens[idx].attrIndex('target');
if (aIndex < 0) {
tokens[idx].attrPush(['target', '_blank']);
} else {
// @ts-ignore
tokens[idx].attrs[aIndex][1] = '_blank';
}
// pass token to default renderer.
return defaultRender(tokens, idx, options, env, self);
};
};
这样就可以实现a标签加上_blank属性
2.2 上传组件
这个第三方库没有提供上传的按钮,但是支持自定义拓展, 具体可以看文档:自定义工具栏、自定义工具栏例子
上传接口就略过了,没啥好说的,formData然后提交。
上传工具栏组件:
import { OnUploadFileFun } from '@/components/MdEditor/data';
import { FileAddOutlined } from '@ant-design/icons';
import { Upload } from 'antd';
import { InsertContentGenerator, NormalToolbar } from 'md-editor-rt';
import type { UploadRequestOption } from 'rc-upload/lib/interface';
interface MarkExtensionProp {
onInsert: (generator: InsertContentGenerator) => void;
}
const UploadFile = (props: MarkExtensionProp & { onUploadFileFun: OnUploadFileFun }) => {
const uploadFileHandler = (files: UploadRequestOption) => {
const file = files.file as File;
// 1. 校验文件大小,确保不超过1MB
// const maxSize = 1 * 1024 * 1024; // 1MB
// if (file.size > maxSize) {
// console.log('文件大小不能超过1MB');
// message.error('文件大小不能超过1MB');
// return;
// }
const form = new FormData();
form.append('file', file);
if (props.onUploadFileFun.formData) {
Object.keys(props.onUploadFileFun.formData).forEach((key) => {
// @ts-ignore
form.append(key, props.onUploadFileFun.formData[key]);
});
}
props.onUploadFileFun.func(form).then((url) => {
const generator: InsertContentGenerator = () => {
return {
targetValue: `[文件:${file.name}-点击下载](${url})`,
select: true,
deviationStart: 0,
deviationEnd: 0,
};
};
props.onInsert(generator);
});
};
return (
<NormalToolbar
title="上传文件"
onClick={() => {}}
trigger={
<Upload showUploadList={false} customRequest={uploadFileHandler}>
<FileAddOutlined
style={{
width: '30px',
height: '30px',
fontSize: '20px',
}}
/>
</Upload>
}
></NormalToolbar>
);
};
export default UploadFile;
这里接收了一个默认上传方法,如果有传的话就按你自定义的上传方法走,否则走默认定义的上传方法。
外部调用:
import UploadFile from '@/components/MdEditor/component/UploadFile';
import '@/styles/md-editor/index.css';
import { ExposeParam, InsertContentGenerator, MdEditor } from 'md-editor-rt';
import { EditorProps } from 'md-editor-rt/lib/types/MdEditor/type';
import React, { useCallback, useEffect, useState } from 'react';
const MarkDownEditor: React.FC = () => {
const [mdValue, setMdValue] = useState<string>('');
useEffect(() => {
setMdValue(customProp.initContent || '');
}, [customProp.initContent]);
const onInsert = useCallback((generator: InsertContentGenerator) => {
editorRef.current?.insert(generator);
}, []);
return (
<MdEditor
style={{ height: '700px' }}
ref={editorRef}
modelValue={mdValue}
onChange={setMdValue}
previewTheme="default"
defToolbars={[
<UploadFile
onInsert={onInsert}
key="uploadFile"
></UploadFile>,
]}
/>
);
};
export default MarkDownEditor;