Define "precedes/follows a line break"
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Wed, 22 Jun 2011 13:08:34 -0600
changeset 309 c0fc2d85fb82
parent 308 fb902b8019df
child 310 0278f12af2f4
Define "precedes/follows a line break"

I'm not actually sure if there are any functional changes in how I'm
using these compared to before, but it helps centralize things so that
they can be replaced by better definitions if it becomes necessary.
editcommands.html
implementation.js
preprocess
source.html
--- a/editcommands.html	Tue Jun 21 16:18:46 2011 -0600
+++ b/editcommands.html	Wed Jun 22 13:08:34 2011 -0600
@@ -38,7 +38,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-21-june-2011>Work in Progress &mdash; Last Update 21 June 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-22-june-2011>Work in Progress &mdash; Last Update 22 June 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -582,6 +582,48 @@
 <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> it, then <a href=#remove-extraneous-line-breaks-at-the-end-of>remove
 extraneous line breaks at the end of</a> it.
 
+<p>A <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <dfn id=follows-a-line-break>follows a line break</dfn> if the following
+algorithm returns true:
+
+<p class=XXX>Editorial issue: These two algorithms depend on block-extending.
+Should that get moved up to the general algorithms?
+
+<ol>
+  <li>Let <var title="">offset</var> be zero.
+
+  <li>While <var title="">offset</var> is zero, set <var title="">offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
+  of <var title="">node</var> and then set <var title="">node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+  <li>Let <var title="">range</var> be a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
+  (<var title="">node</var>, <var title="">offset</var>).
+
+  <li><a href=#block-extend>Block-extend</a> <var title="">range</var>, and let <var title="">new range</var>
+  be the result.
+
+  <li>Return false if <var title="">new range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-bp-before title=concept-bp-before>before</a>
+  (<var title="">node</var>, <var title="">offset</var>), true otherwise.
+</ol>
+
+<p>A <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> <dfn id=precedes-a-line-break>precedes a line break</dfn> if the following
+algorithm returns true:
+
+<ol>
+  <li>Let <var title="">offset</var> be the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">node</var>.
+
+  <li>While <var title="">offset</var> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">node</var>, set
+  <var title="">offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">node</var> and then set
+  <var title="">node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+  <li>Let <var title="">range</var> be a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
+  (<var title="">node</var>, <var title="">offset</var>).
+
+  <li><a href=#block-extend>Block-extend</a> <var title="">range</var>, and let <var title="">new range</var>
+  be the result.
+
+  <li>Return false if <var title="">new range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> is <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-bp-after title=concept-bp-after>after</a>
+  (<var title="">node</var>, <var title="">offset</var>), true otherwise.
+</ol>
+
 <p>To <dfn id=split-the-parent>split the parent</dfn> of a list <var title="">node list</var> of consecutive
 <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-sibling title=concept-tree-sibling>sibling</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>:
 
@@ -603,14 +645,15 @@
   list</var>, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> <var title="">original
   parent</var>.
 
-  <li>If <var title="">original parent</var> is not an <a href=#inline-node>inline node</a>, and the
-  last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node list</var>, and
-  <var title="">original parent</var>'s last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> and <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> are both
-  <a href=#inline-node title="inline node">inline nodes</a>, and <var title="">original
-  parent</var>'s last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
-  <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">original parent</var>, then insert the result into
-  the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately after <var title="">original
-  parent</var>.
+  <li>If the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
+  list</var>, and <var title="">original parent</var> <a href=#follows-a-line-break>follows a line break</a>,
+  set <var title="">follows line break</var> to true.  Otherwise, set <var title="">follows line
+  break</var> to false.
+
+  <li>If the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
+  list</var>, and <var title="">original parent</var> <a href=#precedes-a-line-break>precedes a line
+  break</a>, set <var title="">precedes line break</var> to true.  Otherwise, set
+  <var title="">precedes line break</var> to false.
 
   <li>If the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is not in <var title="">node
   list</var>, but its last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is:
@@ -641,6 +684,12 @@
     parent</var> immediately after <var title="">original parent</var>, <a href=#preserving-ranges>preserving
     ranges</a>.
 
+    <li>If <var title="">precedes line break</var> is true, and the last member of
+    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
+    line break</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+    insert the result immediately after the last member of <var title="">node
+    list</var>.
+
     <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">original
     parent</var>.
 
@@ -670,13 +719,6 @@
     <a href=#preserving-ranges>preserving ranges</a>.
   </ol>
 
-  <li>If the first member of <var title="">node list</var> is an <a href=#inline-node>inline
-  node</a>, and <var title="">original parent</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> is an
-  <a href=#inline-node>inline node</a> other than a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, and <var title="">original parent</var>
-  is not an <a href=#inline-node>inline node</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>, then insert the result into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of
-  <var title="">original parent</var> immediately before <var title="">original parent</var>.
-
   <li>For each <var title="">node</var> in <var title="">node list</var>, insert <var title="">node</var>
   into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately before
   <var title="">original parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
@@ -687,14 +729,29 @@
   removing the element in the final step.  Preserving ranges is only necessary
   for the sake of boundary points in the element or its descendants. -->
 
+  <li>If <var title="">follows line break</var> is true, and the first member of
+  <var title="">node list</var> does not <a href=#follows-a-line-break title="follows a line break">follow a
+  line break</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+  insert the result immediately before the first member of <var title="">node
+  list</var>.
+
   <li>If the last member of <var title="">node list</var> is an <a href=#inline-node>inline node</a>
   other than a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, and the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is
   a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, and <var title="">original parent</var> is not an <a href=#inline-node>inline node</a>,
   remove the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> from <var title="">original
   parent</var>.
 
-  <li>If <var title="">original parent</var> has no <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, remove it from its
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+  <li>If <var title="">original parent</var> has no <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>:
+
+  <ol>
+    <li>Remove <var title="">original parent</var> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+    <li>If <var title="">precedes line break</var> is true, and the last member of
+    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
+    line break</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+    insert the result immediately after the last member of <var title="">node
+    list</var>.
+  </ol>
 
   <li>Otherwise, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a>
   <var title="">original parent</var>.
--- a/implementation.js	Tue Jun 21 16:18:46 2011 -0600
+++ b/implementation.js	Wed Jun 22 13:08:34 2011 -0600
@@ -898,6 +898,52 @@
 	removeExtraneousLineBreaksAtTheEndOf(node);
 }
 
+function followsLineBreak(node) {
+	// "Let offset be zero."
+	var offset = 0;
+
+	// "While offset is zero, set offset to the index of node and then set node
+	// to its parent."
+	while (offset == 0) {
+		offset = getNodeIndex(node);
+		node = node.parentNode;
+	}
+
+	// "Let range be a range with start and end (node, offset)."
+	var range = document.createRange();
+	range.setStart(node, offset);
+
+	// "Block-extend range, and let new range be the result."
+	var newRange = blockExtendRange(range);
+
+	// "Return false if new range's start is before (node, offset), true
+	// otherwise."
+	return getPosition(newRange.startContainer, newRange.startOffset, node, offset) != "before";
+}
+
+function precedesLineBreak(node) {
+	// "Let offset be the length of node."
+	var offset = getNodeLength(node);
+
+	// "While offset is the length of node, set offset to one plus the index of
+	// node and then set node to its parent."
+	while (offset == getNodeLength(node)) {
+		offset = 1 + getNodeIndex(node);
+		node = node.parentNode;
+	}
+
+	// "Let range be a range with start and end (node, offset)."
+	var range = document.createRange();
+	range.setStart(node, offset);
+
+	// "Block-extend range, and let new range be the result."
+	var newRange = blockExtendRange(range);
+
+	// "Return false if new range's end is after (node, offset), true
+	// otherwise."
+	return getPosition(newRange.endContainer, newRange.endOffset, node, offset) != "after";
+}
+
 function splitParent(nodeList) {
 	// "Let original parent be the parent of the first member of node list."
 	var originalParent = nodeList[0].parentNode;
@@ -915,19 +961,17 @@
 		removeExtraneousLineBreaksBefore(originalParent);
 	}
 
-	// "If original parent is not an inline node, and the last child of
-	// original parent is in node list, and original parent's last child and
-	// nextSibling are both inline nodes, and original parent's last child is
-	// not a br, call createElement("br") on the ownerDocument of original
-	// parent, then insert the result into the parent of original parent
-	// immediately after original parent."
-	if (!isInlineNode(originalParent)
-	&& nodeList.indexOf(originalParent.lastChild) != -1
-	&& isInlineNode(originalParent.lastChild)
-	&& isInlineNode(originalParent.nextSibling)
-	&& !isHtmlElement(originalParent.lastChild, "br")) {
-		originalParent.parentNode.insertBefore(originalParent.ownerDocument.createElement("br"), originalParent.nextSibling);
-	}
+	// "If the first child of original parent is in node list, and original
+	// parent follows a line break, set follows line break to true. Otherwise,
+	// set follows line break to false."
+	var followsLineBreak_ = nodeList.indexOf(originalParent.firstChild) != -1
+		&& followsLineBreak(originalParent);
+
+	// "If the last child of original parent is in node list, and original
+	// parent precedes a line break, set precedes line break to true.
+	// Otherwise, set precedes line break to false."
+	var precedesLineBreak_ = nodeList.indexOf(originalParent.lastChild) != -1
+		&& precedesLineBreak(originalParent);
 
 	// "If the first child of original parent is not in node list, but its last
 	// child is:"
@@ -940,6 +984,15 @@
 			movePreservingRanges(nodeList[i], originalParent.parentNode, 1 + getNodeIndex(originalParent));
 		}
 
+		// "If precedes line break is true, and the last member of node list
+		// does not precede a line break, call createElement("br") on the
+		// context object and insert the result immediately after the last
+		// member of node list."
+		if (precedesLineBreak_
+		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
+			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
+		}
+
 		// "Remove extraneous line breaks at the end of original parent."
 		removeExtraneousLineBreaksAtTheEndOf(originalParent);
 
@@ -965,24 +1018,20 @@
 		}
 	}
 
-	// "If the first member of node list is an inline node, and original
-	// parent's previousSibling is an inline node other than a br, and original
-	// parent is not an inline node, call createElement("br") on the context
-	// object, then insert the result into the parent of original parent
-	// immediately before original parent."
-	if (isInlineNode(nodeList[0])
-	&& isInlineNode(originalParent.previousSibling)
-	&& !isHtmlElement(originalParent.previousSibling, "br")
-	&& !isInlineNode(originalParent)) {
-		originalParent.parentNode.insertBefore(document.createElement("br"), originalParent);
-	}
-
 	// "For each node in node list, insert node into the parent of original
 	// parent immediately before original parent, preserving ranges."
 	for (var i = 0; i < nodeList.length; i++) {
 		movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));
 	}
 
+	// "If follows line break is true, and the first member of node list does
+	// not follow a line break, call createElement("br") on the context object
+	// and insert the result immediately before the first member of node list."
+	if (followsLineBreak_
+	&& !followsLineBreak(nodeList[0])) {
+		nodeList[0].parentNode.insertBefore(document.createElement("br"), nodeList[0]);
+	}
+
 	// "If the last member of node list is an inline node other than a br, and
 	// the first child of original parent is a br, and original parent is not
 	// an inline node, remove the first child of original parent from original
@@ -994,10 +1043,20 @@
 		originalParent.removeChild(originalParent.firstChild);
 	}
 
-	// "If original parent has no children, remove it from its parent."
+	// "If original parent has no children:"
 	if (!originalParent.hasChildNodes()) {
+		// "Remove original parent from its parent."
 		originalParent.parentNode.removeChild(originalParent);
 
+		// "If precedes line break is true, and the last member of node list
+		// does not precede a line break, call createElement("br") on the
+		// context object and insert the result immediately after the last
+		// member of node list."
+		if (precedesLineBreak_
+		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
+			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
+		}
+
 	// "Otherwise, remove extraneous line breaks before original parent."
 	} else {
 		removeExtraneousLineBreaksBefore(originalParent);
--- a/preprocess	Tue Jun 21 16:18:46 2011 -0600
+++ b/preprocess	Wed Jun 22 13:08:34 2011 -0600
@@ -16,6 +16,8 @@
     'blockquote': '<code data-anolis-spec=html title="the blockquote element">blockquote</code>',
     'br': '<code data-anolis-spec=html title="the br element">br</code>',
     'boundarypoint': '<span data-anolis-spec=domrange title=concept-boundary-point>boundary point</span>',
+    'bpafter': '<span data-anolis-spec=domrange title=concept-bp-after>after</span>',
+    'bpbefore': '<span data-anolis-spec=domrange title=concept-bp-before>before</span>',
     'bpnode': '<span data-anolis-spec=domrange title=concept-boundary-point-node>node</span>',
     'bpoffset': '<span data-anolis-spec=domrange title=concept-boundary-point-offset>offset</span>',
     'bpposition': '<span data-anolis-spec=domrange title=concept-bp-position>position</span>',
--- a/source.html	Tue Jun 21 16:18:46 2011 -0600
+++ b/source.html	Wed Jun 22 13:08:34 2011 -0600
@@ -527,6 +527,48 @@
 <span>remove extraneous line breaks before</span> it, then <span>remove
 extraneous line breaks at the end of</span> it.
 
+<p>A [[node]] <var>node</var> <dfn>follows a line break</dfn> if the following
+algorithm returns true:
+
+<p class=XXX>Editorial issue: These two algorithms depend on block-extending.
+Should that get moved up to the general algorithms?
+
+<ol>
+  <li>Let <var>offset</var> be zero.
+
+  <li>While <var>offset</var> is zero, set <var>offset</var> to the [[index]]
+  of <var>node</var> and then set <var>node</var> to its [[parent]].
+
+  <li>Let <var>range</var> be a [[range]] with [[rangestart]] and [[rangeend]]
+  (<var>node</var>, <var>offset</var>).
+
+  <li><span>Block-extend</span> <var>range</var>, and let <var>new range</var>
+  be the result.
+
+  <li>Return false if <var>new range</var>'s [[rangestart]] is [[bpbefore]]
+  (<var>node</var>, <var>offset</var>), true otherwise.
+</ol>
+
+<p>A [[node]] <var>node</var> <dfn>precedes a line break</dfn> if the following
+algorithm returns true:
+
+<ol>
+  <li>Let <var>offset</var> be the [[length]] of <var>node</var>.
+
+  <li>While <var>offset</var> is the [[length]] of <var>node</var>, set
+  <var>offset</var> to one plus the [[index]] of <var>node</var> and then set
+  <var>node</var> to its [[parent]].
+
+  <li>Let <var>range</var> be a [[range]] with [[rangestart]] and [[rangeend]]
+  (<var>node</var>, <var>offset</var>).
+
+  <li><span>Block-extend</span> <var>range</var>, and let <var>new range</var>
+  be the result.
+
+  <li>Return false if <var>new range</var>'s [[rangeend]] is [[bpafter]]
+  (<var>node</var>, <var>offset</var>), true otherwise.
+</ol>
+
 <p>To <dfn>split the parent</dfn> of a list <var>node list</var> of consecutive
 [[sibling]] [[nodes]]:
 
@@ -548,16 +590,15 @@
   list</var>, <span>remove extraneous line breaks before</span> <var>original
   parent</var>.
 
-  <li>If <var>original parent</var> is not an <span>inline node</span>, and the
-  last [[child]] of <var>original parent</var> is in <var>node list</var>, and
-  <var>original parent</var>'s last [[child]] and [[nextsibling]] are both
-  <span title="inline node">inline nodes</span>, and <var>original
-  parent</var>'s last [[child]] is not a [[br]], call <code
-  data-anolis-spec=domcore
-  title=dom-Document-createElement>createElement("br")</code> on the
-  [[ownerdocument]] of <var>original parent</var>, then insert the result into
-  the [[parent]] of <var>original parent</var> immediately after <var>original
-  parent</var>.
+  <li>If the first [[child]] of <var>original parent</var> is in <var>node
+  list</var>, and <var>original parent</var> <span>follows a line break</span>,
+  set <var>follows line break</var> to true.  Otherwise, set <var>follows line
+  break</var> to false.
+
+  <li>If the last [[child]] of <var>original parent</var> is in <var>node
+  list</var>, and <var>original parent</var> <span>precedes a line
+  break</span>, set <var>precedes line break</var> to true.  Otherwise, set
+  <var>precedes line break</var> to false.
 
   <li>If the first [[child]] of <var>original parent</var> is not in <var>node
   list</var>, but its last [[child]] is:
@@ -588,6 +629,12 @@
     parent</var> immediately after <var>original parent</var>, <span>preserving
     ranges</span>.
 
+    <li>If <var>precedes line break</var> is true, and the last member of
+    <var>node list</var> does not <span title="precedes a line break">precede a
+    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+    insert the result immediately after the last member of <var>node
+    list</var>.
+
     <li><span>Remove extraneous line breaks at the end of</span> <var>original
     parent</var>.
 
@@ -618,13 +665,6 @@
     <span>preserving ranges</span>.
   </ol>
 
-  <li>If the first member of <var>node list</var> is an <span>inline
-  node</span>, and <var>original parent</var>'s [[previoussibling]] is an
-  <span>inline node</span> other than a [[br]], and <var>original parent</var>
-  is not an <span>inline node</span>, call [[createelement|"br"]] on the
-  [[contextobject]], then insert the result into the [[parent]] of
-  <var>original parent</var> immediately before <var>original parent</var>.
-
   <li>For each <var>node</var> in <var>node list</var>, insert <var>node</var>
   into the [[parent]] of <var>original parent</var> immediately before
   <var>original parent</var>, <span>preserving ranges</span>.
@@ -635,14 +675,29 @@
   removing the element in the final step.  Preserving ranges is only necessary
   for the sake of boundary points in the element or its descendants. -->
 
+  <li>If <var>follows line break</var> is true, and the first member of
+  <var>node list</var> does not <span title="follows a line break">follow a
+  line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+  insert the result immediately before the first member of <var>node
+  list</var>.
+
   <li>If the last member of <var>node list</var> is an <span>inline node</span>
   other than a [[br]], and the first [[child]] of <var>original parent</var> is
   a [[br]], and <var>original parent</var> is not an <span>inline node</span>,
   remove the first [[child]] of <var>original parent</var> from <var>original
   parent</var>.
 
-  <li>If <var>original parent</var> has no [[children]], remove it from its
-  [[parent]].
+  <li>If <var>original parent</var> has no [[children]]:
+
+  <ol>
+    <li>Remove <var>original parent</var> from its [[parent]].
+
+    <li>If <var>precedes line break</var> is true, and the last member of
+    <var>node list</var> does not <span title="precedes a line break">precede a
+    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+    insert the result immediately after the last member of <var>node
+    list</var>.
+  </ol>
 
   <li>Otherwise, <span>remove extraneous line breaks before</span>
   <var>original parent</var>.