Buggy and incomplete superscript/subscript spec
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Sun, 27 Mar 2011 17:59:22 -0600
changeset 38 edb0122f35f2
parent 37 7c418b09b578
child 39 fd250049ac86
Buggy and incomplete superscript/subscript spec

The time has come for me to define Range mutations.
autoimplementation.html
editcommands.html
implementation.js
preprocess
source.html
--- a/autoimplementation.html	Fri Mar 25 16:08:52 2011 -0600
+++ b/autoimplementation.html	Sun Mar 27 17:59:22 2011 -0600
@@ -128,8 +128,8 @@
 
 <button onclick="runTests('subscript')">Run tests</button>
 
-<p><strong>Note:</strong> No spec has yet been written, so the spec column does
-nothing.
+<p><strong>Note:</strong> The subscript spec is still buggy and unstable, so
+don't pay much attention to what's in the spec column.
 
 <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>
--- a/editcommands.html	Fri Mar 25 16:08:52 2011 -0600
+++ b/editcommands.html	Sun Mar 27 17:59:22 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-25-march-2011>Work in Progress &mdash; Last Update 25 March 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-27-march-2011>Work in Progress &mdash; Last Update 27 March 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -236,7 +236,7 @@
 
 <p>The <dfn id=effective-style>effective style</dfn> of a <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#node><code class=external data-anolis-spec=domcore>Node</code></a> <var title="">node</var> for a given
 <var title="">property</var> is returned by the following algorithm, which will return
-either a CSS value or null:
+either a string or null:
 
 <ol>
   <li>If <var title="">node</var> is neither 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> nor a <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, return
@@ -248,14 +248,6 @@
   <li>If <var title="">node</var> is a <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, return the <a href=#effective-style>effective
   style</a> of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> for <var title="">property</var>.
 
-  <li>If <var title="">property</var> is "text-decoration", and the "text-decoration"
-  property of <var title="">node</var> or any of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> computes to
-  "underline", return "underline".  Otherwise, return "none".
-
-  <p class=XXX>We ignore the possibility of text-decorations other than
-  underline for now, so we pretend that there are only two possible values:
-  "underline" and "none".
-
   <li>If <var title="">property</var> is "background-color":
 
   <ol>
@@ -270,6 +262,49 @@
     <var title="">node</var>.
   </ol>
 
+  <li>If <var title="">property</var> is "text-decoration", and the "text-decoration"
+  property of <var title="">node</var> or any of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> computes to
+  "underline", return "underline".  Otherwise, return "none".
+
+  <p class=XXX>We ignore the possibility of text-decorations other than
+  underline for now, so we pretend that there are only two possible values:
+  "underline" and "none".
+
+  <li>If <var title="">property</var> is "vertical-align":
+
+  <p class=XXX>We massively abuse this property.  Maybe we shouldn't be using
+  the CSS names here.
+
+  <ol>
+    <li>Let <var title="">affected by subscript</var> and <var title="">affected by
+    superscript</var> be two boolean variables, both initially false.
+
+    <li>While <var title="">node</var> is 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> whose "display" property
+    computes to "inline":
+
+    <ol>
+      <li>If <var title="">node</var>'s "vertical-align" property computes to "sub", set
+      <var title="">affected by subscript</var> to true.
+
+      <li>Otherwise, if <var title="">node</var>'s "vertical-align" property computes to
+      "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".
+
+      <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>
+
+    <li>If <var title="">affected by subscript</var> and <var title="">affected by
+    superscript</var> are both true, return the string "mixed".
+
+    <li>If <var title="">affected by subscript</var> is true, return "sub".
+
+    <li>If <var title="">affected by superscript</var> is true, return "super".
+
+    <li>Return "baseline".
+  </ol>
+
   <li>Return the computed style of <var title="">property</var> for <var title="">node</var>.
 </ol>
 
@@ -287,6 +322,23 @@
   non-inline background-colors.  Maybe the name "specified style" is
   misleading, though. -->
 
+  <li>If <var title="">property</var> is "vertical-align":
+
+  <ol>
+    <li>If the computed value of the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a>'s "display" property is
+    neither "inline" nor "inline-block" nor "inline-table", return null.
+
+    <li>If the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> has 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 set, and that attribute
+    has the effect of setting "vertical-align", return the value that it sets
+    "vertical-align" to.
+
+    <li>If the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> is a <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sup</code></a>, return "super".
+
+    <li>If the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> is a <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a>, return "sub".
+
+    <li>Return null.
+  </ol>
+
   <li>If the <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element><code class=external data-anolis-spec=domcore>Element</code></a> has 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 set, and that attribute has
   the effect of setting <var title="">property</var>, return the value that it sets
   <var title="">property</var> to.
@@ -317,9 +369,9 @@
 </ol>
 
 <p>A <dfn id=styling-element>styling element</dfn> is a <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>, <a href=http://www.whatwg.org/html/#the-em-element><code class=external data-anolis-spec=html title="the em element">em</code></a>, <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a>, <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>,
-<a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a> element with no attributes except possibly <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, or
-a <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a> element with no attributes except possibly <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, <a href=http://www.whatwg.org/html/#dom-font-color><code class=external data-anolis-spec=html title=dom-font-color>color</code></a>,
-<a href=http://www.whatwg.org/html/#dom-font-face><code class=external data-anolis-spec=html title=dom-font-face>face</code></a>, and/or <a href=http://www.whatwg.org/html/#dom-font-size><code class=external data-anolis-spec=html title=dom-font-size>size</code></a>.
+<a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a>, <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sup</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a> element with no attributes except
+possibly <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, or a <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a> element with no attributes except possibly
+<a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, <a href=http://www.whatwg.org/html/#dom-font-color><code class=external data-anolis-spec=html title=dom-font-color>color</code></a>, <a href=http://www.whatwg.org/html/#dom-font-face><code class=external data-anolis-spec=html title=dom-font-face>face</code></a>, and/or <a href=http://www.whatwg.org/html/#dom-font-size><code class=external data-anolis-spec=html title=dom-font-size>size</code></a>.
 
 <p class=note>Conceptually, a <a href=#styling-element>styling element</a> is a phrasing
 element whose only purpose is to style text.  Thus changing around styling
@@ -332,13 +384,13 @@
 <p>A <dfn id=simple-styling-element>simple styling element</dfn> is an <a href=#html-element>HTML element</a> for
 which at least one of the following holds:
 
-<ol>
-  <li>It is a <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>, <a href=http://www.whatwg.org/html/#the-em-element><code class=external data-anolis-spec=html title="the em element">em</code></a>, <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a>, <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a>, <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>, <a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a>
-  element with no attributes.
+<ul>
+  <li>It is a <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>, <a href=http://www.whatwg.org/html/#the-em-element><code class=external data-anolis-spec=html title="the em element">em</code></a>, <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a>, <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a>, <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>, <a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a>,
+  <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sup</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a> element with no attributes.
 
-  <li>It is a <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>, <a href=http://www.whatwg.org/html/#the-em-element><code class=external data-anolis-spec=html title="the em element">em</code></a>, <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a>, <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a>, <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>, <a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a>
-  element with exactly one attribute, which is <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, which sets no CSS
-  properties (including invalid or unrecognized properties).
+  <li>It is a <a href=http://www.whatwg.org/html/#the-b-element><code class=external data-anolis-spec=html title="the b element">b</code></a>, <a href=http://www.whatwg.org/html/#the-em-element><code class=external data-anolis-spec=html title="the em element">em</code></a>, <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a>, <a href=http://www.whatwg.org/html/#the-i-element><code class=external data-anolis-spec=html title="the i element">i</code></a>, <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a>, <a href=http://www.whatwg.org/html/#the-strong-element><code class=external data-anolis-spec=html title="the strong element">strong</code></a>, <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a>,
+  <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sup</code></a>, or <a href=http://www.whatwg.org/html/#the-u-element><code class=external data-anolis-spec=html title="the u element">u</code></a> element with exactly one attribute, which is <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>,
+  which sets no CSS properties (including invalid or unrecognized properties).
 
   <li>It is a <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a> element with exactly one attribute, which is either
   <a href=http://www.whatwg.org/html/#dom-font-color><code class=external data-anolis-spec=html title=dom-font-color>color</code></a>, <a href=http://www.whatwg.org/html/#dom-font-face><code class=external data-anolis-spec=html title=dom-font-face>face</code></a>, or <a href=http://www.whatwg.org/html/#dom-font-size><code class=external data-anolis-spec=html title=dom-font-size>size</code></a>.
@@ -356,10 +408,14 @@
   unrecognized properties), which is "text-decoration", which is set to
   "underline" or "none".
 
+  <li>It is a <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a> or <a href=http://www.whatwg.org/html/#the-sub-and-sup-elements><code class=external data-anolis-spec=html title="the sub and sup elements">sub</code></a> element with exactly one attribute, which is
+  <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, and the <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 sets exactly one CSS property
+  (including invalid or unrecognized properties), which is "vertical-align".
+
   <li>It is a <a href=http://www.whatwg.org/html/#font><code class=external data-anolis-spec=html title=font>font</code></a> or <a href=http://www.whatwg.org/html/#the-span-element><code class=external data-anolis-spec=html title="the span element">span</code></a> element with exactly one attribute, which is
   <a href=http://www.whatwg.org/html/#the-style-attribute><code class=external data-anolis-spec=html title="the style attribute">style</code></a>, and the <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 sets exactly one CSS property
   (including invalid or unrecognized properties).
-</ol>
+</ul>
 
 <p class=note>Conceptually, a <a href=#simple-styling-element>simple styling element</a> is a
 <a href=#styling-element>styling element</a> which <a href=#specified-style title="specified
@@ -828,6 +884,18 @@
     of <var title="">new parent</var> to <var title="">new value</var>.
   </ol>
 
+  <!-- We always use sup/sub elements, even in CSS mode, following Gecko and
+  contradicting WebKit.  This is because <span style="vertical-align:
+  sub/super">, the obvious equivalent (and what WebKit uses), behaves quite
+  differently: it doesn't reduce font-size, which is ugly. -->
+  <li>If <var title="">property</var> is "vertical-align" and <var title="">new value</var> is
+  "sub", let <var title="">new parent</var> be the result of calling <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement><code class=external data-anolis-spec=domcore title=dom-Document-createElement>createElement("sub")</code></a> on the
+  <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> of <var title="">node</var>.
+
+  <li>If <var title="">property</var> is "vertical-align" and <var title="">new value</var> is
+  "super", let <var title="">new parent</var> be the result of calling <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement><code class=external data-anolis-spec=domcore title=dom-Document-createElement>createElement("sup")</code></a> on the
+  <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> of <var title="">node</var>.
+
   <li>If <var title="">new parent</var> is null, let <var title="">new parent</var> be the result
   of calling <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement><code class=external data-anolis-spec=domcore title=dom-Document-createElement>createElement("span")</code></a> on the
   <a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument><code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument>ownerDocument</code></a> of <var title="">node</var>.
@@ -1370,6 +1438,42 @@
 <dd><strong>Value</strong>:
 
 
+<dt><code title=""><dfn id=command-subscript title=command-subscript>subscript</dfn></code>
+
+<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> "vertical-align" and <var title="">new
+value</var> "baseline".  Otherwise, <a href=#style>style</a> them with <var title="">new
+value</var> "baseline", then <a href=#style>style</a> them again with <var title="">new
+value</var> "sub".
+
+<p class=XXX>This doesn't work, because we'll have removed some of the things
+that we want to style in some cases.  Need to define what happens to a range
+when you style its nodes, then re-decompose the same range before re-styling.
+
+<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 "sub" for "vertical-align".  Otherwise false.
+
+<dd><strong>Value</strong>:
+
+
+<dt><code title=""><dfn id=command-superscript title=command-superscript>superscript</dfn></code>
+
+<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> "vertical-align" and <var title="">new
+value</var> "baseline".  Otherwise, <a href=#style>style</a> them with <var title="">new
+value</var> "baseline", then <a href=#style>style</a> them again with <var title="">new
+value</var> "super".
+
+<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 "super" for "vertical-align".  Otherwise false.
+
+<dd><strong>Value</strong>:
+
+
 <dt><code title=""><dfn id=command-underline title=command-underline>underline</dfn></code>
 
 <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
--- a/implementation.js	Fri Mar 25 16:08:52 2011 -0600
+++ b/implementation.js	Sun Mar 27 17:59:22 2011 -0600
@@ -58,6 +58,13 @@
 		return val1 === val2;
 	}
 
+	if (property == "verticalAlign") {
+		// Fake property values
+		if (val1 == "mixed" || val2 == "mixed") {
+			return val1 === val2;
+		}
+	}
+
 	if (property == "fontWeight") {
 		return val1 == val2
 			|| (val1.toLowerCase() == "bold" && val2 == "700")
@@ -314,19 +321,6 @@
 		return getEffectiveStyle(node.parentNode, property);
 	}
 
-	// "If property is "text-decoration", and the "text-decoration" property of
-	// node or any of its ancestors computes to "underline", return
-	// "underline". Otherwise, return "none"."
-	if (property == "textDecoration") {
-		do {
-			if (getComputedStyle(node).textDecoration == "underline") {
-				return "underline";
-			}
-			node = node.parentNode;
-		} while (node && node.nodeType == Node.ELEMENT_NODE);
-		return "none";
-	}
-
 	// "If property is "background-color":"
 	if (property == "backgroundColor") {
 		// "While the computed style of "background-color" on node is any
@@ -355,6 +349,71 @@
 		return getComputedStyle(node).backgroundColor;
 	}
 
+	// "If property is "text-decoration", and the "text-decoration" property of
+	// node or any of its ancestors computes to "underline", return
+	// "underline". Otherwise, return "none"."
+	if (property == "textDecoration") {
+		do {
+			if (getComputedStyle(node).textDecoration == "underline") {
+				return "underline";
+			}
+			node = node.parentNode;
+		} while (node && node.nodeType == Node.ELEMENT_NODE);
+		return "none";
+	}
+
+	// "If property is "vertical-align":"
+	if (property == "verticalAlign") {
+		// "Let affected by subscript and affected by superscript be two
+		// boolean variables, both initially false."
+		var affectedBySubscript = false;
+		var affectedBySuperscript = false;
+
+		// "While node is an Element whose "display" property computes to
+		// "inline":"
+		while (node
+		&& node.nodeType == Node.ELEMENT_NODE
+		&& getComputedStyle(node).display == "inline") {
+			var verticalAlign = getComputedStyle(node).verticalAlign;
+
+			// "If node's "vertical-align" property computes to "sub", set
+			// affected by subscript to true."
+			if (verticalAlign == "sub") {
+				affectedBySubscript = true;
+			// "Otherwise, if node's "vertical-align" property computes to
+			// "super", set affected by superscript to true."
+			} else if (verticalAlign == "super") {
+				affectedBySuperscript = true;
+			// "Otherwise, if node's "vertical-align" property computes to some
+			// value other than "baseline", return the string "mixed"."
+			} else if (verticalAlign != "baseline") {
+				return "mixed";
+			}
+
+			// "Set node to its parent."
+			node = node.parentNode;
+		}
+
+		// "If affected by subscript and affected by superscript are both true,
+		// return the string "mixed"."
+		if (affectedBySubscript && affectedBySuperscript) {
+			return "mixed";
+		}
+
+		// "If affected by subscript is true, return "sub"."
+		if (affectedBySubscript) {
+			return "sub";
+		}
+
+		// "If affected by superscript is true, return "super"."
+		if (affectedBySuperscript) {
+			return "super";
+		}
+
+		// "Return "baseline"."
+		return "baseline";
+	}
+
 	// "Return the computed style of property for node."
 	return getComputedStyle(node)[property];
 }
@@ -370,6 +429,39 @@
 		return null;
 	}
 
+	// "If property is "vertical-align":"
+	if (property == "verticalAlign") {
+		// "If the computed value of the Element's "display" property is
+		// neither "inline" nor "inline-block" nor "inline-table", return
+		// null."
+		var style = getComputedStyle(element);
+		if (style.display != "inline"
+		&& style.display != "inline-block"
+		&& style.display != "inline-table") {
+			return null;
+		}
+
+		// "If the Element has a style attribute set, and that attribute has
+		// the effect of setting "vertical-align", return the value that it
+		// sets "vertical-align" to."
+		if (element.style.verticalAlign != "") {
+			return element.style.verticalAlign;
+		}
+
+		// "If the Element is a sup, return "super"."
+		if (isHtmlElement(element) && element.tagName == "SUP") {
+			return "super";
+		}
+
+		// "If the Element is a sub, return "sub"."
+		if (isHtmlElement(element) && element.tagName == "SUB") {
+			return "sub";
+		}
+
+		// "Return null."
+		return null;
+	}
+
 	// "If the Element has a style attribute set, and that attribute has the
 	// effect of setting property, return the value that it sets property to."
 	if (element.style[property] != "") {
@@ -416,15 +508,15 @@
 	return null;
 }
 
-// "A styling element is a b, em, i, span, strong, or u element with no
-// attributes except possibly style, or a font element with no attributes
+// "A styling element is a b, em, i, span, strong, sub, sup, or u element with
+// no attributes except possibly style, or a font element with no attributes
 // except possibly style, color, face, and/or size."
 function isStylingElement(node) {
 	if (!isHtmlElement(node)) {
 		return false;
 	}
 
-	if (["B", "EM", "I", "SPAN", "STRONG", "U"].indexOf(node.tagName) != -1) {
+	if (["B", "EM", "I", "SPAN", "STRONG", "SUB", "SUP", "U"].indexOf(node.tagName) != -1) {
 		if (node.attributes.length == 0) {
 			return true;
 		}
@@ -470,11 +562,12 @@
 	}
 
 	// Only these elements can possibly be a simple styling element.
-	if (["B", "EM", "FONT", "I", "SPAN", "STRONG", "U"].indexOf(node.tagName) == -1) {
+	if (["B", "EM", "FONT", "I", "SPAN", "STRONG", "SUB", "SUP", "U"].indexOf(node.tagName) == -1) {
 		return false;
 	}
 
-	// "It is a b, em, font, i, span, strong, or u element with no attributes."
+	// "It is a b, em, font, i, span, strong, sub, sup, or u element with no
+	// attributes."
 	if (node.attributes.length == 0) {
 		return true;
 	}
@@ -484,9 +577,9 @@
 		return false;
 	}
 
-	// "It is a b, em, font, i, span, strong, or u element with exactly one
-	// attribute, which is style, which sets no CSS properties (including
-	// invalid or unrecognized properties)."
+	// "It is a b, em, font, i, span, strong, sub, sup, or u element with
+	// exactly one attribute, which is style, which sets no CSS properties
+	// (including invalid or unrecognized properties)."
 	//
 	// Not gonna try for invalid or unrecognized.
 	if (node.hasAttribute("style")
@@ -531,7 +624,18 @@
 	if (node.tagName == "U"
 	&& node.hasAttribute("style")
 	&& node.style.length == 1
-	&& node.style.textDecoration != "") {
+	&& (node.style.textDecoration == "underline"
+	|| node.style.textDecoration == "none")) {
+		return true;
+	}
+
+	// "It is a sub or sub element with exactly one attribute, which is style,
+	// and the style attribute sets exactly one CSS property (including invalid
+	// or unrecognized properties), which is "vertical-align"."
+	if ((node.tagName == "SUB" || node.tagName == "SUP")
+	&& node.hasAttribute("style")
+	&& node.style.length == 1
+	&& node.style.verticalAlign != "") {
 		return true;
 	}
 
@@ -1061,6 +1165,20 @@
 		}
 	}
 
+	// "If property is "vertical-align" and new value is "sub", let new parent
+	// be the result of calling createElement("sub") on the ownerDocument of
+	// node."
+	if (property == "verticalAlign" && newValue == "sub") {
+		newParent = node.ownerDocument.createElement("sub");
+	}
+
+	// "If property is "vertical-align" and new value is "super", let new
+	// parent be the result of calling createElement("sup") on the
+	// ownerDocument of node."
+	if (property == "verticalAlign" && newValue == "super") {
+		newParent = node.ownerDocument.createElement("sup");
+	}
+
 	// "If new parent is null, let new parent be the result of calling
 	// createElement("span") on the ownerDocument of node."
 	if (!newParent) {
@@ -1343,6 +1461,46 @@
 		cssStylingFlag = Boolean(value);
 		break;
 
+		case "subscript":
+		// "Decompose the Range. If the state of the Range for this command is
+		// then true, style each returned Node with property "vertical-align"
+		// and new value "baseline". Otherwise, style them with new value
+		// "baseline", then style them again with new value "sub"."
+		var nodeList = decomposeRange(range);
+		if (getState(commandId, range)) {
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "baseline");
+			}
+		} else {
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "baseline");
+			}
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "sub");
+			}
+		}
+		break;
+
+		case "superscript":
+		// "Decompose the Range. If the state of the Range for this command is
+		// then true, style each returned Node with property "vertical-align"
+		// and new value "baseline". Otherwise, style them with new value
+		// "baseline", then style them again with new value "super"."
+		var nodeList = decomposeRange(range);
+		if (getState(commandId, range)) {
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "baseline");
+			}
+		} else {
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "baseline");
+			}
+			for (var i = 0; i < nodeList.length; i++) {
+				styleNode(nodeList[i], "verticalAlign", "super");
+			}
+		}
+		break;
+
 		case "underline":
 		// "Decompose the Range. If the state of the Range for this command is
 		// then true, style each returned Node with property "text-decoration"
@@ -1384,7 +1542,9 @@
 
 	if (commandId != "bold"
 	&& commandId != "italic"
-	&& commandId != "underline") {
+	&& commandId != "underline"
+	&& commandId != "subscript"
+	&& commandId != "superscript") {
 		return false;
 	}
 
@@ -1435,6 +1595,22 @@
 			if (decoration !== null && decoration !== "underline") {
 				return false;
 			}
+		} else if (commandId == "subscript") {
+			// "True if every Text node that is effectively contained in the
+			// Range has effective style either null or "sub" for
+			// "vertical-align". Otherwise false."
+			var verticalAlign = getEffectiveStyle(node, "verticalAlign");
+			if (verticalAlign !== null && verticalAlign !== "sub") {
+				return false;
+			}
+		} else if (commandId == "superscript") {
+			// "True if every Text node that is effectively contained in the
+			// Range has effective style either null or "super" for
+			// "vertical-align". Otherwise false."
+			var verticalAlign = getEffectiveStyle(node, "verticalAlign");
+			if (verticalAlign !== null && verticalAlign !== "super") {
+				return false;
+			}
 		}
 	}
 
--- a/preprocess	Fri Mar 25 16:08:52 2011 -0600
+++ b/preprocess	Sun Mar 27 17:59:22 2011 -0600
@@ -53,6 +53,8 @@
     'span': '<code data-anolis-spec=html title="the span element">span</code>',
     'strong': '<code data-anolis-spec=html title="the strong element">strong</code>',
     'style': '<code data-anolis-spec=html title="the style attribute">style</code>',
+    'sub': '<code data-anolis-spec=html title="the sub and sup elements">sub</code>',
+    'sup': '<code data-anolis-spec=html title="the sub and sup elements">sup</code>',
     'text': '<code data-anolis-spec=domcore>Text</code>',
     'treeorder': '<span data-anolis-spec=domcore>tree order</span>',
     'u': '<code data-anolis-spec=html title="the u element">u</code>',
--- a/source.html	Fri Mar 25 16:08:52 2011 -0600
+++ b/source.html	Sun Mar 27 17:59:22 2011 -0600
@@ -226,7 +226,7 @@
 
 <p>The <dfn>effective style</dfn> of a [[node]] <var>node</var> for a given
 <var>property</var> is returned by the following algorithm, which will return
-either a CSS value or null:
+either a string or null:
 
 <ol>
   <li>If <var>node</var> is neither an [[element]] nor a [[text]] node, return
@@ -238,14 +238,6 @@
   <li>If <var>node</var> is a [[text]] node, return the <span>effective
   style</span> of its [[parent]] for <var>property</var>.
 
-  <li>If <var>property</var> is "text-decoration", and the "text-decoration"
-  property of <var>node</var> or any of its [[ancestors]] computes to
-  "underline", return "underline".  Otherwise, return "none".
-
-  <p class=XXX>We ignore the possibility of text-decorations other than
-  underline for now, so we pretend that there are only two possible values:
-  "underline" and "none".
-
   <li>If <var>property</var> is "background-color":
 
   <ol>
@@ -260,6 +252,49 @@
     <var>node</var>.
   </ol>
 
+  <li>If <var>property</var> is "text-decoration", and the "text-decoration"
+  property of <var>node</var> or any of its [[ancestors]] computes to
+  "underline", return "underline".  Otherwise, return "none".
+
+  <p class=XXX>We ignore the possibility of text-decorations other than
+  underline for now, so we pretend that there are only two possible values:
+  "underline" and "none".
+
+  <li>If <var>property</var> is "vertical-align":
+
+  <p class=XXX>We massively abuse this property.  Maybe we shouldn't be using
+  the CSS names here.
+
+  <ol>
+    <li>Let <var>affected by subscript</var> and <var>affected by
+    superscript</var> be two boolean variables, both initially false.
+
+    <li>While <var>node</var> is an [[element]] whose "display" property
+    computes to "inline":
+
+    <ol>
+      <li>If <var>node</var>'s "vertical-align" property computes to "sub", set
+      <var>affected by subscript</var> to true.
+
+      <li>Otherwise, if <var>node</var>'s "vertical-align" property computes to
+      "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".
+
+      <li>Set <var>node</var> to its [[parent]].
+    </ol>
+
+    <li>If <var>affected by subscript</var> and <var>affected by
+    superscript</var> are both true, return the string "mixed".
+
+    <li>If <var>affected by subscript</var> is true, return "sub".
+
+    <li>If <var>affected by superscript</var> is true, return "super".
+
+    <li>Return "baseline".
+  </ol>
+
   <li>Return the computed style of <var>property</var> for <var>node</var>.
 </ol>
 
@@ -277,6 +312,23 @@
   non-inline background-colors.  Maybe the name "specified style" is
   misleading, though. -->
 
+  <li>If <var>property</var> is "vertical-align":
+
+  <ol>
+    <li>If the computed value of the [[element]]'s "display" property is
+    neither "inline" nor "inline-block" nor "inline-table", return null.
+
+    <li>If the [[element]] has a [[style]] attribute set, and that attribute
+    has the effect of setting "vertical-align", return the value that it sets
+    "vertical-align" to.
+
+    <li>If the [[element]] is a [[sup]], return "super".
+
+    <li>If the [[element]] is a [[sub]], return "sub".
+
+    <li>Return null.
+  </ol>
+
   <li>If the [[element]] has a <code data-anolis-spec=html
   title="the style attribute">style</code> attribute set, and that attribute has
   the effect of setting <var>property</var>, return the value that it sets
@@ -308,9 +360,9 @@
 </ol>
 
 <p>A <dfn>styling element</dfn> is a [[b]], [[em]], [[i]], [[span]],
-[[strong]], or [[u]] element with no attributes except possibly [[style]], or
-a [[font]] element with no attributes except possibly [[style]], [[fontcolor]],
-[[fontface]], and/or [[fontsize]].
+[[strong]], [[sub]], [[sup]], or [[u]] element with no attributes except
+possibly [[style]], or a [[font]] element with no attributes except possibly
+[[style]], [[fontcolor]], [[fontface]], and/or [[fontsize]].
 
 <p class=note>Conceptually, a <span>styling element</span> is a phrasing
 element whose only purpose is to style text.  Thus changing around styling
@@ -323,13 +375,13 @@
 <p>A <dfn>simple styling element</dfn> is an <span>HTML element</span> for
 which at least one of the following holds:
 
-<ol>
-  <li>It is a [[b]], [[em]], [[font]], [[i]], [[span]], [[strong]], or [[u]]
-  element with no attributes.
+<ul>
+  <li>It is a [[b]], [[em]], [[font]], [[i]], [[span]], [[strong]], [[sub]],
+  [[sup]], or [[u]] element with no attributes.
 
-  <li>It is a [[b]], [[em]], [[font]], [[i]], [[span]], [[strong]], or [[u]]
-  element with exactly one attribute, which is [[style]], which sets no CSS
-  properties (including invalid or unrecognized properties).
+  <li>It is a [[b]], [[em]], [[font]], [[i]], [[span]], [[strong]], [[sub]],
+  [[sup]], or [[u]] element with exactly one attribute, which is [[style]],
+  which sets no CSS properties (including invalid or unrecognized properties).
 
   <li>It is a [[font]] element with exactly one attribute, which is either
   [[fontcolor]], [[fontface]], or [[fontsize]].
@@ -347,10 +399,14 @@
   unrecognized properties), which is "text-decoration", which is set to
   "underline" or "none".
 
+  <li>It is a [[sub]] or [[sub]] element with exactly one attribute, which is
+  [[style]], and the [[style]] attribute sets exactly one CSS property
+  (including invalid or unrecognized properties), which is "vertical-align".
+
   <li>It is a [[font]] or [[span]] element with exactly one attribute, which is
   [[style]], and the [[style]] attribute sets exactly one CSS property
   (including invalid or unrecognized properties).
-</ol>
+</ul>
 
 <p class=note>Conceptually, a <span>simple styling element</span> is a
 <span>styling element</span> which <span title="specified
@@ -833,6 +889,22 @@
     of <var>new parent</var> to <var>new value</var>.
   </ol>
 
+  <!-- We always use sup/sub elements, even in CSS mode, following Gecko and
+  contradicting WebKit.  This is because <span style="vertical-align:
+  sub/super">, the obvious equivalent (and what WebKit uses), behaves quite
+  differently: it doesn't reduce font-size, which is ugly. -->
+  <li>If <var>property</var> is "vertical-align" and <var>new value</var> is
+  "sub", let <var>new parent</var> be the result of calling <code
+  data-anolis-spec=domcore
+  title=dom-Document-createElement>createElement("sub")</code> on the
+  [[ownerdocument]] of <var>node</var>.
+
+  <li>If <var>property</var> is "vertical-align" and <var>new value</var> is
+  "super", let <var>new parent</var> be the result of calling <code
+  data-anolis-spec=domcore
+  title=dom-Document-createElement>createElement("sup")</code> on the
+  [[ownerdocument]] of <var>node</var>.
+
   <li>If <var>new parent</var> is null, let <var>new parent</var> be the result
   of calling <code data-anolis-spec=domcore
   title=dom-Document-createElement>createElement("span")</code> on the
@@ -1390,6 +1462,42 @@
 <dd><strong>Value</strong>:
 
 
+<dt><code title><dfn title=command-subscript>subscript</dfn></code>
+
+<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> "vertical-align" and <var>new
+value</var> "baseline".  Otherwise, <span>style</span> them with <var>new
+value</var> "baseline", then <span>style</span> them again with <var>new
+value</var> "sub".
+
+<p class=XXX>This doesn't work, because we'll have removed some of the things
+that we want to style in some cases.  Need to define what happens to a range
+when you style its nodes, then re-decompose the same range before re-styling.
+
+<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 "sub" for "vertical-align".  Otherwise false.
+
+<dd><strong>Value</strong>:
+
+
+<dt><code title><dfn title=command-superscript>superscript</dfn></code>
+
+<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> "vertical-align" and <var>new
+value</var> "baseline".  Otherwise, <span>style</span> them with <var>new
+value</var> "baseline", then <span>style</span> them again with <var>new
+value</var> "super".
+
+<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 "super" for "vertical-align".  Otherwise false.
+
+<dd><strong>Value</strong>:
+
+
 <dt><code title><dfn title=command-underline>underline</dfn></code>
 
 <dd><strong>Action</strong>: <span>Decompose</span> the [[range]].  If the