diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 9bdac14d77cae5..aa6a44461ee73c 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -44,7 +44,7 @@ import { useInputEvents } from './use-input-events'; import { useInsertReplacementText } from './use-insert-replacement-text'; import { useFirefoxCompat } from './use-firefox-compat'; import FormatEdit from './format-edit'; -import { getMultilineTag, getAllowedFormats } from './utils'; +import { getAllowedFormats } from './utils'; import { Content } from './content'; import RichTextMultiline from './multiline'; @@ -146,7 +146,6 @@ export function RichTextWrapper( const { getSelectionStart, getSelectionEnd, getBlockRootClientId } = useSelect( blockEditorStore ); const { selectionChange } = useDispatch( blockEditorStore ); - const multilineTag = getMultilineTag( multiline ); const adjustedAllowedFormats = getAllowedFormats( { allowedFormats, disableFormats, @@ -261,7 +260,6 @@ export function RichTextWrapper( onSelectionChange, placeholder, __unstableIsSelected: isSelected, - __unstableMultilineTag: multilineTag, __unstableDisableFormats: disableFormats, preserveWhiteSpace, __unstableDependencies: [ ...dependencies, tagName ], @@ -349,7 +347,6 @@ export function RichTextWrapper( onReplace, onSplit, __unstableEmbedURLOnPaste, - multilineTag, preserveWhiteSpace, pastePlainText, } ), @@ -363,7 +360,6 @@ export function RichTextWrapper( value, onReplace, onSplit, - multilineTag, onChange, disableLineBreaks, onSplitAtEnd, diff --git a/packages/block-editor/src/components/rich-text/index.native.js b/packages/block-editor/src/components/rich-text/index.native.js index b0c82848db6876..67f41f9ae8c108 100644 --- a/packages/block-editor/src/components/rich-text/index.native.js +++ b/packages/block-editor/src/components/rich-text/index.native.js @@ -20,13 +20,9 @@ import { __experimentalRichText as RichText, __unstableCreateElement, isEmpty, - __unstableIsEmptyLine as isEmptyLine, insert, - __unstableInsertLineSeparator as insertLineSeparator, create, - replace, split, - __UNSTABLE_LINE_SEPARATOR as LINE_SEPARATOR, toHTMLString, slice, } from '@wordpress/rich-text'; @@ -338,32 +334,20 @@ function RichTextWrapper( onCustomEnter(); } - if ( multiline ) { - if ( shiftKey ) { - if ( ! disableLineBreaks ) { - onChange( insert( value, '\n' ) ); - } - } else if ( canSplit && isEmptyLine( value ) ) { - splitValue( value ); - } else { - onChange( insertLineSeparator( value ) ); - } - } else { - const { text, start: splitStart, end: splitEnd } = value; - const canSplitAtEnd = - onSplitAtEnd && - splitStart === splitEnd && - splitEnd === text.length; - - if ( shiftKey || ( ! canSplit && ! canSplitAtEnd ) ) { - if ( ! disableLineBreaks ) { - onChange( insert( value, '\n' ) ); - } - } else if ( ! canSplit && canSplitAtEnd ) { - onSplitAtEnd(); - } else if ( canSplit ) { - splitValue( value ); + const { text, start: splitStart, end: splitEnd } = value; + const canSplitAtEnd = + onSplitAtEnd && + splitStart === splitEnd && + splitEnd === text.length; + + if ( shiftKey || ( ! canSplit && ! canSplitAtEnd ) ) { + if ( ! disableLineBreaks ) { + onChange( insert( value, '\n' ) ); } + } else if ( ! canSplit && canSplitAtEnd ) { + onSplitAtEnd(); + } else if ( canSplit ) { + splitValue( value ); } }, // eslint-disable-next-line react-hooks/exhaustive-deps @@ -471,20 +455,8 @@ function RichTextWrapper( } ); if ( typeof content === 'string' ) { - let valueToInsert = create( { html: content } ); - + const valueToInsert = create( { html: content } ); addActiveFormats( valueToInsert, activeFormats ); - - // If the content should be multiline, we should process text - // separated by a line break as separate lines. - if ( multilineTag ) { - valueToInsert = replace( - valueToInsert, - /\n+/g, - LINE_SEPARATOR - ); - } - onChange( insert( value, valueToInsert ) ); } else if ( content.length > 0 ) { // When an URL is pasted in an empty paragraph then the EmbedHandlerPicker should showcase options allowing the transformation of that URL diff --git a/packages/block-editor/src/components/rich-text/multiline.js b/packages/block-editor/src/components/rich-text/multiline.js index 49075d80196bdf..16905f08e4d85d 100644 --- a/packages/block-editor/src/components/rich-text/multiline.js +++ b/packages/block-editor/src/components/rich-text/multiline.js @@ -11,6 +11,7 @@ import { useDispatch } from '@wordpress/data'; import { RichTextWrapper } from './'; import { store as blockEditorStore } from '../../store'; import { useBlockEditContext } from '../block-edit'; +import { getMultilineTag } from './utils'; function RichTextMultiline( { @@ -34,7 +35,7 @@ function RichTextMultiline( const { clientId } = useBlockEditContext(); const { selectionChange } = useDispatch( blockEditorStore ); - const multilineTagName = multiline.toLowerCase(); + const multilineTagName = getMultilineTag( multiline ); value = value || `<${ multilineTagName }>${ multilineTagName }>`; const padded = `${ multilineTagName }>${ value }<${ multilineTagName }>`; const values = padded.split( diff --git a/packages/block-editor/src/components/rich-text/split-value.js b/packages/block-editor/src/components/rich-text/split-value.js index 0ec083c9fe1e50..17f54d9c9edd01 100644 --- a/packages/block-editor/src/components/rich-text/split-value.js +++ b/packages/block-editor/src/components/rich-text/split-value.js @@ -8,13 +8,7 @@ import { isEmpty, split, toHTMLString } from '@wordpress/rich-text'; * as a result of splitting the block by pressing enter, or with blocks as a * result of splitting the block by pasting block content in the instance. */ -export function splitValue( { - value, - pastedBlocks = [], - onReplace, - onSplit, - multilineTag, -} ) { +export function splitValue( { value, pastedBlocks = [], onReplace, onSplit } ) { if ( ! onReplace || ! onSplit ) { return; } @@ -38,13 +32,7 @@ export function splitValue( { // the enter key. if ( ! hasPastedBlocks || ! isEmpty( before ) ) { blocks.push( - onSplit( - toHTMLString( { - value: before, - multilineTag, - } ), - ! isAfterOriginal - ) + onSplit( toHTMLString( { value: before } ), ! isAfterOriginal ) ); lastPastedBlockIndex += 1; } @@ -60,13 +48,7 @@ export function splitValue( { // the enter key. if ( ! hasPastedBlocks || ! isEmpty( after ) ) { blocks.push( - onSplit( - toHTMLString( { - value: after, - multilineTag, - } ), - isAfterOriginal - ) + onSplit( toHTMLString( { value: after } ), isAfterOriginal ) ); } diff --git a/packages/block-editor/src/components/rich-text/use-enter.js b/packages/block-editor/src/components/rich-text/use-enter.js index 623203fb687df0..08c5abf9d7b6bc 100644 --- a/packages/block-editor/src/components/rich-text/use-enter.js +++ b/packages/block-editor/src/components/rich-text/use-enter.js @@ -4,11 +4,7 @@ import { useRef } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; import { ENTER } from '@wordpress/keycodes'; -import { - insert, - __unstableIsEmptyLine as isEmptyLine, - __unstableInsertLineSeparator as insertLineSeparator, -} from '@wordpress/rich-text'; +import { insert } from '@wordpress/rich-text'; import { getBlockTransforms, findTransform } from '@wordpress/blocks'; import { useDispatch } from '@wordpress/data'; @@ -37,7 +33,6 @@ export function useEnter( props ) { value, onReplace, onSplit, - multilineTag, onChange, disableLineBreaks, onSplitAtEnd, @@ -67,40 +62,22 @@ export function useEnter( props ) { } } - if ( multilineTag ) { - if ( event.shiftKey ) { - if ( ! disableLineBreaks ) { - onChange( insert( _value, '\n' ) ); - } - } else if ( canSplit && isEmptyLine( _value ) ) { - splitValue( { - value: _value, - onReplace, - onSplit, - multilineTag, - } ); - } else { - onChange( insertLineSeparator( _value ) ); - } - } else { - const { text, start, end } = _value; - const canSplitAtEnd = - onSplitAtEnd && start === end && end === text.length; + const { text, start, end } = _value; + const canSplitAtEnd = + onSplitAtEnd && start === end && end === text.length; - if ( event.shiftKey || ( ! canSplit && ! canSplitAtEnd ) ) { - if ( ! disableLineBreaks ) { - onChange( insert( _value, '\n' ) ); - } - } else if ( ! canSplit && canSplitAtEnd ) { - onSplitAtEnd(); - } else if ( canSplit ) { - splitValue( { - value: _value, - onReplace, - onSplit, - multilineTag, - } ); + if ( event.shiftKey || ( ! canSplit && ! canSplitAtEnd ) ) { + if ( ! disableLineBreaks ) { + onChange( insert( _value, '\n' ) ); } + } else if ( ! canSplit && canSplitAtEnd ) { + onSplitAtEnd(); + } else if ( canSplit ) { + splitValue( { + value: _value, + onReplace, + onSplit, + } ); } } diff --git a/packages/block-editor/src/components/rich-text/use-paste-handler.js b/packages/block-editor/src/components/rich-text/use-paste-handler.js index d64d7ca6b15bb5..6ebd33e507d6c3 100644 --- a/packages/block-editor/src/components/rich-text/use-paste-handler.js +++ b/packages/block-editor/src/components/rich-text/use-paste-handler.js @@ -9,13 +9,7 @@ import { findTransform, getBlockTransforms, } from '@wordpress/blocks'; -import { - isEmpty, - insert, - create, - replace, - __UNSTABLE_LINE_SEPARATOR as LINE_SEPARATOR, -} from '@wordpress/rich-text'; +import { isEmpty, insert, create } from '@wordpress/rich-text'; import { isURL } from '@wordpress/url'; /** @@ -27,23 +21,6 @@ import { shouldDismissPastedFiles } from '../../utils/pasting'; /** @typedef {import('@wordpress/rich-text').RichTextValue} RichTextValue */ -/** - * Replaces line separators with line breaks if not multiline. - * Replaces line breaks with line separators if multiline. - * - * @param {RichTextValue} value Value to adjust. - * @param {boolean} isMultiline Whether to adjust to multiline or not. - * - * @return {RichTextValue} Adjusted value. - */ -function adjustLines( value, isMultiline ) { - if ( isMultiline ) { - return replace( value, /\n+/g, LINE_SEPARATOR ); - } - - return replace( value, new RegExp( LINE_SEPARATOR, 'g' ), '\n' ); -} - export function usePasteHandler( props ) { const propsRef = useRef( props ); propsRef.current = props; @@ -59,7 +36,6 @@ export function usePasteHandler( props ) { onReplace, onSplit, __unstableEmbedURLOnPaste, - multilineTag, preserveWhiteSpace, pastePlainText, } = propsRef.current; @@ -178,7 +154,6 @@ export function usePasteHandler( props ) { pastedBlocks: blocks, onReplace, onSplit, - multilineTag, } ); } @@ -220,12 +195,7 @@ export function usePasteHandler( props ) { } ); if ( typeof content === 'string' ) { - let valueToInsert = create( { html: content } ); - - // If the content should be multiline, we should process text - // separated by a line break as separate lines. - valueToInsert = adjustLines( valueToInsert, !! multilineTag ); - + const valueToInsert = create( { html: content } ); addActiveFormats( valueToInsert, value.activeFormats ); onChange( insert( value, valueToInsert ) ); } else if ( content.length > 0 ) { @@ -237,7 +207,6 @@ export function usePasteHandler( props ) { pastedBlocks: content, onReplace, onSplit, - multilineTag, } ); } } diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 66749753a9b802..4a19d76d1a4723 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -6,14 +6,7 @@ * @return {Object} The mapped object. */ export function mapRichTextSettings( attributeDefinition ) { - const { - multiline: multilineTag, - __unstableMultilineWrapperTags: multilineWrapperTags, - __unstablePreserveWhiteSpace: preserveWhiteSpace, - } = attributeDefinition; - return { - multilineTag, - multilineWrapperTags, - preserveWhiteSpace, - }; + const { __unstablePreserveWhiteSpace: preserveWhiteSpace } = + attributeDefinition; + return { preserveWhiteSpace }; } diff --git a/packages/block-library/src/pullquote/deprecated.js b/packages/block-library/src/pullquote/deprecated.js index 46ac8d2f13708b..a936aab8680b7e 100644 --- a/packages/block-library/src/pullquote/deprecated.js +++ b/packages/block-library/src/pullquote/deprecated.js @@ -14,12 +14,6 @@ import { useBlockProps, } from '@wordpress/block-editor'; import { select } from '@wordpress/data'; -import { - create, - replace, - toHTMLString, - __UNSTABLE_LINE_SEPARATOR, -} from '@wordpress/rich-text'; /** * Internal dependencies @@ -64,13 +58,14 @@ function parseBorderColor( styleString ) { } function multilineToInline( value ) { - return toHTMLString( { - value: replace( - create( { html: value, multilineTag: 'p' } ), - new RegExp( __UNSTABLE_LINE_SEPARATOR, 'g' ), - '\n' - ), - } ); + value = value || `
`; + const padded = `${ value }`; + const values = padded.split( `
` ); + + values.shift(); + values.pop(); + + return values.join( '\n' ); } const v5 = { diff --git a/packages/rich-text/README.md b/packages/rich-text/README.md index b88d0ffea6b521..84f33bc3afaf19 100644 --- a/packages/rich-text/README.md +++ b/packages/rich-text/README.md @@ -151,7 +151,7 @@ _Returns_ ### create -Create a RichText value from an `Element` tree (DOM), an HTML string or a plain text string, with optionally a `Range` object to set the selection. If called without any input, an empty value will be created. If `multilineTag` is provided, any content of direct children whose type matches `multilineTag` will be separated by two newlines. The optional functions can be used to filter out content. +Create a RichText value from an `Element` tree (DOM), an HTML string or a plain text string, with optionally a `Range` object to set the selection. If called without any input, an empty value will be created. The optional functions can be used to filter out content. A value will have the following shape, which you are strongly encouraged not to modify without the use of helper functions: @@ -174,8 +174,6 @@ _Parameters_ - _$1.text_ `[string]`: Text to create value from. - _$1.html_ `[string]`: HTML to create value from. - _$1.range_ `[Range]`: Range to create value from. -- _$1.multilineTag_ `[string]`: Multiline tag if the structure is multiline. -- _$1.multilineWrapperTags_ `[Array]`: Tags where lines can be found if nesting is possible. - _$1.preserveWhiteSpace_ `[boolean]`: Whether or not to collapse white space characters. - _$1.\_\_unstableIsEditableTree_ `[boolean]`: @@ -416,13 +414,12 @@ _Returns_ ### toHTMLString -Create an HTML string from a Rich Text value. If a `multilineTag` is provided, text separated by a line separator will be wrapped in it. +Create an HTML string from a Rich Text value. _Parameters_ - _$1_ `Object`: Named argements. - _$1.value_ `RichTextValue`: Rich text value. -- _$1.multilineTag_ `[string]`: Multiline tag. - _$1.preserveWhiteSpace_ `[boolean]`: Whether or not to use newline characters for line breaks. _Returns_ diff --git a/packages/rich-text/src/component/index.js b/packages/rich-text/src/component/index.js index 2b437e4436777b..4aaa0b88ebc148 100644 --- a/packages/rich-text/src/component/index.js +++ b/packages/rich-text/src/component/index.js @@ -28,7 +28,6 @@ export function useRichText( { preserveWhiteSpace, onSelectionChange, onChange, - __unstableMultilineTag: multilineTag, __unstableDisableFormats: disableFormats, __unstableIsSelected: isSelected, __unstableDependencies = [], @@ -51,9 +50,6 @@ export function useRichText( { return create( { element: ref.current, range, - multilineTag, - multilineWrapperTags: - multilineTag === 'li' ? [ 'ul', 'ol' ] : undefined, __unstableIsEditableTree: true, preserveWhiteSpace, } ); @@ -63,9 +59,6 @@ export function useRichText( { apply( { value: newRecord, current: ref.current, - multilineTag, - multilineWrapperTags: - multilineTag === 'li' ? [ 'ul', 'ol' ] : undefined, prepareEditableTree: __unstableAddInvisibleFormats, __unstableDomOnly: domOnly, placeholder, @@ -80,9 +73,6 @@ export function useRichText( { _value.current = value; record.current = create( { html: value, - multilineTag, - multilineWrapperTags: - multilineTag === 'li' ? [ 'ul', 'ol' ] : undefined, preserveWhiteSpace, } ); if ( disableFormats ) { @@ -149,7 +139,6 @@ export function useRichText( { formats: __unstableBeforeSerialize( newRecord ), } : newRecord, - multilineTag, preserveWhiteSpace, } ); } @@ -179,7 +168,6 @@ export function useRichText( { formats: __unstableBeforeSerialize( newRecord ), } : newRecord, - multilineTag, preserveWhiteSpace, } ); @@ -227,13 +215,12 @@ export function useRichText( { ref, useDefaultStyle(), useBoundaryStyle( { record } ), - useCopyHandler( { record, multilineTag, preserveWhiteSpace } ), + useCopyHandler( { record, preserveWhiteSpace } ), useSelectObject(), useFormatBoundaries( { record, applyRecord } ), useDelete( { createRecord, handleChange, - multilineTag, } ), useInputAndSelection( { record, diff --git a/packages/rich-text/src/component/index.native.js b/packages/rich-text/src/component/index.native.js index 14fd806d95b3a6..e4beb09acaa443 100644 --- a/packages/rich-text/src/component/index.native.js +++ b/packages/rich-text/src/component/index.native.js @@ -40,10 +40,9 @@ import { getActiveFormat } from '../get-active-format'; import { getActiveFormats } from '../get-active-formats'; import { insert } from '../insert'; import { getTextContent } from '../get-text-content'; -import { isEmpty, isEmptyLine } from '../is-empty'; +import { isEmpty } from '../is-empty'; import { create } from '../create'; import { toHTMLString } from '../to-html-string'; -import { removeLineSeparator } from '../remove-line-separator'; import { isCollapsed } from '../is-collapsed'; import { remove } from '../remove'; import { getFormatColors } from '../get-format-colors'; @@ -436,7 +435,7 @@ export class RichText extends Component { } const isReverse = keyCode === BACKSPACE; - const { onDelete, __unstableMultilineTag: multilineTag } = this.props; + const { onDelete } = this.props; this.lastEventCount = event.nativeEvent.eventCount; this.comesFromAztec = true; this.firedAfterTextChanged = event.nativeEvent.firedAfterTextChanged; @@ -452,24 +451,6 @@ export class RichText extends Component { return; } - if ( multilineTag ) { - if ( - isReverse && - value.start === 0 && - value.end === 0 && - isEmptyLine( value ) - ) { - newValue = removeLineSeparator( value, ! isReverse ); - } else { - newValue = removeLineSeparator( value, isReverse ); - } - if ( newValue ) { - this.onFormatChange( newValue ); - event.preventDefault(); - return; - } - } - // Only process delete if the key press occurs at an uncollapsed edge. if ( ! onDelete || diff --git a/packages/rich-text/src/component/use-copy-handler.js b/packages/rich-text/src/component/use-copy-handler.js index b25e64428a1b4d..c62d83351971c3 100644 --- a/packages/rich-text/src/component/use-copy-handler.js +++ b/packages/rich-text/src/component/use-copy-handler.js @@ -17,8 +17,7 @@ export function useCopyHandler( props ) { propsRef.current = props; return useRefEffect( ( element ) => { function onCopy( event ) { - const { record, multilineTag, preserveWhiteSpace } = - propsRef.current; + const { record, preserveWhiteSpace } = propsRef.current; const { ownerDocument } = element; if ( isCollapsed( record.current ) || @@ -33,7 +32,6 @@ export function useCopyHandler( props ) { let html = toHTMLString( { value: selectedRecord, - multilineTag, preserveWhiteSpace, } ); diff --git a/packages/rich-text/src/component/use-delete.js b/packages/rich-text/src/component/use-delete.js index 3694db42c41b39..69ccd0ee0dc0b6 100644 --- a/packages/rich-text/src/component/use-delete.js +++ b/packages/rich-text/src/component/use-delete.js @@ -9,8 +9,6 @@ import { BACKSPACE, DELETE } from '@wordpress/keycodes'; * Internal dependencies */ import { remove } from '../remove'; -import { removeLineSeparator } from '../remove-line-separator'; -import { isEmptyLine } from '../is-empty'; export function useDelete( props ) { const propsRef = useRef( props ); @@ -18,8 +16,7 @@ export function useDelete( props ) { return useRefEffect( ( element ) => { function onKeyDown( event ) { const { keyCode } = event; - const { createRecord, handleChange, multilineTag } = - propsRef.current; + const { createRecord, handleChange } = propsRef.current; if ( event.defaultPrevented ) { return; @@ -31,34 +28,11 @@ export function useDelete( props ) { const currentValue = createRecord(); const { start, end, text } = currentValue; - const isReverse = keyCode === BACKSPACE; // Always handle full content deletion ourselves. if ( start === 0 && end !== 0 && end === text.length ) { handleChange( remove( currentValue ) ); event.preventDefault(); - return; - } - - if ( multilineTag ) { - let newValue; - - // Check to see if we should remove the first item if empty. - if ( - isReverse && - currentValue.start === 0 && - currentValue.end === 0 && - isEmptyLine( currentValue ) - ) { - newValue = removeLineSeparator( currentValue, ! isReverse ); - } else { - newValue = removeLineSeparator( currentValue, isReverse ); - } - - if ( newValue ) { - handleChange( newValue ); - event.preventDefault(); - } } } diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index fa2befc603b7e4..793bdca77f71d5 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -9,11 +9,7 @@ import { select } from '@wordpress/data'; import { store as richTextStore } from './store'; import { createElement } from './create-element'; import { mergePair } from './concat'; -import { - LINE_SEPARATOR, - OBJECT_REPLACEMENT_CHARACTER, - ZWNBSP, -} from './special-characters'; +import { OBJECT_REPLACEMENT_CHARACTER, ZWNBSP } from './special-characters'; /** @typedef {import('./types').RichTextValue} RichTextValue */ @@ -111,10 +107,8 @@ function toFormat( { tagName, attributes } ) { /** * Create a RichText value from an `Element` tree (DOM), an HTML string or a * plain text string, with optionally a `Range` object to set the selection. If - * called without any input, an empty value will be created. If - * `multilineTag` is provided, any content of direct children whose type matches - * `multilineTag` will be separated by two newlines. The optional functions can - * be used to filter out content. + * called without any input, an empty value will be created. The optional + * functions can be used to filter out content. * * A value will have the following shape, which you are strongly encouraged not * to modify without the use of helper functions: @@ -141,12 +135,8 @@ function toFormat( { tagName, attributes } ) { * @param {string} [$1.text] Text to create value from. * @param {string} [$1.html] HTML to create value from. * @param {Range} [$1.range] Range to create value from. - * @param {string} [$1.multilineTag] Multiline tag if the structure is - * multiline. - * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if - * nesting is possible. - * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white - * space characters. + * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse + * white space characters. * @param {boolean} [$1.__unstableIsEditableTree] * * @return {RichTextValue} A rich text value. @@ -156,8 +146,6 @@ export function create( { text, html, range, - multilineTag, - multilineWrapperTags, __unstableIsEditableTree: isEditableTree, preserveWhiteSpace, } = {} ) { @@ -179,20 +167,9 @@ export function create( { return createEmptyValue(); } - if ( ! multilineTag ) { - return createFromElement( { - element, - range, - isEditableTree, - preserveWhiteSpace, - } ); - } - - return createFromMultilineElement( { + return createFromElement( { element, range, - multilineTag, - multilineWrapperTags, isEditableTree, preserveWhiteSpace, } ); @@ -317,16 +294,11 @@ export function removeReservedCharacters( string ) { /** * Creates a Rich Text value from a DOM element and range. * - * @param {Object} $1 Named argements. - * @param {Element} [$1.element] Element to create value from. - * @param {Range} [$1.range] Range to create value from. - * @param {string} [$1.multilineTag] Multiline tag if the structure is - * multiline. - * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if - * nesting is possible. - * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white - * space characters. - * @param {Array} [$1.currentWrapperTags] + * @param {Object} $1 Named argements. + * @param {Element} [$1.element] Element to create value from. + * @param {Range} [$1.range] Range to create value from. + * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white + * space characters. * @param {boolean} [$1.isEditableTree] * * @return {RichTextValue} A rich text value. @@ -334,9 +306,6 @@ export function removeReservedCharacters( string ) { function createFromElement( { element, range, - multilineTag, - multilineWrapperTags, - currentWrapperTags = [], isEditableTree, preserveWhiteSpace, } ) { @@ -444,30 +413,9 @@ function createFromElement( { if ( format ) delete format.formatType; - if ( - multilineWrapperTags && - multilineWrapperTags.indexOf( tagName ) !== -1 - ) { - const value = createFromMultilineElement( { - element: node, - range, - multilineTag, - multilineWrapperTags, - currentWrapperTags: [ ...currentWrapperTags, format ], - isEditableTree, - preserveWhiteSpace, - } ); - - accumulateSelection( accumulator, node, range, value ); - mergePair( accumulator, value ); - continue; - } - const value = createFromElement( { element: node, range, - multilineTag, - multilineWrapperTags, isEditableTree, preserveWhiteSpace, } ); @@ -516,79 +464,6 @@ function createFromElement( { return accumulator; } -/** - * Creates a rich text value from a DOM element and range that should be - * multiline. - * - * @param {Object} $1 Named argements. - * @param {Element} [$1.element] Element to create value from. - * @param {Range} [$1.range] Range to create value from. - * @param {string} [$1.multilineTag] Multiline tag if the structure is - * multiline. - * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if - * nesting is possible. - * @param {Array} [$1.currentWrapperTags] Whether to prepend a line - * separator. - * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white - * space characters. - * @param {boolean} [$1.isEditableTree] - * - * @return {RichTextValue} A rich text value. - */ -function createFromMultilineElement( { - element, - range, - multilineTag, - multilineWrapperTags, - currentWrapperTags = [], - isEditableTree, - preserveWhiteSpace, -} ) { - const accumulator = createEmptyValue(); - - if ( ! element || ! element.hasChildNodes() ) { - return accumulator; - } - - const length = element.children.length; - - // Optimise for speed. - for ( let index = 0; index < length; index++ ) { - const node = element.children[ index ]; - - if ( node.nodeName.toLowerCase() !== multilineTag ) { - continue; - } - - const value = createFromElement( { - element: node, - range, - multilineTag, - multilineWrapperTags, - currentWrapperTags, - isEditableTree, - preserveWhiteSpace, - } ); - - // Multiline value text should be separated by a line separator. - if ( index !== 0 || currentWrapperTags.length > 0 ) { - mergePair( accumulator, { - formats: [ , ], - replacements: - currentWrapperTags.length > 0 - ? [ currentWrapperTags ] - : [ , ], - text: LINE_SEPARATOR, - } ); - } - - accumulateSelection( accumulator, node, range, value ); - mergePair( accumulator, value ); - } - - return accumulator; -} - /** * Gets the attributes of an element in object shape. * diff --git a/packages/rich-text/src/get-text-content.js b/packages/rich-text/src/get-text-content.js index f400e4b56497f6..71fc9e7a749f0b 100644 --- a/packages/rich-text/src/get-text-content.js +++ b/packages/rich-text/src/get-text-content.js @@ -1,18 +1,10 @@ /** * Internal dependencies */ -import { - OBJECT_REPLACEMENT_CHARACTER, - LINE_SEPARATOR, -} from './special-characters'; +import { OBJECT_REPLACEMENT_CHARACTER } from './special-characters'; /** @typedef {import('./types').RichTextValue} RichTextValue */ -const pattern = new RegExp( - `[${ OBJECT_REPLACEMENT_CHARACTER }${ LINE_SEPARATOR }]`, - 'g' -); - /** * Get the textual content of a Rich Text value. This is similar to * `Element.textContent`. @@ -22,7 +14,5 @@ const pattern = new RegExp( * @return {string} The text content. */ export function getTextContent( { text } ) { - return text.replace( pattern, ( c ) => - c === OBJECT_REPLACEMENT_CHARACTER ? '' : '\n' - ); + return text.replace( OBJECT_REPLACEMENT_CHARACTER, '' ); } diff --git a/packages/rich-text/src/index.ts b/packages/rich-text/src/index.ts index 1f59320df3a63c..f487845a4cd76f 100644 --- a/packages/rich-text/src/index.ts +++ b/packages/rich-text/src/index.ts @@ -7,21 +7,19 @@ export { getActiveFormats } from './get-active-formats'; export { getActiveObject } from './get-active-object'; export { getTextContent } from './get-text-content'; export { isCollapsed } from './is-collapsed'; -export { isEmpty, isEmptyLine as __unstableIsEmptyLine } from './is-empty'; +export { isEmpty } from './is-empty'; export { join } from './join'; export { registerFormatType } from './register-format-type'; export { removeFormat } from './remove-format'; export { remove } from './remove'; export { replace } from './replace'; export { insert } from './insert'; -export { insertLineSeparator as __unstableInsertLineSeparator } from './insert-line-separator'; export { insertObject } from './insert-object'; export { slice } from './slice'; export { split } from './split'; export { toDom as __unstableToDom } from './to-dom'; export { toHTMLString } from './to-html-string'; export { toggleFormat } from './toggle-format'; -export { LINE_SEPARATOR as __UNSTABLE_LINE_SEPARATOR } from './special-characters'; export { unregisterFormatType } from './unregister-format-type'; export { createElement as __unstableCreateElement } from './create-element'; diff --git a/packages/rich-text/src/insert-line-separator.js b/packages/rich-text/src/insert-line-separator.js deleted file mode 100644 index d7a5aa0f97593f..00000000000000 --- a/packages/rich-text/src/insert-line-separator.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Internal dependencies - */ - -import { insert } from './insert'; -import { LINE_SEPARATOR } from './special-characters'; - -/** @typedef {import('./types').RichTextValue} RichTextValue */ - -/** - * Insert a line break character into a Rich Text value at the given - * `startIndex`. Any content between `startIndex` and `endIndex` will be - * removed. Indices are retrieved from the selection if none are provided. - * - * @param {RichTextValue} value Value to modify. - * @param {number} [startIndex] Start index. - * @param {number} [endIndex] End index. - * - * @return {RichTextValue} A new value with the value inserted. - */ -export function insertLineSeparator( - value, - startIndex = value.start, - endIndex = value.end -) { - const beforeText = value.text.slice( 0, startIndex ); - const previousLineSeparatorIndex = beforeText.lastIndexOf( LINE_SEPARATOR ); - const previousLineSeparatorFormats = - value.replacements[ previousLineSeparatorIndex ]; - let replacements = [ , ]; - - if ( previousLineSeparatorFormats ) { - replacements = [ previousLineSeparatorFormats ]; - } - - const valueToInsert = { - formats: [ , ], - replacements, - text: LINE_SEPARATOR, - }; - - return insert( value, valueToInsert, startIndex, endIndex ); -} diff --git a/packages/rich-text/src/is-empty.js b/packages/rich-text/src/is-empty.js index 7baf296bd2a3d6..86bc64bb36b565 100644 --- a/packages/rich-text/src/is-empty.js +++ b/packages/rich-text/src/is-empty.js @@ -1,8 +1,3 @@ -/** - * Internal dependencies - */ -import { LINE_SEPARATOR } from './special-characters'; - /** @typedef {import('./types').RichTextValue} RichTextValue */ /** @@ -16,34 +11,3 @@ import { LINE_SEPARATOR } from './special-characters'; export function isEmpty( { text } ) { return text.length === 0; } - -/** - * Check if the current collapsed selection is on an empty line in case of a - * multiline value. - * - * @param {RichTextValue} value Value te check. - * - * @return {boolean} True if the line is empty, false if not. - */ -export function isEmptyLine( { text, start, end } ) { - if ( start !== end ) { - return false; - } - - if ( text.length === 0 ) { - return true; - } - - if ( start === 0 && text.slice( 0, 1 ) === LINE_SEPARATOR ) { - return true; - } - - if ( start === text.length && text.slice( -1 ) === LINE_SEPARATOR ) { - return true; - } - - return ( - text.slice( start - 1, end + 1 ) === - `${ LINE_SEPARATOR }${ LINE_SEPARATOR }` - ); -} diff --git a/packages/rich-text/src/remove-line-separator.js b/packages/rich-text/src/remove-line-separator.js deleted file mode 100644 index fa45616a45a72a..00000000000000 --- a/packages/rich-text/src/remove-line-separator.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Internal dependencies - */ - -import { LINE_SEPARATOR } from './special-characters'; -import { isCollapsed } from './is-collapsed'; -import { remove } from './remove'; - -/** @typedef {import('./types').RichTextValue} RichTextValue */ - -/** - * Removes a line separator character, if existing, from a Rich Text value at - * the current indices. If no line separator exists on the indices it will - * return undefined. - * - * @param {RichTextValue} value Value to modify. - * @param {boolean} backward Indicates if are removing from the start - * index or the end index. - * - * @return {RichTextValue|undefined} A new value with the line separator - * removed. Or undefined if no line separator - * is found on the position. - */ -export function removeLineSeparator( value, backward = true ) { - const { replacements, text, start, end } = value; - const collapsed = isCollapsed( value ); - let index = start - 1; - let removeStart = collapsed ? start - 1 : start; - let removeEnd = end; - if ( ! backward ) { - index = end; - removeStart = start; - removeEnd = collapsed ? end + 1 : end; - } - - if ( text[ index ] !== LINE_SEPARATOR ) { - return; - } - - let newValue; - // If the line separator that is about te be removed - // contains wrappers, remove the wrappers first. - if ( collapsed && replacements[ index ] && replacements[ index ].length ) { - const newReplacements = replacements.slice(); - - newReplacements[ index ] = replacements[ index ].slice( 0, -1 ); - newValue = { - ...value, - replacements: newReplacements, - }; - } else { - newValue = remove( value, removeStart, removeEnd ); - } - return newValue; -} diff --git a/packages/rich-text/src/special-characters.js b/packages/rich-text/src/special-characters.js index 078525ec1777e6..a05f614daf94b7 100644 --- a/packages/rich-text/src/special-characters.js +++ b/packages/rich-text/src/special-characters.js @@ -1,8 +1,3 @@ -/** - * Line separator character, used for multiline text. - */ -export const LINE_SEPARATOR = '\u2028'; - /** * Object replacement character, used as a placeholder for objects. */ diff --git a/packages/rich-text/src/split.js b/packages/rich-text/src/split.js index cf329d7ef0985e..1853fb7bce585d 100644 --- a/packages/rich-text/src/split.js +++ b/packages/rich-text/src/split.js @@ -2,8 +2,6 @@ * Internal dependencies */ -import { replace } from './replace'; - /** @typedef {import('./types').RichTextValue} RichTextValue */ /** @@ -76,9 +74,5 @@ function splitAtSelection( end: 0, }; - return [ - // Ensure newlines are trimmed. - replace( before, /\u2028+$/, '' ), - replace( after, /^\u2028+/, '' ), - ]; + return [ before, after ]; } diff --git a/packages/rich-text/src/test/create.js b/packages/rich-text/src/test/create.js index 3f79f4f0fb78ef..212496c8cf6b8c 100644 --- a/packages/rich-text/src/test/create.js +++ b/packages/rich-text/src/test/create.js @@ -17,39 +17,28 @@ describe( 'create', () => { require( '../store' ); } ); - spec.forEach( - ( { - description, - multilineTag, - multilineWrapperTags, - html, - createRange, - record, - } ) => { - if ( html === undefined ) { - return; - } + spec.forEach( ( { description, html, createRange, record } ) => { + if ( html === undefined ) { + return; + } - // eslint-disable-next-line jest/valid-title - it( description, () => { - const element = createElement( document, html ); - const range = createRange( element ); - const createdRecord = create( { - element, - range, - multilineTag, - multilineWrapperTags, - } ); - const formatsLength = getSparseArrayLength( record.formats ); - const createdFormatsLength = getSparseArrayLength( - createdRecord.formats - ); - - expect( createdRecord ).toEqual( record ); - expect( createdFormatsLength ).toEqual( formatsLength ); + // eslint-disable-next-line jest/valid-title + it( description, () => { + const element = createElement( document, html ); + const range = createRange( element ); + const createdRecord = create( { + element, + range, } ); - } - ); + const formatsLength = getSparseArrayLength( record.formats ); + const createdFormatsLength = getSparseArrayLength( + createdRecord.formats + ); + + expect( createdRecord ).toEqual( record ); + expect( createdFormatsLength ).toEqual( formatsLength ); + } ); + } ); specWithRegistration.forEach( ( { diff --git a/packages/rich-text/src/test/helpers/index.js b/packages/rich-text/src/test/helpers/index.js index ae7521e55e25bf..cff9daa3e24ece 100644 --- a/packages/rich-text/src/test/helpers/index.js +++ b/packages/rich-text/src/test/helpers/index.js @@ -11,8 +11,6 @@ const em = { type: 'em' }; const strong = { type: 'strong' }; const img = { type: 'img', attributes: { src: '' } }; const a = { type: 'a', attributes: { href: '#' } }; -const ul = { type: 'ul' }; -const ol = { type: 'ol' }; export const spec = [ { @@ -440,200 +438,6 @@ export const spec = [ end: 2, }, }, - { - description: 'should handle empty multiline value', - multilineTag: 'p', - html: '
', - createRange: ( element ) => ( { - startOffset: 0, - startContainer: element.firstChild, - endOffset: 0, - endContainer: element.firstChild, - } ), - startPath: [ 0, 0, 0 ], - endPath: [ 0, 0, 0 ], - record: { - start: 0, - end: 0, - formats: [], - replacements: [], - text: '', - }, - }, - { - description: 'should handle multiline value', - multilineTag: 'p', - html: 'one
two
', - createRange: ( element ) => ( { - startOffset: 1, - startContainer: element.querySelector( 'p' ).firstChild, - endOffset: 0, - endContainer: element.lastChild, - } ), - startPath: [ 0, 0, 1 ], - endPath: [ 1, 0, 0 ], - record: { - start: 1, - end: 4, - formats: [ , , , , , , , ], - replacements: [ , , , , , , , ], - text: 'one\u2028two', - }, - }, - { - description: 'should handle multiline list value', - multilineTag: 'li', - multilineWrapperTags: [ 'ul', 'ol' ], - html: 'one
', - createRange: ( element ) => ( { - startOffset: 0, - startContainer: element.lastChild, - endOffset: 0, - endContainer: element.lastChild, - } ), - startPath: [ 1, 0, 0 ], - endPath: [ 1, 0, 0 ], - record: { - start: 4, - end: 4, - formats: [ , , , , ], - replacements: [ , , , , ], - text: 'one\u2028', - }, - }, - { - description: 'should handle multiline value with element selection', - multilineTag: 'li', - multilineWrapperTags: [ 'ul', 'ol' ], - html: '${ HTML }
` ); diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 305eebaf3e4a6e..e7288e4ba16332 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -104,7 +104,6 @@ function remove( node ) { export function toDom( { value, - multilineTag, prepareEditableTree, isEditableTree = true, placeholder, @@ -134,7 +133,6 @@ export function toDom( { const tree = toTree( { value, - multilineTag, createEmpty, append, getLastChild, @@ -165,13 +163,11 @@ export function toDom( { /** * Create an `Element` tree from a Rich Text value and applies the difference to - * the `Element` tree contained by `current`. If a `multilineTag` is provided, - * text separated by two new lines will be wrapped in an `Element` of that type. + * the `Element` tree contained by `current`. * * @param {Object} $1 Named arguments. * @param {RichTextValue} $1.value Value to apply. * @param {HTMLElement} $1.current The live root node to apply the element tree to. - * @param {string} [$1.multilineTag] Multiline tag. * @param {Function} [$1.prepareEditableTree] Function to filter editorable formats. * @param {boolean} [$1.__unstableDomOnly] Only apply elements, no selection. * @param {string} [$1.placeholder] Placeholder text. @@ -179,7 +175,6 @@ export function toDom( { export function apply( { value, current, - multilineTag, prepareEditableTree, __unstableDomOnly, placeholder, @@ -187,7 +182,6 @@ export function apply( { // Construct a new element tree in memory. const { body, selection } = toDom( { value, - multilineTag, prepareEditableTree, placeholder, doc: current.ownerDocument, diff --git a/packages/rich-text/src/to-html-string.js b/packages/rich-text/src/to-html-string.js index 0b2689248afb72..66ae1d82b38450 100644 --- a/packages/rich-text/src/to-html-string.js +++ b/packages/rich-text/src/to-html-string.js @@ -17,21 +17,18 @@ import { toTree } from './to-tree'; /** @typedef {import('./types').RichTextValue} RichTextValue */ /** - * Create an HTML string from a Rich Text value. If a `multilineTag` is - * provided, text separated by a line separator will be wrapped in it. + * Create an HTML string from a Rich Text value. * * @param {Object} $1 Named argements. * @param {RichTextValue} $1.value Rich text value. - * @param {string} [$1.multilineTag] Multiline tag. * @param {boolean} [$1.preserveWhiteSpace] Whether or not to use newline * characters for line breaks. * * @return {string} HTML string. */ -export function toHTMLString( { value, multilineTag, preserveWhiteSpace } ) { +export function toHTMLString( { value, preserveWhiteSpace } ) { const tree = toTree( { value, - multilineTag, preserveWhiteSpace, createEmpty, append, diff --git a/packages/rich-text/src/to-tree.js b/packages/rich-text/src/to-tree.js index 4db974aaad7142..c380570db561de 100644 --- a/packages/rich-text/src/to-tree.js +++ b/packages/rich-text/src/to-tree.js @@ -4,11 +4,7 @@ import { getActiveFormats } from './get-active-formats'; import { getFormatType } from './get-format-type'; -import { - LINE_SEPARATOR, - OBJECT_REPLACEMENT_CHARACTER, - ZWNBSP, -} from './special-characters'; +import { OBJECT_REPLACEMENT_CHARACTER, ZWNBSP } from './special-characters'; function restoreOnAttributes( attributes, isEditableTree ) { if ( isEditableTree ) { @@ -133,7 +129,6 @@ function isEqualUntil( a, b, index ) { export function toTree( { value, - multilineTag, preserveWhiteSpace, createEmpty, append, @@ -151,21 +146,13 @@ export function toTree( { const { formats, replacements, text, start, end } = value; const formatsLength = formats.length + 1; const tree = createEmpty(); - const multilineFormat = { type: multilineTag }; const activeFormats = getActiveFormats( value ); const deepestActiveFormat = activeFormats[ activeFormats.length - 1 ]; - let lastSeparatorFormats; let lastCharacterFormats; let lastCharacter; - // If we're building a multiline tree, start off with a multiline element. - if ( multilineTag ) { - append( append( tree, { type: multilineTag } ), '' ); - lastCharacterFormats = lastSeparatorFormats = [ multilineFormat ]; - } else { - append( tree, '' ); - } + append( tree, '' ); for ( let i = 0; i < formatsLength; i++ ) { const character = text.charAt( i ); @@ -173,62 +160,13 @@ export function toTree( { isEditableTree && // Pad the line if the line is empty. ( ! lastCharacter || - lastCharacter === LINE_SEPARATOR || // Pad the line if the previous character is a line break, otherwise // the line break won't be visible. lastCharacter === '\n' ); - let characterFormats = formats[ i ]; - - // Set multiline tags in queue for building the tree. - if ( multilineTag ) { - if ( character === LINE_SEPARATOR ) { - characterFormats = lastSeparatorFormats = ( - replacements[ i ] || [] - ).reduce( - ( accumulator, format ) => { - accumulator.push( format, multilineFormat ); - return accumulator; - }, - [ multilineFormat ] - ); - } else { - characterFormats = [ - ...lastSeparatorFormats, - ...( characterFormats || [] ), - ]; - } - } - + const characterFormats = formats[ i ]; let pointer = getLastChild( tree ); - if ( shouldInsertPadding && character === LINE_SEPARATOR ) { - let node = pointer; - - while ( ! isText( node ) ) { - node = getLastChild( node ); - } - - append( getParent( node ), ZWNBSP ); - } - - // Set selection for the start of line. - if ( lastCharacter === LINE_SEPARATOR ) { - let node = pointer; - - while ( ! isText( node ) ) { - node = getLastChild( node ); - } - - if ( onStartIndex && start === i ) { - onStartIndex( tree, node ); - } - - if ( onEndIndex && end === i ) { - onEndIndex( tree, node ); - } - } - if ( characterFormats ) { characterFormats.forEach( ( format, formatIndex ) => { if ( @@ -239,11 +177,7 @@ export function toTree( { characterFormats, lastCharacterFormats, formatIndex - ) && - // Do not reuse the last element if the character is a - // line separator. - ( character !== LINE_SEPARATOR || - characterFormats.length - 1 !== formatIndex ) + ) ) { pointer = getLastChild( pointer ); return; @@ -253,9 +187,7 @@ export function toTree( { format; const boundaryClass = - isEditableTree && - character !== LINE_SEPARATOR && - format === deepestActiveFormat; + isEditableTree && format === deepestActiveFormat; const parent = getParent( pointer ); const newNode = append( @@ -278,13 +210,6 @@ export function toTree( { } ); } - // No need for further processing if the character is a line separator. - if ( character === LINE_SEPARATOR ) { - lastCharacterFormats = characterFormats; - lastCharacter = character; - continue; - } - // If there is selection at 0, handle it before characters are inserted. if ( i === 0 ) { if ( onStartIndex && start === 0 ) {