OSZAR »
` function generate () { var seed = '' for (var i = 0; i < 8; i++) { seed += String.fromCharCode(97+Math.random()*26) } location.hash = seed emit('generate', seed) emit('frame') } }) app.mount(document.body) app.use(function (state, emitter) { state.canvas = document.createElement('canvas') emitter.on('resize', onresize) onresize() function onresize () { state.canvas.setAttribute('width', window.innerWidth) state.canvas.setAttribute('height', window.innerHeight) } state.regl = require('regl')({ extensions: [ 'oes_standard_derivatives', 'oes_element_index_uint' ], canvas: state.canvas }) state.camera = require('regl-camera')(state.regl, { theta: Math.PI/4, phi: 45*Math.PI/180, maxDistance: 10, distance: 3, minDistance: 0.3 }) state.draw = [] emitter.on('add-draw', function (draw) { state.draw.push(draw(state.regl)) }) state.drawing = false emitter.on('frame', function () { if (state.drawing) return state.drawing = true window.requestAnimationFrame(frame) }) function frame () { state.drawing = false state.regl.poll() state.regl.clear({ color: [0.2,0.2,0.2,1], depth: true }) state.camera(function () { for (var i = 0; i < state.draw.length; i++) { var d = state.draw[i] if (typeof d.draw === 'function') d.draw(state) } for (var i = 0; i < state.draw.length; i++) { var d = state.draw[i] if (typeof d.postDraw === 'function') d.postDraw(state) } }) } }) app.use(function (state, emitter) { emitter.emit('add-draw', require('./draw/tile.js')) emitter.emit('add-draw', require('./draw/ocean.js')) emitter.emit('add-draw', require('./draw/wall.js')) }) app.use(require('./store/tile.js')) app.use(require('./store/ocean.js')) app.use(function (state, emitter) { emitter.emit('generate', location.hash.slice(1)) }) app.use(function (state, emitter) { emitter.emit('frame') window.addEventListener('mousemove', onmouse) window.addEventListener('mousedown', onmouse) window.addEventListener('mouseup', onmouse) window.addEventListener('wheel', onmouse) function onmouse (ev) { emitter.emit('frame') } window.addEventListener('resize', function () { emitter.emit('frame') }) }) },{"./draw/ocean.js":6,"./draw/tile.js":7,"./draw/wall.js":8,"./store/ocean.js":49,"./store/tile.js":50,"choo":14,"choo/html":13,"regl":40,"regl-camera":39}],10:[function(require,module,exports){ var trailingNewlineRegex = /\n[\s]+$/ var leadingNewlineRegex = /^\n[\s]+/ var trailingSpaceRegex = /[\s]+$/ var leadingSpaceRegex = /^[\s]+/ var multiSpaceRegex = /[\n\s]+/g var TEXT_TAGS = [ 'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'data', 'dfn', 'em', 'i', 'kbd', 'mark', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'amp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr' ] var VERBATIM_TAGS = [ 'code', 'pre', 'textarea' ] module.exports = function appendChild (el, childs) { if (!Array.isArray(childs)) return var nodeName = el.nodeName.toLowerCase() var hadText = false var value, leader for (var i = 0, len = childs.length; i < len; i++) { var node = childs[i] if (Array.isArray(node)) { appendChild(el, node) continue } if (typeof node === 'number' || typeof node === 'boolean' || typeof node === 'function' || node instanceof Date || node instanceof RegExp) { node = node.toString() } var lastChild = el.childNodes[el.childNodes.length - 1] // Iterate over text nodes if (typeof node === 'string') { hadText = true // If we already had text, append to the existing text if (lastChild && lastChild.nodeName === '#text') { lastChild.nodeValue += node // We didn't have a text node yet, create one } else { node = document.createTextNode(node) el.appendChild(node) lastChild = node } // If this is the last of the child nodes, make sure we close it out // right if (i === len - 1) { hadText = false // Trim the child text nodes if the current node isn't a // node where whitespace matters. if (TEXT_TAGS.indexOf(nodeName) === -1 && VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingNewlineRegex, '') .replace(trailingSpaceRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') if (value === '') { el.removeChild(lastChild) } else { lastChild.nodeValue = value } } else if (VERBATIM_TAGS.indexOf(nodeName) === -1) { // The very first node in the list should not have leading // whitespace. Sibling text nodes should have whitespace if there // was any. leader = i === 0 ? '' : ' ' value = lastChild.nodeValue .replace(leadingNewlineRegex, leader) .replace(leadingSpaceRegex, ' ') .replace(trailingSpaceRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') lastChild.nodeValue = value } } // Iterate over DOM nodes } else if (node && node.nodeType) { // If the last node was a text node, make sure it is properly closed out if (hadText) { hadText = false // Trim the child text nodes if the current node isn't a // text node or a code node if (TEXT_TAGS.indexOf(nodeName) === -1 && VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingNewlineRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') // Remove empty text nodes, append otherwise if (value === '') { el.removeChild(lastChild) } else { lastChild.nodeValue = value } // Trim the child nodes if the current node is not a node // where all whitespace must be preserved } else if (VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingSpaceRegex, ' ') .replace(leadingNewlineRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') lastChild.nodeValue = value } } // Store the last nodename var _nodeName = node.nodeName if (_nodeName) nodeName = _nodeName.toLowerCase() // Append the node to the DOM el.appendChild(node) } } } },{}],11:[function(require,module,exports){ var hyperx = require('hyperx') var appendChild = require('./appendChild') var SVGNS = 'http://www.w3.org/2000/svg' var XLINKNS = 'http://www.w3.org/1999/xlink' var BOOL_PROPS = [ 'autofocus', 'checked', 'defaultchecked', 'disabled', 'formnovalidate', 'indeterminate', 'readonly', 'required', 'selected', 'willvalidate' ] var COMMENT_TAG = '!--' var SVG_TAGS = [ 'svg', 'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile', 'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignObject', 'g', 'glyph', 'glyphRef', 'hkern', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'set', 'stop', 'switch', 'symbol', 'text', 'textPath', 'title', 'tref', 'tspan', 'use', 'view', 'vkern' ] function belCreateElement (tag, props, children) { var el // If an svg tag, it needs a namespace if (SVG_TAGS.indexOf(tag) !== -1) { props.namespace = SVGNS } // If we are using a namespace var ns = false if (props.namespace) { ns = props.namespace delete props.namespace } // Create the element if (ns) { el = document.createElementNS(ns, tag) } else if (tag === COMMENT_TAG) { return document.createComment(props.comment) } else { el = document.createElement(tag) } // Create the properties for (var p in props) { if (props.hasOwnProperty(p)) { var key = p.toLowerCase() var val = props[p] // Normalize className if (key === 'classname') { key = 'class' p = 'class' } // The for attribute gets transformed to htmlFor, but we just set as for if (p === 'htmlFor') { p = 'for' } // If a property is boolean, set itself to the key if (BOOL_PROPS.indexOf(key) !== -1) { if (val === 'true') val = key else if (val === 'false') continue } // If a property prefers being set directly vs setAttribute if (key.slice(0, 2) === 'on') { el[p] = val } else { if (ns) { if (p === 'xlink:href') { el.setAttributeNS(XLINKNS, p, val) } else if (/^xmlns($|:)/i.test(p)) { // skip xmlns definitions } else { el.setAttributeNS(null, p, val) } } else { el.setAttribute(p, val) } } } } appendChild(el, children) return el } module.exports = hyperx(belCreateElement, {comments: true}) module.exports.default = module.exports module.exports.createElement = belCreateElement },{"./appendChild":10,"hyperx":21}],12:[function(require,module,exports){ var assert = require('assert') var LRU = require('nanolru') module.exports = ChooComponentCache function ChooComponentCache (state, emit, lru) { assert.ok(this instanceof ChooComponentCache, 'ChooComponentCache should be created with `new`') assert.equal(typeof state, 'object', 'ChooComponentCache: state should be type object') assert.equal(typeof emit, 'function', 'ChooComponentCache: emit should be type function') if (typeof lru === 'number') this.cache = new LRU(lru) else this.cache = lru || new LRU(100) this.state = state this.emit = emit } // Get & create component instances. ChooComponentCache.prototype.render = function (Component, id) { assert.equal(typeof Component, 'function', 'ChooComponentCache.render: Component should be type function') assert.ok(typeof id === 'string' || typeof id === 'number', 'ChooComponentCache.render: id should be type string or type number') var el = this.cache.get(id) if (!el) { var args = [] for (var i = 2, len = arguments.length; i < len; i++) { args.push(arguments[i]) } args.unshift(Component, id, this.state, this.emit) el = newCall.apply(newCall, args) this.cache.set(id, el) } return el } // Because you can't call `new` and `.apply()` at the same time. This is a mad // hack, but hey it works so we gonna go for it. Whoop. function newCall (Cls) { return new (Cls.bind.apply(Cls, arguments)) // eslint-disable-line } },{"assert":1,"nanolru":29}],13:[function(require,module,exports){ module.exports = require('bel') },{"bel":11}],14:[function(require,module,exports){ var scrollToAnchor = require('scroll-to-anchor') var documentReady = require('document-ready') var nanolocation = require('nanolocation') var nanotiming = require('nanotiming') var nanorouter = require('nanorouter') var nanomorph = require('nanomorph') var nanoquery = require('nanoquery') var nanohref = require('nanohref') var nanoraf = require('nanoraf') var nanobus = require('nanobus') var assert = require('assert') var xtend = require('xtend') var Cache = require('./component/cache') module.exports = Choo var HISTORY_OBJECT = {} function Choo (opts) { if (!(this instanceof Choo)) return new Choo(opts) opts = opts || {} assert.equal(typeof opts, 'object', 'choo: opts should be type object') var self = this // define events used by choo this._events = { DOMCONTENTLOADED: 'DOMContentLoaded', DOMTITLECHANGE: 'DOMTitleChange', REPLACESTATE: 'replaceState', PUSHSTATE: 'pushState', NAVIGATE: 'navigate', POPSTATE: 'popState', RENDER: 'render' } // properties for internal use only this._historyEnabled = opts.history === undefined ? true : opts.history this._hrefEnabled = opts.href === undefined ? true : opts.href this._hasWindow = typeof window !== 'undefined' this._createLocation = nanolocation this._cache = opts.cache this._loaded = false this._stores = [] this._tree = null // state var _state = { events: this._events, components: {} } if (this._hasWindow) { this.state = window.initialState ? xtend(window.initialState, _state) : _state delete window.initialState } else { this.state = _state } // properties that are part of the API this.router = nanorouter({ curry: true }) this.emitter = nanobus('choo.emit') this.emit = this.emitter.emit.bind(this.emitter) // listen for title changes; available even when calling .toString() if (this._hasWindow) this.state.title = document.title this.emitter.prependListener(this._events.DOMTITLECHANGE, function (title) { assert.equal(typeof title, 'string', 'events.DOMTitleChange: title should be type string') self.state.title = title if (self._hasWindow) document.title = title }) } Choo.prototype.route = function (route, handler) { assert.equal(typeof route, 'string', 'choo.route: route should be type string') assert.equal(typeof handler, 'function', 'choo.handler: route should be type function') this.router.on(route, handler) } Choo.prototype.use = function (cb) { assert.equal(typeof cb, 'function', 'choo.use: cb should be type function') var self = this this._stores.push(function (state) { var msg = 'choo.use' msg = cb.storeName ? msg + '(' + cb.storeName + ')' : msg var endTiming = nanotiming(msg) cb(state, self.emitter, self) endTiming() }) } Choo.prototype.start = function () { assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node') var self = this if (this._historyEnabled) { this.emitter.prependListener(this._events.NAVIGATE, function () { self._matchRoute() if (self._loaded) { self.emitter.emit(self._events.RENDER) setTimeout(scrollToAnchor.bind(null, window.location.hash), 0) } }) this.emitter.prependListener(this._events.POPSTATE, function () { self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.PUSHSTATE, function (href) { assert.equal(typeof href, 'string', 'events.pushState: href should be type string') window.history.pushState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.REPLACESTATE, function (href) { assert.equal(typeof href, 'string', 'events.replaceState: href should be type string') window.history.replaceState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) window.onpopstate = function () { self.emitter.emit(self._events.POPSTATE) } if (self._hrefEnabled) { nanohref(function (location) { var href = location.href var currHref = window.location.href if (href === currHref) return self.emitter.emit(self._events.PUSHSTATE, href) }) } } this._setCache(this.state) this._stores.forEach(function (initStore) { initStore(self.state) }) this._matchRoute() this._tree = this._prerender(this.state) assert.ok(this._tree, 'choo.start: no valid DOM node returned for location ' + this.state.href) this.emitter.prependListener(self._events.RENDER, nanoraf(function () { var renderTiming = nanotiming('choo.render') var newTree = self._prerender(self.state) assert.ok(newTree, 'choo.render: no valid DOM node returned for location ' + self.state.href) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.render: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() })) documentReady(function () { self.emitter.emit(self._events.DOMCONTENTLOADED) self._loaded = true }) return this._tree } Choo.prototype.mount = function mount (selector) { if (typeof window !== 'object') { assert.ok(typeof selector === 'string', 'choo.mount: selector should be type String') this.selector = selector return this } assert.ok(typeof selector === 'string' || typeof selector === 'object', 'choo.mount: selector should be type String or HTMLElement') var self = this documentReady(function () { var renderTiming = nanotiming('choo.render') var newTree = self.start() if (typeof selector === 'string') { self._tree = document.querySelector(selector) } else { self._tree = selector } assert.ok(self._tree, 'choo.mount: could not query selector: ' + selector) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.mount: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() }) } Choo.prototype.toString = function (location, state) { this.state = xtend(this.state, state || {}) assert.notEqual(typeof window, 'object', 'choo.mount: window was found. .toString() must be called in Node, use .start() or .mount() if running in the browser') assert.equal(typeof location, 'string', 'choo.toString: location should be type string') assert.equal(typeof this.state, 'object', 'choo.toString: state should be type object') var self = this this._setCache(this.state) this._stores.forEach(function (initStore) { initStore(self.state) }) this._matchRoute(location) var html = this._prerender(this.state) assert.ok(html, 'choo.toString: no valid value returned for the route ' + location) assert(!Array.isArray(html), 'choo.toString: return value was an array for the route ' + location) return typeof html.outerHTML === 'string' ? html.outerHTML : html.toString() } Choo.prototype._matchRoute = function (locationOverride) { var location, queryString if (locationOverride) { location = locationOverride.replace(/\?.+$/, '') queryString = locationOverride } else { location = this._createLocation() queryString = window.location.search } var matched = this.router.match(location) this._handler = matched.cb this.state.href = location this.state.query = nanoquery(queryString) this.state.route = matched.route this.state.params = matched.params return this.state } Choo.prototype._prerender = function (state) { var routeTiming = nanotiming("choo.prerender('" + state.route + "')") var res = this._handler(state, this.emit) routeTiming() return res } Choo.prototype._setCache = function (state) { var cache = new Cache(state, this.emitter.emit.bind(this.emitter), this._cache) state.cache = renderComponent function renderComponent (Component, id) { assert.equal(typeof Component, 'function', 'choo.state.cache: Component should be type function') var args = [] for (var i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]) } return cache.render.apply(cache, args) } // When the state gets stringified, make sure `state.cache` isn't // stringified too. renderComponent.toJSON = function () { return null } } },{"./component/cache":12,"assert":1,"document-ready":15,"nanobus":26,"nanohref":27,"nanolocation":28,"nanomorph":30,"nanoquery":33,"nanoraf":34,"nanorouter":35,"nanotiming":37,"scroll-to-anchor":42,"xtend":47}],15:[function(require,module,exports){ 'use strict' var assert = require('assert') module.exports = ready function ready (callback) { assert.notEqual(typeof document, 'undefined', 'document-ready only runs in the browser') var state = document.readyState if (state === 'complete' || state === 'interactive') { return setTimeout(callback, 0) } document.addEventListener('DOMContentLoaded', function onLoad () { callback() }) } },{"assert":1}],16:[function(require,module,exports){ 'use strict'; module.exports = earcut; module.exports.default = earcut; function earcut(data, holeIndices, dim) { dim = dim || 2; var hasHoles = holeIndices && holeIndices.length, outerLen = hasHoles ? holeIndices[0] * dim : data.length, outerNode = linkedList(data, 0, outerLen, dim, true), triangles = []; if (!outerNode) return triangles; var minX, minY, maxX, maxY, x, y, invSize; if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox if (data.length > 80 * dim) { minX = maxX = data[0]; minY = maxY = data[1]; for (var i = dim; i < outerLen; i += dim) { x = data[i]; y = data[i + 1]; if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } // minX, minY and invSize are later used to transform coords into integers for z-order calculation invSize = Math.max(maxX - minX, maxY - minY); invSize = invSize !== 0 ? 1 / invSize : 0; } earcutLinked(outerNode, triangles, dim, minX, minY, invSize); return triangles; } // create a circular doubly linked list from polygon points in the specified winding order function linkedList(data, start, end, dim, clockwise) { var i, last; if (clockwise === (signedArea(data, start, end, dim) > 0)) { for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); } else { for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); } if (last && equals(last, last.next)) { removeNode(last); last = last.next; } return last; } // eliminate colinear or duplicate points function filterPoints(start, end) { if (!start) return start; if (!end) end = start; var p = start, again; do { again = false; if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { removeNode(p); p = end = p.prev; if (p === p.next) break; again = true; } else { p = p.next; } } while (again || p !== end); return end; } // main ear slicing loop which triangulates a polygon (given as a linked list) function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { if (!ear) return; // interlink polygon nodes in z-order if (!pass && invSize) indexCurve(ear, minX, minY, invSize); var stop = ear, prev, next; // iterate through ears, slicing them one by one while (ear.prev !== ear.next) { prev = ear.prev; next = ear.next; if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { // cut off the triangle triangles.push(prev.i / dim); triangles.push(ear.i / dim); triangles.push(next.i / dim); removeNode(ear); // skipping the next vertice leads to less sliver triangles ear = next.next; stop = next.next; continue; } ear = next; // if we looped through the whole remaining polygon and can't find any more ears if (ear === stop) { // try filtering points and slicing again if (!pass) { earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); // if this didn't work, try curing all small self-intersections locally } else if (pass === 1) { ear = cureLocalIntersections(ear, triangles, dim); earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); // as a last resort, try splitting the remaining polygon into two } else if (pass === 2) { splitEarcut(ear, triangles, dim, minX, minY, invSize); } break; } } } // check whether a polygon node forms a valid ear with adjacent nodes function isEar(ear) { var a = ear.prev, b = ear, c = ear.next; if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // now make sure we don't have other points inside the potential ear var p = ear.next.next; while (p !== ear.prev) { if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.next; } return true; } function isEarHashed(ear, minX, minY, invSize) { var a = ear.prev, b = ear, c = ear.next; if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // triangle bbox; min & max are calculated like this for speed var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); // z-order range for the current triangle bbox; var minZ = zOrder(minTX, minTY, minX, minY, invSize), maxZ = zOrder(maxTX, maxTY, minX, minY, invSize); var p = ear.prevZ, n = ear.nextZ; // look for points inside the triangle in both directions while (p && p.z >= minZ && n && n.z <= maxZ) { if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.prevZ; if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; n = n.nextZ; } // look for remaining points in decreasing z-order while (p && p.z >= minZ) { if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.prevZ; } // look for remaining points in increasing z-order while (n && n.z <= maxZ) { if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; n = n.nextZ; } return true; } // go through all polygon nodes and cure small local self-intersections function cureLocalIntersections(start, triangles, dim) { var p = start; do { var a = p.prev, b = p.next.next; if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { triangles.push(a.i / dim); triangles.push(p.i / dim); triangles.push(b.i / dim); // remove two nodes involved removeNode(p); removeNode(p.next); p = start = b; } p = p.next; } while (p !== start); return p; } // try splitting polygon into two and triangulate them independently function splitEarcut(start, triangles, dim, minX, minY, invSize) { // look for a valid diagonal that divides the polygon into two var a = start; do { var b = a.next.next; while (b !== a.prev) { if (a.i !== b.i && isValidDiagonal(a, b)) { // split the polygon in two by the diagonal var c = splitPolygon(a, b); // filter colinear points around the cuts a = filterPoints(a, a.next); c = filterPoints(c, c.next); // run earcut on each half earcutLinked(a, triangles, dim, minX, minY, invSize); earcutLinked(c, triangles, dim, minX, minY, invSize); return; } b = b.next; } a = a.next; } while (a !== start); } // link every hole into the outer loop, producing a single-ring polygon without holes function eliminateHoles(data, holeIndices, outerNode, dim) { var queue = [], i, len, start, end, list; for (i = 0, len = holeIndices.length; i < len; i++) { start = holeIndices[i] * dim; end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; list = linkedList(data, start, end, dim, false); if (list === list.next) list.steiner = true; queue.push(getLeftmost(list)); } queue.sort(compareX); // process holes from left to right for (i = 0; i < queue.length; i++) { eliminateHole(queue[i], outerNode); outerNode = filterPoints(outerNode, outerNode.next); } return outerNode; } function compareX(a, b) { return a.x - b.x; } // find a bridge between vertices that connects hole with an outer ring and and link it function eliminateHole(hole, outerNode) { outerNode = findHoleBridge(hole, outerNode); if (outerNode) { var b = splitPolygon(outerNode, hole); filterPoints(b, b.next); } } // David Eberly's algorithm for finding a bridge between hole and outer polygon function findHoleBridge(hole, outerNode) { var p = outerNode, hx = hole.x, hy = hole.y, qx = -Infinity, m; // find a segment intersected by a ray from the hole's leftmost point to the left; // segment's endpoint with lesser x will be potential connection point do { if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); if (x <= hx && x > qx) { qx = x; if (x === hx) { if (hy === p.y) return p; if (hy === p.next.y) return p.next; } m = p.x < p.next.x ? p : p.next; } } p = p.next; } while (p !== outerNode); if (!m) return null; if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint // look for points inside the triangle of hole point, segment intersection and endpoint; // if there are no points found, we have a valid connection; // otherwise choose the point of the minimum angle with the ray as connection point var stop = m, mx = m.x, my = m.y, tanMin = Infinity, tan; p = m.next; while (p !== stop) { if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { tan = Math.abs(hy - p.y) / (hx - p.x); // tangential if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { m = p; tanMin = tan; } } p = p.next; } return m; } // interlink polygon nodes in z-order function indexCurve(start, minX, minY, invSize) { var p = start; do { if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize); p.prevZ = p.prev; p.nextZ = p.next; p = p.next; } while (p !== start); p.prevZ.nextZ = null; p.prevZ = null; sortLinked(p); } // Simon Tatham's linked list merge sort algorithm // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html function sortLinked(list) { var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; do { p = list; list = null; tail = null; numMerges = 0; while (p) { numMerges++; q = p; pSize = 0; for (i = 0; i < inSize; i++) { pSize++; q = q.nextZ; if (!q) break; } qSize = inSize; while (pSize > 0 || (qSize > 0 && q)) { if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { e = p; p = p.nextZ; pSize--; } else { e = q; q = q.nextZ; qSize--; } if (tail) tail.nextZ = e; else list = e; e.prevZ = tail; tail = e; } p = q; } tail.nextZ = null; inSize *= 2; } while (numMerges > 1); return list; } // z-order of a point given coords and inverse of the longer side of data bbox function zOrder(x, y, minX, minY, invSize) { // coords are transformed into non-negative 15-bit integer range x = 32767 * (x - minX) * invSize; y = 32767 * (y - minY) * invSize; x = (x | (x << 8)) & 0x00FF00FF; x = (x | (x << 4)) & 0x0F0F0F0F; x = (x | (x << 2)) & 0x33333333; x = (x | (x << 1)) & 0x55555555; y = (y | (y << 8)) & 0x00FF00FF; y = (y | (y << 4)) & 0x0F0F0F0F; y = (y | (y << 2)) & 0x33333333; y = (y | (y << 1)) & 0x55555555; return x | (y << 1); } // find the leftmost node of a polygon ring function getLeftmost(start) { var p = start, leftmost = start; do { if (p.x < leftmost.x) leftmost = p; p = p.next; } while (p !== start); return leftmost; } // check if a point lies within a convex triangle function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; } // check if a diagonal between two polygon nodes is valid (lies in polygon interior) function isValidDiagonal(a, b) { return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); } // signed area of a triangle function area(p, q, r) { return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); } // check if two points are equal function equals(p1, p2) { return p1.x === p2.x && p1.y === p2.y; } // check if two segments intersect function intersects(p1, q1, p2, q2) { if ((equals(p1, q1) && equals(p2, q2)) || (equals(p1, q2) && equals(p2, q1))) return true; return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; } // check if a polygon diagonal intersects any polygon segments function intersectsPolygon(a, b) { var p = a; do { if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true; p = p.next; } while (p !== a); return false; } // check if a polygon diagonal is locally inside the polygon function locallyInside(a, b) { return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; } // check if the middle point of a polygon diagonal is inside the polygon function middleInside(a, b) { var p = a, inside = false, px = (a.x + b.x) / 2, py = (a.y + b.y) / 2; do { if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) inside = !inside; p = p.next; } while (p !== a); return inside; } // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; // if one belongs to the outer ring and another to a hole, it merges it into a single ring function splitPolygon(a, b) { var a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev; a.next = b; b.prev = a; a2.next = an; an.prev = a2; b2.next = a2; a2.prev = b2; bp.next = b2; b2.prev = bp; return b2; } // create a node and optionally link it with previous one (in a circular doubly linked list) function insertNode(i, x, y, last) { var p = new Node(i, x, y); if (!last) { p.prev = p; p.next = p; } else { p.next = last.next; p.prev = last; last.next.prev = p; last.next = p; } return p; } function removeNode(p) { p.next.prev = p.prev; p.prev.next = p.next; if (p.prevZ) p.prevZ.nextZ = p.nextZ; if (p.nextZ) p.nextZ.prevZ = p.prevZ; } function Node(i, x, y) { // vertice index in coordinates array this.i = i; // vertex coordinates this.x = x; this.y = y; // previous and next vertice nodes in a polygon ring this.prev = null; this.next = null; // z-order curve value this.z = null; // previous and next nodes in z-order this.prevZ = null; this.nextZ = null; // indicates whether this is a steiner point this.steiner = false; } // return a percentage difference between the polygon area and its triangulation area; // used to verify correctness of triangulation earcut.deviation = function (data, holeIndices, dim, triangles) { var hasHoles = holeIndices && holeIndices.length; var outerLen = hasHoles ? holeIndices[0] * dim : data.length; var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); if (hasHoles) { for (var i = 0, len = holeIndices.length; i < len; i++) { var start = holeIndices[i] * dim; var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; polygonArea -= Math.abs(signedArea(data, start, end, dim)); } } var trianglesArea = 0; for (i = 0; i < triangles.length; i += 3) { var a = triangles[i] * dim; var b = triangles[i + 1] * dim; var c = triangles[i + 2] * dim; trianglesArea += Math.abs( (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1])); } return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea); }; function signedArea(data, start, end, dim) { var sum = 0; for (var i = start, j = end - dim; i < end; i += dim) { sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); j = i; } return sum; } // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts earcut.flatten = function (data) { var dim = data[0][0].length, result = {vertices: [], holes: [], dimensions: dim}, holeIndex = 0; for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[i].length; j++) { for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]); } if (i > 0) { holeIndex += data[i - 1].length; result.holes.push(holeIndex); } } return result; }; },{}],17:[function(require,module,exports){ module.exports = identity; /** * Set a mat4 to the identity matrix * * @param {mat4} out the receiving matrix * @returns {mat4} out */ function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; },{}],18:[function(require,module,exports){ var identity = require('./identity'); module.exports = lookAt; /** * Generates a look-at matrix with the given eye position, focal point, and up axis * * @param {mat4} out mat4 frustum matrix will be written into * @param {vec3} eye Position of the viewer * @param {vec3} center Point the viewer is looking at * @param {vec3} up vec3 pointing up * @returns {mat4} out */ function lookAt(out, eye, center, up) { var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, eyex = eye[0], eyey = eye[1], eyez = eye[2], upx = up[0], upy = up[1], upz = up[2], centerx = center[0], centery = center[1], centerz = center[2]; if (Math.abs(eyex - centerx) < 0.000001 && Math.abs(eyey - centery) < 0.000001 && Math.abs(eyez - centerz) < 0.000001) { return identity(out); } z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz; len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len; z1 *= len; z2 *= len; x0 = upy * z2 - upz * z1; x1 = upz * z0 - upx * z2; x2 = upx * z1 - upy * z0; len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (!len) { x0 = 0; x1 = 0; x2 = 0; } else { len = 1 / len; x0 *= len; x1 *= len; x2 *= len; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (!len) { y0 = 0; y1 = 0; y2 = 0; } else { len = 1 / len; y0 *= len; y1 *= len; y2 *= len; } out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0; out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0; out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0; out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); out[15] = 1; return out; }; },{"./identity":17}],19:[function(require,module,exports){ module.exports = perspective; /** * Generates a perspective projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} fovy Vertical field of view in radians * @param {number} aspect Aspect ratio. typically viewport width/height * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ function perspective(out, fovy, aspect, near, far) { var f = 1.0 / Math.tan(fovy / 2), nf = 1 / (near - far); out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (2 * far * near) * nf; out[15] = 0; return out; }; },{}],20:[function(require,module,exports){ module.exports = attributeToProperty var transform = { 'class': 'className', 'for': 'htmlFor', 'http-equiv': 'httpEquiv' } function attributeToProperty (h) { return function (tagName, attrs, children) { for (var attr in attrs) { if (attr in transform) { attrs[transform[attr]] = attrs[attr] delete attrs[attr] } } return h(tagName, attrs, children) } } },{}],21:[function(require,module,exports){ var attrToProp = require('hyperscript-attribute-to-property') var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4 var ATTR_KEY = 5, ATTR_KEY_W = 6 var ATTR_VALUE_W = 7, ATTR_VALUE = 8 var ATTR_VALUE_SQ = 9, ATTR_VALUE_DQ = 10 var ATTR_EQ = 11, ATTR_BREAK = 12 var COMMENT = 13 module.exports = function (h, opts) { if (!opts) opts = {} var concat = opts.concat || function (a, b) { return String(a) + String(b) } if (opts.attrToProp !== false) { h = attrToProp(h) } return function (strings) { var state = TEXT, reg = '' var arglen = arguments.length var parts = [] for (var i = 0; i < strings.length; i++) { if (i < arglen - 1) { var arg = arguments[i+1] var p = parse(strings[i]) var xstate = state if (xstate === ATTR_VALUE_DQ) xstate = ATTR_VALUE if (xstate === ATTR_VALUE_SQ) xstate = ATTR_VALUE if (xstate === ATTR_VALUE_W) xstate = ATTR_VALUE if (xstate === ATTR) xstate = ATTR_KEY if (xstate === OPEN) { if (reg === '/') { p.push([ OPEN, '/', arg ]) reg = '' } else { p.push([ OPEN, arg ]) } } else { p.push([ VAR, xstate, arg ]) } parts.push.apply(parts, p) } else parts.push.apply(parts, parse(strings[i])) } var tree = [null,{},[]] var stack = [[tree,-1]] for (var i = 0; i < parts.length; i++) { var cur = stack[stack.length-1][0] var p = parts[i], s = p[0] if (s === OPEN && /^\//.test(p[1])) { var ix = stack[stack.length-1][1] if (stack.length > 1) { stack.pop() stack[stack.length-1][0][2][ix] = h( cur[0], cur[1], cur[2].length ? cur[2] : undefined ) } } else if (s === OPEN) { var c = [p[1],{},[]] cur[2].push(c) stack.push([c,cur[2].length-1]) } else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) { var key = '' var copyKey for (; i < parts.length; i++) { if (parts[i][0] === ATTR_KEY) { key = concat(key, parts[i][1]) } else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) { if (typeof parts[i][2] === 'object' && !key) { for (copyKey in parts[i][2]) { if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) { cur[1][copyKey] = parts[i][2][copyKey] } } } else { key = concat(key, parts[i][2]) } } else break } if (parts[i][0] === ATTR_EQ) i++ var j = i for (; i < parts.length; i++) { if (parts[i][0] === ATTR_VALUE || parts[i][0] === ATTR_KEY) { if (!cur[1][key]) cur[1][key] = strfn(parts[i][1]) else parts[i][1]==="" || (cur[1][key] = concat(cur[1][key], parts[i][1])); } else if (parts[i][0] === VAR && (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) { if (!cur[1][key]) cur[1][key] = strfn(parts[i][2]) else parts[i][2]==="" || (cur[1][key] = concat(cur[1][key], parts[i][2])); } else { if (key.length && !cur[1][key] && i === j && (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) { // https://html.spec.whatwg.org/multipage/infrastructure.html#boolean-attributes // empty string is falsy, not well behaved value in browser cur[1][key] = key.toLowerCase() } if (parts[i][0] === CLOSE) { i-- } break } } } else if (s === ATTR_KEY) { cur[1][p[1]] = true } else if (s === VAR && p[1] === ATTR_KEY) { cur[1][p[2]] = true } else if (s === CLOSE) { if (selfClosing(cur[0]) && stack.length) { var ix = stack[stack.length-1][1] stack.pop() stack[stack.length-1][0][2][ix] = h( cur[0], cur[1], cur[2].length ? cur[2] : undefined ) } } else if (s === VAR && p[1] === TEXT) { if (p[2] === undefined || p[2] === null) p[2] = '' else if (!p[2]) p[2] = concat('', p[2]) if (Array.isArray(p[2][0])) { cur[2].push.apply(cur[2], p[2]) } else { cur[2].push(p[2]) } } else if (s === TEXT) { cur[2].push(p[1]) } else if (s === ATTR_EQ || s === ATTR_BREAK) { // no-op } else { throw new Error('unhandled: ' + s) } } if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) { tree[2].shift() } if (tree[2].length > 2 || (tree[2].length === 2 && /\S/.test(tree[2][1]))) { throw new Error( 'multiple root elements must be wrapped in an enclosing tag' ) } if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string' && Array.isArray(tree[2][0][2])) { tree[2][0] = h(tree[2][0][0], tree[2][0][1], tree[2][0][2]) } return tree[2][0] function parse (str) { var res = [] if (state === ATTR_VALUE_W) state = ATTR for (var i = 0; i < str.length; i++) { var c = str.charAt(i) if (state === TEXT && c === '<') { if (reg.length) res.push([TEXT, reg]) reg = '' state = OPEN } else if (c === '>' && !quot(state) && state !== COMMENT) { if (state === OPEN && reg.length) { res.push([OPEN,reg]) } else if (state === ATTR_KEY) { res.push([ATTR_KEY,reg]) } else if (state === ATTR_VALUE && reg.length) { res.push([ATTR_VALUE,reg]) } res.push([CLOSE]) reg = '' state = TEXT } else if (state === COMMENT && /-$/.test(reg) && c === '-') { if (opts.comments) { res.push([ATTR_VALUE,reg.substr(0, reg.length - 1)],[CLOSE]) } reg = '' state = TEXT } else if (state === OPEN && /^!--$/.test(reg)) { if (opts.comments) { res.push([OPEN, reg],[ATTR_KEY,'comment'],[ATTR_EQ]) } reg = c state = COMMENT } else if (state === TEXT || state === COMMENT) { reg += c } else if (state === OPEN && c === '/' && reg.length) { // no-op, self closing tag without a space
} else if (state === OPEN && /\s/.test(c)) { if (reg.length) { res.push([OPEN, reg]) } reg = '' state = ATTR } else if (state === OPEN) { reg += c } else if (state === ATTR && /[^\s"'=/]/.test(c)) { state = ATTR_KEY reg = c } else if (state === ATTR && /\s/.test(c)) { if (reg.length) res.push([ATTR_KEY,reg]) res.push([ATTR_BREAK]) } else if (state === ATTR_KEY && /\s/.test(c)) { res.push([ATTR_KEY,reg]) reg = '' state = ATTR_KEY_W } else if (state === ATTR_KEY && c === '=') { res.push([ATTR_KEY,reg],[ATTR_EQ]) reg = '' state = ATTR_VALUE_W } else if (state === ATTR_KEY) { reg += c } else if ((state === ATTR_KEY_W || state === ATTR) && c === '=') { res.push([ATTR_EQ]) state = ATTR_VALUE_W } else if ((state === ATTR_KEY_W || state === ATTR) && !/\s/.test(c)) { res.push([ATTR_BREAK]) if (/[\w-]/.test(c)) { reg += c state = ATTR_KEY } else state = ATTR } else if (state === ATTR_VALUE_W && c === '"') { state = ATTR_VALUE_DQ } else if (state === ATTR_VALUE_W && c === "'") { state = ATTR_VALUE_SQ } else if (state === ATTR_VALUE_DQ && c === '"') { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE_SQ && c === "'") { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE_W && !/\s/.test(c)) { state = ATTR_VALUE i-- } else if (state === ATTR_VALUE && /\s/.test(c)) { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ) { reg += c } } if (state === TEXT && reg.length) { res.push([TEXT,reg]) reg = '' } else if (state === ATTR_VALUE && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_VALUE_DQ && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_VALUE_SQ && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_KEY) { res.push([ATTR_KEY,reg]) reg = '' } return res } } function strfn (x) { if (typeof x === 'function') return x else if (typeof x === 'string') return x else if (x && typeof x === 'object') return x else return concat('', x) } } function quot (state) { return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ } var hasOwn = Object.prototype.hasOwnProperty function has (obj, key) { return hasOwn.call(obj, key) } var closeRE = RegExp('^(' + [ 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', '!--', // SVG TAGS 'animate', 'animateTransform', 'circle', 'cursor', 'desc', 'ellipse', 'feBlend', 'feColorMatrix', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'font-face-format', 'font-face-name', 'font-face-uri', 'glyph', 'glyphRef', 'hkern', 'image', 'line', 'missing-glyph', 'mpath', 'path', 'polygon', 'polyline', 'rect', 'set', 'stop', 'tref', 'use', 'view', 'vkern' ].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$') function selfClosing (tag) { return closeRE.test(tag) } },{"hyperscript-attribute-to-property":20}],22:[function(require,module,exports){ 'use strict' module.exports = mouseListen var mouse = require('mouse-event') function mouseListen (element, callback) { if (!callback) { callback = element element = window } var buttonState = 0 var x = 0 var y = 0 var mods = { shift: false, alt: false, control: false, meta: false } var attached = false function updateMods (ev) { var changed = false if ('altKey' in ev) { changed = changed || ev.altKey !== mods.alt mods.alt = !!ev.altKey } if ('shiftKey' in ev) { changed = changed || ev.shiftKey !== mods.shift mods.shift = !!ev.shiftKey } if ('ctrlKey' in ev) { changed = changed || ev.ctrlKey !== mods.control mods.control = !!ev.ctrlKey } if ('metaKey' in ev) { changed = changed || ev.metaKey !== mods.meta mods.meta = !!ev.metaKey } return changed } function handleEvent (nextButtons, ev) { var nextX = mouse.x(ev) var nextY = mouse.y(ev) if ('buttons' in ev) { nextButtons = ev.buttons | 0 } if (nextButtons !== buttonState || nextX !== x || nextY !== y || updateMods(ev)) { buttonState = nextButtons | 0 x = nextX || 0 y = nextY || 0 callback && callback(buttonState, x, y, mods) } } function clearState (ev) { handleEvent(0, ev) } function handleBlur () { if (buttonState || x || y || mods.shift || mods.alt || mods.meta || mods.control) { x = y = 0 buttonState = 0 mods.shift = mods.alt = mods.control = mods.meta = false callback && callback(0, 0, 0, mods) } } function handleMods (ev) { if (updateMods(ev)) { callback && callback(buttonState, x, y, mods) } } function handleMouseMove (ev) { if (mouse.buttons(ev) === 0) { handleEvent(0, ev) } else { handleEvent(buttonState, ev) } } function handleMouseDown (ev) { handleEvent(buttonState | mouse.buttons(ev), ev) } function handleMouseUp (ev) { handleEvent(buttonState & ~mouse.buttons(ev), ev) } function attachListeners () { if (attached) { return } attached = true element.addEventListener('mousemove', handleMouseMove) element.addEventListener('mousedown', handleMouseDown) element.addEventListener('mouseup', handleMouseUp) element.addEventListener('mouseleave', clearState) element.addEventListener('mouseenter', clearState) element.addEventListener('mouseout', clearState) element.addEventListener('mouseover', clearState) element.addEventListener('blur', handleBlur) element.addEventListener('keyup', handleMods) element.addEventListener('keydown', handleMods) element.addEventListener('keypress', handleMods) if (element !== window) { window.addEventListener('blur', handleBlur) window.addEventListener('keyup', handleMods) window.addEventListener('keydown', handleMods) window.addEventListener('keypress', handleMods) } } function detachListeners () { if (!attached) { return } attached = false element.removeEventListener('mousemove', handleMouseMove) element.removeEventListener('mousedown', handleMouseDown) element.removeEventListener('mouseup', handleMouseUp) element.removeEventListener('mouseleave', clearState) element.removeEventListener('mouseenter', clearState) element.removeEventListener('mouseout', clearState) element.removeEventListener('mouseover', clearState) element.removeEventListener('blur', handleBlur) element.removeEventListener('keyup', handleMods) element.removeEventListener('keydown', handleMods) element.removeEventListener('keypress', handleMods) if (element !== window) { window.removeEventListener('blur', handleBlur) window.removeEventListener('keyup', handleMods) window.removeEventListener('keydown', handleMods) window.removeEventListener('keypress', handleMods) } } // Attach listeners attachListeners() var result = { element: element } Object.defineProperties(result, { enabled: { get: function () { return attached }, set: function (f) { if (f) { attachListeners() } else { detachListeners() } }, enumerable: true }, buttons: { get: function () { return buttonState }, enumerable: true }, x: { get: function () { return x }, enumerable: true }, y: { get: function () { return y }, enumerable: true }, mods: { get: function () { return mods }, enumerable: true } }) return result } },{"mouse-event":23}],23:[function(require,module,exports){ 'use strict' function mouseButtons(ev) { if(typeof ev === 'object') { if('buttons' in ev) { return ev.buttons } else if('which' in ev) { var b = ev.which if(b === 2) { return 4 } else if(b === 3) { return 2 } else if(b > 0) { return 1<<(b-1) } } else if('button' in ev) { var b = ev.button if(b === 1) { return 4 } else if(b === 2) { return 2 } else if(b >= 0) { return 1< 0) { this._emit(this._listeners[eventName], data) } if (this._starListeners.length > 0) { this._emit(this._starListeners, eventName, data, emitTiming.uuid) } emitTiming() return this } Nanobus.prototype.on = Nanobus.prototype.addListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.on: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.on: listener should be type function') if (eventName === '*') { this._starListeners.push(listener) } else { if (!this._listeners[eventName]) this._listeners[eventName] = [] this._listeners[eventName].push(listener) } return this } Nanobus.prototype.prependListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.prependListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.prependListener: listener should be type function') if (eventName === '*') { this._starListeners.unshift(listener) } else { if (!this._listeners[eventName]) this._listeners[eventName] = [] this._listeners[eventName].unshift(listener) } return this } Nanobus.prototype.once = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.once: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.once: listener should be type function') var self = this this.on(eventName, once) function once () { listener.apply(self, arguments) self.removeListener(eventName, once) } return this } Nanobus.prototype.prependOnceListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.prependOnceListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.prependOnceListener: listener should be type function') var self = this this.prependListener(eventName, once) function once () { listener.apply(self, arguments) self.removeListener(eventName, once) } return this } Nanobus.prototype.removeListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.removeListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.removeListener: listener should be type function') if (eventName === '*') { this._starListeners = this._starListeners.slice() return remove(this._starListeners, listener) } else { if (typeof this._listeners[eventName] !== 'undefined') { this._listeners[eventName] = this._listeners[eventName].slice() } return remove(this._listeners[eventName], listener) } function remove (arr, listener) { if (!arr) return var index = arr.indexOf(listener) if (index !== -1) { splice(arr, index, 1) return true } } } Nanobus.prototype.removeAllListeners = function (eventName) { if (eventName) { if (eventName === '*') { this._starListeners = [] } else { this._listeners[eventName] = [] } } else { this._starListeners = [] this._listeners = {} } return this } Nanobus.prototype.listeners = function (eventName) { var listeners = eventName !== '*' ? this._listeners[eventName] : this._starListeners var ret = [] if (listeners) { var ilength = listeners.length for (var i = 0; i < ilength; i++) ret.push(listeners[i]) } return ret } Nanobus.prototype._emit = function (arr, eventName, data, uuid) { if (typeof arr === 'undefined') return if (arr.length === 0) return if (data === undefined) { data = eventName eventName = null } if (eventName) { if (uuid !== undefined) { data = [eventName].concat(data, uuid) } else { data = [eventName].concat(data) } } var length = arr.length for (var i = 0; i < length; i++) { var listener = arr[i] listener.apply(listener, data) } } },{"assert":1,"nanotiming":37,"remove-array-items":41}],27:[function(require,module,exports){ var assert = require('assert') var safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/ var protocolLink = /^[\w-_]+:/ module.exports = href function href (cb, root) { assert.notEqual(typeof window, 'undefined', 'nanohref: expected window to exist') root = root || window.document assert.equal(typeof cb, 'function', 'nanohref: cb should be type function') assert.equal(typeof root, 'object', 'nanohref: root should be type object') window.addEventListener('click', function (e) { if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) return var anchor = (function traverse (node) { if (!node || node === root) return if (node.localName !== 'a' || node.href === undefined) { return traverse(node.parentNode) } return node })(e.target) if (!anchor) return if (window.location.origin !== anchor.origin || anchor.hasAttribute('download') || (anchor.getAttribute('target') === '_blank' && safeExternalLink.test(anchor.getAttribute('rel'))) || protocolLink.test(anchor.getAttribute('href'))) return e.preventDefault() cb(anchor) }) } },{"assert":1}],28:[function(require,module,exports){ var assert = require('assert') module.exports = nanolocation function nanolocation () { assert.notEqual(typeof window, 'undefined', 'nanolocation: expected window to exist') var pathname = window.location.pathname.replace(/\/$/, '') var hash = window.location.hash.replace(/^#/, '/') return pathname + hash } },{"assert":25}],29:[function(require,module,exports){ module.exports = LRU function LRU (opts) { if (!(this instanceof LRU)) return new LRU(opts) if (typeof opts === 'number') opts = {max: opts} if (!opts) opts = {} this.cache = {} this.head = this.tail = null this.length = 0 this.max = opts.max || 1000 this.maxAge = opts.maxAge || 0 } Object.defineProperty(LRU.prototype, 'keys', { get: function () { return Object.keys(this.cache) } }) LRU.prototype.clear = function () { this.cache = {} this.head = this.tail = null this.length = 0 } LRU.prototype.remove = function (key) { if (typeof key !== 'string') key = '' + key if (!this.cache.hasOwnProperty(key)) return var element = this.cache[key] delete this.cache[key] this._unlink(key, element.prev, element.next) return element.value } LRU.prototype._unlink = function (key, prev, next) { this.length-- if (this.length === 0) { this.head = this.tail = null } else { if (this.head === key) { this.head = prev this.cache[this.head].next = null } else if (this.tail === key) { this.tail = next this.cache[this.tail].prev = null } else { this.cache[prev].next = next this.cache[next].prev = prev } } } LRU.prototype.peek = function (key) { if (!this.cache.hasOwnProperty(key)) return var element = this.cache[key] if (!this._checkAge(key, element)) return return element.value } LRU.prototype.set = function (key, value) { if (typeof key !== 'string') key = '' + key var element if (this.cache.hasOwnProperty(key)) { element = this.cache[key] element.value = value if (this.maxAge) element.modified = Date.now() // If it's already the head, there's nothing more to do: if (key === this.head) return value this._unlink(key, element.prev, element.next) } else { element = {value: value, modified: 0, next: null, prev: null} if (this.maxAge) element.modified = Date.now() this.cache[key] = element // Eviction is only possible if the key didn't already exist: if (this.length === this.max) this.evict() } this.length++ element.next = null element.prev = this.head if (this.head) this.cache[this.head].next = key this.head = key if (!this.tail) this.tail = key return value } LRU.prototype._checkAge = function (key, element) { if (this.maxAge && (Date.now() - element.modified) > this.maxAge) { this.remove(key) return false } return true } LRU.prototype.get = function (key) { if (typeof key !== 'string') key = '' + key if (!this.cache.hasOwnProperty(key)) return var element = this.cache[key] if (!this._checkAge(key, element)) return if (this.head !== key) { if (key === this.tail) { this.tail = element.next this.cache[this.tail].prev = null } else { // Set prev.next -> element.next: this.cache[element.prev].next = element.next } // Set element.next.prev -> element.prev: this.cache[element.next].prev = element.prev // Element is the new head this.cache[this.head].next = key element.prev = this.head element.next = null this.head = key } return element.value } LRU.prototype.evict = function () { if (!this.tail) return this.remove(this.tail) } },{}],30:[function(require,module,exports){ var assert = require('assert') var morph = require('./lib/morph') var TEXT_NODE = 3 // var DEBUG = false module.exports = nanomorph // Morph one tree into another tree // // no parent // -> same: diff and walk children // -> not same: replace and return // old node doesn't exist // -> insert new node // new node doesn't exist // -> delete old node // nodes are not the same // -> diff nodes and apply patch to old node // nodes are the same // -> walk all child nodes and append to old node function nanomorph (oldTree, newTree) { // if (DEBUG) { // console.log( // 'nanomorph\nold\n %s\nnew\n %s', // oldTree && oldTree.outerHTML, // newTree && newTree.outerHTML // ) // } assert.equal(typeof oldTree, 'object', 'nanomorph: oldTree should be an object') assert.equal(typeof newTree, 'object', 'nanomorph: newTree should be an object') var tree = walk(newTree, oldTree) // if (DEBUG) console.log('=> morphed\n %s', tree.outerHTML) return tree } // Walk and morph a dom tree function walk (newNode, oldNode) { // if (DEBUG) { // console.log( // 'walk\nold\n %s\nnew\n %s', // oldNode && oldNode.outerHTML, // newNode && newNode.outerHTML // ) // } if (!oldNode) { return newNode } else if (!newNode) { return null } else if (newNode.isSameNode && newNode.isSameNode(oldNode)) { return oldNode } else if (newNode.tagName !== oldNode.tagName) { return newNode } else { morph(newNode, oldNode) updateChildren(newNode, oldNode) return oldNode } } // Update the children of elements // (obj, obj) -> null function updateChildren (newNode, oldNode) { // if (DEBUG) { // console.log( // 'updateChildren\nold\n %s\nnew\n %s', // oldNode && oldNode.outerHTML, // newNode && newNode.outerHTML // ) // } var oldChild, newChild, morphed, oldMatch // The offset is only ever increased, and used for [i - offset] in the loop var offset = 0 for (var i = 0; ; i++) { oldChild = oldNode.childNodes[i] newChild = newNode.childNodes[i - offset] // if (DEBUG) { // console.log( // '===\n- old\n %s\n- new\n %s', // oldChild && oldChild.outerHTML, // newChild && newChild.outerHTML // ) // } // Both nodes are empty, do nothing if (!oldChild && !newChild) { break // There is no new child, remove old } else if (!newChild) { oldNode.removeChild(oldChild) i-- // There is no old child, add new } else if (!oldChild) { oldNode.appendChild(newChild) offset++ // Both nodes are the same, morph } else if (same(newChild, oldChild)) { morphed = walk(newChild, oldChild) if (morphed !== oldChild) { oldNode.replaceChild(morphed, oldChild) offset++ } // Both nodes do not share an ID or a placeholder, try reorder } else { oldMatch = null // Try and find a similar node somewhere in the tree for (var j = i; j < oldNode.childNodes.length; j++) { if (same(oldNode.childNodes[j], newChild)) { oldMatch = oldNode.childNodes[j] break } } // If there was a node with the same ID or placeholder in the old list if (oldMatch) { morphed = walk(newChild, oldMatch) if (morphed !== oldMatch) offset++ oldNode.insertBefore(morphed, oldChild) // It's safe to morph two nodes in-place if neither has an ID } else if (!newChild.id && !oldChild.id) { morphed = walk(newChild, oldChild) if (morphed !== oldChild) { oldNode.replaceChild(morphed, oldChild) offset++ } // Insert the node at the index if we couldn't morph or find a matching node } else { oldNode.insertBefore(newChild, oldChild) offset++ } } } } function same (a, b) { if (a.id) return a.id === b.id if (a.isSameNode) return a.isSameNode(b) if (a.tagName !== b.tagName) return false if (a.type === TEXT_NODE) return a.nodeValue === b.nodeValue return false } },{"./lib/morph":32,"assert":25}],31:[function(require,module,exports){ module.exports = [ // attribute events (can be set with attributes) 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onmouseenter', 'onmouseleave', 'ontouchcancel', 'ontouchend', 'ontouchmove', 'ontouchstart', 'ondragstart', 'ondrag', 'ondragenter', 'ondragleave', 'ondragover', 'ondrop', 'ondragend', 'onkeydown', 'onkeypress', 'onkeyup', 'onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onselect', 'onchange', 'onsubmit', 'onreset', 'onfocus', 'onblur', 'oninput', // other common events 'oncontextmenu', 'onfocusin', 'onfocusout' ] },{}],32:[function(require,module,exports){ var events = require('./events') var eventsLength = events.length var ELEMENT_NODE = 1 var TEXT_NODE = 3 var COMMENT_NODE = 8 module.exports = morph // diff elements and apply the resulting patch to the old node // (obj, obj) -> null function morph (newNode, oldNode) { var nodeType = newNode.nodeType var nodeName = newNode.nodeName if (nodeType === ELEMENT_NODE) { copyAttrs(newNode, oldNode) } if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) { if (oldNode.nodeValue !== newNode.nodeValue) { oldNode.nodeValue = newNode.nodeValue } } // Some DOM nodes are weird // https://github.com/patrick-steele-idem/morphdom/blob/master/src/specialElHandlers.js if (nodeName === 'INPUT') updateInput(newNode, oldNode) else if (nodeName === 'OPTION') updateOption(newNode, oldNode) else if (nodeName === 'TEXTAREA') updateTextarea(newNode, oldNode) copyEvents(newNode, oldNode) } function copyAttrs (newNode, oldNode) { var oldAttrs = oldNode.attributes var newAttrs = newNode.attributes var attrNamespaceURI = null var attrValue = null var fromValue = null var attrName = null var attr = null for (var i = newAttrs.length - 1; i >= 0; --i) { attr = newAttrs[i] attrName = attr.name attrNamespaceURI = attr.namespaceURI attrValue = attr.value if (attrNamespaceURI) { attrName = attr.localName || attrName fromValue = oldNode.getAttributeNS(attrNamespaceURI, attrName) if (fromValue !== attrValue) { oldNode.setAttributeNS(attrNamespaceURI, attrName, attrValue) } } else { if (!oldNode.hasAttribute(attrName)) { oldNode.setAttribute(attrName, attrValue) } else { fromValue = oldNode.getAttribute(attrName) if (fromValue !== attrValue) { // apparently values are always cast to strings, ah well if (attrValue === 'null' || attrValue === 'undefined') { oldNode.removeAttribute(attrName) } else { oldNode.setAttribute(attrName, attrValue) } } } } } // Remove any extra attributes found on the original DOM element that // weren't found on the target element. for (var j = oldAttrs.length - 1; j >= 0; --j) { attr = oldAttrs[j] if (attr.specified !== false) { attrName = attr.name attrNamespaceURI = attr.namespaceURI if (attrNamespaceURI) { attrName = attr.localName || attrName if (!newNode.hasAttributeNS(attrNamespaceURI, attrName)) { oldNode.removeAttributeNS(attrNamespaceURI, attrName) } } else { if (!newNode.hasAttributeNS(null, attrName)) { oldNode.removeAttribute(attrName) } } } } } function copyEvents (newNode, oldNode) { for (var i = 0; i < eventsLength; i++) { var ev = events[i] if (newNode[ev]) { // if new element has a whitelisted attribute oldNode[ev] = newNode[ev] // update existing element } else if (oldNode[ev]) { // if existing element has it and new one doesnt oldNode[ev] = undefined // remove it from existing element } } } function updateOption (newNode, oldNode) { updateAttribute(newNode, oldNode, 'selected') } // The "value" attribute is special for the element since it sets the // initial value. Changing the "value" attribute without changing the "value" // property will have no effect since it is only used to the set the initial // value. Similar for the "checked" attribute, and "disabled". function updateInput (newNode, oldNode) { var newValue = newNode.value var oldValue = oldNode.value updateAttribute(newNode, oldNode, 'checked') updateAttribute(newNode, oldNode, 'disabled') if (newValue !== oldValue) { oldNode.setAttribute('value', newValue) oldNode.value = newValue } if (newValue === 'null') { oldNode.value = '' oldNode.removeAttribute('value') } if (!newNode.hasAttributeNS(null, 'value')) { oldNode.removeAttribute('value') } else if (oldNode.type === 'range') { // this is so elements like slider move their UI thingy oldNode.value = newValue } } function updateTextarea (newNode, oldNode) { var newValue = newNode.value if (newValue !== oldNode.value) { oldNode.value = newValue } if (oldNode.firstChild && oldNode.firstChild.nodeValue !== newValue) { // Needed for IE. Apparently IE sets the placeholder as the // node value and vise versa. This ignores an empty update. if (newValue === '' && oldNode.firstChild.nodeValue === oldNode.placeholder) { return } oldNode.firstChild.nodeValue = newValue } } function updateAttribute (newNode, oldNode, name) { if (newNode[name] !== oldNode[name]) { oldNode[name] = newNode[name] if (newNode[name]) { oldNode.setAttribute(name, '') } else { oldNode.removeAttribute(name) } } } },{"./events":31}],33:[function(require,module,exports){ var reg = /([^?=&]+)(=([^&]*))?/g var assert = require('assert') module.exports = qs function qs (url) { assert.equal(typeof url, 'string', 'nanoquery: url should be type string') var obj = {} url.replace(/^.*\?/, '').replace(reg, function (a0, a1, a2, a3) { obj[decodeURIComponent(a1)] = decodeURIComponent(a3) }) return obj } },{"assert":25}],34:[function(require,module,exports){ 'use strict' var assert = require('assert') module.exports = nanoraf // Only call RAF when needed // (fn, fn?) -> fn function nanoraf (render, raf) { assert.equal(typeof render, 'function', 'nanoraf: render should be a function') assert.ok(typeof raf === 'function' || typeof raf === 'undefined', 'nanoraf: raf should be a function or undefined') if (!raf) raf = window.requestAnimationFrame var redrawScheduled = false var args = null return function frame () { if (args === null && !redrawScheduled) { redrawScheduled = true raf(function redraw () { redrawScheduled = false var length = args.length var _args = new Array(length) for (var i = 0; i < length; i++) _args[i] = args[i] render.apply(render, _args) args = null }) } args = arguments } } },{"assert":1}],35:[function(require,module,exports){ var assert = require('assert') var wayfarer = require('wayfarer') // electron support var isLocalFile = (/file:\/\//.test( typeof window === 'object' && window.location && window.location.origin )) /* eslint-disable no-useless-escape */ var electron = '^(file:\/\/|\/)(.*\.html?\/?)?' var protocol = '^(http(s)?(:\/\/))?(www\.)?' var domain = '[a-zA-Z0-9-_\.]+(:[0-9]{1,5})?(\/{1})?' var qs = '[\?].*$' /* eslint-enable no-useless-escape */ var stripElectron = new RegExp(electron) var prefix = new RegExp(protocol + domain) var normalize = new RegExp('#') var suffix = new RegExp(qs) module.exports = Nanorouter function Nanorouter (opts) { if (!(this instanceof Nanorouter)) return new Nanorouter(opts) opts = opts || {} this.router = wayfarer(opts.default || '/404') } Nanorouter.prototype.on = function (routename, listener) { assert.equal(typeof routename, 'string') routename = routename.replace(/^[#/]/, '') this.router.on(routename, listener) } Nanorouter.prototype.emit = function (routename) { assert.equal(typeof routename, 'string') routename = pathname(routename, isLocalFile) return this.router.emit(routename) } Nanorouter.prototype.match = function (routename) { assert.equal(typeof routename, 'string') routename = pathname(routename, isLocalFile) return this.router.match(routename) } // replace everything in a route but the pathname and hash function pathname (routename, isElectron) { if (isElectron) routename = routename.replace(stripElectron, '') else routename = routename.replace(prefix, '') return decodeURI(routename.replace(suffix, '').replace(normalize, '/')) } },{"assert":25,"wayfarer":45}],36:[function(require,module,exports){ var assert = require('assert') var hasWindow = typeof window !== 'undefined' function createScheduler () { var scheduler if (hasWindow) { if (!window._nanoScheduler) window._nanoScheduler = new NanoScheduler(true) scheduler = window._nanoScheduler } else { scheduler = new NanoScheduler() } return scheduler } function NanoScheduler (hasWindow) { this.hasWindow = hasWindow this.hasIdle = this.hasWindow && window.requestIdleCallback this.method = this.hasIdle ? window.requestIdleCallback.bind(window) : this.setTimeout this.scheduled = false this.queue = [] } NanoScheduler.prototype.push = function (cb) { assert.equal(typeof cb, 'function', 'nanoscheduler.push: cb should be type function') this.queue.push(cb) this.schedule() } NanoScheduler.prototype.schedule = function () { if (this.scheduled) return this.scheduled = true var self = this this.method(function (idleDeadline) { var cb while (self.queue.length && idleDeadline.timeRemaining() > 0) { cb = self.queue.shift() cb(idleDeadline) } self.scheduled = false if (self.queue.length) self.schedule() }) } NanoScheduler.prototype.setTimeout = function (cb) { setTimeout(cb, 0, { timeRemaining: function () { return 1 } }) } module.exports = createScheduler },{"assert":25}],37:[function(require,module,exports){ var scheduler = require('nanoscheduler')() var assert = require('assert') var perf nanotiming.disabled = true try { perf = window.performance nanotiming.disabled = window.localStorage.DISABLE_NANOTIMING === 'true' || !perf.mark } catch (e) { } module.exports = nanotiming function nanotiming (name) { assert.equal(typeof name, 'string', 'nanotiming: name should be type string') if (nanotiming.disabled) return noop var uuid = (perf.now() * 10000).toFixed() % Number.MAX_SAFE_INTEGER var startName = 'start-' + uuid + '-' + name perf.mark(startName) function end (cb) { var endName = 'end-' + uuid + '-' + name perf.mark(endName) scheduler.push(function () { var err = null try { var measureName = name + ' [' + uuid + ']' perf.measure(measureName, startName, endName) perf.clearMarks(startName) perf.clearMarks(endName) } catch (e) { err = e } if (cb) cb(err, name) }) } end.uuid = uuid return end } function noop (cb) { if (cb) { scheduler.push(function () { cb(new Error('nanotiming: performance API unavailable')) }) } } },{"assert":25,"nanoscheduler":36}],38:[function(require,module,exports){ module.exports = function parseUnit(str, out) { if (!out) out = [ 0, '' ] str = String(str) var num = parseFloat(str, 10) out[0] = num out[1] = str.match(/[\d.\-\+]*\s*(.*)/)[1] || '' return out } },{}],39:[function(require,module,exports){ var mouseChange = require('mouse-change') var mouseWheel = require('mouse-wheel') var identity = require('gl-mat4/identity') var perspective = require('gl-mat4/perspective') var lookAt = require('gl-mat4/lookAt') module.exports = createCamera var isBrowser = typeof window !== 'undefined' function createCamera (regl, props_) { var props = props_ || {} // Preserve backward-compatibilty while renaming preventDefault -> noScroll if (typeof props.noScroll === 'undefined') { props.noScroll = props.preventDefault; } var cameraState = { view: identity(new Float32Array(16)), projection: identity(new Float32Array(16)), center: new Float32Array(props.center || 3), theta: props.theta || 0, phi: props.phi || 0, distance: Math.log(props.distance || 10.0), eye: new Float32Array(3), up: new Float32Array(props.up || [0, 1, 0]), fovy: props.fovy || Math.PI / 4.0, near: typeof props.near !== 'undefined' ? props.near : 0.01, far: typeof props.far !== 'undefined' ? props.far : 1000.0, noScroll: typeof props.noScroll !== 'undefined' ? props.noScroll : false, flipY: !!props.flipY, dtheta: 0, dphi: 0, rotationSpeed: typeof props.rotationSpeed !== 'undefined' ? props.rotationSpeed : 1, zoomSpeed: typeof props.zoomSpeed !== 'undefined' ? props.zoomSpeed : 1, renderOnDirty: typeof props.renderOnDirty !== undefined ? !!props.renderOnDirty : false } var element = props.element var damping = typeof props.damping !== 'undefined' ? props.damping : 0.9 var right = new Float32Array([1, 0, 0]) var front = new Float32Array([0, 0, 1]) var minDistance = Math.log('minDistance' in props ? props.minDistance : 0.1) var maxDistance = Math.log('maxDistance' in props ? props.maxDistance : 1000) var ddistance = 0 var prevX = 0 var prevY = 0 if (isBrowser && props.mouse !== false) { var source = element || regl._gl.canvas function getWidth () { return element ? element.offsetWidth : window.innerWidth } function getHeight () { return element ? element.offsetHeight : window.innerHeight } mouseChange(source, function (buttons, x, y) { if (buttons & 1) { var dx = (x - prevX) / getWidth() var dy = (y - prevY) / getHeight() cameraState.dtheta += cameraState.rotationSpeed * 4.0 * dx cameraState.dphi += cameraState.rotationSpeed * 4.0 * dy cameraState.dirty = true; } prevX = x prevY = y }) mouseWheel(source, function (dx, dy) { ddistance += dy / getHeight() * cameraState.zoomSpeed cameraState.dirty = true; }, props.noScroll) } function damp (x) { var xd = x * damping if (Math.abs(xd) < 0.1) { return 0 } cameraState.dirty = true; return xd } function clamp (x, lo, hi) { return Math.min(Math.max(x, lo), hi) } function updateCamera (props) { Object.keys(props).forEach(function (prop) { cameraState[prop] = props[prop] }) var center = cameraState.center var eye = cameraState.eye var up = cameraState.up var dtheta = cameraState.dtheta var dphi = cameraState.dphi cameraState.theta += dtheta cameraState.phi = clamp( cameraState.phi + dphi, -Math.PI / 2.0, Math.PI / 2.0) cameraState.distance = clamp( cameraState.distance + ddistance, minDistance, maxDistance) cameraState.dtheta = damp(dtheta) cameraState.dphi = damp(dphi) ddistance = damp(ddistance) var theta = cameraState.theta var phi = cameraState.phi var r = Math.exp(cameraState.distance) var vf = r * Math.sin(theta) * Math.cos(phi) var vr = r * Math.cos(theta) * Math.cos(phi) var vu = r * Math.sin(phi) for (var i = 0; i < 3; ++i) { eye[i] = center[i] + vf * front[i] + vr * right[i] + vu * up[i] } lookAt(cameraState.view, eye, center, up) } cameraState.dirty = true; var injectContext = regl({ context: Object.assign({}, cameraState, { dirty: function () { return cameraState.dirty; }, projection: function (context) { perspective(cameraState.projection, cameraState.fovy, context.viewportWidth / context.viewportHeight, cameraState.near, cameraState.far) if (cameraState.flipY) { cameraState.projection[5] *= -1 } return cameraState.projection } }), uniforms: Object.keys(cameraState).reduce(function (uniforms, name) { uniforms[name] = regl.context(name) return uniforms }, {}) }) function setupCamera (props, block) { if (typeof setupCamera.dirty !== 'undefined') { cameraState.dirty = setupCamera.dirty || cameraState.dirty setupCamera.dirty = undefined; } if (props && block) { cameraState.dirty = true; } if (cameraState.renderOnDirty && !cameraState.dirty) return; if (!block) { block = props props = {} } updateCamera(props) injectContext(block) cameraState.dirty = false; } Object.keys(cameraState).forEach(function (name) { setupCamera[name] = cameraState[name] }) return setupCamera } },{"gl-mat4/identity":17,"gl-mat4/lookAt":18,"gl-mat4/perspective":19,"mouse-change":22,"mouse-wheel":24}],40:[function(require,module,exports){ (function(da,ea){"object"===typeof exports&&"undefined"!==typeof module?module.exports=ea():"function"===typeof define&&define.amd?define(ea):da.createREGL=ea()})(this,function(){function da(a,b){this.id=vb++;this.type=a;this.data=b}function ea(a){if(0===a.length)return[];var b=a.charAt(0),c=a.charAt(a.length-1);if(1>>=b;c=(255>>=c; b|=c;c=(15>>=c;b|=c;c=(3>>c>>1}function fa(a){a:{for(var b=16;268435456>=b;b*=16)if(a<=b){a=b;break a}a=0}b=$a[Za(a)>>2];return 0>2].push(a)}function bb(a,b,c,d,f,k){for(var p=0;pg&&(g=d.buffer.byteLength,5123===t?g>>=1:5125===t&&(g>>=2));d.vertCount= g;g=e;0>e&&(g=4,e=d.buffer.dimension,1===e&&(g=0),2===e&&(g=1),3===e&&(g=4));d.primType=g}function p(a){d.elementsCount--;delete h[a.id];a.buffer.destroy();a.buffer=null}var h={},g=0,r={uint8:5121,uint16:5123};b.oes_element_index_uint&&(r.uint32=5125);f.prototype.bind=function(){this.buffer.bind()};var v=[];return{create:function(a,b){function g(a){if(a)if("number"===typeof a)e(a),n.primType=4,n.vertCount=a|0,n.type=5121;else{var b=null,c=35044,d=-1,f=-1,l=0,p=0;if(Array.isArray(a)||O(a)||ja(a))b= a;else if("data"in a&&(b=a.data),"usage"in a&&(c=hb[a.usage]),"primitive"in a&&(d=Ra[a.primitive]),"count"in a&&(f=a.count|0),"type"in a&&(p=r[a.type]),"length"in a)l=a.length|0;else if(l=f,5123===p||5122===p)l*=2;else if(5125===p||5124===p)l*=4;k(n,b,c,d,f,l,p)}else e(),n.primType=4,n.vertCount=0,n.type=5121;return g}var e=c.create(null,34963,!0),n=new f(e._buffer);d.elementsCount++;g(a);g._reglType="elements";g._elements=n;g.subdata=function(a,b){e.subdata(a,b);return g};g.destroy=function(){p(n)}; return g},createStream:function(a){var b=v.pop();b||(b=new f(c.create(null,34963,!0,!1)._buffer));k(b,a,35040,-1,-1,0,0);return b},destroyStream:function(a){v.push(a)},getElements:function(a){return"function"===typeof a&&a._elements instanceof f?a._elements:null},clear:function(){H(h).forEach(p)}}}function ib(a){for(var b=x.allocType(5123,a.length),c=0;c>> 31<<15,k=(d<<1>>>24)-127,d=d>>13&1023;b[c]=-24>k?f:-14>k?f+(d+1024>>-14-k):15>=f,c.height>>=f,u(c,d[f]),a.mipmask|=1<b;++b)a.images[b]=null;return a}function gb(a){for(var b= a.images,c=0;cb){for(var c=0;c=--this.refCount&&z(this)}});p.profile&&(k.getTotalTextureSize=function(){var a=0;Object.keys(V).forEach(function(b){a+= V[b].stats.size});return a});return{create2D:function(b,c){function d(a,b){var c=f.texInfo;C.call(c);var e=B();"number"===typeof a?"number"===typeof b?w(e,a|0,b|0):w(e,a|0,a|0):a?(M(c,a),t(e,a)):w(e,1,1);c.genMipmaps&&(e.mipmask=(e.width<<1)-1);f.mipmask=e.mipmask;g(f,e);f.internalformat=e.internalformat;d.width=e.width;d.height=e.height;Q(f);Z(e,3553);P(c,3553);Aa();gb(e);p.profile&&(f.stats.size=Ia(f.internalformat,f.type,e.width,e.height,c.genMipmaps,!1));d.format=J[f.internalformat];d.type=W[f.type]; d.mag=la[c.magFilter];d.min=ya[c.minFilter];d.wrapS=ha[c.wrapS];d.wrapT=ha[c.wrapT];return d}var f=new G(3553);V[f.id]=f;k.textureCount++;d(b,c);d.subimage=function(a,b,c,l){b|=0;c|=0;l|=0;var q=e();g(q,f);q.width=0;q.height=0;u(q,a);q.width=q.width||(f.width>>l)-b;q.height=q.height||(f.height>>l)-c;Q(f);m(q,3553,b,c,l);Aa();n(q);return d};d.resize=function(b,c){var e=b|0,g=c|0||e;if(e===f.width&&g===f.height)return d;d.width=f.width=e;d.height=f.height=g;Q(f);for(var q=0;f.mipmask>>q;++q)a.texImage2D(3553, q,f.format,e>>q,g>>q,0,f.format,f.type,null);Aa();p.profile&&(f.stats.size=Ia(f.internalformat,f.type,e,g,!1,!1));return d};d._reglType="texture2d";d._texture=f;p.profile&&(d.stats=f.stats);d.destroy=function(){f.decRef()};return d},createCube:function(b,c,d,f,l,sa){function z(a,b,c,e,d,f){var F,X=h.texInfo;C.call(X);for(F=0;6>F;++F)q[F]=B();if("number"===typeof a||!a)for(a=a|0||1,F=0;6>F;++F)w(q[F],a,a);else if("object"===typeof a)if(b)t(q[0],a),t(q[1],b),t(q[2],c),t(q[3],e),t(q[4],d),t(q[5],f); else if(M(X,a),r(h,a),"faces"in a)for(a=a.faces,F=0;6>F;++F)g(q[F],h),t(q[F],a[F]);else for(F=0;6>F;++F)t(q[F],a);g(h,q[0]);h.mipmask=X.genMipmaps?(q[0].width<<1)-1:q[0].mipmask;h.internalformat=q[0].internalformat;z.width=q[0].width;z.height=q[0].height;Q(h);for(F=0;6>F;++F)Z(q[F],34069+F);P(X,34067);Aa();p.profile&&(h.stats.size=Ia(h.internalformat,h.type,z.width,z.height,X.genMipmaps,!0));z.format=J[h.internalformat];z.type=W[h.type];z.mag=la[X.magFilter];z.min=ya[X.minFilter];z.wrapS=ha[X.wrapS]; z.wrapT=ha[X.wrapT];for(F=0;6>F;++F)gb(q[F]);return z}var h=new G(34067);V[h.id]=h;k.cubeCount++;var q=Array(6);z(b,c,d,f,l,sa);z.subimage=function(a,b,c,q,d){c|=0;q|=0;d|=0;var f=e();g(f,h);f.width=0;f.height=0;u(f,b);f.width=f.width||(h.width>>d)-c;f.height=f.height||(h.height>>d)-q;Q(h);m(f,34069+a,c,q,d);Aa();n(f);return z};z.resize=function(b){b|=0;if(b!==h.width){z.width=h.width=b;z.height=h.height=b;Q(h);for(var c=0;6>c;++c)for(var q=0;h.mipmask>>q;++q)a.texImage2D(34069+c,q,h.format,b>>q, b>>q,0,h.format,h.type,null);Aa();p.profile&&(h.stats.size=Ia(h.internalformat,h.type,z.width,z.height,!1,!0));return z}};z._reglType="textureCube";z._texture=h;p.profile&&(z.stats=h.stats);z.destroy=function(){h.decRef()};return z},clear:function(){for(var b=0;bc;++c)if(0!==(b.mipmask&1<>c,b.height>>c,0,b.internalformat,b.type,null);else for(var e=0;6>e;++e)a.texImage2D(34069+e,c,b.internalformat,b.width>>c,b.height>>c,0,b.internalformat,b.type,null);P(b.texInfo,b.target)})}}}function Jb(a,b,c,d,f,k){function p(a,b,c){this.target=a;this.texture=b;this.renderbuffer=c;var e=a=0;b?(a=b.width,e=b.height):c&&(a=c.width,e=c.height);this.width=a;this.height=e}function h(a){a&& (a.texture&&a.texture._texture.decRef(),a.renderbuffer&&a.renderbuffer._renderbuffer.decRef())}function g(a,b,c){a&&(a.texture?a.texture._texture.refCount+=1:a.renderbuffer._renderbuffer.refCount+=1)}function r(b,c){c&&(c.texture?a.framebufferTexture2D(36160,b,c.target,c.texture._texture.texture,0):a.framebufferRenderbuffer(36160,b,36161,c.renderbuffer._renderbuffer.renderbuffer))}function v(a){var b=3553,c=null,e=null,g=a;"object"===typeof a&&(g=a.data,"target"in a&&(b=a.target|0));a=g._reglType; "texture2d"===a?c=g:"textureCube"===a?c=g:"renderbuffer"===a&&(e=g,b=36161);return new p(b,c,e)}function l(a,b,c,e,g){if(c)return a=d.create2D({width:a,height:b,format:e,type:g}),a._texture.refCount=0,new p(3553,a,null);a=f.create({width:a,height:b,format:e});a._renderbuffer.refCount=0;return new p(36161,null,a)}function u(a){return a&&(a.texture||a.renderbuffer)}function m(a,b,c){a&&(a.texture?a.texture.resize(b,c):a.renderbuffer&&a.renderbuffer.resize(b,c))}function e(){this.id=M++;P[this.id]=this; this.framebuffer=a.createFramebuffer();this.height=this.width=0;this.colorAttachments=[];this.depthStencilAttachment=this.stencilAttachment=this.depthAttachment=null}function n(a){a.colorAttachments.forEach(h);h(a.depthAttachment);h(a.stencilAttachment);h(a.depthStencilAttachment)}function D(b){a.deleteFramebuffer(b.framebuffer);b.framebuffer=null;k.framebufferCount--;delete P[b.id]}function w(b){var e;a.bindFramebuffer(36160,b.framebuffer);var g=b.colorAttachments;for(e=0;ee;++e){for(n=0;na;++a)c[a].resize(e);b.width=b.height=e;return b},_reglType:"framebufferCube",destroy:function(){c.forEach(function(a){a.destroy()})}})},clear:function(){H(P).forEach(D)},restore:function(){H(P).forEach(function(b){b.framebuffer=a.createFramebuffer();w(b)})}})}function pb(){this.w= this.z=this.y=this.x=this.state=0;this.buffer=null;this.size=0;this.normalized=!1;this.type=5126;this.divisor=this.stride=this.offset=0}function Kb(a,b,c,d,f){a=c.maxAttributes;b=Array(a);for(c=0;ca&&(a=b.stats.uniformsCount)});return a},c.getMaxAttributesCount=function(){var a=0;u.forEach(function(b){b.stats.attributesCount>a&&(a=b.stats.attributesCount)});return a});return{clear:function(){var b=a.deleteShader.bind(a);H(r).forEach(b);r={};H(v).forEach(b);v={};u.forEach(function(b){a.deleteProgram(b.program)});u.length=0;l={};c.shaderCount=0},program:function(a,b,f){var d=l[b];d||(d=l[b]={});var m=d[a];m||(m=new h(b,a),c.shaderCount++,g(m,f),d[a]= m,u.push(m));return m},restore:function(){r={};v={};for(var a=0;a="+b+"?"+d+".constant["+b+"]:0;"}).join(""), "}}else{","if(",q,"(",d,".buffer)){",h,"=",g,".createStream(",34962,",",d,".buffer);","}else{",h,"=",g,".getBuffer(",d,".buffer);","}",K,'="type" in ',d,"?",f.glTypes,"[",d,".type]:",h,".dtype;",y.normalized,"=!!",d,".normalized;");e("size");e("offset");e("stride");e("divisor");c("}}");c.exit("if(",y.isStream,"){",g,".destroyStream(",h,");","}");return y})});return g}function O(a){var b=a["static"],c=a.dynamic,e={};Object.keys(b).forEach(function(a){var c=b[a];e[a]=B(function(a,b){return"number"=== typeof c||"boolean"===typeof c?""+c:a.link(c)})});Object.keys(c).forEach(function(a){var b=c[a];e[a]=N(b,function(a,c){return a.invoke(c,b)})});return e}function z(a,b,c,e,d){var f=A(a,d),g=x(a,f,d),l=M(a,d),h=P(a,d),k=C(a,d),m=g.viewport;m&&(h.viewport=m);m=n("scissor.box");(g=g[m])&&(h[m]=g);g=0>1)",u],");")}function b(){c(w,".drawArraysInstancedANGLE(",[p,r,t,u],");")}n?v?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")):b()}function g(){function a(){c(l+".drawElements("+[p,t,W,r+"<<(("+W+"-5121)>>1)"]+");")}function b(){c(l+".drawArrays("+[p,r,t]+");")}n?v?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")): b()}var h=a.shared,l=h.gl,k=h.draw,m=e.draw,n=function(){var d=m.elements,f=b;if(d){if(d.contextDep&&e.contextDynamic||d.propDep)f=c;d=d.append(a,f)}else d=f.def(k,".","elements");d&&f("if("+d+")"+l+".bindBuffer(34963,"+d+".buffer.buffer);");return d}(),p=d("primitive"),r=d("offset"),t=function(){var d=m.count,f=b;if(d){if(d.contextDep&&e.contextDynamic||d.propDep)f=c;d=d.append(a,f)}else d=f.def(k,".","count");return d}();if("number"===typeof t){if(0===t)return}else c("if(",t,"){"),c.exit("}");var u, w;ma&&(u=d("instances"),w=a.instancing);var W=n+".type",v=m.elements&&ta(m.elements);ma&&("number"!==typeof u||0<=u)?"string"===typeof u?(c("if(",u,">0){"),f(),c("}else if(",u,"<0){"),g(),c("}")):f():g()}function ba(a,b,c,e,d){b=t();d=b.proc("body",d);ma&&(b.instancing=d.def(b.shared.extensions,".angle_instanced_arrays"));a(b,d,c,e);return b.compile().body}function R(a,b,c,e){ua(a,b);S(a,b,c,e.attributes,function(){return!0});U(a,b,c,e.uniforms,function(){return!0});H(a,b,b,c)}function W(a,b){var c= a.proc("draw",1);ua(a,c);sa(a,c,b.context);I(a,c,b.framebuffer);T(a,c,b);L(a,c,b.state);E(a,c,b,!1,!0);var e=b.shader.progVar.append(a,c);c(a.shared.gl,".useProgram(",e,".program);");if(b.shader.program)R(a,c,b,b.shader.program);else{var d=a.global.def("{}"),f=c.def(e,".id"),g=c.def(d,"[",f,"]");c(a.cond(g).then(g,".call(this,a0);")["else"](g,"=",d,"[",f,"]=",a.link(function(c){return ba(R,a,b,c,1)}),"(",e,");",g,".call(this,a0);"))}0=--this.refCount&&p(this)};f.profile&&(d.getTotalRenderbufferSize=function(){var a=0;Object.keys(v).forEach(function(b){a+=v[b].stats.size}); return a});return{create:function(b,c){function m(b,c){var d=0,l=0,k=32854;"object"===typeof b&&b?("shape"in b?(l=b.shape,d=l[0]|0,l=l[1]|0):("radius"in b&&(d=l=b.radius|0),"width"in b&&(d=b.width|0),"height"in b&&(l=b.height|0)),"format"in b&&(k=h[b.format])):"number"===typeof b?(d=b|0,l="number"===typeof c?c|0:d):b||(d=l=1);if(d!==e.width||l!==e.height||k!==e.format)return m.width=e.width=d,m.height=e.height=l,e.format=k,a.bindRenderbuffer(36161,e.renderbuffer),a.renderbufferStorage(36161,k,d,l), f.profile&&(e.stats.size=L[e.format]*e.width*e.height),m.format=g[e.format],m}var e=new k(a.createRenderbuffer());v[e.id]=e;d.renderbufferCount++;m(b,c);m.resize=function(b,c){var d=b|0,g=c|0||d;if(d===e.width&&g===e.height)return m;m.width=e.width=d;m.height=e.height=g;a.bindRenderbuffer(36161,e.renderbuffer);a.renderbufferStorage(36161,e.format,d,g);f.profile&&(e.stats.size=L[e.format]*e.width*e.height);return m};m._reglType="renderbuffer";m._renderbuffer=e;f.profile&&(m.stats=e.stats);m.destroy= function(){e.decRef()};return m},clear:function(){H(v).forEach(p)},restore:function(){H(v).forEach(function(b){b.renderbuffer=a.createRenderbuffer();a.bindRenderbuffer(36161,b.renderbuffer);a.renderbufferStorage(36161,b.format,b.width,b.height)});a.bindRenderbuffer(36161,null)}}},ob=[];ob[6408]=4;var Ma=[];Ma[5121]=1;Ma[5126]=4;Ma[36193]=2;var Da=["x","y","z","w"],Pb="blend.func blend.equation stencil.func stencil.opFront stencil.opBack sample.coverage viewport scissor.box polygonOffset.offset".split(" "), Fa={0:0,1:1,zero:0,one:1,"src color":768,"one minus src color":769,"src alpha":770,"one minus src alpha":771,"dst color":774,"one minus dst color":775,"dst alpha":772,"one minus dst alpha":773,"constant color":32769,"one minus constant color":32770,"constant alpha":32771,"one minus constant alpha":32772,"src alpha saturate":776},Ua={never:512,less:513,"<":513,equal:514,"=":514,"==":514,"===":514,lequal:515,"<=":515,greater:516,">":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519}, Oa={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},rb={cw:2304,ccw:2305},sb=new Y(!1,!1,!1,function(){}),Sb=function(a,b){function c(){this.endQueryIndex=this.startQueryIndex=-1;this.sum=0;this.stats=null}function d(a,b,d){var e=h.pop()||new c;e.startQueryIndex=a;e.endQueryIndex=b;e.sum=0;e.stats=d;g.push(e)}var f=b.ext_disjoint_timer_query;if(!f)return null;var k=[],p=[],h=[],g=[],r=[],v=[];return{beginQuery:function(a){var b= k.pop()||f.createQueryEXT();f.beginQueryEXT(35007,b);p.push(b);d(p.length-1,p.length,a)},endQuery:function(){f.endQueryEXT(35007)},pushScopeStats:d,update:function(){var a,b;a=p.length;if(0!==a){v.length=Math.max(v.length,a+1);r.length=Math.max(r.length,a+1);r[0]=0;var c=v[0]=0;for(b=a=0;b=E.length&&d()}var c=tb(E,a);E[c]=b}}}function r(){var a=O.viewport,b=O.scissor_box;a[0]=a[1]=b[0]=b[1]=0;M.viewportWidth=M.framebufferWidth=M.drawingBufferWidth= a[2]=b[2]=m.drawingBufferWidth;M.viewportHeight=M.framebufferHeight=M.drawingBufferHeight=a[3]=b[3]=m.drawingBufferHeight}function v(){M.tick+=1;M.time=u();r();T.procs.poll()}function l(){r();T.procs.refresh();x&&x.update()}function u(){return(ub()-C)/1E3}a=zb(a);if(!a)return null;var m=a.gl,e=m.getContextAttributes();m.isContextLost();var n=Ab(m,a);if(!n)return null;var D=wb(),w={bufferCount:0,elementsCount:0,framebufferCount:0,shaderCount:0,textureCount:0,cubeCount:0,renderbufferCount:0,maxTextureUnits:0}, t=n.extensions,x=Sb(m,t),C=ub(),B=m.drawingBufferWidth,J=m.drawingBufferHeight,M={tick:0,time:0,viewportWidth:B,viewportHeight:J,framebufferWidth:B,framebufferHeight:J,drawingBufferWidth:B,drawingBufferHeight:J,pixelRatio:a.pixelRatio},P=Qb(m,t),G=Bb(m,w,a),Q=Cb(m,t,G,w),B=Kb(m,t,P,G,D),N=Lb(m,D,w,a),z=Fb(m,t,P,function(){T.procs.poll()},M,w,a),L=Rb(m,t,P,w,a),I=Jb(m,t,P,z,L,w),T=Ob(m,D,t,P,G,Q,z,I,{},B,N,{elements:null,primitive:4,count:-1,offset:0,instances:-1},M,x,a),D=Mb(m,I,T.procs.poll,M,e, t),O=T.next,H=m.canvas,E=[],S=[],U=[],R=[a.onDestroy],ba=null;H&&(H.addEventListener("webglcontextlost",f,!1),H.addEventListener("webglcontextrestored",k,!1));var Y=I.setFBO=p({framebuffer:ia.define.call(null,1,"framebuffer")});l();e=A(p,{clear:function(a){if("framebuffer"in a)if(a.framebuffer&&"framebufferCube"===a.framebuffer_reglType)for(var b=0;6>b;++b)Y(A({framebuffer:a.framebuffer.faces[b]},a),h);else Y(a,h);else h(null,a)},prop:ia.define.bind(null,1),context:ia.define.bind(null,2),"this":ia.define.bind(null, 3),draw:p({}),buffer:function(a){return G.create(a,34962,!1,!1)},elements:function(a){return Q.create(a,!1)},texture:z.create2D,cube:z.createCube,renderbuffer:L.create,framebuffer:I.create,framebufferCube:I.createCube,attributes:e,frame:g,on:function(a,b){var c;switch(a){case "frame":return g(b);case "lost":c=S;break;case "restore":c=U;break;case "destroy":c=R}c.push(b);return{cancel:function(){for(var a=0;a} arr The target array * @param {number} startIdx The index to begin removing from (inclusive) * @param {number} removeCount How many items to remove */ module.exports = function removeItems(arr, startIdx, removeCount) { var i, length = arr.length if (startIdx >= length || removeCount === 0) { return } removeCount = (startIdx + removeCount > length ? length - startIdx : removeCount) var len = length - removeCount for (i = startIdx; i < len; ++i) { arr[i] = arr[i + removeCount] } arr.length = len } },{}],42:[function(require,module,exports){ module.exports = scrollToAnchor function scrollToAnchor (anchor, options) { if (anchor) { try { var el = document.querySelector(anchor) if (el) el.scrollIntoView(options) } catch (e) {} } } },{}],43:[function(require,module,exports){ /* * A fast javascript implementation of simplex noise by Jonas Wagner Based on a speed-improved simplex noise algorithm for 2D, 3D and 4D in Java. Which is based on example code by Stefan Gustavson ([email protected]). With Optimisations by Peter Eastman ([email protected]). Better rank ordering method by Stefan Gustavson in 2012. Copyright (c) 2018 Jonas Wagner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function() { 'use strict'; var F2 = 0.5 * (Math.sqrt(3.0) - 1.0); var G2 = (3.0 - Math.sqrt(3.0)) / 6.0; var F3 = 1.0 / 3.0; var G3 = 1.0 / 6.0; var F4 = (Math.sqrt(5.0) - 1.0) / 4.0; var G4 = (5.0 - Math.sqrt(5.0)) / 20.0; function SimplexNoise(randomOrSeed) { var random; if (typeof randomOrSeed == 'function') { random = randomOrSeed; } else if (randomOrSeed) { random = alea(randomOrSeed); } else { random = Math.random; } this.p = buildPermutationTable(random); this.perm = new Uint8Array(512); this.permMod12 = new Uint8Array(512); for (var i = 0; i < 512; i++) { this.perm[i] = this.p[i & 255]; this.permMod12[i] = this.perm[i] % 12; } } SimplexNoise.prototype = { grad3: new Float32Array([1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0, 1, 0, 1, -1, 0, 1, 1, 0, -1, -1, 0, -1, 0, 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1]), grad4: new Float32Array([0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1, 0, -1, -1, -1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1, 1, 1, 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1, -1, 1, 0, 1, -1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, -1, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0]), noise2D: function(xin, yin) { var permMod12 = this.permMod12; var perm = this.perm; var grad3 = this.grad3; var n0 = 0; // Noise contributions from the three corners var n1 = 0; var n2 = 0; // Skew the input space to determine which simplex cell we're in var s = (xin + yin) * F2; // Hairy factor for 2D var i = Math.floor(xin + s); var j = Math.floor(yin + s); var t = (i + j) * G2; var X0 = i - t; // Unskew the cell origin back to (x,y) space var Y0 = j - t; var x0 = xin - X0; // The x,y distances from the cell origin var y0 = yin - Y0; // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords if (x0 > y0) { i1 = 1; j1 = 0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1) else { i1 = 0; j1 = 1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1) // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where // c = (3-sqrt(3))/6 var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords var y1 = y0 - j1 + G2; var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords var y2 = y0 - 1.0 + 2.0 * G2; // Work out the hashed gradient indices of the three simplex corners var ii = i & 255; var jj = j & 255; // Calculate the contribution from the three corners var t0 = 0.5 - x0 * x0 - y0 * y0; if (t0 >= 0) { var gi0 = permMod12[ii + perm[jj]] * 3; t0 *= t0; n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0); // (x,y) of grad3 used for 2D gradient } var t1 = 0.5 - x1 * x1 - y1 * y1; if (t1 >= 0) { var gi1 = permMod12[ii + i1 + perm[jj + j1]] * 3; t1 *= t1; n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1); } var t2 = 0.5 - x2 * x2 - y2 * y2; if (t2 >= 0) { var gi2 = permMod12[ii + 1 + perm[jj + 1]] * 3; t2 *= t2; n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2); } // Add contributions from each corner to get the final noise value. // The result is scaled to return values in the interval [-1,1]. return 70.0 * (n0 + n1 + n2); }, // 3D simplex noise noise3D: function(xin, yin, zin) { var permMod12 = this.permMod12; var perm = this.perm; var grad3 = this.grad3; var n0, n1, n2, n3; // Noise contributions from the four corners // Skew the input space to determine which simplex cell we're in var s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D var i = Math.floor(xin + s); var j = Math.floor(yin + s); var k = Math.floor(zin + s); var t = (i + j + k) * G3; var X0 = i - t; // Unskew the cell origin back to (x,y,z) space var Y0 = j - t; var Z0 = k - t; var x0 = xin - X0; // The x,y,z distances from the cell origin var y0 = yin - Y0; var z0 = zin - Z0; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. // Determine which simplex we are in. var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords if (x0 >= y0) { if (y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order } else { // x0 y0) rankx++; else ranky++; if (x0 > z0) rankx++; else rankz++; if (x0 > w0) rankx++; else rankw++; if (y0 > z0) ranky++; else rankz++; if (y0 > w0) ranky++; else rankw++; if (z0 > w0) rankz++; else rankw++; var i1, j1, k1, l1; // The integer offsets for the second simplex corner var i2, j2, k2, l2; // The integer offsets for the third simplex corner var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. // Many values of c will never occur, since e.g. x>y>z>w makes x= 3 ? 1 : 0; j1 = ranky >= 3 ? 1 : 0; k1 = rankz >= 3 ? 1 : 0; l1 = rankw >= 3 ? 1 : 0; // Rank 2 denotes the second largest coordinate. i2 = rankx >= 2 ? 1 : 0; j2 = ranky >= 2 ? 1 : 0; k2 = rankz >= 2 ? 1 : 0; l2 = rankw >= 2 ? 1 : 0; // Rank 1 denotes the second smallest coordinate. i3 = rankx >= 1 ? 1 : 0; j3 = ranky >= 1 ? 1 : 0; k3 = rankz >= 1 ? 1 : 0; l3 = rankw >= 1 ? 1 : 0; // The fifth corner has all coordinate offsets = 1, so no need to compute that. var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords var y1 = y0 - j1 + G4; var z1 = z0 - k1 + G4; var w1 = w0 - l1 + G4; var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords var y2 = y0 - j2 + 2.0 * G4; var z2 = z0 - k2 + 2.0 * G4; var w2 = w0 - l2 + 2.0 * G4; var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords var y3 = y0 - j3 + 3.0 * G4; var z3 = z0 - k3 + 3.0 * G4; var w3 = w0 - l3 + 3.0 * G4; var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords var y4 = y0 - 1.0 + 4.0 * G4; var z4 = z0 - 1.0 + 4.0 * G4; var w4 = w0 - 1.0 + 4.0 * G4; // Work out the hashed gradient indices of the five simplex corners var ii = i & 255; var jj = j & 255; var kk = k & 255; var ll = l & 255; // Calculate the contribution from the five corners var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; if (t0 < 0) n0 = 0.0; else { var gi0 = (perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32) * 4; t0 *= t0; n0 = t0 * t0 * (grad4[gi0] * x0 + grad4[gi0 + 1] * y0 + grad4[gi0 + 2] * z0 + grad4[gi0 + 3] * w0); } var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; if (t1 < 0) n1 = 0.0; else { var gi1 = (perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32) * 4; t1 *= t1; n1 = t1 * t1 * (grad4[gi1] * x1 + grad4[gi1 + 1] * y1 + grad4[gi1 + 2] * z1 + grad4[gi1 + 3] * w1); } var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; if (t2 < 0) n2 = 0.0; else { var gi2 = (perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32) * 4; t2 *= t2; n2 = t2 * t2 * (grad4[gi2] * x2 + grad4[gi2 + 1] * y2 + grad4[gi2 + 2] * z2 + grad4[gi2 + 3] * w2); } var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; if (t3 < 0) n3 = 0.0; else { var gi3 = (perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32) * 4; t3 *= t3; n3 = t3 * t3 * (grad4[gi3] * x3 + grad4[gi3 + 1] * y3 + grad4[gi3 + 2] * z3 + grad4[gi3 + 3] * w3); } var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; if (t4 < 0) n4 = 0.0; else { var gi4 = (perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32) * 4; t4 *= t4; n4 = t4 * t4 * (grad4[gi4] * x4 + grad4[gi4 + 1] * y4 + grad4[gi4 + 2] * z4 + grad4[gi4 + 3] * w4); } // Sum up and scale the result to cover the range [-1,1] return 27.0 * (n0 + n1 + n2 + n3 + n4); } }; function buildPermutationTable(random) { var i; var p = new Uint8Array(256); for (i = 0; i < 256; i++) { p[i] = i; } for (i = 0; i < 255; i++) { var r = i + ~~(random() * (256 - i)); var aux = p[i]; p[i] = p[r]; p[r] = aux; } return p; } SimplexNoise._buildPermutationTable = buildPermutationTable; function alea() { // Johannes Baagøe , 2010 var s0 = 0; var s1 = 0; var s2 = 0; var c = 1; var mash = masher(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); for (var i = 0; i < arguments.length; i++) { s0 -= mash(arguments[i]); if (s0 < 0) { s0 += 1; } s1 -= mash(arguments[i]); if (s1 < 0) { s1 += 1; } s2 -= mash(arguments[i]); if (s2 < 0) { s2 += 1; } } mash = null; return function() { var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; } function masher() { var n = 0xefc8249d; return function(data) { data = data.toString(); for (var i = 0; i < data.length; i++) { n += data.charCodeAt(i); var h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; } // amd if (typeof define !== 'undefined' && define.amd) define(function() {return SimplexNoise;}); // common js if (typeof exports !== 'undefined') exports.SimplexNoise = SimplexNoise; // browser else if (typeof window !== 'undefined') window.SimplexNoise = SimplexNoise; // nodejs if (typeof module !== 'undefined') { module.exports = SimplexNoise; } })(); },{}],44:[function(require,module,exports){ 'use strict' var parseUnit = require('parse-unit') module.exports = toPX var PIXELS_PER_INCH = 96 function getPropertyInPX(element, prop) { var parts = parseUnit(getComputedStyle(element).getPropertyValue(prop)) return parts[0] * toPX(parts[1], element) } //This brutal hack is needed function getSizeBrutal(unit, element) { var testDIV = document.createElement('div') testDIV.style['font-size'] = '128' + unit element.appendChild(testDIV) var size = getPropertyInPX(testDIV, 'font-size') / 128 element.removeChild(testDIV) return size } function toPX(str, element) { element = element || document.body str = (str || 'px').trim().toLowerCase() if(element === window || element === document) { element = document.body } switch(str) { case '%': //Ambiguous, not sure if we should use width or height return element.clientHeight / 100.0 case 'ch': case 'ex': return getSizeBrutal(str, element) case 'em': return getPropertyInPX(element, 'font-size') case 'rem': return getPropertyInPX(document.body, 'font-size') case 'vw': return window.innerWidth/100 case 'vh': return window.innerHeight/100 case 'vmin': return Math.min(window.innerWidth, window.innerHeight) / 100 case 'vmax': return Math.max(window.innerWidth, window.innerHeight) / 100 case 'in': return PIXELS_PER_INCH case 'cm': return PIXELS_PER_INCH / 2.54 case 'mm': return PIXELS_PER_INCH / 25.4 case 'pt': return PIXELS_PER_INCH / 72 case 'pc': return PIXELS_PER_INCH / 6 } return 1 } },{"parse-unit":38}],45:[function(require,module,exports){ var assert = require('assert') var trie = require('./trie') module.exports = Wayfarer // create a router // str -> obj function Wayfarer (dft) { if (!(this instanceof Wayfarer)) return new Wayfarer(dft) var _default = (dft || '').replace(/^\//, '') var _trie = trie() emit._trie = _trie emit.on = on emit.emit = emit emit.match = match emit._wayfarer = true return emit // define a route // (str, fn) -> obj function on (route, fn) { assert.equal(typeof route, 'string') assert.equal(typeof fn, 'function') var cb = fn._wayfarer && fn._trie ? fn : proxy route = route || '/' cb.route = route if (cb._wayfarer && cb._trie) { _trie.mount(route, cb._trie.trie) } else { var node = _trie.create(route) node.cb = cb } return emit function proxy () { return fn.apply(this, Array.prototype.slice.call(arguments)) } } // match and call a route // (str, obj?) -> null function emit (route) { var matched = match(route) var args = new Array(arguments.length) args[0] = matched.params for (var i = 1; i < args.length; i++) { args[i] = arguments[i] } return matched.cb.apply(matched.cb, args) } function match (route) { assert.notEqual(route, undefined, "'route' must be defined") var matched = _trie.match(route) if (matched && matched.cb) return new Route(matched) var dft = _trie.match(_default) if (dft && dft.cb) return new Route(dft) throw new Error("route '" + route + "' did not match") } function Route (matched) { this.cb = matched.cb this.route = matched.cb.route this.params = matched.params } } },{"./trie":46,"assert":1}],46:[function(require,module,exports){ var mutate = require('xtend/mutable') var assert = require('assert') var xtend = require('xtend') module.exports = Trie // create a new trie // null -> obj function Trie () { if (!(this instanceof Trie)) return new Trie() this.trie = { nodes: {} } } // create a node on the trie at route // and return a node // str -> null Trie.prototype.create = function (route) { assert.equal(typeof route, 'string', 'route should be a string') // strip leading '/' and split routes var routes = route.replace(/^\//, '').split('/') function createNode (index, trie) { var thisRoute = (routes.hasOwnProperty(index) && routes[index]) if (thisRoute === false) return trie var node = null if (/^:|^\*/.test(thisRoute)) { // if node is a name match, set name and append to ':' node if (!trie.nodes.hasOwnProperty('$$')) { node = { nodes: {} } trie.nodes['$$'] = node } else { node = trie.nodes['$$'] } if (thisRoute[0] === '*') { trie.wildcard = true } trie.name = thisRoute.replace(/^:|^\*/, '') } else if (!trie.nodes.hasOwnProperty(thisRoute)) { node = { nodes: {} } trie.nodes[thisRoute] = node } else { node = trie.nodes[thisRoute] } // we must recurse deeper return createNode(index + 1, node) } return createNode(0, this.trie) } // match a route on the trie // and return the node // str -> obj Trie.prototype.match = function (route) { assert.equal(typeof route, 'string', 'route should be a string') var routes = route.replace(/^\//, '').split('/') var params = {} function search (index, trie) { // either there's no match, or we're done searching if (trie === undefined) return undefined var thisRoute = routes[index] if (thisRoute === undefined) return trie if (trie.nodes.hasOwnProperty(thisRoute)) { // match regular routes first return search(index + 1, trie.nodes[thisRoute]) } else if (trie.name) { // match named routes try { params[trie.name] = decodeURIComponent(thisRoute) } catch (e) { return search(index, undefined) } return search(index + 1, trie.nodes['$$']) } else if (trie.wildcard) { // match wildcards try { params['wildcard'] = decodeURIComponent(routes.slice(index).join('/')) } catch (e) { return search(index, undefined) } // return early, or else search may keep recursing through the wildcard return trie.nodes['$$'] } else { // no matches found return search(index + 1) } } var node = search(0, this.trie) if (!node) return undefined node = xtend(node) node.params = params return node } // mount a trie onto a node at route // (str, obj) -> null Trie.prototype.mount = function (route, trie) { assert.equal(typeof route, 'string', 'route should be a string') assert.equal(typeof trie, 'object', 'trie should be a object') var split = route.replace(/^\//, '').split('/') var node = null var key = null if (split.length === 1) { key = split[0] node = this.create(key) } else { var head = split.join('/') key = split[0] node = this.create(head) } mutate(node.nodes, trie.nodes) if (trie.name) node.name = trie.name // delegate properties from '/' to the new node // '/' cannot be reached once mounted if (node.nodes['']) { Object.keys(node.nodes['']).forEach(function (key) { if (key === 'nodes') return node[key] = node.nodes[''][key] }) mutate(node.nodes, node.nodes[''].nodes) delete node.nodes[''].nodes } } },{"assert":1,"xtend":47,"xtend/mutable":48}],47:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; function extend() { var target = {} for (var i = 0; i < arguments.length; i++) { var source = arguments[i] for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target } },{}],48:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; function extend(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target } },{}],49:[function(require,module,exports){ module.exports = function (state, emitter) { var q = 0.995 var seaLevel = +12 state.ocean = { positions: [ [-q,-q,seaLevel], [-q,+q,seaLevel], [+q,+q,seaLevel], [+q,-q,seaLevel], [-q,-q,+0], [-q,+q,+0], [+q,+q,+0], [+q,-q,+0] ], cells: [ [0,1,2],[0,2,3], [0,4,1],[4,5,1], [1,2,5],[2,5,6], [2,3,6],[3,6,7], [3,0,7],[0,7,4] ] } } },{}],50:[function(require,module,exports){ var Simplex = require('simplex-noise') var earcut = require('earcut') module.exports = function (state, emitter) { state.tiles = { size: [0,0], data: [] } emitter.on('generate', function (seed) { var simplex = new Simplex(seed) var v = simplex.noise2D(500,500)*0.5+0.5 var f = Math.pow(simplex.noise2D(1000,1000)*0.5+0.5,8.0) var v = 2.0/Math.pow(simplex.noise2D(1000,1000)*0.5+0.5,2.0) var b = Math.floor(Math.pow(simplex.noise2D(2000,2000)*0.5+0.5,2.0)*64+4) var q = Math.pow(simplex.noise2D(0,0)*0.5+0.5,0.1/v)*0.01 var mesh = { positions: [], cells: [] } var w = 256, h = 256 for (var x = 0; x < w; x++) { for (var y = 0; y < h; y++) { var m = Math.pow(simplex.noise2D(x*q,y*q)*0.5+0.5,1) var z = Math.floor((simplex.noise2D(x*f,y*f)*0.5+0.5)*m*b)+v mesh.positions.push([x,y,z]) } } for (var x = 0; x < w-1; x++) { for (var y = 0; y < h-1; y++) { var p0 = mesh.positions[y*w+x][2] var p1 = mesh.positions[y*w+x+1][2] var p2 = mesh.positions[(y+1)*w+x][2] var p3 = mesh.positions[(y+1)*w+x+1][2] var flip = Math.abs(p1-p2) < 0.1 //if ((p0+p1+p2+p3)/4 % 1 > 0.5) flip = !flip if (flip) { mesh.cells.push([ y*w+x, y*w+x+1, (y+1)*w+x ]) mesh.cells.push([ y*w+x+1, (y+1)*w+x, (y+1)*w+x+1 ]) } else { mesh.cells.push([ y*w+x, y*w+x+1, (y+1)*w+x+1 ]) mesh.cells.push([ y*w+x, (y+1)*w+x, (y+1)*w+x+1 ]) } } } var wall = walls(mesh, w, h) state.tiles.size[0] = w state.tiles.size[1] = h state.tiles.data = [mesh] state.tiles.wall = [wall] emitter.emit('post-generate') }) } function walls (mesh, w, h) { var wall = { positions: [], cells: [], heights: [] } for (var y = 0; y < h; y += h-1) { var k = wall.positions.length for (var x = 0; x < w; x++) { var z = mesh.positions[y*w+x][2] wall.positions.push([y,x,z]) wall.positions.push([y,x,0]) wall.heights.push(z,z) } for (var i = 0; i < w-1; i++) { wall.cells.push( [k+i*2+0,k+i*2+1,k+(i+1)*2+0], [k+i*2+1,k+(i+1)*2+0,k+(i+1)*2+1] ) } } for (var x = 0; x < w; x += w-1) { var k = wall.positions.length for (var y = 0; y < h; y++) { var z = mesh.positions[y*w+x][2] wall.positions.push([y,x,z]) wall.positions.push([y,x,0]) wall.heights.push(z,z) } for (var i = 0; i < h-1; i++) { wall.cells.push( [k+i*2+0,k+i*2+1,k+(i+1)*2+0], [k+i*2+1,k+(i+1)*2+0,k+(i+1)*2+1] ) } } return wall } },{"earcut":16,"simplex-noise":43}]},{},[9]);