Когда вы настраиваете форматы текстов, то кроме добавления иконок в toolbar wysiwyg, вы можете видеть набор настроек для разных плагинов CKEditor. Посмотрим как добавить настройки для своего плагина.
Сложно рассматривать эту задачу чисто теоретически, потому расскажу на примере плагина c5bb.
Плагин позволяет настраивать anchor ссылки, добавляя к ним класс .btn и ряд других классов, которые позволяют в конце концов настроить bootstrap-like button.
Помимо классов относящихся к фреймворку bootstrap, у ссылки есть и собственные естественные атрибуты типа href, target.
В определенный момент я понял, что было бы удобно иметь гибкую настройку bootstrap классов, что сводится к конфигурированию нескольких выпадающих списков.
На скриншоте это три выпадающих списка — Size (btn-sm, btn-lg), Style (btn-primary, btn-secondary) и Color (light, dark).
В общем хотелось бы иметь настройку, позволяющую создавать выпадающие списки, которые настраиваются через admin интерфейс сайта.
Создание плагина конфигурации
Плагин конфигурации — то есть описание элементов формы — задаётся как расширение класса CKEditor5PluginDefault. Его нужно разместить в /src/Plugin/CKEditor5Plugin/.
Для моего случая я написал C5BB класс (файл из модуля c5bb v 1.0.5) C5BB.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
<?php namespace Drupal\c5bb\Plugin\CKEditor5Plugin; use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableInterface; use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableTrait; use Drupal\ckeditor5\Plugin\CKEditor5PluginDefault; use Drupal\ckeditor5\Plugin\CKEditor5PluginElementsSubsetInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\editor\EditorInterface; /** * CKEditor 5 C5BB plugin configuration. * * @internal * Plugin classes are internal. */ class C5BB extends CKEditor5PluginDefault implements CKEditor5PluginConfigurableInterface, CKEditor5PluginElementsSubsetInterface { use CKEditor5PluginConfigurableTrait; const T_CONTEXT = ['context' => 'C5BB module']; /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form['classes'] = [ '#type' => 'textarea', '#title' => $this->t('Class Selectors', [], self::T_CONTEXT), '#description' => $this->t('Configuration of class options', [], self::T_CONTEXT), '#default_value' => $this->configuration['classes'] ?? '', '#rows' => 10, ]; $form['showIconSettings'] = [ '#type' => 'checkbox', '#title' => $this->t('Show Icon Setttings', [], self::T_CONTEXT), '#description' => $this->t('Enbales Glyph and FontAwesome icons', [], self::T_CONTEXT), '#default_value' => $this->configuration['showIconSettings'], ]; return $form; } /** * {@inheritdoc} */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { ; } /** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['classes'] = $form_state->getValue('classes'); $this->configuration['showIconSettings'] = $form_state->getValue('showIconSettings'); } /** * {@inheritdoc} */ public function defaultConfiguration() { return [ 'classes' => <<<__classes__ Size - Small|btn-sm - Normal| - Large|btn-lg Style - Primary|btn-primary - Secondary|btn-secondary Color - Light| - Dark|dark __classes__, 'showIconSettings' => 1, ]; } /** * {@inheritdoc} */ public function getElementsSubset(): array { return ['<a>', '<a class target href>', '<em>', '<em class>', '<span>', '<span class>']; } /** * {@inheritdoc} */ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { // Build selector's config. $classes = explode(PHP_EOL, $this->configuration['classes']); $selectors = []; foreach ($classes as $line) { $line = trim($line); if (empty($line)) { continue; } if ($line[0] != '-') { $selectors[] = [ 'label' => $this->t($line, [], self::T_CONTEXT), 'options' => [], ]; } else { $line = explode('|', $line); $optionLabel = trim(substr($line[0], 1)); $optionValue = trim($line[1] ?? ''); $index = count($selectors) - 1; $selectors[$index]['options'][] = [ 'value' => $optionValue, 'label' => $this->t($optionLabel, [], self::T_CONTEXT), ]; } } return [ 'c5bb' => $this->configuration + ['selectors' => $selectors], ]; } } |
В buildConfigurationForm нужно, используя Form API, объявить требуемые поля. Текущие значения берутся из актуальной конфигурации — $this->configuration.
Как и для обычной формы, вы можете реализовать валидацию и отправку данных — через реализацию методов validateConfigurationForm и submitConfigurationForm интерфейса PluginFormInterface.
В моём случае это просто запись данных формы в конфигурацию:
1 2 3 4 |
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['classes'] = $form_state->getValue('classes'); $this->configuration['showIconSettings'] = $form_state->getValue('showIconSettings'); } |
Частью валидации также является функция getElementsSubset, которая должна передать набор описаний тегов, с которыми работает ваш плагин. Логика описания такая же как при задании секции elements файла *.ckeditor5.yml.
Конфигурация будет передана в ваш js плагин в том виде, как вы это сделаете в методе getDynamicPluginConfig. Обычно это просто передача массива конфигурации:
1 2 3 4 5 6 7 8 9 |
/** * {@inheritdoc} */ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { return [ 'config_name' => $this->configuration, ]; } |
Создание схемы конфигурации
Кроме формы, вам нужно объявить схему данных вашей конфигурации, т.к. вообще она может не соответствовать структуре данных в вашей форме.
Задаётся она в виде описания схемы в /config/schema
Файл c5bb.schema.yml (c5bb модуль м 1.0.5):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Plugin \Drupal\c5bb\Plugin\CKEditor5Plugin\C5BB ckeditor5.plugin.c5bb_bbutton: type: mapping label: 'C5BB settings' mapping: classes: type: string label: 'Classes Definitions' showIconSettings: type: integer label: 'Show Icon Settings' |
У меня схема полностью соответствует форме — т.е. я описал те же два поля — текст и чекбокс.
Обратите внимание на то, как формируется название секции: c5bb_bbutton. Первая часть — название модуля, вторая — название js плагина.
Добавление ссылки на класс в *.ckeditor5.yml.
Созданный ранее класс C5BB нужно «зарегистрировать» в описателе ckeditor5 плагина. Он указывается как свойство «class» в секции drupal.
Файл c5bb.ckedtior5.yml (c5bb модуль м 1.0.5):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
c5bb_bbutton: ckeditor5: plugins: - bbutton.BButton drupal: label: Bootstrap Buttons # Drupal library with the plugin JS. library: c5bb/buttons admin_library: c5bb/admin.styles <strong> class: Drupal\c5bb\Plugin\CKEditor5Plugin\C5BB</strong> # Toolbar button. toolbar_items: BButton: label: Bootstrap Buttons elements: - <a> - <a class href target> - <em class> - <span class> |
Получение данных конфигурации на стороне js плагина
После всех настроек, нужно как то получить передаваемые данные уже в экосистеме CKEditor5 API.
Они становятся частью общей конфигурации редактора, а так как ваш плагин расширяет класс Plugin, то внутри плагина получить настройки можно так:
1 |
const textFormatSettings = this.editor.config.get('config_name'); |