--- a/autoimplementation.html Tue Jun 07 09:57:19 2011 -0600
+++ b/autoimplementation.html Tue Jun 07 10:21:41 2011 -0600
@@ -314,6 +314,9 @@
'<p>foo<br></p><p>[]bar</p>',
'<p>foo<br></p>[]bar',
'foo<br><p>[]bar</p>',
+ '<p>foo<br><br></p><p>[]bar</p>',
+ '<p>foo<br><br></p>[]bar',
+ 'foo<br><br><p>[]bar</p>',
'<div>foo</div><div>[]bar</div>',
'<pre>foo</pre>[]bar',
'foo<br>[]bar',
--- a/editcommands.html Tue Jun 07 09:57:19 2011 -0600
+++ b/editcommands.html Tue Jun 07 10:21:41 2011 -0600
@@ -2481,6 +2481,7 @@
<li>If <var title="">node</var> is a <a href=#prohibited-paragraph-child>prohibited paragraph child</a> and
<var title="">offset</var> is zero:
+ <!-- Then we'll typically want to merge backward into the previous block. -->
<ol>
<li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
@@ -2489,15 +2490,57 @@
<li>Let <var title="">start node</var> equal <var title="">node</var> and let <var title="">start
offset</var> equal <var title="">offset</var>.
- <li>While <var title="">start offset</var> is zero, set <var title="">start 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="">start node</var> and then set <var title="">start 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>.
-
+ <!--
+ Go up until we're no longer at the beginning of an element. As a special
+ case, we make sure to remove a preceding extraneous line break in cases
+ like
+
+ foo<br><p>[]bar</p>
+ -> foo<p>[]bar</p>
+ -> foo[]bar.
+
+ We have to take care that we remove the line break before we go all the way
+ up to the node that contains the line break. Otherwise the offset will no
+ longer be correct: it will be one too high. (Try removing "and start node
+ is the first child of its parent" from the next line, and the two lines
+ after the extraneous line break removal, and see what happens.)
+ -->
+ <li>While <var title="">start offset</var> is zero and <var title="">start node</var> is 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 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>, set <var title="">start 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="">start node</var> and then set <var title="">start 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><a href=#remove-extraneous-line-breaks-before>Remove extraneous line breaks before</a> <var title="">start
+ node</var>.
+
+ <li>Set <var title="">start 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="">start node</var>.
+
+ <li>Set <var title="">start 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>.
+
+ <!--
+ Special case:
+
+ <p>foo</p><br><p>[]bar</p>
+ -> <p>foo</p><p>[]bar</p>
+
+ and likewise for <hr>. But with <img> we merge like in other cases:
+
+ <p>foo</p><img><p>[]bar</p>
+ -> <p>foo</p><img>[]bar.
+
+ Browsers don't do this consistently. Firefox 5.0a2 doesn't seem to do it
+ at all.
+ -->
<li>If the <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="">start node</var> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
- offset</var> minus one 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> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>, set
- <var title="">node</var> to <var title="">start node</var> and <var title="">offset</var> to
- <var title="">start offset</var>, then subtract one from <var title="">start offset</var>.
-
+ offset</var> minus one 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> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code>, set <var title="">node</var> to
+ <var title="">start node</var> and <var title="">offset</var> to <var title="">start offset</var>,
+ then subtract one from <var title="">start offset</var>.
+
+ <!--
+ Regular case: for <p>foo</p><p>[]bar</p>, we delete <p>foo{</p><p>}bar</p>.
+ This will also happen if the preceding element is a span or something, but
+ that doesn't hurt.
+ -->
<li>Otherwise, set <var title="">start 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-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
<var title="">start offset</var> minus one, then set <var title="">start offset</var> to 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="">start node</var>.
@@ -2506,6 +2549,16 @@
whose 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 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="">start 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="">start node</var>, subtract one from <var title="">start
offset</var>.
+ <!--
+ It wouldn't be enough to just remove extraneous line breaks at the end of
+ start node, because we want to remove the line break even if it's not
+ actually extraneous. For instance,
+
+ <p>foo<br><br></p><p>[]bar</p>
+ -> <p>foo<br>bar</p>
+ not
+ -> <p>foo<br><br>bar</p>.
+ -->
<li><a href=#delete-the-contents>Delete the contents</a> of the <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>
(<var title="">start node</var>, <var title="">start offset</var>) 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>
--- a/implementation.js Tue Jun 07 09:57:19 2011 -0600
+++ b/implementation.js Tue Jun 07 10:21:41 2011 -0600
@@ -3191,17 +3191,28 @@
var startNode = node;
var startOffset = offset;
- // "While start offset is zero, set start offset to the index of
- // start node and then set start node to its parent."
- while (startOffset == 0) {
+ // "While start offset is zero and start node is the first child of
+ // its parent, set start offset to the index of start node and then
+ // set start node to its parent."
+ while (startOffset == 0
+ && startNode == startNode.parentNode.firstChild) {
startOffset = getNodeIndex(startNode);
startNode = startNode.parentNode;
}
+ // "Remove extraneous line breaks before start node."
+ removeExtraneousLineBreaksBefore(startNode);
+
+ // "Set start offset to the index of start node."
+ startOffset = getNodeIndex(startNode);
+
+ // "Set start node to its parent."
+ startNode = startNode.parentNode;
+
// "If the child of start node with index start offset minus one is
- // a br or hr or img, set node to start node and offset to start
- // offset, then subtract one from start offset."
- if (isHtmlElement(startNode.childNodes[startOffset - 1], ["br", "hr", "img"])) {
+ // a br or hr, set node to start node and offset to start offset,
+ // then subtract one from start offset."
+ if (isHtmlElement(startNode.childNodes[startOffset - 1], ["br", "hr"])) {
node = startNode;
offset = startOffset;
startOffset--;
--- a/source.html Tue Jun 07 09:57:19 2011 -0600
+++ b/source.html Tue Jun 07 10:21:41 2011 -0600
@@ -2462,6 +2462,7 @@
<li>If <var>node</var> is a <span>prohibited paragraph child</span> and
<var>offset</var> is zero:
+ <!-- Then we'll typically want to merge backward into the previous block. -->
<ol>
<li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
@@ -2470,15 +2471,57 @@
<li>Let <var>start node</var> equal <var>node</var> and let <var>start
offset</var> equal <var>offset</var>.
- <li>While <var>start offset</var> is zero, set <var>start offset</var> to
- the [[index]] of <var>start node</var> and then set <var>start node</var>
- to its [[parent]].
-
+ <!--
+ Go up until we're no longer at the beginning of an element. As a special
+ case, we make sure to remove a preceding extraneous line break in cases
+ like
+
+ foo<br><p>[]bar</p>
+ -> foo<p>[]bar</p>
+ -> foo[]bar.
+
+ We have to take care that we remove the line break before we go all the way
+ up to the node that contains the line break. Otherwise the offset will no
+ longer be correct: it will be one too high. (Try removing "and start node
+ is the first child of its parent" from the next line, and the two lines
+ after the extraneous line break removal, and see what happens.)
+ -->
+ <li>While <var>start offset</var> is zero and <var>start node</var> is the
+ first [[child]] of its [[parent]], set <var>start offset</var> to the
+ [[index]] of <var>start node</var> and then set <var>start node</var> to
+ its [[parent]].
+
+ <li><span>Remove extraneous line breaks before</span> <var>start
+ node</var>.
+
+ <li>Set <var>start offset</var> to the [[index]] of <var>start node</var>.
+
+ <li>Set <var>start node</var> to its [[parent]].
+
+ <!--
+ Special case:
+
+ <p>foo</p><br><p>[]bar</p>
+ -> <p>foo</p><p>[]bar</p>
+
+ and likewise for <hr>. But with <img> we merge like in other cases:
+
+ <p>foo</p><img><p>[]bar</p>
+ -> <p>foo</p><img>[]bar.
+
+ Browsers don't do this consistently. Firefox 5.0a2 doesn't seem to do it
+ at all.
+ -->
<li>If the [[child]] of <var>start node</var> with [[index]] <var>start
- offset</var> minus one is a [[br]] or [[hr]] or [[img]], set
- <var>node</var> to <var>start node</var> and <var>offset</var> to
- <var>start offset</var>, then subtract one from <var>start offset</var>.
-
+ offset</var> minus one is a [[br]] or [[hr]], set <var>node</var> to
+ <var>start node</var> and <var>offset</var> to <var>start offset</var>,
+ then subtract one from <var>start offset</var>.
+
+ <!--
+ Regular case: for <p>foo</p><p>[]bar</p>, we delete <p>foo{</p><p>}bar</p>.
+ This will also happen if the preceding element is a span or something, but
+ that doesn't hurt.
+ -->
<li>Otherwise, set <var>start node</var> to its [[child]] with [[index]]
<var>start offset</var> minus one, then set <var>start offset</var> to the
[[nodelength]] of <var>start node</var>.
@@ -2487,6 +2530,16 @@
whose last [[child]] is a [[br]], and <var>start offset</var> is the
[[nodelength]] of <var>start node</var>, subtract one from <var>start
offset</var>.
+ <!--
+ It wouldn't be enough to just remove extraneous line breaks at the end of
+ start node, because we want to remove the line break even if it's not
+ actually extraneous. For instance,
+
+ <p>foo<br><br></p><p>[]bar</p>
+ -> <p>foo<br>bar</p>
+ not
+ -> <p>foo<br><br>bar</p>.
+ -->
<li><span>Delete the contents</span> of the [[range]] with [[rangestart]]
(<var>start node</var>, <var>start offset</var>) and [[rangeend]]