diff --git a/.babelrc b/.babelrc
index dfb789cd44ba0e6b8f22e3479dd33bfe8b1fd83e..a6378637f21b600ffacd3454a3d3b4ccc3e7775b 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,3 +1,6 @@
 {
-	"presets": ["@babel/env"]
-}
\ No newline at end of file
+	"presets": [
+		["@babel/env", {"modules": false}]
+	],
+	"plugins": ["@babel/plugin-proposal-class-properties"]
+}
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000000000000000000000000000000000000..d64a3b68f4051320da34d4186e0d66e75ca87f24
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,7 @@
+{
+	"singleQuote": true,
+	"trailingComma": "es5",
+	"endOfLine": "lf",
+	"useTabs": true,
+	"arrowParens": "avoid"
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..69b36e697f238802b033715905a6c2694b2d87a0
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+	"[javascript]": {
+		"editor.formatOnSave": true,
+		"editor.defaultFormatter": "vscode.typescript-language-features"
+	}
+}
\ No newline at end of file
diff --git a/A-preparatifs.md b/A-preparatifs.md
index c3d3fce0319ad5f1a47ae617a6a4b921cc95df95..7b45849960614da844b3cb3d460ca9c0ae66828a 100644
--- a/A-preparatifs.md
+++ b/A-preparatifs.md
@@ -12,7 +12,7 @@
 ## A.1. Récupération du projet
 
 **Ce repo contient une solution commentée du précédent TP.** <br>
-Il va vous servir de base pour ce nouveau TP.
+Il va vous de base pour ce nouveau TP.
 
 1. **Commencez par faire un fork du TP :**
 	- soit en cliquant sur le bouton `"Créer une divergence"` (_`"Fork"` sur la version anglaise de gitlab_)
diff --git a/C-modules.md b/C-modules.md
index 80a45906881ec5d488e2f3f49b4de95832b75abd..668fbfe24c8c9c3fec422ea2c78b9ecaf27151f5 100644
--- a/C-modules.md
+++ b/C-modules.md
@@ -141,7 +141,7 @@ Comme vu en cours, le bundler le plus employé en JS est [Webpack](https://webpa
 	}
 	```
 
-4. **Modifiez les scripts `"build"` et `"watch"` du fichier `package.json` pour remplacer babel par webpack** (_notez quand même que **babel sera toujours utilisé mais en arrière plan** par webpack grâce au `webpack.config.js` que l'on vient d'écrire_):
+4. **Modifiez les scripts `"build"` et `"watch"` du fichier `package.json` pour replacer babel par webpack** (_notez quand même que **babel sera toujours utilisé mais en arrière plan** par webpack grâce au `webpack.config.js` que l'on vient d'écrire_):
 	```json
 	"build": "webpack --mode=production",
 	"watch": "webpack --mode=development --watch"
diff --git a/D-poo-avancee.md b/D-poo-avancee.md
index 6169a68c89e0147c8da5552aec979573a7c982ba..c911b1153391a7a7d92a8c3b0e4024570870d057 100644
--- a/D-poo-avancee.md
+++ b/D-poo-avancee.md
@@ -53,54 +53,14 @@ _**L'objectif de cet exercice est d'utiliser une classe à l'intérieur d'une au
 
 	<img src="images/readme/pizzaland-03.png" >
 
-	> _**NB :** Si jamais **le fond blanc derrière "Regina" n'apparaît pas**,_
-	> _vérifiez que votre classe `Component` ajoute bien la classe CSS `pizzaThumbnail`_
-	> _sur la balise `<article>`..._
-
-3. **Grâce aux modifications que l'on vient de faire sur la classe `Component`,**
-	**on peut maintenant créer la classe `PizzaThumbnail`** (dans `src/components/PizzaThumbnail.js`).
-
-	`PizzaThumbnail` est en fait un `Component` auquel on peut passer un objet "pizza"
-	(_une cellule du tableau `data`_) et qui est capable de générer le même code HTML
-	que ce que l'on avait fait dans le TP1.
-
-	Je vous fourni son code car l'intérêt ici, est simplement de **s'assurer que votre classe `Component`**
-	**gère bien les différents cas limites** :
+3. **Créez une classe `PizzaThumbnail`** (dans `src/components/PizzaThumbnail.js`) qui hérite de la classe `Component` et qui utilise **obligatoirement** la classe **`Img`** pour rendre son code HTML.
 
+	Avec le code JS suivant :
 	```js
-	export default class PizzaThumbnail extends Component {
-		constructor({ name, image, price_small, price_large }) {
-			super('article', { name: 'class', value: 'pizzaThumbnail' }, [
-				new Component('a', { name: 'href', value: image }, [
-					new Img(image),
-					new Component('section', null, [
-						new Component('h4', null, name),
-						new Component('ul', null, [
-							new Component('li', null, `Prix petit format : ${price_small.toFixed(2)} €`),
-							new Component('li', null, `Prix grand format : ${price_large.toFixed(2)} €` ),
-						]),
-					]),
-				]),
-			]);
-		}
-	}
-	```
-
-	Comme vous le voyez, on utilise ici le même principe que pour la classe `Img` :
-	on **surcharge juste le constructeur** en invoquant celui de `Component` (`super(...)`)
-	et en lui passant les bons `tagName`, `attribute` et `children`.
-
-	Dans le `src/main.js`, testez votre classe avec le code suivant :
-	```js
-	const pizza = data[0];
-	const pizzaThumbnail = new PizzaThumbnail(pizza);
+	const pizzaThumbnail = new PizzaThumbnail(data[0]);
 	document.querySelector( '.pageContent' ).innerHTML = pizzaThumbnail.render();
 	```
-
-	Si votre classe `Component` est correctement codée
-	(c'est à dire qu'elle prend en compte tous les cas limites)
-	alors le code HTML généré sera le suivant :
-
+	... le code HTML généré sera :
 	```html
 	<article class="pizzaThumbnail">
 		<a href="https://images.unsplash.com/photo-1532246420286-127bcd803104?fit=crop&w=500&h=300">
@@ -115,7 +75,6 @@ _**L'objectif de cet exercice est d'utiliser une classe à l'intérieur d'une au
 		</a>
 	</article>
 	```
-
 	... et le rendu obtenu dans la page sera celui-ci :
 
 	<img src="images/readme/pizzaland-04.png" >
@@ -147,10 +106,6 @@ Le résultat attendu est le suivant :
 
 Dans cet exercice, je vous propose de développer une classe `Router` qui, à l'aide des **propriétés et méthodes statiques**, va gérer l'affichage à la fois du titre de la page, et de son contenu.
 
-C'est une classe qui nous servira dans les prochains TP et qui nous permettra de
-naviguer d'une page à l'autre sans rechargement de page !
-(_principe de base des [SPA](https://en.wikipedia.org/wiki/Single-page_application)_)
-
 ### D.3.1 Rappels de syntaxe
 Pour rappel les propriétés et méthodes statiques peuvent se déclarer à l'aide du mot clé `static`. Ces propriétés/méthodes sont définies et s'utilisent au niveau de la classe (et pas de l'instance) comme ceci :
 
@@ -195,7 +150,7 @@ console.log(
 Dans cet exercice je vous propose d'utiliser plusieurs syntaxes supplémentaires: les **propriétés et méthodes privées** ainsi que les **getters/setters**.
 
 ### D.4.1. Rappels propriétés privées
-Pour déclarer et utiliser des propriétés ou méthodes privées il suffit de les préfixer du caractère `'#'` comme ceci :
+Pour déclarer et utiliser des propriétés ou méthodes privées il suffit de les préfixer du caractère `'#'`comme ceci :
 
 ```js
 class Character {
@@ -208,7 +163,7 @@ class Character {
 }
 ```
 
-Le support des propriétés et méthodes privées est en stage 3/4 de spécification. Ce n'est donc pas encore dans la spec EcmaScript officielle. Néanmoins il est possible de les utiliser grâce au plugin Babel [@babel/plugin-proposal-class-properties](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) que l'on a déjà installé précédemment (c'est le même que pour les propriétés publiques).
+Le support des propriétés et méthodes privées est en stage 3/4 de spécification. Ce n'est donc pas encore dans la spec EcmaScript officielle. Néanmoins il est possible de les utiliser grâce à au plugin Babel [@babel/plugin-proposal-class-properties](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) que l'on a déjà installé précédemment (c'est le même que pour les propriétés publiques).
 
 > _**NB :** Si vous vous demandez pourquoi on écrit `#propriete` et pas `private propriete` comme dans d'autres langages, la réponse se trouve ici :_ https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#why-arent-declarations-private-x
 
@@ -235,9 +190,6 @@ On a l'impression d'utiliser une propriété, mais en réalité c'est une métho
 A l'aide des propriétés privées, des getters et des setters, faire en sorte que le code suivant permette d'afficher la liste des pizzas :
 ```js
 const pizzaList = new PizzaList([]);
-
-Router.titleElement = document.querySelector('.pageTitle');
-Router.contentElement = document.querySelector('.pageContent');
 Router.routes = [{ path: '/', page: pizzaList, title: 'La carte' }];
 
 Router.navigate('/'); // affiche une page vide
diff --git a/index.html b/index.html
index 059864d784d0f8290a8fc1fe1597a9a0a9b99809..21d4d9489ae8bafa7dc479ba05279ea659f884ac 100644
--- a/index.html
+++ b/index.html
@@ -14,7 +14,7 @@
 	<link rel="stylesheet" href="css/pizzaList.css">
 	<link rel="stylesheet" href="css/footer.css">
 
-	<script src="build/main.js" defer></script>
+	<script src="build/main.bundle.js" defer></script>
 </head>
 <body>
 	<header>
diff --git a/package-lock.json b/package-lock.json
index b550b6731d085ba1d342ed2d2f56c3451c0c08cd..ee19b649571bceb5e60e668ae22f4c1ea0924200 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1049,6 +1049,12 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@discoveryjs/json-ext": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz",
+      "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==",
+      "dev": true
+    },
     "@nicolo-ribaudo/chokidar-2": {
       "version": "2.1.8-no-fsevents",
       "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz",
@@ -1069,6 +1075,253 @@
         "upath": "^1.1.1"
       }
     },
+    "@types/eslint": {
+      "version": "7.2.6",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz",
+      "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==",
+      "dev": true,
+      "requires": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "@types/eslint-scope": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz",
+      "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==",
+      "dev": true,
+      "requires": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "0.0.46",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz",
+      "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==",
+      "dev": true
+    },
+    "@types/json-schema": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+      "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "14.14.22",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz",
+      "integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw==",
+      "dev": true
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz",
+      "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/helper-numbers": "1.11.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.0"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz",
+      "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz",
+      "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz",
+      "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-numbers": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz",
+      "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.0",
+        "@webassemblyjs/helper-api-error": "1.11.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz",
+      "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz",
+      "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/helper-buffer": "1.11.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.0",
+        "@webassemblyjs/wasm-gen": "1.11.0"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz",
+      "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==",
+      "dev": true,
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz",
+      "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==",
+      "dev": true,
+      "requires": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz",
+      "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==",
+      "dev": true
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz",
+      "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/helper-buffer": "1.11.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.0",
+        "@webassemblyjs/helper-wasm-section": "1.11.0",
+        "@webassemblyjs/wasm-gen": "1.11.0",
+        "@webassemblyjs/wasm-opt": "1.11.0",
+        "@webassemblyjs/wasm-parser": "1.11.0",
+        "@webassemblyjs/wast-printer": "1.11.0"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz",
+      "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.0",
+        "@webassemblyjs/ieee754": "1.11.0",
+        "@webassemblyjs/leb128": "1.11.0",
+        "@webassemblyjs/utf8": "1.11.0"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz",
+      "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/helper-buffer": "1.11.0",
+        "@webassemblyjs/wasm-gen": "1.11.0",
+        "@webassemblyjs/wasm-parser": "1.11.0"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz",
+      "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/helper-api-error": "1.11.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.0",
+        "@webassemblyjs/ieee754": "1.11.0",
+        "@webassemblyjs/leb128": "1.11.0",
+        "@webassemblyjs/utf8": "1.11.0"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz",
+      "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.11.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webpack-cli/configtest": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.0.tgz",
+      "integrity": "sha512-Un0SdBoN1h4ACnIO7EiCjWuyhNI0Jl96JC+63q6xi4HDUYRZn8Auluea9D+v9NWKc5J4sICVEltdBaVjLX39xw==",
+      "dev": true
+    },
+    "@webpack-cli/info": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.1.tgz",
+      "integrity": "sha512-fLnDML5HZ5AEKzHul8xLAksoKN2cibu6MgonkUj8R9V7bbeVRkd1XbGEGWrAUNYHbX1jcqCsDEpBviE5StPMzQ==",
+      "dev": true,
+      "requires": {
+        "envinfo": "^7.7.3"
+      }
+    },
+    "@webpack-cli/serve": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.2.2.tgz",
+      "integrity": "sha512-03GkWxcgFfm8+WIwcsqJb9agrSDNDDoxaNnexPnCCexP5SCE4IgFd9lNpSy+K2nFqVMpgTFw6SwbmVAVTndVew==",
+      "dev": true
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true
+    },
+    "@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true
+    },
+    "acorn": {
+      "version": "8.0.5",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz",
+      "integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==",
+      "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"
+      }
+    },
+    "ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "dev": true
+    },
+    "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-styles": {
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -1150,6 +1403,35 @@
       "dev": true,
       "optional": true
     },
+    "babel-loader": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz",
+      "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==",
+      "dev": true,
+      "requires": {
+        "find-cache-dir": "^3.3.1",
+        "loader-utils": "^1.4.0",
+        "make-dir": "^3.1.0",
+        "schema-utils": "^2.6.5"
+      },
+      "dependencies": {
+        "make-dir": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+          "dev": true,
+          "requires": {
+            "semver": "^6.0.0"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
     "babel-plugin-dynamic-import-node": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@@ -1225,6 +1507,12 @@
         }
       }
     },
+    "big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "dev": true
+    },
     "binary-extensions": {
       "version": "1.13.1",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
@@ -1286,6 +1574,12 @@
         "node-releases": "^1.1.69"
       }
     },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
     "cache-base": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
@@ -1435,6 +1729,15 @@
         }
       }
     },
+    "chrome-trace-event": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+      "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "class-utils": {
       "version": "0.3.6",
       "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -1460,6 +1763,17 @@
         }
       }
     },
+    "clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "dev": true,
+      "requires": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      }
+    },
     "collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -1498,6 +1812,12 @@
       "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
       "dev": true
     },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
     "component-emitter": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
@@ -1552,6 +1872,17 @@
       "dev": true,
       "optional": 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": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -1629,6 +1960,43 @@
       "integrity": "sha512-P+3q8ugIPezulqoBYaLoUsF0fT4YNpe+zEDmdDUDnHZUAeSbBjMbis+JjJp9duU8BdfWV3VXf27NTBcwhRTsAQ==",
       "dev": true
     },
+    "emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "dev": true
+    },
+    "enhanced-resolve": {
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz",
+      "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      }
+    },
+    "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"
+      }
+    },
+    "envinfo": {
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz",
+      "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==",
+      "dev": true
+    },
+    "es-module-lexer": {
+      "version": "0.3.26",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz",
+      "integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==",
+      "dev": true
+    },
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -1641,12 +2009,68 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "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"
+      }
+    },
+    "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
     },
+    "events": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
+      "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
+      "dev": true
+    },
+    "execa": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz",
+      "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^6.0.0",
+        "human-signals": "^2.1.0",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.1",
+        "onetime": "^5.1.2",
+        "signal-exit": "^3.0.3",
+        "strip-final-newline": "^2.0.0"
+      }
+    },
     "expand-brackets": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -1779,6 +2203,24 @@
         }
       }
     },
+    "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
+    },
+    "fastest-levenshtein": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+      "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+      "dev": true
+    },
     "fill-range": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -1804,6 +2246,44 @@
         }
       }
     },
+    "find-cache-dir": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+      "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "dependencies": {
+        "make-dir": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+          "dev": true,
+          "requires": {
+            "semver": "^6.0.0"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -1863,6 +2343,12 @@
         "has-symbols": "^1.0.1"
       }
     },
+    "get-stream": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz",
+      "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==",
+      "dev": true
+    },
     "get-value": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -1907,6 +2393,12 @@
         }
       }
     },
+    "glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+      "dev": true
+    },
     "globals": {
       "version": "11.12.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -1917,8 +2409,7 @@
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
       "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "has": {
       "version": "1.0.3",
@@ -1976,6 +2467,22 @@
         }
       }
     },
+    "human-signals": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+      "dev": true
+    },
+    "import-local": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz",
+      "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==",
+      "dev": true,
+      "requires": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      }
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -1992,6 +2499,12 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
+    "interpret": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+      "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+      "dev": true
+    },
     "is-accessor-descriptor": {
       "version": "0.1.6",
       "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
@@ -2031,6 +2544,15 @@
       "dev": true,
       "optional": true
     },
+    "is-core-module": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
+      "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
     "is-data-descriptor": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
@@ -2125,11 +2647,16 @@
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
       "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
       "dev": true,
-      "optional": true,
       "requires": {
         "isobject": "^3.0.1"
       }
     },
+    "is-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+      "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+      "dev": true
+    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -2144,12 +2671,45 @@
       "dev": true,
       "optional": true
     },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
     "isobject": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
       "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+      "dev": true
+    },
+    "jest-worker": {
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+      "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
       "dev": true,
-      "optional": true
+      "requires": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^7.0.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        }
+      }
     },
     "js-tokens": {
       "version": "4.0.0",
@@ -2163,6 +2723,18 @@
       "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
       "dev": true
     },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "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
+    },
     "json5": {
       "version": "2.1.3",
       "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
@@ -2176,8 +2748,44 @@
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true
+    },
+    "loader-runner": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz",
+      "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
+      "dev": true
+    },
+    "loader-utils": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+      "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
       "dev": true,
-      "optional": true
+      "requires": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^1.0.1"
+      },
+      "dependencies": {
+        "json5": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.0"
+          }
+        }
+      }
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
     },
     "lodash": {
       "version": "4.17.20",
@@ -2212,6 +2820,12 @@
         "object-visit": "^1.0.0"
       }
     },
+    "merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
     "micromatch": {
       "version": "3.1.10",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -2234,6 +2848,27 @@
         "to-regex": "^3.0.2"
       }
     },
+    "mime-db": {
+      "version": "1.45.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
+      "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.28",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
+      "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
+      "dev": true,
+      "requires": {
+        "mime-db": "1.45.0"
+      }
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -2299,6 +2934,12 @@
         "to-regex": "^3.0.1"
       }
     },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
     "node-releases": {
       "version": "1.1.70",
       "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz",
@@ -2312,6 +2953,15 @@
       "dev": true,
       "optional": true
     },
+    "npm-run-path": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.0.0"
+      }
+    },
     "object-copy": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
@@ -2393,6 +3043,39 @@
         "wrappy": "1"
       }
     },
+    "onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true
+    },
     "pascalcase": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -2407,12 +3090,30 @@
       "dev": true,
       "optional": true
     },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true
+    },
     "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
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
     "picomatch": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
@@ -2426,6 +3127,15 @@
       "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
       "dev": true
     },
+    "pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dev": true,
+      "requires": {
+        "find-up": "^4.0.0"
+      }
+    },
     "posix-character-classes": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -2433,6 +3143,12 @@
       "dev": true,
       "optional": true
     },
+    "prettier": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
+      "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
+      "dev": true
+    },
     "process-nextick-args": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -2440,6 +3156,21 @@
       "dev": true,
       "optional": 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
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
     "readable-stream": {
       "version": "2.3.7",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -2468,6 +3199,15 @@
         "readable-stream": "^2.0.2"
       }
     },
+    "rechoir": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz",
+      "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==",
+      "dev": true,
+      "requires": {
+        "resolve": "^1.9.0"
+      }
+    },
     "regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -2567,6 +3307,31 @@
       "dev": true,
       "optional": true
     },
+    "resolve": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
+      "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
+      "dev": true,
+      "requires": {
+        "is-core-module": "^2.1.0",
+        "path-parse": "^1.0.6"
+      }
+    },
+    "resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^5.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true
+    },
     "resolve-url": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -2597,12 +3362,32 @@
         "ret": "~0.1.10"
       }
     },
+    "schema-utils": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
+      "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
+      "dev": true,
+      "requires": {
+        "@types/json-schema": "^7.0.5",
+        "ajv": "^6.12.4",
+        "ajv-keywords": "^3.5.2"
+      }
+    },
     "semver": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
       "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
       "dev": true
     },
+    "serialize-javascript": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
+      "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
+    },
     "set-value": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -2628,6 +3413,36 @@
         }
       }
     },
+    "shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^6.0.2"
+      }
+    },
+    "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
+    },
+    "signal-exit": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+      "dev": true
+    },
     "slash": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
@@ -2751,6 +3566,12 @@
         }
       }
     },
+    "source-list-map": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+      "dev": true
+    },
     "source-map": {
       "version": "0.5.7",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -2771,6 +3592,24 @@
         "urix": "^0.1.0"
       }
     },
+    "source-map-support": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
     "source-map-url": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
@@ -2821,6 +3660,12 @@
         "safe-buffer": "~5.1.0"
       }
     },
+    "strip-final-newline": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+      "dev": true
+    },
     "supports-color": {
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -2830,6 +3675,79 @@
         "has-flag": "^3.0.0"
       }
     },
+    "tapable": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz",
+      "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==",
+      "dev": true
+    },
+    "terser": {
+      "version": "5.5.1",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
+      "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.20.0",
+        "source-map": "~0.7.2",
+        "source-map-support": "~0.5.19"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.7.3",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+          "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+          "dev": true
+        }
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz",
+      "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==",
+      "dev": true,
+      "requires": {
+        "jest-worker": "^26.6.2",
+        "p-limit": "^3.1.0",
+        "schema-utils": "^3.0.0",
+        "serialize-javascript": "^5.0.1",
+        "source-map": "^0.6.1",
+        "terser": "^5.5.1"
+      },
+      "dependencies": {
+        "p-limit": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+          "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+          "dev": true,
+          "requires": {
+            "yocto-queue": "^0.1.0"
+          }
+        },
+        "schema-utils": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
+          "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.6",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
     "to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -2882,6 +3800,12 @@
         "repeat-string": "^1.6.1"
       }
     },
+    "tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
     "unicode-canonical-property-names-ecmascript": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@@ -2974,6 +3898,15 @@
       "dev": true,
       "optional": true
     },
+    "uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
     "urix": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
@@ -2995,11 +3928,197 @@
       "dev": true,
       "optional": true
     },
+    "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
+    },
+    "watchpack": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.0.tgz",
+      "integrity": "sha512-UjgD1mqjkG99+3lgG36at4wPnUXNvis2v1utwTgQ43C22c4LD71LsYMExdWXh4HZ+RmW+B0t1Vrg2GpXAkTOQw==",
+      "dev": true,
+      "requires": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      }
+    },
+    "webpack": {
+      "version": "5.19.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.19.0.tgz",
+      "integrity": "sha512-egX19vAQ8fZ4cVYtA9Y941eqJtcZAK68mQq87MMv+GTXKZOc3TpKBBxdGX+HXUYlquPxiluNsJ1VHvwwklW7CQ==",
+      "dev": true,
+      "requires": {
+        "@types/eslint-scope": "^3.7.0",
+        "@types/estree": "^0.0.46",
+        "@webassemblyjs/ast": "1.11.0",
+        "@webassemblyjs/wasm-edit": "1.11.0",
+        "@webassemblyjs/wasm-parser": "1.11.0",
+        "acorn": "^8.0.4",
+        "browserslist": "^4.14.5",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.7.0",
+        "es-module-lexer": "^0.3.26",
+        "eslint-scope": "^5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.4",
+        "json-parse-better-errors": "^1.0.2",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "pkg-dir": "^5.0.0",
+        "schema-utils": "^3.0.0",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.1.1",
+        "watchpack": "^2.0.0",
+        "webpack-sources": "^2.1.1"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+          "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^6.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+          "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^5.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+          "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+          "dev": true,
+          "requires": {
+            "yocto-queue": "^0.1.0"
+          }
+        },
+        "p-locate": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+          "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^3.0.2"
+          }
+        },
+        "pkg-dir": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
+          "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==",
+          "dev": true,
+          "requires": {
+            "find-up": "^5.0.0"
+          }
+        },
+        "schema-utils": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
+          "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.6",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
+          }
+        }
+      }
+    },
+    "webpack-cli": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.4.0.tgz",
+      "integrity": "sha512-/Qh07CXfXEkMu5S8wEpjuaw2Zj/CC0hf/qbTDp6N8N7JjdGuaOjZ7kttz+zhuJO/J5m7alQEhNk9lsc4rC6xgQ==",
+      "dev": true,
+      "requires": {
+        "@discoveryjs/json-ext": "^0.5.0",
+        "@webpack-cli/configtest": "^1.0.0",
+        "@webpack-cli/info": "^1.2.1",
+        "@webpack-cli/serve": "^1.2.2",
+        "colorette": "^1.2.1",
+        "commander": "^6.2.0",
+        "enquirer": "^2.3.6",
+        "execa": "^5.0.0",
+        "fastest-levenshtein": "^1.0.12",
+        "import-local": "^3.0.2",
+        "interpret": "^2.2.0",
+        "rechoir": "^0.7.0",
+        "v8-compile-cache": "^2.2.0",
+        "webpack-merge": "^5.7.3"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+          "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+          "dev": true
+        }
+      }
+    },
+    "webpack-merge": {
+      "version": "5.7.3",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz",
+      "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==",
+      "dev": true,
+      "requires": {
+        "clone-deep": "^4.0.1",
+        "wildcard": "^2.0.0"
+      }
+    },
+    "webpack-sources": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz",
+      "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==",
+      "dev": true,
+      "requires": {
+        "source-list-map": "^2.0.1",
+        "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "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"
+      }
+    },
+    "wildcard": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+      "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
+      "dev": true
+    },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
+    },
+    "yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true
     }
   }
 }
diff --git a/package.json b/package.json
index 00564885fe7cc5e47495c8ce63f08a100c0f9161..27cdec7250807ea3093c0560c69dddb4bc0d64df 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,9 @@
   "description": "",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "build": "webpack --mode=production",
+    "watch": "webpack --mode=development --watch"    
   },
   "author": "Thomas Fritsch <thomas.fritsch@univ-lille.fr> (https://gitlab.univ-lille.fr/thomas.fritsch)",
   "homepage": "https://gitlab.univ-lille.fr/js",
@@ -12,6 +14,11 @@
   "devDependencies": {
     "@babel/cli": "^7.12.10",
     "@babel/core": "^7.12.10",
-    "@babel/preset-env": "^7.12.11"
+    "@babel/plugin-proposal-class-properties": "^7.12.1",
+    "@babel/preset-env": "^7.12.11",
+    "babel-loader": "^8.2.2",
+    "prettier": "^2.2.1",
+    "webpack": "^5.19.0",
+    "webpack-cli": "^4.4.0"
   }
 }
diff --git a/src/components/Component.js b/src/components/Component.js
new file mode 100644
index 0000000000000000000000000000000000000000..22154c8a971d3424b7e2e93a0501ac5baf37ec3e
--- /dev/null
+++ b/src/components/Component.js
@@ -0,0 +1,29 @@
+class Component {
+    tagName;
+    attribute
+    children;
+    constructor(tagName, attribute, children) {
+        this.tagName = tagName;
+        this.attribute = attribute;
+        this.children = children;
+    }
+    render() {
+        if (!this.children) {
+            return `<${this.tagName} ${this.renderAttribute()} />`;
+        } else {
+            return `<${this.tagName}>${this.children}</${this.tagName}>`;
+        }
+    }
+
+    renderAttribute() {
+        return `${this.attribute.name}="${this.attribute.value}"`;
+    }
+
+    renderChidren() {
+        return this.children.forEach(element => {
+
+        });
+    }
+}
+
+export default Component;
\ No newline at end of file
diff --git a/src/components/Img.js b/src/components/Img.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fb60ee9d45bcd3ada8cbd8ffceab497a29a20d2
--- /dev/null
+++ b/src/components/Img.js
@@ -0,0 +1,9 @@
+import Component from './Component.js';
+
+class Img extends Component {
+    constructor(sourceImg) {
+        super(`img`, { name: `src`, value: sourceImg });
+    }
+}
+
+export default Img;
\ No newline at end of file
diff --git a/src/data.js b/src/data.js
new file mode 100644
index 0000000000000000000000000000000000000000..cf9612b811dfd883b9986603c9b61735e6c70c05
--- /dev/null
+++ b/src/data.js
@@ -0,0 +1,23 @@
+const data = [
+    {
+        name: 'Regina',
+        base: 'tomate',
+        price_small: 6.5,
+        price_large: 9.95,
+        image: 'https://images.unsplash.com/photo-1532246420286-127bcd803104?fit=crop&w=500&h=300'
+    },
+    {
+        name: 'Napolitaine',
+        base: 'tomate',
+        price_small: 6.5,
+        price_large: 8.95,
+        image: 'https://images.unsplash.com/photo-1562707666-0ef112b353e0?&fit=crop&w=500&h=300'
+    },
+    {
+        name: 'Spicy',
+        base: 'crème',
+        sprice_small: 5.5,
+        price_large: 8,
+        image: 'https://images.unsplash.com/photo-1458642849426-cfb724f15ef7?fit=crop&w=500&h=300',
+    }
+];
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 9bc6f7a62365cece33475f77137ebf98fd0945c8..0f2cf68124f00abcd56eb89095b06346796f99e7 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,131 +1,8 @@
-// D. Manipulation des chaînes
+import Component from './components/Component.js';
+import Img from './components/Img.js';
 
-// const name = 'Regina';
-// const url = `images/${name.toLowerCase()}.jpg`;
-// const html = `
-// 	<article class="pizzaThumbnail">
-// 		<a href="${url}">
-// 			<img src="${url}" />
-// 			<section>${name}</section>
-// 		</a>
-// 	</article>
-// `;
-// document.querySelector('.pageContent').innerHTML = html;
+const title = new Component('h1', null, 'La carte');
+document.querySelector('.pageTitle').innerHTML = title.render();
 
-// // E.1. Manipulation des tableaux
-// let data = [ 'Regina', 'Napolitaine', 'Spicy' ];
-// html = '';
-// // E.1. boucle for :
-// for (let i = 0; i < data.length; i++) {
-// 	const nom = data[i],
-// 		url = `images/${nom.toLowerCase()}.jpg`;
-// 	html += `<article class="pizzaThumbnail">
-// 		<a href="${url}">
-// 			<img src="${url}" />
-// 			<section>${nom}</section>
-// 		</a>
-// 	</article>`;
-// }
-// document.querySelector('.pageContent').innerHTML = html;
-
-// E.1. Array.forEach :
-// html = '';
-// data.forEach( nom => {
-// 	const url = `images/${nom.toLowerCase()}.jpg`;
-// 	html += `<a href="${url}">
-// 		<img src="${url}" />
-// 		<h4>${nom}</h4>
-// 	</a>`;
-// })
-// document.querySelector('.pageContent').innerHTML = html;
-
-// // E.1. Array.map + Array.join :
-// html = data.map( nom => `<a href="images/${nom.toLowerCase()}.jpg">
-// <img src="images/${nom.toLowerCase()}.jpg" />
-// <h4>${nom}</h4>
-// </a>`).join('');
-// document.querySelector('.pageContent').innerHTML = html;
-
-// // E.1. Array.reduce :
-// html = data.reduce( (str, nom) => str+`<a href="images/${nom.toLowerCase()}.jpg">
-// 	<img src="images/${nom.toLowerCase()}.jpg" />
-// 	<h4>${nom}</h4>
-// </a>`,'');
-// document.querySelector('.pageContent').innerHTML = html;
-
-// E.2. Les objets littéraux
-const data = [
-	{
-		name: 'Regina',
-		base: 'tomate',
-		price_small: 6.5,
-		price_large: 9.95,
-		image: 'https://images.unsplash.com/photo-1532246420286-127bcd803104?fit=crop&w=500&h=300'
-	},
-	{
-		name: 'Napolitaine',
-		base: 'tomate',
-		price_small: 6.5,
-		price_large: 8.95,
-		image: 'https://images.unsplash.com/photo-1562707666-0ef112b353e0?&fit=crop&w=500&h=300'
-	},
-	{
-		name: 'Spicy',
-		base: 'crème',
-		price_small: 5.5,
-		price_large: 8,
-		image: 'https://images.unsplash.com/photo-1458642849426-cfb724f15ef7?fit=crop&w=500&h=300',
-	}
-];
-
-function render(pizzas) {
-	const html = pizzas.reduce( (str, {image, name, price_small, price_large}) => str +
-		`<article class="pizzaThumbnail">
-			<a href="${image}">
-				<img src="${image}" />
-				<section>
-					<h4>${name}</h4>
-					<ul>
-						<li>Prix petit format : ${price_small.toFixed(2)} €</li>
-						<li>Prix grand format : ${price_large.toFixed(2)} €</li>
-					</ul>
-				</section>
-			</a>
-		</article>`, '');
-	document.querySelector('.pageContent').innerHTML = html;
-}
-
-// G.1. Tri de tableaux
-function sortByName(a, b) {
-	if ( a.name < b.name ) {
-		return -1;
-	} else if ( a.name > b.name ) {
-		return 1;
-	}
-	return 0;
-}
-
-// tri par price_small croissant PUIS par price_large croissant
-function sortByPrice(a, b) {
-	if ( a.price_small !== b.price_small ) {
-		return a.price_small - b.price_small;
-	}
-	return a.price_large - b.price_large;
-}
-
-// // Attention : data.sort() modifie le tableau original
-render( data );
-// render( data.sort(sortByName) );
-// render( data.sort(sortByPrice) );
-
-// // G.2. Système de filtre
-// render( data.filter( pizza => pizza.base == 'tomate' ))
-// render( data.filter( pizza => pizza.price_small < 6 ))
-// // deux possibilités pour les pizzas avec deux fois la lettre "i"
-// render( data.filter( pizza => pizza.name.split('i').length == 3 ))
-// render( data.filter( pizza => pizza.name.match(/i/g).length == 2 ))
-
-// // G.3. Destructuring
-// render( data.filter( ({base}) => base == 'tomate' ))
-// render( data.filter( ({price_small}) => price_small < 6 ))
-// render( data.filter( ({name}) => name.match(/i/g).length === 2 ));
+const img = new Img('https://images.unsplash.com/photo-1532246420286-127bcd803104?fit=crop&w=500&h=300');
+document.querySelector('.pageContent').innerHTML = img.render();
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..4efb46b22ae7b58fb304ca04d00be384b72a8e9b
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,26 @@
+const path = require('path');
+
+module.exports = {
+    // Fichier d'entrée :
+    entry: './src/main.js',
+    // Fichier de sortie :
+    output: {
+        path: path.resolve(__dirname, './build'),
+        filename: 'main.bundle.js'
+    },
+    // compatibilité anciens navigateurs (si besoin du support de IE11 ou android 4.4)
+    target: ['web', 'es5'],
+    // connexion webpack <-> babel :
+    module: {
+        rules: [
+            {
+                test: /\.js$/, // tous les fichiers js ...
+                exclude: /node_modules/, // ... sauf le dossier node_modules ...
+                use: { // ... seront compilés par babel !
+                    loader: 'babel-loader',
+                }
+            }
+        ]
+    },
+    devtool: 'source-map'
+}
\ No newline at end of file