天天看點

tinymce6插件開發(版本涉及4.x\5.x\6.x\7.x,案例以Element-UI中開發為藍本)基本流程:4.x和5.x版本通用代碼:6.x和7.x版本案例分析與總結:進階學習

網上大部分涉及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. 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() {
          // 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(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();
            }
          });
        }
      });
    });
  }; 

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

參考(其中提供的代碼不一定适合tinymce6):

三種插件開發模式,帶你玩廢tinymce

tinymce系列(二) tinymce 插件開發

關于tinymce插件,開發的自由表單、病曆插件

富文本插件tinymce.init()最全配置參數說明

Element-UI中調用tinymce6如何實作本地化加載,如何解決提示:This domain is not registered with TinyMCE Cloud,必須要api-key麼?

繼續閱讀