diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000000000000000000000000000000000000..e26d62e8181e0a81059f525408fc043ed3a1e061
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,15 @@
+{
+  "root": true,
+  "parserOptions": {
+    "ecmaVersion": 2021,
+    "sourceType": "module",
+    "parser": "babel-eslint"
+  },
+  "env": {
+    "browser": true,
+    "es6": true
+  },
+  "extends": [
+    "eslint:recommended"
+  ]
+}
diff --git a/README.md b/README.md
index e3565308cddbaf11c6258625354f68d8d488ef96..5f4bca8ccae8bf19c5449da6e18855394b4f99c2 100644
--- a/README.md
+++ b/README.md
@@ -3,15 +3,16 @@ This project has been created to help artists document their creative process wi
 
 ## Contributors
 The Tetras Libre team follows some code quality requirements. 
-Indeed, to ensure the respect of the standards PHP rules, we use a pre-commit hook as a safety net before sending any contribution.
+Indeed, to ensure the respect of the standards PHP and JavaScript rules, we use a pre-commit hook as a safety net before sending any contribution.
 The following quality tool scripts will be triggered before reaching commit message editor.
 - **PHPUnit** (functional and unit tests)
 - **PHP_CodeSniffer** (for PSR standards)
 - **PHPSTAN** (for static analysis)
+- **ESLint** (JavaScript linter)
 ***
 ### How to run the code quality scripts?
 First, you need to enter the memorekall-member docker container: `docker-compose exec memorekall-member bash`
-- To run the script independently of a commit: `composer {phpcs/phpstan/tests}`
+- To run the script independently of a commit: `composer {phpcs/phpstan/tests}` or `npm install` and `npm run lint` for ESLint
 - To fix PHP_CodeSniffer errors: `composer phpcbf`
 - To run them all: `composer ci`
 
diff --git a/package-lock.json b/package-lock.json
index 57058fa523b283c9665029328499bfc0afa82640..426042ce7a23f270f0178a4fd879489a28cde56f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,18 +10,22 @@
                 "postcss-loader": "^6.2.0"
             },
             "devDependencies": {
+                "@babel/core": "^7.16.0",
+                "@babel/eslint-parser": "^7.16.3",
                 "@popperjs/core": "^2.10.2",
                 "@symfony/stimulus-bridge": "^2.0.0",
                 "@symfony/webpack-encore": "^1.0.0",
                 "bootstrap": "^5.1.3",
                 "core-js": "^3.0.0",
+                "eslint": "^8.3.0",
                 "file-loader": "^6.2.0",
                 "jquery": "^3.6.0",
                 "node-sass": "^6.0.1",
                 "regenerator-runtime": "^0.13.2",
                 "sass-loader": "^12.3.0",
                 "stimulus": "^2.0.0",
-                "webpack-notifier": "^1.6.0"
+                "webpack-notifier": "^1.6.0",
+                "yorkie": "^2.0.0"
             }
         },
         "node_modules/@babel/code-frame": {
@@ -83,6 +87,42 @@
                 "semver": "bin/semver.js"
             }
         },
+        "node_modules/@babel/eslint-parser": {
+            "version": "7.16.3",
+            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.16.3.tgz",
+            "integrity": "sha512-iB4ElZT0jAt7PKVaeVulOECdGe6UnmA/O0P9jlF5g5GBOwDVbna8AXhHRu4s27xQf6OkveyA8iTDv1jHdDejgQ==",
+            "dev": true,
+            "dependencies": {
+                "eslint-scope": "^5.1.1",
+                "eslint-visitor-keys": "^2.1.0",
+                "semver": "^6.3.0"
+            },
+            "engines": {
+                "node": "^10.13.0 || ^12.13.0 || >=14.0.0"
+            },
+            "peerDependencies": {
+                "@babel/core": ">=7.11.0",
+                "eslint": "^7.5.0 || ^8.0.0"
+            }
+        },
+        "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+            "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/@babel/eslint-parser/node_modules/semver": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+            "dev": true,
+            "bin": {
+                "semver": "bin/semver.js"
+            }
+        },
         "node_modules/@babel/generator": {
             "version": "7.16.0",
             "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz",
@@ -1669,6 +1709,82 @@
                 "node": ">=10.0.0"
             }
         },
+        "node_modules/@eslint/eslintrc": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz",
+            "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==",
+            "dev": true,
+            "dependencies": {
+                "ajv": "^6.12.4",
+                "debug": "^4.3.2",
+                "espree": "^9.0.0",
+                "globals": "^13.9.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^4.1.0",
+                "minimatch": "^3.0.4",
+                "strip-json-comments": "^3.1.1"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/globals": {
+            "version": "13.12.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+            "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+            "dev": true,
+            "dependencies": {
+                "type-fest": "^0.20.2"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/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,
+            "engines": {
+                "node": ">= 4"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/type-fest": {
+            "version": "0.20.2",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@humanwhocodes/config-array": {
+            "version": "0.6.0",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
+            "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==",
+            "dev": true,
+            "dependencies": {
+                "@humanwhocodes/object-schema": "^1.2.0",
+                "debug": "^4.1.1",
+                "minimatch": "^3.0.4"
+            },
+            "engines": {
+                "node": ">=10.10.0"
+            }
+        },
+        "node_modules/@humanwhocodes/object-schema": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+            "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+            "dev": true
+        },
         "node_modules/@nodelib/fs.scandir": {
             "version": "2.1.5",
             "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2267,6 +2383,15 @@
                 "acorn": "^8"
             }
         },
+        "node_modules/acorn-jsx": {
+            "version": "5.3.2",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+            "dev": true,
+            "peerDependencies": {
+                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+            }
+        },
         "node_modules/adjust-sourcemap-loader": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz",
@@ -2370,6 +2495,15 @@
                 "node": ">=0.4.2"
             }
         },
+        "node_modules/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,
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/ansi-html-community": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
@@ -2435,6 +2569,12 @@
                 "readable-stream": "^2.0.6"
             }
         },
+        "node_modules/argparse": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+            "dev": true
+        },
         "node_modules/arity-n": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz",
@@ -3040,6 +3180,12 @@
                 "node": ">=6.0"
             }
         },
+        "node_modules/ci-info": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+            "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+            "dev": true
+        },
         "node_modules/clean-stack": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -3754,6 +3900,12 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/deep-is": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+            "dev": true
+        },
         "node_modules/default-gateway": {
             "version": "6.0.3",
             "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
@@ -3878,6 +4030,18 @@
                 "buffer-indexof": "^1.0.0"
             }
         },
+        "node_modules/doctrine": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "dependencies": {
+                "esutils": "^2.0.2"
+            },
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
         "node_modules/dom-converter": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -3999,6 +4163,18 @@
                 "node": ">=10.13.0"
             }
         },
+        "node_modules/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,
+            "dependencies": {
+                "ansi-colors": "^4.1.1"
+            },
+            "engines": {
+                "node": ">=8.6"
+            }
+        },
         "node_modules/entities": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
@@ -4109,6 +4285,61 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/eslint": {
+            "version": "8.3.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz",
+            "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==",
+            "dev": true,
+            "dependencies": {
+                "@eslint/eslintrc": "^1.0.4",
+                "@humanwhocodes/config-array": "^0.6.0",
+                "ajv": "^6.10.0",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.3.2",
+                "doctrine": "^3.0.0",
+                "enquirer": "^2.3.5",
+                "escape-string-regexp": "^4.0.0",
+                "eslint-scope": "^7.1.0",
+                "eslint-utils": "^3.0.0",
+                "eslint-visitor-keys": "^3.1.0",
+                "espree": "^9.1.0",
+                "esquery": "^1.4.0",
+                "esutils": "^2.0.2",
+                "fast-deep-equal": "^3.1.3",
+                "file-entry-cache": "^6.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob-parent": "^6.0.1",
+                "globals": "^13.6.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "js-yaml": "^4.1.0",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash.merge": "^4.6.2",
+                "minimatch": "^3.0.4",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.1",
+                "progress": "^2.0.0",
+                "regexpp": "^3.2.0",
+                "semver": "^7.2.1",
+                "strip-ansi": "^6.0.1",
+                "strip-json-comments": "^3.1.0",
+                "text-table": "^0.2.0",
+                "v8-compile-cache": "^2.0.3"
+            },
+            "bin": {
+                "eslint": "bin/eslint.js"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
         "node_modules/eslint-scope": {
             "version": "5.1.1",
             "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -4121,6 +4352,168 @@
                 "node": ">=8.0.0"
             }
         },
+        "node_modules/eslint-utils": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+            "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+            "dev": true,
+            "dependencies": {
+                "eslint-visitor-keys": "^2.0.0"
+            },
+            "engines": {
+                "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/mysticatea"
+            },
+            "peerDependencies": {
+                "eslint": ">=5"
+            }
+        },
+        "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+            "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/eslint-visitor-keys": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
+            "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
+            "dev": true,
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/eslint/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/eslint/node_modules/eslint-scope": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
+            "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
+            "dev": true,
+            "dependencies": {
+                "esrecurse": "^4.3.0",
+                "estraverse": "^5.2.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/eslint/node_modules/estraverse": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/eslint/node_modules/glob-parent": {
+            "version": "6.0.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+            "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+            "dev": true,
+            "dependencies": {
+                "is-glob": "^4.0.3"
+            },
+            "engines": {
+                "node": ">=10.13.0"
+            }
+        },
+        "node_modules/eslint/node_modules/globals": {
+            "version": "13.12.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+            "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+            "dev": true,
+            "dependencies": {
+                "type-fest": "^0.20.2"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/eslint/node_modules/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,
+            "engines": {
+                "node": ">= 4"
+            }
+        },
+        "node_modules/eslint/node_modules/strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "dev": true,
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/eslint/node_modules/type-fest": {
+            "version": "0.20.2",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/espree": {
+            "version": "9.1.0",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz",
+            "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==",
+            "dev": true,
+            "dependencies": {
+                "acorn": "^8.6.0",
+                "acorn-jsx": "^5.3.1",
+                "eslint-visitor-keys": "^3.1.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/esquery": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+            "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+            "dev": true,
+            "dependencies": {
+                "estraverse": "^5.1.0"
+            },
+            "engines": {
+                "node": ">=0.10"
+            }
+        },
+        "node_modules/esquery/node_modules/estraverse": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
         "node_modules/esrecurse": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
@@ -4366,6 +4759,18 @@
                 "node": ">=0.8.0"
             }
         },
+        "node_modules/file-entry-cache": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "dev": true,
+            "dependencies": {
+                "flat-cache": "^3.0.4"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
         "node_modules/file-loader": {
             "version": "6.2.0",
             "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
@@ -4461,6 +4866,40 @@
                 "node": ">=8"
             }
         },
+        "node_modules/flat-cache": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+            "dev": true,
+            "dependencies": {
+                "flatted": "^3.1.0",
+                "rimraf": "^3.0.2"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
+        "node_modules/flat-cache/node_modules/rimraf": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+            "dev": true,
+            "dependencies": {
+                "glob": "^7.1.3"
+            },
+            "bin": {
+                "rimraf": "bin.js"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/flatted": {
+            "version": "3.2.4",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
+            "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
+            "dev": true
+        },
         "node_modules/follow-redirects": {
             "version": "1.14.5",
             "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
@@ -4578,6 +5017,12 @@
             "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
             "dev": true
         },
+        "node_modules/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
+        },
         "node_modules/gauge": {
             "version": "2.7.4",
             "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -5134,6 +5579,15 @@
                 "node": ">=8"
             }
         },
+        "node_modules/imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.8.19"
+            }
+        },
         "node_modules/indent-string": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
@@ -5261,6 +5715,18 @@
                 "node": ">=8"
             }
         },
+        "node_modules/is-ci": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+            "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+            "dev": true,
+            "dependencies": {
+                "ci-info": "^1.5.0"
+            },
+            "bin": {
+                "is-ci": "bin.js"
+            }
+        },
         "node_modules/is-core-module": {
             "version": "2.8.0",
             "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
@@ -5518,6 +5984,18 @@
             "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
             "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
         },
+        "node_modules/js-yaml": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+            "dev": true,
+            "dependencies": {
+                "argparse": "^2.0.1"
+            },
+            "bin": {
+                "js-yaml": "bin/js-yaml.js"
+            }
+        },
         "node_modules/jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -5557,6 +6035,12 @@
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
             "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
         },
+        "node_modules/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
+        },
         "node_modules/json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -5610,6 +6094,19 @@
                 "node": ">= 8"
             }
         },
+        "node_modules/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,
+            "dependencies": {
+                "prelude-ls": "^1.2.1",
+                "type-check": "~0.4.0"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
         "node_modules/lilconfig": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz",
@@ -5676,6 +6173,12 @@
             "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
             "dev": true
         },
+        "node_modules/lodash.merge": {
+            "version": "4.6.2",
+            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+            "dev": true
+        },
         "node_modules/lodash.uniq": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -6011,6 +6514,12 @@
                 "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
             }
         },
+        "node_modules/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
+        },
         "node_modules/negotiator": {
             "version": "0.6.2",
             "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -6413,6 +6922,29 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/optionator": {
+            "version": "0.9.1",
+            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+            "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+            "dev": true,
+            "dependencies": {
+                "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"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/optionator/node_modules/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
+        },
         "node_modules/p-event": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz",
@@ -7312,6 +7844,15 @@
             "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
             "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
         },
+        "node_modules/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,
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
         "node_modules/pretty-error": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.4.tgz",
@@ -7328,6 +7869,15 @@
             "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
             "dev": true
         },
+        "node_modules/progress": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
         "node_modules/proxy-addr": {
             "version": "2.0.7",
             "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -7350,6 +7900,12 @@
                 "node": ">= 0.10"
             }
         },
+        "node_modules/pseudomap": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+            "dev": true
+        },
         "node_modules/psl": {
             "version": "1.8.0",
             "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -7637,6 +8193,18 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/regexpp": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+            "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/mysticatea"
+            }
+        },
         "node_modules/regexpu-core": {
             "version": "4.8.0",
             "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
@@ -8639,6 +9207,15 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/strip-eof": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+            "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/strip-final-newline": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
@@ -8660,6 +9237,18 @@
                 "node": ">=8"
             }
         },
+        "node_modules/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,
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/style-loader": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz",
@@ -8867,6 +9456,12 @@
                 "node": ">= 8"
             }
         },
+        "node_modules/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
+        },
         "node_modules/thunky": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
@@ -8991,6 +9586,18 @@
             "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
             "dev": true
         },
+        "node_modules/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,
+            "dependencies": {
+                "prelude-ls": "^1.2.1"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
         "node_modules/type-fest": {
             "version": "0.18.1",
             "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
@@ -9127,6 +9734,12 @@
                 "uuid": "bin/uuid"
             }
         },
+        "node_modules/v8-compile-cache": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+            "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+            "dev": true
+        },
         "node_modules/validate-npm-package-license": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -9654,6 +10267,15 @@
             "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
             "dev": true
         },
+        "node_modules/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,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/wrap-ansi": {
             "version": "5.1.0",
             "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -9959,6 +10581,157 @@
             "funding": {
                 "url": "https://github.com/sponsors/sindresorhus"
             }
+        },
+        "node_modules/yorkie": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz",
+            "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==",
+            "dev": true,
+            "hasInstallScript": true,
+            "dependencies": {
+                "execa": "^0.8.0",
+                "is-ci": "^1.0.10",
+                "normalize-path": "^1.0.0",
+                "strip-indent": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/cross-spawn": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+            "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+            "dev": true,
+            "dependencies": {
+                "lru-cache": "^4.0.1",
+                "shebang-command": "^1.2.0",
+                "which": "^1.2.9"
+            }
+        },
+        "node_modules/yorkie/node_modules/execa": {
+            "version": "0.8.0",
+            "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
+            "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
+            "dev": true,
+            "dependencies": {
+                "cross-spawn": "^5.0.1",
+                "get-stream": "^3.0.0",
+                "is-stream": "^1.1.0",
+                "npm-run-path": "^2.0.0",
+                "p-finally": "^1.0.0",
+                "signal-exit": "^3.0.0",
+                "strip-eof": "^1.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/get-stream": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+            "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/is-stream": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/yorkie/node_modules/lru-cache": {
+            "version": "4.1.5",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+            "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+            "dev": true,
+            "dependencies": {
+                "pseudomap": "^1.0.2",
+                "yallist": "^2.1.2"
+            }
+        },
+        "node_modules/yorkie/node_modules/normalize-path": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
+            "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/yorkie/node_modules/npm-run-path": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+            "dev": true,
+            "dependencies": {
+                "path-key": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/path-key": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/shebang-command": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+            "dev": true,
+            "dependencies": {
+                "shebang-regex": "^1.0.0"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/yorkie/node_modules/shebang-regex": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/yorkie/node_modules/strip-indent": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+            "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+            "dev": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/yorkie/node_modules/which": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+            "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+            "dev": true,
+            "dependencies": {
+                "isexe": "^2.0.0"
+            },
+            "bin": {
+                "which": "bin/which"
+            }
+        },
+        "node_modules/yorkie/node_modules/yallist": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+            "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+            "dev": true
         }
     },
     "dependencies": {
@@ -10007,6 +10780,31 @@
                 }
             }
         },
+        "@babel/eslint-parser": {
+            "version": "7.16.3",
+            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.16.3.tgz",
+            "integrity": "sha512-iB4ElZT0jAt7PKVaeVulOECdGe6UnmA/O0P9jlF5g5GBOwDVbna8AXhHRu4s27xQf6OkveyA8iTDv1jHdDejgQ==",
+            "dev": true,
+            "requires": {
+                "eslint-scope": "^5.1.1",
+                "eslint-visitor-keys": "^2.1.0",
+                "semver": "^6.3.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+                    "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+                    "dev": true
+                },
+                "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/generator": {
             "version": "7.16.0",
             "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz",
@@ -11099,20 +11897,77 @@
                 "globals": "^11.1.0"
             }
         },
-        "@babel/types": {
-            "version": "7.16.0",
-            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz",
-            "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==",
+        "@babel/types": {
+            "version": "7.16.0",
+            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz",
+            "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-validator-identifier": "^7.15.7",
+                "to-fast-properties": "^2.0.0"
+            }
+        },
+        "@discoveryjs/json-ext": {
+            "version": "0.5.5",
+            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz",
+            "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==",
+            "dev": true
+        },
+        "@eslint/eslintrc": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz",
+            "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==",
+            "dev": true,
+            "requires": {
+                "ajv": "^6.12.4",
+                "debug": "^4.3.2",
+                "espree": "^9.0.0",
+                "globals": "^13.9.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^4.1.0",
+                "minimatch": "^3.0.4",
+                "strip-json-comments": "^3.1.1"
+            },
+            "dependencies": {
+                "globals": {
+                    "version": "13.12.0",
+                    "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+                    "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+                    "dev": true,
+                    "requires": {
+                        "type-fest": "^0.20.2"
+                    }
+                },
+                "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
+                },
+                "type-fest": {
+                    "version": "0.20.2",
+                    "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+                    "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+                    "dev": true
+                }
+            }
+        },
+        "@humanwhocodes/config-array": {
+            "version": "0.6.0",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
+            "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==",
             "dev": true,
             "requires": {
-                "@babel/helper-validator-identifier": "^7.15.7",
-                "to-fast-properties": "^2.0.0"
+                "@humanwhocodes/object-schema": "^1.2.0",
+                "debug": "^4.1.1",
+                "minimatch": "^3.0.4"
             }
         },
-        "@discoveryjs/json-ext": {
-            "version": "0.5.5",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz",
-            "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==",
+        "@humanwhocodes/object-schema": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+            "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
             "dev": true
         },
         "@nodelib/fs.scandir": {
@@ -11638,6 +12493,13 @@
             "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
             "requires": {}
         },
+        "acorn-jsx": {
+            "version": "5.3.2",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+            "dev": true,
+            "requires": {}
+        },
         "adjust-sourcemap-loader": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz",
@@ -11716,6 +12578,12 @@
             "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
             "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-html-community": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
@@ -11763,6 +12631,12 @@
                 "readable-stream": "^2.0.6"
             }
         },
+        "argparse": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+            "dev": true
+        },
         "arity-n": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz",
@@ -12221,6 +13095,12 @@
             "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
             "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
         },
+        "ci-info": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+            "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+            "dev": true
+        },
         "clean-stack": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -12766,6 +13646,12 @@
                 "regexp.prototype.flags": "^1.2.0"
             }
         },
+        "deep-is": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+            "dev": true
+        },
         "default-gateway": {
             "version": "6.0.3",
             "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
@@ -12869,6 +13755,15 @@
                 "buffer-indexof": "^1.0.0"
             }
         },
+        "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"
+            }
+        },
         "dom-converter": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -12963,6 +13858,15 @@
                 "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"
+            }
+        },
         "entities": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
@@ -13052,6 +13956,115 @@
             "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
             "dev": true
         },
+        "eslint": {
+            "version": "8.3.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz",
+            "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==",
+            "dev": true,
+            "requires": {
+                "@eslint/eslintrc": "^1.0.4",
+                "@humanwhocodes/config-array": "^0.6.0",
+                "ajv": "^6.10.0",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.3.2",
+                "doctrine": "^3.0.0",
+                "enquirer": "^2.3.5",
+                "escape-string-regexp": "^4.0.0",
+                "eslint-scope": "^7.1.0",
+                "eslint-utils": "^3.0.0",
+                "eslint-visitor-keys": "^3.1.0",
+                "espree": "^9.1.0",
+                "esquery": "^1.4.0",
+                "esutils": "^2.0.2",
+                "fast-deep-equal": "^3.1.3",
+                "file-entry-cache": "^6.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob-parent": "^6.0.1",
+                "globals": "^13.6.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "js-yaml": "^4.1.0",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash.merge": "^4.6.2",
+                "minimatch": "^3.0.4",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.1",
+                "progress": "^2.0.0",
+                "regexpp": "^3.2.0",
+                "semver": "^7.2.1",
+                "strip-ansi": "^6.0.1",
+                "strip-json-comments": "^3.1.0",
+                "text-table": "^0.2.0",
+                "v8-compile-cache": "^2.0.3"
+            },
+            "dependencies": {
+                "ansi-regex": {
+                    "version": "5.0.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+                    "dev": true
+                },
+                "eslint-scope": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
+                    "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
+                    "dev": true,
+                    "requires": {
+                        "esrecurse": "^4.3.0",
+                        "estraverse": "^5.2.0"
+                    }
+                },
+                "estraverse": {
+                    "version": "5.3.0",
+                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+                    "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+                    "dev": true
+                },
+                "glob-parent": {
+                    "version": "6.0.2",
+                    "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+                    "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+                    "dev": true,
+                    "requires": {
+                        "is-glob": "^4.0.3"
+                    }
+                },
+                "globals": {
+                    "version": "13.12.0",
+                    "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+                    "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+                    "dev": true,
+                    "requires": {
+                        "type-fest": "^0.20.2"
+                    }
+                },
+                "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
+                },
+                "strip-ansi": {
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-regex": "^5.0.1"
+                    }
+                },
+                "type-fest": {
+                    "version": "0.20.2",
+                    "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+                    "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+                    "dev": true
+                }
+            }
+        },
         "eslint-scope": {
             "version": "5.1.1",
             "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -13061,6 +14074,57 @@
                 "estraverse": "^4.1.1"
             }
         },
+        "eslint-utils": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+            "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+            "dev": true,
+            "requires": {
+                "eslint-visitor-keys": "^2.0.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+                    "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-visitor-keys": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
+            "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
+            "dev": true
+        },
+        "espree": {
+            "version": "9.1.0",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz",
+            "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==",
+            "dev": true,
+            "requires": {
+                "acorn": "^8.6.0",
+                "acorn-jsx": "^5.3.1",
+                "eslint-visitor-keys": "^3.1.0"
+            }
+        },
+        "esquery": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+            "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^5.1.0"
+            },
+            "dependencies": {
+                "estraverse": {
+                    "version": "5.3.0",
+                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+                    "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+                    "dev": true
+                }
+            }
+        },
         "esrecurse": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
@@ -13273,6 +14337,15 @@
                 "websocket-driver": ">=0.5.1"
             }
         },
+        "file-entry-cache": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "dev": true,
+            "requires": {
+                "flat-cache": "^3.0.4"
+            }
+        },
         "file-loader": {
             "version": "6.2.0",
             "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
@@ -13345,6 +14418,33 @@
                 "path-exists": "^4.0.0"
             }
         },
+        "flat-cache": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+            "dev": true,
+            "requires": {
+                "flatted": "^3.1.0",
+                "rimraf": "^3.0.2"
+            },
+            "dependencies": {
+                "rimraf": {
+                    "version": "3.0.2",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+                    "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+                    "dev": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
+            }
+        },
+        "flatted": {
+            "version": "3.2.4",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
+            "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
+            "dev": true
+        },
         "follow-redirects": {
             "version": "1.14.5",
             "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
@@ -13419,6 +14519,12 @@
             "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
             "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
+        },
         "gauge": {
             "version": "2.7.4",
             "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -13844,6 +14950,12 @@
                 "resolve-cwd": "^3.0.0"
             }
         },
+        "imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "dev": true
+        },
         "indent-string": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
@@ -13940,6 +15052,15 @@
                 "binary-extensions": "^2.0.0"
             }
         },
+        "is-ci": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+            "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+            "dev": true,
+            "requires": {
+                "ci-info": "^1.5.0"
+            }
+        },
         "is-core-module": {
             "version": "2.8.0",
             "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
@@ -14128,6 +15249,15 @@
             "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
             "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
         },
+        "js-yaml": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+            "dev": true,
+            "requires": {
+                "argparse": "^2.0.1"
+            }
+        },
         "jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -14161,6 +15291,12 @@
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
             "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
         },
+        "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
+        },
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -14199,6 +15335,16 @@
             "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz",
             "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ=="
         },
+        "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"
+            }
+        },
         "lilconfig": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz",
@@ -14253,6 +15399,12 @@
             "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
             "dev": true
         },
+        "lodash.merge": {
+            "version": "4.6.2",
+            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+            "dev": true
+        },
         "lodash.uniq": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -14496,6 +15648,12 @@
             "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
             "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ=="
         },
+        "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
+        },
         "negotiator": {
             "version": "0.6.2",
             "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -14795,6 +15953,28 @@
                 "is-wsl": "^2.2.0"
             }
         },
+        "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"
+            },
+            "dependencies": {
+                "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
+                }
+            }
+        },
         "p-event": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz",
@@ -15397,6 +16577,12 @@
             "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
             "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
         },
+        "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
+        },
         "pretty-error": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.4.tgz",
@@ -15413,6 +16599,12 @@
             "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
             "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
+        },
         "proxy-addr": {
             "version": "2.0.7",
             "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -15431,6 +16623,12 @@
                 }
             }
         },
+        "pseudomap": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+            "dev": true
+        },
         "psl": {
             "version": "1.8.0",
             "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -15652,6 +16850,12 @@
                 "define-properties": "^1.1.3"
             }
         },
+        "regexpp": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+            "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+            "dev": true
+        },
         "regexpu-core": {
             "version": "4.8.0",
             "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
@@ -16483,6 +17687,12 @@
                 "ansi-regex": "^2.0.0"
             }
         },
+        "strip-eof": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+            "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+            "dev": true
+        },
         "strip-final-newline": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
@@ -16498,6 +17708,12 @@
                 "min-indent": "^1.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
+        },
         "style-loader": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz",
@@ -16628,6 +17844,12 @@
                 }
             }
         },
+        "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
+        },
         "thunky": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
@@ -16727,6 +17949,15 @@
             "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
             "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.18.1",
             "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
@@ -16833,6 +18064,12 @@
             "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
             "dev": true
         },
+        "v8-compile-cache": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+            "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+            "dev": true
+        },
         "validate-npm-package-license": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -17210,6 +18447,12 @@
             "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
             "dev": true
         },
+        "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
+        },
         "wrap-ansi": {
             "version": "5.1.0",
             "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -17442,6 +18685,125 @@
             "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
             "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
             "dev": true
+        },
+        "yorkie": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz",
+            "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==",
+            "dev": true,
+            "requires": {
+                "execa": "^0.8.0",
+                "is-ci": "^1.0.10",
+                "normalize-path": "^1.0.0",
+                "strip-indent": "^2.0.0"
+            },
+            "dependencies": {
+                "cross-spawn": {
+                    "version": "5.1.0",
+                    "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+                    "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+                    "dev": true,
+                    "requires": {
+                        "lru-cache": "^4.0.1",
+                        "shebang-command": "^1.2.0",
+                        "which": "^1.2.9"
+                    }
+                },
+                "execa": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
+                    "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
+                    "dev": true,
+                    "requires": {
+                        "cross-spawn": "^5.0.1",
+                        "get-stream": "^3.0.0",
+                        "is-stream": "^1.1.0",
+                        "npm-run-path": "^2.0.0",
+                        "p-finally": "^1.0.0",
+                        "signal-exit": "^3.0.0",
+                        "strip-eof": "^1.0.0"
+                    }
+                },
+                "get-stream": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                    "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+                    "dev": true
+                },
+                "is-stream": {
+                    "version": "1.1.0",
+                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+                    "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+                    "dev": true
+                },
+                "lru-cache": {
+                    "version": "4.1.5",
+                    "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+                    "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+                    "dev": true,
+                    "requires": {
+                        "pseudomap": "^1.0.2",
+                        "yallist": "^2.1.2"
+                    }
+                },
+                "normalize-path": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
+                    "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+                    "dev": true
+                },
+                "npm-run-path": {
+                    "version": "2.0.2",
+                    "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+                    "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+                    "dev": true,
+                    "requires": {
+                        "path-key": "^2.0.0"
+                    }
+                },
+                "path-key": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+                    "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+                    "dev": true
+                },
+                "shebang-command": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+                    "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+                    "dev": true,
+                    "requires": {
+                        "shebang-regex": "^1.0.0"
+                    }
+                },
+                "shebang-regex": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+                    "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+                    "dev": true
+                },
+                "strip-indent": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+                    "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+                    "dev": true
+                },
+                "which": {
+                    "version": "1.3.1",
+                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+                    "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+                    "dev": true,
+                    "requires": {
+                        "isexe": "^2.0.0"
+                    }
+                },
+                "yallist": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+                    "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+                    "dev": true
+                }
+            }
         }
     }
 }
diff --git a/package.json b/package.json
index 890bdd2365d95d35a23eef141d721bcf37ea58c0..3f1db48df8ffa6cd102d293c62f2c365ab3b286a 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,21 @@
 {
     "devDependencies": {
+        "@babel/core": "^7.16.0",
+        "@babel/eslint-parser": "^7.16.3",
         "@popperjs/core": "^2.10.2",
         "@symfony/stimulus-bridge": "^2.0.0",
         "@symfony/webpack-encore": "^1.0.0",
         "bootstrap": "^5.1.3",
         "core-js": "^3.0.0",
+        "eslint": "^8.3.0",
         "file-loader": "^6.2.0",
         "jquery": "^3.6.0",
         "node-sass": "^6.0.1",
         "regenerator-runtime": "^0.13.2",
         "sass-loader": "^12.3.0",
         "stimulus": "^2.0.0",
-        "webpack-notifier": "^1.6.0"
+        "webpack-notifier": "^1.6.0",
+        "yorkie": "^2.0.0"
     },
     "license": "UNLICENSED",
     "private": true,
@@ -19,7 +23,8 @@
         "dev-server": "encore dev-server",
         "dev": "encore dev",
         "watch": "encore dev --watch",
-        "build": "encore production --progress"
+        "build": "encore production --progress",
+        "lint": "eslint --max-warnings=0 ."
     },
     "dependencies": {
         "autoprefixer": "^10.4.0",
diff --git a/tools/git-hooks/pre-commit b/tools/git-hooks/pre-commit
index 5e1207c23c0c3e61a26387211a15678b940465d8..7b20d827b517e1eb532def84fd76d46c03711271 100755
--- a/tools/git-hooks/pre-commit
+++ b/tools/git-hooks/pre-commit
@@ -32,3 +32,13 @@ else
 	echo -e "\n ${GREENBOLD} Your code passed static analysis successfully! \n
 	\n Committing your changes now... \n ${NORMAL}"
 fi
+
+echo -e "\n ${BOLD} Starting ESLint... \n ${NORMAL}"
+npm run lint
+if [ $? != 0 ]; then
+	echo -e "\n ${REDBOLD} ESLint verification failed \n ${NORMAL}"
+	exit 1;
+else
+	echo -e "\n ${GREENBOLD} Your code passed JS linter successfully! \n
+	\n Committing your changes now... \n ${NORMAL}"
+fi
\ No newline at end of file