Repository: phoenixframework/phoenix
Pull request #5131 (2022-11-27 03:45:43)

Add password inputs to password reset edit form
the reset_password edit form did not have password or password_confirmation inputs.

joseph-lozano: Happy to add assertions that these inputs exist, but I also am not sure they are necessary.

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6c1657dd0..720f167a6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,7 +21,7 @@ jobs:
             lint: true
             installer: true
 
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-20.04
 
     steps:
     - name: Checkout
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cab323363..7343097f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
 # Changelog for v1.7
 
+See the [upgrade guide](https://gist.github.com/chrismccord/00a6ea2a96bc57df0cce526bd20af8a7) to upgrade from Phoenix 1.6.x.
+
 Phoenix v1.7 requires Elixir v1.11+.
 
 ## Introduction of Verified Routes
@@ -53,6 +55,17 @@ See the [upgrade guide](https://gist.github.com/chrismccord/2ab350f154235ad4a4d0
 
 Phoenix v1.6 requires Elixir v1.9+.
 
+## 1.6.15 (2022-10-26)
+
+### Enhancements
+  * Support for Phoenix.View 2.0
+
+### JavaScript Client Bug Fixes
+  * Fix heartbeat reconnect
+
+## 1.6.14 (2022-10-10)
+  * Fix security vulnerability in wildcard `check_origin` configurations
+
 ## 1.6.13 (2022-09-29)
 
 ### Enhancements
diff --git a/assets/package-lock.json b/assets/package-lock.json
index a4e1eebd5..19a2a833f 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -19,7 +19,7 @@
         "growl": "~> 1.10.0",
         "jsdom": "9.8.3",
         "jsdom-global": "2.1.0",
-        "mocha": "^6.2.2",
+        "mocha": "^10.1.0",
         "mock-socket": "^9.0.0",
         "sinon": "^9.0.1"
       }
@@ -1475,18 +1475,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@eslint/eslintrc/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/@jridgewell/gen-mapping": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
@@ -1798,21 +1786,21 @@
       }
     },
     "node_modules/ansi-colors": {
-      "version": "3.2.3",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
-      "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+      "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-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+      "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": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/ansi-styles": {
@@ -2215,12 +2203,15 @@
       }
     },
     "node_modules/camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
       "dev": true,
       "engines": {
-        "node": ">=6"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/caniuse-lite": {
@@ -2520,50 +2511,6 @@
         "wrap-ansi": "^7.0.0"
       }
     },
-    "node_modules/cliui/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/cliui/node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cliui/node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cliui/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/clone-deep": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@@ -2775,9 +2722,9 @@
       "optional": true
     },
     "node_modules/debug": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
-      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -2792,12 +2739,15 @@
       }
     },
     "node_modules/decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+      "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
       "dev": true,
       "engines": {
-        "node": ">=0.10.0"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/decode-named-character-reference": {
@@ -2814,9 +2764,9 @@
       }
     },
     "node_modules/decode-uri-component": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+      "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
       "dev": true,
       "optional": true,
       "engines": {
@@ -3050,9 +3000,9 @@
       }
     },
     "node_modules/documentation/node_modules/minimatch": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
-      "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz",
+      "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
@@ -3125,15 +3075,6 @@
         "node": ">=8.6"
       }
     },
-    "node_modules/enquirer/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/error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -3143,53 +3084,6 @@
         "is-arrayish": "^0.2.1"
       }
     },
-    "node_modules/es-abstract": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.2.tgz",
-      "integrity": "sha512-byRiNIQXE6HWNySaU6JohoNXzYgbBjztwFnBLUTiJmWXjaU9bSq3urQLUlNLQ292tc+gc07zYZXNZjaOoAX3sw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "es-to-primitive": "^1.2.1",
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.2",
-        "is-callable": "^1.2.3",
-        "is-negative-zero": "^2.0.1",
-        "is-regex": "^1.1.3",
-        "is-string": "^1.0.6",
-        "object-inspect": "^1.10.3",
-        "object-keys": "^1.1.1",
-        "object.assign": "^4.1.2",
-        "string.prototype.trimend": "^1.0.4",
-        "string.prototype.trimstart": "^1.0.4",
-        "unbox-primitive": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/es-to-primitive": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-      "dev": true,
-      "dependencies": {
-        "is-callable": "^1.1.4",
-        "is-date-object": "^1.0.1",
-        "is-symbol": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -3385,15 +3279,6 @@
         "@babel/highlight": "^7.10.4"
       }
     },
-    "node_modules/eslint/node_modules/ansi-regex": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/eslint/node_modules/ansi-styles": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -3545,30 +3430,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/eslint/node_modules/strip-ansi": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/eslint/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/eslint/node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3975,13 +3836,10 @@
       }
     },
     "node_modules/flat": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz",
-      "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
       "dev": true,
-      "dependencies": {
-        "is-buffer": "~2.0.3"
-      },
       "bin": {
         "flat": "cli.js"
       }
@@ -3999,29 +3857,6 @@
         "node": "^10.12.0 || >=12.0.0"
       }
     },
-    "node_modules/flat/node_modules/is-buffer": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
-      "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/flatted": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
@@ -4189,9 +4024,9 @@
       "dev": true
     },
     "node_modules/glob": {
-      "version": "7.1.7",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
       "dev": true,
       "dependencies": {
         "fs.realpath": "^1.0.0",
@@ -4298,15 +4133,6 @@
         "node": ">= 0.4.0"
       }
     },
-    "node_modules/has-bigints": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
-      "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -4615,15 +4441,6 @@
       "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
       "dev": true
     },
-    "node_modules/is-bigint": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
-      "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-binary-path": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
@@ -4637,21 +4454,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-boolean-object": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
-      "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -4659,18 +4461,6 @@
       "dev": true,
       "optional": true
     },
-    "node_modules/is-callable": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
-      "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-core-module": {
       "version": "2.10.0",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
@@ -4706,18 +4496,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-date-object": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
-      "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-descriptor": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
@@ -4763,12 +4541,12 @@
       }
     },
     "node_modules/is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
       "dev": true,
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/is-glob": {
@@ -4783,18 +4561,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-negative-zero": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
-      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -4808,18 +4574,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-number-object": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
-      "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-plain-obj": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
@@ -4844,22 +4598,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-regex": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
-      "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "has-symbols": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-relative": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
@@ -4881,33 +4619,6 @@
         "protocols": "^2.0.1"
       }
     },
-    "node_modules/is-string": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
-      "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-symbol": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-      "dev": true,
-      "dependencies": {
-        "has-symbols": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -4926,6 +4637,18 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -5198,15 +4921,89 @@
       "dev": true
     },
     "node_modules/log-symbols": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
       "dev": true,
       "dependencies": {
-        "chalk": "^2.0.1"
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-symbols/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/log-symbols/node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/log-symbols/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/log-symbols/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/log-symbols/node_modules/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,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/log-symbols/node_modules/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,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/longest-streak": {
@@ -6250,9 +6047,9 @@
       }
     },
     "node_modules/minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^1.1.7"
@@ -6261,12 +6058,6 @@
         "node": "*"
       }
     },
-    "node_modules/minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-      "dev": true
-    },
     "node_modules/mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -6294,227 +6085,246 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/mkdirp": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
-      "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
-      "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.5"
-      },
-      "bin": {
-        "mkdirp": "bin/cmd.js"
-      }
-    },
     "node_modules/mocha": {
-      "version": "6.2.3",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
-      "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==",
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz",
+      "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==",
       "dev": true,
       "dependencies": {
-        "ansi-colors": "3.2.3",
+        "ansi-colors": "4.1.1",
         "browser-stdout": "1.3.1",
-        "debug": "3.2.6",
-        "diff": "3.5.0",
-        "escape-string-regexp": "1.0.5",
-        "find-up": "3.0.0",
-        "glob": "7.1.3",
-        "growl": "1.10.5",
+        "chokidar": "3.5.3",
+        "debug": "4.3.4",
+        "diff": "5.0.0",
+        "escape-string-regexp": "4.0.0",
+        "find-up": "5.0.0",
+        "glob": "7.2.0",
         "he": "1.2.0",
-        "js-yaml": "3.13.1",
-        "log-symbols": "2.2.0",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.4",
-        "ms": "2.1.1",
-        "node-environment-flags": "1.0.5",
-        "object.assign": "4.1.0",
-        "strip-json-comments": "2.0.1",
-        "supports-color": "6.0.0",
-        "which": "1.3.1",
-        "wide-align": "1.1.3",
-        "yargs": "13.3.2",
-        "yargs-parser": "13.1.2",
-        "yargs-unparser": "1.6.0"
+        "js-yaml": "4.1.0",
+        "log-symbols": "4.1.0",
+        "minimatch": "5.0.1",
+        "ms": "2.1.3",
+        "nanoid": "3.3.3",
+        "serialize-javascript": "6.0.0",
+        "strip-json-comments": "3.1.1",
+        "supports-color": "8.1.1",
+        "workerpool": "6.2.1",
+        "yargs": "16.2.0",
+        "yargs-parser": "20.2.4",
+        "yargs-unparser": "2.0.0"
       },
       "bin": {
         "_mocha": "bin/_mocha",
-        "mocha": "bin/mocha"
+        "mocha": "bin/mocha.js"
       },
       "engines": {
-        "node": ">= 6.0.0"
-      }
-    },
-    "node_modules/mocha/node_modules/ansi-regex": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
+        "node": ">= 14.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/mochajs"
       }
     },
-    "node_modules/mocha/node_modules/cliui": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^3.1.0",
-        "strip-ansi": "^5.2.0",
-        "wrap-ansi": "^5.1.0"
-      }
+    "node_modules/mocha/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/mocha/node_modules/debug": {
-      "version": "3.2.6",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-      "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+    "node_modules/mocha/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
       "dev": true,
       "dependencies": {
-        "ms": "^2.1.1"
+        "balanced-match": "^1.0.0"
       }
     },
     "node_modules/mocha/node_modules/diff": {
-      "version": "3.5.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
-      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
       "dev": true,
       "engines": {
         "node": ">=0.3.1"
       }
     },
-    "node_modules/mocha/node_modules/emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-      "dev": true
+    "node_modules/mocha/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
     },
-    "node_modules/mocha/node_modules/glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+    "node_modules/mocha/node_modules/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,
       "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.0.4",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
       },
       "engines": {
-        "node": "*"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mocha/node_modules/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,
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/mocha/node_modules/js-yaml": {
-      "version": "3.13.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "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": "^1.0.7",
-        "esprima": "^4.0.0"
+        "argparse": "^2.0.1"
       },
       "bin": {
         "js-yaml": "bin/js-yaml.js"
       }
     },
-    "node_modules/mocha/node_modules/ms": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-      "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-      "dev": true
+    "node_modules/mocha/node_modules/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,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
     },
-    "node_modules/mocha/node_modules/object.assign": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
-      "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+    "node_modules/mocha/node_modules/minimatch": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
       "dev": true,
       "dependencies": {
-        "define-properties": "^1.1.2",
-        "function-bind": "^1.1.1",
-        "has-symbols": "^1.0.0",
-        "object-keys": "^1.0.11"
+        "brace-expansion": "^2.0.1"
       },
       "engines": {
-        "node": ">= 0.4"
+        "node": ">=10"
       }
     },
-    "node_modules/mocha/node_modules/require-main-filename": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+    "node_modules/mocha/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
       "dev": true
     },
-    "node_modules/mocha/node_modules/string-width": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+    "node_modules/mocha/node_modules/nanoid": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
       "dev": true,
-      "dependencies": {
-        "emoji-regex": "^7.0.1",
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^5.1.0"
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
       },
       "engines": {
-        "node": ">=6"
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
       }
     },
-    "node_modules/mocha/node_modules/strip-ansi": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+    "node_modules/mocha/node_modules/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,
       "dependencies": {
-        "ansi-regex": "^4.1.0"
+        "yocto-queue": "^0.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/mocha/node_modules/supports-color": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
-      "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
+    "node_modules/mocha/node_modules/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,
       "dependencies": {
-        "has-flag": "^3.0.0"
+        "p-limit": "^3.0.2"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/mocha/node_modules/wrap-ansi": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+    "node_modules/mocha/node_modules/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,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/mocha/node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
       "dev": true,
       "dependencies": {
-        "ansi-styles": "^3.2.0",
-        "string-width": "^3.0.0",
-        "strip-ansi": "^5.0.0"
+        "has-flag": "^4.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
       }
     },
     "node_modules/mocha/node_modules/yargs": {
-      "version": "13.3.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
       "dev": true,
       "dependencies": {
-        "cliui": "^5.0.0",
-        "find-up": "^3.0.0",
-        "get-caller-file": "^2.0.1",
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
         "require-directory": "^2.1.1",
-        "require-main-filename": "^2.0.0",
-        "set-blocking": "^2.0.0",
-        "string-width": "^3.0.0",
-        "which-module": "^2.0.0",
-        "y18n": "^4.0.0",
-        "yargs-parser": "^13.1.2"
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mocha/node_modules/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,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/mock-socket": {
@@ -6636,25 +6446,6 @@
         "path-to-regexp": "^1.7.0"
       }
     },
-    "node_modules/node-environment-flags": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
-      "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
-      "dev": true,
-      "dependencies": {
-        "object.getownpropertydescriptors": "^2.0.3",
-        "semver": "^5.7.0"
-      }
-    },
-    "node_modules/node-environment-flags/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
     "node_modules/node-modules-regexp": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
@@ -6815,15 +6606,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/object-inspect": {
-      "version": "1.10.3",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
-      "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/object-keys": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -6864,23 +6646,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/object.getownpropertydescriptors": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz",
-      "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.18.0-next.2"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/object.pick": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@@ -7250,9 +7015,9 @@
       }
     },
     "node_modules/qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+      "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
       "dev": true,
       "engines": {
         "node": ">=0.6"
@@ -7270,6 +7035,15 @@
       "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==",
       "dev": true
     },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
     "node_modules/read-pkg": {
       "version": "7.1.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz",
@@ -7851,11 +7625,14 @@
         "semver": "bin/semver.js"
       }
     },
-    "node_modules/set-blocking": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
-      "dev": true
+    "node_modules/serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "dev": true,
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
     },
     "node_modules/set-value": {
       "version": "2.0.1",
@@ -8022,15 +7799,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/snapdragon": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -8441,42 +8209,17 @@
       }
     },
     "node_modules/string-width": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
       "dev": true,
       "dependencies": {
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^4.0.0"
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
       },
       "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/string.prototype.trimend": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-      "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/string.prototype.trimstart": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-      "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
+        "node": ">=8"
       }
     },
     "node_modules/stringify-entities": {
@@ -8494,24 +8237,27 @@
       }
     },
     "node_modules/strip-ansi": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "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": "^3.0.0"
+        "ansi-regex": "^5.0.1"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/strip-json-comments": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "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": ">=0.10.0"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/supports-color": {
@@ -8577,56 +8323,12 @@
         "url": "https://github.com/sponsors/epoberezkin"
       }
     },
-    "node_modules/table/node_modules/ansi-regex": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/table/node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/table/node_modules/json-schema-traverse": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
       "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
       "dev": true
     },
-    "node_modules/table/node_modules/string-width": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-      "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/table/node_modules/strip-ansi": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -8799,21 +8501,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/unbox-primitive": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
-      "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
-      "dev": true,
-      "dependencies": {
-        "function-bind": "^1.1.1",
-        "has-bigints": "^1.0.1",
-        "has-symbols": "^1.0.2",
-        "which-boxed-primitive": "^1.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/unc-path-regex": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
@@ -9394,49 +9081,6 @@
         "webidl-conversions": "^3.0.0"
       }
     },
-    "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/which-boxed-primitive": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-      "dev": true,
-      "dependencies": {
-        "is-bigint": "^1.0.1",
-        "is-boolean-object": "^1.1.0",
-        "is-number-object": "^1.0.4",
-        "is-string": "^1.0.5",
-        "is-symbol": "^1.0.3"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/which-module": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
-      "dev": true
-    },
-    "node_modules/wide-align": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
-      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^1.0.2 || 2"
-      }
-    },
     "node_modules/word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -9446,6 +9090,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/workerpool": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+      "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+      "dev": true
+    },
     "node_modules/wrap-ansi": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -9463,15 +9113,6 @@
         "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
       }
     },
-    "node_modules/wrap-ansi/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/wrap-ansi/node_modules/ansi-styles": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -9505,41 +9146,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/wrap-ansi/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/wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -9550,205 +9156,74 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz",
       "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=",
-      "dev": true
-    },
-    "node_modules/y18n": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
-      "dev": true
-    },
-    "node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/yargs": {
-      "version": "17.5.1",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
-      "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
-      "dev": true,
-      "dependencies": {
-        "cliui": "^7.0.2",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.3",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^21.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yargs-parser": {
-      "version": "13.1.2",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
-      "dev": true,
-      "dependencies": {
-        "camelcase": "^5.0.0",
-        "decamelize": "^1.2.0"
-      }
-    },
-    "node_modules/yargs-unparser": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
-      "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
-      "dev": true,
-      "dependencies": {
-        "flat": "^4.1.0",
-        "lodash": "^4.17.15",
-        "yargs": "^13.3.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/ansi-regex": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/cliui": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^3.1.0",
-        "strip-ansi": "^5.2.0",
-        "wrap-ansi": "^5.1.0"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-      "dev": true
-    },
-    "node_modules/yargs-unparser/node_modules/require-main-filename": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
-      "dev": true
-    },
-    "node_modules/yargs-unparser/node_modules/string-width": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^7.0.1",
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^5.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
+      "dev": true
     },
-    "node_modules/yargs-unparser/node_modules/strip-ansi": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
       "dev": true,
-      "dependencies": {
-        "ansi-regex": "^4.1.0"
-      },
       "engines": {
-        "node": ">=6"
+        "node": ">=10"
       }
     },
-    "node_modules/yargs-unparser/node_modules/wrap-ansi": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.0",
-        "string-width": "^3.0.0",
-        "strip-ansi": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
+    "node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
     },
-    "node_modules/yargs-unparser/node_modules/yargs": {
-      "version": "13.3.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+    "node_modules/yargs": {
+      "version": "17.5.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
+      "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
       "dev": true,
       "dependencies": {
-        "cliui": "^5.0.0",
-        "find-up": "^3.0.0",
-        "get-caller-file": "^2.0.1",
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
         "require-directory": "^2.1.1",
-        "require-main-filename": "^2.0.0",
-        "set-blocking": "^2.0.0",
-        "string-width": "^3.0.0",
-        "which-module": "^2.0.0",
-        "y18n": "^4.0.0",
-        "yargs-parser": "^13.1.2"
-      }
-    },
-    "node_modules/yargs/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,
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.0.0"
+      },
       "engines": {
-        "node": ">=8"
+        "node": ">=12"
       }
     },
-    "node_modules/yargs/node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+    "node_modules/yargs-parser": {
+      "version": "20.2.4",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+      "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
       "dev": true,
       "engines": {
-        "node": ">=8"
+        "node": ">=10"
       }
     },
-    "node_modules/yargs/node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+    "node_modules/yargs-unparser": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+      "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
       "dev": true,
       "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
+        "camelcase": "^6.0.0",
+        "decamelize": "^4.0.0",
+        "flat": "^5.0.2",
+        "is-plain-obj": "^2.1.0"
       },
       "engines": {
-        "node": ">=8"
+        "node": ">=10"
       }
     },
-    "node_modules/yargs/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==",
+    "node_modules/yargs-unparser/node_modules/is-plain-obj": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+      "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
       "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
       "engines": {
         "node": ">=8"
       }
     },
-    "node_modules/yargs/node_modules/y18n": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
     "node_modules/yargs/node_modules/yargs-parser": {
       "version": "21.1.1",
       "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
@@ -10928,12 +10403,6 @@
           "requires": {
             "type-fest": "^0.8.1"
           }
-        },
-        "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
         }
       }
     },
@@ -11227,15 +10696,15 @@
       }
     },
     "ansi-colors": {
-      "version": "3.2.3",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
-      "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
       "dev": true
     },
     "ansi-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
       "dev": true
     },
     "ansi-styles": {
@@ -11556,9 +11025,9 @@
       "dev": true
     },
     "camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
       "dev": true
     },
     "caniuse-lite": {
@@ -11777,40 +11246,6 @@
         "string-width": "^4.2.0",
         "strip-ansi": "^6.0.0",
         "wrap-ansi": "^7.0.0"
-      },
-      "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
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.3",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.1"
-          }
-        },
-        "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"
-          }
-        }
       }
     },
     "clone-deep": {
@@ -11992,18 +11427,18 @@
       "optional": true
     },
     "debug": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
-      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
       "requires": {
         "ms": "2.1.2"
       }
     },
     "decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+      "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
       "dev": true
     },
     "decode-named-character-reference": {
@@ -12016,9 +11451,9 @@
       }
     },
     "decode-uri-component": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+      "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
       "dev": true,
       "optional": true
     },
@@ -12198,9 +11633,9 @@
           }
         },
         "minimatch": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
-          "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz",
+          "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==",
           "dev": true,
           "requires": {
             "brace-expansion": "^2.0.1"
@@ -12255,14 +11690,6 @@
       "dev": true,
       "requires": {
         "ansi-colors": "^4.1.1"
-      },
-      "dependencies": {
-        "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
-        }
       }
     },
     "error-ex": {
@@ -12274,41 +11701,6 @@
         "is-arrayish": "^0.2.1"
       }
     },
-    "es-abstract": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.2.tgz",
-      "integrity": "sha512-byRiNIQXE6HWNySaU6JohoNXzYgbBjztwFnBLUTiJmWXjaU9bSq3urQLUlNLQ292tc+gc07zYZXNZjaOoAX3sw==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.2",
-        "es-to-primitive": "^1.2.1",
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.2",
-        "is-callable": "^1.2.3",
-        "is-negative-zero": "^2.0.1",
-        "is-regex": "^1.1.3",
-        "is-string": "^1.0.6",
-        "object-inspect": "^1.10.3",
-        "object-keys": "^1.1.1",
-        "object.assign": "^4.1.2",
-        "string.prototype.trimend": "^1.0.4",
-        "string.prototype.trimstart": "^1.0.4",
-        "unbox-primitive": "^1.0.1"
-      }
-    },
-    "es-to-primitive": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-      "dev": true,
-      "requires": {
-        "is-callable": "^1.1.4",
-        "is-date-object": "^1.0.1",
-        "is-symbol": "^1.0.2"
-      }
-    },
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -12399,12 +11791,6 @@
             "@babel/highlight": "^7.10.4"
           }
         },
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
         "ansi-styles": {
           "version": "4.3.0",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -12508,21 +11894,6 @@
             "lru-cache": "^6.0.0"
           }
         },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
-        },
-        "strip-json-comments": {
-          "version": "3.1.1",
-          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-          "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-          "dev": true
-        },
         "supports-color": {
           "version": "7.2.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -12903,21 +12274,10 @@
       }
     },
     "flat": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz",
-      "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==",
-      "dev": true,
-      "requires": {
-        "is-buffer": "~2.0.3"
-      },
-      "dependencies": {
-        "is-buffer": {
-          "version": "2.0.5",
-          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
-          "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
-          "dev": true
-        }
-      }
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+      "dev": true
     },
     "flat-cache": {
       "version": "3.0.4",
@@ -13065,9 +12425,9 @@
       "dev": true
     },
     "glob": {
-      "version": "7.1.7",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
@@ -13151,12 +12511,6 @@
         "function-bind": "^1.1.1"
       }
     },
-    "has-bigints": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
-      "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
-      "dev": true
-    },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -13390,12 +12744,6 @@
       "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
       "dev": true
     },
-    "is-bigint": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
-      "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
-      "dev": true
-    },
     "is-binary-path": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
@@ -13406,15 +12754,6 @@
         "binary-extensions": "^1.0.0"
       }
     },
-    "is-boolean-object": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
-      "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.2"
-      }
-    },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -13422,12 +12761,6 @@
       "dev": true,
       "optional": true
     },
-    "is-callable": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
-      "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
-      "dev": true
-    },
     "is-core-module": {
       "version": "2.10.0",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
@@ -13456,12 +12789,6 @@
         }
       }
     },
-    "is-date-object": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
-      "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
-      "dev": true
-    },
     "is-descriptor": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
@@ -13497,9 +12824,9 @@
       "dev": true
     },
     "is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
       "dev": true
     },
     "is-glob": {
@@ -13511,12 +12838,6 @@
         "is-extglob": "^2.1.1"
       }
     },
-    "is-negative-zero": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
-      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
-      "dev": true
-    },
     "is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -13527,12 +12848,6 @@
         "kind-of": "^3.0.2"
       }
     },
-    "is-number-object": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
-      "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
-      "dev": true
-    },
     "is-plain-obj": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
@@ -13548,16 +12863,6 @@
         "isobject": "^3.0.1"
       }
     },
-    "is-regex": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
-      "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.2",
-        "has-symbols": "^1.0.2"
-      }
-    },
     "is-relative": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
@@ -13576,21 +12881,6 @@
         "protocols": "^2.0.1"
       }
     },
-    "is-string": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
-      "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
-      "dev": true
-    },
-    "is-symbol": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-      "dev": true,
-      "requires": {
-        "has-symbols": "^1.0.2"
-      }
-    },
     "is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -13606,6 +12896,12 @@
         "unc-path-regex": "^0.1.2"
       }
     },
+    "is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true
+    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -13842,12 +13138,64 @@
       "dev": true
     },
     "log-symbols": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
       "dev": true,
       "requires": {
-        "chalk": "^2.0.1"
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "longest-streak": {
@@ -14546,20 +13894,14 @@
       }
     },
     "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
       "dev": true,
       "requires": {
         "brace-expansion": "^1.1.7"
       }
     },
-    "minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-      "dev": true
-    },
     "mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -14583,189 +13925,170 @@
         }
       }
     },
-    "mkdirp": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
-      "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
-      "dev": true,
-      "requires": {
-        "minimist": "^1.2.5"
-      }
-    },
     "mocha": {
-      "version": "6.2.3",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
-      "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==",
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz",
+      "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==",
       "dev": true,
       "requires": {
-        "ansi-colors": "3.2.3",
+        "ansi-colors": "4.1.1",
         "browser-stdout": "1.3.1",
-        "debug": "3.2.6",
-        "diff": "3.5.0",
-        "escape-string-regexp": "1.0.5",
-        "find-up": "3.0.0",
-        "glob": "7.1.3",
-        "growl": "1.10.5",
+        "chokidar": "3.5.3",
+        "debug": "4.3.4",
+        "diff": "5.0.0",
+        "escape-string-regexp": "4.0.0",
+        "find-up": "5.0.0",
+        "glob": "7.2.0",
         "he": "1.2.0",
-        "js-yaml": "3.13.1",
-        "log-symbols": "2.2.0",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.4",
-        "ms": "2.1.1",
-        "node-environment-flags": "1.0.5",
-        "object.assign": "4.1.0",
-        "strip-json-comments": "2.0.1",
-        "supports-color": "6.0.0",
-        "which": "1.3.1",
-        "wide-align": "1.1.3",
-        "yargs": "13.3.2",
-        "yargs-parser": "13.1.2",
-        "yargs-unparser": "1.6.0"
+        "js-yaml": "4.1.0",
+        "log-symbols": "4.1.0",
+        "minimatch": "5.0.1",
+        "ms": "2.1.3",
+        "nanoid": "3.3.3",
+        "serialize-javascript": "6.0.0",
+        "strip-json-comments": "3.1.1",
+        "supports-color": "8.1.1",
+        "workerpool": "6.2.1",
+        "yargs": "16.2.0",
+        "yargs-parser": "20.2.4",
+        "yargs-unparser": "2.0.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+        "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
         },
-        "cliui": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-          "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-          "dev": true,
-          "requires": {
-            "string-width": "^3.1.0",
-            "strip-ansi": "^5.2.0",
-            "wrap-ansi": "^5.1.0"
-          }
-        },
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+        "brace-expansion": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "balanced-match": "^1.0.0"
           }
         },
         "diff": {
-          "version": "3.5.0",
-          "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
-          "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+          "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
           "dev": true
         },
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
           "dev": true
         },
-        "glob": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+        "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": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
+            "locate-path": "^6.0.0",
+            "path-exists": "^4.0.0"
           }
         },
+        "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
+        },
         "js-yaml": {
-          "version": "3.13.1",
-          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-          "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+          "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": "^1.0.7",
-            "esprima": "^4.0.0"
+            "argparse": "^2.0.1"
           }
         },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-          "dev": true
+        "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"
+          }
         },
-        "object.assign": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
-          "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+        "minimatch": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+          "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
           "dev": true,
           "requires": {
-            "define-properties": "^1.1.2",
-            "function-bind": "^1.1.1",
-            "has-symbols": "^1.0.0",
-            "object-keys": "^1.0.11"
+            "brace-expansion": "^2.0.1"
           }
         },
-        "require-main-filename": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+        "ms": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
           "dev": true
         },
-        "string-width": {
+        "nanoid": {
+          "version": "3.3.3",
+          "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+          "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+          "dev": true
+        },
+        "p-limit": {
           "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+          "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
+            "yocto-queue": "^0.1.0"
           }
         },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+        "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": {
-            "ansi-regex": "^4.1.0"
+            "p-limit": "^3.0.2"
           }
         },
-        "supports-color": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
-          "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
+        "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
         },
-        "wrap-ansi": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-          "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+        "supports-color": {
+          "version": "8.1.1",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+          "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
           "dev": true,
           "requires": {
-            "ansi-styles": "^3.2.0",
-            "string-width": "^3.0.0",
-            "strip-ansi": "^5.0.0"
+            "has-flag": "^4.0.0"
           }
         },
         "yargs": {
-          "version": "13.3.2",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-          "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+          "version": "16.2.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+          "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
           "dev": true,
           "requires": {
-            "cliui": "^5.0.0",
-            "find-up": "^3.0.0",
-            "get-caller-file": "^2.0.1",
+            "cliui": "^7.0.2",
+            "escalade": "^3.1.1",
+            "get-caller-file": "^2.0.5",
             "require-directory": "^2.1.1",
-            "require-main-filename": "^2.0.0",
-            "set-blocking": "^2.0.0",
-            "string-width": "^3.0.0",
-            "which-module": "^2.0.0",
-            "y18n": "^4.0.0",
-            "yargs-parser": "^13.1.2"
+            "string-width": "^4.2.0",
+            "y18n": "^5.0.5",
+            "yargs-parser": "^20.2.2"
           }
+        },
+        "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
         }
       }
     },
@@ -14866,24 +14189,6 @@
         "path-to-regexp": "^1.7.0"
       }
     },
-    "node-environment-flags": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
-      "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
-      "dev": true,
-      "requires": {
-        "object.getownpropertydescriptors": "^2.0.3",
-        "semver": "^5.7.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
-      }
-    },
     "node-modules-regexp": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
@@ -15008,12 +14313,6 @@
         }
       }
     },
-    "object-inspect": {
-      "version": "1.10.3",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
-      "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
-      "dev": true
-    },
     "object-keys": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -15042,17 +14341,6 @@
         "object-keys": "^1.1.1"
       }
     },
-    "object.getownpropertydescriptors": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz",
-      "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.18.0-next.2"
-      }
-    },
     "object.pick": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@@ -15335,9 +14623,9 @@
       "dev": true
     },
     "qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+      "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
       "dev": true
     },
     "querystringify": {
@@ -15352,6 +14640,15 @@
       "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==",
       "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"
+      }
+    },
     "read-pkg": {
       "version": "7.1.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz",
@@ -15794,11 +15091,14 @@
       "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
       "dev": true
     },
-    "set-blocking": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
-      "dev": true
+    "serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
     },
     "set-value": {
       "version": "2.0.1",
@@ -15922,12 +15222,6 @@
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
         }
       }
     },
@@ -16280,33 +15574,14 @@
       }
     },
     "string-width": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-      "dev": true,
-      "requires": {
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^4.0.0"
-      }
-    },
-    "string.prototype.trimend": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-      "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3"
-      }
-    },
-    "string.prototype.trimstart": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-      "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
       "dev": true,
       "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3"
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
       }
     },
     "stringify-entities": {
@@ -16320,18 +15595,18 @@
       }
     },
     "strip-ansi": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "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": "^3.0.0"
+        "ansi-regex": "^5.0.1"
       }
     },
     "strip-json-comments": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
       "dev": true
     },
     "supports-color": {
@@ -16381,43 +15656,11 @@
             "uri-js": "^4.2.2"
           }
         },
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
         "json-schema-traverse": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
           "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
           "dev": true
-        },
-        "string-width": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
-          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
         }
       }
     },
@@ -16554,18 +15797,6 @@
       "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
       "dev": true
     },
-    "unbox-primitive": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
-      "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
-      "dev": true,
-      "requires": {
-        "function-bind": "^1.1.1",
-        "has-bigints": "^1.0.1",
-        "has-symbols": "^1.0.2",
-        "which-boxed-primitive": "^1.0.2"
-      }
-    },
     "unc-path-regex": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
@@ -16980,49 +16211,18 @@
         "webidl-conversions": "^3.0.0"
       }
     },
-    "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"
-      }
-    },
-    "which-boxed-primitive": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-      "dev": true,
-      "requires": {
-        "is-bigint": "^1.0.1",
-        "is-boolean-object": "^1.1.0",
-        "is-number-object": "^1.0.4",
-        "is-string": "^1.0.5",
-        "is-symbol": "^1.0.3"
-      }
-    },
-    "which-module": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
-      "dev": true
-    },
-    "wide-align": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
-      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-      "dev": true,
-      "requires": {
-        "string-width": "^1.0.2 || 2"
-      }
-    },
     "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
     },
+    "workerpool": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+      "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+      "dev": true
+    },
     "wrap-ansi": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -17034,12 +16234,6 @@
         "strip-ansi": "^6.0.0"
       },
       "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
-        },
         "ansi-styles": {
           "version": "4.3.0",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -17063,32 +16257,6 @@
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.3",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.1"
-          }
-        },
-        "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"
-          }
         }
       }
     },
@@ -17105,9 +16273,9 @@
       "dev": true
     },
     "y18n": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
       "dev": true
     },
     "yallist": {
@@ -17131,44 +16299,6 @@
         "yargs-parser": "^21.0.0"
       },
       "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
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "string-width": {
-          "version": "4.2.3",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.1"
-          }
-        },
-        "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"
-          }
-        },
-        "y18n": {
-          "version": "5.0.8",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-          "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-          "dev": true
-        },
         "yargs-parser": {
           "version": "21.1.1",
           "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
@@ -17178,103 +16308,28 @@
       }
     },
     "yargs-parser": {
-      "version": "13.1.2",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
-      "dev": true,
-      "requires": {
-        "camelcase": "^5.0.0",
-        "decamelize": "^1.2.0"
-      }
+      "version": "20.2.4",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+      "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+      "dev": true
     },
     "yargs-unparser": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
-      "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+      "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
       "dev": true,
       "requires": {
-        "flat": "^4.1.0",
-        "lodash": "^4.17.15",
-        "yargs": "^13.3.0"
+        "camelcase": "^6.0.0",
+        "decamelize": "^4.0.0",
+        "flat": "^5.0.2",
+        "is-plain-obj": "^2.1.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-          "dev": true
-        },
-        "cliui": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-          "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-          "dev": true,
-          "requires": {
-            "string-width": "^3.1.0",
-            "strip-ansi": "^5.2.0",
-            "wrap-ansi": "^5.1.0"
-          }
-        },
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-          "dev": true
-        },
-        "require-main-filename": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+        "is-plain-obj": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+          "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
           "dev": true
-        },
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        },
-        "wrap-ansi": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-          "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.0",
-            "string-width": "^3.0.0",
-            "strip-ansi": "^5.0.0"
-          }
-        },
-        "yargs": {
-          "version": "13.3.2",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-          "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
-          "dev": true,
-          "requires": {
-            "cliui": "^5.0.0",
-            "find-up": "^3.0.0",
-            "get-caller-file": "^2.0.1",
-            "require-directory": "^2.1.1",
-            "require-main-filename": "^2.0.0",
-            "set-blocking": "^2.0.0",
-            "string-width": "^3.0.0",
-            "which-module": "^2.0.0",
-            "y18n": "^4.0.0",
-            "yargs-parser": "^13.1.2"
-          }
         }
       }
     },
diff --git a/assets/package.json b/assets/package.json
index 4dbea0515..a489780b6 100644
--- a/assets/package.json
+++ b/assets/package.json
@@ -25,7 +25,7 @@
     "growl": "~> 1.10.0",
     "jsdom": "9.8.3",
     "jsdom-global": "2.1.0",
-    "mocha": "^6.2.2",
+    "mocha": "^10.1.0",
     "mock-socket": "^9.0.0",
     "sinon": "^9.0.1"
   },
diff --git a/guides/components.md b/guides/components.md
index 8abe91924..89c952619 100644
--- a/guides/components.md
+++ b/guides/components.md
@@ -1,97 +1,82 @@
-# Components and HEEx Templates
+# Components and HEEx
 
 > **Requirement**: This guide expects that you have gone through the [introductory guides](installation.html) and got a Phoenix application [up and running](up_and_running.html).
 
 > **Requirement**: This guide expects that you have gone through the [request life-cycle guide](request_lifecycle.html).
 
-The Phoenix endpoint pipeline takes a request, routes it with a router to a controller, and calls a view module to render a template. The view interface from the controller is simple – the controller calls a view function with the connections assigns, and the functions job is to return a HEEx template. We call functions that accept assigns and return HEEx, *function components*, which are provided by the `Phoenix.Component` module.
+The Phoenix endpoint pipeline takes a request, routes it with a router to a controller, and calls a view module to render a template. The view interface from the controller is simple – the controller calls a view function with the connections assigns, and the functions job is to return a HEEx template. We call functions that accept assigns and return HEEx, *function components*, which are provided by the [`Phoenix.Component`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html) module.
 
-Function components allow you to define reusable components in your application for building up your user interfaces. A function component is any function that receives an assigns map as an argument and returns
-a rendered struct built with [the `~H` sigil](`Phoenix.Component.sigil_H/2`):
+Function components are the essential building block for any kind of markup-based template rendering you'll perform in Phoenix. They served a shared abstraction for the standard MVC controller-based applications, LiveView applications, layouts, and smaller UI definition you'll use throughout other templates.
 
-```elixir
-defmodule MyComponent do
-  use Phoenix.Component
+In this chapter, we will recap how components were used in previous chapters and find new use cases for them.
 
-  def greet(assigns) do
-    ~H"""
-    <p>Hello, <%= @name %>!</p>
-    """
-  end
-end
+## Function components
+
+At the end of the Request life-cycle chapter, we created a template at `lib/hello_web/controllers/hello_html/show.html.heex`, let's open it up:
+
+```heex
+<section>
+  <h2>Hello World, from <%= @messenger %>!</h2>
+</section>
 ```
 
-Functions components can also be defined in `.heex` files by using `Phoenix.Component.embed_templates/2`:
+This template, is embedded as part of `HelloHTML`, at `lib/hello_web/controllers/hello_html.ex`:
 
 ```elixir
-defmodule MyComponent do
-  use Phoenix.Component
+defmodule HelloWeb.HelloHTML do
+  use HelloWeb, :html
 
-  # embed all .heex templates in current directory, such as "greet.html.heex"
-  embed_templates "*"
+  embed_templates "hello_html/*"
 end
 ```
 
-Function components are the essential building block for any kind of markup-based template rendering you'll perform in Phoenix. They served a shared abstraction for the standard MVC controller-based applications, LiveView applications, and smaller UI definition you'll use throughout other templates.
-
-We'll cover function components and HEEx in detail in a moment, but first let's learn how templates are rendered from the endpoint pipeline.
-
-## Rendering templates from the controller
-
-Phoenix assumes a strong naming convention from controllers to views to the templates they render. `PageController` requires a `PageHTML` to render templates in the `lib/hello_web/controllers/page_html/` directory. While all of these can be customizable (see `Phoenix.Component.embed_templates/2` and `Phoenix.Template` for more information), we recommend users stick with Phoenix' convention.
-
-A newly generated Phoenix application has two view modules - `HelloWeb.ErrorHTML` and `HelloWeb.PageHTML`, which are collocated by the controller in `lib/hello_web/controllers`. Phoenix also includes a `lib/hello_web/components` directory which holds all your shared HEEx function components for the application. Out of the box, a `HelloWeb.Layouts` module is defined at `lib/hello_web/components/layouts.ex`, which defines application layouts, and a `HelloWeb.CoreComponents` module at `lib/hello_web/components/core_components.ex` holds a base set of UI components such as forms, buttons, and modals which are used by the `phx.gen.*` generators and provide a bootstrapped core component building blocks.
+That's simple enough. There's only two lines, `use HelloWeb, :html`. This line calls the `html/0` function defined in `HelloWeb` which sets up the basic imports and configuration for our function components and templates.
 
+All of the imports and aliases we make in our module will also be available in our templates. That's because templates are effectively compiled into functions inside their respective module. For example, if you define a function in your module, you will be able to invoke it directly from the template. Let's see this in practice.
 
-Let's take a quick look at `HelloWeb.Layouts`.
+Imagine we want to refator our `show.html.heex` to move the rendering of `<h2>Hello World, from <%= @messenger %>!</h2>` to its own function. We can move it to a function component inside `HelloHTML`:
 
 ```elixir
-defmodule HelloWeb.Layouts do
+defmodule HelloWeb.HelloHTML do
   use HelloWeb, :html
 
-  embed_templates "layouts/*"
+  embed_templates "hello_html/*"
+
+  attr :messenger, :string
+
+  def greet(assigns) do
+    ~H"""
+    <h2>Hello World, from <%= @messenger %>!</h2>
+    """
+  end
 end
 ```
 
-That's simple enough. There's only two lines, `use HelloWeb, :html`. This line calls the `html/0` function defined in `HelloWeb` which sets up the basic imports and configuration for our function components and templates.
+We declared the attributes we accept via `attr` provided by `Phoenix.Component`, then we defined our `title/1` function which returns the HEEx template. When we reload our home page, we should see our new title. Since templates are compiled inside the view, we can invoke the view function simply as `<.greet messenger="..." />`, but we can also type `<HelloWeb.HelloHTML.greet messenger="..." />` if the component was defined elsewhere.
 
-All of the imports and aliases we make in our module will also be available in our templates. That's because templates are effectively compiled into functions inside their respective module. For example, if you define a function in your module, you will be able to invoke it directly from the template. Let's see this in practice.
+By declaring attributes, Phoenix will warn if we call the `<.greet />` component without passing attributes. If an attribute is optional, you can specify the `:default` option with a value:
 
-Open up our application layout template, `lib/hello_web/components/layouts/root.html.heex`, and change this line,
-
-```heex
-<.live_title suffix=" · Phoenix Framework">
-  <%= assigns[:page_title] || "Hello" %>
-</.live_title>
+```
+attr :messenger, :string, default: nil
 ```
 
-to call a `title/1` function, like this.
+Although this is a quick example, it shows the different roles function components play in Phoenix:
 
-```heex
-<.title suffix=" · Phoenix Framework" />
-```
+* Function components can be defined as functions that receive `assigns` as argument and call the `~H` sigil, as we did in `greet/1`
 
-Now let's add a `title/1` function to our `Layouts` module:
+* Function components can be embedded from template files, that's how we load `show.html.heex` into `HelloWeb.HelloHTML`
 
-```elixir
-defmodule HelloWeb.Layouts do
-  use HelloWeb, :html
+* Function components can declare which attributes are expected, which are validated at compilation time
 
-  embed_templates "layouts/*"
+* Function components can be directly rendered from controllers
 
-  attr :suffix, :string, default: nil
+* Function components can be directly rendered from other function components, as we called `<.greet messenger={@messenger} />` from `show.html.heex`
 
-  def title(assigns) do
-    ~H"""
-    Welcome to HelloWeb! <%= @suffix %>
-    """
-  end
-end
-```
+And there's more. Before we go deeper, let's fully understand the expressive power behind the HEEx template language.
 
-We declared the attributes we accept via `attr` provided by `Phoenix.Component`, then we defined our `title/1` function which returns the HEEx template. When we reload our home page, we should see our new title. Since templates are compiled inside the view, we can invoke the view function simply as `<.title suffix="..." />`, but we can also type `<HelloWeb.LayoutView.title suffix="..." />` if the component was defined elsewhere.
+## HEEx
 
-Our layouts and templates use the `.heex` extension, which stands for  "HTML+EEx". EEx is an Elixir library that uses `<%= expression %>` to execute Elixir expressions and interpolate their results into the template. This is frequently used to display assigns we have set by way of the `@` shortcut. In your controller, if you invoke:
+Function components and templates files are powered by [the HEEx template language](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2), which stands for  "HTML+EEx". EEx is an Elixir library that uses `<%= expression %>` to execute Elixir expressions and interpolate their results into the template. This is frequently used to display assigns we have set by way of the `@` shortcut. In your controller, if you invoke:
 
 ```elixir
   render(conn, :show, username: "joe")
@@ -184,205 +169,76 @@ Likewise, for comprehensions may be written as:
 </ul>
 ```
 
-### HTML components
-
-The last feature provided by HEEx is the idea of components. Components are pure functions that can be either local (same module) or remote (external module).
-
-HEEx allows invoking those function components directly in the template using an HTML-like notation. For example, a remote function:
+## Layouts
 
-```heex
-<MyApp.Weather.city name="Kraków"/>
-```
+Layouts are just function components. They are defined in a module, just like all other function component templates. In a newly generated app, this is `lib/hello_web/components/layouts.ex`. You will also find in a `layouts` folder with the two built-in layouts generated by Phoenix. The default _root layout_ is called `root.html.heex`, and it is the layout into which all templates will be rendered by default. The second is the _app layout_, called `app.html.heex`, which is rendered within the root layout and includes our contents.
 
-A local function can be invoked with a leading dot:
+You may be wondering how the string resulting from a rendered view ends up inside a layout. That's a great question! If we look at `lib/hello_web/components/layouts/root.html.heex`, just about at the end of the `<body>`, we will see this.
 
 ```heex
-<.city name="Kraków"/>
-```
-
-where the component could be defined as follows:
-
-```elixir
-defmodule MyApp.Weather do
-  use Phoenix.Component
-
-  def city(assigns) do
-    ~H"""
-    The chosen city is: <%= @name %>.
-    """
-  end
-
-  def country(assigns) do
-    ~H"""
-    The chosen country is: <%= @name %>.
-    """
-  end
-end
-```
-
-In the example above, we used the `~H` sigil syntax to embed HEEx templates directly into our modules. We have already invoked the `city` component and calling the `country` component wouldn't be different:
-
-```heex
-<div title="My div" {@many_attributes}>
-  <p>Hello <%= @username %></p>
-  <MyApp.Weather.country name="Brazil" />
-</div>
+<%= @inner_content %>
 ```
 
-You can learn more about components in [Phoenix.Component](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html).
-
-### Understanding template compilation
+In other words, the resulting of rendering your page is placed in the `@inner_content` assign.
 
-Phoenix templates are compiled into Elixir code, which make them extremely performant. Let's learn more about this.
+Phoenix provides all kinds of conveniences to control which layout should be rendered. For example, the `Phoenix.Controller` module provides the [`put_root_layout/2`] function for us to switch _root layouts_. This takes `conn` as its first argument and a string for the basename of the layout we want to render. It also accepts `false` to disable the layout altogether.
 
-When a template is compiled into a view, it is simply compiled as a `render/2` function that expects two arguments: the template name and the assigns.
-
-You can prove this by temporarily adding this function clause to your `PageHTML` module in `lib/hello_web/controllers/page_html.ex`.
+You can edit the `index` action of `PageController` in `lib/hello_web/controllers/page_controller.ex` to look like this.
 
 ```elixir
-defmodule HelloWeb.PageHTML do
-  use HelloWeb, :view
-
-  def render("index.html", assigns) do
-    "rendering with assigns #{inspect Map.keys(assigns)}"
-  end
+def index(conn, _params) do
+  conn
+  |> put_root_layout(false)
+  |> render(:index)
 end
 ```
 
-Now if you fire up the server with `mix phx.server` and visit [`http://localhost:4000`](http://localhost:4000), you should see the following text below your layout header instead of the main template page:
-
-```console
-rendering with assigns [:conn]
-```
+After reloading [http://localhost:4000/](http://localhost:4000/), we should see a very different page, one with no title, logo image, or CSS styling at all.
 
-By defining our own clause in `render/2`, it takes higher priority than the template, but the template is still there, which you can verify by simply removing the newly added clause.
+Now let's actually create another layout and render the index template into it. As an example, let's say we had a different layout for the admin section of our application which didn't have the logo image. To do this, let's copy the existing `root.html.heex` to a new file `admin.html.heex` in the same directory `lib/hello_web/components/layouts`. Then let's replace the lines in `admin.html.heex` that displays the logo with the word "Administration".
 
-Pretty neat, right? At compile-time, Phoenix precompiles all `*.html.heex` templates and turns them into `render/2` function clauses on their respective view modules. At runtime, all templates are already loaded in memory. There's no disk reads, complex file caching, or template engine computation involved.
-
-### Manually rendering templates
-
-So far, Phoenix has taken care of putting everything in place and rendering views for us. However, we can also render views directly.
-
-Let's create a new template to play around with, `lib/hello_web/templates/page/test.html.heex`:
+Remove these lines:
 
 ```heex
-This is the message: <%= @message %>
-```
-
-This doesn't correspond to any action in our controller, which is fine. We'll exercise it in an `IEx` session. At the root of our project, we can run `iex -S mix`, and then explicitly render our template. Let's give it a try by calling `Phoenix.Template.render/4` with the view name, the template name, format, and a set of assigns we might have wanted to pass and we got the rendered template as a string:
-
-```elixir
-iex(1)> Phoenix.Template.render(HelloWeb.PageHTML, "test", "html", message: "Hello from IEx!")
-%Phoenix.LiveView.Rendered{
-  dynamic: #Function<1.71437968/1 in Hello16Web.PageHTML."test.html"/1>,
-  fingerprint: 142353463236917710626026938006893093300,
-  root: false,
-  static: ["This is the message: ", ""]
-}
-```
-
-The output we got above is not very helpful. That's the internal representation of how Phoenix keeps our rendered templates. Luckily, we can convert them into strings with `render_to_string/3`:
-
-```elixir
-iex(2)> Phoenix.Template.render_to_string(HelloWeb.PageHTML, "test", "html", message: "Hello from IEx!")
-"This is the message: Hello from IEx!"
-```
-
-That's much better! Let's test out the HTML escaping, just for fun:
-
-```elixir
-iex(3)> Phoenix.Template.render_to_string(HelloWeb.PageHTML, "test", "html", message: "<script>badThings();</script>")
-"This is the message: &lt;script&gt;badThings();&lt;/script&gt;"
+<a href="https://phoenixframework.org/" class="phx-logo">
+  <img src={~p"/images/phoenix.png"} alt="Phoenix Framework Logo"/>
+</a>
 ```
 
-## Layouts
-
-Layouts are just function components. They are defined in a module, just like all other function component templates. In a newly generated app, this is `lib/hello_web/components/layouts.ex`. You may be wondering how the string resulting from a rendered view ends up inside a layout. That's a great question! If we look at `lib/hello_web/components/layouts/root.html.heex`, just about at the end of the `<body>`, we will see this.
+Replace them with:
 
 ```heex
-<%= @inner_content %>
+<p>Administration</p>
 ```
 
-In other words, the inner template is placed in the `@inner_content` assign.
-
-## Rendering JSON
-
-The view's job is not only to render HTML templates. Views are about data presentation. Given a bag of data, the view's purpose is to present that in a meaningful way given some format, be it HTML, JSON, CSV, or others. Many web apps today return JSON to remote clients, and Phoenix views are *great* for JSON rendering.
-
-Phoenix uses the `Jason` library to encode JSON, so all we need to do in our views is to format the data we would like to respond with as a list or a map, and Phoenix will do the rest.
-
-While it is possible to respond with JSON back directly from the controller and skip the view, Phoenix views provide a much more structured approach for doing  so. Let's take our `PageController`, and see what it may look like when we respond with some static page maps as JSON, instead of HTML.
+Then, pass the basename of the new layout into [`put_root_layout/2`] in our `index` action in `lib/hello_web/controllers/page_controller.ex`.
 
 ```elixir
-defmodule HelloWeb.PageController do
-  use HelloWeb, :controller
-
-  def show(conn, _params) do
-    page = %{title: "foo"}
-
-    render(conn, :show, page: page)
-  end
-
-  def index(conn, _params) do
-    pages = [%{title: "foo"}, %{title: "bar"}]
-
-    render(conn, :index, pages: pages)
-  end
+def index(conn, _params) do
+  conn
+  |> put_root_layout(:admin)
+  |> render(:index)
 end
 ```
-Here we are calling `render` with a `:show` or `:index` template. We can have the show and index actions fetch the same data but render different formats by defining a view specific to HTML or JSON. By default, Phoenix applications specify the `:html`, and `:json` formats when calling `use Phoenix.Controller` in your `lib/hello_web.ex` file. This will look for a `PageHTML` and `PageJSON` view module when a request comes into `PageController`. These can be overridden by calling `put_view` directly and specify the view modules per format:
 
-```elixir
-defmodule HelloWeb.PageController do
-  use HelloWeb, :controller
+When we load the page, we should be rendering the admin layout without a logo and with the word "Administration".
 
-  plug :put_view, html: HelloWeb.PageHTML, json: HelloWeb.PageJSON
-end
-```
+The app layout, placed at `app.html.heex`, works similarly and you can customize it using `put_layout`, instead of `put_root_layout`. At this point, you may be wondering, why does Phoenix have two layouts?
 
-For JSON support, we simply define a `PageJSON` module and template functions, just like our HTML templates except this time we'll return a map to be serialized as JSON:
+First of all, it gives us flexibility. In practice, we will hardly have multiple root layouts, as they often contain only HTML headers. This allows us to focus on different application layouts with only the parts that changes between them. Second of all, Phoenix ships with a feature called LiveView, which allows us to build rich and real-time user experiences with server-rendered HTML. LiveView is capable of dynamically changing the contents of the page, but it only ever changes the app layout, never the root layout. We will learn about LiveView in future guides.
 
-```elixir
-defmodule HelloWeb.PageJSON do
-
-  def index(%{pages: pages}) do
-    %{data: Enum.map(pages, fn page -> %{title: page.title} end)}
-  end
+We'll cover function components and HEEx in detail in a moment, but first let's learn how templates are rendered from the endpoint pipeline.
 
-  def show(%{page: page}) do
-    %{data: %{title: page.title}}
-  end
-end
-```
+## CoreComponents
 
-Just like HTML function components, our JSON functions receive assigns from the controller, and here can match on the assigns passed in. Phoenix handles content negotiation and will take care of converting the data-structures we return into JSON. A JSON request to the index action will respond like this:
-
-```json
-{
-  "data": [
-    {
-     "title": "foo"
-    },
-    {
-     "title": "bar"
-    },
- ]
-}
-```
+In a new Phoenix application, you will also find a `core_components.ex` module inside the `components` folder. This module is a great example of defining function components to be reused throughout our application. This guarantees that, as our application evolves, our components will look consistent.
 
-And the show action like this:
+If you look inside `def html` in `HelloWeb` placed at `lib/hello_web.ex`, you will see that `CoreComponents` are automatically imported into all HTML views via `use HelloWeb, :html`. This is also the reason why `CoreComponents` itself performs `use Phoenix.Component` instead `use HelloWeb, :html` at the top: doing the latter would cause a deadlock as we would try to import `CoreComponents` into itself.
 
-```json
-{
-  "data": {
-    "title": "foo"
-  }
-}
-```
+CoreComponents also play an important role in Phoenix code generators, as the code generator assume those components are available in order to quickly scaffold your application. In case you want to learn more about all of these pieces, you may:
 
-## Error pages
+  * Exploring the generated `CoreComponents` module to learn more from practical examples
 
-Phoenix has two views called `ErrorHTML` and `ErrorJSON` which live in `lib/hello_web/controllers/`. The purpose of these views is to handle errors in a general way for incoming HTML or JSON requests. Similar to the views we built in this guide, error views can return both HTML and JSON responses. See the [Custom Error Pages How-To](custom_error_pages.html) for more information.
+  * Read the official documentation for [`Phoenix.Component`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html)
 
-[welcome page]: http://localhost:4000
-[`render/4`]: `Phoenix.Template.render/4`
+  * Read the official documentation for [HEEx and the ~H sigils](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2)
diff --git a/guides/controllers.md b/guides/controllers.md
index a92a8581d..aeabe8d47 100644
--- a/guides/controllers.md
+++ b/guides/controllers.md
@@ -157,65 +157,15 @@ Or you can pass the assigns directly to `render` instead:
   end
 ```
 
-Generally speaking, once all assigns are configured, we invoke the view layer. The view layer then renders `show.html` alongside the layout and a response is sent back to the browser.
+Generally speaking, once all assigns are configured, we invoke the view layer. The view layer (`HelloWeb.HelloHTML`) then renders `show.html` alongside the layout and a response is sent back to the browser.
 
-[Components and templates](components.html) have their own guide, so we won't spend much time on them here. What we will look at is how to assign a different layout, or none at all, from inside a controller action.
+[Components and HEEx templates](components.html) have their own guide, so we won't spend much time on them here. What we will look at is how to render different formats from inside a controller action.
 
-### Assigning layouts
-
-Layouts are just a special subset of templates. They live in the `lib/hello_web/components/layouts` folder. Phoenix created two for us when we generated our app. The default _root layout_ is called `root.html.heex`, and it is the layout into which all templates will be rendered by default.
-
-Since layouts are really just templates, they need a module to render them. This one is `Layouts` which is defined in `lib/hello_web/components/layouts.ex`. Since Phoenix generated this module for us, we won't have to create a new one as long as we put the layouts we want to render inside the `lib/hello_web/components/layouts` directory.
-
-Before we create a new layout, though, let's do the simplest possible thing and render a template with no layout at all.
-
-The `Phoenix.Controller` module provides the [`put_root_layout/2`] function for us to switch _root layouts_. This takes `conn` as its first argument and a string for the basename of the layout we want to render. It also accepts `false` to disable the layout altogether.
-
-You can edit the `index` action of `PageController` in `lib/hello_web/controllers/page_controller.ex` to look like this.
-
-```elixir
-def index(conn, _params) do
-  conn
-  |> put_root_layout(false)
-  |> render(:index)
-end
-```
-
-After reloading [http://localhost:4000/](http://localhost:4000/), we should see a very different page, one with no title, logo image, or CSS styling at all.
-
-Now let's actually create another layout and render the index template into it. As an example, let's say we had a different layout for the admin section of our application which didn't have the logo image. To do this, let's copy the existing `root.html.heex` to a new file `admin.html.heex` in the same directory `lib/hello_web/components/layouts`. Then let's replace the lines in `admin.html.heex` that displays the logo with the word "Administration".
-
-Remove these lines:
-
-```heex
-<a href="https://phoenixframework.org/" class="phx-logo">
-  <img src={~p"/images/phoenix.png"} alt="Phoenix Framework Logo"/>
-</a>
-```
-
-Replace them with:
-
-```heex
-<p>Administration</p>
-```
-
-Then, pass the basename of the new layout into [`put_root_layout/2`] in our `index` action in `lib/hello_web/controllers/page_controller.ex`.
-
-```elixir
-def index(conn, _params) do
-  conn
-  |> put_root_layout(:admin)
-  |> render(:index)
-end
-```
-
-When we load the page, we should be rendering the admin layout without a logo and with the word "Administration".
-
-### Overriding rendering formats
+## New rendering formats
 
 Rendering HTML through a template is fine, but what if we need to change the rendering format on the fly? Let's say that sometimes we need HTML, sometimes we need plain text, and sometimes we need JSON. Then what?
 
-Phoenix allows us to change formats on the fly with the `_format` query string parameter. To make this happen, Phoenix requires an appropriately named view and an appropriately named template in the correct directory.
+The view's job is not only to render HTML templates. Views are about data presentation. Given a bag of data, the view's purpose is to present that in a meaningful way given some format, be it HTML, JSON, CSV, or others. Many web apps today return JSON to remote clients, and Phoenix views are *great* for JSON rendering.
 
 As an example, let's take `PageController`'s `index` action from a newly generated app. Out of the box, this has the right view `PageHTML`, the embedded templates from (`lib/hello_web/controllers/page_html`), and the right template for rendering HTML (`index.html.heex`.)
 
@@ -225,20 +175,20 @@ def index(conn, _params) do
 end
 ```
 
-What it doesn't have is an alternative template for rendering JSON. Phoenix Controller hands off to a view module to render templates, and it does so per format. We already have a view for the HTML format, but we need to instruct Phoenix how to render the JSON format as well. By default, you can see which formats your controllers support in `lib/hello_web.ex`:
+What it doesn't have is a view for rendering JSON. Phoenix Controller hands off to a view module to render templates, and it does so per format. We already have a view for the HTML format, but we need to instruct Phoenix how to render the JSON format as well. By default, you can see which formats your controllers support in `lib/hello_web.ex`:
 
 ```elixir
   def controller do
     quote do
       use Phoenix.Controller,
-        namespace: HelloWeb,
-        formats: [:html, :json]
+        formats: [:html, :json],
+        layouts: [html: HelloWeb.Layouts]
       ...
     end
   end
 ```
 
-So out of the box Phoenix will look for a `HelloHTML` and `HelloJSON` view module based on the request format. We can also explicitly tell Phoenix in our controller which view(s) to use for each format. For example, what Phoenix does by default can be explicitly set with the following in your controller:
+So out of the box Phoenix will look for a `HTML` and `JSON` view modules based on the request format and the controller name. We can also explicitly tell Phoenix in our controller which view(s) to use for each format. For example, what Phoenix does by default can be explicitly set with the following in your controller:
 
 ```elixir
 plug :put_view, html: HelloWeb.PageHTML, json: HelloWeb.PageJSON
@@ -256,14 +206,14 @@ end
 
 Since the Phoenix View layer is simply a function that the controller renders, passing connection assigns, we can define a regular `index/1` function and return a map to be serialized as JSON.
 
-There are just a few more things we need to do to make this work. We need to tell our router that it should accept the `json` format. We do that by adding `json` to the list of accepted formats in the `:browser` pipeline. Let's open up `lib/hello_web/router.ex` and change `plug :accepts` to include `json` as well as `html` like this.
+There are just a few more things we need to do to make this work. Because we want to render both HTML and JSON from the same controller, we need to tell our router that it should accept the `json` format. We do that by adding `json` to the list of accepted formats in the `:browser` pipeline. Let's open up `lib/hello_web/router.ex` and change `plug :accepts` to include `json` as well as `html` like this.
 
 ```elixir
 defmodule HelloWeb.Router do
   use HelloWeb, :router
 
   pipeline :browser do
-    plug :accepts, ["html", "text"]
+    plug :accepts, ["html", "json"]
     plug :fetch_session
     plug :fetch_live_flash
     plug :put_root_layout, {HelloWeb.LayoutView, :root}
@@ -273,7 +223,9 @@ defmodule HelloWeb.Router do
 ...
 ```
 
-If we go to [`http://localhost:4000/?_format=text`](http://localhost:4000/?_format=text), we will see %{"message": "this is some JSON"}.
+Phoenix allows us to change formats on the fly with the `_format` query string parameter. If we go to [`http://localhost:4000/?_format=json`](http://localhost:4000/?_format=json), we will see `%{"message": "this is some JSON"}`. 
+
+In practice, however, applications that need to render both formats typically use two distinct pipelines for each, such as the `pipeline :api` already defined in your router file. To learn more, see [our JSON and APIs guide](json_and_apis.md).
 
 ### Sending responses directly
 
@@ -301,7 +253,7 @@ end
 
 Using `Plug` functions in this way, we can craft just the response we need.
 
-### Setting the Content Type
+### Setting the content type
 
 Analogous to the `_format` query string param, we can render any sort of format we want by modifying the HTTP Content-Type Header and providing the appropriate template.
 
@@ -452,80 +404,11 @@ Besides [`put_flash/3`], the `Phoenix.Controller` module has another useful func
 
 Phoenix does not enforce which keys are stored in the flash. As long as we are internally consistent, all will be well. `:info` and `:error`, however, are common and are handled by default in our templates.
 
-## Action fallback
-
-Action fallback allows us to centralize error handling code in plugs, which are called when a controller action fails to return a [`%Plug.Conn{}`](`t:Plug.Conn.t/0`) struct. These plugs receive both the `conn` which was originally passed to the controller action along with the return value of the action.
-
-Let's say we have a `show` action which uses [`with`](`with/1`) to fetch a blog post and then authorize the current user to view that blog post. In this example we might expect `fetch_post/1` to return `{:error, :not_found}` if the post is not found and `authorize_user/3` might return `{:error, :unauthorized}` if the user is unauthorized. We could use our `ErrorHTML` and `ErrorJSON` views which are generated by Phoenix for every new application to handle these error paths accordingly:
-
-```elixir
-defmodule HelloWeb.MyController do
-  use Phoenix.Controller
-
-  def show(conn, %{"id" => id}, current_user) do
-    with {:ok, post} <- fetch_post(id),
-         :ok <- authorize_user(current_user, :view, post) do
-      render(conn, :show, post: post)
-    else
-      {:error, :not_found} ->
-        conn
-        |> put_status(:not_found)
-        |> put_view(html: HelloWeb.ErrorHTML, json: HelloWeb.ErrorJSON)
-        |> render(:"404")
-
-      {:error, :unauthorized} ->
-        conn
-        |> put_status(403)
-        |> put_view(html: HelloWeb.ErrorHTML, json: HelloWeb.ErrorJSON)
-        |> render(:"403")
-    end
-  end
-end
-```
-
-Now imagine you may need to implement similar logic for every controller and action handled by your API. This would result in a lot of repetition.
-
-Instead we can define a module plug which knows how to handle these error cases specifically. Since controllers are module plugs, let's define our plug as a controller:
-
-```elixir
-defmodule HelloWeb.MyFallbackController do
-  use Phoenix.Controller
-
-  def call(conn, {:error, :not_found}) do
-    conn
-    |> put_status(:not_found)
-    |> put_view(json: HelloWeb.ErrorJSON)
-    |> render(:"404")
-  end
-
-  def call(conn, {:error, :unauthorized}) do
-    conn
-    |> put_status(403)
-    |> put_view(json: HelloWeb.ErrorJSON)
-    |> render(:"403")
-  end
-end
-```
-
-Then we can reference our new controller as the `action_fallback` and simply remove the `else` block from our `with`:
-
-```elixir
-defmodule HelloWeb.MyController do
-  use Phoenix.Controller
-
-  action_fallback HelloWeb.MyFallbackController
-
-  def show(conn, %{"id" => id}, current_user) do
-    with {:ok, post} <- fetch_post(id),
-         :ok <- authorize_user(current_user, :view, post) do
-      render(conn, :show, post: post)
-    end
-  end
-end
-```
+## Error pages
 
-Whenever the `with` conditions do not match, `HelloWeb.MyFallbackController` will receive the original `conn` as well as the result of the action and respond accordingly.
+Phoenix has two views called `ErrorHTML` and `ErrorJSON` which live in `lib/hello_web/controllers/`. The purpose of these views is to handle errors in a general way for incoming HTML or JSON requests. Similar to the views we built in this guide, error views can return both HTML and JSON responses. See the [Custom Error Pages How-To](custom_error_pages.html) for more information.
 
+[`render/4`]: `Phoenix.Template.render/4`
 [`/hello/Frank`]:  http://localhost:4000/hello/Frank
 [`assign/3`]: `Plug.Conn.assign/3`
 [`clear_flash/1`]: `Phoenix.Controller.clear_flash/1`
diff --git a/guides/ecto.md b/guides/ecto.md
index c2846bccc..67be98a37 100644
--- a/guides/ecto.md
+++ b/guides/ecto.md
@@ -562,7 +562,7 @@ The last change is to open up `lib/hello_phoenix/repo.ex` and make sure to set t
 Now all we need to do is fetch our new dependency, and we'll be ready to go.
 
 ```console
-$ mix do deps.get, compile
+$ mix deps.get
 ```
 
 With our new adapter installed and configured, we're ready to create our database.
diff --git a/guides/howto/custom_error_pages.md b/guides/howto/custom_error_pages.md
index 385e76fa6..bd94ea93c 100644
--- a/guides/howto/custom_error_pages.md
+++ b/guides/howto/custom_error_pages.md
@@ -14,10 +14,10 @@ defmodule HelloWeb.ErrorHTML do
   # uncomment the embed_templates/1 call below
   # and add pages to the error directory:
   #
-  #   * lib/<%= @lib_web_name %>/controllers/error/404.html.heex
-  #   * lib/<%= @lib_web_name %>/controllers/error/500.html.heex
+  #   * lib/<%= @lib_web_name %>/controllers/error_html/404.html.heex
+  #   * lib/<%= @lib_web_name %>/controllers/error_html/500.html.heex
   #
-  # embed_templates "error/*"
+  # embed_templates "error_html/*"
 
   # The default is to render a plain text page based on
   # the template name. For example, "404.html" becomes
diff --git a/guides/json_and_apis.md b/guides/json_and_apis.md
new file mode 100644
index 000000000..9d78fb0dd
--- /dev/null
+++ b/guides/json_and_apis.md
@@ -0,0 +1,329 @@
+# JSON and APIs
+
+> **Requirement**: This guide expects that you have gone through the [introductory guides](installation.html) and got a Phoenix application [up and running](up_and_running.html).
+
+> **Requirement**: This guide expects that you have gone through the [Controllers guide](controllers.html).
+
+You can also use the Phoenix Framework to build [Web APIs](https://en.wikipedia.org/wiki/Web_API). By default Phoenix supports JSON but you can bring any other rendering format you desire.
+
+## The JSON API
+
+For this guide let's create a simple JSON API to store our favourite links, that will support all the CRUD (Create, Read, Update, Delete) operations out of the box.
+
+For this guide, we will use Phoenix generators to scaffold our API infrastructure:
+
+```console
+mix phx.gen.json Urls Url urls link:string title:string
+* creating lib/hello_web/controllers/url_controller.ex
+* creating lib/hello_web/controllers/url_json.ex
+* creating lib/hello_web/controllers/changeset_json.ex
+* creating test/hello_web/controllers/url_controller_test.exs
+* creating lib/hello_web/controllers/fallback_controller.ex
+* creating lib/hello/urls/url.ex
+* creating priv/repo/migrations/20221129120234_create_urls.exs
+* creating lib/hello/urls.ex
+* injecting lib/hello/urls.ex
+* creating test/hello/urls_test.exs
+* injecting test/hello/urls_test.exs
+* creating test/support/fixtures/urls_fixtures.ex
+* injecting test/support/fixtures/urls_fixtures.ex
+```
+
+We will break those files into four categories:
+
+  * Files in `lib/hello_web` responsible for effectively rendering JSON
+  * Files in `lib/hello` responsible for defining our context and logic to persist links to the database
+  * Files in `priv/repo/migrations` responsible for updating our database
+  * Files in `test` to test our controllers and contexts
+
+In this guide, we will explore only the first category of files. To learn more about how Phoenix stores and manage data, check out [the Ecto guide](ecto.md) and [the Contexts guide](contexts.md) for more information. We also have a whole section dedicating on testing.
+
+At the end, the generator asks us to add the `/url` resource to our `:api` scope in `lib/links_web/router.ex`:
+
+```elixir
+scope "/api", LinksWeb do
+  pipe_through :api
+  resources "/urls", UrlController, except: [:new, :edit]
+end
+```
+
+The API scope uses the `:api` pipeline, which will run specific steps such as ensuring the client can handle JSON responses.
+
+Then we need to update our repository by running migrations:
+
+```console
+mix ecto.migrate
+```
+
+### Trying out the JSON API
+
+Before we go ahead and change those files, let's take a look at how our API behaves from the command line.
+
+First, we need to start the server:
+
+```console
+mix phx.server
+```
+
+Next, let's make a smoke test to check our API is working with:
+
+```console
+curl -i http://localhost:4000/api/urls
+```
+
+If everything went as planned we should get a `200` response:
+
+```console
+HTTP/1.1 200 OK
+cache-control: max-age=0, private, must-revalidate
+content-length: 11
+content-type: application/json; charset=utf-8
+date: Fri, 06 May 2022 21:22:42 GMT
+server: Cowboy
+x-request-id: Fuyg-wMl4S-hAfsAAAUk
+
+{"data":[]}
+```
+
+We didn't get any data because we haven't populated the database with any yet. So let's add some links:
+
+```console
+curl -iX POST http://localhost:4000/api/urls \
+   -H 'Content-Type: application/json' \
+   -d '{"url": {"link":"https://phoenixframework.org", "title":"Phoenix Framework"}}'
+
+curl -iX POST http://localhost:4000/api/urls \
+   -H 'Content-Type: application/json' \
+   -d '{"url": {"link":"https://elixir-lang.org", "title":"Elixir"}}'
+```
+
+Now we can retrieve all links:
+
+```console
+curl -i http://localhost:4000/api/urls
+```
+
+Or we can just retrieve a link it's `id`:
+
+```console
+curl -i http://localhost:4000/api/urls/1
+```
+
+Next, we can update a link with:
+
+```console
+curl -iX PUT http://localhost:4000/api/urls/2 \
+   -H 'Content-Type: application/json' \
+   -d '{"url": {"title":"Elixir Programming Language"}}'
+```
+
+The response should be a `200` with the update link in the body.
+
+Finally, we need to try out the removal of a link:
+
+```console
+curl -iX DELETE http://localhost:4000/api/urls/2 \
+   -H 'Content-Type: application/json'
+```
+
+A `204` response should be returned to indicate the successful removal of the link.
+
+## Rendering JSON
+
+To understand how to render JSON, let's start with the `index` action from `UrlController` defined at `lib/hello_web/controllers/url_controller.ex`:
+
+```elixir
+  def index(conn, _params) do
+    urls = Urls.list_urls()
+    render(conn, :index, urls: urls)
+  end
+```
+
+As we can see, this is not any different from how Phoenix renders HTML templates. We call `render/3`, passing the connection, the template we want our views to render (`:index`), and the data we want to make available to our views.
+
+Phoenix typically uses one view per rendering format. When rendering HTML, we would use `HelloHTML`. Now that we are rendering JSON, we will find a `UrlJSON` view collocated with the template at `lib/hello_web/controllers/url_json.ex`. Let's open it up:
+
+```elixir
+defmodule HelloWeb.UrlJSON do
+  alias Hello.Urls.Url
+
+  @doc """
+  Renders a list of urls.
+  """
+  def index(%{urls: urls}) do
+    %{data: for(url <- urls, do: data(url))}
+  end
+
+  @doc """
+  Renders a single url.
+  """
+  def show(%{url: url}) do
+    %{data: data(url)}
+  end
+
+  defp data(%Url{} = url) do
+    %{
+      id: url.id,
+      link: url.link,
+      title: url.title
+    }
+  end
+end
+```
+
+This view is very simple. The `index` function receives all URLs, and converts them into a list of maps. Those maps are placed inside the data key at the root, exactly as we saw when interfacing with our application from `cURL`. In other words, our JSON view converts our complex data into simple Elixir data-structures. Once our view layer returns, Phoenix uses the `Jason` library to encode JSON and send the response to the client.
+
+If you explore the remaining the controller, you will learn the `show` action is similar to the `index` one. For `create`, `update`, and `delete` actions, Phoenix uses one other important feature, called "Action fallback".
+
+## Action fallback
+
+Action fallback allows us to centralize error handling code in plugs, which are called when a controller action fails to return a [`%Plug.Conn{}`](`t:Plug.Conn.t/0`) struct. These plugs receive both the `conn` which was originally passed to the controller action along with the return value of the action.
+
+Let's say we have a `show` action which uses [`with`](`with/1`) to fetch a blog post and then authorize the current user to view that blog post. In this example we might expect `fetch_post/1` to return `{:error, :not_found}` if the post is not found and `authorize_user/3` might return `{:error, :unauthorized}` if the user is unauthorized. We could use our `ErrorHTML` and `ErrorJSON` views which are generated by Phoenix for every new application to handle these error paths accordingly:
+
+```elixir
+defmodule HelloWeb.MyController do
+  use Phoenix.Controller
+
+  def show(conn, %{"id" => id}, current_user) do
+    with {:ok, post} <- fetch_post(id),
+         :ok <- authorize_user(current_user, :view, post) do
+      render(conn, :show, post: post)
+    else
+      {:error, :not_found} ->
+        conn
+        |> put_status(:not_found)
+        |> put_view(html: HelloWeb.ErrorHTML, json: HelloWeb.ErrorJSON)
+        |> render(:"404")
+
+      {:error, :unauthorized} ->
+        conn
+        |> put_status(403)
+        |> put_view(html: HelloWeb.ErrorHTML, json: HelloWeb.ErrorJSON)
+        |> render(:"403")
+    end
+  end
+end
+```
+
+Now imagine you may need to implement similar logic for every controller and action handled by your API. This would result in a lot of repetition.
+
+Instead we can define a module plug which knows how to handle these error cases specifically. Since controllers are module plugs, let's define our plug as a controller:
+
+```elixir
+defmodule HelloWeb.MyFallbackController do
+  use Phoenix.Controller
+
+  def call(conn, {:error, :not_found}) do
+    conn
+    |> put_status(:not_found)
+    |> put_view(json: HelloWeb.ErrorJSON)
+    |> render(:"404")
+  end
+
+  def call(conn, {:error, :unauthorized}) do
+    conn
+    |> put_status(403)
+    |> put_view(json: HelloWeb.ErrorJSON)
+    |> render(:"403")
+  end
+end
+```
+
+Then we can reference our new controller as the `action_fallback` and simply remove the `else` block from our `with`:
+
+```elixir
+defmodule HelloWeb.MyController do
+  use Phoenix.Controller
+
+  action_fallback HelloWeb.MyFallbackController
+
+  def show(conn, %{"id" => id}, current_user) do
+    with {:ok, post} <- fetch_post(id),
+         :ok <- authorize_user(current_user, :view, post) do
+      render(conn, :show, post: post)
+    end
+  end
+end
+```
+
+Whenever the `with` conditions do not match, `HelloWeb.MyFallbackController` will receive the original `conn` as well as the result of the action and respond accordingly.
+
+## FallbackController and ChangesetJSON
+
+With this knowledge in hand, we can explore the `FallbackController` (`lib/hello_web/controllers/fallback_controller.ex`) generated by `mix phx.gen.json`. In particular, it handles one clause (the other is generated as an example):
+
+```elixir
+  def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
+    conn
+    |> put_status(:unprocessable_entity)
+    |> put_view(json: HelloWeb.ChangesetJSON)
+    |> render("error.json", changeset: changeset)
+  end
+```
+
+The goal of this clause is to handle the `{:error, changeset}` return types from the `HelloWeb.Urls` context and render them into rendered errors via the `ChangesetJSON` view. Let's open up `lib/hello_web/controllers/changeset_json.ex` to learn more:
+
+```elixir
+defmodule HelloWeb.ChangesetJSON do
+  @doc """
+  Renders changeset errors.
+  """
+  def error(%{changeset: changeset}) do
+    # When encoded, the changeset returns its errors
+    # as a JSON object. So we just pass it forward.
+    %{errors: Ecto.Changeset.traverse_errors(changeset, &HelloWeb.CoreComponents.translate_error/1)}
+  end
+end
+```
+
+As we can see, it will convert the errors into a data structure, which will be rendered as JSON. The changeset is a data structure responsible for casting and validating data. For our example, it is defined in `Hello.Urls.Url.changeset/1`. Let's open up `lib/hello/urls/url.ex` and see its definition:
+
+```elixir
+  @doc false
+  def changeset(url, attrs) do
+    url
+    |> cast(attrs, [:link, :title])
+    |> validate_required([:link, :title])
+  end
+```
+
+As you can see, the changeset requires both link and title to be given. This means we can try posting a url with no link and title and see how our API responds:
+
+```console
+curl -iX POST http://localhost:4000/api/urls \
+   -H 'Content-Type: application/json' \
+   -d '{"url": {}}'
+
+{"errors": {"link": ["can't be blank"], "title": ["can't be blank"]}}
+```
+
+Feel free to modify the `changeset` function and see how your API behaves.
+
+## API-only applications
+
+In case you want to generate a Phoenix application exclusively for APIs, you can pass
+several options when invoking `mix phx.new`. Let's check which `--no-*` flags we need
+to use to not generate the scaffolding that isn't necessary on our Phoenix application
+for the REST API.
+
+From your terminal run:
+
+```console
+mix help phx.new
+```
+
+The output should contain the following:
+
+```text
+  • --no-assets - do not generate the assets folder
+  • --no-ecto - do not generate Ecto files
+  • --no-html - do not generate HTML views
+  • --no-gettext - do not generate gettext files
+  • --no-dashboard - do not include Phoenix.LiveDashboard
+  • --no-mailer - do not generate Swoosh mailer files
+```
+
+The `--no-html` is the obvious one we want to use when creating any Phoenix application for an API in order to leave out all the unnecessary HTML scaffolding. You may also pass `--no-assets`, if you don't want any of the asset management bit, `--no-gettext` if you don't support internationalization, and so on.
+
+Also bear in mind that nothing stops you to have a backend that supports simultaneously the REST API and a Web App (HTML, assets, internationalization and sockets).
diff --git a/guides/request_lifecycle.md b/guides/request_lifecycle.md
index 66edc5126..48f8cfbdb 100644
--- a/guides/request_lifecycle.md
+++ b/guides/request_lifecycle.md
@@ -117,11 +117,9 @@ defmodule HelloWeb.HelloHTML do
 end
 ```
 
-To add templates to this view, we can define them as function components in the module or in separate files. Function components are great for smaller templates and separate files are a good choice when you have a lot of markup or your functions start to feel unmanageable.
+To add templates to this view, we can define them as function components in the module or in separate files.
 
-Template files are compiled into the module as function components themselves, there is no runtime or performance difference between the two styles.
-
-Here's how you would define a template a function component:
+Let's start by defining a function component:
 
 ```elixir
 defmodule HelloWeb.HelloHTML do
@@ -135,10 +133,11 @@ defmodule HelloWeb.HelloHTML do
 end
 ```
 
-You can read more about function components and `~H` heex templates in the
-[Components and HEEx Templates guide](components.html).
+We defined a function that receives `assigns` as arguments and use [the `~H` sigil](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2) to put the contents we want to render. Inside the `~H` sigil, we use a templating language called HEEx, which stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site-Scripting with no extra work on your part.
+
+A template file works in the same way. Function components are great for smaller templates and separate files are a good choice when you have a lot of markup or your functions start to feel unmanageable.
 
-Now lets define a template in its own file. First delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
+Let's give it a try by defining a template in its own file. First delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
 
 ```elixir
 defmodule HelloWeb.HelloHTML do
@@ -148,11 +147,11 @@ defmodule HelloWeb.HelloHTML do
 end
 ```
 
- Here we are telling `Phoenix.Component` to embed all `.heex` templates found in the sibling `hello_html` directory into our module as function definitions.
+Here we are telling `Phoenix.Component` to embed all `.heex` templates found in the sibling `hello_html` directory into our module as function definitions.
 
- Next, we need to add files to the `lib/hello_web/controllers/hello_html` directory.
+Next, we need to add files to the `lib/hello_web/controllers/hello_html` directory.
 
- Note the controller name (`HelloController`), the view name (`HelloHTML`), and the template directory (`hello_html`) all follow the same naming convention and are named after each other. They are also collocated together in the directory tree:
+Note the controller name (`HelloController`), the view name (`HelloHTML`), and the template directory (`hello_html`) all follow the same naming convention and are named after each other. They are also collocated together in the directory tree:
 
 ```
 lib/hello_web
@@ -163,27 +162,27 @@ lib/hello_web
 |       ├── index.html.heex
 ```
 
-A template file has the following structure: `NAME.FORMAT.TEMPLATING_LANGUAGE`. In our case, we will create an `index.html.heex` file at `lib/hello_web/controllers/hello_html/index.html.heex`. ".heex" stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site-Scripting with no extra work on your part.
-
-Create `lib/hello_web/controllers/hello_html/index.html.heex` and make it look like this:
+A template file has the following structure: `NAME.FORMAT.TEMPLATING_LANGUAGE`. In our case, let's create an `index.html.heex` file at `lib/hello_web/controllers/hello_html/index.html.heex`:
 
 ```heex
-<section class="phx-hero">
+<section>
   <h2>Hello World, from Phoenix!</h2>
 </section>
 ```
 
+Template files are compiled into the module as function components themselves, there is no runtime or performance difference between the two styles.
+
 Now that we've got the route, controller, view, and template, we should be able to point our browsers at [http://localhost:4000/hello](http://localhost:4000/hello) and see our greeting from Phoenix! (In case you stopped the server along the way, the task to restart it is `mix phx.server`.)
 
 ![Phoenix Greets Us](assets/images/hello-from-phoenix.png)
 
-There are a couple of interesting things to notice about what we just did. We didn't need to stop and restart the server while we made these changes. Yes, Phoenix has hot code reloading! Also, even though our `index.html.heex` file consists of only a single `section` tag, the page we get is a full HTML document. Our index template is rendered into the application layout: `lib/hello_web/components/layouts/app.html.heex`. If you open it, you'll see a line that looks like this:
+There are a couple of interesting things to notice about what we just did. We didn't need to stop and restart the server while we made these changes. Yes, Phoenix has hot code reloading! Also, even though our `index.html.heex` file consists of only a single `section` tag, the page we get is a full HTML document. Our index template is actually rendered into layouts: first it renders `lib/hello_web/components/layouts/root.html.heex` which renders `lib/hello_web/components/layouts/app.html.heex` which finally includes our contents. If you open those files, you'll see a line that looks like this at the bottom:
 
 ```heex
 <%= @inner_content %>
 ```
 
-Which injects our template into the layout before the HTML is sent off to the browser.
+Which injects our template into the layout before the HTML is sent off to the browser. We will talk more about layouts in the Controllers guide.
 
 > A note on hot code reloading: Some editors with their automatic linters may prevent hot code reloading from working. If it's not working for you, please see the discussion in [this issue](https://github.com/phoenixframework/phoenix/issues/1165).
 
@@ -220,7 +219,7 @@ At this moment, you may be thinking this can be a lot of steps to simply render
 
   * controller (`Phoenix.Controller`) - the job of the controller is to retrieve request information, talk to your business domain, and prepare data for the presentation layer.
 
-  * view - the view handles the structured data from the controller and converts it to a presentation to be shown to users.
+  * view - the view handles the structured data from the controller and converts it to a presentation to be shown to users. Views are often named after the content format they are rendering.
 
 Let's do a quick recap and how the last three components work together by adding another page.
 
@@ -246,7 +245,7 @@ end
 
 Notice that we use the `:messenger` syntax in the path. Phoenix will take whatever value that appears in that position in the URL and convert it into a parameter. For example, if we point the browser at: `http://localhost:4000/hello/Frank`, the value of `"messenger"` will be `"Frank"`.
 
-### Another new Action
+### Another new action
 
 Requests to our new route will be handled by the `HelloWeb.HelloController` `show` action. We already have the controller at `lib/hello_web/controllers/hello_controller.ex`, so all we need to do is edit that controller and add a `show` action to it. This time, we'll need to extract the messenger from the parameters so that we can pass it (the messenger) to the template. To do that, we add this show function to the controller:
 
@@ -272,14 +271,14 @@ It's good to remember that the keys of the `params` map will always be strings,
 
 For the last piece of this puzzle, we'll need a new template. Since it is for the `show` action of `HelloController`, it will go into the `lib/hello_web/controllers/hello_html` directory and be called `show.html.heex`. It will look surprisingly like our `index.html.heex` template, except that we will need to display the name of our messenger.
 
-To do that, we'll use the special EEx tags for executing Elixir expressions: `<%=  %>`. Notice that the initial tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag in the HTML output. If the equals sign were missing, the code would still be executed, but the value would not appear on the page.
+To do that, we'll use the special HEEx tags for executing Elixir expressions: `<%=  %>`. Notice that the initial tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag in the HTML output. If the equals sign were missing, the code would still be executed, but the value would not appear on the page.
 
 Remember our templates are written in HEEx (HTML+EEx). HEEx is a superset of EEx which is why it shares the `<%= %>` syntax.
 
 And this is what the template should look like:
 
 ```heex
-<section class="phx-hero">
+<section>
   <h2>Hello World, from <%= @messenger %>!</h2>
 </section>
 ```
diff --git a/guides/routing.md b/guides/routing.md
index 472b2f5b5..cead676be 100644
--- a/guides/routing.md
+++ b/guides/routing.md
@@ -28,7 +28,7 @@ defmodule HelloWeb.Router do
   scope "/", HelloWeb do
     pipe_through :browser
 
-    get "/", PageController, :index
+    get "/", PageController, :home
   end
 
   # Other scopes may use custom stacks.
@@ -48,7 +48,7 @@ Scopes have their own section in this guide, so we won't spend time on the `scop
 Inside the scope block, however, we have our first actual route:
 
 ```elixir
-get "/", PageController, :index
+get "/", PageController, :home
 ```
 
 `get` is a Phoenix macro that corresponds to the HTTP verb GET. Similar macros exist for other HTTP verbs, including POST, PUT, PATCH, DELETE, OPTIONS, CONNECT, TRACE, and HEAD.
@@ -61,11 +61,11 @@ Let's see how this works. Go to the root of a newly-generated Phoenix applicatio
 
 ```console
 $ mix phx.routes
-GET  /  HelloWeb.PageController :index
+GET  /  HelloWeb.PageController :home
 ...
 ```
 
-The route above tells us that any HTTP GET request for the root of the application will be handled by the `index` action of the `HelloWeb.PageController`.
+The route above tells us that any HTTP GET request for the root of the application will be handled by the `home` action of the `HelloWeb.PageController`.
 
 ## Resources
 
@@ -75,7 +75,7 @@ The router supports other macros besides those for HTTP verbs like [`get`](`Phoe
 scope "/", HelloWeb do
   pipe_through :browser
 
-  get "/", PageController, :index
+  get "/", PageController, :home
   resources "/users", UserController
   ...
 end
@@ -469,7 +469,7 @@ defmodule HelloWeb.Router do
   scope "/", HelloWeb do
     pipe_through :browser
 
-    get "/", PageController, :index
+    get "/", PageController, :home
   end
 
   # Other scopes may use custom stacks.
@@ -484,7 +484,7 @@ end
 
 When the server accepts a request, the request will always first pass through the plugs in our endpoint, after which it will attempt to match on the path and HTTP verb.
 
-Let's say that the request matches our first route: a GET to `/`. The router will first pipe that request through the `:browser` pipeline - which will fetch the session data, fetch the flash, and execute forgery protection - before it dispatches the request to `PageController`'s `index` action.
+Let's say that the request matches our first route: a GET to `/`. The router will first pipe that request through the `:browser` pipeline - which will fetch the session data, fetch the flash, and execute forgery protection - before it dispatches the request to `PageController`'s `home` action.
 
 Conversely, suppose the request matches any of the routes defined by the [`resources/2`](`Phoenix.Router.resources/2`) macro. In that case, the router will pipe it through the `:api` pipeline — which currently only performs content negotiation — before it dispatches further to the correct action of the `HelloWeb.ReviewController`.
 
diff --git a/guides/telemetry.md b/guides/telemetry.md
index f8f1c4731..fe6f82776 100644
--- a/guides/telemetry.md
+++ b/guides/telemetry.md
@@ -518,6 +518,7 @@ Library authors are actively encouraged to send a PR adding
 their own (in alphabetical order, please):
 
 * [Absinthe](https://hexdocs.pm/absinthe) - [Events](https://hexdocs.pm/absinthe/telemetry.html)
+* [Ash Framework](https://hexdocs.pm/ash) - [Events](https://hexdocs.pm/ash/monitoring.html)
 * [Broadway](https://hexdocs.pm/broadway) - [Events](https://hexdocs.pm/broadway/Broadway.html#module-telemetry)
 * [Ecto](https://hexdocs.pm/ecto) - [Events](https://hexdocs.pm/ecto/Ecto.Repo.html#module-telemetry-events)
 * [Oban](https://hexdocs.pm/oban) - [Events](https://hexdocs.pm/oban/Oban.Telemetry.html)
diff --git a/installer/lib/mix/tasks/phx.new.ex b/installer/lib/mix/tasks/phx.new.ex
index 43cb56a2a..cbc1fd406 100644
--- a/installer/lib/mix/tasks/phx.new.ex
+++ b/installer/lib/mix/tasks/phx.new.ex
@@ -43,8 +43,8 @@ defmodule Mix.Tasks.Phx.New do
 
     * `--no-dashboard` - do not include Phoenix.LiveDashboard
 
-    * `--no-live` - comment out LiveView socket setup in assets/js/app.js
-      and also on the endpoint (the latter also requires `--no-dashboard`)
+    * `--no-live` - comment out LiveView socket setup in assets/js/app.js.
+      Automatically disabled if --no-html is given
 
     * `--no-mailer` - do not generate Swoosh mailer files
 
@@ -170,8 +170,25 @@ defmodule Mix.Tasks.Phx.New do
     maybe_cd(path, fn ->
       mix_step = install_mix(project, install?)
 
-      if mix_step == [] and rebar_available?() do
-        cmd(project, "mix deps.compile")
+      if mix_step == [] do
+        tasks =
+          if Keyword.get(project.opts, :assets, true) do
+            # First compile only esbuild and tailwind so we can install in parallel
+            cmd(project, "mix deps.compile esbuild tailwind")
+
+            Enum.map(
+              ["mix tailwind.install", "mix esbuild.install"],
+              &Task.async(fn -> cmd(project, &1) end)
+            )
+          else
+            []
+          end
+
+        if rebar_available?() do
+          cmd(project, "mix deps.compile")
+        end
+
+        Task.await_many(tasks, :infinity)
       end
 
       print_missing_steps(cd_step ++ mix_step)
@@ -208,7 +225,11 @@ defmodule Mix.Tasks.Phx.New do
   defp switch_to_string({name, val}), do: name <> "=" <> val
 
   defp install_mix(project, install?) do
-    maybe_cmd(project, "mix deps.get", true, install? && hex_available?())
+    if install? && hex_available?() do
+      cmd(project, "mix deps.get")
+    else
+      ["$ mix deps.get"]
+    end
   end
 
   # TODO: Elixir v1.15 automatically installs Hex/Rebar if missing, so we can simplify this.
@@ -266,24 +287,12 @@ defmodule Mix.Tasks.Phx.New do
 
   ## Helpers
 
-  defp maybe_cmd(project, cmd, should_run?, can_run?) do
-    cond do
-      should_run? && can_run? ->
-        cmd(project, cmd)
-      should_run? ->
-        ["$ #{cmd}"]
-      true ->
-        []
-    end
-  end
-
   defp cmd(%Project{} = project, cmd) do
     Mix.shell().info [:green, "* running ", :reset, cmd]
+
     case Mix.shell().cmd(cmd, cmd_opts(project)) do
-      0 ->
-        []
-      _ ->
-        ["$ #{cmd}"]
+      0 -> []
+      _ -> ["$ #{cmd}"]
     end
   end
 
diff --git a/installer/lib/phx_new/single.ex b/installer/lib/phx_new/single.ex
index 8f5a0a0b2..9e0d77ddb 100644
--- a/installer/lib/phx_new/single.ex
+++ b/installer/lib/phx_new/single.ex
@@ -54,7 +54,7 @@ defmodule Phx.New.Single do
      "phx_web/components/layouts/app.html.heex":
        "lib/:lib_web_name/components/layouts/app.html.heex",
      "phx_web/components/layouts.ex": "lib/:lib_web_name/components/layouts.ex"},
-    {:eex, :web, "phx_live/assets/topbar.js": "assets/vendor/topbar.js"}
+    {:eex, :web, "phx_assets/topbar.js": "assets/vendor/topbar.js"}
   ])
 
   template(:ecto, [
@@ -83,7 +83,6 @@ defmodule Phx.New.Single do
   template(:static, [
     {:text, :web,
      "phx_static/robots.txt": "priv/static/robots.txt",
-     "phx_static/phoenix.png": "priv/static/images/phoenix.png",
      "phx_static/favicon.ico": "priv/static/favicon.ico"}
   ])
 
diff --git a/installer/lib/phx_new/web.ex b/installer/lib/phx_new/web.ex
index 87a593979..2605d0386 100644
--- a/installer/lib/phx_new/web.ex
+++ b/installer/lib/phx_new/web.ex
@@ -51,7 +51,7 @@ defmodule Phx.New.Web do
        "lib/:web_app/controllers/page_html/home.html.heex",
      "phx_test/controllers/page_controller_test.exs":
        "test/:web_app/controllers/page_controller_test.exs",
-     "phx_live/assets/topbar.js": "assets/vendor/topbar.js",
+     "phx_assets/topbar.js": "assets/vendor/topbar.js",
      "phx_web/components/layouts/root.html.heex": "lib/:web_app/components/layouts/root.html.heex",
      "phx_web/components/layouts/app.html.heex": "lib/:web_app/components/layouts/app.html.heex"}
   ])
diff --git a/installer/templates/phx_live/assets/topbar.js b/installer/templates/phx_assets/topbar.js
similarity index 100%
rename from installer/templates/phx_live/assets/topbar.js
rename to installer/templates/phx_assets/topbar.js
diff --git a/installer/templates/phx_single/README.md b/installer/templates/phx_single/README.md
index cb0a1617b..5c96eb63a 100644
--- a/installer/templates/phx_single/README.md
+++ b/installer/templates/phx_single/README.md
@@ -2,8 +2,7 @@
 
 To start your Phoenix server:
 
-  * Install dependencies with `mix deps.get`<%= if @ecto do %>
-  * Create and migrate your database with `mix ecto.setup`<% end %>
+  * Run `mix setup` to install and setup dependencies
   * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
 
 Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
diff --git a/installer/templates/phx_single/lib/app_name_web.ex b/installer/templates/phx_single/lib/app_name_web.ex
index bf3382b4f..a2d52e1d3 100644
--- a/installer/templates/phx_single/lib/app_name_web.ex
+++ b/installer/templates/phx_single/lib/app_name_web.ex
@@ -39,7 +39,6 @@ defmodule <%= @web_namespace %> do
   def controller do
     quote do
       use Phoenix.Controller,
-        namespace: <%= @web_namespace %>,
         formats: [:html, :json],
         layouts: [html: <%= @web_namespace %>.Layouts]
 
diff --git a/installer/templates/phx_single/mix.exs b/installer/templates/phx_single/mix.exs
index bea1b5f68..34d446639 100644
--- a/installer/templates/phx_single/mix.exs
+++ b/installer/templates/phx_single/mix.exs
@@ -66,10 +66,11 @@ defmodule <%= @app_module %>.MixProject do
   # See the documentation for `Mix` for more info on aliases.
   defp aliases do
     [
-      setup: ["deps.get"<%= if @ecto do %>, "ecto.setup"<% end %>]<%= if @ecto do %>,
+      setup: ["deps.get"<%= if @ecto do %>, "ecto.setup"<% end %><%= if @assets do %>, "assets.setup"<% end %>]<%= if @ecto do %>,
       "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
       "ecto.reset": ["ecto.drop", "ecto.setup"],
       test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]<% end %><%= if @assets do %>,
+      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
       "assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]<% end %>
     ]
   end
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/README.md b/installer/templates/phx_umbrella/apps/app_name_web/README.md
index d462ec3e8..fdb87dfcf 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/README.md
+++ b/installer/templates/phx_umbrella/apps/app_name_web/README.md
@@ -2,8 +2,7 @@
 
 To start your Phoenix server:
 
-  * Install dependencies with `mix deps.get`<%= if @ecto do %>
-  * Create and migrate your database with `mix ecto.setup`<% end %>
+  * Run `mix setup` to install and setup dependencies
   * Start Phoenix endpoint with `mix phx.server`
 
 Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
index bf3382b4f..a2d52e1d3 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
+++ b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
@@ -39,7 +39,6 @@ defmodule <%= @web_namespace %> do
   def controller do
     quote do
       use Phoenix.Controller,
-        namespace: <%= @web_namespace %>,
         formats: [:html, :json],
         layouts: [html: <%= @web_namespace %>.Layouts]
 
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
index 711b02cf4..6f70f2200 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
+++ b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
@@ -60,8 +60,9 @@ defmodule <%= @web_namespace %>.MixProject do
   # See the documentation for `Mix` for more info on aliases.
   defp aliases do
     [
-      setup: ["deps.get"]<%= if @ecto do %>,
+      setup: ["deps.get"<%= if @assets do %>, "assets.setup"<% end %>]<%= if @ecto do %>,
       test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]<% end %><%= if @assets do %>,
+      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
       "assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]<% end %>
     ]
   end
diff --git a/installer/templates/phx_web/components/core_components.ex b/installer/templates/phx_web/components/core_components.ex
index 8ec842aea..d504b5361 100644
--- a/installer/templates/phx_web/components/core_components.ex
+++ b/installer/templates/phx_web/components/core_components.ex
@@ -47,7 +47,12 @@ defmodule <%= @web_namespace %>.CoreComponents do
 
   def modal(assigns) do
     ~H"""
-    <div id={@id} phx-mounted={@show && show_modal(@id)} class="relative z-50 hidden">
+    <div
+      id={@id}
+      phx-mounted={@show && show_modal(@id)}
+      phx-remove={hide_modal(@id)}
+      class="relative z-50 hidden"
+    >
       <div id={"#{@id}-bg"} class="fixed inset-0 bg-zinc-50/90 transition-opacity" aria-hidden="true" />
       <div
         class="fixed inset-0 overflow-y-auto"
@@ -82,7 +87,11 @@ defmodule <%= @web_namespace %>.CoreComponents do
                   <h1 id={"#{@id}-title"} class="text-lg font-semibold leading-8 text-zinc-800">
                     <%%= render_slot(@title) %>
                   </h1>
-                  <p :if={@subtitle != []} class="mt-2 text-sm leading-6 text-zinc-600">
+                  <p
+                    :if={@subtitle != []}
+                    id={"#{@id}-description"}
+                    class="mt-2 text-sm leading-6 text-zinc-600"
+                  >
                     <%%= render_slot(@subtitle) %>
                   </p>
                 </header>
@@ -259,8 +268,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
   attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
   attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
-  attr :rest, :global, include: ~w(autocomplete disabled form max maxlength min minlength
-                                   pattern placeholder readonly required size step)
+  attr :rest, :global, include: ~w(autocomplete cols disabled form max maxlength min minlength
+                                   pattern placeholder readonly required rows size step)
   slot :inner_block
 
   def input(%{field: {f, field}} = assigns) do
@@ -330,7 +339,6 @@ defmodule <%= @web_namespace %>.CoreComponents do
         ]}
         {@rest}
       >
-
     <%%= @value %></textarea>
       <.error :for={msg <- @errors}><%%= msg %></.error>
     </div>
@@ -568,6 +576,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       transition: {"transition-all transform ease-out duration-300", "opacity-0", "opacity-100"}
     )
     |> show("##{id}-container")
+    |> JS.add_class("overflow-hidden", to: "body")
     |> JS.focus_first(to: "##{id}-content")
   end
 
@@ -579,6 +588,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
     )
     |> hide("##{id}-container")
     |> JS.hide(to: "##{id}", transition: {"block", "block", "hidden"})
+    |> JS.remove_class("overflow-hidden", to: "body")
     |> JS.pop_focus()
   end
 
diff --git a/installer/templates/phx_web/components/layouts/root.html.heex b/installer/templates/phx_web/components/layouts/root.html.heex
index a2fad7ea5..aa2e9961b 100644
--- a/installer/templates/phx_web/components/layouts/root.html.heex
+++ b/installer/templates/phx_web/components/layouts/root.html.heex
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="en" style="scrollbar-gutter: stable;">
   <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
diff --git a/installer/templates/phx_web/controllers/error_html.ex b/installer/templates/phx_web/controllers/error_html.ex
index 0a9df6221..9d575e7da 100644
--- a/installer/templates/phx_web/controllers/error_html.ex
+++ b/installer/templates/phx_web/controllers/error_html.ex
@@ -5,10 +5,10 @@ defmodule <%= @web_namespace %>.ErrorHTML do
   # uncomment the embed_templates/1 call below
   # and add pages to the error directory:
   #
-  #   * lib/<%= @lib_web_name %>/controllers/error/404.html.heex
-  #   * lib/<%= @lib_web_name %>/controllers/error/500.html.heex
+  #   * lib/<%= @lib_web_name %>/controllers/error_html/404.html.heex
+  #   * lib/<%= @lib_web_name %>/controllers/error_html/500.html.heex
   #
-  # embed_templates "error/*"
+  # embed_templates "error_html/*"
 
   # The default is to render a plain text page based on
   # the template name. For example, "404.html" becomes
diff --git a/lib/mix/phoenix/schema.ex b/lib/mix/phoenix/schema.ex
index 4777a31bf..17bf41da0 100644
--- a/lib/mix/phoenix/schema.ex
+++ b/lib/mix/phoenix/schema.ex
@@ -279,7 +279,7 @@ defmodule Mix.Phoenix.Schema do
 
   defp type_to_default(key, t, :create) do
     case t do
-        {:array, _}     -> []
+        {:array, type} -> build_array_values(type, :create)
         {:enum, values} -> build_enum_values(values, :create)
         :integer        -> 42
         :float          -> 120.5
@@ -300,7 +300,7 @@ defmodule Mix.Phoenix.Schema do
   end
   defp type_to_default(key, t, :update) do
     case t do
-        {:array, _}     -> []
+        {:array, type}  -> build_array_values(type, :update)
         {:enum, values} -> build_enum_values(values, :update)
         :integer        -> 43
         :float          -> 456.7
@@ -320,6 +320,17 @@ defmodule Mix.Phoenix.Schema do
     end
   end
 
+  defp build_array_values(:string, :create),
+    do: Enum.map([1,2], &("option#{&1}"))
+  defp build_array_values(:integer, :create),
+    do: [1,2]
+  defp build_array_values(:string, :update),
+    do: ["option1"]
+  defp build_array_values(:integer, :update),
+    do: [1]
+  defp build_array_values(_, _),
+    do: []
+
   defp build_enum_values(values, action) do
     case {action, translate_enum_vals(values)} do
       {:create, vals} -> hd(vals)
diff --git a/lib/mix/tasks/phx.gen.html.ex b/lib/mix/tasks/phx.gen.html.ex
index a6e5419a1..bd2d598e0 100644
--- a/lib/mix/tasks/phx.gen.html.ex
+++ b/lib/mix/tasks/phx.gen.html.ex
@@ -201,17 +201,14 @@ defmodule Mix.Tasks.Phx.Gen.Html do
       {key, :naive_datetime} ->
         ~s(<.input field={{f, #{inspect(key)}}} type="datetime-local" label="#{label(key)}" />)
 
-      {key, {:array, :integer}} ->
-        ~s(<.input field={{f, #{inspect(key)}}} type="datetime-local" label="#{label(key)}" />)
-
-      {key, {:array, _}} ->
+      {key, {:array, _} = type} ->
         ~s"""
         <.input
           field={{f, #{inspect(key)}}}
           type="select"
           multiple
           label="#{label(key)}"
-          options={[{"Option 1", "option1"}, {"Option 2", "option2"}]}
+          options={#{inspect(default_options(type))}}
         />
         """
 
@@ -231,7 +228,15 @@ defmodule Mix.Tasks.Phx.Gen.Html do
     end)
   end
 
-  defp label(key), do: to_string(key)
+  defp default_options({:array, :string}),
+    do: Enum.map([1,2], &({"Option #{&1}", "option#{&1}"}))
+
+  defp default_options({:array, :integer}),
+    do: Enum.map([1,2], &({"#{&1}", &1}))
+
+  defp default_options({:array, _}), do: []
+
+  defp label(key), do: Phoenix.Naming.humanize(to_string(key))
 
   @doc false
   def indent_inputs(inputs, column_padding) do
diff --git a/lib/mix/tasks/phx.gen.json.ex b/lib/mix/tasks/phx.gen.json.ex
index 432b0cd0f..e2c4a8a00 100644
--- a/lib/mix/tasks/phx.gen.json.ex
+++ b/lib/mix/tasks/phx.gen.json.ex
@@ -97,7 +97,13 @@ defmodule Mix.Tasks.Phx.Gen.Json do
     {context, schema} = Gen.Context.build(args)
     Gen.Context.prompt_for_code_injection(context)
 
-    binding = [context: context, schema: schema]
+    binding = [
+      context: context,
+      schema: schema,
+      core_components?: Code.ensure_loaded?(Module.concat(context.web_module, "CoreComponents")),
+      gettext?: Code.ensure_loaded?(Module.concat(context.web_module, "Gettext"))
+    ]
+
     paths = Mix.Phoenix.generator_paths()
 
     prompt_for_conflicts(context)
diff --git a/lib/phoenix/channel.ex b/lib/phoenix/channel.ex
index 8636e734f..8080aff3c 100644
--- a/lib/phoenix/channel.ex
+++ b/lib/phoenix/channel.ex
@@ -68,7 +68,7 @@ defmodule Phoenix.Channel do
       end
 
   ## Broadcasts
- 
+
   Here's an example of receiving an incoming `"new_msg"` event from one client,
   and broadcasting the message to all topic subscribers for this socket.
 
@@ -125,7 +125,7 @@ defmodule Phoenix.Channel do
   `reply/2`.
 
   ## Pushes
-  
+
   Calling `push/3` allows you to send a message to the client which is not a
   reply to a specific client message. Because it is not a reply, a pushed
   message does not contain a client message `ref`; there is no prior client
@@ -228,12 +228,12 @@ defmodule Phoenix.Channel do
   `terminate/2`, however, won't be invoked in case of errors nor in
   case of exits. This is the same behaviour as you find in Elixir
   abstractions like `GenServer` and others. Similar to `GenServer`,
-  it would also be possible `:trap_exit` to guarantee that `terminate/2`
+  it would also be possible to `:trap_exit` to guarantee that `terminate/2`
   is invoked. This practice is not encouraged though.
 
-  Typically speaking, if you want to clean something up, it is better to
+  Generally speaking, if you want to clean something up, it is better to
   monitor your channel process and do the clean up from another process.
-  All channel callbacks including `join/3` are called from within the
+  All channel callbacks, including `join/3`, are called from within the
   channel process. Therefore, `self()` in any of them returns the PID to
   be monitored.
 
@@ -324,12 +324,13 @@ defmodule Phoenix.Channel do
 
   ## Shutdown
 
-  You can configure the shutdown of each channel used when your application
-  is shutting down by setting the `:shutdown` value on use:
+  You can configure the shutdown behavior of each channel used when your
+  application is shutting down by setting the `:shutdown` value on use:
 
       use Phoenix.Channel, shutdown: 5_000
 
-  It defaults to 5_000.
+  It defaults to 5_000. The supported values are described under the
+  in the `Supervisor` module docs.
 
   ## Logging
 
diff --git a/lib/phoenix/controller.ex b/lib/phoenix/controller.ex
index 98f20d571..53bfdd4f4 100644
--- a/lib/phoenix/controller.ex
+++ b/lib/phoenix/controller.ex
@@ -6,7 +6,7 @@ defmodule Phoenix.Controller do
   require Phoenix.Endpoint
 
   @unsent [:unset, :set, :set_chunked, :set_file]
-  
+
   @type view :: atom()
   @type layout :: {module(), layout_name :: atom()} | false
 
@@ -25,7 +25,7 @@ defmodule Phoenix.Controller do
 
         def show(conn, %{"id" => id}) do
           user = Repo.get(User, id)
-          render(conn, "show.html", user: user)
+          render(conn, :show, user: user)
         end
       end
 
@@ -33,16 +33,9 @@ defmodule Phoenix.Controller do
   and the request parameters as arguments. The connection is a
   `Plug.Conn` struct, as specified by the Plug library.
 
-  ## Options
-
-  When used, the controller supports the following options:
-
-    * `:namespace` - sets the namespace to properly inflect
-      the layout view. By default it uses the base alias
-      in your controller name
-
-    * `:put_default_views` - controls whether the default view
-      and layout should be set or not
+  Then we invoke `render/3`, passing the connection, the template
+  to render (typically named after the action), and the `user: user`
+  as assigns. We will explore all of those concepts next.
 
   ## Connection
 
@@ -61,6 +54,73 @@ defmodule Phoenix.Controller do
   without fully implementing the controller, you can import both
   modules directly instead of `use Phoenix.Controller`.
 
+  ## Rendering and layouts
+
+  One of the main features provided by controllers is the ability
+  to perform content negotiation and render templates based on
+  information sent by the client.
+
+  There are two ways to render content in a controller. One option
+  is to invoke format-specific functions, such as `html/2` and `json/2`.
+
+  However, most commonly controllers invoke custom modules called
+  views. Views are modules capable of rendering a custom format.
+  This is done by specifying the option `:formats` when defining
+  the controller:
+
+      use Phoenix.Controller,
+        formats: [:html, :json]
+
+   Now, when invoking `render/3`, a controller named `MyAppWeb.UserController`
+   will invoke `MyAppWeb.UserHTML` and `MyAppWeb.UserJSON` respectively
+   when rendering each format:
+
+      def show(conn, %{"id" => id}) do
+        user = Repo.get(User, id)
+        # Will invoke UserHTML.show(%{user: user}) for html requests
+        # Will invoke UserJSON.show(%{user: user}) for json requests
+        render(conn, :show, user: user)
+      end
+
+  Some formats are also handy to have layouts, which render content
+  shared across all pages. We can also specify layouts on `use`:
+
+      use Phoenix.Controller,
+        formats: [:html, :json],
+        layouts: [html: MyAppWeb.Layouts]
+
+  You can also specify formats and layouts to render by calling
+  `put_view/2` and `put_layout/2` directly with a connection.
+  The line above can also be written directly in your actions as:
+
+      conn
+      |> put_view(html: MyAppWeb.UserHTML, json: MyAppWeb.UserJSON)
+      |> put_layout(html: MyAppWeb.Layouts)
+
+  ### Options
+
+  When used, the controller supports the following options to customize
+  template rendering:
+
+    * `:formats` - the formats this controller will render
+      by default. For example, specifying `formats: [:html, :json]`
+      for a controller named `MyAppWeb.UserController` will
+      invoke `MyAppWeb.UserHTML` and `MyAppWeb.UserJSON` when
+      respectively rendering each format. If `:formats` is not
+      set, the default view is set to `MyAppWeb.UserView`
+
+    * `:layouts` - which layouts to render for each format,
+      for example: `[html: DemoWeb.Layouts]`
+
+  Deprecated options:
+
+    * `:namespace` - sets the namespace for the layout. Use
+      `:layouts` instead
+
+    * `:put_default_views` - controls whether the default view
+      and layout should be set or not. Set `formats: []` and
+      `layouts: []` instead
+
   ## Plug pipeline
 
   As with routers, controllers also have their own plug pipeline.
@@ -150,18 +210,15 @@ defmodule Phoenix.Controller do
         # ...
       end
 
-  ## Rendering and layouts
-
-  One of the main features provided by controllers is the ability
-  to perform content negotiation and render templates based on
-  information sent by the client. Read `render/3` to learn more.
-
-  It is also important not to confuse `Phoenix.Controller.render/3`
-  with `Phoenix.View.render/3`. The former expects
-  a connection and relies on content negotiation while the latter is
-  connection-agnostic and typically invoked from your views.
   """
   defmacro __using__(opts) do
+    opts =
+      if Macro.quoted_literal?(opts) do
+        Macro.prewalk(opts, &expand_alias(&1, __CALLER__))
+      else
+        opts
+      end
+
     quote bind_quoted: [opts: opts] do
       import Phoenix.Controller
 
@@ -177,6 +234,11 @@ defmodule Phoenix.Controller do
     end
   end
 
+  defp expand_alias({:__aliases__, _, _} = alias, env),
+    do: Macro.expand(alias, %{env | function: {:action, 2}})
+
+  defp expand_alias(other, _env), do: other
+
   @doc """
   Registers the plug to call as a fallback to the controller action.
 
@@ -446,15 +508,15 @@ defmodule Phoenix.Controller do
   Stores the view for rendering.
 
   Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
-  
+
   ## Examples
-  
+
       # Use single view module
       iex> put_view(conn, AppView)
-      
+
       # Use multiple view module for content negotiation
       iex> put_view(conn, html: AppHTML, json: AppJSON)
-      
+
   """
   @spec put_view(Plug.Conn.t(), [{format :: atom, view}] | view) :: Plug.Conn.t()
   def put_view(%Plug.Conn{state: state} = conn, formats) when state in @unsent do
@@ -536,15 +598,11 @@ defmodule Phoenix.Controller do
       iex> layout(conn)
       false
 
-      iex> conn = put_layout conn, {AppView, "application.html"}
-      iex> layout(conn)
-      {AppView, "application.html"}
-
-      iex> conn = put_layout conn, "print.html"
+      iex> conn = put_layout(conn, {AppView, :application})
       iex> layout(conn)
-      {AppView, "print.html"}
+      {AppView, :application}
 
-      iex> conn = put_layout conn, :print
+      iex> conn = put_layout(conn, :print)
       iex> layout(conn)
       {AppView, :print}
 
@@ -635,15 +693,11 @@ defmodule Phoenix.Controller do
       iex> root_layout(conn)
       false
 
-      iex> conn = put_root_layout conn, {AppView, "root.html"}
-      iex> root_layout(conn)
-      {AppView, "root.html"}
-
-      iex> conn = put_root_layout conn, "bare.html"
+      iex> conn = put_root_layout(conn, {AppView, :root})
       iex> root_layout(conn)
-      {AppView, "bare.html"}
+      {AppView, :root}
 
-      iex> conn = put_root_layout conn, :bare
+      iex> conn = put_root_layout(conn, :bare)
       iex> root_layout(conn)
       {AppView, :bare}
 
@@ -1758,7 +1812,7 @@ defmodule Phoenix.Controller do
 
           other ->
             raise ArgumentError, """
-            expected :layouts to be a list of format module pairs of the form: [html: DemoWEb.Layouts] or [html: {DemoWeb.Layouts, :app}]
+            expected :layouts to be a list of format module pairs of the form: [html: DemoWeb.Layouts] or [html: {DemoWeb.Layouts, :app}]
 
             Got: #{inspect(other)}
             """
diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex
index 072d0eb1e..e740b59de 100644
--- a/lib/phoenix/endpoint.ex
+++ b/lib/phoenix/endpoint.ex
@@ -115,7 +115,7 @@ defmodule Phoenix.Endpoint do
       detect if the client is running on the latest version of all assets.
 
     * `:cache_manifest_skip_vsn` - when true, skips the appended query string
-      "?vsn=d" when generatic paths to static assets. This query string is used
+      "?vsn=d" when generating paths to static assets. This query string is used
       by `Plug.Static` to set long expiry dates, therefore, you should set this
       option to true only if you are not using `Plug.Static` to serve assets,
       for example, if you are using a CDN. If you are setting this option, you
@@ -606,7 +606,7 @@ defmodule Phoenix.Endpoint do
           {path, plug, conn_ast, plug_opts} <- socket_paths(module, path, socket, socket_opts) do
         quote do
           defp do_socket_dispatch(unquote(path), conn) do
-            unquote(plug).call(unquote(conn_ast), unquote(Macro.escape(plug_opts)))
+            halt(unquote(plug).call(unquote(conn_ast), unquote(Macro.escape(plug_opts))))
           end
         end
       end
diff --git a/lib/phoenix/endpoint/supervisor.ex b/lib/phoenix/endpoint/supervisor.ex
index 49149704a..a13fb9479 100644
--- a/lib/phoenix/endpoint/supervisor.ex
+++ b/lib/phoenix/endpoint/supervisor.ex
@@ -406,7 +406,7 @@ defmodule Phoenix.Endpoint.Supervisor do
   end
 
   defp browser_open(endpoint, conf) do
-    if Application.get_env(:phoenix, :browser_open) && server?(conf) do
+    if Application.get_env(:phoenix, :browser_open, false) && server?(conf) do
       url = endpoint.url()
 
       {cmd, args} =
diff --git a/lib/phoenix/presence.ex b/lib/phoenix/presence.ex
index a062e5c5f..87983cfa1 100644
--- a/lib/phoenix/presence.ex
+++ b/lib/phoenix/presence.ex
@@ -504,7 +504,7 @@ defmodule Phoenix.Presence do
   def handle_info({task_ref, {:phoenix, ref, computed_diffs}}, state) do
     %{current_task: current_task} = state
     {^ref, %Task{ref: ^task_ref} = task} = current_task
-    {:exit, _} = Task.shutdown(task)
+    Task.shutdown(task)
 
     Enum.each(computed_diffs, fn {topic, presence_diff} ->
       Phoenix.Channel.Server.local_broadcast(
diff --git a/lib/phoenix/verified_routes.ex b/lib/phoenix/verified_routes.ex
index 858e2e371..69e734bd0 100644
--- a/lib/phoenix/verified_routes.ex
+++ b/lib/phoenix/verified_routes.ex
@@ -111,8 +111,14 @@ defmodule Phoenix.VerifiedRoutes do
 
   defmacro __using__(opts) do
     opts =
-      if Macro.quoted_literal?(opts) do
-        Macro.prewalk(opts, &expand_alias(&1, __CALLER__))
+      if Keyword.keyword?(opts) do
+        for {k, v} <- opts do
+          if Macro.quoted_literal?(v) do
+            {k, Macro.prewalk(v, &expand_alias(&1, __CALLER__))}
+          else
+            {k, v}
+          end
+        end
       else
         opts
       end
diff --git a/mix.exs b/mix.exs
index a474082ae..17873b6a3 100644
--- a/mix.exs
+++ b/mix.exs
@@ -55,7 +55,6 @@ defmodule Phoenix.MixProject do
       mod: {Phoenix, []},
       extra_applications: [:logger, :eex, :crypto, :public_key],
       env: [
-        browser_open: false,
         logger: true,
         stacktrace_depth: nil,
         filter_parameters: ["password"],
@@ -146,6 +145,7 @@ defmodule Phoenix.MixProject do
       "guides/components.md",
       "guides/ecto.md",
       "guides/contexts.md",
+      "guides/json_and_apis.md",
       "guides/mix_tasks.md",
       "guides/telemetry.md",
       "guides/asset_management.md",
diff --git a/priv/templates/phx.gen.auth/reset_password_edit.html.heex b/priv/templates/phx.gen.auth/reset_password_edit.html.heex
index 00f0ab0eb..1b3cdc7be 100644
--- a/priv/templates/phx.gen.auth/reset_password_edit.html.heex
+++ b/priv/templates/phx.gen.auth/reset_password_edit.html.heex
@@ -1,7 +1,6 @@
 <div class="mx-auto max-w-sm">
   <.header class="text-center">
-    Forgot your password?
-    <:subtitle>We'll send a password reset link to your inbox</:subtitle>
+    Reset Password
   </.header>
 
   <.simple_form :let={f} for={@changeset} action={~p"<%= schema.route_prefix %>/reset_password/#{@token}"}>
@@ -9,11 +8,13 @@
       Oops, something went wrong! Please check the errors below.
     </.error>
 
-    <.input field={{f, :email}} type="email" placeholder="Email" required />
+    <.input field={{f, :password}} type="password" label="New Password" required />
+    <.input field={{f, :password_confirmation}} type="password" label="Confirm new password" required />
     <:actions>
-      <.button phx-disable-with="Sending..." class="w-full">
-        Send password reset instructions
+      <.button phx-disable-with="Resetting..." class="w-full">
+        Reset password
       </.button>
     </:actions>
   </.simple_form>
 </div>
+
diff --git a/priv/templates/phx.gen.embedded/embedded_schema.ex b/priv/templates/phx.gen.embedded/embedded_schema.ex
index e3acfb81a..fe815b932 100644
--- a/priv/templates/phx.gen.embedded/embedded_schema.ex
+++ b/priv/templates/phx.gen.embedded/embedded_schema.ex
@@ -3,9 +3,10 @@ defmodule <%= inspect schema.module %> do
   import Ecto.Changeset
   alias <%= inspect schema.module %>
 
-  embedded_schema do
-<%= Mix.Phoenix.Schema.format_fields_for_schema(schema) %>
-  end
+  embedded_schema do <%= if !Map.equal?(schema.types, %{}) do %>
+<%= Mix.Phoenix.Schema.format_fields_for_schema(schema) %><% end %>
+<%= for {_, k, _, _} <- schema.assocs do %>    field <%= inspect k %>, <%= if schema.binary_id do %>:binary_id<% else %>:id<% end %>
+<% end %>  end
 
   @doc false
   def changeset(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
diff --git a/priv/templates/phx.gen.json/changeset_json.ex b/priv/templates/phx.gen.json/changeset_json.ex
index 77f511f6d..89b1aa1d1 100644
--- a/priv/templates/phx.gen.json/changeset_json.ex
+++ b/priv/templates/phx.gen.json/changeset_json.ex
@@ -1,20 +1,39 @@
 defmodule <%= inspect context.web_module %>.ChangesetJSON do
-  @doc """
-  Traverses and translates changeset errors.
-
-  See `Ecto.Changeset.traverse_errors/2` and
-  `<%= inspect context.web_module %>.CoreCompponents.translate_error/1` for more details.
-  """
-  def translate_errors(changeset) do
-    Ecto.Changeset.traverse_errors(changeset, &<%= inspect context.web_module %>.CoreComponents.translate_error/1)
-  end
-
   @doc """
   Renders changeset errors.
-  """
+  """<%= if core_components? do %>
+  def error(%{changeset: changeset}) do
+    # When encoded, the changeset returns its errors
+    # as a JSON object. So we just pass it forward.
+    %{errors: Ecto.Changeset.traverse_errors(changeset, &<%= inspect context.web_module %>.CoreComponents.translate_error/1)}
+  end<% else %>
   def error(%{changeset: changeset}) do
     # When encoded, the changeset returns its errors
     # as a JSON object. So we just pass it forward.
-    %{errors: translate_errors(changeset)}
+    %{errors: Ecto.Changeset.traverse_errors(changeset, &translate_error/1)}
+  end
+<%= if gettext? do %>
+  defp translate_error({msg, opts}) do
+    # set by Ecto and indicates we should also apply plural rules.
+    if count = opts[:count] do
+      Gettext.dngettext(<%= inspect context.web_module %>.Gettext, "errors", msg, msg, count, opts)
+    else
+      Gettext.dgettext(<%= inspect context.web_module %>.Gettext, "errors", msg, opts)
+    end
   end
+<% else %>
+  defp translate_error({msg, opts}) do
+    # You can make use of gettext to translate error messages by
+    # uncommenting and adjusting the following code:
+
+    # if count = opts[:count] do
+    #   Gettext.dngettext(<%= inspect context.web_module %>.Gettext, "errors", msg, msg, count, opts)
+    # else
+    #   Gettext.dgettext(<%= inspect context.web_module %>.Gettext, "errors", msg, opts)
+    # end
+
+    Enum.reduce(opts, msg, fn {key, value}, acc ->
+      String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
+    end)
+  end<% end %><% end %>
 end
diff --git a/priv/templates/phx.gen.live/core_components.ex b/priv/templates/phx.gen.live/core_components.ex
index 8ec842aea..d504b5361 100644
--- a/priv/templates/phx.gen.live/core_components.ex
+++ b/priv/templates/phx.gen.live/core_components.ex
@@ -47,7 +47,12 @@ defmodule <%= @web_namespace %>.CoreComponents do
 
   def modal(assigns) do
     ~H"""
-    <div id={@id} phx-mounted={@show && show_modal(@id)} class="relative z-50 hidden">
+    <div
+      id={@id}
+      phx-mounted={@show && show_modal(@id)}
+      phx-remove={hide_modal(@id)}
+      class="relative z-50 hidden"
+    >
       <div id={"#{@id}-bg"} class="fixed inset-0 bg-zinc-50/90 transition-opacity" aria-hidden="true" />
       <div
         class="fixed inset-0 overflow-y-auto"
@@ -82,7 +87,11 @@ defmodule <%= @web_namespace %>.CoreComponents do
                   <h1 id={"#{@id}-title"} class="text-lg font-semibold leading-8 text-zinc-800">
                     <%%= render_slot(@title) %>
                   </h1>
-                  <p :if={@subtitle != []} class="mt-2 text-sm leading-6 text-zinc-600">
+                  <p
+                    :if={@subtitle != []}
+                    id={"#{@id}-description"}
+                    class="mt-2 text-sm leading-6 text-zinc-600"
+                  >
                     <%%= render_slot(@subtitle) %>
                   </p>
                 </header>
@@ -259,8 +268,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
   attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
   attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
-  attr :rest, :global, include: ~w(autocomplete disabled form max maxlength min minlength
-                                   pattern placeholder readonly required size step)
+  attr :rest, :global, include: ~w(autocomplete cols disabled form max maxlength min minlength
+                                   pattern placeholder readonly required rows size step)
   slot :inner_block
 
   def input(%{field: {f, field}} = assigns) do
@@ -330,7 +339,6 @@ defmodule <%= @web_namespace %>.CoreComponents do
         ]}
         {@rest}
       >
-
     <%%= @value %></textarea>
       <.error :for={msg <- @errors}><%%= msg %></.error>
     </div>
@@ -568,6 +576,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       transition: {"transition-all transform ease-out duration-300", "opacity-0", "opacity-100"}
     )
     |> show("##{id}-container")
+    |> JS.add_class("overflow-hidden", to: "body")
     |> JS.focus_first(to: "##{id}-content")
   end
 
@@ -579,6 +588,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
     )
     |> hide("##{id}-container")
     |> JS.hide(to: "##{id}", transition: {"block", "block", "hidden"})
+    |> JS.remove_class("overflow-hidden", to: "body")
     |> JS.pop_focus()
   end
 
diff --git a/priv/templates/phx.gen.presence/presence.ex b/priv/templates/phx.gen.presence/presence.ex
index 204ef333c..de5d98d61 100644
--- a/priv/templates/phx.gen.presence/presence.ex
+++ b/priv/templates/phx.gen.presence/presence.ex
@@ -5,6 +5,7 @@ defmodule <%= module %> do
   See the [`Phoenix.Presence`](https://hexdocs.pm/phoenix/Phoenix.Presence.html)
   docs for more details.
   """
-  use Phoenix.Presence, otp_app: <%= inspect otp_app %>,
-                        pubsub_server: <%= inspect pubsub_server %>
+  use Phoenix.Presence,
+    otp_app: <%= inspect otp_app %>,
+    pubsub_server: <%= inspect pubsub_server %>
 end


Test patch:
diff --git a/installer/test/phx_new_test.exs b/installer/test/phx_new_test.exs
index b12b5490b..71b9f1e4a 100644
--- a/installer/test/phx_new_test.exs
+++ b/installer/test/phx_new_test.exs
@@ -320,7 +320,6 @@ defmodule Mix.Tasks.Phx.NewTest do
       # No assets & No HTML
       refute_file("phx_blog/priv/static/assets/app.css")
       refute_file("phx_blog/priv/static/favicon.ico")
-      refute_file("phx_blog/priv/static/images/phoenix.png")
       refute_file("phx_blog/priv/static/assets/app.js")
 
       # No Ecto
@@ -519,7 +518,6 @@ defmodule Mix.Tasks.Phx.NewTest do
       assert_file("phx_blog/priv/static/assets/app.css")
       assert_file("phx_blog/priv/static/assets/app.js")
       assert_file("phx_blog/priv/static/favicon.ico")
-      assert_file("phx_blog/priv/static/images/phoenix.png")
 
       assert_file("phx_blog/config/config.exs", fn file ->
         refute file =~ "config :esbuild"
@@ -578,11 +576,6 @@ defmodule Mix.Tasks.Phx.NewTest do
       assert_file("custom_path/mix.exs", ~r/app: :phx_blog/)
       assert_file("custom_path/lib/phx_blog_web/endpoint.ex", ~r/app: :phx_blog/)
       assert_file("custom_path/config/config.exs", ~r/namespace: PhoteuxBlog/)
-
-      assert_file(
-        "custom_path/lib/phx_blog_web.ex",
-        ~r/use Phoenix.Controller,\n.*namespace: PhoteuxBlogWeb/
-      )
     end)
   end
 
diff --git a/installer/test/phx_new_umbrella_test.exs b/installer/test/phx_new_umbrella_test.exs
index 05318881f..99bd4f160 100644
--- a/installer/test/phx_new_umbrella_test.exs
+++ b/installer/test/phx_new_umbrella_test.exs
@@ -184,7 +184,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
       assert_file(web_path(@app, "assets/css/app.css"))
 
       assert_file(web_path(@app, "priv/static/favicon.ico"))
-      assert_file(web_path(@app, "priv/static/images/phoenix.png"))
 
       refute File.exists?(web_path(@app, "priv/static/assets/app.css"))
       refute File.exists?(web_path(@app, "priv/static/assets/app.js"))
@@ -345,7 +344,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
       refute_file(web_path(@app, "priv/static/assets/app.js"))
       refute_file(web_path(@app, "priv/static/assets/app.css"))
       refute_file(web_path(@app, "priv/static/favicon.ico"))
-      refute_file(web_path(@app, "priv/static/images/phoenix.png"))
 
       # No Ecto
       config = ~r/config :phx_umb, PhxUmb.Repo,/
@@ -510,7 +508,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
       assert_file(web_path(@app, "priv/static/assets/app.js"))
       assert_file(web_path(@app, "priv/static/assets/app.css"))
       assert_file(web_path(@app, "priv/static/favicon.ico"))
-      assert_file(web_path(@app, "priv/static/images/phoenix.png"))
     end)
   end
 
@@ -559,11 +556,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
         ~r/app: :#{@app}_web/
       )
 
-      assert_file(
-        "custom_path_umbrella/apps/phx_umb_web/lib/#{@app}_web.ex",
-        ~r/use Phoenix.Controller,\n.*namespace: PhoteuxBlogWeb/
-      )
-
       assert_file(
         "custom_path_umbrella/apps/phx_umb/lib/phx_umb/application.ex",
         ~r/defmodule PhoteuxBlog.Application/
@@ -833,7 +825,6 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
         # assets
         assert_file("another/.gitignore", ~r/\n$/)
         assert_file("another/priv/static/favicon.ico")
-        assert_file("another/priv/static/images/phoenix.png")
         assert_file("another/assets/css/app.css")
 
         refute File.exists?("another/priv/static/assets/app.css")
diff --git a/lib/phoenix/test/conn_test.ex b/lib/phoenix/test/conn_test.ex
index 013af32ca..520938bbf 100644
--- a/lib/phoenix/test/conn_test.ex
+++ b/lib/phoenix/test/conn_test.ex
@@ -589,6 +589,7 @@ defmodule Phoenix.ConnTest do
   def redirected_params(%Plug.Conn{} = conn, status \\ 302) do
     router = Phoenix.Controller.router_module(conn)
     %URI{path: path, host: host} = conn |> redirected_to(status) |> URI.parse()
+    path = remove_script_name(conn, router, path)
 
     case Phoenix.Router.route_info(router, "GET", path, host || conn.host) do
       :error ->
@@ -598,6 +599,17 @@ defmodule Phoenix.ConnTest do
     end
   end
 
+  defp remove_script_name(conn, router, path) do
+    case conn.private[router] do
+      [_ | _] = list ->
+        script_name = "/" <> Enum.join(list, ",")
+        String.replace_leading(path, script_name, "")
+
+      _ ->
+        path
+    end
+  end
+
   @doc """
   Returns the matched params of the URL for the `%Plug.Conn{}`'s router.
 
diff --git a/priv/templates/phx.gen.auth/reset_password_controller_test.exs b/priv/templates/phx.gen.auth/reset_password_controller_test.exs
index 8ce98ab98..99594fcbc 100644
--- a/priv/templates/phx.gen.auth/reset_password_controller_test.exs
+++ b/priv/templates/phx.gen.auth/reset_password_controller_test.exs
@@ -60,7 +60,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
     test "renders reset password", %{conn: conn, token: token} do
       conn = get(conn, ~p"<%= schema.route_prefix %>/reset_password/#{token}")
-      assert html_response(conn, 200) =~ "Send password reset instructions"
+      assert html_response(conn, 200) =~ "Reset password"
     end
 
     test "does not render reset password with invalid token", %{conn: conn} do
diff --git a/test/mix/phoenix_test.exs b/test/mix/phoenix_test.exs
index 2fde37a23..fce3de3f6 100644
--- a/test/mix/phoenix_test.exs
+++ b/test/mix/phoenix_test.exs
@@ -18,6 +18,7 @@ defmodule Mix.PhoenixTest do
   test "attrs/1 defaults each type" do
     attrs = [
       "logins:array:string",
+      "lottery_numbers:array:integer",
       "age:integer",
       "temp:float",
       "temp_2:decimal",
@@ -32,6 +33,7 @@ defmodule Mix.PhoenixTest do
 
     assert Mix.Phoenix.Schema.attrs(attrs) == [
              logins: {:array, :string},
+             lottery_numbers: {:array, :integer},
              age: :integer,
              temp: :float,
              temp_2: :decimal,
@@ -71,7 +73,7 @@ defmodule Mix.PhoenixTest do
     ]
 
     assert Mix.Phoenix.Schema.params(params) == %{
-             logins: [],
+             logins: ["option1", "option2"],
              age: 42,
              temp: 120.5,
              temp_2: "120.5",
@@ -110,6 +112,9 @@ defmodule Mix.PhoenixTest do
     assert Mix.Phoenix.Schema.live_form_value(~U[2020-10-09T14:00:00Z]) ==
              "2020-10-09T14:00:00Z"
 
+    assert Mix.Phoenix.Schema.live_form_value([1]) == [1]
+    assert Mix.Phoenix.Schema.live_form_value(["option1"]) == ["option1"]
+
     assert Mix.Phoenix.Schema.live_form_value(:value) == :value
   end
 
diff --git a/test/mix/tasks/phx.gen.cert_test.exs b/test/mix/tasks/phx.gen.cert_test.exs
index 7e8c66090..06d5a30c9 100644
--- a/test/mix/tasks/phx.gen.cert_test.exs
+++ b/test/mix/tasks/phx.gen.cert_test.exs
@@ -56,7 +56,7 @@ defmodule Mix.Tasks.Phx.CertTest do
 
       # We don't actually verify the server cert contents, we just check that
       # the client and server are able to complete the TLS handshake
-      assert {:ok, client} = :ssl.connect('localhost', port, [], @timeout)
+      assert {:ok, client} = :ssl.connect('localhost', port, [verify: :verify_none], @timeout)
       :ssl.close(client)
       :ssl.close(server)
     end)
diff --git a/test/mix/tasks/phx.gen.embedded_test.exs b/test/mix/tasks/phx.gen.embedded_test.exs
index e0526f8d7..df47f5702 100644
--- a/test/mix/tasks/phx.gen.embedded_test.exs
+++ b/test/mix/tasks/phx.gen.embedded_test.exs
@@ -91,4 +91,18 @@ defmodule Mix.Tasks.Phx.Gen.EmbeddedTest do
       end)
     end)
   end
+
+  test "generates embedded schema with references", config do
+    in_tmp_project(config.test, fn ->
+      Gen.Embedded.run(
+        ~w(Blog.Comment comments body word_count:integer author_id:references:author)
+      )
+
+      assert_file("lib/phoenix/blog/comment.ex", fn file ->
+        assert file =~ "field :author_id, :id"
+        assert file =~ "field :body, :string"
+        assert file =~ "field :word_count, :integer"
+      end)
+    end)
+  end
 end
diff --git a/test/mix/tasks/phx.gen.html_test.exs b/test/mix/tasks/phx.gen.html_test.exs
index d1168a594..435df6ee4 100644
--- a/test/mix/tasks/phx.gen.html_test.exs
+++ b/test/mix/tasks/phx.gen.html_test.exs
@@ -158,7 +158,7 @@ defmodule Mix.Tasks.Phx.Gen.HtmlTest do
         assert_file("lib/phoenix_web/controllers/post_html/#{filename}", fn file ->
           assert file =~ ~s(<.input field={{f, :title}} type="text")
           assert file =~ ~s(<.input field={{f, :votes}} type="number")
-          assert file =~ ~s(<.input field={{f, :cost}} type="number" label="cost" step="any")
+          assert file =~ ~s(<.input field={{f, :cost}} type="number" label="Cost" step="any")
           assert file =~ """
             <.input
               field={{f, :tags}}
@@ -171,7 +171,7 @@ defmodule Mix.Tasks.Phx.Gen.HtmlTest do
           assert file =~ ~s(<.input field={{f, :deleted_at}} type="datetime-local")
           assert file =~ ~s(<.input field={{f, :announcement_date}} type="date")
           assert file =~ ~s(<.input field={{f, :alarm}} type="time")
-          assert file =~ ~s(<.input field={{f, :secret}} type="text" label="secret" />)
+          assert file =~ ~s(<.input field={{f, :secret}} type="text" label="Secret" />)
           assert file =~ """
             <.input
               field={{f, :status}}
diff --git a/test/mix/tasks/phx.gen.json_test.exs b/test/mix/tasks/phx.gen.json_test.exs
index cc9475a45..40999e5b4 100644
--- a/test/mix/tasks/phx.gen.json_test.exs
+++ b/test/mix/tasks/phx.gen.json_test.exs
@@ -181,6 +181,10 @@ defmodule Mix.Tasks.Phx.Gen.JsonTest do
         assert file =~ "defmodule PhoenixWeb.Blog.PostJSON"
       end)
 
+      assert_file("lib/phoenix_web/controllers/blog/changeset_json.ex", fn file ->
+        assert file =~ "Ecto.Changeset.traverse_errors(changeset, &translate_error/1)"
+      end)
+
       assert_receive {:mix_shell, :info,
                       [
                         """
@@ -326,4 +330,28 @@ defmodule Mix.Tasks.Phx.Gen.JsonTest do
       end)
     end
   end
+
+  test "with existing core_components.ex file", config do
+    in_tmp_project(config.test, fn ->
+      File.mkdir_p!("lib/phoenix_web/components")
+
+      File.write!("lib/phoenix_web/components/core_components.ex", """
+      defmodule PhoenixWeb.CoreComponents do
+      end
+      """)
+
+      [{module, _}] = Code.compile_file("lib/phoenix_web/components/core_components.ex")
+
+      Gen.Json.run(~w(Blog Post posts title:string --web Blog))
+
+      assert_file("lib/phoenix_web/controllers/blog/changeset_json.ex", fn file ->
+        assert file =~
+                 "Ecto.Changeset.traverse_errors(changeset, &PhoenixWeb.CoreComponents.translate_error/1)"
+      end)
+
+      # Clean up test case specific compile artifact so it doesn't leak to other test cases
+      :code.purge(module)
+      :code.delete(module)
+    end)
+  end
 end
diff --git a/test/mix/tasks/phx.gen.live_test.exs b/test/mix/tasks/phx.gen.live_test.exs
index 2fcf90665..32fb35cb2 100644
--- a/test/mix/tasks/phx.gen.live_test.exs
+++ b/test/mix/tasks/phx.gen.live_test.exs
@@ -102,7 +102,7 @@ defmodule Mix.Tasks.Phx.Gen.LiveTest do
         assert file =~ ~s(<.simple_form\n        :let={f}\n        for={@changeset}\n)
         assert file =~ ~s(<.input field={{f, :title}} type="text")
         assert file =~ ~s(<.input field={{f, :votes}} type="number")
-        assert file =~ ~s(<.input field={{f, :cost}} type="number" label="cost" step="any")
+        assert file =~ ~s(<.input field={{f, :cost}} type="number" label="Cost" step="any")
         assert file =~ """
                 <.input
                   field={{f, :tags}}
@@ -115,7 +115,7 @@ defmodule Mix.Tasks.Phx.Gen.LiveTest do
         assert file =~ ~s(<.input field={{f, :deleted_at}} type="datetime-local")
         assert file =~ ~s(<.input field={{f, :announcement_date}} type="date")
         assert file =~ ~s(<.input field={{f, :alarm}} type="time")
-        assert file =~ ~s(<.input field={{f, :secret}} type="text" label="secret" />)
+        assert file =~ ~s(<.input field={{f, :secret}} type="text" label="Secret" />)
         assert file =~ """
                 <.input
                   field={{f, :status}}
diff --git a/test/phoenix/test/conn_test.exs b/test/phoenix/test/conn_test.exs
index 36dc360b8..1041794e1 100644
--- a/test/phoenix/test/conn_test.exs
+++ b/test/phoenix/test/conn_test.exs
@@ -39,6 +39,7 @@ defmodule Phoenix.Test.ConnTest.Router do
   scope "/" do
     pipe_through :browser
     get "/stat", CatchAll, :stat, private: %{route: :stat}
+    forward "/redir", Phoenix.Test.ConnTest.RedirRouter
     forward "/", CatchAll
   end
 
@@ -438,6 +439,16 @@ defmodule Phoenix.Test.ConnTest do
       assert redirected_params(conn) == %{id: "123"}
     end
 
+    test "with matching forwarded route" do
+      conn =
+        build_conn(:get, "/redir")
+        |> Router.call(Router.init([]))
+        |> put_resp_header("location", "/redir/posts/123")
+        |> send_resp(302, "foo")
+
+      assert redirected_params(conn) == %{id: "123"}
+    end
+
     test "raises Phoenix.Router.NoRouteError for unmatched location" do
       conn =
         build_conn(:get, "/")