Skip to content

Commit 2a32b40

Browse files
committed
Add new floating toc
1 parent 6e0ea35 commit 2a32b40

13 files changed

+259
-24
lines changed

bin/args.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = require('nomnom')
1010
css: { metavar: 'FILE', help: 'Write Emu CSS dependencies to FILE' },
1111
js: { metavar: 'FILE', help: 'Write Emu JS dependencies to FILE' },
1212
toc: { flag: true, help: 'Don\'t include the table of contents' },
13+
oldToc: { full: 'old-toc', name: 'old-toc', flag: true, help: 'Use the old table of contents styling' },
1314
verbose: { flag: true, default: false, help: 'Display document build progress' },
1415
version: {
1516
abbr: 'v',

bin/ecmarkup.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ ecmarkup.build(args.infile, fetch, args).then(function (spec) {
3030
}
3131

3232
if (args.js) {
33-
fs.writeFileSync(args.js, fs.readFileSync(Path.join(__dirname, '../js/ecmarkup.js')));
33+
fs.writeFileSync(args.js, fs.readFileSync(Path.join(__dirname, '../js/menu.js')));
3434
}
3535
});

css/elements.css

+150-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
html {
2-
padding: 0 7em;
32
}
43

54
body {
@@ -8,8 +7,13 @@ body {
87
font-family: Cambria, Palatino Linotype, Palatino, Liberation Serif, serif;
98
padding: 0;
109
color: #333;
11-
max-width: 65em;
12-
margin: 0 auto;
10+
max-width: 844px;
11+
margin: 0 0 0 31%;
12+
overflow-x: hidden;
13+
}
14+
15+
body.oldtoc {
16+
margin: 0 auto;
1317
}
1418

1519
a {
@@ -327,3 +331,146 @@ del {
327331
del.block {
328332
display: block;
329333
}
334+
335+
/* Menu Styles */
336+
#menu-toggle {
337+
font-size: 2em;
338+
339+
position: fixed;
340+
top: 0;
341+
left: 0;
342+
width: 1.5em;
343+
height: 1.5em;
344+
z-index: 3;
345+
visibility: hidden;
346+
347+
background-color: #111;
348+
color: #B6C8E4;
349+
350+
line-height: 1.5em;
351+
text-align: center;
352+
-webkit-touch-callout: none;
353+
-webkit-user-select: none;
354+
-khtml-user-select: none;
355+
-moz-user-select: none;
356+
-ms-user-select: none;
357+
user-select: none;;
358+
359+
cursor: pointer;
360+
}
361+
362+
#menu {
363+
position: fixed;
364+
left: 0;
365+
top: 0;
366+
height: 100%;
367+
width: 24%;
368+
z-index: 2;
369+
overflow-x: hidden;
370+
overflow-y: auto;
371+
box-sizing: border-box;
372+
373+
background-color: #111;
374+
375+
transition: opacity 0.1s linear;
376+
}
377+
378+
#menu.active {
379+
display: block;
380+
opacity: 1;
381+
}
382+
383+
#menu-toc > ol {
384+
padding: 0;
385+
}
386+
387+
#menu-toc > ol , #menu-toc > ol ol {
388+
list-style-type: none;
389+
}
390+
391+
#menu-toc > ol ol {
392+
padding-left: 0.75em;
393+
}
394+
395+
#menu-toc li {
396+
text-overflow: ellipsis;
397+
overflow: hidden;
398+
white-space: nowrap;
399+
}
400+
401+
#menu-toc .item-toggle {
402+
display: inline-block;
403+
transform: rotate(-45deg) translate(-5px, -5px);
404+
transition: transform 0.1s ease;
405+
width: 1em;
406+
407+
color: #555F6E;
408+
409+
-webkit-touch-callout: none;
410+
-webkit-user-select: none;
411+
-khtml-user-select: none;
412+
-moz-user-select: none;
413+
-ms-user-select: none;
414+
user-select: none;;
415+
416+
cursor: pointer;
417+
}
418+
419+
#menu-toc .item-toggle-none {
420+
display: inline-block;
421+
width: 1em;
422+
}
423+
424+
#menu-toc li.active > .item-toggle {
425+
transform: rotate(0);
426+
}
427+
428+
#menu-toc li > ol {
429+
display: none;
430+
}
431+
432+
#menu-toc li.active > ol {
433+
display: block;
434+
}
435+
436+
#menu-toc li > a {
437+
padding-left: 0.25em;
438+
color: #B6C8E4;
439+
}
440+
441+
@media (max-width: 1366px) {
442+
body {
443+
margin: 0 0 0 150px;
444+
}
445+
446+
#menu {
447+
display: none;
448+
padding-top: 2em;
449+
width: 323px;
450+
}
451+
452+
#menu-toggle {
453+
visibility: visible;
454+
}
455+
}
456+
457+
@media only screen and (max-width: 800px) {
458+
body {
459+
margin: 2em 10px 0 10px;
460+
}
461+
462+
#menu {
463+
width: 100%;
464+
}
465+
466+
h1 .secnum {
467+
display: inline;
468+
position: inherit;
469+
left: 0;
470+
right: 0;
471+
}
472+
473+
h1 .secnum:empty {
474+
margin: 0; padding: 0;
475+
}
476+
}

js/menu.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use strict";
2+
3+
function Menu() {
4+
this.$toggle = document.getElementById('menu-toggle');
5+
this.$menu = document.getElementById('menu');
6+
7+
this.$toggle.addEventListener('click', this.toggle.bind(this));
8+
9+
var tocItems = this.$menu.querySelectorAll('#menu-toc li');
10+
for (var i = 0; i < tocItems.length; i++) {
11+
var $item = tocItems[i];
12+
$item.addEventListener('click', function($item, event) {
13+
$item.classList.toggle('active');
14+
event.stopPropagation();
15+
}.bind(null, $item));
16+
}
17+
18+
var tocLinks = this.$menu.querySelectorAll('#menu-toc li > a');
19+
for (var i = 0; i < tocLinks.length; i++) {
20+
var $link = tocLinks[i];
21+
$link.addEventListener('click', function(event) {
22+
this.toggle();
23+
event.stopPropagation();
24+
}.bind(this));
25+
}
26+
}
27+
28+
Menu.prototype.toggle = function () {
29+
this.$menu.classList.toggle("active");
30+
}
31+
32+
function init() {
33+
var menu = new Menu();
34+
}
35+
36+
document.addEventListener('DOMContentLoaded', init);

lib/Menu.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
const Builder = require('./Builder');
4+
const Toc = require('./Toc');
5+
6+
module.exports = class Menu extends Builder {
7+
build() {
8+
const toc = Toc.build(this.spec, true);
9+
const tocContainer = this.spec.doc.createElement('div');
10+
tocContainer.setAttribute('id', 'menu-toc');
11+
tocContainer.innerHTML = toc;
12+
13+
const menuContainer = this.spec.doc.createElement('div');
14+
menuContainer.setAttribute('id', 'menu');
15+
menuContainer.appendChild(tocContainer);
16+
17+
this.spec.doc.body.insertBefore(menuContainer, this.spec.doc.body.firstChild);
18+
19+
const menuToggle = this.spec.doc.createElement('div');
20+
menuToggle.setAttribute('id', 'menu-toggle');
21+
menuToggle.textContent = '☰';
22+
23+
this.spec.doc.body.insertBefore(menuToggle, this.spec.doc.body.firstChild);
24+
}
25+
};

lib/Spec.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const Algorithm = require('./Algorithm');
1313
const Dfn = require('./Dfn');
1414
const Note = require('./Note');
1515
const Toc = require('./Toc');
16+
const Menu = require('./Menu');
1617
const Production = require('./Production');
1718
const ProdRef = require('./ProdRef');
1819
const Grammar = require('./Grammar');
@@ -124,8 +125,15 @@ module.exports = class Spec {
124125
if (this.opts.toc) {
125126
p = p.then(function() {
126127
this._log('Building table of contents...');
127-
const tb = new Toc(this);
128-
return tb.build();
128+
129+
let toc;
130+
131+
if (this.opts.oldToc) {
132+
toc = new Toc(this);
133+
} else {
134+
toc = new Menu(this);
135+
}
136+
return toc.build();
129137
}.bind(this));
130138
}
131139

@@ -311,4 +319,3 @@ function assign(target, source) {
311319
target[k] = source[k];
312320
});
313321
}
314-

lib/Toc.js

+28-12
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,42 @@ module.exports = class Toc extends Builder {
99
return;
1010
}
1111

12-
const html = buildToc(this.spec);
12+
const html = Toc.build(this.spec);
1313
const tocContainer = this.spec.doc.createElement('div');
1414
tocContainer.innerHTML = '<h2>Table of Contents</h2>' + html;
1515
const intro = this.spec.doc.querySelector('emu-intro, emu-clause, emu-annex');
1616
intro.parentNode.insertBefore(tocContainer, intro);
17+
18+
const bodyClass = this.spec.doc.body.getAttribute('class') || '';
19+
this.spec.doc.body.setAttribute('class', bodyClass + ' oldtoc');
1720
}
18-
};
1921

20-
function buildToc(spec, level) {
21-
level = level || spec;
22+
static build(level, expandy) {
23+
let html = '<ol class="toc">';
24+
25+
level.subclauses.forEach(function(sub) {
26+
html += '<li>';
2227

23-
let html = '<ol class="toc">';
28+
if (expandy) {
29+
if (sub.subclauses.length > 0) {
30+
html += '<span class="item-toggle">◢</span>';
31+
} else {
32+
html += '<span class="item-toggle-none"></span>';
33+
}
34+
}
2435

25-
level.subclauses.forEach(function (sub) {
26-
html += '<li><a href="#' + sub.id + '"><span class="secnum">' + sub.number + '</span> ' + emd.fragment(sub.title) + '</a>';
27-
if (sub.subclauses.length > 0) html += buildToc(spec, sub);
28-
html += '</li>';
29-
});
36+
html += '<a href="#' + sub.id + '" title="' + sub.title + '"><span class="secnum">' + sub.number + '</span> ' + emd.fragment(shorten(sub.title)) + '</a>';
37+
if (sub.subclauses.length > 0) html += Toc.build(sub, expandy);
38+
html += '</li>';
39+
});
3040

31-
html += '</ol>';
41+
html += '</ol>';
42+
43+
return html;
44+
}
45+
};
3246

33-
return html;
47+
function shorten(title) {
48+
return title.replace('Static Semantics:', 'SS:')
49+
.replace('Runtime Semantics:', 'RS:');
3450
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ecmarkup",
3-
"version": "2.0.0-beta4",
3+
"version": "2.0.0-beta5",
44
"description": "Custom element definitions and core utilities for markup that specifies ECMAScript and related technologies.",
55
"main": "lib/ecmarkup.js",
66
"scripts": {

spec/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<!doctype html>
22
<meta charset="utf8">
33
<title>Ecmarkup</title>
4+
<script src="ecmarkup.js"></script>
45
<link rel="stylesheet" href="elements.css">
56
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/solarized_light.min.css">
67
<pre class=metadata>

test/build.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const Promise = require('bluebird');
44

55
const build = require('../lib/ecmarkup').build;
66

7-
const doc = '<!doctype html><emu-clause><h1>hi</h1></emu-clause>';
8-
const out = '<!doctype html>\n<head></head><body><div><h2>Table of Contents</h2><ol class="toc"><li><a href="#"><span class="secnum">1</span> hi</a></li></ol></div><emu-clause><h1><span class="secnum">1</span>hi<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1></emu-clause></body>';
7+
const doc = '<!doctype html><pre class=metadata>toc: false</pre><emu-clause><h1>hi</h1></emu-clause>';
8+
const out = '<!doctype html>\n<head></head><body><emu-clause><h1><span class="secnum">1</span>hi<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1></emu-clause></body>';
99
function fetch(file) {
1010
if (file.match(/\.json$/)) {
1111
return '{}';

test/clauses.html

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<pre class=metadata>oldToc: true</pre>
12
<emu-intro>
23
<h1>Intro</h1>
34
<emu-intro>

test/clauses.html.baseline

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<!doctype html>
2-
<head></head><body><div><h2>Table of Contents</h2><ol class="toc"><li><a href="#"><span class="secnum"></span> Intro</a><ol class="toc"><li><a href="#"><span class="secnum"></span> Sub Intro</a></li></ol></li><li><a href="#"><span class="secnum">1</span> Clause Foo(<var>a</var>, <var>b</var>)</a><ol class="toc"><li><a href="#Foo"><span class="secnum">1.1</span> Sub Clause</a></li></ol></li><li><a href="#"><span class="secnum">A</span> Annex</a><ol class="toc"><li><a href="#"><span class="secnum">A.1</span> Sub-annex</a></li></ol></li></ol></div><emu-intro>
2+
<head></head><body class=" oldtoc">
3+
<div><h2>Table of Contents</h2><ol class="toc"><li><a href="#" title="Intro"><span class="secnum"></span> Intro</a><ol class="toc"><li><a href="#" title="Sub Intro"><span class="secnum"></span> Sub Intro</a></li></ol></li><li><a href="#" title="Clause Foo(_a_, _b_)"><span class="secnum">1</span> Clause Foo(<var>a</var>, <var>b</var>)</a><ol class="toc"><li><a href="#Foo" title="Sub Clause"><span class="secnum">1.1</span> Sub Clause</a></li></ol></li><li><a href="#" title="Annex"><span class="secnum">A</span> Annex</a><ol class="toc"><li><a href="#" title="Sub-annex"><span class="secnum">A.1</span> Sub-annex</a></li></ol></li></ol></div><emu-intro>
34
<h1><span class="secnum"></span>Intro<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1>
45
<emu-intro>
56
<h1><span class="secnum"></span>Sub Intro<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1>

test/test.html.baseline

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!doctype html>
22
<head><meta charset="utf-8">
33
<link rel="stylesheet" href="https://bterlson.github.com/ecmarkup/elements.css">
4-
</head><body><div><h2>Table of Contents</h2><ol class="toc"><li><a href="#"><span class="secnum"></span> Intro</a><ol class="toc"><li><a href="#"><span class="secnum"></span> Sub Intro</a></li></ol></li><li><a href="#"><span class="secnum">1</span> Clause Foo(<var>a</var>, <var>b</var>)</a><ol class="toc"><li><a href="#Foo"><span class="secnum">1.1</span> Sub Clause</a></li><li><a href="#Bar"><span class="secnum">1.2</span> Sub Clause</a></li><li><a href="#Baz"><span class="secnum">1.3</span> Header</a><ol class="toc"><li><a href="#import3"><span class="secnum">1.3.1</span> Import 3</a></li></ol></li></ol></li><li><a href="#"><span class="secnum">A</span> Annex</a></li></ol></div><emu-intro>
4+
</head><body><div id="menu-toggle">☰</div><div id="menu"><div id="menu-toc"><ol class="toc"><li><span class="item-toggle">◢</span><a href="#" title="Intro"><span class="secnum"></span> Intro</a><ol class="toc"><li><span class="item-toggle-none"></span><a href="#" title="Sub Intro"><span class="secnum"></span> Sub Intro</a></li></ol></li><li><span class="item-toggle">◢</span><a href="#" title="Clause Foo(_a_, _b_)"><span class="secnum">1</span> Clause Foo(<var>a</var>, <var>b</var>)</a><ol class="toc"><li><span class="item-toggle-none"></span><a href="#Foo" title="Sub Clause"><span class="secnum">1.1</span> Sub Clause</a></li><li><span class="item-toggle-none"></span><a href="#Bar" title="Sub Clause"><span class="secnum">1.2</span> Sub Clause</a></li><li><span class="item-toggle">◢</span><a href="#Baz" title="Header"><span class="secnum">1.3</span> Header</a><ol class="toc"><li><span class="item-toggle-none"></span><a href="#import3" title="Import 3"><span class="secnum">1.3.1</span> Import 3</a></li></ol></li></ol></li><li><span class="item-toggle-none"></span><a href="#" title="Annex"><span class="secnum">A</span> Annex</a></li></ol></div></div><emu-intro>
55
<h1><span class="secnum"></span>Intro<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1>
66
<emu-intro>
77
<h1><span class="secnum"></span>Sub Intro<span class="utils"><span class="anchor"><a href="#">#</a></span></span></h1>

0 commit comments

Comments
 (0)