This paragraph is here to demonstrate that it is possible to add a completely custom piece of HTML inside the SotD.
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).
The fundamental ideas that underlie ReSpec.js are:
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.
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
.
This is the status of the document, as keyed in the following table. If in doubt,
use ED
.
key | value |
---|---|
NOTE | Note |
WG-NOTE | Working Group Note |
CG-NOTE | Co-ordination Group Note |
IG-NOTE | Interest Group Note |
Member-SUBM | Member Submission |
Team-SUBM | Team Submission |
XGR | Incubator Group Report |
MO | Member-Only Document |
ED | Editor's Draft |
FPWD | First Public Working Draft |
WD | Working Draft |
LC | Last Call Working Draft |
CR | Candidate Recommendation |
PR | Proposed Recommendation |
PER | Proposed Edited Recommendation |
REC | Recommendation |
RSCND | Rescinded 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".
additionalCopyrightHolders
reads
"Copyright © 2009 W3C ... " then with
"Foo" listed it will read "Copyright © 2009 Foo &
W3C ... ".
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.
An array describing editors that contains objects with the following fields:
key | optional | description |
---|---|---|
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:
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.
If specified, defines an array of alternate formats in which document is available (e.g., XML, Postscript). The format of the array is:
key | description |
---|---|
uri | the relative or absolute URI to the alternate version. |
label | the label to use for the version. |
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
.
wg
, without the
"@w3c.org" part. For instance for the DAP WG it is "public-device-apis".
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.
The ToC is generated entirely for you, so long as you are careful to stick to the following simple rules:
section
elementshn
element containing its title
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).
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.
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]]):
title
attribute of the dfn
elementtitle
attribute of the only child element of dfn
when it is
abbr
or acronym
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".
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.
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.
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) + ''; }
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 [[!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:
The WebIDL testing document provides a number of additional examples.
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.
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.
The initial ReSpec processor was written in Perl, for the Web API WG.
Many thanks to Marcos Cáceres for moral support, and to Bert Bos and Geoffrey Sneddon for their tools from which I pilfered joyfully.