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:
- Drupal's CKEditor 5 architecture: https://api.drupal.org/api/drupal/core!modules!ckeditor5!ckeditor5.api.p...
- Drupal's API for working with CKEditor 5: https://www.drupal.org/docs/drupal-apis/ckeditor-5-api/overview
- "CKEditor 5 Dev Tools" (https://www.drupal.org/project/ckeditor5_dev/) includes a starter template with useful inline comments about naming.
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 (#3272732: Drupal 10 & CKEditor 5 readiness). 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).
| Comment | File | Size | Author |
|---|---|---|---|
| #44 | url_embed-ckeditor5-support-3316376-37-svg-fix.patch | 703 bytes | mpaans |
| #39 | urlembed.zip | 1.25 KB | emptyvoid |
| #38 | urlembed.png | 2.69 KB | emptyvoid |
| #37 | interdiff_30-37.txt | 643 bytes | spurlos |
| #37 | url_embed-ckeditor5-support-3316376-37.patch | 182.36 KB | spurlos |
Issue fork url_embed-3316376
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
Comment #2
mark_fullmerNote to maintainers: I created this issue after not finding an existing issue about CKEditor 5 support. If there is any existing work for this present, you can close this issue.
If there is no existing work/issue, I have some familiarity with the CKEditor 5 API and should be able to provide an implementation. Let me know if that's welcome!
Comment #3
mark_fullmerComment #4
mark_fullmerThe attached patch provides a completed CKEditor 5 plugin integrated alongside the existing CKEditor 4 plugin.
This implementation was largely based on Drupal core's implementation of the "drupalImage" plugin, as well as from #3272732: Drupal 10 & CKEditor 5 readiness.
Separate from confirmation about the architectural decisions (listed in the issue description, above) and standard code review, the only remaining work is test coverage, which I can do, but would like approval of the architecture before proceeding.
Comment #5
berdirUnsure about the architecture questions. 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.
Comment #6
mark_fullmerComment #7
mark_fullmerI am also not certain about whether or not to remove the Drupal Embed dependency. We would end up duplicating some of the preview functionality, which would then have to be maintained separately. And I'm not sure if it would have an adverse effect, at least while sites are still using CKEditor 4 in contrib, for existing sites that have customized their URL embed button.
We could keep the CKEditor 4 implementation as-is for the time being, which would mean that the Drupal Embed dependency would have to remain, but build the CKEditor 5 implementation to be independent, and then eventually deprecate & remove the CKEditor 4 implementation altogether, and then remove the dependency. Hmm. Hmm?
In any case, I've replayed the working implementation in #4 for CKEditor 5 on the 2.x branch, and also done an implementation that does remove Drupal Embed from the CKEditor 5 part. The interdiff attached shows what that consists of.
- 3316376_cke5-support_7.patch : replayed changes from #4 on 2.x
- 3316376_cke5-support_7.no-drupal-embed.patch : additionally removed Drupal Embed
- 3316376_cke5-support_7.no-drupal-embed.interdiff.txt : diff of the two above
Comment #10
mark_fullmerEduardo Morales Alberti, can you summarize what the MR that was just opened does, and its relationship to the patches in #7? Thanks!
Comment #11
eduardo morales alberti@mark_fullmer, I created the PR because is easiest to know the changes without applying the patch on a clone project, in this case, the patch was huge. Also, for maintainers is easy to merge and understand what is going on.
Comment #12
mark_fullmerThanks, Eduardo. When I asked "can you summarize what the MR that was just opened does, and its relationship to the patches," I was more precisely asking that you comment in the thread on which of the approaches demonstrated in #7 was represented in the MR. Upon inspection, it appears that the MR provides the approach where the "Embed" module is still a dependency, i.e., 3316376_cke5-support_7.patch.
I think we need input from the module maintainers on which architectural approach they prefer before going further on actual implementation.
Comment #13
mark_fullmerHaving 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!
Comment #14
berdirAs 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.
Comment #15
mark_fullmerGreat point. I've created #3345823: [3.x] Remove dependency on "drupal/embed" contrib module 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
embedmodule.Comment #16
mark_fullmerComment #17
mark_fullmerI'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
Comment #18
mark_fullmerComment #19
astringer commentedI 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
(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)
Comment #20
astringer commentedre: #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.
Comment #21
mark_fullmerThanks 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.
Comment #22
ricksta commentedMy 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.
Comment #23
millnut commentedConfirming 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.
Comment #24
proteo commentedYet another confirmation that the patch in the merge request works as intended. Thanks!
Comment #25
jjose.quevedo commentedHi,
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
Comment #26
mark_fullmerCan you confirm that your syntax in the
composer.jsonfile was the following?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.
Comment #27
jjose.quevedo commentedNo, I didn't use that syntax. Instead, I used the following syntax:
Comment #28
mark_fullmerHrm. 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?
Comment #29
jjose.quevedo commentedI 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?
Comment #30
jjose.quevedo commented@mark_fullmer Great news! I successfully applied the patch, and I'm sharing it here just in case anyone else might find it useful
Comment #31
liquidcms commentedI 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?
Comment #32
robertragas commented@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.
Update:
I see in the topic started thread both have been chosen on purpose. So I guess we need to write our own migration, but also for users who had their own embed button defined (in my case to also alter the behaviour) we need to remove this and alter the original one.
Comment #33
mark_fullmerThat'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.
Comment #34
2dareis2do commentedI 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, iframes are not viewable in ckeditor. That said the embeds are not updated until I save the node, so iframe is still there where i have not updated/saved yet.
My guess is that these will be stripped out if I try to save these nodes with out ckeditor 5 support.
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)
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?
Comment #35
2dareis2do commentedOk, I have discovered the iframe and iframe_media module. Works with CK editor 5 like any other media type entity.
https://www.drupal.org/project/media_iframe
Comment #36
eduardo morales albertiRecently 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 migration from URL embed to core media.
Comment #37
spurlos commentedAs of patch https://www.drupal.org/project/embed/issues/3310328 in Embed module all buttons require and SVG icon to be displayed.
I have amended the patch to use CKEditor5 icon.
Comment #38
emptyvoid commentedI 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.
Comment #39
emptyvoid commentedHelps if I upload the zip too.
Comment #41
berdirFinally 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?
Comment #42
berdirComment #43
mark_fullmerThat'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
embedmodule intourl_embed, as mentioned in the issue description in #3345823: [3.x] Remove dependency on "drupal/embed" contrib module.Removing CKEditor 4 support and the
embedmodule dependency in a new major version (3.x) sounds like the right way to handle this transition seamlessly.Comment #44
mpaans commented@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.
Comment #45
berdirIt 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.