npm package: @qingbing/ts-v3-md-editor
Description: 基于 md-editor-v3 二次封装的 MdEditor 编辑器
Author: qingbing
Latest version: 2.0.7

# MdEditor 插件介绍

- [MdEditor 插件介绍](#mdeditor-插件介绍)
  - [1. 概要说明](#1-概要说明)
    - [1.1 地址](#11-地址)
    - [1.2 插件描述](#12-插件描述)
    - [1.3 重要依赖](#13-重要依赖)
    - [1.4 插件安装](#14-插件安装)
  - [2. MdPreview 说明](#2-mdpreview-说明)
    - [2.1 属性说明](#21-属性说明)
    - [2.2 事件说明, 主要参考 `md-editor-v3`](#22-事件说明-主要参考-md-editor-v3)
    - [2.3 实例暴露说明](#23-实例暴露说明)
  - [3. MdEditor 说明](#3-mdeditor-说明)
    - [3.1 属性说明](#31-属性说明)
    - [3.2 事件说明, 主要参考 `md-editor-v3`， 拥有 MdPreview 的所有属性](#32-事件说明-主要参考-md-editor-v3-拥有-mdpreview-的所有属性)
    - [3.3 实例暴露说明](#33-实例暴露说明)
  - [4. 示例](#4-示例)
    - [4.1 全局注册使用](#41-全局注册使用)
    - [4.2 模板组件使用](#42-模板组件使用)

## 1. 概要说明
### 1.1 地址

[https://gitee.com/duqingbing/ts-v3-package/tree/ts-v3-md-editor](https://gitee.com/duqingbing/ts-v3-package/tree/ts-v3-md-editor)

### 1.2 插件描述

vite + ts + vue3 二次封装 md-editor-v3 出来的 MdEditor 编辑器

### 1.3 重要依赖

- @qingbing/ts-v3-utils: ^2.0.15"
- md-editor-v3: ^4.12.2"
- vue: ^3.4.21"

### 1.4 插件安装

```bash
# yarn 安装
yarn add @qingbing/ts-v3-md-editor

# npm 安装
npm i @qingbing/ts-v3-md-editor
```

## 2. MdPreview 说明

### 2.1 属性说明

| 属性名 | 类型   | 是否必需 | 默认值                                      | 意义     |
| :----- | :----- | :------- | :------------------------------------------ | :------- |
| conf   | Object | 否       | { theme: 'light', showCodeRowNumber: true } | 预览配置 |

- conf 内部属性说明(主要参考 `md-editor-v3`)

| 属性名               | 类型                                                   | 默认值                            | 意义                                                                                             |
| :------------------- | :----------------------------------------------------- | :-------------------------------- | :----------------------------------------------------------------------------------------------- |
| modelValue           | string                                                 | ''                                | 编辑内容，可使用 v-model="value" 实现双向绑定                                                    |
| theme                | 'light'                                                | 'dark'                            | 'light'                                                                                          | 主题 |
| class                | string                                                 | ''                                | 编辑器最外层样式                                                                                 |
| language             | string                                                 | 'zh-CN'                           | 内置中英文('zh-CN','en-US')                                                                      |
| previewTheme         | TMdEditorPreviewTheme                                  | 'default'                         | 预览内容主题                                                                                     |
| editorId             | string                                                 | 'md-editor-v3'                    | 编辑器唯一标识，非必须，防止产生服务端与客户端渲染内容不一致错误提示，以及单页面多编辑器时做区别 |
| showCodeRowNumber    | boolean                                                | false                             | 代码块显示行号                                                                                   |
| style                | string \ CSSProperties                                 | ''                                | 编辑器内联样式                                                                                   |
| noMermaid            | boolean                                                | false                             | 不希望使用图表展示内容，可以设置关闭                                                             |
| noKatex              | boolean                                                | false                             | 不希望使用数学公式展示内容，可以设置关闭                                                         |
| codeTheme            | TMdEditorCodeTheme                                     | 'atom'                            | 代码块高亮样式名称                                                                               |
| noIconfont           | boolean                                                | true                              | 不插入 iconfont 链接，可以下载到本地自行引入                                                     |
| codeStyleReverse     | boolean                                                | true                              | 在主题下的 light 模式上使用暗色系的代码风格                                                      |
| codeStyleReverseList | Array<string>                                          | ['default', 'mk-cute']            | 需要自动调整的预览主题                                                                           |
| noHighlight          | boolean                                                | false                             | 不高亮代码，也不会加载相应的扩展库                                                               |
| noImgZoomIn          | boolean                                                | false                             | 关闭编辑器默认的放大功能（^4.4.0）                                                               |
| customIcon           | CustomIcon                                             | {}                                | 自定义的图标                                                                                     |
| sanitizeMermaid      | (h: string) => Promise<string>                         | (h: string) => Promise.resolve(h) | 转换生成的 mermaid 代码                                                                          |
| mdHeadingId          | (text: string, level: number, index: number) => string | (text) => text                    | 构造标题ID的生成方式                                                                             |
| formatCopiedText     | (text: string) => string                               | (text) => text                    | 格式化复制代码                                                                                   |

### 2.2 事件说明, 主要参考 `md-editor-v3`

| 事件名        | 类型                       | 意义                                      |
| :------------ | :------------------------- | :---------------------------------------- |
| onHtmlChanged | (h: string) => void        | html 变化回调事件，用于获取预览 html 代码 |
| onGetCatalog  | (list: HeadList[]) => void | 动态获取markdown目录                      |

### 2.3 实例暴露说明

| 属性名 | 类型 |
| :----- | :--- |
| -      | 无   |


## 3. MdEditor 说明

### 3.1 属性说明

| 属性名 | 类型   | 是否必需 | 默认值                                                      | 意义       |
| :----- | :----- | :------- | :---------------------------------------------------------- | :--------- |
| conf   | Object | 否       | { mode: "simple", theme: 'light', showCodeRowNumber: true } | 编辑器配置 |

- conf 内部属性说明(主要参考 `md-editor-v3`)， 拥有 MdPreview - conf 的所有属性

| 属性名          | 类型                   | 默认值   | 说明                                                                       |
| :-------------- | :--------------------- | :------- | :------------------------------------------------------------------------- |
| **mode**        | string                 | 'simple' | 组件定义的编辑器模式，主要控制 toolbar                                     |
| pageFullscreen  | boolean                | false    | 页面内全屏                                                                 |
| preview         | boolean                | true     | 是否显示预览                                                               |
| htmlPreview     | boolean                | false    | 是否显示 html 预览。当设置为true时，需要将preview设置为false               |
| toolbars        | TMdEditorToolbarItem[] | [all]    | 选择性展示工具栏                                                           |
| toolbarsExclude | TMdEditorToolbarItem[] | []       | 选择性不展示工具栏                                                         |
| noPrettier      | boolean                | false    | 是否启用 prettier 优化 md 内容                                             |
| tabWidth        | number                 | 2        | 编辑器一个 TAB 键等于空格数                                                |
| tableShape      | [number, number]       | [6, 4]   | 标题栏添加表格时，预设待选表格大小，第一个代表最大列数，第二个代表最大行数 |
| placeholder     | string                 | ''       | 啊这-_-！                                                                  |
| footers         | Array<'markdownTotal'  | '='      | 'scrollSwitch'                                                             | number> | ['markdownTotal', '=', 'scrollSwitch'] | 页脚显示内容，'='左右分割，设置为[]不显示页脚 |
| scrollAuto      | boolean                | true     | 同步滚动状态                                                               |
| noUploadImg     | boolean                | false    | 工具栏不显示上传图片入口                                                   |
| autoFocus       | boolean                | false    | 原生属性，文本区域自动获得焦点                                             |
| disabled        | boolean                | false    | 原生属性，禁用文本区域                                                     |
| readOnly        | boolean                | false    | 原生属性，文本区域为只读                                                   |
| maxLength       | number                 | ``       | 原生属性，文本区域允许的最大字符数                                         |
| autoDetectCode  | boolean                | false    | 是否启用自动识别粘贴代码类别，目前仅支持从vscode复制的内容                 |
| showToolbarName | boolean                | false    | 是否在工具栏下面显示对应的文字名称                                         |
| inputBoxWitdh   | string                 | 50%      | 输入框默认的宽度x                                                          |
| inputBoxWidth   | string                 | 50%      | 输入框默认的宽度x, 纠正组件单词错误                                        |

### 3.2 事件说明, 主要参考 `md-editor-v3`， 拥有 MdPreview 的所有属性

| 事件名                | 类型                                    | 意义                                                                    |
| :-------------------- | :-------------------------------------- | :---------------------------------------------------------------------- |
| onChange              | (v: string) => void                     | 内容变化事件（当前与textarea的oninput事件绑定，每输入一个单字即会触发） |
| onSave                | (v: string, h: Promise<string>) => void | 保存事件，快捷键与保存按钮均会触发                                      |
| onUploadImg           | (files:Array<File>,callBack:(urls:      | string[]                                                                | Array<{url:string,alt:string,title:string}>) => void) => void | 上传图片事件，弹窗会等待上传结果，务必将上传后的 urls 作为 callback 入参回传 |
| onError               | (err: { name: 'Cropper'                 | 'fullscreen'                                                            | 'prettier'                                                    | 'overlength', message: string}) => void                                      | 捕获执行错误事件，目前支持Cropper、fullscreen、prettier实例未加载完成操作，以及输入内容超出限制长度的错误 |
| onBlur                | (event: FocusEvent) => void             | 输入框失去焦点时触发事件                                                |
| onFocus               | (event: FocusEvent) => void             | 输入框获得焦点时触发事件                                                |
| onInput               | (event: Event) => void                  | 输入框键入内容事件                                                      |
| onDrop                | (event: DragEvent) => void              | 拖放内容事件                                                            |
| onInputBoxWitdhChange | (width: string) => void                 | 调整输入框宽度事件                                                      |
| onInputBoxWidthChange | (width: string) => void                 | 调整输入框宽度事件, 纠正组件单词错误                                    |


### 3.3 实例暴露说明

| 属性名 | 类型 |
| :----- | :--- |
| -      | 无   |

## 4. 示例
### 4.1 全局注册使用

- 一旦注册， `MdEditor` 和 `MdPreview` 作为组件全局通用 
- 使用方法参考 [3.2 模板组件使用](#32-模板组件使用), 去掉组件导入的语句即可

```ts
// main.ts
import "@qingbing/ts-v3-md-editor/dist/style.css"
import { MdEditorPlugin } from '@qingbing/ts-v3-md-editor'
app.use(MdEditorPlugin)
```

### 4.2 模板组件使用

```vue
<template>
    <h1>Page</h1>
    <h2> editor</h2>
    <MdEditor v-model="text" :conf="mdEditorConf" />
    <MdEditor v-model="content" :conf="{ mode: 'mini' }" />
    <MdEditor v-model="content" :conf="{ mode: 'simple' }" />
    <MdEditor v-model="content" :conf="{ mode: 'normal' }" />
    <MdEditor v-model="content" />
    <hr>
    <MdPreview v-model="content" />
    <MdPreview v-model="content" :conf="mdPreviewConf" />
</template>
  
<script setup  lang="ts">
import 'md-editor-v3/lib/style.css'; // 编辑器样式
import 'md-editor-v3/lib/preview.css'; // 编辑器预览样式
import type { TMdEditorInnerError, TMdEditorProps, TMdEditorUploadImgCallBack, TMdPreviewProps } from "@qingbing/ts-v3-md-editor";
import { ref } from 'vue';
import { MdEditor, MdPreview } from "@qingbing/ts-v3-md-editor"; // 如果全局注册，这句直接删除

const mdEditorConf: TMdEditorProps = {
    mode: 'normal',
    // 内容变化事件（当前与textarea的oninput事件绑定，每输入一个单字即会触发）
    onChange: (v: string) => {
        console.log(v);
    },
    // 保存事件，快捷键与保存按钮均会触发
    onSave: (v: string, h: Promise<string>) => {
        console.log(v);
        h.then((html) => {
            console.log(html);
        });
    },
    // 上传图片事件，弹窗会等待上传结果，务必将上传后的 urls 作为 callback 入参回传
    onUploadImg: async (files: Array<File>, callback: TMdEditorUploadImgCallBack) => {
        const res = await Promise.all(
            files.map((file) => {
                return new Promise((rev, rej) => {
                    rev([
                        {
                            data: {
                                url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
                            }
                        },
                        {
                            data: {
                                url: 'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg'
                            }
                        },
                    ])
                    // 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) => 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'));

        // 方式二
        // callback(
        //     res.map((item: any) => ({
        //         url: item.data.url,
        //         alt: 'alt',
        //         title: 'title'
        //     }))
        // );
    },
    // 捕获执行错误事件，目前支持Cropper、fullscreen、prettier实例未加载完成操作，以及输入内容超出限制长度的错误
    onError: (err: TMdEditorInnerError) => {
        alert(err.message);
    },
    // 输入框失去焦点时触发事件
    onBlur: (event: FocusEvent) => {
        console.log('onBlur', event);
    },
    // 输入框获得焦点时触发事件
    onFocus: (event: FocusEvent) => { },
    // 输入框键入内容事件,
    onInput: (event: Event) => { },
    // 拖放内容事件
    onDrop: (event: DragEvent) => {
        event.stopPropagation();
        console.log('ee', event.dataTransfer?.files[0]);
    },
    // 调整输入框宽度事件
    onInputBoxWitdhChange: (width: string) => { },
}

const mdPreviewConf: TMdPreviewProps = {
    theme: 'dark',
    showCodeRowNumber: false
}
const content = ref("# title\n## sub title");
const text = ref("# Hello Editor\n```php\n$a = 5;\n$b = 6;\n$c = $a + $b\n```");
</script>
```