Define indeterm for several more commands
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Tue, 28 Jun 2011 14:06:43 -0600
changeset 337 82989e38ad2e
parent 336 4be87fc75653
child 338 8963fd7c4a1f
Define indeterm for several more commands

italic, strikethrough, subscript, superscript, underline.
editcommands.html
implementation.js
source.html
tests.js
--- a/editcommands.html	Tue Jun 28 13:32:08 2011 -0600
+++ b/editcommands.html	Tue Jun 28 14:06:43 2011 -0600
@@ -1160,6 +1160,11 @@
     computes to "inline":
 
     <ol>
+      <!-- Firefox 6.0a2 ignores vertical-align for this purpose, and only
+      cares about <sub> and <sup> tags themselves.  Opera 11.11 is similar, and
+      in fact behaves like that even for commands like bold.  The spec follows
+      Chrome 14 dev, mainly because WebKit itself will produce spans with
+      vertical-align sub or super, and we want to handle them correctly. -->
       <li>If <var title="">node</var>'s "vertical-align" property computes to "sub", set
       <var title="">affected by subscript</var> to true.
 
@@ -1167,7 +1172,7 @@
       "super", set <var title="">affected by superscript</var> to true.
 
       <li>Otherwise, if <var title="">node</var>'s "vertical-align" property computes to
-      some value other than "baseline", return the string "mixed".
+      some value other than "baseline", return the string "other".
 
       <li>Set <var title="">node</var> to 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>.
     </ol>
@@ -2523,6 +2528,12 @@
 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 "italic", otherwise <a href=#set-the-value>set the value</a> to
 "normal".
 
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if among <a href=#editable>editable</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> nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, there is at least one with <a href=#effective-value>effective value</a> either
+"italic" or "oblique" and at least one with <a href=#effective-value>effective value</a>
+"normal".  Otherwise false.
+
 <p><a href=#state>State</a>: True if every <a href=#editable>editable</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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
 <a href=#effective-value>effective value</a> either "italic" or "oblique", and there is at
@@ -2662,6 +2673,12 @@
 
 <p class=XXX>Has all the same problems as <a href=#the-underline-command>the <code title="">underline</code> command</a>.
 
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if among <a href=#editable>editable</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> nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, there is at least one with <a href=#effective-value>effective value</a>
+"line-through" and at least one with <a href=#effective-value>effective value</a> null.
+Otherwise false.
+
 <p><a href=#state>State</a>: True if every <a href=#editable>editable</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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
 <a href=#effective-value>effective value</a> "line-through", and there is at least one such
@@ -2686,18 +2703,28 @@
   to "sub".
 </ol>
 
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if either among <a href=#editable>editable</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> nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, there is at least one with <a href=#effective-value>effective value</a> "sub" and
+at least one with some other <a href=#effective-value>effective value</a>; or if there is some
+<a href=#editable>editable</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 <a href=#effectively-contained>effectively contained</a> in the
+<a href=#active-range>active range</a> with <a href=#effective-value>effective value</a> "mixed".  Otherwise
+false.
+
 <p><a href=#state>State</a>: True if every <a href=#editable>editable</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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
 <a href=#effective-value>effective value</a> "sub", and there is at least one such <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.  Otherwise false.
 <!--
 For <sup><sub>foo</sub></sup>, Firefox 6.0a2 and Opera 11.11 say the state is
-true for both superscript and subscript; Chrome 14 dev says it's true for
-subscript but not superscript.  We follow neither of these behaviors: we return
-false for both.  The reason is because we want to return true if we'll do
-nothing, false if we'll do something; and if we have nesting like this, we'll
-always do something, namely get rid of all those ancestors and replace them
-with a single tag.
+true for both superscript and subscript, and indeterminate is false; Chrome 14
+dev says it's true for subscript but not superscript, and indeterminate is
+false.  We follow neither of these behaviors: we return false for both states,
+and say indeterminate is true.  The reason is because we want to return true
+for a state if we'll do nothing, false if we'll do something; and if we have
+nesting like this, we'll always do something, namely get rid of all those
+ancestors and replace them with a single tag.  This matches what happens in
+other indeterminate situations, so it's fair to consider it indeterminate.
 -->
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "vertical-align"
@@ -2721,6 +2748,14 @@
   to "super".
 </ol>
 
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if either among <a href=#editable>editable</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> nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, there is at least one with <a href=#effective-value>effective value</a> "super"
+and at least one with some other <a href=#effective-value>effective value</a>; or if there is
+some <a href=#editable>editable</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 <a href=#effectively-contained>effectively contained</a> in
+the <a href=#active-range>active range</a> with <a href=#effective-value>effective value</a> "mixed".
+Otherwise false.
+
 <p><a href=#state>State</a>: True if every <a href=#editable>editable</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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
 <a href=#effective-value>effective value</a> "super", and there is at least one such <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code>
@@ -2784,6 +2819,12 @@
 may be.
 </div>
 
+<p><a href=#indeterminate-flag>Indeterminate flag</a>: True if among <a href=#editable>editable</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> nodes that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
+range</a>, there is at least one with <a href=#effective-value>effective value</a>
+"underline" and at least one with <a href=#effective-value>effective value</a> null.  Otherwise
+false.
+
 <p><a href=#state>State</a>: True if every <a href=#editable>editable</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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
 <a href=#effective-value>effective value</a> "underline", and there is at least one such
--- a/implementation.js	Tue Jun 28 13:32:08 2011 -0600
+++ b/implementation.js	Tue Jun 28 14:06:43 2011 -0600
@@ -1707,9 +1707,9 @@
 			} else if (verticalAlign == "super") {
 				affectedBySuperscript = true;
 			// "Otherwise, if node's "vertical-align" property computes to some
-			// value other than "baseline", return the string "mixed"."
+			// value other than "baseline", return the string "other"."
 			} else if (verticalAlign != "baseline") {
-				return "mixed";
+				return "other";
 			}
 
 			// "Set node to its parent."
@@ -2991,7 +2991,14 @@
 		for (var i = 0; i < nodeList.length; i++) {
 			setNodeValue(nodeList[i], "italic", newValue);
 		}
-	}, state: function() { return stateHelper(function(node) {
+	}, indeterm: function() { return indetermHelper(function(node) {
+		// "True if among editable Text nodes that are effectively contained in
+		// the active range, there is at least one with effective value either
+		// "italic" or "oblique" and at least one with effective value
+		// "normal". Otherwise false."
+		var value = getEffectiveValue(node, "italic");
+		return value == "italic" || value == "oblique";
+	})}, state: function() { return stateHelper(function(node) {
 		// "True if every editable Text node that is effectively contained in
 		// the active range has effective value either "italic" or "oblique",
 		// and there is at least one such Text node.  Otherwise false."
@@ -3092,7 +3099,13 @@
 		for (var i = 0; i < nodeList.length; i++) {
 			setNodeValue(nodeList[i], "strikethrough", newValue);
 		}
-	}, state: function() { return stateHelper(function(node) {
+	}, indeterm: function() { return indetermHelper(function(node) {
+		// "True if among editable Text nodes that are effectively contained in
+		// the active range, there is at least one with effective value
+		// "line-through" and at least one with effective value null. Otherwise
+		// false."
+		return getEffectiveValue(node, "strikethrough") == "line-through";
+	})}, state: function() { return stateHelper(function(node) {
 		// "True if every editable Text node that is effectively contained in
 		// the active range has effective value "line-through", and there is at
 		// least one such Text node. Otherwise false."
@@ -3124,6 +3137,25 @@
 				setNodeValue(nodeList[i], "subscript", "sub");
 			}
 		}
+	}, indeterm: function() {
+		// "True if either among editable Text nodes that are effectively
+		// contained in the active range, there is at least one with effective
+		// value "sub" and at least one with some other effective value; or if
+		// there is some editable Text node effectively contained in the active
+		// range with effective value "mixed". Otherwise false."
+		//
+		// The use of stateHelper() here is a bit of a hack, but it works.  The
+		// way the logic works out is that it returns true if every editable
+		// text node etc. does *not* have effective value "mixed" and there's
+		// at least one, so if we negate it that means either there's no
+		// editable etc. text node or else one has effective value mixed.  The
+		// second invocation of stateHelper() handles the case where there are
+		// no editable Text nodes effectively contained in the range.
+		if (indetermHelper(function(node) { return getEffectiveValue(node, "subscript") == "sub" })) {
+			return true;
+		}
+		return !stateHelper(function(node) { return getEffectiveValue(node, "subscript") != "mixed" })
+			&& stateHelper(function() { return true });
 	}, state: function() { return stateHelper(function(node) {
 		// "True if every editable Text node that is effectively contained in
 		// the active range has effective value "sub", and there is at least
@@ -3156,6 +3188,19 @@
 				setNodeValue(nodeList[i], "superscript", "super");
 			}
 		}
+	}, indeterm: function() {
+		// "True if either among editable Text nodes that are effectively
+		// contained in the active range, there is at least one with effective
+		// value "super" and at least one with some other effective value; or
+		// if there is some editable Text node effectively contained in the
+		// active range with effective value "mixed". Otherwise false."
+		//
+		// See subscript for implementation remark.
+		if (indetermHelper(function(node) { return getEffectiveValue(node, "superscript") == "super" })) {
+			return true;
+		}
+		return !stateHelper(function(node) { return getEffectiveValue(node, "superscript") != "mixed" })
+			&& stateHelper(function() { return true });
 	}, state: function() { return stateHelper(function(node) {
 		// "True if every editable Text node that is effectively contained in
 		// the active range has effective value "super", and there is at least
@@ -3177,7 +3222,13 @@
 		for (var i = 0; i < nodeList.length; i++) {
 			setNodeValue(nodeList[i], "underline", newValue);
 		}
-	}, state: function() { return stateHelper(function(node) {
+	}, indeterm: function() { return indetermHelper(function(node) {
+		// "True if among editable Text nodes that are effectively contained in
+		// the active range, there is at least one with effective value
+		// "underline" and at least one with effective value null. Otherwise
+		// false."
+		return getEffectiveValue(node, "underline") === "underline";
+	})}, state: function() { return stateHelper(function(node) {
 		// "True if every editable Text node that is effectively contained in
 		// the active range has effective value "underline", and there is at
 		// least one such Text node. Otherwise false."
--- a/source.html	Tue Jun 28 13:32:08 2011 -0600
+++ b/source.html	Tue Jun 28 14:06:43 2011 -0600
@@ -1113,6 +1113,11 @@
     computes to "inline":
 
     <ol>
+      <!-- Firefox 6.0a2 ignores vertical-align for this purpose, and only
+      cares about <sub> and <sup> tags themselves.  Opera 11.11 is similar, and
+      in fact behaves like that even for commands like bold.  The spec follows
+      Chrome 14 dev, mainly because WebKit itself will produce spans with
+      vertical-align sub or super, and we want to handle them correctly. -->
       <li>If <var>node</var>'s "vertical-align" property computes to "sub", set
       <var>affected by subscript</var> to true.
 
@@ -1120,7 +1125,7 @@
       "super", set <var>affected by superscript</var> to true.
 
       <li>Otherwise, if <var>node</var>'s "vertical-align" property computes to
-      some value other than "baseline", return the string "mixed".
+      some value other than "baseline", return the string "other".
 
       <li>Set <var>node</var> to its [[parent]].
     </ol>
@@ -2499,6 +2504,12 @@
 returned [[node]] to "italic", otherwise <span>set the value</span> to
 "normal".
 
+<p><span>Indeterminate flag</span>: True if among <span>editable</span>
+[[text]] nodes that are <span>effectively contained</span> in the <span>active
+range</span>, there is at least one with <span>effective value</span> either
+"italic" or "oblique" and at least one with <span>effective value</span>
+"normal".  Otherwise false.
+
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
 <span>effective value</span> either "italic" or "oblique", and there is at
@@ -2639,6 +2650,12 @@
 <p class=XXX>Has all the same problems as <span>the <code
 title>underline</code> command</span>.
 
+<p><span>Indeterminate flag</span>: True if among <span>editable</span>
+[[text]] nodes that are <span>effectively contained</span> in the <span>active
+range</span>, there is at least one with <span>effective value</span>
+"line-through" and at least one with <span>effective value</span> null.
+Otherwise false.
+
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
 <span>effective value</span> "line-through", and there is at least one such
@@ -2663,18 +2680,28 @@
   to "sub".
 </ol>
 
+<p><span>Indeterminate flag</span>: True if either among <span>editable</span>
+[[text]] nodes that are <span>effectively contained</span> in the <span>active
+range</span>, there is at least one with <span>effective value</span> "sub" and
+at least one with some other <span>effective value</span>; or if there is some
+<span>editable</span> [[text]] node <span>effectively contained</span> in the
+<span>active range</span> with <span>effective value</span> "mixed".  Otherwise
+false.
+
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
 <span>effective value</span> "sub", and there is at least one such [[text]]
 node.  Otherwise false.
 <!--
 For <sup><sub>foo</sub></sup>, Firefox 6.0a2 and Opera 11.11 say the state is
-true for both superscript and subscript; Chrome 14 dev says it's true for
-subscript but not superscript.  We follow neither of these behaviors: we return
-false for both.  The reason is because we want to return true if we'll do
-nothing, false if we'll do something; and if we have nesting like this, we'll
-always do something, namely get rid of all those ancestors and replace them
-with a single tag.
+true for both superscript and subscript, and indeterminate is false; Chrome 14
+dev says it's true for subscript but not superscript, and indeterminate is
+false.  We follow neither of these behaviors: we return false for both states,
+and say indeterminate is true.  The reason is because we want to return true
+for a state if we'll do nothing, false if we'll do something; and if we have
+nesting like this, we'll always do something, namely get rid of all those
+ancestors and replace them with a single tag.  This matches what happens in
+other indeterminate situations, so it's fair to consider it indeterminate.
 -->
 
 <p><span>Relevant CSS property</span>: "vertical-align"
@@ -2698,6 +2725,14 @@
   to "super".
 </ol>
 
+<p><span>Indeterminate flag</span>: True if either among <span>editable</span>
+[[text]] nodes that are <span>effectively contained</span> in the <span>active
+range</span>, there is at least one with <span>effective value</span> "super"
+and at least one with some other <span>effective value</span>; or if there is
+some <span>editable</span> [[text]] node <span>effectively contained</span> in
+the <span>active range</span> with <span>effective value</span> "mixed".
+Otherwise false.
+
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
 <span>effective value</span> "super", and there is at least one such [[text]]
@@ -2763,6 +2798,12 @@
 may be.
 </div>
 
+<p><span>Indeterminate flag</span>: True if among <span>editable</span>
+[[text]] nodes that are <span>effectively contained</span> in the <span>active
+range</span>, there is at least one with <span>effective value</span>
+"underline" and at least one with <span>effective value</span> null.  Otherwise
+false.
+
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
 <span>effective value</span> "underline", and there is at least one such
--- a/tests.js	Tue Jun 28 13:32:08 2011 -0600
+++ b/tests.js	Tue Jun 28 14:06:43 2011 -0600
@@ -210,7 +210,7 @@
 
 		'<p style="font-weight: bold">foo[bar]baz</p>',
 
-		// Tests for queryCommandIndeterm()
+		// Tests for queryCommandIndeterm() and queryCommandState()
 		'fo[o<b>b]ar</b>baz',
 		'foo<b>ba[r</b>b]az',
 		'fo[o<b>bar</b>b]az',
@@ -2232,6 +2232,21 @@
 		'foo bar <b>baz [qoz</b> quz] sic',
 		'foo [bar <i>baz] qoz</i> quz sic',
 		'foo bar <i>baz [qoz</i> quz] sic',
+
+		// Tests for queryCommandIndeterm() and queryCommandState()
+		'fo[o<i>b]ar</i>baz',
+		'foo<i>ba[r</i>b]az',
+		'fo[o<i>bar</i>b]az',
+		'foo[<i>b]ar</i>baz',
+		'foo<i>ba[r</i>]baz',
+		'foo[<i>bar</i>]baz',
+		'foo<i>[bar]</i>baz',
+		'foo{<i>bar</i>}baz',
+		'fo[o<span style=font-style:italic>b]ar</span>baz',
+		'fo[o<span style=font-style:oblique>b]ar</span>baz',
+		'<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>',
+		'<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>',
+		'<i>fo[o</i><address>b]ar</address>',
 	],
 	//@}
 	justifycenter: [
@@ -2921,6 +2936,19 @@
 		'foo<span class="line-through">b[a]r</span>baz',
 		'foo<span class="underline-and-line-through">[bar]</span>baz',
 		'foo<span class="underline-and-line-through">b[a]r</span>baz',
+
+		// Tests for queryCommandIndeterm() and queryCommandState()
+		'fo[o<s>b]ar</s>baz',
+		'foo<s>ba[r</s>b]az',
+		'fo[o<s>bar</s>b]az',
+		'foo[<s>b]ar</s>baz',
+		'foo<s>ba[r</s>]baz',
+		'foo[<s>bar</s>]baz',
+		'foo<s>[bar]</s>baz',
+		'foo{<s>bar</s>}baz',
+		'fo[o<span style=text-decoration:line-through>b]ar</span>baz',
+		'<strike>fo[o</strike><s>b]ar</s>',
+		'<s>fo[o</s><del>b]ar</del>',
 	],
 	//@}
 	subscript: [
@@ -2929,8 +2957,6 @@
 		'<span>foo</span>{}<span>bar</span>',
 		'<span>foo[</span><span>]bar</span>',
 		'foo[bar]baz',
-		'foo]bar[baz',
-		'{<p><p> <p>foo</p>}',
 		'foo[bar<b>baz]qoz</b>quz',
 
 		'<table><tbody><tr><td>foo<td>b[a]r<td>baz</table>',
@@ -2945,6 +2971,9 @@
 		'foo<sup>[bar]</sup>baz',
 		'foo<sup>b[a]r</sup>baz',
 
+		'foo<span style=vertical-align:sub>[bar]</span>baz',
+		'foo<span style=vertical-align:super>[bar]</span>baz',
+
 		'foo<sub><sub>[bar]</sub></sub>baz',
 		'foo<sub><sub>b[a]r</sub></sub>baz',
 		'foo<sub>b<sub>[a]</sub>r</sub>baz',
@@ -2957,6 +2986,20 @@
 		'foo<sup><sub>[bar]</sub></sup>baz',
 		'foo<sup><sub>b[a]r</sub></sup>baz',
 		'foo<sup>b<sub>[a]</sub>r</sup>baz',
+
+		// Tests for queryCommandIndeterm() and queryCommandState()
+		'fo[o<sub>b]ar</sub>baz',
+		'foo<sub>ba[r</sub>b]az',
+		'fo[o<sub>bar</sub>b]az',
+		'foo[<sub>b]ar</sub>baz',
+		'foo<sub>ba[r</sub>]baz',
+		'foo[<sub>bar</sub>]baz',
+		'foo<sub>[bar]</sub>baz',
+		'foo{<sub>bar</sub>}baz',
+		'<sub>fo[o</sub><sup>b]ar</sup>',
+		'<sub>fo[o</sub><span style=vertical-align:sub>b]ar</span>',
+		'foo<span style=vertical-align:top>[bar]</span>baz',
+		'<sub>fo[o</sub><span style=vertical-align:top>b]ar</span>',
 	],
 	//@}
 	superscript: [
@@ -2965,8 +3008,6 @@
 		'<span>foo</span>{}<span>bar</span>',
 		'<span>foo[</span><span>]bar</span>',
 		'foo[bar]baz',
-		'foo]bar[baz',
-		'{<p><p> <p>foo</p>}',
 		'foo[bar<b>baz]qoz</b>quz',
 
 		'<table><tbody><tr><td>foo<td>b[a]r<td>baz</table>',
@@ -2981,6 +3022,9 @@
 		'foo<sup>[bar]</sup>baz',
 		'foo<sup>b[a]r</sup>baz',
 
+		'foo<span style=vertical-align:sub>[bar]</span>baz',
+		'foo<span style=vertical-align:super>[bar]</span>baz',
+
 		'foo<sub><sub>[bar]</sub></sub>baz',
 		'foo<sub><sub>b[a]r</sub></sub>baz',
 		'foo<sub>b<sub>[a]</sub>r</sub>baz',
@@ -2993,6 +3037,20 @@
 		'foo<sup><sub>[bar]</sub></sup>baz',
 		'foo<sup><sub>b[a]r</sub></sup>baz',
 		'foo<sup>b<sub>[a]</sub>r</sup>baz',
+
+		// Tests for queryCommandIndeterm() and queryCommandState()
+		'fo[o<sup>b]ar</sup>baz',
+		'foo<sup>ba[r</sup>b]az',
+		'fo[o<sup>bar</sup>b]az',
+		'foo[<sup>b]ar</sup>baz',
+		'foo<sup>ba[r</sup>]baz',
+		'foo[<sup>bar</sup>]baz',
+		'foo<sup>[bar]</sup>baz',
+		'foo{<sup>bar</sup>}baz',
+		'<sup>fo[o</sup><sub>b]ar</sub>',
+		'<sup>fo[o</sup><span style=vertical-align:super>b]ar</span>',
+		'foo<span style=vertical-align:bottom>[bar]</span>baz',
+		'<sup>fo[o</sup><span style=vertical-align:bottom>b]ar</span>',
 	],
 	//@}
 	underline: [
@@ -3071,6 +3129,19 @@
 		'foo<span class="line-through">b[a]r</span>baz',
 		'foo<span class="underline-and-line-through">[bar]</span>baz',
 		'foo<span class="underline-and-line-through">b[a]r</span>baz',
+
+		// Tests for queryCommandIndeterm() and queryCommandState()
+		'fo[o<u>b]ar</u>baz',
+		'foo<u>ba[r</u>b]az',
+		'fo[o<u>bar</u>b]az',
+		'foo[<u>b]ar</u>baz',
+		'foo<u>ba[r</u>]baz',
+		'foo[<u>bar</u>]baz',
+		'foo<u>[bar]</u>baz',
+		'foo{<u>bar</u>}baz',
+		'fo[o<span style=text-decoration:underline>b]ar</span>baz',
+		'<ins>fo[o</ins><u>b]ar</u>',
+		'<u>fo[o</u><ins>b]ar</ins>',
 	],
 	//@}
 	unlink: [