Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions packages/editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,8 @@ export class RichText extends Component {
// If we click shift+Enter on inline RichTexts, we avoid creating two contenteditables
// We also split the content and call the onSplit prop if provided.
if ( keyCode === ENTER ) {
event.preventDefault();

if ( this.props.onReplace ) {
const text = getTextContent( this.getRecord() );
const transformation = findTransform( this.enterPatterns, ( item ) => {
Expand All @@ -603,7 +605,6 @@ export class RichText extends Component {
// important that we stop other handlers (e.g. ones
// registered by TinyMCE) from also handling this event.
event.stopImmediatePropagation();
event.preventDefault();
this.props.onReplace( [
transformation.transform( { content: text } ),
] );
Expand All @@ -612,27 +613,33 @@ export class RichText extends Component {
}

if ( this.props.multiline ) {
if ( ! this.props.onSplit ) {
return;
}

const record = this.getRecord();

if ( ! isEmptyLine( record ) ) {
return;
if ( this.props.onSplit && isEmptyLine( record ) ) {
this.props.onSplit( ...split( record ).map( this.valueToFormat ) );
} else {
// Character is used to separate lines in multiline values.
this.onChange( insert( record, '\u2028' ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why Unicode 2028 instead of a plain (ASCII-level) line break?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we're using that to delimit lines in multiline values. We could probably benefit from a helper or a constant...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And \n are used for single line breaks which convert to <br> elements.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair, but let's add a comment for it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment then 🚢 🚢 !

}
} else if ( event.shiftKey || ! this.props.onSplit ) {
const record = this.getRecord();
const text = getTextContent( record );
const length = text.length;
let toInsert = '\n';

// If the caret is at the end of the text, and there is no
// trailing line break or no text at all, we have to insert two
// line breaks in order to create a new line visually and place
// the caret there.
if ( record.end === length && (
text.charAt( length - 1 ) !== '\n' || length === 0
) ) {
toInsert = '\n\n';
}

event.preventDefault();

this.props.onSplit( ...split( record ).map( this.valueToFormat ) );
this.onChange( insert( this.getRecord(), toInsert ) );
} else {
event.preventDefault();

if ( event.shiftKey || ! this.props.onSplit ) {
this.editor.execCommand( 'InsertLineBreak', false, event );
} else {
this.splitContent();
}
this.splitContent();
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions packages/rich-text/src/create-element.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Parse the given HTML into a body element.
*
* @param {HTMLDocument} document The HTML document to use to parse.
* @param {string} html The HTML to parse.
*
* @return {HTMLBodyElement} Body element with parsed HTML.
*/
export function createElement( { implementation }, html ) {
const { body } = implementation.createHTMLDocument( '' );
body.innerHTML = html;
return body;
}
24 changes: 8 additions & 16 deletions packages/rich-text/src/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,14 @@

import { isEmpty } from './is-empty';
import { isFormatEqual } from './is-format-equal';
import { createElement } from './create-element';

/**
* Browser dependencies
*/

const { TEXT_NODE, ELEMENT_NODE } = window.Node;

/**
* Parse the given HTML into a body element.
*
* @param {string} html The HTML to parse.
*
* @return {HTMLBodyElement} Body element with parsed HTML.
*/
function createElement( html ) {
const htmlDocument = document.implementation.createHTMLDocument( '' );

htmlDocument.body.innerHTML = html;

return htmlDocument.body;
}

function createEmptyValue() {
return { formats: [], text: '' };
}
Expand Down Expand Up @@ -74,7 +60,7 @@ export function create( {
}

if ( typeof html === 'string' && html.length > 0 ) {
element = createElement( html );
element = createElement( document, html );
}

if ( typeof element !== 'object' ) {
Expand Down Expand Up @@ -147,6 +133,12 @@ function accumulateSelection( accumulator, node, range, value ) {
node === endContainer.childNodes[ endOffset - 1 ]
) {
accumulator.end = currentLength + value.text.length;
// Range indicates that the selection is before the current node.
} else if (
parentNode === endContainer &&
node === endContainer.childNodes[ endOffset ]
) {
accumulator.end = currentLength;
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/rich-text/src/split.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ export function split( { formats, text, start, end }, string ) {
nextStart += string.length + substring.length;

if ( start !== undefined && end !== undefined ) {
if ( start > startIndex && start < nextStart ) {
if ( start >= startIndex && start < nextStart ) {
value.start = start - startIndex;
} else if ( start < startIndex && end > startIndex ) {
value.start = 0;
}

if ( end > startIndex && end < nextStart ) {
if ( end >= startIndex && end < nextStart ) {
value.end = end - startIndex;
} else if ( start < nextStart && end > nextStart ) {
value.end = substring.length;
Expand Down
Loading