花了3个小时,我用AI开发了一个markdown文档编辑器

1,418 阅读3分钟

hi, 大家好, 我是徐小夕. 之前一直在社区分享零代码&低代码的技术实践,也陆陆续续设计并开发了多款可视化搭建产品,比如:

  • H5-Dooring(页面可视化搭建平台)
  • V6.Dooring(可视化大屏搭建平台)
  • Flowmix/Docx 多模态文档编辑器: 让文档不止于文档

最近也一直在研究多模态文档 + AI相关的技术实践, 花了一天时间,做了一款可本地存储数据和文档管理的开源markdown编辑器——md-editor。

图片

一. 什么是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 授权,这意味着我们可以自由地使用、修改和分发该项目。我们非常欢迎各种形式的贡献。

更多推荐