especser is an in-browser app to browse and read the ECMA-262 ECMAScript Standard Specification Edition 6.0. Written by Awal Garg aka Rash. on github at https://github.com/awalGarg/especser/
29 |
30 |
31 |
32 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "especser",
3 | "version": "1.0.0",
4 | "description": "browse the es spec",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Awal Garg aka Rash ",
10 | "license": "WTFPL",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/awalGarg/especser/"
14 | },
15 | "jspm": {
16 | "directories": {},
17 | "dependencies": {
18 | "fetch": "github:github/fetch@^0.9.0",
19 | "less": "github:aaike/jspm-less-plugin@^0.0.5",
20 | "localforage": "npm:localforage@^1.2.3"
21 | },
22 | "devDependencies": {
23 | "babel": "npm:babel-core@^5.1.13",
24 | "babel-runtime": "npm:babel-runtime@^5.1.13",
25 | "core-js": "npm:core-js@^0.9.4"
26 | }
27 | },
28 | "devDependencies": {
29 | "jspm": "^0.15.7",
30 | "less": "^2.5.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #especser
2 |
3 | especser is an in browser app to browse and read the ECMA-262 standard's 6th edition for ECMAScript standardized by ECMAInternational
4 |
5 | ##why
6 |
7 | the es specs are pretty much awful to read. even more awful to navigate. especser presents the spec in an easy on eyes way, with fuzzy searching of the different sections in the spec, tabbed browsing support, internal routing of links etc.
8 |
9 | ##how
10 |
11 | 1. goto http://awalGarg.github.io/especser
12 | 2. click the update button on the corner
13 | 3. this will fetch the spec directly from http://ecma-international.org/ecma-262/6.0/index.html, pass it through some weirdo functions, store a json map and different parts of the spec in indexedDB
14 | 4. you only have to do this once, and the spec will only be fetched once
15 | 5. you can search for stuff you want. use up/down arrow keys to select one of the results and hit enter (or click on one of the search result)
16 | 6. press `Ctrl+P` to toggle the top-bar
17 | 7. opened tabs are shown on the sidebar on the left.
18 | 8. top of the content is shown a path to the present page. you can click on any link in between to open that
19 | 9. bottom of the content is shown a list of links to sub-sections for the page if any
20 | 10. click on the large index number at the top-left of any content page and copy the url in the address bar to share a perma-link to that section with anyone else
21 | 11. links inside the spec are internal. so clicking on any link inside the spec will open that section within the app
22 | 12. you can remove the data from indexedDB by clicking the clear store button
23 | 13. keep hitting the down arrow key while searching to extract more results
24 | 14. if your search starts with `sec: `, it will list all those sections and subsections. if a query follows, only sections matching it will be listed.
25 |
26 | ##running locally
27 |
28 | - clone repo
29 | - `npm install`
30 | - `jspm install`
31 | - `iojs build.js`
32 | - start a webserver in the project root
33 | - open the url to the server
34 |
35 | ##screenshots
36 |
37 | ofcourse
38 |
39 | 
40 |
41 | 
42 |
43 | ##license
44 |
45 | WTFPL
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | export let config = {
2 | // SPEC_URL: '/spec_cache.html',
3 | SPEC_URL: 'http://crossorigin.me/http://www.ecma-international.org/ecma-262/6.0/index.html',
4 | IDBstoreName: 'sec'
5 | };
--------------------------------------------------------------------------------
/src/css/content.css:
--------------------------------------------------------------------------------
1 | /**
2 | * directly copied from ecmascript's own css
3 | */
4 | .tab-content { /* this one is slightly modified... maaybe */
5 | background-color: #fdfdfc;
6 | color: #333333;
7 | font-family: Cambria, Palatino Linotype, Palatino, Liberation Serif, serif;
8 | font-size: 17px;
9 | line-height: 135%;
10 | padding: 1rem;
11 |
12 | h1 {
13 | font-size: 110%;
14 | margin-bottom: 0.8em;
15 | padding-bottom: 0.2em;
16 | position: sticky;
17 | top: 0;
18 | z-index: 1;
19 | background-color: #fdfdfc;
20 | box-shadow: 0 0 6px #fdfdfc;
21 | margin-left: -7em;
22 | padding-left: 7em;
23 | }
24 |
25 | .stern.warning {
26 | font-weight: bold;
27 | text-transform: uppercase;
28 | }
29 |
30 | p.ECMAaddress {
31 | margin-bottom: 0em;
32 | margin-top: 0em;
33 | }
34 |
35 | p.normalBullet {
36 | margin-left: 4em;
37 | text-indent: -1.7em;
38 | margin-top: 0em;
39 | margin-bottom: 0.25em;
40 | }
41 |
42 | p.normalBulletSubstep {
43 | margin-left: 6em;
44 | text-indent: -1em;
45 | margin-top: 0em;
46 | margin-bottom: 0.25em;
47 | }
48 |
49 | pre.NoteCode {
50 | margin-bottom: 0em;
51 | margin-top: 0em;
52 | }
53 |
54 | div.note {
55 | margin: 1em 0 1em 6em;
56 | }
57 |
58 | span.nh {
59 | float: left;
60 | width: 6em;
61 | margin-left: -6em;
62 | }
63 |
64 | figure {
65 | display: block;
66 | margin: 1em 0 3em 0;
67 | }
68 |
69 | figure object {
70 | display: block;
71 | margin: 0 auto;
72 | }
73 |
74 | figure table.real-table {
75 | margin: 0 auto;
76 | }
77 |
78 | figure figcaption {
79 | display: block;
80 | color: #555555;
81 | font-weight: bold;
82 | text-align: center;
83 | margin-bottom: 0.25em;
84 | }
85 |
86 | figcaption :target {
87 | /* When a user visits #table-1, slide the caption down
88 | so it won't be obscured by a sticky heading (issue #73).
89 | Thanks to Claude Pache for this "nasty trick" (his words). */
90 | display: inline-block;
91 | padding-top: 2em;
92 | margin-top: -2em;
93 | }
94 |
95 | table.real-table {
96 | border-collapse: collapse;
97 | }
98 |
99 | table.real-table td, table.real-table th {
100 | border: 1px solid black;
101 | padding: 0.4em;
102 | vertical-align: baseline;
103 | }
104 |
105 | table.real-table th {
106 | background-color: #eeeeee;
107 | }
108 |
109 | table.lightweight-table {
110 | border-collapse: collapse;
111 | margin: 0 0 0 1.5em;
112 | }
113 |
114 | table.lightweight-table td, table.lightweight-table th {
115 | border: none;
116 | padding: 0 0.5em;
117 | vertical-align: baseline;
118 | }
119 |
120 | div.display {
121 | margin: 1em 0 1em 2em;
122 | }
123 |
124 | div.gp {
125 | margin-left: 2.4em;
126 | margin-top: 0.9em;
127 | }
128 |
129 | div.gp.prod {
130 | margin-left: 0;
131 | }
132 |
133 | div.rhs {
134 | margin-left: 2.4em;
135 | margin-right: -10em;
136 | }
137 |
138 | div.pile {
139 | margin-left: 2.4em;
140 | max-width: 40em;
141 | }
142 |
143 | div.keyword.pile code {
144 | float: left;
145 | width: 25%;
146 | }
147 |
148 | div.keyword5.pile code {
149 | float: left;
150 | width: 20%;
151 | }
152 |
153 | div.operator.pile code {
154 | float: left;
155 | width: 16%;
156 | }
157 |
158 | div.end-pile {
159 | clear: both;
160 | }
161 |
162 | sub.g-opt {
163 | color: #d1009e;
164 | /* sort of magenta */
165 | }
166 |
167 | sub.g-params {
168 | color: #49a08a;
169 | /* sort of aqua */
170 | }
171 |
172 | code {
173 | /* including code.t, meaning "terminal" or "token" */
174 | font-weight: bold;
175 | color: #555555;
176 | }
177 |
178 | span.nt {
179 | /* nonterminal */
180 | font-family: Times New Roman, Times, FreeSerif, serif;
181 | font-style: italic;
182 | }
183 |
184 | span.geq {
185 | font-weight: bold;
186 | }
187 |
188 | span.grhsmod {
189 | /* right-hand side modifier, like "one of", "but not" */
190 | font-weight: bold;
191 | color: #555555;
192 | }
193 |
194 | span.grhsannot {
195 | /* right-hand side annotation, like "[empty]" */
196 | font-family: Helvetica, Arial, Liberation Sans, sans-serif;
197 | font-size: smaller;
198 | }
199 |
200 | span.chgloss {
201 | /* gloss for a character, like "asterisk" */
202 | font-style: italic;
203 | }
204 |
205 | span.gprose {
206 | font-family: Helvetica, Arial, Liberation Sans, sans-serif;
207 | font-size: 90%;
208 | }
209 |
210 | div.gsumxref {
211 | /* grammar summary cross-reference, used in Annex A */
212 | width: 8em;
213 | float: right;
214 | }
215 |
216 | span.prod {
217 | margin-left: 5pt;
218 | margin-right: 5pt;
219 | }
220 |
221 | div.rhs > code.t,
222 | div.rhs > span.nt,
223 | div.rhs > span.grhsannot,
224 | div.rhs > span.grhsmod,
225 | div.rhs > span.chgloss,
226 | div.rhs > span.gprose,
227 | div.rhs > var,
228 | .prod > span.geq,
229 | .prod > code.t,
230 | .prod > span.nt,
231 | .prod > span.grhsannot,
232 | .prod > span.grhsmod,
233 | .prod > span.chgloss,
234 | .prod > span.gprose,
235 | div.rhs > var {
236 | margin-left: 5pt;
237 | }
238 |
239 | div.rhs > code.t:first-child,
240 | div.rhs > span.nt:first-child,
241 | div.rhs > span.grhsannot:first-child,
242 | div.rhs > span.grhsmod:first-child,
243 | div.rhs > span.chgloss:first-child,
244 | div.rhs > span.gprose:first-child,
245 | div.rhs > var:first-child,
246 | .prod > span.geq:first-child,
247 | .prod > code.t:first-child,
248 | .prod > span.nt:first-child,
249 | .prod > span.grhsannot:first-child,
250 | .prod > span.grhsmod:first-child,
251 | .prod > span.chprose:first-child,
252 | .prod > span.gprose:first-child,
253 | .prod > var:first-child {
254 | margin-left: 0;
255 | }
256 |
257 | ul > li {
258 | list-style-type: disc;
259 | }
260 |
261 | ul > li > p {
262 | margin-bottom: 0.25em;
263 | margin-top: 0em;
264 | }
265 |
266 | ol.proc {
267 | margin-top: 0.5em;
268 | }
269 |
270 | ol.proc > li {
271 | list-style-type: decimal;
272 | }
273 |
274 | ol.proc > li > ol.block > li {
275 | list-style-type: lower-latin;
276 | }
277 |
278 | .tab-content
279 | ol.proc > li > ol.block > li > ol.block > li {
280 | list-style-type: lower-roman;
281 | }
282 |
283 | ol.proc > li > ol.block > li > ol.block > li >
284 | ol.block > li {
285 | list-style-type: decimal;
286 | }
287 |
288 | ol.proc > li > ol.block > li > ol.block > li >
289 | ol.block > li > ol.block > li {
290 | list-style-type: lower-latin;
291 | }
292 |
293 | .tab-content
294 | ol.proc > li > ol.block > li > ol.block > li >
295 | ol.block > li > ol.block > li > ol.block > li {
296 | list-style-type: lower-roman;
297 | }
298 |
299 | p.special1 {
300 | padding-left: +3em;
301 | text-indent: -1em;
302 | }
303 |
304 | p.special2 {
305 | padding-left: +11em;
306 | text-indent: -1em;
307 | }
308 |
309 | p.special3 {
310 | padding-left: +6em;
311 | text-indent: -1em;
312 | }
313 |
314 | p.special4 {
315 | padding-left: +3em;
316 | text-indent: -1em;
317 | }
318 | }
--------------------------------------------------------------------------------
/src/css/fonts.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Copyright 2013
3 | * Open Sans is licensed under the Apache License version 2.0.
4 | */
5 | @font-face{font-family:'Open Sans';src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:normal;font-style:normal}@font-face{font-family:'Open Sans';src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:bold;font-style:normal}@font-face{font-family:'Open Sans';src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:normal;font-style:italic}@font-face{font-family:'Open Sans';src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:bold;font-style:italic}
--------------------------------------------------------------------------------
/src/css/layout.css:
--------------------------------------------------------------------------------
1 | *, *:after, *:before {
2 | box-sizing: border-box;
3 | outline: 0px;
4 | margin: 0px;
5 | }
6 | input, form, fieldset, div, p, section, body, html {
7 | padding: 0px;
8 | }
9 | body {
10 | background-color: #303030;
11 | color: #c9c9c9;
12 | font: normal 1em/1.7 "Open Sans", Helvetica, Arial, sans-serif;
13 | height: 100vh;
14 | width: 100vw;
15 | word-wrap: break-word;
16 | overflow-wrap: break-word;
17 | display: flex;
18 | flex-direction: column;
19 | }
20 |
21 | /* layout */
22 | #top-bar {
23 | background: #212121;
24 | width: 100%;
25 | display: flex;
26 | border: 1px solid #333;
27 | position: absolute;
28 | z-index: 5;
29 |
30 | .logoish {
31 | color: inherit;
32 | padding: 0 1rem;
33 | font-style: italic;
34 | text-shadow: 0px 0px 0.2rem;
35 | text-decoration: none;
36 | }
37 |
38 | #search-form {
39 | flex-grow: 1;
40 | height: 2rem;
41 | line-height: 100%;
42 | background-color: inherit;
43 |
44 | input {
45 | width: 100%;
46 | height: 2rem;
47 | border-radius: 0;
48 | border: 1px solid #333;
49 | border-width: 0px 1px 0px 0px;
50 | font: inherit;
51 | font-size: 0.875rem;
52 | background-color: rgba(0, 0, 0, 0.5);
53 | color: #fff;
54 | padding: 0em 1rem;
55 | position: relative;
56 | }
57 | #search-results {
58 | background-color: inherit;
59 | border: 1px solid #333;
60 | padding: 0;
61 | list-style: none;
62 | max-height: 80vh;
63 | overflow-y: auto;
64 |
65 | .result {
66 | display: block;
67 | padding: 0.5rem 1rem;
68 | font-size: 0.875rem;
69 | color: inherit;
70 | text-decoration: none;
71 |
72 | .result-heading {
73 | font-weight: normal;
74 | }
75 | .result-path, .result-index {
76 | font-size: small;
77 | padding-right: 0.5rem;
78 | }
79 | }
80 | .result.active {
81 | background-color: #4C4C4C;
82 | }
83 | }
84 | }
85 | .option-box {
86 | white-space: nowrap;
87 | margin: 0 1em;
88 |
89 | button {
90 | background: transparent;
91 | color: inherit;
92 | border-width: 0px;
93 | font: inherit;
94 | font-size: 0.8rem;
95 | padding: 0 0.2rem;
96 | cursor: pointer;
97 | }
98 | }
99 | }
100 |
101 | .content-wrapper {
102 | display: flex;
103 | flex-grow: 1;
104 | position: relative;
105 |
106 | #sidebar {
107 | position: relative;
108 | min-width: 20vw;
109 | max-width: 20vw;
110 | border-right: 1px solid rgba(255, 255, 255, 0.2);
111 | position: relative;
112 | overflow-y: auto;
113 |
114 | #open-tab-descriptors {
115 | list-style: none;
116 | color: inherit;
117 | padding: 0;
118 | font-size: 0.875rem;
119 | white-space: nowrap;
120 |
121 | li {
122 | height: 2.5rem;
123 | border: 1px inset #6b6b6b;
124 | display: flex;
125 | align-items: center;
126 | font-weight: bold;
127 | padding: 0;
128 | border-width: 1px 0px;
129 |
130 | div.tab-descriptor.link-tab-descriptor {
131 | display: flex;
132 | text-overflow: ellipsis;
133 | overflow: hidden;
134 | align-items: center;
135 | width: 100%;
136 | padding: 0 1rem;
137 | height: 100%;
138 |
139 | a.link-tab-activate {
140 | flex-grow: 1;
141 | color: inherit;
142 | text-decoration: inherit;
143 | text-overflow: ellipsis;
144 | overflow: hidden;
145 | }
146 |
147 | span.tab-close {
148 | display: inline-block;
149 | margin-left: auto;
150 | }
151 |
152 | span.tab-close:before {
153 | content: '✕';
154 | }
155 | }
156 |
157 | div.tab-descriptor.link-tab-descriptor.active {
158 | background-color: #232323;
159 | }
160 | }
161 |
162 | li:first-of-type {
163 | border-top: 1px inset #111;
164 | }
165 | }
166 |
167 | }
168 |
169 | #content {
170 | flex-grow: 1;
171 | overflow-x: hidden;
172 | overflow-y: auto;
173 | position: relative;
174 | }
175 |
176 | .__info {
177 | border: 1px solid #111;
178 | background: #232323;
179 | color: white;
180 | padding: 0.5rem 1rem;
181 | border-radius: 0.3rem;
182 | font: normal 0.875rem 'Open Sans';
183 |
184 | a {
185 | text-decoration: inherit;
186 | color: inherit;
187 | font-weight: inherit;
188 | }
189 |
190 | .__info-path a {
191 | margin-right: 0.5rem;
192 | }
193 |
194 | .__info-path a:after {
195 | content: '»';
196 | margin-left: 0.5rem;
197 | }
198 |
199 | .__info-path a:last-of-type:after {
200 | content: '';
201 | }
202 |
203 | .__info-label {
204 | display: inline-block;
205 | line-height: 200%;
206 | }
207 | }
208 |
209 | .__info:first-of-type {
210 | margin-bottom: 2rem;
211 | }
212 |
213 | .__info:last-of-type {
214 | margin-top: 2rem;
215 | }
216 |
217 |
218 | .__info-children span {
219 | margin-right: 0.5rem;
220 | }
221 |
222 | }
223 |
224 | #console {
225 | position: absolute;
226 | bottom: 0;
227 | width: 100%;
228 | color: white;
229 | background-color: #111;
230 | }
231 |
232 | /* meta classes */
233 | .abs {
234 | position: absolute;
235 | }
236 | .hidden {
237 | display: none!important;
238 | }
239 | .reveal-on-parent-hover {
240 | display: none;
241 | }
242 | *:hover .reveal-on-parent-hover {
243 | display: block;
244 | }
245 | .static-background {
246 | bottom: 10px;
247 | background-color: inherit;
248 | position: fixed;
249 | display: flex;
250 | justify-content: center;
251 | align-items: center;
252 | padding: 0 1rem;
253 | opacity: 0.5;
254 | z-index: -1;
255 | }
256 |
--------------------------------------------------------------------------------
/src/domhandler.js:
--------------------------------------------------------------------------------
1 | import * as Spec from './spec';
2 | import * as Shortcuts from './mod/shortcuts';
3 | import * as Utils from './mod/utils';
4 | import {domconsole} from './mod/domconsole';
5 |
6 | /**
7 | * helpers for handlers
8 | */
9 |
10 | function emphasizeSearch (search, text) {
11 | return text.replace(RegExp(Utils.re.escape(search), 'gi'), '$&');
12 | }
13 |
14 | /**
15 | * event handlers
16 | */
17 |
18 | // a live nodelist increases performance in the following event handlers
19 | let results = document.getElementById('search-results').getElementsByClassName('result');
20 | let inputBox = $.nam('search');
21 | let active = inputBox;
22 | let resultsGenerator;
23 | let resultsBox = $.id('search-results');
24 |
25 | function createResultList (results, val) {
26 | return results.map(res => $.make('li', {
27 | childNodes: [$.make('a', {
28 | classList: ['result', 'link-newtab'],
29 | href: `#${encodeURIComponent(res.index)}`,
30 | dataset: {
31 | index: res.index
32 | },
33 | on: {
34 | click: function (e) {
35 | e.preventDefault();
36 | active.classList.remove('active');
37 | this.classList.add('active');
38 | active = this;
39 | form$onEnter.call($.id('search-form'), {target: inputBox});
40 | }
41 | },
42 | childNodes: [
43 | $.make('h4', {
44 | classList: ['result-heading'],
45 | innerHTML: emphasizeSearch(val, res.title)
46 | }),
47 | $.make('span', {
48 | classList: ['result-index'],
49 | textContent: res.index
50 | }),
51 | $.make('span', {
52 | classList: ['result-path'],
53 | textContent: Spec.indexToPath(res.index)
54 | })
55 | ]
56 | })]
57 | }));
58 | }
59 |
60 | function input$onInput () {
61 | let val = this.value.trim();
62 | resultsGenerator = Spec.search(val);
63 | active = inputBox;
64 |
65 | let resultList = createResultList(resultsGenerator.next().value, val);
66 |
67 | $$.tag('li', resultsBox).forEach($.remove);
68 |
69 | resultList.forEach(el => $.append(el, resultsBox));
70 | }
71 |
72 | function form$onKeyDown (ev) {
73 | const DOWN_ARROW = 40;
74 | const UP_ARROW = 38;
75 | const ENTER_KEY = 13;
76 | const ESC_KEY = 27;
77 |
78 | switch (ev.keyCode || ev.which) {
79 | case DOWN_ARROW:
80 | ev.preventDefault();
81 | form$onDownArrow.call(this);
82 | break;
83 | case UP_ARROW:
84 | ev.preventDefault();
85 | form$onUpArrow.call(this);
86 | break;
87 | case ENTER_KEY:
88 | ev.preventDefault();
89 | ev.stopImmediatePropagation();
90 | form$onEnter.call(this, ev);
91 | break;
92 | case ESC_KEY:
93 | ev.preventDefault();
94 | ev.stopImmediatePropagation();
95 | form$onEscape.call(this);
96 | break;
97 | }
98 | }
99 |
100 | function form$onDownArrow () {
101 | if (active === inputBox) {
102 | return results[0] && simulateFocus(results[0]);
103 | }
104 | if (active.classList.contains('result')) {
105 | if (active === resultsBox.lastElementChild.firstElementChild) {
106 | let moreResults = resultsGenerator.next();
107 | if (moreResults.done) return;
108 | if (moreResults.value.length) {
109 | let resultList = createResultList(moreResults.value, inputBox.value.trim());
110 | resultList.forEach(el => $.append(el, resultsBox));
111 | simulateFocus(resultList[0].firstChild);
112 | return;
113 | }
114 | return;
115 | }
116 | try {
117 | return simulateFocus(active.parentNode.nextElementSibling.firstChild);
118 | } catch (er) {}
119 | }
120 | }
121 |
122 | function form$onUpArrow () {
123 | if (active === inputBox) {
124 | let lastResult = results[results.length - 1];
125 | if (lastResult) {
126 | return simulateFocus(lastResult);
127 | }
128 | else return;
129 | }
130 | if (active.classList.contains('result')) {
131 | if (active === results[0]) {
132 | return;
133 | }
134 | try {
135 | return simulateFocus(active.parentNode.previousElementSibling.firstChild);
136 | } catch (err) {}
137 | }
138 | }
139 |
140 | function form$onEnter (ev) {
141 | let target = ev.target || ev.srcElement;
142 | if (target !== inputBox) return;
143 |
144 | if (!active.classList.contains('result')) return;
145 | target = active;
146 | openTab(target.dataset.index);
147 | form$onEscape.call(this);
148 | }
149 |
150 | function form$onEscape () {
151 | this.parentNode.classList.add('hidden');
152 | }
153 |
154 | function simulateFocus (el) {
155 | active.classList.remove('active');
156 | el.classList.add('active');
157 | active = el;
158 | el.scrollIntoView();
159 | }
160 |
161 | function window$loaded (ev) {
162 | if (window.localStorage.getItem('lastIndexed')) {
163 | Spec.initialize().then(_ => app$navigated.call(this, ev));
164 | }
165 | else {
166 | domconsole.log('hi! especser is an app to search the ECMAScript specification ed6.0. please click update to cache spec for the first time.');
167 | }
168 | }
169 |
170 | function app$navigated (ev) {
171 | let newIndex = window.location.hash.replace('#', '').trim();
172 | let frame = Spec.indexToFrame(newIndex);
173 | if (frame) {
174 | Promise.resolve(openTab(newIndex)).then(_ => $.id('top-bar').classList.add('hidden'));
175 | }
176 | }
177 |
178 | /**
179 | * attach the above awesomeness to dom!
180 | */
181 |
182 | inputBox.addEventListener('input', Utils.throttle(input$onInput, 200, inputBox, 'discard-repeats'), true);
183 | $.id('search-form').addEventListener('keydown', form$onKeyDown, false);
184 | $.id('btn-update').addEventListener('click', Spec.initialize, false);
185 | $.id('btn-clear').addEventListener('click', Spec.clear, false);
186 | window.addEventListener('hashchange', app$navigated, false);
187 | window.addEventListener('load', window$loaded);
188 |
189 | /**
190 | * tab creation, previewing, and handling
191 | */
192 |
193 | import {TabGroup, Tab} from './mod/tabbing';
194 |
195 | let group = new TabGroup();
196 |
197 | let content = $.id('content');
198 | let suspendedTabs = $.id('suspended-tabs');
199 | let descriptorList = $.id('open-tab-descriptors');
200 |
201 | let state = {
202 | open: Object.create(null),
203 | tokenToIndexMap: Object.create(null),
204 | get activeTabIndex () {
205 | let el = $.cl('tab-content', content);
206 | if (!el) return;
207 | return el.dataset.secIndex;
208 | }
209 | };
210 |
211 | function openTab (index) {
212 | if (index in state.open) {
213 | return group.open(state.open[index]);
214 | }
215 |
216 | let tabData = Spec.indexToFrame(index);
217 |
218 | let descriptor = createDescriptor(tabData);
219 | descriptorList.appendChild(descriptor);
220 | descriptor.scrollIntoView();
221 |
222 | let tab = new Tab(tabData.title, tabData.path, index);
223 | let tabToken = group.attach(tab);
224 |
225 | state.open[index] = tabToken;
226 | state.tokenToIndexMap[tabToken] = index;
227 | }
228 |
229 | function createDescriptor (res) {
230 | return $.make('li', {
231 | childNodes: [
232 | $.make('div', {
233 | classList: ['tab-descriptor', 'link-tab-descriptor', 'active'],
234 | childNodes: [
235 | $.make('a', {
236 | textContent: res.title,
237 | href: `#${res.index}`,
238 | dataset: {
239 | index: res.index
240 | },
241 | classList: ['link-tab-activate']
242 | }),
243 | $.make('span', {
244 | classList: ['tab-close'],
245 | on: {
246 | click: function () {
247 | group.detach(state.open[res.index]);
248 | $.remove(this.parentNode.parentNode);
249 | }
250 | }
251 | })
252 | ]
253 | })
254 | ]
255 | });
256 | }
257 |
258 | function closeTab (index) {
259 | if (!(index in state.open)) {
260 | return;
261 | }
262 | group.detach(state.open[index]);
263 | delete state.tokenToIndexMap[token];
264 | delete state.open[index];
265 | }
266 |
267 | function storeAsSuspended (index, data) {
268 | if (!data) return;
269 | $.remove(data);
270 | $.apply(data, {
271 | classList: ['tab-content'],
272 | dataset: {
273 | secIndex: index
274 | }
275 | });
276 | suspendedTabs.appendChild(data);
277 | }
278 |
279 | function getDescriptor (index) {
280 | return $.data('index=', index, descriptorList).parentNode.parentNode;
281 | }
282 |
283 | function suspendActiveTab () {
284 | let index = state.activeTabIndex;
285 | if (!index) return;
286 | let data = $.data('sec-index=', index, content);
287 | storeAsSuspended(index, data);
288 | }
289 |
290 | function getFromSuspended (index) {
291 | return $.data('sec-index=', index, suspendedTabs);
292 | }
293 |
294 | function onAttach ({id: token}) {
295 | let index = group.tabs[token].meta;
296 |
297 | let el = generateView(Spec.indexToFrame(index));
298 | el.then(data => storeAsSuspended(index, data)).then(_ => group.open(token));
299 | }
300 |
301 | function onOpen ({id: token}) {
302 | let index = group.tabs[token].meta;
303 | suspendActiveTab();
304 | content.appendChild(getFromSuspended(index));
305 | $.cl('tab-descriptor', getDescriptor(index)).classList.add('active');
306 | }
307 |
308 | function onClose ({id: token}) {
309 | suspendActiveTab();
310 | $.cl('active', descriptorList).classList.remove('active');
311 | }
312 |
313 | function onDetach ({id: token}) {
314 | $.remove(getFromSuspended(state.tokenToIndexMap[token]));
315 | group.restoreLast();
316 | }
317 |
318 | group.events.on('open', onOpen);
319 | group.events.on('close', onClose);
320 | group.events.on('attach', onAttach);
321 | group.events.on('detach', onDetach);
322 |
323 | function generateView (res) {
324 | let path = Spec.indexToPath(res.index);
325 | let info = $.make('div', {
326 | classList: ['__info'],
327 | childNodes: [
328 | $.make('span', {classList: ['__info-label'], textContent: 'Path till here'}),
329 | $.make('h4', {
330 | classList: ['__info-path'],
331 | childNodes: [...res.path.map(place => $.make('a', {
332 | href: `#${place}`,
333 | textContent: Spec.indexToFrame(place).title
334 | }))]
335 | })
336 | ]
337 | });
338 | let children = $.make('div', {
339 | classList: ['__info'],
340 | childNodes: [
341 | $.make('span', {classList: ['__info-label'], textContent: 'Topics inside'}),
342 | $.make('h4', {
343 | classList: ['__info-children'],
344 | childNodes: res.children.length ? [...res.children.map(child => $.make('div', {
345 | childNodes: [
346 | $.make('span', {
347 | classList: ['__info-children-index'],
348 | textContent: child
349 | }),
350 | $.make('a', {
351 | classList: ['__info-children-anchor'],
352 | href: `#${child}`,
353 | textContent: Spec.indexToFrame(child).title
354 | })
355 | ]
356 | }))] : [$.make('span', {textContent: 'none'})]
357 | })
358 | ]
359 | });
360 | let content = $.make('div', {
361 | classList: ['tab-content'],
362 | childNodes: [info]
363 | });
364 | return Spec.Store.getItem(res.index).then(
365 | html => {
366 | content.insertAdjacentHTML('beforeend', html);
367 | content.appendChild(children);
368 | return content;
369 | }
370 | );
371 | }
372 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import * as Shortcuts from './mod/shortcuts';
2 | import './mod/sdm';
3 | import './domhandler';
4 | import * as Spec from './spec';
5 | import {domconsole} from './mod/domconsole';
6 |
7 | let topbar = $.id('top-bar'), search = $.nam('search');
8 |
9 | Shortcuts.register({modifier: 'Ctrl', key: 'P'}, function (e) {
10 | e.preventDefault();
11 | topbar.classList.toggle('hidden');
12 | if (topbar.classList.contains('hidden')) return;
13 | search.focus();
14 | });
15 |
16 | Shortcuts.register({key: 'Esc'}, function (e) {
17 | e.preventDefault();
18 | topbar.classList.add('hidden');
19 | });
20 |
--------------------------------------------------------------------------------
/src/mod/domconsole.js:
--------------------------------------------------------------------------------
1 | let c = $.id('console');
2 | export let domconsole = {
3 | log (...args) {
4 | c.classList.remove('hidden');
5 | c.style.color = '';
6 | c.textContent = args.join(' ');
7 | },
8 | error (...args) {
9 | c.classList.remove('hidden');
10 | c.style.color = 'red';
11 | c.textContent = args.join(' ');
12 | },
13 | clear () {
14 | c.style.color = '';
15 | c.textContent = '';
16 | }
17 | }
--------------------------------------------------------------------------------
/src/mod/events.js:
--------------------------------------------------------------------------------
1 | export class EventEmitter {
2 |
3 | constructor () {
4 | this.events = {
5 | any: []
6 | };
7 | }
8 |
9 | on (event, listener) {
10 | if (!this.events[event]) {
11 | this.events[event] = [];
12 | }
13 | this.events[event].push(listener);
14 | }
15 |
16 | once (event, listener) {
17 | let that = this;
18 | this.on(event, function oneTimeListener (...data) {
19 | listener.apply(null, data);
20 | that.off(event, oneTimeListener);
21 | });
22 | }
23 |
24 | off (event, listener) {
25 | if (!this.events[event]) {
26 | return;
27 | }
28 | if (!listener) {
29 | this.events[event] = [];
30 | return;
31 | }
32 | let s = this.events[event];
33 | let i = s.indexOf(listener);
34 | if (i === -1) {
35 | return;
36 | }
37 | s.splice(i, 1);
38 | }
39 |
40 | emit (event, ...data) {
41 | let s = this.events[event];
42 | if (!s || !s.length) return;
43 | return Promise.all(
44 | s.map(
45 | fn => Promise.resolve(
46 | fn.apply(null, data)
47 | )
48 | )
49 | );
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/mod/localforage.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | localForage -- Offline Storage, Improved
3 | Version 1.2.2
4 | https://mozilla.github.io/localForage
5 | (c) 2013-2015 Mozilla, Apache License 2.0
6 | */
7 | !function(){var a,b,c,d;!function(){var e={},f={};a=function(a,b,c){e[a]={deps:b,callback:c}},d=c=b=function(a){function c(b){if("."!==b.charAt(0))return b;for(var c=b.split("/"),d=a.split("/").slice(0,-1),e=0,f=c.length;f>e;e++){var g=c[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(d._eak_seen=e,f[a])return f[a];if(f[a]={},!e[a])throw new Error("Could not find module "+a);for(var g,h=e[a],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)k.push("exports"===i[l]?g={}:b(c(i[l])));var n=j.apply(this,k);return f[a]=g||n}}(),a("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;jb;b+=4)c=e.indexOf(a[b]),d=e.indexOf(a[b+1]),f=e.indexOf(a[b+2]),g=e.indexOf(a[b+3]),l[j++]=c<<2|d>>4,l[j++]=(15&d)<<4|f>>2,l[j++]=(3&f)<<6|63&g;return k}function d(a){var b,c=new Uint8Array(a),d="";for(b=0;b>2],d+=e[(3&c[b])<<4|c[b+1]>>4],d+=e[(15&c[b+1])<<2|c[b+2]>>6],d+=e[63&c[b+2]];return c.length%3===2?d=d.substring(0,d.length-1)+"=":c.length%3===1&&(d=d.substring(0,d.length-2)+"=="),d}var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f="__lfsc__:",g=f.length,h="arbf",i="blob",j="si08",k="ui08",l="uic8",m="si16",n="si32",o="ur16",p="ui32",q="fl32",r="fl64",s=g+h.length,t={serialize:a,deserialize:b,stringToBuffer:c,bufferToString:d};"undefined"!=typeof module&&module.exports?module.exports=t:"function"==typeof define&&define.amd?define("localforageSerializer",function(){return t}):this.localforageSerializer=t}.call(window),function(){"use strict";function a(a){var b=this,c={db:null};if(a)for(var d in a)c[d]=a[d];return new k(function(a,d){var e=l.open(c.name,c.version);e.onerror=function(){d(e.error)},e.onupgradeneeded=function(){e.result.createObjectStore(c.storeName)},e.onsuccess=function(){c.db=e.result,b._dbInfo=c,a()}})}function b(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=f.get(a);g.onsuccess=function(){var a=g.result;void 0===a&&(a=null),b(a)},g.onerror=function(){d(g.error)}})["catch"](d)});return j(d,b),d}function c(a,b){var c=this,d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=f.openCursor(),h=1;g.onsuccess=function(){var c=g.result;if(c){var d=a(c.value,c.key,h++);void 0!==d?b(d):c["continue"]()}else b()},g.onerror=function(){d(g.error)}})["catch"](d)});return j(d,b),d}function d(a,b,c){var d=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var e=new k(function(c,e){d.ready().then(function(){var f=d._dbInfo,g=f.db.transaction(f.storeName,"readwrite"),h=g.objectStore(f.storeName);null===b&&(b=void 0);var i=h.put(b,a);g.oncomplete=function(){void 0===b&&(b=null),c(b)},g.onabort=g.onerror=function(){var a=i.error?i.error:i.transaction.error;e(a)}})["catch"](e)});return j(e,c),e}function e(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readwrite"),g=f.objectStore(e.storeName),h=g["delete"](a);f.oncomplete=function(){b()},f.onerror=function(){d(h.error)},f.onabort=function(){var a=h.error?h.error:h.transaction.error;d(a)}})["catch"](d)});return j(d,b),d}function f(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readwrite"),f=e.objectStore(d.storeName),g=f.clear();e.oncomplete=function(){a()},e.onabort=e.onerror=function(){var a=g.error?g.error:g.transaction.error;c(a)}})["catch"](c)});return j(c,a),c}function g(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readonly").objectStore(d.storeName),f=e.count();f.onsuccess=function(){a(f.result)},f.onerror=function(){c(f.error)}})["catch"](c)});return j(c,a),c}function h(a,b){var c=this,d=new k(function(b,d){return 0>a?void b(null):void c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=!1,h=f.openCursor();h.onsuccess=function(){var c=h.result;return c?void(0===a?b(c.key):g?b(c.key):(g=!0,c.advance(a))):void b(null)},h.onerror=function(){d(h.error)}})["catch"](d)});return j(d,b),d}function i(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readonly").objectStore(d.storeName),f=e.openCursor(),g=[];f.onsuccess=function(){var b=f.result;return b?(g.push(b.key),void b["continue"]()):void a(g)},f.onerror=function(){c(f.error)}})["catch"](c)});return j(c,a),c}function j(a,b){b&&a.then(function(a){b(null,a)},function(a){b(a)})}var k="undefined"!=typeof module&&module.exports?require("promise"):this.Promise,l=l||this.indexedDB||this.webkitIndexedDB||this.mozIndexedDB||this.OIndexedDB||this.msIndexedDB;if(l){var m={_driver:"asyncStorage",_initStorage:a,iterate:c,getItem:b,setItem:d,removeItem:e,clear:f,length:g,key:h,keys:i};"undefined"!=typeof module&&module.exports?module.exports=m:"function"==typeof define&&define.amd?define("asyncStorage",function(){return m}):this.asyncStorage=m}}.call(window),function(){"use strict";function a(a){var b=this,c={};if(a)for(var d in a)c[d]=a[d];c.keyPrefix=c.name+"/",b._dbInfo=c;var e=new k(function(a){q===p.DEFINE?require(["localforageSerializer"],a):a(q===p.EXPORT?require("./../utils/serializer"):l.localforageSerializer)});return e.then(function(a){return m=a,k.resolve()})}function b(a){var b=this,c=b.ready().then(function(){for(var a=b._dbInfo.keyPrefix,c=n.length-1;c>=0;c--){var d=n.key(c);0===d.indexOf(a)&&n.removeItem(d)}});return j(c,a),c}function c(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo,d=n.getItem(b.keyPrefix+a);return d&&(d=m.deserialize(d)),d});return j(d,b),d}function d(a,b){var c=this,d=c.ready().then(function(){for(var b=c._dbInfo.keyPrefix,d=b.length,e=n.length,f=0;e>f;f++){var g=n.key(f),h=n.getItem(g);if(h&&(h=m.deserialize(h)),h=a(h,g.substring(d),f+1),void 0!==h)return h}});return j(d,b),d}function e(a,b){var c=this,d=c.ready().then(function(){var b,d=c._dbInfo;try{b=n.key(a)}catch(e){b=null}return b&&(b=b.substring(d.keyPrefix.length)),b});return j(d,b),d}function f(a){var b=this,c=b.ready().then(function(){for(var a=b._dbInfo,c=n.length,d=[],e=0;c>e;e++)0===n.key(e).indexOf(a.keyPrefix)&&d.push(n.key(e).substring(a.keyPrefix.length));return d});return j(c,a),c}function g(a){var b=this,c=b.keys().then(function(a){return a.length});return j(c,a),c}function h(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo;n.removeItem(b.keyPrefix+a)});return j(d,b),d}function i(a,b,c){var d=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var e=d.ready().then(function(){void 0===b&&(b=null);var c=b;return new k(function(e,f){m.serialize(b,function(b,g){if(g)f(g);else try{var h=d._dbInfo;n.setItem(h.keyPrefix+a,b),e(c)}catch(i){("QuotaExceededError"===i.name||"NS_ERROR_DOM_QUOTA_REACHED"===i.name)&&f(i),f(i)}})})});return j(e,c),e}function j(a,b){b&&a.then(function(a){b(null,a)},function(a){b(a)})}var k="undefined"!=typeof module&&module.exports?require("promise"):this.Promise,l=this,m=null,n=null;try{if(!(this.localStorage&&"setItem"in this.localStorage))return;n=this.localStorage}catch(o){return}var p={DEFINE:1,EXPORT:2,WINDOW:3},q=p.WINDOW;"undefined"!=typeof module&&module.exports?q=p.EXPORT:"function"==typeof define&&define.amd&&(q=p.DEFINE);var r={_driver:"localStorageWrapper",_initStorage:a,iterate:d,getItem:c,setItem:i,removeItem:h,clear:b,length:g,key:e,keys:f};q===p.EXPORT?module.exports=r:q===p.DEFINE?define("localStorageWrapper",function(){return r}):this.localStorageWrapper=r}.call(window),function(){"use strict";function a(a){var b=this,c={db:null};if(a)for(var d in a)c[d]="string"!=typeof a[d]?a[d].toString():a[d];var e=new k(function(a){p===o.DEFINE?require(["localforageSerializer"],a):a(p===o.EXPORT?require("./../utils/serializer"):l.localforageSerializer)}),f=new k(function(d,e){try{c.db=n(c.name,String(c.version),c.description,c.size)}catch(f){return b.setDriver(b.LOCALSTORAGE).then(function(){return b._initStorage(a)}).then(d)["catch"](e)}c.db.transaction(function(a){a.executeSql("CREATE TABLE IF NOT EXISTS "+c.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],function(){b._dbInfo=c,d()},function(a,b){e(b)})})});return e.then(function(a){return m=a,f})}function b(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName+" WHERE key = ? LIMIT 1",[a],function(a,c){var d=c.rows.length?c.rows.item(0).value:null;d&&(d=m.deserialize(d)),b(d)},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function c(a,b){var c=this,d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName,[],function(c,d){for(var e=d.rows,f=e.length,g=0;f>g;g++){var h=e.item(g),i=h.value;if(i&&(i=m.deserialize(i)),i=a(i,h.key,g+1),void 0!==i)return void b(i)}b()},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function d(a,b,c){var d=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var e=new k(function(c,e){d.ready().then(function(){void 0===b&&(b=null);var f=b;m.serialize(b,function(b,g){if(g)e(g);else{var h=d._dbInfo;h.db.transaction(function(d){d.executeSql("INSERT OR REPLACE INTO "+h.storeName+" (key, value) VALUES (?, ?)",[a,b],function(){c(f)},function(a,b){e(b)})},function(a){a.code===a.QUOTA_ERR&&e(a)})}})})["catch"](e)});return j(e,c),e}function e(a,b){var c=this;"string"!=typeof a&&(window.console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("DELETE FROM "+e.storeName+" WHERE key = ?",[a],function(){b()},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function f(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("DELETE FROM "+d.storeName,[],function(){a()},function(a,b){c(b)})})})["catch"](c)});return j(c,a),c}function g(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT COUNT(key) as c FROM "+d.storeName,[],function(b,c){var d=c.rows.item(0).c;a(d)},function(a,b){c(b)})})})["catch"](c)});return j(c,a),c}function h(a,b){var c=this,d=new k(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT key FROM "+e.storeName+" WHERE id = ? LIMIT 1",[a+1],function(a,c){var d=c.rows.length?c.rows.item(0).key:null;b(d)},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function i(a){var b=this,c=new k(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT key FROM "+d.storeName,[],function(b,c){for(var d=[],e=0;e
6 | * License WTFPL
7 | */
8 |
9 | "use strict";
10 |
11 | function slice (stuff) {
12 | return stuff && Array.prototype.slice.call(stuff);
13 | }
14 |
15 | function type (stuff) {
16 | return ({}).toString.call(stuff).replace('[object ', '').replace(']', '').toLowerCase();
17 | }
18 |
19 | var $ = window.$ = function (sel, parent) {
20 | return (parent||document).querySelector(sel);
21 | };
22 | var $$ = window.$$ = function (sel, parent) {
23 | return slice((parent||document).querySelectorAll(sel));
24 | };
25 | function wrapQuotes (val) {
26 | if (val) return '"' + val + '"';
27 | return val;
28 | }
29 | $.id = function (id, parent) {
30 | return (parent || document).getElementById(id);
31 | };
32 | $.cl = function (cl, parent) {
33 | return $$.cl(cl, parent)[0];
34 | };
35 | $.nam = function (nam, parent) {
36 | return $$.nam(nam, parent)[0];
37 | };
38 | $.tag = function (tag, parent) {
39 | return $$.tag(tag, parent)[0];
40 | };
41 | $.attr = function (attr, val, parent) {
42 | if (typeof val === 'undefined') val = '';
43 | return (parent||document).querySelector('[' + attr + wrapQuotes(val) + ']');
44 | };
45 | $.data = function (set, val, parent) {
46 | return $.attr('data-' + set, val, parent);
47 | };
48 |
49 | $$.cl = function (cl, parent) {
50 | return slice((parent||document).getElementsByClassName(cl));
51 | };
52 | $$.nam = function (nam, parent) {
53 | return slice((parent||document).getElementsByName(nam));
54 | };
55 | $$.tag = function (tag, parent) {
56 | return slice((parent||document).getElementsByTagName(tag));
57 | };
58 | $$.attr = function (attr, val, parent) {
59 | if (typeof val === 'undefined') val = '';
60 | return slice((parent||document).querySelectorAll('[' + attr + wrapQuotes(val) + ']'));
61 | };
62 | $$.data = function (set, val, parent) {
63 | return $$.attr('data-' + set, val, parent);
64 | };
65 |
66 | function assignProps (obj, stuff) {
67 | if (obj && stuff) Object.keys(stuff).forEach(function (key) {
68 | obj[key] = stuff[key];
69 | });
70 | }
71 |
72 | $.apply = function (el, opts) {
73 |
74 | if (!opts) return el;
75 |
76 | assignProps(el.style, opts.style);
77 | delete opts.style;
78 | assignProps(el.dataset, opts.dataset);
79 | delete opts.dataset;
80 | if (opts.classList) opts.classList.forEach(function (cl) {
81 | el.classList.add(cl);
82 | });
83 | delete opts.dataset;
84 | if (opts.childNodes) opts.childNodes.forEach(function (child) {
85 | el.appendChild(child);
86 | });
87 | delete opts.childNodes;
88 | var events = opts.on;
89 | if (events) Object.keys(events).forEach(function (ev) {
90 | var det = events[ev];
91 | if (type(det) !== 'array') det = [det];
92 | det.forEach(function(li) {
93 | var maybeCapture = type(li) === 'array';
94 | el.addEventListener(
95 | ev,
96 | maybeCapture ? li[0] : li,
97 | maybeCapture ? li[1] : false
98 | );
99 | });
100 | });
101 | delete opts.on;
102 | if (opts.attributes) Object.keys(opts.attributes).forEach(function (attr) {
103 | el.setAttribute(attr, opts.attributes[attr]);
104 | });
105 |
106 |
107 | Object.keys(opts).forEach(function (key) {
108 | try {
109 | el[key] = opts[key];
110 | }
111 | catch (e) {}
112 | });
113 |
114 | return el;
115 |
116 | };
117 |
118 | $.make = function make (sign, opts) {
119 |
120 | if (sign === '#text') return document.createTextNode(opts);
121 |
122 | if (sign === '#frag') return $.apply(
123 | document.createDocumentFragment(),
124 | {childNodes: opts && opts.childNodes}
125 | );
126 |
127 | var el;
128 |
129 | if (typeof sign === 'string') {
130 | el = document.createElement(sign);
131 | }
132 | else {
133 | el = sign.cloneNode(opts && opts.deep);
134 | }
135 |
136 | if (!opts) return el;
137 |
138 | delete opts.deep;
139 |
140 | return $.apply(el, opts);
141 | };
142 |
143 | $.append = function (elem, refElem, position) {
144 | position = (position || "bottom").toLowerCase();
145 |
146 | if (position === "top") {
147 | if (!refElem.childNodes.length) return refElem.appendChild(elem);
148 | return refElem.insertBefore(elem, refElem.firstChild);
149 | }
150 | else if (position === "bottom") {
151 | return refElem.appendChild(elem);
152 | }
153 | else if (position === "before") {
154 | return refElem.parentNode.insertBefore(elem, refElem);
155 | }
156 | else if (position === "after") {
157 | if (!refElem.nextElementSibling) return refElem.parentNode.appendChild(elem);
158 | return refElem.parentNode.insertBefore(elem, refElem.nextElementSibling);
159 | }
160 | else if (position === "replace") {
161 | return refElem.parentNode.replaceChild(elem, refElem);
162 | }
163 | else {
164 | throw new Error('Unknown position specified. Expected "top", "bottom", "before", "after" or "replace".');
165 | }
166 |
167 | };
168 |
169 | $.remove = function (node) {
170 | if (typeof node === 'string') node = $(node);
171 | if (node && node.parentNode) node.parentNode.removeChild(node);
172 | };
173 |
174 | })(window, document);
--------------------------------------------------------------------------------
/src/mod/shortcuts.js:
--------------------------------------------------------------------------------
1 | let shortcuts = {
2 | keypress: {},
3 | keydown: {}
4 | };
5 |
6 | let Key_Mappings = {
7 | F: 70,
8 | P: 80,
9 | ESC: 27
10 | };
11 |
12 | document.addEventListener('keypress', handler, true);
13 | document.addEventListener('keydown', handler, true);
14 |
15 | function handler (ev) {
16 | let mods = [];
17 | if (ev.altKey) mods.push('alt');
18 | if (ev.ctrlKey) mods.push('ctrl');
19 | if (ev.shiftKey) mods.push('shift');
20 | mods = mods.sort();
21 | let keyCode = ev.keyCode;
22 | let id = `${mods.join('+')}:${keyCode}`;
23 |
24 | if (shortcuts[ev.type].hasOwnProperty(id)) {
25 | let {callback, thisArg, args} = shortcuts[ev.type][id];
26 | callback.call(thisArg, ev, ...args);
27 | }
28 | }
29 |
30 | function findKeyCode (key) {
31 | return Key_Mappings[key.toUpperCase()];
32 | }
33 |
34 | function parseKey ({modifier = [], key = ''}) {
35 | if (!Array.isArray(modifier)) modifier = [modifier];
36 | let mods = modifier.map(m => m.toLowerCase()).sort();
37 | let evType, keyCode;
38 | if (!modifier.length && String(key).length === 1) {
39 | evType = 'keypress';
40 | keyCode = key.toLowerCase().charCodeAt();
41 | }
42 | else {
43 | evType = 'keydown';
44 | keyCode = key;
45 | if (!Number(key)) {
46 | keyCode = findKeyCode(key);
47 | }
48 | }
49 | if (!keyCode) throw new Error(`Unable to parse key definition. Passed modifier: ${modifier}. Passed Key: ${key}.`);
50 | let id = `${mods.join('+')}:${keyCode}`;
51 | return { mods, id, keyCode, evType, key };
52 | }
53 |
54 | export function register (definition, callback, thisArg, ...args) {
55 | let descriptor = parseKey(definition);
56 | let data = {callback, thisArg, args};
57 | shortcuts[descriptor.evType][descriptor.id] = data;
58 | }
59 |
60 | export function remove (definition) {
61 | let {evType, id} = parseKey(definition);
62 | delete shortcuts[evType][id];
63 | }
64 |
65 | export function removeAll () {
66 | shortcuts = {
67 | keypress: {},
68 | keydown: {}
69 | };
70 | }
--------------------------------------------------------------------------------
/src/mod/tabbing.js:
--------------------------------------------------------------------------------
1 | /*jslint esnext: true*/
2 |
3 | import {EventEmitter} from './events';
4 |
5 | let Utils = {
6 | randString () {
7 | return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/x/g, function () {
8 | return String.fromCharCode(Math.floor(Math.random()*120)+1);
9 | });
10 | }
11 | };
12 |
13 | export class TabGroup {
14 |
15 | constructor () {
16 | this.events = new EventEmitter();
17 | this.tabs = Object.create(null);
18 | this.store = new WeakMap();
19 | this.activeTabId = null;
20 | this.history = [];
21 | }
22 |
23 | attach (tab) {
24 | if (!(tab instanceof Tab)) {
25 | throw new Error('Expected tab to be of instance Tab. Unknown type passed.');
26 | }
27 | if (this.store.has(tab)) {
28 | throw new Error('Tab is already in this TabGroup. Aborting.');
29 | }
30 | let id = Utils.randString();
31 | this.tabs[id] = tab;
32 | this.store.set(tab, id);
33 | this.status = {
34 | type: 'attach',
35 | id
36 | };
37 | return id;
38 | }
39 |
40 | detach (thing) {
41 | let {tab, id} = this.find(thing);
42 | if (this.activeTabId === id) {
43 | this.close(thing);
44 | }
45 | delete this.tabs[id];
46 | this.status = {
47 | type: 'detach',
48 | id
49 | };
50 | this.store.delete(tab);
51 | }
52 |
53 | open (thing) {
54 | let {tab, id} = this.find(thing);
55 | if (this.activeTabId === id) return;
56 | if (this.activeTabId) {
57 | this.close(this.activeTabId);
58 | }
59 | this.activeTabId = id;
60 | this.status = {
61 | type: 'open',
62 | id
63 | };
64 | }
65 |
66 | close (thing) {
67 | let {tab, id} = this.find(thing);
68 | if (this.activeTabId !== id) return;
69 | this.activeTabId = null;
70 | this.status = {
71 | type: 'close',
72 | id
73 | };
74 | }
75 |
76 | restoreLast () {
77 | let last;
78 | for (let i = this.history.length - 1; i >= 0; i--) {
79 | let desc = this.history[i];
80 | if (desc.type === 'close' && typeof this.tabs[desc.id] !== 'undefined') {
81 | last = desc.id;
82 | break;
83 | }
84 | }
85 | if (!last) {
86 | return;
87 | }
88 | this.open(last);
89 | }
90 |
91 | find (thing) {
92 | let tab, id;
93 | if (typeof thing === 'string') {
94 | if (typeof this.tabs[thing] === 'undefined') {
95 | throw new Error('TabGroup contains no tab with id ' + thing);
96 | }
97 | tab = this.tabs[thing];
98 | id = thing;
99 | } else if (thing instanceof Tab) {
100 | if (this.store.has(thing)) {
101 | tab = thing;
102 | id = this.store.get(thing);
103 | } else {
104 | throw new Error('This tab is not a part of this TabGroup.');
105 | }
106 | } else {
107 | throw new Error('Unidentified object passed.');
108 | }
109 | return {tab, id};
110 | }
111 |
112 | set status (stat) {
113 | let type = stat.type;
114 | if (!type) throw new Error('Unable to set status. No valid type found.');
115 |
116 | this.history.push(stat);
117 | this.events.emit(type, stat);
118 | }
119 |
120 | get status () {
121 | return this.history[this.history.length - 1];
122 | }
123 |
124 | }
125 |
126 | export class Tab {
127 |
128 | constructor (title, description, meta) {
129 | this.title = title;
130 | this.description = description;
131 | this.meta = meta;
132 | }
133 |
134 | attachTo (group) {
135 | if (!(group instanceof TabGroup)) {
136 | throw new Error('Expected group to be instance of TabGroup. Unidentifiable object passed.');
137 | }
138 | group.attach(this);
139 | }
140 |
141 | }
--------------------------------------------------------------------------------
/src/mod/utils.js:
--------------------------------------------------------------------------------
1 | export function frag (html) {
2 | let doc = new DOMParser().parseFromString(html, 'text/html');
3 | let frag = doc.createDocumentFragment();
4 | let body = doc.body;
5 | while (body.firstChild) {
6 | frag.appendChild(body.firstChild);
7 | }
8 | return frag;
9 | }
10 |
11 | export function throttle (fn, time, thisArg, repeatAction) {
12 |
13 | let lastRun = false;
14 | let nextTime = 0;
15 |
16 | return function throttled (...args) {
17 | let now = Date.now();
18 | return new Promise(function (resolve) {
19 | if (!lastRun) {
20 | lastRun = now;
21 | return resolve(fn.apply(thisArg, args));
22 | }
23 | if ((now - lastRun) <= time) {
24 | if (repeatAction === 'discard-repeats') return;
25 | nextTime += time - (now - lastRun);
26 | return setTimeout(function () {
27 | lastRun = Date.now();
28 | return resolve(fn.apply(thisArg, args));
29 | }, nextTime);
30 | }
31 | lastRun = now;
32 | return resolve(fn.apply(thisArg, args));
33 | });
34 | };
35 |
36 | }
37 |
38 | export let re = {
39 | escape: function RegexpEscape (s) {
40 | return String(s).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
41 | }
42 | }
--------------------------------------------------------------------------------
/src/spec.js:
--------------------------------------------------------------------------------
1 | import 'fetch';
2 | import * as Utils from './mod/utils';
3 | import {domconsole} from './mod/domconsole';
4 | import {config} from './config';
5 | // storage stuff
6 |
7 | export let Store = localforage.createInstance({
8 | name: 'especser',
9 | storeName: config.IDBstoreName
10 | });
11 |
12 | export let Data = {
13 | indexToId: {}, // 4.6.5: #sec-foo
14 | idToIndex: {}, // #sec-foo: 4.6.5...
15 | indexToFrameIndex: {}, // eg: 2.1.3 maps to 17 where 17 is the index of the corresponding frame inside stack
16 | stack: [] // contains frames containing data
17 | };
18 |
19 | export function indexToPath (index) {
20 | let pathNums = index.split('.');
21 | return pathNums.map((_, i, arr) => arr.slice(0, i + 1).join('.')).map(
22 | num => Data.stack[Data.indexToFrameIndex[num]].title
23 | ).join(' | ');
24 | }
25 |
26 | export function indexToFrame (index) {
27 | try {
28 | return Data.stack[Data.indexToFrameIndex[index]];
29 | } catch (err) { return null; }
30 | }
31 |
32 | // functions to scrape spec
33 |
34 | function fetchSpec (url = config.SPEC_URL) {
35 | console.log('sending request to %s', url);
36 | let f = fetch(
37 | url
38 | ).then(res => res.text())
39 | .then(html => new DOMParser().parseFromString(html, 'text/html'));
40 | return f;
41 | }
42 |
43 | // replaces multiple simultaneous whitespace characters with single space
44 | function normalize (string) {
45 | return string.replace(/(?:\n+|\s+)/g, ' ');
46 | }
47 |
48 | // *internal* takes list element, secnum (whatever) and extracts a title value
49 | function extractText (el, secnum) {
50 | let c = $.cl('toc', el);
51 | let title = '';
52 | let nextEl = secnum.nextSibling;
53 | while (nextEl && nextEl.nodeName.toLowerCase() !== 'ol') {
54 | title += nextEl.textContent;
55 | nextEl = nextEl.nextSibling;
56 | }
57 | return normalize(title.trim());
58 | }
59 |
60 | function parseIndex (doc) {
61 | let elements = $$('span.secnum[id^="sec-"]', doc);
62 |
63 | elements.forEach(function (secnum, stackIndex) {
64 |
65 | let index = secnum.textContent;
66 | let isAnnex = false;
67 | if (index.startsWith('Annex')) {
68 | index = index.replace('Annex', '').trim();
69 | isAnnex = true;
70 | }
71 |
72 | let path = index.split('.');
73 | path = path.reduce(function (path, place) {
74 | let curr = path[path.length - 1];
75 | path.push(curr + '.' + place);
76 | return path;
77 | }, [path.shift()]);
78 |
79 | let id = secnum.firstChild.getAttribute('href').replace('#', '');
80 |
81 | let title = secnum.parentNode.textContent;
82 |
83 | if (isAnnex) {
84 | title = title.replace('Annex ' + index, '').trim();
85 | }
86 | else {
87 | title = title.replace(index, '').trim();
88 | }
89 |
90 | let children = [];
91 | let def = {index, id, title, children, path, stackIndex};
92 | Data.stack.push(def);
93 |
94 | Data.indexToId[index] = id;
95 | Data.idToIndex[id] = index;
96 | Data.indexToFrameIndex[index] = stackIndex;
97 |
98 | let parent = path[path.length - 2];
99 | if (parent) {
100 | Data.stack[Data.indexToFrameIndex[parent]].children.push(index);
101 | }
102 |
103 | });
104 |
105 | return doc;
106 |
107 | }
108 |
109 | function processStack (doc) {
110 | console.log('starting stack processing of %s frames', Data.stack.length);
111 | return Promise.all(Data.stack.map( // we have to defer this because if #8.5 refers to #9.5, the index will not be found
112 | frame => Store.setItem(frame.index, extractMaterial(frame.id, doc))
113 | )).then(
114 | _ => Store.setItem('appdata', Data)
115 | );
116 | }
117 |
118 | // *internal* conditionally assigns data-index attribute to element and returns modified element
119 | function assignIndex (el) {
120 | let id = el.getAttribute('href');
121 | if (!id || !id.startsWith('#')) return el;
122 | let index = Data.idToIndex[id.replace('#', '')];
123 | if (!index) return el;
124 | el.setAttribute('href', '#' + index);
125 | el.dataset.index = index;
126 | el.classList.add('link-newtab');
127 | return el;
128 | }
129 |
130 | function extractMaterial (hash, content) {
131 | let c = $.id(hash.replace('#', ''), content);
132 | let f = $.cl('front', c);
133 | let container = f || c;
134 | let clone = container.cloneNode(true);
135 | $$.attr('id', undefined, clone).forEach(el => {el.removeAttribute('id');});
136 | $$.attr('href^=', '#', clone).forEach(assignIndex);
137 | return clone.innerHTML;
138 | }
139 |
140 | export function update () {
141 | console.log('update started');
142 | domconsole.log('fetching latest version of spec and caching locally. this might take a while.')
143 | return fetchSpec().then(parseIndex).then(processStack).then(
144 | _ => window.localStorage.setItem('lastIndexed', Date.now())
145 | ).then(
146 | _ => {
147 | console.log('stack processed and saved in indexeddb. marked lastindex in localstorage');
148 | domconsole.log('caching and parsing completed! you can search for stuff and browse the spec now! :) (double click here to hide me)');
149 | $.id('console').addEventListener('dblclick', function removeMe () {
150 | this.classList.add('hidden');
151 | this.removeEventListener('dblclick', removeMe);
152 | }, false);
153 | window.dispatchEvent(new Event('hashchange'));
154 | }
155 | );
156 | }
157 |
158 | export function initialize () {
159 | console.log('initializing especser. we have ignition!');
160 | if (window.localStorage.getItem('lastIndexed')) {
161 | return Store.getItem('appdata').then(val => {
162 | Data = val;
163 | console.log('retrieved appdata from indexeddb from %s', localStorage.getItem('lastIndexed'));
164 | });
165 | }
166 | console.log('this session is brand new. starting update threads!');
167 | return update();
168 | }
169 |
170 | export function clear () {
171 | console.log('I have got orders from high command to evacuate all data from the ship.');
172 | domconsole.log('clearing store. this might take some time.');
173 | Data = {
174 | indexToId: {},
175 | idToIndex: {},
176 | indexToFrameIndex: {},
177 | stack: []
178 | };
179 | Store.clear().then(_ => localStorage.removeItem('lastIndexed')).then(
180 | _ => domconsole.log('store was emptied. click update to cache spec again.')
181 | );
182 | }
183 |
184 | // spec usage API to be exposed
185 |
186 | const MAX_RESULTS = 8;
187 |
188 | // *internal* query to be found in name
189 | function fuzzySearch (name, query, max = MAX_RESULTS) {
190 | let pos = -1;
191 | for (let i = 0, len = query.length; i < len; i++) {
192 | let char = query[i];
193 | if (!char.trim()) continue; // removing whitespace
194 | pos = name.indexOf(char, pos+1);
195 | if (pos === -1) return false;
196 | }
197 | return true;
198 | }
199 |
200 | const RE_SEC = /^sec:\s*(?:(?:\d+\.?)+,?\s*)+\b/i;
201 |
202 | /*
203 |
204 | ^ # start of string |||||
205 | sec: # "sec:" |||||
206 | \s* # forgive whitespace |||||
207 | (?: # begin matching set of indices ||||| |||||
208 | (?: # begin matching individaul indices ||||| ||||| |||||
209 | \d+ # one or more digits ||||| ||||| |||||
210 | \.? # followed by a period ||||| ||||| |||||
211 | )+ # and done ||||| ||||| |||||
212 | ,? # and maybe commas ||||| |||||
213 | \s* # and maybe whitespace ||||| |||||
214 | )+ # 1 or more times ||||| |||||
215 | \b # and word boundary so trailing commas aren't matched |||||
216 |
217 | */
218 |
219 | function* executeSearch (stack, query, max = MAX_RESULTS) {
220 |
221 | query = (query + '').trim().toLowerCase();
222 | if (!query) return [];
223 |
224 | let index = query.match(RE_SEC), selectedStack = [];
225 |
226 | if (index && index[0]) {
227 | let indices = index[0].replace('sec:', '').trim().split(/,\s*/);
228 |
229 | // initializing selectedStack with parent indices and all there children
230 | // our stack is pretty large. so not using closures here
231 | for (let i = 0; i < indices.length; i++) {
232 | let frame = indexToFrame(indices[i]);
233 | if (!frame) continue;
234 | indices.push(...frame.children);
235 | selectedStack.push(frame);
236 | }
237 | query = query.replace(RE_SEC, '').replace(/[.,]/g, '').trim();
238 | if (!query) return selectedStack; // we return it here itself because the stack will likely not be large
239 | } else {
240 | selectedStack = stack;
241 | }
242 |
243 | for (
244 | let i = 0, len = selectedStack.length,
245 | results = [], fuzzyResults = [];
246 | i < len;
247 | i++
248 | ) {
249 | let title = selectedStack[i].title.toLowerCase();
250 | if (title.indexOf(query) >= 0) {
251 | results.push(selectedStack[i]);
252 | }
253 | else if (fuzzySearch(title, query)) {
254 | fuzzyResults.push(selectedStack[i]);
255 | }
256 | if (results.length >= max) {
257 | yield results;
258 | results = [];
259 | continue;
260 | }
261 | else if (i >= len - 1) {
262 | results.push(...fuzzyResults.slice(0, (max - results.length) - 1));
263 | yield results;
264 | results = [];
265 | continue;
266 | }
267 | }
268 | return [];
269 |
270 | }
271 |
272 | export function search (query) {
273 | return executeSearch(Data.stack, query);
274 | };
275 |
--------------------------------------------------------------------------------