--- a/autoimplementation.html Wed Apr 13 14:01:04 2011 -0600
+++ b/autoimplementation.html Thu Apr 14 10:11:40 2011 -0600
@@ -1,4 +1,5 @@
<!doctype html>
+<meta charset=utf-8>
<title>Auto-running execCommand() tests</title>
<style>
body { font-family: serif }
@@ -431,6 +432,57 @@
'<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>',
],
+ indent: [
+ // All these have a trailing unselected paragraph, because otherwise
+ // Gecko is unhappy: it throws exceptions in non-CSS mode, and in CSS
+ // mode it adds the indentation invisibly to the wrapper div in many
+ // cases.
+ 'foo[]bar<p>extra',
+ '<span>foo</span>{}<span>bar</span><p>extra',
+ '<span>foo[</span><span>]bar</span><p>extra',
+ 'foo[bar]baz<p>extra',
+ '<p dir=rtl>פו[בר]בז<p dir=rtl>נוםף',
+ 'foo]bar[baz<p>extra',
+ '{<p><p> <p>foo</p>}<p>extra',
+ 'foo[bar<i>baz]qoz</i>quz<p>extra',
+
+ '<table><tbody><tr><td>foo<td>b[a]r<td>baz</table><p>extra',
+ '<table><tbody><tr data-start=1 data-end=2><td>foo<td>bar<td>baz</table><p>extra',
+ '<table><tbody><tr data-start=0 data-end=2><td>foo<td>bar<td>baz</table><p>extra',
+ '<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table><p>extra',
+ '<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table><p>extra',
+ '{<table><tr><td>foo<td>bar<td>baz</table>}<p>extra',
+
+ '<p>foo[bar]</p><p>baz</p><p>extra',
+ '<p>[foobar</p><p>ba]z</p><p>extra',
+ 'foo[bar]<br>baz<p>extra',
+ 'foo[bar<br>ba]z<p>extra',
+
+ // These mimic existing indentation in various browsers, to see how
+ // they cope with indenting twice. This is Gecko non-CSS and Opera:
+ '<blockquote><p>foo[bar]</p><p>baz</p></blockquote><p>extra',
+ '<blockquote><p>foo[bar</p><p>b]az</p></blockquote><p>extra',
+ '<blockquote><p>foo[bar]</p></blockquote><p>baz</p><p>extra',
+ '<blockquote><p>foo[bar</p></blockquote><p>b]az</p><p>extra',
+
+ // IE:
+ '<blockquote style="margin-right: 0" dir="ltr"><p>foo[bar]</p><p>baz</p></blockquote><p>extra',
+ '<blockquote style="margin-right: 0" dir="ltr"><p>foo[bar</p><p>b]az</p></blockquote><p>extra',
+ '<blockquote style="margin-right: 0" dir="ltr"><p>foo[bar]</p></blockquote><p>baz</p><p>extra',
+ '<blockquote style="margin-right: 0" dir="ltr"><p>foo[bar</p></blockquote><p>b]az</p><p>extra',
+
+ // Firefox CSS mode:
+ '<p style="margin-left: 40px">foo[bar]</p><p style="margin-left: 40px">baz</p><p>extra',
+ '<p style="margin-left: 40px">foo[bar</p><p style="margin-left: 40px">b]az</p><p>extra',
+ '<p style="margin-left: 40px">foo[bar]</p><p>baz</p><p>extra',
+ '<p style="margin-left: 40px">foo[bar</p><p>b]az</p><p>extra',
+
+ // WebKit:
+ '<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px"><p>foo[bar]</p><p>baz</p></blockquote><p>extra',
+ '<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px"><p>foo[bar</p><p>b]az</p></blockquote><p>extra',
+ '<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px"><p>foo[bar]</p></blockquote><p>baz</p><p>extra',
+ '<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px"><p>foo[bar</p></blockquote><p>b]az</p><p>extra',
+ ],
inserthorizontalrule: [
'foo[]bar',
'<span>foo</span>{}<span>bar</span>',
@@ -904,9 +956,19 @@
hilitecolor: 'In IE we run backColor instead of hiliteColor.',
};
-var doubleTestingCommands = ["backcolor", "bold", "italic", "strikethrough",
- "underline", "forecolor", "fontname", "fontsize", "subscript",
- "superscript"];
+var doubleTestingCommands = [
+ "backcolor",
+ "bold",
+ "fontname",
+ "fontsize",
+ "forecolor",
+ "indent",
+ "italic",
+ "strikethrough",
+ "subscript",
+ "superscript",
+ "underline",
+];
// Set up all the HTML automatically so I can add new commands to test without
// copy-pasting in five places
@@ -994,18 +1056,10 @@
}
function doSetup(command, idx) {
- document.getElementById(command).contentEditable = "true";
- document.getElementById(command).spellcheck = false;
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
- // while you're stopped at a breakpoint . . .
- //if (table.childNodes.length == 1) {
- table.appendChild(tr);
- //} else {
- // table.insertBefore(tr, table.childNodes[1]);
- //}
+ table.appendChild(tr);
return tr;
}
@@ -1045,8 +1099,12 @@
if (range.collapsed) {
range.setEnd(points[0], points[1]);
}
+ specCell.firstChild.contentEditable = "true";
+ specCell.firstChild.spellcheck = false;
myExecCommand("styleWithCSS", false, styleWithCss);
myExecCommand(command, false, value, range);
+ specCell.firstChild.contentEditable = "inherit";
+ specCell.firstChild.removeAttribute("spellcheck");
addBrackets(range);
if (specCell.childNodes.length == 2) {
specCell.lastChild.textContent = specCell.firstChild.innerHTML;
@@ -1054,6 +1112,8 @@
throw "The cell didn't have two children. Did something spill outside the test div?";
}
} catch (e) {
+ specCell.firstChild.contentEditable = "inherit";
+ specCell.firstChild.removeAttribute("spellcheck");
specCell.lastChild.style.color = "red";
specCell.lastChild.style.fontWeight = "bold";
specCell.lastChild.textContent = "Note, exception: " + e;
@@ -1096,32 +1156,36 @@
tr.appendChild(browserCell);
try {
var points = setupCell(browserCell, test);
+
var testDiv = browserCell.firstChild;
// Work around weird Firefox bug:
// https://bugzilla.mozilla.org/show_bug.cgi?id=649138
- // But only with removeFormat, because it tends to cause weird behavior
- // sometimes if content winds up being put outside the div for some
- // reason: then it's mysteriously below the table.
- if (command == "removeformat") {
- document.getElementById(command).appendChild(testDiv);
- }
+ document.body.appendChild(testDiv);
setSelection(points[0], points[1], points[2], points[3]);
+ testDiv.contentEditable = "true";
+ testDiv.spellcheck = false;
+
try {
document.execCommand("styleWithCSS", false, styleWithCss);
} catch (e) {}
document.execCommand(command, false, value);
+
+ testDiv.contentEditable = "inherit";
+ testDiv.removeAttribute("spellcheck");
if (getSelection().rangeCount) {
addBrackets(getSelection().getRangeAt(0));
}
- if (testDiv.parentNode != browserCell) {
- browserCell.insertBefore(testDiv, browserCell.firstChild);
- }
+ browserCell.insertBefore(testDiv, browserCell.firstChild);
if (browserCell.childNodes.length == 2) {
browserCell.lastChild.textContent = browserCell.firstChild.innerHTML;
} else {
throw "The cell didn't have two children. Did something spill outside the test div?";
}
} catch (e) {
+ if (testDiv) {
+ testDiv.contenteditable = "inherit";
+ testDiv.removeAttribute("spellcheck");
+ }
browserCell.lastChild.style.color = "red";
browserCell.lastChild.style.fontWeight = "bold";
browserCell.lastChild.textContent = "Exception: " + e;
@@ -1190,8 +1254,6 @@
function doTearDown(command) {
getSelection().removeAllRanges();
- document.getElementById(command).contentEditable = "inherit";
- document.getElementById(command).removeAttribute("spellcheck");
}
function setupCell(cell, test) {
--- a/editcommands.html Wed Apr 13 14:01:04 2011 -0600
+++ b/editcommands.html Thu Apr 14 10:11:40 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-—-last-update-13-april-2011>Work in Progress — Last Update 13 April 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-14-april-2011>Work in Progress — Last Update 14 April 2011</h2>
<dl>
<dt>Editor
<dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -1681,6 +1681,97 @@
<dd><strong>Relevant CSS Property</strong>: "background-color"
+<!--
+<dt><code title><dfn title=command-indent>indent</dfn></code>
+-->
+<!--
+IE9: Outputs <blockquote style="margin-right: 0px" dir="ltr">, or when
+ surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">.
+Firefox 4.0: In styleWithCSS mode, adds style="margin-left: 40px" to the
+ appropriate block container (or margin-right if it's RTL). If there's no
+ appropriate block container, adds a div. In non-styleWithCSS mode, uses
+ <blockquote>, so it indents on both sides.
+Chrome 12 dev: Outputs <blockquote class="webkit-indent-blockquote"
+ style="margin: 0 0 0 40px; border: none; padding: 0px"> in both modes for
+ both LTR and RTL (which is broken for RTL, since it indents only on the
+ right).
+Opera 11.00: Outputs <blockquote>, so it indents on both sides.
+
+For repeated indentation, everyone except Opera that outputs <blockquote>s just
+puts them at the outermost possible location, which works well. Opera puts
+them in the innermost position, which is broken, because it will even put them
+inside <p> (which will not round-trip through text/html serialization).
+
+Gecko in CSS mode messes up by adding margins even to things like <blockquote>
+that already have margins from CSS rules, instead of nesting a div, so it
+doesn't actually increase the indentation. However, if an element has an
+explicit left margin (assuming LTR), it will increase the margin to 80px, so it
+works with WebKit's blockquotes.
+-->
+
+<!--
+<dd><strong>Action</strong>:
+
+<ol>
+ <li>Let <var title>start node</var>, <var title>start offset</var>, <var title>end node</var>,
+ and <var title>end offset</var> be the <span data-anolis-spec=domrange title=concept-range-start>start</span> and <span data-anolis-spec=domrange title=concept-range-end>end</span> <span data-anolis-spec=domrange title=concept-boundary-point-node>nodes</span>
+ and <span data-anolis-spec=domrange title=concept-boundary-point-offset>offsets</span> of the <span data-anolis-spec=domrange title=concept-range>range</span>.
+
+ <p class=XXX>Handle corner cases: endpoints are detached, documents, document
+ fragments, html/body, head or things in head . . .
+
+ <li>Repeat the following steps:
+
+ <ol>
+ <li>If <var title>start node</var> is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node or
+ <var title>start offset</var> is 0, set <var title>start offset</var> to the <span data-anolis-spec=domrange title=concept-indexof>index</span>
+ of <var title>start node</var> and then set <var title>start node</var> to its
+ <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
+
+ <li>Otherwise, if the <var title>start offset</var> is equal to the
+ <span data-anolis-spec=domrange title=concept-node-length>length</span> of <var title>start node</var>, set <var title>start offset</var> to one
+ plus the <span data-anolis-spec=domrange title=concept-indexof>index</span> of <var title>start node</var> and then set <var title>start
+ node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
+
+ <li>Otherwise, if the <span data-anolis-spec=domcore title=concept-tree-child>child</span> of <var title>start node</var> with <span data-anolis-spec=domrange title=concept-indexof>index</span>
+ <var title>start offset</var> minus one is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node, or an
+ (insert definition here), subtract one from <var title>start offset</var>.
+
+ <p class=XXX>The definition should include all inline elements except
+ <br>. As elsewhere, we have trouble with the exact definition because
+ HTML doesn't classify non-conforming elements, but those are common in
+ editing and need to be handled correctly.
+
+ <li>Otherwise, break from this loop.
+ </ol>
+
+ <li>Repeat the following steps:
+
+ <ol>
+ <li>If <var title>end node</var> is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node or <var title>end
+ offset</var> is 0, set <var title>end offset</var> to the <span data-anolis-spec=domrange title=concept-indexof>index</span> of <var title>end
+ node</var> and then set <var title>end node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
+
+ <li>Otherwise, if the <var title>end offset</var> is equal to the <span data-anolis-spec=domrange title=concept-node-length>length</span>
+ of <var title>end node</var>, set <var title>end offset</var> to one plus the <span data-anolis-spec=domrange title=concept-indexof>index</span>
+ of <var title>end node</var> and then set <var title>end node</var> to its <span data-anolis-spec=domcore title=concept-tree-parent>parent</span>.
+
+ <li>Otherwise, if the <span data-anolis-spec=domcore title=concept-tree-child>child</span> of <var title>end node</var> with <span data-anolis-spec=domrange title=concept-indexof>index</span>
+ <var title>end offset</var> plus one is a <code data-anolis-spec=domcore>Text</code> or <code data-anolis-spec=domcore>Comment</code> node, or an
+ (insert definition here), add one to <var title>end offset</var>.
+
+ <p class=XXX>Same definition as before.
+
+ <li>Otherwise, break from this loop.
+ </ol>
+</ol>
+
+<dd><strong>State</strong>:
+
+<dd><strong>Value</strong>:
+-->
+
+
<dt><code title=""><dfn id=command-inserthorizontalrule title=command-inserthorizontalrule>insertHorizontalRule</dfn></code>
<dd><strong>Action</strong>:
@@ -1953,6 +2044,15 @@
<dt><code title=""><dfn id=command-stylewithcss title=command-stylewithcss>styleWithCSS</dfn></code>
+<!-- IE9 and Opera 11.00 don't support this command. By and large, they act
+the way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
+WebKit also supports it:
+
+https://bugs.webkit.org/show_bug.cgi?id=13490
+
+The default in Firefox 4.0 is off, while all other browsers behave like the
+default is on (and IE/Opera give no way to turn it off), so I default it to on.
+-->
<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
@@ -2080,6 +2180,10 @@
<dt><code title=""><dfn id=command-usecss title=command-usecss>useCSS</dfn></code>
+<!-- Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which don't support
+styleWithCSS either), nor by Chrome 12 dev (which does support styleWithCSS.
+useCSS was the original feature in Mozilla 1.3, but the meaning is backward, so
+Gecko added styleWithCSS as a replacement. -->
<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
@@ -2089,6 +2193,10 @@
<p class=XXX>Properly cross-reference.
+<p class=XXX>The meaning of this command is backwards, and only Gecko supports
+it. It would be great if Gecko would agree to drop support, so that we could
+get rid of it.
+
<dd><strong>State</strong>:
<dd><strong>Value</strong>:
--- a/source.html Wed Apr 13 14:01:04 2011 -0600
+++ b/source.html Thu Apr 14 10:11:40 2011 -0600
@@ -1697,6 +1697,97 @@
<dd><strong>Relevant CSS Property</strong>: "background-color"
+<!--
+<dt><code title><dfn title=command-indent>indent</dfn></code>
+-->
+<!--
+IE9: Outputs <blockquote style="margin-right: 0px" dir="ltr">, or when
+ surrounding RTL blocks, <blockquote style="margin-left: 0px" dir="rtl">.
+Firefox 4.0: In styleWithCSS mode, adds style="margin-left: 40px" to the
+ appropriate block container (or margin-right if it's RTL). If there's no
+ appropriate block container, adds a div. In non-styleWithCSS mode, uses
+ <blockquote>, so it indents on both sides.
+Chrome 12 dev: Outputs <blockquote class="webkit-indent-blockquote"
+ style="margin: 0 0 0 40px; border: none; padding: 0px"> in both modes for
+ both LTR and RTL (which is broken for RTL, since it indents only on the
+ right).
+Opera 11.00: Outputs <blockquote>, so it indents on both sides.
+
+For repeated indentation, everyone except Opera that outputs <blockquote>s just
+puts them at the outermost possible location, which works well. Opera puts
+them in the innermost position, which is broken, because it will even put them
+inside <p> (which will not round-trip through text/html serialization).
+
+Gecko in CSS mode messes up by adding margins even to things like <blockquote>
+that already have margins from CSS rules, instead of nesting a div, so it
+doesn't actually increase the indentation. However, if an element has an
+explicit left margin (assuming LTR), it will increase the margin to 80px, so it
+works with WebKit's blockquotes.
+-->
+
+<!--
+<dd><strong>Action</strong>:
+
+<ol>
+ <li>Let <var>start node</var>, <var>start offset</var>, <var>end node</var>,
+ and <var>end offset</var> be the [[rangestart]] and [[rangeend]] [[bpnodes]]
+ and [[bpoffsets]] of the [[range]].
+
+ <p class=XXX>Handle corner cases: endpoints are detached, documents, document
+ fragments, html/body, head or things in head . . .
+
+ <li>Repeat the following steps:
+
+ <ol>
+ <li>If <var>start node</var> is a [[text]] or [[comment]] node or
+ <var>start offset</var> is 0, set <var>start offset</var> to the [[index]]
+ of <var>start node</var> and then set <var>start node</var> to its
+ [[parent]].
+
+ <li>Otherwise, if the <var>start offset</var> is equal to the
+ [[nodelength]] of <var>start node</var>, set <var>start offset</var> to one
+ plus the [[index]] of <var>start node</var> and then set <var>start
+ node</var> to its [[parent]].
+
+ <li>Otherwise, if the [[child]] of <var>start node</var> with [[index]]
+ <var>start offset</var> minus one is a [[text]] or [[comment]] node, or an
+ (insert definition here), subtract one from <var>start offset</var>.
+
+ <p class=XXX>The definition should include all inline elements except
+ <br>. As elsewhere, we have trouble with the exact definition because
+ HTML doesn't classify non-conforming elements, but those are common in
+ editing and need to be handled correctly.
+
+ <li>Otherwise, break from this loop.
+ </ol>
+
+ <li>Repeat the following steps:
+
+ <ol>
+ <li>If <var>end node</var> is a [[text]] or [[comment]] node or <var>end
+ offset</var> is 0, set <var>end offset</var> to the [[index]] of <var>end
+ node</var> and then set <var>end node</var> to its [[parent]].
+
+ <li>Otherwise, if the <var>end offset</var> is equal to the [[nodelength]]
+ of <var>end node</var>, set <var>end offset</var> to one plus the [[index]]
+ of <var>end node</var> and then set <var>end node</var> to its [[parent]].
+
+ <li>Otherwise, if the [[child]] of <var>end node</var> with [[index]]
+ <var>end offset</var> plus one is a [[text]] or [[comment]] node, or an
+ (insert definition here), add one to <var>end offset</var>.
+
+ <p class=XXX>Same definition as before.
+
+ <li>Otherwise, break from this loop.
+ </ol>
+</ol>
+
+<dd><strong>State</strong>:
+
+<dd><strong>Value</strong>:
+-->
+
+
<dt><code title><dfn title=command-inserthorizontalrule>insertHorizontalRule</dfn></code>
<dd><strong>Action</strong>:
@@ -1988,6 +2079,15 @@
<dt><code title><dfn title=command-stylewithcss>styleWithCSS</dfn></code>
+<!-- IE9 and Opera 11.00 don't support this command. By and large, they act
+the way Gecko and WebKit do when styleWithCSS is off. Gecko invented it, and
+WebKit also supports it:
+
+https://bugs.webkit.org/show_bug.cgi?id=13490
+
+The default in Firefox 4.0 is off, while all other browsers behave like the
+default is on (and IE/Opera give no way to turn it off), so I default it to on.
+-->
<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
@@ -2117,6 +2217,10 @@
<dt><code title><dfn title=command-usecss>useCSS</dfn></code>
+<!-- Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which don't support
+styleWithCSS either), nor by Chrome 12 dev (which does support styleWithCSS.
+useCSS was the original feature in Mozilla 1.3, but the meaning is backward, so
+Gecko added styleWithCSS as a replacement. -->
<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
@@ -2128,6 +2232,10 @@
<p class=XXX>Properly cross-reference.
+<p class=XXX>The meaning of this command is backwards, and only Gecko supports
+it. It would be great if Gecko would agree to drop support, so that we could
+get rid of it.
+
<dd><strong>State</strong>:
<dd><strong>Value</strong>: