Merge pull request #1 from shautvast/master

initial commit
This commit is contained in:
Sander Hautvast 2020-11-05 16:21:46 +01:00 committed by GitHub
commit 0c82f789f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 1900 additions and 0 deletions

29
.eslintrc.json Normal file
View file

@ -0,0 +1,29 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
]
}
}

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.idea/
node_modules/

76
Appendix_A_Awful_Parts.js Normal file
View file

@ -0,0 +1,76 @@
(function () {
console.info("**Awful Parts**");
// Global Variables
/* sure */
// parseInt
console.info("\n*parseInt*");
console.info(`=> parseInt("16") = ${parseInt("16")} // OK`);
console.info(`=> parseInt("16 tons") = ${parseInt("16 tons")} // NOT OK`);
/* and also ('a tin teardrop') parseFloat */
// parseFloat
console.info("\n*parseFloat*");
console.info(`=> parseFloat("16") = ${parseFloat("16")} // OK`);
console.info(`=> parseFloat("16 tons") = ${parseFloat("16 tons")} // NOT OK`);
// Floating Point
/* well that's just IEE754, don't blame javascript for it. Many other languages are bad at this at well */
/* just be aware! of it */
// Nan
console.info("\n*NaN*");
console.info(`=> typeOf NaN = "${typeof NaN}"`);
console.info(`=> NaN !== 0: ${NaN !== 0}`);
console.info(`=> NaN === NaN: ${NaN === NaN}`);
console.info(`=> NaN !== NaN: ${NaN !== NaN}`);
console.info(`=> + "oops" = ${+"oops"}`);
console.info(`=> isNaN(NaN) = ${isNaN(NaN)}`);
console.info(`=> isNaN(0) = ${isNaN(0)}`);
console.info(`=> isNaN("oops") = ${isNaN("oops")}`);
console.info(`=> isNaN("0") = ${isNaN("0")}`);
// Arrays and Falsy Values
console.info("\n*Arrays*");
let is_array1 = function (maybe_array) {
return maybe_array && typeof maybe_array === "object" && maybe_array.constructor === Array;
};
console.info(`let is_array1 = ${is_array1}`);
console.info(`=> is_array1([]): ${is_array1([])}`);
console.info(`=> is_array1({}): ${is_array1({})}`);
console.info(`=> is_array1("array"): ${is_array1("array")}`);
console.info(`=> is_array1(0): ${is_array1(0)} ???`); /* WTF? */
console.info(`=> is_array1(null): ${is_array1(null)}`); /* 'works' for all falsy values */
/* Let's try another version */
let is_array2 = function (maybe_array) {
return Object.prototype.toString.apply(maybe_array) === "[object Array]";
};
console.info(`\nlet is_array2 = ${is_array2}`);
console.info(`=> is_array2([]): ${is_array2([])}`);
console.info(`=> is_array2({}}): ${is_array2({})}`);
console.info(`=> is_array2("array"): ${is_array2("array")}`);
console.info(`=> is_array2(0): ${is_array2(0)}`);
console.info(`=> is_array2(null): ${is_array2(null)}`);
/* I'd use this! */
/* The book is not wrong, because the code there is slightly different there and works correctly, because 0 and NaN are falsy and have to be coerced into a boolean
* because the expression is part of an if-statement.
* In this case there is no coercion. 0 && false -> 0 and 0 && true -> 0
* Gotcha!
*/
console.log("Explanation");
console.log("let falsy_value = 0 | NaN | '' | false | null | undefined // pseudo-code");
console.log("=> (falsy_value && true) = falsy_value not false");
/* true and false are not even being evaluated because 0 is falsy */
// hasOwnProperty
// don't mess with it
// Object
// be wary of special names when using objects
}());

58
Appendix_B_Bad_Parts.js Normal file
View file

@ -0,0 +1,58 @@
(function () {
// Appendix B Bad Parts
console.info("\n\n** Appendix B Bad Parts **");
// == comparison
console.info("\n* == comparison *");
console.info(`=> "" == "0": ${"" == "0"}`);
console.info(`=> 0 == "": ${0 == ""}`);
console.info(`=> 0 == "0": ${0 == "0"}`);
console.info(`\n=> false == "false": ${false == "false"}`);
console.info(`=> false == "0": ${false == "0"}`);
console.info(`\n=> false == undefined: ${false == undefined}`);
console.info(`=> false == null: ${false == null}`);
console.info(`=> null == undefined: ${null == undefined}`);
console.info(`\n=> " \\t\\r\\n " == 0: ${" \t\r\n " == 0}`);
// with Statement
/* Just don't use it */
// eval
/* you probably don't need it. think again */
// continue
/* take it out whenever you come across it */
// switch Fall Through
/* it is error prone */
// Block-less statements
/* just do like the java-peoples */
// ++ and --
/* I find no offense here, but +=1 or -=1 looks nicer */
// Bitwise operators
/* javascript is really bad at them */
// The function Statement Versus the function Expression
/* just avoid hoisting, be more hip and say: let f = function(){} */
// Typed Wrappers
/* don't use new Boolean(false), use false
* dont' use new Object(), use {}
* don't use new Array(), use []
*/
// new
/* better not use it */
// void
console.info("* void *");
console.info(`=> void 1 = ${void 1} ... really weird`);
// Avoid void.
}());

16
_0_index.js Normal file
View file

@ -0,0 +1,16 @@
/*jslint node: true */
import "./_3_objects.js";
import "./_4_functions.js";
import "./_5_inheritance.js";
import "./_6_arrays.js";
import "./Appendix_A_Awful_Parts.js";
import "./Appendix_B_Bad_Parts.js";
/* use of comment indicators
// in code, indicates comment copied straight from the book
// not in code, is a paragraph heading
/* indicates my own comments and thoughts, can be nested within a // comment */

148
_3_objects.js Normal file
View file

@ -0,0 +1,148 @@
(function () {
console.info("**Chapter 3 Objects**\n");
/*
* letter: [A-Za-z]
* digit: [0-9]
* underscore: _
* name: [letter][letter digit underscore]*
*
*/
let empty_object = {};
// object literals
console.info("*Object Literals*\n");
let stooge = {
"first-name": "Jerome", // object property name must be quoted, because it is not a legal javascript _name_
"last-name": "Howard"
};
console.info(`let stooge = {
"first-name": "Jerome", // object property name must be quoted, because it is not a legal javascript name
"last-name": "Howard"
};`);
console.info("Retrieve property with 'stooge[\"first-name\"]': ", stooge["first-name"]);
// nested object
let flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
};
console.info(`\nlet flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
};`);
console.info("Retrieve property with 'flight.departure.IATA': ", flight.departure.IATA);
console.info("Retrieve undefined property with 'flight.status': ", flight.status);
try {
console.info("Retrieve property of undefined with 'flight.equipment.model': ");
console.info(flight.equipment.model);
} catch (e) {
console.info("\tCaught error:", e.message);
}
console.info(`Retrieve property of undefined with 'flight.equipment && flight.equipment.model': ${flight.equipment && flight.equipment.model}`);
// update
stooge["first-name"] = "Moe";
console.info(`Retrieve updated property with 'stooge["first-name"]': ${stooge["first-name"]}`);
stooge["middle-name"] = "middle-stooge";
console.info(`Retrieve property of augmented object with 'stooge["middle-name"]': ${stooge["middle-name"]}`);
let x = stooge;
x.nickname = "Curly";
let nick = stooge.nickname;
console.info(`nick is 'Curly' because x and stooge are references to the same object: ${nick}`);
// Prototype
console.info("\n*Prototype*\n");
//create a new object from a prototype
if (typeof Object.createFrom !== "function") { // 'create' is a built-in starting from ES5
Object.createFrom = function (o) {
let F = function () {
};
F.prototype = o;
return new F();
};
}
console.info(`Object.createFrom = ${Object.createFrom}`);
let another_stooge = Object.createFrom(stooge);
another_stooge["first-name"] = "Shemp";
console.info(`another stooge is created from stooge, but is a new reference. another_stooge.first-name = ${another_stooge["first-name"]}`);
console.info(`stooge is unchanged stooge.first-name = ${stooge["first-name"]}`);
// reflection
console.info("\n*Reflection*");
console.info("\nThe type of a property is retrieved wth 'typeof property'");
console.info(`typeof flight.number = ${typeof flight.number}`,);
console.info(`typeof flight.status = ${typeof flight.status}`);
console.info(`typeof flight.arrival = ${typeof flight.arrival}`);
console.info(`typeof flight.manifest = ${typeof flight.manifest}`);
console.info(`typeof flight.toString = ${typeof flight.toString}`);
console.info("\nhasOwnProperty returns true if the object defines that property");
console.info(`flight.hasOwnProperty("number"): ${Object.prototype.hasOwnProperty.call(flight, "number")}`); // the actual code is actually correct
console.info(`flight.hasOwnProperty("constructor"): ${Object.prototype.hasOwnProperty.call(flight, "constructor")}`);
// enumeration
console.info("\n*Enumeration*");
console.info("Enumeration shows all properties of an object");
// order is not guaranteed
console.info(`for (let name in another_stooge) {
if (typeof another_stooge[name] !== 'function') { // intellij warns that hasOwnProperty check is *probably* missing but that would change the output, because most properties are in the prototype!
console.info(\`name: \${another_stooge[name]}\`)
}
}`);
for (let name in another_stooge) {
if (typeof another_stooge[name] !== "function") { // intellij warns that hasOwnProperty check is *probably* missing but that would change the output, because most properties are in the prototype!
console.info(`name: ${another_stooge[name]}`);
}
}
// order is guaranteed
console.info("\nAgain with fixed properties in guaranteed order:");
console.info(`const properties = ['first-name', 'middle-name', 'last-name', 'profession'];
for (let i = 0; i < properties.length; i++) {
console.log(\`\${properties[i]}: \${another_stooge[properties[i]]}\`);
}`);
const properties = ["first-name", "middle-name", "last-name", "profession"];
for (let i = 0; i < properties.length; i++) {
console.log(`${properties[i]}: ${another_stooge[properties[i]]}`);
}
//delete
console.info("\n*Delete*");
console.info("_delete_ deletes a property, and this has the effect that it's prototype property of the same name (if it's there) is now visible");
another_stooge.nickname = "Moe";
console.info(`=> original nickname: ${another_stooge.nickname}`);
console.info("Delete reveals prototype value");
console.info("delete another_stooge.nickname;");
delete another_stooge.nickname;
console.info(`=> nickname after delete: ${another_stooge.nickname}`);
delete stooge.nickname;
console.info("delete another_stooge.nickname;");
console.info(`=> nickname after delete stooge.nickname: ${another_stooge.nickname}`);
// Global atonement
// no examples
}());

459
_4_functions.js Normal file
View file

@ -0,0 +1,459 @@
(function () {
// 4 Functions
console.info("\n\n**Chapter 4 Functions**");
// function literals
console.info("\n*Function literals*");
console.info("Functions can be declared as:");
// Create a variable called add and store a function
// in it that adds two numbers. */
let add = function (a, b) {
console.info(`DEBUG _add_ is a global function: _this_ is _${this}_`);
return a + b;
};
console.info(`add = ${add}`);
console.info(`=> add(2,3) = ${add(2, 3)}`);
/* is there a difference using var or let?*/
var add2 = function (a, b) {
console.info(`DEBUG _add2_ is a global function defined with _var_ instead of _let_: _this_ is _${this}_`);
return a + b;
};
add2(2, 3);
/* apparently not even though the book says _this_ in this case is the global object for functions, using _var_ to declare them. Is that behavior superseded? */
//Method Invocation Pattern
console.info("\n*The Method Invocation pattern*");
console.info("A method is a function that is bound to an object.");
// Create myObject. It has a value and an increment
// method. The increment methods takes an optional
// parameter. If the argument is not a number, then 1
// is used as the default.
let myObject = {
value: 0,
increment: function (inc) {
console.debug(`DEBUG _increment_ is a method: _this_ is ${this}`);
this.value += (typeof inc === "number" ? inc : 1);
},
toString: function () {
return `myObject [value=${this.value}]`;
}
};
myObject.increment(); // 1
console.info(`=> myObject.value after myObject.increment(): ${myObject.value}`);
myObject.increment(2); // 3
console.info(`=> myObject.value after myObject.increment(2): ${myObject.value}`);
/*
* The explanation under the heading 'The Function invocation Pattern' is not immediately clear. It starts of with explaning that _this_ is bound to the global
* object in case of a function (which, btw I cannot replicate in node 15.1/ES6). But then it goes on explaning that _this_ is not correctly bound in
* a nested function of a method. Is that the same thing?, ie. a global function and a nested function?
* Lets test it:
*/
// Augment myObject with a double method
console.info("\n_this_ in a nested function is undefined. The outer method must first assign it to some varaiable (_that_).");
myObject.double = function () {
let that = this;
let helper = function () {
that.value = add(that.value, that.value); /* indeed a nested function has no _this_. The code using _this_ won't run. Too bad. */
};
helper();
};
myObject.double(); // 6
console.info(`=> ${myObject.toString()}`);
console.info("But for lambdas this is not necessary.");
/* And what about lambda notation ? */
myObject.triple = function () {
let helper = () => this.value = 3 * this.value;
helper();
};
myObject.triple(); // 18
console.info(`=> ${myObject.toString()}`); /* yay, now it does work! */
// The Constructor Invocation Pattern
console.info("\n*The Constructor Invocation Pattern*");
console.info(`This pattern was seemingly added to make it look OO- and java-like. Don't use it.
All state is public and forgetting _new_ when using it makes for nasty errors.`);
// Create a constructor function called Quo. It makes an object with a status property.
let Quo = function (string) {
this.status = string;
};
console.info(`let Quo = ${Quo}`);
// Give all instances of Quo a public method called get_status.
Quo.prototype.get_status = function () {
return this.status;
};
console.info(`Quo.prototype.get_status = ${Quo.prototype.get_status}`);
// Make an instance of Quo.
let myQuo = new Quo("confused");
console.info("let myQuo = new Quo(\"confused\");");
console.info(`=> The status of myQuo is "${myQuo.get_status()}"`);
/* Let's say this pattern is deprecated */
//The Apply Invocation Pattern
console.info(`\n*The Apply invocation pattern*
Earlier we defined a function sum that takes two parameters
We can also pass it an array of two elements.
Note that adding any subsequent array elements, will not change the outcome. They will be ignored`);
// Make an array of 2 numbers and add them
console.info(`let array = [3, 4];
let sum = add.apply(null, array);`);
let array = [3, 4];
let sum = add.apply(null, array); // sum is 7
console.info(`=> sum is ${sum}`);
// statusObject does not inherit from Quo.prototype,
// but we can invoke the get_status method on
// statusObject even though statusObject does not have
// a get_status method.
/* Make an object with a status member */
let statusObject = {
status: "A-OK"
};
console.info("\nHere is a form of structural typing. As long as an argument behaves as expected for the function it is passed to, you can pass it.");
console.info("We can pass statusObject to the get_status method/function because that function simply looks for a _value_ variable.");
console.info("Quo.get_status does not kwow anything about statusOject, but that does not matter.");
let status = Quo.prototype.get_status.apply(statusObject); /* oh really? */
console.info(`=> The status of statusObject should be 'A-OK', result: ${status}`);
// Arguments
console.info("\n*Arguments*");
console.info("Within a function _arguments_ can be used to retrieve any number of (undeclared) arguments.");
// Make a function that adds a lot of stuff
console.info("mySum is a function that does not declare parameters");
let mySum = function () { // sum has already been declared
let mySum = 0;
for (let i = 0; i < arguments.length; i++) {
mySum += arguments[i];
}
return mySum;
};
console.info(`let mySum = ${mySum}`);
console.info(`=> mySum(4, 8, 15, 16, 23, 42) should be 108: ${mySum(4, 8, 15, 16, 23, 42)}`);
/* 'this is not a particularly useful pattern' */
/* 'arguments is not really an array' */
// Return
/* no code here */
// Exceptions
console.info("\n*Exceptions*");
console.info("You can throw and catch exceptions in the same vein as java Runtime exceptions.");
let myAdd = function (a, b) { // add has
if (typeof a !== "number" || typeof b !== "number") {
throw {
name: "TypeError",
message: "myAdd needs numbers"
};
}
return a + b;
};
console.info(`let myAdd = ${myAdd}`);
try {
console.info("calling myAdd() without arguments");
myAdd();
} catch (e) {
console.info(`=> Exception caught: ${e.message}`);
}
/* very java like */
// Augmenting types
console.info("\n*Augmenting types*");
console.info("The Function prototype can be used to add functions to existing types (strings, numbers etc) that were not there before.");
/* define a method _method_ on the Function prototype to make it available to al functions*/
Function.prototype.method = function (name, func) {
if (!Function.prototype[name]) { /* added later on page 33 to avoid clashes (well does it?, but at least it's 'nicer' to already defined libraries) */
this.prototype[name] = func;
}
return this;
};
console.info(`Function.prototype.method = ${Function.prototype.method}`);
/* and use _method_ to augment numbers with an _integer_ method */
console.info("Augmenting numbers with integer");
Number.method("integer", function () {
return Math[this < 0 ? "ceil" : "floor"](this); /* I just love this */
});
console.info(`Number.prototype.integer = ${Number.prototype.integer}`);
console.info(`=> calling _integer_ on minus 10 thirds ((-10 / 3).integer()), should be -3: ${(-10 / 3).integer()}`);
/* or use _method_ to augment String with a trim method */
console.info("Augmenting String with trim");
String.method("trim", function () {
return this.replace(/^\s+|\s+$/g, "");
});
console.info(`String.prototype.trim = ${String.prototype.trim}`);
console.info(`=> " neat ".trim() should result in "neat", and it is: "${" neat ".trim()}"`);
// Recursion
console.info("\n*Recursion*");
console.info("The Towers of Hanoi");
console.info("_hanoi_ is a recursive function because it calls itself.");
let hanoi = function (disc, src, aux, dst) {
if (disc > 0) {
hanoi(disc - 1, src, dst, aux);
console.debug(`Move disc ${disc} from ${src} to ${dst}`);
hanoi(disc - 1, aux, src, dst);
}
};
console.info(`let hanoi = ${hanoi}`);
console.info("=>");
hanoi(3, "Src", "Aux", "Dst");
/* no DOM in node, so skipping this part */
console.info("\n*Tail recursion*");
console.info("_factorial_ is a tail recursive function, because the *last* thing it does is calling itself.");
// make a factorial function with tail
// recursion. It is tail recursive because
// it returns the result of calling itself.
/* ie. calling itself is the very last thing it does */
// JavaScript does not currently optimize this form /* Not true anymore in ES6 according to SO */
let factorial = function factorial(i, a) {
a = a || 1;
if (i < 2) {
return a;
} else {
return factorial(i - 1, a * i);
}
};
console.info(`let factorial = ${factorial}`);
console.info(`10 factorial : ${factorial(10)}`);
console.info(`which by the way is the nr of seconds in 6 weeks: factorial(10) / (60*60*24*7) = ${factorial(10) / (60 * 60 * 24 * 7)} 😀`);
// Scope
console.info("\n*Scope*");
console.info("We print _a_ before it (seemingly) is declared. This is possible because in the compiled code,");
console.info("the declaration is put at the start of the function.");
console.info("This is true for _var_ but not for _let_ and _const_");
/* _a_ has function scope */
let foo = function () {
console.info(`In the code _a_ is declared after this line, but when running _a_ is defined first. It's value is _${a}_, because its assignment has not yet been executed`);
var a = 1; // _let_ and _const_ would not allow this
};
console.info(`let foo = ${foo}`);
foo();
// Closure
console.info("\n*Closure*");
console.info("meaning: a nested function has access to the state of the outer function");
console.info("it closes over that state.");
let someObject = function () {
let value = 0;
return {
inc: function () { /* slightly simpler than the book provides */
value += 1;
},
getValue() {
return value; /* value is accessible here */
}
};
}(); /* I took away the extra parentheses */
someObject.inc();
console.info(`=> someObject's value after 1 increment (by 1) is ${someObject.getValue()}`);
// A better quo
console.info("\nQuo as defined earlier can be rewritten in a better fashion using closures:");
let quo = function (status) {
return {
get_status() {
return status;
}
};
};
console.info(`let quo = ${quo}`);
console.info("\nUsing closures the wrong way:");
// BAD EXAMPLE
// Make a function that assigns event handler functions to an array of nodes the wrong way
// When you click on the node /* simulated here */, an alert box is supposed to display the ordinal of the node.
// But it always displays the number of nodes instead
let add_the_handlers = function (nodes) {
let i; /* _i_ is shared by all onclick function instances */
for (i = 0; i < nodes.length; i++) { /* and the same _i_ is mutated here*/
nodes[i].onclick = function () {
console.info(`ordinal: ${i}`);
};
}
};
console.info(`let add_the_handlers = ${add_the_handlers}`);
let nodes = [{}, {}, {}];
add_the_handlers(nodes);
// simulate clicking the nodes
console.info("=>");
for (let j = 0; j < nodes.length; j++) {
nodes[j].onclick();
}
/* The ordinal is always 3 because the onclick functions close over the shared mutable variable _i_
instead there should be a separate state for all onclick functions, and it should not be mutable */
// BETTER EXAMPLE
// Make a function that assigns event handler functions to an array of nodes.
// When you click on the node, an alert box will display the ordinal of the node.
let add_the_handlers2 = function (nodes) {
let helper = function (i) { /* the passed value of i is the state to close over */
const ordinal = i; /* not necessary, but added to stress immutability*/
return function () {
console.info(`ordinal ${ordinal}`);
};
};
for (let i = 0; i < nodes.length; i++) {
nodes[i].onclick = helper(i);
}
};
console.info("This is the right way:");
console.info(`let add_the_handlers2 = ${add_the_handlers2}`);
add_the_handlers2(nodes);
console.info("=>");
for (let j = 0; j < nodes.length; j++) {
nodes[j].onclick();
}
// Callbacks
/* node code*/
// Module
console.info("\n*Modules*");
String.method("deentityify",
function () {
// The entity table. It maps entity names to characters.
let entity = {
quot: "\"",
lt: "<",
gt: ">"
};
return function () {
return this.replace(/&([^&;]+);/g, function (a, b) {
let r = entity[b];
return typeof r === "string" ? r : a;
});
};
}()
);
console.info(`String.prototype.deentityify = ${String.prototype.deentityify}`);
console.info("NB The code you see outputted here is not the actual code, but the result of it...");
console.info("The entity table is hidden and can never be accessed, not even by new functions that are added to deentityify later on");
console.info(`=> "&lt;&quot;&gt;".deentityify() = ${"&lt;&quot;&gt;".deentityify()}`);
/* What I fail to see is how you could access entity, had you put it in deentityify directly */
// Cascade
/* Also called Fluent pattern */
/* return _this_ instead of _undefined_ so you can chain method calls on the same object */
/* you get don't you? */
// Curry
/* After famous computer scientist Haskell Curry */
console.info("\n*Curry*");
console.info("Currying a function results in a new function that does the same thing, but is has part of the original's parameters already entered.");
Function.method("curry", function () {
let slice = Array.prototype.slice, /* this workaround is explained in the book */
args = slice.apply(arguments),
that = this; /* store the arguments for _curry_ and the function it's called on */
return function () {
return that.apply(null, args.concat(slice.apply(arguments))); /* nifty: the argument for _curry_ precede all arguments for the eventual function call */
};
});
console.info(`Function.prototype.curry = ${Function.prototype.curry}`);
let add1 = add.curry(1);
console.info(`We've curried _add_ with argument numeric 1 in _add1_. So add1(6) will give you ${add1(6)}`);
// Memoization
console.info("\nMemoization");
/* I added a track_calls function that keeps track of all calls to a supplied function */
let track_calls = function (track_object, fn) {
return function () {
track_object.calls += 1;
fn.apply(null, arguments);
};
};
let tracker = {calls: 0}; /* not really elegant but I can't think of anything better right now */
let fibonacci = track_calls(tracker, function fib(n) {
if (n < 2) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2); /* important here to not call fib, but the tracked function */
}
});
console.info(`let fibonacci = ${fibonacci}`);
for (let i = 0; i < 11; i++) {
console.info(`=> ${i}: ${fibonacci(i)}`);
}
console.info(`It works but is inefficient because the function is often called (${tracker.calls} times!) on mostly the same values,
which could also have been stored somewhere after calculation.`);
let memo_fibo = function () {
let memo = [0, 1];
let fib = function (n) {
let result = memo[n];
if (typeof result !== "number") {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}();
console.info(`\nlet memo_fibo = function () {
let memo = [0, 1];
let fib = function (n) {
let result = memo[n];
if (typeof result !== 'number') {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}();`);
for (let i = 0; i < 11; i++) {
console.info(`=> ${i}: ${memo_fibo(i)}`);
}
console.info("This works efficiently, but we could extract the memoization function to make it more general.");
let memoizer = function (track_object, memo, formula) { /* call tracking built-in */
let recur = function (n) {
let result = memo[n];
if (result === undefined) { /* slightly altered to allow for non-numeric types as well */
track_object.calls += 1;
result = formula(recur, n);
memo[n] = result;
}
return result;
};
return recur;
};
console.info(`let memoizer = ${memoizer}`);
tracker = {calls: 0};
let ultimate_fibonacci = memoizer(tracker, [0, 1], function (recur, n) {
return recur(n - 1) + recur(n - 2);
});
console.info("We've redefined fibonacci to make use of _memoizer_");
console.info(`let ultimate_fibonacci = memoizer([0,1], function (recur, n){
return recur(n-1) + recur(n-2);
});`);
for (let i = 0; i < 11; i++) {
console.info(`=> ${i}: ${ultimate_fibonacci(i)}`);
}
console.info(`The number of times something had to be calculated is now ${tracker.calls}!`);
}());

138
_5_inheritance.js Normal file
View file

@ -0,0 +1,138 @@
(function () {
// 5 Inheritance
console.info("\n\n**Chapter 5 Inheritance**");
console.info("\n*Pseudoclassical*");
console.info("\n*Object Specifiers*");
console.info("\n*Prototypal*");
console.info("Prototypal inheritance is simpler");
let prototypal_mammal = {
name: "Herb the Mammal",
get_name: function () {
return this.name;
},
says: function () {
return this.saying || "";
}
};
let prototypal_cat = Object.create(prototypal_mammal);
prototypal_cat.name = "Henrietta"; /* uses existing property */
prototypal_cat.saying = "Meow!"; /* is sort of abstract in mammal */
prototypal_cat.purr = function (n) { /* add new behavior */
let s = "";
for (let i = 0; i < n; i += 1) {
if (s) {
s += "-";
}
s += "r";
}
return s;
};
prototypal_cat.get_name = function () { /* alter existing behavior */
return this.says() + " " + this.name + " " + this.says();
};
console.info(`${prototypal_cat.get_name()}`);
console.info("*Functional*");
console.info("Yet a better way to deal with objects");
let mammal = function (spec) {
let that = {};
that.get_name = function () {
return spec.name;
};
that.says = function () {
return spec.saying || "";
};
return that;
};
let cat = function (spec) {
spec.saying = spec.saying || "meow";
let that = mammal(spec);
that.purr = function (n) {
let s = "";
for (let i = 0; i < n; i += 1) {
if (s) {
s += "-";
}
s += "r";
}
return s;
};
that.get_name = function () {
return that.says() + " " + spec.name + " " + that.says();
};
return that;
};
// We make a _superior_ method that takes a method and returns a function that invokes that method
Object.method("superior", function (name) {
let that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});
/* I don't see the 'superior' in this. What version of the method you get depends on the calling order, right? It just saves a method reference in a function. */
let coolcat = function (spec) {
let that = cat(spec),
super_get_name = that.superior("get_name"); // just try putting this after line 82
that.get_name = function () {
return `like ${super_get_name()} baby`;
};
return that;
};
let myCoolCat = coolcat({name: "Brix"});
console.info(`my cool cat's name = ${myCoolCat.get_name()}`);
// Parts
/* The code was not immediately obvious to me. Copying it from the book helped me understand.
* At the same time taking the liberty to improve it - forgive my hubris - only superficial though */
let eventuality = function (that) {
let registry = {};
that.fire = function (event) { /* add a _fire_ method */
let handler_array,
type = (typeof event === "string") ? event : event.type;
// If an array of handlers exist for this event, then loop through it and execute the handlers in order.
/* nit: is the book's code properly indented ? */
if (Object.prototype.hasOwnProperty.call(registry, type)) {
handler_array = registry[type];
for (let i = 0; i < handler_array.length; i += 1) { /* I do like this better than _i++_ */
let handler = handler_array[i];
// A handler record contains a method and an optional array of parameters. If the method is a name, look up the function
let func = handler.method; /* This makes me think: objects, records and structs in strongly typed languages really define a contract.
* Here being the fact that _handler_ *has* a _method_ */
if (typeof func === "string") {
func = this[func]; /* what is this here? */
}
func.apply(this, handler.parameters || [event]);
}
}
return this;
};
// Register an event. Make a handler record. Put it in a handler array, making one if it doesn't yet exist for this type.
that.on = function (type, method, parameters) { /* add an _on_ method */
let handler = {
method: method,
parameters: parameters
}; /* might this serve as a contract? */
if (Object.prototype.hasOwnProperty.call(registry, type)) {
registry[type].push(handler);
} else {
registry[type] = [handler];
}
return this;
};
return that;
};
}());

48
_6_arrays.js Normal file
View file

@ -0,0 +1,48 @@
(function () {
// 6 Arrays
console.info("\n\n**Chapter 6 Arrays**");
console.info("\n*Array literals*");
let empty = [];
let numbers = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
console.info(`=> element 1 of empty array: ${empty[1]}`); // undefined
console.info(`=> element 1 of non-empty array: ${numbers[1]}`); // 'one'
console.info(`=> length of empty array: ${empty.length}`); // 0
console.info(`=> length of non-empty array: ${numbers.length}`); // 10
// arrays can contain any element type
let misc = ["string", 98.6, true, false, null, undefined, ["nested", "array"], {object: true}, NaN, Infinity];
// Length
console.info("\n*Length*");
let myArray = [1, 2, 3];
console.info(`let myArray = [${myArray}]`);
console.info(`=> myArray.length = ${myArray.length}`);
console.info("Array length is not fixed. Let's add an element at index 8");
myArray[8] = true;
console.info(`=> myArray = [${myArray}]`);
console.info(`=> myArray.length = ${myArray.length}`);
console.info("Surprisingly you can set array length:");
myArray.length = 10;
console.info(`Just set it to 10. => myArray.length = ${myArray.length}, => myArray = [${myArray}]`);
myArray.length = 2;
console.info(`=> And now it's set to 2: [${myArray}]`);
// Delete
console.info("Delete element 1");
delete myArray[1];
console.info(`=> myArray = [${myArray}]`);
// Enumeration
console.info("C-style for is the only good way to enumerate over arrays.");
// Confusion
// Book says this is the way to detect an array:
let is_array = function (value) {
return Object.prototype.toString().apply(value) === "[object Array]";
};
// Methods
// While this is interesting, it's not hard to understand, so I'm skipping this right now.
}());

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

912
package-lock.json generated Normal file
View file

@ -0,0 +1,912 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.4"
}
},
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
},
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
}
}
},
"@eslint/eslintrc": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz",
"integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.1.1",
"espree": "^7.3.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.2.1",
"js-yaml": "^3.13.1",
"lodash": "^4.17.19",
"minimatch": "^3.0.4",
"strip-json-comments": "^3.1.1"
}
},
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
},
"acorn-jsx": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
"dev": true
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
"dev": true
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
},
"astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"debug": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
"integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"requires": {
"esutils": "^2.0.2"
}
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
"dev": true,
"requires": {
"ansi-colors": "^4.1.1"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"eslint": {
"version": "7.12.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz",
"integrity": "sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@eslint/eslintrc": "^0.2.1",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"enquirer": "^2.3.5",
"eslint-scope": "^5.1.1",
"eslint-utils": "^2.1.0",
"eslint-visitor-keys": "^2.0.0",
"espree": "^7.3.0",
"esquery": "^1.2.0",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash": "^4.17.19",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"progress": "^2.0.0",
"regexpp": "^3.1.0",
"semver": "^7.2.1",
"strip-ansi": "^6.0.0",
"strip-json-comments": "^3.1.0",
"table": "^5.2.3",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
}
},
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"requires": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
}
},
"eslint-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
}
}
},
"eslint-visitor-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
"integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
"dev": true
},
"espree": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
"integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
"dev": true,
"requires": {
"acorn": "^7.4.0",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.3.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
}
}
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"esquery": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
"integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
"dev": true,
"requires": {
"estraverse": "^5.1.0"
},
"dependencies": {
"estraverse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
}
}
},
"esrecurse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"requires": {
"estraverse": "^5.2.0"
},
"dependencies": {
"estraverse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
}
}
},
"estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"file-entry-cache": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
"integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
"dev": true,
"requires": {
"flat-cache": "^2.0.1"
}
},
"flat-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
"integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
"dev": true,
"requires": {
"flatted": "^2.0.0",
"rimraf": "2.6.3",
"write": "1.0.3"
}
},
"flatted": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"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"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"dev": true,
"requires": {
"type-fest": "^0.8.1"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"import-fresh": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz",
"integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
}
},
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"js-yaml": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
"dev": true,
"requires": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0",
"word-wrap": "^1.2.3"
}
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"requires": {
"callsites": "^3.0.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
},
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
"regexpp": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
"integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
"dev": true
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
"dev": true
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"slice-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
"integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"astral-regex": "^1.0.0",
"is-fullwidth-code-point": "^2.0.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
},
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
"dev": true,
"requires": {
"ajv": "^6.10.2",
"lodash": "^4.17.14",
"slice-ansi": "^2.1.0",
"string-width": "^3.0.0"
}
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1"
}
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
"uri-js": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
},
"v8-compile-cache": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
"integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
"integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
"dev": true,
"requires": {
"mkdirp": "^0.5.1"
}
}
}
}

6
package.json Normal file
View file

@ -0,0 +1,6 @@
{
"type": "module",
"devDependencies": {
"eslint": "^7.12.1"
}
}