Verified Commit a266ba6e authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3247795 by heddn, Graber, ravi.shankar, yogeshmpawar, Anchal_gupta, Wim...

Issue #3247795 by heddn, Graber, ravi.shankar, yogeshmpawar, Anchal_gupta, Wim Leers, Fabianx, alexpott, benmorss, catch: Add text filter plugin to support <img loading="lazy"> and remove it from editor_file_reference
parent bd4448db
Loading
Loading
Loading
Loading
+2 −2
Changes for core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -543,7 +543,7 @@ public function testEditorFileReferenceIntegration() {
    $uploaded_image = File::load(1);
    $image_url = $this->container->get('file_url_generator')->generateString($uploaded_image->getFileUri());
    $image_uuid = $uploaded_image->uuid();
    $assert_session->elementExists('xpath', sprintf('//img[@src="%s" and @loading="lazy" and @width and @height and @data-entity-uuid="%s" and @data-entity-type="file"]', $image_url, $image_uuid));
    $assert_session->elementExists('xpath', sprintf('//img[@src="%s" and @width and @height and @data-entity-uuid="%s" and @data-entity-type="file"]', $image_url, $image_uuid));

    // Ensure that width, height, and length attributes are not stored in the
    // database.
@@ -555,7 +555,7 @@ public function testEditorFileReferenceIntegration() {
    $this->assertNotEmpty($assert_session->waitForElement('css', '.ck-editor'));
    $page->pressButton('Save');

    $assert_session->elementExists('xpath', sprintf('//img[@src="%s" and @loading="lazy" and @width and @height and @data-entity-uuid="%s" and @data-entity-type="file"]', $image_url, $image_uuid));
    $assert_session->elementExists('xpath', sprintf('//img[@src="%s" and @width and @height and @data-entity-uuid="%s" and @data-entity-type="file"]', $image_url, $image_uuid));
  }

  /**
+31 −0
Changes for core/modules/editor/editor.post_update.php: 31 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -5,6 +5,10 @@
 * Post update functions for Editor.
 */

use Drupal\filter\Entity\FilterFormat;
use Drupal\filter\FilterFormatInterface;
use Drupal\filter\FilterPluginCollection;

/**
 * Implements hook_removed_post_updates().
 */
@@ -13,3 +17,30 @@ function editor_removed_post_updates() {
    'editor_post_update_clear_cache_for_file_reference_filter' => '9.0.0',
  ];
}

/**
 * Enable filter_image_lazy_load if editor_file_reference is enabled.
 */
function editor_post_update_image_lazy_load(): void {
  if (\Drupal::service('plugin.manager.filter')->hasDefinition('editor_file_reference')) {
    foreach (FilterFormat::loadMultiple() as $format) {
      assert($format instanceof FilterFormatInterface);
      $collection = $format->filters();
      $configuration = $collection->getConfiguration();
      assert($collection instanceof FilterPluginCollection);
      if (array_key_exists('editor_file_reference', $configuration)) {
        $collection->addInstanceId('filter_image_lazy_load');
        $configuration['filter_image_lazy_load'] = [
          'id' => 'filter_image_lazy_load',
          'provider' => 'editor',
          'status' => TRUE,
          // Place lazy loading after editor file reference.
          'weight' => $configuration['editor_file_reference']['weight'] + 1,
          'settings' => [],
        ];
        $collection->setConfiguration($configuration);
        $format->save();
      }
    }
  }
}
+7 −13
Changes for core/modules/editor/src/Plugin/Filter/EditorFileReference.php: 7 added lines, 13 removed lines.
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
 * @Filter(
 *   id = "editor_file_reference",
 *   title = @Translation("Track images uploaded via a Text Editor"),
 *   description = @Translation("Ensures that the latest versions of images uploaded via a Text Editor are displayed."),
 *   description = @Translation("Ensures that the latest versions of images uploaded via a Text Editor are displayed, along with their dimensions."),
 *   type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE
 * )
 */
@@ -92,22 +92,16 @@ public function process($text, $langcode) {
          if ($file instanceof FileInterface) {
            $node->setAttribute('src', $file->createFileUrl());
            if ($node->nodeName == 'img') {
              // Without dimensions specified, layout shifts can occur,
              // which are more noticeable on pages that take some time to load.
              // As a result, only mark images as lazy load that have dimensions.
              $image = $this->imageFactory->get($file->getFileUri());
              $width = $image->getWidth();
              $height = $image->getHeight();
              if ($width !== NULL && $height !== NULL) {
                if (!$node->hasAttribute('width')) {
                  $node->setAttribute('width', $width);
                }
                if (!$node->hasAttribute('height')) {
                  $node->setAttribute('height', $height);
                }
                if (!$node->hasAttribute('loading')) {
                  $node->setAttribute('loading', 'lazy');
              // Set dimensions to avoid content layout shift (CLS).
              // @see https://web.dev/cls/
              if ($width !== NULL && !$node->hasAttribute('width')) {
                $node->setAttribute('width', (string) $width);
              }
              if ($height !== NULL && !$node->hasAttribute('height')) {
                $node->setAttribute('height', (string) $height);
              }
            }
          }
+48 −0
Changes for core/modules/editor/tests/src/Functional/Update/EditorAddLazyLoadImageFilterUpdateTest.php: 48 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\editor\Functional\Update;

use Drupal\FunctionalTests\Update\UpdatePathTestBase;

/**
 * Tests automatically adding editor_image_lazy_load filter to text formats
 * using editor_file_reference.
 *
 * @group Update
 */
class EditorAddLazyLoadImageFilterUpdateTest extends UpdatePathTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function setDatabaseDumpFiles(): void {
    $this->databaseDumpFiles = [
      __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-9.4.0.bare.standard.php.gz',
    ];
  }

  /**
   * Tests upgrading filter settings.
   *
   * @see editor_post_update_image_lazy_load()
   */
  public function testUpdateLazyImageLoad(): void {
    $config = $this->config('filter.format.full_html');
    $this->assertArrayNotHasKey('filter_image_lazy_load', $config->get('filters'));

    $this->runUpdates();

    $config = $this->config('filter.format.full_html');
    $filters = $config->get('filters');
    $this->assertArrayHasKey('filter_image_lazy_load', $filters);
    $this->assertEquals($filters['editor_file_reference']['weight'] + 1, $filters['filter_image_lazy_load']['weight']);
  }

}
+6 −6
Changes for core/modules/editor/tests/src/Kernel/EditorFileReferenceFilterTest.php: 6 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ public function testEditorFileReferenceFilter() {
    $this->assertSame($expected_output, $output->getProcessedText());
    $this->assertEquals($cache_tag, $output->getCacheTags());

    // Add a valid image for test lazy loading feature.
    // Add a valid image for image dimension testing.
    /** @var array stdClass */
    $files = $this->getTestFiles('image');
    $image = reset($files);
@@ -138,16 +138,16 @@ public function testEditorFileReferenceFilter() {
    [$width, $height] = getimagesize('public://llama.jpg');
    $dimensions = 'width="' . $width . '" height="' . $height . '"';

    // Image dimensions and loading attributes are present.
    // Image dimensions are present.
    $input = '<img src="llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" />';
    $expected_output = '<img src="/' . $this->siteDirectory . '/files/llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" ' . $dimensions . ' loading="lazy" />';
    $expected_output = '<img src="/' . $this->siteDirectory . '/files/llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" ' . $dimensions . ' />';
    $output = $test($input);
    $this->assertSame($expected_output, $output->getProcessedText());
    $this->assertEquals($cache_tag, $output->getCacheTags());

    // Image dimensions and loading attributes are set manually.
    $input = '<img src="llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '"width="41" height="21" loading="eager" />';
    $expected_output = '<img src="/' . $this->siteDirectory . '/files/llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" width="41" height="21" loading="eager" />';
    // Image dimensions are set manually.
    $input = '<img src="llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '"width="41" height="21" />';
    $expected_output = '<img src="/' . $this->siteDirectory . '/files/llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" width="41" height="21" />';
    $output = $test($input);
    $this->assertSame($expected_output, $output->getProcessedText());
    $this->assertEquals($cache_tag, $output->getCacheTags());
Loading