hi, 大家好, 我是徐小夕. 之前一直在社区分享零代码&低代码的技术实践,也陆陆续续设计并开发了多款可视化搭建产品,比如:
- H5-Dooring(页面可视化搭建平台)
- V6.Dooring(可视化大屏搭建平台)
- Flowmix/Docx 多模态文档编辑器: 让文档不止于文档
最近也一直在研究多模态文档 + AI相关的技术实践, 花了一天时间,做了一款可本地存储数据和文档管理的开源markdown编辑器——md-editor。
- github地址:github.com/MrXujiang/m…
一. 什么是md-editor?
在当今数字化的时代,Markdown 作为一种轻量级的标记语言,因其简洁、易读易写的特性,在开发者和文字工作者中广受欢迎。为了满足大家对于高效、便捷 Markdown 编辑的需求,我花了3个小时,开发了md-editor
—— 一款开箱即用的开源 Markdown 编辑器。
md-editor
是一款专为开发者和文字工作者设计的开源 Markdown 编辑器,致力于让创作回归纯粹,同时赋予用户专业级的编辑力量。它融合了极简界面与强大功能,无论你是在记录日常笔记、撰写技术文档还是进行博客创作,md-editor
都能成为你的得力助手。
二. 技术栈
- 核心框架:采用 React 和 Typescript 作为核心技术栈,结合了 React 的组件化开发思想和 Typescript 的静态类型检查优势,让代码更加健壮、易于维护。
- 编辑器引擎:基于 ByteMd 构建,ByteMd 是一个功能强大的 Markdown 编辑器引擎,提供了丰富的插件系统和良好的用户体验。
- 样式系统:使用 Less 和 CSS Module 来管理样式,使得样式的编写和维护更加灵活、高效。
我们可以根据自己的喜好和项目需求,选择不同的安装方式:
# yarn or pnpmnpm install
本地启动:
npm run dev
本地打包部署:
npm run build
总之,如果我们想在本地对 md-editor
进行开发和调试,只需简单的几步:
git clone git@github.com:MrXujiang/md-editor.gitcd md-editornpm installnpm run dev
三、核心功能与代码实现
1. 编辑器配置
在EditorContainer.tsx
文件中,我们对编辑器进行了详细的配置:
// 配置 ByteMD 插件
const plugins = [
gfm({
// 配置 GFM 插件选项
breaks: true, // 支持软换行
bulletListMarker: '-', // 无序列表标记
emoji: true, // 支持 emoji
tasklist: true, // 支持任务列表
strikethrough: true, // 支持删除线
list: true
}),
highlight({
// 配置代码高亮
theme: 'github' // 或其他主题
}),
math(),
breaks(),
frontmatter(),
mermaid()
];
// 编辑器配置
const editorConfig = {
mode: 'split', // 分屏模式
placeholder: '开始编写你的 Markdown 文档...',
uploadImages: async (files: File[]) => {
// 这里可以实现图片上传功能
return files.map(file => ({
url: URL.createObjectURL(file),
alt: file.name,
title: file.name
}));
}
};
通过这些配置,我们为用户提供了丰富的 Markdown 编辑功能,包括软换行、emoji 支持、代码高亮、数学公式、任务列表等,同时还支持图片上传。
2. 文档管理
md-editor
支持创建、保存、删除文档等基本操作,并且使用 localStorage
来实现数据的持久化存储:
const createNewDoc = () => {
const newDoc: Document = {
id: `doc_${Date.now()}`,
title: '未命名文档',
content: getDefaultContent(),
created: Date.now(),
updated: Date.now()
};
setDocuments([newDoc, ...documents]);
setCurrentDoc(newDoc);
showNotification('新文档已创建', 'success');
};
const saveDoc = () => {
if (!currentDoc) return;
const updatedDoc = {
...currentDoc,
updated: Date.now()
};
setDocuments(documents.map(doc =>
doc.id === currentDoc.id ? updatedDoc : doc
));
setCurrentDoc(updatedDoc);
localStorage.setItem('lastDocId', updatedDoc.id);
showNotification('文档已保存', 'success');
};
const deleteDoc = (docId: string) => {
if (!window.confirm('确定要删除这个文档吗?')) return;
setDocuments(documents.filter(doc => doc.id !== docId));
if (currentDoc?.id === docId) {
setCurrentDoc(null);
}
showNotification('文档已删除', 'success');
};
3. 实时保存与标题提取
在我们编辑文档时,md-editor
会自动保存文档内容,并实时提取文档标题:
const handleDocChange = (content: string) => {
console.log(content);
if (!currentDoc) return;
const title = extractTitle(content) || '未命名文档';
setCurrentDoc({
...currentDoc,
title,
content,
updated: Date.now()
});
// 自动保存
const updatedDocs = documents.map(doc =>
doc.id === currentDoc.id ? { ...doc, title, content, updated: Date.now() } : doc
);
localStorage.setItem('lastDocId', currentDoc.id);
setDocuments(updatedDocs);
};
const extractTitle = (content: string): string => {
// 从内容中提取第一个标题作为文档标题
const match = content.match(/^#\s+(.+)$/m);
return match ? match[1].trim() : '';
};
4. 开源与贡献
md-editor 采用 MIT License 授权,这意味着我们可以自由地使用、修改和分发该项目。我们非常欢迎各种形式的贡献。