Commit another day's work
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Thu, 24 Mar 2011 15:43:26 -0600
changeset 27 61e55187231f
parent 26 4dead548b9d6
child 28 016f8f5f3c84
Commit another day's work

A lot of it was spent trying to get the autoimplementation to work in
IE. The rest was mostly research and testing, so not many normative
spec changes.
autoimplementation.html
editcommands.html
source.html
--- a/autoimplementation.html	Wed Mar 23 16:03:54 2011 -0600
+++ b/autoimplementation.html	Thu Mar 24 15:43:26 2011 -0600
@@ -23,10 +23,14 @@
 <p>Legend: {[ are the selection anchor, }] are the selection focus, {}
 represent an element boundary point, [] represent a text node boundary point.
 Syntax and some of the tests taken from <a
-href=http://www.browserscope.org/richtext2/test>Browserscope</a>.
+href=http://www.browserscope.org/richtext2/test>Browserscope</a>.  data-start
+and data-end attributes also represent element boundary points, with the node
+being the element with the attribute and the offset given as the attribute
+value, for cases where HTML parsing doesn't allow text nodes.
 
 <h1>Table of Contents</h1>
 <ul>
+	<li><a href=#backcolor>backcolor</a>
 	<li><a href=#bold>bold</a>
 	<li><a href=#fontname>fontname</a>
 	<li><a href=#forecolor>forecolor</a>
@@ -35,9 +39,25 @@
 	<li><a href=#underline>underline</a>
 </ul>
 
+<div id=backcolor>
+<h1>backcolor</h1>
+
+<button onclick="runTests('backcolor')">Run tests</button>
+
+<p>Tests set the color to "#FF8888".
+
+<table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
+<table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
+
+<p><label>Enter new test here: <input></label>
+<button onclick="addTest('backcolor', document.querySelector('#backcolor input').value)">Add test</button>
+</div>
+
 <div id=bold>
 <h1>bold</h1>
 
+<button onclick="runTests('bold')">Run tests</button>
+
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 
@@ -48,18 +68,22 @@
 <div id=fontname>
 <h1>fontname</h1>
 
+<button onclick="runTests('fontname')">Run tests</button>
+
 <p>Tests set the font-family to "sans-serif".  Note that the body's font-family is "serif".
 
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 
 <p><label>Enter new test here: <input></label>
-<button onclick="addTest('bold', document.querySelector('#fontname input').value)">Add test</button>
+<button onclick="addTest('fontname', document.querySelector('#fontname input').value)">Add test</button>
 </div>
 
 <div id=forecolor>
 <h1>forecolor</h1>
 
+<button onclick="runTests('forecolor')">Run tests</button>
+
 <p>Tests set the color to "#FF0000".
 
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
@@ -72,7 +96,9 @@
 <div id=hilitecolor>
 <h1>hilitecolor</h1>
 
-<p>Tests set the color to "#FF8888".
+<button onclick="runTests('hilitecolor')">Run tests</button>
+
+<p>Tests set the color to "#FF8888".  In IE we run backColor instead of hiliteColor.
 
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 
@@ -83,6 +109,8 @@
 <div id=italic>
 <h1>italic</h1>
 
+<button onclick="runTests('italic')">Run tests</button>
+
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 
@@ -93,6 +121,8 @@
 <div id=underline>
 <h1>underline</h1>
 
+<button onclick="runTests('underline')">Run tests</button>
+
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 <table border=1><tr><th>Input <th>Spec <th>Browser <th>Same?</table>
 
@@ -103,6 +133,7 @@
 <script src=implementation.js></script>
 <script>
 var values = {
+	backcolor: "#FF8888",
 	bold: null,
 	fontname: "sans-serif",
 	forecolor: "#FF0000",
@@ -112,10 +143,27 @@
 };
 
 var tests = {
+	backcolor: [
+		'<p>foo[bar]baz',
+		'<p>foo]bar[baz',
+		'<div><p>foo[bar]baz</p></div>',
+
+		'<table><tbody><tr><td>foo<td>b[a]r<td>baz</table>',
+		'<table><tbody><tr data-start=1 data-end=2><td>foo<td>bar<td>baz</table>',
+		'<table><tbody><tr data-start=0 data-end=2><td>foo<td>bar<td>baz</table>',
+		'<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table>',
+		'<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>',
+		'{<table><tr><td>foo<td>bar<td>baz</table>}',
+
+		'{<p><p> <p>foo</p>}',
+		'{<p>foo</p><p>bar</p>}',
+		'<p>[foo</p><p>bar]</p>',
+		'<p>foo[bar<i>baz]qoz</i>quz',
+	],
 	bold: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 		'foo[bar<i>baz]qoz</i>quz',
 
 		'foo<span style="font-weight: bold">[bar]</span>baz',
@@ -177,32 +225,34 @@
 		'<span style="font-weight: 700">foo[barbaz</span>}',
 		'<span style="font-weight: 900">foo[barbaz</span>}',
 
-		'<h3>Foo[bar]baz</h3>',
-		'{<h3>Foobar]baz</h3>',
-		'<h3>Foo[barbaz</h3>}',
-		'<h3>[Foobarbaz]</h3>',
-		'{<h3>Foobarbaz]</h3>',
-		'<h3>[Foobarbaz</h3>}',
-		'{<h3>Foobarbaz</h3>}',
+		'<h3>foo[bar]baz</h3>',
+		'{<h3>foobar]baz</h3>',
+		'<h3>foo[barbaz</h3>}',
+		'<h3>[foobarbaz]</h3>',
+		'{<h3>foobarbaz]</h3>',
+		'<h3>[foobarbaz</h3>}',
+		'{<h3>foobarbaz</h3>}',
 
-		'<b>Foo<span style="font-weight: normal">bar<b>[baz]</b>quz</span>qoz</b>',
-		'<b>Foo<span style="font-weight: normal">[bar]</span>baz</b>',
+		'<b>foo<span style="font-weight: normal">bar<b>[baz]</b>quz</span>qoz</b>',
+		'<b>foo<span style="font-weight: normal">[bar]</span>baz</b>',
 
-		'{<b>Foo</b> <b>bar</b>}',
-		'{<h3>Foo</h3><b>bar</b>}',
+		'{<b>foo</b> <b>bar</b>}',
+		'{<h3>foo</h3><b>bar</b>}',
 
-		'<i><b>Foo</b></i>[bar]<i><b>baz</b></i>',
-		'<i><b>Foo</b></i>[bar]<b>baz</b>',
-		'<b>Foo</b>[bar]<i><b>baz</b></i>',
-		'<font color=red face=monospace><b>Foo</b></font>[bar]',
+		'<i><b>foo</b></i>[bar]<i><b>baz</b></i>',
+		'<i><b>foo</b></i>[bar]<b>baz</b>',
+		'<b>foo</b>[bar]<i><b>baz</b></i>',
+		'<font color=red face=monospace><b>foo</b></font>[bar]',
 
 		'foo<span style="font-weight: normal"><b>{bar}</b></span>baz',
-		'[Foo<span class=notbold>bar</span>baz]',
+		'[foo<span class=notbold>bar</span>baz]',
+
+		'<p style="font-weight: bold">foo[bar]baz</p>',
 	],
 	fontname: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 
 		'foo<code>[bar]</code>baz',
 		'foo<kbd>[bar]</kbd>baz',
@@ -247,7 +297,7 @@
 	forecolor: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 		'foo[bar<i>baz]qoz</i>quz',
 		'foo<font color=red>[bar]</font>baz',
 		'foo{<font color=red>bar</font>}baz',
@@ -263,17 +313,24 @@
 	hilitecolor: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 		'foo[bar<i>baz]qoz</i>quz',
 		'<p style="background-color: rgb(255, 136, 136)">foo[bar]baz</p>',
 		'<p style="background-color: #ff8888">foo[bar]baz</p>',
 		'<p style="background-color: aqua">foo[bar]baz</p>',
 		'{<p style="background-color: aqua">foo</p><p>bar</p>}',
+		'<span style="background-color: #ff8888">foo<span style="background-color: aqua">[bar]</span>baz</span>',
+		'<span style="background-color: #f88">foo<span style="background-color: aqua">[bar]</span>baz</span>',
+		'<span style="background-color: rgb(255, 136, 136)">foo<span style="background-color: aqua">[bar]</span>baz</span>',
+		'<span style="background-color: #ff8888">foo<span style="background-color: aqua">b[ar]</span>baz</span>',
+		'<p style="background-color: #ff8888">foo<span style="background-color: aqua">b[ar]</span>baz</p>',
+		'<div style="background-color: #ff8888"><p style="background-color: aqua">b[ar]</p></div>',
+		'<span style="display: block; background-color: #ff8888"><span style="display: block; background-color: aqua">b[ar]</span></span>',
 	],
 	italic: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 		'foo[bar<b>baz]qoz</b>quz',
 		'foo<span style="font-style: italic">[bar]</span>baz',
 		'foo<address>[bar]</address>baz',
@@ -325,7 +382,7 @@
 	underline: [
 		'foo[bar]baz',
 		'foo]bar[baz',
-		'{<p><p> <p>Foo</p>}',
+		'{<p><p> <p>foo</p>}',
 		'foo[bar<b>baz]qoz</b>quz',
 		'foo<u>[bar]</u>baz',
 		'foo<span style="text-decoration: underline">[bar]</span>baz',
@@ -338,15 +395,35 @@
 	],
 };
 
-for (testCat in tests) {
-	for (var i = 0; i < tests[testCat].length; i++) {
-		addTest(testCat, tests[testCat][i]);
+function runTests(command) {
+	var runTestsButton = document.querySelector("#" + command + " button");
+	runTestsButton.parentNode.removeChild(runTestsButton);
+
+	var addTestButton = document.querySelector("#" + command + " button");
+	var input = document.querySelector("#" + command + " input");
+	for (var i = 0; i < tests[command].length; i++) {
+		// The following code should logically be equivalent to:
+		//   addTest(command, tests[command][i]);
+		// But that only works to set one cell, in IE9.  All the other tests
+		// fail.  So, um, WTF, but it works.
+		input.value = tests[command][i];
+		input.focus();
+		addTestButton.click();
 	}
+	input.value = "";
 }
 
 function addTest(command, test) {
-	var doubleTesting = ["bold", "italic", "underline", "forecolor",
-	"fontname", "fontsize"].indexOf(command) != -1;
+	var doubleTesting = ["backcolor", "bold", "italic", "underline",
+	"forecolor", "fontname", "fontsize"].indexOf(command) != -1;
+
+	// I tried to feature-detect styleWithCSS, but it was too much of a pain,
+	// with Firefox randomly throwing exceptions all over the place.  So I'm
+	// just browser-sniffing here.
+	if (navigator.userAgent.indexOf("Opera") != -1
+	|| navigator.userAgent.indexOf("MSIE") != -1) {
+		doubleTesting = false;
+	}
 
 	var tr = doSetup(command, 0);
 
@@ -368,10 +445,7 @@
 }
 
 function doSetup(command, idx) {
-	var div = document.getElementById(command);
-	div.contentEditable = "true";
-	div.spellcheck = false;
-	var table = div.querySelectorAll("table")[idx];
+	var table = document.querySelectorAll("#" + command + " > table")[idx];
 
 	var tr = document.createElement("tr");
 	// Insert at the top, because Chrome debugger doesn't let you scroll down
@@ -397,11 +471,9 @@
 	var value = values[command];
 
 	var specCell = document.createElement("td");
-	specCell.innerHTML = "<div></div><div></div>";
-	specCell.firstChild.innerHTML = test;
 	tr.appendChild(specCell);
 	try {
-		var points = parseBrackets(specCell);
+		var points = setupCell(specCell, test);
 		var range = document.createRange();
 		range.setStart(points[0], points[1]);
 		range.setEnd(points[2], points[3]);
@@ -436,12 +508,22 @@
 function doBrowserCell(tr, test, command, styleWithCss) {
 	var value = values[command];
 
+	if (command == "hilitecolor" && navigator.userAgent.indexOf("MSIE") != -1) {
+		// IE behaves differently, and I want to see how it works.
+		command = "backcolor";
+	}
+
+	if (command == "hilitecolor") {
+		// Firefox refuses to do anything unless styleWithCSS is true.
+		styleWithCss = true;
+	}
+
 	var browserCell = document.createElement("td");
-	browserCell.innerHTML = "<div></div><div></div>";
-	browserCell.firstChild.innerHTML = test;
 	tr.appendChild(browserCell);
 	try {
-		var points = parseBrackets(browserCell);
+		var points = setupCell(browserCell, test);
+		browserCell.firstChild.contentEditable = "true";
+		browserCell.firstChild.spellcheck = false;
 		setSelection(points[0], points[1], points[2], points[3]);
 		try {
 			document.execCommand("styleWithCSS", false, styleWithCss);
@@ -451,26 +533,57 @@
 	} catch (e) {
 		browserCell.textContent = "Exception: " + e;
 	}
+	browserCell.firstChild.contentEditable = "inherit";
+	browserCell.firstChild.removeAttribute("spellcheck");
 }
 
 function doSameCell(tr) {
 	var sameCell = document.createElement("td");
-	// Ad hoc normalization to avoid basically spurious mismatches
-	var normalizedSpecCell = tr.childNodes[1].childNodes[1].textContent
-		.replace(/;? ?"/g, '"');
-	var normalizedBrowserCell = tr.childNodes[2].childNodes[1].textContent
-		.replace(/;? ?"/g, '"')
-		.replace(/<(\/?)strong/g, '<$1b')
-		.replace(/<(\/?)em/g, '<$1i')
-		.replace(/ class="Apple-style-span"/g, "");
-	if (normalizedSpecCell == normalizedBrowserCell) {
+	var exception = false;
+	try {
+		// Ad hoc normalization to avoid basically spurious mismatches
+		var normalizedSpecCell = tr.childNodes[1].childNodes[1].textContent
+			.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(/<(\/?)strong/g, '<$1b')
+			.replace(/<(\/?)em/g, '<$1i')
+			.replace(/#[0-9a-fA-F]{6}/g, function(match) { return match.toUpperCase(); })
+			.replace(/ class="Apple-style-span"/g, "");
+		if (navigator.userAgent.indexOf("MSIE") != -1) {
+			// IE produces <font style> instead of <span style>, so let's
+			// translate all <span>s to <font>s.
+			normalizedSpecCell = normalizedSpecCell
+				.replace(/<(\/?)span/g, '<$1font');
+			normalizedBrowserCell = normalizedBrowserCell
+				.replace(/<(\/?)span/g, '<$1font');
+		}
+	} catch (e) {
+		exception = true;
+	}
+	if (!exception && normalizedSpecCell == normalizedBrowserCell) {
 		sameCell.className = "yes";
-		sameCell.innerHTML = "&#x2713;";
+		sameCell.textContent = "\u2713";
 	} else {
 		sameCell.className = "no";
-		sameCell.innerHTML = "&#x2717;";
+		sameCell.textContent = "\u2717";
 	}
 	tr.appendChild(sameCell);
+
+	// Insert zero-width spaces so IE doesn't stretch the screen
+	try {
+		tr.childNodes[2].childNodes[1].textContent =
+			tr.childNodes[2].childNodes[1].textContent
+			.replace(/</g, "\u200B<")
+			.replace(/>/g, ">\u200B");
+		tr.childNodes[1].childNodes[1].textContent =
+			tr.childNodes[1].childNodes[1].textContent
+			.replace(/</g, "\u200B<")
+			.replace(/>/g, ">\u200B");
+	} catch (e) {};
 }
 
 function doTearDown(command) {
@@ -478,17 +591,49 @@
 	document.getElementById(command).contentEditable = "inherit";
 }
 
-function parseBrackets(node) {
-	if (node.textContent.replace(/[^{[]/g, "").length != 1) {
-		throw "Need one [ or {, found " + node.textContent.replace(/[^{[]/g, "").length;
+function setupCell(cell, test) {
+	// A variety of checks to avoid simple errors.  Not foolproof, of course.
+	var startMarkers = /\{|\[|data-start/.exec(test);
+	if (!startMarkers) {
+		startMarkers = [];
+	}
+	if (startMarkers.length != 1) {
+		throw "Need exactly one start marker ([ or { or data-start), found " + startMarkers.length;
 	}
 
-	if (node.textContent.replace(/[^}\]]/g, "").length != 1) {
-		throw "Need one ] or }, found " + node.textContent.replace(/[^}\]]/g, "").length;
+	var endMarkers = /\}|\]|data-end/.exec(test);
+	if (!endMarkers) {
+		endMarkers = [];
+	}
+	if (endMarkers.length != 1) {
+		throw "Need exactly one end marker (] or } or data-end), found " + endMarkers.length;
 	}
 
+	cell.innerHTML = "<div></div><div></div>";
+	node = cell.firstChild;
+	node.innerHTML = test;
+
 	var startNode, startOffset, endNode, endOffset;
 
+	// For braces that don't lie inside text nodes, we can't just set
+	// innerHTML, because that might disturb the DOM.  For instance, if the
+	// brace is right before a <tr>, it could get moved outside the table
+	// entirely, which messes everything up pretty badly.  So we instead
+	// allow using data attributes: data-start and data-end on the start and
+	// end nodes, with a numeric value indicating the offset.  This format
+	// doesn't allow the parent div to be a start or end node, but in that case
+	// you can always use the curly braces.
+	if (node.querySelector("[data-start]")) {
+		startNode = node.querySelector("[data-start]");
+		startOffset = startNode.getAttribute("data-start");
+		startNode.removeAttribute("data-start");
+	}
+	if (node.querySelector("[data-end]")) {
+		endNode = node.querySelector("[data-end]");
+		endOffset = endNode.getAttribute("data-end");
+		endNode.removeAttribute("data-end");
+	}
+
 	var cur = node;
 	while (true) {
 		if (!cur || (cur != node && !(cur.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_CONTAINS))) {
--- a/editcommands.html	Wed Mar 23 16:03:54 2011 -0600
+++ b/editcommands.html	Thu Mar 24 15:43:26 2011 -0600
@@ -27,7 +27,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-23-march-2011>Work in Progress &mdash; Last Update 23 March 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-24-march-2011>Work in Progress &mdash; Last Update 24 March 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -135,6 +135,9 @@
 
 <h2 id=issues><span class=secno>2 </span>Issues</h2>
 
+<p>This specification is very preliminary, and should not be used for anything
+other than review and comment.
+
 <ul>
   <li>Need to make CSS terminology more precise, about setting/unsetting CSS
   properties.  The intent is to modify the style attribute, CSSOM-style.
@@ -167,6 +170,9 @@
   <li>I don't pay attention to whether designMode/contenteditable is actually
   set.  I should be doing things like not doing anything if the selection isn't
   editable, making sure not to break out of contenteditable regions, etc.
+
+  <li>I haven't yet paid any attention to value parsing.  This is going to be
+  important to specify exactly in some cases, like with colors.
 </ul>
 
 <p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -532,32 +538,38 @@
 <var title="">node</var>, given a CSS property name <var title="">property</var> and a new value
 <var title="">new value</var>, it must run the following steps:
 
-<!-- This algorithm goes up to just below the nearest ancestor with the right
+<div class=XXX>
+<p>This algorithm goes up to just below the nearest ancestor with the right
 style, then re-applies the bad styles repeatedly going down, omitting the
 things we want to have the new style.  This is basically what WebKit does,
 although WebKit sometimes starts higher up and therefore makes more intrusive
-changes, often creating more markup.
+changes, often creating more markup.  IE follows the same general approach too.
 
-Gecko instead seems to start breaking up elements from the bottom, so that the
+<p>Gecko instead seems to start breaking up elements from the bottom, so that the
 range consists of a few consecutive siblings, and it can then break up the
 problematic element into a maximum of two pieces.  The spec's approach seems to
 create fewer elements and simpler markup (or at least markup that's no more
-complex) in every case I throw at it.
+complex) in most cases I throw at it.
 
-Gecko's approach does have the major advantage that it gets underlines right in
+<p>Gecko's approach does have the major advantage that it gets underlines right in
 many cases for free.  E.g.,
 
-  <u>foo<font color=red>[bar]baz</font></u>
+</p><xmp>  <u>foo<font color=red>[bar]baz</font></u>
   -> <u>foo</u><font color=red>bar<u>baz</u></font> (spec)
-  -> <u>foo</u><font color=red>bar</font><u><font color=red>baz</font></u> (Gecko)
+  -> <u>foo</u><font color=red>bar</font><u><font color=red>baz</font></u> (Gecko)</xmp>
 
-The spec's markup here is much shorter and contains fewer elements, but is
+<p>The spec's markup here is much shorter and contains fewer elements, but is
 wrong: the underline under "baz" has changed color from black to red.  It might
 be worth trying to copy Gecko's results in such cases, but that won't solve all
 underline problems, so perhaps it's not worth it.
 
-Opera also seems to break up the markup surrounding the range, but even more
-aggressively: even if it doesn't need to pull down styles. -->
+<p>Opera also seems to break up the markup surrounding the range, but even more
+aggressively: even if it doesn't need to pull down styles.  In some cases this
+does actually result in shorter markup, specifically if the existing tags are
+short (like <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a> or <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>) and we're adding tags that are long (like <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>
+with a <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a> attribute).
+</div>
+
 <ol>
   <li>If <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-parent title=concept-tree-parent>parent</a> is not an <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>, abort this
   algorithm. <!-- E.g., a text node child of a document fragment. -->
@@ -749,6 +761,11 @@
     <li><a href=#force-the-style>Force the style</a> of each <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> in <var title="">children</var>,
     with <var title="">property</var> and <var title="">new value</var> as in this invocation of
     the algorithm.
+    <!-- This means that if it has no children, we do nothing.  IE9 inserts an
+    empty wrapper element in that case, but I'm not sure what the point is, and
+    no one else does, so I don't.  WebKit seems to ignore the node if its only
+    child consists solely of whitespace, but I don't see any grounds for that
+    and no one else does, so I don't. -->
 
     <li>Abort this algorithm.
   </ol>
@@ -998,19 +1015,69 @@
 <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#ascii-case-insensitive>ASCII case-insensitive</a> manner.
 
 <dl>
+<dt><code title=""><dfn id=command-backcolor title=command-backcolor>backColor</dfn></code>
+
+<dd><strong>Action</strong>:
+
+<div class=XXX>
+<p>We have three behaviors to choose from for this one:
+
+<ol>
+  <li>Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9
+  RC doesn't support hiliteColor itself).
+
+  <li>Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
+  something like that.  In testing, it seems to jump out of contenteditable
+  elements to style non-editable ancestors, which is alarming.
+
+  <li>Firefox 4 in CSS mode and Opera 11 set the background of the nearest
+  block container, although it doesn't seem to be very dependable (probably I
+  just don't get what exactlyit's doing).
+</ol>
+
+<p>(1) is obviously redundant, but has plurality support, so we could spec it
+that way if the other ways were useless.
+
+<p>(3) is incoherent from a user perspective.  For instance, if you try it on
+paragraphs the background will have big gaps where the margins are.  If you try
+it on an inline element that's a child of the editing host, it will do nothing
+or apply the background to everything or such, even though such an inline
+element is visually indistinguishable from one sitting inside a div.  This
+would only make sense if we take considerable effort to ensure that block
+elements all have no margins, or if we wrap things in a div if they have
+margins, or something like that.
+
+<p>That leaves (2).  That might be useful if it actually set the document's
+background color, but it seems like it sets table cell backgrounds sometimes
+instead, which is really confusing.
+
+<p>The path of least resistance seems to be to standardize this as meaning the
+same thing as hiliteColor, and make up new commands if we want to do things
+like set the document background color.  Feedback appreciated on this point.
+</div>
+
+<dd><strong>State</strong>:
+
+<dd><strong>Value</strong>:
+
+
 <dt><code title=""><dfn id=command-bold title=command-bold>bold</dfn></code>
 
-<dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
+<dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
 state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
 returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "font-weight" and <var title="">new
 value</var> "normal".  Otherwise, <a href=#style>style</a> them with <var title="">new
 value</var> "bold".
 
-<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
+<dd><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective
 style</a> either null or at least 700 for font-weight.  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
+bold, and this seems to match at least OpenOffice.org's bold feature. -->
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 <!-- We have lots of options here (and presumably for all the others where
 value is meaningless).  IE 9 RC returns the boolean false, Firefox 4b11 and
 Opera 11 both return the empty string, Chrome 10 returns the string "false".
@@ -1022,7 +1089,7 @@
 
 <dt><code title=""><dfn id=command-createlink title=command-createlink>createLink</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must run the following steps:
+<dd><strong>Action</strong>: The user agent must run the following steps:
 
 <ol>
   <li>If <var title="">value</var> is the empty string, abort these steps and do
@@ -1101,15 +1168,15 @@
   </ol>
 </ol>
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 <!-- I'd have expected the value to be the URL, but guess not. -->
 
 
 <dt><code title=""><dfn id=command-fontname title=command-fontname>fontName</dfn></code>
 
-<dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>, then
+<dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>, then
 <a href=#style>style</a> each returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> equal to
 "font-family" and <var title="">new value</var> equal to <var title="">value</var>.
 <!-- UAs differ a bit in the details here:
@@ -1133,9 +1200,9 @@
 understand CSS font-family syntax?), so I don't think such usability concerns
 apply. -->
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: The computed value of the CSS property
+<dd><strong>Value</strong>: The computed value of the CSS property
 "font-family" for . . .
 <!-- Complicated.
 
@@ -1157,7 +1224,7 @@
 
 <dt><code title=""><dfn id=command-forecolor title=command-forecolor>foreColor</dfn></code>
 
-<dd><p><strong>Action</strong>: If <var title="">value</var> is not a valid CSS color,
+<dd><strong>Action</strong>: If <var title="">value</var> is not a valid CSS color,
 the user agent must do nothing and abort these steps.
 <!-- Browsers are all over the place here.  IE 9 RC seems to treat unrecognized
 colors as black, but everyone else ignores them.  There are also special rules
@@ -1177,36 +1244,66 @@
 <a href=#style>style</a> each returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> equal to
 "color" and <var title="">new value</var> equal to <var title="">value</var>.
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 <!-- This matches IE 9 RC and Chrome 10.  Opera 11 seems to return true if
 there's some color style applied, false otherwise, which seems fairly useless;
 authors want to use value here, not state.  Firefox 4b11 throws an exception,
 which is an interesting approach, but I'll go with IE/WebKit, which makes at
 least as much sense. -->
 
-<dd><p><strong>Value</strong>: The computed value of the CSS property "color"
+<dd><strong>Value</strong>: The computed value of the CSS property "color"
 for . . .
 <!-- IE 9 RC returns the number 0 always, which makes no sense at all.  This
 matches the other browsers. -->
 
 
 <dt><code title=""><dfn id=command-hilitecolor title=command-hiliteColor>hiliteColor</dfn></code>
+<!-- IE 9 RC doesn't support this.  It uses backColor instead, but Gecko and
+Opera treat that differently, while all non-IE browsers treat hiliteColor the
+same, so I'm standardizing hiliteColor as the way to highlight text. -->
 
-<dd><p><strong>Action</strong>: If <var title="">value</var> is not a valid CSS color,
+<dd><strong>Action</strong>: If <var title="">value</var> is not a valid CSS color,
 do nothing and abort these steps.  Otherwise, <a href=#decompose>decompose</a> the
 <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>, then <a href=#style>style</a> each returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with
 <var title="">property</var> equal to "background-color" and <var title="">new value</var> equal
 to <var title="">value</var>.
 
-<dd><p><strong>State</strong>: Always false.
+<div class=XXX>
+<p>This is tricky, because background-color does different things on block and
+inline elements.  Given the name ("hiliteColor"), we really only want to apply
+it to inline elements.  This is how everyone but Gecko behaves, but Gecko
+sometimes applies it to blocks too.  We don't do this in the spec.
 
-<dd><p><strong>Value</strong>: The <a href=#effective-style>effective style</a> for
+<p>Clearing is also an issue.  If the user has a whole block selected which
+already has an existing background-color, do we want to clear that, or just
+wrap its children?  Obviously Gecko clears it (sets it, in fact).  WebKit also
+clears it, as does the current spec, but IE and Opera don't.  The reason we
+shouldn't clear it is because the user is only asking for a highlight, and
+highlights should be on top of the block's background, not instead of it.
+
+<p>Finally, what about pushing down?  Pushing down styles is not supposed to
+change the visible result, that's the whole point, but pushing down from a
+block to inlines will remove the coloring from the parts of the block not
+covered by inlines.  WebKit does it anyway, and so does the current spec, but
+non-WebKit browsers seem not to do it (although this is probably because none
+of them ever push down inline styles, they only break up formatting elements
+like <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>).
+
+<p>My current thought is to change things so that hiliteColor never touches
+background-color on blocks.  If users want to remove it, they'll have to use
+removeFormat.  I'll return to this after I figure out what to do about
+backColor.
+</div>
+
+<dd><strong>State</strong>: Always false.
+
+<dd><strong>Value</strong>: The <a href=#effective-style>effective style</a> for
 "background-color" on . . .
 
 
 <dt><code title=""><dfn id=command-insertimage title=command-insertimage>insertImage</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must run the following steps:
+<dd><strong>Action</strong>: The user agent must run the following steps:
 
 <ol>
   <li>If <var title="">value</var> is the empty string, abort these steps and do
@@ -1241,44 +1338,44 @@
   <var title="">child</var>)</code></a> on <var title="">node</var>.
 </ol>
 
-<dd><p><strong>State</strong>:
+<dd><strong>State</strong>:
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 
 
 <dt><code title=""><dfn id=command-italic title=command-italic>italic</dfn></code>
 
-<dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
+<dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
 state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
 returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "font-style" and <var title="">new
 value</var> "normal".  Otherwise, <a href=#style>style</a> them with <var title="">new
 value</var> "italic".
 
-<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
+<dd><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective
 style</a> either null, "italic", or "oblique" for font-style.  Otherwise
 false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title=""><dfn id=command-stylewithcss title=command-stylewithcss>styleWithCSS</dfn></code>
 
-<dd><p><strong>Action</strong>: Convert <var title="">value</var> to a boolean according
+<dd><strong>Action</strong>: Convert <var title="">value</var> to a boolean according
 to the algorithm in WebIDL, and set the <a href=#css-styling-flag>CSS styling flag</a> to the
 result.
 
 <p class=XXX>Properly cross-reference.
 
-<dd><p><strong>State</strong>: True if the <a href=#css-styling-flag>CSS styling flag</a> is
+<dd><strong>State</strong>: True if the <a href=#css-styling-flag>CSS styling flag</a> is
 true, otherwise false.
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 
 
 <dt><code title=""><dfn id=command-underline title=command-underline>underline</dfn></code>
 
-<dd><p><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
+<dd><strong>Action</strong>: <a href=#decompose>Decompose</a> the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a>.  If the
 state of the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> for this command is then true, <a href=#style>style</a> each
 returned <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> with <var title="">property</var> "text-decoration" and <var title="">new
 value</var> "none".  Otherwise, <a href=#style>style</a> them with <var title="">new
@@ -1320,16 +1417,16 @@
 future.
 </div>
 
-<dd><p><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
+<dd><strong>State</strong>: True if every <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text><code class=external data-anolis-spec=domcore>Text</code></a> node that is
 <a href=#effectively-contained>effectively contained</a> in the <a href=http://html5.org/specs/dom-range.html#range><code class=external data-anolis-spec=domrange>Range</code></a> has <a href=#effective-style>effective
 style</a> either null or "underline" for text-decoration.  Otherwise false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title=""><dfn id=command-unlink title=command-unlink>unlink</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must execute the following
+<dd><strong>Action</strong>: The user agent must execute the following
 steps:
 <!-- IE 9 RC unlinks the whole link you're pointing at.  Others just unlink
 your selection, which does nothing if you have nothing selected.
@@ -1369,14 +1466,14 @@
   </ol>
 </ol>
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title=""><dfn id=command-usecss title=command-usecss>useCSS</dfn></code>
 
-<dd><p><strong>Action</strong>: Convert <var title="">value</var> to a boolean according
+<dd><strong>Action</strong>: Convert <var title="">value</var> to a boolean according
 to the algorithm in WebIDL, and set the <a href=#css-styling-flag>CSS styling flag</a> to the
 negation of the result.  Since the effect of this command is the opposite of
 what one would expect, user agents are encouraged to point authors to <a href=#command-stylewithcss><code title=command-stylewithcss>styleWithCSS</code></a> when <a href=#command-usecss><code title=command-usecss>useCSS</code></a> is used, such as by logging a warning to an
@@ -1384,9 +1481,9 @@
 
 <p class=XXX>Properly cross-reference.
 
-<dd><p><strong>State</strong>:
+<dd><strong>State</strong>:
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 </dl>
 
 
--- a/source.html	Wed Mar 23 16:03:54 2011 -0600
+++ b/source.html	Thu Mar 24 15:43:26 2011 -0600
@@ -122,6 +122,9 @@
 
 <h2>Issues</h2>
 
+<p>This specification is very preliminary, and should not be used for anything
+other than review and comment.
+
 <ul>
   <li>Need to make CSS terminology more precise, about setting/unsetting CSS
   properties.  The intent is to modify the style attribute, CSSOM-style.
@@ -155,6 +158,9 @@
   <li>I don't pay attention to whether designMode/contenteditable is actually
   set.  I should be doing things like not doing anything if the selection isn't
   editable, making sure not to break out of contenteditable regions, etc.
+
+  <li>I haven't yet paid any attention to value parsing.  This is going to be
+  important to specify exactly in some cases, like with colors.
 </ul>
 
 <p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -528,32 +534,38 @@
 <var>node</var>, given a CSS property name <var>property</var> and a new value
 <var>new value</var>, it must run the following steps:
 
-<!-- This algorithm goes up to just below the nearest ancestor with the right
+<div class=XXX>
+<p>This algorithm goes up to just below the nearest ancestor with the right
 style, then re-applies the bad styles repeatedly going down, omitting the
 things we want to have the new style.  This is basically what WebKit does,
 although WebKit sometimes starts higher up and therefore makes more intrusive
-changes, often creating more markup.
+changes, often creating more markup.  IE follows the same general approach too.
 
-Gecko instead seems to start breaking up elements from the bottom, so that the
+<p>Gecko instead seems to start breaking up elements from the bottom, so that the
 range consists of a few consecutive siblings, and it can then break up the
 problematic element into a maximum of two pieces.  The spec's approach seems to
 create fewer elements and simpler markup (or at least markup that's no more
-complex) in every case I throw at it.
+complex) in most cases I throw at it.
 
-Gecko's approach does have the major advantage that it gets underlines right in
+<p>Gecko's approach does have the major advantage that it gets underlines right in
 many cases for free.  E.g.,
 
-  <u>foo<font color=red>[bar]baz</font></u>
+<xmp>  <u>foo<font color=red>[bar]baz</font></u>
   -> <u>foo</u><font color=red>bar<u>baz</u></font> (spec)
-  -> <u>foo</u><font color=red>bar</font><u><font color=red>baz</font></u> (Gecko)
+  -> <u>foo</u><font color=red>bar</font><u><font color=red>baz</font></u> (Gecko)</xmp>
 
-The spec's markup here is much shorter and contains fewer elements, but is
+<p>The spec's markup here is much shorter and contains fewer elements, but is
 wrong: the underline under "baz" has changed color from black to red.  It might
 be worth trying to copy Gecko's results in such cases, but that won't solve all
 underline problems, so perhaps it's not worth it.
 
-Opera also seems to break up the markup surrounding the range, but even more
-aggressively: even if it doesn't need to pull down styles. -->
+<p>Opera also seems to break up the markup surrounding the range, but even more
+aggressively: even if it doesn't need to pull down styles.  In some cases this
+does actually result in shorter markup, specifically if the existing tags are
+short (like [[i]] or [[b]]) and we're adding tags that are long (like [[span]]
+with a [[style]] attribute).
+</div>
+
 <ol>
   <li>If <var>node</var>'s [[parent]] is not an [[element]], abort this
   algorithm. <!-- E.g., a text node child of a document fragment. -->
@@ -745,6 +757,11 @@
     <li><span>Force the style</span> of each [[node]] in <var>children</var>,
     with <var>property</var> and <var>new value</var> as in this invocation of
     the algorithm.
+    <!-- This means that if it has no children, we do nothing.  IE9 inserts an
+    empty wrapper element in that case, but I'm not sure what the point is, and
+    no one else does, so I don't.  WebKit seems to ignore the node if its only
+    child consists solely of whitespace, but I don't see any grounds for that
+    and no one else does, so I don't. -->
 
     <li>Abort this algorithm.
   </ol>
@@ -1008,19 +1025,69 @@
 <span data-anolis-spec=domcore>ASCII case-insensitive</span> manner.
 
 <dl>
+<dt><code title><dfn title=command-backcolor>backColor</dfn></code>
+
+<dd><strong>Action</strong>:
+
+<div class=XXX>
+<p>We have three behaviors to choose from for this one:
+
+<ol>
+  <li>Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9
+  RC doesn't support hiliteColor itself).
+
+  <li>Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
+  something like that.  In testing, it seems to jump out of contenteditable
+  elements to style non-editable ancestors, which is alarming.
+
+  <li>Firefox 4 in CSS mode and Opera 11 set the background of the nearest
+  block container, although it doesn't seem to be very dependable (probably I
+  just don't get what exactlyit's doing).
+</ol>
+
+<p>(1) is obviously redundant, but has plurality support, so we could spec it
+that way if the other ways were useless.
+
+<p>(3) is incoherent from a user perspective.  For instance, if you try it on
+paragraphs the background will have big gaps where the margins are.  If you try
+it on an inline element that's a child of the editing host, it will do nothing
+or apply the background to everything or such, even though such an inline
+element is visually indistinguishable from one sitting inside a div.  This
+would only make sense if we take considerable effort to ensure that block
+elements all have no margins, or if we wrap things in a div if they have
+margins, or something like that.
+
+<p>That leaves (2).  That might be useful if it actually set the document's
+background color, but it seems like it sets table cell backgrounds sometimes
+instead, which is really confusing.
+
+<p>The path of least resistance seems to be to standardize this as meaning the
+same thing as hiliteColor, and make up new commands if we want to do things
+like set the document background color.  Feedback appreciated on this point.
+</div>
+
+<dd><strong>State</strong>:
+
+<dd><strong>Value</strong>:
+
+
 <dt><code title><dfn title=command-bold>bold</dfn></code>
 
-<dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
+<dd><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>style</span> each
 returned [[node]] with <var>property</var> "font-weight" and <var>new
 value</var> "normal".  Otherwise, <span>style</span> them with <var>new
 value</var> "bold".
 
-<dd><p><strong>State</strong>: True if every [[text]] node that is
+<dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
 style</span> either null or at least 700 for font-weight.  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
+bold, and this seems to match at least OpenOffice.org's bold feature. -->
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 <!-- We have lots of options here (and presumably for all the others where
 value is meaningless).  IE 9 RC returns the boolean false, Firefox 4b11 and
 Opera 11 both return the empty string, Chrome 10 returns the string "false".
@@ -1032,7 +1099,7 @@
 
 <dt><code title><dfn title=command-createlink>createLink</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must run the following steps:
+<dd><strong>Action</strong>: The user agent must run the following steps:
 
 <ol>
   <li>If <var>value</var> is the empty string, abort these steps and do
@@ -1115,15 +1182,15 @@
   </ol>
 </ol>
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 <!-- I'd have expected the value to be the URL, but guess not. -->
 
 
 <dt><code title><dfn title=command-fontname>fontName</dfn></code>
 
-<dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]], then
+<dd><strong>Action</strong>: <span>Decompose</span> the [[range]], then
 <span>style</span> each returned [[node]] with <var>property</var> equal to
 "font-family" and <var>new value</var> equal to <var>value</var>.
 <!-- UAs differ a bit in the details here:
@@ -1147,9 +1214,9 @@
 understand CSS font-family syntax?), so I don't think such usability concerns
 apply. -->
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: The computed value of the CSS property
+<dd><strong>Value</strong>: The computed value of the CSS property
 "font-family" for . . .
 <!-- Complicated.
 
@@ -1171,7 +1238,7 @@
 
 <dt><code title><dfn title=command-forecolor>foreColor</dfn></code>
 
-<dd><p><strong>Action</strong>: If <var>value</var> is not a valid CSS color,
+<dd><strong>Action</strong>: If <var>value</var> is not a valid CSS color,
 the user agent must do nothing and abort these steps.
 <!-- Browsers are all over the place here.  IE 9 RC seems to treat unrecognized
 colors as black, but everyone else ignores them.  There are also special rules
@@ -1191,36 +1258,66 @@
 <span>style</span> each returned [[node]] with <var>property</var> equal to
 "color" and <var>new value</var> equal to <var>value</var>.
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 <!-- This matches IE 9 RC and Chrome 10.  Opera 11 seems to return true if
 there's some color style applied, false otherwise, which seems fairly useless;
 authors want to use value here, not state.  Firefox 4b11 throws an exception,
 which is an interesting approach, but I'll go with IE/WebKit, which makes at
 least as much sense. -->
 
-<dd><p><strong>Value</strong>: The computed value of the CSS property "color"
+<dd><strong>Value</strong>: The computed value of the CSS property "color"
 for . . .
 <!-- IE 9 RC returns the number 0 always, which makes no sense at all.  This
 matches the other browsers. -->
 
 
 <dt><code title><dfn title=command-hiliteColor>hiliteColor</dfn></code>
+<!-- IE 9 RC doesn't support this.  It uses backColor instead, but Gecko and
+Opera treat that differently, while all non-IE browsers treat hiliteColor the
+same, so I'm standardizing hiliteColor as the way to highlight text. -->
 
-<dd><p><strong>Action</strong>: If <var>value</var> is not a valid CSS color,
+<dd><strong>Action</strong>: If <var>value</var> is not a valid CSS color,
 do nothing and abort these steps.  Otherwise, <span>decompose</span> the
 [[range]], then <span>style</span> each returned [[node]] with
 <var>property</var> equal to "background-color" and <var>new value</var> equal
 to <var>value</var>.
 
-<dd><p><strong>State</strong>: Always false.
+<div class=XXX>
+<p>This is tricky, because background-color does different things on block and
+inline elements.  Given the name ("hiliteColor"), we really only want to apply
+it to inline elements.  This is how everyone but Gecko behaves, but Gecko
+sometimes applies it to blocks too.  We don't do this in the spec.
 
-<dd><p><strong>Value</strong>: The <span>effective style</span> for
+<p>Clearing is also an issue.  If the user has a whole block selected which
+already has an existing background-color, do we want to clear that, or just
+wrap its children?  Obviously Gecko clears it (sets it, in fact).  WebKit also
+clears it, as does the current spec, but IE and Opera don't.  The reason we
+shouldn't clear it is because the user is only asking for a highlight, and
+highlights should be on top of the block's background, not instead of it.
+
+<p>Finally, what about pushing down?  Pushing down styles is not supposed to
+change the visible result, that's the whole point, but pushing down from a
+block to inlines will remove the coloring from the parts of the block not
+covered by inlines.  WebKit does it anyway, and so does the current spec, but
+non-WebKit browsers seem not to do it (although this is probably because none
+of them ever push down inline styles, they only break up formatting elements
+like [[b]]).
+
+<p>My current thought is to change things so that hiliteColor never touches
+background-color on blocks.  If users want to remove it, they'll have to use
+removeFormat.  I'll return to this after I figure out what to do about
+backColor.
+</div>
+
+<dd><strong>State</strong>: Always false.
+
+<dd><strong>Value</strong>: The <span>effective style</span> for
 "background-color" on . . .
 
 
 <dt><code title><dfn title=command-insertimage>insertImage</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must run the following steps:
+<dd><strong>Action</strong>: The user agent must run the following steps:
 
 <ol>
   <li>If <var>value</var> is the empty string, abort these steps and do
@@ -1261,44 +1358,44 @@
   <var>child</var>)</code> on <var>node</var>.
 </ol>
 
-<dd><p><strong>State</strong>:
+<dd><strong>State</strong>:
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 
 
 <dt><code title><dfn title=command-italic>italic</dfn></code>
 
-<dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
+<dd><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>style</span> each
 returned [[node]] with <var>property</var> "font-style" and <var>new
 value</var> "normal".  Otherwise, <span>style</span> them with <var>new
 value</var> "italic".
 
-<dd><p><strong>State</strong>: True if every [[text]] node that is
+<dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
 style</span> either null, "italic", or "oblique" for font-style.  Otherwise
 false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title><dfn title=command-stylewithcss>styleWithCSS</dfn></code>
 
-<dd><p><strong>Action</strong>: Convert <var>value</var> to a boolean according
+<dd><strong>Action</strong>: Convert <var>value</var> to a boolean according
 to the algorithm in WebIDL, and set the <span>CSS styling flag</span> to the
 result.
 
 <p class=XXX>Properly cross-reference.
 
-<dd><p><strong>State</strong>: True if the <span>CSS styling flag</span> is
+<dd><strong>State</strong>: True if the <span>CSS styling flag</span> is
 true, otherwise false.
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 
 
 <dt><code title><dfn title=command-underline>underline</dfn></code>
 
-<dd><p><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
+<dd><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the
 state of the [[range]] for this command is then true, <span>style</span> each
 returned [[node]] with <var>property</var> "text-decoration" and <var>new
 value</var> "none".  Otherwise, <span>style</span> them with <var>new
@@ -1340,16 +1437,16 @@
 future.
 </div>
 
-<dd><p><strong>State</strong>: True if every [[text]] node that is
+<dd><strong>State</strong>: True if every [[text]] node that is
 <span>effectively contained</span> in the [[range]] has <span>effective
 style</span> either null or "underline" for text-decoration.  Otherwise false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title><dfn title=command-unlink>unlink</dfn></code>
 
-<dd><p><strong>Action</strong>: The user agent must execute the following
+<dd><strong>Action</strong>: The user agent must execute the following
 steps:
 <!-- IE 9 RC unlinks the whole link you're pointing at.  Others just unlink
 your selection, which does nothing if you have nothing selected.
@@ -1389,14 +1486,14 @@
   </ol>
 </ol>
 
-<dd><p><strong>State</strong>: Always false.
+<dd><strong>State</strong>: Always false.
 
-<dd><p><strong>Value</strong>: Always the empty string.
+<dd><strong>Value</strong>: Always the empty string.
 
 
 <dt><code title><dfn title=command-usecss>useCSS</dfn></code>
 
-<dd><p><strong>Action</strong>: Convert <var>value</var> to a boolean according
+<dd><strong>Action</strong>: Convert <var>value</var> to a boolean according
 to the algorithm in WebIDL, and set the <span>CSS styling flag</span> to the
 negation of the result.  Since the effect of this command is the opposite of
 what one would expect, user agents are encouraged to point authors to <code
@@ -1406,9 +1503,9 @@
 
 <p class=XXX>Properly cross-reference.
 
-<dd><p><strong>State</strong>:
+<dd><strong>State</strong>:
 
-<dd><p><strong>Value</strong>:
+<dd><strong>Value</strong>:
 </dl>