Problem/Motivation

Webform is currently using customized CKEditor 4, included with Drupal 8 and 9. Drupal 10 ships with CKEditor 5.

Proposed resolution

Replace Webform's custom CKEditor with hidden default 'webform' only text format/editor.

The Webform module provided a custom instance of the CKEditor, which added additional dependencies and maintenance challenges. The Webform module now provides a default hidden 'webform_default' text format that leverages Drupal core's editor and CKEditor modules.

The new default 'webform_default' text format is completely hidden from all instances of the text format element and the admin UI. The approach allows the new default 'webform_default' text format to be backward compatible and fully maintained by the Webform module.

Steps to review

  • Install webform 6.2.x
  • Confirm that old default ckeditor is working as expected. /admin/structure/webform/config
  • Apply patch
  • Run database updates
  • Confirm that the webform text format and editor is installed via config export
  • Confirm that new ckeditor is working as expected. /admin/structure/webform/config
  • Confirm that the element and mail format are set to webform. /admin/structure/webform/config/elements
  • Confirm that existing HTML with BR tags is converted to P tags and wrapped P tags
  • Confirm that custom HTML attributes are supported
  • Reinstall with a patch applied and confirm webform text format is installed
  • Confirm that the default webform text format is hidden and not configurable.

Version installation and upgrade manual tests

Install Webform 6.2.x and Drupal 9.4 with CKEditor patch.

  • Confirm CKEditor4 is used

Install Webform 6.2.x and Drupal 9.5 with CKEditor patch. CKEditor5 is part of the standard.profile in Drupal 9.5+

  • Confirm CKEditor5 is used

Install Webform 6.2.x and Drupal 10.0 with patch

  • Confirm CKEditor5 is used

Install Webform 6.2.x and Drupal 9.4 without CKEditor patch.

  • Confirm Custom CKEditor is used

Upgrade Webform 6.2.x and Drupal 9.4 with CKEditor patch.

  • Confirm Text format CKEditor4 is used

Upgrade from Drupal 9.4 to Drupal 10.0 with CKEditor and D10

  • Note: Missing rdf and ckeditor modules will display errors.
  • Confirm no editor is used because ckeditor module is missing and ckeditor5 module is not installed.

Install CKEditor5 module.

  • If the rdf and ckeditor modules are missing, go to /admin/structure/webform/config/elements and 'Save configuration', and confirm Text format CKEditor5 is used
  • If the rdf and ckeditor modules are NOT missing, confirm Text format CKEditor5 is used

Remaining tasks

  • Write patch
  • Review patch
  • Commit patch

User interface changes

New default webform text format/editor has the same buttons but does not support the codemirror source mode. Some other feature might be missing.

General/API changes

  • Adds editor.editor.webform_default.yml
  • Adds filter.format.webform_default.yml
  • Removes all ckeditor libraries
  • Removes custom ckeditor JS

Data model changes

TBD

Issue fork webform-3322552

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jrockowitz created an issue. See original summary.

jrockowitz’s picture

Priority: Normal » Critical
Issue summary: View changes

I am having a very difficult time reusing Drupal core's version of CKEditor. As far as I can tell core is generating the editor based on YAML configuration files. I am not able to determine which libraries are required to build a simple isolated CKEditor. I am going to ask for help via Drupal Slack.

wim leers’s picture

To paraphrase @acbramley from Slack:

Just curious why webform doesn't use a format/editor config?

In Slack you wrote:

Webform is NOT using a text format/editor instead, we are loading the core/ckeditor library and then configuring the editor via https://git.drupalcode.org/project/webform/-/blob/6.1.x/js/webform.eleme...

😱 This was never supported by the CKEditor (4) module in Drupal core! This is not using the API provided by Drupal.

You chose to use the CKEditor 4 API directly (i.e. https://ckeditor.com/docs/ckeditor4/latest/guide/index.html).

For example. the Webform's HTML editor, use BR tags instead of P tags.

… that's not just any example, that is a really crucial atypical behavior 😱 You used https://ckeditor.com/docs/ckeditor4/latest/guide/dev_best_practices.html... to achieve this.

And per https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/... … I'm afraid CKEditor 5 won't support this anymore:

			<td><a href="/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-forceEnterMode">forceEnterMode</a></td>
			<td>N/A. Se also <a href="#enterMode"><code>config.enterMode

.

… so the only potential solution I see for you is to create a custom htmlWriter plugin that still allows <p> in the editor but converts them to <br> when converting ("downcasting") to actual HTML. Fortunately we have somewhat of an example for you in Drupal core: core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/*.

wim leers’s picture

Title: CKEditor5 support » CKEditor 5 support
jrockowitz’s picture

If we want to roll a custom editor for webform... is it still possible to include the ckeditor5 libraries from Drupal core and create a custom editor?

Here is an example of my attempt to load the required libraries and initialize a basic editor. No errors are logged, but the editor is disabled. When I start adding plugins to the editor, I get a whole bunch of different errors.

I need a tiny push in the right direction or someone to say it is not feasible to reuse core ckeditor5 libraries.

nigelcunningham’s picture

Perhaps it's asking if it's worth the pain? Perhaps doing things the Drupally way is the go?

joseph.olstad’s picture

***EDIT***
the issue I'm describing here occurs whether or not a wysiwyg editor is used, even on non-wysiwyg fields for labels edited with input boxes in the webform translation ui. So I thought some more and questioned the assumption below as probably incorrect which is why I'm editting my own comment here.
*** END EDIT ***

This above issue discussed by @Wimleer might explain why we're still observing this issue with +64kb long webform translations

#2836206: [Translations] Translation of big webforms broken

for some reason webforms is processing translations as a single line when saving translations with the web gui interface, however if importing with drush the correct multiline translation import is working (provided the \r\n are replaced first).

#2844452: Export configuration YAML strings as multiline

jrockowitz’s picture

CKEditor support for Webform the Drupally way

  • Create a 'webform' text format with an optimized CKEditor.
  • Hide the 'webform' text format from other text_format elements using #process via TextFormat element. This prevents the 'webform' text format from appearing everywhere.
  • Default Webform HTML Editor to use the webform format. (html_editor.element_format)
  • Remove the custom CKEditor code.
joseph.olstad’s picture

Status: Active » Needs review

I'd like to trigger tests, I'm also going to try to test this with 9.4.8 and ckeditor5 (enable this core module)

joseph.olstad’s picture

@jrockowitz,

line 731 of your merge request
js/webform.element.html_editor.ckeditor..js: {}

this line was probably instead intended to be like this:

js/webform.element.html_editor.ckeditor.js: {}

Could this explain your trouble?

joseph.olstad’s picture

Triggered a Drupal 10 test (manually)
Triggered a Drupal 9.4 test (was automatic)

joseph.olstad’s picture

ok I ran 6.2.x-dev with this MR branch on a site with: Drupal 9.4.8,

I enabled the ckeditor5 module however the text format default remained the same when I was editing webform configurations (advanced html form items using the GUI).

I tested also the translation of webforms, didn't notice any change in behavior here.

the ckeditor 1.0.1 module (ckeditor v4) was still trying to find library files:

Not Found
The requested URL "http://f7fb44f3-5fdf-4283-ac13-7b0b4f153111.web.ahdev.cloud/modules/cont..." was not found on this server.

Not Found
The requested URL "http://f7fb44f3-5fdf-4283-ac13-7b0b4f153111.web.ahdev.cloud/modules/cont..." was not found on this server.

In Drupal 9.4.8, ckeditor version 5 is included with Drupal 9.4.8 core however ckeditor 4 is now a contrib module.

the new html_editor.element_format I couldn't confirm if this was actually working or not, I didn't notice a difference before or after using the 6.2.x-dev with the above branch.

one thing I did test is I did uninstall the ckeditor module, once I did this, gutenberg kicked in but ckeditor 5 was not visible.

I also tested a super long translation of a super long webform > 64 kilobytes in the configuration file, no change in behavior, could not save a change in any version of webform with any branch or release, the \r\n single line locales_source blob limit problem issue is caused somewhere else inside drupal (the webform module?) because I could not save a change through the GUI interface of the translated webform, only could do that using drush cim after having a clean yml file (drush webform-tidy) (drush webform-tidy very useful btw). So unfortunately I'm still looking for a solution to :

#2836206: [Translations] Translation of big webforms broken

joseph.olstad’s picture

conclusion:
More testing is needed, suggest testing these changes with Drupal 10
As for these changes on Drupal 9.4.8, I didn't notice much change at all, with that said, it didn't seem to bring up the ckeditor5 even when the ckeditor5 module was enabled. Perhaps there's a webform settings change needed for the new text format.

seems to still need work but good start so far.

jrockowitz’s picture

@joseph.olstad I think the current branch is worthless, and the new branch will need to be cut. By the way, I think for 6.2.x, we will probably take the approach in #8 for D9 and D10.

joseph.olstad’s picture

@jrockowitz, may the force be with you, I'll test your new branch out whenever it comes.

  • 4629a1b committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • b9de697 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • 6513cb9 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • c63fd81 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

Testing new patch, which needs work and documentation.

The attached patch replaces the custom CKEditor for Webform 6.2.x and Drupal 9 with a 'webform' text format.

Below is the before and after.

Status: Needs review » Needs work

The last submitted patch, 21: 3322552-16.patch, failed testing. View results

  • 7928faa committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new42.66 KB

  • b911b79 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

Status: Needs review » Needs work

The last submitted patch, 24: 3322552-24.patch, failed testing. View results

  • 0e2f3da committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • 3a911be committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • 3701d1f committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new44.76 KB

Status: Needs review » Needs work

The last submitted patch, 30: 3322552-29.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

  • de470d2 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

StatusFileSize
new58.78 KB
jrockowitz’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 33: 3322552-33.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

  • d00c1ca committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new58.16 KB
jrockowitz’s picture

Issue summary: View changes

  • a316886 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    

  • aa62cad committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

StatusFileSize
new60.48 KB
jrockowitz’s picture

Issue summary: View changes

  • 82cb703 committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
jrockowitz’s picture

StatusFileSize
new73.47 KB

  • 1535a5d committed on 3322552-ckeditor5
    Issue #3322552: CKEditor 5 support
    
joseph.olstad’s picture

@jrockowitz, I quickly tested your new branch with D9.4.8
installed the ckeditor5 core module however when I uninstalled ckeditor4 it uninstalled two text formats (kinda expected)
next time I'll try with both ckeditor5 and ckeditor4 installed.

jrockowitz’s picture

Issue summary: View changes
StatusFileSize
new80.29 KB

I had to move the ckeditor switching to hook_requirements. If you have the ckeditor and ckeditor5 module enabled it should figure out the right version,

jrockowitz’s picture

Issue summary: View changes
StatusFileSize
new79.97 KB

This patch is ready for a full review.

jrockowitz’s picture

@Wim Leers @Nigel Cunningham Thanks for the nudge to avoid using a custom CKEditor. The new approach still has some custom code to hide the webform's text format, but it should be much easier to maintain and compatible with future versions of Drupal and CKEditor.

jrockowitz’s picture

jrockowitz’s picture

StatusFileSize
new82.23 KB

Status: Needs review » Needs work

The last submitted patch, 51: 3322552-51.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

joseph.olstad’s picture

@jrockowitz
Great work!

I saw the dependency error, I added an upstream ticket for Drupal 10 support of that dependency.

#3326466: Offering to maintain jQuery UI Checkboxradio

the related dependency found in the 1 failure needs a D10 release.

I haven't yet looked at the test code closely to see about a fix

jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new86.23 KB

We need to ignore the failing test which is NOT related to CKEditor support.

@see https://www.drupal.org/pift-ci-job/2542827

wim leers’s picture

Sorry for my silence here! 😬 But excellent progress! 🤩

#5: that is an excellent question! Sadly, the links you posted no longer work … probably because you rebased in the mean time (GitLab strikes again 😬).

#49: oh, NICE! Even better :)

If I understand #54 correctly, then it's still keeping CKEditor 4 support around, just switching it to the same "hidden text format/editor" approach.

  1. +++ b/includes/webform.editor.inc
    @@ -19,6 +19,36 @@ use Drupal\Core\Config\Entity\ConfigEntityInterface;
    +function webform_filter_format_load($entities) {
    +  foreach ($entities as $entity) {
    +    if ($entity->id() === WebformHtmlEditor::DEFAULT_FILTER_FORMAT) {
    +      $route_name = \Drupal::routeMatch()->getRouteName();
    +      $filter_format = \Drupal::routeMatch()->getParameter('filter_format');
    +      if ($route_name === 'filter.admin_overview') {
    +        // Set status to FALSE which hides the default webform filter format.
    +        $entity->set('status',  FALSE);
    +      }
    +      elseif ($filter_format === WebformHtmlEditor::DEFAULT_FILTER_FORMAT) {
    +        // Throw not found exception to prevent the default webform
    +        // filter format from being edited.
    +        throw new NotFoundHttpException();
    +      }
    +    }
    +  }
    +}
    

    😳🤔 Route-based runtime config entity altering … I am not quite sure if this is actually free of side effects …

    AFAIK the correct/supported way to do this is through \Drupal\Core\Config\ConfigFactoryOverrideInterface.

    Or … maybe better yet, I'm wondering if we can work around this at the \Drupal\filter\FilterFormatListBuilder level by using access control logic 🤔

    That class determines which FilterFormat config entities to list using \Drupal\Core\Entity\EntityListBuilder::getEntityIds().

    I checked to see if one could use hook_query_alter() to apply this restriction, but that is not possible, because \Drupal\Core\Config\Entity\Query\Query::execute() does not use the DB query API 😬

    So I suggest subclassing FilterFormatListBuilder, overriding getEntityIds() and then overriding the "list_builder" = "Drupal\filter\FilterFormatListBuilder" entity type annotation.

    (I doubt anybody else has the same need … http://grep.xnddx.ru/search?text=FilterFormatListBuilder&filename= finds 2 matches, but they're just copy/paste leftovers 👍)

  2. +++ b/src/Element/WebformHtmlEditor.php
    @@ -14,7 +16,12 @@ use Drupal\webform\Utility\WebformXss;
    +  const DEFAULT_FILTER_FORMAT = 'webform_default';
    
    @@ -279,4 +259,85 @@ class WebformHtmlEditor extends FormElement {
    +    // Remove the 'webform' default text format from allowed formats.
    +    // This is needed because the webform default text format DOES NOT filter HTML.
    

    🤔 Why not do this instead?

    function webform_entity_filter_format_access(EntityInterface $entity, $operation, AccountInterface $account) {
      if ($entity->id() === 'webform_default') {
        return AccessResult::forbidden('This text format can only be used by Webform.');
      }
      // No opinion.
      return AccessResult::neutral();
    }
    

P.S.: seems like this is the contrib use case that would justify adding FilterFormat::isLocked(), which 5 config entity types in Drupal core already have!

jrockowitz’s picture

Thanks for the review.

The main issue with webform_entity_filter_format_access() is that for administrators, a.k.a USER1, entity access checks are disabled.

Still, you are right that webform_entity_filter_format_access() should be added to prevent non-admins from accessing the webform default filter at an API level.

Overriding Drupal\filter\FilterFormatListBuilder only accounts for the filter format list page, I also want to ensure no one can alter the webform default filter by calling the filter format edit form.

Besides adding webform_entity_filter_format_access(), I'm going to also add a dedicated WebformFilterFormatDefaultAccesssTest to ensure we test all edge cases and track side effects.

jrockowitz’s picture

Only allowing access to 'use' the format prevents an admin from updating the hidden webform default format.
@see https://git.drupalcode.org/project/webform/-/merge_requests/254/diffs#97...

Removing the hidden webform default format from /admin/config/content/formats can't be done via access checks. I feel the current approach via route detection in webform_filter_format_load() is the simplest solution without conflicting with other modules.
@see https://git.drupalcode.org/project/webform/-/merge_requests/254/diffs#97...

I added dedicated test coverage to check access and track edge cases.
https://git.drupalcode.org/project/webform/-/merge_requests/254/diffs#5d...

I am open to overriding \Drupal\filter\FilterFormatListBuilder.

wim leers’s picture

a.k.a USER1, entity access checks are disabled.

IIRC, AccessResult::forbidden() applies always, including to user 1.

IIRC, the only thing that is special cased is that user 1 automatically gets all permissions, but that doesn't mean everything is necessarily accessible. See \Drupal\user\Entity\User::hasPermission().

A quick check of \Drupal\Core\Entity\EntityAccessControlHandler::access() appears to confirm this. But I can definitely be wrong.

jrockowitz’s picture

#58 @Wim Leers Thanks for confirming what I saw in my testing.

jrockowitz’s picture

There is enough test coverage to ensure the hidden webform default format is not accessible; even if it appears on the text format list page.

I will merge this MR to push people to test and review the change/improvement in the last dev and beta releases. I will hold off tagging a stable release of 6.2.x until next year.

jrockowitz’s picture

Status: Needs review » Fixed

  • 86bf349b committed on 6.2.x
    Issue #3322552 by jrockowitz, joseph.olstad: CKEditor 5 support
    

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.