The Drop Times: Join Us for the Drupal Global Contribution Weekend 2024
Four Kitchens: Tips for upgrading to CKEditor5
January 1, 1970
At Four Kitchens we keep several lists of “Hot Topics” to share our learnings across the dozens of sites that we care for. Are you upgrading a Drupal site to CKEditor5? We’ve tidied up one of these internal wiki documents into this set of general upgrade guidelines that might pertain to your website.
Rough steps to upgrade
The level of effort needed for this upgrade will be different for each site. It may take some time to figure out. CKEditor 5 is available in Drupal 9.5 and beyond. You can try switching/upgrading on a local site or multidev and assess the situation.
First, create a list of CKEditor enhancement modules on the site and check if they are Drupal 10 ready (the reports from Upgrade Status and this Drupal.org page may help). Common modules to look for include Linkit, Anchor Link, Advanced Link, IMCE, Entity Embed, Video Embed Field, Footnotes, and anything with the word “editor” in the title.
As a best practice, you should test both the creation of new content, and editing existing content in several places. This will help make sure that some lesser used HTML isn’t treated differently in the new CKEditor. Run visual regression tests (if available).
You may need to point out key interface changes to your clients or stakeholders (e.g., contextual windows for links/media/tables instead of modals, etc.). While it is a bit of a change, it’s overall an improved user experience, especially for new people who are coming in cold.
Anchor links
Anchor link gives editors the ability to create links to different sections within a page.
For “better integration with Drupal 10, CKEditor 5, and LinkIt” there is a 3.0.0@alpha version. If your project isn’t using wikimedia/composer-merge-plugin, you must require northernco/ckeditor5-anchor-drupal package and add the following to the repositories section of composer.json:
{ "type": "package", "package": { "name": "northernco/ckeditor5-anchor-drupal", "version": "0.3.0", "type": "drupal-library", "dist": { "url": "https://registry.npmjs.org/@northernco/ckeditor5-anchor-drupal/-/ckeditor5-anchor-drupal-0.3.0.tgz", "type": "tar" } } }Embedded media
Depending on the age of your site, it might be using one of several techniques to embed media into the WYSIWYG:
- Entity embed
- Video embed field
- The embedding functionality built into more recent versions of Drupal Core
If your site is using the video_embed_field module (most sites are probably using Drupal core’s media module), there is a patch that adds support for CKE5. Insert Image works slightly different (though this is probably not the case if your site uses core’s media module). It’s worth considering if there is a way to enhance this for user experience, if necessary.
If your site uses custom Entity Embed for media, consider switching to the core media library. It may provide a better administrative user experience in some cases.
The insert image button in CKEditor functions a little differently than it used to. Rather than bringing up a modal with fields to upload an image like the image below:
It now immediately pulls up your computer’s file system for you to search for images like so:
After adding your image, the alt tag box prompts you underneath the image:
After submitting your alt tag, you can adjust alignment and sizing:
Moving general styles to link styles
It was common in CKEditor4 to use its “Styles” feature to provide a way to add variations of links (to make them look like buttons, or to add icons).
There are a few UX problems with that approach. Either the styles are set to apply on <span>
, which means that they can be applied to non-links, or the styles are set to apply on <a>
, which means that they are mysteriously grayed out most of the time (until you select a link). Either way, it’s not intuitive how to apply a link style. In CKEditor5, we can switch to using the Link Styles module.
Change in Styles dropdown behavior
In CKEditor4, when integrated with Drupal, the Styles dropdown only allowed applying one style to an element (e.g., “external link”). If you tried to apply a different style, such as “locked link,” the previous style would be removed.
The Drupal implementation of CKEditor5 allows for multiple styles to be applied to elements via the Styles dropdown. This change may be unexpected for some, and could result in elements that look broken, such as when a link has both the “external link” and “locked link” styles.
CKEditor5 introduced a new API for adding theme-specific styles. The new architecture might cause the CKEditor5 theme to bleed into the admin theme. To know how to deal with these issues, review new API for adding theme-specific styles in CKEditor5.
You’ll likely run into an issue with styles bleeding outside of the editor, so see the other section within this page.
Cut and paste
Paste-from-Word, paste-from-Google-Docs, etc. is now built-in to CKEditor5. (At least for 90% of use cases.) There’s a paid plugin for more esoteric needs.
There is no paste-as-plain-text plugin for CKEditor5. You can use Ctrl-Shift-V (or Cmd-Shift-V) to paste as plain text. If you want to get rid of all formatting (including bold, links, etc.) in existing text, you can highlight the text, use Ctrl-C to copy, then Ctrl-Shift-V to paste it back as plain text.
Behat
Many of our Behat automated test broke after the update because there were multiple structural changes, so this is how we solved it: First, here is the doc about how to get the editor instance in case you want to know more about it. This is how we rewrite our custom step to fill out the CKEditor during testing. (We found the code in an article post-post).
/** * A step to help fill in a ckeditor wysiwyg. * * @param string $locator * The css locator of the field that ckeditor has taken over. * @param string $value * The html value you wish to fill in to ckeditor. * * @Then I fill in wysiwyg on field :locator with :value */ public function iFillInWysiwygOnFieldWith($locator, $value) { // https://ckeditor.com/docs/ckeditor5/latest/support/faq.html#how-to-get-the-editor-instance-object-from-the-dom-element $ckeditor5_drupal_editable_element = "div.form-item-$locator .ck-editor__editable"; $this->getSession() ->executeScript( " var domEditableElement = document.querySelector(\"$ckeditor5_drupal_editable_element\"); if (domEditableElement.ckeditorInstance) { const editorInstance = domEditableElement.ckeditorInstance; if (editorInstance) { editorInstance.setData(\"$value\"); } else { throw new Exception('Could not get the editor instance!'); } } else { throw new Exception('Could not find the element!'); } " ); }and the mink step for regular field:
And I fill in wysiwyg on field "field-summary-0-value" with "Some Teaser Text"
And for a field inside a paragraph:
And I fill in wysiwyg on field "field-sidebar-content-0-subform-field-simple-text-0-value" with "Behat Side Nav Body Text"
Preventing custom styles from bleeding into admin theme with CKEditor5
See the new API documentation about implementing theme styles in the new way. This may require some adjustments on your end.
One of the major changes with CKEditor5 is that it pulls WYSIWYG styles onto the whole page when there is a WYSIWYG on the page. In CKEditor4, styles were only pulled into the CKEditor iframe. This can be extremely frustrating when the admin theme looks odd or different on pages that contain a WYSIWYG.
Limit the number of stylesheets being pulled into the WYSWIYG. (First, note that this method has only been confirmed to work on newer versions of Sous using specific webpack settings. If you are having problems with it, make sure your webpack settings allow for multiple manifests to be generated. You may need to refer to a newer site to see how it is configured.)
The first step is to create a new stylesheet (a manifest) called wysiwyg.scss
in the same directory as your styles.scss
file, which assembles all the stylesheets used in your theme. For this stylesheet, we’ll only want to include the stylesheets that our WYSIWYG needs. For example, I have one that looks like this:
In this example, we are pulling in a couple needed files from node_modules (normalize and breakpoint), and then any .scss
files from base, and then select files from atoms (links, text, lists, tables, and images).
Compile and make sure that it has created the new files at /dist/css/wysiwyg.css
. If you get any errors, you may need to include another file that has a variable you need, or something along those lines.
1.) Update your .info file In your theme’s .info
file, set CKEditor5 to use your new stylesheet:
2.) Review the WYSIWYG. Visit a page with a WYSIWYG on the page, and verify that the limited styles are loading properly within the WYSIWYG. Try all the dropdowns and buttons that are included in the WYSIWYG settings. If anything appears unthemed, review your styles to see if there’s a stylesheet missing from your manifest.
3.) Review the rest of the page. Now review the page around the WYSIWYG and note how if differs from other pages that do not have a WYSIWYG. Common differences to look for are: heading styles, text styles, buttons — basically anything that you included in your manifest.
4.) Limit styles
- Find the page’s body class for node edit pages (in our test case,
.gin--edit-form
). It may depend on your admin theme. - Find the wrapper class for the WYSIWYG. Most likely the best choice is
.ck-content
. Our approach will be to hide styles from.gin--edit-form
, but then add them to.ck-content
.
For example:
body { background-color: clr(background); color: clr(text); @include body-copy; }becomes:
body:not(.gin--edit-form), .ck-content { background-color: clr(background); color: clr(text); @include body-copy; }And for buttons:
.main .button { @include button-base; @include button-color-primary; @include button-medium; }it becomes:
body:not(.gin--edit-form) .button, .main .button, .ck-content a.button { @include button-base; @include button-color-primary; @include button-medium; }With any luck, the styles used apply mixin
s, which makes it easy to filter out where to apply the styles. In some cases, the overriding of styles may become hard because of the order in which the stylesheets are loaded. Try to avoid !important
s and instead use things like an additional element or class to firm up your override.
One issue that may come up is your overrides here end up overriding things in your custom theme, depending on how they are defined. In this case, don’t wrap the styles in the body classes, but rather undo the custom theme’s style on the admin page items manually. Luckily, since we’re narrowly applying custom styles, only things used in the WYSIWYG will need to be addressed.
For instance:
// Apply general link styles to all links. a { @include link; } // Overrides for Admin pages containing CKEditor (you will need a body class only on admin pages). .user-logged-in { a { background-image: none; transition: none; } .horizontal-tabs-list a, .toolbar a { font-weight: normal; } } // Reapply link styles to links within the WYSIWYG .ck-editor a { @include link; }Continue to review your page and adjust it until it no longer differs from other admin pages.
Editor explodes out of its container in deeper paragraphs
This issue seems to occur only with rich text fields within a paragraph. It might be limited to the Gin theme.
This issue might be because of the container’s width. If input fields inside the container have a specified size exceeding the screen width, it can lead the editor to inherit the container’s width, extending beyond the screen. You can see this as a Drupal Core/CKEditor5 bug in Drupal.org: CKEditor5 toolbar items of multivalue field (typically Paragraphs) overflowing on narrow viewports and overlapping with node form’s sidebar on wide viewports.
To resolve this quickly, set the input fields to 100% width, making sure everything works seamlessly. Be sure to include this in a stylesheet of your admin theme.
.node-form input[size] { width: 100%; }We can also modify the ‘flex-wrap’ property of the CKEditor buttons to make sure they stay within the container’s width:
.ck-editor .ck.ck-toolbar.ck-toolbar_grouping > .ck-toolbar__items { flex-wrap: wrap; }Additional resources
- Five Can’t Miss Articles on CKEditor 5 in Drupal
- Upgrading to CKEditor5
- Upgrading my site from CKEditor4 to CKEditor5
- How to upgrade from CKEditor4 to CKEditor5
The post Tips for upgrading to CKEditor5 appeared first on Four Kitchens.
ComputerMinds.co.uk: Aegir 3 and Drupal 10: eeek!
Aegir is a hosting system built in Drupal, for Drupal.
It lets you easily create new Drupal sites and create databases, filesystems, virtual hosts etc. for the sites. You can manage hundreds or thousands of sites using a simple Drupal based UI. As simple as you would manage a list of 100 blog posts, you can manage 100 Drupal websites.
Currently the latest released version of Aegir is: Aegir 3.
Aegir 3 relies on Drush 8, which means it can work with: Drupal 7; Drupal 8 and Drupal 9. But not Drupal 10. Oh.
I have need for it to work with Drupal 10. Specifically we have a large collection of Drupal sites, that currently Drupal 9, but ready and waiting to jump to Drupal 10. Yes, we've left it too late, we should have done this a long time ago, but we are where we are.
I've spent the day looking into various options, they are roughly:
- Move to BOA
- Get Aegir 3 to work with Drupal 10
- Move to Aegir 4
- Move to Aegir 5
- Move to something else
My terms of reference
I'm looking for a solution that changes as little as possible in the current stack. We've got a big, beefy server, and lots and lots of Drupal sites on it. The Drupal sites themselves run fine and we're after the management of them really. We don't need to scale out particularly, and if we do, we've got options on the hardware side vertically. We also don't need some fancy multi-datacenter approach, and ideally keep with our Nginx, Varnish and Apache sandwich.
I do want to manage things in the old school way, but I need a few, select, non-technical users to be able to manage the sites in a friendly UI like Aegir's hosting system.
Lots of the new hotness out there are essentially orchestrating Kubernetes, and that's great, but I don't actually want 100 containers all running PHP which is how I understand all of these systems would essentially function.
I used to be an Aegir maintainer, and I have a deep knowledge of how Aegir works and even helped write some of the inter-process communications stuff in Drush 8.
Move to BOA
The first option is one that has shown to be working, and requires a custom fork of Drush 8, some core patches and using BOA. BOA is quite an aggressive fork of Aegir, and I'm not sure I want all the changes and whatnot that comes with it. I think I have to discount it, because the last time I looked there would simply be too much change on the nginx side of things at least, and it was doing all kinds of things I don't simply understand and thus won't be able to reason about.
The main inspiration I take from BOA is that they've got it working! Well, they've got something working. It looks like they've essentially forked Drush 8, applied some Drupal core and Aegir patches. This makes it so that Aegir can still use it's aliases, code and talk to Drupal 10 sites. How they've been able to do this is very impressive indeed. I feel like it's just a matter of time before it breaks though, surely Drupal 10 is going to change something in it's lifecycle and cause issues. I don't quite see how this can work with Drush commands in contrib modules. For example, during deployments on our sites we revert features, but that's a features module provided Drush command, which won't be callable from Drush 8 in Drupal 10.
Get Aegir 3 to work with Drupal 10
This I feel is the least effort option. Find some way to get standard Aegir 3 to communicate with Drupal 10. Now, Drush 8 can't directly bootstrap a Drupal 10 site. Aegir 3 uses Drush 8 to be both the backend storage for all the data about the sites to host, and to bootstrap the sites it manages.
This worked really well in the Drupal 5/6/7 days, and just about coped with Drupal 8/9, but hasn't for Drupal 10. Think of it this way, what if instead of hosting a Drupal site, it was a Wordpress site? Aegir simply wouldn't be able to neatly bootstrap into a Drupal site and do it's stuff. It's the same with Drupal 10.
How much stuff does it really do though? I'm not 100% sure. I know that it gets the currently installed packages for example, but what else does it do. It looks to me like it often hands off a Drush subprocess do the heavy lifting. Maybe we can hand off to another subprocess, one that runs a site-local Drush 12+ instance, passing in all the options it needs to bootstrap and run the actual commands on the site.
Please, if this is a completely crazy way to go, someone please comment and let me know!
Move to Aegir 4
So there is a 4.x branch of Aegir, and apparently it can work with Drupal 10 sites. It does this by replicating the aliases to YAML files and then running a global Drush 11, which can then bootstrap the Drupal sites. Apparently it also has replaced some of the Drush invocations with standard process invocations. I guess it had to do this because the Drush to Drush process communication stuff was in Drush 8 and got removed.
It seems like Aegir 4 also brought in a lot of other changes too, and that's not particularly something I want or need. Also, it's never been officially released/tested by the community etc.
Move to Aegir 5
This got announced in a few blog posts a while back, and I've not heard anything since. It's possible that it's there and ready to go, but as far as I understand it, it's a whole change to how the sites would be managed and hosted, and while an import from Aegir 3 is on the roadmap, it seems like it would import the sites into something completely different, not some simple vhosts and a DB server.
Also, even if it does exist, it'll have had minimal testing and eyes on it.
Move to something else
I think this is my preferred long-term option. These sites don't really need Drupal. They could actually be static sites plugged into a central content repository. That would drastically simplify lots and lots of things. Or we keep the Drupal sites, but move them to Kubernetes and using something like Amazee's Lagoon to host them etc. This would be very cool, but probably quite expensive in terms of having enough resources to host all the containers.
One for the long term future I think.
Get Aegir 3 to work with Drupal 10
I might give this a go in that I think what I can do is this:
- Get Aegir running normally.
- Install a Drupal 9 site.
- Get a single Aegir task running that doesn't bootstrap the Drupal 9 site with Drush 8. I'm thinking something like getting the one-time login link. This has data flowing in both directions, and I think, Drush 8 trying to bootstrap Drupal to the run the provision command. Getting this working would involve calling a site local Drush based on the data from the alias, but not actually using the alias.
- If that works, put something into settings.php that throws an exception if Drush 8 is detected, and then try to get everything else working for my use-cases.
- Then try and set up a Drupal 10 site.
I'd love to know your thoughts on this. Do you have an old Aegir running sites, and you don't know what to do with it? Or do you think I'm crazy and want to offer me a better way to go, use the comments below, please!
Updates/notes
So looking at the provision commands, the actual provision command to say, get the one-time login link bootstraps the Drupal site. So that would need to change that command so that it no-longer bootstrapped Drupal at all, but instead changed to be a pure Drush command. Then it could load the data from the alias etc.
I'm tempted to go ahead and get a dev instance of Aegir running and the add a new Drush command, that doesn't bootstrap Drupal, but does attempt to grab data from an alias and see what I can do. That possibly an even simpler proof of concept, as it's an entirely new Drush command, but one I then know could be called by provision's task runner instead of the current one.
Acquia Developer Portal Blog: Drupal Cache Strategy with Varnish and Edge CDN on Acquia
The requirement is to cache content for as long as possible, but update promptly when content changes are made in Drupal.
Note that in this setup I’m using Acquia Edge powered by Cloudflare, but the strategy would be similar for Acquia Edge powered by Akamai.
The objective is to bootstrap Drupal as infrequently as possible, by relying on the Varnish and CDN layers, but always to serve fresh content: Cache pages in Varnish for a long time, but provide a method (Purge) to invalidate Varnish when a content change is made in Drupal. At the CDN layer, the goal is to make sure the current version of a page is delivered to the browser, by checking Varnish frequently to see if a new version is available. This check is a lightweight call to Varnish. If Varnish does not have a new version, the CDN-cached version is delivered.
Drupal Modules:
Acquia Developer Portal Blog: Cache Strategy Considerations for Drupal Backend with Node.js Frontend
An increasingly common setup is to use Drupal as the CMS / backend of an application with a frontend Node.js application: Drupal holds the content and manages certain things like search indexing and integration with certain third-party tools (DAM, for example), and the Node application creates the presentation layer. An assumption in this post is that the Node.js application is making JSON:API requests to the Drupal application via the Drupal core JSON:API module’s functionality.
With this setup, it’s critically important to plan a cache strategy, to avoid making excessive requests to the backend and potentially sacrificing performance. Here are some considerations.
Objective: For the best results in terms of performance and utilization, both the Drupal backend and the Node.js frontend should have a cache strategy in place.
Golems GABB: Innovative Approaches to Creating Slideshows Using Drupal Views
We all know such an effective and common way of demonstrating content as a slideshow. Similarly, visual content was shown even before the invention of computers on ancient mechanical devices that used slides. This is where the name comes from.
But, sometimes, a simple carousel of pictures is boring. Today, the Drupal web development agency tells you how to add slideshows using Drupal views effectively and creatively.
ImageX: Libraries Going Digital: A Guide Through Useful Features For Library Websites, and How Drupal Fits In
Authored by: Nadiia Nykolaichuk.
Libraries are known as one of the most traditional ways of helping people get valuable knowledge. Most people imagine a library as a quiet building with long shelves, filled with the scent of well-worn books and the quiet rustle of turning pages. It’s a true intellectual haven, and librarians are its guardians.
Drupal Association blog: Credit for Events Sponsored and Reducing Redundancy in Contribution Credit
Drupal's contribution recognition system is a key part of the way we recognize and incentivize contribution in the Drupal project. It's a system that needs constant care and feeding, both to ensure that we're recognizing the many kinds of contributions people and organizations are making, and to ensure that the system itself is proportional and fair for the effort being put in.
Event Sponsorship credit
We're about to introduce a new way for organizations to improve their marketplace rank. Drupal.org/community/events has allowed organizers to feature their sponsors since the beginning. Now, those sponsors listed will automatically receive contribution credit as well. To start, this will be a fixed amount for small events and a larger one for DrupalCon, but in the future, in collaboration with event organizers, we'd like it to scale to each sponsor's level of support.
We hope this will encourage companies to do the important work of financially supporting the grass roots events that help our community thrive. (And reward those who already do!).
Reducing redundancy
We're also making a small tweak to the system this week related to how we recognize Contributor Roles. Contributor Roles are community submitted, and represent all of the many ways contribution happens in our community. However, we want to avoid double counting credit for certain types of roles. For example, issue credit is a fundamental pillar of our contribution recognition system, and some of our community roles such as 'Project Contributor' are also organically receiving credit from issues.
We will no longer be granting marketplace rank to organizations sponsoring roles that are already represented in other ways, and we'll update the contributor role descriptions to reflect when this restriction applies.
We expect this change to help level the playing field between some organizations who've made extensive use of the role system, and others who have kept a laser focus on contribution and innovation directly in issues.
LN Webworks: Drupal For Web Development: Why It’s a Great Choice
Drupal is a cutting-edge open-source content management system that has won global acclaim as a web development tool. Every Drupal development company across the globe and business organization relying on Drupal proclaims that the CMS is unmatchable in terms of web development. If you have also heard a lot about the magic of Drupal and wonder what makes it so phenomenal, this blog is for you. It elucidates 4 reasons why Drupal is a worthwhile investment for web development.