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 (#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).

Issue fork url_embed-3316376

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

mark_fullmer created an issue. See original summary.

mark_fullmer’s picture

Note 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!

mark_fullmer’s picture

Issue summary: View changes
mark_fullmer’s picture

Status: Active » Needs review
StatusFileSize
new175.36 KB

The 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.

berdir’s picture

Unsure 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.

mark_fullmer’s picture

Version: 8.x-1.x-dev » 2.x-dev
mark_fullmer’s picture

StatusFileSize
new25.45 KB
new186.54 KB
new175.23 KB

I 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

Eduardo Morales Alberti made their first commit to this issue’s fork.

mark_fullmer’s picture

Eduardo Morales Alberti, can you summarize what the MR that was just opened does, and its relationship to the patches in #7? Thanks!

eduardo morales alberti’s picture

@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.

mark_fullmer’s picture

I created the PR because is easiest to know the changes without applying the patch on a clone project

Thanks, 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.

mark_fullmer’s picture

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!

berdir’s picture

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.

mark_fullmer’s picture

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 #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 embed module.

mark_fullmer’s picture

Issue summary: View changes
mark_fullmer’s picture

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

mark_fullmer’s picture

Issue summary: View changes
astringer’s picture

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

(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)

astringer’s picture

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.

mark_fullmer’s picture

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.

ricksta’s picture

Status: Needs review » Reviewed & tested by the community

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.

millnut’s picture

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.

proteo’s picture

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

jjose.quevedo’s picture

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

mark_fullmer’s picture

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.

jjose.quevedo’s picture

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

            "drupal/url_embed": {
                "CKEditor 5 Support": "./patches/10.patch"
            }
mark_fullmer’s picture

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?

jjose.quevedo’s picture

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?

jjose.quevedo’s picture

StatusFileSize
new181.67 KB

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

liquidcms’s picture

Status: Reviewed & tested by the community » Needs work

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?

robertragas’s picture

@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.

mark_fullmer’s picture

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.

2dareis2do’s picture

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, 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)

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?

2dareis2do’s picture

Ok, 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

eduardo morales alberti’s picture

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 migration from URL embed to core media.

spurlos’s picture

StatusFileSize
new182.36 KB
new643 bytes

As 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.

emptyvoid’s picture

StatusFileSize
new2.69 KB

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.

url embed icon sample

emptyvoid’s picture

StatusFileSize
new1.25 KB

Helps if I upload the zip too.

berdir’s picture

Category: Task » Feature request
Status: Needs work » Fixed

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?

berdir’s picture

mark_fullmer’s picture

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 #3345823: [3.x] Remove dependency on "drupal/embed" contrib module.

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.

mpaans’s picture

@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.

berdir’s picture

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.

Status: Fixed » Closed (fixed)

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