When caption is applied to embedded media, indicate view mode

Created on 23 September 2022, about 2 years ago
Updated 30 September 2023, about 1 year ago

Problem/Motivation

Applying style to embedded media that has a caption can be tricky. This is because to apply a caption, the embedded media entity is wrapped in a tag. The figure tag does not give any indication of the view mode selected for the embedded media item.

As a simple example, suppose I have embedded a media image entity and use a view mode named "50% width" to indicate that the image should be sized to 50% the available width. If I then apply a caption to the image, I still want the image to be the correct size, but now that style must be applied to the wrapping element (the figure tag) so that both the image and the caption are the correct width.

Proposed resolution

A simple solution is for the tag to have an attribute that inherits the view mode value from the media entity on which the caption is being applied. This is already happening for the class attribute so that the tag inherits any alignment applied to the embedded entity. The same can be done for the view mode.

A simple change would be to update the $classes variable value on line 107 of core/modules/filter/src/Plugin/Filter/FilterCaption.php to the following two lines:

        $viewmode = ($node->getAttribute('data-view-mode')) ? $node->getAttribute('data-view-mode') : 'default';
        $classes = $node->getAttribute('class') . ' view-mode--' . $viewmode;

This would add another class to the element to indicate the view mode of the embedded entity on which the caption has been applied. This class would be very helpful for theming.

I experimented with this change and it would work fine. Another way to do this would be to add a separate attribute to the tag that carried the name of the view mode. That would accomplish the same thing without interfering with the class attribute but still allow for styling.

One other enhancement would be to make the filter aware of the default view mode selected in the editor. The Drupal media embed tag in CKEditor will not display the data-view-mode attribute if the media element was embedded using the default view mode. Here, I've just set the value to "default", but it would be great if there was a way to access the Media Library filter configuration to get the actual name of the default view mode.

Caveat

I have not looked at how this works in CKEditor 5. I don't know if it's already better or if applying this enhancement would be much more difficult. I know CKEditor 4 is going away soon, so it would be great if it were possible to make this change for both CKEditor 4 and 5.

✨ Feature request
Status

Needs review

Version

9.5

Component
FilterΒ  β†’

Last updated 3 days ago

No maintainer
Created by

πŸ‡ΊπŸ‡ΈUnited States aaronpinero

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

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

  • πŸ‡―πŸ‡΄Jordan Qusai Taha Amman

    The patch is working, thank you!

  • Status changed to Needs work about 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Previously tagged for tests, which are still needed.

  • last update about 1 year ago
    30,407 pass, 1 fail
  • πŸ‡ΊπŸ‡ΈUnited States aaronpinero

    I don't know much about determining what tests are needed or how to write the necessary tests.

    I asked ChatGPT to evaluate the patch and suggest tests and this is what I got as a reply:

    To ensure the patch works as expected, here are some test cases you should add to cover key areas of functionality. These can be incorporated into Drupal's existing test suite, particularly in a unit test or functional test format.

    ### **1. Check the Presence of `view-mode--default` Class When `data-view-mode` is Missing**
    You need to test the fallback behavior when the `data-view-mode` attribute is absent. This ensures that the class `view-mode--default` is added correctly.

    - **Test Case:** Render content with a caption element **without** a `data-view-mode` attribute.
    - **Expected Outcome:** The `class` attribute of the caption element should contain `view-mode--default`.

    ```php
    // Test case simulating a caption element without a 'data-view-mode' attribute.
    $this->assertContains('view-mode--default', $processed_node->getAttribute('class'));
    ```

    ### **2. Check the Correct `view-mode--[mode]` Class When `data-view-mode` is Present**
    Test that when a `data-view-mode` attribute is present, the correct `view-mode--[mode]` class is added to the caption element.

    - **Test Case:** Render content with a caption element that **has** a `data-view-mode` attribute (e.g., `data-view-mode="teaser"`).
    - **Expected Outcome:** The `class` attribute of the caption should include `view-mode--teaser` or the specified view mode.

    ```php
    // Test case for a caption element with a 'data-view-mode' attribute.
    $this->assertContains('view-mode--teaser', $processed_node->getAttribute('class'));
    ```

    ### **3. Verify Existing Class Attributes are Preserved**
    Ensure that existing classes in the `class` attribute are preserved and the new `view-mode--[mode]` class is appended correctly.

    - **Test Case:** Render content with a caption element that has existing classes (e.g., `class="some-existing-class"`).
    - **Expected Outcome:** The `class` attribute should include both the existing class and the new `view-mode--[mode]` class.

    ```php
    // Test case for an element that has existing classes.
    $this->assertContains('some-existing-class', $processed_node->getAttribute('class'));
    $this->assertContains('view-mode--default', $processed_node->getAttribute('class'));
    ```

    ### **4. Test Nested Elements (e.g., `` Inside `` or `

    - **Test Case:** Render content where a captioned element is nested inside an anchor tag (``).
    - **Expected Outcome:** The class handling should work properly, ensuring the correct class is added to the appropriate node.

    ```php
    // Test case for a caption element inside an tag.
    $this->assertContains('view-mode--default', $parent_node->getAttribute('class'));
    ```

    ### **5. Ensure No Duplicates in the Class Attribute**
    Test that no duplicate `view-mode--[mode]` classes are added, even if the `data-view-mode` is processed multiple times.

    - **Test Case:** Process a node multiple times with the same `data-view-mode`.
    - **Expected Outcome:** The `view-mode--[mode]` class should only appear once.

    ```php
    // Test case to check for duplicate class names.
    $this->assertSame(1, substr_count($processed_node->getAttribute('class'), 'view-mode--default'));
    ```

    ### **6. Test Integration with Other Filters (e.g., Filter Align)**
    Since the comment mentions collaboration with other filters like `filter_align`, ensure that the patch doesn’t break any existing functionality where alignment filters might also manipulate the class attributes.

    - **Test Case:** Apply the `filter_align` filter to the captioned element in conjunction with the `data-view-mode` modification.
    - **Expected Outcome:** The class attributes for both the view mode and alignment are applied correctly.

    ```php
    // Test case where another filter like 'filter_align' collaborates with this patch.
    $this->assertContains('align-left', $processed_node->getAttribute('class'));
    $this->assertContains('view-mode--default', $processed_node->getAttribute('class'));
    ```

    ### **7. Test with Multiple View Modes**
    Ensure that the patch works with various view modes (e.g., `teaser`, `full`, `custom`).

    - **Test Case:** Render content with different `data-view-mode` values.
    - **Expected Outcome:** The class should change dynamically to match the view mode provided.

    ```php
    // Test case for multiple view modes like 'teaser', 'full', etc.
    $this->assertContains('view-mode--full', $processed_node->getAttribute('class'));
    $this->assertContains('view-mode--custom', $processed_node->getAttribute('class'));
    ```

    ### Additional Considerations
    - **Sanitization:** Ensure that any `data-view-mode` values are sanitized or validated to avoid injecting invalid class names.
    - **Edge Cases:** Test behavior when the `data-view-mode` contains unexpected or malformed values, such as special characters.

    ### Summary
    These test cases will ensure that your patch is robust and works as expected across a variety of scenarios, from simple view modes to more complex interactions with nested elements and other filters. You can use Drupal's `KernelTestBase` or `BrowserTestBase` for functional tests, depending on how deeply integrated the changes are with the rendered content and front-end behavior.

  • πŸ‡ΊπŸ‡ΈUnited States alphex Atlanta, GA USA

    This patch worked perfectly! (on 10.3.5)

    Thank you.

    How do we get this in to core?

Production build 0.71.5 2024