Skip to content

Commit

Permalink
Add emu-example
Browse files Browse the repository at this point in the history
  • Loading branch information
bterlson committed Aug 19, 2015
1 parent 27bd1fc commit 22970e5
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 18 deletions.
14 changes: 12 additions & 2 deletions css/elements.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,27 @@ emu-eqn div:first-child {

emu-note {
display: block;
margin-left: 5em;
margin-left: 6em;
color: #666;
}

emu-note span.note {
text-transform: uppercase;
margin-left: -5em;
margin-left: -6em;
display: block;
float: left;
}

emu-example {
display: block;
margin: 1em 3em;
}

emu-example figure figcaption {
margin-top: 0.5em;
text-align: left;
}

emu-production {
display: block;
margin-top: 1em;
Expand Down
26 changes: 23 additions & 3 deletions lib/Clause.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const CLAUSE_ELEMS = ['EMU-INTRO', 'EMU-CLAUSE', 'EMU-ANNEX'];
const Note = require('./Note');
const Example = require('./Example');
const emd = require('ecmarkdown');
const utils = require('./utils');
const Builder = require('./Builder');
Expand Down Expand Up @@ -56,7 +57,9 @@ module.exports = class Clause extends Builder {
number: this.number
};

this.notes = this.getNotes();
const record = this.getNotesAndExamples();
this.notes = record[0];
this.examples = record[1];
}

build() {
Expand All @@ -69,6 +72,7 @@ module.exports = class Clause extends Builder {
processEmd(this);

this.buildNotes();
this.buildExamples();
}

buildNotes() {
Expand All @@ -82,8 +86,20 @@ module.exports = class Clause extends Builder {
}
}

getNotes() {
buildExamples() {
if (this.examples.length === 1) {
this.examples[0].build();
} else {
// pass along example index
this.examples.forEach(function (example, i) {
example.build(i + 1);
}, this);
}
}

getNotesAndExamples() {
const notes = [];
const examples = [];

utils.domWalk(this.node, function (child) {
if (CLAUSE_ELEMS.indexOf(child.nodeName) > -1) {
Expand All @@ -93,9 +109,13 @@ module.exports = class Clause extends Builder {
if (child.nodeName === 'EMU-NOTE') {
notes.push(new Note(this.spec, child));
}

if (child.nodeName === 'EMU-EXAMPLE') {
examples.push(new Example(this.spec, child, this));
}
}.bind(this));

return notes;
return [notes, examples];
}

buildUtils() {
Expand Down
42 changes: 42 additions & 0 deletions lib/Example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';
const Builder = require('./Builder');

module.exports = class Example extends Builder {
constructor(spec, node, clause) {
super(spec, node);
this.clause = clause;
this.caption = this.node.getAttribute('caption');
if (this.node.hasAttribute('id')) {
this.id = this.node.getAttribute('id');
}
}

build(number) {
// biblio is added during the build step as we don't know
// the number at build time. Could probably be fixed.
this.spec.biblio.examples[this.id] = {
location: '',
id: this.id,
number: number || 1,
clauseId: this.clause.id
};

this.node.innerHTML = '<figure>' + this.node.innerHTML + '</figure>';

let caption = 'Example';
if (number) {
caption += ' ' + number;
}

caption += ' (Informative)';

if (this.caption) {
caption += ': ' + this.caption;
}

const captionElem = this.spec.doc.createElement('figcaption');
captionElem.textContent = caption;
this.node.childNodes[0].appendChild(captionElem);
}
};

22 changes: 20 additions & 2 deletions lib/Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ module.exports = class Spec {
clauses: {},
ops: {},
productions: {},
terms: {}
terms: {},
examles: {}
};
this.biblio = {
clauses: {},
ops: {},
productions: {},
terms: {}
terms: {},
examples: {}
};
this._prodsByName = {};

Expand All @@ -61,6 +63,8 @@ module.exports = class Spec {
buildAll(selector, Builder, opts) {
opts = opts || {};

this._log('Building ' + selector + '...');

let elems;
if (typeof selector === 'string') {
elems = this.doc.querySelectorAll(selector);
Expand Down Expand Up @@ -106,6 +110,7 @@ module.exports = class Spec {

if (this.opts.toc) {
p = p.then(function() {
this._log('Building table of contents...');
const tb = new Toc(this);
return tb.build();
}.bind(this));
Expand Down Expand Up @@ -231,6 +236,19 @@ module.exports = class Spec {
}
}

lookupBiblioEntryById(id) {
const types = ['clause', 'production', 'example'];
for (let i = 0; i < types.length; i++) {
const type = types[i];
const entry = this.spec.biblio[type + 's'][id] || this.spec.externalBiblio[type + 's'][id];
if (entry) {
return { type: type, entry: entry };
}
}

return null;
}

_log() {
if (!this.opts.verbose) return;
console.log.apply(console, arguments);
Expand Down
45 changes: 37 additions & 8 deletions lib/Xref.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,26 @@ module.exports = class Xref extends Builder {
return;
}

let entry = this.spec.biblio.clauses[href.slice(1)] || this.spec.externalBiblio.clauses[href.slice(1)];
if (entry) {
buildClauseLink(xref, entry);
const id = href.slice(1);

const entry = this.spec.lookupBiblioEntryById(id);
if (!entry) {
console.log('Warning: can\'t find clause, production or example with id ' + href);
return;
}

entry = this.spec.biblio.productions[href.slice(1)] || this.spec.externalBiblio.productions[href.slice(1)];
if (entry) {
buildProductionLink(xref, entry);
return;
switch (entry.type) {
case 'clause':
buildClauseLink(xref, entry.entry);
break;
case 'production':
buildProductionLink(xref, entry.entry);
break;
case 'example':
buildExampleLink(this.spec, xref, entry.entry);
break;
default:
console.log('Warning: found unknown biblio entry (this is a bug, please file it)');
}
} else if (aoid) {
const entry = this.spec.biblio.ops[aoid] || this.spec.externalBiblio.ops[aoid];
Expand All @@ -41,9 +51,10 @@ module.exports = class Xref extends Builder {
buildAOLink(xref, entry);
return;
}

console.log('Warning: can\'t find abstract op with aoid ' + aoid);
}

console.log('Warning: can\'t find clause or production with id ' + href);
}
};

Expand Down Expand Up @@ -75,6 +86,24 @@ function buildAOLink(xref, entry) {
}
}

function buildExampleLink(spec, xref, entry) {
if (xref.textContent.trim() === '') {
// first need to find the associated clause
const clauseEntry = spec.lookupBiblioEntryById(entry.clauseId);
if (clauseEntry.type !== 'clause') {
console.log('Warning: could not find parent clause for example id ' + entry.id);
}

if (xref.hasAttribute('title')) {
xref.innerHTML = buildXrefLink(entry, clauseEntry.entry.title + ' Example ' + entry.number);
} else {
xref.innerHTML = buildXrefLink(entry, clauseEntry.entry.number + ' Example ' + entry.number);
}
} else {
xref.innerHTML = buildXrefLink(entry, xref.innerHTML);
}
}

function buildXrefLink(entry, contents) {
return '<a href="' + entry.location + '#' + entry.id + '">' + contents + '</a>';

Expand Down
39 changes: 36 additions & 3 deletions spec/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ <h1>Metadata</h1>
<p>To add metadata to your document, use yaml syntax inside a `&lt;pre class=metadata>` element somewhere in the root of your document.</p>
<p>The following table lists the currently supported metadata:</p>
<table>
<tr><th>Option</th><th>Description</th></tr>
<tr><td>toc</td><td>Emit table of contents. Boolean, default true.</td></tr>
</table>
<h2>Example document with metadata</h2>
Expand Down Expand Up @@ -126,24 +127,56 @@ <h2>Example</h2>

<emu-clause id="emu-xref">
<h1>emu-xref</h1>
<p>Cross-reference another clause. If the text content of this element is empty, the target clause's section number or title will be used.</p>
<p>Cross-reference another clause, production, example, or abstract operation. If the text content of this element is empty, a suitable default is used. The `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.</p>
<p>Cross-references to an id check for clauses, productions, and examples in this order. For each type, the local document is consulted before looking for external sources including the default ES6 biblio.</p>

<h2>Attributes</h2>
<p><b>href:</b> Required: URL of the target clause to cross-reference. May simply be a fragment identifier (see examples below).</p>
<p><b>href:</b> Optional: URL of the target clause, production, or example to cross-reference.</p>
<p><b>title:</b> Optional: If present, xref will be filled in with the referenced clause's title. Otherwise, the clause's section number is used.</p>
<p><b>aoid:</b> Optional: aoid of an abstract operation to reference.</p>

<p>One of aoid or href must be specified.</p>

<h2>Example</h2>
<pre><code class="language-html">
&lt;p>The clause element is specified in &lt;emu-xref href="#emu-clause">&lt;/emu-xref>.&lt;/p>
&lt;p>See &lt;emu-xref href="#emu-note" title>&lt;/emu-xref> for information on the emu-note element.&lt;/p>
&lt;p>The &lt;emu-xref href="#emu-biblio">biblio element&lt;/emu-xref> will eventually support xref to external specs.&lt;/p>
&lt;p>The &lt;emu-xref href="#emu-biblio">biblio element&lt;/emu-xref> supports xref to external specs.&lt;/p>
&lt;p>&lt;emu-xref aoid="Get">&lt;/emu-xref> is an abstract operation from ES6&lt;/p>
</code></pre>

<b>Result</b>
<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> will eventually support xref to external specs.</p>
<p><emu-xref aoid="Get"></emu-xref> is an abstract operation from ES6</p>
</emu-clause>

<emu-clause id="emu-example">
<h1>emu-example</h1>
<p>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`.</p>

<h2>Attributes</h2>
<p><b>caption:</b> Optional: Caption for the example</p>

<h2>Example</h2>
<pre><code class="language-html">
&lt;emu-example caption="Example Example">
This is an example.
&lt;/emu-example>

&lt;emu-example caption="Another Example Example">
This is also an example.
&lt;/emu-example>
</code></pre>
<emu-example caption="Example Example">
This is an example.
</emu-example>

<emu-example caption="Another Example Example">
This is also an example.
</emu-example>
</emu-clause>
<emu-clause id="emu-biblio">
<h1>emu-biblio</h1>
<p>Links a bibliography file. The bibliography file is a JSON document containing URLs for referenced documents along with any algorithms they define.</p>
Expand Down
24 changes: 24 additions & 0 deletions test/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<pre class=metadata>toc: false</pre>
<p>Examples outside of clauses aren't processed specially.</p>
<emu-example>
This is an example.
</emu-example>
<emu-clause id="sec-example">
<h1>Example Section</h1>
<emu-example>
Examples inside clauses are numbered and have captions. Captions are optional.
</emu-example>
<emu-clause id="sec-example-subclause">
<h1>Example Subclause</h1>
<emu-example caption="An example">
Multiple examples are numbered similar to notes
</emu-example>
<emu-example caption="A second example">
So this becomes example 2.
</emu-example>
</emu-clause>
</emu-clause>
26 changes: 26 additions & 0 deletions test/example.html.baseline
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<head></head><body>
<p>Examples outside of clauses aren't processed specially.</p>
<emu-example>
This is an example.
</emu-example>

<emu-clause id="sec-example">
<h1><span class="secnum">1</span>Example Section<span class="utils"><span class="anchor"><a href="#sec-example">#</a></span></span></h1>
<emu-example><figure>
Examples inside clauses are numbered and have captions. Captions are optional.
<figcaption>Example (Informative)</figcaption></figure></emu-example>

<emu-clause id="sec-example-subclause">
<h1><span class="secnum">1.1</span>Example Subclause<span class="utils"><span class="anchor"><a href="#sec-example-subclause">#</a></span></span></h1>
<emu-example caption="An example"><figure>
Multiple examples are numbered similar to notes
<figcaption>Example 1 (Informative): An example</figcaption></figure></emu-example>

<emu-example caption="A second example"><figure>
So this becomes example 2.
<figcaption>Example 2 (Informative): A second example</figcaption></figure></emu-example>
</emu-clause>
</emu-clause>

</body>
Loading

0 comments on commit 22970e5

Please sign in to comment.