import React, { useEffect, useMemo, useState, useRef } from 'react';
import * as ReactMarkdown from 'react-markdown';
import styles from './index.less';
import MarkdownIt from 'markdown-it';
import MdEditor from 'react-markdown-editor-lite';
// 参考文档:https://github.com/HarryChen0506/react-markdown-editor-lite/blob/master/docs/configure.zh-CN.md
import 'react-markdown-editor-lite/lib/index.css';
import { message, Image } from 'antd';
import { setUploadFile } from '@/services/globalService';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-light.css';
import 'highlight.js/styles/github.css';
const MarkdownModule = (props) => {
const mdParser = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}
return ''; // use external default escaping
},
});
const initState = () => ({
permissionLoading: true,
uploadImgLink: '',
value: '',
readyHtml: false,
}),
[state, setState] = useState(initState),
[messageApi, contextHolder] = message.useMessage();
const mdModuleRef = useRef(null); // 编辑器ref
const [mdContent, setMdContent] = useState('');
// Finish!
const handleEditorChange = ({ html, text }) => {
try{
// 自定义处理图片链接的正则表达式
const imageRegex = /!\[(.*?)\]\((.*?)\)/g;
text = text || "";
text = text.replace(imageRegex, (match, alt, src) => {
src = src || "";
if(src.includes(".mp4")){
return `<video width="320" height="240" controls><source src="${src}" type="video/mp4">${alt}</video>`;
}
return match;
});
}catch(e){
console.log("match",e)
}
setState((o) => ({
...o,
readyHtml: false,
}));
setMdContent(text);
changeEditor(text);
};
var defaultRender = mdParser.renderer.rules.image;
mdParser.renderer.rules.image = function (tokens, idx, options, env, self) {
let src = tokens[idx].attrs.find(attr => attr[0] === 'src');
if(src || src.length > 1){
src = src[1]
}
if(src.includes(".mp4")){
return `<video width="320" height="240" controls><source src="${src}" type="video/mp4">${tokens[idx].content}</video>`;
}
// 其他图片保持默认渲染方式
return defaultRender(tokens, idx, options, env, self);
};
const onImageUpload = (file) => {
return setUploadFile({ file: file, pathIndex: 0 }).then((response) => {
response = response.data || {};
if ('00000' !== response?.code) {
message.error('图片过大,请上传小于2MB的图片');
} else {
return response?.data?.url;
}
});
};
const changeEditor = (value) => {
props.changeEditor(value);
};
const renderHTMLDom = (text) => {
// 使用 markdown-it
// return mdParser.render(text);
// 使用 react-markdown
return <ReactMarkdown source={text} />;
// React.createElement(ReactMarkdown, {
// source: text,
// });
};
useEffect(() => {
setMdContent(props.value);
setState((o) => ({
...o,
readyHtml: props?.defaultKey == 1 || props.readOnly ? true : false,
}));
// setView({md:true})
return () => {};
}, [props]);
return (
<div
className={styles['preview-body']}
style={{ padding: '30px', borderRadius: '10px' }}
>
<MdEditor
ref={mdModuleRef}
placeholder="请输入"
readOnly={state?.readyHtml}
value={mdContent}
shortcuts={true}
preview={true}
lineNum={true}
subfield={true}
style={{ height: '500px' }}
config={{
view: {
menu: props?.defaultKey == 0 ? true : false,
md: props?.defaultKey == 0 ? true : false,
html: true,
},
imageAccept: '.jpg,.png,.jpeg,.svg,.mp4,.avi,.mp3,.flv',
// imageUrl: 'https://octodex.github.com/images/minion.png'
}}
renderHTML={(text) => mdParser.render(text)}
onChange={handleEditorChange}
// renderHTML={renderHTMLDom}
onImageUpload={onImageUpload}
changeEditor={changeEditor}
btnModePreview
/>
{contextHolder}
</div>
);
};
export default MarkdownModule;
markdown-it如何上传视频 react
于 2024-07-11 17:53:43 首次发布