Index: imaps-frontend/node_modules/immutable/README.md
===================================================================
--- imaps-frontend/node_modules/immutable/README.md	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/README.md	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,761 @@
+# Immutable collections for JavaScript
+
+[![Build Status](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml?query=branch%3Amain) [Chat on slack](https://immutable-js.slack.com)
+
+[Read the docs](https://immutable-js.com/docs/) and eat your vegetables.
+
+Docs are automatically generated from [README.md][] and [immutable.d.ts][].
+Please contribute! Also, don't miss the [wiki][] which contains articles on
+additional specific topics. Can't find something? Open an [issue][].
+
+**Table of contents:**
+
+- [Introduction](#introduction)
+- [Getting started](#getting-started)
+- [The case for Immutability](#the-case-for-immutability)
+- [JavaScript-first API](#javascript-first-api)
+- [Nested Structures](#nested-structures)
+- [Equality treats Collections as Values](#equality-treats-collections-as-values)
+- [Batching Mutations](#batching-mutations)
+- [Lazy Seq](#lazy-seq)
+- [Additional Tools and Resources](#additional-tools-and-resources)
+- [Contributing](#contributing)
+
+## Introduction
+
+[Immutable][] data cannot be changed once created, leading to much simpler
+application development, no defensive copying, and enabling advanced memoization
+and change detection techniques with simple logic. [Persistent][] data presents
+a mutative API which does not update the data in-place, but instead always
+yields new updated data.
+
+Immutable.js provides many Persistent Immutable data structures including:
+`List`, `Stack`, `Map`, `OrderedMap`, `Set`, `OrderedSet` and `Record`.
+
+These data structures are highly efficient on modern JavaScript VMs by using
+structural sharing via [hash maps tries][] and [vector tries][] as popularized
+by Clojure and Scala, minimizing the need to copy or cache data.
+
+Immutable.js also provides a lazy `Seq`, allowing efficient
+chaining of collection methods like `map` and `filter` without creating
+intermediate representations. Create some `Seq` with `Range` and `Repeat`.
+
+Want to hear more? Watch the presentation about Immutable.js:
+
+[![Immutable Data and React](website/public/Immutable-Data-and-React-YouTube.png)](https://youtu.be/I7IdS-PbEgI)
+
+[README.md]: https://github.com/immutable-js/immutable-js/blob/main/README.md
+[immutable.d.ts]: https://github.com/immutable-js/immutable-js/blob/main/type-definitions/immutable.d.ts
+[wiki]: https://github.com/immutable-js/immutable-js/wiki
+[issue]: https://github.com/immutable-js/immutable-js/issues
+[Persistent]: https://en.wikipedia.org/wiki/Persistent_data_structure
+[Immutable]: https://en.wikipedia.org/wiki/Immutable_object
+[hash maps tries]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
+[vector tries]: https://hypirion.com/musings/understanding-persistent-vector-pt-1
+
+## Getting started
+
+Install `immutable` using npm.
+
+```shell
+# using npm
+npm install immutable
+
+# using Yarn
+yarn add immutable
+
+# using pnpm
+pnpm add immutable
+
+# using Bun
+bun add immutable
+```
+
+Then require it into any module.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 50);
+map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
+```
+
+### Browser
+
+Immutable.js has no dependencies, which makes it predictable to include in a Browser.
+
+It's highly recommended to use a module bundler like [webpack](https://webpack.js.org/),
+[rollup](https://rollupjs.org/), or
+[browserify](https://browserify.org/). The `immutable` npm module works
+without any additional consideration. All examples throughout the documentation
+will assume use of this kind of tool.
+
+Alternatively, Immutable.js may be directly included as a script tag. Download
+or link to a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
+or [jsDelivr](https://www.jsdelivr.com/package/npm/immutable).
+
+Use a script tag to directly add `Immutable` to the global scope:
+
+```html
+<script src="immutable.min.js"></script>
+<script>
+  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
+  var map2 = map1.set('b', 50);
+  map1.get('b'); // 2
+  map2.get('b'); // 50
+</script>
+```
+
+Or use an AMD-style loader (such as [RequireJS](https://requirejs.org/)):
+
+```js
+require(['./immutable.min.js'], function (Immutable) {
+  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
+  var map2 = map1.set('b', 50);
+  map1.get('b'); // 2
+  map2.get('b'); // 50
+});
+```
+
+### Flow & TypeScript
+
+Use these Immutable collections and sequences as you would use native
+collections in your [Flowtype](https://flowtype.org/) or [TypeScript](https://typescriptlang.org) programs while still taking
+advantage of type generics, error detection, and auto-complete in your IDE.
+
+Installing `immutable` via npm brings with it type definitions for Flow (v0.55.0 or higher)
+and TypeScript (v2.1.0 or higher), so you shouldn't need to do anything at all!
+
+#### Using TypeScript with Immutable.js v4
+
+Immutable.js type definitions embrace ES2015. While Immutable.js itself supports
+legacy browsers and environments, its type definitions require TypeScript's 2015
+lib. Include either `"target": "es2015"` or `"lib": "es2015"` in your
+`tsconfig.json`, or provide `--target es2015` or `--lib es2015` to the
+`tsc` command.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 50);
+map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
+```
+
+#### Using TypeScript with Immutable.js v3 and earlier:
+
+Previous versions of Immutable.js include a reference file which you can include
+via relative path to the type definitions at the top of your file.
+
+```js
+///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
+import { Map } from 'immutable';
+var map1: Map<string, number>;
+map1 = Map({ a: 1, b: 2, c: 3 });
+var map2 = map1.set('b', 50);
+map1.get('b'); // 2
+map2.get('b'); // 50
+```
+
+## The case for Immutability
+
+Much of what makes application development difficult is tracking mutation and
+maintaining state. Developing with immutable data encourages you to think
+differently about how data flows through your application.
+
+Subscribing to data events throughout your application creates a huge overhead of
+book-keeping which can hurt performance, sometimes dramatically, and creates
+opportunities for areas of your application to get out of sync with each other
+due to easy to make programmer error. Since immutable data never changes,
+subscribing to changes throughout the model is a dead-end and new data can only
+ever be passed from above.
+
+This model of data flow aligns well with the architecture of [React][]
+and especially well with an application designed using the ideas of [Flux][].
+
+When data is passed from above rather than being subscribed to, and you're only
+interested in doing work when something has changed, you can use equality.
+
+Immutable collections should be treated as _values_ rather than _objects_. While
+objects represent some thing which could change over time, a value represents
+the state of that thing at a particular instance of time. This principle is most
+important to understanding the appropriate use of immutable data. In order to
+treat Immutable.js collections as values, it's important to use the
+`Immutable.is()` function or `.equals()` method to determine _value equality_
+instead of the `===` operator which determines object _reference identity_.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+map1.equals(map2); // true
+map1 === map2; // false
+```
+
+Note: As a performance optimization Immutable.js attempts to return the existing
+collection when an operation would result in an identical collection, allowing
+for using `===` reference equality to determine if something definitely has not
+changed. This can be extremely useful when used within a memoization function
+which would prefer to re-run the function if a deeper equality check could
+potentially be more costly. The `===` equality check is also used internally by
+`Immutable.is` and `.equals()` as a performance optimization.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 2); // Set to same value
+map1 === map2; // true
+```
+
+If an object is immutable, it can be "copied" simply by making another reference
+to it instead of copying the entire object. Because a reference is much smaller
+than the object itself, this results in memory savings and a potential boost in
+execution speed for programs which rely on copies (such as an undo-stack).
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const map = Map({ a: 1, b: 2, c: 3 });
+const mapCopy = map; // Look, "copies" are free!
+```
+
+[React]: https://reactjs.org/
+[Flux]: https://facebook.github.io/flux/docs/in-depth-overview/
+
+
+## JavaScript-first API
+
+While Immutable.js is inspired by Clojure, Scala, Haskell and other functional
+programming environments, it's designed to bring these powerful concepts to
+JavaScript, and therefore has an Object-Oriented API that closely mirrors that
+of [ES2015][] [Array][], [Map][], and [Set][].
+
+[es2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
+[array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
+[map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
+[set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
+
+The difference for the immutable collections is that methods which would mutate
+the collection, like `push`, `set`, `unshift` or `splice`, instead return a new
+immutable collection. Methods which return new arrays, like `slice` or `concat`,
+instead return new immutable collections.
+
+<!-- runkit:activate -->
+
+```js
+const { List } = require('immutable');
+const list1 = List([1, 2]);
+const list2 = list1.push(3, 4, 5);
+const list3 = list2.unshift(0);
+const list4 = list1.concat(list2, list3);
+assert.equal(list1.size, 2);
+assert.equal(list2.size, 5);
+assert.equal(list3.size, 6);
+assert.equal(list4.size, 13);
+assert.equal(list4.get(0), 1);
+```
+
+Almost all of the methods on [Array][] will be found in similar form on
+`Immutable.List`, those of [Map][] found on `Immutable.Map`, and those of [Set][]
+found on `Immutable.Set`, including collection operations like `forEach()`
+and `map()`.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const alpha = Map({ a: 1, b: 2, c: 3, d: 4 });
+alpha.map((v, k) => k.toUpperCase()).join();
+// 'A,B,C,D'
+```
+
+### Convert from raw JavaScript objects and arrays.
+
+Designed to inter-operate with your existing JavaScript, Immutable.js
+accepts plain JavaScript Arrays and Objects anywhere a method expects a
+`Collection`.
+
+<!-- runkit:activate -->
+
+```js
+const { Map, List } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3, d: 4 });
+const map2 = Map({ c: 10, a: 20, t: 30 });
+const obj = { d: 100, o: 200, g: 300 };
+const map3 = map1.merge(map2, obj);
+// Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }
+const list1 = List([1, 2, 3]);
+const list2 = List([4, 5, 6]);
+const array = [7, 8, 9];
+const list3 = list1.concat(list2, array);
+// List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+```
+
+This is possible because Immutable.js can treat any JavaScript Array or Object
+as a Collection. You can take advantage of this in order to get sophisticated
+collection methods on JavaScript Objects, which otherwise have a very sparse
+native API. Because Seq evaluates lazily and does not cache intermediate
+results, these operations can be extremely efficient.
+
+<!-- runkit:activate -->
+
+```js
+const { Seq } = require('immutable');
+const myObject = { a: 1, b: 2, c: 3 };
+Seq(myObject)
+  .map(x => x * x)
+  .toObject();
+// { a: 1, b: 4, c: 9 }
+```
+
+Keep in mind, when using JS objects to construct Immutable Maps, that
+JavaScript Object properties are always strings, even if written in a quote-less
+shorthand, while Immutable Maps accept keys of any type.
+
+<!-- runkit:activate -->
+
+```js
+const { fromJS } = require('immutable');
+
+const obj = { 1: 'one' };
+console.log(Object.keys(obj)); // [ "1" ]
+console.log(obj['1'], obj[1]); // "one", "one"
+
+const map = fromJS(obj);
+console.log(map.get('1'), map.get(1)); // "one", undefined
+```
+
+Property access for JavaScript Objects first converts the key to a string, but
+since Immutable Map keys can be of any type the argument to `get()` is
+not altered.
+
+### Converts back to raw JavaScript objects.
+
+All Immutable.js Collections can be converted to plain JavaScript Arrays and
+Objects shallowly with `toArray()` and `toObject()` or deeply with `toJS()`.
+All Immutable Collections also implement `toJSON()` allowing them to be passed
+to `JSON.stringify` directly. They also respect the custom `toJSON()` methods of
+nested objects.
+
+<!-- runkit:activate -->
+
+```js
+const { Map, List } = require('immutable');
+const deep = Map({ a: 1, b: 2, c: List([3, 4, 5]) });
+console.log(deep.toObject()); // { a: 1, b: 2, c: List [ 3, 4, 5 ] }
+console.log(deep.toArray()); // [ 1, 2, List [ 3, 4, 5 ] ]
+console.log(deep.toJS()); // { a: 1, b: 2, c: [ 3, 4, 5 ] }
+JSON.stringify(deep); // '{"a":1,"b":2,"c":[3,4,5]}'
+```
+
+### Embraces ES2015
+
+Immutable.js supports all JavaScript environments, including legacy
+browsers (even IE11). However it also takes advantage of features added to
+JavaScript in [ES2015][], the latest standard version of JavaScript, including
+[Iterators][], [Arrow Functions][], [Classes][], and [Modules][]. It's inspired
+by the native [Map][] and [Set][] collections added to ES2015.
+
+All examples in the Documentation are presented in ES2015. To run in all
+browsers, they need to be translated to ES5.
+
+```js
+// ES2015
+const mapped = foo.map(x => x * x);
+// ES5
+var mapped = foo.map(function (x) {
+  return x * x;
+});
+```
+
+All Immutable.js collections are [Iterable][iterators], which allows them to be
+used anywhere an Iterable is expected, such as when spreading into an Array.
+
+<!-- runkit:activate -->
+
+```js
+const { List } = require('immutable');
+const aList = List([1, 2, 3]);
+const anArray = [0, ...aList, 4, 5]; // [ 0, 1, 2, 3, 4, 5 ]
+```
+
+Note: A Collection is always iterated in the same order, however that order may
+not always be well defined, as is the case for the `Map` and `Set`.
+
+[Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
+[Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
+[Classes]: https://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
+[Modules]: https://www.2ality.com/2014/09/es6-modules-final.html
+
+
+## Nested Structures
+
+The collections in Immutable.js are intended to be nested, allowing for deep
+trees of data, similar to JSON.
+
+<!-- runkit:activate -->
+
+```js
+const { fromJS } = require('immutable');
+const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }
+```
+
+A few power-tools allow for reading and operating on nested data. The
+most useful are `mergeDeep`, `getIn`, `setIn`, and `updateIn`, found on `List`,
+`Map` and `OrderedMap`.
+
+<!-- runkit:activate -->
+
+```js
+const { fromJS } = require('immutable');
+const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
+
+const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
+
+console.log(nested2.getIn(['a', 'b', 'd'])); // 6
+
+const nested3 = nested2.updateIn(['a', 'b', 'd'], value => value + 1);
+console.log(nested3);
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }
+
+const nested4 = nested3.updateIn(['a', 'b', 'c'], list => list.push(6));
+// Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
+```
+
+## Equality treats Collections as Values
+
+Immutable.js collections are treated as pure data _values_. Two immutable
+collections are considered _value equal_ (via `.equals()` or `is()`) if they
+represent the same collection of values. This differs from JavaScript's typical
+_reference equal_ (via `===` or `==`) for Objects and Arrays which only
+determines if two variables represent references to the same object instance.
+
+Consider the example below where two identical `Map` instances are not
+_reference equal_ but are _value equal_.
+
+<!-- runkit:activate -->
+
+```js
+// First consider:
+const obj1 = { a: 1, b: 2, c: 3 };
+const obj2 = { a: 1, b: 2, c: 3 };
+obj1 !== obj2; // two different instances are always not equal with ===
+
+const { Map, is } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+map1 !== map2; // two different instances are not reference-equal
+map1.equals(map2); // but are value-equal if they have the same values
+is(map1, map2); // alternatively can use the is() function
+```
+
+Value equality allows Immutable.js collections to be used as keys in Maps or
+values in Sets, and retrieved with different but equivalent collections:
+
+<!-- runkit:activate -->
+
+```js
+const { Map, Set } = require('immutable');
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+const set = Set().add(map1);
+set.has(map2); // true because these are value-equal
+```
+
+Note: `is()` uses the same measure of equality as [Object.is][] for scalar
+strings and numbers, but uses value equality for Immutable collections,
+determining if both are immutable and all keys and values are equal
+using the same measure of equality.
+
+[object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
+
+#### Performance tradeoffs
+
+While value equality is useful in many circumstances, it has different
+performance characteristics than reference equality. Understanding these
+tradeoffs may help you decide which to use in each case, especially when used
+to memoize some operation.
+
+When comparing two collections, value equality may require considering every
+item in each collection, on an `O(N)` time complexity. For large collections of
+values, this could become a costly operation. Though if the two are not equal
+and hardly similar, the inequality is determined very quickly. In contrast, when
+comparing two collections with reference equality, only the initial references
+to memory need to be compared which is not based on the size of the collections,
+which has an `O(1)` time complexity. Checking reference equality is always very
+fast, however just because two collections are not reference-equal does not rule
+out the possibility that they may be value-equal.
+
+#### Return self on no-op optimization
+
+When possible, Immutable.js avoids creating new objects for updates where no
+change in _value_ occurred, to allow for efficient _reference equality_ checking
+to quickly determine if no change occurred.
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const originalMap = Map({ a: 1, b: 2, c: 3 });
+const updatedMap = originalMap.set('b', 2);
+updatedMap === originalMap; // No-op .set() returned the original reference.
+```
+
+However updates which do result in a change will return a new reference. Each
+of these operations occur independently, so two similar updates will not return
+the same reference:
+
+<!-- runkit:activate -->
+
+```js
+const { Map } = require('immutable');
+const originalMap = Map({ a: 1, b: 2, c: 3 });
+const updatedMap = originalMap.set('b', 1000);
+// New instance, leaving the original immutable.
+updatedMap !== originalMap;
+const anotherUpdatedMap = originalMap.set('b', 1000);
+// Despite both the results of the same operation, each created a new reference.
+anotherUpdatedMap !== updatedMap;
+// However the two are value equal.
+anotherUpdatedMap.equals(updatedMap);
+```
+
+## Batching Mutations
+
+> If a tree falls in the woods, does it make a sound?
+>
+> If a pure function mutates some local data in order to produce an immutable
+> return value, is that ok?
+>
+> — Rich Hickey, Clojure
+
+Applying a mutation to create a new immutable object results in some overhead,
+which can add up to a minor performance penalty. If you need to apply a series
+of mutations locally before returning, Immutable.js gives you the ability to
+create a temporary mutable (transient) copy of a collection and apply a batch of
+mutations in a performant manner by using `withMutations`. In fact, this is
+exactly how Immutable.js applies complex mutations itself.
+
+As an example, building `list2` results in the creation of 1, not 3, new
+immutable Lists.
+
+<!-- runkit:activate -->
+
+```js
+const { List } = require('immutable');
+const list1 = List([1, 2, 3]);
+const list2 = list1.withMutations(function (list) {
+  list.push(4).push(5).push(6);
+});
+assert.equal(list1.size, 3);
+assert.equal(list2.size, 6);
+```
+
+Note: Immutable.js also provides `asMutable` and `asImmutable`, but only
+encourages their use when `withMutations` will not suffice. Use caution to not
+return a mutable copy, which could result in undesired behavior.
+
+_Important!_: Only a select few methods can be used in `withMutations` including
+`set`, `push` and `pop`. These methods can be applied directly against a
+persistent data-structure where other methods like `map`, `filter`, `sort`,
+and `splice` will always return new immutable data-structures and never mutate
+a mutable collection.
+
+## Lazy Seq
+
+`Seq` describes a lazy operation, allowing them to efficiently chain
+use of all the higher-order collection methods (such as `map` and `filter`)
+by not creating intermediate collections.
+
+**Seq is immutable** — Once a Seq is created, it cannot be
+changed, appended to, rearranged or otherwise modified. Instead, any mutative
+method called on a `Seq` will return a new `Seq`.
+
+**Seq is lazy** — `Seq` does as little work as necessary to respond to any
+method call. Values are often created during iteration, including implicit
+iteration when reducing or converting to a concrete data structure such as
+a `List` or JavaScript `Array`.
+
+For example, the following performs no work, because the resulting
+`Seq`'s values are never iterated:
+
+```js
+const { Seq } = require('immutable');
+const oddSquares = Seq([1, 2, 3, 4, 5, 6, 7, 8])
+  .filter(x => x % 2 !== 0)
+  .map(x => x * x);
+```
+
+Once the `Seq` is used, it performs only the work necessary. In this
+example, no intermediate arrays are ever created, filter is called three
+times, and map is only called once:
+
+```js
+oddSquares.get(1); // 9
+```
+
+Any collection can be converted to a lazy Seq with `Seq()`.
+
+<!-- runkit:activate -->
+
+```js
+const { Map, Seq } = require('immutable');
+const map = Map({ a: 1, b: 2, c: 3 });
+const lazySeq = Seq(map);
+```
+
+`Seq` allows for the efficient chaining of operations, allowing for the
+expression of logic that can otherwise be very tedious:
+
+```js
+lazySeq
+  .flip()
+  .map(key => key.toUpperCase())
+  .flip();
+// Seq { A: 1, B: 2, C: 3 }
+```
+
+As well as expressing logic that would otherwise seem memory or time
+limited, for example `Range` is a special kind of Lazy sequence.
+
+<!-- runkit:activate -->
+
+```js
+const { Range } = require('immutable');
+Range(1, Infinity)
+  .skip(1000)
+  .map(n => -n)
+  .filter(n => n % 2 === 0)
+  .take(2)
+  .reduce((r, n) => r * n, 1);
+// 1006008
+```
+
+## Comparison of filter(), groupBy(), and partition()
+
+The `filter()`, `groupBy()`, and `partition()` methods are similar in that they
+all divide a collection into parts based on applying a function to each element.
+All three call the predicate or grouping function once for each item in the
+input collection.  All three return zero or more collections of the same type as
+their input.  The returned collections are always distinct from the input
+(according to `===`), even if the contents are identical.
+
+Of these methods, `filter()` is the only one that is lazy and the only one which
+discards items from the input collection. It is the simplest to use, and the
+fact that it returns exactly one collection makes it easy to combine with other
+methods to form a pipeline of operations.
+
+The `partition()` method is similar to an eager version of `filter()`, but it
+returns two collections; the first contains the items that would have been
+discarded by `filter()`, and the second contains the items that would have been
+kept.  It always returns an array of exactly two collections, which can make it
+easier to use than `groupBy()`.  Compared to making two separate calls to
+`filter()`, `partition()` makes half as many calls it the predicate passed to
+it.
+
+The `groupBy()` method is a more generalized version of `partition()` that can
+group by an arbitrary function rather than just a predicate.  It returns a map
+with zero or more entries, where the keys are the values returned by the
+grouping function, and the values are nonempty collections of the corresponding
+arguments.  Although `groupBy()` is more powerful than `partition()`, it can be
+harder to use because it is not always possible predict in advance how many
+entries the returned map will have and what their keys will be.
+
+| Summary                       | `filter` | `partition` | `groupBy`      |
+|:------------------------------|:---------|:------------|:---------------|
+| ease of use                   | easiest  | moderate    | hardest        |
+| generality                    | least    | moderate    | most           |
+| laziness                      | lazy     | eager       | eager          |
+| # of returned sub-collections | 1        | 2           | 0 or more      |
+| sub-collections may be empty  | yes      | yes         | no             |
+| can discard items             | yes      | no          | no             |
+| wrapping container            | none     | array       | Map/OrderedMap |
+
+## Additional Tools and Resources
+
+- [Atom-store](https://github.com/jameshopkins/atom-store/)
+  - A Clojure-inspired atom implementation in Javascript with configurability
+    for external persistance.
+
+- [Chai Immutable](https://github.com/astorije/chai-immutable)
+  - If you are using the [Chai Assertion Library](https://chaijs.com/), this
+    provides a set of assertions to use against Immutable.js collections.
+
+- [Fantasy-land](https://github.com/fantasyland/fantasy-land)
+  - Specification for interoperability of common algebraic structures in JavaScript.
+
+- [Immutagen](https://github.com/pelotom/immutagen)
+  - A library for simulating immutable generators in JavaScript.
+
+- [Immutable-cursor](https://github.com/redbadger/immutable-cursor)
+  - Immutable cursors incorporating the Immutable.js interface over
+  Clojure-inspired atom.
+
+- [Immutable-ext](https://github.com/DrBoolean/immutable-ext)
+  - Fantasyland extensions for immutablejs
+
+- [Immutable-js-tools](https://github.com/madeinfree/immutable-js-tools)
+  - Util tools for immutable.js
+
+- [Immutable-Redux](https://github.com/gajus/redux-immutable)
+  - redux-immutable is used to create an equivalent function of Redux
+  combineReducers that works with Immutable.js state.
+
+- [Immutable-Treeutils](https://github.com/lukasbuenger/immutable-treeutils)
+  - Functional tree traversal helpers for ImmutableJS data structures.
+
+- [Irecord](https://github.com/ericelliott/irecord)
+  - An immutable store that exposes an RxJS observable. Great for React.
+
+- [Mudash](https://github.com/brianneisler/mudash)
+  - Lodash wrapper providing Immutable.JS support.
+
+- [React-Immutable-PropTypes](https://github.com/HurricaneJames/react-immutable-proptypes)
+  - PropType validators that work with Immutable.js.
+
+- [Redux-Immutablejs](https://github.com/indexiatech/redux-immutablejs)
+  - Redux Immutable facilities.
+
+- [Rxstate](https://github.com/yamalight/rxstate)
+  - Simple opinionated state management library based on RxJS and Immutable.js.
+
+- [Transit-Immutable-js](https://github.com/glenjamin/transit-immutable-js)
+  - Transit serialisation for Immutable.js.
+  - See also: [Transit-js](https://github.com/cognitect/transit-js)
+
+Have an additional tool designed to work with Immutable.js?
+Submit a PR to add it to this list in alphabetical order.
+
+## Contributing
+
+Use [Github issues](https://github.com/immutable-js/immutable-js/issues) for requests.
+
+We actively welcome pull requests, learn how to [contribute](https://github.com/immutable-js/immutable-js/blob/main/.github/CONTRIBUTING.md).
+
+Immutable.js is maintained within the [Contributor Covenant's Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/).
+
+### Changelog
+
+Changes are tracked as [Github releases](https://github.com/immutable-js/immutable-js/releases).
+
+### License
+
+Immutable.js is [MIT-licensed](./LICENSE).
+
+### Thanks
+
+[Phil Bagwell](https://www.youtube.com/watch?v=K2NYwP90bNs), for his inspiration
+and research in persistent data structures.
+
+[Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package
+name. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).
