CKEditor 5 Support

Created on 19 October 2022, about 2 years ago
Updated 25 January 2024, 11 months ago

Problem/Motivation

CKEditor 4 is marked as deprecated in Drupal 9.5 ( https://www.drupal.org/project/drupal/issues/3304326 β†’ ) and will be removed in Drupal 10. We should provide a CKEditor 5-compatible version of this plugin.

Proposed resolution

Add a CKEditor 5 plugin to the existing module (alongside the CKEditor 4 plugin) to simplify the migration path.

Integration within Drupal should follow documentation provided below:

Summary of functional requirements

1. A CKEditor toolbar icon called "URL Embed" will be available for placement in CKEditor 5 Editors.
2. When the button is clicked, a modal with a form for entering a URL will be shown.
3. User input into this form will be validated against the Embed library's discovery of a suitable provider (if no suitable provider is found, the form will display a validation error).
4. Upon successful submission of a supported URL, the plugin will provide a data-downcast version of markup in the following format:

<drupal-url data-embed-url="[URL as supplied by user]" data-url-provider="[Provider as discovered by Embed"></drupal-url>

5. An editing-downcast version of markup will be provided, as retrieved from the Embed library, via an asynchronous request.
6. To edit an already embedded URL embed, the user may click once on the embed in the CKEditor editing area and then click the toolbar button. The form in modal will populate the input with the existing URL.
7. If the selection in the CKEditor editing window matches an attribute that is not a drupalUrl attribute, the URL Embed toolbar button will be disabled (this is achieved by implementing a refresh() method in the CKEditor command.
8. The module will simultaneously support CKEditor 4 and CKEditor 5 implementations.

Architecture design

The architecture of the CKEditor 5 Model plugin should follow the design of Drupal core's drupalImage plugin, as well as contrib module Entity Embed's implementation ( ✨ Drupal 10 & CKEditor 5 readiness Fixed ). The actual form logic should be located in a Drupal form, rather than a CKEditor5 balloon, so that current and future patches that seek to modify the Form can be maintained by Drupal-centric developers.

Architecture change callout

The CKEditor 4 version of this plugin supports multiple buttons for the URL Embed button, implementing the design proferred by the Drupal module "Embed." Multiple buttons make sense for other implementers, such as "Entity Embed" (where you might want different buttons for embedding a Drupal node vs a Drupal block, etc.). But multiple buttons does not make sense for "URL Embed," where there is only one input variation (a URL) and only one output variation (oEmbed's). If this conclusion is erroneous, I welcome correction. If not, I propose simplifying the implementation to be designed around a single button.

Suggesting testing

Code changes to be evaluated are in https://git.drupalcode.org/project/url_embed/-/merge_requests/10

Beyond a normal code review for logic and syntax correctness:

1. Review the new FunctionalJavascript test coverage for sufficiency: it demonstrates that unsupported URLs will trigger a validation warning and that supported URLs will be inserted into the editing area with the same format as the existing text format filter expects.
2. Functionally test this in the context of a plain Drupal 9.5.x and Drupal 10.x site following the "Installation" section on the project homepage, https://www.drupal.org/project/url_embed β†’
3. Read the instructions in js/ckeditor5_plugins/urlembed/README.md and verify that you can introduce a nominal change to the Javascript and complete the build process (yarn run build).
4. Note that CKEditor 5 requires an SVG icon; this module previously only had a PNG. Confirm that the SVG Icon, generated by IcoMoon, complies with Drupal policy on 3rd-party assets ( https://www.drupal.org/node/422996 β†’ ).

✨ Feature request
Status

Fixed

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    kinda weird to have the embed dependency at all which has the multiple instances thing built-in and then not actually use that, so maybe, maybe removing that might make sense, but that's a fairly big change too.

    Having reflected on this architectural question, I would like to make the recommendation that we remove the "middleware" dependency on drupal/embed, and instead, directly call logic from embed/embed.

    This change is already performed in the patch in #7, "3316376_cke5-support_7.no-drupal-embed.patch", with passing tests, so the "fairly big change" part of the statement above is, at least, mostly behind us :)

    Looking forward to hearing what the maintainers think about this!

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    As discussed, we need to decide what to do with the plugin, possibly flag as deprecated, with a label/explanation in the UI and remove in an upcoming major version.

    That said, the removal of the embed module dependency seems barely related to CkEditor 5 support (it's 90% copy pasting of the code from the embed module that we *do* need), so I'd suggest we split that up into two issues either way, get this in first and then the dependency change becomes easier to review and manage?

    I'm not sure when I'll have time to really test this myself, so what would help a lot is people reporting back on whether or not this works for them.

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    the removal of the embed module dependency seems barely related to CkEditor 5 support (it's 90% copy pasting of the code from the embed module that we *do* need), so I'd suggest we split that up into two issues either way

    Great point. I've created πŸ“Œ Consider removing dependency on "embed" contrib module Active to capture the thoughts on the removal of the embed module dependency, and agree that CKEditor 5 readiness should not involve that scope.

    For folks coming here to test: use the merge request (https://git.drupalcode.org/project/url_embed/-/merge_requests/10), which only includes the CKEditor 5 support and does not remove the dependency on the embed module.

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson
  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    I've added test coverage, which completes the requirements spelled out in the issue description. Per request from maintainers, what would help is for others to test & report whether this is working for them.

    Suggested testing

    The staged code is at https://git.drupalcode.org/project/url_embed/-/merge_requests/10

    For testing steps, this issue's description, specifically: https://www.drupal.org/project/url_embed/issues/3316376#testing ✨ CKEditor 5 Support Fixed

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson
  • πŸ‡ΊπŸ‡ΈUnited States astringer

    I applied your patch to 2.x-dev running Drupal 9.5.5, with CKEditor 5. And it works, except for Facebook and Instagram, they are throwing the error, below. Which may or may not be related to this issue: https://www.drupal.org/project/url_embed/issues/3272702 πŸ“Œ Support for Facebook/Instagram API (2022), switch to embed/embed v4 Fixed

    (I tested it with Vimeo, Youtube, Twitter, Facebook and Insta.)

    Warning: Attempt to read property "html" on null in Drupal\url_embed\Plugin\Filter\UrlEmbedFilter->process() (line 78 of modules/contrib/url_embed/src/Plugin/Filter/UrlEmbedFilter.php).
    Drupal\url_embed\Plugin\Filter\UrlEmbedFilter->process('
    ', 'en') (Line: 118)
    Drupal\filter\Element\ProcessedText::preRenderText(Array)
    call_user_func_array(Array, Array) (Line: 101)
    Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725 β†’ ', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
    Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
    Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
    Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
    Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 161)
    Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 91)
    Drupal\embed\Controller\EmbedController->preview(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 50)
    Drupal\ban\BanMiddleware->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
    Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

  • πŸ‡ΊπŸ‡ΈUnited States astringer

    re: #19

    I'm a goof, I did not know you needed an API key for Facebook/Instagram. I did not have one when I tested, and I am fairly certain that is probably why it failed.

    In a perfect world, an exception might be helpful there.

    (Sorry we just don't use them, I just thought I'd try them. I need it for Youtube and Vimeo.)

    So someone who has those API credentials should test those. Otherwise it worked great for me.

    Thanks.

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    Thanks for testing! Regarding the Facebook API requirement, in a large sense, that is out of scope of this issue. The URL Embed module consists of a CKEditor plugin that provides a UI for inserting URLs and a Drupal text filter for rendering them. This issue's scope only regards the former (the UI for inserting links); nothing in the latter (the rendering of the links) has changed here.

  • Status changed to RTBC over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States ricksta

    My organization has been using the latest patch on multiple sites in production, without incident, for over a week, so I think this patch is good to go.

  • πŸ‡¬πŸ‡§United Kingdom millnut

    Confirming also that the latest patch was used on multiple sites in production without issues, so I also agree that this patch is good to go.

  • Yet another confirmation that the patch in the merge request works as intended. Thanks!

  • πŸ‡ΊπŸ‡ΎUruguay jjose.quevedo

    Hi,

    I wanted to provide an update regarding the patch I received from the merge request and my attempt to apply it. Unfortunately, the patch did not produce the expected results. Here is what I did:

    1. Updated the contrib module to version 2.x.
    2. Added the patch to the composer.json file.
    3. Made an attempt to apply the patch.

    Also, I found an error in the output:
    "Could not apply patch! Skipping. The error was: Cannot apply patch."

    I would appreciate any help in this regard

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    Made an attempt to apply the patch.

    Can you confirm that your syntax in the composer.json file was the following?

          "drupal/url_embed": {
            "CKEditor 5 Support": "https://git.drupalcode.org/project/url_embed/-/merge_requests/10.diff",
          },
    

    If so, are you trying to apply any *other* patches to url_embed simultaneously?

    Note: in practice, patches should not be directly referenced from Gitlab, as shown in the example above, since they could potentially be changed by anyone with a drupal.org account. Ideally, you should download the contents of a patchfile and host it directly in your own code.

  • πŸ‡ΊπŸ‡ΎUruguay jjose.quevedo

    No, I didn't use that syntax. Instead, I used the following syntax:

                "drupal/url_embed": {
                    "CKEditor 5 Support": "./patches/10.patch"
                }
    
  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    Hrm. Nothing has been committed to the 2.x branch since that patch was created, so that's not the problem. My guess is that there's something problematic in the contents of the patchfile that you have locally. Maybe you could test the syntax shown in #26, above, and if that works, that would help confirm that the issue is with the local patch file?

  • πŸ‡ΊπŸ‡ΎUruguay jjose.quevedo

    I used the syntax in #26 and it worked properly, but I'm curious as to why the patch file is not functioning as expected. Just to clarify, I downloaded the patch file from the merge request and copied it into my project. Is there anything else that needs to be done in order to apply the patch file successfully?

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update over 1 year ago
    6 pass
  • πŸ‡ΊπŸ‡ΎUruguay jjose.quevedo

    @mark_fullmer Great news! I successfully applied the patch, and I'm sharing it here just in case anyone else might find it useful

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.1.x + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Composer require failure
  • Status changed to Needs work over 1 year ago
  • πŸ‡¨πŸ‡¦Canada liquidcms

    I applied the patch from #30. Patch applies cleanly but when i set text format as CK5 i still get: The CKEditor 4 button url does not have a known upgrade path.

    I am pretty sure that "url" button is this module; is it not?

  • πŸ‡³πŸ‡±Netherlands robertragas

    @liquidcms

    I am indeed also experiencing the same issue. Not only would you get that, but also adding your own embed buttons through admin/config/content/embed on the type url is not possible, as they do not show in the toolbar.

  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    adding your own embed buttons through admin/config/content/embed on the type url is not possible, as they do not show in the toolbar.

    I see in the topic started thread both have been chosen on purpose.

    That's correct. For others coming here, the section "Architecture change callout" in this issue's description explains the rationale for removing the ability to add additional embed buttons.

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    I am just coming here as I have used this plugin with wysiwyg module and ckeditor 4.

    Actually I have migrated to ckeditor 5, however where I had previously added via url_embed module are not viewable in ckeditor.

    My guess is that these will be stripped out if I try to save these nodes?

    I have tried this patch url_embed_ckeditor5_support.patch and could not notice any change here? (btw this is one of the biggest patches I have ever applied)

    I propose simplifying the implementation to be designed around a single button.

    Probably should be a separate issue to this one.

    All I am really interested in is how to get this working with ckeditor 5. What is the change here required to achieve that?

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Ok, I have discovered the iframe and iframe_media module. Works with CK editor like any other media type entity.

    https://www.drupal.org/project/media_iframe β†’

  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Recently we are updating to Drupal CKEditor 5, drupal core media uses oembed, but only has Vimeo and youtube.

    But there is a contrib module that allows you to choose more providers https://www.drupal.org/project/oembed_providers β†’

    Should we keep the URL Embed if the Media Core already provides it?

    Maybe we should provide a migrator.

  • πŸ‡²πŸ‡©Moldova Spurlos Chisinau

    As of patch https://www.drupal.org/project/embed/issues/3310328 πŸ“Œ When CKEditor5 is installed, only allow SVGs for button icons Fixed in Embed module all buttons require and SVG icon to be displayed.

    I have amended the patch to use CKEditor5 icon.

  • πŸ‡ΊπŸ‡ΈUnited States emptyvoid

    I humbly submit this svg icon I made for the button.
    Note: I had to wrap it in a zip file to upload.. just extract and review.

  • πŸ‡ΊπŸ‡ΈUnited States emptyvoid

    Helps if I upload the zip too.

  • Status changed to Fixed 12 months ago
  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    Finally got around to properly test this on Drupal 10 with CKEditor5.

    This seems to work well enough and I'm going ahead and committing it, we can make further adjustments later on if necessary.

    @Spurlos: Can you create a new issue for that? If you use ckeditor 5 then you no longer need an embed button at all, that would only be when still using CKEditor4 and therefore unrelated to this issue.

    @emptyvoid: I think I prefer the current svg icon in the project, feel free to create a new issue and propose that, if others like it too then I'm open to changing it.

    @mark_fullmer: Do I understand correctly that if we remove the ckeditor4 integration, this module wouldn't depend on embed anymore at all and we could do a 3.x release (maybe, in the future) that removes both that plugin and the embed.module dependency?

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland
  • πŸ‡ΊπŸ‡ΈUnited States mark_fullmer Tucson

    Do I understand correctly that if we remove the ckeditor4 integration, this module wouldn't depend on embed anymore at all and we could do a 3.x release (maybe, in the future) that removes both that plugin and the embed.module dependency

    That's correct, with the clarification that it's not *just* removal: we would also need to do some copy-paste of some helper methods in the embed module into url_embed, as mentioned in the issue description in πŸ“Œ Consider removing dependency on "embed" contrib module Active .

    Removing CKEditor 4 support and the embed module dependency in a new major version (3.x) sounds like the right way to handle this transition seamlessly.

  • πŸ‡³πŸ‡±Netherlands MPaans

    @mark_fullmer please note that MR10 does not contain the svg fix that #37 has. Not sure if that is intentional, but I was assured by frontend team that it is vital. Which means this issue isn't completely fixed yet. We're currently applying this patch on alpha2.

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    It is my understanding that this is only the CKEditor 4 integration and unused for CKEditor5 and that's why I suggested doing that as it's own issue. If you migrated to CKEditor5 you can remove that embed configuration AFAIK.

    Even if not, at this point it should be filled in a new issue.

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

Production build 0.71.5 2024