Repository: phoenixframework/phoenix
Pull request #5184 (2023-01-01 15:29:21)

Bump parse-url from 7.0.2 to 8.1.0 in /assets
Bumps [parse-url](https://github.com/IonicaBizau/parse-url) from 7.0.2 to 8.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/IonicaBizau/parse-url/releases">parse-url's releases</a>.</em></p>
<blockquote>
<h2>8.1.0</h2>
<h3><code>parse-url@8.1.0</code></h3>
<ul>
<li>fix: cjs to load normalize-url /cc <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/58">#58</a></li>
<li>fix: Include index.d.ts in package.json /cc <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/63">#63</a></li>
<li>feat: support custom SSH username /cc <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/60">#60</a></li>
<li>feat: improve regex pattern /cc <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/59">#59</a></li>
</ul>
<p>Thanks to <a href="https://github.com/privatenumber"><code>@​privatenumber</code></a> and <a href="https://github.com/briancoit"><code>@​briancoit</code></a> for their contributions! :cake:</p>
<h2>8.0.0</h2>
<h3>parse-url 8.0.0</h3>
<p><strong>Breaking Changes</strong></p>
<ul>
<li>The <code>resource</code> property will not contain the port, but the <code>host</code> one will.</li>
<li>Throw an error if the input is invalid. Hence, file paths like <code>/home/path/to/dir</code> will only be valid if the <code>file://</code> protocol is added (<code>file://home/path/to/dir</code>)</li>
<li>Throw an error if the input length exceeds the maximum length (parse.MAX_URL_LENGTH), by default 2048.</li>
</ul>
<p><strong>Fixes</strong></p>
<ul>
<li>fix file protocol spoofing <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/48">#48</a>, thanks <a href="https://github.com/vovikhangcdv"><code>@​vovikhangcdv</code></a>!</li>
<li>fix: support hyphens in git@ URLs (<a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/50">#50</a>) <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/51">#51</a>, thanks <a href="https://github.com/crenshaw-dev"><code>@​crenshaw-dev</code></a>!</li>
<li>fix: support dot in git@ URLS <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/52">#52</a>, thanks <a href="https://github.com/GalHalupSeaLights"><code>@​GalHalupSeaLights</code></a>!</li>
</ul>
<p><strong>Other changes</strong></p>
<ul>
<li>build: add CommonJS distribution thanks to <a href="https://github.com/privatenumber"><code>@​privatenumber</code></a>! /cc <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/54">#54</a> :cake:</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/4412976f34515399f2eabe4d50cef71657e4e238"><code>4412976</code></a> Updated docs</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/ac17353a92e668a34ce82e717be879050c88edb8"><code>ac17353</code></a> Merge branch 'patch-1' of github.com:briancoit/parse-url into new-version</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/778a0a54fcfd0e483419fcae1d93efcbf4718800"><code>778a0a5</code></a> Merge branch 'support-custom-user' of github.com:privatenumber/parse-url into...</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/0baab4fc594d083899fb189f8ff9eb1249b0ec20"><code>0baab4f</code></a> Merge branch 'improve-regex' of github.com:privatenumber/parse-url into new-v...</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/d1a4395bed3a83497beedc47de0d9d186ce749a2"><code>d1a4395</code></a> Merge branch 'fix-cjs' of github.com:privatenumber/parse-url into new-version</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/9cacf38de02db0fb1358bd6ec04543e523cd6a8e"><code>9cacf38</code></a> :arrow_up: 8.1.0 :tada:</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/9a78bd8583c5ad3689656b785f16ae0560b2acbe"><code>9a78bd8</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/IonicaBizau/parse-url/issues/61">#61</a> from privatenumber/move-funding-yml</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/18831365e1b30d1ea6d008b7b2dd0efd929fd316"><code>1883136</code></a> Include index.d.ts in package</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/92f899b60541bea4736cc8b4d246af2eeb40ea8c"><code>92f899b</code></a> chore: move FUNDING.yml out of workflows</li>
<li><a href="https://github.com/IonicaBizau/parse-url/commit/9500430a3b9973bb1b5b2b9b319af2685ad272b3"><code>9500430</code></a> feat: support custom user in ssh url</li>
<li>Additional commits viewable in <a href="https://github.com/IonicaBizau/parse-url/compare/7.0.2...8.1.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=parse-url&package-manager=npm_and_yarn&previous-version=7.0.2&new-version=8.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/phoenixframework/phoenix/network/alerts).

</details>


Patch:
diff --git a/assets/package-lock.json b/assets/package-lock.json
index 19a2a833f..392c190d0 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -2857,9 +2857,9 @@
       }
     },
     "node_modules/documentation": {
-      "version": "14.0.0",
-      "resolved": "https://registry.npmjs.org/documentation/-/documentation-14.0.0.tgz",
-      "integrity": "sha512-4AwFzdiseEdtqR0KKLrruIQ5fvh7n5epg47P0ZyOidA5Fes5am+6xjqkDECHPwcv4pxJ6zITaHwzCoGblP0+JQ==",
+      "version": "14.0.1",
+      "resolved": "https://registry.npmjs.org/documentation/-/documentation-14.0.1.tgz",
+      "integrity": "sha512-Y/brACCE3sNnDJPFiWlhXrqGY+NelLYVZShLGse5bT1KdohP4JkPf5T2KNq1YWhIEbDYl/1tebRLC0WYbPQxVw==",
       "dev": true,
       "dependencies": {
         "@babel/core": "^7.18.10",
@@ -2871,7 +2871,7 @@
         "chokidar": "^3.5.3",
         "diff": "^5.1.0",
         "doctrine-temporary-fork": "2.1.0",
-        "git-url-parse": "^12.0.0",
+        "git-url-parse": "^13.1.0",
         "github-slugger": "1.4.0",
         "glob": "^8.0.3",
         "globals-docs": "^2.4.1",
@@ -3999,22 +3999,22 @@
       }
     },
     "node_modules/git-up": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/git-up/-/git-up-6.0.0.tgz",
-      "integrity": "sha512-6RUFSNd1c/D0xtGnyWN2sxza2bZtZ/EmI9448n6rCZruFwV/ezeEn2fJP7XnUQGwf0RAtd/mmUCbtH6JPYA2SA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz",
+      "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==",
       "dev": true,
       "dependencies": {
         "is-ssh": "^1.4.0",
-        "parse-url": "^7.0.2"
+        "parse-url": "^8.1.0"
       }
     },
     "node_modules/git-url-parse": {
-      "version": "12.0.0",
-      "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-12.0.0.tgz",
-      "integrity": "sha512-I6LMWsxV87vysX1WfsoglXsXg6GjQRKq7+Dgiseo+h0skmp5Hp2rzmcEIRQot9CPA+uzU7x1x7jZdqvTFGnB+Q==",
+      "version": "13.1.0",
+      "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz",
+      "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==",
       "dev": true,
       "dependencies": {
-        "git-up": "^6.0.0"
+        "git-up": "^7.0.0"
       }
     },
     "node_modules/github-slugger": {
@@ -4788,9 +4788,9 @@
       "dev": true
     },
     "node_modules/json5": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
-      "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
       "dev": true,
       "bin": {
         "json5": "lib/cli.js"
@@ -6500,18 +6500,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/normalize-url": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
-      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/nwmatcher": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
@@ -6766,24 +6754,21 @@
       }
     },
     "node_modules/parse-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-5.0.0.tgz",
-      "integrity": "sha512-qOpH55/+ZJ4jUu/oLO+ifUKjFPNZGfnPJtzvGzKN/4oLMil5m9OH4VpOj6++9/ytJcfks4kzH2hhi87GL/OU9A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz",
+      "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==",
       "dev": true,
       "dependencies": {
         "protocols": "^2.0.0"
       }
     },
     "node_modules/parse-url": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-7.0.2.tgz",
-      "integrity": "sha512-PqO4Z0eCiQ08Wj6QQmrmp5YTTxpYfONdOEamrtvK63AmzXpcavIVQubGHxOEwiIoDZFb8uDOoQFS0NCcjqIYQg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz",
+      "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==",
       "dev": true,
       "dependencies": {
-        "is-ssh": "^1.4.0",
-        "normalize-url": "^6.1.0",
-        "parse-path": "^5.0.0",
-        "protocols": "^2.0.1"
+        "parse-path": "^7.0.0"
       }
     },
     "node_modules/parse5": {
@@ -11520,9 +11505,9 @@
       }
     },
     "documentation": {
-      "version": "14.0.0",
-      "resolved": "https://registry.npmjs.org/documentation/-/documentation-14.0.0.tgz",
-      "integrity": "sha512-4AwFzdiseEdtqR0KKLrruIQ5fvh7n5epg47P0ZyOidA5Fes5am+6xjqkDECHPwcv4pxJ6zITaHwzCoGblP0+JQ==",
+      "version": "14.0.1",
+      "resolved": "https://registry.npmjs.org/documentation/-/documentation-14.0.1.tgz",
+      "integrity": "sha512-Y/brACCE3sNnDJPFiWlhXrqGY+NelLYVZShLGse5bT1KdohP4JkPf5T2KNq1YWhIEbDYl/1tebRLC0WYbPQxVw==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.18.10",
@@ -11535,7 +11520,7 @@
         "chokidar": "^3.5.3",
         "diff": "^5.1.0",
         "doctrine-temporary-fork": "2.1.0",
-        "git-url-parse": "^12.0.0",
+        "git-url-parse": "^13.1.0",
         "github-slugger": "1.4.0",
         "glob": "^8.0.3",
         "globals-docs": "^2.4.1",
@@ -12400,22 +12385,22 @@
       }
     },
     "git-up": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/git-up/-/git-up-6.0.0.tgz",
-      "integrity": "sha512-6RUFSNd1c/D0xtGnyWN2sxza2bZtZ/EmI9448n6rCZruFwV/ezeEn2fJP7XnUQGwf0RAtd/mmUCbtH6JPYA2SA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz",
+      "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==",
       "dev": true,
       "requires": {
         "is-ssh": "^1.4.0",
-        "parse-url": "^7.0.2"
+        "parse-url": "^8.1.0"
       }
     },
     "git-url-parse": {
-      "version": "12.0.0",
-      "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-12.0.0.tgz",
-      "integrity": "sha512-I6LMWsxV87vysX1WfsoglXsXg6GjQRKq7+Dgiseo+h0skmp5Hp2rzmcEIRQot9CPA+uzU7x1x7jZdqvTFGnB+Q==",
+      "version": "13.1.0",
+      "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz",
+      "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==",
       "dev": true,
       "requires": {
-        "git-up": "^6.0.0"
+        "git-up": "^7.0.0"
       }
     },
     "github-slugger": {
@@ -13026,9 +13011,9 @@
       "dev": true
     },
     "json5": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
-      "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
       "dev": true
     },
     "jsprim": {
@@ -14230,12 +14215,6 @@
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
       "dev": true
     },
-    "normalize-url": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
-      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
-      "dev": true
-    },
     "nwmatcher": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
@@ -14431,24 +14410,21 @@
       }
     },
     "parse-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-5.0.0.tgz",
-      "integrity": "sha512-qOpH55/+ZJ4jUu/oLO+ifUKjFPNZGfnPJtzvGzKN/4oLMil5m9OH4VpOj6++9/ytJcfks4kzH2hhi87GL/OU9A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz",
+      "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==",
       "dev": true,
       "requires": {
         "protocols": "^2.0.0"
       }
     },
     "parse-url": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-7.0.2.tgz",
-      "integrity": "sha512-PqO4Z0eCiQ08Wj6QQmrmp5YTTxpYfONdOEamrtvK63AmzXpcavIVQubGHxOEwiIoDZFb8uDOoQFS0NCcjqIYQg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz",
+      "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==",
       "dev": true,
       "requires": {
-        "is-ssh": "^1.4.0",
-        "normalize-url": "^6.1.0",
-        "parse-path": "^5.0.0",
-        "protocols": "^2.0.1"
+        "parse-path": "^7.0.0"
       }
     },
     "parse5": {
diff --git a/guides/json_and_apis.md b/guides/json_and_apis.md
index 5daecdd8f..9d78fb0dd 100644
--- a/guides/json_and_apis.md
+++ b/guides/json_and_apis.md
@@ -266,23 +266,13 @@ The goal of this clause is to handle the `{:error, changeset}` return types from
 
 ```elixir
 defmodule HelloWeb.ChangesetJSON do
-  @doc """
-  Traverses and translates changeset errors.
-
-  See `Ecto.Changeset.traverse_errors/2` and
-  `HelloWeb.CoreCompponents.translate_error/1` for more details.
-  """
-  def translate_errors(changeset) do
-    Ecto.Changeset.traverse_errors(changeset, &HelloWeb.CoreComponents.translate_error/1)
-  end
-
   @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: translate_errors(changeset)}
+    %{errors: Ecto.Changeset.traverse_errors(changeset, &HelloWeb.CoreComponents.translate_error/1)}
   end
 end
 ```
diff --git a/guides/routing.md b/guides/routing.md
index cead676be..0ce693c63 100644
--- a/guides/routing.md
+++ b/guides/routing.md
@@ -98,7 +98,7 @@ DELETE  /users/:id       HelloWeb.UserController :delete
 ...
 ```
 
-This is the standard matrix of HTTP verbs, paths, and controller actions. For a while, this was known as RESTful routes, but most consider this a misnomer nowadays. Let's look at them individually, in a slightly different order.
+This is the standard matrix of HTTP verbs, paths, and controller actions. For a while, this was known as RESTful routes, but most consider this a misnomer nowadays. Let's look at them individually.
 
 - A GET request to `/users` will invoke the `index` action to show all the users.
 - A GET request to `/users/:id/edit` will invoke the `edit` action with an ID to retrieve an individual user from the data store and present the information in a form for editing.
diff --git a/installer/templates/phx_single/mix.exs b/installer/templates/phx_single/mix.exs
index 9519dd745..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 @assets do %>, "tailwind.install --if-missing", "esbuild.install --if-missing"<% 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/mix.exs b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
index 516cd1f9f..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 @assets do %>, "tailwind.install --if-missing", "esbuild.install --if-missing"<% end %>]<%= 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 284246445..4b632d353 100644
--- a/installer/templates/phx_web/components/core_components.ex
+++ b/installer/templates/phx_web/components/core_components.ex
@@ -147,7 +147,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       :if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)}
       id={@id}
       phx-mounted={@autoshow && show("##{@id}")}
-      phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("#flash")}
+      phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
       role="alert"
       class={[
         "fixed hidden top-2 right-2 w-80 sm:w-96 z-50 rounded-lg p-3 shadow-md shadow-zinc-900/5 ring-1",
@@ -338,7 +338,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
           "phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400 phx-no-feedback:focus:ring-zinc-800/5"
         ]}
         {@rest}
-      ><%%= @value %></textarea>
+      >
+    <%%= @value %></textarea>
       <.error :for={msg <- @errors}><%%= msg %></.error>
     </div>
     """
diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex
index 5ea3e9ea9..06a1e1b89 100644
--- a/lib/phoenix/endpoint.ex
+++ b/lib/phoenix/endpoint.ex
@@ -188,8 +188,6 @@ defmodule Phoenix.Endpoint do
     * `:live_reload` - configuration for the live reload option.
       Configuration requires a `:patterns` option which should be a list of
       file patterns to watch. When these files change, it will trigger a reload.
-      If you are using a tool like [pow](http://pow.cx) in development,
-      you may need to set the `:url` option appropriately.
 
           live_reload: [
             url: "ws://localhost:4000",
@@ -606,7 +604,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/verified_routes.ex b/lib/phoenix/verified_routes.ex
index 69e734bd0..9856e8067 100644
--- a/lib/phoenix/verified_routes.ex
+++ b/lib/phoenix/verified_routes.ex
@@ -756,6 +756,10 @@ defmodule Phoenix.VerifiedRoutes do
     {static?, test_path, path_ast, static_ast}
   end
 
+  defp attr!(%{function: nil}, _) do
+    raise "Phoenix.VerifiedRoutes can only be used inside functions, please move your usage of ~p to functions"
+  end
+
   defp attr!(env, :endpoint) do
     Module.get_attribute(env.module, :endpoint) ||
       raise """
diff --git a/mix.exs b/mix.exs
index 17873b6a3..250c42bee 100644
--- a/mix.exs
+++ b/mix.exs
@@ -71,6 +71,7 @@ defmodule Phoenix.MixProject do
       {:plug_crypto, "~> 1.2"},
       {:telemetry, "~> 0.4 or ~> 1.0"},
       {:phoenix_pubsub, "~> 2.1"},
+      # TODO drop phoenix_view as an optional dependency in Phoenix v2.0
       {:phoenix_view, "~> 2.0", optional: true},
       {:phoenix_template, "~> 1.0"},
       {:websock_adapter, "~> 0.4"},
diff --git a/priv/templates/phx.gen.auth/confirmation_edit.html.heex b/priv/templates/phx.gen.auth/confirmation_edit.html.heex
index 9e4128f2b..06d1b795e 100644
--- a/priv/templates/phx.gen.auth/confirmation_edit.html.heex
+++ b/priv/templates/phx.gen.auth/confirmation_edit.html.heex
@@ -1,13 +1,15 @@
-<.header>Confirm account</.header>
+<div class="mx-auto max-w-sm">
+  <.header class="text-center">Confirm account</.header>
 
-<.simple_form :let={_f} for={:<%= schema.singular %>} action={~p"<%= schema.route_prefix %>/confirm/#{@token}"}>
-  <:actions>
-    <.button>Confirm my account</.button>
-  </:actions>
-</.simple_form>
+  <.simple_form :let={_f} for={:<%= schema.singular %>} action={~p"<%= schema.route_prefix %>/confirm/#{@token}"}>
+    <:actions>
+      <.button class="w-full">Confirm my account</.button>
+    </:actions>
+  </.simple_form>
 
-<p>
-  <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
-  |
-  <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
-</p>
+  <p class="text-center mt-4">
+    <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+    |
+    <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+  </p>
+</div>
diff --git a/priv/templates/phx.gen.auth/confirmation_live.ex b/priv/templates/phx.gen.auth/confirmation_live.ex
index b6196baf3..125b67bf4 100644
--- a/priv/templates/phx.gen.auth/confirmation_live.ex
+++ b/priv/templates/phx.gen.auth/confirmation_live.ex
@@ -5,20 +5,22 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
   def render(%{live_action: :edit} = assigns) do
     ~H"""
-    <.header>Confirm Account</.header>
-
-    <.simple_form :let={f} for={:<%= schema.singular %>} id="confirmation_form" phx-submit="confirm_account">
-      <.input field={{f, :token}} type="hidden" value={@token} />
-      <:actions>
-        <.button phx-disable-with="Confirming...">Confirm my account</.button>
-      </:actions>
-    </.simple_form>
-
-    <p>
-      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
-      |
-      <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
-    </p>
+    <div class="mx-auto max-w-sm">
+      <.header class="text-center">Confirm Account</.header>
+
+      <.simple_form :let={f} for={:<%= schema.singular %>} id="confirmation_form" phx-submit="confirm_account">
+        <.input field={{f, :token}} type="hidden" value={@token} />
+        <:actions>
+          <.button phx-disable-with="Confirming..." class="w-full">Confirm my account</.button>
+        </:actions>
+      </.simple_form>
+
+      <p class="text-center mt-4">
+        <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+        |
+        <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+      </p>
+    </div>
     """
   end
 
diff --git a/priv/templates/phx.gen.auth/forgot_password_live.ex b/priv/templates/phx.gen.auth/forgot_password_live.ex
index ebed73e15..db0ce3725 100644
--- a/priv/templates/phx.gen.auth/forgot_password_live.ex
+++ b/priv/templates/phx.gen.auth/forgot_password_live.ex
@@ -19,6 +19,11 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
           </.button>
         </:actions>
       </.simple_form>
+      <p class="text-center mt-4">
+        <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+        |
+        <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+      </p>
     </div>
     """
   end
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..3dd5a966a 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,22 @@
       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>
+  <p class="text-center mt-4">
+    <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+    |
+    <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+  </p>
 </div>
diff --git a/priv/templates/phx.gen.auth/reset_password_live.ex b/priv/templates/phx.gen.auth/reset_password_live.ex
index 1785e4997..5d411c1ab 100644
--- a/priv/templates/phx.gen.auth/reset_password_live.ex
+++ b/priv/templates/phx.gen.auth/reset_password_live.ex
@@ -5,36 +5,38 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
   def render(assigns) do
     ~H"""
-    <.header>Reset Password</.header>
+    <div class="mx-auto max-w-sm">
+      <.header class="text-center">Reset Password</.header>
 
-    <.simple_form
-      :let={f}
-      for={@changeset}
-      id="reset_password_form"
-      phx-submit="reset_password"
-      phx-change="validate"
-    >
-      <.error :if={@changeset.action == :insert}>
-        Oops, something went wrong! Please check the errors below.
-      </.error>
+      <.simple_form
+        :let={f}
+        for={@changeset}
+        id="reset_password_form"
+        phx-submit="reset_password"
+        phx-change="validate"
+      >
+        <.error :if={@changeset.action == :insert}>
+          Oops, something went wrong! Please check the errors below.
+        </.error>
 
-      <.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="Resetting...">Reset Password</.button>
-      </:actions>
-    </.simple_form>
+        <.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="Resetting..." class="w-full">Reset Password</.button>
+        </:actions>
+      </.simple_form>
 
-    <p>
-      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
-      |
-      <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
-    </p>
+      <p class="text-center mt-4">
+        <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+        |
+        <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+      </p>
+    </div>
     """
   end
 
diff --git a/priv/templates/phx.gen.auth/reset_password_new.html.heex b/priv/templates/phx.gen.auth/reset_password_new.html.heex
index e2badda06..c7968829d 100644
--- a/priv/templates/phx.gen.auth/reset_password_new.html.heex
+++ b/priv/templates/phx.gen.auth/reset_password_new.html.heex
@@ -12,4 +12,9 @@
       </.button>
     </:actions>
   </.simple_form>
+  <p class="text-center mt-4">
+    <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+    |
+    <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
+  </p>
 </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.live/core_components.ex b/priv/templates/phx.gen.live/core_components.ex
index f9264a307..4b632d353 100644
--- a/priv/templates/phx.gen.live/core_components.ex
+++ b/priv/templates/phx.gen.live/core_components.ex
@@ -147,7 +147,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       :if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)}
       id={@id}
       phx-mounted={@autoshow && show("##{@id}")}
-      phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("#flash")}
+      phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
       role="alert"
       class={[
         "fixed hidden top-2 right-2 w-80 sm:w-96 z-50 rounded-lg p-3 shadow-md shadow-zinc-900/5 ring-1",
@@ -339,7 +339,6 @@ defmodule <%= @web_namespace %>.CoreComponents do
         ]}
         {@rest}
       >
-
     <%%= @value %></textarea>
       <.error :for={msg <- @errors}><%%= msg %></.error>
     </div>


Test patch:
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/fixtures/templates/layout/root.html.eex b/test/fixtures/templates/layout/root.html.eex
new file mode 100644
index 000000000..4fc56964e
--- /dev/null
+++ b/test/fixtures/templates/layout/root.html.eex
@@ -0,0 +1,1 @@
+ROOTSTART[<%= @title %>]<%= @inner_content %>ROOTEND
diff --git a/test/fixtures/views.exs b/test/fixtures/views.exs
index 835e95197..2b4d623c5 100644
--- a/test/fixtures/views.exs
+++ b/test/fixtures/views.exs
@@ -8,13 +8,6 @@ end
 
 defmodule MyApp.LayoutView do
   use Phoenix.View, root: "test/fixtures/templates"
-  import Phoenix.HTML
-
-  def render("root.html", assigns) do
-    ~E"""
-    ROOTSTART[<%= @title %>]<%= @inner_content %>ROOTEND
-    """
-  end
 
   def default_title do
     "MyApp"
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