好用的 Markdown 编辑器组件

ByteMD

bytedance/bytemd: ByteMD v1 repository (github.com)

这里由于我的项目是 Next,所以安装 @bytemd/react, 阅读官方文档,执行命令来安装编辑器主体、以及 gfm(表格支持)插件、highlight 代码高亮插件:

shell 复制代码
npm i @bytemd/react
npm i @bytemd/plugin-highlight @bytemd/plugin-gfm

但是浏览器的样式不好看,我们可以引入第三方主题:
github-markdown-css

shell 复制代码
npm install github-markdown-css
复制代码
import 'github-markdown-css/github-markdown-light.css';

然后使用组件:

src/components/MdEditor/index.tsx

tsx 复制代码
import { Editor } from "@bytemd/react";
import gfm from "@bytemd/plugin-gfm";
import highlight from "@bytemd/plugin-highlight";
import 'github-markdown-css/github-markdown-light.css';
import "bytemd/dist/index.css";
import "highlight.js/styles/vs.css";
import "./index.css";

interface Props {
    value?: string;
    onChange?: (v: string) => void;
    placeholder?: string;
}

const plugins = [gfm(), highlight()];

/**
 * Markdown 编辑器
 * @param props
 * @constructor
 */
const MdEditor = (props: Props) => {
    const { value = "", onChange, placeholder } = props;

    return (
        <div className="md-editor">
            <Editor
                value={value || ""}
                placeholder={placeholder}
                mode="split"
                plugins={plugins}
                onChange={onChange}
            />
        </div>
    );
};

export default MdEditor;

把 MdEditor 当前输入的值暴露给父组件,便于父组件去使用,同时也是提高组件的通用性,所以定义了属性和属性类型,把 value 和 onChange 事件交给父组件去管理。

src/components/MdEditor/index.css

css 复制代码
.md-editor {
    .bytemd-toolbar-icon.bytemd-tippy.bytemd-tippy-right:last-child {
        display: none;
    }
}

隐藏编辑器中不需要的操作图标(像 GitHub 图标)

编辑好文本,自然有浏览文本的地方,所以浏览器:

src/components/MdViewer/index.tsx

tsx 复制代码
import { Viewer } from "@bytemd/react";
import gfm from "@bytemd/plugin-gfm";
import highlight from "@bytemd/plugin-highlight";
import 'github-markdown-css/github-markdown-light.css';
import "bytemd/dist/index.css";
import "highlight.js/styles/vs.css";
import "./index.css";

interface Props {
    value?: string;
}

const plugins = [gfm(), highlight()];

/**
 * Markdown 浏览器
 * @param props
 * @constructor
 */
const MdViewer = (props: Props) => {
    const { value = "" } = props;

    return (
        <div className="md-viewer">
            <Viewer value={value} plugins={plugins} />
        </div>
    );
};

export default MdViewer;

src/components/MdViewer/index.css

css 复制代码
.md-viewer {
    .bytemd-toolbar-icon.bytemd-tippy.bytemd-tippy-right:last-child {
        display: none;
    }
}

可以在任意客户端渲染页面(或组件)引入组件进行测试,这是因为该组件用到了 useRef 之类的仅客户端才支持的函数。

tsx 复制代码
const [text, setText] = useState<string>('');

<MdEditor value={text} onChange={setText} />
<MdViewer value={text} />

md-editor-v3

文本编辑器/md-editor-v3 (gitee.com)

这个是之前写 Vue3 用过的一个编辑器,也很不错,用法简单,同样支持 Vue、React 等。

安装

复制代码
yarn add md-editor-v3

更多使用及贡献方式参考:md-editor-extension

编辑器模式

vue 复制代码
<template>
  <MdEditor v-model="text" />
</template>

<script setup>
import { ref } from 'vue';
import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

const text = ref('# Hello Editor');
</script>

仅预览模式

vue 复制代码
<template>
  <MdPreview :editorId="id" :modelValue="text" />
  <MdCatalog :editorId="id" :scrollElement="scrollElement" />
</template>

<script setup>
import { ref } from 'vue';
import { MdPreview, MdCatalog } from 'md-editor-v3';
import 'md-editor-v3/lib/preview.css';

const id = 'preview-only';
const text = ref('# Hello Editor');
const scrollElement = document.documentElement;
</script>
相关推荐
Larcher10 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐22 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭35 分钟前
如何理解HTML语义化
前端·html
sonrisa_1 小时前
下载CUDA Toolkit和VS后,配置vscode
ide·vscode·编辑器
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花1 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端