TinyMCE 旨在通过自定义插件轻松扩展;它提供了用于注册自定义插件以及创建和本地化自定义 UI 的 API。

要求

要被 TinyMCE 识别为插件,自定义插件的代码必须包含一个具有单一入口点的 JavaScript 文件,该文件通过 PluginManager API 将插件注册到 TinyMCE。任何其他代码或资源都可以位于单独的文件中,并可以以任何标准方式加载。TinyMCE 还提供了各种 API,用于加载脚本和样式表。

除了这些要求外,TinyMCE 不需要任何特殊的文件结构或工具,因此可以使用大多数框架和工具开发自定义插件。

向 TinyMCE 注册自定义插件

使用 PluginManager 向 TinyMCE 注册自定义插件。PluginManager.add() 接受一个表示插件标识符的字符串和一个包含插件初始化代码的函数。

传递给 PluginManager.add() 的插件标识符由 TinyMCE 用作标识符字符串。它应该:

  • 是一个字母数字字符串,

  • 不包含任何空格或其他空白字符,

  • 是一个唯一的标识符,不与 TinyMCE 提供的插件或任何其他正在使用的 TinyMCE 插件的 ID 匹配。

如果多个插件具有相同的标识符,则其中一个将覆盖其他插件。

可选地,传递给 PluginManager.add() 的函数可以返回一个对象,该对象包含 TinyMCE 或其他插件可以使用的数据。Tiny 建议包含一个 getMetadata 回调,该回调返回一个包含可用于填充帮助插件对话框中插件列表的数据的对象。元数据对象应包含以下值:

  • name:一个包含插件名称的字符串,通常采用人类可读的格式。

  • url:一个包含 URL 的字符串,通常用于链接到帮助文档。

示例:插件注册样板代码

tinymce.PluginManager.add('pluginId', (editor, url) => {
  // 在此添加插件代码

  return {
    getMetadata: () => ({
      name: 'Custom plugin',
      url: 'https://example.com/docs/customplugin'
    })
  }
});

向自定义插件添加工具栏按钮

使用 editor.ui.registry.addButton 添加工具栏按钮,并使用 editor.addCommand 定义操作。两者都在传递给 PluginManager.add() 的插件回调中注册:

tinymce.PluginManager.add('myplugin', (editor, url) => {
  editor.addCommand('myCommand', () => {
    editor.insertContent('&nbsp;<strong>Inserted content</strong>&nbsp;');
  });

  editor.ui.registry.addButton('mybutton', {
    text: 'My Button',
    onAction: () => editor.execCommand('myCommand')
  });

  return {
    getMetadata: () => ({
      name: 'My plugin',
      url: 'https://example.com/docs'
    })
  };
});

然后在编辑器配置中包含插件和按钮:

tinymce.init({
  selector: 'textarea',
  plugins: 'myplugin',
  toolbar: 'mybutton',
  external_plugins: {
    myplugin: '/path/to/myplugin.js'
  }
});

有关更多工具栏按钮类型,请参阅工具栏按钮。

在 TinyMCE 中使用自定义插件

可以通过以下方式将自定义插件添加到 TinyMCE 实例中:

  • 使用 external_plugins:使用external_plugins 选项指定插件入口点文件的基于 URL 的位置。

  • 将代码复制到 plugins 文件夹:将入口点文件(以及任何其他文件)复制到分发的 TinyMCE 代码的 plugins 文件夹中。然后,可以通过在plugins 选项指定的插件列表中包含该插件来使用它。

Tiny 建议对自定义插件使用 external_plugins 选项。

示例:使用 external_plugins

tinymce.init({
  selector: 'textarea',  // 根据您的 HTML 更改此值
  external_plugins: {
    pluginId: 'https://example.com/customplugincode.min.js'
  },
  plugins: ''
});

示例:将插件代码复制到 plugins 文件夹

tinymce.init({
  selector: 'textarea',  // 根据您的 HTML 更改此值
  plugins: 'pluginId'
});

测试 TinyMCE

由于 TinyMCE 使用的浏览器 API 范围广泛;在测试 TinyMCE 或任何自定义插件时,TinyMCE 需要一个在真实浏览器上运行的测试框架。模拟浏览器的测试框架将无法工作。

语言本地化

如果自定义插件包含使用 TinyMCE 的UI API创建的任何自定义 UI,则可能需要进行本地化。

TinyMCE 附带了许多语言的许多字符串的翻译。要为自定义插件向支持的语言添加额外的字符串,请使用以下过程。

  1. 在自定义插件的根目录中创建一个“langs”目录用于自定义翻译。

  2. 对于插件支持的每种语言,创建一个翻译文件。

    这些文件应为 JavaScript 文件,并使用相关的语言代码作为文件名。例如:TinyMCE 会在 <your plugin>/langs/es_ES.js 路径下查找西班牙语翻译文件,其中 <your plugin> 指包含插件入口文件的目录。支持的语言列表请参阅:支持的语言。

  3. 在每个翻译文件中,通过向 tinymce.addI18n() API 传递一个包含源字符串与翻译字符串键值对的对象,来添加翻译字符串。

  4. 在插件的入口文件中,调用 tinymce.PluginManager.requireLangPack(),并传入插件标识符以及以逗号分隔的待加载语言代码字符串。

示例:西班牙语额外翻译文件的内容

tinymce.addI18n('es_ES', {
  'Example plugin': 'Complemento de ejemplo'
});

示例:为自定义插件加载额外的翻译文件

// 注册自定义插件
tinymce.PluginManager.add('pluginId', (editor, url) => {
  // 在此处添加插件代码
});
// 加载所需的翻译文件
tinymce.PluginManager.requireLangPack('pluginId', 'es_ES,de_AT');

示例插件

此示例插件演示了如何添加一个简单的工具栏按钮和菜单项。该按钮会打开一个对话框,允许在编辑器中输入标题。菜单项将打开与按钮相同的对话框。

HTML

<textarea id="custom-plugin"><p>要为编辑器内容添加“标题: ”,请点击“My button”并填写对话框,然后保存更改。</p><p>&nbsp;</p></textarea>

JS

/*
  注意:出于演示目的,我们将插件与 TinyMCE 实例放在同一个 JavaScript 文件中。
  Tiny 建议不要将插件与 TinyMCE 实例放在一起维护,而是使用 `external_plugins` 选项。
*/
tinymce.PluginManager.add('example', (editor, url) => {
  const openDialog = () => editor.windowManager.open({
    title: 'Example plugin',
    body: {
      type: 'panel',
      items: [
        {
          type: 'input',
          name: 'title',
          label: 'Title'
        }
      ]
    },
    buttons: [
      {
        type: 'cancel',
        text: 'Close'
      },
      {
        type: 'submit',
        text: 'Save',
        buttonType: 'primary'
      }
    ],
    onSubmit: (api) => {
      const data = api.getData();
      /* 当窗口表单提交时插入内容 */
      editor.insertContent('Title: ' + data.title);
      api.close();
    }
  });
  /* 添加一个用于打开窗口的按钮 */
  editor.ui.registry.addButton('example', {
    text: 'My button',
    onAction: () => {
      /* 打开窗口 */
      openDialog();
    }
  });
  /* 添加一个菜单项,可通过 menu/menubar 配置将其包含在任何菜单中 */
  editor.ui.registry.addMenuItem('example', {
    text: 'Example plugin',
    onAction: () => {
      /* 打开窗口 */
      openDialog();
    }
  });
  /* 返回 help 插件的元数据 */
  return {
    getMetadata: () => ({
      name: 'Example plugin',
      url: 'http://exampleplugindocsurl.com'
    })
  };
});

/*
  以下是一个使用新插件和新工具栏按钮的示例。
*/
tinymce.init({
  selector: 'textarea#custom-plugin',
  plugins: 'example help',
  toolbar: 'example | help'
});