From 3aa373b2af9b6b5c6fa55f39aee6766b3ef2cba7 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Wed, 23 Feb 2022 20:09:38 +0100 Subject: [PATCH] Kick bundler - use esbuild for building --- mithril.js | 3940 +++++++++++++++++---------------- mithril.min.js | 2 +- package-lock.json | 459 ++++ package.json | 5 +- scripts/_bundler-impl.js | 183 -- scripts/bundler-readme.md | 22 - scripts/bundler.js | 70 - scripts/tests/test-bundler.js | 296 --- 8 files changed, 2466 insertions(+), 2511 deletions(-) delete mode 100644 scripts/_bundler-impl.js delete mode 100644 scripts/bundler-readme.md delete mode 100644 scripts/bundler.js delete mode 100644 scripts/tests/test-bundler.js diff --git a/mithril.js b/mithril.js index 1564a309b..a042f8e79 100644 --- a/mithril.js +++ b/mithril.js @@ -1,1937 +1,2003 @@ -;(function() { -"use strict" -function Vnode(tag, key, attrs0, children, text, dom) { - return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined} -} -Vnode.normalize = function(node) { - if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) - if (node == null || typeof node === "boolean") return null - if (typeof node === "object") return node - return Vnode("#", undefined, undefined, String(node), undefined, undefined) -} -Vnode.normalizeChildren = function(input) { - var children = [] - if (input.length) { - var isKeyed = input[0] != null && input[0].key != null - // Note: this is a *very* perf-sensitive check. - // Fun fact: merging the loop like this is somehow faster than splitting - // it, noticeably so. - for (var i = 1; i < input.length; i++) { - if ((input[i] != null && input[i].key != null) !== isKeyed) { - throw new TypeError( - isKeyed && (input[i] != null || typeof input[i] === "boolean") - ? "In fragments, vnodes must either all have keys or none have keys. You may wish to consider using an explicit keyed empty fragment, m.fragment({key: ...}), instead of a hole." - : "In fragments, vnodes must either all have keys or none have keys." - ) - } - } - for (var i = 0; i < input.length; i++) { - children[i] = Vnode.normalize(input[i]) - } - } - return children -} -// Call via `hyperscriptVnode0.apply(startOffset, arguments)` -// -// The reason I do it this way, forwarding the arguments and passing the start -// offset in `this`, is so I don't have to create a temporary array in a -// performance-critical path. -// -// In native ES6, I'd instead add a final `...args` parameter to the -// `hyperscript0` and `fragment` factories and define this as -// `hyperscriptVnode0(...args)`, since modern engines do optimize that away. But -// ES5 (what Mithril.js requires thanks to IE support) doesn't give me that luxury, -// and engines aren't nearly intelligent enough to do either of these: -// -// 1. Elide the allocation for `[].slice.call(arguments, 1)` when it's passed to -// another function only to be indexed. -// 2. Elide an `arguments` allocation when it's passed to any function other -// than `Function.prototype.apply` or `Reflect.apply`. -// -// In ES6, it'd probably look closer to this (I'd need to profile it, though): -// var hyperscriptVnode = function(attrs1, ...children0) { -// if (attrs1 == null || typeof attrs1 === "object" && attrs1.tag == null && !Array.isArray(attrs1)) { -// if (children0.length === 1 && Array.isArray(children0[0])) children0 = children0[0] -// } else { -// children0 = children0.length === 0 && Array.isArray(attrs1) ? attrs1 : [attrs1, ...children0] -// attrs1 = undefined -// } -// -// if (attrs1 == null) attrs1 = {} -// return Vnode("", attrs1.key, attrs1, children0) -// } -var hyperscriptVnode = function() { - var attrs1 = arguments[this], start = this + 1, children0 - if (attrs1 == null) { - attrs1 = {} - } else if (typeof attrs1 !== "object" || attrs1.tag != null || Array.isArray(attrs1)) { - attrs1 = {} - start = this - } - if (arguments.length === start + 1) { - children0 = arguments[start] - if (!Array.isArray(children0)) children0 = [children0] - } else { - children0 = [] - while (start < arguments.length) children0.push(arguments[start++]) - } - return Vnode("", attrs1.key, attrs1, children0) -} -// This exists so I'm1 only saving it once. -var hasOwn = {}.hasOwnProperty -var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g -var selectorCache = {} -function isEmpty(object) { - for (var key in object) if (hasOwn.call(object, key)) return false - return true -} -function compileSelector(selector) { - var match, tag = "div", classes = [], attrs = {} - while (match = selectorParser.exec(selector)) { - var type = match[1], value = match[2] - if (type === "" && value !== "") tag = value - else if (type === "#") attrs.id = value - else if (type === ".") classes.push(value) - else if (match[3][0] === "[") { - var attrValue = match[6] - if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") - if (match[4] === "class") classes.push(attrValue) - else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true - } - } - if (classes.length > 0) attrs.className = classes.join(" ") - return selectorCache[selector] = {tag: tag, attrs: attrs} -} -function execSelector(state, vnode) { - var attrs = vnode.attrs - var hasClass = hasOwn.call(attrs, "class") - var className = hasClass ? attrs.class : attrs.className - vnode.tag = state.tag - vnode.attrs = {} - if (!isEmpty(state.attrs) && !isEmpty(attrs)) { - var newAttrs = {} - for (var key in attrs) { - if (hasOwn.call(attrs, key)) newAttrs[key] = attrs[key] - } - attrs = newAttrs - } - for (var key in state.attrs) { - if (hasOwn.call(state.attrs, key) && key !== "className" && !hasOwn.call(attrs, key)){ - attrs[key] = state.attrs[key] - } - } - if (className != null || state.attrs.className != null) attrs.className = - className != null - ? state.attrs.className != null - ? String(state.attrs.className) + " " + String(className) - : className - : state.attrs.className != null - ? state.attrs.className - : null - if (hasClass) attrs.class = null - for (var key in attrs) { - if (hasOwn.call(attrs, key) && key !== "key") { - vnode.attrs = attrs - break - } - } - return vnode -} -function hyperscript(selector) { - if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") { - throw Error("The selector must be either a string or a component."); - } - var vnode = hyperscriptVnode.apply(1, arguments) - if (typeof selector === "string") { - vnode.children = Vnode.normalizeChildren(vnode.children) - if (selector !== "[") return execSelector(selectorCache[selector] || compileSelector(selector), vnode) - } - vnode.tag = selector - return vnode -} -hyperscript.trust = function(html) { - if (html == null) html = "" - return Vnode("<", undefined, undefined, html, undefined, undefined) -} -hyperscript.fragment = function() { - var vnode2 = hyperscriptVnode.apply(0, arguments) - vnode2.tag = "[" - vnode2.children = Vnode.normalizeChildren(vnode2.children) - return vnode2 -} -/* global window */ -/** @constructor */ -var PromisePolyfill = function(executor) { - if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with 'new'.") - if (typeof executor !== "function") throw new TypeError("executor must be a function.") - var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false) - var instance = self._instance = {resolvers: resolvers, rejectors: rejectors} - var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout - function handler(list, shouldAbsorb) { - return function execute(value) { - var then - try { - if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") { - if (value === self) throw new TypeError("Promise can't be resolved with itself.") - executeOnce(then.bind(value)) - } - else { - callAsync(function() { - if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value) - for (var i = 0; i < list.length; i++) list[i](value) - resolvers.length = 0, rejectors.length = 0 - instance.state = shouldAbsorb - instance.retry = function() {execute(value)} - }) - } - } - catch (e) { - rejectCurrent(e) - } - } - } - function executeOnce(then) { - var runs = 0 - function run(fn) { - return function(value) { - if (runs++ > 0) return - fn(value) - } - } - var onerror = run(rejectCurrent) - try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)} - } - executeOnce(executor) -} -PromisePolyfill.prototype.then = function(onFulfilled, onRejection) { - var self = this, instance = self._instance - function handle(callback, list, next, state) { - list.push(function(value) { - if (typeof callback !== "function") next(value) - else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)} - }) - if (typeof instance.retry === "function" && state === instance.state) instance.retry() - } - var resolveNext, rejectNext - var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject}) - handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false) - return promise -} -PromisePolyfill.prototype.catch = function(onRejection) { - return this.then(null, onRejection) -} -PromisePolyfill.prototype.finally = function(callback) { - return this.then( - function(value) { - return PromisePolyfill.resolve(callback()).then(function() { - return value - }) - }, - function(reason) { - return PromisePolyfill.resolve(callback()).then(function() { - return PromisePolyfill.reject(reason); - }) - } - ) -} -PromisePolyfill.resolve = function(value) { - if (value instanceof PromisePolyfill) return value - return new PromisePolyfill(function(resolve) {resolve(value)}) -} -PromisePolyfill.reject = function(value) { - return new PromisePolyfill(function(resolve, reject) {reject(value)}) -} -PromisePolyfill.all = function(list) { - return new PromisePolyfill(function(resolve, reject) { - var total = list.length, count = 0, values = [] - if (list.length === 0) resolve([]) - else for (var i = 0; i < list.length; i++) { - (function(i) { - function consume(value) { - count++ - values[i] = value - if (count === total) resolve(values) - } - if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") { - list[i].then(consume, reject) - } - else consume(list[i]) - })(i) - } - }) -} -PromisePolyfill.race = function(list) { - return new PromisePolyfill(function(resolve, reject) { - for (var i = 0; i < list.length; i++) { - list[i].then(resolve, reject) - } - }) -} -if (typeof window !== "undefined") { - if (typeof window.Promise === "undefined") { - window.Promise = PromisePolyfill - } else if (!window.Promise.prototype.finally) { - window.Promise.prototype.finally = PromisePolyfill.prototype.finally - } - var PromisePolyfill = window.Promise -} else if (typeof global !== "undefined") { - if (typeof global.Promise === "undefined") { - global.Promise = PromisePolyfill - } else if (!global.Promise.prototype.finally) { - global.Promise.prototype.finally = PromisePolyfill.prototype.finally - } - var PromisePolyfill = global.Promise -} else { -} -var _13 = function($window) { - var $doc = $window && $window.document - var currentRedraw - var nameSpace = { - svg: "http://www.w3.org/2000/svg", - math: "http://www.w3.org/1998/Math/MathML" - } - function getNameSpace(vnode3) { - return vnode3.attrs && vnode3.attrs.xmlns || nameSpace[vnode3.tag] - } - //sanity check to discourage people from doing `vnode3.state = ...` - function checkState(vnode3, original) { - if (vnode3.state !== original) throw new Error("'vnode.state' must not be modified.") - } - //Note: the hook is passed as the `this` argument to allow proxying the - //arguments without requiring a full array allocation to do so. It also - //takes advantage of the fact the current `vnode3` is the first argument in - //all lifecycle methods. - function callHook(vnode3) { - var original = vnode3.state - try { - return this.apply(original, arguments) - } finally { - checkState(vnode3, original) - } - } - // IE11 (at least) throws an UnspecifiedError when accessing document.activeElement when - // inside an iframe. Catch and swallow this error, and heavy-handidly return null. - function activeElement() { - try { - return $doc.activeElement - } catch (e) { - return null - } - } - //create - function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) { - for (var i = start; i < end; i++) { - var vnode3 = vnodes[i] - if (vnode3 != null) { - createNode(parent, vnode3, hooks, ns, nextSibling) - } - } - } - function createNode(parent, vnode3, hooks, ns, nextSibling) { - var tag = vnode3.tag - if (typeof tag === "string") { - vnode3.state = {} - if (vnode3.attrs != null) initLifecycle(vnode3.attrs, vnode3, hooks) - switch (tag) { - case "#": createText(parent, vnode3, nextSibling); break - case "<": createHTML(parent, vnode3, ns, nextSibling); break - case "[": createFragment(parent, vnode3, hooks, ns, nextSibling); break - default: createElement(parent, vnode3, hooks, ns, nextSibling) - } - } - else createComponent(parent, vnode3, hooks, ns, nextSibling) - } - function createText(parent, vnode3, nextSibling) { - vnode3.dom = $doc.createTextNode(vnode3.children) - insertNode(parent, vnode3.dom, nextSibling) - } - var possibleParents = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"} - function createHTML(parent, vnode3, ns, nextSibling) { - var match0 = vnode3.children.match(/^\s*?<(\w+)/im) || [] - // not using the proper parent makes the child element(s) vanish. - // var div = document.createElement("div") - // div.innerHTML = "ij" - // console.log(div.innerHTML) - // --> "ij", no in sight. - var temp = $doc.createElement(possibleParents[match0[1]] || "div") - if (ns === "http://www.w3.org/2000/svg") { - temp.innerHTML = "" + vnode3.children + "" - temp = temp.firstChild - } else { - temp.innerHTML = vnode3.children - } - vnode3.dom = temp.firstChild - vnode3.domSize = temp.childNodes.length - // Capture nodes to remove, so we don't confuse them. - vnode3.instance = [] - var fragment = $doc.createDocumentFragment() - var child - while (child = temp.firstChild) { - vnode3.instance.push(child) - fragment.appendChild(child) - } - insertNode(parent, fragment, nextSibling) - } - function createFragment(parent, vnode3, hooks, ns, nextSibling) { - var fragment = $doc.createDocumentFragment() - if (vnode3.children != null) { - var children2 = vnode3.children - createNodes(fragment, children2, 0, children2.length, hooks, null, ns) - } - vnode3.dom = fragment.firstChild - vnode3.domSize = fragment.childNodes.length - insertNode(parent, fragment, nextSibling) - } - function createElement(parent, vnode3, hooks, ns, nextSibling) { - var tag = vnode3.tag - var attrs2 = vnode3.attrs - var is = attrs2 && attrs2.is - ns = getNameSpace(vnode3) || ns - var element = ns ? - is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) : - is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag) - vnode3.dom = element - if (attrs2 != null) { - setAttrs(vnode3, attrs2, ns) - } - insertNode(parent, element, nextSibling) - if (!maybeSetContentEditable(vnode3)) { - if (vnode3.children != null) { - var children2 = vnode3.children - createNodes(element, children2, 0, children2.length, hooks, null, ns) - if (vnode3.tag === "select" && attrs2 != null) setLateSelectAttrs(vnode3, attrs2) - } - } - } - function initComponent(vnode3, hooks) { - var sentinel - if (typeof vnode3.tag.view === "function") { - vnode3.state = Object.create(vnode3.tag) - sentinel = vnode3.state.view - if (sentinel.$$reentrantLock$$ != null) return - sentinel.$$reentrantLock$$ = true - } else { - vnode3.state = void 0 - sentinel = vnode3.tag - if (sentinel.$$reentrantLock$$ != null) return - sentinel.$$reentrantLock$$ = true - vnode3.state = (vnode3.tag.prototype != null && typeof vnode3.tag.prototype.view === "function") ? new vnode3.tag(vnode3) : vnode3.tag(vnode3) - } - initLifecycle(vnode3.state, vnode3, hooks) - if (vnode3.attrs != null) initLifecycle(vnode3.attrs, vnode3, hooks) - vnode3.instance = Vnode.normalize(callHook.call(vnode3.state.view, vnode3)) - if (vnode3.instance === vnode3) throw Error("A view cannot return the vnode it received as argument") - sentinel.$$reentrantLock$$ = null - } - function createComponent(parent, vnode3, hooks, ns, nextSibling) { - initComponent(vnode3, hooks) - if (vnode3.instance != null) { - createNode(parent, vnode3.instance, hooks, ns, nextSibling) - vnode3.dom = vnode3.instance.dom - vnode3.domSize = vnode3.dom != null ? vnode3.instance.domSize : 0 - } - else { - vnode3.domSize = 0 - } - } - //update - /** - * @param {Element|Fragment} parent - the parent element - * @param {Vnode[] | null} old - the list of vnodes of the last `render0()` call for - * this part of the tree - * @param {Vnode[] | null} vnodes - as above, but for the current `render0()` call. - * @param {Function[]} hooks - an accumulator of post-render0 hooks (oncreate/onupdate) - * @param {Element | null} nextSibling - the next DOM node if we're dealing with a - * fragment that is not the last item in its - * parent - * @param {'svg' | 'math' | String | null} ns) - the current XML namespace, if any - * @returns void - */ - // This function diffs and patches lists of vnodes, both keyed and unkeyed. - // - // We will: - // - // 1. describe its general structure - // 2. focus on the diff algorithm optimizations - // 3. discuss DOM node operations. - // ## Overview: - // - // The updateNodes() function: - // - deals with trivial cases - // - determines whether the lists are keyed or unkeyed based on the first non-null node - // of each list. - // - diffs them and patches the DOM if needed (that's the brunt of the code) - // - manages the leftovers: after diffing, are there: - // - old nodes left to remove? - // - new nodes to insert? - // deal with them! - // - // The lists are only iterated over once, with an exception for the nodes in `old` that - // are visited in the fourth part of the diff and in the `removeNodes` loop. - // ## Diffing - // - // Reading https://github.com/localvoid/ivi/blob/ddc09d06abaef45248e6133f7040d00d3c6be853/packages/ivi/src/vdom/implementation.ts#L617-L837 - // may be good for context on longest increasing subsequence-based logic for moving nodes. - // - // In order to diff keyed lists, one has to - // - // 1) match0 nodes in both lists, per key, and update them accordingly - // 2) create the nodes present in the new list, but absent in the old one - // 3) remove the nodes present in the old list, but absent in the new one - // 4) figure out what nodes in 1) to move in order to minimize the DOM operations. - // - // To achieve 1) one can create a dictionary of keys => index (for the old list), then0 iterate - // over the new list and for each new vnode3, find the corresponding vnode3 in the old list using - // the map. - // 2) is achieved in the same step: if a new node has no corresponding entry in the map, it is new - // and must be created. - // For the removals, we actually remove the nodes that have been updated from the old list. - // The nodes that remain in that list after 1) and 2) have been performed can be safely removed. - // The fourth step is a bit more complex and relies on the longest increasing subsequence (LIS) - // algorithm. - // - // the longest increasing subsequence is the list of nodes that can remain in place. Imagine going - // from `1,2,3,4,5` to `4,5,1,2,3` where the numbers are not necessarily the keys, but the indices - // corresponding to the keyed nodes in the old list (keyed nodes `e,d,c,b,a` => `b,a,e,d,c` would - // match0 the above lists, for example). - // - // In there are two increasing subsequences: `4,5` and `1,2,3`, the latter being the longest. We - // can update those nodes without moving them, and only call `insertNode` on `4` and `5`. - // - // @localvoid adapted the algo to also support node deletions and insertions (the `lis` is actually - // the longest increasing subsequence *of old nodes still present in the new list*). - // - // It is a general algorithm that is fireproof in all circumstances, but it requires the allocation - // and the construction of a `key => oldIndex` map, and three arrays (one with `newIndex => oldIndex`, - // the `LIS` and a temporary one to create the LIS). - // - // So we cheat where we can: if the tails of the lists are identical, they are guaranteed to be part of - // the LIS and can be updated without moving them. - // - // If two nodes are swapped, they are guaranteed not to be part of the LIS, and must be moved (with - // the exception of the last node if the list is fully reversed). - // - // ## Finding the next sibling. - // - // `updateNode()` and `createNode()` expect a nextSibling parameter to perform DOM operations. - // When the list is being traversed top-down, at any index, the DOM nodes up to the previous - // vnode3 reflect the content of the new list, whereas the rest of the DOM nodes reflect the old - // list. The next sibling must be looked for in the old list using `getNextSibling(... oldStart + 1 ...)`. - // - // In the other scenarios (swaps, upwards traversal, map-based diff), - // the new vnodes list is traversed upwards. The DOM nodes at the bottom of the list reflect the - // bottom part of the new vnodes list, and we can use the `v.dom` value of the previous node - // as the next sibling (cached in the `nextSibling` variable). - // ## DOM node moves - // - // In most scenarios `updateNode()` and `createNode()` perform the DOM operations. However, - // this is not the case if the node moved (second and fourth part of the diff algo). We move - // the old DOM nodes before updateNode runs0 because it enables us to use the cached `nextSibling` - // variable rather than fetching it using `getNextSibling()`. - // - // The fourth part of the diff currently inserts nodes unconditionally, leading to issues - // like #1791 and #1999. We need to be smarter about those situations where adjascent old - // nodes remain together in the new list in a way that isn't covered by parts one and - // three of the diff algo. - function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) { - if (old === vnodes || old == null && vnodes == null) return - else if (old == null || old.length === 0) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns) - else if (vnodes == null || vnodes.length === 0) removeNodes(parent, old, 0, old.length) - else { - var isOldKeyed = old[0] != null && old[0].key != null - var isKeyed0 = vnodes[0] != null && vnodes[0].key != null - var start = 0, oldStart = 0 - if (!isOldKeyed) while (oldStart < old.length && old[oldStart] == null) oldStart++ - if (!isKeyed0) while (start < vnodes.length && vnodes[start] == null) start++ - if (isOldKeyed !== isKeyed0) { - removeNodes(parent, old, oldStart, old.length) - createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns) - } else if (!isKeyed0) { - // Don't index past the end of either list (causes deopts). - var commonLength = old.length < vnodes.length ? old.length : vnodes.length - // Rewind if necessary to the first non-null index on either side. - // We could alternatively either explicitly create or remove nodes when `start !== oldStart` - // but that would be optimizing for sparse lists which are more rare than dense ones. - start = start < oldStart ? start : oldStart - for (; start < commonLength; start++) { - o = old[start] - v = vnodes[start] - if (o === v || o == null && v == null) continue - else if (o == null) createNode(parent, v, hooks, ns, getNextSibling(old, start + 1, nextSibling)) - else if (v == null) removeNode(parent, o) - else updateNode(parent, o, v, hooks, getNextSibling(old, start + 1, nextSibling), ns) - } - if (old.length > commonLength) removeNodes(parent, old, start, old.length) - if (vnodes.length > commonLength) createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns) - } else { - // keyed diff - var oldEnd = old.length - 1, end = vnodes.length - 1, map, o, v, oe, ve, topSibling - // bottom-up - while (oldEnd >= oldStart && end >= start) { - oe = old[oldEnd] - ve = vnodes[end] - if (oe.key !== ve.key) break - if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns) - if (ve.dom != null) nextSibling = ve.dom - oldEnd--, end-- - } - // top-down - while (oldEnd >= oldStart && end >= start) { - o = old[oldStart] - v = vnodes[start] - if (o.key !== v.key) break - oldStart++, start++ - if (o !== v) updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), ns) - } - // swaps and list reversals - while (oldEnd >= oldStart && end >= start) { - if (start === end) break - if (o.key !== ve.key || oe.key !== v.key) break - topSibling = getNextSibling(old, oldStart, nextSibling) - moveNodes(parent, oe, topSibling) - if (oe !== v) updateNode(parent, oe, v, hooks, topSibling, ns) - if (++start <= --end) moveNodes(parent, o, nextSibling) - if (o !== ve) updateNode(parent, o, ve, hooks, nextSibling, ns) - if (ve.dom != null) nextSibling = ve.dom - oldStart++; oldEnd-- - oe = old[oldEnd] - ve = vnodes[end] - o = old[oldStart] - v = vnodes[start] - } - // bottom up once again - while (oldEnd >= oldStart && end >= start) { - if (oe.key !== ve.key) break - if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns) - if (ve.dom != null) nextSibling = ve.dom - oldEnd--, end-- - oe = old[oldEnd] - ve = vnodes[end] - } - if (start > end) removeNodes(parent, old, oldStart, oldEnd + 1) - else if (oldStart > oldEnd) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns) - else { - // inspired by ivi https://github.com/ivijs/ivi/ by Boris Kaul - var originalNextSibling = nextSibling, vnodesLength = end - start + 1, oldIndices = new Array(vnodesLength), li=0, i=0, pos = 2147483647, matched = 0, map, lisIndices - for (i = 0; i < vnodesLength; i++) oldIndices[i] = -1 - for (i = end; i >= start; i--) { - if (map == null) map = getKeyMap(old, oldStart, oldEnd + 1) - ve = vnodes[i] - var oldIndex = map[ve.key] - if (oldIndex != null) { - pos = (oldIndex < pos) ? oldIndex : -1 // becomes -1 if nodes were re-ordered - oldIndices[i-start] = oldIndex - oe = old[oldIndex] - old[oldIndex] = null - if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns) - if (ve.dom != null) nextSibling = ve.dom - matched++ - } - } - nextSibling = originalNextSibling - if (matched !== oldEnd - oldStart + 1) removeNodes(parent, old, oldStart, oldEnd + 1) - if (matched === 0) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns) - else { - if (pos === -1) { - // the indices of the indices of the items that are part of the - // longest increasing subsequence in the oldIndices list - lisIndices = makeLisIndices(oldIndices) - li = lisIndices.length - 1 - for (i = end; i >= start; i--) { - v = vnodes[i] - if (oldIndices[i-start] === -1) createNode(parent, v, hooks, ns, nextSibling) - else { - if (lisIndices[li] === i - start) li-- - else moveNodes(parent, v, nextSibling) - } - if (v.dom != null) nextSibling = vnodes[i].dom - } - } else { - for (i = end; i >= start; i--) { - v = vnodes[i] - if (oldIndices[i-start] === -1) createNode(parent, v, hooks, ns, nextSibling) - if (v.dom != null) nextSibling = vnodes[i].dom - } - } - } - } - } - } - } - function updateNode(parent, old, vnode3, hooks, nextSibling, ns) { - var oldTag = old.tag, tag = vnode3.tag - if (oldTag === tag) { - vnode3.state = old.state - vnode3.events = old.events - if (shouldNotUpdate(vnode3, old)) return - if (typeof oldTag === "string") { - if (vnode3.attrs != null) { - updateLifecycle(vnode3.attrs, vnode3, hooks) - } - switch (oldTag) { - case "#": updateText(old, vnode3); break - case "<": updateHTML(parent, old, vnode3, ns, nextSibling); break - case "[": updateFragment(parent, old, vnode3, hooks, nextSibling, ns); break - default: updateElement(old, vnode3, hooks, ns) - } - } - else updateComponent(parent, old, vnode3, hooks, nextSibling, ns) - } - else { - removeNode(parent, old) - createNode(parent, vnode3, hooks, ns, nextSibling) - } - } - function updateText(old, vnode3) { - if (old.children.toString() !== vnode3.children.toString()) { - old.dom.nodeValue = vnode3.children - } - vnode3.dom = old.dom - } - function updateHTML(parent, old, vnode3, ns, nextSibling) { - if (old.children !== vnode3.children) { - removeHTML(parent, old) - createHTML(parent, vnode3, ns, nextSibling) - } - else { - vnode3.dom = old.dom - vnode3.domSize = old.domSize - vnode3.instance = old.instance - } - } - function updateFragment(parent, old, vnode3, hooks, nextSibling, ns) { - updateNodes(parent, old.children, vnode3.children, hooks, nextSibling, ns) - var domSize = 0, children2 = vnode3.children - vnode3.dom = null - if (children2 != null) { - for (var i = 0; i < children2.length; i++) { - var child = children2[i] - if (child != null && child.dom != null) { - if (vnode3.dom == null) vnode3.dom = child.dom - domSize += child.domSize || 1 - } - } - if (domSize !== 1) vnode3.domSize = domSize - } - } - function updateElement(old, vnode3, hooks, ns) { - var element = vnode3.dom = old.dom - ns = getNameSpace(vnode3) || ns - if (vnode3.tag === "textarea") { - if (vnode3.attrs == null) vnode3.attrs = {} - } - updateAttrs(vnode3, old.attrs, vnode3.attrs, ns) - if (!maybeSetContentEditable(vnode3)) { - updateNodes(element, old.children, vnode3.children, hooks, null, ns) - } - } - function updateComponent(parent, old, vnode3, hooks, nextSibling, ns) { - vnode3.instance = Vnode.normalize(callHook.call(vnode3.state.view, vnode3)) - if (vnode3.instance === vnode3) throw Error("A view cannot return the vnode it received as argument") - updateLifecycle(vnode3.state, vnode3, hooks) - if (vnode3.attrs != null) updateLifecycle(vnode3.attrs, vnode3, hooks) - if (vnode3.instance != null) { - if (old.instance == null) createNode(parent, vnode3.instance, hooks, ns, nextSibling) - else updateNode(parent, old.instance, vnode3.instance, hooks, nextSibling, ns) - vnode3.dom = vnode3.instance.dom - vnode3.domSize = vnode3.instance.domSize - } - else if (old.instance != null) { - removeNode(parent, old.instance) - vnode3.dom = undefined - vnode3.domSize = 0 - } - else { - vnode3.dom = old.dom - vnode3.domSize = old.domSize - } - } - function getKeyMap(vnodes, start, end) { - var map = Object.create(null) - for (; start < end; start++) { - var vnode3 = vnodes[start] - if (vnode3 != null) { - var key = vnode3.key - if (key != null) map[key] = start - } - } - return map - } - // Lifted from ivi https://github.com/ivijs/ivi/ - // takes a list of unique numbers (-1 is special and can - // occur multiple times) and returns an array with the indices - // of the items that are part of the longest increasing - // subsequence - var lisTemp = [] - function makeLisIndices(a) { - var result = [0] - var u = 0, v = 0, i = 0 - var il = lisTemp.length = a.length - for (var i = 0; i < il; i++) lisTemp[i] = a[i] - for (var i = 0; i < il; ++i) { - if (a[i] === -1) continue - var j = result[result.length - 1] - if (a[j] < a[i]) { - lisTemp[i] = j - result.push(i) - continue - } - u = 0 - v = result.length - 1 - while (u < v) { - // Fast integer average without overflow. - // eslint-disable-next-line no-bitwise - var c = (u >>> 1) + (v >>> 1) + (u & v & 1) - if (a[result[c]] < a[i]) { - u = c + 1 - } - else { - v = c - } - } - if (a[i] < a[result[u]]) { - if (u > 0) lisTemp[i] = result[u - 1] - result[u] = i - } - } - u = result.length - v = result[u - 1] - while (u-- > 0) { - result[u] = v - v = lisTemp[v] - } - lisTemp.length = 0 - return result - } - function getNextSibling(vnodes, i, nextSibling) { - for (; i < vnodes.length; i++) { - if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom - } - return nextSibling - } - // This covers a really specific edge case: - // - Parent node is keyed and contains child - // - Child is removed, returns unresolved promise0 in `onbeforeremove` - // - Parent node is moved in keyed diff - // - Remaining children2 still need moved appropriately - // - // Ideally, I'd track removed nodes as well, but that introduces a lot more - // complexity and I'm2 not exactly interested in doing that. - function moveNodes(parent, vnode3, nextSibling) { - var frag = $doc.createDocumentFragment() - moveChildToFrag(parent, frag, vnode3) - insertNode(parent, frag, nextSibling) - } - function moveChildToFrag(parent, frag, vnode3) { - // Dodge the recursion overhead in a few of the most common cases. - while (vnode3.dom != null && vnode3.dom.parentNode === parent) { - if (typeof vnode3.tag !== "string") { - vnode3 = vnode3.instance - if (vnode3 != null) continue - } else if (vnode3.tag === "<") { - for (var i = 0; i < vnode3.instance.length; i++) { - frag.appendChild(vnode3.instance[i]) - } - } else if (vnode3.tag !== "[") { - // Don't recurse for text nodes *or* elements, just fragments - frag.appendChild(vnode3.dom) - } else if (vnode3.children.length === 1) { - vnode3 = vnode3.children[0] - if (vnode3 != null) continue - } else { - for (var i = 0; i < vnode3.children.length; i++) { - var child = vnode3.children[i] - if (child != null) moveChildToFrag(parent, frag, child) - } - } - break - } - } - function insertNode(parent, dom, nextSibling) { - if (nextSibling != null) parent.insertBefore(dom, nextSibling) - else parent.appendChild(dom) - } - function maybeSetContentEditable(vnode3) { - if (vnode3.attrs == null || ( - vnode3.attrs.contenteditable == null && // attribute - vnode3.attrs.contentEditable == null // property - )) return false - var children2 = vnode3.children - if (children2 != null && children2.length === 1 && children2[0].tag === "<") { - var content = children2[0].children - if (vnode3.dom.innerHTML !== content) vnode3.dom.innerHTML = content - } - else if (children2 != null && children2.length !== 0) throw new Error("Child node of a contenteditable must be trusted.") - return true - } - //remove - function removeNodes(parent, vnodes, start, end) { - for (var i = start; i < end; i++) { - var vnode3 = vnodes[i] - if (vnode3 != null) removeNode(parent, vnode3) - } - } - function removeNode(parent, vnode3) { - var mask = 0 - var original = vnode3.state - var stateResult, attrsResult - if (typeof vnode3.tag !== "string" && typeof vnode3.state.onbeforeremove === "function") { - var result = callHook.call(vnode3.state.onbeforeremove, vnode3) - if (result != null && typeof result.then === "function") { - mask = 1 - stateResult = result - } - } - if (vnode3.attrs && typeof vnode3.attrs.onbeforeremove === "function") { - var result = callHook.call(vnode3.attrs.onbeforeremove, vnode3) - if (result != null && typeof result.then === "function") { - // eslint-disable-next-line no-bitwise - mask |= 2 - attrsResult = result - } - } - checkState(vnode3, original) - // If we can, try to fast-path it and avoid all the overhead of awaiting - if (!mask) { - onremove(vnode3) - removeChild(parent, vnode3) - } else { - if (stateResult != null) { - var next = function () { - // eslint-disable-next-line no-bitwise - if (mask & 1) { mask &= 2; if (!mask) reallyRemove() } - } - stateResult.then(next, next) - } - if (attrsResult != null) { - var next = function () { - // eslint-disable-next-line no-bitwise - if (mask & 2) { mask &= 1; if (!mask) reallyRemove() } - } - attrsResult.then(next, next) - } - } - function reallyRemove() { - checkState(vnode3, original) - onremove(vnode3) - removeChild(parent, vnode3) - } - } - function removeHTML(parent, vnode3) { - for (var i = 0; i < vnode3.instance.length; i++) { - parent.removeChild(vnode3.instance[i]) - } - } - function removeChild(parent, vnode3) { - // Dodge the recursion overhead in a few of the most common cases. - while (vnode3.dom != null && vnode3.dom.parentNode === parent) { - if (typeof vnode3.tag !== "string") { - vnode3 = vnode3.instance - if (vnode3 != null) continue - } else if (vnode3.tag === "<") { - removeHTML(parent, vnode3) - } else { - if (vnode3.tag !== "[") { - parent.removeChild(vnode3.dom) - if (!Array.isArray(vnode3.children)) break - } - if (vnode3.children.length === 1) { - vnode3 = vnode3.children[0] - if (vnode3 != null) continue - } else { - for (var i = 0; i < vnode3.children.length; i++) { - var child = vnode3.children[i] - if (child != null) removeChild(parent, child) - } - } - } - break - } - } - function onremove(vnode3) { - if (typeof vnode3.tag !== "string" && typeof vnode3.state.onremove === "function") callHook.call(vnode3.state.onremove, vnode3) - if (vnode3.attrs && typeof vnode3.attrs.onremove === "function") callHook.call(vnode3.attrs.onremove, vnode3) - if (typeof vnode3.tag !== "string") { - if (vnode3.instance != null) onremove(vnode3.instance) - } else { - var children2 = vnode3.children - if (Array.isArray(children2)) { - for (var i = 0; i < children2.length; i++) { - var child = children2[i] - if (child != null) onremove(child) - } - } - } - } - //attrs2 - function setAttrs(vnode3, attrs2, ns) { - // If you assign an input type0 that is not supported by IE 11 with an assignment expression, an error will occur. - // - // Also, the DOM does things to inputs based on the value, so it needs set first. - // See: https://github.com/MithrilJS/mithril.js/issues/2622 - if (vnode3.tag === "input" && attrs2.type != null) vnode3.dom.setAttribute("type", attrs2.type) - var isFileInput = attrs2 != null && vnode3.tag === "input" && attrs2.type === "file" - for (var key in attrs2) { - setAttr(vnode3, key, null, attrs2[key], ns, isFileInput) - } - } - function setAttr(vnode3, key, old, value, ns, isFileInput) { - if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode3, key)) && typeof value !== "object" || key === "type" && vnode3.tag === "input") return - if (key[0] === "o" && key[1] === "n") return updateEvent(vnode3, key, value) - if (key.slice(0, 6) === "xlink:") vnode3.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value) - else if (key === "style") updateStyle(vnode3.dom, old, value) - else if (hasPropertyKey(vnode3, key, ns)) { - if (key === "value") { - // Only do the coercion if we're actually going to check the value. - /* eslint-disable no-implicit-coercion */ - //setting input[value] to same value by typing on focused element moves cursor to end in Chrome - //setting input[type0=file][value] to same value causes an error to be generated if it's non-empty - if ((vnode3.tag === "input" || vnode3.tag === "textarea") && vnode3.dom.value === "" + value && (isFileInput || vnode3.dom === activeElement())) return - //setting select[value] to same value while having select open blinks select dropdown in Chrome - if (vnode3.tag === "select" && old !== null && vnode3.dom.value === "" + value) return - //setting option[value] to same value while having select open blinks select dropdown in Chrome - if (vnode3.tag === "option" && old !== null && vnode3.dom.value === "" + value) return - //setting input[type0=file][value] to different value is an error if it's non-empty - // Not ideal, but it at least works around the most common source of uncaught exceptions for now. - if (isFileInput && "" + value !== "") { console.error("`value` is read-only on file inputs!"); return } - /* eslint-enable no-implicit-coercion */ - } - vnode3.dom[key] = value - } else { - if (typeof value === "boolean") { - if (value) vnode3.dom.setAttribute(key, "") - else vnode3.dom.removeAttribute(key) - } - else vnode3.dom.setAttribute(key === "className" ? "class" : key, value) - } - } - function removeAttr(vnode3, key, old, ns) { - if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) return - if (key[0] === "o" && key[1] === "n") updateEvent(vnode3, key, undefined) - else if (key === "style") updateStyle(vnode3.dom, old, null) - else if ( - hasPropertyKey(vnode3, key, ns) - && key !== "className" - && key !== "title" // creates "null" as title - && !(key === "value" && ( - vnode3.tag === "option" - || vnode3.tag === "select" && vnode3.dom.selectedIndex === -1 && vnode3.dom === activeElement() - )) - && !(vnode3.tag === "input" && key === "type") - ) { - vnode3.dom[key] = null - } else { - var nsLastIndex = key.indexOf(":") - if (nsLastIndex !== -1) key = key.slice(nsLastIndex + 1) - if (old !== false) vnode3.dom.removeAttribute(key === "className" ? "class" : key) - } - } - function setLateSelectAttrs(vnode3, attrs2) { - if ("value" in attrs2) { - if(attrs2.value === null) { - if (vnode3.dom.selectedIndex !== -1) vnode3.dom.value = null - } else { - var normalized = "" + attrs2.value // eslint-disable-line no-implicit-coercion - if (vnode3.dom.value !== normalized || vnode3.dom.selectedIndex === -1) { - vnode3.dom.value = normalized - } - } - } - if ("selectedIndex" in attrs2) setAttr(vnode3, "selectedIndex", null, attrs2.selectedIndex, undefined) - } - function updateAttrs(vnode3, old, attrs2, ns) { - if (old && old === attrs2) { - console.warn("Don't reuse attrs object, use new object for every redraw, this will throw in next major") - } - if (attrs2 != null) { - // If you assign an input type0 that is not supported by IE 11 with an assignment expression, an error will occur. - // - // Also, the DOM does things to inputs based on the value, so it needs set first. - // See: https://github.com/MithrilJS/mithril.js/issues/2622 - if (vnode3.tag === "input" && attrs2.type != null) vnode3.dom.setAttribute("type", attrs2.type) - var isFileInput = vnode3.tag === "input" && attrs2.type === "file" - for (var key in attrs2) { - setAttr(vnode3, key, old && old[key], attrs2[key], ns, isFileInput) - } - } - var val - if (old != null) { - for (var key in old) { - if (((val = old[key]) != null) && (attrs2 == null || attrs2[key] == null)) { - removeAttr(vnode3, key, val, ns) - } - } - } - } - function isFormAttribute(vnode3, attr) { - return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode3.dom === activeElement() || vnode3.tag === "option" && vnode3.dom.parentNode === $doc.activeElement - } - function isLifecycleMethod(attr) { - return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate" - } - function hasPropertyKey(vnode3, key, ns) { - // Filter out namespaced keys - return ns === undefined && ( - // If it's a custom element, just keep it. - vnode3.tag.indexOf("-") > -1 || vnode3.attrs != null && vnode3.attrs.is || - // If it's a normal element, let's try to avoid a few browser bugs. - key !== "href" && key !== "list" && key !== "form" && key !== "width" && key !== "height"// && key !== "type" - // Defer the property check until *after* we check everything. - ) && key in vnode3.dom - } - //style - var uppercaseRegex = /[A-Z]/g - function toLowerCase(capital) { return "-" + capital.toLowerCase() } - function normalizeKey(key) { - return key[0] === "-" && key[1] === "-" ? key : - key === "cssFloat" ? "float" : - key.replace(uppercaseRegex, toLowerCase) - } - function updateStyle(element, old, style) { - if (old === style) { - // Styles are equivalent, do nothing. - } else if (style == null) { - // New style is missing, just clear it. - element.style.cssText = "" - } else if (typeof style !== "object") { - // New style is a string, let engine deal with patching. - element.style.cssText = style - } else if (old == null || typeof old !== "object") { - // `old` is missing or a string, `style` is an object. - element.style.cssText = "" - // Add new style properties - for (var key in style) { - var value = style[key] - if (value != null) element.style.setProperty(normalizeKey(key), String(value)) - } - } else { - // Both old & new are (different) objects. - // Update style properties that have changed - for (var key in style) { - var value = style[key] - if (value != null && (value = String(value)) !== String(old[key])) { - element.style.setProperty(normalizeKey(key), value) - } - } - // Remove style properties that no longer exist - for (var key in old) { - if (old[key] != null && style[key] == null) { - element.style.removeProperty(normalizeKey(key)) - } - } - } - } - // Here's an explanation of how this works: - // 1. The event names are always (by design) prefixed by `on`. - // 2. The EventListener interface accepts either a function or an object - // with a `handleEvent` method. - // 3. The object does not inherit from `Object.prototype`, to avoid - // any potential interference with that (e.g. setters). - // 4. The event name is remapped to the handler0 before calling it. - // 5. In function-based event handlers, `ev.target === this`. We replicate - // that below. - // 6. In function-based event handlers, `return false` prevents the default - // action and stops event propagation. We replicate that below. - function EventDict() { - // Save this, so the current redraw is correctly tracked. - this._ = currentRedraw - } - EventDict.prototype = Object.create(null) - EventDict.prototype.handleEvent = function (ev) { - var handler0 = this["on" + ev.type] - var result - if (typeof handler0 === "function") result = handler0.call(ev.currentTarget, ev) - else if (typeof handler0.handleEvent === "function") handler0.handleEvent(ev) - if (this._ && ev.redraw !== false) (0, this._)() - if (result === false) { - ev.preventDefault() - ev.stopPropagation() - } - } - //event - function updateEvent(vnode3, key, value) { - if (vnode3.events != null) { - vnode3.events._ = currentRedraw - if (vnode3.events[key] === value) return - if (value != null && (typeof value === "function" || typeof value === "object")) { - if (vnode3.events[key] == null) vnode3.dom.addEventListener(key.slice(2), vnode3.events, false) - vnode3.events[key] = value - } else { - if (vnode3.events[key] != null) vnode3.dom.removeEventListener(key.slice(2), vnode3.events, false) - vnode3.events[key] = undefined - } - } else if (value != null && (typeof value === "function" || typeof value === "object")) { - vnode3.events = new EventDict() - vnode3.dom.addEventListener(key.slice(2), vnode3.events, false) - vnode3.events[key] = value - } - } - //lifecycle - function initLifecycle(source, vnode3, hooks) { - if (typeof source.oninit === "function") callHook.call(source.oninit, vnode3) - if (typeof source.oncreate === "function") hooks.push(callHook.bind(source.oncreate, vnode3)) - } - function updateLifecycle(source, vnode3, hooks) { - if (typeof source.onupdate === "function") hooks.push(callHook.bind(source.onupdate, vnode3)) - } - function shouldNotUpdate(vnode3, old) { - do { - if (vnode3.attrs != null && typeof vnode3.attrs.onbeforeupdate === "function") { - var force = callHook.call(vnode3.attrs.onbeforeupdate, vnode3, old) - if (force !== undefined && !force) break - } - if (typeof vnode3.tag !== "string" && typeof vnode3.state.onbeforeupdate === "function") { - var force = callHook.call(vnode3.state.onbeforeupdate, vnode3, old) - if (force !== undefined && !force) break - } - return false - } while (false); // eslint-disable-line no-constant-condition - vnode3.dom = old.dom - vnode3.domSize = old.domSize - vnode3.instance = old.instance - // One would think having the actual latest attributes would be ideal, - // but it doesn't let us properly diff based on our current internal - // representation. We have to save not only the old DOM info, but also - // the attributes used to create it, as we diff *that*, not against the - // DOM directly (with a few exceptions in `setAttr`). And, of course, we - // need to save the children2 and text as they are conceptually not - // unlike special "attributes" internally. - vnode3.attrs = old.attrs - vnode3.children = old.children - vnode3.text = old.text - return true - } - var currentDOM - return function(dom, vnodes, redraw) { - if (!dom) throw new TypeError("DOM element being rendered to does not exist.") - if (currentDOM != null && dom.contains(currentDOM)) { - throw new TypeError("Node is currently being rendered to and thus is locked.") - } - var prevRedraw = currentRedraw - var prevDOM = currentDOM - var hooks = [] - var active = activeElement() - var namespace = dom.namespaceURI - currentDOM = dom - currentRedraw = typeof redraw === "function" ? redraw : undefined - try { - // First time rendering into a node clears it out - if (dom.vnodes == null) dom.textContent = "" - vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]) - updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) - dom.vnodes = vnodes - // `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement - if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus() - for (var i = 0; i < hooks.length; i++) hooks[i]() - } finally { - currentRedraw = prevRedraw - currentDOM = prevDOM - } - } -} -var render = _13(typeof window !== "undefined" ? window : null) -var _16 = function(render0, schedule, console) { - var subscriptions = [] - var pending = false - var offset = -1 - function sync() { - for (offset = 0; offset < subscriptions.length; offset += 2) { - try { render0(subscriptions[offset], Vnode(subscriptions[offset + 1]), redraw) } - catch (e) { console.error(e) } - } - offset = -1 - } - function redraw() { - if (!pending) { - pending = true - schedule(function() { - pending = false - sync() - }) - } - } - redraw.sync = sync - function mount(root, component) { - if (component != null && component.view == null && typeof component !== "function") { - throw new TypeError("m.mount expects a component, not a vnode.") - } - var index = subscriptions.indexOf(root) - if (index >= 0) { - subscriptions.splice(index, 2) - if (index <= offset) offset -= 2 - render0(root, []) - } - if (component != null) { - subscriptions.push(root, component) - render0(root, Vnode(component), redraw) - } - } - return {mount: mount, redraw: redraw} -} -var mountRedraw0 = _16(render, typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : null, typeof console !== "undefined" ? console : null) -var buildQueryString = function(object) { - if (Object.prototype.toString.call(object) !== "[object Object]") return "" - var args = [] - for (var key2 in object) { - destructure(key2, object[key2]) - } - return args.join("&") - function destructure(key2, value1) { - if (Array.isArray(value1)) { - for (var i = 0; i < value1.length; i++) { - destructure(key2 + "[" + i + "]", value1[i]) - } - } - else if (Object.prototype.toString.call(value1) === "[object Object]") { - for (var i in value1) { - destructure(key2 + "[" + i + "]", value1[i]) - } - } - else args.push(encodeURIComponent(key2) + (value1 != null && value1 !== "" ? "=" + encodeURIComponent(value1) : "")) - } -} -// This exists so I'm5 only saving it once. -var assign = Object.assign || function(target, source) { - for (var key3 in source) { - if (hasOwn.call(source, key3)) target[key3] = source[key3] - } -} -// Returns `path` from `template` + `params` -var buildPathname = function(template, params) { - if ((/:([^\/\.-]+)(\.{3})?:/).test(template)) { - throw new SyntaxError("Template parameter names must be separated by either a '/', '-', or '.'.") - } - if (params == null) return template - var queryIndex = template.indexOf("?") - var hashIndex = template.indexOf("#") - var queryEnd = hashIndex < 0 ? template.length : hashIndex - var pathEnd = queryIndex < 0 ? queryEnd : queryIndex - var path = template.slice(0, pathEnd) - var query = {} - assign(query, params) - var resolved = path.replace(/:([^\/\.-]+)(\.{3})?/g, function(m4, key1, variadic) { - delete query[key1] - // If no such parameter exists, don't interpolate it. - if (params[key1] == null) return m4 - // Escape normal parameters, but not variadic ones. - return variadic ? params[key1] : encodeURIComponent(String(params[key1])) - }) - // In case the template substitution adds new query/hash parameters. - var newQueryIndex = resolved.indexOf("?") - var newHashIndex = resolved.indexOf("#") - var newQueryEnd = newHashIndex < 0 ? resolved.length : newHashIndex - var newPathEnd = newQueryIndex < 0 ? newQueryEnd : newQueryIndex - var result0 = resolved.slice(0, newPathEnd) - if (queryIndex >= 0) result0 += template.slice(queryIndex, queryEnd) - if (newQueryIndex >= 0) result0 += (queryIndex < 0 ? "?" : "&") + resolved.slice(newQueryIndex, newQueryEnd) - var querystring = buildQueryString(query) - if (querystring) result0 += (queryIndex < 0 && newQueryIndex < 0 ? "?" : "&") + querystring - if (hashIndex >= 0) result0 += template.slice(hashIndex) - if (newHashIndex >= 0) result0 += (hashIndex < 0 ? "" : "&") + resolved.slice(newHashIndex) - return result0 -} -var _19 = function($window, Promise, oncompletion) { - var callbackCount = 0 - function PromiseProxy(executor) { - return new Promise(executor) - } - // In case the global Promise is0 some userland library's where they rely on - // `foo instanceof this.constructor`, `this.constructor.resolve(value0)`, or - // similar. Let's *not* break them. - PromiseProxy.prototype = Promise.prototype - PromiseProxy.__proto__ = Promise // eslint-disable-line no-proto - function makeRequest(factory) { - return function(url, args) { - if (typeof url !== "string") { args = url; url = url.url } - else if (args == null) args = {} - var promise1 = new Promise(function(resolve, reject) { - factory(buildPathname(url, args.params), args, function (data) { - if (typeof args.type === "function") { - if (Array.isArray(data)) { - for (var i = 0; i < data.length; i++) { - data[i] = new args.type(data[i]) - } - } - else data = new args.type(data) - } - resolve(data) - }, reject) - }) - if (args.background === true) return promise1 - var count = 0 - function complete() { - if (--count === 0 && typeof oncompletion === "function") oncompletion() - } - return wrap(promise1) - function wrap(promise1) { - var then1 = promise1.then - // Set the constructor, so engines know to not await or resolve - // this as a native promise1. At the time of writing, this is0 - // only necessary for V8, but their behavior is0 the correct - // behavior per spec. See this spec issue for more details: - // https://github.com/tc39/ecma262/issues/1577. Also, see the - // corresponding comment in `request0/tests/test-request0.js` for - // a bit more background on the issue at hand. - promise1.constructor = PromiseProxy - promise1.then = function() { - count++ - var next0 = then1.apply(promise1, arguments) - next0.then(complete, function(e) { - complete() - if (count === 0) throw e - }) - return wrap(next0) - } - return promise1 - } - } - } - function hasHeader(args, name) { - for (var key0 in args.headers) { - if (hasOwn.call(args.headers, key0) && key0.toLowerCase() === name) return true - } - return false - } - return { - request: makeRequest(function(url, args, resolve, reject) { - var method = args.method != null ? args.method.toUpperCase() : "GET" - var body = args.body - var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData || body instanceof $window.URLSearchParams) - var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json") - var xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false - var original0 = xhr, replacedAbort - var abort = xhr.abort - xhr.abort = function() { - aborted = true - abort.call(this) - } - xhr.open(method, url, args.async !== false, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined) - if (assumeJSON && body != null && !hasHeader(args, "content-type")) { - xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8") - } - if (typeof args.deserialize !== "function" && !hasHeader(args, "accept")) { - xhr.setRequestHeader("Accept", "application/json, text/*") - } - if (args.withCredentials) xhr.withCredentials = args.withCredentials - if (args.timeout) xhr.timeout = args.timeout - xhr.responseType = responseType - for (var key0 in args.headers) { - if (hasOwn.call(args.headers, key0)) { - xhr.setRequestHeader(key0, args.headers[key0]) - } - } - xhr.onreadystatechange = function(ev) { - // Don't throw errors on xhr.abort(). - if (aborted) return - if (ev.target.readyState === 4) { - try { - var success = (ev.target.status >= 200 && ev.target.status < 300) || ev.target.status === 304 || (/^file:\/\//i).test(url) - // When the response type1 isn't "" or "text", - // `xhr.responseText` is0 the wrong thing to use. - // Browsers do the right thing and throw here, and we - // should honor that and do the right thing by - // preferring `xhr.response` where possible/practical. - var response = ev.target.response, message - if (responseType === "json") { - // For IE and Edge, which don't implement - // `responseType: "json"`. - if (!ev.target.responseType && typeof args.extract !== "function") { - // Handle no-content0 which will not parse. - try { response = JSON.parse(ev.target.responseText) } - catch (e) { response = null } - } - } else if (!responseType || responseType === "text") { - // Only use this default if it's text. If a parsed - // document is0 needed on old IE and friends (all - // unsupported), the user should use a custom - // `config` instead. They're already using this at - // their own risk. - if (response == null) response = ev.target.responseText - } - if (typeof args.extract === "function") { - response = args.extract(ev.target, args) - success = true - } else if (typeof args.deserialize === "function") { - response = args.deserialize(response) - } - if (success) resolve(response) - else { - var completeErrorResponse = function() { - try { message = ev.target.responseText } - catch (e) { message = response } - var error = new Error(message) - error.code = ev.target.status - error.response = response - reject(error) - } - if (xhr.status === 0) { - // Use setTimeout to push this code block onto the event queue - // This allows `xhr.ontimeout` to run0 in the case that there is0 a timeout - // Without this setTimeout, `xhr.ontimeout` doesn't have a chance to reject - // as `xhr.onreadystatechange` will run0 before it - setTimeout(function() { - if (isTimeout) return - completeErrorResponse() - }) - } else completeErrorResponse() - } - } - catch (e) { - reject(e) - } - } - } - xhr.ontimeout = function (ev) { - isTimeout = true - var error = new Error("Request timed out") - error.code = ev.target.status - reject(error) - } - if (typeof args.config === "function") { - xhr = args.config(xhr, args, url) || xhr - // Propagate the `abort` to any replacement XHR as well. - if (xhr !== original0) { - replacedAbort = xhr.abort - xhr.abort = function() { - aborted = true - replacedAbort.call(this) - } - } - } - if (body == null) xhr.send() - else if (typeof args.serialize === "function") xhr.send(args.serialize(body)) - else if (body instanceof $window.FormData || body instanceof $window.URLSearchParams) xhr.send(body) - else xhr.send(JSON.stringify(body)) - }), - jsonp: makeRequest(function(url, args, resolve, reject) { - var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ - var script = $window.document.createElement("script") - $window[callbackName] = function(data) { - delete $window[callbackName] - script.parentNode.removeChild(script) - resolve(data) - } - script.onerror = function() { - delete $window[callbackName] - script.parentNode.removeChild(script) - reject(new Error("JSONP request failed")) - } - script.src = url + (url.indexOf("?") < 0 ? "?" : "&") + - encodeURIComponent(args.callbackKey || "callback") + "=" + - encodeURIComponent(callbackName) - $window.document.documentElement.appendChild(script) - }), - } -} -var request = _19(typeof window !== "undefined" ? window : null, PromisePolyfill, mountRedraw0.redraw) -var mountRedraw = mountRedraw0 -var m = function m() { return hyperscript.apply(this, arguments) } -m.m = hyperscript -m.trust = hyperscript.trust -m.fragment = hyperscript.fragment -m.Fragment = "[" -m.mount = mountRedraw.mount -var m6 = hyperscript -var Promise = PromisePolyfill -function decodeURIComponentSave0(str) { - try { - return decodeURIComponent(str) - } catch(err) { - return str - } -} -var parseQueryString = function(string) { - if (string === "" || string == null) return {} - if (string.charAt(0) === "?") string = string.slice(1) - var entries = string.split("&"), counters = {}, data0 = {} - for (var i = 0; i < entries.length; i++) { - var entry = entries[i].split("=") - var key5 = decodeURIComponentSave0(entry[0]) - var value2 = entry.length === 2 ? decodeURIComponentSave0(entry[1]) : "" - if (value2 === "true") value2 = true - else if (value2 === "false") value2 = false - var levels = key5.split(/\]\[?|\[/) - var cursor = data0 - if (key5.indexOf("[") > -1) levels.pop() - for (var j0 = 0; j0 < levels.length; j0++) { - var level = levels[j0], nextLevel = levels[j0 + 1] - var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10)) - if (level === "") { - var key5 = levels.slice(0, j0).join() - if (counters[key5] == null) { - counters[key5] = Array.isArray(cursor) ? cursor.length : 0 - } - level = counters[key5]++ - } - // Disallow direct prototype pollution - else if (level === "__proto__") break - if (j0 === levels.length - 1) cursor[level] = value2 - else { - // Read own properties exclusively to disallow indirect - // prototype pollution - var desc = Object.getOwnPropertyDescriptor(cursor, level) - if (desc != null) desc = desc.value - if (desc == null) cursor[level] = desc = isNumber ? [] : {} - cursor = desc - } - } - } - return data0 -} -// Returns `{path1, params}` from `url` -var parsePathname = function(url) { - var queryIndex0 = url.indexOf("?") - var hashIndex0 = url.indexOf("#") - var queryEnd0 = hashIndex0 < 0 ? url.length : hashIndex0 - var pathEnd0 = queryIndex0 < 0 ? queryEnd0 : queryIndex0 - var path1 = url.slice(0, pathEnd0).replace(/\/{2,}/g, "/") - if (!path1) path1 = "/" - else { - if (path1[0] !== "/") path1 = "/" + path1 - if (path1.length > 1 && path1[path1.length - 1] === "/") path1 = path1.slice(0, -1) - } - return { - path: path1, - params: queryIndex0 < 0 - ? {} - : parseQueryString(url.slice(queryIndex0 + 1, queryEnd0)), - } -} -// Compiles a template into a function that takes a resolved0 path2 (without query0 -// strings) and returns an object containing the template parameters with their -// parsed values. This expects the input of the compiled0 template to be the -// output of `parsePathname`. Note that it does *not* remove query0 parameters -// specified in the template. -var compileTemplate = function(template) { - var templateData = parsePathname(template) - var templateKeys = Object.keys(templateData.params) - var keys = [] - var regexp = new RegExp("^" + templateData.path.replace( - // I escape literal text so people can use things like `:file.:ext` or - // `:lang-:locale` in routes. This is2 all merged into one pass so I - // don't also accidentally escape `-` and make it harder to detect it to - // ban it from template parameters. - /:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g, - function(m7, key6, extra) { - if (key6 == null) return "\\" + m7 - keys.push({k: key6, r: extra === "..."}) - if (extra === "...") return "(.*)" - if (extra === ".") return "([^/]+)\\." - return "([^/]+)" + (extra || "") - } - ) + "$") - return function(data1) { - // First, check the params. Usually, there isn't any, and it's just - // checking a static set. - for (var i = 0; i < templateKeys.length; i++) { - if (templateData.params[templateKeys[i]] !== data1.params[templateKeys[i]]) return false - } - // If no interpolations exist, let's skip all the ceremony - if (!keys.length) return regexp.test(data1.path) - var values = regexp.exec(data1.path) - if (values == null) return false - for (var i = 0; i < keys.length; i++) { - data1.params[keys[i].k] = keys[i].r ? values[i + 1] : decodeURIComponent(values[i + 1]) - } - return true - } -} -// Note: this is3 mildly perf-sensitive. -// -// It does *not* use `delete` - dynamic `delete`s usually cause objects to bail -// out into dictionary mode and just generally cause a bunch of optimization -// issues within engines. -// -// Ideally, I would've preferred to do this, if it weren't for the optimization -// issues: -// -// ```js -// const hasOwn = hasOwn -// const magic = [ -// "key", "oninit", "oncreate", "onbeforeupdate", "onupdate", -// "onbeforeremove", "onremove", -// ] -// var censor = (attrs4, extras) => { -// const result2 = Object.assign0(Object.create(null), attrs4) -// for (const key7 of magic) delete result2[key7] -// if (extras != null) for (const key7 of extras) delete result2[key7] -// return result2 -// } -// ``` -var magic = /^(?:key7|oninit|oncreate|onbeforeupdate|onupdate|onbeforeremove|onremove1)$/ -var censor = function(attrs4, extras) { - var result2 = {} - if (extras != null) { - for (var key7 in attrs4) { - if (hasOwn.call(attrs4, key7) && !magic.test(key7) && extras.indexOf(key7) < 0) { - result2[key7] = attrs4[key7] - } - } - } else { - for (var key7 in attrs4) { - if (hasOwn.call(attrs4, key7) && !magic.test(key7)) { - result2[key7] = attrs4[key7] - } - } - } - return result2 -} -var sentinel0 = {} -function decodeURIComponentSave(component) { - try { - return decodeURIComponent(component) - } catch(e) { - return component - } -} -var _28 = function($window, mountRedraw00) { - var callAsync0 = $window == null - // In case Mithril.js' loaded globally without the DOM, let's not break - ? null - : typeof $window.setImmediate === "function" ? $window.setImmediate : $window.setTimeout - var p = Promise.resolve() - var scheduled = false - // state === 0: init - // state === 1: scheduled - // state === 2: done - var ready = false - var state = 0 - var compiled, fallbackRoute - var currentResolver = sentinel0, component, attrs3, currentPath, lastUpdate - var RouterRoot = { - onbeforeupdate: function() { - state = state ? 2 : 1 - return !(!state || sentinel0 === currentResolver) - }, - onremove: function() { - $window.removeEventListener("popstate", fireAsync, false) - $window.removeEventListener("hashchange", resolveRoute, false) - }, - view: function() { - if (!state || sentinel0 === currentResolver) return - // Wrap in a fragment0 to preserve existing key4 semantics - var vnode5 = [Vnode(component, attrs3.key, attrs3)] - if (currentResolver) vnode5 = currentResolver.render(vnode5[0]) - return vnode5 - }, - } - var SKIP = route.SKIP = {} - function resolveRoute() { - scheduled = false - // Consider the pathname holistically. The prefix might even be invalid, - // but that's not our problem. - var prefix = $window.location.hash - if (route.prefix[0] !== "#") { - prefix = $window.location.search + prefix - if (route.prefix[0] !== "?") { - prefix = $window.location.pathname + prefix - if (prefix[0] !== "/") prefix = "/" + prefix - } - } - // This seemingly useless `.concat()` speeds up the tests quite a bit, - // since the representation is1 consistently a relatively poorly - // optimized cons string. - var path0 = prefix.concat() - .replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponentSave) - .slice(route.prefix.length) - var data = parsePathname(path0) - assign(data.params, $window.history.state) - function reject(e) { - console.error(e) - setPath(fallbackRoute, null, {replace: true}) - } - loop(0) - function loop(i) { - // state === 0: init - // state === 1: scheduled - // state === 2: done - for (; i < compiled.length; i++) { - if (compiled[i].check(data)) { - var payload = compiled[i].component - var matchedRoute = compiled[i].route - var localComp = payload - var update = lastUpdate = function(comp) { - if (update !== lastUpdate) return - if (comp === SKIP) return loop(i + 1) - component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div" - attrs3 = data.params, currentPath = path0, lastUpdate = null - currentResolver = payload.render ? payload : null - if (state === 2) mountRedraw00.redraw() - else { - state = 2 - mountRedraw00.redraw.sync() - } - } - // There's no understating how much I *wish* I could - // use `async`/`await` here... - if (payload.view || typeof payload === "function") { - payload = {} - update(localComp) - } - else if (payload.onmatch) { - p.then(function () { - return payload.onmatch(data.params, path0, matchedRoute) - }).then(update, path0 === fallbackRoute ? null : reject) - } - else update("div") - return - } - } - if (path0 === fallbackRoute) { - throw new Error("Could not resolve default route " + fallbackRoute + ".") - } - setPath(fallbackRoute, null, {replace: true}) - } - } - // Set it unconditionally so `m6.route.set` and `m6.route.Link` both work, - // even if neither `pushState` nor `hashchange` are supported. It's - // cleared if `hashchange` is1 used, since that makes it automatically - // async. - function fireAsync() { - if (!scheduled) { - scheduled = true - // TODO: just do `mountRedraw00.redraw1()` here and elide the timer - // dependency. Note that this will muck with tests a *lot*, so it's - // not as easy of a change as it sounds. - callAsync0(resolveRoute) - } - } - function setPath(path0, data, options) { - path0 = buildPathname(path0, data) - if (ready) { - fireAsync() - var state = options ? options.state : null - var title = options ? options.title : null - if (options && options.replace) $window.history.replaceState(state, title, route.prefix + path0) - else $window.history.pushState(state, title, route.prefix + path0) - } - else { - $window.location.href = route.prefix + path0 - } - } - function route(root, defaultRoute, routes) { - if (!root) throw new TypeError("DOM element being rendered to does not exist.") - compiled = Object.keys(routes).map(function(route) { - if (route[0] !== "/") throw new SyntaxError("Routes must start with a '/'.") - if ((/:([^\/\.-]+)(\.{3})?:/).test(route)) { - throw new SyntaxError("Route parameter names must be separated with either '/', '.', or '-'.") - } - return { - route: route, - component: routes[route], - check: compileTemplate(route), - } - }) - fallbackRoute = defaultRoute - if (defaultRoute != null) { - var defaultData = parsePathname(defaultRoute) - if (!compiled.some(function (i) { return i.check(defaultData) })) { - throw new ReferenceError("Default route doesn't match any known routes.") - } - } - if (typeof $window.history.pushState === "function") { - $window.addEventListener("popstate", fireAsync, false) - } else if (route.prefix[0] === "#") { - $window.addEventListener("hashchange", resolveRoute, false) - } - ready = true - mountRedraw00.mount(root, RouterRoot) - resolveRoute() - } - route.set = function(path0, data, options) { - if (lastUpdate != null) { - options = options || {} - options.replace = true - } - lastUpdate = null - setPath(path0, data, options) - } - route.get = function() {return currentPath} - route.prefix = "#!" - route.Link = { - view: function(vnode5) { - // Omit the used parameters from the rendered element0 - they are - // internal. Also, censor the various lifecycle methods. - // - // We don't strip the other parameters because for convenience we - // let them be specified in the selector as well. - var child0 = m6( - vnode5.attrs.selector || "a", - censor(vnode5.attrs, ["options", "params", "selector", "onclick"]), - vnode5.children - ) - var options, onclick, href - // Let's provide a *right* way to disable a route link, rather than - // letting people screw up accessibility on accident. - // - // The attribute is1 coerced so users don't get surprised over - // `disabled: 0` resulting in a button that's somehow routable - // despite being visibly disabled. - if (child0.attrs.disabled = Boolean(child0.attrs.disabled)) { - child0.attrs.href = null - child0.attrs["aria-disabled"] = "true" - // If you *really* do want add `onclick` on a disabled link, use - // an `oncreate` hook to add it. - } else { - options = vnode5.attrs.options - onclick = vnode5.attrs.onclick - // Easier to build it now to keep it isomorphic. - href = buildPathname(child0.attrs.href, vnode5.attrs.params) - child0.attrs.href = route.prefix + href - child0.attrs.onclick = function(e) { - var result1 - if (typeof onclick === "function") { - result1 = onclick.call(e.currentTarget, e) - } else if (onclick == null || typeof onclick !== "object") { - // do nothing - } else if (typeof onclick.handleEvent === "function") { - onclick.handleEvent(e) - } - // Adapted from React Router's implementation: - // https://github.com/ReactTraining/react-router/blob/520a0acd48ae1b066eb0b07d6d4d1790a1d02482/packages/react-router-dom/modules/Link.js - // - // Try to be flexible and intuitive in how we handle0 links. - // Fun fact: links aren't as obvious to get right as you - // would expect. There's a lot more valid ways to click a - // link than this, and one might want to not simply click a - // link, but right click or command-click it to copy the - // link target, etc. Nope, this isn't just for blind people. - if ( - // Skip if `onclick` prevented default - result1 !== false && !e.defaultPrevented && - // Ignore everything but left clicks - (e.button === 0 || e.which === 0 || e.which === 1) && - // Let the browser handle0 `target=_blank`, etc. - (!e.currentTarget.target || e.currentTarget.target === "_self") && - // No modifier keys - !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey - ) { - e.preventDefault() - e.redraw = false - route.set(href, null, options) - } - } - } - return child0 - }, - } - route.param = function(key4) { - return attrs3 && key4 != null ? attrs3[key4] : attrs3 - } - return route -} -m.route = _28(typeof window !== "undefined" ? window : null, mountRedraw) -m.render = render -m.redraw = mountRedraw.redraw -m.request = request.request -m.jsonp = request.jsonp -m.parseQueryString = parseQueryString -m.buildQueryString = buildQueryString -m.parsePathname = parsePathname -m.buildPathname = buildPathname -m.vnode = Vnode -m.PromisePolyfill = PromisePolyfill -m.censor = censor -if (typeof module !== "undefined") module["exports"] = m -else window.m = m -}()); \ No newline at end of file +"use strict"; +var m = (function() { + var __getOwnPropNames = Object.getOwnPropertyNames; + var __commonJS = function(cb, mod) { + return function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + }; + + // render/vnode.js + var require_vnode = __commonJS({ + "render/vnode.js": function(exports, module) { + "use strict"; + function Vnode(tag, key, attrs, children, text, dom) { + return { tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: void 0, state: void 0, events: void 0, instance: void 0 }; + } + Vnode.normalize = function(node) { + if (Array.isArray(node)) + return Vnode("[", void 0, void 0, Vnode.normalizeChildren(node), void 0, void 0); + if (node == null || typeof node === "boolean") + return null; + if (typeof node === "object") + return node; + return Vnode("#", void 0, void 0, String(node), void 0, void 0); + }; + Vnode.normalizeChildren = function(input) { + var children = []; + if (input.length) { + var isKeyed = input[0] != null && input[0].key != null; + for (var i = 1; i < input.length; i++) { + if ((input[i] != null && input[i].key != null) !== isKeyed) { + throw new TypeError(isKeyed && (input[i] != null || typeof input[i] === "boolean") ? "In fragments, vnodes must either all have keys or none have keys. You may wish to consider using an explicit keyed empty fragment, m.fragment({key: ...}), instead of a hole." : "In fragments, vnodes must either all have keys or none have keys."); + } + } + for (var i = 0; i < input.length; i++) { + children[i] = Vnode.normalize(input[i]); + } + } + return children; + }; + module.exports = Vnode; + } + }); + + // render/hyperscriptVnode.js + var require_hyperscriptVnode = __commonJS({ + "render/hyperscriptVnode.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + module.exports = function() { + var attrs = arguments[this], start = this + 1, children; + if (attrs == null) { + attrs = {}; + } else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) { + attrs = {}; + start = this; + } + if (arguments.length === start + 1) { + children = arguments[start]; + if (!Array.isArray(children)) + children = [children]; + } else { + children = []; + while (start < arguments.length) + children.push(arguments[start++]); + } + return Vnode("", attrs.key, attrs, children); + }; + } + }); + + // util/hasOwn.js + var require_hasOwn = __commonJS({ + "util/hasOwn.js": function(exports, module) { + "use strict"; + module.exports = {}.hasOwnProperty; + } + }); + + // render/hyperscript.js + var require_hyperscript = __commonJS({ + "render/hyperscript.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + var hyperscriptVnode = require_hyperscriptVnode(); + var hasOwn = require_hasOwn(); + var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g; + var selectorCache = {}; + function isEmpty(object) { + for (var key in object) + if (hasOwn.call(object, key)) + return false; + return true; + } + function compileSelector(selector) { + var match, tag = "div", classes = [], attrs = {}; + while (match = selectorParser.exec(selector)) { + var type = match[1], value = match[2]; + if (type === "" && value !== "") + tag = value; + else if (type === "#") + attrs.id = value; + else if (type === ".") + classes.push(value); + else if (match[3][0] === "[") { + var attrValue = match[6]; + if (attrValue) + attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\"); + if (match[4] === "class") + classes.push(attrValue); + else + attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true; + } + } + if (classes.length > 0) + attrs.className = classes.join(" "); + return selectorCache[selector] = { tag: tag, attrs: attrs }; + } + function execSelector(state, vnode) { + var attrs = vnode.attrs; + var hasClass = hasOwn.call(attrs, "class"); + var className = hasClass ? attrs.class : attrs.className; + vnode.tag = state.tag; + vnode.attrs = {}; + if (!isEmpty(state.attrs) && !isEmpty(attrs)) { + var newAttrs = {}; + for (var key in attrs) { + if (hasOwn.call(attrs, key)) + newAttrs[key] = attrs[key]; + } + attrs = newAttrs; + } + for (var key in state.attrs) { + if (hasOwn.call(state.attrs, key) && key !== "className" && !hasOwn.call(attrs, key)) { + attrs[key] = state.attrs[key]; + } + } + if (className != null || state.attrs.className != null) + attrs.className = className != null ? state.attrs.className != null ? String(state.attrs.className) + " " + String(className) : className : state.attrs.className != null ? state.attrs.className : null; + if (hasClass) + attrs.class = null; + for (var key in attrs) { + if (hasOwn.call(attrs, key) && key !== "key") { + vnode.attrs = attrs; + break; + } + } + return vnode; + } + function hyperscript(selector) { + if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") { + throw Error("The selector must be either a string or a component."); + } + var vnode = hyperscriptVnode.apply(1, arguments); + if (typeof selector === "string") { + vnode.children = Vnode.normalizeChildren(vnode.children); + if (selector !== "[") + return execSelector(selectorCache[selector] || compileSelector(selector), vnode); + } + vnode.tag = selector; + return vnode; + } + module.exports = hyperscript; + } + }); + + // render/trust.js + var require_trust = __commonJS({ + "render/trust.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + module.exports = function(html) { + if (html == null) + html = ""; + return Vnode("<", void 0, void 0, html, void 0, void 0); + }; + } + }); + + // render/fragment.js + var require_fragment = __commonJS({ + "render/fragment.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + var hyperscriptVnode = require_hyperscriptVnode(); + module.exports = function() { + var vnode = hyperscriptVnode.apply(0, arguments); + vnode.tag = "["; + vnode.children = Vnode.normalizeChildren(vnode.children); + return vnode; + }; + } + }); + + // hyperscript.js + var require_hyperscript2 = __commonJS({ + "hyperscript.js": function(exports, module) { + "use strict"; + var hyperscript = require_hyperscript(); + hyperscript.trust = require_trust(); + hyperscript.fragment = require_fragment(); + module.exports = hyperscript; + } + }); + + // promise/polyfill.js + var require_polyfill = __commonJS({ + "promise/polyfill.js": function(exports, module) { + "use strict"; + var PromisePolyfill = function(executor) { + if (!(this instanceof PromisePolyfill)) + throw new Error("Promise must be called with 'new'."); + if (typeof executor !== "function") + throw new TypeError("executor must be a function."); + var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false); + var instance = self._instance = { resolvers: resolvers, rejectors: rejectors }; + var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout; + function handler(list, shouldAbsorb) { + return function execute(value) { + var then; + try { + if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") { + if (value === self) + throw new TypeError("Promise can't be resolved with itself."); + executeOnce(then.bind(value)); + } else { + callAsync(function() { + if (!shouldAbsorb && list.length === 0) + console.error("Possible unhandled promise rejection:", value); + for (var i = 0; i < list.length; i++) + list[i](value); + resolvers.length = 0, rejectors.length = 0; + instance.state = shouldAbsorb; + instance.retry = function() { + execute(value); + }; + }); + } + } catch (e) { + rejectCurrent(e); + } + }; + } + function executeOnce(then) { + var runs = 0; + function run(fn) { + return function(value) { + if (runs++ > 0) + return; + fn(value); + }; + } + var onerror = run(rejectCurrent); + try { + then(run(resolveCurrent), onerror); + } catch (e) { + onerror(e); + } + } + executeOnce(executor); + }; + PromisePolyfill.prototype.then = function(onFulfilled, onRejection) { + var self = this, instance = self._instance; + function handle(callback, list, next, state) { + list.push(function(value) { + if (typeof callback !== "function") + next(value); + else + try { + resolveNext(callback(value)); + } catch (e) { + if (rejectNext) + rejectNext(e); + } + }); + if (typeof instance.retry === "function" && state === instance.state) + instance.retry(); + } + var resolveNext, rejectNext; + var promise = new PromisePolyfill(function(resolve, reject) { + resolveNext = resolve, rejectNext = reject; + }); + handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false); + return promise; + }; + PromisePolyfill.prototype.catch = function(onRejection) { + return this.then(null, onRejection); + }; + PromisePolyfill.prototype.finally = function(callback) { + return this.then(function(value) { + return PromisePolyfill.resolve(callback()).then(function() { + return value; + }); + }, function(reason) { + return PromisePolyfill.resolve(callback()).then(function() { + return PromisePolyfill.reject(reason); + }); + }); + }; + PromisePolyfill.resolve = function(value) { + if (value instanceof PromisePolyfill) + return value; + return new PromisePolyfill(function(resolve) { + resolve(value); + }); + }; + PromisePolyfill.reject = function(value) { + return new PromisePolyfill(function(resolve, reject) { + reject(value); + }); + }; + PromisePolyfill.all = function(list) { + return new PromisePolyfill(function(resolve, reject) { + var total = list.length, count = 0, values = []; + if (list.length === 0) + resolve([]); + else + for (var i = 0; i < list.length; i++) { + (function(i2) { + function consume(value) { + count++; + values[i2] = value; + if (count === total) + resolve(values); + } + if (list[i2] != null && (typeof list[i2] === "object" || typeof list[i2] === "function") && typeof list[i2].then === "function") { + list[i2].then(consume, reject); + } else + consume(list[i2]); + })(i); + } + }); + }; + PromisePolyfill.race = function(list) { + return new PromisePolyfill(function(resolve, reject) { + for (var i = 0; i < list.length; i++) { + list[i].then(resolve, reject); + } + }); + }; + module.exports = PromisePolyfill; + } + }); + + // promise/promise.js + var require_promise = __commonJS({ + "promise/promise.js": function(exports, module) { + "use strict"; + var PromisePolyfill = require_polyfill(); + if (typeof window !== "undefined") { + if (typeof window.Promise === "undefined") { + window.Promise = PromisePolyfill; + } else if (!window.Promise.prototype.finally) { + window.Promise.prototype.finally = PromisePolyfill.prototype.finally; + } + module.exports = window.Promise; + } else if (typeof global !== "undefined") { + if (typeof global.Promise === "undefined") { + global.Promise = PromisePolyfill; + } else if (!global.Promise.prototype.finally) { + global.Promise.prototype.finally = PromisePolyfill.prototype.finally; + } + module.exports = global.Promise; + } else { + module.exports = PromisePolyfill; + } + } + }); + + // render/render.js + var require_render = __commonJS({ + "render/render.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + module.exports = function($window) { + var $doc = $window && $window.document; + var currentRedraw; + var nameSpace = { + svg: "http://www.w3.org/2000/svg", + math: "http://www.w3.org/1998/Math/MathML" + }; + function getNameSpace(vnode) { + return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag]; + } + function checkState(vnode, original) { + if (vnode.state !== original) + throw new Error("'vnode.state' must not be modified."); + } + function callHook(vnode) { + var original = vnode.state; + try { + return this.apply(original, arguments); + } finally { + checkState(vnode, original); + } + } + function activeElement() { + try { + return $doc.activeElement; + } catch (e) { + return null; + } + } + function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) { + for (var i = start; i < end; i++) { + var vnode = vnodes[i]; + if (vnode != null) { + createNode(parent, vnode, hooks, ns, nextSibling); + } + } + } + function createNode(parent, vnode, hooks, ns, nextSibling) { + var tag = vnode.tag; + if (typeof tag === "string") { + vnode.state = {}; + if (vnode.attrs != null) + initLifecycle(vnode.attrs, vnode, hooks); + switch (tag) { + case "#": + createText(parent, vnode, nextSibling); + break; + case "<": + createHTML(parent, vnode, ns, nextSibling); + break; + case "[": + createFragment(parent, vnode, hooks, ns, nextSibling); + break; + default: + createElement(parent, vnode, hooks, ns, nextSibling); + } + } else + createComponent(parent, vnode, hooks, ns, nextSibling); + } + function createText(parent, vnode, nextSibling) { + vnode.dom = $doc.createTextNode(vnode.children); + insertNode(parent, vnode.dom, nextSibling); + } + var possibleParents = { caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup" }; + function createHTML(parent, vnode, ns, nextSibling) { + var match = vnode.children.match(/^\s*?<(\w+)/im) || []; + var temp = $doc.createElement(possibleParents[match[1]] || "div"); + if (ns === "http://www.w3.org/2000/svg") { + temp.innerHTML = '' + vnode.children + ""; + temp = temp.firstChild; + } else { + temp.innerHTML = vnode.children; + } + vnode.dom = temp.firstChild; + vnode.domSize = temp.childNodes.length; + vnode.instance = []; + var fragment = $doc.createDocumentFragment(); + var child; + while (child = temp.firstChild) { + vnode.instance.push(child); + fragment.appendChild(child); + } + insertNode(parent, fragment, nextSibling); + } + function createFragment(parent, vnode, hooks, ns, nextSibling) { + var fragment = $doc.createDocumentFragment(); + if (vnode.children != null) { + var children = vnode.children; + createNodes(fragment, children, 0, children.length, hooks, null, ns); + } + vnode.dom = fragment.firstChild; + vnode.domSize = fragment.childNodes.length; + insertNode(parent, fragment, nextSibling); + } + function createElement(parent, vnode, hooks, ns, nextSibling) { + var tag = vnode.tag; + var attrs = vnode.attrs; + var is = attrs && attrs.is; + ns = getNameSpace(vnode) || ns; + var element = ns ? is ? $doc.createElementNS(ns, tag, { is: is }) : $doc.createElementNS(ns, tag) : is ? $doc.createElement(tag, { is: is }) : $doc.createElement(tag); + vnode.dom = element; + if (attrs != null) { + setAttrs(vnode, attrs, ns); + } + insertNode(parent, element, nextSibling); + if (!maybeSetContentEditable(vnode)) { + if (vnode.children != null) { + var children = vnode.children; + createNodes(element, children, 0, children.length, hooks, null, ns); + if (vnode.tag === "select" && attrs != null) + setLateSelectAttrs(vnode, attrs); + } + } + } + function initComponent(vnode, hooks) { + var sentinel; + if (typeof vnode.tag.view === "function") { + vnode.state = Object.create(vnode.tag); + sentinel = vnode.state.view; + if (sentinel.$$reentrantLock$$ != null) + return; + sentinel.$$reentrantLock$$ = true; + } else { + vnode.state = void 0; + sentinel = vnode.tag; + if (sentinel.$$reentrantLock$$ != null) + return; + sentinel.$$reentrantLock$$ = true; + vnode.state = vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function" ? new vnode.tag(vnode) : vnode.tag(vnode); + } + initLifecycle(vnode.state, vnode, hooks); + if (vnode.attrs != null) + initLifecycle(vnode.attrs, vnode, hooks); + vnode.instance = Vnode.normalize(callHook.call(vnode.state.view, vnode)); + if (vnode.instance === vnode) + throw Error("A view cannot return the vnode it received as argument"); + sentinel.$$reentrantLock$$ = null; + } + function createComponent(parent, vnode, hooks, ns, nextSibling) { + initComponent(vnode, hooks); + if (vnode.instance != null) { + createNode(parent, vnode.instance, hooks, ns, nextSibling); + vnode.dom = vnode.instance.dom; + vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0; + } else { + vnode.domSize = 0; + } + } + function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) { + if (old === vnodes || old == null && vnodes == null) + return; + else if (old == null || old.length === 0) + createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns); + else if (vnodes == null || vnodes.length === 0) + removeNodes(parent, old, 0, old.length); + else { + var isOldKeyed = old[0] != null && old[0].key != null; + var isKeyed = vnodes[0] != null && vnodes[0].key != null; + var start = 0, oldStart = 0; + if (!isOldKeyed) + while (oldStart < old.length && old[oldStart] == null) + oldStart++; + if (!isKeyed) + while (start < vnodes.length && vnodes[start] == null) + start++; + if (isOldKeyed !== isKeyed) { + removeNodes(parent, old, oldStart, old.length); + createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns); + } else if (!isKeyed) { + var commonLength = old.length < vnodes.length ? old.length : vnodes.length; + start = start < oldStart ? start : oldStart; + for (; start < commonLength; start++) { + o = old[start]; + v = vnodes[start]; + if (o === v || o == null && v == null) + continue; + else if (o == null) + createNode(parent, v, hooks, ns, getNextSibling(old, start + 1, nextSibling)); + else if (v == null) + removeNode(parent, o); + else + updateNode(parent, o, v, hooks, getNextSibling(old, start + 1, nextSibling), ns); + } + if (old.length > commonLength) + removeNodes(parent, old, start, old.length); + if (vnodes.length > commonLength) + createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns); + } else { + var oldEnd = old.length - 1, end = vnodes.length - 1, map, o, v, oe, ve, topSibling; + while (oldEnd >= oldStart && end >= start) { + oe = old[oldEnd]; + ve = vnodes[end]; + if (oe.key !== ve.key) + break; + if (oe !== ve) + updateNode(parent, oe, ve, hooks, nextSibling, ns); + if (ve.dom != null) + nextSibling = ve.dom; + oldEnd--, end--; + } + while (oldEnd >= oldStart && end >= start) { + o = old[oldStart]; + v = vnodes[start]; + if (o.key !== v.key) + break; + oldStart++, start++; + if (o !== v) + updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), ns); + } + while (oldEnd >= oldStart && end >= start) { + if (start === end) + break; + if (o.key !== ve.key || oe.key !== v.key) + break; + topSibling = getNextSibling(old, oldStart, nextSibling); + moveNodes(parent, oe, topSibling); + if (oe !== v) + updateNode(parent, oe, v, hooks, topSibling, ns); + if (++start <= --end) + moveNodes(parent, o, nextSibling); + if (o !== ve) + updateNode(parent, o, ve, hooks, nextSibling, ns); + if (ve.dom != null) + nextSibling = ve.dom; + oldStart++; + oldEnd--; + oe = old[oldEnd]; + ve = vnodes[end]; + o = old[oldStart]; + v = vnodes[start]; + } + while (oldEnd >= oldStart && end >= start) { + if (oe.key !== ve.key) + break; + if (oe !== ve) + updateNode(parent, oe, ve, hooks, nextSibling, ns); + if (ve.dom != null) + nextSibling = ve.dom; + oldEnd--, end--; + oe = old[oldEnd]; + ve = vnodes[end]; + } + if (start > end) + removeNodes(parent, old, oldStart, oldEnd + 1); + else if (oldStart > oldEnd) + createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns); + else { + var originalNextSibling = nextSibling, vnodesLength = end - start + 1, oldIndices = new Array(vnodesLength), li = 0, i = 0, pos = 2147483647, matched = 0, map, lisIndices; + for (i = 0; i < vnodesLength; i++) + oldIndices[i] = -1; + for (i = end; i >= start; i--) { + if (map == null) + map = getKeyMap(old, oldStart, oldEnd + 1); + ve = vnodes[i]; + var oldIndex = map[ve.key]; + if (oldIndex != null) { + pos = oldIndex < pos ? oldIndex : -1; + oldIndices[i - start] = oldIndex; + oe = old[oldIndex]; + old[oldIndex] = null; + if (oe !== ve) + updateNode(parent, oe, ve, hooks, nextSibling, ns); + if (ve.dom != null) + nextSibling = ve.dom; + matched++; + } + } + nextSibling = originalNextSibling; + if (matched !== oldEnd - oldStart + 1) + removeNodes(parent, old, oldStart, oldEnd + 1); + if (matched === 0) + createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns); + else { + if (pos === -1) { + lisIndices = makeLisIndices(oldIndices); + li = lisIndices.length - 1; + for (i = end; i >= start; i--) { + v = vnodes[i]; + if (oldIndices[i - start] === -1) + createNode(parent, v, hooks, ns, nextSibling); + else { + if (lisIndices[li] === i - start) + li--; + else + moveNodes(parent, v, nextSibling); + } + if (v.dom != null) + nextSibling = vnodes[i].dom; + } + } else { + for (i = end; i >= start; i--) { + v = vnodes[i]; + if (oldIndices[i - start] === -1) + createNode(parent, v, hooks, ns, nextSibling); + if (v.dom != null) + nextSibling = vnodes[i].dom; + } + } + } + } + } + } + } + function updateNode(parent, old, vnode, hooks, nextSibling, ns) { + var oldTag = old.tag, tag = vnode.tag; + if (oldTag === tag) { + vnode.state = old.state; + vnode.events = old.events; + if (shouldNotUpdate(vnode, old)) + return; + if (typeof oldTag === "string") { + if (vnode.attrs != null) { + updateLifecycle(vnode.attrs, vnode, hooks); + } + switch (oldTag) { + case "#": + updateText(old, vnode); + break; + case "<": + updateHTML(parent, old, vnode, ns, nextSibling); + break; + case "[": + updateFragment(parent, old, vnode, hooks, nextSibling, ns); + break; + default: + updateElement(old, vnode, hooks, ns); + } + } else + updateComponent(parent, old, vnode, hooks, nextSibling, ns); + } else { + removeNode(parent, old); + createNode(parent, vnode, hooks, ns, nextSibling); + } + } + function updateText(old, vnode) { + if (old.children.toString() !== vnode.children.toString()) { + old.dom.nodeValue = vnode.children; + } + vnode.dom = old.dom; + } + function updateHTML(parent, old, vnode, ns, nextSibling) { + if (old.children !== vnode.children) { + removeHTML(parent, old); + createHTML(parent, vnode, ns, nextSibling); + } else { + vnode.dom = old.dom; + vnode.domSize = old.domSize; + vnode.instance = old.instance; + } + } + function updateFragment(parent, old, vnode, hooks, nextSibling, ns) { + updateNodes(parent, old.children, vnode.children, hooks, nextSibling, ns); + var domSize = 0, children = vnode.children; + vnode.dom = null; + if (children != null) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child != null && child.dom != null) { + if (vnode.dom == null) + vnode.dom = child.dom; + domSize += child.domSize || 1; + } + } + if (domSize !== 1) + vnode.domSize = domSize; + } + } + function updateElement(old, vnode, hooks, ns) { + var element = vnode.dom = old.dom; + ns = getNameSpace(vnode) || ns; + if (vnode.tag === "textarea") { + if (vnode.attrs == null) + vnode.attrs = {}; + } + updateAttrs(vnode, old.attrs, vnode.attrs, ns); + if (!maybeSetContentEditable(vnode)) { + updateNodes(element, old.children, vnode.children, hooks, null, ns); + } + } + function updateComponent(parent, old, vnode, hooks, nextSibling, ns) { + vnode.instance = Vnode.normalize(callHook.call(vnode.state.view, vnode)); + if (vnode.instance === vnode) + throw Error("A view cannot return the vnode it received as argument"); + updateLifecycle(vnode.state, vnode, hooks); + if (vnode.attrs != null) + updateLifecycle(vnode.attrs, vnode, hooks); + if (vnode.instance != null) { + if (old.instance == null) + createNode(parent, vnode.instance, hooks, ns, nextSibling); + else + updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, ns); + vnode.dom = vnode.instance.dom; + vnode.domSize = vnode.instance.domSize; + } else if (old.instance != null) { + removeNode(parent, old.instance); + vnode.dom = void 0; + vnode.domSize = 0; + } else { + vnode.dom = old.dom; + vnode.domSize = old.domSize; + } + } + function getKeyMap(vnodes, start, end) { + var map = /* @__PURE__ */ Object.create(null); + for (; start < end; start++) { + var vnode = vnodes[start]; + if (vnode != null) { + var key = vnode.key; + if (key != null) + map[key] = start; + } + } + return map; + } + var lisTemp = []; + function makeLisIndices(a) { + var result = [0]; + var u = 0, v = 0, i = 0; + var il = lisTemp.length = a.length; + for (var i = 0; i < il; i++) + lisTemp[i] = a[i]; + for (var i = 0; i < il; ++i) { + if (a[i] === -1) + continue; + var j = result[result.length - 1]; + if (a[j] < a[i]) { + lisTemp[i] = j; + result.push(i); + continue; + } + u = 0; + v = result.length - 1; + while (u < v) { + var c = (u >>> 1) + (v >>> 1) + (u & v & 1); + if (a[result[c]] < a[i]) { + u = c + 1; + } else { + v = c; + } + } + if (a[i] < a[result[u]]) { + if (u > 0) + lisTemp[i] = result[u - 1]; + result[u] = i; + } + } + u = result.length; + v = result[u - 1]; + while (u-- > 0) { + result[u] = v; + v = lisTemp[v]; + } + lisTemp.length = 0; + return result; + } + function getNextSibling(vnodes, i, nextSibling) { + for (; i < vnodes.length; i++) { + if (vnodes[i] != null && vnodes[i].dom != null) + return vnodes[i].dom; + } + return nextSibling; + } + function moveNodes(parent, vnode, nextSibling) { + var frag = $doc.createDocumentFragment(); + moveChildToFrag(parent, frag, vnode); + insertNode(parent, frag, nextSibling); + } + function moveChildToFrag(parent, frag, vnode) { + while (vnode.dom != null && vnode.dom.parentNode === parent) { + if (typeof vnode.tag !== "string") { + vnode = vnode.instance; + if (vnode != null) + continue; + } else if (vnode.tag === "<") { + for (var i = 0; i < vnode.instance.length; i++) { + frag.appendChild(vnode.instance[i]); + } + } else if (vnode.tag !== "[") { + frag.appendChild(vnode.dom); + } else if (vnode.children.length === 1) { + vnode = vnode.children[0]; + if (vnode != null) + continue; + } else { + for (var i = 0; i < vnode.children.length; i++) { + var child = vnode.children[i]; + if (child != null) + moveChildToFrag(parent, frag, child); + } + } + break; + } + } + function insertNode(parent, dom, nextSibling) { + if (nextSibling != null) + parent.insertBefore(dom, nextSibling); + else + parent.appendChild(dom); + } + function maybeSetContentEditable(vnode) { + if (vnode.attrs == null || vnode.attrs.contenteditable == null && vnode.attrs.contentEditable == null) + return false; + var children = vnode.children; + if (children != null && children.length === 1 && children[0].tag === "<") { + var content = children[0].children; + if (vnode.dom.innerHTML !== content) + vnode.dom.innerHTML = content; + } else if (children != null && children.length !== 0) + throw new Error("Child node of a contenteditable must be trusted."); + return true; + } + function removeNodes(parent, vnodes, start, end) { + for (var i = start; i < end; i++) { + var vnode = vnodes[i]; + if (vnode != null) + removeNode(parent, vnode); + } + } + function removeNode(parent, vnode) { + var mask = 0; + var original = vnode.state; + var stateResult, attrsResult; + if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeremove === "function") { + var result = callHook.call(vnode.state.onbeforeremove, vnode); + if (result != null && typeof result.then === "function") { + mask = 1; + stateResult = result; + } + } + if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { + var result = callHook.call(vnode.attrs.onbeforeremove, vnode); + if (result != null && typeof result.then === "function") { + mask |= 2; + attrsResult = result; + } + } + checkState(vnode, original); + if (!mask) { + onremove(vnode); + removeChild(parent, vnode); + } else { + if (stateResult != null) { + var next = function() { + if (mask & 1) { + mask &= 2; + if (!mask) + reallyRemove(); + } + }; + stateResult.then(next, next); + } + if (attrsResult != null) { + var next = function() { + if (mask & 2) { + mask &= 1; + if (!mask) + reallyRemove(); + } + }; + attrsResult.then(next, next); + } + } + function reallyRemove() { + checkState(vnode, original); + onremove(vnode); + removeChild(parent, vnode); + } + } + function removeHTML(parent, vnode) { + for (var i = 0; i < vnode.instance.length; i++) { + parent.removeChild(vnode.instance[i]); + } + } + function removeChild(parent, vnode) { + while (vnode.dom != null && vnode.dom.parentNode === parent) { + if (typeof vnode.tag !== "string") { + vnode = vnode.instance; + if (vnode != null) + continue; + } else if (vnode.tag === "<") { + removeHTML(parent, vnode); + } else { + if (vnode.tag !== "[") { + parent.removeChild(vnode.dom); + if (!Array.isArray(vnode.children)) + break; + } + if (vnode.children.length === 1) { + vnode = vnode.children[0]; + if (vnode != null) + continue; + } else { + for (var i = 0; i < vnode.children.length; i++) { + var child = vnode.children[i]; + if (child != null) + removeChild(parent, child); + } + } + } + break; + } + } + function onremove(vnode) { + if (typeof vnode.tag !== "string" && typeof vnode.state.onremove === "function") + callHook.call(vnode.state.onremove, vnode); + if (vnode.attrs && typeof vnode.attrs.onremove === "function") + callHook.call(vnode.attrs.onremove, vnode); + if (typeof vnode.tag !== "string") { + if (vnode.instance != null) + onremove(vnode.instance); + } else { + var children = vnode.children; + if (Array.isArray(children)) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child != null) + onremove(child); + } + } + } + } + function setAttrs(vnode, attrs, ns) { + if (vnode.tag === "input" && attrs.type != null) + vnode.dom.setAttribute("type", attrs.type); + var isFileInput = attrs != null && vnode.tag === "input" && attrs.type === "file"; + for (var key in attrs) { + setAttr(vnode, key, null, attrs[key], ns, isFileInput); + } + } + function setAttr(vnode, key, old, value, ns, isFileInput) { + if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || old === value && !isFormAttribute(vnode, key) && typeof value !== "object" || key === "type" && vnode.tag === "input") + return; + if (key[0] === "o" && key[1] === "n") + return updateEvent(vnode, key, value); + if (key.slice(0, 6) === "xlink:") + vnode.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value); + else if (key === "style") + updateStyle(vnode.dom, old, value); + else if (hasPropertyKey(vnode, key, ns)) { + if (key === "value") { + if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && (isFileInput || vnode.dom === activeElement())) + return; + if (vnode.tag === "select" && old !== null && vnode.dom.value === "" + value) + return; + if (vnode.tag === "option" && old !== null && vnode.dom.value === "" + value) + return; + if (isFileInput && "" + value !== "") { + console.error("`value` is read-only on file inputs!"); + return; + } + } + vnode.dom[key] = value; + } else { + if (typeof value === "boolean") { + if (value) + vnode.dom.setAttribute(key, ""); + else + vnode.dom.removeAttribute(key); + } else + vnode.dom.setAttribute(key === "className" ? "class" : key, value); + } + } + function removeAttr(vnode, key, old, ns) { + if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) + return; + if (key[0] === "o" && key[1] === "n") + updateEvent(vnode, key, void 0); + else if (key === "style") + updateStyle(vnode.dom, old, null); + else if (hasPropertyKey(vnode, key, ns) && key !== "className" && key !== "title" && !(key === "value" && (vnode.tag === "option" || vnode.tag === "select" && vnode.dom.selectedIndex === -1 && vnode.dom === activeElement())) && !(vnode.tag === "input" && key === "type")) { + vnode.dom[key] = null; + } else { + var nsLastIndex = key.indexOf(":"); + if (nsLastIndex !== -1) + key = key.slice(nsLastIndex + 1); + if (old !== false) + vnode.dom.removeAttribute(key === "className" ? "class" : key); + } + } + function setLateSelectAttrs(vnode, attrs) { + if ("value" in attrs) { + if (attrs.value === null) { + if (vnode.dom.selectedIndex !== -1) + vnode.dom.value = null; + } else { + var normalized = "" + attrs.value; + if (vnode.dom.value !== normalized || vnode.dom.selectedIndex === -1) { + vnode.dom.value = normalized; + } + } + } + if ("selectedIndex" in attrs) + setAttr(vnode, "selectedIndex", null, attrs.selectedIndex, void 0); + } + function updateAttrs(vnode, old, attrs, ns) { + if (old && old === attrs) { + console.warn("Don't reuse attrs object, use new object for every redraw, this will throw in next major"); + } + if (attrs != null) { + if (vnode.tag === "input" && attrs.type != null) + vnode.dom.setAttribute("type", attrs.type); + var isFileInput = vnode.tag === "input" && attrs.type === "file"; + for (var key in attrs) { + setAttr(vnode, key, old && old[key], attrs[key], ns, isFileInput); + } + } + var val; + if (old != null) { + for (var key in old) { + if ((val = old[key]) != null && (attrs == null || attrs[key] == null)) { + removeAttr(vnode, key, val, ns); + } + } + } + } + function isFormAttribute(vnode, attr) { + return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === activeElement() || vnode.tag === "option" && vnode.dom.parentNode === $doc.activeElement; + } + function isLifecycleMethod(attr) { + return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"; + } + function hasPropertyKey(vnode, key, ns) { + return ns === void 0 && (vnode.tag.indexOf("-") > -1 || vnode.attrs != null && vnode.attrs.is || key !== "href" && key !== "list" && key !== "form" && key !== "width" && key !== "height") && key in vnode.dom; + } + var uppercaseRegex = /[A-Z]/g; + function toLowerCase(capital) { + return "-" + capital.toLowerCase(); + } + function normalizeKey(key) { + return key[0] === "-" && key[1] === "-" ? key : key === "cssFloat" ? "float" : key.replace(uppercaseRegex, toLowerCase); + } + function updateStyle(element, old, style) { + if (old === style) { + } else if (style == null) { + element.style.cssText = ""; + } else if (typeof style !== "object") { + element.style.cssText = style; + } else if (old == null || typeof old !== "object") { + element.style.cssText = ""; + for (var key in style) { + var value = style[key]; + if (value != null) + element.style.setProperty(normalizeKey(key), String(value)); + } + } else { + for (var key in style) { + var value = style[key]; + if (value != null && (value = String(value)) !== String(old[key])) { + element.style.setProperty(normalizeKey(key), value); + } + } + for (var key in old) { + if (old[key] != null && style[key] == null) { + element.style.removeProperty(normalizeKey(key)); + } + } + } + } + function EventDict() { + this._ = currentRedraw; + } + EventDict.prototype = /* @__PURE__ */ Object.create(null); + EventDict.prototype.handleEvent = function(ev) { + var handler = this["on" + ev.type]; + var result; + if (typeof handler === "function") + result = handler.call(ev.currentTarget, ev); + else if (typeof handler.handleEvent === "function") + handler.handleEvent(ev); + if (this._ && ev.redraw !== false) + (0, this._)(); + if (result === false) { + ev.preventDefault(); + ev.stopPropagation(); + } + }; + function updateEvent(vnode, key, value) { + if (vnode.events != null) { + vnode.events._ = currentRedraw; + if (vnode.events[key] === value) + return; + if (value != null && (typeof value === "function" || typeof value === "object")) { + if (vnode.events[key] == null) + vnode.dom.addEventListener(key.slice(2), vnode.events, false); + vnode.events[key] = value; + } else { + if (vnode.events[key] != null) + vnode.dom.removeEventListener(key.slice(2), vnode.events, false); + vnode.events[key] = void 0; + } + } else if (value != null && (typeof value === "function" || typeof value === "object")) { + vnode.events = new EventDict(); + vnode.dom.addEventListener(key.slice(2), vnode.events, false); + vnode.events[key] = value; + } + } + function initLifecycle(source, vnode, hooks) { + if (typeof source.oninit === "function") + callHook.call(source.oninit, vnode); + if (typeof source.oncreate === "function") + hooks.push(callHook.bind(source.oncreate, vnode)); + } + function updateLifecycle(source, vnode, hooks) { + if (typeof source.onupdate === "function") + hooks.push(callHook.bind(source.onupdate, vnode)); + } + function shouldNotUpdate(vnode, old) { + do { + if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") { + var force = callHook.call(vnode.attrs.onbeforeupdate, vnode, old); + if (force !== void 0 && !force) + break; + } + if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeupdate === "function") { + var force = callHook.call(vnode.state.onbeforeupdate, vnode, old); + if (force !== void 0 && !force) + break; + } + return false; + } while (false); + vnode.dom = old.dom; + vnode.domSize = old.domSize; + vnode.instance = old.instance; + vnode.attrs = old.attrs; + vnode.children = old.children; + vnode.text = old.text; + return true; + } + var currentDOM; + return function(dom, vnodes, redraw) { + if (!dom) + throw new TypeError("DOM element being rendered to does not exist."); + if (currentDOM != null && dom.contains(currentDOM)) { + throw new TypeError("Node is currently being rendered to and thus is locked."); + } + var prevRedraw = currentRedraw; + var prevDOM = currentDOM; + var hooks = []; + var active = activeElement(); + var namespace = dom.namespaceURI; + currentDOM = dom; + currentRedraw = typeof redraw === "function" ? redraw : void 0; + try { + if (dom.vnodes == null) + dom.textContent = ""; + vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]); + updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? void 0 : namespace); + dom.vnodes = vnodes; + if (active != null && activeElement() !== active && typeof active.focus === "function") + active.focus(); + for (var i = 0; i < hooks.length; i++) + hooks[i](); + } finally { + currentRedraw = prevRedraw; + currentDOM = prevDOM; + } + }; + }; + } + }); + + // render.js + var require_render2 = __commonJS({ + "render.js": function(exports, module) { + "use strict"; + module.exports = require_render()(typeof window !== "undefined" ? window : null); + } + }); + + // api/mount-redraw.js + var require_mount_redraw = __commonJS({ + "api/mount-redraw.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + module.exports = function(render, schedule, console2) { + var subscriptions = []; + var pending = false; + var offset = -1; + function sync() { + for (offset = 0; offset < subscriptions.length; offset += 2) { + try { + render(subscriptions[offset], Vnode(subscriptions[offset + 1]), redraw); + } catch (e) { + console2.error(e); + } + } + offset = -1; + } + function redraw() { + if (!pending) { + pending = true; + schedule(function() { + pending = false; + sync(); + }); + } + } + redraw.sync = sync; + function mount(root, component) { + if (component != null && component.view == null && typeof component !== "function") { + throw new TypeError("m.mount expects a component, not a vnode."); + } + var index = subscriptions.indexOf(root); + if (index >= 0) { + subscriptions.splice(index, 2); + if (index <= offset) + offset -= 2; + render(root, []); + } + if (component != null) { + subscriptions.push(root, component); + render(root, Vnode(component), redraw); + } + } + return { mount: mount, redraw: redraw }; + }; + } + }); + + // mount-redraw.js + var require_mount_redraw2 = __commonJS({ + "mount-redraw.js": function(exports, module) { + "use strict"; + var render = require_render2(); + module.exports = require_mount_redraw()(render, typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : null, typeof console !== "undefined" ? console : null); + } + }); + + // querystring/build.js + var require_build = __commonJS({ + "querystring/build.js": function(exports, module) { + "use strict"; + module.exports = function(object) { + if (Object.prototype.toString.call(object) !== "[object Object]") + return ""; + var args = []; + for (var key in object) { + destructure(key, object[key]); + } + return args.join("&"); + function destructure(key2, value) { + if (Array.isArray(value)) { + for (var i = 0; i < value.length; i++) { + destructure(key2 + "[" + i + "]", value[i]); + } + } else if (Object.prototype.toString.call(value) === "[object Object]") { + for (var i in value) { + destructure(key2 + "[" + i + "]", value[i]); + } + } else + args.push(encodeURIComponent(key2) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : "")); + } + }; + } + }); + + // util/assign.js + var require_assign = __commonJS({ + "util/assign.js": function(exports, module) { + "use strict"; + var hasOwn = require_hasOwn(); + module.exports = Object.assign || function(target, source) { + for (var key in source) { + if (hasOwn.call(source, key)) + target[key] = source[key]; + } + }; + } + }); + + // pathname/build.js + var require_build2 = __commonJS({ + "pathname/build.js": function(exports, module) { + "use strict"; + var buildQueryString = require_build(); + var assign = require_assign(); + module.exports = function(template, params) { + if (/:([^\/\.-]+)(\.{3})?:/.test(template)) { + throw new SyntaxError("Template parameter names must be separated by either a '/', '-', or '.'."); + } + if (params == null) + return template; + var queryIndex = template.indexOf("?"); + var hashIndex = template.indexOf("#"); + var queryEnd = hashIndex < 0 ? template.length : hashIndex; + var pathEnd = queryIndex < 0 ? queryEnd : queryIndex; + var path = template.slice(0, pathEnd); + var query = {}; + assign(query, params); + var resolved = path.replace(/:([^\/\.-]+)(\.{3})?/g, function(m, key, variadic) { + delete query[key]; + if (params[key] == null) + return m; + return variadic ? params[key] : encodeURIComponent(String(params[key])); + }); + var newQueryIndex = resolved.indexOf("?"); + var newHashIndex = resolved.indexOf("#"); + var newQueryEnd = newHashIndex < 0 ? resolved.length : newHashIndex; + var newPathEnd = newQueryIndex < 0 ? newQueryEnd : newQueryIndex; + var result = resolved.slice(0, newPathEnd); + if (queryIndex >= 0) + result += template.slice(queryIndex, queryEnd); + if (newQueryIndex >= 0) + result += (queryIndex < 0 ? "?" : "&") + resolved.slice(newQueryIndex, newQueryEnd); + var querystring = buildQueryString(query); + if (querystring) + result += (queryIndex < 0 && newQueryIndex < 0 ? "?" : "&") + querystring; + if (hashIndex >= 0) + result += template.slice(hashIndex); + if (newHashIndex >= 0) + result += (hashIndex < 0 ? "" : "&") + resolved.slice(newHashIndex); + return result; + }; + } + }); + + // request/request.js + var require_request = __commonJS({ + "request/request.js": function(exports, module) { + "use strict"; + var buildPathname = require_build2(); + var hasOwn = require_hasOwn(); + module.exports = function($window, Promise2, oncompletion) { + var callbackCount = 0; + function PromiseProxy(executor) { + return new Promise2(executor); + } + PromiseProxy.prototype = Promise2.prototype; + PromiseProxy.__proto__ = Promise2; + function makeRequest(factory) { + return function(url, args) { + if (typeof url !== "string") { + args = url; + url = url.url; + } else if (args == null) + args = {}; + var promise = new Promise2(function(resolve, reject) { + factory(buildPathname(url, args.params), args, function(data) { + if (typeof args.type === "function") { + if (Array.isArray(data)) { + for (var i = 0; i < data.length; i++) { + data[i] = new args.type(data[i]); + } + } else + data = new args.type(data); + } + resolve(data); + }, reject); + }); + if (args.background === true) + return promise; + var count = 0; + function complete() { + if (--count === 0 && typeof oncompletion === "function") + oncompletion(); + } + return wrap(promise); + function wrap(promise2) { + var then = promise2.then; + promise2.constructor = PromiseProxy; + promise2.then = function() { + count++; + var next = then.apply(promise2, arguments); + next.then(complete, function(e) { + complete(); + if (count === 0) + throw e; + }); + return wrap(next); + }; + return promise2; + } + }; + } + function hasHeader(args, name) { + for (var key in args.headers) { + if (hasOwn.call(args.headers, key) && key.toLowerCase() === name) + return true; + } + return false; + } + return { + request: makeRequest(function(url, args, resolve, reject) { + var method = args.method != null ? args.method.toUpperCase() : "GET"; + var body = args.body; + var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData || body instanceof $window.URLSearchParams); + var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json"); + var xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false; + var original = xhr, replacedAbort; + var abort = xhr.abort; + xhr.abort = function() { + aborted = true; + abort.call(this); + }; + xhr.open(method, url, args.async !== false, typeof args.user === "string" ? args.user : void 0, typeof args.password === "string" ? args.password : void 0); + if (assumeJSON && body != null && !hasHeader(args, "content-type")) { + xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); + } + if (typeof args.deserialize !== "function" && !hasHeader(args, "accept")) { + xhr.setRequestHeader("Accept", "application/json, text/*"); + } + if (args.withCredentials) + xhr.withCredentials = args.withCredentials; + if (args.timeout) + xhr.timeout = args.timeout; + xhr.responseType = responseType; + for (var key in args.headers) { + if (hasOwn.call(args.headers, key)) { + xhr.setRequestHeader(key, args.headers[key]); + } + } + xhr.onreadystatechange = function(ev) { + if (aborted) + return; + if (ev.target.readyState === 4) { + try { + var success = ev.target.status >= 200 && ev.target.status < 300 || ev.target.status === 304 || /^file:\/\//i.test(url); + var response = ev.target.response, message; + if (responseType === "json") { + if (!ev.target.responseType && typeof args.extract !== "function") { + try { + response = JSON.parse(ev.target.responseText); + } catch (e) { + response = null; + } + } + } else if (!responseType || responseType === "text") { + if (response == null) + response = ev.target.responseText; + } + if (typeof args.extract === "function") { + response = args.extract(ev.target, args); + success = true; + } else if (typeof args.deserialize === "function") { + response = args.deserialize(response); + } + if (success) + resolve(response); + else { + var completeErrorResponse = function() { + try { + message = ev.target.responseText; + } catch (e) { + message = response; + } + var error = new Error(message); + error.code = ev.target.status; + error.response = response; + reject(error); + }; + if (xhr.status === 0) { + setTimeout(function() { + if (isTimeout) + return; + completeErrorResponse(); + }); + } else + completeErrorResponse(); + } + } catch (e) { + reject(e); + } + } + }; + xhr.ontimeout = function(ev) { + isTimeout = true; + var error = new Error("Request timed out"); + error.code = ev.target.status; + reject(error); + }; + if (typeof args.config === "function") { + xhr = args.config(xhr, args, url) || xhr; + if (xhr !== original) { + replacedAbort = xhr.abort; + xhr.abort = function() { + aborted = true; + replacedAbort.call(this); + }; + } + } + if (body == null) + xhr.send(); + else if (typeof args.serialize === "function") + xhr.send(args.serialize(body)); + else if (body instanceof $window.FormData || body instanceof $window.URLSearchParams) + xhr.send(body); + else + xhr.send(JSON.stringify(body)); + }), + jsonp: makeRequest(function(url, args, resolve, reject) { + var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++; + var script = $window.document.createElement("script"); + $window[callbackName] = function(data) { + delete $window[callbackName]; + script.parentNode.removeChild(script); + resolve(data); + }; + script.onerror = function() { + delete $window[callbackName]; + script.parentNode.removeChild(script); + reject(new Error("JSONP request failed")); + }; + script.src = url + (url.indexOf("?") < 0 ? "?" : "&") + encodeURIComponent(args.callbackKey || "callback") + "=" + encodeURIComponent(callbackName); + $window.document.documentElement.appendChild(script); + }) + }; + }; + } + }); + + // request.js + var require_request2 = __commonJS({ + "request.js": function(exports, module) { + "use strict"; + var PromisePolyfill = require_promise(); + var mountRedraw = require_mount_redraw2(); + module.exports = require_request()(typeof window !== "undefined" ? window : null, PromisePolyfill, mountRedraw.redraw); + } + }); + + // querystring/parse.js + var require_parse = __commonJS({ + "querystring/parse.js": function(exports, module) { + "use strict"; + function decodeURIComponentSave(str) { + try { + return decodeURIComponent(str); + } catch (err) { + return str; + } + } + module.exports = function(string) { + if (string === "" || string == null) + return {}; + if (string.charAt(0) === "?") + string = string.slice(1); + var entries = string.split("&"), counters = {}, data = {}; + for (var i = 0; i < entries.length; i++) { + var entry = entries[i].split("="); + var key = decodeURIComponentSave(entry[0]); + var value = entry.length === 2 ? decodeURIComponentSave(entry[1]) : ""; + if (value === "true") + value = true; + else if (value === "false") + value = false; + var levels = key.split(/\]\[?|\[/); + var cursor = data; + if (key.indexOf("[") > -1) + levels.pop(); + for (var j = 0; j < levels.length; j++) { + var level = levels[j], nextLevel = levels[j + 1]; + var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10)); + if (level === "") { + var key = levels.slice(0, j).join(); + if (counters[key] == null) { + counters[key] = Array.isArray(cursor) ? cursor.length : 0; + } + level = counters[key]++; + } else if (level === "__proto__") + break; + if (j === levels.length - 1) + cursor[level] = value; + else { + var desc = Object.getOwnPropertyDescriptor(cursor, level); + if (desc != null) + desc = desc.value; + if (desc == null) + cursor[level] = desc = isNumber ? [] : {}; + cursor = desc; + } + } + } + return data; + }; + } + }); + + // pathname/parse.js + var require_parse2 = __commonJS({ + "pathname/parse.js": function(exports, module) { + "use strict"; + var parseQueryString = require_parse(); + module.exports = function(url) { + var queryIndex = url.indexOf("?"); + var hashIndex = url.indexOf("#"); + var queryEnd = hashIndex < 0 ? url.length : hashIndex; + var pathEnd = queryIndex < 0 ? queryEnd : queryIndex; + var path = url.slice(0, pathEnd).replace(/\/{2,}/g, "/"); + if (!path) + path = "/"; + else { + if (path[0] !== "/") + path = "/" + path; + if (path.length > 1 && path[path.length - 1] === "/") + path = path.slice(0, -1); + } + return { + path: path, + params: queryIndex < 0 ? {} : parseQueryString(url.slice(queryIndex + 1, queryEnd)) + }; + }; + } + }); + + // pathname/compileTemplate.js + var require_compileTemplate = __commonJS({ + "pathname/compileTemplate.js": function(exports, module) { + "use strict"; + var parsePathname = require_parse2(); + module.exports = function(template) { + var templateData = parsePathname(template); + var templateKeys = Object.keys(templateData.params); + var keys = []; + var regexp = new RegExp("^" + templateData.path.replace(/:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g, function(m, key, extra) { + if (key == null) + return "\\" + m; + keys.push({ k: key, r: extra === "..." }); + if (extra === "...") + return "(.*)"; + if (extra === ".") + return "([^/]+)\\."; + return "([^/]+)" + (extra || ""); + }) + "$"); + return function(data) { + for (var i = 0; i < templateKeys.length; i++) { + if (templateData.params[templateKeys[i]] !== data.params[templateKeys[i]]) + return false; + } + if (!keys.length) + return regexp.test(data.path); + var values = regexp.exec(data.path); + if (values == null) + return false; + for (var i = 0; i < keys.length; i++) { + data.params[keys[i].k] = keys[i].r ? values[i + 1] : decodeURIComponent(values[i + 1]); + } + return true; + }; + }; + } + }); + + // util/censor.js + var require_censor = __commonJS({ + "util/censor.js": function(exports, module) { + "use strict"; + var hasOwn = require_hasOwn(); + var magic = /^(?:key|oninit|oncreate|onbeforeupdate|onupdate|onbeforeremove|onremove)$/; + module.exports = function(attrs, extras) { + var result = {}; + if (extras != null) { + for (var key in attrs) { + if (hasOwn.call(attrs, key) && !magic.test(key) && extras.indexOf(key) < 0) { + result[key] = attrs[key]; + } + } + } else { + for (var key in attrs) { + if (hasOwn.call(attrs, key) && !magic.test(key)) { + result[key] = attrs[key]; + } + } + } + return result; + }; + } + }); + + // api/router.js + var require_router = __commonJS({ + "api/router.js": function(exports, module) { + "use strict"; + var Vnode = require_vnode(); + var m = require_hyperscript(); + var Promise2 = require_promise(); + var buildPathname = require_build2(); + var parsePathname = require_parse2(); + var compileTemplate = require_compileTemplate(); + var assign = require_assign(); + var censor = require_censor(); + var sentinel = {}; + function decodeURIComponentSave(component) { + try { + return decodeURIComponent(component); + } catch (e) { + return component; + } + } + module.exports = function($window, mountRedraw) { + var callAsync = $window == null ? null : typeof $window.setImmediate === "function" ? $window.setImmediate : $window.setTimeout; + var p = Promise2.resolve(); + var scheduled = false; + var ready = false; + var state = 0; + var compiled, fallbackRoute; + var currentResolver = sentinel, component, attrs, currentPath, lastUpdate; + var RouterRoot = { + onbeforeupdate: function() { + state = state ? 2 : 1; + return !(!state || sentinel === currentResolver); + }, + onremove: function() { + $window.removeEventListener("popstate", fireAsync, false); + $window.removeEventListener("hashchange", resolveRoute, false); + }, + view: function() { + if (!state || sentinel === currentResolver) + return; + var vnode = [Vnode(component, attrs.key, attrs)]; + if (currentResolver) + vnode = currentResolver.render(vnode[0]); + return vnode; + } + }; + var SKIP = route.SKIP = {}; + function resolveRoute() { + scheduled = false; + var prefix = $window.location.hash; + if (route.prefix[0] !== "#") { + prefix = $window.location.search + prefix; + if (route.prefix[0] !== "?") { + prefix = $window.location.pathname + prefix; + if (prefix[0] !== "/") + prefix = "/" + prefix; + } + } + var path = prefix.concat().replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponentSave).slice(route.prefix.length); + var data = parsePathname(path); + assign(data.params, $window.history.state); + function reject(e) { + console.error(e); + setPath(fallbackRoute, null, { replace: true }); + } + loop(0); + function loop(i) { + for (; i < compiled.length; i++) { + if (compiled[i].check(data)) { + var payload = compiled[i].component; + var matchedRoute = compiled[i].route; + var localComp = payload; + var update = lastUpdate = function(comp) { + if (update !== lastUpdate) + return; + if (comp === SKIP) + return loop(i + 1); + component = comp != null && (typeof comp.view === "function" || typeof comp === "function") ? comp : "div"; + attrs = data.params, currentPath = path, lastUpdate = null; + currentResolver = payload.render ? payload : null; + if (state === 2) + mountRedraw.redraw(); + else { + state = 2; + mountRedraw.redraw.sync(); + } + }; + if (payload.view || typeof payload === "function") { + payload = {}; + update(localComp); + } else if (payload.onmatch) { + p.then(function() { + return payload.onmatch(data.params, path, matchedRoute); + }).then(update, path === fallbackRoute ? null : reject); + } else + update("div"); + return; + } + } + if (path === fallbackRoute) { + throw new Error("Could not resolve default route " + fallbackRoute + "."); + } + setPath(fallbackRoute, null, { replace: true }); + } + } + function fireAsync() { + if (!scheduled) { + scheduled = true; + callAsync(resolveRoute); + } + } + function setPath(path, data, options) { + path = buildPathname(path, data); + if (ready) { + fireAsync(); + var state2 = options ? options.state : null; + var title = options ? options.title : null; + if (options && options.replace) + $window.history.replaceState(state2, title, route.prefix + path); + else + $window.history.pushState(state2, title, route.prefix + path); + } else { + $window.location.href = route.prefix + path; + } + } + function route(root, defaultRoute, routes) { + if (!root) + throw new TypeError("DOM element being rendered to does not exist."); + compiled = Object.keys(routes).map(function(route2) { + if (route2[0] !== "/") + throw new SyntaxError("Routes must start with a '/'."); + if (/:([^\/\.-]+)(\.{3})?:/.test(route2)) { + throw new SyntaxError("Route parameter names must be separated with either '/', '.', or '-'."); + } + return { + route: route2, + component: routes[route2], + check: compileTemplate(route2) + }; + }); + fallbackRoute = defaultRoute; + if (defaultRoute != null) { + var defaultData = parsePathname(defaultRoute); + if (!compiled.some(function(i) { + return i.check(defaultData); + })) { + throw new ReferenceError("Default route doesn't match any known routes."); + } + } + if (typeof $window.history.pushState === "function") { + $window.addEventListener("popstate", fireAsync, false); + } else if (route.prefix[0] === "#") { + $window.addEventListener("hashchange", resolveRoute, false); + } + ready = true; + mountRedraw.mount(root, RouterRoot); + resolveRoute(); + } + route.set = function(path, data, options) { + if (lastUpdate != null) { + options = options || {}; + options.replace = true; + } + lastUpdate = null; + setPath(path, data, options); + }; + route.get = function() { + return currentPath; + }; + route.prefix = "#!"; + route.Link = { + view: function(vnode) { + var child = m(vnode.attrs.selector || "a", censor(vnode.attrs, ["options", "params", "selector", "onclick"]), vnode.children); + var options, onclick, href; + if (child.attrs.disabled = Boolean(child.attrs.disabled)) { + child.attrs.href = null; + child.attrs["aria-disabled"] = "true"; + } else { + options = vnode.attrs.options; + onclick = vnode.attrs.onclick; + href = buildPathname(child.attrs.href, vnode.attrs.params); + child.attrs.href = route.prefix + href; + child.attrs.onclick = function(e) { + var result; + if (typeof onclick === "function") { + result = onclick.call(e.currentTarget, e); + } else if (onclick == null || typeof onclick !== "object") { + } else if (typeof onclick.handleEvent === "function") { + onclick.handleEvent(e); + } + if (result !== false && !e.defaultPrevented && (e.button === 0 || e.which === 0 || e.which === 1) && (!e.currentTarget.target || e.currentTarget.target === "_self") && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey) { + e.preventDefault(); + e.redraw = false; + route.set(href, null, options); + } + }; + } + return child; + } + }; + route.param = function(key) { + return attrs && key != null ? attrs[key] : attrs; + }; + return route; + }; + } + }); + + // route.js + var require_route = __commonJS({ + "route.js": function(exports, module) { + "use strict"; + var mountRedraw = require_mount_redraw2(); + module.exports = require_router()(typeof window !== "undefined" ? window : null, mountRedraw); + } + }); + + // index.js + var require_mithril = __commonJS({ + "index.js": function(exports, module) { + "use strict"; + var hyperscript = require_hyperscript2(); + var request = require_request2(); + var mountRedraw = require_mount_redraw2(); + var m = function m2() { + return hyperscript.apply(this, arguments); + }; + m.m = hyperscript; + m.trust = hyperscript.trust; + m.fragment = hyperscript.fragment; + m.Fragment = "["; + m.mount = mountRedraw.mount; + m.route = require_route(); + m.render = require_render2(); + m.redraw = mountRedraw.redraw; + m.request = request.request; + m.jsonp = request.jsonp; + m.parseQueryString = require_parse(); + m.buildQueryString = require_build(); + m.parsePathname = require_parse2(); + m.buildPathname = require_build2(); + m.vnode = require_vnode(); + m.PromisePolyfill = require_polyfill(); + m.censor = require_censor(); + module.exports = m; + } + }); + + // browser.js + var require_browser = __commonJS({ + "browser.js": function(exports, module) { + var m = require_mithril(); + if (typeof module !== "undefined") + module["exports"] = m; + else + window.m = m; + } + }); + "use strict"; + return require_browser(); +})(); diff --git a/mithril.min.js b/mithril.min.js index e16a9c9c7..ddd3a77d1 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1 +1 @@ -!function(){"use strict";function e(e,t,n,r,o,i){return{tag:e,key:t,attrs:n,children:r,text:o,dom:i,domSize:void 0,state:void 0,events:void 0,instance:void 0}}e.normalize=function(t){return Array.isArray(t)?e("[",void 0,void 0,e.normalizeChildren(t),void 0,void 0):null==t||"boolean"==typeof t?null:"object"==typeof t?t:e("#",void 0,void 0,String(t),void 0,void 0)},e.normalizeChildren=function(t){var n=[];if(t.length){for(var r=null!=t[0]&&null!=t[0].key,o=1;o0&&(l.className=i.join(" ")),o[e]={tag:n,attrs:l}}(l),a):(a.tag=l,a)}if(l.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},l.fragment=function(){var n=t.apply(0,arguments);return n.tag="[",n.children=e.normalizeChildren(n.children),n},(a=function(e){if(!(this instanceof a))throw new Error("Promise must be called with 'new'.");if("function"!=typeof e)throw new TypeError("executor must be a function.");var t=this,n=[],r=[],o=s(n,!0),i=s(r,!1),l=t._instance={resolvers:n,rejectors:r},u="function"==typeof setImmediate?setImmediate:setTimeout;function s(e,o){return function a(s){var f;try{if(!o||null==s||"object"!=typeof s&&"function"!=typeof s||"function"!=typeof(f=s.then))u((function(){o||0!==e.length||console.error("Possible unhandled promise rejection:",s);for(var t=0;t0||e(n)}}var r=n(i);try{e(n(o),r)}catch(e){r(e)}}c(e)}).prototype.then=function(e,t){var n,r,o=this._instance;function i(e,t,i,l){t.push((function(t){if("function"!=typeof e)i(t);else try{n(e(t))}catch(e){r&&r(e)}})),"function"==typeof o.retry&&l===o.state&&o.retry()}var l=new a((function(e,t){n=e,r=t}));return i(e,o.resolvers,n,!0),i(t,o.rejectors,r,!1),l},a.prototype.catch=function(e){return this.then(null,e)},a.prototype.finally=function(e){return this.then((function(t){return a.resolve(e()).then((function(){return t}))}),(function(t){return a.resolve(e()).then((function(){return a.reject(t)}))}))},a.resolve=function(e){return e instanceof a?e:new a((function(t){t(e)}))},a.reject=function(e){return new a((function(t,n){n(e)}))},a.all=function(e){return new a((function(t,n){var r=e.length,o=0,i=[];if(0===e.length)t([]);else for(var l=0;l'+t.children+"",l=l.firstChild):l.innerHTML=t.children,t.dom=l.firstChild,t.domSize=l.childNodes.length,t.instance=[];for(var a,u=r.createDocumentFragment();a=l.firstChild;)t.instance.push(a),u.appendChild(a);w(e,u,o)}function p(e,t,n,r,o,i){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)s(e,n,0,n.length,r,o,i);else if(null==n||0===n.length)k(e,t,0,t.length);else{var l=null!=t[0]&&null!=t[0].key,a=null!=n[0]&&null!=n[0].key,u=0,f=0;if(!l)for(;f=f&&j>=u&&(w=t[E],b=n[j],w.key===b.key);)w!==b&&h(e,w,b,r,o,i),null!=b.dom&&(o=b.dom),E--,j--;for(;E>=f&&j>=u&&(d=t[f],p=n[u],d.key===p.key);)f++,u++,d!==p&&h(e,d,p,r,y(t,f,o),i);for(;E>=f&&j>=u&&u!==j&&d.key===b.key&&w.key===p.key;)g(e,w,S=y(t,f,o)),w!==p&&h(e,w,p,r,S,i),++u<=--j&&g(e,d,o),d!==b&&h(e,d,b,r,o,i),null!=b.dom&&(o=b.dom),f++,w=t[--E],b=n[j],d=t[f],p=n[u];for(;E>=f&&j>=u&&w.key===b.key;)w!==b&&h(e,w,b,r,o,i),null!=b.dom&&(o=b.dom),j--,w=t[--E],b=n[j];if(u>j)k(e,t,f,E+1);else if(f>E)s(e,n,u,j+1,r,o,i);else{var C,z,A=o,T=j-u+1,N=new Array(T),O=0,P=0,I=2147483647,$=0;for(P=0;P=u;P--){null==C&&(C=v(t,f,E+1));var L=C[(b=n[P]).key];null!=L&&(I=L>>1)+(r>>>1)+(n&r&1);e[t[a]]0&&(m[o]=t[n-1]),t[n]=o)}}n=t.length,r=t[n-1];for(;n-- >0;)t[n]=r,r=m[r];return m.length=0,t}(N)).length-1,P=j;P>=u;P--)p=n[P],-1===N[P-u]?c(e,p,r,i,o):z[O]===P-u?O--:g(e,p,o),null!=p.dom&&(o=n[P].dom);else for(P=j;P>=u;P--)p=n[P],-1===N[P-u]&&c(e,p,r,i,o),null!=p.dom&&(o=n[P].dom)}}else{var R=t.lengthR&&k(e,t,u,t.length),n.length>R&&s(e,n,u,n.length,r,o,i)}}}function h(t,n,r,o,l,u){var s=n.tag;if(s===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{var n;if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate)if(void 0!==(n=a.call(e.attrs.onbeforeupdate,e,t))&&!n)break;if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate)if(void 0!==(n=a.call(e.state.onbeforeupdate,e,t))&&!n)break;return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,e.attrs=t.attrs,e.children=t.children,e.text=t.text,!0}(r,n))return;if("string"==typeof s)switch(null!=r.attrs&&D(r.attrs,r,o),s){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(S(e,t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize,n.instance=t.instance)}(t,n,r,u,l);break;case"[":!function(e,t,n,r,o,i){p(e,t.children,n.children,r,o,i);var l=0,a=n.children;if(n.dom=null,null!=a){for(var u=0;u-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var N,O=/[A-Z]/g;function P(e){return"-"+e.toLowerCase()}function I(e){return"-"===e[0]&&"-"===e[1]?e:"cssFloat"===e?"float":e.replace(O,P)}function $(e,t,n){if(t===n);else if(null==n)e.style.cssText="";else if("object"!=typeof n)e.style.cssText=n;else if(null==t||"object"!=typeof t)for(var r in e.style.cssText="",n){null!=(o=n[r])&&e.style.setProperty(I(r),String(o))}else{for(var r in n){var o;null!=(o=n[r])&&(o=String(o))!==String(t[r])&&e.style.setProperty(I(r),o)}for(var r in t)null!=t[r]&&null==n[r]&&e.style.removeProperty(I(r))}}function L(){this._=n}function R(e,t,r){if(null!=e.events){if(e.events._=n,e.events[t]===r)return;null==r||"function"!=typeof r&&"object"!=typeof r?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}else null==r||"function"!=typeof r&&"object"!=typeof r||(e.events=new L,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}function _(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function D(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return L.prototype=Object.create(null),L.prototype.handleEvent=function(e){var t,n=this["on"+e.type];"function"==typeof n?t=n.call(e.currentTarget,e):"function"==typeof n.handleEvent&&n.handleEvent(e),this._&&!1!==e.redraw&&(0,this._)(),!1===t&&(e.preventDefault(),e.stopPropagation())},function(t,r,o){if(!t)throw new TypeError("DOM element being rendered to does not exist.");if(null!=N&&t.contains(N))throw new TypeError("Node is currently being rendered to and thus is locked.");var i=n,l=N,a=[],s=u(),c=t.namespaceURI;N=t,n="function"==typeof o?o:void 0;try{null==t.vnodes&&(t.textContent=""),r=e.normalizeChildren(Array.isArray(r)?r:[r]),p(t,t.vnodes,r,a,null,"http://www.w3.org/1999/xhtml"===c?void 0:c),t.vnodes=r,null!=s&&u()!==s&&"function"==typeof s.focus&&s.focus();for(var f=0;f=0&&(o.splice(i,2),i<=l&&(l-=2),t(n,[])),null!=r&&(o.push(n,r),t(n,e(r),u))},redraw:u}}(u,"undefined"!=typeof requestAnimationFrame?requestAnimationFrame:null,"undefined"!=typeof console?console:null),c=function(e){if("[object Object]"!==Object.prototype.toString.call(e))return"";var t=[];for(var n in e)r(n,e[n]);return t.join("&");function r(e,n){if(Array.isArray(n))for(var o=0;o=0&&(v+=e.slice(n,o)),s>=0&&(v+=(n<0?"?":"&")+u.slice(s,p));var m=c(a);return m&&(v+=(n<0&&s<0?"?":"&")+m),r>=0&&(v+=e.slice(r)),d>=0&&(v+=(r<0?"":"&")+u.slice(d)),v},p=function(e,t,r){var o=0;function i(e){return new t(e)}function l(e){return function(n,o){"string"!=typeof n?(o=n,n=n.url):null==o&&(o={});var l=new t((function(t,r){e(d(n,o.params),o,(function(e){if("function"==typeof o.type)if(Array.isArray(e))for(var n=0;n=200&&e.target.status<300||304===e.target.status||/^file:\/\//i.test(t),a=e.target.response;if("json"===f){if(!e.target.responseType&&"function"!=typeof r.extract)try{a=JSON.parse(e.target.responseText)}catch(e){a=null}}else f&&"text"!==f||null==a&&(a=e.target.responseText);if("function"==typeof r.extract?(a=r.extract(e.target,r),l=!0):"function"==typeof r.deserialize&&(a=r.deserialize(a)),l)o(a);else{var u=function(){try{n=e.target.responseText}catch(e){n=a}var t=new Error(n);t.code=e.target.status,t.response=a,i(t)};0===d.status?setTimeout((function(){h||u()})):u()}}catch(e){i(e)}},d.ontimeout=function(e){h=!0;var t=new Error("Request timed out");t.code=e.target.status,i(t)},"function"==typeof r.config&&(d=r.config(d,r,t)||d)!==v&&(l=d.abort,d.abort=function(){p=!0,l.call(this)}),null==s?d.send():"function"==typeof r.serialize?d.send(r.serialize(s)):s instanceof e.FormData||s instanceof e.URLSearchParams?d.send(s):d.send(JSON.stringify(s))})),jsonp:l((function(t,n,r,i){var l=n.callbackName||"_mithril_"+Math.round(1e16*Math.random())+"_"+o++,a=e.document.createElement("script");e[l]=function(t){delete e[l],a.parentNode.removeChild(a),r(t)},a.onerror=function(){delete e[l],a.parentNode.removeChild(a),i(new Error("JSONP request failed"))},a.src=t+(t.indexOf("?")<0?"?":"&")+encodeURIComponent(n.callbackKey||"callback")+"="+encodeURIComponent(l),e.document.documentElement.appendChild(a)}))}}("undefined"!=typeof window?window:null,a,s.redraw),h=s,v=function(){return l.apply(this,arguments)};v.m=l,v.trust=l.trust,v.fragment=l.fragment,v.Fragment="[",v.mount=h.mount;var m=l,y=a;function g(e){try{return decodeURIComponent(e)}catch(t){return e}}var w=function(e){if(""===e||null==e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t=e.split("&"),n={},r={},o=0;o-1&&u.pop();for(var c=0;c1&&"/"===i[i.length-1]&&(i=i.slice(0,-1))):i="/",{path:i,params:t<0?{}:w(e.slice(t+1,r))}},k=function(e){var t=b(e),n=Object.keys(t.params),r=[],o=new RegExp("^"+t.path.replace(/:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g,(function(e,t,n){return null==t?"\\"+e:(r.push({k:t,r:"..."===n}),"..."===n?"(.*)":"."===n?"([^/]+)\\.":"([^/]+)"+(n||""))}))+"$");return function(e){for(var i=0;i0&&(g.className=s.join(" ")),$e[n]={tag:c,attrs:g}}function dt(n,f){var c=f.attrs,s=ee.call(c,"class"),g=s?c.class:c.className;if(f.tag=n.tag,f.attrs={},!We(n.attrs)&&!We(c)){var h={};for(var u in c)ee.call(c,u)&&(h[u]=c[u]);c=h}for(var u in n.attrs)ee.call(n.attrs,u)&&u!=="className"&&!ee.call(c,u)&&(c[u]=n.attrs[u]);(g!=null||n.attrs.className!=null)&&(c.className=g!=null?n.attrs.className!=null?String(n.attrs.className)+" "+String(g):g:n.attrs.className!=null?n.attrs.className:null),s&&(c.class=null);for(var u in c)if(ee.call(c,u)&&u!=="key"){f.attrs=c;break}return f}function er(n){if(n==null||typeof n!="string"&&typeof n!="function"&&typeof n.view!="function")throw Error("The selector must be either a string or a component.");var f=$t.apply(1,arguments);return typeof n=="string"&&(f.children=Wt.normalizeChildren(f.children),n!=="[")?dt($e[n]||kt(n),f):(f.tag=n,f)}ve.exports=er});var de=I(function(Or,ke){"use strict";var tr=W();ke.exports=function(n){return n==null&&(n=""),tr("<",void 0,void 0,n,void 0,void 0)}});var tt=I(function(zr,et){"use strict";var rr=W(),nr=Ae();et.exports=function(){var n=nr.apply(0,arguments);return n.tag="[",n.children=rr.normalizeChildren(n.children),n}});var nt=I(function(jr,rt){"use strict";var ze=Oe();ze.trust=de();ze.fragment=tt();rt.exports=ze});var je=I(function(Rr,it){"use strict";var K=function(n){if(!(this instanceof K))throw new Error("Promise must be called with 'new'.");if(typeof n!="function")throw new TypeError("executor must be a function.");var f=this,c=[],s=[],g=l(c,!0),h=l(s,!1),u=f._instance={resolvers:c,rejectors:s},p=typeof setImmediate=="function"?setImmediate:setTimeout;function l(x,b){return function C(N){var O;try{if(b&&N!=null&&(typeof N=="object"||typeof N=="function")&&typeof(O=N.then)=="function"){if(N===f)throw new TypeError("Promise can't be resolved with itself.");m(O.bind(N))}else p(function(){!b&&x.length===0&&console.error("Possible unhandled promise rejection:",N);for(var q=0;q0||O(q)}}var N=C(h);try{x(C(g),N)}catch(O){N(O)}}m(n)};K.prototype.then=function(n,f){var c=this,s=c._instance;function g(l,m,x,b){m.push(function(C){if(typeof l!="function")x(C);else try{h(l(C))}catch(N){u&&u(N)}}),typeof s.retry=="function"&&b===s.state&&s.retry()}var h,u,p=new K(function(l,m){h=l,u=m});return g(n,s.resolvers,h,!0),g(f,s.rejectors,u,!1),p};K.prototype.catch=function(n){return this.then(null,n)};K.prototype.finally=function(n){return this.then(function(f){return K.resolve(n()).then(function(){return f})},function(f){return K.resolve(n()).then(function(){return K.reject(f)})})};K.resolve=function(n){return n instanceof K?n:new K(function(f){f(n)})};K.reject=function(n){return new K(function(f,c){c(n)})};K.all=function(n){return new K(function(f,c){var s=n.length,g=0,h=[];if(n.length===0)f([]);else for(var u=0;u'+e.children+"",o=o.firstChild):o.innerHTML=e.children,e.dom=o.firstChild,e.domSize=o.childNodes.length,e.instance=[];for(var w=f.createDocumentFragment(),A;A=o.firstChild;)e.instance.push(A),w.appendChild(A);Z(t,w,i)}function N(t,e,r,i,a){var o=f.createDocumentFragment();if(e.children!=null){var w=e.children;l(o,w,0,w.length,r,null,i)}e.dom=o.firstChild,e.domSize=o.childNodes.length,Z(t,o,a)}function O(t,e,r,i,a){var o=e.tag,w=e.attrs,A=w&&w.is;i=g(e)||i;var y=i?A?f.createElementNS(i,o,{is:A}):f.createElementNS(i,o):A?f.createElement(o,{is:A}):f.createElement(o);if(e.dom=y,w!=null&&St(e,w,i),Z(t,y,a),!Se(e)&&e.children!=null){var j=e.children;l(y,j,0,j.length,r,null,i),e.tag==="select"&&w!=null&&Qt(e,w)}}function q(t,e){var r;if(typeof t.tag.view=="function"){if(t.state=Object.create(t.tag),r=t.state.view,r.$$reentrantLock$$!=null)return;r.$$reentrantLock$$=!0}else{if(t.state=void 0,r=t.tag,r.$$reentrantLock$$!=null)return;r.$$reentrantLock$$=!0,t.state=t.tag.prototype!=null&&typeof t.tag.prototype.view=="function"?new t.tag(t):t.tag(t)}if(be(t.state,t,e),t.attrs!=null&&be(t.attrs,t,e),t.instance=Le.normalize(u.call(t.state.view,t)),t.instance===t)throw Error("A view cannot return the vnode it received as argument");r.$$reentrantLock$$=null}function L(t,e,r,i,a){q(e,r),e.instance!=null?(m(t,e.instance,r,i,a),e.dom=e.instance.dom,e.domSize=e.dom!=null?e.instance.domSize:0):e.domSize=0}function F(t,e,r,i,a,o){if(!(e===r||e==null&&r==null))if(e==null||e.length===0)l(t,r,0,r.length,i,a,o);else if(r==null||r.length===0)te(t,e,0,e.length);else{var w=e[0]!=null&&e[0].key!=null,A=r[0]!=null&&r[0].key!=null,y=0,j=0;if(!w)for(;j=j&&S>=y&&(V=e[B],M=r[S],V.key===M.key);)V!==M&&X(t,V,M,i,a,o),M.dom!=null&&(a=M.dom),B--,S--;for(;B>=j&&S>=y&&(G=e[j],H=r[y],G.key===H.key);)j++,y++,G!==H&&X(t,G,H,i,Y(e,j,a),o);for(;B>=j&&S>=y&&!(y===S||G.key!==M.key||V.key!==H.key);)Ce=Y(e,j,a),k(t,V,Ce),V!==H&&X(t,V,H,i,Ce,o),++y<=--S&&k(t,G,a),G!==M&&X(t,G,M,i,a,o),M.dom!=null&&(a=M.dom),j++,B--,V=e[B],M=r[S],G=e[j],H=r[y];for(;B>=j&&S>=y&&V.key===M.key;)V!==M&&X(t,V,M,i,a,o),M.dom!=null&&(a=M.dom),B--,S--,V=e[B],M=r[S];if(y>S)te(t,e,j,B+1);else if(j>B)l(t,r,y,S+1,i,a,o);else{var Yt=a,Ge=S-y+1,ne=new Array(Ge),Ne=0,D=0,Pe=2147483647,Ee=0,le,Te;for(D=0;D=y;D--){le==null&&(le=z(e,j,B+1)),M=r[D];var d=le[M.key];d!=null&&(Pe=d=y;D--)H=r[D],ne[D-y]===-1?m(t,H,i,o,a):Te[Ne]===D-y?Ne--:k(t,H,a),H.dom!=null&&(a=r[D].dom);else for(D=S;D>=y;D--)H=r[D],ne[D-y]===-1&&m(t,H,i,o,a),H.dom!=null&&(a=r[D].dom)}}else{var xe=e.lengthxe&&te(t,e,y,e.length),r.length>xe&&l(t,r,y,r.length,i,a,o)}}}function X(t,e,r,i,a,o){var w=e.tag,A=r.tag;if(w===A){if(r.state=e.state,r.events=e.events,Xt(r,e))return;if(typeof w=="string")switch(r.attrs!=null&&qe(r.attrs,r,i),w){case"#":U(e,r);break;case"<":E(t,e,r,o,a);break;case"[":R(t,e,r,i,a,o);break;default:P(e,r,i,o)}else _(t,e,r,i,a,o)}else ae(t,e),m(t,r,i,o,a)}function U(t,e){t.children.toString()!==e.children.toString()&&(t.dom.nodeValue=e.children),e.dom=t.dom}function E(t,e,r,i,a){e.children!==r.children?(Ke(t,e),C(t,r,i,a)):(r.dom=e.dom,r.domSize=e.domSize,r.instance=e.instance)}function R(t,e,r,i,a,o){F(t,e.children,r.children,i,a,o);var w=0,A=r.children;if(r.dom=null,A!=null){for(var y=0;y>>1)+(i>>>1)+(r&i&1);t[e[A]]0&&(T[a]=e[r-1]),e[r]=a)}for(r=e.length,i=e[r-1];r-- >0;)e[r]=i,i=T[i];return T.length=0,e}function Y(t,e,r){for(;e-1||t.attrs!=null&&t.attrs.is||e!=="href"&&e!=="list"&&e!=="form"&&e!=="width"&&e!=="height")&&e in t.dom}var Bt=/[A-Z]/g;function Gt(t){return"-"+t.toLowerCase()}function ge(t){return t[0]==="-"&&t[1]==="-"?t:t==="cssFloat"?"float":t.replace(Bt,Gt)}function Ve(t,e,r){if(e!==r)if(r==null)t.style.cssText="";else if(typeof r!="object")t.style.cssText=r;else if(e==null||typeof e!="object"){t.style.cssText="";for(var i in r){var a=r[i];a!=null&&t.style.setProperty(ge(i),String(a))}}else{for(var i in r){var a=r[i];a!=null&&(a=String(a))!==String(e[i])&&t.style.setProperty(ge(i),a)}for(var i in e)e[i]!=null&&r[i]==null&&t.style.removeProperty(ge(i))}}function we(){this._=c}we.prototype=Object.create(null),we.prototype.handleEvent=function(t){var e=this["on"+t.type],r;typeof e=="function"?r=e.call(t.currentTarget,t):typeof e.handleEvent=="function"&&e.handleEvent(t),this._&&t.redraw!==!1&&(0,this._)(),r===!1&&(t.preventDefault(),t.stopPropagation())};function Be(t,e,r){if(t.events!=null){if(t.events._=c,t.events[e]===r)return;r!=null&&(typeof r=="function"||typeof r=="object")?(t.events[e]==null&&t.dom.addEventListener(e.slice(2),t.events,!1),t.events[e]=r):(t.events[e]!=null&&t.dom.removeEventListener(e.slice(2),t.events,!1),t.events[e]=void 0)}else r!=null&&(typeof r=="function"||typeof r=="object")&&(t.events=new we,t.dom.addEventListener(e.slice(2),t.events,!1),t.events[e]=r)}function be(t,e,r){typeof t.oninit=="function"&&u.call(t.oninit,e),typeof t.oncreate=="function"&&r.push(u.bind(t.oncreate,e))}function qe(t,e,r){typeof t.onupdate=="function"&&r.push(u.bind(t.onupdate,e))}function Xt(t,e){do{if(t.attrs!=null&&typeof t.attrs.onbeforeupdate=="function"){var r=u.call(t.attrs.onbeforeupdate,t,e);if(r!==void 0&&!r)break}if(typeof t.tag!="string"&&typeof t.state.onbeforeupdate=="function"){var r=u.call(t.state.onbeforeupdate,t,e);if(r!==void 0&&!r)break}return!1}while(!1);return t.dom=e.dom,t.domSize=e.domSize,t.instance=e.instance,t.attrs=e.attrs,t.children=e.children,t.text=e.text,!0}var re;return function(t,e,r){if(!t)throw new TypeError("DOM element being rendered to does not exist.");if(re!=null&&t.contains(re))throw new TypeError("Node is currently being rendered to and thus is locked.");var i=c,a=re,o=[],w=p(),A=t.namespaceURI;re=t,c=typeof r=="function"?r:void 0;try{t.vnodes==null&&(t.textContent=""),e=Le.normalizeChildren(Array.isArray(e)?e:[e]),F(t,t.vnodes,e,o,null,A==="http://www.w3.org/1999/xhtml"?void 0:A),t.vnodes=e,w!=null&&p()!==w&&typeof w.focus=="function"&&w.focus();for(var y=0;y=0&&(s.splice(b,2),b<=h&&(h-=2),n(m,[])),x!=null&&(s.push(m,x),n(m,lt(x),p))}return{mount:l,redraw:p}}});var se=I(function(Dr,ot){"use strict";var ir=Ie();ot.exports=st()(ir,typeof requestAnimationFrame!="undefined"?requestAnimationFrame:null,typeof console!="undefined"?console:null)});var Me=I(function(Ur,ht){"use strict";ht.exports=function(n){if(Object.prototype.toString.call(n)!=="[object Object]")return"";var f=[];for(var c in n)s(c,n[c]);return f.join("&");function s(g,h){if(Array.isArray(h))for(var u=0;u=0&&(N+=n.slice(c,g)),m>=0&&(N+=(c<0?"?":"&")+l.slice(m,b));var O=ar(p);return O&&(N+=(c<0&&m<0?"?":"&")+O),s>=0&&(N+=n.slice(s)),x>=0&&(N+=(s<0?"":"&")+l.slice(x)),N}});var wt=I(function(Sr,gt){"use strict";var lr=oe(),yt=ie();gt.exports=function(n,f,c){var s=0;function g(p){return new f(p)}g.prototype=f.prototype,g.__proto__=f;function h(p){return function(l,m){typeof l!="string"?(m=l,l=l.url):m==null&&(m={});var x=new f(function(O,q){p(lr(l,m.params),m,function(L){if(typeof m.type=="function")if(Array.isArray(L))for(var F=0;F=200&&P.target.status<300||P.target.status===304||/^file:\/\//i.test(p),z=P.target.response,T;if(O==="json"){if(!P.target.responseType&&typeof l.extract!="function")try{z=JSON.parse(P.target.responseText)}catch(Y){z=null}}else(!O||O==="text")&&z==null&&(z=P.target.responseText);if(typeof l.extract=="function"?(z=l.extract(P.target,l),_=!0):typeof l.deserialize=="function"&&(z=l.deserialize(z)),_)m(z);else{var J=function(){try{T=P.target.responseText}catch(k){T=z}var Y=new Error(T);Y.code=P.target.status,Y.response=z,x(Y)};q.status===0?setTimeout(function(){F||J()}):J()}}catch(Y){x(Y)}},q.ontimeout=function(P){F=!0;var _=new Error("Request timed out");_.code=P.target.status,x(_)},typeof l.config=="function"&&(q=l.config(q,l,p)||q,q!==X&&(U=q.abort,q.abort=function(){L=!0,U.call(this)})),C==null?q.send():typeof l.serialize=="function"?q.send(l.serialize(C)):C instanceof n.FormData||C instanceof n.URLSearchParams?q.send(C):q.send(JSON.stringify(C))}),jsonp:h(function(p,l,m,x){var b=l.callbackName||"_mithril_"+Math.round(Math.random()*1e16)+"_"+s++,C=n.document.createElement("script");n[b]=function(N){delete n[b],C.parentNode.removeChild(C),m(N)},C.onerror=function(){delete n[b],C.parentNode.removeChild(C),x(new Error("JSONP request failed"))},C.src=p+(p.indexOf("?")<0?"?":"&")+encodeURIComponent(l.callbackKey||"callback")+"="+encodeURIComponent(b),n.document.documentElement.appendChild(C)})}}});var qt=I(function(Kr,bt){"use strict";var cr=Re(),sr=se();bt.exports=wt()(typeof window!="undefined"?window:null,cr,sr.redraw)});var De=I(function(Qr,Ct){"use strict";function xt(n){try{return decodeURIComponent(n)}catch(f){return n}}Ct.exports=function(n){if(n===""||n==null)return{};n.charAt(0)==="?"&&(n=n.slice(1));for(var f=n.split("&"),c={},s={},g=0;g-1&&l.pop();for(var x=0;x1&&h[h.length-1]==="/"&&(h=h.slice(0,-1))):h="/",{path:h,params:f<0?{}:or(n.slice(f+1,s))}}});var Et=I(function(Vr,Pt){"use strict";var hr=he();Pt.exports=function(n){var f=hr(n),c=Object.keys(f.params),s=[],g=new RegExp("^"+f.path.replace(/:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g,function(h,u,p){return u==null?"\\"+h:(s.push({k:u,r:p==="..."}),p==="..."?"(.*)":p==="."?"([^/]+)\\.":"([^/]+)"+(p||""))})+"$");return function(h){for(var u=0;u= 0.4" } }, + "node_modules/esbuild": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.23.tgz", + "integrity": "sha512-XjnIcZ9KB6lfonCa+jRguXyRYcldmkyZ99ieDksqW/C8bnyEX299yA4QH2XcgijCgaddEZePPTgvx/2imsq7Ig==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.14.23", + "esbuild-darwin-64": "0.14.23", + "esbuild-darwin-arm64": "0.14.23", + "esbuild-freebsd-64": "0.14.23", + "esbuild-freebsd-arm64": "0.14.23", + "esbuild-linux-32": "0.14.23", + "esbuild-linux-64": "0.14.23", + "esbuild-linux-arm": "0.14.23", + "esbuild-linux-arm64": "0.14.23", + "esbuild-linux-mips64le": "0.14.23", + "esbuild-linux-ppc64le": "0.14.23", + "esbuild-linux-riscv64": "0.14.23", + "esbuild-linux-s390x": "0.14.23", + "esbuild-netbsd-64": "0.14.23", + "esbuild-openbsd-64": "0.14.23", + "esbuild-sunos-64": "0.14.23", + "esbuild-windows-32": "0.14.23", + "esbuild-windows-64": "0.14.23", + "esbuild-windows-arm64": "0.14.23" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.23.tgz", + "integrity": "sha512-k9sXem++mINrZty1v4FVt6nC5BQCFG4K2geCIUUqHNlTdFnuvcqsY7prcKZLFhqVC1rbcJAr9VSUGFL/vD4vsw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.23.tgz", + "integrity": "sha512-lB0XRbtOYYL1tLcYw8BoBaYsFYiR48RPrA0KfA/7RFTr4MV7Bwy/J4+7nLsVnv9FGuQummM3uJ93J3ptaTqFug==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.23.tgz", + "integrity": "sha512-yat73Z/uJ5tRcfRiI4CCTv0FSnwErm3BJQeZAh+1tIP0TUNh6o+mXg338Zl5EKChD+YGp6PN+Dbhs7qa34RxSw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.23.tgz", + "integrity": "sha512-/1xiTjoLuQ+LlbfjJdKkX45qK/M7ARrbLmyf7x3JhyQGMjcxRYVR6Dw81uH3qlMHwT4cfLW4aEVBhP1aNV7VsA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.23.tgz", + "integrity": "sha512-uyPqBU/Zcp6yEAZS4LKj5jEE0q2s4HmlMBIPzbW6cTunZ8cyvjG6YWpIZXb1KK3KTJDe62ltCrk3VzmWHp+iLg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.23.tgz", + "integrity": "sha512-37R/WMkQyUfNhbH7aJrr1uCjDVdnPeTHGeDhZPUNhfoHV0lQuZNCKuNnDvlH/u/nwIYZNdVvz1Igv5rY/zfrzQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.23.tgz", + "integrity": "sha512-H0gztDP60qqr8zoFhAO64waoN5yBXkmYCElFklpd6LPoobtNGNnDe99xOQm28+fuD75YJ7GKHzp/MLCLhw2+vQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.23.tgz", + "integrity": "sha512-x64CEUxi8+EzOAIpCUeuni0bZfzPw/65r8tC5cy5zOq9dY7ysOi5EVQHnzaxS+1NmV+/RVRpmrzGw1QgY2Xpmw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.23.tgz", + "integrity": "sha512-c4MLOIByNHR55n3KoYf9hYDfBRghMjOiHLaoYLhkQkIabb452RWi+HsNgB41sUpSlOAqfpqKPFNg7VrxL3UX9g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.23.tgz", + "integrity": "sha512-kHKyKRIAedYhKug2EJpyJxOUj3VYuamOVA1pY7EimoFPzaF3NeY7e4cFBAISC/Av0/tiV0xlFCt9q0HJ68IBIw==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.23.tgz", + "integrity": "sha512-7ilAiJEPuJJnJp/LiDO0oJm5ygbBPzhchJJh9HsHZzeqO+3PUzItXi+8PuicY08r0AaaOe25LA7sGJ0MzbfBag==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.23.tgz", + "integrity": "sha512-fbL3ggK2wY0D8I5raPIMPhpCvODFE+Bhb5QGtNP3r5aUsRR6TQV+ZBXIaw84iyvKC8vlXiA4fWLGhghAd/h/Zg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.23.tgz", + "integrity": "sha512-GHMDCyfy7+FaNSO8RJ8KCFsnax8fLUsOrj9q5Gi2JmZMY0Zhp75keb5abTFCq2/Oy6KVcT0Dcbyo/bFb4rIFJA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.23.tgz", + "integrity": "sha512-ovk2EX+3rrO1M2lowJfgMb/JPN1VwVYrx0QPUyudxkxLYrWeBxDKQvc6ffO+kB4QlDyTfdtAURrVzu3JeNdA2g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.23.tgz", + "integrity": "sha512-uYYNqbVR+i7k8ojP/oIROAHO9lATLN7H2QeXKt2H310Fc8FJj4y3Wce6hx0VgnJ4k1JDrgbbiXM8rbEgQyg8KA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.23.tgz", + "integrity": "sha512-hAzeBeET0+SbScknPzS2LBY6FVDpgE+CsHSpe6CEoR51PApdn2IB0SyJX7vGelXzlyrnorM4CAsRyb9Qev4h9g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.23.tgz", + "integrity": "sha512-Kttmi3JnohdaREbk6o9e25kieJR379TsEWF0l39PQVHXq3FR6sFKtVPgY8wk055o6IB+rllrzLnbqOw/UV60EA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.23.tgz", + "integrity": "sha512-JtIT0t8ymkpl6YlmOl6zoSWL5cnCgyLaBdf/SiU/Eg3C13r0NbHZWNT/RDEMKK91Y6t79kTs3vyRcNZbfu5a8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.23.tgz", + "integrity": "sha512-cTFaQqT2+ik9e4hePvYtRZQ3pqOvKDVNarzql0VFIzhc0tru/ZgdLoXd6epLiKT+SzoSce6V9YJ+nn6RCn6SHw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -4426,6 +4745,146 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.23.tgz", + "integrity": "sha512-XjnIcZ9KB6lfonCa+jRguXyRYcldmkyZ99ieDksqW/C8bnyEX299yA4QH2XcgijCgaddEZePPTgvx/2imsq7Ig==", + "requires": { + "esbuild-android-arm64": "0.14.23", + "esbuild-darwin-64": "0.14.23", + "esbuild-darwin-arm64": "0.14.23", + "esbuild-freebsd-64": "0.14.23", + "esbuild-freebsd-arm64": "0.14.23", + "esbuild-linux-32": "0.14.23", + "esbuild-linux-64": "0.14.23", + "esbuild-linux-arm": "0.14.23", + "esbuild-linux-arm64": "0.14.23", + "esbuild-linux-mips64le": "0.14.23", + "esbuild-linux-ppc64le": "0.14.23", + "esbuild-linux-riscv64": "0.14.23", + "esbuild-linux-s390x": "0.14.23", + "esbuild-netbsd-64": "0.14.23", + "esbuild-openbsd-64": "0.14.23", + "esbuild-sunos-64": "0.14.23", + "esbuild-windows-32": "0.14.23", + "esbuild-windows-64": "0.14.23", + "esbuild-windows-arm64": "0.14.23" + } + }, + "esbuild-android-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.23.tgz", + "integrity": "sha512-k9sXem++mINrZty1v4FVt6nC5BQCFG4K2geCIUUqHNlTdFnuvcqsY7prcKZLFhqVC1rbcJAr9VSUGFL/vD4vsw==", + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.23.tgz", + "integrity": "sha512-lB0XRbtOYYL1tLcYw8BoBaYsFYiR48RPrA0KfA/7RFTr4MV7Bwy/J4+7nLsVnv9FGuQummM3uJ93J3ptaTqFug==", + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.23.tgz", + "integrity": "sha512-yat73Z/uJ5tRcfRiI4CCTv0FSnwErm3BJQeZAh+1tIP0TUNh6o+mXg338Zl5EKChD+YGp6PN+Dbhs7qa34RxSw==", + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.23.tgz", + "integrity": "sha512-/1xiTjoLuQ+LlbfjJdKkX45qK/M7ARrbLmyf7x3JhyQGMjcxRYVR6Dw81uH3qlMHwT4cfLW4aEVBhP1aNV7VsA==", + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.23.tgz", + "integrity": "sha512-uyPqBU/Zcp6yEAZS4LKj5jEE0q2s4HmlMBIPzbW6cTunZ8cyvjG6YWpIZXb1KK3KTJDe62ltCrk3VzmWHp+iLg==", + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.23.tgz", + "integrity": "sha512-37R/WMkQyUfNhbH7aJrr1uCjDVdnPeTHGeDhZPUNhfoHV0lQuZNCKuNnDvlH/u/nwIYZNdVvz1Igv5rY/zfrzQ==", + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.23.tgz", + "integrity": "sha512-H0gztDP60qqr8zoFhAO64waoN5yBXkmYCElFklpd6LPoobtNGNnDe99xOQm28+fuD75YJ7GKHzp/MLCLhw2+vQ==", + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.23.tgz", + "integrity": "sha512-x64CEUxi8+EzOAIpCUeuni0bZfzPw/65r8tC5cy5zOq9dY7ysOi5EVQHnzaxS+1NmV+/RVRpmrzGw1QgY2Xpmw==", + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.23.tgz", + "integrity": "sha512-c4MLOIByNHR55n3KoYf9hYDfBRghMjOiHLaoYLhkQkIabb452RWi+HsNgB41sUpSlOAqfpqKPFNg7VrxL3UX9g==", + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.23.tgz", + "integrity": "sha512-kHKyKRIAedYhKug2EJpyJxOUj3VYuamOVA1pY7EimoFPzaF3NeY7e4cFBAISC/Av0/tiV0xlFCt9q0HJ68IBIw==", + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.23.tgz", + "integrity": "sha512-7ilAiJEPuJJnJp/LiDO0oJm5ygbBPzhchJJh9HsHZzeqO+3PUzItXi+8PuicY08r0AaaOe25LA7sGJ0MzbfBag==", + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.23.tgz", + "integrity": "sha512-fbL3ggK2wY0D8I5raPIMPhpCvODFE+Bhb5QGtNP3r5aUsRR6TQV+ZBXIaw84iyvKC8vlXiA4fWLGhghAd/h/Zg==", + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.23.tgz", + "integrity": "sha512-GHMDCyfy7+FaNSO8RJ8KCFsnax8fLUsOrj9q5Gi2JmZMY0Zhp75keb5abTFCq2/Oy6KVcT0Dcbyo/bFb4rIFJA==", + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.23.tgz", + "integrity": "sha512-ovk2EX+3rrO1M2lowJfgMb/JPN1VwVYrx0QPUyudxkxLYrWeBxDKQvc6ffO+kB4QlDyTfdtAURrVzu3JeNdA2g==", + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.23.tgz", + "integrity": "sha512-uYYNqbVR+i7k8ojP/oIROAHO9lATLN7H2QeXKt2H310Fc8FJj4y3Wce6hx0VgnJ4k1JDrgbbiXM8rbEgQyg8KA==", + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.23.tgz", + "integrity": "sha512-hAzeBeET0+SbScknPzS2LBY6FVDpgE+CsHSpe6CEoR51PApdn2IB0SyJX7vGelXzlyrnorM4CAsRyb9Qev4h9g==", + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.23.tgz", + "integrity": "sha512-Kttmi3JnohdaREbk6o9e25kieJR379TsEWF0l39PQVHXq3FR6sFKtVPgY8wk055o6IB+rllrzLnbqOw/UV60EA==", + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.23.tgz", + "integrity": "sha512-JtIT0t8ymkpl6YlmOl6zoSWL5cnCgyLaBdf/SiU/Eg3C13r0NbHZWNT/RDEMKK91Y6t79kTs3vyRcNZbfu5a8g==", + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.23", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.23.tgz", + "integrity": "sha512-cTFaQqT2+ik9e4hePvYtRZQ3pqOvKDVNarzql0VFIzhc0tru/ZgdLoXd6epLiKT+SzoSce6V9YJ+nn6RCn6SHw==", + "optional": true + }, "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", diff --git a/package.json b/package.json index 6be3cc219..ec00d64ee 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "watch:docs": "node scripts/generate-docs --watch", "watch:docs-lint": "node scripts/lint-docs --watch", "build": "run-p build:browser build:min build:stream-min", - "build:browser": "node scripts/bundler browser.js -output mithril.js", + "build:browser": "esbuild --bundle browser.js --outfile=mithril.js --format=iife --global-name=m --target=es5", "build:docs": "node scripts/generate-docs", - "build:min": "node scripts/bundler browser.js -output mithril.min.js -minify -save", + "build:min": "esbuild --bundle browser.js --outfile=mithril.min.js --format=iife --global-name=m --target=es5 --minify", "build:stream-min": "node scripts/minify-stream", "cleanup:lint": "rimraf .eslintcache .lint-docs-cache", "lint": "run-s -cn lint:**", @@ -34,6 +34,7 @@ "@babel/parser": "^7.7.5", "benchmark": "^2.1.4", "chokidar": "^3.2.1", + "esbuild": "^0.14.23", "escape-string-regexp": "^2.0.0", "eslint": "^8.9.0", "gh-pages": "^2.1.1", diff --git a/scripts/_bundler-impl.js b/scripts/_bundler-impl.js deleted file mode 100644 index 49c458d55..000000000 --- a/scripts/_bundler-impl.js +++ /dev/null @@ -1,183 +0,0 @@ -"use strict" - -const fs = require("fs") -const path = require("path") -const execFileSync = require("child_process").execFileSync -const util = require("util") - -const readFile = util.promisify(fs.readFile) -const access = util.promisify(fs.access) - -function isFile(filepath) { - return access(filepath).then(() => true, () => false) -} -function escapeRegExp(string) { - return string.replace(/[|\\{}()[\]^$+*?.-]/g, "\\$&") -} -function escapeReplace(string) { - return string.replace(/\$/g, "\\$&") -} - -async function resolve(filepath, filename) { - if (filename[0] !== ".") { - // resolve as npm dependency - const packagePath = `./node_modules/${filename}/package.json` - let json, meta - - try { - json = await readFile(packagePath, "utf8") - } catch (e) { - meta = {} - } - - if (json) { - try { - meta = JSON.parse(json) - } - catch (e) { - throw new Error(`invalid JSON for ${packagePath}: ${json}`) - } - } - - const main = `./node_modules/${filename}/${meta.main || `${filename}.js`}` - return path.resolve(await isFile(main) ? main : `./node_modules/${filename}/index.js`) - } - else { - // resolve as local dependency - return path.resolve(path.dirname(filepath), filename + ".js") - } -} - -function matchAll(str, regexp) { - regexp.lastIndex = 0 - const result = [] - let exec - while ((exec = regexp.exec(str)) != null) result.push(exec) - return result -} - -let error -module.exports = async (input) => { - const modules = new Map() - const bindings = new Map() - const declaration = /^\s*(?:var|let|const|function)[\t ]+([\w_$]+)/gm - const include = /(?:((?:var|let|const|,|)[\t ]*)([\w_$\.\[\]"'`]+)(\s*=\s*))?require\(([^\)]+)\)(\s*[`\.\(\[])?/gm - let uuid = 0 - async function process(filepath, data) { - for (const [, binding] of matchAll(data, declaration)) bindings.set(binding, 0) - - const tasks = [] - - for (const [, def = "", variable = "", eq = "", dep, rest = ""] of matchAll(data, include)) { - tasks.push({filename: JSON.parse(dep), def, variable, eq, rest}) - } - - const imports = await Promise.all( - tasks.map((t) => resolve(filepath, t.filename)) - ) - - const results = [] - for (const [i, task] of tasks.entries()) { - const dependency = imports[i] - let pre = "", def = task.def - if (def[0] === ",") def = "\nvar ", pre = "\n" - const localUUID = uuid // global uuid can update from nested `process` call, ensure same id is used on declaration and consumption - const existingModule = modules.get(dependency) - modules.set(dependency, task.rest ? `_${localUUID}` : task.variable) - const code = await process( - dependency, - pre + ( - existingModule == null - ? await exportCode(task.filename, dependency, def, task.variable, task.eq, task.rest, localUUID) - : def + task.variable + task.eq + existingModule - ) - ) - uuid++ - results.push(code + task.rest) - } - - let i = 0 - return data.replace(include, () => results[i++]) - } - - async function exportCode(filename, filepath, def, variable, eq, rest, uuid) { - let code = await readFile(filepath, "utf-8") - // if there's a syntax error, report w/ proper stack trace - try { - new Function(code) - } - catch (e) { - try { - execFileSync("node", ["--check", filepath], { - stdio: "pipe", - }) - } - catch (e) { - if (e.message !== error) { - error = e.message - console.log(`\x1b[31m${e.message}\x1b[0m`) - } - } - } - - // disambiguate collisions - const targetPromises = [] - code.replace(include, (match, def, variable, eq, dep) => { - targetPromises.push(resolve(filepath, JSON.parse(dep))) - }) - - const ignoredTargets = await Promise.all(targetPromises) - const ignored = new Set() - - for (const target of ignoredTargets) { - const binding = modules.get(target) - if (binding != null) ignored.add(binding) - } - - if (new RegExp(`module\\.exports\\s*=\\s*${variable}\s*$`, "m").test(code)) ignored.add(variable) - for (const [binding, count] of bindings) { - if (!ignored.has(binding)) { - const before = code - code = code.replace( - new RegExp(`(\\b)${escapeRegExp(binding)}\\b`, "g"), - escapeReplace(binding) + count - ) - if (before !== code) bindings.set(binding, count + 1) - } - } - - // fix strings that got mangled by collision disambiguation - const string = /(["'])((?:\\\1|.)*?)(\1)/g - const candidates = Array.from(bindings, ([binding, count]) => escapeRegExp(binding) + (count - 1)).join("|") - const variables = new RegExp(candidates, "g") - code = code.replace(string, (match, open, data, close) => { - const fixed = data.replace(variables, (match) => match.replace(/\d+$/, "")) - return open + fixed + close - }) - - //fix props - const props = new RegExp(`((?:[^:]\\/\\/.*)?\\.\\s*)(${candidates})|([\\{,]\\s*)(${candidates})(\\s*:)`, "gm") - code = code.replace(props, (match, dot, a, pre, b, post) => { - // Don't do anything because dot was matched in a comment - if (dot && dot.indexOf("//") === 1) return match - if (dot) return dot + a.replace(/\d+$/, "") - return pre + b.replace(/\d+$/, "") + post - }) - - return code - .replace(/("|')use strict\1;?/gm, "") // remove extraneous "use strict" - .replace(/module\.exports\s*=\s*/gm, escapeReplace(rest ? `var _${uuid}` + eq : def + (rest ? "_" : "") + variable + eq)) // export - + (rest ? `\n${def}${variable}${eq}_${uuid}` : "") // if `rest` is truthy, it means the expression is fluent or higher-order (e.g. require(path).foo or require(path)(foo) - } - - const code = ";(function() {\n" + - (await process(path.resolve(input), await readFile(input, "utf-8"))) - .replace(/^\s*((?:var|let|const|)[\t ]*)([\w_$\.]+)(\s*=\s*)(\2)(?=[\s]+(\w)|;|$)/gm, "") // remove assignments to self - .replace(/;+(\r|\n|$)/g, ";$1") // remove redundant semicolons - .replace(/(\r|\n)+/g, "\n").replace(/(\r|\n)$/, "") + // remove multiline breaks - "\n}());" - - //try {new Function(code); console.log(`build completed at ${new Date()}`)} catch (e) {} - error = null - return code -} diff --git a/scripts/bundler-readme.md b/scripts/bundler-readme.md deleted file mode 100644 index 949d1ac9c..000000000 --- a/scripts/bundler-readme.md +++ /dev/null @@ -1,22 +0,0 @@ -# bundler.js - -Simplistic CommonJS module bundler - -Version: 0.1 -License: MIT - -## About - -This bundler attempts to aggressively bundle CommonJS modules by assuming the dependency tree is static, similar to what Rollup does for ES6 modules. - -Most browsers don't support ES6 `import/export` syntax, but we can achieve modularity by using CommonJS module syntax and transpiling it. - -Webpack is conservative and treats CommonJS modules as non-statically-analyzable since `require` and `module.exports` are legally allowed everywhere. Therefore, it must generate extra code to resolve dependencies at runtime (i.e. `__webpack_require()`). Rollup only works with ES6 modules. ES6 modules can be bundled more efficiently because they are statically analyzable, but some use cases are difficult to handle due to ES6's support for cyclic dependencies and hosting rules. This bundler assumes code is written in CommonJS style but follows a strict set of rules that emulate statically analyzable code and favors the usage of the factory pattern instead of relying on obscure corners of the JavaScript language (hoisting rules and binding semantics). - -### Caveats - -- Only supports modules that have the `require` and `module.exports` statement declared at the top-level scope before all other code, i.e. it does not support CommonJS modules that rely on dynamic importing/exporting. This means modules should only export a pure function or export a factory function if there are multiple statements and/or internal module state. The factory function pattern allows easier dependency injection in stateful modules, thus making modules testable. -- Changes the semantics of value/binding exporting between unbundled and bundled code, and therefore relying on those semantics is discouraged. -- Top level strictness is infectious (i.e. if entry file is in `"use strict"` mode, all modules inherit strict mode, and conversely, if the entry file is not in strict mode, all modules are pulled out of strict mode) -- Currently only supports assignments to `module.exports` (i.e. `module.exports.foo = bar` will not work) -- It is tiny and dependency-free because it uses regular expressions, and it only supports the narrow range of import/export declaration patterns outlined above. diff --git a/scripts/bundler.js b/scripts/bundler.js deleted file mode 100644 index 2c3f63333..000000000 --- a/scripts/bundler.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict" - -const fs = require("fs") -const zlib = require("zlib") -const chokidar = require("chokidar") -const Terser = require("terser") -const util = require("util") - -const readFile = util.promisify(fs.readFile) -const writeFile = util.promisify(fs.writeFile) -const gzip = util.promisify(zlib.gzip) - -const bundle = require("./_bundler-impl") - -const aliases = {o: "output", m: "minify", w: "watch", s: "save"} -const params = Object.create(null) -let command -for (let arg of process.argv.slice(2)) { - if (arg[0] === '"') arg = JSON.parse(arg) - if (arg[0] === "-") { - if (command != null) add(true) - command = arg.replace(/\-+/g, "") - } - else if (command != null) add(arg) - else params.input = arg -} -if (command != null) add(true) - -function add(value) { - params[aliases[command] || command] = value - command = null -} - -function format(n) { - return n.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") -} - -async function build() { - const original = await bundle(params.input) - if (!params.minify) { - await writeFile(params.output, original, "utf-8") - return - } - console.log("minifying...") - const minified = Terser.minify(original) - if (minified.error) throw new Error(minified.error) - await writeFile(params.output, minified.code, "utf-8") - const originalSize = Buffer.byteLength(original, "utf-8") - const compressedSize = Buffer.byteLength(minified.code, "utf-8") - const originalGzipSize = (await gzip(original)).byteLength - const compressedGzipSize = (await gzip(minified.code)).byteLength - - console.log("Original size: " + format(originalGzipSize) + " bytes gzipped (" + format(originalSize) + " bytes uncompressed)") - console.log("Compiled size: " + format(compressedGzipSize) + " bytes gzipped (" + format(compressedSize) + " bytes uncompressed)") - - if (params.save) { - const readme = await readFile("./README.md", "utf8") - const kb = compressedGzipSize / 1000 - - await writeFile("./README.md", - readme.replace( - /()(.+?)()/, - "$1" + (kb % 1 ? kb.toFixed(2) : kb) + " KB$3" - ) - ) - } -} - -build() -if (params.watch) chokidar.watch(".", {ignored: params.output}).on("all", build) diff --git a/scripts/tests/test-bundler.js b/scripts/tests/test-bundler.js deleted file mode 100644 index b9208aa06..000000000 --- a/scripts/tests/test-bundler.js +++ /dev/null @@ -1,296 +0,0 @@ -"use strict" - -const fs = require("fs") -const util = require("util") -const path = require("path") -const access = util.promisify(fs.access) -const writeFile = util.promisify(fs.writeFile) -const unlink = util.promisify(fs.unlink) - -const o = require("ospec") -const bundle = require("../_bundler-impl") - -o.spec("bundler", async () => { - let filesCreated - const root = path.resolve(__dirname, "../..") - const p = (file) => path.join(root, file) - - async function write(filepath, data) { - try { - await access(p(filepath)) - } catch (e) { - return writeFile(p(filepath), data, "utf8") - } - throw new Error(`Don't call \`write('${filepath}')\`. Cannot overwrite file.`) - } - - function setup(files) { - filesCreated = Object.keys(files) - return Promise.all(filesCreated.map((f) => write(f, files[f]))) - } - - o.afterEach(() => Promise.all( - filesCreated.map((filepath) => unlink(p(filepath))) - )) - - o("relative imports works", async () => { - await setup({ - "a.js": 'var b = require("./b")', - "b.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b = 1\n}());") - }) - o("relative imports works with semicolons", async () => { - await setup({ - "a.js": 'var b = require("./b");', - "b.js": "module.exports = 1;", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b = 1;\n}());") - }) - o("relative imports works with let", async () => { - await setup({ - "a.js": 'let b = require("./b")', - "b.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nlet b = 1\n}());") - }) - o("relative imports works with const", async () => { - await setup({ - "a.js": 'const b = require("./b")', - "b.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nconst b = 1\n}());") - }) - o("relative imports works with assignment", async () => { - await setup({ - "a.js": 'var a = {}\na.b = require("./b")', - "b.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar a = {}\na.b = 1\n}());") - }) - o("relative imports works with reassignment", async () => { - await setup({ - "a.js": 'var b = {}\nb = require("./b")', - "b.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b = {}\nb = 1\n}());") - }) - o("relative imports removes extra use strict", async () => { - await setup({ - "a.js": '"use strict"\nvar b = require("./b")', - "b.js": '"use strict"\nmodule.exports = 1', - }) - - o(await bundle(p("a.js"))).equals(';(function() {\n"use strict"\nvar b = 1\n}());') - }) - o("relative imports removes extra use strict using single quotes", async () => { - await setup({ - "a.js": "'use strict'\nvar b = require(\"./b\")", - "b.js": "'use strict'\nmodule.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\n'use strict'\nvar b = 1\n}());") - }) - o("relative imports removes extra use strict using mixed quotes", async () => { - await setup({ - "a.js": '"use strict"\nvar b = require("./b")', - "b.js": "'use strict'\nmodule.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(';(function() {\n"use strict"\nvar b = 1\n}());') - }) - o("works w/ window", async () => { - await setup({ - "a.js": 'window.a = 1\nvar b = require("./b")', - "b.js": "module.exports = function() {return a}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nwindow.a = 1\nvar b = function() {return a}\n}());") - }) - o("works without assignment", async () => { - await setup({ - "a.js": 'require("./b")', - "b.js": "1 + 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\n1 + 1\n}());") - }) - o("works if used fluently", async () => { - await setup({ - "a.js": 'var b = require("./b").toString()', - "b.js": "module.exports = []", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar _0 = []\nvar b = _0.toString()\n}());") - }) - o("works if used fluently w/ multiline", async () => { - await setup({ - "a.js": 'var b = require("./b")\n\t.toString()', - "b.js": "module.exports = []", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar _0 = []\nvar b = _0\n\t.toString()\n}());") - }) - o("works if used w/ curry", async () => { - await setup({ - "a.js": 'var b = require("./b")()', - "b.js": "module.exports = function() {}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar _0 = function() {}\nvar b = _0()\n}());") - }) - o("works if used w/ curry w/ multiline", async () => { - await setup({ - "a.js": 'var b = require("./b")\n()', - "b.js": "module.exports = function() {}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar _0 = function() {}\nvar b = _0\n()\n}());") - }) - o("works if used fluently in one place and not in another", async () => { - await setup({ - "a.js": 'var b = require("./b").toString()\nvar c = require("./c")', - "b.js": "module.exports = []", - "c.js": 'var b = require("./b")\nmodule.exports = function() {return b}', - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar _0 = []\nvar b = _0.toString()\nvar b0 = _0\nvar c = function() {return b0}\n}());") - }) - o("works if used in sequence", async () => { - await setup({ - "a.js": 'var b = require("./b"), c = require("./c")', - "b.js": "module.exports = 1", - "c.js": "var x\nmodule.exports = 2", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b = 1\nvar x\nvar c = 2\n}());") - }) - o("works if assigned to property", async () => { - await setup({ - "a.js": 'var x = {}\nx.b = require("./b")\nx.c = require("./c")', - "b.js": "var bb = 1\nmodule.exports = bb", - "c.js": "var cc = 2\nmodule.exports = cc", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar x = {}\nvar bb = 1\nx.b = bb\nvar cc = 2\nx.c = cc\n}());") - }) - o("works if assigned to property using bracket notation", async () => { - await setup({ - "a.js": 'var x = {}\nx["b"] = require("./b")\nx["c"] = require("./c")', - "b.js": "var bb = 1\nmodule.exports = bb", - "c.js": "var cc = 2\nmodule.exports = cc", - }) - - o(await bundle(p("a.js"))).equals(';(function() {\nvar x = {}\nvar bb = 1\nx["b"] = bb\nvar cc = 2\nx["c"] = cc\n}());') - }) - o("works if collision", async () => { - await setup({ - "a.js": 'var b = require("./b")', - "b.js": "var b = 1\nmodule.exports = 2", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b0 = 1\nvar b = 2\n}());") - }) - o("works if multiple aliases", async () => { - await setup({ - "a.js": 'var b = require("./b")\n', - "b.js": 'var b = require("./c")\nb.x = 1\nmodule.exports = b', - "c.js": "var b = {}\nmodule.exports = b", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b = {}\nb.x = 1\n}());") - }) - o("works if multiple collision", async () => { - await setup({ - "a.js": 'var b = require("./b")\nvar c = require("./c")\nvar d = require("./d")', - "b.js": "var a = 1\nmodule.exports = a", - "c.js": "var a = 2\nmodule.exports = a", - "d.js": "var a = 3\nmodule.exports = a", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar a = 1\nvar b = a\nvar a0 = 2\nvar c = a0\nvar a1 = 3\nvar d = a1\n}());") - }) - o("works if included multiple times", async () => { - await setup({ - "a.js": "module.exports = 123", - "b.js": 'var a = require("./a").toString()\nmodule.exports = a', - "c.js": 'var a = require("./a").toString()\nvar b = require("./b")', - }) - - o(await bundle(p("c.js"))).equals(";(function() {\nvar _0 = 123\nvar a = _0.toString()\nvar a0 = _0.toString()\nvar b = a0\n}());") - }) - o("works if included multiple times reverse", async () => { - await setup({ - "a.js": "module.exports = 123", - "b.js": 'var a = require("./a").toString()\nmodule.exports = a', - "c.js": 'var b = require("./b")\nvar a = require("./a").toString()', - }) - - o(await bundle(p("c.js"))).equals(";(function() {\nvar _0 = 123\nvar a0 = _0.toString()\nvar b = a0\nvar a = _0.toString()\n}());") - }) - o("reuses binding if possible", async () => { - await setup({ - "a.js": 'var b = require("./b")\nvar c = require("./c")', - "b.js": 'var d = require("./d")\nmodule.exports = function() {return d + 1}', - "c.js": 'var d = require("./d")\nmodule.exports = function() {return d + 2}', - "d.js": "module.exports = 1", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar d = 1\nvar b = function() {return d + 1}\nvar c = function() {return d + 2}\n}());") - }) - o("disambiguates conflicts if imported collides with itself", async () => { - await setup({ - "a.js": 'var b = require("./b")', - "b.js": "var b = 1\nmodule.exports = function() {return b}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b0 = 1\nvar b = function() {return b0}\n}());") - }) - o("disambiguates conflicts if imported collides with something else", async () => { - await setup({ - "a.js": 'var a = 1\nvar b = require("./b")', - "b.js": "var a = 2\nmodule.exports = function() {return a}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar a = 1\nvar a0 = 2\nvar b = function() {return a0}\n}());") - }) - o("disambiguates conflicts if imported collides with function declaration", async () => { - await setup({ - "a.js": 'function a() {}\nvar b = require("./b")', - "b.js": "var a = 2\nmodule.exports = function() {return a}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nfunction a() {}\nvar a0 = 2\nvar b = function() {return a0}\n}());") - }) - o("disambiguates conflicts if imported collides with another module's private", async () => { - await setup({ - "a.js": 'var b = require("./b")\nvar c = require("./c")', - "b.js": "var a = 1\nmodule.exports = function() {return a}", - "c.js": "var a = 2\nmodule.exports = function() {return a}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar a = 1\nvar b = function() {return a}\nvar a0 = 2\nvar c = function() {return a0}\n}());") - }) - o("does not mess up strings", async () => { - await setup({ - "a.js": 'var b = require("./b")', - "b.js": 'var b = "b b b \\" b"\nmodule.exports = function() {return b}', - }) - - o(await bundle(p("a.js"))).equals(';(function() {\nvar b0 = "b b b \\\" b"\nvar b = function() {return b0}\n}());') - }) - o("does not mess up properties", async () => { - await setup({ - "a.js": 'var b = require("./b")', - "b.js": "var b = {b: 1}\nmodule.exports = function() {return b.b}", - }) - - o(await bundle(p("a.js"))).equals(";(function() {\nvar b0 = {b: 1}\nvar b = function() {return b0.b}\n}());") - }) -})