Vue3集成Tinymce富文本和markdown编辑器

845 阅读3分钟

Vue3集成Tinymce富文本和markdown编辑器,实现插入markdown数据的功能,实现富文本转为markdown的功能。

其中实现插入markdown的功能,最后采用了方案一和方案三。 方案一适用于在富文本编辑框中输入markdown的情况。方案三适用于把从其他渠道获取的markdown的大片文本黏贴进富文本的情况。 其中富文本转为markdown通过自定义插件的方法解决的,核心逻辑是获取到富文本编辑器的内容,把html转为markdown。

实现插入markdown的功能

方案一,使用插件

  • 可以自己实现类似markdown类的文本语法结构 textpattern.
plugins:'textpattern',

textpattern_patterns: [

{ start: "*", end: "*", format: "italic" },

{ start: "**", end: "**", format: "bold" },

{ start: "#", format: "h1" },

{ start: "##", format: "h2" },

{ start: "###", format: "h3" },

{ start: "####", format: "h4" },

{ start: "#####", format: "h5" },

{ start: "######", format: "h6" },

{ start: "1. ", cmd: "InsertOrderedList" },

{ start: "* ", cmd: "InsertUnorderedList" },

{ start: "- ", cmd: "InsertUnorderedList" },

{ start: "\n", replacement: "<br/>" },

{ start: "---", replacement: "<hr/>" },

{ start: "--", replacement: "—" },

{ start: "-", replacement: "—" },

{ start: "(c)", replacement: "©" },

{ start: "//brb", replacement: "Be Right Back" },

{

start: "//heading",

replacement:

'<h1 style="color:blue">Heading here</h1><p><em>Date: 01/01/2000</em></p> ',

},

],

  • 有三种匹配方式:
1  包围匹配
形如:{start: '**', end: '**', format: 'bold'} 即为包围匹配。
2 块匹配
形如:{start: '1. ', cmd: 'InsertOrderedList'}, 即为块匹配。
3 替换匹配
{start: '(c)', replacement: '©'} 为替换模式的写法。

  • 缺陷是匹配方式,有三种匹配方式中不能处理以下内容一行中有多个标签的情况,如 “# 一级标题 /n ## 二级标题”。

方案二

  • 使用官方插件tinymce markdown
  • 不过需要版本7,而且需要付费。

image.png

方案三

# Vue3 使用marked【代码高亮,安装使用教程】

  • marked:转换markdown语法为HTML
  • highlight.js:高亮代码块
npm install marked @types/marked highlight.js -S
  • 使用方法:src/App.vue .
  • TinymceEditor是我封装的富文本组件。
<template>

<div class="doc-box">

<div>

<a-space wrap>

<a-input v-model:value="valueMarkedTest" style="width: 300px"></a-input>

<a-button type="primary" @click="handleInsertText">插入文本</a-button>

<a-button @click="handleInsertMarkdown">插入markdown</a-button>

<a-button type="text">Text Button</a-button>

<a-button type="link">Link Button</a-button>

</a-space>

<div v-html="markdownToHtml" class="markdown-body"></div>

</div>

<div class="editor-box">

<TinymceEditor :value="formData.content" @update:value="updateContent" />

</div>

</div>

</template>

<script setup>

import { shallowRef, ref, reactive } from "vue";

import TinymceEditor from "./components/MyTiny/index.vue";

import { marked } from "marked";

import hljs from "highlight.js";

import "highlight.js/styles/foundation.css";

const value = ref("heww loo");

const formData = reactive({

content: "",

});

const updateContent = (v) => {

formData.content = v;

console.log(`内容变更了:` + v);

};

const handleInsertText = () => {

formData.content = formData.content + " 插入的文本123 ";

};

  


const render = new marked.Renderer();

marked.setOptions({

renderer: render, // 这是必填项

gfm: true, // 启动类似于Github样式的Markdown语法

pedantic: false, // 只解析符合Markdwon定义的,不修正Markdown的错误

sanitize: false, // 原始输出,忽略HTML标签(关闭后,可直接渲染HTML标签)

  


// 高亮的语法规范

highlight: (code, lang) => hljs.highlight(code, { language: lang }).value,

});

  


const valueMarkedTest = ref("**Hello,World** \n# 一级菜单 \n ## 二级菜单 ");

const markdownToHtml = shallowRef("");

markdownToHtml.value = marked(valueMarkedTest.value);

// // markdown转为html后,直接更新到富文本内容中

const handleInsertMarkdown = () => {

markdownToHtml.value = marked(valueMarkedTest.value);

console.log(markdownToHtml.value);

formData.content = formData.content + markdownToHtml.value;

};

</script>

  


<style scoped>

.doc-box {

padding: 0;

height: 100%;

border: solid 1px red;

width: 100%;

height: 100%;

}

  


.markdown-body {

background-color: pink;

margin: 10px;

}

  


.editor-box {

margin-top: 10px;

width: 100%;

max-height: calc(100% - 60px);

border: solid 1px green;

padding: 0;

}

</style>

富文本转为markdown

-插件Markdownfortinymce

1 在public下新建文件夹 public/tinymce/plugins/markdown 。
2 复制.js文件到该目录下。
  当前我的版本是tinymce5.10.3 ,需要微调下addButton、addMenuItem方法。
3 在.vue组件中使用这个插件
plugins:'markdown',
contextmenu: "markdown",
toolbar:'markdown'

  • 核心代码截图 image.png

  • 转换前 image.png

  • 转换后 image.png

源码

本文档中示例源码已上传到这里,供参考。