Ecmarkup is a number of custom elements and a toolchain suitable for formally specifying semantics for ECMAScript proposals.
Ecmarkup offers the following conveniences (among many others):
This document is itself written using Ecmarkup. Its source can be viewed on github. Additionally, you can view the Array.prototype.includes proposal in Ecmarkup format.
npm install -g ecmarkup ecmarkup --help ecmarkup spec.html out.html
Styles are provided by elements.css under the css directory. The --css command line option will emit the CSS file to a location of your choosing. You may also link to https://bterlson.github.io/ecmarkup/elements.css which will contain the latest styles for the forseeable future (though I don't promise this won't break you if you're not tracking the latest version).
There are a number of settings that allow customizations or enable generation of boilerplate. Metadata can be included in the document and passed on the command line, for example --no-toc --title "Document 1". Metadata given on the command line takes precedence.
To add metadata to your document, use yaml syntax inside a <pre class=metadata> element somewhere in the root of your document.
The following table lists the currently supported metadata:
| Option | Description |
|---|---|
| toc | Emit table of contents. Boolean, default true. |
<pre class=metadata>
Title: Document 1
toc: false
</pre>
Clauses are referenced using their id and are numbered automatically based on document position. Ecmarkdown syntax can be used in descendent text nodes as well. Text nodes are parsed as Ecmarkdown Fragments.
Non-normative introductory information.
id: Clause id. Must be unique.
aoid: Abstract operation ID. A unique name identifying this clause as an abstract operation. Algorithm steps will auto-link calls to this abstract operation to this clause. If left blank, the aoid will be
Normative clause.
id: Clause id. Must be unique.
aoid: Abstract operation ID. A unique name identifying this clause as an abstract operation. Algorithm steps will auto-link calls to this abstract operation to this clause. If left blank, the aoid will be
Annex clause.
normative: If present, annex is normative. Default is non-normative.
id: Clause id. Must be unique.
aoid: Abstract operation ID. A unique name identifying this clause as an abstract operation. Algorithm steps will auto-link calls to this abstract operation to this clause. If left blank, the aoid will be
Algorithm steps. Should not contain any HTML. The node's textContent is parsed as an Ecmarkdown document. Additionally, calls to abstract operations inside algorithm steps are automatically linked to their definitions by first checking for any clauses or algorithms with the appropriate "aoid" in the current spec, and afterwards checking any linked bibliography files.
<emu-alg aoid="EmuAlgExample">
1. let _clauseAbstractOp_ be the result of calling EmuAlg()
2. Step 2
1. let _recurse_ be the result of calling EmuAlgExample(`true`)
2. Return the result of evaluating this |NonTerminalProduction|
</emu-alg>
true)An equation, similar to those found in ES6
aoid: Required: the abstract operation id that this equation defines.
Non-normative explanatory text.
For authentication only, servers and clients MUST support SASL Salted Challenge Response Authentication Mechanism [SCRAM].
Cross-title attribute controls this default - when present, clauses are referred to using their title rather than number. This also applies to examples which are indexed first by their containing clause and then their example number.
Cross-references to an id check for clauses, productions, and examples in this order. For each
href: Optional: URL of the target clause, production, or example to cross-
title: Optional: If present, xref will be filled in with the referenced clause's title. Otherwise, the clause's section number is used.
aoid: Optional: aoid of an abstract operation to
One of aoid or href must be specified.
<p>The clause element is specified in <emu-xref href="#emu-clause"></emu-xref>.</p>
<p>See <emu-xref href="#emu-note" title></emu-xref> for information on the emu-note element.</p>
<p>The <emu-xref href="#emu-biblio">biblio element</emu-xref> supports xref to external specs.</p>
<p><emu-xref aoid="Get"></emu-xref> is an abstract operation from ES6</p>
Result
The clause element is specified in
See
The
Creates a figure that can be xrefed by ID using the emu-xref element.
caption: Optional: Caption for the example
informative: Optional: If present, the figure is informative. Otherwise it is normative.
<emu-figure caption="Example figure">
[[insert some awesome graphic here, maybe something like figure 2]]
</emu-figure>
Creates a table that can be xrefed by ID using the emu-xref element.
caption: Optional: Caption for the example
informative: Optional: If present, the table is informative. Otherwise it is normative.
<emu-table caption="Example table">
<table>
<tr><th>Column 1</th><th>Column 2</th></tr>
<tr><td>Value</td><td>Value 2</td></tr>
<tr><td>Value</td><td>Value 2</td></tr>
<tr><td>Value</td><td>Value 2</td></tr>
<tr><td>Value</td><td>Value 2</td></tr>
</table>
</emu-table>
| Column 1 | Column 2 |
|---|---|
| Value | Value 2 |
| Value | Value 2 |
| Value | Value 2 |
| Value | Value 2 |
Creates an informative example. Examples are numbered based on how many are present in the example's containing clause. Can be xrefed by ID using emu-xref.
caption: Optional: Caption for the example
<emu-example caption="Example Example">
This is an example.
</emu-example>
<emu-example caption="Another Example Example">
This is also an example.
</emu-example>
Links a bibliography file. The bibliography file is a JSON document containing URLs for referenced documents along with any algorithms they define.
href: Required: URL to the biblio file.
{
"http://people.mozilla.org/~jorendorff/es6-draft.html": {
"abstract operations": {
"ReturnIfAbrupt": "#sec-returnifabrupt",
"Get": "#sec-get-o-p"
}
}
}
spec.js
<emu-biblio href="./spec.js"></emu-biblio>
<emu-alg>
1. let _res_ be some value.
2. ReturnIfAbrupt(_res_)
</emu-alg>
Result
There are two ways to specify grammar in Ecmarkup: using the emu-production element and related elements, or by using the emu-grammar element which allows specifying grammar using a plaintext format.
<emu-production name="WhileStatement">
<emu-rhs>while ( <emu-nt>Expression</emu-nt> ) <emu-nt>Statement</emu-nt></emu-rhs>
</emu-production>
<emu-production name="ArgumentList">
<emu-rhs><emu-nt>AssignmentExpression</emu-nt></emu-rhs>
<emu-rhs><emu-nt>ArgumentList</emu-nt> , <emu-nt>AssignmentExpression</emu-nt></emu-rhs>
</emu-production>
<emu-production name="IterationStatement">
<emu-rhs>for ( <emu-nt>LexicalDeclaration</emu-nt> ; <emu-nt optional>Expression</emu-nt> ;
<emu-nt optional>Expression</emu-nt> ) <emu-nt>Statement</emu-nt></emu-rhs>
</emu-production>
<emu-production name="Identifier" type="lexical">
<emu-rhs><emu-nt>IdentifierName</emu-nt> <emu-gmod>but not
<emu-nt>ReservedWord</emu-nt></emu-gmod></emu-rhs>
</emu-production>
<emu-production name="SourceCharacter" type="lexical">
<emu-rhs><emu-gprose>any Unicode code point</emu-gprose></emu-rhs>
</emu-production>
<emu-production name="ExpressionStatement" params="Yield">
<emu-rhs>
<emu-gann>lookahead ∉ {
<emu-t>{</emu-t>,
<emu-t>function</emu-t>,
<emu-t>class</emu-t>,
<emu-t>let [</emu-t>
}</emu-gann>
</emu-rhs>
</emu-production>
<emu-production name="DecimalDigit" type="lexical" oneof>
<emu-rhs>0 1 2 3 4 5 6 7 8 9</emu-rhs>
</emu-production>
<emu-production name="StatementList" params="Return, In">
<emu-rhs constraints="~Return"><emu-nt>ReturnStatement</emu-nt></emu-rhs>
<emu-rhs><emu-nt>ExpressionStatement</emu-nt></emu-rhs>
</emu-production>
Text inside emu-grammar elements is parsed using Grammarkdown. The syntax is essentially identical to the notational conventions in ECMAScript (minus formatting). See the Grammarkdown readme.
This is the top level element that contains all grammar productions. Each production MUST include at least one right-hand side (see emu-rhs).
Name: Required. Name of the production (i.e. the non-terminal on the LHS).
Params: Parameters for this production. Multiple parameters separated by commas.
oneof: If present, production is a one-of production. See DecimalDigit example above.
Describes one right-hand-side alternative of a production. Text nodes inside of an rhs are split on each space and turned into terminals. For example,
<emu-rhs>a b c</emu-rhs>is semantically equivalent to
<emu-rhs><emu-t>a</emu-t> <emu-t>b</emu-t> <emu-t>c</emu-t>
constraints: any constraints for this RHS. Multiple constraints separated by commas. See StatementList example above.
a: Optional alternative id used to emu-prodref. Must be unique for all emu-rhs elements inside an emu-production. Example might be `
Non-terminal. Alpha characters only.
Params: Parameters for this production. Multiple parameters separated by commas.
oneof: If present, production is a one-of production (see DecimalDigit example above).
Terminal. No attributes available. Mostly don't need to create these elements manually as they are created automatically inside emu-rhs elements.
Contains well-known modifiers to a right-hand side of a production. The only well-known modifier at present is the "but not" modifier. See the Identifier example above.
Contains well-known annotations to to a right-hand side of a production. The only well-known modifiers at present are "lookahead" and "empty". See the ExpressionStatement example above. Any text inside a gann element is wrapped in square brackets.
Contains any prose text that describes a production. See SourceCharacter example above.
References a production defined elsewhere in the document. Ecmarkup will insert either the entire production or a particular RHS depending on attributes.
name: Required. Name of the production to
a: Optional. If present, specified a particular alternative ID to
HTML Imports are treated specially in an ecmarkup document. Every import is inlined into its parent document at the location of the import tag. This is useful for breaking your spec document up into many smaller pieces.
The ins and del HTML tags can be used to mark insertions and deletions respectively. When adding or removing block content (such as entire list items, paragrpahs, clauses, grammar RHSes, etc.), use a class of "block".
ECMAScript <del>6</del><ins>2015</ins> <del>will be ratified</del><ins>was ratified</ins> in June, 2015.
ECMAScript 62015 will be ratifiedwas ratified in June, 2015.
<p>|HoistableDeclaration| is modified as follows:</p>
<emu-production name="HoistableDeclaration">
<emu-rhs><emu-nt>FunctionDeclaration</emu-nt></emu-rhs>
<emu-rhs><emu-nt>GeneratorDeclaration</emu-nt></emu-rhs>
<ins class="block"><emu-rhs><emu-nt>AsyncFunctionDeclaration</emu-nt></emu-rhs></ins>
</emu-production>