好用的 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>
相关推荐
忆琳7 分钟前
Vue3 全局自动大写转换:一个配置,全站生效
javascript·element
喵个咪10 分钟前
Headless 架构优势:内容与展示解耦,一套 API 打通全端生态
前端·后端·cms
小江的记录本14 分钟前
【JEECG Boot】 JEECG Boot——数据字典管理 系统性知识体系全解析
java·前端·spring boot·后端·spring·spring cloud·mybatis
喵个咪17 分钟前
传统 CMS 太笨重?试试 Headless 架构的 GoWind,轻量又强大
前端·后端·cms
chenjingming66618 分钟前
jmeter导入浏览器上按F12抓的数据包
前端·chrome·jmeter
张元清18 分钟前
不用 Server Components 也能做 React 流式 SSR —— 实战指南
前端·javascript·面试
前端技术21 分钟前
ArkTS第三章:声明式UI开发实战
java·前端·人工智能·python·华为·鸿蒙
码小瑞25 分钟前
画布文字在不同缩放屏幕上的归一化
前端
神の愛25 分钟前
java日志功能
java·开发语言·前端