Problem/Motivation

In #2994696-198: Render embedded media items in CKEditor, @effulgentsia requested:

This warrants a theme hook, so that themes can override the markup and classes.

"This" refers to the error message that the media_embed filter will output for media items that cannot be loaded for rendering during text processing. Right now, the message and its container is not themeable.

Proposed resolution

Make the error message themeable, possibly by adding a new theme hook.

Remaining tasks

Determine the best way to do this, and make it happen.

User interface changes

None.

API changes

Potentially a new theme hook; TBD.

Data model changes

None anticipated.

Release notes snippet

TBD.

CommentFileSizeAuthor
#49 interdiff.txt1020 byteslauriii
#44 3071713-44.patch22.61 KBoknate
#44 3071713-interdiff--41-44.txt1022 bytesoknate
#41 3071713-41.patch21.61 KBoknate
#41 3071713--interdiff-37-41.txt3.32 KBoknate
#37 3071713-37.patch20.22 KBoknate
#37 3071713-interdiff--33-37.txt3.14 KBoknate
#35 3071713-35.patch20.3 KBoknate
#35 3071713-interdiff--33-35.txt13.28 KBoknate
#34 3071713-33.patch19.64 KBoknate
#34 3071713-interdiff--26-33.txt1.88 KBoknate
#28 3071713-26.patch19.5 KBoknate
#28 3071713--interdiff-25-26.txt5.09 KBoknate
#25 3071713-25.patch19.71 KBoknate
#25 3071713-interdiff--22-25.txt4.19 KBoknate
#22 3071713-22.patch19.14 KBWim Leers
#22 interdiff.txt3.28 KBWim Leers
#21 3071713-21.patch17.53 KBWim Leers
#21 interdiff.txt1.63 KBWim Leers
#18 3071713-18.patch17.36 KBWim Leers
#18 interdiff.txt6.71 KBWim Leers
#17 3071713-17.patch11.53 KBWim Leers
#17 interdiff.txt3.63 KBWim Leers
#13 3071713-13.patch8.41 KBoknate
#13 3071713--interdiff-10-13.txt585 bytesoknate
#12 3071713-12--with-stable-template.patch8.38 KBoknate
#12 3071713-12.patch8.36 KBoknate
#12 3071713--interdiff-10-12.txt539 bytesoknate
#10 3071713-10.patch7.83 KBoknate
#10 3071713--interdiff-7-10.txt3.06 KBoknate
#7 3071713-7.patch8.93 KBoknate
#7 3071713--interdiff-6-7.txt3.54 KBoknate
#6 3071713-5.patch5.98 KBoknate
#6 3071713--interdiff-4-5.txt4.5 KBoknate
#4 3071713--4.patch5.18 KBbnjmnm
#2 3071713-2--do-not-test.patch3.38 KBoknate
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

phenaproxima created an issue. See original summary.

oknate’s picture

Here's an interdiff I'm extracting for reference. It's built off of #2994696: Render embedded media items in CKEditor #194.

phenaproxima’s picture

Title: [PP-1] Make error messages for embedded media themeable » Make error messages for embedded media themeable
Status: Postponed » Needs review

Blocker is in, so this is no longer postponed.

bnjmnm’s picture

Not interdiffing as #2 was there for reference and not intended to work. This builds off of that and adds tests which expose what might be an issue: When performing the test steps manually, I can trigger the preprocess hook that confirms the message is themeable. In the FunctionalJavascript test it does not work, as I discovered it is generating the markup from theDrupal.theme.mediaEmbedError in plugin.es6.js.

I'm hoping it's just been a long week and there's an obvious way to resolve this, but it seems like making the embedded media error messages themeable could cause consistency problems as they're not always generated by the theme layout.

Status: Needs review » Needs work

The last submitted patch, 4: 3071713--4.patch, failed testing. View results

oknate’s picture

Status: Needs work » Needs review
FileSize
4.5 KB
5.98 KB

Thanks for the patch!

The consistency problem you're describing is actually the expected behavior. There are two types of error messages related to media embeds:
1) One from the backend, that comes from the preview route (which should be themable in a twig template). This one I like to call (borrowed from Wim Leers) the "missing media indicator".
2) One from the javascript:

  Drupal.theme.mediaEmbedError = function () {
    var error = Drupal.t('An error occurred while trying to preview the media. Please save your work and reload this page.');
    return '<div class="media-embed-error media-embed-error--preview-error">' + error + '</div>';
  };

This one is out of scope for this issue, as it already has a javascript theme function. The test updated in #4, ::testPreviewFailure() is the second one, so that's the wrong error message. It shouldn't get the template modifications.

A second thing, the changed the attached library shouldn't change based on #2, but keep the current library. I'm switching it back. The correct library in HEAD is media/media_embed.

oknate’s picture

Adding functional js testing for the missing media indicator, as we only have a kernel test right now. I think there's value in putting them both in the same test function as well as some comments explaining the differences between the two types of errors. This will add a bit more test coverage and also provide some documentation if someone greps for renderMissingMediaIndicator() in the code base.

AaronMcHale’s picture

Would solving #2859550: "status_messages"-like render element with a preset message help with this issue as it sounds like the two might be related?

A related issue over there #3078400: Remove hard coded messages markup might also be relevant here.

Wim Leers’s picture

Status: Needs review » Needs work
Related issues: +#2994696: Render embedded media items in CKEditor

Looking good! I found only nits.

  1. +++ b/core/modules/media/templates/media-embed-error.html.twig
    @@ -0,0 +1,16 @@
    + * - string message: The message text.
    

    🤓The string string here should be removed.

  2. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -210,6 +211,31 @@ public function testPreviewFailure() {
    +    // There's a second kind of error message that comes from the backend.
    ...
    +    // Test that restoring a valid uuid results in the media embed preview
    

    Nits:
    - s/backend/back end/
    - s/uuid/UUID/

  3. +++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
    --- /dev/null
    +++ b/core/themes/classy/templates/content/media-embed-error.html.twig
    

    🤔 What's the point of this Twig template if it does exactly the same anyway?

  4. +++ b/core/themes/classy/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,13 @@
    + * - string message: The message text.
    + * - string classes: The classes to add to the HTML tag.
    
    +++ b/core/themes/stable/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,13 @@
    + * - string message: The message text.
    + * - string classes: The classes to add to the HTML tag.
    

    Same here as in point 1.

oknate’s picture

Status: Needs work » Needs review
FileSize
3.06 KB
7.83 KB

Addressing #9.
Fixed nits and dropped redundant templates.

Status: Needs review » Needs work

The last submitted patch, 10: 3071713-10.patch, failed testing. View results

oknate’s picture

Adding media-embed-error to the list of templates to skip for stable. This allows us to not put the redundant template in stable. This hasn't been used but once before. So, are we supposed to copy redundant templates to stable? I'm adding a second patch here that has the template in stable, since I suspect we're breaking a precedent by not copying it to stable.

oknate’s picture

Same as the last one (with stable template), but with the updates suggested in #9.1 and #9.4.

Wim Leers credited bnjmmn.

Wim Leers credited lauriii.

Wim Leers’s picture

Assigned: Unassigned » Wim Leers
Status: Needs review » Needs work
Related issues: +#3072319: Determine the scope of default styling for embedded media (what belongs in Classy, Stable, etc.?)

Per #3072319-16: Determine the scope of default styling for embedded media (what belongs in Classy, Stable, etc.?):

Discussed with @lauriii.

The only reason we have this issue, which is about deciding where the default styling for the "missing media indicator" lives is that there even is default markup with default classes. Once we do #3071713: Make error messages for embedded media themeable, there is no default styling: the markup with the .media-embed-error error should itself be moved to Classy, then Classy and its subclasses will get it. Any themes that choose not to use classy as their base theme already consciously choose to not inherit any classes or CSS, so it's normal to expect them to specify their own classes and CSS.

I'll roll a patch for #3071713: Make error messages for embedded media themeable per @lauriii's recommendations above.

Thanks, @lauriii! 🙏🥳

Moving issue credit over.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
3.63 KB
11.53 KB

This implements @lauriii's suggestions for the server-side (@Filter=media_embed)-triggered media embed errors.

The client-side (@CKEditorPlugin=drupal_media)-triggered media embed errors still needs to be handled.

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
FileSize
6.71 KB
17.36 KB

And this does the client-side portion.

Which also revealed a bug: in HEAD, it's impossible for themes to override the Drupal.theme.* functions defined in core/modules/media/js/plugins/drupalmedia/plugin.es6.js!

(This is untested, I need to move on to other issues. But I trust @oknate can push it across the finish line 😀!)

The last submitted patch, 17: 3071713-17.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 18: 3071713-18.patch, failed testing. View results

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
1.63 KB
17.53 KB

Fixes the test failure in #17.

Wim Leers’s picture

And this should fix most of the test failures in #18 (untested).

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

Status: Needs review » Needs work

The last submitted patch, 22: 3071713-22.patch, failed testing. View results

oknate’s picture

Status: Needs work » Needs review
FileSize
4.19 KB
19.71 KB

Fixing tests.

phenaproxima’s picture

  1. +++ b/core/modules/media/tests/modules/media_test_filter/media_test_filter.module
    @@ -23,3 +23,10 @@ function media_test_filter_entity_access(EntityInterface $entity, $operation, Ac
    +/**
    + * Implements hook_preprocess_HOOK().
    + */
    +function media_test_filter_preprocess_media_embed_error(&$variables) {
    +  $variables['attributes']['class'][] = 'this-error-message-is-themeable';
    +}
    

    I'm surprised we repeat this code in both media_test_filter and media_test_ckeditor. Why's that?

  2. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -187,21 +187,21 @@ public function testOnlyDrupalMediaTagProcessed() {
    -    $this->assertEmpty($assert_session->waitForElementVisible('css', 'img[src*="image-test.png"]', 1000));
    +    $this->assertEmpty($assert_session->waitForElementVisible('css', 'img[src*="image-test.png"]'));
    

    Why this change?

  3. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -210,6 +210,45 @@ public function testPreviewFailure() {
    +    // There's a second kind of error message that comes from the back end.
    

    How suspenseful! :) Can the comment elaborate a bit on what kind of error message it is and why it would appear?

  4. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -210,6 +210,45 @@ public function testPreviewFailure() {
    +    // Test an additional class is added in
    +    // media_test_ckeditor_preprocess_media_embed_error() appears.
    +    $this->assertTrue($missing_media_indicator->hasClass('this-error-message-is-themeable'));
    

    This is redundant. The fact that we've waited for an element with this class is enough. Can we move the comment to just above the assertNotEmpty() call?

  5. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -210,6 +210,45 @@ public function testPreviewFailure() {
    +    $this->container->get('config.factory')
    +      ->getEditable('system.theme')
    +      ->set('default', 'classy')
    +      ->save();
    

    Nit: This can be done with $this->config('system.theme')->set('default', 'classy')->save(). No need to get the config factory.

  6. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -210,6 +210,45 @@ public function testPreviewFailure() {
    +    $this->assertNotEmpty($missing_media_indicator = $assert_session->waitForElement('css', 'drupal-media figure.caption-drupal-media .this-error-message-is-themeable'));
    +    $this->assertTrue($missing_media_indicator->hasClass('media-embed-error--missing-source'));
    

    We don't need the assertTrue(); we can just add the media-embed-error--missing-source class to the selector we're waiting for.

  7. +++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
    @@ -296,11 +296,12 @@ public function testMissingEntityIndicator($uuid, array $filter_ids, array $addi
    -      $expected_class .= ' align-' . $additional_attributes['data-align'];
    +      $align_class = 'align-' . $additional_attributes['data-align'];
    +      $expected_class = "$align_class " . $expected_class;
    

    I assume this changed because the CSS classes are now applied by the backend in a different order.

    If I'm correct, then this is why I'm not a huge fan of checking for CSS classes using assertSame(); it becomes brittle and subject to arbitrary changes in ordering, which does not affect the validity of the class attribute in any way, yet can cause the test to fail. However, I realize that fixing this is a bit out of scope since this is a pre-existing condition. So you can ignore this feedback, and I'll just pout about it to myself.

    But...if we wanted to fix this, I'd suggest changing the selector we pass to $this->cssSelect(), since we're already changing that anyway in this patch. If we do that, we are asserting that the correct classes are present, but we don't have to worry about random order changes breaking our tests.

  8. +++ b/core/themes/classy/classy.info.yml
    @@ -23,3 +23,5 @@ libraries-extend:
    +  media/media_embed_ckeditor_theme:
    +    - classy/media_embed_ckeditor_theme
    

    Is this in the correct place alphabetically, relative to other things in libraries-extend?

  9. +++ b/core/themes/classy/classy.libraries.yml
    @@ -97,3 +97,14 @@ user:
    +media_embed_ckeditor_theme:
    +  version: VERSION
    +  js:
    +    js/media_embed_ckeditor.theme.js: {}
    

    Wouldn't we be using libraries-override for this?

Wim Leers’s picture

#26.9: Maybe, good question! 👍

Let me explain why I did it this way. I grepped for Drupal.theme. in JS files in core/themes/ and found these in stable.info.yml:

libraries-extend:
  core/drupal.ajax:
    - stable/drupal.ajax
  user/drupal.user:
    - stable/drupal.user

Hence the use of libraries-extend instead of libraries-override.

oknate’s picture

Responding to #26:
1. One is for the filter kernel test and one is for the functional javascript CKEditor test. I guess we don’t need it in both places or the test modules could be combined. But I think that’s out of scope. For now, I think it’s appropriate to have the hook in both places, as I think it's valuable to test both in the filter kernel test and in the CKEditor integration FunctionalJavascript test. I think a follow-up issue to see if those two test modules could be combined is the right thing to do.
2. ✅Undoing that change. I misread it, and missed the assertEmpty, so I thought, the wait was unnecessary. Since we’re expecting it to be empty, having a shorter wait time was right. Undoing the change.
3. ✅ Ruined the suspense with a lengthy explanation.
4. ✅ Removed redundant assertion.
5. ✅ Replaced how we’re setting classy to not use config factory.
6. ✅ Removed the assertion, and added the class to the previous assertion.
7. ✅ Updated to use cssSelect()
8. ✅ I alphabetized them. Seems out of scope? Never mind, undoing this change. It looks very out of scope. They're not alphabetized.
9. We actually want to load both, as we’re only overriding the theme function for the missing media indicator, while leaving the edit button alone. if we used libraries-override without adding the edit button, we’d lose the edit button, and if we add the edit button, I guess we’re doing it unnecessarily.

Wim Leers’s picture

  1. #28.3 😂
  2. +++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php
    @@ -296,13 +296,11 @@ public function testMissingEntityIndicator($uuid, array $filter_ids, array $addi
    -    $this->assertSame($expected_class, (string) $error_element['class']);
    +
       }
    

    Übernit: extraneous newline being added here.

  3. As far as I'm concerned, this is RTBC. I can't RTBC though, I've written too much of the code in this patch. Hopefully @phenaproxima will RTBC soon.
phenaproxima’s picture

Issue tags: +Needs followup

Responding to #28.1:

I think a follow-up issue to see if those two test modules could be combined is the right thing to do.

Agreed. Tagging this issue for a follow-up.

phenaproxima’s picture

  1. +++ b/core/modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php
    @@ -199,9 +201,7 @@ public function testPreviewFailure() {
    +    $this->assertNotEmpty($assert_session->waitforText('An error occurred while trying to preview the media. Please save your work and reload this page.'));
    

    Nit: This should be waitForText, not waitforText. This is fixable on commit.

  2. +++ b/core/themes/classy/classy.libraries.yml
    similarity index 84%
    rename from core/modules/media/css/filter.media_embed.css
    
    rename from core/modules/media/css/filter.media_embed.css
    rename to core/themes/classy/css/components/media-embed-error.css
    

    👍 This makes sense, since the only thing in that style sheet is...styling for the errors.

Apart from that one nit, I don't see anything to complain about here. +1 RTBC once green on all backends and the follow-up mentioned in #28.1 is filed.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs followup
Related issues: +#3085264: Merge media_test_filter and media_test_ckeditor
lauriii’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/media/js/media_embed_ckeditor.theme.es6.js
    @@ -0,0 +1,33 @@
    +   * @return {string}
    +   *   A string representing a DOM fragment.
    +   */
    +  Drupal.theme.mediaEmbedPreviewError = () =>
    +    `<div>${Drupal.t(
    +      'An error occurred while trying to preview the media. Please save your work and reload this page.'
    +    )}</div>`;
    

    Let's add a @see comment to reference the template here.

  2. +++ b/core/modules/media/templates/media-embed-error.html.twig
    @@ -0,0 +1,16 @@
    + * @ingroup themeable
    + */
    +#}
    

    Let's add @see comment here to reference the theme function.

  3. +++ b/core/modules/media/src/Plugin/Filter/MediaEmbed.php
    @@ -237,25 +237,11 @@ protected function renderMedia(MediaInterface $media, $view_mode, $langcode) {
    -      '#type' => 'html_tag',
    -      '#tag' => 'div',
    

    💯

  4. +++ b/core/modules/media/templates/media-embed-error.html.twig
    @@ -0,0 +1,16 @@
    +
    
    +++ b/core/themes/classy/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,17 @@
    +
    
    +++ b/core/themes/stable/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,16 @@
    +
    

    🕵️‍♂️ Ubernit: We can remove this line changes because otherwise, they end up in the actual rendered output.

oknate’s picture

Fixing nits in #29 and #31

oknate’s picture

Status: Needs work » Needs review
FileSize
13.28 KB
20.3 KB

Doing my best to address #33

lauriii’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/media/js/media_embed_ckeditor.theme.es6.js
    @@ -0,0 +1,35 @@
    +   * @see \Drupal\media\Plugin\Filter\MediaEmbed::renderMissingMediaIndicator()
    
    +++ b/core/themes/classy/templates/content/media-embed-error.html.twig
    --- /dev/null
    +++ b/core/themes/stable/templates/content/media-embed-error.html.twig
    

    We can probably just reference the template directly. As in @see media-embed-error.html.twig.

  2. +++ b/core/modules/media/templates/media-embed-error.html.twig
    @@ -0,0 +1,21 @@
    + * @see Drupal.theme.mediaEmbedPreviewError
    
    +++ b/core/themes/classy/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,22 @@
    + * @see Drupal.theme.mediaEmbedPreviewError
    
    +++ b/core/themes/stable/templates/content/media-embed-error.html.twig
    @@ -0,0 +1,21 @@
    + * @see Drupal.theme.mediaEmbedPreviewError
    

    👍

  3. #33.4 still needs to be addressed.
oknate’s picture

Trying again to address #33.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

From the interdiff, it looks like @lauriii's feedback is fixed. RTBC once green on all backends.

lauriii’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/themes/classy/classy.libraries.yml
@@ -97,3 +97,14 @@ user:
+      css/components/media-embed-error.css: {}

We should load this CSS in the CKEditor as well by using the ckeditor_stylesheets property in the classy.info.yml file.

Wim Leers’s picture

😵🤦‍♀️ Of course!

oknate’s picture

1) Adding ckeditor_stylesheets to classy.info. I confirmed without this, it's not styled in the CKEditor and with it, it's styled. Added an assertion to CKEditorIntegrationTest::testErrorMessages().
2) I was getting an error due to CKEditor trying to load a css file that no longer exists in DrupalMedia::getCssFiles(), so removed that.

-      $this->moduleExtensionList->getPath('media') . '/css/filter.media_embed.css',

3) I checked and found the library deleted from media, 'media_embed' was still in stable, so removed that and it's css file.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
  • #41.1: test coverage, yay!
  • #41.2 + #41.3: thanks! 👍 I missed those in #17! 😅

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 41: 3071713-41.patch, failed testing. View results

oknate’s picture

Fixing the test failure, due to new ckeditor_stylesheets addition.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Looks like the previous failure was due to an outdated assertion. Restoring RTBC on the assumption that all backends will be green.

lauriii’s picture

Issue tags: +Needs change record

The patch looks good. Could we open a change record to notify theme maintainers not using Stable of the new template and theme function?

phenaproxima’s picture

Issue tags: -Needs change record

  • lauriii committed 67dd0ad on 8.8.x
    Issue #3071713 by oknate, Wim Leers, bnjmnm, phenaproxima, lauriii: Make...
lauriii’s picture

Status: Reviewed & tested by the community » Fixed
FileSize
1020 bytes
+++ b/core/modules/media/js/media_embed_ckeditor.theme.es6.js
@@ -0,0 +1,35 @@
+   * @param {string} error
+   *   The error message to display
+   *

Removed this on commit because the param doesn't exist. I also used yarn prettier to fix eslint failures.

Status: Fixed » Closed (fixed)

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