@@ -23,7 +23,6 @@ import deprecated from '@wordpress/deprecated';
2323 * Internal dependencies
2424 */
2525import FormatEdit from './format-edit' ;
26- import Editable from './editable' ;
2726import { create } from '../create' ;
2827import { apply } from '../to-dom' ;
2928import { toHTMLString } from '../to-html-string' ;
@@ -57,6 +56,24 @@ const INSERTION_INPUT_TYPES_TO_IGNORE = new Set( [
5756 'insertLink' ,
5857] ) ;
5958
59+ // In HTML, leading and trailing spaces are not visible, and multiple spaces
60+ // elsewhere are visually reduced to one space. This rule prevents spaces from
61+ // collapsing so all space is visible in the editor and can be removed. It also
62+ // prevents some browsers from inserting non-breaking spaces at the end of a
63+ // line to prevent the space from visually disappearing. Sometimes these non
64+ // breaking spaces can linger in the editor causing unwanted non breaking spaces
65+ // in between words. If also prevent Firefox from inserting a trailing `br` node
66+ // to visualise any trailing space, causing the element to be saved.
67+ //
68+ // > Authors are encouraged to set the 'white-space' property on editing hosts
69+ // > and on markup that was originally created through these editing mechanisms
70+ // > to the value 'pre-wrap'. Default HTML whitespace handling is not well
71+ // > suited to WYSIWYG editing, and line wrapping will not work correctly in
72+ // > some corner cases if 'white-space' is left at its default value.
73+ // >
74+ // > https://html.spec.whatwg.org/multipage/interaction.html#best-practices-for-in-page-editors
75+ const whiteSpace = 'pre-wrap' ;
76+
6077/**
6178 * Global stylesheet.
6279 */
@@ -143,6 +160,8 @@ class RichText extends Component {
143160 console . warn ( 'RichText cannot be used with an inline container. Please use a different tagName.' ) ;
144161 }
145162 }
163+
164+ this . applyRecord ( this . record , { domOnly : true } ) ;
146165 }
147166
148167 createRecord ( ) {
@@ -814,9 +833,11 @@ class RichText extends Component {
814833 __unstableIsSelected : isSelected ,
815834 } = this . props ;
816835
836+ // Check if tag name changed.
837+ let shouldReapply = tagName !== prevProps . tagName ;
838+
817839 // Check if the content changed.
818- let shouldReapply = (
819- tagName === prevProps . tagName &&
840+ shouldReapply = shouldReapply || (
820841 value !== prevProps . value &&
821842 value !== this . value
822843 ) ;
@@ -935,25 +956,21 @@ class RichText extends Component {
935956
936957 Editable ( props ) {
937958 const {
938- tagName,
939- style,
959+ tagName : TagName = 'div' ,
960+ style = { } ,
940961 className,
941962 placeholder,
942963 forwardedRef,
943- __unstableMultilineTag : multilineTag ,
944964 } = this . props ;
945965 const ariaProps = pickBy ( this . props , ( value , key ) =>
946966 startsWith ( key , 'aria-' ) ) ;
947967
948968 return (
949- < Editable
969+ < TagName
950970 { ...props }
951971 { ...ariaProps }
952972 ref = { forwardedRef }
953- tagName = { tagName }
954- style = { style }
955- value = { this . record }
956- placeholder = { placeholder }
973+ style = { { ...style , whiteSpace } }
957974 className = { classnames ( 'rich-text' , className ) }
958975 onPaste = { this . onPaste }
959976 onInput = { this . onInput }
@@ -973,8 +990,11 @@ class RichText extends Component {
973990 onKeyUp = { this . onSelectionChange }
974991 onMouseUp = { this . onSelectionChange }
975992 onTouchEnd = { this . onSelectionChange }
976- multilineTag = { multilineTag }
977- prepareEditableTree = { createPrepareEditableTree ( this . props , 'format_prepare_functions' ) }
993+ role = "textbox"
994+ aria-multiline
995+ aria-label = { placeholder }
996+ contentEditable
997+ suppressContentEditableWarning
978998 />
979999 ) ;
9801000 }
0 commit comments