summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPirate Praveen <praveen@debian.org>2019-06-18 18:00:17 +0200
committerPirate Praveen <praveen@debian.org>2019-06-18 18:00:17 +0200
commitdc9638c0f4584b9a51b86338eb191d71c34ed5ec (patch)
treed21f8a8b7d35a4a3ffb18b6bd8a4f55032a2d579
Import node-d3-collection_1.0.7.orig.tar.gz
[dgit import orig node-d3-collection_1.0.7.orig.tar.gz]
-rw-r--r--.eslintrc.json15
-rw-r--r--.gitignore5
-rw-r--r--.npmignore4
-rw-r--r--LICENSE27
-rw-r--r--README.md271
-rw-r--r--d3-collection.sublime-project17
-rw-r--r--package.json42
-rw-r--r--rollup.config.js36
-rw-r--r--src/entries.js5
-rw-r--r--src/index.js6
-rw-r--r--src/keys.js5
-rw-r--r--src/map.js75
-rw-r--r--src/nest.js73
-rw-r--r--src/set.js39
-rw-r--r--src/values.js5
-rw-r--r--test/entries-test.js35
-rw-r--r--test/isNaN.js10
-rw-r--r--test/keys-test.js24
-rw-r--r--test/map-test.js353
-rw-r--r--test/nest-test.js172
-rw-r--r--test/set-test.js254
-rw-r--r--test/values-test.js44
-rw-r--r--yarn.lock939
23 files changed, 2456 insertions, 0 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..8287875
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "sourceType": "module",
+ "ecmaVersion": 8
+ },
+ "env": {
+ "es6": true,
+ "node": true,
+ "browser": true
+ },
+ "rules": {
+ "no-cond-assign": 0
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8abcf6a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.sublime-workspace
+.DS_Store
+dist/
+node_modules
+npm-debug.log
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..0de69fc
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,4 @@
+*.sublime-*
+dist/*.zip
+img/
+test/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..12e3727
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2010-2016, Mike Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the author nor the names of contributors may be used to
+ endorse or promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b2221cd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,271 @@
+# d3-collection
+
+Handy data structures for elements keyed by string.
+
+## Installing
+
+If you use NPM, `npm install d3-collection`. Otherwise, download the [latest release](https://github.com/d3/d3-collection/releases/latest). You can also load directly from [d3js.org](https://d3js.org), either as a [standalone library](https://d3js.org/d3-collection.v1.min.js) or as part of [D3 4.0](https://github.com/d3/d3). AMD, CommonJS, and vanilla environments are supported. In vanilla, a `d3` global is exported:
+
+```html
+<script src="https://d3js.org/d3-collection.v1.min.js"></script>
+<script>
+
+var map = d3.map()
+ .set("foo", 1)
+ .set("bar", 2);
+
+</script>
+```
+
+[Try d3-collection in your browser.](https://tonicdev.com/npm/d3-collection)
+
+## API Reference
+
+* [Objects](#objects)
+* [Maps](#maps)
+* [Sets](#sets)
+* [Nests](#nests)
+
+### Objects
+
+A common data type in JavaScript is the *associative array*, or more simply the *object*, which has a set of named properties. The standard mechanism for iterating over the keys (or property names) in an associative array is the [for…in loop](https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in). However, note that the iteration order is undefined. D3 provides several methods for converting associative arrays to standard arrays with numeric indexes.
+
+A word of caution: it is tempting to use plain objects as maps, but this causes [unexpected behavior](http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/) when built-in property names are used as keys, such as `object["__proto__"] = 42` and `"hasOwnProperty" in object`. If you cannot guarantee that map keys and set values will be safe, use [maps](#maps) and [sets](#sets) (or their ES6 equivalents) instead of plain objects.
+
+<a name="keys" href="#keys">#</a> d3.<b>keys</b>(<i>object</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/keys.js "Source")
+
+Returns an array containing the property names of the specified object (an associative array). The order of the returned array is undefined.
+
+<a name="values" href="#values">#</a> d3.<b>values</b>(<i>object</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/values.js "Source")
+
+Returns an array containing the property values of the specified object (an associative array). The order of the returned array is undefined.
+
+<a name="entries" href="#entries">#</a> d3.<b>entries</b>(<i>object</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/entries.js "Source")
+
+Returns an array containing the property keys and values of the specified object (an associative array). Each entry is an object with a key and value attribute, such as `{key: "foo", value: 42}`. The order of the returned array is undefined.
+
+```js
+d3.entries({foo: 42, bar: true}); // [{key: "foo", value: 42}, {key: "bar", value: true}]
+```
+
+### Maps
+
+Like [ES6 Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), but with a few differences:
+
+* Keys are coerced to strings.
+* [map.each](#map_each), not [map.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach). (Also, no *thisArg*.)
+* [map.remove](#map_remove), not [map.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete).
+* [map.entries](#map_entries) returns an array of {key, value} objects, not an iterator of [key, value].
+* [map.size](#map_size) is a method, not a [property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size); also, there’s [map.empty](#map_empty).
+
+<a name="map" href="#map">#</a> d3.<b>map</b>([<i>object</i>[, <i>key</i>]]) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js "Source")
+
+Constructs a new map. If *object* is specified, copies all enumerable properties from the specified object into this map. The specified object may also be an array or another map. An optional *key* function may be specified to compute the key for each value in the array. For example:
+
+```js
+var map = d3.map([{name: "foo"}, {name: "bar"}], function(d) { return d.name; });
+map.get("foo"); // {"name": "foo"}
+map.get("bar"); // {"name": "bar"}
+map.get("baz"); // undefined
+```
+
+See also [nests](#nests).
+
+<a name="map_has" href="#map_has">#</a> <i>map</i>.<b>has</b>(<i>key</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L7 "Source")
+
+Returns true if and only if this map has an entry for the specified *key* string. Note: the value may be `null` or `undefined`.
+
+<a name="map_get" href="#map_get">#</a> <i>map</i>.<b>get</b>(<i>key</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L10 "Source")
+
+Returns the value for the specified *key* string. If the map does not have an entry for the specified *key*, returns `undefined`.
+
+<a name="map_set" href="#map_set">#</a> <i>map</i>.<b>set</b>(<i>key</i>, <i>value</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L13 "Source")
+
+Sets the *value* for the specified *key* string. If the map previously had an entry for the same *key* string, the old entry is replaced with the new value. Returns the map, allowing chaining. For example:
+
+```js
+var map = d3.map()
+ .set("foo", 1)
+ .set("bar", 2)
+ .set("baz", 3);
+
+map.get("foo"); // 1
+```
+
+<a name="map_remove" href="#map_remove">#</a> <i>map</i>.<b>remove</b>(<i>key</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L17 "Source")
+
+If the map has an entry for the specified *key* string, removes the entry and returns true. Otherwise, this method does nothing and returns false.
+
+<a name="map_clear" href="#map_clear">#</a> <i>map</i>.<b>clear</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L21 "Source")
+
+Removes all entries from this map.
+
+<a name="map_keys" href="#map_keys">#</a> <i>map</i>.<b>keys</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L24 "Source")
+
+Returns an array of string keys for every entry in this map. The order of the returned keys is arbitrary.
+
+<a name="map_values" href="#map_values">#</a> <i>map</i>.<b>values</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L29 "Source")
+
+Returns an array of values for every entry in this map. The order of the returned values is arbitrary.
+
+<a name="map_entries" href="#map_entries">#</a> <i>map</i>.<b>entries</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L34 "Source")
+
+Returns an array of key-value objects for each entry in this map. The order of the returned entries is arbitrary. Each entry’s key is a string, but the value has arbitrary type.
+
+<a name="map_each" href="#map_each">#</a> <i>map</i>.<b>each</b>(<i>function</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L48 "Source")
+
+Calls the specified *function* for each entry in this map, passing the entry’s value and key as arguments, followed by the map itself. Returns undefined. The iteration order is arbitrary.
+
+<a name="map_empty" href="#map_empty">#</a> <i>map</i>.<b>empty</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L44 "Source")
+
+Returns true if and only if this map has zero entries.
+
+<a name="map_size" href="#map_size">#</a> <i>map</i>.<b>size</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/map.js#L39 "Source")
+
+Returns the number of entries in this map.
+
+### Sets
+
+Like [ES6 Sets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), but with a few differences:
+
+* Values are coerced to strings.
+* [set.each](#set_each), not [set.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/forEach). (Also, no *thisArg*.)
+* [set.remove](#set_remove), not [set.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete).
+* [set.size](#set_size) is a method, not a [property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size); also, there’s [set.empty](#set_empty).
+
+<a name="set" href="#set">#</a> d3.<b>set</b>([<i>array</i>[, <i>accessor</i>]]) [<>](https://github.com/d3/d3-collection/blob/master/src/set.js "Source")
+
+Constructs a new set. If *array* is specified, adds the given *array* of string values to the returned set. The specified array may also be another set. An optional *accessor* function may be specified, which is equivalent to calling *array.map(accessor)* before constructing the set.
+
+<a name="set_has" href="#set_has">#</a> <i>set</i>.<b>has</b>(<i>value</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L9 "Source")
+
+Returns true if and only if this set has an entry for the specified *value* string.
+
+<a name="set_add" href="#set_add">#</a> <i>set</i>.<b>add</b>(<i>value</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L10 "Source")
+
+Adds the specified *value* string to this set. Returns the set, allowing chaining. For example:
+
+```js
+var set = d3.set()
+ .add("foo")
+ .add("bar")
+ .add("baz");
+
+set.has("foo"); // true
+```
+
+<a name="set_remove" href="#set_remove">#</a> <i>set</i>.<b>remove</b>(<i>value</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L15 "Source")
+
+If the set contains the specified *value* string, removes it and returns true. Otherwise, this method does nothing and returns false.
+
+<a name="set_clear" href="#set_clear">#</a> <i>set</i>.<b>clear</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L16 "Source")
+
+Removes all values from this set.
+
+<a name="set_values" href="#set_values">#</a> <i>set</i>.<b>values</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L17 "Source")
+
+Returns an array of the string values in this set. The order of the returned values is arbitrary. Can be used as a convenient way of computing the unique values for a set of strings. For example:
+
+```js
+d3.set(["foo", "bar", "foo", "baz"]).values(); // "foo", "bar", "baz"
+```
+
+<a name="set_each" href="#set_each">#</a> <i>set</i>.<b>each</b>(<i>function</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L20 "Source")
+
+Calls the specified *function* for each value in this set, passing the value as the first two arguments (for symmetry with [*map*.each](#map_each)), followed by the set itself. Returns undefined. The iteration order is arbitrary.
+
+<a name="set_empty" href="#set_empty">#</a> <i>set</i>.<b>empty</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L19 "Source")
+
+Returns true if and only if this set has zero values.
+
+<a name="set_size" href="#set_size">#</a> <i>set</i>.<b>size</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/set.js#L18 "Source")
+
+Returns the number of values in this set.
+
+### Nests
+
+Nesting allows elements in an array to be grouped into a hierarchical tree structure; think of it like the GROUP BY operator in SQL, except you can have multiple levels of grouping, and the resulting output is a tree rather than a flat table. The levels in the tree are specified by key functions. The leaf nodes of the tree can be sorted by value, while the internal nodes can be sorted by key. An optional rollup function will collapse the elements in each leaf node using a summary function. The nest operator (the object returned by [nest](#nest)) is reusable, and does not retain any references to the data that is nested.
+
+For example, consider the following tabular data structure of Barley yields, from various sites in Minnesota during 1931-2:
+
+```js
+var yields = [
+ {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
+ {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
+ {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"},
+ ...
+];
+```
+
+To facilitate visualization, it may be useful to nest the elements first by year, and then by variety, as follows:
+
+```js
+var entries = d3.nest()
+ .key(function(d) { return d.year; })
+ .key(function(d) { return d.variety; })
+ .entries(yields);
+```
+
+This returns a nested array. Each element of the outer array is a key-values pair, listing the values for each distinct key:
+
+```js
+[{key: "1931", values: [
+ {key: "Manchuria", values: [
+ {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
+ {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
+ {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"}, ...]},
+ {key: "Glabron", values: [
+ {yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm"},
+ {yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca"}, ...]}, ...]},
+ {key: "1932", values: ...}]
+```
+
+The nested form allows easy iteration and generation of hierarchical structures in SVG or HTML.
+
+For a longer introduction to nesting, see:
+
+* Phoebe Bright’s [D3 Nest Tutorial and examples](http://bl.ocks.org/phoebebright/raw/3176159/)
+* Shan Carter’s [Mister Nester](http://bl.ocks.org/shancarter/raw/4748131/)
+
+<a name="nest" href="#nest">#</a> d3.<b>nest</b>() [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js "Source")
+
+Creates a new nest operator. The set of keys is initially empty.
+
+<a name="nest_key" href="#nest_key">#</a> <i>nest</i>.<b>key</b>(<i>key</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L4 "Source")
+
+Registers a new *key* function. The *key* function will be invoked for each element in the input array and must return a string identifier to assign the element to its group. Most often, the function is a simple accessor, such as the year and variety accessors above. (Keys functions are *not* passed the input array index.) Each time a key is registered, it is pushed onto the end of the internal array of keys, and the nest operator applies an additional level of nesting.
+
+<a name="nest_sortKeys" href="#nest_sortKeys">#</a> <i>nest</i>.<b>sortKeys</b>(<i>comparator</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L5 "Source")
+
+Sorts key values for the [current key](#nest_key) using the specified *comparator* function, such as [d3.ascending](https://github.com/d3/d3-array#ascending) or [d3.descending](https://github.com/d3/d3-array#descending). If no comparator is specified for the current key, the order in which keys will be returned is undefined. For example, to sort years in ascending order and varieties in descending order:
+
+```js
+var entries = d3.nest()
+ .key(function(d) { return d.year; }).sortKeys(d3.ascending)
+ .key(function(d) { return d.variety; }).sortKeys(d3.descending)
+ .entries(yields);
+```
+
+Note that this only affects the result of [*nest*.entries](#nest_entries); the order of keys returned by [*nest*.map](#nest_map) and [*nest*.object](#nest_object) is always undefined, regardless of comparator.
+
+<a name="nest_sortValues" href="#nest_sortValues">#</a> <i>nest</i>.<b>sortValues</b>(<i>comparator</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L6 "Source")
+
+Sorts leaf elements using the specified *comparator* function, such as [d3.ascending](https://github.com/d3/d3-array#ascending) or [d3.descending](https://github.com/d3/d3-array#descending). This is roughly equivalent to sorting the input array before applying the nest operator; however it is typically more efficient as the size of each group is smaller. If no value comparator is specified, elements will be returned in the order they appeared in the input array. This applies to [*nest*.map](#nest_map), [*nest*.entries](#nest_entries) and [*nest*.object](#nest_object).
+
+<a name="nest_rollup" href="#nest_rollup">#</a> <i>nest</i>.<b>rollup</b>(<i>function</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L7 "Source")
+
+Specifies a rollup *function* to be applied on each group of leaf elements. The return value of the rollup function will replace the array of leaf values in either the associative array returned by [*nest*.map](#nest_map) or [*nest*.object](#nest_object); for [*nest*.entries](#nest_entries), it replaces the leaf *entry*.values with *entry*.value. If a [leaf comparator](#nest_sortValues) is specified, the leaf elements are sorted prior to invoking the rollup function.
+
+<a name="nest_map" href="#nest_map">#</a> <i>nest</i>.<b>map</b>(<i>array</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L50 "Source")
+
+Applies the nest operator to the specified *array*, returning a nested [map](#map). Each entry in the returned map corresponds to a distinct key value returned by the first key function. The entry value depends on the number of registered key functions: if there is an additional key, the value is another map; otherwise, the value is the array of elements filtered from the input *array* that have the given key value. If no keys are defined, returns the input *array*.
+
+<a name="nest_object" href="#nest_object">#</a> <i>nest</i>.<b>object</b>(<i>array</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L49 "Source")
+
+Applies the nest operator to the specified *array*, returning a nested object. Each entry in the returned associative array corresponds to a distinct key value returned by the first key function. The entry value depends on the number of registered key functions: if there is an additional key, the value is another associative array; otherwise, the value is the array of elements filtered from the input *array* that have the given key value.
+
+Note: this method is unsafe if any of the keys conflict with built-in JavaScript properties, such as `__proto__`. If you cannot guarantee that the keys will be safe, you should use [nest.map](#nest_map) instead.
+
+<a name="nest_entries" href="#nest_entries">#</a> <i>nest</i>.<b>entries</b>(<i>array</i>) [<>](https://github.com/d3/d3-collection/blob/master/src/nest.js#L51 "Source")
+
+Applies the nest operator to the specified *array*, returning an array of key-values entries. Conceptually, this is similar to applying [*map*.entries](#map_entries) to the associative array returned by [*nest*.map](#nest_map), but it applies to every level of the hierarchy rather than just the first (outermost) level. Each entry in the returned array corresponds to a distinct key value returned by the first key function. The entry value depends on the number of registered key functions: if there is an additional key, the value is another nested array of entries; otherwise, the value is the array of elements filtered from the input *array* that have the given key value.
diff --git a/d3-collection.sublime-project b/d3-collection.sublime-project
new file mode 100644
index 0000000..772dfa5
--- /dev/null
+++ b/d3-collection.sublime-project
@@ -0,0 +1,17 @@
+{
+ "folders": [
+ {
+ "path": ".",
+ "file_exclude_patterns": ["*.sublime-workspace"],
+ "folder_exclude_patterns": ["dist"]
+ }
+ ],
+ "build_systems": [
+ {
+ "name": "yarn test",
+ "cmd": ["yarn", "test"],
+ "file_regex": "\\((...*?):([0-9]*):([0-9]*)\\)",
+ "working_dir": "$project_path"
+ }
+ ]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..bf7f89c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "d3-collection",
+ "version": "1.0.7",
+ "description": "Handy data structures for elements keyed by string.",
+ "keywords": [
+ "d3",
+ "d3-module",
+ "nest",
+ "data",
+ "map",
+ "set",
+ "object",
+ "collection"
+ ],
+ "homepage": "https://d3js.org/d3-collection/",
+ "license": "BSD-3-Clause",
+ "author": {
+ "name": "Mike Bostock",
+ "url": "http://bost.ocks.org/mike"
+ },
+ "main": "dist/d3-collection.js",
+ "unpkg": "dist/d3-collection.min.js",
+ "jsdelivr": "dist/d3-collection.min.js",
+ "module": "src/index.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/d3/d3-collection.git"
+ },
+ "scripts": {
+ "pretest": "rollup -c",
+ "test": "tape 'test/**/*-test.js' && eslint src test",
+ "prepublishOnly": "rm -rf dist && yarn test",
+ "postpublish": "git push && git push --tags && cd ../d3.github.com && git pull && cp ../${npm_package_name}/dist/${npm_package_name}.js ${npm_package_name}.v${npm_package_version%%.*}.js && cp ../${npm_package_name}/dist/${npm_package_name}.min.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git add ${npm_package_name}.v${npm_package_version%%.*}.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git commit -m \"${npm_package_name} ${npm_package_version}\" && git push && cd - && zip -j dist/${npm_package_name}.zip -- LICENSE README.md dist/${npm_package_name}.js dist/${npm_package_name}.min.js"
+ },
+ "devDependencies": {
+ "d3-array": "1",
+ "eslint": "5",
+ "rollup": "0.64",
+ "rollup-plugin-terser": "1",
+ "tape": "4"
+ }
+}
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 0000000..804bba8
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,36 @@
+import {terser} from "rollup-plugin-terser";
+import * as meta from "./package.json";
+
+const config = {
+ input: "src/index.js",
+ external: Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)),
+ output: {
+ file: `dist/${meta.name}.js`,
+ name: "d3",
+ format: "umd",
+ indent: false,
+ extend: true,
+ banner: `// ${meta.homepage} v${meta.version} Copyright ${(new Date).getFullYear()} ${meta.author.name}`,
+ globals: Object.assign({}, ...Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)).map(key => ({[key]: "d3"})))
+ },
+ plugins: []
+};
+
+export default [
+ config,
+ {
+ ...config,
+ output: {
+ ...config.output,
+ file: `dist/${meta.name}.min.js`
+ },
+ plugins: [
+ ...config.plugins,
+ terser({
+ output: {
+ preamble: config.output.banner
+ }
+ })
+ ]
+ }
+];
diff --git a/src/entries.js b/src/entries.js
new file mode 100644
index 0000000..03d5ee6
--- /dev/null
+++ b/src/entries.js
@@ -0,0 +1,5 @@
+export default function(map) {
+ var entries = [];
+ for (var key in map) entries.push({key: key, value: map[key]});
+ return entries;
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..d454e73
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,6 @@
+export {default as nest} from "./nest";
+export {default as set} from "./set";
+export {default as map} from "./map";
+export {default as keys} from "./keys";
+export {default as values} from "./values";
+export {default as entries} from "./entries";
diff --git a/src/keys.js b/src/keys.js
new file mode 100644
index 0000000..1206f61
--- /dev/null
+++ b/src/keys.js
@@ -0,0 +1,5 @@
+export default function(map) {
+ var keys = [];
+ for (var key in map) keys.push(key);
+ return keys;
+}
diff --git a/src/map.js b/src/map.js
new file mode 100644
index 0000000..6459e57
--- /dev/null
+++ b/src/map.js
@@ -0,0 +1,75 @@
+export var prefix = "$";
+
+function Map() {}
+
+Map.prototype = map.prototype = {
+ constructor: Map,
+ has: function(key) {
+ return (prefix + key) in this;
+ },
+ get: function(key) {
+ return this[prefix + key];
+ },
+ set: function(key, value) {
+ this[prefix + key] = value;
+ return this;
+ },
+ remove: function(key) {
+ var property = prefix + key;
+ return property in this && delete this[property];
+ },
+ clear: function() {
+ for (var property in this) if (property[0] === prefix) delete this[property];
+ },
+ keys: function() {
+ var keys = [];
+ for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
+ return keys;
+ },
+ values: function() {
+ var values = [];
+ for (var property in this) if (property[0] === prefix) values.push(this[property]);
+ return values;
+ },
+ entries: function() {
+ var entries = [];
+ for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
+ return entries;
+ },
+ size: function() {
+ var size = 0;
+ for (var property in this) if (property[0] === prefix) ++size;
+ return size;
+ },
+ empty: function() {
+ for (var property in this) if (property[0] === prefix) return false;
+ return true;
+ },
+ each: function(f) {
+ for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
+ }
+};
+
+function map(object, f) {
+ var map = new Map;
+
+ // Copy constructor.
+ if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
+
+ // Index array by numeric index or specified key function.
+ else if (Array.isArray(object)) {
+ var i = -1,
+ n = object.length,
+ o;
+
+ if (f == null) while (++i < n) map.set(i, object[i]);
+ else while (++i < n) map.set(f(o = object[i], i, object), o);
+ }
+
+ // Convert object to map.
+ else if (object) for (var key in object) map.set(key, object[key]);
+
+ return map;
+}
+
+export default map;
diff --git a/src/nest.js b/src/nest.js
new file mode 100644
index 0000000..21c2a4a
--- /dev/null
+++ b/src/nest.js
@@ -0,0 +1,73 @@
+import map from "./map";
+
+export default function() {
+ var keys = [],
+ sortKeys = [],
+ sortValues,
+ rollup,
+ nest;
+
+ function apply(array, depth, createResult, setResult) {
+ if (depth >= keys.length) {
+ if (sortValues != null) array.sort(sortValues);
+ return rollup != null ? rollup(array) : array;
+ }
+
+ var i = -1,
+ n = array.length,
+ key = keys[depth++],
+ keyValue,
+ value,
+ valuesByKey = map(),
+ values,
+ result = createResult();
+
+ while (++i < n) {
+ if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
+ values.push(value);
+ } else {
+ valuesByKey.set(keyValue, [value]);
+ }
+ }
+
+ valuesByKey.each(function(values, key) {
+ setResult(result, key, apply(values, depth, createResult, setResult));
+ });
+
+ return result;
+ }
+
+ function entries(map, depth) {
+ if (++depth > keys.length) return map;
+ var array, sortKey = sortKeys[depth - 1];
+ if (rollup != null && depth >= keys.length) array = map.entries();
+ else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
+ return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
+ }
+
+ return nest = {
+ object: function(array) { return apply(array, 0, createObject, setObject); },
+ map: function(array) { return apply(array, 0, createMap, setMap); },
+ entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
+ key: function(d) { keys.push(d); return nest; },
+ sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
+ sortValues: function(order) { sortValues = order; return nest; },
+ rollup: function(f) { rollup = f; return nest; }
+ };
+}
+
+function createObject() {
+ return {};
+}
+
+function setObject(object, key, value) {
+ object[key] = value;
+}
+
+function createMap() {
+ return map();
+}
+
+function setMap(map, key, value) {
+ map.set(key, value);
+}
diff --git a/src/set.js b/src/set.js
new file mode 100644
index 0000000..7c67e00
--- /dev/null
+++ b/src/set.js
@@ -0,0 +1,39 @@
+import {default as map, prefix} from "./map";
+
+function Set() {}
+
+var proto = map.prototype;
+
+Set.prototype = set.prototype = {
+ constructor: Set,
+ has: proto.has,
+ add: function(value) {
+ value += "";
+ this[prefix + value] = value;
+ return this;
+ },
+ remove: proto.remove,
+ clear: proto.clear,
+ values: proto.keys,
+ size: proto.size,
+ empty: proto.empty,
+ each: proto.each
+};
+
+function set(object, f) {
+ var set = new Set;
+
+ // Copy constructor.
+ if (object instanceof Set) object.each(function(value) { set.add(value); });
+
+ // Otherwise, assume it’s an array.
+ else if (object) {
+ var i = -1, n = object.length;
+ if (f == null) while (++i < n) set.add(object[i]);
+ else while (++i < n) set.add(f(object[i], i, object));
+ }
+
+ return set;
+}
+
+export default set;
diff --git a/src/values.js b/src/values.js
new file mode 100644
index 0000000..69b093d
--- /dev/null
+++ b/src/values.js
@@ -0,0 +1,5 @@
+export default function(map) {
+ var values = [];
+ for (var key in map) values.push(map[key]);
+ return values;
+}
diff --git a/test/entries-test.js b/test/entries-test.js
new file mode 100644
index 0000000..2a8edd4
--- /dev/null
+++ b/test/entries-test.js
@@ -0,0 +1,35 @@
+var tape = require("tape"),
+ d3 = Object.assign({}, require("d3-array"), require("../"));
+
+require("./isNaN");
+
+tape("entries(object) enumerates every entry", function(test) {
+ test.deepEqual(d3.entries({a: 1, b: 2}).sort(ascendingKey), [{key: "a", value: 1}, {key: "b", value: 2}]);
+ test.end();
+});
+
+tape("entries(object) includes entries defined on prototypes", function(test) {
+ function abc() {
+ this.a = 1;
+ this.b = 2;
+ }
+ abc.prototype.c = 3;
+ test.deepEqual(d3.entries(new abc).sort(ascendingKey), [{key: "a", value: 1}, {key: "b", value: 2}, {key: "c", value: 3}]);
+ test.end();
+});
+
+tape("entries(object) includes null, undefined and NaN values", function(test) {
+ var v = d3.entries({a: null, b: undefined, c: NaN}).sort(ascendingKey);
+ test.equal(v.length, 3);
+ test.equal(v[0].key, "a");
+ test.equal(v[0].value, null);
+ test.equal(v[1].key, "b");
+ test.equal(v[1].value, undefined);
+ test.equal(v[2].key, "c");
+ test.isNaN(v[2].value);
+ test.end();
+});
+
+function ascendingKey(a, b) {
+ return d3.ascending(a.key, b.key);
+}
diff --git a/test/isNaN.js b/test/isNaN.js
new file mode 100644
index 0000000..2a31629
--- /dev/null
+++ b/test/isNaN.js
@@ -0,0 +1,10 @@
+var tape = require("tape");
+
+tape.Test.prototype.isNaN = function(actual) {
+ this._assert(isNaN(actual) && actual !== actual, {
+ message: "should be NaN",
+ operator: "isNaN",
+ actual: actual,
+ expected: NaN
+ });
+};
diff --git a/test/keys-test.js b/test/keys-test.js
new file mode 100644
index 0000000..7f43043
--- /dev/null
+++ b/test/keys-test.js
@@ -0,0 +1,24 @@
+var tape = require("tape"),
+ d3 = Object.assign({}, require("d3-array"), require("../"));
+
+require("./isNaN");
+
+tape("keys(object) enumerates every entry", function(test) {
+ test.deepEqual(d3.keys({a: 1, b: 2}).sort(d3.ascending), ["a", "b"]);
+ test.end();
+});
+
+tape("keys(object) includes keys defined on prototypes", function(test) {
+ function abc() {
+ this.a = 1;
+ this.b = 2;
+ }
+ abc.prototype.c = 3;
+ test.deepEqual(d3.keys(new abc).sort(d3.ascending), ["a", "b", "c"]);
+ test.end();
+});
+
+tape("keys(object) includes null, undefined and NaN values", function(test) {
+ test.deepEqual(d3.keys({a: null, b: undefined, c: NaN}).sort(d3.ascending), ["a", "b", "c"]);
+ test.end();
+});
diff --git a/test/map-test.js b/test/map-test.js
new file mode 100644
index 0000000..69ba0a8
--- /dev/null
+++ b/test/map-test.js
@@ -0,0 +1,353 @@
+var tape = require("tape"),
+ d3 = require("../");
+
+tape("map() returns an empty map", function(test) {
+ var m = d3.map();
+ test.equal(m instanceof d3.map, true);
+ test.deepEqual(m.keys(), []);
+ test.end();
+});
+
+tape("map(null) returns an empty map", function(test) {
+ var m = d3.map(null);
+ test.deepEqual(m.keys(), []);
+ test.end();
+});
+
+tape("map(object) copies enumerable keys", function(test) {
+ var m1 = d3.map({foo: 42});
+ test.equal(m1.has("foo"), true);
+ test.equal(m1.get("foo"), 42);
+ var m2 = d3.map(Object.create(null, {foo: {value: 42, enumerable: true}}));
+ test.equal(m2.has("foo"), true);
+ test.equal(m2.get("foo"), 42);
+ test.end();
+});
+
+tape("map(object) copies inherited keys", function(test) {
+ function Foo() {}
+ Foo.prototype.foo = 42;
+ var m1 = d3.map(Object.create({foo: 42}));
+ test.equal(m1.has("foo"), true);
+ test.equal(m1.get("foo"), 42);
+ var m2 = d3.map(new Foo());
+ test.equal(m2.has("foo"), true);
+ test.equal(m2.get("foo"), 42);
+ test.end();
+});
+
+tape("map(object) does not copy non-enumerable keys", function(test) {
+ var m1 = d3.map({__proto__: 42}); // because __proto__ isn't enumerable
+ test.equal(m1.has("__proto__"), false);
+ test.equal(m1.get("__proto__"), undefined);
+ var m2 = d3.map(Object.create(null, {foo: {value: 42, enumerable: false}}));
+ test.equal(m2.has("foo"), false);
+ test.equal(m2.get("foo"), undefined);
+ test.end();
+});
+
+tape("map(map) copies the given map", function(test) {
+ var a = d3.map({foo: 42}),
+ b = d3.map(a);
+ test.equal(b.has("foo"), true);
+ test.equal(b.get("foo"), 42);
+ a.set("bar", true);
+ test.equal(b.has("bar"), false);
+ test.end();
+});
+
+tape("map(array) creates a map by index", function(test) {
+ test.deepEqual(d3.map(["foo", "bar"]).entries(), [{key: "0", value: "foo"}, {key: "1", value: "bar"}]);
+ test.end();
+});
+
+tape("map(array) indexes missing elements in sparse collection", function(test) {
+ // eslint-disable-next-line no-sparse-arrays
+ test.deepEqual(d3.map(["foo",, "bar"]).entries(), [{key: "0", value: "foo"}, {key: "1", value: undefined}, {key: "2", value: "bar"}]);
+ test.end();
+});
+
+tape("map(array, f) creates a map by accessor", function(test) {
+ test.deepEqual(d3.map([{field: "foo"}, {field: "bar"}], function(d) { return d.field; }).entries(), [{key: "foo", value: {field: "foo"}}, {key: "bar", value: {field: "bar"}}]);
+ test.deepEqual(d3.map([{field: "foo"}, {field: "bar"}], function(d, i) { return i; }).entries(), [{key: "0", value: {field: "foo"}}, {key: "1", value: {field: "bar"}}]);
+ test.deepEqual(d3.map([{field: "foo"}, {field: "bar"}], function(d, i, array) { return array[i].field; }).entries(), [{key: "foo", value: {field: "foo"}}, {key: "bar", value: {field: "bar"}}]);
+ test.end();
+});
+
+tape("map.size() returns the number of distinct keys", function(test) {
+ var m = d3.map();
+ test.equal(m.size(), 0);
+ m.set("foo", 1);
+ test.equal(m.size(), 1);
+ m.set("foo", 2);
+ test.equal(m.size(), 1);
+ m.set("bar", 2);
+ test.equal(m.size(), 2);
+ m.remove("foo");
+ test.equal(m.size(), 1);
+ m.remove("foo");
+ test.equal(m.size(), 1);
+ m.remove("bar");
+ test.equal(m.size(), 0);
+ test.end();
+});
+
+tape("map.clear() removes all entries", function(test) {
+ var m = d3.map().set("foo", 1).set("bar", 2).set("foo", 3);
+ test.equal(m.size(), 2);
+ m.clear();
+ test.equal(m.size(), 0);
+ test.deepEqual(m.entries(), []);
+ test.end();
+});
+
+tape("map.empty() returns true only if the map is empty", function(test) {
+ var m = d3.map();
+ test.equal(m.empty(), true);
+ m.set("foo", 1);
+ test.equal(m.empty(), false);
+ m.set("foo", 2);
+ test.equal(m.empty(), false);
+ m.set("bar", 2);
+ test.equal(m.empty(), false);
+ m.remove("foo");
+ test.equal(m.empty(), false);
+ m.remove("foo");
+ test.equal(m.empty(), false);
+ m.remove("bar");
+ test.equal(m.empty(), true);
+ test.end();
+});
+
+tape("map.each(callback) passes value, key and the map", function(test) {
+ var m = d3.map({foo: 1, bar: "42"}),
+ c = [];
+ m.each(function(v, k, m) { c.push([k, v, m]); });
+ c.sort(function(a, b) { return a[0].localeCompare(b[0]); });
+ test.deepEqual(c, [["bar", "42", m], ["foo", 1, m]]);
+ test.end();
+});
+
+tape("map.each(callback) uses the global context", function(test) {
+ var m = d3.map({foo: 1, bar: "42"}),
+ c = [];
+ m.each(function() { c.push(this); });
+ test.strictEqual(c[0], global);
+ test.strictEqual(c[1], global);
+ test.equal(c.length, 2);
+ test.end();
+});
+
+tape("map.each(callback) iterates in arbitrary order", function(test) {
+ var m1 = d3.map({foo: 1, bar: "42"}),
+ m2 = d3.map({bar: "42", foo: 1}),
+ c1 = [],
+ c2 = [];
+ m1.each(function(v, k) { c1.push([k, v]); });
+ m2.each(function(v, k) { c2.push([k, v]); });
+ c1.sort(function(a, b) { return a[0].localeCompare(b[0]); });
+ c2.sort(function(a, b) { return a[0].localeCompare(b[0]); });
+ test.deepEqual(c1, c2);
+ test.end();
+});
+
+tape("map.keys() returns an array of string keys", function(test) {
+ var m = d3.map({foo: 1, bar: "42"});
+ test.deepEqual(m.keys().sort(), ["bar", "foo"]);
+ test.end();
+});
+
+tape("map.keys() properly unescapes zero-prefixed keys", function(test) {
+ var m = d3.map().set("__proto__", 42).set("$weird", 42);
+ test.deepEqual(m.keys().sort(), ["$weird", "__proto__"]);
+ test.end();
+});
+
+tape("map.values() returns an array of arbitrary values", function(test) {
+ var m = d3.map({foo: 1, bar: "42"});
+ test.deepEqual(m.values().sort(), [1, "42"]);
+ test.end();
+});
+
+tape("map.entries() returns an array of key-value objects", function(test) {
+ var m = d3.map({foo: 1, bar: "42"});
+ test.deepEqual(m.entries().sort(ascendingByKey), [{key: "bar", value: "42"}, {key: "foo", value: 1}]);
+ test.end();
+});
+
+tape("map.entries() empty maps have an empty entries array", function(test) {
+ var m = d3.map();
+ test.deepEqual(m.entries(), []);
+ m.set("foo", "bar");
+ test.deepEqual(m.entries(), [{key: "foo", value: "bar"}]);
+ m.remove("foo");
+ test.deepEqual(m.entries(), []);
+ test.end();
+});
+
+tape("map.entries() entries are returned in arbitrary order", function(test) {
+ var m1 = d3.map({foo: 1, bar: "42"});
+ test.deepEqual(m1.entries().sort(ascendingByKey), [{key: "bar", value: "42"}, {key: "foo", value: 1}]);
+ var m2 = d3.map({bar: "42", foo: 1});
+ test.deepEqual(m2.entries().sort(ascendingByKey), [{key: "bar", value: "42"}, {key: "foo", value: 1}]);
+ test.end();
+});
+
+tape("map.entries() observes changes via set and remove", function(test) {
+ var m = d3.map({foo: 1, bar: "42"});
+ test.deepEqual(m.entries().sort(ascendingByKey), [{key: "bar", value: "42"}, {key: "foo", value: 1}]);
+ m.remove("foo");
+ test.deepEqual(m.entries(), [{key: "bar", value: "42"}]);
+ m.set("bar", "bar");
+ test.deepEqual(m.entries(), [{key: "bar", value: "bar"}]);
+ m.set("foo", "foo");
+ test.deepEqual(m.entries().sort(ascendingByKey), [{key: "bar", value: "bar"}, {key: "foo", value: "foo"}]);
+ m.remove("bar");
+ test.deepEqual(m.entries(), [{key: "foo", value: "foo"}]);
+ m.remove("foo");
+ test.deepEqual(m.entries(), []);
+ m.remove("foo");
+ test.deepEqual(m.entries(), []);
+ test.end();
+});
+
+tape("map.has(key) empty maps do not have object built-ins", function(test) {
+ var m = d3.map();
+ test.equal(m.has("__proto__"), false);
+ test.equal(m.has("hasOwnProperty"), false);
+ test.end();
+});
+
+tape("map.has(key) can has keys using built-in names", function(test) {
+ var m = d3.map().set("__proto__", 42);
+ test.equal(m.has("__proto__"), true);
+ test.end();
+});
+
+tape("map.has(key) can has keys with null or undefined properties", function(test) {
+ var m = d3.map().set("", "").set("null", null).set("undefined", undefined);
+ test.equal(m.has(""), true);
+ test.equal(m.has("null"), true);
+ test.equal(m.has("undefined"), true);
+ test.end();
+});
+
+tape("map.has(key) coerces keys to strings", function(test) {
+ var m = d3.map({"42": "foo", "null": 1, "undefined": 2});
+ test.equal(m.has(42), true);
+ test.equal(m.has(null), true);
+ test.equal(m.has(undefined), true);
+ test.end();
+});
+
+tape("map.has(key) returns the latest value", function(test) {
+ var m = d3.map({foo: 42});
+ test.equal(m.has("foo"), true);
+ m.set("foo", 43);
+ test.equal(m.has("foo"), true);
+ m.remove("foo");
+ test.equal(m.has("foo"), false);
+ m.set("foo", "bar");
+ test.equal(m.has("foo"), true);
+ test.end();
+});
+
+tape("map.has(key) returns undefined for missing keys", function(test) {
+ var m = d3.map({foo: 42});
+ test.equal(m.has("bar"), false);
+ test.end();
+});
+
+tape("map.get(key) empty maps do not have object built-ins", function(test) {
+ var m = d3.map();
+ test.equal(m.get("__proto__"), undefined);
+ test.equal(m.get("hasOwnProperty"), undefined);
+ test.end()
+});
+
+tape("map.get(key) can get keys using built-in names", function(test) {
+ var m = d3.map();
+ m.set("__proto__", 42);
+ test.equal(m.get("__proto__"), 42);
+ test.end()
+});
+
+tape("map.get(key) coerces keys to strings", function(test) {
+ var m = d3.map({"42": 1, "null": 2, "undefined": 3});
+ test.equal(m.get(42), 1);
+ test.equal(m.get(null), 2);
+ test.equal(m.get(undefined), 3);
+ test.end()
+});
+
+tape("map.get(key) returns the latest value", function(test) {
+ var m = d3.map({foo: 42});
+ test.equal(m.get("foo"), 42);
+ m.set("foo", 43);
+ test.equal(m.get("foo"), 43);
+ m.remove("foo");
+ test.equal(m.get("foo"), undefined);
+ m.set("foo", "bar");
+ test.equal(m.get("foo"), "bar");
+ test.end()
+});
+
+tape("map.get(key) returns undefined for missing keys", function(test) {
+ var m = d3.map({foo: 42});
+ test.equal(m.get("bar"), undefined);
+ test.end()
+});
+
+tape("map.set(key, value) returns the map", function(test) {
+ var m = d3.map();
+ test.equal(m.set("foo", 42), m);
+ test.end();
+});
+
+tape("map.set(key, value) can set keys using built-in names", function(test) {
+ var m = d3.map();
+ m.set("__proto__", 42);
+ test.equal(m.get("__proto__"), 42);
+ test.end();
+});
+
+tape("map.set(key, value) can set keys using zero-prefixed names", function(test) {
+ var m = d3.map();
+ m.set("$weird", 42);
+ test.equal(m.get("$weird"), 42);
+ test.end();
+});
+
+tape("map.set(key, value) coerces keys to strings", function(test) {
+ var m = d3.map();
+ m.set(42, 1);
+ test.equal(m.get(42), 1);
+ m.set(null, 2);
+ test.equal(m.get(null), 2);
+ m.set(undefined, 3);
+ test.equal(m.get(undefined), 3);
+ test.deepEqual(m.keys().sort(), ["42", "null", "undefined"]);
+ test.end();
+});
+
+tape("map.set(key, value) can replace values", function(test) {
+ var m = d3.map({foo: 42});
+ test.equal(m.get("foo"), 42);
+ m.set("foo", 43);
+ test.equal(m.get("foo"), 43);
+ m.set("foo", "bar");
+ test.equal(m.get("foo"), "bar");
+ test.end();
+});
+
+tape("map.set(key, value) can set null, undefined or empty string values", function(test) {
+ var m = d3.map().set("", "").set("null", null).set("undefined", undefined);
+ test.equal(m.get(""), "");
+ test.equal(m.get("null"), null);
+ test.equal(m.get("undefined"), undefined);
+ test.end();
+});
+
+function ascendingByKey(a, b) {
+ return a.key.localeCompare(b.key);
+}
diff --git a/test/nest-test.js b/test/nest-test.js
new file mode 100644
index 0000000..717a578
--- /dev/null
+++ b/test/nest-test.js
@@ -0,0 +1,172 @@
+var tape = require("tape"),
+ d3 = Object.assign({}, require("d3-array"), require("../"));
+
+tape("nest.entries(array) returns the array of input values, in input order", function(test) {
+ var nest = d3.nest();
+ test.deepEqual(nest.entries([1, 2, 3]), [1, 2, 3]);
+ test.deepEqual(nest.entries([1, 3, 2]), [1, 3, 2]);
+ test.deepEqual(nest.entries([3, 1, 2]), [3, 1, 2]);
+ test.end();
+});
+
+tape("nest.sortValues(order).entries(array) returns input values in sorted order", function(test) {
+ var nestAscending = d3.nest().sortValues(function(a, b) { return a.foo - b.foo; }),
+ nestDescending = d3.nest().sortValues(function(a, b) { return b.foo - a.foo; }),
+ a = {foo: 1},
+ b = {foo: 2},
+ c = {foo: 3};
+ test.deepEqual(nestAscending.entries([a, b, c]), [a, b, c]);
+ test.deepEqual(nestAscending.entries([a, c, b]), [a, b, c]);
+ test.deepEqual(nestAscending.entries([c, a, b]), [a, b, c]);
+ test.deepEqual(nestDescending.entries([a, b, c]), [c, b, a]);
+ test.deepEqual(nestDescending.entries([a, c, b]), [c, b, a]);
+ test.deepEqual(nestDescending.entries([c, a, b]), [c, b, a]);
+ test.end();
+});
+
+tape("nest.key(key).entries(array) returns entries for each distinct key, with values in input order", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.ascending),
+ a = {foo: 1},
+ b = {foo: 1},
+ c = {foo: 2};
+ test.deepEqual(nest.entries([c, a, b, c]), [{key: "1", values: [a, b]}, {key: "2", values: [c, c]}]);
+ test.deepEqual(nest.entries([c, b, a, c]), [{key: "1", values: [b, a]}, {key: "2", values: [c, c]}]);
+ test.end();
+});
+
+tape("nest.key(key) coerces key values to strings", function(test) {
+ var nest = d3.nest().key(function(d) { return d.number ? 1 : "1"; }).sortKeys(d3.ascending),
+ a = {number: true},
+ b = {number: false};
+ test.deepEqual(nest.entries([a, b]), [{key: "1", values: [a, b]}]);
+ test.end();
+});
+
+tape("nest.key(key1).key(key2).entries(array) returns entries for each distinct key set, with values in input order", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.ascending).key(function(d) { return d.bar; }).sortKeys(d3.ascending),
+ a = {foo: 1, bar: "a"},
+ b = {foo: 1, bar: "a"},
+ c = {foo: 2, bar: "a"},
+ d = {foo: 1, bar: "b"},
+ e = {foo: 1, bar: "b"},
+ f = {foo: 2, bar: "b"};
+ test.deepEqual(nest.entries([a, b, c, d, e, f]), [{key: "1", values: [{key: "a", values: [a, b]}, {key: "b", values: [d, e]}]}, {key: "2", values: [{key: "a", values: [c]}, {key: "b", values: [f]}]}]);
+ test.deepEqual(nest.entries([f, e, d, c, b, a]), [{key: "1", values: [{key: "a", values: [b, a]}, {key: "b", values: [e, d]}]}, {key: "2", values: [{key: "a", values: [c]}, {key: "b", values: [f]}]}]);
+ test.end();
+});
+
+tape("nest.key(key).sortKeys(order).entries(array) sorts entries by key using the specified order function", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.descending),
+ a = {foo: 1},
+ b = {foo: 1},
+ c = {foo: 2};
+ test.deepEqual(nest.entries([c, a, b, c]), [{key: "2", values: [c, c]}, {key: "1", values: [a, b]}]);
+ test.deepEqual(nest.entries([c, b, a, c]), [{key: "2", values: [c, c]}, {key: "1", values: [b, a]}]);
+ test.end();
+});
+
+tape("nest.key(key1).sortKeys(order1).key(key2).sortKeys(order2).entries(array) sorts entries by key using the specified order functions", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.descending).key(function(d) { return d.bar; }).sortKeys(d3.descending),
+ a = {foo: 1, bar: "a"},
+ b = {foo: 1, bar: "a"},
+ c = {foo: 2, bar: "a"},
+ d = {foo: 1, bar: "b"},
+ e = {foo: 1, bar: "b"},
+ f = {foo: 2, bar: "b"};
+ test.deepEqual(nest.entries([a, b, c, d, e, f]), [{key: "2", values: [{key: "b", values: [f]}, {key: "a", values: [c]}]}, {key: "1", values: [{key: "b", values: [d, e]}, {key: "a", values: [a, b]}]}]);
+ test.deepEqual(nest.entries([f, e, d, c, b, a]), [{key: "2", values: [{key: "b", values: [f]}, {key: "a", values: [c]}]}, {key: "1", values: [{key: "b", values: [e, d]}, {key: "a", values: [b, a]}]}]);
+ test.end();
+});
+
+tape("nest.rollup(rollup).entries(array) aggregates values using the specified rollup function", function(test) {
+ test.equal(d3.nest().rollup(function(values) { return values.length; }).entries([1, 2, 3, 4, 5]), 5);
+ test.equal(d3.nest().rollup(d3.sum).entries([1, 2, 3, 4, 5]), 1 + 2 + 3 + 4 + 5);
+ test.equal(d3.nest().rollup(d3.max).entries([1, 2, 3, 4, 5]), 5);
+ test.deepEqual(d3.nest().rollup(d3.extent).entries([1, 2, 3, 4, 5]), [1, 5]);
+ test.end();
+});
+
+tape("nest.rollup(rollup) uses the global this context", function(test) {
+ var that;
+ d3.nest().rollup(function() { that = this; }).entries([1, 2, 3, 4, 5]);
+ test.equal(that, global);
+ test.end();
+});
+
+tape("nest.key(key).rollup(rollup).entries(array) aggregates values per key using the specified rollup function", function(test) {
+ var a = {foo: 1},
+ b = {foo: 1},
+ c = {foo: 2};
+ test.deepEqual(d3.nest().key(function(d) { return d.foo; }).rollup(function(values) { return values.length; }).entries([a, b, c]), [{key: "1", value: 2}, {key: "2", value: 1}]);
+ test.end();
+});
+
+tape("nest.key(key).sortValues(order).rollup(rollup).entries(array) sorts values before rollup", function(test) {
+ var a = {foo: 1, bar: 1},
+ b = {foo: 1, bar: 2},
+ c = {foo: 2, bar: 3};
+ test.deepEqual(d3.nest().key(function(d) { return d.foo; }).sortValues(function(a, b) { return b.bar - a.bar; }).rollup(function(values) { return values[0].bar; }).entries([a, b, c]), [{key: "1", value: 2}, {key: "2", value: 3}]);
+ test.end();
+});
+
+tape("nest.map(array) returns the array of input values, in input order", function(test) {
+ var nest = d3.nest();
+ test.deepEqual(nest.map([1, 2, 3]), [1, 2, 3]);
+ test.deepEqual(nest.map([1, 3, 2]), [1, 3, 2]);
+ test.deepEqual(nest.map([3, 1, 2]), [3, 1, 2]);
+ test.end();
+});
+
+tape("nest.sortValues(order).map(array) returns input values in sorted order", function(test) {
+ var nestAscending = d3.nest().sortValues(function(a, b) { return a.foo - b.foo; }),
+ nestDescending = d3.nest().sortValues(function(a, b) { return b.foo - a.foo; }),
+ a = {foo: 1},
+ b = {foo: 2},
+ c = {foo: 3};
+ test.deepEqual(nestAscending.map([a, b, c]), [a, b, c]);
+ test.deepEqual(nestAscending.map([a, c, b]), [a, b, c]);
+ test.deepEqual(nestAscending.map([c, a, b]), [a, b, c]);
+ test.deepEqual(nestDescending.map([a, b, c]), [c, b, a]);
+ test.deepEqual(nestDescending.map([a, c, b]), [c, b, a]);
+ test.deepEqual(nestDescending.map([c, a, b]), [c, b, a]);
+ test.end();
+});
+
+tape("nest.key(key).map(array) returns entries for each distinct key, with values in input order", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.ascending),
+ a = {foo: 1},
+ b = {foo: 1},
+ c = {foo: 2};
+ test.deepEqual(nest.map([c, a, b, c]), d3.map({1: [a, b], 2: [c, c]}));
+ test.deepEqual(nest.map([c, b, a, c]), d3.map({1: [b, a], 2: [c, c]}));
+ test.end();
+});
+
+tape("nest.key(key1).key(key2).map(array) returns entries for each distinct key set, with values in input order", function(test) {
+ var nest = d3.nest().key(function(d) { return d.foo; }).sortKeys(d3.ascending).key(function(d) { return d.bar; }).sortKeys(d3.ascending),
+ a = {foo: 1, bar: "a"},
+ b = {foo: 1, bar: "a"},
+ c = {foo: 2, bar: "a"},
+ d = {foo: 1, bar: "b"},
+ e = {foo: 1, bar: "b"},
+ f = {foo: 2, bar: "b"};
+ test.deepEqual(nest.map([a, b, c, d, e, f]), d3.map({1: d3.map({a: [a, b], b: [d, e]}), 2: d3.map({a: [c], b: [f]})}));
+ test.deepEqual(nest.map([f, e, d, c, b, a]), d3.map({1: d3.map({a: [b, a], b: [e, d]}), 2: d3.map({a: [c], b: [f]})}));
+ test.end();
+});
+
+tape("nest.rollup(rollup).map(array) aggregates values using the specified rollup function", function(test) {
+ test.equal(d3.nest().rollup(function(values) { return values.length; }).map([1, 2, 3, 4, 5]), 5);
+ test.equal(d3.nest().rollup(d3.sum).map([1, 2, 3, 4, 5]), 1 + 2 + 3 + 4 + 5);
+ test.equal(d3.nest().rollup(d3.max).map([1, 2, 3, 4, 5]), 5);
+ test.deepEqual(d3.nest().rollup(d3.extent).map([1, 2, 3, 4, 5]), [1, 5]);
+ test.end();
+});
+
+tape("nest.key(key).rollup(rollup).map(array) aggregates values per key using the specified rollup function", function(test) {
+ var a = {foo: 1},
+ b = {foo: 1},
+ c = {foo: 2};
+ test.deepEqual(d3.nest().key(function(d) { return d.foo; }).rollup(function(values) { return values.length; }).map([a, b, c]), d3.map({1: 2, 2: 1}));
+ test.end();
+});
diff --git a/test/set-test.js b/test/set-test.js
new file mode 100644
index 0000000..dda6b14
--- /dev/null
+++ b/test/set-test.js
@@ -0,0 +1,254 @@
+var tape = require("tape"),
+ d3 = Object.assign({}, require("d3-array"), require("../"));
+
+tape("set() returns an empty set", function(test) {
+ var s = d3.set();
+ test.equal(s instanceof d3.set, true);
+ test.deepEqual(s.values(), []);
+ test.end();
+});
+
+tape("set(null) returns an empty set", function(test) {
+ var s = d3.set(null);
+ test.deepEqual(s.values(), []);
+ test.end();
+});
+
+tape("set(array) adds array entries", function(test) {
+ var s1 = d3.set(["foo"]);
+ test.equal(s1.has("foo"), true);
+ var s2 = d3.set(["foo", "bar"]);
+ test.equal(s2.has("foo"), true);
+ test.equal(s2.has("bar"), true);
+ test.end();
+});
+
+tape("set(array, f) observes the specified accessor function", function(test) {
+ var name = function(d) { return d.name; };
+ var s1 = d3.set([{name: "foo"}], name);
+ test.equal(s1.has("foo"), true);
+ var s2 = d3.set([{name: "foo"}, {name: "bar"}], name);
+ test.equal(s2.has("foo"), true);
+ test.equal(s2.has("bar"), true);
+ test.end();
+});
+
+tape("set(set) copies the given set", function(test) {
+ var a = d3.set(["foo"]),
+ b = d3.set(a);
+ test.equal(b.has("foo"), true);
+ test.equal(b.has("foo"), true);
+ a.add("bar");
+ test.equal(b.has("bar"), false);
+ test.end();
+});
+
+tape("set.size() returns the number of distinct values", function(test) {
+ var s = d3.set();
+ test.equal(s.size(), 0);
+ s.add("foo");
+ test.equal(s.size(), 1);
+ s.add("foo");
+ test.equal(s.size(), 1);
+ s.add("bar");
+ test.equal(s.size(), 2);
+ s.remove("foo");
+ test.equal(s.size(), 1);
+ s.remove("foo");
+ test.equal(s.size(), 1);
+ s.remove("bar");
+ test.equal(s.size(), 0);
+ test.end();
+});
+
+tape("set.clear() removes all values", function(test) {
+ var s = d3.set().add("foo").add("bar").add("foo");
+ test.equal(s.size(), 2);
+ s.clear();
+ test.equal(s.size(), 0);
+ test.deepEqual(s.values(), []);
+ test.end();
+});
+
+tape("set.empty() returns true only if the set is empty", function(test) {
+ var s = d3.set();
+ test.equal(s.empty(), true);
+ s.add("foo");
+ test.equal(s.empty(), false);
+ s.add("foo");
+ test.equal(s.empty(), false);
+ s.add("bar");
+ test.equal(s.empty(), false);
+ s.remove("foo");
+ test.equal(s.empty(), false);
+ s.remove("foo");
+ test.equal(s.empty(), false);
+ s.remove("bar");
+ test.equal(s.empty(), true);
+ test.end();
+});
+
+tape("set.each(callback) passes value, value and the set", function(test) {
+ var s = d3.set(["foo", "bar"]),
+ c = [];
+ s.each(function(v0, v1, s) { c.push([v0, v1, s]); });
+ c.sort();
+ test.deepEqual(c, [["bar", "bar", s], ["foo", "foo", s]]);
+ test.end();
+});
+
+tape("set.each(callback) uses the global context", function(test) {
+ var s = d3.set(["foo", "bar"]),
+ c = [];
+ s.each(function() { c.push(this); });
+ test.strictEqual(c[0], global);
+ test.strictEqual(c[1], global);
+ test.equal(c.length, 2);
+ test.end();
+});
+
+tape("set.each(callback) iterates in arbitrary order", function(test) {
+ var s1 = d3.set(["foo", "bar"]),
+ s2 = d3.set(["bar", "foo"]),
+ c1 = [],
+ c2 = [];
+ s1.each(function(v) { c1.push(v); });
+ s2.each(function(v) { c2.push(v); });
+ c1.sort();
+ c2.sort();
+ test.deepEqual(c1, c2);
+ test.end();
+});
+
+tape("set.values() returns an array of string values", function(test) {
+ var s = d3.set(["foo", "bar"]);
+ test.deepEqual(s.values().sort(), ["bar", "foo"]);
+ test.end();
+});
+
+tape("set.values() empty sets have an empty values array", function(test) {
+ var s = d3.set();
+ test.deepEqual(s.values(), []);
+ s.add("foo");
+ test.deepEqual(s.values(), ["foo"]);
+ s.remove("foo");
+ test.deepEqual(s.values(), []);
+ test.end();
+});
+
+tape("set.values() values are returned in arbitrary order", function(test) {
+ var s1 = d3.set(["foo", "bar"]);
+ test.deepEqual(s1.values().sort(d3.ascending), ["bar", "foo"]);
+ var s2 = d3.set(["bar", "foo"]);
+ test.deepEqual(s2.values().sort(d3.ascending), ["bar", "foo"]);
+ test.end();
+});
+
+tape("set.values() properly unescapes prefixed keys", function(test) {
+ var s = d3.set(["__proto__", "$weird"]);
+ test.deepEqual(s.values().sort(d3.ascending), ["$weird", "__proto__"]);
+ test.end();
+});
+
+tape("set.values() observes changes via add and remove", function(test) {
+ var s = d3.set(["foo", "bar"]);
+ test.deepEqual(s.values().sort(d3.ascending), ["bar", "foo"]);
+ s.remove("foo");
+ test.deepEqual(s.values(), ["bar"]);
+ s.add("bar");
+ test.deepEqual(s.values(), ["bar"]);
+ s.add("foo");
+ test.deepEqual(s.values().sort(d3.ascending), ["bar", "foo"]);
+ s.remove("bar");
+ test.deepEqual(s.values(), ["foo"]);
+ s.remove("foo");
+ test.deepEqual(s.values(), []);
+ s.remove("foo");
+ test.deepEqual(s.values(), []);
+ test.end();
+});
+
+tape("set.has(value) empty sets do not have object built-ins", function(test) {
+ var s = d3.set();
+ test.equal(s.has("__proto__"), false);
+ test.equal(s.has("hasOwnProperty"), false);
+ test.end();
+});
+
+tape("set.has(value) coerces values to strings", function(test) {
+ var s = d3.set(["42", "null", "undefined"]);
+ test.equal(s.has(42), true);
+ test.equal(s.has(null), true);
+ test.equal(s.has(undefined), true);
+ test.end();
+});
+
+tape("set.has(value) observes changes via add and remove", function(test) {
+ var s = d3.set(["foo"]);
+ test.equal(s.has("foo"), true);
+ s.add("foo");
+ test.equal(s.has("foo"), true);
+ s.remove("foo");
+ test.equal(s.has("foo"), false);
+ s.add("foo");
+ test.equal(s.has("foo"), true);
+ test.end();
+});
+
+tape("set.has(value) returns undefined for missing values", function(test) {
+ var s = d3.set(["foo"]);
+ test.equal(s.has("bar"), false);
+ test.end();
+});
+
+tape("set.add(value) returns the set", function(test) {
+ var s = d3.set();
+ test.equal(s.add("foo"), s);
+ test.equal(s.add(2), s);
+ test.deepEqual(s.values().sort(), ["2", "foo"]);
+ test.end();
+});
+
+tape("set.add(value) can add values using built-in names", function(test) {
+ var s = d3.set().add("__proto__");
+ test.equal(s.has("__proto__"), true);
+ test.end();
+});
+
+tape("set.add(value) can add values using zero-prefixed names", function(test) {
+ var s = d3.set().add("$weird");
+ test.equal(s.has("$weird"), true);
+ test.end();
+});
+
+tape("set.add(value) coerces values to strings", function(test) {
+ var s = d3.set();
+ s.add(42);
+ test.equal(s.has(42), true);
+ s.add(null);
+ test.equal(s.has(null), true);
+ s.add(undefined);
+ test.equal(s.has(undefined), true);
+ test.deepEqual(s.values().sort(), ["42", "null", "undefined"]);
+ test.end();
+});
+
+tape("set.add(value) can add null, undefined or empty string values", function(test) {
+ var s = d3.set().add("").add("null").add("undefined");
+ test.equal(s.has(""), true);
+ test.equal(s.has("null"), true);
+ test.equal(s.has("undefined"), true);
+ test.end();
+});
+
+tape("set.remove(value) returns true if the value was removed", function(test) {
+ var s = d3.set(["foo"]);
+ test.equal(s.remove("foo"), true);
+ test.end();
+});
+
+tape("set.remove(value) returns false if the value is not an element", function(test) {
+ var s = d3.set();
+ test.equal(s.remove("foo"), false);
+ test.end();
+});
diff --git a/test/values-test.js b/test/values-test.js
new file mode 100644
index 0000000..8e8f16a
--- /dev/null
+++ b/test/values-test.js
@@ -0,0 +1,44 @@
+var tape = require("tape"),
+ d3 = Object.assign({}, require("d3-array"), require("../"));
+
+require("./isNaN");
+
+tape("values(object) enumerates every value", function(test) {
+ test.deepEqual(d3.values({a: 1, b: 2}).sort(d3.ascending), [1, 2]);
+ test.end();
+});
+
+tape("values(object) includes values defined on prototypes", function(test) {
+ function abc() {
+ this.a = 1;
+ this.b = 2;
+ }
+ abc.prototype.c = 3;
+ test.deepEqual(d3.values(new abc).sort(d3.ascending), [1, 2, 3]);
+ test.end();
+});
+
+tape("values(object) includes null, undefined and NaN values", function(test) {
+ var v = d3.values({a: null, b: undefined, c: NaN}).map(box).sort(order).map(unbox);
+ test.equal(v.length, 3);
+ test.equal(v[0], null);
+ test.equal(v[1], undefined);
+ test.isNaN(v[2]);
+ test.end();
+});
+
+function box(value) {
+ return {value: value};
+}
+
+function unbox(box) {
+ return box.value;
+}
+
+function order(a, b) {
+ a = a.value;
+ b = b.value;
+ return d3.ascending(a, b)
+ || isNaN(a) - isNaN(b)
+ || (b === b) - (a === a);
+}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..5e0e91d
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,939 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0-beta.47":
+ version "7.0.0-rc.3"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-rc.3.tgz#d77a587401f818a3168700f596e41cd6905947b2"
+ dependencies:
+ "@babel/highlight" "7.0.0-rc.3"
+
+"@babel/highlight@7.0.0-rc.3":
+ version "7.0.0-rc.3"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-rc.3.tgz#c2ee83f8e5c0c387279a8c48e06fef2e32027004"
+ dependencies:
+ chalk "^2.0.0"
+ esutils "^2.0.2"
+ js-tokens "^4.0.0"
+
+"@types/estree@0.0.39":
+ version "0.0.39"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
+
+"@types/node@*":
+ version "10.9.1"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.1.tgz#06f002136fbcf51e730995149050bb3c45ee54e6"
+
+acorn-jsx@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e"
+ dependencies:
+ acorn "^5.0.3"
+
+acorn@^5.0.3, acorn@^5.6.0:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5"
+
+ajv-keywords@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
+
+ajv@^6.0.1, ajv@^6.5.0:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
+ dependencies:
+ fast-deep-equal "^2.0.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-escapes@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ dependencies:
+ color-convert "^1.9.0"
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ dependencies:
+ sprintf-js "~1.0.2"
+
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+arrify@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+babel-code-frame@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ dependencies:
+ chalk "^1.1.3"
+ esutils "^2.0.2"
+ js-tokens "^3.0.2"
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+
+caller-path@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+ dependencies:
+ callsites "^0.2.0"
+
+callsites@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+
+chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+chalk@^2.0.0, chalk@^2.1.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chardet@^0.4.0:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+
+circular-json@^0.3.1:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+
+cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ dependencies:
+ restore-cursor "^2.0.0"
+
+cli-width@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
+
+color-convert@^1.9.0:
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147"
+ dependencies:
+ color-name "1.1.1"
+
+color-name@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
+
+commander@~2.16.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+cross-spawn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+d3-array@1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
+
+debug@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ dependencies:
+ ms "2.0.0"
+
+deep-equal@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+define-properties@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+ dependencies:
+ object-keys "^1.0.12"
+
+defined@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+
+del@^2.0.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+ dependencies:
+ globby "^5.0.0"
+ is-path-cwd "^1.0.0"
+ is-path-in-cwd "^1.0.0"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ rimraf "^2.2.8"
+
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ dependencies:
+ esutils "^2.0.2"
+
+es-abstract@^1.5.0:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
+ dependencies:
+ es-to-primitive "^1.1.1"
+ function-bind "^1.1.1"
+ has "^1.0.1"
+ is-callable "^1.1.3"
+ is-regex "^1.0.4"
+
+es-to-primitive@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
+ dependencies:
+ is-callable "^1.1.1"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.1"
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+eslint-scope@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172"
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint-utils@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
+
+eslint-visitor-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
+eslint@5:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.4.0.tgz#d068ec03006bb9e06b429dc85f7e46c1b69fac62"
+ dependencies:
+ ajv "^6.5.0"
+ babel-code-frame "^6.26.0"
+ chalk "^2.1.0"
+ cross-spawn "^6.0.5"
+ debug "^3.1.0"
+ doctrine "^2.1.0"
+ eslint-scope "^4.0.0"
+ eslint-utils "^1.3.1"
+ eslint-visitor-keys "^1.0.0"
+ espree "^4.0.0"
+ esquery "^1.0.1"
+ esutils "^2.0.2"
+ file-entry-cache "^2.0.0"
+ functional-red-black-tree "^1.0.1"
+ glob "^7.1.2"
+ globals "^11.7.0"
+ ignore "^4.0.2"
+ imurmurhash "^0.1.4"
+ inquirer "^5.2.0"
+ is-resolvable "^1.1.0"
+ js-yaml "^3.11.0"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.3.0"
+ lodash "^4.17.5"
+ minimatch "^3.0.4"
+ mkdirp "^0.5.1"
+ natural-compare "^1.4.0"
+ optionator "^0.8.2"
+ path-is-inside "^1.0.2"
+ pluralize "^7.0.0"
+ progress "^2.0.0"
+ regexpp "^2.0.0"
+ require-uncached "^1.0.3"
+ semver "^5.5.0"
+ strip-ansi "^4.0.0"
+ strip-json-comments "^2.0.1"
+ table "^4.0.3"
+ text-table "^0.2.0"
+
+espree@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634"
+ dependencies:
+ acorn "^5.6.0"
+ acorn-jsx "^4.1.1"
+
+esprima@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+
+esquery@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
+ dependencies:
+ estraverse "^4.0.0"
+
+esrecurse@^4.1.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
+ dependencies:
+ estraverse "^4.1.0"
+
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
+esutils@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+external-editor@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
+ dependencies:
+ chardet "^0.4.0"
+ iconv-lite "^0.4.17"
+ tmp "^0.0.33"
+
+fast-deep-equal@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+
+fast-levenshtein@~2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+figures@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+file-entry-cache@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+ dependencies:
+ flat-cache "^1.2.1"
+ object-assign "^4.0.1"
+
+flat-cache@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
+ dependencies:
+ circular-json "^0.3.1"
+ del "^2.0.2"
+ graceful-fs "^4.1.2"
+ write "^0.2.1"
+
+for-each@~0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
+ dependencies:
+ is-callable "^1.1.3"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+
+functional-red-black-tree@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+
+glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globals@^11.7.0:
+ version "11.7.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
+
+globby@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+ dependencies:
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ glob "^7.0.3"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+graceful-fs@^4.1.2:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+
+has@^1.0.1, has@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ dependencies:
+ function-bind "^1.1.1"
+
+iconv-lite@^0.4.17:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+ignore@^4.0.2:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inquirer@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726"
+ dependencies:
+ ansi-escapes "^3.0.0"
+ chalk "^2.0.0"
+ cli-cursor "^2.1.0"
+ cli-width "^2.0.0"
+ external-editor "^2.1.0"
+ figures "^2.0.0"
+ lodash "^4.3.0"
+ mute-stream "0.0.7"
+ run-async "^2.2.0"
+ rxjs "^5.5.2"
+ string-width "^2.1.0"
+ strip-ansi "^4.0.0"
+ through "^2.3.6"
+
+is-callable@^1.1.1, is-callable@^1.1.3:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
+
+is-date-object@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+
+is-fullwidth-code-point@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
+is-path-cwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
+is-path-in-cwd@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+ dependencies:
+ is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-promise@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
+is-regex@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+ dependencies:
+ has "^1.0.1"
+
+is-resolvable@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
+
+is-symbol@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+js-tokens@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+
+js-yaml@^3.11.0:
+ version "3.12.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+
+levn@^0.3.0, levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0:
+ version "4.17.10"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
+mimic-fn@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+mkdirp@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ dependencies:
+ minimist "0.0.8"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+mute-stream@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
+nice-try@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
+
+object-assign@^4.0.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object-inspect@~1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
+
+object-keys@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+onetime@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ dependencies:
+ mimic-fn "^1.0.0"
+
+optionator@^0.8.2:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.4"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ wordwrap "~1.0.0"
+
+os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
+path-key@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+
+path-parse@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+
+pify@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pluralize@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+progress@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
+
+punycode@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+
+regexpp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365"
+
+require-uncached@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+ dependencies:
+ caller-path "^0.1.0"
+ resolve-from "^1.0.0"
+
+resolve-from@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+
+resolve@~1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
+ dependencies:
+ path-parse "^1.0.5"
+
+restore-cursor@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ dependencies:
+ onetime "^2.0.0"
+ signal-exit "^3.0.2"
+
+resumer@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
+ dependencies:
+ through "~2.3.4"
+
+rimraf@^2.2.8:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+ dependencies:
+ glob "^7.0.5"
+
+rollup-plugin-terser@1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-1.0.1.tgz#ba5f497cbc9aa38ba19d3ee2167c04ea3ed279af"
+ dependencies:
+ "@babel/code-frame" "^7.0.0-beta.47"
+ terser "^3.7.5"
+
+rollup@0.64:
+ version "0.64.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.64.1.tgz#9188ee368e5fcd43ffbc00ec414e72eeb5de87ba"
+ dependencies:
+ "@types/estree" "0.0.39"
+ "@types/node" "*"
+
+run-async@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ dependencies:
+ is-promise "^2.1.0"
+
+rxjs@^5.5.2:
+ version "5.5.11"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87"
+ dependencies:
+ symbol-observable "1.0.1"
+
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+
+semver@^5.5.0:
+ version "5.5.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+
+signal-exit@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+slice-ansi@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
+ dependencies:
+ is-fullwidth-code-point "^2.0.0"
+
+source-map-support@~0.5.6:
+ version "0.5.9"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+string-width@^2.1.0, string-width@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+ dependencies:
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^4.0.0"
+
+string.prototype.trim@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.0"
+ function-bind "^1.0.2"
+
+strip-ansi@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ dependencies:
+ ansi-regex "^3.0.0"
+
+strip-json-comments@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ dependencies:
+ has-flag "^3.0.0"
+
+symbol-observable@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
+
+table@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
+ dependencies:
+ ajv "^6.0.1"
+ ajv-keywords "^3.0.0"
+ chalk "^2.1.0"
+ lodash "^4.17.4"
+ slice-ansi "1.0.0"
+ string-width "^2.1.1"
+
+tape@4:
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9"
+ dependencies:
+ deep-equal "~1.0.1"
+ defined "~1.0.0"
+ for-each "~0.3.3"
+ function-bind "~1.1.1"
+ glob "~7.1.2"
+ has "~1.0.3"
+ inherits "~2.0.3"
+ minimist "~1.2.0"
+ object-inspect "~1.6.0"
+ resolve "~1.7.1"
+ resumer "~0.0.0"
+ string.prototype.trim "~1.1.2"
+ through "~2.3.8"
+
+terser@^3.7.5:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-3.8.1.tgz#cb70070ac9e0a71add169dfb63c0a64fca2738ac"
+ dependencies:
+ commander "~2.16.0"
+ source-map "~0.6.1"
+ source-map-support "~0.5.6"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+through@^2.3.6, through@~2.3.4, through@~2.3.8:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ dependencies:
+ prelude-ls "~1.1.2"
+
+uri-js@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+ dependencies:
+ punycode "^2.1.0"
+
+which@^1.2.9:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ dependencies:
+ isexe "^2.0.0"
+
+wordwrap@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+ dependencies:
+ mkdirp "^0.5.1"