Rewrite underline to work with strikethrough
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Thu, 07 Apr 2011 15:08:58 -0600
changeset 49 c2df7ab3cca1
parent 48 7f271e7fde68
child 50 8971dcba61df
Rewrite underline to work with strikethrough
autoimplementation.html
editcommands.html
implementation.js
source.html
--- a/autoimplementation.html	Thu Apr 07 14:14:37 2011 -0600
+++ b/autoimplementation.html	Thu Apr 07 15:08:58 2011 -0600
@@ -796,12 +796,14 @@
 		// now this includes ignoring where the selection goes.
 		var normalizedSpecCell = tr.childNodes[1].childNodes[1].textContent
 			.replace(/[[\]{}]/g, "")
+			.replace(/: /g, ":")
 			.replace(/;? ?"/g, '"')
 			.replace(/<(\/?)strong/g, '<$1b')
 			.replace(/<(\/?)em/g, '<$1i')
 			.replace(/#[0-9a-fA-F]{6}/g, function(match) { return match.toUpperCase(); });
 		var normalizedBrowserCell = tr.childNodes[2].childNodes[1].textContent
 			.replace(/[[\]{}]/g, "")
+			.replace(/: /g, ":")
 			.replace(/;? ?"/g, '"')
 			.replace(/<(\/?)strong/g, '<$1b')
 			.replace(/<(\/?)em/g, '<$1i')
--- a/editcommands.html	Thu Apr 07 14:14:37 2011 -0600
+++ b/editcommands.html	Thu Apr 07 15:08:58 2011 -0600
@@ -221,13 +221,10 @@
 either a string or null:
 
 <ol>
-  <li>If <var title="">node</var> is neither an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> nor a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, return
+  <li>If neither <var title="">node</var> nor 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> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, return
   null.
 
-  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and 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> is null, return
-  null.
-
-  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, return the <a href=#effective-value>effective
+  <li>If <var title="">node</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, return the <a href=#effective-value>effective
   value</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> for <var title="">command</var>.
 
   <li>If <var title="">command</var> is "createLink" or "unlink":
@@ -290,7 +287,7 @@
   <li>If <var title="">command</var> is "underline", and the "text-decoration"
   property of <var title="">node</var> or 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> computes to
   a value containing "underline", return "underline".  Otherwise, return
-  "none".
+  null.
 
   <li>Return the computed style for <var title="">node</var> of the <a href=#relevant-css-property>relevant CSS
   property</a> for <var title="">command</var>.
@@ -330,6 +327,19 @@
     <li>Return null.
   </ol>
 
+  <li>If <var title="">command</var> is "underline", and <var title="">element</var> has a
+  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/html/#the-style-attribute>style</a></code> attribute set, and that attribute sets "text-decoration":
+
+  <ol>
+    <li>If <var title="">element</var>'s <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/html/#the-style-attribute>style</a></code> attribute sets "text-decoration" to a
+    value containing "underline", return "underline".
+
+    <li>Return null.
+  </ol>
+
+  <li>If <var title="">command</var> is "underline" and <var title="">element</var> is a <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/html/#the-u-element>u</a></code>
+  element, return "underline".
+
   <li>Let <var title="">property</var> be the <a href=#relevant-css-property>relevant CSS property</a> for
   <var title="">command</var>.
 
@@ -355,9 +365,6 @@
     <dt><code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/html/#the-i-element>i</a></code>
     <dt><code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/html/#the-em-element>em</a></code>
     <dd>font-style: "italic"
-
-    <dt><code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/html/#the-u-element>u</a></code>
-    <dd>text-decoration: "underline"
   </dl>
 
   <li>Return null.
@@ -544,22 +551,23 @@
     <li>Return <var title="">children</var>.
   </ol>
 
-  <li>Let <var title="">property</var> be the <a href=#relevant-css-property>relevant CSS property</a> for
-  <var title="">command</var>.
+  <li>If <var title="">command</var> is "underline", and <var title="">element</var> has a
+  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/html/#the-style-attribute>style</a></code> attribute that sets "text-decoration" to some value containing
+  "underline", delete "underline" from the value.
 
-  <li>If <var title="">property</var> is not null, unset the CSS property
-  <var title="">property</var> of <var title="">element</var>.
+  <li>If the <a href=#relevant-css-property>relevant CSS property</a> for <var title="">command</var> is not
+  null, unset that property of <var title="">element</var>.
 
   <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/html/#font>font</a></code> element:
 
   <ol>
-    <li>If <var title="">property</var> is "color", unset <var title="">element</var>'s
+    <li>If <var title="">command</var> is "foreColor", unset <var title="">element</var>'s
     <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/html/#dom-font-color>color</a></code> attribute, if set.
 
-    <li>If <var title="">property</var> is "font-family", unset
-    <var title="">element</var>'s <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/html/#dom-font-face>face</a></code> attribute, if set.
+    <li>If <var title="">command</var> is "fontName", unset <var title="">element</var>'s
+    <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/html/#dom-font-face>face</a></code> attribute, if set.
 
-    <li>If <var title="">property</var> is "font-size", unset <var title="">element</var>'s
+    <li>If <var title="">command</var> is "fontSize", unset <var title="">element</var>'s
     <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/html/#dom-font-size>size</a></code> attribute, if set.
   </ol>
 
@@ -915,6 +923,11 @@
   property</a> for <var title="">command</var> is not null, set that CSS property of
   <var title="">new parent</var> to <var title="">new value</var>.
 
+  <li>If <var title="">command</var> is "underline", and <var title="">new value</var> is
+  "underline", and the <a href=#effective-value>effective value</a> of "underline" for <var title="">new
+  parent</var> is not "underline", set the "text-decoration" property of
+  <var title="">new parent</var> to "underline".
+
   <li>Append <var title="">node</var> to <var title="">new parent</var> as 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>,
   <a href=#preserving-ranges>preserving ranges</a>.
 
@@ -927,9 +940,19 @@
 
     <li>Remove <var title="">new 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="">new parent</var> is a <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/html/#the-span-element>span</a></code>, and the <a href=#relevant-css-property>relevant CSS
-    property</a> for <var title="">command</var> is not null, set that CSS property
-    of <var title="">node</var> to <var title="">new value</var>.
+    <li>If <var title="">new parent</var> is a <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/html/#the-span-element>span</a></code>, and either <var title="">command</var>
+    is "underline" or the <a href=#relevant-css-property>relevant CSS property</a> for
+    <var title="">command</var> is not null:
+
+    <ol>
+      <li>If the <a href=#relevant-css-property>relevant CSS property</a> for <var title="">command</var> is
+      not null, set that CSS property of <var title="">node</var> to <var title="">new
+      value</var>.
+
+      <li>If <var title="">command</var> is "underline" and <var title="">new value</var> is
+      "underline", alter the "text-decoration" property of <var title="">node</var> to
+      include "underline" (preserving "overline" or "line-through" if present).
+    </ol>
 
     <li>Otherwise:
 
@@ -1169,7 +1192,7 @@
 
 <dd><strong>State</strong>: True if every <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> has <a href=#effective-value>effective
-value</a> either null or at least 700.  Otherwise false.
+value</a> at least 700.  Otherwise false.
 <!-- For bold and similar commands, IE 9 RC seems to consider the state true or
 false depending on the first element.  All other browsers follow the same
 general idea as the spec, considering a range bold only if all text in it is
@@ -1405,7 +1428,7 @@
 
 <dd><strong>State</strong>: True if every <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> has <a href=#effective-value>effective
-value</a> either null, "italic", or "oblique".  Otherwise false.
+value</a> either "italic" or "oblique".  Otherwise false.
 
 <dd><strong>Value</strong>: Always the empty string.
 
@@ -1438,7 +1461,7 @@
 
 <dd><strong>State</strong>: True if every <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> has <a href=#effective-value>effective
-value</a> either null or "sub".  Otherwise false.
+value</a> "sub".  Otherwise false.
 
 <dd><strong>Value</strong>:
 
@@ -1457,7 +1480,7 @@
 
 <dd><strong>State</strong>: True if every <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> has <a href=#effective-value>effective
-value</a> either null or "super".  Otherwise false.
+value</a> "super".  Otherwise false.
 
 <dd><strong>Value</strong>:
 
@@ -1468,9 +1491,8 @@
 
 <dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>.  If the
 state of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> for this command is then true, <a href=#set-the-value>set the
-value</a> of each returned <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> with <var title="">new value</var> "none".
-Otherwise, <a href=#set-the-value title="set the value">set their value</a> with <var title="">new
-value</var> "underline".
+value</a> of each returned <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> to null.  Otherwise, <a href=#set-the-value title="set
+the value">set their value</a> to "underline".
 
 <div class=XXX>
 <p>There are a lot of problems with underline color and thickness, because
@@ -1523,12 +1545,10 @@
 
 <dd><strong>State</strong>: True if every <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> has <a href=#effective-value>effective
-value</a> either null or "underline".  Otherwise false.
+value</a> "underline".  Otherwise false.
 
 <dd><strong>Value</strong>: Always the empty string.
 
-<dd><strong>Relevant CSS Property</strong>: "text-decoration"
-
 
 <dt><code title=""><dfn id=command-unlink title=command-unlink>unlink</dfn></code>
 
--- a/implementation.js	Thu Apr 07 14:14:37 2011 -0600
+++ b/implementation.js	Thu Apr 07 15:08:58 2011 -0600
@@ -281,21 +281,15 @@
  * "effective value" per edit command spec
  */
 function getEffectiveValue(node, command) {
-	// "If node is neither an Element nor a Text node, return null."
+	// "If neither node nor its parent is an Element, return null."
 	if (node.nodeType != Node.ELEMENT_NODE
-	&& node.nodeType != Node.TEXT_NODE) {
+	&& (!node.parentNode || node.parentNode.nodeType != Node.ELEMENT_NODE)) {
 		return null;
 	}
 
-	// "If node is a Text node and its parent is null, return null."
-	if (node.nodeType == Node.TEXT_NODE
-	&& !node.parentNode) {
-		return null;
-	}
-
-	// "If node is a Text node, return the effective value of its parent for
+	// "If node is not an Element, return the effective value of its parent for
 	// command."
-	if (node.nodeType == Node.TEXT_NODE) {
+	if (node.nodeType != Node.ELEMENT_NODE) {
 		return getEffectiveValue(node.parentNode, command);
 	}
 
@@ -401,7 +395,7 @@
 
 	// "If command is "underline", and the "text-decoration" property of node
 	// or any of its ancestors computes to a value containing "underline",
-	// return "underline". Otherwise, return "none"."
+	// return "underline". Otherwise, return null."
 	if (command == "underline") {
 		do {
 			if ((" " + getComputedStyle(node).textDecoration + " ").indexOf(" underline ") != -1) {
@@ -409,7 +403,7 @@
 			}
 			node = node.parentNode;
 		} while (node && node.nodeType == Node.ELEMENT_NODE);
-		return "none";
+		return null;
 	}
 
 	// "Return the computed style for node of the relevant CSS property for
@@ -475,6 +469,28 @@
 		return null;
 	}
 
+	// "If command is "underline", and element has a style attribute set, and
+	// that attribute sets "text-decoration":"
+	if (command == "underline"
+	&& element.style.textDecoration != "") {
+		// "If element's style attribute sets "text-decoration" to a value
+		// containing "underline", return "underline"."
+		if (element.style.textDecoration.indexOf("underline") != -1) {
+			return "underline";
+		}
+
+		// "Return null."
+		return null;
+	}
+
+	// "If command is "underline" and element is a u element, return
+	// "underline"."
+	if (command == "underline"
+	&& isHtmlElement(element)
+	&& element.tagName == "U") {
+		return "underline";
+	}
+
 	// "Let property be the relevant CSS property for command."
 	var property = getRelevantCssProperty(command);
 
@@ -520,10 +536,6 @@
 	&& (element.tagName == "I" || element.tagName == "EM")) {
 		return "italic";
 	}
-	if (property == "textDecoration"
-	&& element.tagName == "U") {
-		return "underline";
-	}
 
 	// "Return null."
 	return null;
@@ -847,12 +859,25 @@
 		return children;
 	}
 
-	// "Let property be the relevant CSS property for command."
-	var property = getRelevantCssProperty(command);
+	// "If command is "underline", and element has a style attribute that sets
+	// "text-decoration" to some value containing "underline", delete
+	// "underline" from the value."
+	if (command == "underline"
+	&& element.style.textDecoration.indexOf("underline") != -1) {
+		if (element.style.textDecoration == "underline") {
+			element.style.textDecoration = "";
+		} else {
+			element.style.textDecoration = element.style.textDecoration.replace("underline", "");
+		}
+		if (element.getAttribute("style") == "") {
+			element.removeAttribute("style");
+		}
+	}
 
-	// "If property is not null, unset the CSS property property of element."
-	if (property !== null) {
-		element.style[property] = '';
+	// "If the relevant CSS property for command is not null, unset the CSS
+	// property property of element."
+	if (getRelevantCssProperty(command) !== null) {
+		element.style[getRelevantCssProperty(command)] = '';
 		if (element.getAttribute("style") == "") {
 			element.removeAttribute("style");
 		}
@@ -860,20 +885,18 @@
 
 	// "If element is a font element:"
 	if (isHtmlNamespace(element.namespaceURI) && element.tagName == "FONT") {
-		// "If property is "color", unset element's color attribute, if set."
-		if (property == "color") {
+		// "If command is "foreColor", unset element's color attribute, if set."
+		if (command == "forecolor") {
 			element.removeAttribute("color");
 		}
 
-		// "If property is "font-family", unset element's face attribute, if
-		// set."
-		if (property == "fontFamily") {
+		// "If command is "fontName", unset element's face attribute, if set."
+		if (command == "fontname") {
 			element.removeAttribute("face");
 		}
 
-		// "If property is "font-size", unset element's size attribute, if
-		// set."
-		if (property == "fontSize") {
+		// "If command is "fontSize", unset element's size attribute, if set."
+		if (command == "fontsize") {
 			element.removeAttribute("size");
 		}
 	}
@@ -962,8 +985,8 @@
 
 	// "If the parent of the last member of ancestor list is not an Element,
 	// abort this algorithm."
-	if (!ancestorList[ancestorList.length - 1]
-	|| ancestorList[ancestorList.length - 1].nodeType != Node.ELEMENT_NODE) {
+	if (!ancestorList[ancestorList.length - 1].parentNode
+	|| ancestorList[ancestorList.length - 1].parentNode.nodeType != Node.ELEMENT_NODE) {
 		return;
 	}
 
@@ -1279,6 +1302,15 @@
 		newParent.style[property] = newValue;
 	}
 
+	// "If command is "underline", and new value is "underline", and the
+	// effective value of "underline" for new parent is not "underline", set
+	// the "text-decoration" property of new parent to "underline"."
+	if (command == "underline"
+	&& newValue == "underline"
+	&& getEffectiveValue(newParent, "underline") != "underline") {
+		newParent.style.textDecoration = "underline";
+	}
+
 	// "Append node to new parent as its last child, preserving ranges."
 	movePreservingRanges(node, newParent, newParent.childNodes.length);
 
@@ -1293,11 +1325,27 @@
 		// "Remove new parent from its parent."
 		newParent.parentNode.removeChild(newParent);
 
-		// "If new parent is a span, and the relevant CSS property for command
-		// is not null, set that CSS property of node to new value."
+		// "If new parent is a span, and either command is "underline" or the
+		// relevant CSS property for command is not null:"
 		if (newParent.tagName == "SPAN"
-		&& property !== null) {
-			node.style[property] = newValue;
+		&& (command == "underline" || property !== null)) {
+			// "If the relevant CSS property for command is not null, set that
+			// CSS property of node to new value."
+			if (property !== null) {
+				node.style[property] = newValue;
+			}
+
+			// "If command is "underline" and new value is "underline", alter
+			// the "text-decoration" property of node to include "underline"
+			// (preserving "overline" or "line-through" if present)."
+			if (command == "underline" && newValue == "underline") {
+				if (node.style.textDecoration == ""
+				|| node.style.textDecoration == "none") {
+					node.style.textDecoration = "underline";
+				} else {
+					node.style.textDecoration += " underline";
+				}
+			}
 
 			// "Otherwise:"
 		} else {
@@ -1402,7 +1450,6 @@
 		italic: "fontStyle",
 		subscript: "verticalAlign",
 		superscript: "verticalAlign",
-		underline: "textDecoration",
 	}[command];
 
 	if (typeof prop == "undefined") {
@@ -1564,10 +1611,10 @@
 
 		case "underline":
 		// "Decompose the range. If the state of the range for this command is
-		// then true, set the value of each returned node with new value
-		// "none". Otherwise, set their value with new value "underline"."
+		// then true, set the value of each returned node to null. Otherwise,
+		// set their value to "underline"."
 		var nodeList = decomposeRange(range);
-		var newValue = getState("underline", range) ? "none" : "underline";
+		var newValue = getState("underline", range) ? null : "underline";
 		for (var i = 0; i < nodeList.length; i++) {
 			setNodeValue(nodeList[i], command, newValue);
 		}
@@ -1637,11 +1684,9 @@
 
 		if (command == "bold") {
 			// "True if every Text node that is effectively contained in the
-			// range has effective value either null or at least 700. Otherwise
-			// false."
+			// range has effective value at least 700. Otherwise false."
 			var fontWeight = getEffectiveValue(node, command);
-			if (fontWeight !== null
-			&& fontWeight !== "bold"
+			if (fontWeight !== "bold"
 			&& fontWeight !== "700"
 			&& fontWeight !== "800"
 			&& fontWeight !== "900") {
@@ -1649,36 +1694,32 @@
 			}
 		} else if (command == "italic") {
 			// "True if every Text node that is effectively contained in the
-			// range has effective value either null, "italic", or "oblique".
+			// range has effective value either "italic" or "oblique".
 			// Otherwise false."
 			var fontStyle = getEffectiveValue(node, command);
-			if (fontStyle !== null
-			&& fontStyle !== "italic"
+			if (fontStyle !== "italic"
 			&& fontStyle !== "oblique") {
 				return false;
 			}
 		} else if (command == "underline") {
 			// "True if every Text node that is effectively contained in the
-			// range has effective value either null or "underline". Otherwise
-			// false."
+			// range has effective value "underline". Otherwise false."
 			var textDecoration = getEffectiveValue(node, command);
-			if (textDecoration !== null && textDecoration !== "underline") {
+			if (textDecoration !== "underline") {
 				return false;
 			}
 		} else if (command == "subscript") {
 			// "True if every Text node that is effectively contained in the
-			// range has effective value either null or "sub". Otherwise
-			// false."
+			// range has effective value "sub". Otherwise false."
 			var verticalAlign = getEffectiveValue(node, command);
-			if (verticalAlign !== null && verticalAlign !== "sub") {
+			if (verticalAlign !== "sub") {
 				return false;
 			}
 		} else if (command == "superscript") {
 			// "True if every Text node that is effectively contained in the
-			// range has effective value either null or "super". Otherwise
-			// false."
+			// range has effective value "super". Otherwise false."
 			var verticalAlign = getEffectiveValue(node, command);
-			if (verticalAlign !== null && verticalAlign !== "super") {
+			if (verticalAlign !== "super") {
 				return false;
 			}
 		}
--- a/source.html	Thu Apr 07 14:14:37 2011 -0600
+++ b/source.html	Thu Apr 07 15:08:58 2011 -0600
@@ -210,13 +210,10 @@
 either a string or null:
 
 <ol>
-  <li>If <var>node</var> is neither an [[element]] nor a [[text]] node, return
+  <li>If neither <var>node</var> nor its [[parent]] is an [[element]], return
   null.
 
-  <li>If <var>node</var> is a [[text]] node and its [[parent]] is null, return
-  null.
-
-  <li>If <var>node</var> is a [[text]] node, return the <span>effective
+  <li>If <var>node</var> is not an [[element]], return the <span>effective
   value</span> of its [[parent]] for <var>command</var>.
 
   <li>If <var>command</var> is "createLink" or "unlink":
@@ -279,7 +276,7 @@
   <li>If <var>command</var> is "underline", and the "text-decoration"
   property of <var>node</var> or any of its [[ancestors]] computes to
   a value containing "underline", return "underline".  Otherwise, return
-  "none".
+  null.
 
   <li>Return the computed style for <var>node</var> of the <span>relevant CSS
   property</span> for <var>command</var>.
@@ -319,6 +316,19 @@
     <li>Return null.
   </ol>
 
+  <li>If <var>command</var> is "underline", and <var>element</var> has a
+  [[style]] attribute set, and that attribute sets "text-decoration":
+
+  <ol>
+    <li>If <var>element</var>'s [[style]] attribute sets "text-decoration" to a
+    value containing "underline", return "underline".
+
+    <li>Return null.
+  </ol>
+
+  <li>If <var>command</var> is "underline" and <var>element</var> is a [[u]]
+  element, return "underline".
+
   <li>Let <var>property</var> be the <span>relevant CSS property</span> for
   <var>command</var>.
 
@@ -344,9 +354,6 @@
     <dt>[[i]]
     <dt>[[em]]
     <dd>font-style: "italic"
-
-    <dt>[[u]]
-    <dd>text-decoration: "underline"
   </dl>
 
   <li>Return null.
@@ -537,22 +544,23 @@
     <li>Return <var>children</var>.
   </ol>
 
-  <li>Let <var>property</var> be the <span>relevant CSS property</span> for
-  <var>command</var>.
+  <li>If <var>command</var> is "underline", and <var>element</var> has a
+  [[style]] attribute that sets "text-decoration" to some value containing
+  "underline", delete "underline" from the value.
 
-  <li>If <var>property</var> is not null, unset the CSS property
-  <var>property</var> of <var>element</var>.
+  <li>If the <span>relevant CSS property</span> for <var>command</var> is not
+  null, unset that property of <var>element</var>.
 
   <li>If <var>element</var> is a [[font]] element:
 
   <ol>
-    <li>If <var>property</var> is "color", unset <var>element</var>'s
+    <li>If <var>command</var> is "foreColor", unset <var>element</var>'s
     [[fontcolor]] attribute, if set.
 
-    <li>If <var>property</var> is "font-family", unset
-    <var>element</var>'s [[fontface]] attribute, if set.
+    <li>If <var>command</var> is "fontName", unset <var>element</var>'s
+    [[fontface]] attribute, if set.
 
-    <li>If <var>property</var> is "font-size", unset <var>element</var>'s
+    <li>If <var>command</var> is "fontSize", unset <var>element</var>'s
     [[fontsize]] attribute, if set.
   </ol>
 
@@ -924,6 +932,11 @@
   property</span> for <var>command</var> is not null, set that CSS property of
   <var>new parent</var> to <var>new value</var>.
 
+  <li>If <var>command</var> is "underline", and <var>new value</var> is
+  "underline", and the <span>effective value</span> of "underline" for <var>new
+  parent</var> is not "underline", set the "text-decoration" property of
+  <var>new parent</var> to "underline".
+
   <li>Append <var>node</var> to <var>new parent</var> as its last [[child]],
   <span>preserving ranges</span>.
 
@@ -936,9 +949,19 @@
 
     <li>Remove <var>new parent</var> from its [[parent]].
 
-    <li>If <var>new parent</var> is a [[span]], and the <span>relevant CSS
-    property</span> for <var>command</var> is not null, set that CSS property
-    of <var>node</var> to <var>new value</var>.
+    <li>If <var>new parent</var> is a [[span]], and either <var>command</var>
+    is "underline" or the <span>relevant CSS property</span> for
+    <var>command</var> is not null:
+
+    <ol>
+      <li>If the <span>relevant CSS property</span> for <var>command</var> is
+      not null, set that CSS property of <var>node</var> to <var>new
+      value</var>.
+
+      <li>If <var>command</var> is "underline" and <var>new value</var> is
+      "underline", alter the "text-decoration" property of <var>node</var> to
+      include "underline" (preserving "overline" or "line-through" if present).
+    </ol>
 
     <li>Otherwise:
 
@@ -1182,7 +1205,7 @@
 
 <dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
-value</span> either null or at least 700.  Otherwise false.
+value</span> at least 700.  Otherwise false.
 <!-- For bold and similar commands, IE 9 RC seems to consider the state true or
 false depending on the first element.  All other browsers follow the same
 general idea as the spec, considering a range bold only if all text in it is
@@ -1424,7 +1447,7 @@
 
 <dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
-value</span> either null, "italic", or "oblique".  Otherwise false.
+value</span> either "italic" or "oblique".  Otherwise false.
 
 <dd><strong>Value</strong>: Always the empty string.
 
@@ -1457,7 +1480,7 @@
 
 <dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
-value</span> either null or "sub".  Otherwise false.
+value</span> "sub".  Otherwise false.
 
 <dd><strong>Value</strong>:
 
@@ -1476,7 +1499,7 @@
 
 <dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
-value</span> either null or "super".  Otherwise false.
+value</span> "super".  Otherwise false.
 
 <dd><strong>Value</strong>:
 
@@ -1487,9 +1510,8 @@
 
 <dd><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>set the
-value</span> of each returned [[node]] with <var>new value</var> "none".
-Otherwise, <span title="set the value">set their value</span> with <var>new
-value</var> "underline".
+value</span> of each returned [[node]] to null.  Otherwise, <span title="set
+the value">set their value</span> to "underline".
 
 <div class=XXX>
 <p>There are a lot of problems with underline color and thickness, because
@@ -1544,12 +1566,10 @@
 
 <dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
-value</span> either null or "underline".  Otherwise false.
+value</span> "underline".  Otherwise false.
 
 <dd><strong>Value</strong>: Always the empty string.
 
-<dd><strong>Relevant CSS Property</strong>: "text-decoration"
-
 
 <dt><code title><dfn title=command-unlink>unlink</dfn></code>