by David Snopek on May 17, 2019 - 8:49am

In my experience, a big part of making a Drupal 8 site usable for content editors is customizing the WYSIWYG, which usually includes adding a couple additional CKEditor plugins.

Of course, you can simply download the plugins into the 'libraries' folder, and that's fine. But these days, it's becoming best practice to pull in all of your site's dependencies using Composer.

Adding 'package' repositories to your composer.json for the CKEditor plugins (the current best practice) works fine - but only for your individual site.

It doesn't work so well if you want to install:

  • A Drupal "Feature" (like with the Features module) that configures the WYSIWYG, including adding some CKEditor plugins, or
  • A Drupal distribution (like Panopoly or Lightning)

In those cases, you can't depend on what the individual site may have in its top-level composer.json, and asking the user to manually copy-paste a bunch of 'package' repositories in there may create enough confusion or problems that potential users will just give up.

Well, I've got an possible solution to this problem: an experimental Composer repository which includes CKEditor plugins for use on a Drupal site.

It works better for Feature modules and distributions, but can also make life easier for individual sites too.

Read more to find out how it works and how to use it!

A use case: Panopoly WYSIWYG

This all started with porting the Panopoly WYSIWYG (panopoly_wysiwyg) feature module to Drupal 8...

Panopoly WYSIWYG provides a highly usable (and re-usable!) WYSIWYG configuration, originally based on Wordpress's WYSIWYG. It's part of the Panopoly distribution, but can be used on vanilla Drupal sites, or in other distributions.

In order to work, it needs a number of CKEditor plugins. In the old world order, we used Drush .make files to pull in any necessary plugins, and this is how it still works for Drupal 7. However, with Drupal 8, this needs to be done via Composer.

We could put a requirement into panopoly_wysiwyg's composer.json, like:

    "require": {
        "drupal-ckeditor-plugin/colorbutton": "4.*"
    }

However, unless the user first added the necessary 'package' repository to their top-level composer.json, the installation will fail, because there isn't any package on Packagist called 'drupal-ckeditor-plugin/colorbutton'.

Adding those 'package' repositories would work, but it poses a number of problems...

What's wrong with 'package' repositories?

For an individual site - nothing!

But there's a few issues for a reusable module:

  1. 'package' repository definitions are long and contain a lot of stuff. This may sound like a minor thing, but if you're asking your users to copy-paste something into their composer.json, the smaller and simpler the content can be, the harder it'll be to mess it up and lead to bad experiences and support requests. Panopoly WYSIWYG uses 6 plugins, and all the necessary 'package' repositories definitions amount to like 2 pages of text. :-)
  2. Different people may do them differently, either on purpose or accident. Since this would need to be defined in each and every site's composer.json, it can be made different. Maybe one site owner decides to pull in a different version of a plugin, or name it differently, or give it a different 'type' (to control where it goes in the code base). This creates inconsistency, which can, again, lead to bad experiences and support requests.
  3. We can't change them over time. If we find out that there was a better way to do the definition, well, then we have to tell everyone to go update their composer.json files in a specific way. Most people probably won't get the message, and it's another error prone step where the site owner could make a mistake.
  4. We can't add to them over time. Panopoly WYSIWYG currently uses 6 plugins - what if we want to add another? Well, 'composer update' will fail until the user adds the new 'package' repository to their composer.json.
  5. The plugin versions need to match the CKEditor version in Drupal core. Drupal core frequently updates the version of CKEditor in minor releases. For example, Drupal 8.6 uses CKEditor 4.10.1 and Drupal 8.7 uses CKeditor 4.11.3. If you're using a "core" CKEditor plugin (one that's bundled in the CKEditor source code) you should use the same version of the plugin as CKEditor. This means you need to update the versions in your 'package' repositories when updating to a new Drupal core minor, and creates challenges for a package like panopoly_wysiwyg that aims to work with either version.

So, in the context of a reusable feature or distribution, this is definitely not ideal.

Solving these problems with a Composer repository

A Composer repository is basically a remote collection of package definitions.

Packagist.org is the main Composer repository where package definitions are pulled from by default, but it's also possible to use additional repositories. For example, Drupal.org provides a Composer repository that includes all Drupal modules, themes, etc from Drupal.org.

Pointing your composer.json to an additional Composer repository, involves either (a) adding about 4 lines to your composer.json, or (b) running a single 'composer config' command.

It's easy to explain, simple to do, and hard to get wrong.

Also, since the the actual data is stored remotely, that means:

  1. Lots of people can share this same repository
  2. We can update it over time, adding or removing CKEditor plugins, or changing how they are defined
  3. We can add multiple versions of the same plugin with different requirements, for example, declaring which version of Drupal core they work with.

Introducing the drupal-ckeditor-plugins Composer repository!

So, we created an experimental Composer repository with package definitions for CKEditor plugins, which is hosted on GitLab pages here:

https://panopoly.gitlab.io/drupal-ckeditor-plugins/

This is generated using satis, based on some simple configuration files stored in this GitLab repository:

https://gitlab.com/panopoly/drupal-ckeditor-plugins

Using GitLab CI, any time we commit a change to that repo, it'll regenerate the Composer repository. So, if you want to see any CKEditor plugins added or contribute to this project, please submit an MR to that project. :-)

TL;DR - How to use it with my site?

So, while the idea for this came from wanting a better solution for Feature modules or distributions, it can also be used on an individual site to install CKEditor plugins, and it is easier than the old recommended way.

To add the repository, run this command:

composer config repositories.drupal-ckeditor-plugins composer https://panopoly.gitlab.io/drupal-ckeditor-plugins

And to install a CKEditor plugin - for example, the 'colorbutton' plugin - run this command:

composer require drupal-ckeditor-plugin/colorbutton:4.*

This will put the right plugin version for your version of Drupal core into your 'libraries' folder, and you didn't have to manually edit your composer.json at all.

And, if you update your Drupal core version, composer will know that you also need to update your CKEditor plugins to match.

TL;DR - How to use it with my feature or distribution?

To use with a Feature module or distribution, you need to do only two things:

  1. Add a requirement on a CKEditor plugin from the repository, like "drupal-ckeditor-plugin/colorbutton" (for the 'colorbutton' plugin, for example)
  2. Tell your users to run this command before installing your module or distribution:

composer config repositories.drupal-ckeditor-plugins composer https://panopoly.gitlab.io/drupal-ckeditor-plugins

Optionally, if you provide a Composer project template for starting new sites (like the panopoly-composer-template), you can add the repository to that composer.json, so that new users don't need to follow any steps at all!

Wait - why is this "experimental"?

Every time I've referred to this Composer repository above, I've called it "experimental".

This is because, while this seems to work, we haven't really used it in practice yet. After spending some weeks or months using this with real modules and sites, we may find out that there was a better solution.

So, while I really encourage you to try it out, please know that this is the early stages, and doesn't (yet) change any of the best practices.

However, I will say that I don't ever intend to take this down.

It's hosted on GitLab Pages, so as long as GitLab.com continues to exist, this Composer repository will also exist. So, if you start to depend on it, it isn't going to go away.

But, just a warning: at some point, it could become deprecated if a better solution to these problems is found.

Please let me know your thoughts in the comments below or in issues/MRs for the project on GitLab!

Want to read more articles like this?

myDropWizard.com blog Subscribe to the myDropWizard.com blog and recieve e-mail updates when new articles are published!

Add comment

o