Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOM: Restore horizontal edge traversal implementation #8461

Merged
merged 2 commits into from
Aug 7, 2018
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
57 changes: 48 additions & 9 deletions packages/dom/src/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,54 @@ export function isHorizontalEdge( container, isReverse ) {
range.collapse( ! isSelectionForward( selection ) );
}

const { endContainer, endOffset } = range;
range.selectNodeContents( container );
range.setEnd( endContainer, endOffset );

// Check if the caret position is at the expected start/end position based
// on the value of `isReverse`. If so, consider the horizontal edge to be
// reached.
const caretOffset = range.toString().length;
return caretOffset === ( isReverse ? 0 : container.textContent.length );
let node = range.startContainer;

let extentOffset;
if ( isReverse ) {
// When in reverse, range node should be first.
extentOffset = 0;
} else if ( node.nodeValue ) {
// Otherwise, vary by node type. A text node has no children. Its range
// offset reflects its position in nodeValue.
//
// "If the startContainer is a Node of type Text, Comment, or
// CDATASection, then the offset is the number of characters from the
// start of the startContainer to the boundary point of the Range."
//
// See: https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
// See: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue
extentOffset = node.nodeValue.length;
} else {
// "For other Node types, the startOffset is the number of child nodes
// between the start of the startContainer and the boundary point of
// the Range."
//
// See: https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
extentOffset = node.childNodes.length;
}

// Offset of range should be at expected extent.
const position = isReverse ? 'start' : 'end';
const offset = range[ `${ position }Offset` ];
if ( offset !== extentOffset ) {
return false;
}

// If confirmed to be at extent, traverse up through DOM, verifying that
// the node is at first or last child for reverse or forward respectively.
// Continue until container is reached.
const order = isReverse ? 'first' : 'last';
while ( node !== container ) {
const parentNode = node.parentNode;
if ( parentNode[ `${ order }Child` ] !== node ) {
return false;
}

node = parentNode;
}

// If reached, range is assumed to be at edge.
return true;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions test/e2e/specs/__snapshots__/splitting-merging.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`splitting and merging blocks Should delete an empty first line 1`] = `
"<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->"
`;

exports[`splitting and merging blocks Should merge into inline boundary position 1`] = `
"<!-- wp:paragraph -->
<p>Bar</p>
Expand Down
17 changes: 17 additions & 0 deletions test/e2e/specs/splitting-merging.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,21 @@ describe( 'splitting and merging blocks', () => {

expect( await getEditedPostContent() ).toMatchSnapshot();
} );

it( 'Should delete an empty first line', async () => {
// Regression Test: When a paragraph block has line break, and the first
// line has no text, pressing backspace at the start of the second line
// should remove the first.
//
// See: https://github.com/WordPress/gutenberg/issues/8388
await insertBlock( 'Paragraph' );
await page.keyboard.down( 'Shift' );
await page.keyboard.press( 'Enter' );
await page.keyboard.up( 'Shift' );

// Delete the soft line break.
await page.keyboard.press( 'Backspace' );

expect( await getEditedPostContent() ).toMatchSnapshot();
} );
} );