Unverified Commit eddae137 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3241295 by mherchel, glynster, _utsavsharma, Emil Stoianov, rkoller,...

Issue #3241295 by mherchel, glynster, _utsavsharma, Emil Stoianov, rkoller, Wim Leers, gaurav-mathur, DeepaliJ, geek-merlin, tgoeg, ckrina, mgifford, zcht, Dom., smustgrave, nod_, mstrelan, RgnYLDZ: CKEditor 5 isn't respecting field widgets row settings
parent 0498fbfc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1101,6 +1101,7 @@ someschema
somethinggeneric
sortablejs
sourcedir
sourceediting
spacebar
spagna
specialchars
+11 −0
Original line number Diff line number Diff line
@@ -8,3 +8,14 @@
  opacity: 1 !important;
  fill-opacity: 1 !important;
}

/**
 * Set the min-height equal to configuration value for the number of rows.
 *
 * The `--ck-min-height` value is set on the parent `.ck-editor` element by
 * JavaScript. We add that there because the `.ck-editor__editable` element's
 * inline styles are cleared on focus.
 */
.ck-editor__main > :is(.ck-editor__editable, .ck-source-editing-area) {
  min-height: var(--ck-min-height);
}
+46 −0
Original line number Diff line number Diff line
@@ -370,9 +370,55 @@

      ClassicEditor.create(element, editorConfig)
        .then((editor) => {
          /**
           * Injects a temporary <p> into CKEditor and then calculates the entire
           * height of the amount of the <p> tags from the passed in rows value.
           *
           * This takes into account collapsing margins, and line-height of the
           * current theme.
           *
           * @param {number} - the number of rows.
           *
           * @returns {number} - the height of a div in pixels.
           */
          function calculateLineHeight(rows) {
            const element = document.createElement('p');
            element.setAttribute('style', 'visibility: hidden;');
            element.innerHTML = '&nbsp;';
            editor.ui.view.editable.element.append(element);

            const styles = window.getComputedStyle(element);
            const height = element.clientHeight;
            const marginTop = parseInt(styles.marginTop, 10);
            const marginBottom = parseInt(styles.marginBottom, 10);
            const mostMargin =
              marginTop >= marginBottom ? marginTop : marginBottom;

            element.remove();
            return (
              (height + mostMargin) * (rows - 1) +
              marginTop +
              height +
              marginBottom
            );
          }

          // Save a reference to the initialized instance.
          Drupal.CKEditor5Instances.set(id, editor);

          // Set the minimum height of the editable area to correspond with the
          // value of the number of rows. We attach this custom property to
          // the `.ck-editor` element, as that doesn't get its inline styles
          // cleared on focus. The editable element is then set to use this
          // property within the stylesheet.
          const rows = editor.sourceElement.getAttribute('rows');
          editor.ui.view.editable.element
            .closest('.ck-editor')
            .style.setProperty(
              '--ck-min-height',
              `${calculateLineHeight(rows)}px`,
            );

          // CKEditor 4 had a feature to remove the required attribute
          // see: https://www.drupal.org/project/drupal/issues/1954968
          if (element.hasAttribute('required')) {
+175 −0
Original line number Diff line number Diff line
module.exports = {
  '@tags': ['core', 'ckeditor5'],
  before(browser) {
    browser.drupalInstall({ installProfile: 'minimal' });
  },
  after(browser) {
    browser.drupalUninstall();
  },
  'Ensure CKEditor respects field widget row value': (browser) => {
    browser.drupalLoginAsAdmin(() => {
      browser
        // Enable required modules.
        .drupalRelativeURL('/admin/modules')
        .click('[name="modules[ckeditor5][enable]"]')
        .click('[name="modules[field_ui][enable]"]')
        .submitForm('input[type="submit"]') // Submit module form.
        .waitForElementVisible(
          '.system-modules-confirm-form input[value="Continue"]',
        )
        .submitForm('input[value="Continue"]') // Confirm installation of dependencies.
        .waitForElementVisible('.system-modules', 10000)

        // Create new input format.
        .drupalRelativeURL('/admin/config/content/formats/add')
        .waitForElementVisible('[data-drupal-selector="edit-name"]')
        .updateValue('[data-drupal-selector="edit-name"]', 'test')
        .waitForElementVisible('#edit-name-machine-name-suffix')
        .click(
          '[data-drupal-selector="edit-editor-editor"] option[value=ckeditor5]',
        )
        // Wait for CKEditor 5 settings to be visible.
        .waitForElementVisible(
          '[data-drupal-selector="edit-editor-settings-toolbar"]',
        )
        .click('.ckeditor5-toolbar-button-sourceEditing') // Select the Source Editing button.
        .keys(browser.Keys.DOWN) // Hit the down arrow key to move it to the toolbar.
        // Wait for new source editing vertical tab to be present before continuing.
        .waitForElementVisible(
          '[href*=edit-editor-settings-plugins-ckeditor5-sourceediting]',
        )
        .submitForm('input[type="submit"]')
        .waitForElementVisible('[data-drupal-messages]')
        .assert.textContains('[data-drupal-messages]', 'Added text format')
        // Create new content type.
        .drupalRelativeURL('/admin/structure/types/add')
        .waitForElementVisible('[data-drupal-selector="edit-name"]')
        .updateValue('[data-drupal-selector="edit-name"]', 'test')
        .waitForElementVisible('#edit-name-machine-name-suffix') // Wait for machine name to update.
        .submitForm('input[type="submit"]')
        .waitForElementVisible('[data-drupal-messages]')
        .assert.textContains(
          '[data-drupal-messages]',
          'The content type test has been added',
        )
        // Navigate to the create content page and measure height of the editor.
        .drupalRelativeURL('/node/add/test')
        .waitForElementVisible('.ck-editor__editable')
        .execute(
          // eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
          function () {
            const height = document.querySelector(
              '.ck-editor__editable',
            ).clientHeight;

            // We expect height to be 320, but test to ensure that it's greater
            // than 300. We want to ensure that we don't hard code a very specific
            // value because tests might break if styles change (line-height, etc).
            // Note that the default height for CKEditor5 is 47px.
            return height > 300;
          },
          [],
          (result) => {
            browser.assert.ok(
              result.value,
              'Editor height is set to 9 rows (default).',
            );
          },
        )
        .click('.ck-source-editing-button')
        .waitForElementVisible('.ck-source-editing-area')
        .execute(
          // eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
          function () {
            const height = document.querySelector(
              '.ck-source-editing-area',
            ).clientHeight;

            // We expect height to be 320, but test to ensure that it's greater
            // than 300. We want to ensure that we don't hard code a very specific
            // value because tests might break if styles change (line-height, etc).
            // Note that the default height for CKEditor5 is 47px.
            return height > 300;
          },
          [],
          (result) => {
            browser.assert.ok(
              result.value,
              'Source editing height is set to 9 rows (default).',
            );
          },
        )

        // Double the editor row count.
        .drupalRelativeURL('/admin/structure/types/manage/test/form-display')
        .waitForElementVisible(
          '[data-drupal-selector="edit-fields-body-settings-edit"]',
        )
        .click('[data-drupal-selector="edit-fields-body-settings-edit"]')
        .waitForElementVisible(
          '[data-drupal-selector="edit-fields-body-settings-edit-form-settings-rows"]',
        )
        .updateValue(
          '[data-drupal-selector="edit-fields-body-settings-edit-form-settings-rows"]',
          '18',
        )
        // Save field settings.
        .click(
          '[data-drupal-selector="edit-fields-body-settings-edit-form-actions-save-settings"]',
        )
        .waitForElementVisible(
          '[data-drupal-selector="edit-fields-body"] .field-plugin-summary',
        )
        .click('[data-drupal-selector="edit-submit"]')
        .waitForElementVisible('[data-drupal-messages]')
        .assert.textContains(
          '[data-drupal-messages]',
          'Your settings have been saved',
        )

        // Navigate to the create content page and measure height of the editor.
        .drupalRelativeURL('/node/add/test')
        .execute(
          // eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
          function () {
            const height = document.querySelector(
              '.ck-editor__editable',
            ).clientHeight;

            // We expect height to be 640, but test to ensure that it's greater
            // than 600. We want to ensure that we don't hard code a very specific
            // value because tests might break if styles change (line-height, etc).
            // Note that the default height for CKEditor5 is 47px.
            return height > 600;
          },
          [],
          (result) => {
            browser.assert.ok(result.value, 'Editor height is set to 18 rows.');
          },
        )
        .click('.ck-source-editing-button')
        .waitForElementVisible('.ck-source-editing-area')
        .execute(
          // eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
          function () {
            const height = document.querySelector(
              '.ck-source-editing-area',
            ).clientHeight;

            // We expect height to be 640, but test to ensure that it's greater
            // than 600. We want to ensure that we don't hard code a very specific
            // value because tests might break if styles change (line-height, etc).
            // Note that the default height for CKEditor5 is 47px.
            return height > 600;
          },
          [],
          (result) => {
            browser.assert.ok(
              result.value,
              'Source editing height is set to 18 rows (default).',
            );
          },
        );
    });
  },
};
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ class TextareaWidget extends StringTextareaWidget {
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $element = parent::settingsForm($form, $form_state);
    $element['rows']['#description'] = $this->t('Text editors (like CKEditor) may override this setting.');
    $element['rows']['#description'] = $this->t('Text editors may override this setting.');
    return $element;
  }