This is the documentation for ReSpec.js, a tool that helps with specification editing primarily within a W3C context.

This paragraph is here to demonstrate that it is possible to add a completely custom piece of HTML inside the SotD.

Introduction

ReSpec is a Javascript [[ECMA-262]] based tool that unobtrusively allows editors to write a specification focusing on the actual features and correctness, while needing to pay as little attention as possible to issues pertaining to styling, referential integrity, and the friendly dragon to slay that are the W3C Publication Rules.

There are many good existing tools that can be used to produce W3C specifications. A non-exhaustive list includes:

But I was dissatisfied with all of them, including the one I wrote. The primary reason for that was that they all require one to run a tool in between editing and reloading the browser — an extra step that at the end of a long day's work editing is one step too many. Beyond that there are some smaller issues that I personally have with each, but it is largely a matter of taste.

At this point I have applied at least cursory testing to this tool using Firefox 3.5, Opera 10, and Safari 4. Without testing I would expect it to work in a reasonably recent Chrome, and not in any version of Internet Explorer (patches welcome).

Concepts

The fundamental ideas that underlie ReSpec.js are:

It Just HTML
You just edit HTML, with some extra convention but nothing extra. All the decoration is performed by the script, informed by some very basic configuration. There is a simple template that you can use to get started.
No Tool
You never have to run a tool outside of your editor and browser. While the specification is being developed that's all that's needed. When a snapshot is needed for publication, all it takes is saving the generated DOM to a file (the script is very careful to cleanly remove itself and its dependencies so that you should normally get a document that's PubRules-OK).
DRY
You shouldn't have to repeat anything within a specification, or across specifications (apart from the template). For instance, marking RFC 2119 keywords is automatic, the WebIDL support makes it possible to specify both the WebIDL and its documentation in the same place without repeating a single part of it, etc..

General Structure

Most of what is described here will make a whole lot more sense if you look at the template's source before you get started.

The general structure of a ReSpec document is that of an HTML5 [[!HTML5]] document, with a few extra conventions so that the ReSpec processor may infer additional semantics.

Inside head, the title element contains the title that will also be used to generate the h1 in the specification's header. Then external script element loads in ReSpec, and another one inlines the basic configuration that it requires.

Inside the body, each section of the specification is contained inside a section element. At least one of these MUST have an id of "abstract" (and MUST contain just the text of the abstract). Sections can be nested to any depth and are expected to have a heading title. Any of h2-h6 is acceptable as they will be automatically renamed to the hN applicable to that depth.

If there is a section element with id "sotd" anywhere with the document, it will be removed, and its content will be inserted inside the Status of this Document as additional custom content.

If there is a section element with id "conformance" in the document (and that element MAY be completely empty), it will be replaced with a template conformance section that mentions the RFC 2119 keywords and the such. If it has any content it will be appended after that template.

During processing, section elements will be converted to div elements with class "section".

Any section at the beginning that has a class of "introductory" will not be included in the Table of Contents. The first root-level section with a class of "appendix" will start the appendices section, labelled with letters.

Each section MAY have an id — if not, one will be generated based on the textContent of its heading.

Any section that has a class of "informative" will be marked as "non-normative" in the output using the usual text.

You MUST NOT create sections for the Status of this Document, the ToC, or the References as they will be automatically generated for you.

Configuration

The only part of ReSpec that isn't just straightforward HTML is the configuration, which thankfully is minimal (and a lot simpler than the HTML that it generates and which is required in all W3C specifications).

The configuration is stored in a Javascript object called respecConfig.

specStatus

This is the status of the document, as keyed in the following table. If in doubt, use ED.

key value
NOTENote
WG-NOTEWorking Group Note
CG-NOTECo-ordination Group Note
IG-NOTEInterest Group Note
Member-SUBMMember Submission
Team-SUBMTeam Submission
XGRIncubator Group Report
MOMember-Only Document
EDEditor's Draft
FPWDFirst Public Working Draft
WDWorking Draft
LCLast Call Working Draft
CRCandidate Recommendation
PRProposed Recommendation
PERProposed Edited Recommendation
RECRecommendation
RSCNDRescinded Recommendation

The specStatus is used to pick the base style sheet, as well as to configure various parts of the specification's header and Status of this Document. Some of the header notably depends on whether the specification is on "Rec-track", which is the case if the specStatus is one of: "FPWD", "WD", "LC", "CR", "PR", "PER", or "REC".

shortName
The specification's short name, as in http://www.w3.org/TR/short-name/. Note that short names are assigned by the Director — ask your Team contact or Chair in advance of publication.
subtitle
W3C specifications have an optional subtitle that is displayed below the title in the heading section. Define yours here if you have one.
copyrightStart
Some W3C specifications have a copyright that spans a range of years. You can specify the optional starting year with this parameter.
publishDate
When a draft is made ready for publication it is often done several days in advance. In that case, set this to the desired date in YYYY-MM-DD format. Otherwise comment it out, it'll default to today.
previousPublishDate
If there is a previously published version of this draft, set this to its date in YYYY-MM-DD format. If there isn't simply comment it out (or set it to a false value).
previousMaturity
If there is a previously published version of this draft, set this to its maturity level.
additionalCopyrightHolders
If there are additional copyright holders in addition to the W3, they can be listed in this parameter. For example, if the copyright notice without additionalCopyrightHolders reads "Copyright © 2009 W3C ... " then with "Foo" listed it will read "Copyright © 2009 Foo & W3C ... ".
edDraftURI
If there a publicly available Editor's Draft, this is the link to it. This will typically be the link to the CVS version of the document you're editing.
lcEnd
If the draft is a Last Call WD it needs to have a review period with a given end date. This is that date in YYYY-MM-DD format. This is otherwise ignored.
prevRecShortname
If there is an earler version of this specification at the Recommendation level, set this to the shortname of that version. This is optional and not usually necessary.
extraCSS
This is an array that contains URI references (that may be absolute or relative) to additional CSS style sheets that you may wish to be loaded into the document. It is RECOMMENDED that you include http://dev.w3.org/2009/dap/ReSpec.js/css/respec.css as one of those, though you may of course skip it and take care of the additional styles yourself.
editors

An array describing editors that contains objects with the following fields:

keyoptionaldescription
name No The name of the editor.
url Yes The URL to the editor's website.
company Yes The editor's affiliation.
companyURL Yes The URL to the editor's affiliation's website.
mailto Yes The email address for the editor.
note Yes Additional note related to this editor, displayed as parenthetical after other information.

At least one editor is required, and you can have as many as you want. They will be displayed in the provided order. There are two conventions usually applied within W3C: by alphabetical order of last name, or of first name — choose whichever applies to your WG. Sometimes one editor who stands out as having contributed far more than most is placed first.

A note may be used to display additional relevant information, such as the specific release the editor worked on, for example. This could be done by setting note to "2nd Edition", for example:

Mr Example, Foo Company ( 2nd Edition )

authors

An array describing authors that contains objects with fields for each author. The format and definitions of the fields are the same as for editors.

Use of authors is entirely optional,none are required. You can have as many authors as you want. Display is the same as described for editors.

errata
Specifies the optional URI to the errata for the document. This is normally only available when the document is a 'REC'.
alternateFormats

If specified, defines an array of alternate formats in which document is available (e.g., XML, Postscript). The format of the array is:

keydescription
uri the relative or absolute URI to the alternate version.
label the label to use for the version.
maxTocLevel
If specified, is an integer used to indicate the maximum depth of the ToC. The depth is the number of numbering levels, so for instance 4.19.5 is at depth 3. The first level is always included in the ToC (otherwise there would be no ToC).
noIDLSorting
By default, the generated WebIDL is produced in the order in which it is in the document, but the generated HTML descriptions that match are sorted (this behaviour matches that found in the DOM specifications). Setting this option to true causes the generated HTML to also be in document order.
noIDLIn
Historically, IDL parameters have all started with "in", as inherited from OMG IDL. In WebIDL this is optional, and this option turns it off for the entire document.
refNote

If the refNote parameter is defined, the text contained within it is provided as a paragraph in the References section, before the normative and informative reference sub-sections. If not defined then no paragraph is included.

This may be used to provide a note regarding use of subsequent revisions of references for example:

respecConfig.refNote = "Dated references below are to the latest known \
or appropriate edition of the referenced work.  The referenced works \
may be subject to revision, and conformant implementations may follow, \
and are encouraged to investigate the appropriateness of following, \
some or all more recent editions or replacements of the works \
cited. It is in each case implementation-defined which  editions are \
supported."; 
wg
The full and official name of the group (WG, IG, CG, XG, TF, etc.) in charge of this document.
wgURI
The URI to the public page of the group named in wg.
wgPublicList
The name of the public mailing list for the group named in wg, without the "@w3c.org" part. For instance for the DAP WG it is "public-device-apis".
wgPatentURI

The URI to the patent status for this group. This is for Rec-track documents only.

IMPORTANT: this is an important and legally relevant piece of information. Do not copy this URI from another document unless you are certain that it is the correct one that applies to your group and to that document. If you have the slightest shade of a doubt, ask your friendly neighbourhood Team Contact.

Table of Contents & Numbering

The ToC is generated entirely for you, so long as you are careful to stick to the following simple rules:

Sections can be nested to any depth. Any of h2-h6 is acceptable for their required title as they will be automatically renamed to the hN applicable to that depth.

Any section at the beginning that has a class of "introductory" will not be included in the Table of Contents. The first root-level section with a class of "appendix" will start the appendices section, labelled with letters.

Each section MAY have an id — if not, one will be generated based on the textContent of its heading (the algorithm was taken with minor modification from Anolis).

RFC 2119

Any editor who wishes to do a good job MUST have read RFC 2119 [[!RFC2119]]. This RFC defines a number of keywords that have a specific meaning in a standards context.

ReSpec recognises the full list of keywords (MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL) without requiring any specific markup. They only need to be in uppercase so as to distinguish them from the regular usage of such words that may otherwise occur.

Definitions

A definition is a term that is specified or clarified for the specific use of the given specification. It is created using the dfn element. The terms being defined will be either and in order (as per slightly enriched [[!HTML5]]):

  1. the title attribute of the dfn element
  2. the title attribute of the only child element of dfn when it is abbr or acronym
  3. the textContent of the dfn element

Definitions can then be referred to using an a element (as per [[!HTML5]]) without an href attribute (it will be added). As in this paragraph, the title attribute can be used to provide the exact term to which the reference is being made.

When referring to a term defined in another specification, the a element without href is still to be used, but with a class set to "externalDFN".

References

Specifications make two kinds of references: normative and informative (sometimes referred to as "non-normative" or "other references"). Reference maintenance is always painful, and will regularly go out of synch.

ReSpec relies on an external database of references stored as the berjon.biblio Javascript object. The keys to that database are the terms used to refer to a given specification, and the values the HTML that is inserted. The contents of that database were originally extracted from the database in Refer format that is part of the CSS3 Module Preprocessor but is now maintained separately.

If you wish to acces an automatically generated HTML version of the biblio DB you can get it in the biblio.html file, but be warned that this may be slow to render. Using the initial JS document is often easier.

If you notice that a given entry is missing or out of date, you may patch it directly in CVS, or contact Robin to update it.

In order to insert an informative reference, look for its code in the database and use the following syntax: [[CODE]]. This will produce a result like the following: [[DAHUT]].

Likewise, in order to insert a normative reference, look for its code in the database and use the same syntax but with a "!" in front of the code: [[!CODE]]. This will produce a result like the following: [[!ELEMENTTRAVERSAL]].

If the refNote parameter is defined then a paragraph will be created in the References section with the content of that parameter, as noted in the Configuration section.

Abbreviations

ReSpec supports both abbr and acronym (and really doesn't want to hear about the debate concerning these two — if you have a side, use whatever makes you happy). Once an abbreviation is defined anywhere inside the document using one of these two elements and its title attribute, any occurrence of the same abbreviation anywhere else in the body of the specification will see itself wrapped automatically in the same element, with the same title. You can therefore define an abbreviation thus: DAHUT.

Note that thanks the standard header, some abbreviations like W3C or ERCIM are always defined, while others such as DAHUT come from the rest of the content.

Including other data

Sometimes a specification will need to incorporate data that is best kept in an external file (e.g., an XML Schema implementation of the datatypes would be in an '.xsd' file, but should also be in-line in the spec). ReSpec permits this by allowing inclusion of arbitrary external data and also allowing optional transformation of that data.

To reference an external resource, define the resource via the data-include attribute (e.g., <div data-include='myDatatypes.xsd'></div> ). The contents of the element with that attribute will be replaced with the data read from the file.

To perform one or more transformations on the contents before they are placed in the document, specify the names of transformation methods via the data-oninclude attribute (e.g., <div data-include='myDatatypes.xsd' data-oninclude='updateSchema'></div> ). Each whitespace separated method named will be called and passed two parameters: the berjon.respec object and the contents of the resource retrieved.

Here's a simple transformation method:

function updateExample(doc, content) {
    // perform transformations to make it render and prettier
    return '
' + doc._esc(content) + '
'; }

Transforming data

Another thing you might want to do is transform arbitrary content in your document (for example, to ensure that content within an 'example' block is escaped). You can do this via the data-transform. Just like the data-oninclude attribute above, this allows you to specify a whitespace separated list of method names. Each will be called and passed two parameters: the berjon.respec object and the contents of the element.

Here is an example, using the same method as above:

function updateExample(doc, content) {
    // perform transformations to make it render and prettier
    return '
' + doc._esc(content) + '
'; }

And then the content:

        <pre class='example' data-transform='updateExample'>
        <html>
        ...
        </html>
        </pre>
      

WebIDL Support

WebIDL [[!WEBIDL]] is the language that is used to define APIs inside W3C specifications. It is powerful and very expressive, and at this stage ReSpec only supports a limited (but hopefully useful) subset of it.

The issues with editing WebIDL directly in documents are as follow:

ReSpec does its best to provide all three of the above at a minimal cost.

Currently only interface and exception definitions are supported, and on them only the simple variants of attributes, constants, and operations (with extended attributes everywhere). Additional features will be added on a need-to-be-done basis.

The approach is simple. An interface is defined using a dl element, with a class of "idl" and the title of which is the defining line for the interface, for instance [Constructor] interface Dahut : Mammal, Cryptoid or exception Boom.

Inside the dl, each dt/dd pair defines an interface member (attribute, constant, or operation). The content of the dt element is the line that defines the member (e.g. readonly attribute DOMString chirality or void yell ([AllowAny] in unsigned long volume, [TreatNullAs=EmptyString] in DOMString sentence)); and the dd element contains the description.

This format has the advantage of keeping information well-grouped together, using HTML markup for the most part (so that even WYSIWYG editors can be used), while being simple to parse and sufficiently expressive for most needs (especially as more features are added).

The output that is generated replaces the dl with a syntax-highlighted and linked WebIDL segment with all the members for the given interface in the order in which they were defined; followed by two subsections listing respectively attributes and methods in alphabetical order (further details will progressively be added to those descriptions).

An example will probably speak more clearly; the following simple code:

<dl title='[Constructor] interface Dahut : Mammal, Cryptoid' class='idl'>
  <dt>const unsigned short LEVROGYROUS = 0</dt>
  <dd>
    Turning left.
  </dd>
  <dt>const unsigned short DEXTROGYROUS = 1</dt>
  <dd>
    Turning right.
  </dd>
  <dt>readonly attribute DOMString chirality</dt>
  <dd>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor (...)
  </dd>
  <dt>attribute unsigned long age</dt>
  <dd>
     Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip (...)
  </dd>
  <dt>Dahut turnAround (in float angle, in boolean fall)</dt>
  <dd>
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat (...)
  </dd>
  <dt>unsigned long trip ()</dt>
  <dd>
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit (...)
  </dd>
  <dt>void yell ([AllowAny] in unsigned long volume, [TreatNullAs=EmptyString] in DOMString sentence)</dt>
  <dd>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt (...)
  </dd>
</dl>

Will produce the following WebIDL section with links and syntax highlighting, as well as the two following subsections that list attributes and methods:

const unsigned short LEVROGYROUS = 0
Turning left.
const unsigned short DEXTROGYROUS = 1
Turning right.
readonly attribute DOMString chirality
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
attribute unsigned long age
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Dahut turnAround (in float angle, in boolean fall)
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
unsigned long trip ()
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
void yell ([AllowAny] in unsigned long volume, [TreatNullAs=EmptyString] in DOMString sentence)
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

The WebIDL testing document provides a number of additional examples.

Saving the Generated Specification

Of course the downside of the approach taken by ReSpec is that the specification as it is expected to be, with all its bells and whistles, exists only in your browser's memory. Publishing directly with the script would not work as it does not work for all browsers (and there are still quite a few people using Internet Explorer out there) and would not show all the content for search indexing. And sadly enough browsers aren't very good at saving HTML that's been modified by script.

The solution that is used here is that you hit the Ctrl+Shift+Alt+S key combination (this is subject to change until we agree on an option we all like). That will show a menu offering to either "Save as HTML", or "Save as HTML (Source)". You can hit Esc to hide it.

Those two options are very similar. The first one opens a new window (which may be in a new tab depending on your configuration) and shows you a document that should look exactly the same as the one you're editing. That's normal. The difference is that it's a static document that represents the same DOM tree as the live one after ReSpec has run. That page you can then save using your browser's vanilla saving mechanism (be sure to refuse any option that tries to save the complete page with images and other dependencies — you want just the HTML). The "Source" alternative shows you the same page's source code so that you can paste it into your favourite editor.

Note that some browsers will still save the original document when you use the non-Source alternative, so if in doubt use the Source alternative.

Currently only HTML 4.01 is supported because getting browsers to output XHTML can be a fair bit more painful. Patches are welcome in this area. HTML5 is not supported because it is currently rejected by PubRules.

The idea is that such snapshots would be created only when actual official W3C publication is required — all the while that the specification is an Editor's Draft it should simply live as itself.

Examples

The source code of this very document makes use of many ReSpec features. It provides a good starting point for examples.

Additionally there is a test specification that exercises all features at least in part, and can therefore be studied to see different aspects of ReSpec in action.

History

The initial ReSpec processor was written in Perl, for the Web API WG.

Acknowledgements

Many thanks to Marcos Cáceres for moral support, and to Bert Bos and Geoffrey Sneddon for their tools from which I pilfered joyfully.