Problem/Motivation

Noticed while reviewing #3259179: Split ckeditor5_alignment CKEditor 5 plugin, to allow for more precise upgrade path.

Alignment controls show up twice! They are present as dedicated toolbar buttons for given type of alignment, then they also present in a dropdown that includes all enabled alignment options.

Aside from this being noisy and feeling a bit "broken", this is especially confusing for non-sighted users that don't have the visual context clues to confirm these are duplicated controls in a slightly different package. It could be misinterpreted as a navigation bug - returning to an already-navigated element. It may also lead to the false impression that the control does something different without the visual cue of an identical icon.

CKEditor 5's default appears to be the dropdown https://ckeditor.com/docs/ckeditor5/latest/features/text-alignment.html

Steps to reproduce

Proposed resolution

  1. Keep the dropdown, lose the buttons
  2. Make the dropdown configurable (similar to headings), where the user can choose what alignment options will be available in the dropdown.
  3. Modify the upgrade path in \Drupal\ckeditor5\Plugin\CKEditor4To5Upgrade\Core::mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem() to instead generate the dropdown, and then also expand ::computeCKEditor5PluginSubsetConfiguration() to generate the appropriate configuration (much like headings).

Remaining tasks

- Implement UI to configure the alignments in the dropdown
- Implement an upgrade path from CK 4 to 5
- Implement an upgrade for already migrated CKE5 configs (to be defined, see #6)
- Implement test coverage both for the functionality and the CKE version upgrade
- Review that all until RTBC

User interface changes

Adds a configuration for the alignments (similarly to what headings does) in the text format configuration page when the alignment dropdown is added to the page.

API changes

The API will need to change in the CKE 4 to 5 upgrade path methods.

Data model changes

Release notes snippet

CKEditor 5 alignment was previously available via individual toolbar buttons or within a single dropdown. It is now only available via dropdown. Existing text formats using the individual buttons will automatically migrated to using the dropdown.

Issue fork drupal-3259593

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

bnjmnm created an issue. See original summary.

wim leers’s picture

  1. Keep the dropdown, lose the buttons
  2. Make the dropdown configurable (similar to headings), where the user can choose what alignment options will be available in the dropdown.

+1

wim leers’s picture

Issue summary: View changes
Issue tags: +Usability

This change will affect the upgrade path too, so added:

  1. Modify the upgrade path in \Drupal\ckeditor5\Plugin\CKEditor4To5Upgrade\Core::mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem() to instead generate the dropdown, and then also expand ::computeCKEditor5PluginSubsetConfiguration() to generate the appropriate configuration (much like headings).
wim leers’s picture

Getting this done would help #3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets — this is not a blocker, but it'd make things simpler and clearer there.

dom.’s picture

dom.’s picture

Issue summary: View changes
Status: Active » Needs work

Pushed my current work on the subject : provide a configurable setup for the dropdown alignment button.

Updating issue "Remaining tasks" : it now takes a CKE 4 to 5 upgrade path and some tests coverage.

Note 1: it is highly likely that the API for the methods for upgrading from CKE 4 to 5 since we will need to keep track of already migrating plugins (or buttons). This is new as it is the first use case of many buttons in CKE4 turning to 1 only with a configuration associated in CK5.

Note 2: I am not sure an upgrade path is necessary for already migrated CKE5 text formats. Indeed, it is currently not possible to use CKE5 with multiple alignments as it crashes, so it is sure the former CKE4 configs are lost as upgrade already occurred and new CKE5 do not have multiple alignments or it would fail.

tim.plunkett’s picture

Component: ckeditor.module » ckeditor5.module
wim leers’s picture

Priority: Normal » Major

Thanks so much for pushing this forward, @Dom.! Here's some pointers to help you finish this up:

  1. The Drupal\Tests\quickedit\FunctionalJavascript\QuickEditFileTest failure is unrelated. Random failure, unfortunately.
  2. Same for 1) Drupal\Tests\layout_builder\FunctionalJavascript\BlockFormMessagesTest::testValidationMessage
  3. 1) Drupal\Tests\ckeditor5\Kernel\ConfigurablePluginTest::testDefaults
    

    → simple update of the expectations in that test is all that we need.

  4. 1) Drupal\Tests\ckeditor5\Kernel\WildcardHtmlSupportTest::testGhsConfiguration
    

    → you'll need to update the Editor::create() call in \Drupal\Tests\ckeditor5\Kernel\WildcardHtmlSupportTest::testGhsConfiguration() to check if in_array('alignment', $additional_toolbar_items, TRUE) and if so, add the default configuration for the alignment plugin

  5. For
    1) Drupal\Tests\ckeditor5\Kernel\CKEditor5PluginManagerTest::testEnabledPlugins
    Failed asserting that two arrays are identical.
    

    you will have to update

        // Case 7: GHS is enabled for other text editors if they are using a
        // CKEditor 5 plugin that uses wildcard tags.
        $settings['toolbar']['items'][] = 'alignment:center';
    

    → that needs to become 'alignment', and you'll need to configure the alignment plugin to only allow center — then the rest of the test should become trivial to update.

  6. 1) Drupal\Tests\ckeditor5\Kernel\CKEditor4to5UpgradeCompletenessTest::testCKEditor5ConfigurableSubsetPlugins
    OutOfBoundsException: No upgrade path found for the "ckeditor5_alignment" elements subset configuration.
    

    This needs to be fixed first, and then SmartDefaultSettingsTest should be updated.

    This can be fixed by updating \Drupal\ckeditor5\Plugin\CKEditor4To5Upgrade\Core::computeCKEditor5PluginSubsetConfiguration(), look at the case 'ckeditor5_heading': code branch for how to do this, we need something similar for ckeditor5_alignment.

    I think the logic can be as simple as "if any tag allows the text-align-left value on the class attribute, enable the left checkbox for the Alignment plugin's settings". Same thing for right, center and justify.

wim leers’s picture

FYI: this is using the enabled_alignments top-level key for its configuration, which means we could add an tags top-level key in #3259367: [upstream] Allow configuring *which* HTML tags can be aligned, when CKEditor 5 adds upstream support for configuring that.

IOW: this issue does not do things in a way that more configuration could not be added anymore in the future, which is very important! 👍

wim leers’s picture

@Dom. I'll start working on this early next week — no pressure on you at all, just letting you know that if you don't get to it, that's completely fine 😊

dom.’s picture

One test in SmartDefaultSettingsTest should still fail. I have not yet figured why the <p> tag is added.

dom.’s picture

Somehow I messed up the branch in the middle. Reverted and rebased on 9.4.x to re-apply cleanly. That make the whole ticket verbose to followers, sorry for that, but easier to take back from here for next developer.

dom.’s picture

During the CKE4 to 5 process, multiple buttons from CKE4 can merge to one button only in CKE5, for instance the four alignment types in CKE4 now converts to one button only in CKE5.
That creates duplicates during the createSettingsFromCKEditor4 process as we will get multiple times the same button as a result of mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem.

There is two approach:

  1. dedupe the buttons in createSettingsFromCKEditor4 after they are all converted.
  2. Make mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem aware not only on the current CKE4 button being converted, but also the already converted CKE5 buttons and potentially the other CKE4 buttons to be converted.

Approach 2 has many implications:

  • it is confusing for DX as we expect DX to return the the converted CKE5 button, not add it to the already converted buttons which as read-only information
  • it is overwhelming information as of separation of concerns regarding what is really done here (map a CK4 button to another in CKE5)
  • It would sound similar to what we do in process_hook(&$variable) but with a different type of method signature, once more a new approach as of drupal

For this purpose, I preferred to deduplicate afterward in createSettingsFromCKEditor4. The resulting code is not particularly elegant, maybe some as-readable but more elegant version can be found of this.
The purpose is to remove duplicates and empty values. One of each only must be kept, and the groups '|' must be preserved.

dom.’s picture

Note: I still have the additional <p> tag added in SmartDefaultSettingsTest.php that I don't know how to solve.

--- Expected
+++ Actual
@@ @@
                 10 => '<h4 id>'
                 11 => '<h5 id>'
                 12 => '<h6 id>'
+                13 => '<p class="text-align-center">'
             )
         )
         'ckeditor5_alignment' => Array &6 (
dom.’s picture

Also in ValidatorTest.php, the SourceEditingRedundantTagsConstraint->availablePluginsMessage still popups, but with no more 'Alignment' in the overlapping_tags which is now empty. I don't suppose that constraint should popup at all I guess.

wim leers’s picture

#15: You discovered a bug outside the scope of this MR 🤓 (In HTMLRestrictions::fromString(), called by \Drupal\ckeditor5\SmartDefaultSettings::computeNetNewElementsForPlugin().) Pushed ef41c4f5ad2bf8539b5de1fdef8429b71f35938a for that.

You have two choices here:

  1. Make the tests introduced in ef41c4f5ad2bf8539b5de1fdef8429b71f35938a pass.
  2. Revert that commit/those tests and change
        elements:
          - <$text-container class="text-align-left">
          - <$text-container class="text-align-center">
          - <$text-container class="text-align-right">
          - <$text-container class="text-align-justify">
    

    to

        elements:
          - <$text-container class="text-align-left text-align-center text-align-right text-align-justify">
    
wim leers’s picture

Issue tags: +Needs followup

Fixing the bug I described in #17 is not stable-blocking. This bug is. So I'm making the decision: reverting the test, and fixing it by working around it, i.e. the second choice in #17.

Doing that would require also changing this bit in \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getProvidedElements():

        elseif (isset($editor)) {
          $subset = $this->getPlugin($id, $editor)->getElementsSubset();
          $subset_violations = array_diff($subset, $defined_elements);
          if (!empty($subset_violations)) {
            throw new \LogicException(sprintf('The "%s" CKEditor 5 plugin implements ::getElementsSubset() and did not return a subset, the following tags are absent from the plugin definition: "%s".', $id, implode(' ', $subset_violations)));
          }
          $defined_elements = $subset;
        }

So we have no choice but to fix the bug in HTMLRestrictions::fromString().

hooroomoo’s picture

Assigned: dom. » hooroomoo
hooroomoo’s picture

1. I can't seem to trigger the "ckeditor5_alignment" case in \Drupal\ckeditor5\Plugin\CKEditor4To5Upgrade\Core::computeCKEditor5PluginSubsetConfiguration. While in CKEditor 4, I dragged the justifyLeft button into the active toolbar, then switched to CKEditor5 and I expected that to work. Am I missing something?

2. in #18, I added the change in \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getProvidedElements():. I'm assuming you also mean to fix the HTMLRestrictions::fromString() bug in this MR. What exactly is the bug? It's not exactly clear to me from the test failure.

3. What test coverage is left that needs to be added?

wim leers’s picture

I committed 2db233e0 to make test runs faster. The number of failures remains the same, meaning only CKE5 tests are failing 👍

Will now do the revert I mentioned on the merge request 15 minutes ago. This should reduce the number of failures. It's not making a meaningful change, it's just reverting a step in the wrong direction because of my confusing comment at #18 🙈

wim leers’s picture

Simply doing the revert I mentioned in #21 fixed most failures! The remaining failures look legitimate: the expectations need to be updated. 👍

#20:

  1. Odd, that works fine for me. I wonder if that was due to the bug that was fixed in #21? 🤔
  2. See #21. We don't need to fix it here anymore, thanks to changes that #3261599: Use CKEditor 5's native <ol start> support (and also support <ol reversed>) introduced! 😄 There's still a bug though. That's why this issue is tagged Needs followup. I'll create the follow-up issue and add the unit test that I added in #17 (which you reverted). 👍
  3. None! 😄
wim leers’s picture

hooroomoo’s picture

Status: Needs work » Needs review
wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Let's get this in! 😄

bnjmnm’s picture

Status: Reviewed & tested by the community » Needs work

One of the pending tasks was

Implement an upgrade for already migrated CKE5 configs (to be defined, see #6)

. I tested this manually by enabling a single button alignment on HEAD (multiple buttons are known to not work 👉#3273510: CKEditor 5 crash when multiple alignment buttons are activated due to duplicate configuration) then switching to this branch with all the usual cache clears.

Since CKEditor 5 is experimental, I'm not sure this is mandatory, but it would certainly be nice unless it's prohibitively complex. Seems like something an update hook could address?

hooroomoo’s picture

Hook adds configuration I want but editor won't load 🤔

wim leers’s picture

Issue tags: +Needs tests

Posted comment on MR with pointers. We want an update path test — see UpdatePathTestBase.

hooroomoo’s picture

Added upgrade path test but it fails with
Drupal\Component\Plugin\Exception\PluginNotFoundException : The "ckeditor5" plugin does not exist. Valid plugin IDs for Drupal\editor\Plugin\EditorManager are: ckeditor

But the update hook works now, tested it manually by doing steps in #27

lauriii made their first commit to this issue’s fork.

lauriii’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
wim leers’s picture

Assigned: hooroomoo » Unassigned
Status: Needs review » Needs work

Still two unused use statements 😅

wim leers’s picture

Status: Needs work » Reviewed & tested by the community
lauriii’s picture

StatusFileSize
new28.88 KB
bnjmnm’s picture

Status: Reviewed & tested by the community » Needs work

I went through this and almost committed but spotted two naming/location related things I'd like changed before this gets in.

  1. +++ b/core/modules/ckeditor5/tests/src/Unit/AlignmentPluginTest.php
    --- /dev/null
    +++ b/core/modules/ckeditor5/tests/src/Update/CKEditor5UpdateAlignmentTest.php
    

    Id like this to keep the pattern of if being in a subdirectory of Functional (typically Functional/Update)

  2. +++ b/core/modules/ckeditor5/tests/src/Update/CKEditor5UpdateAlignmentTest.php
    @@ -0,0 +1,62 @@
    +      __DIR__ . '/../../fixtures/update/ckeditor5.php',
    

    This fixture filename should be more specific. There may be future update path tests that require different fixtures and it will make them easier to distinguish,

wim leers’s picture

Status: Needs work » Reviewed & tested by the community

Did both of those. #36.2 is an interesting remark — the JsonApiUpdatePathTest example I linked to also has this weakness 😅 The only example that does this better in core is ActionConfigTest: it makes it more specific by including the d.o issue number. So matched that example.

wim leers’s picture

StatusFileSize
new28.95 KB
git diff 12fb247a3cb14281e849e123493aac3a094c7f09 060ecfe2e681f1cd1536df9c3b6c7614e9b8b5e9 > 3259593-38.patch
bnjmnm’s picture

StatusFileSize
new28.93 KB

The last submitted patch, 38: 3259593-38.patch, failed testing. View results

bnjmnm’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/ckeditor5/tests/src/Functional/Update/CKEditor5UpdateAlignmentTest.php
@@ -0,0 +1,62 @@
+      __DIR__ . '/../../../../system/tests/fixtures/update/drupal-9.3.0.filled.standard.php.gz',
+      __DIR__ . '/../../fixtures/update/ckeditor5-3259593.php',

The file references in CKEditor5UpdateAlignmentTest need an additional ../ now that they're moved.

wim leers’s picture

Status: Needs work » Reviewed & tested by the community

The 9.3.x patch is not applying only because of #3269657: [drupalMedia] The CKEditor 4 → 5 upgrade path for the media_embed filter should not forcefully allow the `data-view-mode` attribute on `<drupal-media>` not yet having been committed to 9.3.x.

And … #41: 🙈 — I was not meticulous enough! This time I ran the update path test locally 😅

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 39: 3259593-39-93x.patch, failed testing. View results

wim leers’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new28.96 KB

Alright, genuinely green now!

So, back to RTBC, and a patch to test against all branches :)

wim leers’s picture

bnjmnm’s picture

Issue summary: View changes
Issue tags: +9.4.0 release notes

  • bnjmnm committed 11ac481 on 10.0.x
    Issue #3259593 by hooroomoo, Dom., Wim Leers, lauriii: Alignment being...

  • bnjmnm committed ac1dc4b on 9.5.x
    Issue #3259593 by hooroomoo, Dom., Wim Leers, lauriii: Alignment being...

  • bnjmnm committed 1d9dc4c on 9.4.x
    Issue #3259593 by hooroomoo, Dom., Wim Leers, lauriii: Alignment being...
bnjmnm’s picture

Version: 9.4.x-dev » 9.3.x-dev

The update test is failing on 9.3.x. Will investigate what would be needed for a 9.3 backport.

wim leers’s picture

It's odd that https://www.drupal.org/pift-ci-job/2380478 lists no useful output at all 🤯

And … I checked out 9.3.x HEAD locally. That works fine. I tested using PHP 7.4 though. Queued a PHP 7.4 test run. Seems to confirm that the problem is specific to PHP 7.3.

lauriii’s picture

wim leers’s picture

😮 I've never seen that UI before. Odd that it's not available on d.o's usual output page… Since Jenkins results disappear after a while, copy/pasting for posterity:

Testing Drupal\Tests\ckeditor5\Functional\Update\CKEditor5UpdateAlignmentTest
E                                                                   1 / 1 (100%)

Time: 5.78 seconds, Memory: 4.00 MB

There was 1 error:

1) Drupal\Tests\ckeditor5\Functional\Update\CKEditor5UpdateAlignmentTest::testUpdateAlignmentButtons
Erroneous data format for unserializing 'Symfony\Component\Routing\Route'

/var/www/html/core/lib/Drupal/Core/Routing/RouteProvider.php:252
/var/www/html/core/lib/Drupal/Core/Routing/RouteProvider.php:204
/var/www/html/core/lib/Drupal/Core/Routing/UrlGenerator.php:426
/var/www/html/core/lib/Drupal/Core/Routing/UrlGenerator.php:270
/var/www/html/core/lib/Drupal/Core/Render/MetadataBubblingUrlGenerator.php:105
/var/www/html/core/lib/Drupal/Core/Url.php:763
/var/www/html/core/tests/Drupal/Tests/UiHelperTrait.php:376
/var/www/html/core/tests/Drupal/Tests/UiHelperTrait.php:325
/var/www/html/core/tests/Drupal/Tests/UpdatePathTestTrait.php:46
/var/www/html/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php:270
/var/www/html/core/modules/ckeditor5/tests/src/Functional/Update/CKEditor5UpdateAlignmentTest.php:42
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php:703

→ the pattern described in #3152660: Symfony routing problems in 9.01 + #3145563: Route serialization incompatibilities between PHP 7.4 and 7.3 (9.x only).

wim leers’s picture

Status: Reviewed & tested by the community » Needs work

Un-RTBC'ing for 9.3 to signal current status correctly.

I won't get to this today, but I will next week. Fine by me if somebody else figures this one out though!

larowlan’s picture

To fix that error, you have to dump the DB on php 7.3

Last time this happened, I took some notes for the future https://www.drupal.org/project/drupal/issues/3275093#comment-14481944

So the DB dump needs updating basically

wim leers’s picture

Assigned: Unassigned » wim leers

Thanks!

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.32 MB
new1.35 MB

Hah — after attempting to redo the crazy things @larowlan linked in #55, I realized something: its results were committed to 9.4.x only.

So what if I just cherry-pick those two files instead?

That worked! 🤓

So basically this patch is:

git checkout 9.3.x
curl -O https://www.drupal.org/files/issues/2022-05-12/3259593-44.patch
git apply -3v 3259593-44.patch
git ci -am 44
git checkout 3aa89b9 -- core/modules/system/tests/fixtures/update/drupal-9.3.0.bare.standard.php.gz
git checkout 3aa89b9 -- core/modules/system/tests/fixtures/update/drupal-9.3.0.filled.standard.php.gz
git ci -nam 57

→ only the "bare" dump changes.

wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Patch applied successfully (wasn't sure about that due to binary diff), so back to RTBC: test should pass on DrupalCI on PHP 7.3 too.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed a9a0696 and pushed to 9.3.x. Thanks!

  • alexpott committed a9a0696 on 9.3.x
    Issue #3259593 by hooroomoo, Dom., Wim Leers, bnjmnm, lauriii: Alignment...

Status: Fixed » Closed (fixed)

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