tinymce6插件开发(版本涉及4.x\5.x\6.x\7.x,案例以Element-UI中开发为蓝本)

网上大部分涉及tinymce插件开发的文章以4.x和5.x版本为主,而目前最新的6.x版很多老插件都无法正常加载或运行了。

基本流程:

本开发流程以一个包含checkbox组件的弹窗为例:

  1. 创建插件文件夹,例如 myplugin,文件夹中创建三个文件:
    index.js 用于引导;
    plugin.js 开发主文件;
    plugin.min.js 已打包文件,选择tinymce.min.js时自动调用。
  2. plugin.js 文件中定义插件,使用 TinyMCE 的插件系统注册插件。
  3. 在插件中定义弹窗,使用 TinyMCE 的 UI 组件系统创建弹窗。
  4. 在弹窗中添加 checkbox 和说明,使用 TinyMCE 的 UI 组件系统添加 checkbox 和说明。
  5. 在确定按钮事件处理函数中,根据 checkbox 的值修改编辑器内的文本。
  6. 在 TinyMCE 配置中启用插件,使用 TinyMCE 的配置系统启用插件。

在这里插入图片描述

以下代码为Element-UI页面中调用自定义组件方法,本文的插件代码案例都以此为目标地。

// view/tinymcetest.vue
<template>
  <div>
    <Editor
      :init="init"
    />
  </div>  
</template>
<script setup>
import Editor from "@tinymce/tinymce-vue"
import 'tinymce/tinymce'
...
import 'tinymce/plugins/myplugin'
const init = {
    
    
	plugins: 'myplugin',
	toolbar: 'myplugin',
	mybold:true, //自定义参数
}
</script>

4.x和5.x版本通用代码:

如果你对这两个版本很熟悉了,那么可以直接忽略本小节。

tinymce.PluginManager.add('myplugin', function(editor) {
    
    
  // Add a button that opens a window
  // editor.addButton('myplugin', { // 4.x版
  editor.ui.registry.addButton('myplugin', {
    
     // 5.x版
    text: 'My Button',
    onAction: function() {
    
    
      // Open window
      editor.windowManager.open({
    
    
        title: 'My Plugin Window',
        body: [
          {
    
    
            type: 'checkbox',
            name: 'bold',
            text: 'Bold',
            checked: false
          },{
    
    
            type: 'checkbox',
            name: 'italic',
            text: 'Italic',
            checked: true
          }
        ],
        onSubmit: function(e) {
    
    
          // Get the values from the checkboxes
          var bold = e.data.bold;
          var italic = e.data.italic;

          // Modify the text in the editor
          var text = editor.selection.getContent({
    
    format: 'text'});
          var style = '';
          if (bold) {
    
    
            style += 'font-weight: bold;';
          }
          if (italic) {
    
    
            style += 'font-style: italic;';
          }
          editor.insertContent('<span style="' + style + '">' + text + '</span>');
        }
      });
    }
  });
});

这段代码实现了以下功能:

  • 添加一个名为 “My Button” 的按钮。
  • 点击按钮时打开一个名为 “My Plugin Window” 的弹窗。
  • 弹窗中包含两个 checkbox,一个是 “Bold”,一个是 “Italic”。
  • 点击确定按钮后,获取 checkbox 的值,并将选中的文本改为粗体或斜体(或两者都是)。

如果使用了 TinyMCE Vue 组件,则插件开发方式与上面给出的代码略有不同。具体而言,您需要使用 Vue 插件,而不是 TinyMCE 插件。这是因为 TinyMCE Vue 组件是通过 Vue 组件包装 TinyMCE 编辑器,并允许您使用 Vue 组件的形式与 TinyMCE 编辑器进行交互。

以下演示在 TinyMCE Vue 中实现该功能插件:

import Vue from 'vue'

const MyPlugin = {
    
    
  install(editor, url) {
    
    
    // editor.addButton('myplugin', { // 4.x版
    editor.ui.registry.addButton('myplugin', {
    
     // 5.x版
      text: 'My Button',
      onAction: function() {
    
    
        // Open window
        editor.windowManager.open({
    
    
          title: 'My Plugin Window',
          body: [
            {
    
    
              type: 'checkbox',
              name: 'bold',
              text: 'Bold',
              checked: false
            },{
    
    
              type: 'checkbox',
              name: 'italic',
              text: 'Italic',
              checked: true
            }
          ],
          onSubmit: function(e) {
    
    
            // Get the values from the checkboxes
            var bold = e.data.bold;
            var italic = e.data.italic;

            // Modify the text in the editor
            var text = editor.selection.getContent({
    
    format: 'text'});
            var style = '';
            if (bold) {
    
    
              style += 'font-weight: bold;';
            }
            if (italic) {
    
    
              style += 'font-style: italic;';
            }
            editor.insertContent('<span style="' + style + '">' + text + '</span>');
          }
        });
      }
    });
  }
}

Vue.use(MyPlugin)

6.x和7.x版本案例分析与总结:

虽然整体思路还是差不多,但6.x以上版本中有很多规范、函数都变了,可能删除,可能修改,可能新增:

  1. 官方风格:在plugin.js 的立即执行函数 (function(){...}) 中写一个具备注册按钮或菜单等功能的函数并且运行该函数;
  2. 使用tinymce中的功能需要先加载对应模块
    a) tinymce.util.Tools.resolve('tinymce.PluginManager') 方法加载插件模块;
    b) tinymce.PluginManager 方式操作 ;
  3. 弹窗配置中必须配置按钮参数 buttons
buttons: [{
    
    
  type: 'cancel',
  name: 'cancel',
  text: 'Cancel'
},{
    
    
  type: 'submit',
  name: 'save',
  text: 'Save',
  primary: true
}]
  1. 插件名如果是 myplugin ,那么 addButton() 时候的按钮名也是 myPlugin 才能显示;
global.add('myplugin', editor => {
    
    
  editor.ui.registry.addButton('myplugin', {
    
    });
});
  1. 在不同版本下,各种组件的属性可能有所差异,比如原来的 text ,现在可能是 label
  2. 获取组件值的方法为 .getData(),老版本使用 .data
  3. 组件初始值(非默认值)需要在 initialData 中给对应组件 name 赋值,而老版本则可能是使用诸如 checked:true
// checked为true,在打开面板的时候,对应的checkbox将会被选中
body: [{
    
    
  type: "container",
  items: [{
    
    
    type: 'checkbox',
    name: 'bold',
    text: 'Bold',
    checked:true
}]

// initialData中设置了初始值,那么在打开面板的时候,对应的checkbox将会被选中
body:{
    
     
  type: 'panel',
  items: [{
    
    
    type: 'checkbox',
    name: 'bold',
    label: 'Bold'
  }
]},
initialData:{
    
    
  bold: true,
}
  1. .options.get().getParam() 函数从当前editor编辑器中获得参数,一般用于插件默认值或函数,在调用tinymce时的init参数中配置;
    .getParam(name: String, defaultVal: String, type: String): String按名称返回配置参数,其中包含了默认值。
    但在 TinyMCE 6.0 中已弃用,虽然还能实现,但在 TinyMCE 7.0 中标记为删除,改用 .options.get,具体实现看案例比较。
// Returns a specific config value from the currently active editor
const someval = tinymce.activeEditor.getParam('myvalue');

// Returns a specific config value from a specific editor instance by id
const someval2 = tinymce.get('my_editor').getParam('myvalue');
  1. 原来使用getParam()的方法结合了注册默认值和获取当前值,但最新版本中已将这两个功能分开了。
// 4.x 5.x 6.x版方法
editor.getParam('mybold',true); //如果mybold参数不存在,则为true

// 6.x 7.x版方法
const registerOption = editor.options.register; // 注册默认值
registerOption('mybold', {
    
    
  processor: 'boolean',
  default: true
});

editor.options.get('mybold') // 获取当前值

按照官方风格写插件

// node_modules/tinymce/plugins/myplugin/plugin.js
(function () {
    
    
  'use strict';
  //Load plugin util
  var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  
  const MyPlugin = () => {
    
    
    global.add('myplugin', editor => {
    
    
      // get option and set default value 另一种获取init参数的方法,本案例使用6.0官方风格获取
      /*const setting = {
        bold: editor.getParam('mybold',false),
        italic: editor.getParam('myitalic',false)
      };*/
  
	  // reg option 注册默认值
	  editor.options.register('mybold', {
    
    
	    processor: 'boolean',
	    default: true
	  });
	  editor.options.register('myitalic', {
    
    
	    processor: 'boolean',
	    default: true
	  });
	
	  // Get option 获取当前值
	  const setting = {
    
    
	    bold: editor.options.get('mybold'),
	    italic: editor.options.get('myitalic')
	  };

      // Add a button that opens a window
      editor.ui.registry.addButton('myplugin', {
    
    
        text: 'My Button',
        onAction: function() {
    
    
          // Open window
          editor.windowManager.open({
    
    
            title: 'My Plugin Window',
            body:{
    
     
              type: 'panel',
              items: [{
    
    
                type: 'checkbox',
                name: 'bold',
                label: 'Bold'
              },{
    
    
                type: 'checkbox',
                name: 'italic',
                label: 'Italic'
              }
            ]},
            buttons: [{
    
    
              type: 'cancel',
              name: 'cancel',
              text: 'Cancel'
            },{
    
    
              type: 'submit',
              name: 'save',
              text: 'Save',
              primary: true
            }],
            //Like [input:name=bold].checked=true;[input:name=italic].checked=false;
            initialData:{
    
    
              bold: setting.bold,
              italic: setting.italic
            },
            onSubmit: e => {
    
    
              // Get the values from the checkboxes
              var bold = e.getData().bold;
              var italic = e.getData().italic;
    
              // Modify the text in the editor
              var text = editor.selection.getContent({
    
    format: 'text'});
              var style = '';
              if (bold) {
    
    
                style += 'font-weight: bold;';
              }
              if (italic) {
    
    
                style += 'font-style: italic;';
              }
              editor.insertContent('<span style="' + style + '">' + text + '</span>');
  
              // Close window
              e.close();
            }
          });
        }
      });
    });
  }; 
  
  // Run
  MyPlugin();	
})();

按照老版本代码修改插件

在老版本基础上修改了新版里对应的部分,下面的代码也可直接放于vue页面中,无需用import引用。
其中getParam()函数目前也可用在官方风格的插件中,但未来可能被禁用。

// node_modules/tinymce/plugins/myplugin/plugin.js
tinymce.PluginManager.add('myplugin', function(editor, url) {
    
    
  // get option and set default value
  const setting = {
    
    
    bold: editor.getParam('mybold',false),
    italic: editor.getParam('myitalic',false)
  };
  // Add a button that opens a window
  editor.ui.registry.addButton('myplugin', {
    
    
    text: 'My Button',
    onAction: function() {
    
    
      // Open window
      editor.windowManager.open({
    
    
        title: 'My Plugin Window',
        body:{
    
     
              type: 'panel',
              items:[
          {
    
    
            type: 'checkbox',
            name: 'bold',
            label: 'Bold'
          },
          {
    
    
            type: 'checkbox',
            name: 'italic',
            label: 'Italic'
          }
        ]},
        buttons: [{
    
    
          type: 'cancel',
          name: 'cancel',
          text: 'Cancel'
        },{
    
    
          type: 'submit',
          name: 'save',
          text: 'Save',
          primary: true
        }],
        //Like [input:name=bold].checked=true;[input:name=italic].checked=false;
        initialData:{
    
    
          bold: setting.bold,
          italic: setting.italic
       },
        onSubmit: function(e) {
    
    
          // Get the values from the checkboxes
          var bold = e.getData().bold;
          var italic = e.getData().italic;

          // Modify the text in the editor
          var text = editor.selection.getContent({
    
    format: 'text'});
          var style = '';
          if (bold) {
    
    
            style += 'font-weight: bold;';
          }
          if (italic) {
    
    
            style += 'font-style: italic;';
          }
          editor.insertContent('<span style="' + style + '">' + text + '</span>');
        }
      });
    }
  });
});

进阶学习

  1. icon
    Icons Available for TinyMCE
    TinyMCE 富文本编辑器 ━━ (Version: 5.0.4)内含icon对照表
  2. ui
    打开链接后看左侧列表所在位置为 Creating custom UI components
    Creating custom dialogs
  3. 参数注册、设置与删除
    tinymce.EditorOptions
  4. 弹窗布局和组件
    Custom dialog body components
  5. 修改弹窗当前配置状态(这里并非重置到初始配置,而是修改后的配置)
    Interactive example using Redial
    比如实现在弹窗中选中某个checkbox后,另一个checkbox也会选中,那么此时就要用到.redial(config)来重置弹窗中各组件、各状态等。
    注意,目前版本只能将所有配置同时重置,而不能单独针对某一个组件进行重置。
  6. 弹窗互动
    Interactive example using Redial
    例如:所有dialog的改变都用onChange()统一监听
...
onSubmit: api => {
    
    
  console.log('提交表单');
},
onChange: (dialogApi, details) => {
    
    
  const data = dialogApi.getData();
  console.log('是否选中粗体组件:'+data.mybold);
  dialogApi.redial(config);
  console.log('修改弹窗');
}
...
  1. Element-UI打包后仍旧为老插件,刷新也没用
    找到 node_modules\.vite\deps\_metadata.json 文件,删除该下面部分后,重新打包即可。
    "tinymce/plugins/myplugin": {
    
    
      "src": "../../tinymce/plugins/myplugin/index.js",
      "file": "tinymce_plugins_myplugin.js",
      "fileHash": "1234567",
      "needsInterop": true
    }

仿复杂化官方代码

参考官方的插件代码书写,将上面写的代码再进一步复杂化~~看懂后,自己看官方插件也基本没问题了

(function () {
    
    
  'use strict';
  //Load plugin util
  var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

  // reg option
  const register = editor => {
    
    
    const registerOption = editor.options.register;
    registerOption('mybold', {
    
    
      processor: 'boolean',
      default: true
    });
    registerOption('myitalic', {
    
    
      processor: 'boolean',
      default: true
    });
  };
  // get option
  const option = name => editor => editor.options.get(name);
  const setting = {
    
    
    bold: option('mybold'),
    italic: option('myitalic')
  };

  const MyPlugin = () => {
    
    
    global.add('myplugin', editor => {
    
          
	  // reg option
      register(editor);
      
      // Add a button that opens a window
      editor.ui.registry.addButton('myplugin', {
    
    
        text: 'My Button',
        icon: 'bold',
        onAction: function() {
    
    
          let config = {
    
    
            title: 'My Plugin Window',
            body:{
    
     
              type: 'panel',
              items: [{
    
    
                type: 'checkbox',
                name: 'bold',
                label: 'Bold'
              },{
    
    
                type: 'checkbox',
                name: 'italic',
                label: 'Italic'
              }
            ]},
            buttons: [{
    
    
              type: 'cancel',
              name: 'cancel',
              text: 'Cancel'
            },{
    
    
              type: 'submit',
              name: 'save',
              text: 'Save',
              primary: true
            }],
            //Like [input:name=bold].checked=true;[input:name=italic].checked=false;
            initialData:{
    
    
              bold: setting.bold(editor),
              italic: setting.italic(editor),
            },
            onSubmit: e => {
    
    
              // Get the values from the checkboxes
              var bold = e.getData().bold;
              var italic = e.getData().italic;
    
              // Modify the text in the editor
              var text = editor.selection.getContent({
    
    format: 'text'});
              var style = '';
              if (bold) {
    
    
                style += 'font-weight: bold;';
              }
              if (italic) {
    
    
                style += 'font-style: italic;';
              }
              editor.insertContent('<span style="' + style + '">' + text + '</span>');
  
              // Close window
              e.close();
            },
            onChange(dialogApi, details) => {
    
    
	          const data = dialogApi.getData();
	          // if bold is checked, then italic is checked too
	          if(data.bold){
    
    
	            config.initialData.italic = true;	          
	            dialogApi.redial(config);
	          }
	        }
          };
          
          // Open window
          editor.windowManager.open(config);
        }
      });
    });
  }; 

  // Run
  MyPlugin();	
})();

参考(其中提供的代码不一定适合tinymce6):
三种插件开发模式,带你玩废tinymce
tinymce系列(二) tinymce 插件开发
关于tinymce插件,开发的自由表单、病历插件
富文本插件tinymce.init()最全配置参数说明
Element-UI中调用tinymce6如何实现本地化加载,如何解决提示:This domain is not registered with TinyMCE Cloud,必须要api-key么?

猜你喜欢

转载自blog.csdn.net/snans/article/details/128917094