diff --git a/core/modules/ckeditor5/css/editor.css b/core/modules/ckeditor5/css/editor.css index 5c28250f97..969a0a9537 100644 --- a/core/modules/ckeditor5/css/editor.css +++ b/core/modules/ckeditor5/css/editor.css @@ -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); +} diff --git a/core/modules/ckeditor5/js/ckeditor5.es6.js b/core/modules/ckeditor5/js/ckeditor5.es6.js index 61e7e12854..8602bfbcd1 100644 --- a/core/modules/ckeditor5/js/ckeditor5.es6.js +++ b/core/modules/ckeditor5/js/ckeditor5.es6.js @@ -420,9 +420,55 @@ ClassicEditor.create(element, editorConfig) .then((editor) => { + /** + * Injects a temporary

into CKEditor and then calculates the entire + * height of the amount of the

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 = ' '; + 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')) { diff --git a/core/modules/ckeditor5/js/ckeditor5.js b/core/modules/ckeditor5/js/ckeditor5.js index 06f4970fd6..dcf7eb11cb 100644 --- a/core/modules/ckeditor5/js/ckeditor5.js +++ b/core/modules/ckeditor5/js/ckeditor5.js @@ -172,7 +172,22 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len var id = setElementId(element); var ClassicEditor = editorClassic.ClassicEditor; ClassicEditor.create(element, editorConfig).then(function (editor) { + function calculateLineHeight(rows) { + var element = document.createElement('p'); + element.setAttribute('style', 'visibility: hidden;'); + element.innerHTML = ' '; + editor.ui.view.editable.element.append(element); + var styles = window.getComputedStyle(element); + var height = element.clientHeight; + var marginTop = parseInt(styles.marginTop, 10); + var marginBottom = parseInt(styles.marginBottom, 10); + var mostMargin = marginTop >= marginBottom ? marginTop : marginBottom; + element.remove(); + return (height + mostMargin) * (rows - 1) + marginTop + height + marginBottom; + } Drupal.CKEditor5Instances.set(id, editor); + var rows = editor.sourceElement.getAttribute('rows'); + editor.ui.view.editable.element.closest('.ck-editor').style.setProperty('--ck-min-height', "".concat(calculateLineHeight(rows), "px")); if (element.hasAttribute('required')) { required.add(id); element.removeAttribute('required');