Drupal 8 has greatly improved editor experience out-of-the-box. It comes shipped with CKEditor for WYSIWYG editing. Although, D8 ships with a custom build of CKEditor and it may not have the plugins that you would like to have or that your client wants to have. I will show you how to add new plugins into the CKEditor that comes with Drupal 8.
Adding plugins with a button
First, create a bare-bones custom module called editor_experience
. Files will be added here that will tell Drupal that there is a new CKEditor plugin. Find a plugin to actually install... for the first example I will use bootstrap buttons ckeditor plugin. Place the downloaded plugin inside libraries
directory at the root of the Drupal installation; or use a make file to place it there. Also make sure you have the libraries module installed drupal module:download libraries
.
Create a file inside of the editor_experience
module inside of src/Plugin/CKEditorPlugin
called BtButton.php
. Add the name space and the two use
statements shown below.
<?php
/**
* @file
* Definition of \Drupal\editor_experience\Plugin\CKEditorPlugin\BtButton.
*/
namespace Drupal\editor_experience\Plugin\CKEditorPlugin;
use Drupal\ckeditor\CKEditorPluginBase;
use Drupal\editor\Entity\Editor;
/**
* Defines the "Bootstrap Buttons" plugin.
*
* @CKEditorPlugin(
* id = "btbutton",
* label = @Translation("Bootstrap Buttons")
* )
*/
class BtButton extends CKEditorPluginBase {
... // Methods will go here
}
The annotation @CKEditorPlugin
tells Drupal there is a plugin for CKEditor to load. For the id, use the name of the plugin as defined in the plugin.js file that came with the btbutton download. Now we add several methods to our BtButton
class.
First method will return false since it is not part of the internal CKEditor build.
<?php
/**
* Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::isInternal().
*/
public function isInternal() {
return FALSE;
}
Next method will get the plugin's javascript file.
<?php
/**
* Implements \Drupal\ckeditor\Plugin\CKEditorPluginInterface::getFile().
*/
public function getFile() {
return libraries_get_path('btbutton') . '/plugin.js';
}
Let Drupal know where your button is. Be sure that the key is set to the name of the plugin. In this case btbutton
.
<?php
/**
* Implements \Drupal\ckeditor\Plugin\CKEditorPluginButtonsInterface::getButtons().
*/
public function getButtons() {
return [
'btbutton' => [
'label' => t('Bootstrap Buttons'),
'image' => libraries_get_path('btbutton') . '/icons/btbutton.png'
]
];
}
Also implement getConfig()
and return an empty array since this plugin has no configurations.
Then go to admin/config/content/formats/manage/basic_html
or whatever format you have that uses the CKEditor and pull the Bootstrap button icon down into the toolbar.
Now the button is available for use on the CKEditor!
Adding plugins without a button (CKEditor font)
Some plugins do not come with a button png that allows users to drag the tool into the configuration, so what then?
In order to get a plugin into Drupal that does not have a button, the implementation of getButtons()
is a little different. For example to add the Font/Font size dropdowns use image_alternative
like below:
<?php
/**
* Implements \Drupal\ckeditor\Plugin\CKEditorPluginButtonsInterface::getButtons().
*/
public function getButtons() {
return [
'Font' => [
'label' => t('Font'),
'image_alternative' => [
'#type' => 'inline_template',
'#template' => '<a href="#" role="button" aria-label="{{ font }}"><span class="ckeditor-button-dropdown">{{ font }}<span class="ckeditor-button-arrow"></span></span></a>',
'#context' => [
'font' => t('Font'),
],
],
],
'FontSize' => [
'label' => t('Font Size'),
'image_alternative' => [
'#type' => 'inline_template',
'#template' => '<a href="#" role="button" aria-label="{{ font }}"><span class="ckeditor-button-dropdown">{{ font }}<span class="ckeditor-button-arrow"></span></span></a>',
'#context' => [
'font' => t('Font Size'),
],
],
],
];
}
Then pull in the dropdown the same way the Bootstrap button plugin was added! Have any questions? Comment below or tweet us @activelamp.