diff --git a/.gitignore b/.gitignore
index 58b805f..475f26d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
.DS_Store
-node_modules/
\ No newline at end of file
+node_modules/
+coverage/
+package-lock.json
diff --git a/.npmignore b/.npmignore
index 391f31b..ab01da5 100644
--- a/.npmignore
+++ b/.npmignore
@@ -8,4 +8,4 @@ _config.yml
.travis.yml
babel-plugins.json
package-lock.json
-rollup.coinfig.js
\ No newline at end of file
+rollup.config.js
\ No newline at end of file
diff --git a/README.md b/README.md
index c4229aa..9e8e8cd 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,34 @@
[](https://github.com/WebReflection/donate) [](https://coveralls.io/github/WebReflection/domdiff?branch=master) [](https://travis-ci.org/WebReflection/domdiff) [](https://opensource.org/licenses/ISC)
-A vDOM-less implementation of the [snabbdom](https://github.com/snabbdom/snabbdom) diffing logic.
+A vDOM-less implementation of the [petit-dom](https://github.com/yelouafi/petit-dom) diffing logic, at the core of [hyperHTML](https://github.com/WebReflection/hyperHTML).
+
+
+### V2 breaking change
+
+ * the good old snabdom diff logic has been 100% replaced
+ * lists with `null` or `undefined` nodes are not allowed anymore
+
+... but I guess having null nodes in the equation was quite possibly a bad idea in the first place ...
+
+#### V2 Diffing Strategies:
+
+ * common prefixes
+ * common suffixes
+ * skip same lists
+ * add boundaries
+ * remove boundaries
+ * simple sub-sequences insertions and removals
+ * one to many and many to one replacements
+ * fast inverted list swap
+ * O(ND) algo with a limit of 50 attempts
+ * last fallback with a simplified Hunt Szymanski algorithm
+
+The current goal is to have in about 1K the best DOM diffing library out there.
+
+#### V1 breaking change
+
+The signature has moved from `parent, current[], future[], getNode(), beforeNode` to `parent, current[], future[], {before, compare(), node()}`.
### Signature
@@ -13,8 +40,10 @@ futureNodes = domdiff(
parentNode, // where changes happen
currentNodes, // Array of current items/nodes
futureNodes, // Array of future items/nodes (returned)
- getNode, // optional way to retrieve a node from an item
- beforeNode // optional item/node to use as insertBefore delimiter
+ options // optional object with one of the following properties
+ // before: domNode
+ // compare(generic, generic) => true if same generic
+ // node(generic) => Node
);
```
@@ -56,3 +85,95 @@ parentNode.textContent;
### Compatibility:
Every. JavaScript. Engine.
+
+
+### A `{node: (generic, info) => node}` callback for complex data
+
+The optional `{node: (generic, info) => node}` is invoked per each operation on the DOM.
+
+This can be useful to represent node through wrappers, whenever that is needed.
+
+The passed `info` value can be:
+
+ * `1` when the item/node is being appended
+ * `0` when the item/node is being used as insert _before_ reference
+ * `-0` when the item/node is being used as insert _after_ reference
+ * `-1` when the item/node is being removed
+
+[Example](https://codepen.io/WebReflection/pen/bYJVPd?editors=0010)
+
+```js
+function node(item, i) {
+ // case removal or case after
+ if ((1 / i) < 0) {
+ // case removal
+ if (i) {
+ // if the item has more than a node
+ // remove all other nodes at once
+ if (item.length > 1) {
+ const range = document.createRange();
+ range.setStartBefore(item[1]);
+ range.setEndAfter(item[item.length - 1]);
+ range.deleteContents();
+ }
+ // return the first node to be removed
+ return item[0];
+ }
+ // case after
+ else {
+ return item[item.length - 1];
+ }
+ }
+ // case insert
+ else if (i) {
+ const fragment = document.createDocumentFragment();
+ fragment.append(...item);
+ return fragment;
+ }
+ // case before
+ else {
+ return item[0];
+ }
+}
+
+const and = [document.createTextNode(' & ')];
+
+const Bob = [
+ document.createTextNode('B'),
+ document.createTextNode('o'),
+ document.createTextNode('b')
+];
+
+const Lucy = [
+ document.createTextNode('L'),
+ document.createTextNode('u'),
+ document.createTextNode('c'),
+ document.createTextNode('y')
+];
+
+// clean the body for demo purpose
+document.body.textContent = '';
+let content = domdiff(
+ document.body,
+ [],
+ [Bob, and, Lucy],
+ {node}
+);
+
+// ... later on ...
+content = domdiff(
+ document.body,
+ content,
+ [Lucy, and, Bob],
+ {node}
+);
+
+// clean up
+domdiff(
+ document.body,
+ content,
+ [],
+ {node}
+);
+
+```
diff --git a/babel-plugins.json b/babel-plugins.json
deleted file mode 100644
index d982204..0000000
--- a/babel-plugins.json
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- "check-es2015-constants",
- "transform-es2015-arrow-functions",
- "transform-es2015-block-scoped-functions",
- "transform-es2015-block-scoping",
- "transform-es2015-computed-properties",
- "transform-es2015-destructuring",
- "transform-es2015-duplicate-keys",
- "transform-es2015-function-name",
- "transform-es2015-literals",
- "transform-es2015-shorthand-properties",
- "transform-es2015-spread"
-]
\ No newline at end of file
diff --git a/cjs/index.js b/cjs/index.js
index ffadf64..2345036 100644
--- a/cjs/index.js
+++ b/cjs/index.js
@@ -1,117 +1,217 @@
'use strict';
-/*! (c) 2017 Andrea Giammarchi (ISC) */
+/*! (c) 2018 Andrea Giammarchi (ISC) */
-/**
- * This code is a revisited port of the snabbdom vDOM diffing logic,
- * the same that fuels as fork Vue.js, Preact, and other libraries.
- * @credits https://github.com/snabbdom/snabbdom
- */
-
-const identity = O => O;
+const {
+ eqeq, identity, indexOf, isReversed, next, append, remove, smartDiff
+} = require('./utils.js');
const domdiff = (
parentNode, // where changes happen
currentNodes, // Array of current items/nodes
futureNodes, // Array of future items/nodes
- getNode, // optional way to retrieve a node from an item
- beforeNode // optional item/node to use as insertBefore delimiter
+ options // optional object with one of the following properties
+ // before: domNode
+ // compare(generic, generic) => true if same generic
+ // node(generic) => Node
) => {
- const get = getNode || identity;
- const before = beforeNode == null ? null : get(beforeNode);
- let currentStart = 0, futureStart = 0;
- let currentEnd = currentNodes.length - 1;
- let currentStartNode = currentNodes[0];
- let currentEndNode = currentNodes[currentEnd];
- let futureEnd = futureNodes.length - 1;
- let futureStartNode = futureNodes[0];
- let futureEndNode = futureNodes[futureEnd];
- while (currentStart <= currentEnd && futureStart <= futureEnd) {
- if (currentStartNode == null) {
- currentStartNode = currentNodes[++currentStart];
- }
- else if (currentEndNode == null) {
- currentEndNode = currentNodes[--currentEnd];
- }
- else if (futureStartNode == null) {
- futureStartNode = futureNodes[++futureStart];
- }
- else if (futureEndNode == null) {
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentStartNode == futureStartNode) {
- currentStartNode = currentNodes[++currentStart];
- futureStartNode = futureNodes[++futureStart];
- }
- else if (currentEndNode == futureEndNode) {
- currentEndNode = currentNodes[--currentEnd];
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentStartNode == futureEndNode) {
- parentNode.insertBefore(
- get(currentStartNode),
- get(currentEndNode).nextSibling || before
+ if (!options)
+ options = {};
+
+ const compare = options.compare || eqeq;
+ const get = options.node || identity;
+ const before = options.before == null ? null : get(options.before, 0);
+
+ const currentLength = currentNodes.length;
+ let currentEnd = currentLength;
+ let currentStart = 0;
+
+ let futureEnd = futureNodes.length;
+ let futureStart = 0;
+
+ // common prefix
+ while (
+ currentStart < currentEnd &&
+ futureStart < futureEnd &&
+ compare(currentNodes[currentStart], futureNodes[futureStart])
+ ) {
+ currentStart++;
+ futureStart++;
+ }
+
+ // common suffix
+ while (
+ currentStart < currentEnd &&
+ futureStart < futureEnd &&
+ compare(currentNodes[currentEnd - 1], futureNodes[futureEnd - 1])
+ ) {
+ currentEnd--;
+ futureEnd--;
+ }
+
+ const currentSame = currentStart === currentEnd;
+ const futureSame = futureStart === futureEnd;
+
+ // same list
+ if (currentSame && futureSame)
+ return futureNodes;
+
+ // only stuff to add
+ if (currentSame && futureStart < futureEnd) {
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ next(get, currentNodes, currentStart, currentLength, before)
+ );
+ return futureNodes;
+ }
+
+ // only stuff to remove
+ if (futureSame && currentStart < currentEnd) {
+ remove(
+ get,
+ currentNodes,
+ currentStart,
+ currentEnd
+ );
+ return futureNodes;
+ }
+
+ const currentChanges = currentEnd - currentStart;
+ const futureChanges = futureEnd - futureStart;
+ let i = -1;
+
+ // 2 simple indels: the shortest sequence is a subsequence of the longest
+ if (currentChanges < futureChanges) {
+ i = indexOf(
+ futureNodes,
+ futureStart,
+ futureEnd,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ compare
+ );
+ // inner diff
+ if (-1 < i) {
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ i,
+ get(currentNodes[currentStart], 0)
);
- currentStartNode = currentNodes[++currentStart];
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentEndNode == futureStartNode) {
- parentNode.insertBefore(
- get(currentEndNode),
- get(currentStartNode)
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ i + currentChanges,
+ futureEnd,
+ next(get, currentNodes, currentEnd, currentLength, before)
);
- currentEndNode = currentNodes[--currentEnd];
- futureStartNode = futureNodes[++futureStart];
- }
- else {
- let index = currentNodes.indexOf(futureStartNode);
- if (index < 0) {
- parentNode.insertBefore(
- get(futureStartNode),
- get(currentStartNode)
- );
- futureStartNode = futureNodes[++futureStart];
- }
- else {
- let el = currentNodes[index];
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
- /* istanbul ignore if */
- if (el != futureStartNode) {
- parentNode.insertBefore(
- get(futureStartNode),
- get(currentStartNode)
- );
- } else {
- currentNodes[index] = null;
- parentNode.insertBefore(
- get(el),
- get(currentStartNode)
- );
- }
- futureStartNode = futureNodes[++futureStart];
- }
+ return futureNodes;
}
}
- if (currentStart > currentEnd) {
- const pin = futureNodes[futureEnd + 1];
- const place = pin != null ? get(pin) : before;
- while (futureStart <= futureEnd) {
- const ch = futureNodes[futureStart++];
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
- /* istanbul ignore else */
- if (ch != null) parentNode.insertBefore(get(ch), place);
+ /* istanbul ignore else */
+ else if (futureChanges < currentChanges) {
+ i = indexOf(
+ currentNodes,
+ currentStart,
+ currentEnd,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ compare
+ );
+ // outer diff
+ if (-1 < i) {
+ remove(
+ get,
+ currentNodes,
+ currentStart,
+ i
+ );
+ remove(
+ get,
+ currentNodes,
+ i + futureChanges,
+ currentEnd
+ );
+ return futureNodes;
}
}
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
+
+ // common case with one replacement for many nodes
+ // or many nodes replaced for a single one
/* istanbul ignore else */
- else if (futureStart > futureEnd) {
- while (currentStart <= currentEnd) {
- const ch = currentNodes[currentStart++];
- if (ch != null) parentNode.removeChild(get(ch));
- }
+ if ((currentChanges < 2 || futureChanges < 2)) {
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ get(currentNodes[currentStart], 0)
+ );
+ remove(
+ get,
+ currentNodes,
+ currentStart,
+ currentEnd
+ );
+ return futureNodes;
+ }
+
+ // the half match diff part has been skipped in petit-dom
+ // https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L391-L397
+ // accordingly, I think it's safe to skip in here too
+ // if one day it'll come out like the speediest thing ever to do
+ // then I might add it in here too
+
+ // Extra: before going too fancy, what about reversed lists ?
+ // This should bail out pretty quickly if that's not the case.
+ if (
+ currentChanges === futureChanges &&
+ isReversed(
+ futureNodes,
+ futureEnd,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ compare
+ )
+ ) {
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ next(get, currentNodes, currentEnd, currentLength, before)
+ );
+ return futureNodes;
}
+
+ // last resort through a smart diff
+ smartDiff(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ futureChanges,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ currentChanges,
+ currentLength,
+ compare,
+ before
+ );
+
return futureNodes;
};
diff --git a/cjs/package.json b/cjs/package.json
new file mode 100644
index 0000000..0292b99
--- /dev/null
+++ b/cjs/package.json
@@ -0,0 +1 @@
+{"type":"commonjs"}
\ No newline at end of file
diff --git a/cjs/utils.js b/cjs/utils.js
new file mode 100644
index 0000000..efc98cc
--- /dev/null
+++ b/cjs/utils.js
@@ -0,0 +1,388 @@
+'use strict';
+const {indexOf: iOF} = require('uarray');
+
+const append = (get, parent, children, start, end, before) => {
+ const isSelect = 'selectedIndex' in parent;
+ let noSelection = isSelect;
+ while (start < end) {
+ const child = get(children[start], 1);
+ parent.insertBefore(child, before);
+ if (isSelect && noSelection && child.selected) {
+ noSelection = !noSelection;
+ let {selectedIndex} = parent;
+ parent.selectedIndex = selectedIndex < 0 ?
+ start :
+ iOF.call(parent.querySelectorAll('option'), child);
+ }
+ start++;
+ }
+};
+exports.append = append;
+
+const eqeq = (a, b) => a == b;
+exports.eqeq = eqeq;
+
+const identity = O => O;
+exports.identity = identity;
+
+const indexOf = (
+ moreNodes,
+ moreStart,
+ moreEnd,
+ lessNodes,
+ lessStart,
+ lessEnd,
+ compare
+) => {
+ const length = lessEnd - lessStart;
+ /* istanbul ignore if */
+ if (length < 1)
+ return -1;
+ while ((moreEnd - moreStart) >= length) {
+ let m = moreStart;
+ let l = lessStart;
+ while (
+ m < moreEnd &&
+ l < lessEnd &&
+ compare(moreNodes[m], lessNodes[l])
+ ) {
+ m++;
+ l++;
+ }
+ if (l === lessEnd)
+ return moreStart;
+ moreStart = m + 1;
+ }
+ return -1;
+};
+exports.indexOf = indexOf;
+
+const isReversed = (
+ futureNodes,
+ futureEnd,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ compare
+) => {
+ while (
+ currentStart < currentEnd &&
+ compare(
+ currentNodes[currentStart],
+ futureNodes[futureEnd - 1]
+ )) {
+ currentStart++;
+ futureEnd--;
+ };
+ return futureEnd === 0;
+};
+exports.isReversed = isReversed;
+
+const next = (get, list, i, length, before) => i < length ?
+ get(list[i], 0) :
+ (0 < i ?
+ get(list[i - 1], -0).nextSibling :
+ before);
+exports.next = next;
+
+const remove = (get, children, start, end) => {
+ while (start < end)
+ drop(get(children[start++], -1));
+};
+exports.remove = remove;
+
+// - - - - - - - - - - - - - - - - - - -
+// diff related constants and utilities
+// - - - - - - - - - - - - - - - - - - -
+
+const DELETION = -1;
+const INSERTION = 1;
+const SKIP = 0;
+const SKIP_OND = 50;
+
+const HS = (
+ futureNodes,
+ futureStart,
+ futureEnd,
+ futureChanges,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ currentChanges
+) => {
+
+ let k = 0;
+ /* istanbul ignore next */
+ let minLen = futureChanges < currentChanges ? futureChanges : currentChanges;
+ const link = Array(minLen++);
+ const tresh = Array(minLen);
+ tresh[0] = -1;
+
+ for (let i = 1; i < minLen; i++)
+ tresh[i] = currentEnd;
+
+ const nodes = currentNodes.slice(currentStart, currentEnd);
+
+ for (let i = futureStart; i < futureEnd; i++) {
+ const index = nodes.indexOf(futureNodes[i]);
+ if (-1 < index) {
+ const idxInOld = index + currentStart;
+ k = findK(tresh, minLen, idxInOld);
+ /* istanbul ignore else */
+ if (-1 < k) {
+ tresh[k] = idxInOld;
+ link[k] = {
+ newi: i,
+ oldi: idxInOld,
+ prev: link[k - 1]
+ };
+ }
+ }
+ }
+
+ k = --minLen;
+ --currentEnd;
+ while (tresh[k] > currentEnd) --k;
+
+ minLen = currentChanges + futureChanges - k;
+ const diff = Array(minLen);
+ let ptr = link[k];
+ --futureEnd;
+ while (ptr) {
+ const {newi, oldi} = ptr;
+ while (futureEnd > newi) {
+ diff[--minLen] = INSERTION;
+ --futureEnd;
+ }
+ while (currentEnd > oldi) {
+ diff[--minLen] = DELETION;
+ --currentEnd;
+ }
+ diff[--minLen] = SKIP;
+ --futureEnd;
+ --currentEnd;
+ ptr = ptr.prev;
+ }
+ while (futureEnd >= futureStart) {
+ diff[--minLen] = INSERTION;
+ --futureEnd;
+ }
+ while (currentEnd >= currentStart) {
+ diff[--minLen] = DELETION;
+ --currentEnd;
+ }
+ return diff;
+};
+
+// this is pretty much the same petit-dom code without the delete map part
+// https://github.com/yelouafi/petit-dom/blob/bd6f5c919b5ae5297be01612c524c40be45f14a7/src/vdom.js#L556-L561
+const OND = (
+ futureNodes,
+ futureStart,
+ rows,
+ currentNodes,
+ currentStart,
+ cols,
+ compare
+) => {
+ const length = rows + cols;
+ const v = [];
+ let d, k, r, c, pv, cv, pd;
+ outer: for (d = 0; d <= length; d++) {
+ /* istanbul ignore if */
+ if (d > SKIP_OND)
+ return null;
+ pd = d - 1;
+ /* istanbul ignore next */
+ pv = d ? v[d - 1] : [0, 0];
+ cv = v[d] = [];
+ for (k = -d; k <= d; k += 2) {
+ if (k === -d || (k !== d && pv[pd + k - 1] < pv[pd + k + 1])) {
+ c = pv[pd + k + 1];
+ } else {
+ c = pv[pd + k - 1] + 1;
+ }
+ r = c - k;
+ while (
+ c < cols &&
+ r < rows &&
+ compare(
+ currentNodes[currentStart + c],
+ futureNodes[futureStart + r]
+ )
+ ) {
+ c++;
+ r++;
+ }
+ if (c === cols && r === rows) {
+ break outer;
+ }
+ cv[d + k] = c;
+ }
+ }
+
+ const diff = Array(d / 2 + length / 2);
+ let diffIdx = diff.length - 1;
+ for (d = v.length - 1; d >= 0; d--) {
+ while (
+ c > 0 &&
+ r > 0 &&
+ compare(
+ currentNodes[currentStart + c - 1],
+ futureNodes[futureStart + r - 1]
+ )
+ ) {
+ // diagonal edge = equality
+ diff[diffIdx--] = SKIP;
+ c--;
+ r--;
+ }
+ if (!d)
+ break;
+ pd = d - 1;
+ /* istanbul ignore next */
+ pv = d ? v[d - 1] : [0, 0];
+ k = c - r;
+ if (k === -d || (k !== d && pv[pd + k - 1] < pv[pd + k + 1])) {
+ // vertical edge = insertion
+ r--;
+ diff[diffIdx--] = INSERTION;
+ } else {
+ // horizontal edge = deletion
+ c--;
+ diff[diffIdx--] = DELETION;
+ }
+ }
+ return diff;
+};
+
+const applyDiff = (
+ diff,
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ currentNodes,
+ currentStart,
+ currentLength,
+ before
+) => {
+ const live = [];
+ const length = diff.length;
+ let currentIndex = currentStart;
+ let i = 0;
+ while (i < length) {
+ switch (diff[i++]) {
+ case SKIP:
+ futureStart++;
+ currentIndex++;
+ break;
+ case INSERTION:
+ // TODO: bulk appends for sequential nodes
+ live.push(futureNodes[futureStart]);
+ append(
+ get,
+ parentNode,
+ futureNodes,
+ futureStart++,
+ futureStart,
+ currentIndex < currentLength ?
+ get(currentNodes[currentIndex], 0) :
+ before
+ );
+ break;
+ case DELETION:
+ currentIndex++;
+ break;
+ }
+ }
+ i = 0;
+ while (i < length) {
+ switch (diff[i++]) {
+ case SKIP:
+ currentStart++;
+ break;
+ case DELETION:
+ // TODO: bulk removes for sequential nodes
+ if (-1 < live.indexOf(currentNodes[currentStart]))
+ currentStart++;
+ else
+ remove(
+ get,
+ currentNodes,
+ currentStart++,
+ currentStart
+ );
+ break;
+ }
+ }
+};
+
+const findK = (ktr, length, j) => {
+ let lo = 1;
+ let hi = length;
+ while (lo < hi) {
+ const mid = ((lo + hi) / 2) >>> 0;
+ if (j < ktr[mid])
+ hi = mid;
+ else
+ lo = mid + 1;
+ }
+ return lo;
+}
+
+const smartDiff = (
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ futureEnd,
+ futureChanges,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ currentChanges,
+ currentLength,
+ compare,
+ before
+) => {
+ applyDiff(
+ OND(
+ futureNodes,
+ futureStart,
+ futureChanges,
+ currentNodes,
+ currentStart,
+ currentChanges,
+ compare
+ ) ||
+ HS(
+ futureNodes,
+ futureStart,
+ futureEnd,
+ futureChanges,
+ currentNodes,
+ currentStart,
+ currentEnd,
+ currentChanges
+ ),
+ get,
+ parentNode,
+ futureNodes,
+ futureStart,
+ currentNodes,
+ currentStart,
+ currentLength,
+ before
+ );
+};
+exports.smartDiff = smartDiff;
+
+const drop = node => (node.remove || dropChild).call(node);
+
+function dropChild() {
+ const {parentNode} = this;
+ /* istanbul ignore else */
+ if (parentNode)
+ parentNode.removeChild(this);
+}
diff --git a/coverage/coverage.json b/coverage/coverage.json
deleted file mode 100644
index 3e7e2d9..0000000
--- a/coverage/coverage.json
+++ /dev/null
@@ -1 +0,0 @@
-{"/home/webreflection/code/domdiff/cjs/index.js":{"path":"/home/webreflection/code/domdiff/cjs/index.js","s":{"1":1,"2":569,"3":1,"4":98,"5":98,"6":98,"7":98,"8":98,"9":98,"10":98,"11":98,"12":98,"13":98,"14":447,"15":44,"16":403,"17":11,"18":392,"19":22,"20":370,"21":5,"22":365,"23":140,"24":140,"25":225,"26":50,"27":50,"28":175,"29":52,"30":52,"31":52,"32":123,"33":27,"34":27,"35":27,"36":96,"37":96,"38":52,"39":52,"40":44,"41":44,"42":0,"43":44,"44":44,"45":44,"46":98,"47":52,"48":52,"49":52,"50":63,"51":63,"52":63,"53":46,"54":46,"55":116,"56":116,"57":100,"58":98,"59":1},"b":{"1":[98,96],"2":[50,48],"3":[545,493],"4":[44,403],"5":[11,392],"6":[22,370],"7":[5,365],"8":[140,225],"9":[50,175],"10":[52,123],"11":[52,9],"12":[27,96],"13":[52,44],"14":[0,44],"15":[52,46],"16":[25,27],"17":[63,0],"18":[46,0],"19":[100,16]},"f":{},"fnMap":{},"statementMap":{"1":{"start":{"line":10,"column":0},"end":{"line":10,"column":24}},"2":{"start":{"line":10,"column":22},"end":{"line":10,"column":23}},"3":{"start":{"line":12,"column":0},"end":{"line":116,"column":2}},"4":{"start":{"line":19,"column":2},"end":{"line":19,"column":34}},"5":{"start":{"line":20,"column":2},"end":{"line":20,"column":61}},"6":{"start":{"line":21,"column":2},"end":{"line":21,"column":40}},"7":{"start":{"line":22,"column":2},"end":{"line":22,"column":43}},"8":{"start":{"line":23,"column":2},"end":{"line":23,"column":41}},"9":{"start":{"line":24,"column":2},"end":{"line":24,"column":48}},"10":{"start":{"line":25,"column":2},"end":{"line":25,"column":41}},"11":{"start":{"line":26,"column":2},"end":{"line":26,"column":39}},"12":{"start":{"line":27,"column":2},"end":{"line":27,"column":45}},"13":{"start":{"line":28,"column":2},"end":{"line":94,"column":3}},"14":{"start":{"line":29,"column":4},"end":{"line":93,"column":5}},"15":{"start":{"line":30,"column":6},"end":{"line":30,"column":54}},"16":{"start":{"line":32,"column":9},"end":{"line":93,"column":5}},"17":{"start":{"line":33,"column":6},"end":{"line":33,"column":50}},"18":{"start":{"line":35,"column":9},"end":{"line":93,"column":5}},"19":{"start":{"line":36,"column":6},"end":{"line":36,"column":51}},"20":{"start":{"line":38,"column":9},"end":{"line":93,"column":5}},"21":{"start":{"line":39,"column":6},"end":{"line":39,"column":47}},"22":{"start":{"line":41,"column":9},"end":{"line":93,"column":5}},"23":{"start":{"line":42,"column":6},"end":{"line":42,"column":54}},"24":{"start":{"line":43,"column":6},"end":{"line":43,"column":51}},"25":{"start":{"line":45,"column":9},"end":{"line":93,"column":5}},"26":{"start":{"line":46,"column":6},"end":{"line":46,"column":50}},"27":{"start":{"line":47,"column":6},"end":{"line":47,"column":47}},"28":{"start":{"line":49,"column":9},"end":{"line":93,"column":5}},"29":{"start":{"line":50,"column":6},"end":{"line":53,"column":8}},"30":{"start":{"line":54,"column":6},"end":{"line":54,"column":54}},"31":{"start":{"line":55,"column":6},"end":{"line":55,"column":47}},"32":{"start":{"line":57,"column":9},"end":{"line":93,"column":5}},"33":{"start":{"line":58,"column":6},"end":{"line":61,"column":8}},"34":{"start":{"line":62,"column":6},"end":{"line":62,"column":50}},"35":{"start":{"line":63,"column":6},"end":{"line":63,"column":51}},"36":{"start":{"line":66,"column":6},"end":{"line":66,"column":56}},"37":{"start":{"line":67,"column":6},"end":{"line":92,"column":7}},"38":{"start":{"line":68,"column":8},"end":{"line":71,"column":10}},"39":{"start":{"line":72,"column":8},"end":{"line":72,"column":53}},"40":{"start":{"line":75,"column":8},"end":{"line":75,"column":37}},"41":{"start":{"line":79,"column":8},"end":{"line":90,"column":9}},"42":{"start":{"line":80,"column":10},"end":{"line":83,"column":12},"skip":true},"43":{"start":{"line":85,"column":10},"end":{"line":85,"column":37}},"44":{"start":{"line":86,"column":10},"end":{"line":89,"column":12}},"45":{"start":{"line":91,"column":8},"end":{"line":91,"column":53}},"46":{"start":{"line":95,"column":2},"end":{"line":114,"column":3}},"47":{"start":{"line":96,"column":4},"end":{"line":96,"column":43}},"48":{"start":{"line":97,"column":4},"end":{"line":97,"column":50}},"49":{"start":{"line":98,"column":4},"end":{"line":104,"column":5}},"50":{"start":{"line":99,"column":6},"end":{"line":99,"column":44}},"51":{"start":{"line":103,"column":6},"end":{"line":103,"column":62}},"52":{"start":{"line":103,"column":22},"end":{"line":103,"column":62}},"53":{"start":{"line":109,"column":7},"end":{"line":114,"column":3}},"54":{"start":{"line":110,"column":4},"end":{"line":113,"column":5}},"55":{"start":{"line":111,"column":6},"end":{"line":111,"column":46}},"56":{"start":{"line":112,"column":6},"end":{"line":112,"column":54}},"57":{"start":{"line":112,"column":22},"end":{"line":112,"column":54}},"58":{"start":{"line":115,"column":2},"end":{"line":115,"column":21}},"59":{"start":{"line":118,"column":0},"end":{"line":118,"column":78}}},"branchMap":{"1":{"line":19,"type":"binary-expr","locations":[{"start":{"line":19,"column":14},"end":{"line":19,"column":21}},{"start":{"line":19,"column":25},"end":{"line":19,"column":33}}]},"2":{"line":20,"type":"cond-expr","locations":[{"start":{"line":20,"column":38},"end":{"line":20,"column":42}},{"start":{"line":20,"column":45},"end":{"line":20,"column":60}}]},"3":{"line":28,"type":"binary-expr","locations":[{"start":{"line":28,"column":9},"end":{"line":28,"column":35}},{"start":{"line":28,"column":39},"end":{"line":28,"column":63}}]},"4":{"line":29,"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":29,"column":4}},{"start":{"line":29,"column":4},"end":{"line":29,"column":4}}]},"5":{"line":32,"type":"if","locations":[{"start":{"line":32,"column":9},"end":{"line":32,"column":9}},{"start":{"line":32,"column":9},"end":{"line":32,"column":9}}]},"6":{"line":35,"type":"if","locations":[{"start":{"line":35,"column":9},"end":{"line":35,"column":9}},{"start":{"line":35,"column":9},"end":{"line":35,"column":9}}]},"7":{"line":38,"type":"if","locations":[{"start":{"line":38,"column":9},"end":{"line":38,"column":9}},{"start":{"line":38,"column":9},"end":{"line":38,"column":9}}]},"8":{"line":41,"type":"if","locations":[{"start":{"line":41,"column":9},"end":{"line":41,"column":9}},{"start":{"line":41,"column":9},"end":{"line":41,"column":9}}]},"9":{"line":45,"type":"if","locations":[{"start":{"line":45,"column":9},"end":{"line":45,"column":9}},{"start":{"line":45,"column":9},"end":{"line":45,"column":9}}]},"10":{"line":49,"type":"if","locations":[{"start":{"line":49,"column":9},"end":{"line":49,"column":9}},{"start":{"line":49,"column":9},"end":{"line":49,"column":9}}]},"11":{"line":52,"type":"binary-expr","locations":[{"start":{"line":52,"column":8},"end":{"line":52,"column":39}},{"start":{"line":52,"column":43},"end":{"line":52,"column":49}}]},"12":{"line":57,"type":"if","locations":[{"start":{"line":57,"column":9},"end":{"line":57,"column":9}},{"start":{"line":57,"column":9},"end":{"line":57,"column":9}}]},"13":{"line":67,"type":"if","locations":[{"start":{"line":67,"column":6},"end":{"line":67,"column":6}},{"start":{"line":67,"column":6},"end":{"line":67,"column":6}}]},"14":{"line":79,"type":"if","locations":[{"start":{"line":79,"column":8},"end":{"line":79,"column":8},"skip":true},{"start":{"line":79,"column":8},"end":{"line":79,"column":8}}]},"15":{"line":95,"type":"if","locations":[{"start":{"line":95,"column":2},"end":{"line":95,"column":2}},{"start":{"line":95,"column":2},"end":{"line":95,"column":2}}]},"16":{"line":97,"type":"cond-expr","locations":[{"start":{"line":97,"column":32},"end":{"line":97,"column":40}},{"start":{"line":97,"column":43},"end":{"line":97,"column":49}}]},"17":{"line":103,"type":"if","locations":[{"start":{"line":103,"column":6},"end":{"line":103,"column":6}},{"start":{"line":103,"column":6},"end":{"line":103,"column":6},"skip":true}]},"18":{"line":109,"type":"if","locations":[{"start":{"line":109,"column":7},"end":{"line":109,"column":7}},{"start":{"line":109,"column":7},"end":{"line":109,"column":7},"skip":true}]},"19":{"line":112,"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":112,"column":6}},{"start":{"line":112,"column":6},"end":{"line":112,"column":6}}]}}}}
\ No newline at end of file
diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css
deleted file mode 100644
index 29737bc..0000000
--- a/coverage/lcov-report/base.css
+++ /dev/null
@@ -1,213 +0,0 @@
-body, html {
- margin:0; padding: 0;
- height: 100%;
-}
-body {
- font-family: Helvetica Neue, Helvetica, Arial;
- font-size: 14px;
- color:#333;
-}
-.small { font-size: 12px; }
-*, *:after, *:before {
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- box-sizing:border-box;
- }
-h1 { font-size: 20px; margin: 0;}
-h2 { font-size: 14px; }
-pre {
- font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
- margin: 0;
- padding: 0;
- -moz-tab-size: 2;
- -o-tab-size: 2;
- tab-size: 2;
-}
-a { color:#0074D9; text-decoration:none; }
-a:hover { text-decoration:underline; }
-.strong { font-weight: bold; }
-.space-top1 { padding: 10px 0 0 0; }
-.pad2y { padding: 20px 0; }
-.pad1y { padding: 10px 0; }
-.pad2x { padding: 0 20px; }
-.pad2 { padding: 20px; }
-.pad1 { padding: 10px; }
-.space-left2 { padding-left:55px; }
-.space-right2 { padding-right:20px; }
-.center { text-align:center; }
-.clearfix { display:block; }
-.clearfix:after {
- content:'';
- display:block;
- height:0;
- clear:both;
- visibility:hidden;
- }
-.fl { float: left; }
-@media only screen and (max-width:640px) {
- .col3 { width:100%; max-width:100%; }
- .hide-mobile { display:none!important; }
-}
-
-.quiet {
- color: #7f7f7f;
- color: rgba(0,0,0,0.5);
-}
-.quiet a { opacity: 0.7; }
-
-.fraction {
- font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
- font-size: 10px;
- color: #555;
- background: #E8E8E8;
- padding: 4px 5px;
- border-radius: 3px;
- vertical-align: middle;
-}
-
-div.path a:link, div.path a:visited { color: #333; }
-table.coverage {
- border-collapse: collapse;
- margin: 10px 0 0 0;
- padding: 0;
-}
-
-table.coverage td {
- margin: 0;
- padding: 0;
- vertical-align: top;
-}
-table.coverage td.line-count {
- text-align: right;
- padding: 0 5px 0 20px;
-}
-table.coverage td.line-coverage {
- text-align: right;
- padding-right: 10px;
- min-width:20px;
-}
-
-table.coverage td span.cline-any {
- display: inline-block;
- padding: 0 5px;
- width: 100%;
-}
-.missing-if-branch {
- display: inline-block;
- margin-right: 5px;
- border-radius: 3px;
- position: relative;
- padding: 0 4px;
- background: #333;
- color: yellow;
-}
-
-.skip-if-branch {
- display: none;
- margin-right: 10px;
- position: relative;
- padding: 0 4px;
- background: #ccc;
- color: white;
-}
-.missing-if-branch .typ, .skip-if-branch .typ {
- color: inherit !important;
-}
-.coverage-summary {
- border-collapse: collapse;
- width: 100%;
-}
-.coverage-summary tr { border-bottom: 1px solid #bbb; }
-.keyline-all { border: 1px solid #ddd; }
-.coverage-summary td, .coverage-summary th { padding: 10px; }
-.coverage-summary tbody { border: 1px solid #bbb; }
-.coverage-summary td { border-right: 1px solid #bbb; }
-.coverage-summary td:last-child { border-right: none; }
-.coverage-summary th {
- text-align: left;
- font-weight: normal;
- white-space: nowrap;
-}
-.coverage-summary th.file { border-right: none !important; }
-.coverage-summary th.pct { }
-.coverage-summary th.pic,
-.coverage-summary th.abs,
-.coverage-summary td.pct,
-.coverage-summary td.abs { text-align: right; }
-.coverage-summary td.file { white-space: nowrap; }
-.coverage-summary td.pic { min-width: 120px !important; }
-.coverage-summary tfoot td { }
-
-.coverage-summary .sorter {
- height: 10px;
- width: 7px;
- display: inline-block;
- margin-left: 0.5em;
- background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
-}
-.coverage-summary .sorted .sorter {
- background-position: 0 -20px;
-}
-.coverage-summary .sorted-desc .sorter {
- background-position: 0 -10px;
-}
-.status-line { height: 10px; }
-/* dark red */
-.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
-.low .chart { border:1px solid #C21F39 }
-/* medium red */
-.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
-/* light red */
-.low, .cline-no { background:#FCE1E5 }
-/* light green */
-.high, .cline-yes { background:rgb(230,245,208) }
-/* medium green */
-.cstat-yes { background:rgb(161,215,106) }
-/* dark green */
-.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
-.high .chart { border:1px solid rgb(77,146,33) }
-/* dark yellow (gold) */
-.medium .chart { border:1px solid #f9cd0b; }
-.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
-/* light yellow */
-.medium { background: #fff4c2; }
-/* light gray */
-span.cline-neutral { background: #eaeaea; }
-
-.cbranch-no { background: yellow !important; color: #111; }
-
-.cstat-skip { background: #ddd; color: #111; }
-.fstat-skip { background: #ddd; color: #111 !important; }
-.cbranch-skip { background: #ddd !important; color: #111; }
-
-
-.cover-fill, .cover-empty {
- display:inline-block;
- height: 12px;
-}
-.chart {
- line-height: 0;
-}
-.cover-empty {
- background: white;
-}
-.cover-full {
- border-right: none !important;
-}
-pre.prettyprint {
- border: none !important;
- padding: 0 !important;
- margin: 0 !important;
-}
-.com { color: #999 !important; }
-.ignore-none { color: #999; font-weight: normal; }
-
-.wrapper {
- min-height: 100%;
- height: auto !important;
- height: 100%;
- margin: 0 auto -48px;
-}
-.footer, .push {
- height: 48px;
-}
diff --git a/coverage/lcov-report/cjs/index.html b/coverage/lcov-report/cjs/index.html
deleted file mode 100644
index 389c96b..0000000
--- a/coverage/lcov-report/cjs/index.html
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
- Code coverage report for cjs/
-
-
-
-
-
-
-
-
-
-
-
-
- 100%
- Statements
- 59/59
-
-
- 100%
- Branches
- 38/38
-
-
- 100%
- Functions
- 0/0
-
-
- 100%
- Lines
- 56/56
-
-
- 1 statement, 3 branches
- Ignored
-
-
-
-
-
-
-
-
- | File |
- |
- Statements |
- |
- Branches |
- |
- Functions |
- |
- Lines |
- |
-
-
-
- | index.js |
- |
- 100% |
- 59/59 |
- 100% |
- 38/38 |
- 100% |
- 0/0 |
- 100% |
- 56/56 |
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/coverage/lcov-report/cjs/index.js.html b/coverage/lcov-report/cjs/index.js.html
deleted file mode 100644
index bdc474c..0000000
--- a/coverage/lcov-report/cjs/index.js.html
+++ /dev/null
@@ -1,423 +0,0 @@
-
-
-
- Code coverage report for cjs/index.js
-
-
-
-
-
-
-
-
-
-
-
-
- 100%
- Statements
- 59/59
-
-
- 100%
- Branches
- 38/38
-
-
- 100%
- Functions
- 0/0
-
-
- 100%
- Lines
- 56/56
-
-
- 1 statement, 3 branches
- Ignored
-
-
-
-
-
-| 1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119 |
-
-
-
-
-
-
-
-
-569×
-
-1×
-
-
-
-
-
-
-98×
-98×
-98×
-98×
-98×
-98×
-98×
-98×
-98×
-98×
-447×
-44×
-
-403×
-11×
-
-392×
-22×
-
-370×
-5×
-
-365×
-140×
-140×
-
-225×
-50×
-50×
-
-175×
-52×
-
-
-
-52×
-52×
-
-123×
-27×
-
-
-
-27×
-27×
-
-
-96×
-96×
-52×
-
-
-
-52×
-
-
-44×
-
-
-
-44×
-1×
-
-
-
-
-44×
-44×
-
-
-
-
-44×
-
-
-
-98×
-52×
-52×
-52×
-63×
-
-
-
-63×
-
-
-
-
-
-46×
-46×
-116×
-116×
-
-
-98×
-
-
-1×
- | 'use strict';
-/*! (c) 2017 Andrea Giammarchi (ISC) */
-
-/**
- * This code is a revisited port of the snabbdom vDOM diffing logic,
- * the same that fuels as fork Vue.js, Preact, and other libraries.
- * @credits https://github.com/snabbdom/snabbdom
- */
-
-const identity = O => O;
-
-const domdiff = (
- parentNode, // where changes happen
- currentNodes, // Array of current items/nodes
- futureNodes, // Array of future items/nodes
- getNode, // optional way to retrieve a node from an item
- beforeNode // optional item/node to use as insertBefore delimiter
-) => {
- const get = getNode || identity;
- const before = beforeNode == null ? null : get(beforeNode);
- let currentStart = 0, futureStart = 0;
- let currentEnd = currentNodes.length - 1;
- let currentStartNode = currentNodes[0];
- let currentEndNode = currentNodes[currentEnd];
- let futureEnd = futureNodes.length - 1;
- let futureStartNode = futureNodes[0];
- let futureEndNode = futureNodes[futureEnd];
- while (currentStart <= currentEnd && futureStart <= futureEnd) {
- if (currentStartNode == null) {
- currentStartNode = currentNodes[++currentStart];
- }
- else if (currentEndNode == null) {
- currentEndNode = currentNodes[--currentEnd];
- }
- else if (futureStartNode == null) {
- futureStartNode = futureNodes[++futureStart];
- }
- else if (futureEndNode == null) {
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentStartNode == futureStartNode) {
- currentStartNode = currentNodes[++currentStart];
- futureStartNode = futureNodes[++futureStart];
- }
- else if (currentEndNode == futureEndNode) {
- currentEndNode = currentNodes[--currentEnd];
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentStartNode == futureEndNode) {
- parentNode.insertBefore(
- get(currentStartNode),
- get(currentEndNode).nextSibling || before
- );
- currentStartNode = currentNodes[++currentStart];
- futureEndNode = futureNodes[--futureEnd];
- }
- else if (currentEndNode == futureStartNode) {
- parentNode.insertBefore(
- get(currentEndNode),
- get(currentStartNode)
- );
- currentEndNode = currentNodes[--currentEnd];
- futureStartNode = futureNodes[++futureStart];
- }
- else {
- let index = currentNodes.indexOf(futureStartNode);
- if (index < 0) {
- parentNode.insertBefore(
- get(futureStartNode),
- get(currentStartNode)
- );
- futureStartNode = futureNodes[++futureStart];
- }
- else {
- let el = currentNodes[index];
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
- /* istanbul ignore if */
- Iif (el != futureStartNode) {
- parentNode.insertBefore(
- get(futureStartNode),
- get(currentStartNode)
- );
- } else {
- currentNodes[index] = null;
- parentNode.insertBefore(
- get(el),
- get(currentStartNode)
- );
- }
- futureStartNode = futureNodes[++futureStart];
- }
- }
- }
- if (currentStart > currentEnd) {
- const pin = futureNodes[futureEnd + 1];
- const place = pin != null ? get(pin) : before;
- while (futureStart <= futureEnd) {
- const ch = futureNodes[futureStart++];
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
- /* istanbul ignore else */
- Eif (ch != null) parentNode.insertBefore(get(ch), place);
- }
- }
- // until I am sure the else could never happen
- // it might be a vDOM thing 'cause it never happens here
- /* istanbul ignore else */
- else Eif (futureStart > futureEnd) {
- while (currentStart <= currentEnd) {
- const ch = currentNodes[currentStart++];
- if (ch != null) parentNode.removeChild(get(ch));
- }
- }
- return futureNodes;
-};
-
-Object.defineProperty(exports, '__esModule', {value: true}).default = domdiff;
- |
-
-
-
-
-
-
-
-
-
-
diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html
deleted file mode 100644
index 6d62ef1..0000000
--- a/coverage/lcov-report/index.html
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
- Code coverage report for All files
-
-
-
-
-
-
-
-
-
-
- /
-
-
-
- 100%
- Statements
- 59/59
-
-
- 100%
- Branches
- 38/38
-
-
- 100%
- Functions
- 0/0
-
-
- 100%
- Lines
- 56/56
-
-
- 1 statement, 3 branches
- Ignored
-
-
-
-
-
-
-
-
- | File |
- |
- Statements |
- |
- Branches |
- |
- Functions |
- |
- Lines |
- |
-
-
-
- | cjs/ |
- |
- 100% |
- 59/59 |
- 100% |
- 38/38 |
- 100% |
- 0/0 |
- 100% |
- 56/56 |
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css
deleted file mode 100644
index b317a7c..0000000
--- a/coverage/lcov-report/prettify.css
+++ /dev/null
@@ -1 +0,0 @@
-.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js
deleted file mode 100644
index ef51e03..0000000
--- a/coverage/lcov-report/prettify.js
+++ /dev/null
@@ -1 +0,0 @@
-window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^
+
+
+
+