Commit 1ccdb3b5 authored by Ben Mullins's avatar Ben Mullins
Browse files

Issue #3231337 by lauriii, Wim Leers: [drupalMedia] Remove manual dataDowncast...

Issue #3231337 by lauriii, Wim Leers: [drupalMedia] Remove manual dataDowncast from DrupalMediaEditing
parent 33850359
Loading
Loading
Loading
Loading
+1 −1

File changed.

Preview size limit exceeded, changes collapsed.

+20 −11
Original line number Diff line number Diff line
@@ -274,21 +274,30 @@ export default class DrupalMediaEditing extends Plugin {
   *   The drupalMedia model element to be converted.
   * @return {string}
   *   The model element converted into HTML.
   *
   * @todo: is there a better way to get the rendered dataDowncast string
   *   https://www.drupal.org/project/ckeditor5/issues/3231337?
   */
  _renderElement(modelElement) {
    const attrs = modelElement.getAttributes();
    let element = '<drupal-media';
    Array.from(attrs).forEach((attr) => {
      if (this.attrs[attr[0]] && attr[0] !== 'drupalMediaCaption') {
        element += ` ${this.attrs[attr[0]]}="${attr[1]}"`;
      }
    // Create model document fragment which contains the model element so that
    // it can be stringified using the dataDowncast.
    const modelDocumentFragment = this.editor.model.change((writer) => {
      const modelDocumentFragment = writer.createDocumentFragment();
      // Create shallow clone of the model element to ensure that the original
      // model element remains untouched and that the caption is not rendered
      // into the preview.
      const clonedModelElement = writer.cloneElement(modelElement, false);
      // Remove attributes from the model element to ensure they are not
      // downcast into the preview request. For example, the `linkHref` model
      // attribute would downcast into a wrapping `<a>` element, which the
      // preview endpoint would not be able to handle.
      const attributeIgnoreList = ['linkHref'];
      attributeIgnoreList.forEach((attribute) => {
        writer.removeAttribute(attribute, clonedModelElement);
      });
      writer.append(clonedModelElement, modelDocumentFragment);

      return modelDocumentFragment;
    });
    element += '></drupal-media>';

    return element;
    return this.editor.data.stringify(modelDocumentFragment);
  }

  /**
+0 −9
Original line number Diff line number Diff line
@@ -127,15 +127,6 @@ function modelToEditingViewAttributeConverter() {
      },
      { priority: 'low' },
    );

    // Render arbitrary attributes on the CKEditor 5 widget wrapper until
    // arbitrary attributes are included as part of the server rendered preview.
    // @see https://www.drupal.org/project/drupal/issues/3231337
    dispatcher.on(
      'attribute:htmlAttributes:drupalMedia',
      modelToDataAttributeConverter,
      { priority: 'low' },
    );
  };
}

+23 −3
Original line number Diff line number Diff line
@@ -220,15 +220,35 @@ public function testMediaArbitraryHtml() {
    $editor->setSettings($settings);
    $editor->save();

    $filter_format = $editor->getFilterFormat();
    $filter_format->setFilterConfig('filter_html', [
      'status' => TRUE,
      'settings' => [
        'allowed_html' => '<p> <br> <strong> <em> <a href> <drupal-media data-entity-type data-entity-uuid data-align data-caption alt data-foo>',
      ],
    ]);
    $filter_format->save();
    $this->assertSame([], array_map(
      function (ConstraintViolation $v) {
        return (string) $v->getMessage();
      },
      iterator_to_array(CKEditor5::validatePair(
        Editor::load('test_format'),
        FilterFormat::load('test_format')
      ))
    ));

    // Add data-foo use to an existing drupal-media tag.
    $original_value = $this->host->body->value;
    $this->host->body->value = str_replace('drupal-media', 'drupal-media data-foo="bar" ', $original_value);
    $this->host->save();
    $this->drupalGet($this->host->toUrl('edit-form'));

    // Confirm data-foo is present in the upcasted drupal-media.
    $upcasted_media = $assert_session->waitForElementVisible('css', '.ck-widget.drupal-media');
    $this->assertEquals('bar', $upcasted_media->getAttribute('data-foo'));
    // Confirm data-foo is present in the drupal-media preview.
    $this->assertNotEmpty($upcasted_media = $assert_session->waitForElementVisible('css', '.ck-widget.drupal-media'));
    $this->assertFalse($upcasted_media->hasAttribute('data-foo'));
    $this->assertNotEmpty($preview = $assert_session->waitForElementVisible('css', '.ck-widget.drupal-media > [data-drupal-media-preview="ready"] > .media', 30000));
    $this->assertEquals('bar', $preview->getAttribute('data-foo'));

    // Confirm data-foo is not stripped from source.
    $this->assertSourceAttributeSame('data-foo', 'bar');