--- a/implementation.js Wed Sep 21 11:53:03 2011 -0600+++ b/implementation.js Wed Sep 21 14:29:54 2011 -0600@@ -1349,10 +1349,16 @@ newParentInstructions = function() { return null }; }- // "If node list is empty, or the first member of node list is not- // editable, return null and abort these steps."- if (!nodeList.length- || !isEditable(nodeList[0])) {+ // "If every member of node list is invisible, and none is a br, return+ // null and abort these steps."+ if (nodeList.every(isInvisible)+ && !nodeList.some(function(node) { return isHtmlElement(node, "br") })) {+ return null;+ }++ // "If node list's first member's parent is null, return null and abort+ // these steps."+ if (!nodeList[0].parentNode) { return null; }@@ -1364,6 +1370,18 @@ nodeList.push(nodeList[nodeList.length - 1].nextSibling); }+ // "While node list's first member's previousSibling is invisible, prepend+ // it to node list."+ while (isInvisible(nodeList[0].previousSibling)) {+ nodeList.unshift(nodeList[0].previousSibling);+ }++ // "While node list's last member's nextSibling is invisible, append it to+ // node list."+ while (isInvisible(nodeList[nodeList.length - 1].nextSibling)) {+ nodeList.push(nodeList[nodeList.length - 1].nextSibling);+ }+ // "If the previousSibling of the first member of node list is editable and // running sibling criteria on it returns true, let new parent be the // previousSibling of the first member of node list."@@ -1416,14 +1434,14 @@ // "If new parent is before the first member of node list in tree order:" if (isBefore(newParent, nodeList[0])) {- // "If new parent is not an inline node, but the last child of new- // parent and the first member of node list are both inline nodes, and- // the last child of new parent is not a br, call createElement("br")- // on the ownerDocument of new parent and append the result as the last- // child of new parent."+ // "If new parent is not an inline node, but the last visible child of+ // new parent and the first visible member of node list are both inline+ // nodes, and the last child of new parent is not a br, call+ // createElement("br") on the ownerDocument of new parent and append+ // the result as the last child of new parent." if (!isInlineNode(newParent)- && isInlineNode(newParent.lastChild)- && isInlineNode(nodeList[0])+ && isInlineNode([].filter.call(newParent.childNodes, isVisible).slice(-1)[0])+ && isInlineNode(nodeList.filter(isVisible)[0]) && !isHtmlElement(newParent.lastChild, "BR")) { newParent.appendChild(newParent.ownerDocument.createElement("br")); }@@ -1436,14 +1454,14 @@ // "Otherwise:" } else {- // "If new parent is not an inline node, but the first child of new- // parent and the last member of node list are both inline nodes, and- // the last member of node list is not a br, call createElement("br")- // on the ownerDocument of new parent and insert the result as the- // first child of new parent."+ // "If new parent is not an inline node, but the first visible child of+ // new parent and the last visible member of node list are both inline+ // nodes, and the last member of node list is not a br, call+ // createElement("br") on the ownerDocument of new parent and insert+ // the result as the first child of new parent." if (!isInlineNode(newParent)- && isInlineNode(newParent.firstChild)- && isInlineNode(nodeList[nodeList.length - 1])+ && isInlineNode([].filter.call(newParent.childNodes, isVisible)[0])+ && isInlineNode(nodeList.filter(isVisible).slice(-1)[0]) && !isHtmlElement(nodeList[nodeList.length - 1], "BR")) { newParent.insertBefore(newParent.ownerDocument.createElement("br"), newParent.firstChild); }@@ -6750,14 +6768,24 @@ || isAllowedChild(node, "ol")); });- // "If the first member of node list is an li whose parent is an ol or- // ul, and its previousSibling is an li as well, normalize sublists of- // its previousSibling."- if (nodeList.length- && isHtmlElement(nodeList[0], "LI")- && isHtmlElement(nodeList[0].parentNode, ["OL", "UL"])- && isHtmlElement(nodeList[0].previousSibling, "LI")) {- normalizeSublists(nodeList[0].previousSibling);+ // "If the first visible member of node list is an li whose parent is+ // an ol or ul:"+ if (isHtmlElement(nodeList.filter(isVisible)[0], "li")+ && isHtmlElement(nodeList.filter(isVisible)[0].parentNode, ["ol", "ul"])) {+ // "Let sibling be node list's first visible member's+ // previousSibling."+ var sibling = nodeList.filter(isVisible)[0].previousSibling;++ // "While sibling is invisible, set sibling to its+ // previousSibling."+ while (isInvisible(sibling)) {+ sibling = sibling.previousSibling;+ }++ // "If sibling is an li, normalize sublists of sibling."+ if (isHtmlElement(sibling, "li")) {+ normalizeSublists(sibling);+ } } // "While node list is not empty:"

--- a/source.html Wed Sep 21 11:53:03 2011 -0600+++ b/source.html Wed Sep 21 14:29:54 2011 -0600@@ -1432,8 +1432,16 @@ title>&lt;b></code> element. <ol>- <li>If <var>node list</var> is empty, or the first member of <var>node- list</var> is not <span>editable</span>, return null and abort these steps.+ <li>+ <p class=comments>We need to treat [[br]]s as visible here even if they're+ not, because wrapping them might be significant even if they're invisible: it+ can turn an extraneous line break into a non-extraneous one.++ <p>If every member of <var>node list</var> is <span>invisible</span>, and+ none is a [[br]], return null and abort these steps.++ <li>If <var>node list</var>'s first member's [[parent]] is null, return null+ and abort these steps. <li> <p class=comments>Trailing br's like this always need to go along with their@@ -1444,6 +1452,24 @@ that's not a [[br]], and <var>node list</var>'s last member's [[nextsibling]] is a [[br]], append that [[br]] to <var>node list</var>.+ <li>+ <p class=comments>See <a+ href=http://www.w3.org/Bugs/Public/show_bug.cgi?id=13811>bug 13811</a>, <a+ href=http://www.w3.org/Bugs/Public/show_bug.cgi?id=14231>bug 14231</a>. If+ there's a non-adjacent sibling that matches the sibling criteria and only+ invisible nodes intervene, we want to skip over the invisible nodes. For+ instance, bolding {{code|<b>foo</b><!--bar-->[baz]}} should produce+ {{code|<b>foo<!--bar-->baz</b>}}. Similarly, and more usefully, creating an+ ordered list with {{code|<ol><li>foo</ol> <p>[bar]</p>}} should produce+ {{code|<ol><li>foo</li> <li>[bar]</ol>}}, not+ {{code|<ol><li>foo</ol> <ol><li>[bar]</ol>}}.++ <p>While <var>node list</var>'s first member's [[previoussibling]] is+ <span>invisible</span>, prepend it to <var>node list</var>.++ <li>While <var>node list</var>'s last member's [[nextsibling]] is+ <span>invisible</span>, append it to <var>node list</var>.+ <li>If the [[previoussibling]] of the first member of <var>node list</var> is <span>editable</span> and running <var>sibling criteria</var> on it returns true, let <var>new parent</var> be the [[previoussibling]] of the@@ -1546,11 +1572,10 @@ <ol> <li>If <var>new parent</var> is not an <span>inline node</span>, but the- last [[child]] of <var>new parent</var> and the first member of <var>node- list</var> are both <span title="inline node">inline nodes</span>, and the- last [[child]] of <var>new parent</var> is not a [[br]], call <code- data-anolis-spec=domcore- title=dom-Document-createElement>createElement("br")</code> on the+ last <span>visible</span> [[child]] of <var>new parent</var> and the first+ <span>visible</span> member of <var>node list</var> are both <span+ title="inline node">inline nodes</span>, and the last [[child]] of <var>new+ parent</var> is not a [[br]], call [[createelement|"br"]] on the [[ownerdocument]] of <var>new parent</var> and append the result as the last [[child]] of <var>new parent</var>.@@ -1563,11 +1588,10 @@ <ol> <li>If <var>new parent</var> is not an <span>inline node</span>, but the- first [[child]] of <var>new parent</var> and the last member of <var>node- list</var> are both <span title="inline node">inline nodes</span>, and the- last member of <var>node list</var> is not a [[br]], call <code- data-anolis-spec=domcore- title=dom-Document-createElement>createElement("br")</code> on the+ first <span>visible</span> [[child]] of <var>new parent</var> and the last+ <span>visible</span> member of <var>node list</var> are both <span+ title="inline node">inline nodes</span>, and the last member of <var>node+ list</var> is not a [[br]], call [[createelement|"br"]] on the [[ownerdocument]] of <var>new parent</var> and insert the result as the first [[child]] of <var>new parent</var>.@@ -7907,9 +7931,19 @@ <p class=comments>Without this step, the last child of the previous sibling might be a list, which the li wouldn't get appended to.- <p>If the first member of <var>node list</var> is an [[li]] whose [[parent]]- is an [[ol]] or [[ul]], and its [[previoussibling]] is an [[li]] as well,- <span>normalize sublists</span> of its [[previoussibling]].+ <p>If the first <span>visible</span> member of <var>node list</var> is an+ [[li]] whose [[parent]] is an [[ol]] or [[ul]]:++ <ol>+ <li>Let <var>sibling</var> be <var>node list</var>'s first+ <span>visible</span> member's [[previoussibling]].++ <li>While <var>sibling</var> is <span>invisible</span>, set+ <var>sibling</var> to its [[previoussibling]].++ <li>If <var>sibling</var> is an [[li]], <span>normalize sublists</span> of+ <var>sibling</var>.+ </ol> <li>While <var>node list</var> is not empty: