--- a/editcommands.html Sun Jul 10 09:40:21 2011 -0600
+++ b/editcommands.html Sun Jul 10 10:51:09 2011 -0600
@@ -3071,6 +3071,12 @@
<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same editing host</a>:
<ol>
+ <li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, <a href=#wrap>wrap</a> the
+ one-<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> list consisting of <var title="">node</var>, with <a href=#sibling-criteria>sibling
+ criteria</a> matching any <code class=external data-anolis-spec=html title="the dl element"><a href=http://www.whatwg.org/html/#the-dl-element>dl</a></code> with no <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-attribute title=concept-attribute>attributes</a>, and <a href=#new-parent-instructions>new
+ parent instructions</a> returning the result of calling
+ <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("dl")</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 abort these steps.
+
<li>If <var title="">node</var> is not a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>,
abort these steps.
@@ -3881,7 +3887,8 @@
<p>To remove 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> while <dfn id=preserving-its-descendants>preserving its
descendants</dfn>, <a href=#split-the-parent>split the parent</a> of <var title="">node</var>'s
-<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>.
+<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> if it has any. If it 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>, instead 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>.
<h3 id=canonical-space-sequences><span class=secno>8.6 </span>Canonical space sequences</h3>
@@ -5121,6 +5128,18 @@
<li><a href=#split-the-parent>Split the parent</a> of the one-<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> list consisting of
<var title="">node</var>.
+ <li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
+ <a href=#allowed-child>allowed child</a> of any of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same
+ editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to
+ the <a href=#default-single-line-container-name>default single-line container name</a> and let <var title="">node</var>
+ be the result.
+ <!--
+ Annoying hack to prevent the dl from being re-added when fixing disallowed
+ ancestors. In most cases we want a wrapper dl added, but in two cases
+ (delete and insertParagraph) we're actually trying to outdent the list
+ item. There might be a better way to do this.
+ -->
+
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">node</var>.
<li>Abort these steps.
@@ -5332,11 +5351,8 @@
<li>Let <var title="">value</var> be <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#converted-to-ascii-lowercase>converted to
ASCII lowercase</a>.
- <li>If <var title="">value</var> is not "address", "div", "h1", "h2", "h3", "h4",
- "h5", "h6", "p", or "pre", raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SYNTAX_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-syntax_err>SYNTAX_ERR</a></code> exception.
-
- <p class=XXX>We should support dt and dd here, since they make sense here and
- there's no other way to create them.
+ <li>If <var title="">value</var> is not "address", "dd", "div", "dt", "h1", "h2",
+ "h3", "h4", "h5", "h6", "p", or "pre", raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SYNTAX_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-syntax_err>SYNTAX_ERR</a></code> exception.
<!--
Opera 11.10 throws NOT_SUPPORTED_ERR for bad elements, all other tested
browsers ignore the input. Testing in IE9, Firefox 4.0, Chrome 13 dev, and
@@ -5367,15 +5383,16 @@
<a href=#editable>editable</a>, the last member of <var title="">original node list</var> (if
any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>, <var title="">node</var> is either a
<a href=#non-list-single-line-container>non-list single-line container</a> or an <a href=#allowed-child>allowed child</a>
- of "p", and <var title="">node</var> is not the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <a href=#prohibited-paragraph-child>prohibited
- paragraph child</a>.
+ of "p" or a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and <var title="">node</var> is not the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of
+ a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>.
<li>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>
is the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of an <a href=#editable>editable</a> <a href=#html-element>HTML element</a>
<a href=#in-the-same-editing-host>in the same editing host</a>, which has <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "address",
- "div", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre", and which is not
- the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, <a href=#split-the-parent>split
- the parent</a> of the one-<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> list consisting of <var title="">node</var>.
+ "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre", and
+ which is not the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>,
+ <a href=#split-the-parent>split the parent</a> of the one-<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> list consisting of
+ <var title="">node</var>.
<!--
This tries to avoid misnesting if only some lines of an element are selected,
so <h1>[foo]<br>bar</h1> becomes <p>[foo]</p><h1>bar</h1> instead of
@@ -5409,8 +5426,9 @@
IE9 will just change the elements as they are, so it gives
<p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
<div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
- for foo<br>bar. This is unreasonable, but the two possible inputs here look
- identical to the user and might have been produced by identical user input.
+ for foo<br>bar. This is unreasonable, because the two possible inputs here
+ look identical to the user and might have been produced by identical user
+ input.
Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
<h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
@@ -5424,46 +5442,27 @@
predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
-->
- <li>If <var title="">value</var> is "div" or "p", then while <var title="">node list</var> is
- not empty:
+ <li>While <var title="">node list</var> is not empty:
<ol>
- <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
- single-line container</a>, <a href=#set-the-tag-name>set the tag name</a> of the first
- member of <var title="">node list</var> to <var title="">value</var>, then remove the first
- member from <var title="">node list</var> and continue this loop from the beginning.
-
- <li>Let <var title="">sublist</var> be an empty list of <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>.
-
- <li>Remove the first member of <var title="">node list</var> and append it to
- <var title="">sublist</var>.
-
- <li>While <var title="">node list</var> is not empty, and the first member of
- <var title="">node list</var> is the <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> of the last member of
- <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
- <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
- <var title="">sublist</var> 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>, remove the first member of <var title="">node
- list</var> and append it to <var title="">sublist</var>.
-
- <li><a href=#wrap>Wrap</a> <var title="">sublist</var>, with <a href=#sibling-criteria>sibling
- criteria</a> matching nothing and <a href=#new-parent-instructions>new parent instructions</a>
- returning the result of running <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(<var title="">value</var>)</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 <a href=#fix-disallowed-ancestors>fix disallowed ancestors</a> of the
- result.
- <!-- It's possible to have disallowed ancestors in obscure corner cases,
- where a node is an allowed child of a p but p is not an allowed child of
- the node's parent and the node's parent is also not one of the whitelisted
- elements but is a block element. <xmp>[foo]</xmp> is the only case I can
- think of. -->
- </ol>
-
- <li>Otherwise, while <var title="">node list</var> is not empty:
-
- <ol>
- <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
- single-line container</a>:
+ <li>If the first member of <var title="">node list</var> is a <a href=#single-line-container>single-line
+ container</a>:
<ol>
+ <!--
+ If you try to format a single-line container with no children, IE10PP2
+ inserts an nbsp before formatting. (It uses nbsp instead of <br> to make
+ blocks not collapse, so the equivalent for us would be to insert a <br>.)
+ Firefox 7.0a2 and Opera 11.50 make the element disappear. Chrome 14 dev
+ leaves it alone and doesn't format it. I follow Firefox/Opera just
+ because it's the simplest given how I happen to have written the spec,
+ and it's a corner case, so exact behavior isn't important.
+
+ For blocks that contain only a collapsed whitespace node, IE10PP2 and
+ Firefox 7.0a2 convert them like normal. Chrome 14 dev and Opera 11.50
+ leave it alone and don't format it. I go with the majority, which is
+ again simpler to spec.
+ -->
<li>Let <var title="">sublist</var> be 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>children</a> of the first member of
<var title="">node list</var>.
@@ -5484,16 +5483,16 @@
<li>While <var title="">node list</var> is not empty, and the first member of
<var title="">node list</var> is the <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> of the last member of
<var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
- <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
+ <a href=#single-line-container>single-line container</a>, and the last member of
<var title="">sublist</var> 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>, remove the first member of <var title="">node
list</var> and append it to <var title="">sublist</var>.
</ol>
- <li><a href=#wrap>Wrap</a> <var title="">sublist</var>, with <a href=#sibling-criteria>sibling
- criteria</a> matching any <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a>
- <var title="">value</var> and no attributes, and <a href=#new-parent-instructions>new parent
- instructions</a> returning the result of running
- <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(<var title="">value</var>)</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
+ <li><a href=#wrap>Wrap</a> <var title="">sublist</var>. If <var title="">value</var> is "div" or
+ "p", <a href=#sibling-criteria>sibling criteria</a> match nothing; otherwise they match any
+ <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">value</var> and no
+ attributes. <a href=#new-parent-instructions>New parent instructions</a> return the result of
+ running <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(<var title="">value</var>)</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
<a href=#fix-disallowed-ancestors>fix disallowed ancestors</a> of the result.
</ol>
</ol>
@@ -6262,6 +6261,18 @@
<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 append the result as
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="">container</var>.
+ <li>If <var title="">container</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
+ <a href=#allowed-child>allowed child</a> of any of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same
+ editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">container</var>
+ to the <a href=#default-single-line-container-name>default single-line container name</a> and let
+ <var title="">container</var> be the result.
+ <!--
+ Annoying hack to prevent the dl from being re-added when fixing disallowed
+ ancestors. In most cases we want a wrapper dl added, but in two cases
+ (delete and insertParagraph) we're actually trying to outdent the list
+ item. There might be a better way to do this.
+ -->
+
<li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">container</var>.
<li>Abort these steps.
--- a/implementation.js Sun Jul 10 09:40:21 2011 -0600
+++ b/implementation.js Sun Jul 10 10:51:09 2011 -0600
@@ -3419,14 +3419,21 @@
// "If node is not an allowed child of any of its ancestors in the same
// editing host:"
- var hasAllowedAncestor = false;
- for (var ancestor = node.parentNode; inSameEditingHost(node, ancestor); ancestor = ancestor.parentNode) {
- if (isAllowedChild(node, ancestor)) {
- hasAllowedAncestor = true;
- break;
- }
- }
- if (!hasAllowedAncestor) {
+ if (getAncestors(node).every(function(ancestor) {
+ return !inSameEditingHost(node, ancestor)
+ || !isAllowedChild(node, ancestor)
+ })) {
+ // "If node is a dd or dt, wrap the one-node list consisting of node,
+ // with sibling criteria matching any dl with no attributes, and new
+ // parent instructions returning the result of calling
+ // createElement("dl") on the context object. Then abort these steps."
+ if (isHtmlElement(node, ["dd", "dt"])) {
+ wrap([node],
+ function(sibling) { return isHtmlElement(sibling, "dl") && !sibling.attributes.length },
+ function() { return document.createElement("dl") });
+ return;
+ }
+
// "If node is not a prohibited paragraph child, abort these steps."
if (!isProhibitedParagraphChild(node)) {
return;
@@ -4352,9 +4359,14 @@
}
// "To remove a node node while preserving its descendants, split the parent of
-// node's children."
+// node's children if it has any. If it has no children, instead remove it from
+// its parent."
function removePreservingDescendants(node) {
- splitParent([].slice.call(node.childNodes));
+ if (node.hasChildNodes()) {
+ splitParent([].slice.call(node.childNodes));
+ } else {
+ node.parentNode.removeChild(node);
+ }
}
//@}
@@ -5281,6 +5293,18 @@
// "Split the parent of the one-node list consisting of node."
splitParent([node]);
+ // "If node is a dd or dt, and it is not an allowed child of any of
+ // its ancestors in the same editing host, set the tag name of node
+ // to the default single-line container name and let node be the
+ // result."
+ if (isHtmlElement(node, ["dd", "dt"])
+ && getAncestors(node).every(function(ancestor) {
+ return !inSameEditingHost(node, ancestor)
+ || !isAllowedChild(node, ancestor)
+ })) {
+ node = setTagName(node, defaultSingleLineContainerName);
+ }
+
// "Fix disallowed ancestors of node."
fixDisallowedAncestors(node);
@@ -5457,10 +5481,10 @@
// "Let value be converted to ASCII lowercase."
value = value.toLowerCase();
- // "If value is not "address", "div", "h1", "h2", "h3", "h4", "h5",
- // "h6", "p", or "pre", raise a SYNTAX_ERR exception."
- if (["ADDRESS", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "P",
- "PRE"].indexOf(value.toUpperCase()) == -1) {
+ // "If value is not "address", "dd", "div", "dt", "h1", "h2", "h3",
+ // "h4", "h5", "h6", "p", or "pre", raise a SYNTAX_ERR exception."
+ if (["address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6",
+ "p", "pre"].indexOf(value) == -1) {
throw "SYNTAX_ERR";
}
@@ -5472,125 +5496,85 @@
// "For each node node contained in new range, append node to node list
// if it is editable, the last member of original node list (if any) is
// not an ancestor of node, node is either a non-list single-line
- // container or an allowed child of "p", and node is not the ancestor
- // of a prohibited paragraph child."
+ // container or an allowed child of "p" or a dd or dt, and node is not
+ // the ancestor of a prohibited paragraph child."
var nodeList = getContainedNodes(newRange, function(node) {
return isEditable(node)
&& (isNonListSingleLineContainer(node)
- || isAllowedChild(node, "p"))
+ || isAllowedChild(node, "p")
+ || isHtmlElement(node, ["dd", "dt"]))
&& !getDescendants(node).some(isProhibitedParagraphChild);
});
// "For each node in node list, while node is the descendant of an
// editable HTML element in the same editing host, which has local name
- // "address", "div", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre",
- // and which is not the ancestor of a prohibited paragraph child, split
- // the parent of the one-node list consisting of node."
+ // "address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6",
+ // "p", or "pre", and which is not the ancestor of a prohibited
+ // paragraph child, split the parent of the one-node list consisting of
+ // node."
for (var i = 0; i < nodeList.length; i++) {
var node = nodeList[i];
while (getAncestors(node).some(function(ancestor) {
return isEditable(ancestor)
&& inSameEditingHost(ancestor, node)
- && isHtmlElement(ancestor, ["address", "div", "h1", "h2", "h3", "h4", "h5", "h6", "p", "pre"])
+ && isHtmlElement(ancestor, ["address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6", "p", "pre"])
&& !getDescendants(ancestor).some(isProhibitedParagraphChild);
})) {
splitParent([node]);
}
}
- // "If value is "div" or "p", then while node list is not empty:"
- if (value == "div" || value == "p") {
- while (nodeList.length) {
- // "If the first member of node list is a non-list single-line
- // container, set the tag name of the first member of node list
- // to value, then remove the first member from node list and
- // continue this loop from the beginning."
- if (isNonListSingleLineContainer(nodeList[0])) {
- setTagName(nodeList[0], value);
- nodeList.shift();
- continue;
- }
-
+ // "While node list is not empty:"
+ while (nodeList.length) {
+ var sublist;
+
+ // "If the first member of node list is a single-line
+ // container:"
+ if (isSingleLineContainer(nodeList[0])) {
+ // "Let sublist be the children of the first member of node
+ // list."
+ sublist = [].slice.call(nodeList[0].childNodes);
+
+ // "Remove the first member of node list from its parent,
+ // preserving its descendants."
+ removePreservingDescendants(nodeList[0]);
+
+ // "Remove the first member from node list."
+ nodeList.shift();
+
+ // "Otherwise:"
+ } else {
// "Let sublist be an empty list of nodes."
- var sublist = [];
+ sublist = [];
// "Remove the first member of node list and append it to
// sublist."
sublist.push(nodeList.shift());
- // "While node list is not empty, and the first member of node
- // list is the nextSibling of the last member of sublist, and
- // the first member of node list is not a non-list single-line
- // container, and the last member of sublist is not a br,
- // remove the first member of node list and append it to
- // sublist."
+ // "While node list is not empty, and the first member of
+ // node list is the nextSibling of the last member of
+ // sublist, and the first member of node list is not a
+ // single-line container, and the last member of sublist is
+ // not a br, remove the first member of node list and
+ // append it to sublist."
while (nodeList.length
&& nodeList[0] == sublist[sublist.length - 1].nextSibling
- && !isNonListSingleLineContainer(nodeList[0])
+ && !isSingleLineContainer(nodeList[0])
&& !isHtmlElement(sublist[sublist.length - 1], "BR")) {
sublist.push(nodeList.shift());
}
-
- // "Wrap sublist, with sibling criteria matching nothing and
- // new parent instructions returning the result of running
- // createElement(value) on the context object. Then fix
- // disallowed ancestors of the result."
- fixDisallowedAncestors(wrap(sublist,
- function() { return false },
- function() { return document.createElement(value) }));
}
- // "Otherwise, while node list is not empty:"
- } else {
- while (nodeList.length) {
- var sublist;
-
- // "If the first member of node list is a non-list single-line
- // container:"
- if (isNonListSingleLineContainer(nodeList[0])) {
- // "Let sublist be the children of the first member of node
- // list."
- sublist = [].slice.call(nodeList[0].childNodes);
-
- // "Remove the first member of node list from its parent,
- // preserving its descendants."
- removePreservingDescendants(nodeList[0]);
-
- // "Remove the first member from node list."
- nodeList.shift();
-
- // "Otherwise:"
- } else {
- // "Let sublist be an empty list of nodes."
- sublist = [];
-
- // "Remove the first member of node list and append it to
- // sublist."
- sublist.push(nodeList.shift());
-
- // "While node list is not empty, and the first member of
- // node list is the nextSibling of the last member of
- // sublist, and the first member of node list is not a
- // non-list single-line container, and the last member of
- // sublist is not a br, remove the first member of node
- // list and append it to sublist."
- while (nodeList.length
- && nodeList[0] == sublist[sublist.length - 1].nextSibling
- && !isNonListSingleLineContainer(nodeList[0])
- && !isHtmlElement(sublist[sublist.length - 1], "BR")) {
- sublist.push(nodeList.shift());
- }
- }
-
- // "Wrap sublist, with sibling criteria matching any HTML
- // element with local name value and no attributes, and new
- // parent instructions returning the result of running
- // createElement(value) on the context object. Then fix
- // disallowed ancestors of the result."
- fixDisallowedAncestors(wrap(sublist,
- function(node) { return isHtmlElement(node, value.toUpperCase()) && !node.attributes.length },
- function() { return document.createElement(value) }));
- }
+ // "Wrap sublist. If value is "div" or "p", sibling criteria match
+ // nothing; otherwise they match any HTML element with local name
+ // value and no attributes. New parent instructions return the
+ // result of running createElement(value) on the context object.
+ // Then fix disallowed ancestors of the result."
+ fixDisallowedAncestors(wrap(sublist,
+ ["div", "p"].indexOf(value) == - 1
+ ? function(node) { return isHtmlElement(node, value) && !node.attributes.length }
+ : function() { return false },
+ function() { return document.createElement(value) }));
}
}, indeterm: function() {
// "Block-extend the active range, and let new range be the result."
@@ -6357,6 +6341,25 @@
// "Split the parent of the one-node list consisting of container."
splitParent([container]);
+ // "If container has no children, call createElement("br") on the
+ // context object and append the result as the last child of
+ // container."
+ if (!container.hasChildNodes()) {
+ container.appendChild(document.createElement("br"));
+ }
+
+ // "If container is a dd or dt, and it is not an allowed child of
+ // any of its ancestors in the same editing host, set the tag name
+ // of container to the default single-line container name and let
+ // container be the result."
+ if (isHtmlElement(container, ["dd", "dt"])
+ && getAncestors(container).every(function(ancestor) {
+ return !inSameEditingHost(container, ancestor)
+ || !isAllowedChild(container, ancestor)
+ })) {
+ container = setTagName(container, defaultSingleLineContainerName);
+ }
+
// "Fix disallowed ancestors of container."
fixDisallowedAncestors(container);
--- a/preprocess Sun Jul 10 09:40:21 2011 -0600
+++ b/preprocess Sun Jul 10 10:51:09 2011 -0600
@@ -10,6 +10,7 @@
'a': '<code data-anolis-spec=html title="the a element">a</code>',
'ancestor': '<span data-anolis-spec=domcore title=concept-tree-ancestor>ancestor</span>',
'ancestorcontainer': '<span data-anolis-spec=domrange title="ancestor container">ancestor container</span>',
+ 'attribute': '<span data-anolis-spec=domcore title=concept-attribute>attribute</span>',
'attrlocalname': '<span data-anolis-spec=domcore title=concept-attribute-local-name>local name</span>',
'attrvalue': '<span data-anolis-spec=domcore title=concept-attribute-value>value</span>',
'b': '<code data-anolis-spec=html title="the b element">b</code>',
@@ -144,7 +145,7 @@
s = re.sub(r"\[\[" + key + "\|([^]]*)\]\]", fnreplace[key], s)
if "[[" in s:
- raise Exception("Something mistyped? " + s[s.find("[["):s.find("]]") + 2])
+ raise Exception("Unrecognized macro: " + s[s.find("[["):s.find("]]") + 2])
s = s.replace("<var>", "<var title>")
--- a/source.html Sun Jul 10 09:40:21 2011 -0600
+++ b/source.html Sun Jul 10 10:51:09 2011 -0600
@@ -3047,6 +3047,12 @@
[[ancestors]] <span>in the same editing host</span>:
<ol>
+ <li>If <var>node</var> is a [[dd]] or [[dt]], <span>wrap</span> the
+ one-[[node]] list consisting of <var>node</var>, with <span>sibling
+ criteria</span> matching any [[dl]] with no [[attributes]], and <span>new
+ parent instructions</span> returning the result of calling
+ [[createelement|"dl"]] on the [[contextobject]]. Then abort these steps.
+
<li>If <var>node</var> is not a <span>prohibited paragraph child</span>,
abort these steps.
@@ -3861,7 +3867,8 @@
<p>To remove a [[node]] <var>node</var> while <dfn>preserving its
descendants</dfn>, <span>split the parent</span> of <var>node</var>'s
-[[children]].
+[[children]] if it has any. If it has no [[children]], instead remove it from
+its [[parent]].
<!-- @} -->
<h3>Canonical space sequences</h3>
@@ -5122,6 +5129,18 @@
<li><span>Split the parent</span> of the one-[[node]] list consisting of
<var>node</var>.
+ <li>If <var>node</var> is a [[dd]] or [[dt]], and it is not an
+ <span>allowed child</span> of any of its [[ancestors]] <span>in the same
+ editing host</span>, <span>set the tag name</span> of <var>node</var> to
+ the <span>default single-line container name</span> and let <var>node</var>
+ be the result.
+ <!--
+ Annoying hack to prevent the dl from being re-added when fixing disallowed
+ ancestors. In most cases we want a wrapper dl added, but in two cases
+ (delete and insertParagraph) we're actually trying to outdent the list
+ item. There might be a better way to do this.
+ -->
+
<li><span>Fix disallowed ancestors</span> of <var>node</var>.
<li>Abort these steps.
@@ -5333,11 +5352,8 @@
<li>Let <var>value</var> be <span data-anolis-spec=domcore>converted to
ASCII lowercase</span>.
- <li>If <var>value</var> is not "address", "div", "h1", "h2", "h3", "h4",
- "h5", "h6", "p", or "pre", raise a [[SYNTAX_ERR]] exception.
-
- <p class=XXX>We should support dt and dd here, since they make sense here and
- there's no other way to create them.
+ <li>If <var>value</var> is not "address", "dd", "div", "dt", "h1", "h2",
+ "h3", "h4", "h5", "h6", "p", or "pre", raise a [[SYNTAX_ERR]] exception.
<!--
Opera 11.10 throws NOT_SUPPORTED_ERR for bad elements, all other tested
browsers ignore the input. Testing in IE9, Firefox 4.0, Chrome 13 dev, and
@@ -5368,15 +5384,16 @@
<span>editable</span>, the last member of <var>original node list</var> (if
any) is not an [[ancestor]] of <var>node</var>, <var>node</var> is either a
<span>non-list single-line container</span> or an <span>allowed child</span>
- of "p", and <var>node</var> is not the [[ancestor]] of a <span>prohibited
- paragraph child</span>.
+ of "p" or a [[dd]] or [[dt]], and <var>node</var> is not the [[ancestor]] of
+ a <span>prohibited paragraph child</span>.
<li>For each <var>node</var> in <var>node list</var>, while <var>node</var>
is the [[descendant]] of an <span>editable</span> <span>HTML element</span>
<span>in the same editing host</span>, which has [[localname]] "address",
- "div", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre", and which is not
- the [[ancestor]] of a <span>prohibited paragraph child</span>, <span>split
- the parent</span> of the one-[[node]] list consisting of <var>node</var>.
+ "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre", and
+ which is not the [[ancestor]] of a <span>prohibited paragraph child</span>,
+ <span>split the parent</span> of the one-[[node]] list consisting of
+ <var>node</var>.
<!--
This tries to avoid misnesting if only some lines of an element are selected,
so <h1>[foo]<br>bar</h1> becomes <p>[foo]</p><h1>bar</h1> instead of
@@ -5410,8 +5427,9 @@
IE9 will just change the elements as they are, so it gives
<p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
<div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
- for foo<br>bar. This is unreasonable, but the two possible inputs here look
- identical to the user and might have been produced by identical user input.
+ for foo<br>bar. This is unreasonable, because the two possible inputs here
+ look identical to the user and might have been produced by identical user
+ input.
Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
<h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
@@ -5425,46 +5443,27 @@
predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
-->
- <li>If <var>value</var> is "div" or "p", then while <var>node list</var> is
- not empty:
+ <li>While <var>node list</var> is not empty:
<ol>
- <li>If the first member of <var>node list</var> is a <span>non-list
- single-line container</span>, <span>set the tag name</span> of the first
- member of <var>node list</var> to <var>value</var>, then remove the first
- member from <var>node list</var> and continue this loop from the beginning.
-
- <li>Let <var>sublist</var> be an empty list of [[nodes]].
-
- <li>Remove the first member of <var>node list</var> and append it to
- <var>sublist</var>.
-
- <li>While <var>node list</var> is not empty, and the first member of
- <var>node list</var> is the [[nextsibling]] of the last member of
- <var>sublist</var>, and the first member of <var>node list</var> is not a
- <span>non-list single-line container</span>, and the last member of
- <var>sublist</var> is not a [[br]], remove the first member of <var>node
- list</var> and append it to <var>sublist</var>.
-
- <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
- criteria</span> matching nothing and <span>new parent instructions</span>
- returning the result of running [[createelement|<var>value</var>]] on the
- [[contextobject]]. Then <span>fix disallowed ancestors</span> of the
- result.
- <!-- It's possible to have disallowed ancestors in obscure corner cases,
- where a node is an allowed child of a p but p is not an allowed child of
- the node's parent and the node's parent is also not one of the whitelisted
- elements but is a block element. <xmp>[foo]</xmp> is the only case I can
- think of. -->
- </ol>
-
- <li>Otherwise, while <var>node list</var> is not empty:
-
- <ol>
- <li>If the first member of <var>node list</var> is a <span>non-list
- single-line container</span>:
+ <li>If the first member of <var>node list</var> is a <span>single-line
+ container</span>:
<ol>
+ <!--
+ If you try to format a single-line container with no children, IE10PP2
+ inserts an nbsp before formatting. (It uses nbsp instead of <br> to make
+ blocks not collapse, so the equivalent for us would be to insert a <br>.)
+ Firefox 7.0a2 and Opera 11.50 make the element disappear. Chrome 14 dev
+ leaves it alone and doesn't format it. I follow Firefox/Opera just
+ because it's the simplest given how I happen to have written the spec,
+ and it's a corner case, so exact behavior isn't important.
+
+ For blocks that contain only a collapsed whitespace node, IE10PP2 and
+ Firefox 7.0a2 convert them like normal. Chrome 14 dev and Opera 11.50
+ leave it alone and don't format it. I go with the majority, which is
+ again simpler to spec.
+ -->
<li>Let <var>sublist</var> be the [[children]] of the first member of
<var>node list</var>.
@@ -5485,16 +5484,16 @@
<li>While <var>node list</var> is not empty, and the first member of
<var>node list</var> is the [[nextsibling]] of the last member of
<var>sublist</var>, and the first member of <var>node list</var> is not a
- <span>non-list single-line container</span>, and the last member of
+ <span>single-line container</span>, and the last member of
<var>sublist</var> is not a [[br]], remove the first member of <var>node
list</var> and append it to <var>sublist</var>.
</ol>
- <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
- criteria</span> matching any <span>HTML element</span> with [[localname]]
- <var>value</var> and no attributes, and <span>new parent
- instructions</span> returning the result of running
- [[createelement|<var>value</var>]] on the [[contextobject]]. Then
+ <li><span>Wrap</span> <var>sublist</var>. If <var>value</var> is "div" or
+ "p", <span>sibling criteria</span> match nothing; otherwise they match any
+ <span>HTML element</span> with [[localname]] <var>value</var> and no
+ attributes. <span>New parent instructions</span> return the result of
+ running [[createelement|<var>value</var>]] on the [[contextobject]]. Then
<span>fix disallowed ancestors</span> of the result.
</ol>
</ol>
@@ -6275,6 +6274,18 @@
[[createelement|"br"]] on the [[contextobject]] and append the result as
the last [[child]] of <var>container</var>.
+ <li>If <var>container</var> is a [[dd]] or [[dt]], and it is not an
+ <span>allowed child</span> of any of its [[ancestors]] <span>in the same
+ editing host</span>, <span>set the tag name</span> of <var>container</var>
+ to the <span>default single-line container name</span> and let
+ <var>container</var> be the result.
+ <!--
+ Annoying hack to prevent the dl from being re-added when fixing disallowed
+ ancestors. In most cases we want a wrapper dl added, but in two cases
+ (delete and insertParagraph) we're actually trying to outdent the list
+ item. There might be a better way to do this.
+ -->
+
<li><span>Fix disallowed ancestors</span> of <var>container</var>.
<li>Abort these steps.
--- a/tests.js Sun Jul 10 09:40:21 2011 -0600
+++ b/tests.js Sun Jul 10 10:51:09 2011 -0600
@@ -1905,6 +1905,8 @@
'<dl><dt>{}<br></dt></dl>',
'<dl><dt>foo<dd>{}<br></dl>',
'<dl><dt>{}<br><dd>bar</dl>',
+ '<dl><dt>foo<dd>bar<dl><dt>{}<br><dd>baz</dl></dl>',
+ '<dl><dt>foo<dd>bar<dl><dt>baz<dd>{}<br></dl></dl>',
'<h1>foo[bar</h1><p>baz]quz</p>',
'<p>foo[bar</p><h1>baz]quz</h1>',