git ssb

0+

dangerousbeans / web-bootloader



forked from Dominic / web-bootloader

Tree: 4e5895551993e8c4236b5e05cb6196315a19e2cb

Files: 4e5895551993e8c4236b5e05cb6196315a19e2cb / index.html

48686 bytesRaw
1<!DOCTYPE html>
2<html manifest="./manifest.appcache"><head>
3<title>---</title>
4<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
5<meta charset=utf-8></head>
6<body></body>
7<script>
8(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
9var SecureUrl = require('./fetch')
10var u = require('./util')
11
12module.exports = function (prefix, store, log) {
13 var appname = prefix
14 var wb, running = false
15
16 //destroy everything
17 function scorchedEarth () {
18 for(var k in localStorage) {
19 delete localStorage[k]
20 }
21 }
22 function onProgress (ev) {
23 wb.onprogress && wb.onprogress(ev)
24 }
25
26 var init = '#'+appname+'_INIT'
27
28 return wb = {
29 scorchedEarth: scorchedEarth,
30 isInit: function () {
31 return location.hash.substring(0, init.length) === init
32 },
33 setup: function () {
34 if(!wb.isInit())
35 location.hash = init + location.hash
36 location.reload()
37 },
38 reinitialize: function (cb) {
39 delete localStorage[appname+'_current']
40 store.destroy(cb)
41 },
42 install: function (url, cb) {
43 onProgress('installing from:'+url)
44 var id = SecureUrl.isSecureUrl(url)
45 if(!id) return cb(new Error('not a secure url:'+url))
46 //check whether we already have this
47 //before downloading anything
48 store.get(id, function (err, data) {
49 if(!err) return cb(null, data, id)
50 SecureUrl(url, function (err, data, id) {
51 if(err) cb(err)
52 else store.add(data, id, function (err) {
53 cb(err, data, id)
54 })
55 })
56 })
57 },
58 installAndRun(url, cb) {
59 wb.install(url, function (err, _, id) {
60 if(err) cb(err)
61 else wb.run(id, cb)
62 })
63 },
64 add: store.add,
65 run: function (id, cb) {
66 if(!id) return cb(new Error('WebBoot.run: id must be provided'))
67 var _id
68 //if we are already running, restart
69 //clear out init code, if we are in setup mode
70 if(wb.isInit())
71 location.hash = location.hash.substring(init.length)
72
73 log.head(function (err, data) {
74 if(err) return cb(err)
75 if(data) _id = data.value
76 if(_id === id)
77 run(id)
78 else
79 log.append(id, function (err) {
80 if(err) return cb(err)
81 run(id)
82 })
83 })
84
85 function run (id) {
86 if(running) {
87 //reload, and then the current version will trigger.
88 cb()
89 location.reload()
90 }
91 else
92 store.get(id, function (err, data) {
93 if(err) return cb(err)
94 var script = document.createElement('script')
95 running = true
96 document.body.innerHTML = ''
97 script.textContent = u.toUtf8(data)
98 document.head.appendChild(script) //run javascript.
99 cb()
100 })
101 }
102 },
103 size: function (cb) {
104 store.ls(function (err, ls) {
105 if(err) cb(err)
106 else cb(null, ls.reduce(function (total, item) {
107 return total + item.size
108 }, 0))
109 })
110 },
111 //clear target amount of space.
112 prune: function (target, cb) {
113 if(!target) return cb(new Error('WebBoot.prune: size to clear must be provided'))
114 var cleared = 0, remove = []
115
116 function clear () {
117 var n = remove.length
118 while(remove.length) store.rm(remove.shift(), function () {
119 if(--n) return
120 if(cleared < target)
121 cb(new Error('could not clear requested space'), cleared)
122 else
123 cb(null, cleared)
124 })
125 }
126
127 store.ls(function (err, ls) {
128 if(err) return cb(err)
129 log.unfiltered(function (err, unfiltered) {
130 var stored = unfiltered.reverse()
131 for(var i = 0; i < stored.length; i++) {
132 var id = stored[i].value
133 var item = ls.find(function (e) {
134 return e.id === id
135 })
136
137 if(item) {
138 cleared += item.size
139 remove.push(id)
140 if(cleared >= target) return clear()
141 }
142 }
143 clear()
144 })
145 })
146 },
147
148 version: require('./package.json').version,
149 remove: store.rm,
150 has: store.has,
151 versions: function (cb) {
152 log.filtered(function (err, ls) {
153 if(err) return cb(err)
154 else if(ls.length) cb(null, ls)
155 else {
156 console.log('restore from legacy log...')
157 var versions = u.parse(localStorage[appname+'_versions'])
158 if(!versions) return cb(null, [])
159 var n = Object.keys(versions).length
160 for(var ts in versions) {
161 log.append(versions[ts], function () {
162 if(--n) return
163 //try again
164 log.filtered(cb)
165 })
166 }
167 }
168 })
169 },
170 history: log.unfiltered,
171 current: log.head,
172 append: log.append,
173 revert: log.revert,
174 onprogress: null
175 }
176}
177
178
179},{"./fetch":2,"./package.json":20,"./util":23}],2:[function(require,module,exports){
180var BinaryXHR = require('binary-xhr')
181var hasHash = /([A-Za-z0-9\/+]{43}=)\.sha256/
182var isUrl = /^https?:\/\//
183
184var u = require('./util')
185
186//before calling this, always check whether you alread have
187//a file with this hash.
188exports = module.exports = function (secure_url, cb) {
189 var id = exports.isSecureUrl(secure_url)
190 if(!id)
191 return cb(new Error('is not a secure url:'+secure_url))
192
193 BinaryXHR(secure_url, function (err, data) {
194 if(err)
195 return cb(new Error('could not retrive secure url:'+err))
196 if(!data || !data.length)
197 return cb(new Error('empty response from: '+secure_url))
198 u.hash(data, function (err, _id) {
199 if(_id !== id) cb(u.HashError(_id, id))
200
201 cb(null, data, id)
202 })
203 })
204}
205
206exports.isSecureUrl = function (string) {
207 var h = hasHash.exec(string)
208 return isUrl.test(string) && h && h[1]
209}
210
211},{"./util":23,"binary-xhr":6}],3:[function(require,module,exports){
212'use strict'
213
214var appname = 'SWB'
215var store = require('./store')(appname, localStorage)
216var log = require('./log')(appname, localStorage)
217var wb = window.WebBoot = require('./bootloader')(appname, store, log)
218
219//minimal user interface...
220require('./ui')(appname, wb)
221
222
223},{"./bootloader":1,"./log":4,"./store":21,"./ui":22}],4:[function(require,module,exports){
224var u = require('./util')
225
226/*
227 this uses localStorage, so it doesn't need async,
228 but i used async api anyway,
229 so it will be easy to switch to indexeddb.
230*/
231
232module.exports = function (prefix, storage) {
233 //pass in non-local storage, to make testing easy.
234 storage = storage || localStorage
235 var log
236 function _append (data, cb) {
237 var log = u.parse(storage[prefix]) || []
238 log.unshift(data)
239 storage[prefix] = JSON.stringify(log)
240 cb(null, data)
241 }
242
243 function filtered (log) {
244 var revert = null
245 var output = []
246 for(var i = 0; i < log.length; i++) {
247 var item = log[i]
248 if(revert && revert <= item.ts) //this op was reverted.
249 ;
250 else if(item.revert)
251 revert = item.revert
252 else
253 output.push(item)
254 }
255 return output
256 }
257
258 function getLog() {
259 return u.parse(storage[prefix]) || []
260 }
261
262 return log = {
263 head: function (cb) {
264 cb(null, filtered(getLog())[0])
265 },
266 filtered: function (cb) {
267 cb(null, filtered(getLog()))
268 },
269 unfiltered: function (cb) {
270 cb(null, getLog())
271 },
272 append: function (data, cb) {
273 _append({value: data, ts: Date.now()}, cb)
274 },
275 revert: function (ts, cb) {
276 if(!ts) return cb(new Error('log.revert: must provide ts to revert to'))
277 _append({revert: ts, ts: Date.now()}, function (err) {
278 if(err) cb(err)
279 else cb(null, filtered(getLog())[0])
280 })
281 }
282 }
283}
284
285
286
287},{"./util":23}],5:[function(require,module,exports){
288module.exports = function ToBase64(buf) {
289 buf = new Uint8Array(buf)
290 var s = ''
291 for(var i = 0; i < buf.byteLength; i++)
292 s+=String.fromCharCode(buf[i])
293 return btoa(s)
294}
295
296
297},{}],6:[function(require,module,exports){
298var inherits = require('inherits')
299
300module.exports = function(url, cb) {
301 return new BinaryXHR(url, cb)
302}
303
304function BinaryXHR(url, cb) {
305 var self = this
306 var xhr = new XMLHttpRequest()
307 this.xhr = xhr
308 xhr.open("GET", url, true)
309 xhr.responseType = 'arraybuffer'
310 xhr.onreadystatechange = function () {
311 if (self.xhr.readyState === 4) {
312 if (self.xhr.status !== 200) {
313 cb(self.xhr.status, self.xhr.response);
314 } else if (self.xhr.response && self.xhr.response.byteLength > 0) {
315 cb(false, self.xhr.response)
316 } else {
317 if (self.xhr.response && self.xhr.response.byteLength === 0) return cb('response length 0')
318 cb('no response')
319 }
320 }
321 }
322 xhr.send(null)
323}
324
325},{"inherits":16}],7:[function(require,module,exports){
326
327},{}],8:[function(require,module,exports){
328/*!
329 * Cross-Browser Split 1.1.1
330 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
331 * Available under the MIT License
332 * ECMAScript compliant, uniform cross-browser split method
333 */
334
335/**
336 * Splits a string into an array of strings using a regex or string separator. Matches of the
337 * separator are not included in the result array. However, if `separator` is a regex that contains
338 * capturing groups, backreferences are spliced into the result each time `separator` is matched.
339 * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
340 * cross-browser.
341 * @param {String} str String to split.
342 * @param {RegExp|String} separator Regex or string to use for separating the string.
343 * @param {Number} [limit] Maximum number of items to include in the result array.
344 * @returns {Array} Array of substrings.
345 * @example
346 *
347 * // Basic use
348 * split('a b c d', ' ');
349 * // -> ['a', 'b', 'c', 'd']
350 *
351 * // With limit
352 * split('a b c d', ' ', 2);
353 * // -> ['a', 'b']
354 *
355 * // Backreferences in result array
356 * split('..word1 word2..', /([a-z]+)(\d+)/i);
357 * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
358 */
359module.exports = (function split(undef) {
360
361 var nativeSplit = String.prototype.split,
362 compliantExecNpcg = /()??/.exec("")[1] === undef,
363 // NPCG: nonparticipating capturing group
364 self;
365
366 self = function(str, separator, limit) {
367 // If `separator` is not a regex, use `nativeSplit`
368 if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
369 return nativeSplit.call(str, separator, limit);
370 }
371 var output = [],
372 flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
373 (separator.sticky ? "y" : ""),
374 // Firefox 3+
375 lastLastIndex = 0,
376 // Make `global` and avoid `lastIndex` issues by working with a copy
377 separator = new RegExp(separator.source, flags + "g"),
378 separator2, match, lastIndex, lastLength;
379 str += ""; // Type-convert
380 if (!compliantExecNpcg) {
381 // Doesn't need flags gy, but they don't hurt
382 separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
383 }
384 /* Values for `limit`, per the spec:
385 * If undefined: 4294967295 // Math.pow(2, 32) - 1
386 * If 0, Infinity, or NaN: 0
387 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
388 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
389 * If other: Type-convert, then use the above rules
390 */
391 limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
392 limit >>> 0; // ToUint32(limit)
393 while (match = separator.exec(str)) {
394 // `separator.lastIndex` is not reliable cross-browser
395 lastIndex = match.index + match[0].length;
396 if (lastIndex > lastLastIndex) {
397 output.push(str.slice(lastLastIndex, match.index));
398 // Fix browsers whose `exec` methods don't consistently return `undefined` for
399 // nonparticipating capturing groups
400 if (!compliantExecNpcg && match.length > 1) {
401 match[0].replace(separator2, function() {
402 for (var i = 1; i < arguments.length - 2; i++) {
403 if (arguments[i] === undef) {
404 match[i] = undef;
405 }
406 }
407 });
408 }
409 if (match.length > 1 && match.index < str.length) {
410 Array.prototype.push.apply(output, match.slice(1));
411 }
412 lastLength = match[0].length;
413 lastLastIndex = lastIndex;
414 if (output.length >= limit) {
415 break;
416 }
417 }
418 if (separator.lastIndex === match.index) {
419 separator.lastIndex++; // Avoid an infinite loop
420 }
421 }
422 if (lastLastIndex === str.length) {
423 if (lastLength || !separator.test("")) {
424 output.push("");
425 }
426 } else {
427 output.push(str.slice(lastLastIndex));
428 }
429 return output.length > limit ? output.slice(0, limit) : output;
430 };
431
432 return self;
433})();
434
435},{}],9:[function(require,module,exports){
436// contains, add, remove, toggle
437var indexof = require('indexof')
438
439module.exports = ClassList
440
441function ClassList(elem) {
442 var cl = elem.classList
443
444 if (cl) {
445 return cl
446 }
447
448 var classList = {
449 add: add
450 , remove: remove
451 , contains: contains
452 , toggle: toggle
453 , toString: $toString
454 , length: 0
455 , item: item
456 }
457
458 return classList
459
460 function add(token) {
461 var list = getTokens()
462 if (indexof(list, token) > -1) {
463 return
464 }
465 list.push(token)
466 setTokens(list)
467 }
468
469 function remove(token) {
470 var list = getTokens()
471 , index = indexof(list, token)
472
473 if (index === -1) {
474 return
475 }
476
477 list.splice(index, 1)
478 setTokens(list)
479 }
480
481 function contains(token) {
482 return indexof(getTokens(), token) > -1
483 }
484
485 function toggle(token) {
486 if (contains(token)) {
487 remove(token)
488 return false
489 } else {
490 add(token)
491 return true
492 }
493 }
494
495 function $toString() {
496 return elem.className
497 }
498
499 function item(index) {
500 var tokens = getTokens()
501 return tokens[index] || null
502 }
503
504 function getTokens() {
505 var className = elem.className
506
507 return filter(className.split(" "), isTruthy)
508 }
509
510 function setTokens(list) {
511 var length = list.length
512
513 elem.className = list.join(" ")
514 classList.length = length
515
516 for (var i = 0; i < list.length; i++) {
517 classList[i] = list[i]
518 }
519
520 delete list[length]
521 }
522}
523
524function filter (arr, fn) {
525 var ret = []
526 for (var i = 0; i < arr.length; i++) {
527 if (fn(arr[i])) ret.push(arr[i])
528 }
529 return ret
530}
531
532function isTruthy(value) {
533 return !!value
534}
535
536},{"indexof":15}],10:[function(require,module,exports){
537module.exports = function h (tag, attrs, content) {
538 if(Array.isArray(attrs)) content = attrs, attrs = {}
539 var el = document.createElement(tag)
540 for(var k in attrs) el[k] = attrs[k]
541 if(content) content.forEach(function (e) {
542 if(e) el.appendChild('string' == typeof e ? document.createTextNode(e) : e)
543 })
544 return el
545}
546
547
548
549
550
551},{}],11:[function(require,module,exports){
552/**
553 * Print a human readable timestamp to the terminal
554 * given a number representing seconds
555 *
556 * Author: Dave Eddy <dave@daveeddy.com>
557 * Date: 8/18/2014
558 * License: MIT
559 */
560
561var util = require('util');
562
563module.exports = human;
564
565function human(seconds) {
566 if (seconds instanceof Date)
567 seconds = Math.round((Date.now() - seconds) / 1000);
568 var suffix = seconds < 0 ? 'from now' : 'ago';
569 seconds = Math.abs(seconds);
570
571 var times = [
572 seconds / 60 / 60 / 24 / 365, // years
573 seconds / 60 / 60 / 24 / 30, // months
574 seconds / 60 / 60 / 24 / 7, // weeks
575 seconds / 60 / 60 / 24, // days
576 seconds / 60 / 60, // hours
577 seconds / 60, // minutes
578 seconds // seconds
579 ];
580 var names = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'];
581
582 for (var i = 0; i < names.length; i++) {
583 var time = Math.floor(times[i]);
584 if (time > 1)
585 return util.format('%d %ss %s', time, names[i], suffix);
586 else if (time === 1)
587 return util.format('%d %s %s', time, names[i], suffix);
588 }
589 return util.format('0 seconds %s', suffix);
590}
591
592},{"util":19}],12:[function(require,module,exports){
593var h = require('hyperscript')
594
595function select (ready) {
596 return h('input', {type: 'file', onchange: function (ev) {
597 var file = ev.target.files[0]
598 ready(new FileReader(), file)
599 }})
600
601}
602
603module.exports = function (onFile) {
604 return select(function (reader, file) {
605 reader.onload = function () {
606 onFile(new Buffer(reader.result))
607 }
608 reader.readAsArrayBuffer(file)
609 })
610}
611
612module.exports.asDataURL = function (onFile) {
613 return select(function (reader, file) {
614 reader.onload = function () {
615 onFile(reader.result)
616 }
617 reader.readAsDataURL(file)
618 })
619}
620
621
622
623},{"hyperscript":14}],13:[function(require,module,exports){
624
625function create (tag, classname, children) {
626 var el = document.createElement(tag)
627 classname && el.classList.add(classname)
628 children && children.forEach(function (e) {
629 console.log('append', e)
630 el.appendChild(
631 'string' === typeof e ? document.createTextNode(e) : e
632 )
633 })
634 return el
635}
636
637module.exports = function (steps) {
638 var list = create('ul', 'hyperprogress__list')
639 var error = create('pre', 'hyperprogress__error')
640 var liquid = create('div', 'hyperprogress__liquid', ['.'])
641 var bar = create('div', 'hyperprogress__bar', [liquid])
642 liquid.style.width = '0%'
643
644 var n = 0
645
646 var prog = create('div', 'hyperprogress', [
647 steps ? bar : '',
648 list,
649 //only show bar if a number of steps is provided.
650 error
651 ])
652
653 prog.complete = function () {
654 liquid.style.width = '100%'
655 prog.classList.add('hyperprogress--complete')
656 }
657
658 prog.next = function (name) {
659 n = Math.min(n+1, steps)
660 if(list.lastChild)
661 list.lastChild.classList.add('hyperprogress--okay')
662
663 if(name)
664 list.appendChild(create('li', 'hyperprogress__started', [name]))
665
666 liquid.style.width = Math.round((n/steps)*100)+'%'
667
668 if(n === steps)
669 prog.complete()
670 }
671
672 prog.fail = function (err) {
673 prog.classList.add('hyperprogress--failed')
674 list.lastChild.classList.add('hyperprogress--error')
675 if(err && err.stack)
676 error.textContent = err.stack
677 else if(err && err.name && err.message)
678 error.textContent = err.name + ': ' + err.message
679 else
680 error.textContent = JSON.stringify(err)
681 }
682
683 prog.reset = function () {
684 n = 0
685 error.innerHTML = list.innerHTML = ''
686 liquid.style.width = '0%'
687 return prog
688 }
689
690 return prog
691}
692
693
694
695
696
697},{}],14:[function(require,module,exports){
698var split = require('browser-split')
699var ClassList = require('class-list')
700require('html-element')
701
702function context () {
703
704 var cleanupFuncs = []
705
706 function h() {
707 var args = [].slice.call(arguments), e = null
708 function item (l) {
709 var r
710 function parseClass (string) {
711 // Our minimal parser doesn’t understand escaping CSS special
712 // characters like `#`. Don’t use them. More reading:
713 // https://mathiasbynens.be/notes/css-escapes .
714
715 var m = split(string, /([\.#]?[^\s#.]+)/)
716 if(/^\.|#/.test(m[1]))
717 e = document.createElement('div')
718 forEach(m, function (v) {
719 var s = v.substring(1,v.length)
720 if(!v) return
721 if(!e)
722 e = document.createElement(v)
723 else if (v[0] === '.')
724 ClassList(e).add(s)
725 else if (v[0] === '#')
726 e.setAttribute('id', s)
727 })
728 }
729
730 if(l == null)
731 ;
732 else if('string' === typeof l) {
733 if(!e)
734 parseClass(l)
735 else
736 e.appendChild(r = document.createTextNode(l))
737 }
738 else if('number' === typeof l
739 || 'boolean' === typeof l
740 || l instanceof Date
741 || l instanceof RegExp ) {
742 e.appendChild(r = document.createTextNode(l.toString()))
743 }
744 //there might be a better way to handle this...
745 else if (isArray(l))
746 forEach(l, item)
747 else if(isNode(l))
748 e.appendChild(r = l)
749 else if(l instanceof Text)
750 e.appendChild(r = l)
751 else if ('object' === typeof l) {
752 for (var k in l) {
753 if('function' === typeof l[k]) {
754 if(/^on\w+/.test(k)) {
755 (function (k, l) { // capture k, l in the closure
756 if (e.addEventListener){
757 e.addEventListener(k.substring(2), l[k], false)
758 cleanupFuncs.push(function(){
759 e.removeEventListener(k.substring(2), l[k], false)
760 })
761 }else{
762 e.attachEvent(k, l[k])
763 cleanupFuncs.push(function(){
764 e.detachEvent(k, l[k])
765 })
766 }
767 })(k, l)
768 } else {
769 // observable
770 e[k] = l[k]()
771 cleanupFuncs.push(l[k](function (v) {
772 e[k] = v
773 }))
774 }
775 }
776 else if(k === 'style') {
777 if('string' === typeof l[k]) {
778 e.style.cssText = l[k]
779 }else{
780 for (var s in l[k]) (function(s, v) {
781 if('function' === typeof v) {
782 // observable
783 e.style.setProperty(s, v())
784 cleanupFuncs.push(v(function (val) {
785 e.style.setProperty(s, val)
786 }))
787 } else
788 e.style.setProperty(s, l[k][s])
789 })(s, l[k][s])
790 }
791 } else if (k.substr(0, 5) === "data-") {
792 e.setAttribute(k, l[k])
793 } else {
794 e[k] = l[k]
795 }
796 }
797 } else if ('function' === typeof l) {
798 //assume it's an observable!
799 var v = l()
800 e.appendChild(r = isNode(v) ? v : document.createTextNode(v))
801
802 cleanupFuncs.push(l(function (v) {
803 if(isNode(v) && r.parentElement)
804 r.parentElement.replaceChild(v, r), r = v
805 else
806 r.textContent = v
807 }))
808 }
809
810 return r
811 }
812 while(args.length)
813 item(args.shift())
814
815 return e
816 }
817
818 h.cleanup = function () {
819 for (var i = 0; i < cleanupFuncs.length; i++){
820 cleanupFuncs[i]()
821 }
822 cleanupFuncs.length = 0
823 }
824
825 return h
826}
827
828var h = module.exports = context()
829h.context = context
830
831function isNode (el) {
832 return el && el.nodeName && el.nodeType
833}
834
835function isText (el) {
836 return el && el.nodeName === '#text' && el.nodeType == 3
837}
838
839function forEach (arr, fn) {
840 if (arr.forEach) return arr.forEach(fn)
841 for (var i = 0; i < arr.length; i++) fn(arr[i], i)
842}
843
844function isArray (arr) {
845 return Object.prototype.toString.call(arr) == '[object Array]'
846}
847
848},{"browser-split":8,"class-list":9,"html-element":7}],15:[function(require,module,exports){
849
850var indexOf = [].indexOf;
851
852module.exports = function(arr, obj){
853 if (indexOf) return arr.indexOf(obj);
854 for (var i = 0; i < arr.length; ++i) {
855 if (arr[i] === obj) return i;
856 }
857 return -1;
858};
859},{}],16:[function(require,module,exports){
860module.exports = inherits
861
862function inherits (c, p, proto) {
863 proto = proto || {}
864 var e = {}
865 ;[c.prototype, proto].forEach(function (s) {
866 Object.getOwnPropertyNames(s).forEach(function (k) {
867 e[k] = Object.getOwnPropertyDescriptor(s, k)
868 })
869 })
870 c.prototype = Object.create(p.prototype, e)
871 c.super = p
872}
873
874//function Child () {
875// Child.super.call(this)
876// console.error([this
877// ,this.constructor
878// ,this.constructor === Child
879// ,this.constructor.super === Parent
880// ,Object.getPrototypeOf(this) === Child.prototype
881// ,Object.getPrototypeOf(Object.getPrototypeOf(this))
882// === Parent.prototype
883// ,this instanceof Child
884// ,this instanceof Parent])
885//}
886//function Parent () {}
887//inherits(Child, Parent)
888//new Child
889
890},{}],17:[function(require,module,exports){
891if (typeof Object.create === 'function') {
892 // implementation from standard node.js 'util' module
893 module.exports = function inherits(ctor, superCtor) {
894 ctor.super_ = superCtor
895 ctor.prototype = Object.create(superCtor.prototype, {
896 constructor: {
897 value: ctor,
898 enumerable: false,
899 writable: true,
900 configurable: true
901 }
902 });
903 };
904} else {
905 // old school shim for old browsers
906 module.exports = function inherits(ctor, superCtor) {
907 ctor.super_ = superCtor
908 var TempCtor = function () {}
909 TempCtor.prototype = superCtor.prototype
910 ctor.prototype = new TempCtor()
911 ctor.prototype.constructor = ctor
912 }
913}
914
915},{}],18:[function(require,module,exports){
916module.exports = function isBuffer(arg) {
917 return arg && typeof arg === 'object'
918 && typeof arg.copy === 'function'
919 && typeof arg.fill === 'function'
920 && typeof arg.readUInt8 === 'function';
921}
922},{}],19:[function(require,module,exports){
923// Copyright Joyent, Inc. and other Node contributors.
924//
925// Permission is hereby granted, free of charge, to any person obtaining a
926// copy of this software and associated documentation files (the
927// "Software"), to deal in the Software without restriction, including
928// without limitation the rights to use, copy, modify, merge, publish,
929// distribute, sublicense, and/or sell copies of the Software, and to permit
930// persons to whom the Software is furnished to do so, subject to the
931// following conditions:
932//
933// The above copyright notice and this permission notice shall be included
934// in all copies or substantial portions of the Software.
935//
936// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
937// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
938// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
939// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
940// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
941// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
942// USE OR OTHER DEALINGS IN THE SOFTWARE.
943
944var formatRegExp = /%[sdj%]/g;
945exports.format = function(f) {
946 if (!isString(f)) {
947 var objects = [];
948 for (var i = 0; i < arguments.length; i++) {
949 objects.push(inspect(arguments[i]));
950 }
951 return objects.join(' ');
952 }
953
954 var i = 1;
955 var args = arguments;
956 var len = args.length;
957 var str = String(f).replace(formatRegExp, function(x) {
958 if (x === '%%') return '%';
959 if (i >= len) return x;
960 switch (x) {
961 case '%s': return String(args[i++]);
962 case '%d': return Number(args[i++]);
963 case '%j':
964 try {
965 return JSON.stringify(args[i++]);
966 } catch (_) {
967 return '[Circular]';
968 }
969 default:
970 return x;
971 }
972 });
973 for (var x = args[i]; i < len; x = args[++i]) {
974 if (isNull(x) || !isObject(x)) {
975 str += ' ' + x;
976 } else {
977 str += ' ' + inspect(x);
978 }
979 }
980 return str;
981};
982
983
984// Mark that a method should not be used.
985// Returns a modified function which warns once by default.
986// If --no-deprecation is set, then it is a no-op.
987exports.deprecate = function(fn, msg) {
988 // Allow for deprecating things in the process of starting up.
989 if (isUndefined(global.process)) {
990 return function() {
991 return exports.deprecate(fn, msg).apply(this, arguments);
992 };
993 }
994
995 if (process.noDeprecation === true) {
996 return fn;
997 }
998
999 var warned = false;
1000 function deprecated() {
1001 if (!warned) {
1002 if (process.throwDeprecation) {
1003 throw new Error(msg);
1004 } else if (process.traceDeprecation) {
1005 console.trace(msg);
1006 } else {
1007 console.error(msg);
1008 }
1009 warned = true;
1010 }
1011 return fn.apply(this, arguments);
1012 }
1013
1014 return deprecated;
1015};
1016
1017
1018var debugs = {};
1019var debugEnviron;
1020exports.debuglog = function(set) {
1021 if (isUndefined(debugEnviron))
1022 debugEnviron = process.env.NODE_DEBUG || '';
1023 set = set.toUpperCase();
1024 if (!debugs[set]) {
1025 if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
1026 var pid = process.pid;
1027 debugs[set] = function() {
1028 var msg = exports.format.apply(exports, arguments);
1029 console.error('%s %d: %s', set, pid, msg);
1030 };
1031 } else {
1032 debugs[set] = function() {};
1033 }
1034 }
1035 return debugs[set];
1036};
1037
1038
1039/**
1040 * Echos the value of a value. Trys to print the value out
1041 * in the best way possible given the different types.
1042 *
1043 * @param {Object} obj The object to print out.
1044 * @param {Object} opts Optional options object that alters the output.
1045 */
1046/* legacy: obj, showHidden, depth, colors*/
1047function inspect(obj, opts) {
1048 // default options
1049 var ctx = {
1050 seen: [],
1051 stylize: stylizeNoColor
1052 };
1053 // legacy...
1054 if (arguments.length >= 3) ctx.depth = arguments[2];
1055 if (arguments.length >= 4) ctx.colors = arguments[3];
1056 if (isBoolean(opts)) {
1057 // legacy...
1058 ctx.showHidden = opts;
1059 } else if (opts) {
1060 // got an "options" object
1061 exports._extend(ctx, opts);
1062 }
1063 // set default options
1064 if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
1065 if (isUndefined(ctx.depth)) ctx.depth = 2;
1066 if (isUndefined(ctx.colors)) ctx.colors = false;
1067 if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
1068 if (ctx.colors) ctx.stylize = stylizeWithColor;
1069 return formatValue(ctx, obj, ctx.depth);
1070}
1071exports.inspect = inspect;
1072
1073
1074// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
1075inspect.colors = {
1076 'bold' : [1, 22],
1077 'italic' : [3, 23],
1078 'underline' : [4, 24],
1079 'inverse' : [7, 27],
1080 'white' : [37, 39],
1081 'grey' : [90, 39],
1082 'black' : [30, 39],
1083 'blue' : [34, 39],
1084 'cyan' : [36, 39],
1085 'green' : [32, 39],
1086 'magenta' : [35, 39],
1087 'red' : [31, 39],
1088 'yellow' : [33, 39]
1089};
1090
1091// Don't use 'blue' not visible on cmd.exe
1092inspect.styles = {
1093 'special': 'cyan',
1094 'number': 'yellow',
1095 'boolean': 'yellow',
1096 'undefined': 'grey',
1097 'null': 'bold',
1098 'string': 'green',
1099 'date': 'magenta',
1100 // "name": intentionally not styling
1101 'regexp': 'red'
1102};
1103
1104
1105function stylizeWithColor(str, styleType) {
1106 var style = inspect.styles[styleType];
1107
1108 if (style) {
1109 return '\u001b[' + inspect.colors[style][0] + 'm' + str +
1110 '\u001b[' + inspect.colors[style][1] + 'm';
1111 } else {
1112 return str;
1113 }
1114}
1115
1116
1117function stylizeNoColor(str, styleType) {
1118 return str;
1119}
1120
1121
1122function arrayToHash(array) {
1123 var hash = {};
1124
1125 array.forEach(function(val, idx) {
1126 hash[val] = true;
1127 });
1128
1129 return hash;
1130}
1131
1132
1133function formatValue(ctx, value, recurseTimes) {
1134 // Provide a hook for user-specified inspect functions.
1135 // Check that value is an object with an inspect function on it
1136 if (ctx.customInspect &&
1137 value &&
1138 isFunction(value.inspect) &&
1139 // Filter out the util module, it's inspect function is special
1140 value.inspect !== exports.inspect &&
1141 // Also filter out any prototype objects using the circular check.
1142 !(value.constructor && value.constructor.prototype === value)) {
1143 var ret = value.inspect(recurseTimes, ctx);
1144 if (!isString(ret)) {
1145 ret = formatValue(ctx, ret, recurseTimes);
1146 }
1147 return ret;
1148 }
1149
1150 // Primitive types cannot have properties
1151 var primitive = formatPrimitive(ctx, value);
1152 if (primitive) {
1153 return primitive;
1154 }
1155
1156 // Look up the keys of the object.
1157 var keys = Object.keys(value);
1158 var visibleKeys = arrayToHash(keys);
1159
1160 if (ctx.showHidden) {
1161 keys = Object.getOwnPropertyNames(value);
1162 }
1163
1164 // IE doesn't make error fields non-enumerable
1165 // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
1166 if (isError(value)
1167 && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
1168 return formatError(value);
1169 }
1170
1171 // Some type of object without properties can be shortcutted.
1172 if (keys.length === 0) {
1173 if (isFunction(value)) {
1174 var name = value.name ? ': ' + value.name : '';
1175 return ctx.stylize('[Function' + name + ']', 'special');
1176 }
1177 if (isRegExp(value)) {
1178 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
1179 }
1180 if (isDate(value)) {
1181 return ctx.stylize(Date.prototype.toString.call(value), 'date');
1182 }
1183 if (isError(value)) {
1184 return formatError(value);
1185 }
1186 }
1187
1188 var base = '', array = false, braces = ['{', '}'];
1189
1190 // Make Array say that they are Array
1191 if (isArray(value)) {
1192 array = true;
1193 braces = ['[', ']'];
1194 }
1195
1196 // Make functions say that they are functions
1197 if (isFunction(value)) {
1198 var n = value.name ? ': ' + value.name : '';
1199 base = ' [Function' + n + ']';
1200 }
1201
1202 // Make RegExps say that they are RegExps
1203 if (isRegExp(value)) {
1204 base = ' ' + RegExp.prototype.toString.call(value);
1205 }
1206
1207 // Make dates with properties first say the date
1208 if (isDate(value)) {
1209 base = ' ' + Date.prototype.toUTCString.call(value);
1210 }
1211
1212 // Make error with message first say the error
1213 if (isError(value)) {
1214 base = ' ' + formatError(value);
1215 }
1216
1217 if (keys.length === 0 && (!array || value.length == 0)) {
1218 return braces[0] + base + braces[1];
1219 }
1220
1221 if (recurseTimes < 0) {
1222 if (isRegExp(value)) {
1223 return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
1224 } else {
1225 return ctx.stylize('[Object]', 'special');
1226 }
1227 }
1228
1229 ctx.seen.push(value);
1230
1231 var output;
1232 if (array) {
1233 output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
1234 } else {
1235 output = keys.map(function(key) {
1236 return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
1237 });
1238 }
1239
1240 ctx.seen.pop();
1241
1242 return reduceToSingleString(output, base, braces);
1243}
1244
1245
1246function formatPrimitive(ctx, value) {
1247 if (isUndefined(value))
1248 return ctx.stylize('undefined', 'undefined');
1249 if (isString(value)) {
1250 var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
1251 .replace(/'/g, "\\'")
1252 .replace(/\\"/g, '"') + '\'';
1253 return ctx.stylize(simple, 'string');
1254 }
1255 if (isNumber(value))
1256 return ctx.stylize('' + value, 'number');
1257 if (isBoolean(value))
1258 return ctx.stylize('' + value, 'boolean');
1259 // For some reason typeof null is "object", so special case here.
1260 if (isNull(value))
1261 return ctx.stylize('null', 'null');
1262}
1263
1264
1265function formatError(value) {
1266 return '[' + Error.prototype.toString.call(value) + ']';
1267}
1268
1269
1270function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
1271 var output = [];
1272 for (var i = 0, l = value.length; i < l; ++i) {
1273 if (hasOwnProperty(value, String(i))) {
1274 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
1275 String(i), true));
1276 } else {
1277 output.push('');
1278 }
1279 }
1280 keys.forEach(function(key) {
1281 if (!key.match(/^\d+$/)) {
1282 output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
1283 key, true));
1284 }
1285 });
1286 return output;
1287}
1288
1289
1290function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
1291 var name, str, desc;
1292 desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
1293 if (desc.get) {
1294 if (desc.set) {
1295 str = ctx.stylize('[Getter/Setter]', 'special');
1296 } else {
1297 str = ctx.stylize('[Getter]', 'special');
1298 }
1299 } else {
1300 if (desc.set) {
1301 str = ctx.stylize('[Setter]', 'special');
1302 }
1303 }
1304 if (!hasOwnProperty(visibleKeys, key)) {
1305 name = '[' + key + ']';
1306 }
1307 if (!str) {
1308 if (ctx.seen.indexOf(desc.value) < 0) {
1309 if (isNull(recurseTimes)) {
1310 str = formatValue(ctx, desc.value, null);
1311 } else {
1312 str = formatValue(ctx, desc.value, recurseTimes - 1);
1313 }
1314 if (str.indexOf('\n') > -1) {
1315 if (array) {
1316 str = str.split('\n').map(function(line) {
1317 return ' ' + line;
1318 }).join('\n').substr(2);
1319 } else {
1320 str = '\n' + str.split('\n').map(function(line) {
1321 return ' ' + line;
1322 }).join('\n');
1323 }
1324 }
1325 } else {
1326 str = ctx.stylize('[Circular]', 'special');
1327 }
1328 }
1329 if (isUndefined(name)) {
1330 if (array && key.match(/^\d+$/)) {
1331 return str;
1332 }
1333 name = JSON.stringify('' + key);
1334 if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
1335 name = name.substr(1, name.length - 2);
1336 name = ctx.stylize(name, 'name');
1337 } else {
1338 name = name.replace(/'/g, "\\'")
1339 .replace(/\\"/g, '"')
1340 .replace(/(^"|"$)/g, "'");
1341 name = ctx.stylize(name, 'string');
1342 }
1343 }
1344
1345 return name + ': ' + str;
1346}
1347
1348
1349function reduceToSingleString(output, base, braces) {
1350 var numLinesEst = 0;
1351 var length = output.reduce(function(prev, cur) {
1352 numLinesEst++;
1353 if (cur.indexOf('\n') >= 0) numLinesEst++;
1354 return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
1355 }, 0);
1356
1357 if (length > 60) {
1358 return braces[0] +
1359 (base === '' ? '' : base + '\n ') +
1360 ' ' +
1361 output.join(',\n ') +
1362 ' ' +
1363 braces[1];
1364 }
1365
1366 return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
1367}
1368
1369
1370// NOTE: These type checking functions intentionally don't use `instanceof`
1371// because it is fragile and can be easily faked with `Object.create()`.
1372function isArray(ar) {
1373 return Array.isArray(ar);
1374}
1375exports.isArray = isArray;
1376
1377function isBoolean(arg) {
1378 return typeof arg === 'boolean';
1379}
1380exports.isBoolean = isBoolean;
1381
1382function isNull(arg) {
1383 return arg === null;
1384}
1385exports.isNull = isNull;
1386
1387function isNullOrUndefined(arg) {
1388 return arg == null;
1389}
1390exports.isNullOrUndefined = isNullOrUndefined;
1391
1392function isNumber(arg) {
1393 return typeof arg === 'number';
1394}
1395exports.isNumber = isNumber;
1396
1397function isString(arg) {
1398 return typeof arg === 'string';
1399}
1400exports.isString = isString;
1401
1402function isSymbol(arg) {
1403 return typeof arg === 'symbol';
1404}
1405exports.isSymbol = isSymbol;
1406
1407function isUndefined(arg) {
1408 return arg === void 0;
1409}
1410exports.isUndefined = isUndefined;
1411
1412function isRegExp(re) {
1413 return isObject(re) && objectToString(re) === '[object RegExp]';
1414}
1415exports.isRegExp = isRegExp;
1416
1417function isObject(arg) {
1418 return typeof arg === 'object' && arg !== null;
1419}
1420exports.isObject = isObject;
1421
1422function isDate(d) {
1423 return isObject(d) && objectToString(d) === '[object Date]';
1424}
1425exports.isDate = isDate;
1426
1427function isError(e) {
1428 return isObject(e) &&
1429 (objectToString(e) === '[object Error]' || e instanceof Error);
1430}
1431exports.isError = isError;
1432
1433function isFunction(arg) {
1434 return typeof arg === 'function';
1435}
1436exports.isFunction = isFunction;
1437
1438function isPrimitive(arg) {
1439 return arg === null ||
1440 typeof arg === 'boolean' ||
1441 typeof arg === 'number' ||
1442 typeof arg === 'string' ||
1443 typeof arg === 'symbol' || // ES6 symbol
1444 typeof arg === 'undefined';
1445}
1446exports.isPrimitive = isPrimitive;
1447
1448exports.isBuffer = require('./support/isBuffer');
1449
1450function objectToString(o) {
1451 return Object.prototype.toString.call(o);
1452}
1453
1454
1455function pad(n) {
1456 return n < 10 ? '0' + n.toString(10) : n.toString(10);
1457}
1458
1459
1460var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
1461 'Oct', 'Nov', 'Dec'];
1462
1463// 26 Feb 16:19:34
1464function timestamp() {
1465 var d = new Date();
1466 var time = [pad(d.getHours()),
1467 pad(d.getMinutes()),
1468 pad(d.getSeconds())].join(':');
1469 return [d.getDate(), months[d.getMonth()], time].join(' ');
1470}
1471
1472
1473// log is just a thin wrapper to console.log that prepends a timestamp
1474exports.log = function() {
1475 console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
1476};
1477
1478
1479/**
1480 * Inherit the prototype methods from one constructor into another.
1481 *
1482 * The Function.prototype.inherits from lang.js rewritten as a standalone
1483 * function (not on Function.prototype). NOTE: If this file is to be loaded
1484 * during bootstrapping this function needs to be rewritten using some native
1485 * functions as prototype setup using normal JavaScript does not work as
1486 * expected during bootstrapping (see mirror.js in r114903).
1487 *
1488 * @param {function} ctor Constructor function which needs to inherit the
1489 * prototype.
1490 * @param {function} superCtor Constructor function to inherit prototype from.
1491 */
1492exports.inherits = require('inherits');
1493
1494exports._extend = function(origin, add) {
1495 // Don't do anything if add isn't an object
1496 if (!add || !isObject(add)) return origin;
1497
1498 var keys = Object.keys(add);
1499 var i = keys.length;
1500 while (i--) {
1501 origin[keys[i]] = add[keys[i]];
1502 }
1503 return origin;
1504};
1505
1506function hasOwnProperty(obj, prop) {
1507 return Object.prototype.hasOwnProperty.call(obj, prop);
1508}
1509
1510},{"./support/isBuffer":18,"inherits":17}],20:[function(require,module,exports){
1511module.exports={
1512 "name": "web-bootloader",
1513 "description": "",
1514 "version": "1.0.2",
1515 "homepage": "https://github.com/dominictarr/web-bootloader",
1516 "repository": {
1517 "type": "git",
1518 "url": "git://github.com/dominictarr/web-bootloader.git"
1519 },
1520 "devDependencies": {
1521 "arraybuffer-base64": "^1.0.0",
1522 "binary-xhr": "0.0.2",
1523 "browserify": "^13.0.1",
1524 "hyperfile": "^1.1.1",
1525 "hyperprogress": "^0.1.1",
1526 "indexhtmlify": "^1.3.0",
1527 "tape": "^4.6.0"
1528 },
1529 "browser": {
1530 "./_util": false
1531 },
1532 "scripts": {
1533 "test": "set -e; for t in test/*.js; do node $t; done",
1534 "build": "browserify index.js --igv , | indexhtmlify --appcache > index.html && node handler/cache.js > manifest.appcache",
1535 "gh-pages": "git checkout master && git branch -D gh-pages ; git checkout -b gh-pages && git push origin gh-pages; git checkout master"
1536 },
1537 "author": "'Dominic Tarr' <dominic.tarr@gmail.com> (dominictarr.com)",
1538 "license": "MIT",
1539 "dependencies": {
1540 "hscrpt": "0.0.1",
1541 "human-time": "0.0.1"
1542 }
1543}
1544
1545},{}],21:[function(require,module,exports){
1546var u = require('./util')
1547
1548module.exports = function (prefix, storage) {
1549 return {
1550 get: function (id, cb) {
1551 var data = (
1552 storage[prefix+'_versions_'+id] || storage[prefix+'_version_'+id]
1553 )
1554 if(data)
1555 u.hash(data, function (err, _id) {
1556 if(err) cb(err)
1557 else if(_id !== id) cb(u.HashError(_id, id))
1558 else cb(null, data)
1559 })
1560 else cb(new Error('not found:'+id))
1561 },
1562
1563 add: function (data, id, cb) {
1564 if(!cb) cb = id, id = null
1565 u.hash(data, function (err, _id) {
1566 if(err) cb(err)
1567 else if(id && _id !== id) cb(u.HashError(_id, id))
1568 else {
1569 try {
1570 storage[prefix+'_versions_'+_id] = u.toUtf8(data)
1571 }
1572 catch(err) { return cb(err) } //this will be quota error
1573 cb(null, _id)
1574 }
1575 })
1576 },
1577
1578 has: function (id, cb) {
1579 return cb(null,
1580 !!storage[prefix+'_versions_'+id] ||
1581 !!storage[prefix+'_version_'+id] //legacy
1582 )
1583 },
1584
1585 rm: function (id, cb) {
1586 delete storage[prefix+'_versions_'+id]
1587
1588 cb()
1589 },
1590
1591
1592 ls: function (cb) {
1593 var match = new RegExp('^'+prefix+'_versions_'), ary = []
1594 for(var key in storage) {
1595 if(match.test(key)) {
1596 var data = storage[key]
1597 ary.push({
1598 id: key.replace(match, ''),
1599 size: data && data.length || 0
1600 })
1601 }
1602 }
1603 cb(null, ary)
1604 },
1605
1606 destroy: function (cb) {
1607 var match = new RegExp('^'+prefix+'_versions_')
1608 for(var key in storage) {
1609 if(match.test(key)) {
1610 delete storage[key]
1611 }
1612 }
1613
1614 cb()
1615 }
1616 }
1617}
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635},{"./util":23}],22:[function(require,module,exports){
1636var h = require('hscrpt')
1637var input_file = require('hyperfile')
1638var Progress = require('hyperprogress')
1639var u = require('./util')
1640var prog = Progress()
1641
1642//split the hash.
1643var parts = window.location.hash.split('#').slice(1)
1644var QUOTA = 5*1024*1024
1645
1646var human = require('human-time')
1647
1648module.exports = function (appname, wb) {
1649 document.body.appendChild(prog)
1650
1651 function nice_error(err, msg) {
1652 if(err.name && err.message && err.stack)
1653 return err
1654 if('object' !== typeof err)
1655 return new Error(msg+JSON.stringify(err))
1656 }
1657
1658 function btn (label, action) {
1659 return h('button', {onclick: action}, [label])
1660 }
1661
1662 function kb (bytes) {
1663 return (Math.round((bytes / 1024) * 100)/100) + 'k'
1664 }
1665
1666// var isElectron = typeof process !== 'undefined'
1667// && process.env && process.env[appname+'_INIT']
1668
1669 function handleQuota(err, data, id) {
1670 if(err
1671 && err.name == "QuotaExceededError"
1672 && confirm ('adding: '+id+' exceedes quota, clear cache?')
1673 ) {
1674 wb.prune(data.length, function (err) {
1675 if(err) throw prog.fail(err)
1676 wb.add(data, id, function (err) {
1677 if(err) throw prog.fail(err)
1678 wb.run(id, function (err) {
1679 if(err) throw prog.fail(err)
1680 })
1681 })
1682 })
1683 }
1684 else if(!err) wb.run(id, function (err) {
1685 if(err) throw prog.fail(err)
1686 })
1687 else
1688 throw prog.fail(err)
1689 }
1690
1691 ;(function redraw () {
1692 wb.versions(function (err, log) {
1693 if(err) throw prog.fail(err)
1694 document.body.innerHTML = ''
1695 if(log.length && !wb.isInit())
1696 return wb.run(log[0].value, function (err) {
1697 if(err) throw prog.fail(err)
1698 })
1699
1700 document.body.appendChild(
1701 h('div', {classList: 'WebBoot'}, [
1702 ( !log.length
1703 ? h('h2', 'please enter secure-url or select file to run')
1704 : h('ol', {classList: 'WebBoot__recent'}, log.map(function (v) {
1705 return h('li', [
1706 h('code', [v.value]),
1707 h('label',
1708 { title: new Date(v.ts).toString() },
1709 [ ' (loaded ', human(new Date(v.ts)), ') ']
1710 ),
1711 h('div', [
1712 btn('run', function () {
1713 wb.run(v.value)
1714 }),
1715 btn('revert', function () {
1716 wb.revert(v.ts, function (err) {
1717 if(err) throw prog.fail(err)
1718 redraw()
1719 })
1720 })
1721 ])
1722 ])
1723 }))
1724 ),
1725
1726 //paste a secure url into this text input
1727 h('input', {
1728 placeholder: 'enter secure url',
1729 onchange: function (ev) {
1730 //else, download it. if that succeeds,
1731 //add to store, if success, run.
1732 //if that fails, offer to clean up, or fail.
1733 //add to store, if success, run.
1734
1735 //this can fail from quota exceeded.
1736 //check whether we have this already, if so, run it.
1737 var url = ev.target.value
1738
1739 wb.install(url, handleQuota)
1740 }
1741 }),
1742
1743 //or select a local file to run
1744 input_file(function (data) {
1745 wb.add(data, function (err, id) {
1746 handleQuota(err, data, id)
1747 })
1748 })
1749 ])
1750 )
1751 })
1752 })()
1753
1754}
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769},{"./util":23,"hscrpt":10,"human-time":11,"hyperfile":12,"hyperprogress":13}],23:[function(require,module,exports){
1770//attempt to load node version.
1771u = require('./_util')
1772if(u.parse) return module.exports = u, console.log("loaded node version for testing")
1773
1774var decoder = new TextDecoder('utf8')
1775var encoder = new TextEncoder('utf8')
1776var u = exports
1777
1778u.toUtf8 = function (data) {
1779 return 'string' == typeof data ? data : decoder.decode(data)
1780}
1781
1782u.toBuffer = function (data) {
1783 return 'string' !== typeof data
1784 ? data
1785 : new Uint8Array(encoder.encode(data))
1786}
1787
1788u.toBase64 = require('arraybuffer-base64')
1789
1790u.hash = function (data, cb) {
1791 window.crypto.subtle.digest(
1792 { name: "SHA-256" },
1793 u.toBuffer(data)
1794 )
1795 .then(function(hash){
1796 return cb(null, exports.toBase64(new Uint8Array(hash)))
1797 })
1798 .catch(function(err){
1799 cb(err)
1800 })
1801}
1802
1803u.parse = function (str) {
1804 try {
1805 return JSON.parse(str)
1806 } catch (_) { }
1807}
1808
1809u.HashError = function (_id, id) {
1810 return new Error('incorrect hash:'+_id+'\n expected:'+id)
1811}
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826},{"./_util":7,"arraybuffer-base64":5}]},{},[3]);
1827</script>
1828</html>
1829

Built with git-ssb-web