Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/imzbf/md-editor-rt

Markdown editor for react, developed in jsx and typescript, dark theme、beautify content by prettier、render articles directly、paste or clip the picture and upload it...
https://github.com/imzbf/md-editor-rt

editor markdown markdown-editor react ssr theme

Last synced: 14 days ago
JSON representation

Markdown editor for react, developed in jsx and typescript, dark theme、beautify content by prettier、render articles directly、paste or clip the picture and upload it...

Awesome Lists containing this project

README

        

# 🎄 md-editor-rt

![](https://img.shields.io/github/package-json/v/imzbf/md-editor-rt) ![](https://img.shields.io/npm/dm/md-editor-rt) ![](https://img.shields.io/github/license/imzbf/md-editor-rt) ![](https://img.shields.io/badge/ssr-%3E1.0.0-brightgreen) ![](https://img.shields.io/badge/webcomponent-%3E4.19.0-brightgreen)

[English](https://github.com/imzbf/md-editor-rt) \| 中文

react 版本的 Markdown 编辑器,[md-editor-v3](https://imzbf.github.io/md-editor-v3)同系列项目。

- 文档与在线预览:[传送门](https://imzbf.github.io/md-editor-rt)

- 在线尝试示例:[传送门](https://codesandbox.io/s/elated-khorana-65jmr)

## ⭐️ 功能一览

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

## 📦 安装

```shell
yarn add md-editor-rt
```

使用已存在的语言、主题扩展,例如:日语

```shell
yarn add @vavt/cm-extension
```

使用更多的扩展工具栏组件,例如:导出内容为 PDF

```shell
yarn add @vavt/rt-extension
```

更多使用及贡献方式参考:[md-editor-extension](https://github.com/imzbf/md-editor-extension)

## 💡 用法

当使用服务端渲染时,请务必设置`editorId`为固定值。

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

### ✍🏻 编辑器模式

```jsx
import React, { useState } from 'react';
import { MdEditor } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

export default () => {
const [text, setText] = useState('# Hello Editor');
return ;
};
```

### 📖 仅预览模式

```jsx
import React, { useState } from 'react';
import { MdEditor, MdCatalog } from 'md-editor-rt';
import 'md-editor-rt/lib/preview.css';

const scrollElement = document.documentElement;

export default () => {
const [text] = useState('# Hello Editor');
const [id] = useState('preview-only');

return (
<>


>
);
};
```

当使用服务端渲染时,`scrollElement`应该是字符类型,例:`body`、`#id`、`.class`。

## 🗺 预览图

| 默认模式 | 暗黑模式 | 仅预览 |
| --- | --- | --- |
| ![默认模式](https://imzbf.github.io/md-editor-rt/imgs/preview-light.png) | ![暗黑模式](https://imzbf.github.io/md-editor-rt/imgs/preview-dark.png) | ![](https://imzbf.github.io/md-editor-rt/imgs/preview-previewOnly.png) |

输入提示和自定义简单的标记、表情扩展预览

![](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)

## 🎁 Apis

### 🔖 MdPreivew Props

| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| modelValue | `string` | '' | md 编辑内容 |
| theme | `light \| dark` | 'light' | 主题切换 |
| className | `string` | '' | 编辑器类名 |
| style | `CSSProperties` | {} | 编辑器内联样式 |
| language | `string` | 'zh-CN' | 内置中英文('zh-CN','en-US'),可自行扩展其他语言,同时可覆盖内置的中英文 |
| editorId | `string` | 'md-editor-rt\_[\d]' | 编辑器唯一标识,默认数字累加,当使用服务端渲染时,请务必设置该属性为固定值 |
| showCodeRowNumber | `boolean` | true | 代码块是否显示行号 |
| previewTheme | `'default' \| 'github' \| 'vuepress' \| 'mk-cute' \| 'smart-blue' \| 'cyanosis'` | 'default' | 预览内容主题,自定义主题规则见下方 |
| noMermaid | `boolean` | false | 如果你不希望使用图表展示内容,可以设置关闭 |
| noKatex | `boolean` | false | 不使用 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内容 |
| noIconfont | `boolean` | false | 不插入 iconfont 链接,你可以在[这里](https://imzbf.github.io/md-editor-rt/zh-CN/docs#%F0%9F%A4%9E%F0%9F%8F%BC%20noIconfont)获取最新链接 |
| formatCopiedText | `(text: string) => string` | (text: string) => text | 格式化复制代码 |
| codeStyleReverse | `boolean` | true | 代码块为暗色背景的预览主题,将代码风格设置为暗色风格 |
| codeStyleReverseList | `Array` | ['default', 'mk-cute'] | 代码块为暗色背景的预览主题 |
| noHighlight | `boolean` | false | 是否不高亮代码 |
| noImgZoomIn | `boolean` | false | 是否关闭编辑器默认的放大功能 |
| customIcon | `CustomIcon` | {} | 自定义的图标 |
| sanitizeMermaid | `(h: string) => Promise` | (h: string) => Promise.resolve(h) | 转换生成的 mermaid 代码 |
| codeFoldable | `boolean` | true | 是否开启折叠代码功能 |
| autoFoldThreshold | `number` | 30 | 触发自动折叠代码的行数阈值 |

### 🔩 MdEditor Props

除去和`MdPreivew`相同的以外:

| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| pageFullscreen | `boolean` | false | 页面内全屏 |
| preview | `boolean` | true | 是否预览 |
| htmlPreview | `boolean` | false | 是否 html 预览 |
| toolbars | `Array` | [toolbars] | 选择性展示工具栏,可选内容见下方`toolbars` |
| toolbarsExclude | `Array` | [] | 选择性不展示工具栏,内容同`toolbars` |
| noPrettier | `boolean` | false | 是否启用 prettier 优化 md 内容 |
| tabWidth | `number` | 2 | 编辑器 TAB 键位等于空格数 |
| tableShape | `[number, number] \| [number, number, number, number]` | [6, 4] | 标题栏添加表格时,预设待选表格大小,[列数,行数,扩展最大列数,扩展最大行数] |
| placeholder | `string` | '' | |
| defToolbars | `Array` | [] | 使用内置的组件自定义扩展工具栏 |
| footers | `Array<'markdownTotal' \| '=' \| 'scrollSwitch' \| number>` | ['markdownTotal', '=', 'scrollSwitch'] | 页脚显示内容,`=`左右分割,设置为`[]`不显示页脚 |
| scrollAuto | `boolean` | true | 默认左右滚动状态 |
| defFooters | `Array` | [] | 自定义扩展页脚 |
| noUploadImg | `boolean` | false | 不展示上传图片选项 |
| autoFocus | `boolean` | false | 文本区域自动获得焦点 |
| disabled | `boolean` | false | 禁用文本区域 |
| readOnly | `boolean` | false | 文本区域为只读 |
| maxLength | `number` | | 文本区域允许的最大字符数 |
| autoDetectCode | `boolean` | false | 是否启用自动识别粘贴代码类别,目前仅支持从`vscode`复制的内容 |
| completions | `Array` | [] | `@codemirror/autocomplete`匹配关键词的方法列表 |
| showToolbarName | `boolean` | false | 是否在工具栏下面显示对应的文字名称 |
| inputBoxWitdh | `string` | '50%' | 输入框默认的宽度 |
| transformImgUrl | `(imgUrl: string) => string \| Promise` | t => t | 转换图片链接 |

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

『toolbars』

```js
[
'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',
'previewOnly',
'htmlPreview',
'catalog',
'github'
];
```

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

『StaticTextDefaultValue』

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

```typescript
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;
previewOnly?: string;
htmlPreview?: string;
github?: string;
'-'?: string;
'='?: string;
}

export interface StaticTextDefaultValue {
// 工具栏hover title提示
toolbarTips?: ToolbarTips;
// 标题下拉框内容
titleItem?: {
h1?: string;
h2?: string;
h3?: string;
h4?: string;
h5?: string;
h6?: string;
};
// v1.6.0
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;
};
// 预览代码中复制代码提示,v1.1.4
copyCode?: {
text?: string;
successTips?: string;
failTips?: string;
};
// v1.8.0
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 绑定事件

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| onChange | `value: string` | 内容变化事件(当前与`textare`的`oninput`事件绑定,每输入一个单字即会触发) |
| onHtmlChanged | `html: string` | html 变化回调事件,用于获取预览 html 代码 |
| onGetCatalog | `list: Array` | 动态获取`markdown`目录 |

### 🪢 MdEditor 绑定事件

除去和`MdPreivew`相同的以外:

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| onSave | `value: string, html: Promise` | 保存事件,快捷键与保存按钮均会触发 |
| onUploadImg | `files: Array, callback: (urls: string[] \| { url: string; alt: string; title: string }[]) => void` | 上传图片事件,弹窗会等待上传结果,务必将上传后的 urls 作为 callback 入参回传 |
| onError | `err: { name: 'Cropper' \| 'fullscreen' \| 'prettier' \| 'overlength'; message: string }` | 运行错误反馈事件,目前包括`Cropper`、`fullscreen`、`prettier`实例未加载完成操作错误,以及输入内容超出限制长度错误 |
| onBlur | `event: FocusEvent` | 输入框失去焦点时触发事件 |
| onFocus | `event: FocusEvent` | 输入框获得焦点时触发事件 |
| onInput | `event: Event` | 输入框键入内容事件 |
| onDrop | `event: DragEvent` | 拖放所选内容触发事件 |
| onInputBoxWitdhChange | `(width: string) => void` | 调整输入框宽度事件 |

## 🤱🏼 实例暴露

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

```jsx
import React, { useState, useEffect, useRef } from 'react';
import { MdEditor, ExposeParam } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

export default () => {
const [text, setText] = useState('#Hello Editor');

const editorRef = useRef();

useEffect(() => {
editorRef.current?.on('catalog', console.log);
}, []);

return ;
};
```

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

### 👂🏼 on

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

```ts
type Keys =
| 'pageFullscreen'
| 'fullscreen'
| 'preview'
| 'previewOnly'
| 'htmlPreview'
| 'catalog';
```

```js
editorRef.current?.on('pageFullscreen', (status) => console.log(status));
```

### 💻 togglePageFullscreen

切换页面内全屏。

```js
editorRef.current?.togglePageFullscreen(true);
```

### 🖥 toggleFullscreen

切换屏幕全屏。

```js
editorRef.current?.toggleFullscreen(true);
```

### 📖 togglePreview

切换是否显示预览。

```js
editorRef.current?.togglePreview(true);
```

### 📖 togglePreviewOnly

切换仅预览状态。

```js
editorRef.current?.togglePreviewOnly(true);
```

### 📼 toggleHtmlPreview

切换是否显示 html 预览。

```js
editorRef.current?.toggleHtmlPreview(true);
```

### 🧬 toggleCatalog

切换是否显示目录。

```js
editorRef.current?.toggleCatalog(true);
```

### 💾 triggerSave

触发保存操作。

### 💉 insert

手动向文本框插入内容。

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

示例参考文档源码中的[扩展组件](https://github.com/imzbf/md-editor-rt/blob/dev-docs/src/components/MarkExtension/index.tsx)

### 🎯 focus

手动聚焦输入框。

```ts
import type { FocusOption } from 'md-editor-rt';

const option: FocusOption | undefined = 'start';

// 聚焦时光标的位置,不提供默认上次失焦时的位置
editorRef.current?.focus(option);
```

### ✒️ rerender

手动重新渲染内容。

### 🔍 getSelectedText

获取当前选中的文字。

### 🗑 resetHistory

清除当前的历史记录。

### 🎛 domEventHandlers

支持监听全部的dom事件。

```js
editorRef.current?.domEventHandlers({
compositionstart: () => {
console.log('compositionstart');
}
});
```

### 🎛 execCommand

通过触发器向编辑器插入内容。

```js
editorRef.current?.execCommand('bold');
```

### 🔖 getEditorView

获取 codemirror 实例。

## 💴 编辑器配置

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

> [!WARNING]
>
> 我们建议你在项目入口配置,例如 vite 创建的项目中的 main.js。不要在组件中去调用 `config` !

### codeMirrorExtensions

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

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

```js
import { config } from 'md-editor-rt';
import { lineNumbers } from '@codemirror/view';

config({
codeMirrorExtensions(_theme, extensions) {
return [...extensions, lineNumbers()];
}
});
```

### markdownItConfig

自定义 markdown-it 核心库扩展、属性等。

```ts
type MarkdownItConfig = (
md: markdownit,
options: {
editorId: string;
}
) => void;
```

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

```js
import { config } from 'md-editor-rt';
import ancher from 'markdown-it-anchor';

config({
markdownItConfig(mdit) {
mdit.use(ancher, {
permalink: true
});
}
});
```

### markdownItPlugins

挑选、新增 markdown-it 核心库已预设的扩展。

```ts
type MarkdownItPlugins = (
plugins: Array,
options: {
editorId: string;
}
) => Array;
```

使用示例:修改图片的类名

```js
import { config } from 'md-editor-rt';

config({
markdownItPlugins(plugins) {
return plugins.map((p) => {
if (p.type === 'image') {
return {
...p,
options: {
...p.options,
classes: 'my-class'
}
};
}

return p;
});
}
});
```

### editorConfig

编辑器常规配置,语言、`mermaid`默认模板和渲染延迟:

```js
import { config } from 'md-editor-rt';

config({
editorConfig: {
// 语言
languageUserDefined: { lang: StaticTextDefaultValue },
// mermaid模板
mermaidTemplate: {
flow: `flow tempalte`,
...more
},
// 输入渲染延迟,默认500ms。当仅预览模式时,未设置此项默认0ms
renderDelay: 500,
// 内部弹窗的zIndex
zIndex: 2000
}
});
```

### editorExtensions

类型如下,用于配置编辑器内部的扩展

```js
import { config } from 'md-editor-rt';

config({
editorExtensions: { iconfont: 'https://xxx.cc' }
});
```

『EditorExtensions』

```typescript
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;
};
}
```

### editorExtensionsAttrs

同步添加CDN链接标签的上属性,类型与`editorExtensions`一直,值类型是`HTMLElementTagNameMap`

内部提供所有链接的`integrity`值,使用方式如下:

```js
import { config, editorExtensionsAttrs } from 'md-editor-rt';

config({
editorExtensionsAttrs
});
```

不要尝试在editorExtensionsAttrs定义script的src\onload\id,link的rel\href\id它们会被默认值覆盖

### 🫨 iconfontType

固定使用那种方式展示图标,可以切换展示的方式

- `svg`: symbol 方式
- `class`: font-class 方式

如果通过属性`customIcon`自定义了图标,会优先使用自定义的。

### 🎨 mermaidConfig

mermaid 配置项,[配置详情](https://mermaid.js.org/config/schema-docs/config.html)

```js
import { config } from 'md-editor-rt';

config({
mermaidConfig(base: any) {
return {
...base,
logLevel: 'error'
};
}
});
```

### 🔧 katexConfig

katex 配置项,[配置详情](https://katex.org/docs/options)

```js
import { config } from 'md-editor-rt';

config({
katexConfig(base: any) {
return {
...base,
strict: false
};
}
});
```

## 🪡 快捷键

主要以`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-6 | 1-6 级标题 | `# 标题` |
| CTRL + ↑ | 上角标 | `<sup>上角标</sup>` |
| CTRL + ↓ | 下角标 | `<sub>下角标</sub>` |
| CTRL + O | 有序列表 | `1. 有序列表` |
| CTRL + L | 链接 | `[链接](https://github.com/imzbf/md-editor-rt)` |
| CTRL + Z | 撤回 | 触发编辑器内内容撤回,与系统无关 |
| CTRL + SHIFT + S | 删除线 | `~删除线~` |
| CTRL + SHIFT + U | 无序列表 | `- 无序列表` |
| CTRL + SHIFT + C | 块级代码 | 多行代码块 |
| CTRL + SHIFT + I | 图片链接 | `![图片](https://imzbf.github.io/md-editor-rt/imgs/preview-light.png)` |
| CTRL + SHIFT + Z | 前进一步 | 触发编辑器内内容前进,与系统无关 |
| CTRL + SHIFT + F | 美化内容 | |
| CTRL + ALT + C | 行内代码 | 行内代码块 |
| CTRL + SHIFT + ALT + T | 表格 | `\|表格\|` |

## 🪤 内部组件

按需引入内部扩展组件:

```js
import { NormalToolbar } from 'md-editor-rt';
```

使用参考:[文档页面](https://imzbf.github.io/md-editor-rt)

### 🐣 普通扩展工具栏

`NormalToolbar`

- **props**

- `title`: `string`,非必须,作为工具栏上的 hover 提示。
- `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。

- **events**

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

### 🐼 下拉扩展工具栏

`DropdownToolbar`

- **props**

- `title`: `string`,非必须,作为工具栏上的 hover 提示。
- `visible`: `boolean`,必须,下拉状态。
- `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。
- `overlay`: `ReactNode`,必须,下拉框中的内容。

- **events**

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

### 🦉 弹窗扩展工具栏

`ModalToolbar`

- **props**

- `title`: `string`,非必须,作为工具栏上的 hover 提示。
- `modalTitle`: `ReactNode`,非必须,弹窗的标题。
- `visible`: `boolean`,必须,弹窗显示状态。
- `width`: `string`,非必须,弹窗宽度,默认`auto`。
- `height`: `string`,同`width`。
- `showAdjust`: `boolean`,非必须,是否显示弹窗全屏按钮。
- `isFullscreen`: `boolean`,显示全屏按钮时必须,弹窗全屏状态。
- `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。
- `children`: `ReactNode`,必须,弹窗中的内容。
- `className`: `string`,非必须,类名。
- `style`: `CSSProperties`,非必须,样式。
- `showMask`: `boolean`, 非必须,是否展示遮罩层,默认true。

- **events**

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

### 🐻 目录导航

`MdCatalog`

- **props**

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

- **events**

- `onClick`: `(e: MouseEvent, t: TocItem) => void`,非必须,导航点击事件。
- `onActive`: `(heading: HeadList | undefined) => void`,非必须,高亮的标题变化事件。

### 🛸 弹窗组件

`MdModal`

- **props**

- `title`: `ReactNode`,非必须,弹窗标题栏。
- `visible`: `boolean`,必须,弹窗显示状态。
- `width`: `string`,非必须,弹窗宽度,默认`auto`。
- `height`: `string`,同`width`。
- `showAdjust`: `boolean`,非必须,是否显示弹窗全屏按钮。
- `isFullscreen`: `boolean`,显示全屏按钮时必须,弹窗全屏状态。
- `children`: `ReactNode`,非必须,弹窗显示的内容。
- `className`: `string`,非必须,类名。
- `style`: `CSSProperties`,非必须,样式。
- `showMask`: `boolean`,非必须,是否展示遮罩层,默认true。

- **events**

- `onClose`: `() => void`,必须,弹窗点击关闭事件。
- `onAdjust`: `(val: boolean) => void`,弹窗全屏按钮点击事件。

### 🛸 普通页脚工具

`NormalFooterToolbar`

- **props**

- `children`: `ReactNode`,必须,内容。

- **events**

- `onClick`: `(e: MouseEvent) => void`,非必须,点击事件。

## 🪤 内部配置

```js
import {
iconfontClassUrl,
iconfontSvgUrl,
allToolbar,
allFooter,
zh_CN,
en_US
} from 'md-editor-rt';

console.log(iconfontClassUrl, iconfontSvgUrl, allToolbar, allFooter, zh_CN, en_US);
```

## 🗂 部分示例

### 🥹 上传图片

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

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

```jsx
import React, { useState } from 'react';
import { MdEditor } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';

export default () => {
const [text, setText] = useState('#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));
// 方式二
// callback(
// res.map((item: any) => ({
// url: item.data.url,
// alt: 'alt',
// title: 'title'
// }))
// );
};

return <MdEditor modelValue={text} onChange={setText} onUploadImg={onUploadImg} />;
};
```

### 🧙‍♂️ 调整编辑器样式

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

```less
.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, #333, #f2f2f2);
--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-modal-shadow: if(@isDark, 0px 6px 24px 2px #00000066, 0px 6px 24px 2px #0000000a);
--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 变量,比如调整暗夜模式下的背景:

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