md-eidtor-v3地址

md-editor-v3 的 github地址 及使用文档
md-editor-v3 预览效果地址

其它markdown编辑器

mavon-editor文本编辑器上传图片用法
Vue富文本编辑器-mavon-editor文本编辑器
v-md-editor使用 & 生成el-tree文章目录滚动跟随高亮

🎄 md-editor-v3

English | 中文

vue3 环境的 Markdown 编辑器,使用 jsxtypescript 语法开发,支持在 tsx 项目使用。

⭐️ 功能一览

  • 快捷插入内容工具栏、编辑器浏览器全屏、页面内全屏等;
  • 内置的白色主题和暗黑主题,支持绑定切换;
  • 支持快捷键插入内容; 支持使用 prettier 格式化内容(使用 CDN 方式引入,只支持格式化 md 内容,可在代码内设置关闭);
  • 多语言,支持自行扩展语言;
  • 粘贴上传图片,图片裁剪上传;
  • 仅预览模式(不显示编辑器,只显示 md 预览内容,无额外监听);
  • 预览主题,内置defalutvuepressgithubcyanosismk-cutesmart-blue 6 种预览主题(不完全相同),支持自定义主题(参考文档 demo 页示例);
  • mermaid绘图(>=1.8.0),katex数学公式(>=1.9.0);
  • 自定义工具栏顺序或显示,自定义扩展工具栏(支持点击类型、下拉菜单类型及弹窗类型)等。
  • 按需引用(>=4.0.0)。

📦 安装

yarn add md-editor-v3

使用语言、预览主题扩展库:

yarn add @vavt/md-editor-extension

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

💡 用法

✍🏻 编辑器模式

<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>

v4.0.0开始,内部组件支持按需引用。

如果页面存在多个编辑器,请给组件设置不相同的editorId

📖 仅预览模式

<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>

🗺 预览图

| 默认模式 | 暗黑模式 | 仅预览 |
| --- | --- | --- |
| [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqbbuwp9-1685158108017)(https://imzbf.github.io/md-editor-v3/imgs/preview-light.png)] | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C7viERoK-1685158108017)(https://imzbf.github.io/md-editor-v3/imgs/preview-dark.png)] | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j8yYa47E-1685158108022)(https://imzbf.github.io/md-editor-v3/imgs/preview-previewOnly.png)] |

简单的标记和表情扩展预览

在这里插入图片描述

🎁 Apis

🔖 MdPreivew Props

名称类型默认值说明
modelValuestring‘’md 编辑内容,vue 模板支持双向绑定(v-model=“value”)
themelight | dark‘light’主题切换
classstring‘’编辑器类名
languagestring‘zh-CN’内置中英文(‘zh-CN’,‘en-US’),可自行扩展其他语言,同时可覆盖内置的中英文
editorIdstring‘md-editor-v3’编辑器唯一标识,非必须项,当相同页面存在两个编辑器时,请务必区别该属性
showCodeRowNumberbooleanfalse代码块是否显示行号
previewTheme'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'‘default’预览内容主题,自定义主题规则见下方
stylestring | CSSProperties{}编辑器内联样式
noMermaidbooleanfalse如果你不希望使用图表展示内容,可以设置关闭
noKatexbooleanfalse不使用 katex 展示数学公式
codeTheme'atom' | 'a11y' | 'github' | 'gradient' | 'kimbie' | 'paraiso' | 'qtcreator' | 'stackoverflow'‘atom’代码块 highlight 样式名称,扩展更多见下方
mdHeadingId(text: string, level: number, index: number) => string(text) => text标题ID计算方式
sanitize(html: string) => string(html) => html在每次生成 html 后,通过该方法移除危险内容,比如 xss 相关。
noIconfontbooleanfalse不插入 iconfont 链接,你可以下载到本地自行引入
formatCopiedText(text: string) => string(text: string) => text格式化复制代码
codeStyleReversebooleantrue代码块为暗色背景的预览主题,将代码风格设置为暗色风格
codeStyleReverseListArray<string>[‘default’, ‘mk-cute’]代码块为暗色背景的预览主题
noHighlightbooleanfalse永远不高亮代码

🔩 MdEditor Props

除去和MdPreivew相同的以外:

名称类型默认值说明
pageFullscreenbooleanfalse页面内全屏
previewbooleantrue是否预览
htmlPreviewbooleanfalse是否 html 预览(如果是 true,preview 需要设置为 false)
toolbarsArray<ToolbarNames | number>[toolbars]选择性展示工具栏,可选内容见下方toolbars
toolbarsExcludeArray<ToolbarNames | number>[]选择性不展示工具栏,内容同toolbars
noPrettierbooleanfalse是否启用 prettier 优化 md 内容
tabWidthnumber2编辑器 TAB 键位等于空格数
tableShape[number, number][6, 4]标题栏添加表格时,预设待选表格大小,第一个代表最大列数,第二个代表最大行数。
placeholderstring‘’
footersArray<'markdownTotal' | '=' | 'scrollSwitch' | number>[‘markdownTotal’, ‘=’, ‘scrollSwitch’]页脚显示内容,=左右分割,设置为[]不显示页脚
scrollAutobooleantrue默认左右滚动状态
noUploadImgbooleanfalse不展示上传图片选项
autoFocusbooleanfalse文本区域自动获得焦点
disabledbooleanfalse禁用文本区域
readOnlybooleanfalse文本区域为只读
maxLengthnumber文本区域允许的最大字符数
autoDetectCodebooleanfalse是否启用自动识别粘贴代码类别,目前仅支持从vscode复制的内容

如果你重新定义了标题,请务必通过mdHeadingId告诉编辑器你生成标题 ID 的算法。以便生成的内部目录能够正确导航。

『toolbars』
[
  'bold',
  'underline',
  'italic',
  '-',
  'strikeThrough',
  'title',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  'task', // ^2.4.0
  '-',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  'mermaid',
  'katex',
  '-',
  'revoke',
  'next',
  'save',
  '=',
  'pageFullscreen',
  'fullscreen',
  'preview',
  'htmlPreview',
  'catalog',
  'github'
];

你可以随意排序工具栏,通过'-'分割两个工具,通过'='实现左右放置!

你可以自定义工具栏,将defToolbars中自定义工具项的下标穿插在toolbars实现展示(这并不规范),更多请参考文档

『StaticTextDefaultValue』

自定义语言,需要替换的下面的全部内容(某些字段若不主动提供,会造成页面不美观):

export interface ToolbarTips {
  bold?: string;
  underline?: string;
  italic?: string;
  strikeThrough?: string;
  title?: string;
  sub?: string;
  sup?: string;
  quote?: string;
  unorderedList?: string;
  orderedList?: string;
  task?: string; // ^2.4.0
  codeRow?: string;
  code?: string;
  link?: string;
  image?: string;
  table?: string;
  mermaid?: string;
  katex?: string;
  revoke?: string;
  next?: string;
  save?: string;
  prettier?: string;
  pageFullscreen?: string;
  fullscreen?: string;
  catalog?: string;
  preview?: string;
  htmlPreview?: string;
  github?: string;
  '-'?: string;
  '='?: string;
}

export interface StaticTextDefaultValue {
  // 工具栏hover提示
  toolbarTips?: ToolbarTips;
  // 标题下拉框内容
  titleItem?: {
    h1?: string;
    h2?: string;
    h3?: string;
    h4?: string;
    h5?: string;
    h6?: string;
  };
  imgTitleItem?: {
    link: string;
    upload: string;
    clip2upload: string;
  };
  // 添加链接或图片时弹窗提示
  linkModalTips?: {
    linkTitle?: string;
    imageTitle?: string;
    descLabel?: string;
    descLabelPlaceHolder?: string;
    urlLabel?: string;
    urlLabelPlaceHolder?: string;
    buttonOK?: string;
  };
  // 裁剪图片弹窗提示,v1.2.0
  clipModalTips?: {
    title?: string;
    buttonUpload?: string;
  };
  // 预览代码中复制代码提示
  copyCode?: {
    text?: string;
    successTips?: string;
    failTips?: string;
  };
  mermaid?: {
    // 流程图
    flow?: string;
    // 时序图
    sequence?: string;
    // 甘特图
    gantt?: string;
    // 类图
    class?: string;
    // 状态图
    state?: string;
    // 饼图
    pie?: string;
    // 关系图
    relationship?: string;
    // 旅程图
    journey?: string;
  };
  katex?: {
    // 行内公式
    inline: string;
    // 块级公式
    block: string;
  };
  footer?: {
    markdownTotal: string;
    scrollAuto: string;
  };
}

🧵 MdPreview 绑定事件

名称入参说明
onHtmlChangedhtml: stringhtml 变化回调事件,用于获取预览 html 代码
onGetCataloglist: Array<HeadList>获取markdown目录

🪢 MdEditor 绑定事件

除去和MdPreivew相同的以外:

名称入参说明
onChangevalue: string内容变化事件(当前与textareoninput事件绑定,每输入一个单字即会触发)
onSavevalue: string, html: Promise<string>保存事件,快捷键与保存按钮均会触发
onUploadImgfiles: Array<File>, callback: (urls: Array<string>) => void上传图片事件,弹窗会等待上传结果,务必将上传后的 urls 作为 callback 入参回传
onErrorerr: { name: string; message: string }运行错误反馈事件,目前包括Cropperfullscreenprettier实例未加载完成操作错误
onBlurevent: FocusEvent输入框失去焦点时触发事件
onFocusevent: FocusEvent输入框获得焦点时触发事件

🎍 插槽

名称类型默认值说明
defToolbarsArray<DropdownToolbar | NormalToolbar | ModalToolbar>null使用内置的组件自定义扩展工具栏
defFootersArray<string | VNode | JSX.Element>null自定义扩展页脚

使用内置的 3 个组件(说明见下方),自定义工具栏,简单示例:

<template>
  <MdEditor>
    <template #defToolbars>
      <NormalToolbar title="mark" @onClick="handler">
        <template #trigger>
          <svg class="md-editor-icon" aria-hidden="true">
            <use xlink:href="#md-editor-icon-mark"></use>
          </svg>
        </template>
      </NormalToolbar>
    </template>
  </MdEditor>
</template>

<script setup lang="ts">
import { MdEditor, NormalToolbar } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

const handler = () => {
  console.log('NormalToolbar clicked!');
};
</script>

🤱🏼 实例暴露

编辑器暴露了若干方法在组件实例上,用来快捷监听编辑器内部状态或对调整内部状态。

<template>
  <MdEditor ref="editorRef" />
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { MdEditor } from 'md-editor-v3';
import type { ExposeParam } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

const editorRef = ref<ExposeParam>();

onMounted(() => {
  editorRef.value?.on('catalog', console.log);
});
</script>

触发方法不设置入参切换为相反状态

👂🏼 on

监听编辑器内部状态,包括:屏幕全屏、浏览器全屏、预览文本、预览 html、目录等。

  • pageFullscreen

    editorRef.value?.on('pageFullscreen', (status) => console.log(status));
    
  • fullscreen

    editorRef.value?.on('fullscreen', (status) => console.log(status));
    
  • preview

    editorRef.value?.on('preview', (status) => console.log(status));
    
  • htmlPreview

    editorRef.value?.on('htmlPreview', (status) => console.log(status));
    
  • catalog

    editorRef.value?.on('catalog', (status) => console.log(status));
    

💻 togglePageFullscreen

切换页面内全屏。

editorRef.value?.togglePageFullscreen(true);

🖥 toggleFullscreen

切换屏幕全屏。

editorRef.value?.toggleFullscreen(true);

📖 togglePreview

切换是否显示预览。

editorRef.value?.togglePreview(true);

📼 toggleHtmlPreview

切换是否显示 html 预览。

editorRef.value?.toggleHtmlPreview(true);

🧬 toggleCatalog

切换是否显示目录。

editorRef.value?.toggleCatalog(true);

💾 triggerSave

触发保存。

editorRef.value?.triggerSave();

💉 insert

手动向文本框插入内容。

/**
 * @params selectedText 选中的内容
 */
editorRef.value?.insert((selectedText) => {
  /**
   * @return targetValue    待插入内容
   * @return select         插入后是否自动选中内容
   * @return deviationStart 插入后选中内容鼠标开始位置
   * @return deviationEnd   插入后选中内容鼠标结束位置
   */
  return {
    targetValue: `${selectedText}`,
    select: true,
    deviationStart: 0,
    deviationEnd: 0
  };
});

示例参考文档源码中的扩展组件

🎯 focus

手动聚焦输入框。

editorRef.value?.focus();

💴 编辑器配置

使用config(option: ConfigOption)方法,可以对构建实例进行定制。

  • codeMirrorExtensions: 根据主题和内部默认的 codeMirror 扩展自定义新的扩展。

    使用示例:编辑器默认不显示输入框的行号,需要手动添加扩展

    import { config } from 'md-editor-v3';
    import { lineNumbers } from '@codemirror/view';
    
    config({
      codeMirrorExtensions(_theme, extensions) {
        return [...extensions, lineNumbers()];
      }
    });
    
  • markdownItConfig: 自定义 markdown-it 核心库扩展、属性等。

    使用示例:配置使用markdown-it-anchor并在标题右侧显示一个超链接符号

    import { config } from 'md-editor-v3';
    import ancher from 'markdown-it-anchor';
    
    config({
      markdownItConfig(mdit) {
        mdit.use(ancher, {
          permalink: true
        });
      }
    });
    
  • editorConfig: 编辑器常规配置,语言、mermaid默认模板和渲染延迟:

    import { config } from 'md-editor-v3';
    
    config({
      editorConfig: {
        // 语言
        languageUserDefined: { lang: StaticTextDefaultValue },
        // mermaid模板
        mermaidTemplate: {
          flow: `flow tempalte`,
          ...more
        },
        // 输入渲染延迟,默认500ms。当仅预览模式时,未设置此项默认0ms
        renderDelay: 500
      }
    });
    
  • editorExtensions: 类型如下,用于配置编辑器内部的扩展

    import { config } from 'md-editor-v3';
    
    config({
      editorExtensions: { iconfont: 'https://xxx.cc' }
    });
    
    『EditorExtensions』
    export interface EditorExtensions {
      highlight?: {
        instance?: any;
        js?: string;
        css?: {
          [key: string]: {
            light: string;
            dark: string;
          };
        };
      };
      prettier?: {
        standaloneJs?: string;
        parserMarkdownJs?: string;
      };
      cropper?: {
        instance?: any;
        js?: string;
        css?: string;
      };
      iconfont?: string;
      screenfull?: {
        instance?: any;
        js?: string;
      };
      mermaid?: {
        instance?: any;
        js?: string;
      };
      katex?: {
        instance?: any;
        js?: string;
        css?: string;
      };
    }
    

🪡 快捷键

主要以CTRL搭配对应功能英文单词首字母,冲突项添加SHIFT,再冲突替换为ALT

请注意,快捷键仅在输入框获取到焦点时可用!

键位功能说明
TAB空格通过tabWidth属性预设 TAB 键位新增空格长度,默认 2,支持多行
SHIFT + TAB取消空格同上,一次取消两个空格,支持多行
CTRL + C复制选中时复制选中内容,未选中时复制当前行内容
CTRL + X剪切选中时剪切选中内容,未选中时剪切当前行
CTRL + D删除选中时删除选中内容,未选中时删除当前行
CTRL + S保存触发编辑器的onSave回调
CTRL + B加粗**加粗**
CTRL + U下划线<u>下划线</u>
CTRL + I斜体*斜体*
CTRL + 1-61-6 级标题# 标题
CTRL + ↑上角标<sup>上角标</sup>
CTRL + ↓下角标<sub>下角标</sub>
CTRL + O有序列表1. 有序列表
CTRL + L链接[链接](https://github.com/imzbf/md-editor-v3)
CTRL + Z撤回触发编辑器内内容撤回,与系统无关
CTRL + SHIFT + S删除线~删除线~
CTRL + SHIFT + U无序列表- 无序列表
CTRL + SHIFT + C块级代码多行代码块
CTRL + SHIFT + I图片链接![图片](https://imzbf.github.io/md-editor-v3/imgs/preview-light.png)
CTRL + SHIFT + Z前进一步触发编辑器内内容前进,与系统无关
CTRL + SHIFT + F美化内容
CTRL + ALT + C行内代码行内代码块
CTRL + SHIFT + ALT + T表格|表格|

🪤 内部组件

按需引入内部扩展组件:

<script lang="ts" setup>
import { NormalToolbar } from 'md-editor-v3';
</script>

使用参考:文档页面

🐣 普通扩展工具栏

NormalToolbar

  • props

    • title: string,非必须,作为工具栏上的 hover 提示。
  • events

    • onClick: (e: MouseEvent) => void,必须,点击事件。
  • slots

    • trigger: string | JSX.Element,必须,通常是个图标,用来展示在工具栏上。

🐼 下拉扩展工具栏

DropdownToolbar

  • props

    • title: string,非必须,作为工具栏上的 hover 提示。
    • visible: boolean,必须,下拉状态。
  • events

    • onChange: (visible: boolean) => void,必须,状态变化事件。
  • slots

    • trigger: string | JSX.Element,必须,通常是个图标,用来展示在工具栏上。
    • overlay: string | JSX.Element,必须,下拉框中的内容。

🦉 弹窗扩展工具栏

ModalToolbar

  • props

    • title: string,非必须,作为工具栏上的 hover 提示。
    • modalTitle: string,非必须,弹窗的标题。
    • visible: boolean,必须,弹窗显示状态。
    • width: string,非必须,弹窗宽度,默认auto
    • height: string,同width
    • showAdjust: boolean,非必须,是否显示弹窗全屏按钮。
    • isFullscreen: boolean,显示全屏按钮时必须,弹窗全屏状态。
  • events

    • onClick: () => void,必须,工具栏点击事件。
    • onClose: () => void,必须,弹窗点击关闭事件。
    • onAdjust: (val: boolean) => void,弹窗全屏按钮点击事件。
  • slots

    • trigger: string | JSX.Element,必须,通常是个图标,用来展示在工具栏上。
    • overlay: string | JSX.Element,必须,下拉框中的内容。

🐻 目录导航

MdCatalog

  • props

    • editorId: string,必须,对应编辑器的editorId,在内部注册目录变化监听事件。
    • class: string,非必须,目录组件最外层类名。
    • mdHeadingId: MdHeadingId,非必须,特殊化编辑器标题的算法,与编辑器相同。
    • scrollElement: string | HTMLElement,非必须,为字符时应是一个元素选择器。仅预览模式中,整页滚动时,设置为document.documentElement
    • theme: 'light' | 'dark',非必须,当需要切换主题时提供,同编辑器的theme
    • offsetTop: number,非必须,标题距离顶部该像素时高亮当前目录项,默认 20 像素。
    • scrollElementOffsetTop: number,非必须,滚动区域的固定顶部高度,默认 0。
  • events

    • onClick: (e: MouseEvent, t: TocItem) => void,非必须,导航点击事件。

🗂 部分示例

🎸 Jsx 模板

import { defineComponent, reactive } from 'vue';
import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

export default defineComponent({
  setup() {
    const md = reactive({
      text: '# Hello Editor'
    });
    return () => (
      <MdEditor modelValue={md.text} onChange={(value) => (md.text = value)} />
    );
  }
});

🥹 上传图片

默认可以选择多张图片,支持粘贴板上传图片。

注意:粘贴板上传时,如果是网页上的 gif 图,无法正确上传为 gif 格式!

<template>
  <MdEditor v-model="text" @onUploadImg="onUploadImg" />
</template>

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

const text = ref('# Hello Editor');

const onUploadImg = async (files, callback) => {
  const res = await Promise.all(
    files.map((file) => {
      return new Promise((rev, rej) => {
        const form = new FormData();
        form.append('file', file);

        axios
          .post('/api/img/upload', form, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          })
          .then((res) => rev(res))
          .catch((error) => rej(error));
      });
    })
  );

  callback(res.map((item) => item.data.url));
};
</script>

🧙‍♂️ 调整编辑器样式

2.x 使用 css 变量定义了大部分内容:

.css-vars(@isDark) {
  --md-color: if(@isDark, #999, #222);
  --md-hover-color: if(@isDark, #bbb, #000);
  --md-bk-color: if(@isDark, #000, #fff);
  --md-bk-color-outstand: if(@isDark, #111, #f6f6f6);
  --md-bk-hover-color: if(@isDark, #1b1a1a, #f5f7fa);
  --md-border-color: if(@isDark, #2d2d2d, #e6e6e6);
  --md-border-hover-color: if(@isDark, #636262, #b9b9b9);
  --md-border-active-color: if(@isDark, #777, #999);
  --md-modal-mask: #00000073;
  --md-scrollbar-bg-color: if(@isDark, #0f0f0f, #e2e2e2);
  --md-scrollbar-thumb-color: if(@isDark, #2d2d2d, #0000004d);
  --md-scrollbar-thumb-hover-color: if(@isDark, #3a3a3a, #00000059);
  --md-scrollbar-thumb-active-color: if(@isDark, #3a3a3a, #00000061);
}

.md-editor {
  .css-vars(false);
}

.md-editor-dark {
  .css-vars(true);
}

只需要调整对应的 css 变量,比如调整暗夜模式下的背景:

.md-editor-dark {
  --md-bk-color: #333 !important;
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐