update ReSpec to latest version to get RDFa 1.1 support; also add a diff of our local changes
authorRichard Cyganiak <richard@cyganiak.de>
Thu, 31 May 2012 22:42:01 +0100
changeset 422 3c573f88170b
parent 421 520dc48fca50
child 423 dfdecd941c5a
update ReSpec to latest version to get RDFa 1.1 support; also add a diff of our local changes
ReSpec.js/documentation.html
ReSpec.js/js/respec.js
ReSpec.js/js/respec.js.diff
ReSpec.js/js/sh_main.min.js
--- a/ReSpec.js/documentation.html	Thu May 31 22:11:18 2012 +0100
+++ b/ReSpec.js/documentation.html	Thu May 31 22:42:01 2012 +0100
@@ -189,28 +189,7 @@
 The class signals that this will be replaced with a link containing
   the section number and title as follows:
 <pre>&lt;a href="#general-structure" class="sectionRef"&gt;section Section-Number Section-Title&lt;/a&gt;</pre>
-This results in a link such as the following <a href="#general-structure"
-  class="sectionRef" /> for this document, in this example.
 </p>
-<p>Best practices may be shown, numbered and formatted using the
-  following formatting:
-  <pre>
-  &lt;pre class='example'&gt;
-    &lt;div class="practice"&gt;
-      &lt;p&gt;&lt;a name="sample-practice" id="sample-practice"&gt;&lt;/a&gt;
-        &lt;span class="practicelab"&gt;Summary of the practice &lt;/span&gt;&lt;/p&gt;
-      &lt;p class="practicedesc"&gt;
-        More detailed decription of the practice.          
-      &lt;/p&gt;
-    &lt;/div&gt;
-  </pre>
-    <div class="practice">
-      <p><a id="sample-practice"></a>
-        <span class="practicelab">Summary of the practice </span></p>
-      <p class="practicedesc">
-        More detailed decription of the practice.          
-      </p>
-    </div>
     </section>
     <section>
       <h2>Configuration</h2>
@@ -333,6 +312,17 @@
           Recommendation level, set this to the shortname of that
           version. This is
           optional and not usually necessary.
+        <dt>prevRecURI</dt>
+        <dd>An optional URI if the previous recommendation specified by prevRecShortname
+          needs a specific URI as opposed to just the simple shortname
+          in TR space at W3C.</dd>
+        <dt>prevRecHeader</dt>
+        <dd>An optional header if the previous recommendation reference needs a more specific
+          header than the default "Latest recommendation".</dd>
+        <dt>testSuiteURI</dt>
+        <dd>Specifies the optional URI to the test suite for the specification.</dd>
+        <dt>implementationReportURI</dt>
+        <dd>Specifies the optional URI to the implementation report for the specification.  This is normally only used during the Proposed Recommendation phase of publication.</dd>
         <dt>extraCSS</dt>
         <dd>
           This is an array that contains URI references (that may be absolute or relative) to additional
@@ -459,9 +449,11 @@
         </dd>
         <dt>doRDFa</dt>
         <dd>
-          If this parameter is set to true, ReSpec.js will embed various RDFa attributes throughout 
+          If this parameter is set, ReSpec.js will embed various RDFa attributes throughout 
           the generated specification.  The triples generated use vocabulary items from the dcterms, 
-          foaf, and bibo.  The parameter defaults to false.
+          foaf, and bibo.  The parameter defaults to false.  If set to true
+          the system will generate RDFa 1.0 content.  If set to "1.1" it will
+          generate RDFa 1.1 content.
         </dd>
         <dt>noIDLSorting</dt>
         <dd>
@@ -602,7 +594,7 @@
         <code>href</code> is still to be used, but with a <code>class</code> set to "externalDFN".
       </p>
     </section>
-    
+
     <section>
       <h2>References</h2>
       <p>
@@ -657,6 +649,36 @@
     </section>
 
     <section>
+      <h2>Best Practice Documents</h2>
+      <p>
+<p>Best practices may be shown, numbered and formatted using the
+  following formatting:
+  <pre class='example'>
+    &lt;div class="practice"&gt;
+      &lt;p&gt;
+        &lt;span id="sample-practice" class="practicelab"&gt;Title of the practice&lt;/span&gt;&lt;/p&gt;
+      &lt;p class="practicedesc"&gt;
+        More detailed decription of the practice.          
+      &lt;/p&gt;
+    &lt;/div&gt;
+  </pre>
+    <div class="practice">
+      <p>
+        <span id="sample-practice" class="practicelab">Title of the practice</span></p>
+      <p class="practicedesc">
+        More detailed decription of the practice.          
+      </p>
+    </div>
+<p>If a <code>section</code> element with <code>id</code> "bp-summary" is
+  present, then a summary 
+  list of best practices will be placed in it, linked to the best
+  practices that have an id on the <code>span</code> element.</p>
+<pre class="example">
+  &lt;section id='bp-summary'&gt;&lt;/section&gt;
+</pre>
+</section>
+
+    <section>
       <h2>Including other data</h2>
       <p>
         Sometimes a specification will need to incorporate data that is best kept in
@@ -837,6 +859,9 @@
         The <a href='test-spec/webidl.html'>WebIDL testing document</a> provides a number of additional
         examples.
       </p>
+      <div class="note">
+        The <code>data-merge</code> attribute on the interface <code>dl</code> element instructs the preprocessor to merge the dictionary WebIDL definition(s) with the interface WebIDL definition. The value of the <code>data-merge</code> attribute is a whitespace delimited list of dictionary names to be merged with the interface.
+      </div>
     </section>
     
     <section>
@@ -983,6 +1008,14 @@
           <li>2011-01-07 - added same document references (fjh)</li>
           <li>2011-02-15 - added addPatentNote, update sotd language
           for CR to state exit not earlier than (fjh)</li>
+          <li>2011-07-14 - revised and moved best practice material to
+          new section. Updated code to auto check for best
+          practices processing and to generate best practice summary
+          if section with class id bp-summary present. Clean up
+          section ref documentation.  (fjh).</li>
+          <li>2012-05-22 - added additional prevRecShortname handling s
+          authors can specify a different header for the item (via 
+          prevRecHeader) and a different URI (via prevRecURI). (spm).</li>
       </ul>
     </section>
     
--- a/ReSpec.js/js/respec.js	Thu May 31 22:11:18 2012 +0100
+++ b/ReSpec.js/js/respec.js	Thu May 31 22:42:01 2012 +0100
@@ -54,6 +54,14 @@
 function warning (str) {
     sn.element("li", { style: "color: #666" }, _errEl(), str);
 }
+function isArray (obj) {
+    return Object.prototype.toString.call(obj) == '[object Array]'
+}
+function joinAnd (arr) {
+    var last = arr.pop();
+    arr[arr.length - 1] += " and " + last;
+    return arr.join(", ");
+}
 berjon.respec = function () {
     for (var k in this.status2text) {
         if (this.status2long[k]) continue;
@@ -63,6 +71,7 @@
 berjon.respec.prototype = {
     title:          null,
     additionalCopyrightHolders: null,
+    overrideCopyright: null,
     editors:        [],
     authors:        [],
 
@@ -106,6 +115,7 @@
 		"FPWD-NOTE": "WD", 
        	"WD-NOTE":  "WD", 
 		"LC-NOTE":  "LC",
+		"IG-NOTE":  "NOTE",
         "WG-NOTE":  "NOTE"
     },
     
@@ -194,8 +204,18 @@
             this.webIDL();
             this.examples();
 
+            // only process best practices if element with class
+            // practicelab found, do not slow down non best-practice
+            // docs.
+            // doBestPractices must be called before makeTOC, fjh
+            // this might not work with old browsers like IE 8
+
+            var bpnode = document.getElementsByClassName("practicelab");
+            if(bpnode.length > 0) this.doBestPractices(); 
+
             this.informative();
             this.fixHeaders();
+
             this.makeTOC();
             this.idHeaders();
 
@@ -205,8 +225,6 @@
 
             // if (this.doMicroData) this.makeMicroData();
             if (this.doRDFa) this.makeRDFa();
-            if( this.practiceNum) this.doBestPractices(); // do not
-            // slow down those who do not need it , fjh
             this.makeSectionRefs(); // allow references to sections using name for text, fjh
            this.unHTML5();
             this.removeRespec();
@@ -221,7 +239,7 @@
         catch (e) {
             document.body.style.display = "inherit";
             error("Processing error: " + e);
-            window.console && console.log && console.log(e);
+            if (typeof(console) != "undefined" && console.log) console.log(e);
         }
         document.body.style.display = "inherit";
         real_hash = window.location.hash;
@@ -260,7 +278,8 @@
             }
             if (about != '') {
                 secs[i].setAttribute('typeof', 'bibo:Chapter') ;
-                secs[i].setAttribute('about', about) ;
+                secs[i].setAttribute('resource', about) ;
+                secs[i].setAttribute('rel', "bibo:chapter" ) ;
             }
         }
     },
@@ -317,8 +336,13 @@
         }
         if (this.doRDFa) {
             if (prefixAtr != '') prefixAtr += ' ';
-            prefixAtr += "dcterms: http://purl.org/dc/terms/ bibo: http://purl.org/ontology/bibo/ foaf: http://xmlns.com/foaf/0.1/ xsd: http://www.w3.org/2001/XMLSchema#";
+            if (this.doRDFa != "1.1") {
+                prefixAtr += "dcterms: http://purl.org/dc/terms/ bibo: http://purl.org/ontology/bibo/ foaf: http://xmlns.com/foaf/0.1/ xsd: http://www.w3.org/2001/XMLSchema#";
+            } else {
+                prefixAtr += "bibo: http://purl.org/ontology/bibo/";
+            }
             str += " prefix=\"" + this._esc(prefixAtr) + "\"";
+            str += " typeof=\"bibo:Document\"";
         }
 
         str += ">\n";
@@ -335,8 +359,13 @@
         }
         else { 
             if (this.doRDFa) {
-                // use the standard RDFa doctype
-                str += " PUBLIC '-//W3C//DTD XHTML+RDFa 1.0//EN' 'http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd'";
+                if (this.doRDFa == "1.1") {
+                    // use the standard RDFa 1.1 doctype
+                    str += " PUBLIC '-//W3C//DTD XHTML+RDFa 1.1//EN' 'http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd'";
+                } else {
+                    // use the standard RDFa doctype
+                    str += " PUBLIC '-//W3C//DTD XHTML+RDFa 1.0//EN' 'http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd'";
+                }
             } else {
                 str += " PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'";
             }
@@ -346,100 +375,101 @@
         var ats = document.documentElement.attributes;
         var prefixAtr = '' ;
 
-        var hasxmlns = 0 ;
+        var hasxmlns = false;
         for (var i = 0; i < ats.length; i++) {
             var an = ats[i].name;
-            if (an == "lang" ) {
-                continue ;
-            }
-            if (an == "xmlns" ) {
-                hasxmlns = 1;
-            }
+            if (an == "lang") continue;
+            if (an == "xmlns") hasxmlns = true;
             if (an == "prefix") {
                 prefixAtr = ats[i].value;
                 continue;
             }
             str += " " + an + "=\"" + this._esc(ats[i].value) + "\"";
         }
-        if (!hasxmlns) {
-            str += ' xmlns="http://www.w3.org/1999/xhtml"';
-        }
+        if (!hasxmlns) str += ' xmlns="http://www.w3.org/1999/xhtml"';
         if (this.doRDFa) {
-            str += " xmlns:dcterms='http://purl.org/dc/terms/' xmlns:bibo='http://purl.org/ontology/bibo/' xmlns:foaf='http://xmlns.com/foaf/0.1/' xmlns:xsd='http://www.w3.org/2001/XMLSchema#'";
-            if (prefixAtr != '') {
-                var list = prefixAtr.split(/\s+/) ;
-                for (var i = 0; i < list.length; i += 2) {
-                    var n = list[i] ;
-                    n = n.replace(/:$/,'');
-                    str += ' xmlns:'+n+'="' + list[i+1] + '"';
+            if (this.doRDFa != "1.1") {
+                str += " xmlns:dcterms='http://purl.org/dc/terms/' xmlns:bibo='http://purl.org/ontology/bibo/' xmlns:foaf='http://xmlns.com/foaf/0.1/' xmlns:xsd='http://www.w3.org/2001/XMLSchema#'";
+                // there was already some prefix information
+                if (prefixAtr != '') {
+                    var list = prefixAtr.split(/\s+/) ;
+                    for (var i = 0; i < list.length; i += 2) {
+                        var n = list[i] ;
+                        n = n.replace(/:$/,'');
+                        str += ' xmlns:'+n+'="' + list[i+1] + '"';
+                    }
+                }
+                str += ' version="XHTML+RDFa 1.0"';
+            } else {
+                if (prefixAtr != '') {
+                    str += " prefix='" + prefixAtr + " bibo: http://purl.org/ontology/bibo/'" ;
+                } else {
+                    str += " prefix='bibo: http://purl.org/ontology/bibo/'" ;
                 }
             }
         }
-
+        str += " typeof=\"bibo:Document\"";
         str += ">\n";
         // walk the entire DOM tree grabbing nodes and emitting them - possibly modifying them
         // if they need the funny closing tag
         var pRef = this ;
-        var closers = [ "br", "img", "input", "area", "base", "basefont", "col", "isindex", "link", "meta", "param", "hr"] ;
-        var dumpNode = function(node) {
-            var out = '' ;
+        var selfClosing = {};
+        "br img input area base basefont col isindex link meta param hr".split(" ").forEach(function (n) {
+            selfClosing[n] = true;
+        });
+        var noEsc = [false];
+        var dumpNode = function (node) {
+            var out = '';
             // if the node is the document node.. process the children
             if ( node.nodeType == 9 || ( node.nodeType == 1 && node.nodeName.toLowerCase() == 'html' ) ) {
-                var children = node.childNodes;
-                var cLen = children.length ;
-                if (cLen) {
-                    for (var i = 0; i < cLen; i++) {
-                        out += dumpNode(children[i]) ;
-                    }
-                }
-            } else 
-            // if the node is an element, process it
-            if ( node.nodeType == 1 ) {
+                for (var i = 0; i < node.childNodes.length; i++) out += dumpNode(node.childNodes[i]) ;
+            } 
+            // element
+            else if (1 === node.nodeType) {
                 var ename = node.nodeName.toLowerCase() ;
-                var empty = 0 ;
-                for (var i = 0; i < closers.length; i++) {
-                    if (ename == closers[i]) {
-                        empty = 1;
-                    }
-                }
                 out += '<' + ename ;
-                var attrs = node.attributes;
-                var aLen = attrs.length ;
-                if (aLen) {
-                    for (var i = 0; i < aLen; i++) {
-                        out += " " + attrs[i].name + "=\"" + pRef._esc(attrs[i].value) + "\"";
-                    }
+                for (var i = 0; i < node.attributes.length; i++) {
+                    var atn = node.attributes[i]
+                    out += " " + atn.name + "=\"" + pRef._esc(atn.value) + "\"";
                 }
-                if (empty) {
+                if (selfClosing[ename]) {
                     out += ' />';
-                } else {
-                    out += '>' ;
-                    if ( ename == 'pre' ) {
-                        out += "\n" + node.innerHTML;
-                    } else {
-                        var children = node.childNodes;
-                        var cLen = children.length ;
-                        if (cLen) {
-                            for (var i = 0; i < cLen; i++) {
-                                out += dumpNode(children[i]) ;
-                            }
-                        }
-                    }
-                    out += '</' + ename + '>' ;
                 }
-            } else if (node.nodeType == 8 ) {
+                else {
+                    out += '>';
+                    // XXX removing this, as it does not seem correct at all
+                    // if ( ename == 'pre' ) {
+                    //     out += "\n" + node.innerHTML;
+                    // } 
+                    // else {
+                        // console.log("NAME: " + ename);
+                        noEsc.push(ename === "style" || ename === "script");
+                        // console.log(noEsc);
+                        for (var i = 0; i < node.childNodes.length; i++) out += dumpNode(node.childNodes[i]);
+                        noEsc.pop();
+                    // }
+                    out += '</' + ename + '>';
+                }
+            }
+            // comments
+            else if (8 === node.nodeType) {
                 out += "\n<!-- " + node.nodeValue + " -->\n";
-            } else {
-                // otherwise, return the content of the node as a string
-                out += node.nodeValue ;
             }
-            return out ;
+            // text or cdata
+            else if (3 === node.nodeType || 4 === node.nodeType) {
+                // console.log("TEXT: " + noEsc[noEsc.length - 1]);
+                out += noEsc[noEsc.length - 1] ? node.nodeValue : pRef._esc(node.nodeValue);
+            }
+            // we don't handle other types for the time being
+            else {
+                warning("Cannot handle serialising nodes of type: " + node.nodeType);
+            }
+            return out;
         };
         var node = document.documentElement;
         str += dumpNode(document.documentElement) ;
         str += "</html>";
         return str;
-
     },
     
     toDiffHTMLSource:  function () {
@@ -531,11 +561,12 @@
         if (!cfg.alternateFormats) cfg.alternateFormats = [];
         if (cfg.inlineCSS === undefined) cfg.inlineCSS = true;
         if (!cfg.noIDLSorting) cfg.noIDLSorting = false;
-        if (!cfg.noIDLIn) cfg.noIDLIn = false;
+        if (cfg.noIDLIn === undefined) cfg.noIDLIn = true;
+        if (cfg.tocIntroductory === undefined) cfg.tocIntroductory = false;
         if (!cfg.maxTocLevel) cfg.maxTocLevel = 0;
-        if (!cfg.diffTool) cfg.diffTool = 'http://www3.aptest.com/standards/htmldiff/htmldiff.pl';
+        if (!cfg.diffTool) cfg.diffTool = 'http://www5.aptest.com/standards/htmldiff/htmldiff.pl';
         if (!cfg.noRecTrack) cfg.noRecTrack = false;
-        if (!cfg.doRDFa) cfg.doRDFa = false ;
+        if (!cfg.doRDFa) cfg.doRDFa = false;
         for (var k in cfg) this[k] = cfg[k];
         this.isRecTrack = cfg.noRecTrack ? false : this.recTrackStatus.indexOf(this.specStatus) >= 0;
         this.isNoTrack = this.noTrackStatus.indexOf(this.specStatus) >= 0;
@@ -676,6 +707,9 @@
         if ( this.doRDFa ) {
             if ( name == 'Editor' ) {
                 re = " rel='bibo:editor'";
+                if (this.doRDFa == "1.1") {
+                    re += " inlist=''" ;
+                }
                 rn = " property='foaf:name'";
                 rm = " rel='foaf:mbox'";
                 rp = " typeof='foaf:Person'";
@@ -723,6 +757,7 @@
                 }
             }
             if (pers.mailto) {
+                header += ", ";
                 header += " <span class='ed_mailto'><a" + rm + " href='mailto:" + pers.mailto + "'>" + pers.mailto + "</a></span> ";
             }
             if (pers.note) {
@@ -848,8 +883,13 @@
         }
 
         if (this.prevRecShortname) {
-            var prevRecURI = "http://www.w3.org/TR/" + this.prevRecShortname + "/";
-            header += "<dt>Latest recommendation:</dt><dd>" + 
+            var prevRecURI = this.prevRecURI ? this.prevRecURI : "http://www.w3.org/TR/" + this.prevRecShortname + "/";
+            if (this.prevRecHeader) {
+                header += "<dt>" + this.prevRecHeader;
+            } else {
+                header += "<dt>Latest recommendation" ;
+            }
+            header += ":</dt><dd>" + 
                 '<a href="' + prevRecURI + '">' + prevRecURI + "</a></dd>";
         }
 
@@ -898,39 +938,46 @@
         if (this.specStatus == "REC")
             header += '<p>The English version of this specification is the only normative version. Non-normative <a href="http://www.w3.org/Consortium/Translation/">translations</a> may also be available.</p>';
 
-        header += "<p class='copyright'>";
         if (this.specStatus == "unofficial") {
-            if (this.additionalCopyrightHolders) header += this.additionalCopyrightHolders;
-            else header += "This document is licensed under a <a class='subfoot' href='http://creativecommons.org/licenses/by/3.0/' rel='license'>Creative Commons Attribution 3.0 License</a>.";
+            var copyright;
+            if (this.additionalCopyrightHolders) copyright = "<p class='copyright'>" + this.additionalCopyrightHolders + "</p>";
+            else if (this.overrideCopyright) copyright = this.overrideCopyright;
+            else copyright = "<p class='copyright'>This document is licensed under a <a class='subfoot' href='http://creativecommons.org/licenses/by/3.0/' rel='license'>Creative Commons Attribution 3.0 License</a>.</p>";
+            header += copyright;
         }
         else {
-            if (this.doRDFa) {
-            header += 
-                "<a rel='license' href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>Copyright</a> &copy; " ;
-            } else {
-            header += 
-                "<a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>Copyright</a> &copy; " ;
-            }
-            if (this.copyrightStart) {
-                header += this.copyrightStart + '-';
+            if (this.overrideCopyright) {
+                header += this.overrideCopyright;
             }
-            header += this.publishDate.getFullYear();
-            if (this.additionalCopyrightHolders) header += " " + this.additionalCopyrightHolders + " &amp;";
-            if (this.doRDFa) {
-                header += " <span rel='dcterms:publisher'><span typeof='foaf:Organization'><a rel='foaf:homepage' property='foaf:name' content='World Wide Web Consotrium' href='http://www.w3.org/'><acronym title='World Wide Web Consortium'>W3C</acronym></a><sup>&reg;</sup></span></span> ";
-            } else {
-                header += " <a href='http://www.w3.org/'><acronym title='World Wide Web Consortium'>W3C</acronym></a><sup>&reg;</sup> " ;
+            else {
+                header += "<p class='copyright'>";
+                if (this.doRDFa) {
+                    header += "<a rel='license' href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>Copyright</a> &copy; ";
+                }
+                else {
+                    header += "<a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>Copyright</a> &copy; ";
+                }
+                if (this.copyrightStart) {
+                    header += this.copyrightStart + '-';
+                }
+                header += this.publishDate.getFullYear();
+                if (this.additionalCopyrightHolders) header += " " + this.additionalCopyrightHolders + " &amp;";
+                if (this.doRDFa) {
+                    header += " <span rel='dcterms:publisher'><span typeof='foaf:Organization'><a rel='foaf:homepage' property='foaf:name' content='World Wide Web Consortium' href='http://www.w3.org/'><acronym title='World Wide Web Consortium'>W3C</acronym></a><sup>&reg;</sup></span></span> ";
+                } else {
+                    header += " <a href='http://www.w3.org/'><acronym title='World Wide Web Consortium'>W3C</acronym></a><sup>&reg;</sup> ";
+                }
+                header +=
+                    "(<a href='http://www.csail.mit.edu/'><acronym title='Massachusetts Institute of Technology'>MIT</acronym></a>, " +
+                    "<a href='http://www.ercim.eu/'><acronym title='European Research Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, " +
+                    "<a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved. " +
+                    "W3C <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>, " + 
+                    "<a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a> and " +
+                    "<a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document use</a> rules apply.</p>";
+
             }
-            header +=
-                "(<a href='http://www.csail.mit.edu/'><acronym title='Massachusetts Institute of Technology'>MIT</acronym></a>, " +
-                "<a href='http://www.ercim.eu/'><acronym title='European Research Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, " +
-                "<a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved. " +
-                "W3C <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>, " + 
-                "<a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a> and " +
-                "<a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document use</a> rules apply.";
-            
         }
-        header += "</p><hr/></div>";
+        header += "<hr/></div>";
         return header;
     },
     
@@ -938,7 +985,6 @@
         var header;
         if (this.specStatus === "finding" || this.specStatus === "draft-finding") header = this.makeTAGHeaders();
         else header = this.makeNormalHeaders();
-        window.console && console.log && console.log(header);
         var tmp = sn.element("div");
         tmp.innerHTML = header;
         document.body.insertBefore(tmp.firstChild, document.body.firstChild);
@@ -947,6 +993,12 @@
     makeAbstract:    function () {
         var abs = document.getElementById("abstract");
         if (!abs) error("Document must have one element with ID 'abstract'");
+        if (abs.getElementsByTagName("p").length === 0) {
+            // warning("The abstract section should contain a <p> element rather than text directly. Attempting to insert one.");
+            var p = sn.element("p");
+            sn.copyChildren(abs, p);
+            abs.appendChild(p);
+        }
         var h2 = sn.element("h2", {}, null, "Abstract");
         abs.insertBefore(h2, abs.firstChild);
         sn.addClass(abs, "introductory");
@@ -988,8 +1040,18 @@
                 "of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports " +
                 "index</a> at http://www.w3.org/TR/.</em></p>";
             if (custom) sotd += custom.innerHTML;
-            sotd +=
-                "<p>This document was published by the <a href='" + this.wgURI + "'>" + this.wg + "</a> as " + art + this.status2long[this.specStatus] + ".";
+            sotd += "<p>This document was published by the ";
+            if (isArray(this.wg)) {
+                var wgs = [];
+                for (var i = 0, n = this.wg.length; i < n; i++) {
+                    wgs.push("<a href='" + this.wgURI[i] + "'>" + this.wg[i] + "</a>")
+                }
+                sotd += joinAnd(wgs);
+            }
+            else {
+                sotd += "<a href='" + this.wgURI + "'>" + this.wg + "</a>";
+            }
+            sotd += " as " + art + this.status2long[this.specStatus] + ".";
             if (this.isRecTrack && this.specStatus != "REC") sotd += " This document is intended to become a W3C Recommendation.";
             sotd +=
                 " If you wish to make comments regarding this document, please send them to <a href='mailto:" + this.wgPublicList + "@w3.org'>" + 
@@ -1002,27 +1064,48 @@
                                                  this._humanDate(this.crEnd) + ".";
             sotd += " All feedback is welcome.</p>";
             if (this.specStatus != "REC") {
-                sotd += "<p>Publication as a " + this.status2text[this.specStatus] + " does not imply endorsement by the W3C Membership. " +
+                sotd += "<p>Publication as " + art + this.status2text[this.specStatus] + " does not imply endorsement by the W3C Membership. " +
                     "This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate " +
                     "to cite this document as other than work in progress.</p>";
             }
             if (this.specStatus == "LC") 
                 sotd += "<p>This is a Last Call Working Draft and thus the Working Group has determined that this document has satisfied the " +
                         "relevant technical requirements and is sufficiently stable to advance through the Technical Recommendation process.</p>";
-            sotd +=
-                "<p>This document was produced by a group operating under the <a href='http://www.w3.org/Consortium/Patent-Policy-20040205/'>5 February " +
-                "2004 W3C Patent Policy</a>.";
+            if (this.specStatus != "IG-NOTE") {
+                sotd +=
+                    "<p>This document was produced by a group operating under the <a href='http://www.w3.org/Consortium/Patent-Policy-20040205/'>5 February " +
+                    "2004 W3C Patent Policy</a>.";
+            }
 
 			if (!this.isRecTrack && mat == "WD")
 				sotd += " The group does not expect this document to become a W3C Recommendation.";
 			
-			sotd +=
-				" W3C maintains a <a href='" + this.wgPatentURI + "' rel='disclosure'>public list of any patent disclosures</a> " +
-                "made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An " +
-                "individual who has actual knowledge of a patent which the individual believes contains " +
-                "<a href='http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential'>Essential Claim(s)</a> must disclose the " +
-                "information in accordance with <a href='http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure'>section " +
-                "6 of the W3C Patent Policy</a>.</p>";
+            if (this.specStatus != "IG-NOTE") {
+                if (isArray(this.wgPatentURI)) {
+                    sotd += " W3C maintains a public list of any patent disclosures (";
+                    var wgs = [];
+                    for (var i = 0, n = this.wg.length; i < n; i++) {
+                        wgs.push("<a href='" + this.wgPatentURI[i] + "' rel='disclosure'>" + this.wg[i] + "</a>")
+                    }
+                    sotd += wgs.join(", ") + ") ";
+                }
+                else {
+                    sotd += " W3C maintains a <a href='" + this.wgPatentURI + "' rel='disclosure'>public list of any patent disclosures</a> ";
+                }
+    			sotd +=
+                    "made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An " +
+                    "individual who has actual knowledge of a patent which the individual believes contains " +
+                    "<a href='http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential'>Essential Claim(s)</a> must disclose the " +
+                    "information in accordance with <a href='http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure'>section " +
+                    "6 of the W3C Patent Policy</a>.</p>";
+            }
+            else {
+                // XXX
+                if (!this.charterDisclosureURI) error("IG-NOTEs must link to charter's disclosure section using charterDisclosureURI");
+                else {
+                    sotd += "<p>The disclosure obligations of the Participants of this group are described in the <a href='" + this.charterDisclosureURI + "'>charter</a>. </p>";
+                }
+            }
             if (this.addPatentNote) sotd += "<p>" + this.addPatentNote + "</p>";
             sotd += "</section>";
         }
@@ -1102,11 +1185,14 @@
     lastNonAppendix:    0,
     alphabet:   "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
     makeTOCAtLevel:    function (parent, current, level) {
-        var secs = sn.findNodes("./x:section[not(@class='introductory')]|./section[not(@class='introductory')]", parent);
+        var xpath = this.tocIntroductory ? "./x:section|./section" :
+                                           "./x:section[not(@class='introductory')]|./section[not(@class='introductory')]"
+        var secs = sn.findNodes(xpath, parent);
         if (secs.length == 0) return null;
         var ul = sn.element("ul", { "class": "toc" });
         for (var i = 0; i < secs.length; i++) {
-            var sec = secs[i];
+            var sec = secs[i],
+                isIntro = sn.hasClass(sec, "introductory");
             if (!sec.childNodes.length) continue;
             var h = sec.firstElementChild;
             var ln = h.localName.toLowerCase();
@@ -1134,7 +1220,7 @@
                 }
             }
             var id = sn.makeID(sec, null, title);
-            current[current.length-1]++;
+            if (!isIntro) current[current.length-1]++;
             var secnos = current.slice();
             if (sn.hasClass(sec, "appendix") && current.length == 1 && !this.appendixMode) {
                 this.lastNonAppendix = current[0];
@@ -1142,9 +1228,9 @@
             }
             if (this.appendixMode) secnos[0] = this.alphabet.charAt(current[0] - this.lastNonAppendix);
             var secno = secnos.join(".");
-            if (!/\./.test(secno)) secno = secno;
+            if (!/\./.test(secno)) secno = secno + ".";
             var df = sn.documentFragment();
-            sn.element("span", { "class": "secno" }, df, secno + " ");
+            if (!isIntro) sn.element("span", { "class": "secno" }, df, secno + " ");
             // sn.text(" ", df);
             var df2 = df.cloneNode(true);
             h.insertBefore(df, h.firstChild);
@@ -1252,14 +1338,13 @@
                     }
                     // ABBR
                     else if (abbrMap[matched]) {
-                        if (sn.findNodes("ancestor::abbr", txt)) sn.text(matched, df);
+                        if (sn.findNodes("ancestor::abbr", txt).length) sn.text(matched, df);
                         else sn.element("abbr", { title: abbrMap[matched] }, df, matched);
                     }
                     // ACRO
                     else if (acroMap[matched]) {
-                        if (sn.findNodes("ancestor::acronym", txt)) sn.text(matched, df);
+                        if (sn.findNodes("ancestor::acronym", txt).length) sn.text(matched, df);
                         else sn.element("acronym", { title: acroMap[matched] }, df, matched);
-                        // sn.element("acronym", { title: acroMap[matched] }, df, matched);
                     }
                     // FAIL
                     else {
@@ -1366,12 +1451,37 @@
     doBestPractices: function () {
         this.practiceNum = 1;
         var spans = document.querySelectorAll("span.practicelab");
+        var contents = "<h2>Best Practices Summary</h2><ul>"
+        // scan all the best practices to number them and add handle
+        // at same time generate summary section contents if section
+        // is provided in source, using links if possible
+        //
+        // probably not the most efficient here but only used for best
+        // practices document
         for (var i = 0; i < spans.length; i++) {
             var span = spans[i];
             var label = span.innerHTML;
-            span.innerHTML = "Best Practice " + this.practiceNum + ": " +  label;
+            var ref = span.getAttribute("id");
+            var handle = "Best Practice " + this.practiceNum;
+            var content =  ": " + label;
+            var item = handle + content;
+            if(!ref) {
+                contents += "<li>" + handle + content + "</li>";
+            } else {
+                contents += "<li><a href='#" + ref + "'>" + handle +
+                    "</a>" + content + "</li>";
+            }
+            span.innerHTML = item;
             this.practiceNum++;
         }
+        contents += "</ul>";
+
+        var sec = document.getElementById("bp-summary");
+        if(!sec) {
+//             alert("no bp-summary section");
+            return;
+        }
+        sec.innerHTML = contents;
     },
     
     //  <link href="section id" class="sectionRef" />
@@ -1424,7 +1534,7 @@
             var inf = w.definition(idl);
             var df = w.makeMarkup();
             idl.parentNode.replaceChild(df, idl);
-            if (inf.type == "interface" || inf.type == "exception") infNames.push(inf.id);
+            if (inf.type == "interface" || inf.type == "exception" || inf.type == "dictionary" || inf.type == "typedef") infNames.push(inf.id);
         }
         document.normalize();
         var ants = document.querySelectorAll("a:not([href])");
@@ -1581,8 +1691,9 @@
         var def = { children: [] };
         var str = idl.getAttribute("title");
         str = this.parseExtendedAttributes(str, def);
-        if      (str.indexOf("interface") == 0) this.interface(def, str, idl);
+        if      (str.indexOf("interface") == 0 || str.indexOf("partial") === 0) this.interface(def, str, idl);
         else if (str.indexOf("exception") == 0) this.exception(def, str, idl);
+        else if (str.indexOf("dictionary") == 0) this.dictionary(def, str, idl);
         else if (str.indexOf("typedef") == 0)   this.typedef(def, str, idl);
         else if (/\bimplements\b/.test(str))     this.implements(def, str, idl);
         else    error("Expected definition, got: " + str);
@@ -1593,14 +1704,34 @@
     
     interface:  function (inf, str, idl) {
         inf.type = "interface";
-        var match = /^\s*interface\s+([A-Za-z][A-Za-z0-9]*)(?:\s+:\s*([^{]+)\s*)?/.exec(str);
+        var match = /^\s*(partial\s+)?interface\s+([A-Za-z][A-Za-z0-9]*)(?:\s+:\s*([^{]+)\s*)?/.exec(str);
+        if (match) {
+            inf.partial = !!match[1];
+            inf.id = match[2];
+            inf.refId = this._id(inf.id);
+            if (idl.getAttribute('data-merge')) {
+                inf.merge = [];
+                var merge = idl.getAttribute('data-merge').split(' ');
+                for (var i = 0; i < merge.length; i++) inf.merge.push(merge[i]);
+            }
+            if (match[3]) inf.superclasses = match[3].split(/\s*,\s*/);
+        }
+        else {
+            error("Expected interface, got: " + str);
+        }
+        return inf;
+    },
+    
+    dictionary:  function (inf, str, idl) {
+        inf.type = "dictionary";
+        var match = /^\s*dictionary\s+([A-Za-z][A-Za-z0-9]*)(?:\s+:\s*([^{]+)\s*)?/.exec(str);
         if (match) {
             inf.id = match[1];
             inf.refId = this._id(inf.id);
             if (match[2]) inf.superclasses = match[2].split(/\s*,\s*/);
         }
         else {
-            error("Expected interface, got: " + str);
+            error("Expected dictionary, got: " + str);
         }
         return inf;
     },
@@ -1672,6 +1803,9 @@
             if (obj.type == "exception") {
                 mem = this.exceptionMember(dt, dd);
             }
+            else if (obj.type == "dictionary") {
+                mem = this.dictionaryMember(dt, dd);
+            }
             else {
                 mem = this.interfaceMember(dt, dd);
             }
@@ -1731,7 +1865,41 @@
         }
 
         // NOTHING MATCHED
-        error("Expected interface member, got: " + str);
+        error("Expected exception member, got: " + str);
+    },
+    
+    dictionaryMember:    function (dt, dd) {
+        var mem = { children: [] };
+        var str = this._norm(dt.textContent);
+        mem.description = sn.documentFragment();
+        sn.copyChildren(dd, mem.description);
+        str = this.parseExtendedAttributes(str, mem);
+    
+        // MEMBER
+        var match = /^\s*([^=]+\??)\s+([^=\s]+)(?:\s*=\s*(.*))?$/.exec(str);
+        // var match = /^\s*(.*?)\s+(\S+)\s*$/.exec(str);
+        if (match) {
+            mem.type = "member";
+            var type = match[1];
+            mem.id = match[2];
+            mem.refId = this._id(mem.id);
+            mem.defaultValue = match[3];
+            mem.nullable = false;
+            if (/\?$/.test(type)) {
+                type = type.replace(/\?$/, "");
+                mem.nullable = true;
+            }
+            mem.array = false;
+            if (/\[\]$/.test(type)) {
+                type = type.replace(/\[\]$/, "");
+                mem.array = true;
+            }
+            mem.datatype = type;
+            return mem;
+        }
+
+        // NOTHING MATCHED
+        error("Expected dictionary member, got: " + str);
     },
     
     interfaceMember:    function (dt, dd) {
@@ -2058,6 +2226,51 @@
             return df;
         }
 
+        else if (obj.type == "dictionary") {
+            var df = sn.documentFragment();
+            var curLnk = "widl-" + obj.refId + "-";
+            var things = obj.children;
+            if (things.length == 0) return df;
+            if (!this.noIDLSorting) {
+                things.sort(function (a, b) {
+                    if (a.id < b.id) return -1;
+                    if (a.id > b.id) return 1;
+                      return 0;
+                });
+            }
+            
+            var sec = sn.element("section", {}, df);
+            cnt = [sn.text("Dictionary "),
+                   sn.element("a", { "class": "idlType" }, null, obj.id),
+                   sn.text(" Members")];
+            sn.element("h2", {}, sec, cnt);
+            var dl = sn.element("dl", { "class": "dictionary-members" }, sec);
+            for (var j = 0; j < things.length; j++) {
+                var it = things[j];
+                var dt = sn.element("dt", { id: curLnk + it.refId }, dl);
+                sn.element("code", {}, dt, it.id);
+                var desc = sn.element("dd", {}, dl, [it.description]);
+                sn.text(" of type ", dt);
+                if (it.array) sn.text("array of ", dt);
+                var span = sn.element("span", { "class": "idlMemberType" }, dt);
+                var matched = /^sequence<(.+)>$/.exec(it.datatype);
+                if (matched) {
+                    sn.text("sequence<", span);
+                    sn.element("a", {}, span, matched[1]);
+                    sn.text(">", span);
+                }
+                else {
+                    sn.element("a", {}, span, it.datatype);
+                }
+                if (it.nullable) sn.text(", nullable", dt);
+                if (it.defaultValue) {
+                    sn.text(", defaulting to ", dt);
+                    sn.element("code", {}, dt, [sn.text(it.defaultValue)]);
+                }
+            }
+            return df;
+        }
+
         else if (obj.type == "interface") {
             var df = sn.documentFragment();
             var curLnk = "widl-" + obj.refId + "-";
@@ -2117,32 +2330,32 @@
                         else {
                             sn.element("div", {}, desc, [sn.element("em", {}, null, "No parameters.")]);
                         }
-                        if (it.raises.length) {
-                            var table = sn.element("table", { "class": "exceptions" }, desc);
-                            var tr = sn.element("tr", {}, table);
-                            ["Exception", "Description"].forEach(function (tit) { sn.element("th", {}, tr, tit); });
-                            for (var k = 0; k < it.raises.length; k++) {
-                                var exc = it.raises[k];
-                                var tr = sn.element("tr", {}, table);
-                                sn.element("td", { "class": "excName" }, tr, [sn.element("a", {}, null, exc.id)]);
-                                var dtd = sn.element("td", { "class": "excDesc" }, tr);
-                                if (exc.type == "simple") {
-                                    dtd.appendChild(exc.description);
-                                }
-                                else {
-                                    var ctab = sn.element("table", { "class": "exceptionCodes" }, dtd );
-                                    for (var m = 0; m < exc.description.length; m++) {
-                                        var cd = exc.description[m];
-                                        var tr = sn.element("tr", {}, ctab);
-                                        sn.element("td", { "class": "excCodeName" }, tr, [sn.element("code", {}, null, cd.id)]);
-                                        sn.element("td", { "class": "excCodeDesc" }, tr, [cd.description]);
-                                    }
-                                }
-                            }
-                        }
-                        else {
-                            sn.element("div", {}, desc, [sn.element("em", {}, null, "No exceptions.")]);
-                        }
+                        // if (it.raises.length) {
+                        //     var table = sn.element("table", { "class": "exceptions" }, desc);
+                        //     var tr = sn.element("tr", {}, table);
+                        //     ["Exception", "Description"].forEach(function (tit) { sn.element("th", {}, tr, tit); });
+                        //     for (var k = 0; k < it.raises.length; k++) {
+                        //         var exc = it.raises[k];
+                        //         var tr = sn.element("tr", {}, table);
+                        //         sn.element("td", { "class": "excName" }, tr, [sn.element("a", {}, null, exc.id)]);
+                        //         var dtd = sn.element("td", { "class": "excDesc" }, tr);
+                        //         if (exc.type == "simple") {
+                        //             dtd.appendChild(exc.description);
+                        //         }
+                        //         else {
+                        //             var ctab = sn.element("table", { "class": "exceptionCodes" }, dtd );
+                        //             for (var m = 0; m < exc.description.length; m++) {
+                        //                 var cd = exc.description[m];
+                        //                 var tr = sn.element("tr", {}, ctab);
+                        //                 sn.element("td", { "class": "excCodeName" }, tr, [sn.element("code", {}, null, cd.id)]);
+                        //                 sn.element("td", { "class": "excCodeDesc" }, tr, [cd.description]);
+                        //             }
+                        //         }
+                        //     }
+                        // }
+                        // else {
+                        //     sn.element("div", {}, desc, [sn.element("em", {}, null, "No exceptions.")]);
+                        // }
                         var reDiv = sn.element("div", {}, desc);
                         sn.element("em", {}, reDiv, "Return type: ");
                         var matched = /^sequence<(.+)>$/.exec(it.datatype);
@@ -2174,36 +2387,36 @@
                         if (it.readonly) sn.text(", readonly", dt);
                         if (it.nullable) sn.text(", nullable", dt);
                         
-                        if (it.raises.length) {
-                            var table = sn.element("table", { "class": "exceptions" }, desc);
-                            var tr = sn.element("tr", {}, table);
-                            ["Exception", "On Get", "On Set", "Description"].forEach(function (tit) { sn.element("th", {}, tr, tit); });
-                            for (var k = 0; k < it.raises.length; k++) {
-                                var exc = it.raises[k];
-                                var tr = sn.element("tr", {}, table);
-                                sn.element("td", { "class": "excName" }, tr, [sn.element("a", {}, null, exc.id)]);
-                                ["onGet", "onSet"].forEach(function (gs) {
-                                    if (exc[gs]) sn.element("td", { "class": "excGetSetTrue" }, tr, "\u2714");
-                                    else         sn.element("td", { "class": "excGetSetFalse" }, tr, "\u2718");
-                                });
-                                var dtd = sn.element("td", { "class": "excDesc" }, tr);
-                                if (exc.type == "simple") {
-                                    dtd.appendChild(exc.description);
-                                }
-                                else {
-                                    var ctab = sn.element("table", { "class": "exceptionCodes" }, dtd );
-                                    for (var m = 0; m < exc.description.length; m++) {
-                                        var cd = exc.description[m];
-                                        var tr = sn.element("tr", {}, ctab);
-                                        sn.element("td", { "class": "excCodeName" }, tr, [sn.element("code", {}, null, cd.id)]);
-                                        sn.element("td", { "class": "excCodeDesc" }, tr, [cd.description]);
-                                    }
-                                }
-                            }
-                        }
-                        else {
-                            sn.element("div", {}, desc, [sn.element("em", {}, null, "No exceptions.")]);
-                        }
+                        // if (it.raises.length) {
+                        //     var table = sn.element("table", { "class": "exceptions" }, desc);
+                        //     var tr = sn.element("tr", {}, table);
+                        //     ["Exception", "On Get", "On Set", "Description"].forEach(function (tit) { sn.element("th", {}, tr, tit); });
+                        //     for (var k = 0; k < it.raises.length; k++) {
+                        //         var exc = it.raises[k];
+                        //         var tr = sn.element("tr", {}, table);
+                        //         sn.element("td", { "class": "excName" }, tr, [sn.element("a", {}, null, exc.id)]);
+                        //         ["onGet", "onSet"].forEach(function (gs) {
+                        //             if (exc[gs]) sn.element("td", { "class": "excGetSetTrue" }, tr, "\u2714");
+                        //             else         sn.element("td", { "class": "excGetSetFalse" }, tr, "\u2718");
+                        //         });
+                        //         var dtd = sn.element("td", { "class": "excDesc" }, tr);
+                        //         if (exc.type == "simple") {
+                        //             dtd.appendChild(exc.description);
+                        //         }
+                        //         else {
+                        //             var ctab = sn.element("table", { "class": "exceptionCodes" }, dtd );
+                        //             for (var m = 0; m < exc.description.length; m++) {
+                        //                 var cd = exc.description[m];
+                        //                 var tr = sn.element("tr", {}, ctab);
+                        //                 sn.element("td", { "class": "excCodeName" }, tr, [sn.element("code", {}, null, cd.id)]);
+                        //                 sn.element("td", { "class": "excCodeDesc" }, tr, [cd.description]);
+                        //             }
+                        //         }
+                        //     }
+                        // }
+                        // else {
+                        //     sn.element("div", {}, desc, [sn.element("em", {}, null, "No exceptions.")]);
+                        // }
                     }
                     else if (type == "constant") {
                         sn.text(" of type ", dt);
@@ -2212,6 +2425,18 @@
                     }
                 }
             }
+            if (typeof obj.merge !== "undefined" && obj.merge.length > 0) {
+                // hackish: delay the execution until the DOM has been initialized, then merge
+                setTimeout(function () {
+                    for (var i = 0; i < obj.merge.length; i++) {
+                        var idlInterface = document.querySelector("#idl-def-" + obj.refId),
+                            idlDictionary = document.querySelector("#idl-def-" + obj.merge[i]);
+                        idlDictionary.parentNode.parentNode.removeChild(idlDictionary.parentNode);
+                        idlInterface.appendChild(document.createElement("br"));
+                        idlInterface.appendChild(idlDictionary);
+                    }
+                }, 0);
+            }
             return df;
         }
     },
@@ -2257,7 +2482,9 @@
         else if (obj.type == "interface") {
             var str = "<span class='idlInterface' id='idl-def-" + obj.refId + "'>";
             if (obj.extendedAttributes) str += this._idn(indent) + "[<span class='extAttr'>" + obj.extendedAttributes + "</span>]\n";
-            str += this._idn(indent) + "interface <span class='idlInterfaceID'>" + obj.id + "</span>";
+            str += this._idn(indent);
+            if (obj.partial) str += "partial ";
+            str += "interface <span class='idlInterfaceID'>" + obj.id + "</span>";
             if (obj.superclasses && obj.superclasses.length) str += " : " +
                                                 obj.superclasses.map(function (it) {
                                                                         return "<span class='idlSuperclass'><a>" + it + "</a></span>"
@@ -2306,6 +2533,31 @@
             str += this._idn(indent) + "};</span>\n";
             return str;
         }
+        else if (obj.type == "dictionary") {
+            var str = "<span class='idlDictionary' id='idl-def-" + obj.refId + "'>";
+            if (obj.extendedAttributes) str += this._idn(indent) + "[<span class='extAttr'>" + obj.extendedAttributes + "</span>]\n";
+            str += this._idn(indent) + "dictionary <span class='idlDictionaryID'>" + obj.id + "</span>";
+            if (obj.superclasses && obj.superclasses.length) str += " : " +
+                                                obj.superclasses.map(function (it) {
+                                                                        return "<span class='idlSuperclass'><a>" + it + "</a></span>"
+                                                                    })
+                                                                .join(", ");
+            str += " {\n";
+            var max = 0;
+            obj.children.forEach(function (it, idx) {
+                var len = it.datatype.length;
+                if (it.nullable) len = len + 1;
+                if (it.array) len = len + 2;
+                max = (len > max) ? len : max;
+            });
+            var curLnk = "widl-" + obj.refId + "-";
+            for (var i = 0; i < obj.children.length; i++) {
+                var ch = obj.children[i];
+                str += this.writeMember(ch, max, indent + 1, curLnk);
+            }
+            str += this._idn(indent) + "};</span>\n";
+            return str;
+        }
     },
     
     writeField:    function (attr, max, indent, curLnk) {
@@ -2350,16 +2602,16 @@
         str += "<span class='idlAttrType'>" + this.writeDatatype(attr.datatype) + arr + nullable + "</span> ";
         for (var i = 0; i < pad; i++) str += " ";
         str += "<span class='idlAttrName'><a href='#" + curLnk + attr.refId + "'>" + attr.id + "</a></span>";
-        if (gets.length) {
-            str += " getraises (" +
-                   gets.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; }).join(", ") +
-                   ")";
-        }
-        if (sets.length) {
-            str += " setraises (" +
-                   sets.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; }).join(", ") +
-                   ")";
-        }
+        // if (gets.length) {
+        //     str += " getraises (" +
+        //            gets.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; }).join(", ") +
+        //            ")";
+        // }
+        // if (sets.length) {
+        //     str += " setraises (" +
+        //            sets.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; }).join(", ") +
+        //            ")";
+        // }
         str += ";</span>\n";
         return str;
     },
@@ -2393,12 +2645,12 @@
                                 })
                           .join(", ");
         str += ")";
-        if (meth.raises.length) {
-            str += " raises ("
-            str += meth.raises.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; })
-                              .join(", ");
-            str += ")";
-        }
+        // if (meth.raises.length) {
+        //     str += " raises ("
+        //     str += meth.raises.map(function (it) { return "<span class='idlRaises'><a>" + it.id + "</a></span>"; })
+        //                       .join(", ");
+        //     str += ")";
+        // }
         str += ";</span>\n";
         return str;
     },
@@ -2417,9 +2669,27 @@
         return str;
     },
 
+    writeMember:    function (memb, max, indent, curLnk) {
+        var str = "<span class='idlMember'>";
+        str += this._idn(indent);
+        var pad = max - memb.datatype.length;
+        if (memb.nullable) pad = pad - 1;
+        var nullable = memb.nullable ? "?" : "";
+        str += "<span class='idlMemberType'>" + this.writeDatatype(memb.datatype) + nullable + "</span> ";
+        for (var i = 0; i < pad; i++) str += " ";
+        str += "<span class='idlMemberName'><a href='#" + curLnk + memb.refId + "'>" + memb.id + "</a></span>";
+        if (memb.defaultValue) str += " = <span class='idlMemberValue'>" + memb.defaultValue + "</span>"
+        str += ";</span>\n";
+        return str;
+    },
+
     writeDatatype:    function (dt) {
+        // if (/sequence/.test(dt) || /dict/.test(dt)) {
+            console.log(dt);
+        // }
         var matched = /^sequence<(.+)>$/.exec(dt);
         if (matched) {
+            console.log("MATCHED!", matched[1])
             return "sequence&lt;<a>" + matched[1] + "</a>&gt;";
         }
         else {
@@ -2456,3 +2726,105 @@
     alert("DUMP\n" + str);
 }
 })();
+
+// ReSpec XPath substitute JS workaround for UA's without DOM L3 XPath support
+// By Travis Leithead (travil AT microsoft dotcom)
+// (select APIs and behaviors specifically for ReSpec's usage of DOM L3 XPath; no more an no less)
+// For IE, requires v.9+
+(function () {
+    if (!document.evaluate) {
+        //////////////////////////////////////
+        // interface XPathResult
+        //////////////////////////////////////
+        // Augments a generic JS Array to appear to be an XPathResult (thus allowing [] notation to work)
+        window.XPathResult = function (list) {
+            list.snapshotLength = list.length;
+            list.snapshotItem = function (index) { return this[index]; };
+            return list;
+        }
+        window.XPathResult.prototype.ORDERED_NODE_SNAPSHOT_TYPE = 7;
+        window.XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7;
+
+        //////////////////////////////////////
+        // interface XPathEvaluator
+        //////////////////////////////////////
+        // Not exposed to the window (not needed)
+        function XPathEvaluator(assignee) {
+            var findElementsContainingContextNode = function (element, contextNode) {
+                var allUpList = document.querySelectorAll(element);
+                var resultSet = [];
+                for (var i = 0, len = allUpList.length; i < len; i++) {
+                    if (allUpList[i].compareDocumentPosition(contextNode) & 16)
+                        resultSet.push(allUpList[i]);
+                }
+                return resultSet;
+            }
+            var allTextCache = null;
+            var buildTextCacheUnderBody = function () {
+                if (allTextCache == null) {
+                    var iter = document.createNodeIterator(document.body, 4, function () { return 1; }, false);
+                    allTextCache = [];
+                    while (n = iter.nextNode()) {
+                        allTextCache.push(n);
+                    }
+                }
+                // Note: no cache invalidation for dynamic updates...
+            }
+            var getAllTextNodesUnderContext = function (contextNode) {
+                buildTextCacheUnderBody();
+                var candidates = [];
+                for (var i = 0, len = allTextCache.length; i < len; i++) {
+                    if (allTextCache[i].compareDocumentPosition(contextNode) & 8)
+                        candidates.push(allTextCache[i]);
+                }
+                return candidates;
+            }
+            var findAncestorsOfContextNode = function (element, contextNode) {
+                var allUpList = document.querySelectorAll(element);
+                var candidates = [];
+                for (var i = 0, len = allUpList.length; i < len; i++) {
+                    if (allUpList[i].compareDocumentPosition(contextNode) & 16)
+                        candidates.push(allUpList[i]);
+                }
+                return candidates;
+            }
+            var findSpecificChildrenOfContextNode = function (contextNode, selector) { // element.querySelectorAll(":scope > "+elementType)
+                var allUpList = contextNode.querySelectorAll(selector);
+                // Limit to children only...
+                var candidates = [];
+                for (var i = 0, len = allUpList.length; i < len; i++) {
+                    if (allUpList[i].parentNode == contextNode)
+                        candidates.push(allUpList[i]);
+                }
+                return candidates;
+            }
+            assignee.evaluate = function (xPathExpression, contextNode, resolverCallback, type, result) {
+                // "ancestor::x:section|ancestor::section", sec
+                if (xPathExpression == "ancestor::x:section|ancestor::section") // e.g., "section :scope" (but matching section)
+                    return XPathResult(findElementsContainingContextNode("section", contextNode));
+                else if (xPathExpression == "./x:section|./section") // e.g., ":scope > section"
+                    return XPathResult(findSpecificChildrenOfContextNode(contextNode, "section"));
+                else if (xPathExpression == "./x:section[not(@class='introductory')]|./section[not(@class='introductory')]") // e.g., ":scope > section:not([class='introductory'])"
+                    return XPathResult(findSpecificChildrenOfContextNode(contextNode, "section:not([class='introductory'])"));
+                else if (xPathExpression == ".//text()") // Not possible via Selectors API. Note that ":contains("...") can be used to find particular element containers of text
+                    return XPathResult(getAllTextNodesUnderContext(contextNode));
+                else if ((xPathExpression == "ancestor::abbr") || (xPathExpression == "ancestor::acronym")) // e.g., "abbr :scope, acronym :scope" (but match the element, not the scope)
+                    return XPathResult(findAncestorsOfContextNode((xPathExpression == "ancestor::abbr") ? "abbr" : "acronym", contextNode));
+                else if (xPathExpression == "./dt") // e.g., ":scope > dt"
+                    return XPathResult(findSpecificChildrenOfContextNode(contextNode, "dt"));
+                else if (xPathExpression == "dl[@class='parameters']")
+                    return XPathResult(contextNode.querySelectorAll("dl[class='parameters']"));
+                else if (xPathExpression == "*[@class='exception']")
+                    return XPathResult(contextNode.querySelectorAll("[class='exception']"));
+                else // Anything else (not supported)
+                    return XPathResult([]);
+            };
+        }
+        // Document implements XPathExpression
+        if (window.Document) {
+            XPathEvaluator(Document.prototype);
+        }
+        else // no prototype hierarchy support (or Document doesn't exist)
+            XPathEvaluator(window.document);
+    }
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ReSpec.js/js/respec.js.diff	Thu May 31 22:42:01 2012 +0100
@@ -0,0 +1,24 @@
+244a245,247
+>         real_hash = window.location.hash;
+>         window.location.hash = "#";
+>         window.location.hash = real_hash;
+761c764
+<                 header += " ( " + pers.note + " )";
+---
+>                 header += " (" + pers.note + ")";
+898a902,907
+>         if (this.otherContributors) {
+>             for (var role in this.otherContributors) {
+>                 if (!this.otherContributors.hasOwnProperty(role)) continue;
+>                 header += this.showPeople(role, this.otherContributors[role]);
+>             }
+>         }
+1363a1373,1376
+>         var tmp = document.getElementById("references");
+>         if (tmp) {
+>             tmp.parentNode.removeChild(tmp);
+>         }
+1369a1383,1385
+>         if (tmp) {
+>             sn.copyChildren(tmp, refsec);
+>         }
--- a/ReSpec.js/js/sh_main.min.js	Thu May 31 22:11:18 2012 +0100
+++ b/ReSpec.js/js/sh_main.min.js	Thu May 31 22:42:01 2012 +0100
@@ -1,4 +1,4 @@
 /* Copyright (C) 2007, 2008 [email protected] */
 /* License: http://shjs.sourceforge.net/doc/gplv3.html */
 
-if(!this.sh_languages){this.sh_languages={}}var sh_requests={};function sh_isEmailAddress(a){if(/^mailto:/.test(a)){return false}return a.indexOf("@")!==-1}function sh_setHref(b,c,d){var a=d.substring(b[c-2].pos,b[c-1].pos);if(a.length>=2&&a.charAt(0)==="<"&&a.charAt(a.length-1)===">"){a=a.substr(1,a.length-2)}if(sh_isEmailAddress(a)){a="mailto:"+a}b[c-2].node.href=a}function sh_konquerorExec(b){var a=[""];a.index=b.length;a.input=b;return a}function sh_highlightString(B,o){if(/Konqueror/.test(navigator.userAgent)){if(!o.konquered){for(var F=0;F<o.length;F++){for(var H=0;H<o[F].length;H++){var G=o[F][H][0];if(G.source==="$"){G.exec=sh_konquerorExec}}}o.konquered=true}}var N=document.createElement("a");var q=document.createElement("span");var A=[];var j=0;var n=[];var C=0;var k=null;var x=function(i,a){var p=i.length;if(p===0){return}if(!a){var Q=n.length;if(Q!==0){var r=n[Q-1];if(!r[3]){a=r[1]}}}if(k!==a){if(k){A[j++]={pos:C};if(false && k==="sh_url"){sh_setHref(A,j,B)}}if(a){var P;if(false && a==="sh_url"){P=N.cloneNode(false)}else{P=q.cloneNode(false)}P.className=a;A[j++]={node:P,pos:C}}}C+=p;k=a};var t=/\r\n|\r|\n/g;t.lastIndex=0;var d=B.length;while(C<d){var v=C;var l;var w;var h=t.exec(B);if(h===null){l=d;w=d}else{l=h.index;w=t.lastIndex}var g=B.substring(v,l);var M=[];for(;;){var I=C-v;var D;var y=n.length;if(y===0){D=0}else{D=n[y-1][2]}var O=o[D];var z=O.length;var m=M[D];if(!m){m=M[D]=[]}var E=null;var u=-1;for(var K=0;K<z;K++){var f;if(K<m.length&&(m[K]===null||I<=m[K].index)){f=m[K]}else{var c=O[K][0];c.lastIndex=I;f=c.exec(g);m[K]=f}if(f!==null&&(E===null||f.index<E.index)){E=f;u=K;if(f.index===I){break}}}if(E===null){x(g.substring(I),null);break}else{if(E.index>I){x(g.substring(I,E.index),null)}var e=O[u];var J=e[1];var b;if(J instanceof Array){for(var L=0;L<J.length;L++){b=E[L+1];x(b,J[L])}}else{b=E[0];x(b,J)}switch(e[2]){case -1:break;case -2:n.pop();break;case -3:n.length=0;break;default:n.push(e);break}}}if(k){A[j++]={pos:C};if(false && k==="sh_url"){sh_setHref(A,j,B)}k=null}C=w}return A}function sh_getClasses(d){var a=[];var b=d.className;if(b&&b.length>0){var e=b.split(" ");for(var c=0;c<e.length;c++){if(e[c].length>0){a.push(e[c])}}}return a}function sh_addClass(c,a){var d=sh_getClasses(c);for(var b=0;b<d.length;b++){if(a.toLowerCase()===d[b].toLowerCase()){return}}d.push(a);c.className=d.join(" ")}function sh_extractTagsFromNodeList(c,a){var f=c.length;for(var d=0;d<f;d++){var e=c.item(d);switch(e.nodeType){case 1:if(e.nodeName.toLowerCase()==="br"){var b;if(/MSIE/.test(navigator.userAgent)){b="\r"}else{b="\n"}a.text.push(b);a.pos++}else{a.tags.push({node:e.cloneNode(false),pos:a.pos});sh_extractTagsFromNodeList(e.childNodes,a);a.tags.push({pos:a.pos})}break;case 3:case 4:a.text.push(e.data);a.pos+=e.length;break}}}function sh_extractTags(c,b){var a={};a.text=[];a.tags=b;a.pos=0;sh_extractTagsFromNodeList(c.childNodes,a);return a.text.join("")}function sh_mergeTags(d,f){var a=d.length;if(a===0){return f}var c=f.length;if(c===0){return d}var i=[];var e=0;var b=0;while(e<a&&b<c){var h=d[e];var g=f[b];if(h.pos<=g.pos){i.push(h);e++}else{i.push(g);if(f[b+1].pos<=h.pos){b++;i.push(f[b]);b++}else{i.push({pos:h.pos});f[b]={node:g.node.cloneNode(false),pos:h.pos}}}}while(e<a){i.push(d[e]);e++}while(b<c){i.push(f[b]);b++}return i}function sh_insertTags(k,h){var g=document;var l=document.createDocumentFragment();var e=0;var d=k.length;var b=0;var j=h.length;var c=l;while(b<j||e<d){var i;var a;if(e<d){i=k[e];a=i.pos}else{a=j}if(a<=b){if(i.node){var f=i.node;c.appendChild(f);c=f}else{c=c.parentNode}e++}else{c.appendChild(g.createTextNode(h.substring(b,a)));b=a}}return l}function sh_highlightElement(d,g){sh_addClass(d,"sh_sourceCode");var c=[];var e=sh_extractTags(d,c);var f=sh_highlightString(e,g);var b=sh_mergeTags(c,f);var a=sh_insertTags(b,e);while(d.hasChildNodes()){d.removeChild(d.firstChild)}d.appendChild(a)}function sh_getXMLHttpRequest(){if(window.ActiveXObject){return new ActiveXObject("Msxml2.XMLHTTP")}else{if(window.XMLHttpRequest){return new XMLHttpRequest()}}throw"No XMLHttpRequest implementation available"}function sh_load(language,element,prefix,suffix){if(language in sh_requests){sh_requests[language].push(element);return}sh_requests[language]=[element];var request=sh_getXMLHttpRequest();var url=prefix+"sh_"+language+suffix;request.open("GET",url,true);request.onreadystatechange=function(){if(request.readyState===4){try{if(!request.status||request.status===200){eval(request.responseText);var elements=sh_requests[language];for(var i=0;i<elements.length;i++){sh_highlightElement(elements[i],sh_languages[language])}}else{throw"HTTP error: status "+request.status}}finally{request=null}}};request.send(null)}function sh_highlightDocument(g,k){var b=document.getElementsByTagName("pre");for(var e=0;e<b.length;e++){var f=b.item(e);var a=sh_getClasses(f);for(var c=0;c<a.length;c++){var h=a[c].toLowerCase();if(h==="sh_sourcecode"){continue}if(h.substr(0,3)==="sh_"){var d=h.substring(3);if(d in sh_languages){sh_highlightElement(f,sh_languages[d])}else{if(typeof(g)==="string"&&typeof(k)==="string"){sh_load(d,f,g,k)}else{throw'Found <pre> element with class="'+h+'", but no such language exists'}}break}}}};
\ No newline at end of file
+if(!this.sh_languages){this.sh_languages={}}var sh_requests={};function sh_isEmailAddress(a){if(/^mailto:/.test(a)){return false}return a.indexOf("@")!==-1}function sh_setHref(b,c,d){var a=d.substring(b[c-2].pos,b[c-1].pos);if(a.length>=2&&a.charAt(0)==="<"&&a.charAt(a.length-1)===">"){a=a.substr(1,a.length-2)}if(sh_isEmailAddress(a)){a="mailto:"+a}b[c-2].node.href=a}function sh_konquerorExec(b){var a=[""];a.index=b.length;a.input=b;return a}function sh_highlightString(B,o){if(/Konqueror/.test(navigator.userAgent)){if(!o.konquered){for(var F=0;F<o.length;F++){for(var H=0;H<o[F].length;H++){var G=o[F][H][0];if(G.source==="$"){G.exec=sh_konquerorExec}}}o.konquered=true}}var N=document.createElement("a");var q=document.createElement("span");var A=[];var j=0;var n=[];var C=0;var k=null;var x=function(i,a){var p=i.length;if(p===0){return}if(!a){var Q=n.length;if(Q!==0){var r=n[Q-1];if(!r[3]){a=r[1]}}}if(k!==a){if(k){A[j++]={pos:C};if(false && k==="sh_url"){sh_setHref(A,j,B)}}if(a){var P;if(false && a==="sh_url"){P=N.cloneNode(false)}else{P=q.cloneNode(false)}P.className=a;A[j++]={node:P,pos:C}}}C+=p;k=a};var t=/\r\n|\r|\n/g;t.lastIndex=0;var d=B.length;while(C<d){var v=C;var l;var w;var h=t.exec(B);if(h===null){l=d;w=d}else{l=h.index;w=t.lastIndex}var g=B.substring(v,l);var M=[];for(;;){var I=C-v;var D;var y=n.length;if(y===0){D=0}else{D=n[y-1][2]}var O=o[D];var z=O.length;var m=M[D];if(!m){m=M[D]=[]}var E=null;var u=-1;for(var K=0;K<z;K++){var f;if(K<m.length&&(m[K]===null||I<=m[K].index)){f=m[K]}else{var c=O[K][0];c.lastIndex=I;f=c.exec(g);m[K]=f}if(f!==null&&(E===null||f.index<E.index)){E=f;u=K;if(f.index===I){break}}}if(E===null){x(g.substring(I),null);break}else{if(E.index>I){x(g.substring(I,E.index),null)}var e=O[u];var J=e[1];var b;if(J instanceof Array){for(var L=0;L<J.length;L++){b=E[L+1];x(b,J[L])}}else{b=E[0];x(b,J)}switch(e[2]){case -1:break;case -2:n.pop();break;case -3:n.length=0;break;default:n.push(e);break}}}if(k){A[j++]={pos:C};if(false && k==="sh_url"){sh_setHref(A,j,B)}k=null}C=w}return A}function sh_getClasses(d){var a=[];var b=d.className;if(b&&b.length>0){var e=b.split(" ");for(var c=0;c<e.length;c++){if(e[c].length>0){a.push(e[c])}}}return a}function sh_addClass(c,a){var d=sh_getClasses(c);for(var b=0;b<d.length;b++){if(a.toLowerCase()===d[b].toLowerCase()){return}}d.push(a);c.className=d.join(" ")}function sh_extractTagsFromNodeList(c,a){var f=c.length;for(var d=0;d<f;d++){var e=c.item(d);switch(e.nodeType){case 1:if(e.nodeName.toLowerCase()==="br"){var b;if(/MSIE/.test(navigator.userAgent)){b="\r"}else{b="\n"}a.text.push(b);a.pos++}else{a.tags.push({node:e.cloneNode(false),pos:a.pos});sh_extractTagsFromNodeList(e.childNodes,a);a.tags.push({pos:a.pos})}break;case 3:case 4:a.text.push(e.data);a.pos+=e.length;break}}}function sh_extractTags(c,b){var a={};a.text=[];a.tags=b;a.pos=0;sh_extractTagsFromNodeList(c.childNodes,a);return a.text.join("")}function sh_mergeTags(d,f){var a=d.length;if(a===0){return f}var c=f.length;if(c===0){return d}var i=[];var e=0;var b=0;while(e<a&&b<c){var h=d[e];var g=f[b];if(h.pos<=g.pos){i.push(h);e++}else{i.push(g);if(f[b+1].pos<=h.pos){b++;i.push(f[b]);b++}else{i.push({pos:h.pos});f[b]={node:g.node.cloneNode(false),pos:h.pos}}}}while(e<a){i.push(d[e]);e++}while(b<c){i.push(f[b]);b++}return i}function sh_insertTags(k,h){var g=document;var l=document.createDocumentFragment();var e=0;var d=k.length;var b=0;var j=h.length;var c=l;while(b<j||e<d){var i;var a;if(e<d){i=k[e];a=i.pos}else{a=j}if(a<=b){if(i.node){var f=i.node;c.appendChild(f);c=f}else{c=c.parentNode}e++}else{c.appendChild(g.createTextNode(h.substring(b,a)));b=a}}return l}function sh_highlightElement(d,g){sh_addClass(d,"sh_sourceCode");var c=[];var e=sh_extractTags(d,c);var f=sh_highlightString(e,g);var b=sh_mergeTags(c,f);var a=sh_insertTags(b,e);while(d.hasChildNodes()){d.removeChild(d.firstChild)}d.appendChild(a)}function sh_getXMLHttpRequest(){if(window.XMLHttpRequest){return new XMLHttpRequest()}else{if(window.ActiveXObject){return new ActiveXObject("Msxml2.XMLHTTP")}}throw"No XMLHttpRequest implementation available"}function sh_load(language,element,prefix,suffix){if(language in sh_requests){sh_requests[language].push(element);return}sh_requests[language]=[element];var request=sh_getXMLHttpRequest();var url=prefix+"sh_"+language+suffix;request.open("GET",url,true);request.onreadystatechange=function(){if(request.readyState===4){try{if(!request.status||request.status===200){eval(request.responseText);var elements=sh_requests[language];for(var i=0;i<elements.length;i++){sh_highlightElement(elements[i],sh_languages[language])}}else{throw"HTTP error: status "+request.status}}finally{request=null}}};request.send(null)}function sh_highlightDocument(g,k){var b=document.getElementsByTagName("pre");for(var e=0;e<b.length;e++){var f=b.item(e);var a=sh_getClasses(f);for(var c=0;c<a.length;c++){var h=a[c].toLowerCase();if(h==="sh_sourcecode"){continue}if(h.substr(0,3)==="sh_"){var d=h.substring(3);if(d in sh_languages){sh_highlightElement(f,sh_languages[d])}else{if(typeof(g)==="string"&&typeof(k)==="string"){sh_load(d,f,g,k)}else{throw'Found <pre> element with class="'+h+'", but no such language exists'}}break}}}};
\ No newline at end of file