首页 > WEB开发 > wangEditor 5 增加源码模式插件
2024
11-06

wangEditor 5 增加源码模式插件

一、背景介绍:

wangEditor 5默认没有源码模式切换功能,但在实际应用中需要这个功能

二、插件开发

1、新建插件目录

插件结构.PNG

2、根据官网API编写类文件和注册文件(https://www.wangeditor.com/v5/development.html)

sourceMenu.js

// 定义菜单类,参考官网 https://www.wangeditor.com/v5/development.html
class SourceMenu {
  constructor() {
    this.title = '源码' // 自定义菜单标题
    this.iconSvg = "<svg t='1730795024638' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='8483' width='64' height='64'><path d='M280.746667 164.48H2.858667v822.485333h1021.013333V314.794667H442.453333L280.746667 164.48z m689.194666 765.781333H56.746667V221.226667h204.202666l161.706667 153.173333h547.328v555.861333zM510.506667 192.853333L354.517333 36.864H59.562667v56.746667H328.96l155.989333 155.989333h538.88V192.853333H510.464zM360.192 482.133333L201.386667 632.448l158.805333 147.498667 39.68-42.538667-116.266667-104.96 116.309334-107.776-39.722667-42.538667z m331.818667 297.813334l158.848-147.498667-158.848-150.314667-39.68 42.538667 116.266666 107.776-116.266666 104.96 39.68 42.538667z m-261.888 40.661333l113.408-368.64 54.186666 16.64-113.365333 368.64-54.186667-16.64z' fill='#5A5B5A' p-id='8484'></path></svg>" // 图标
    this.tag = 'button'
    this.active = false
  }

  /**
     * 获取编辑器内容源码
     */
  getValue(editor) {
    return editor.getHtml();
  }

  /**
     * 菜单是否需要激活,当切换为源码时菜单激活
     */
  isActive(editor) {
    return this.active;
  }

  /**
     * 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
     */
  isDisabled(editor) {
    return false;
  }

  /**
     * 点击菜单时触发的函数
     */
  exec(editor, value) {
    this.active = !this.active;
    if (this.isDisabled(editor)) return
    editor.emit('clickSource', this.active);
  }
}
export default SourceMenu;

register.js

import SourceMenu from "./sourceMenu.js";
import prettier from 'prettier/standalone';
import parserHtml from 'prettier/parser-html';

/**
 * 在编辑器中得到的html源码是没有格式的html字符串
 * 所以需要格式化展示代码
 * 格式化html代码
 */
export const parserHtmlCode = (code) => {
  try {
    return prettier.format(code, {
      parser: 'html',
      plugins: [parserHtml],
      // 格式化的标签不换行 例如span标签等>格式化后会换行
      htmlWhitespaceSensitivity: 'ignore'
    });
  } catch (e) {
    console.error('格式化代码错误', e);
    return code;
  }
}

/**
 * 将编辑器html转换为代码块内容
 */
export const parseEditorCode = (html) => {
  const code = html
    .replace(/&nbsp;/g, '')
    .replace(new RegExp('<p><br></p>', 'g'), '');
  const data = parserHtmlCode(code).trim();
  const textCode = data
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/ /g, "&nbsp;");
  return `<pre><code class="language-html">${textCode}</code></pre>`;
}

/**
 * 将代码块转换为编辑器html
 */
export const parseCodeEditor = (preCode) => {
  // 转码
  let data = encodeURI(preCode);
  // 将&nbsp;转换为空格
  data = data.replace(/%C2%A0/g, '%20');
  // 解码
  data = decodeURI(data);
  const htmlStr = data
    .replace('<pre><code class="language-html">', '')
    .replace('</code></pre>', '')
    .replace(/&lt;/ig, "<")
    .replace(/&gt;/ig, ">");
  return htmlStr
    .replace(new RegExp('\\n', 'g'), '')
    .replace(new RegExp('<p><br></p>', 'g'), '')
    .trim();
}

export const sourceConf = {
  // 工具栏中的唯一key
  key: 'source',
  // 组件
  factory: () => new SourceMenu()
};


三、页面中使用

<div>
	<Toolbar
	  style="border-bottom: 1px solid #ccc"
	  :editor="editor"
	  :default-config="toolbarConfig"
	/>
	<Editor
	  v-model="form.content"
	  style="height: 400px; overflow-y: hidden;"
	  @onCreated="onCreated"
	/>
</div>


<script>
import '@wangeditor/editor/dist/css/style.css'
import { Boot } from '@wangeditor/editor';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { parseCodeEditor, parseEditorCode, sourceConf } from "@/utils/wangEditor5-plug/register.js";
export default {
  components: { Editor, Toolbar },
  data() {
    return {
      editor: null,
      toolbarConfig: { // 使用自定义扩展菜单'source'
        insertKeys: {
          index: 25,
          keys: ['source']
        }
      },
    }
  },
  mounted() {
  },
  created() {
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时,及时销毁编辑器
  },
  methods: {
    // 源码模式点击事件
    clickSource(active, editor) {
      let value = editor.getHtml();
      // 先将编辑器内容清空
      this.editor.clear();
      if (active) {
        // 将html代码转换为html代码块 dangerouslyInsertHtml是插入html不是重置html
        this.editor.dangerouslyInsertHtml(parseEditorCode(value));
      } else {
        // 将html代码块转换为editor的html
        this.editor.dangerouslyInsertHtml(parseCodeEditor(value));
        console.log("parseCodeEditor(value)", parseCodeEditor(value))
        value = parseCodeEditor(value);
      }
    },
    onCreated(editor) {
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
      if (!this.editor.getAllMenuKeys().includes('source')) {
        Boot.registerMenu(sourceConf); // 注册菜单
      }
      this.editor.on('clickSource', (active) => this.clickSource(active, this.editor));
    }
  }
}
</script>


作者:admin
admin
TTF的家园-www.ttfde.top 个人博客以便写写东西,欢迎喜欢互联网的朋友一起交流!

本文》有 0 条评论

留下一个回复