Repository: playwright-community/eslint-plugin-playwright
Pull request #317 (2024-09-18 00:00:43)

chore(deps-dev): Bump vite from 5.2.8 to 5.4.6
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.8 to 5.4.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/vitejs/vite/releases">vite's releases</a>.</em></p>
<blockquote>
<h2>create-vite@5.4.0</h2>
<p>Please refer to <a href="https://github.com/vitejs/vite/blob/create-vite@5.4.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p>
<h2>create-vite@5.3.0</h2>
<p>Please refer to <a href="https://github.com/vitejs/vite/blob/create-vite@5.3.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/vitejs/vite/blob/v5.4.6/packages/vite/CHANGELOG.md">vite's changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted -->5.4.6 (2024-09-16)<!-- raw HTML omitted --></h2>
<ul>
<li>fix: avoid DOM Clobbering gadget in <code>getRelativeUrlFromDocument</code> (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18115">#18115</a>) (<a href="https://github.com/vitejs/vite/commit/179b17773cf35c73ddb041f9e6c703fd9f3126af">179b177</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/18115">#18115</a></li>
<li>fix: fs raw query (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18112">#18112</a>) (<a href="https://github.com/vitejs/vite/commit/6820bb3b9a54334f3268fc5ee1e967d2e1c0db34">6820bb3</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/18112">#18112</a></li>
</ul>
<h2><!-- raw HTML omitted -->5.4.5 (2024-09-13)<!-- raw HTML omitted --></h2>
<ul>
<li>fix(preload): backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18098">#18098</a>, throw error preloading module as well (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18099">#18099</a>) (<a href="https://github.com/vitejs/vite/commit/faa2405e5d1da07a7c7fb6d48e887bf97a2f3dba">faa2405</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/18098">#18098</a> <a href="https://redirect.github.com/vitejs/vite/issues/18099">#18099</a></li>
</ul>
<h2><!-- raw HTML omitted -->5.4.4 (2024-09-11)<!-- raw HTML omitted --></h2>
<ul>
<li>fix: backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17997">#17997</a>, ensure req.url matches moduleByEtag URL to avoid incorrect 304 (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18078">#18078</a>) (<a href="https://github.com/vitejs/vite/commit/74a79c53b2286c91739d1473945012b5d206eddf">74a79c5</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17997">#17997</a> <a href="https://redirect.github.com/vitejs/vite/issues/18078">#18078</a></li>
<li>fix: backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18063">#18063</a>, allow scanning exports from <code>script module</code> in svelte (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18077">#18077</a>) (<a href="https://github.com/vitejs/vite/commit/d90ba40474aa1da8e722e1660ba739621238e5ac">d90ba40</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/18063">#18063</a> <a href="https://redirect.github.com/vitejs/vite/issues/18077">#18077</a></li>
<li>fix(preload): backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18046">#18046</a>, allow ignoring dep errors (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18076">#18076</a>) (<a href="https://github.com/vitejs/vite/commit/8760293d6836dac554d1d6f214b8b09ed97cccd4">8760293</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/18046">#18046</a> <a href="https://redirect.github.com/vitejs/vite/issues/18076">#18076</a></li>
</ul>
<h2><!-- raw HTML omitted -->5.4.3 (2024-09-03)<!-- raw HTML omitted --></h2>
<ul>
<li>fix: allow getting URL of JS files in publicDir (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17915">#17915</a>) (<a href="https://github.com/vitejs/vite/commit/943ece177e7709b3ba574e810afce347c51d4442">943ece1</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17915">#17915</a></li>
<li>fix: cjs warning respect the logLevel flag (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17993">#17993</a>) (<a href="https://github.com/vitejs/vite/commit/dc3c14f39fcd57867c8ae81b75ae768b53b4b880">dc3c14f</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17993">#17993</a></li>
<li>fix: improve CJS warning trace information (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17926">#17926</a>) (<a href="https://github.com/vitejs/vite/commit/5c5f82c84bb64309875b42eee9d4dd525ab42e8c">5c5f82c</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17926">#17926</a></li>
<li>fix: only remove entry assets handled by Vite core (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17916">#17916</a>) (<a href="https://github.com/vitejs/vite/commit/ebfaa7e6019783f308db5e759a6a67abb7cc626c">ebfaa7e</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17916">#17916</a></li>
<li>fix: waitForRequestIdle locked (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17982">#17982</a>) (<a href="https://github.com/vitejs/vite/commit/ad1376018a94b42540a8488d897cc520849e1228">ad13760</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17982">#17982</a></li>
<li>fix(css): fix directory index import in sass modern api (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17960">#17960</a>) (<a href="https://github.com/vitejs/vite/commit/9b001baa70c8489ac5550107c110a5dca281cda4">9b001ba</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17960">#17960</a></li>
<li>fix(css): fix sass <code>file://</code> reference (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17909">#17909</a>) (<a href="https://github.com/vitejs/vite/commit/561b940f6f963fbb78058a6e23b4adad53a2edb9">561b940</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17909">#17909</a></li>
<li>fix(css): fix sass modern source map (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17938">#17938</a>) (<a href="https://github.com/vitejs/vite/commit/d428e7e3a05f8da5ea00bb1b6a0827a5cc225899">d428e7e</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17938">#17938</a></li>
<li>fix(deps): bump tsconfck  (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17990">#17990</a>) (<a href="https://github.com/vitejs/vite/commit/8c661b20e92f33eb2e3ba3841b20dd6f6076f1ef">8c661b2</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17990">#17990</a></li>
<li>fix(html): rewrite assets url in &lt;template&gt; (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17988">#17988</a>) (<a href="https://github.com/vitejs/vite/commit/413c86aa971bc1ad8958578c929f45a368799f74">413c86a</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17988">#17988</a></li>
<li>fix(preload): add crossorigin attribute in CSS link tags (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17930">#17930</a>) (<a href="https://github.com/vitejs/vite/commit/15871c75e0722adeda23f771fd6c45fecba4d118">15871c7</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17930">#17930</a></li>
<li>chore: reduce diffs with v6 branch (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17942">#17942</a>) (<a href="https://github.com/vitejs/vite/commit/bf9065aa13da6a519014c3bc1d34cfb1cb49ccca">bf9065a</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17942">#17942</a></li>
<li>chore(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17945">#17945</a>) (<a href="https://github.com/vitejs/vite/commit/cfb621e7a5a3e24d710a9af156e6855e73caf891">cfb621e</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17945">#17945</a></li>
<li>chore(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17991">#17991</a>) (<a href="https://github.com/vitejs/vite/commit/0ca53cff9ff49108fcec75ff01d2445f9c2f2a4c">0ca53cf</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17991">#17991</a></li>
</ul>
<h2><!-- raw HTML omitted -->5.4.2 (2024-08-20)<!-- raw HTML omitted --></h2>
<ul>
<li>chore: remove stale TODOs (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17866">#17866</a>) (<a href="https://github.com/vitejs/vite/commit/e012f296df583bd133d26399397bd4ae49de1497">e012f29</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17866">#17866</a></li>
<li>refactor: remove redundant prepend/strip base (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17887">#17887</a>) (<a href="https://github.com/vitejs/vite/commit/3b8f03d789ec3ef1a099c884759bd4e61b03ce7c">3b8f03d</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17887">#17887</a></li>
<li>fix: resolve relative URL generated by <code>renderBuiltUrl</code> passed to module preload (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/16084">#16084</a>) (<a href="https://github.com/vitejs/vite/commit/fac3a8ed6855c4ab3032957137b74f21ec501e72">fac3a8e</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/16084">#16084</a></li>
<li>feat: support originalFilename (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17867">#17867</a>) (<a href="https://github.com/vitejs/vite/commit/7d8c0e2dcbdea3a3465a1d87e259988e82561035">7d8c0e2</a>), closes <a href="https://redirect.github.com/vitejs/vite/issues/17867">#17867</a></li>
</ul>
<h2><!-- raw HTML omitted -->5.4.1 (2024-08-15)<!-- raw HTML omitted --></h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/vitejs/vite/commit/f9691767ad763720065cc7c5c7f369f97b4e7ea8"><code>f969176</code></a> release: v5.4.6</li>
<li><a href="https://github.com/vitejs/vite/commit/179b17773cf35c73ddb041f9e6c703fd9f3126af"><code>179b177</code></a> fix: avoid DOM Clobbering gadget in <code>getRelativeUrlFromDocument</code> (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18115">#18115</a>)</li>
<li><a href="https://github.com/vitejs/vite/commit/6820bb3b9a54334f3268fc5ee1e967d2e1c0db34"><code>6820bb3</code></a> fix: fs raw query (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18112">#18112</a>)</li>
<li><a href="https://github.com/vitejs/vite/commit/37881e71980ddbf6a93444c2d21b8ee6c076ad07"><code>37881e7</code></a> release: v5.4.5</li>
<li><a href="https://github.com/vitejs/vite/commit/faa2405e5d1da07a7c7fb6d48e887bf97a2f3dba"><code>faa2405</code></a> fix(preload): backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18098">#18098</a>, throw error preloading module as well (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18099">#18099</a>)</li>
<li><a href="https://github.com/vitejs/vite/commit/54c55dbffc86f21ae88a171a5af90c37876db226"><code>54c55db</code></a> release: v5.4.4</li>
<li><a href="https://github.com/vitejs/vite/commit/74a79c53b2286c91739d1473945012b5d206eddf"><code>74a79c5</code></a> fix: backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/17997">#17997</a>, ensure req.url matches moduleByEtag URL to avoid incorr...</li>
<li><a href="https://github.com/vitejs/vite/commit/d90ba40474aa1da8e722e1660ba739621238e5ac"><code>d90ba40</code></a> fix: backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18063">#18063</a>, allow scanning exports from <code>script module</code> in svelte (...</li>
<li><a href="https://github.com/vitejs/vite/commit/8760293d6836dac554d1d6f214b8b09ed97cccd4"><code>8760293</code></a> fix(preload): backport <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18046">#18046</a>, allow ignoring dep errors (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/18076">#18076</a>)</li>
<li><a href="https://github.com/vitejs/vite/commit/ccbfc1a06816ccf45b93cffa9f8c2b94d3ad97d3"><code>ccbfc1a</code></a> release: v5.4.3</li>
<li>Additional commits viewable in <a href="https://github.com/vitejs/vite/commits/v5.4.6/packages/vite">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=5.2.8&new-version=5.4.6)](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 show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@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/playwright-community/eslint-plugin-playwright/network/alerts).

</details>


Patch:
diff --git a/README.md b/README.md
index 73d387a..b86d0a3 100644
--- a/README.md
+++ b/README.md
@@ -195,6 +195,7 @@ CLI option\
 | [prefer-hooks-on-top](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-on-top.md)                 | Suggest having hooks before any test cases                         |     |     |     |
 | [prefer-lowercase-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-lowercase-title.md)           | Enforce lowercase test names                                       |     | 🔧  |     |
 | [prefer-native-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-native-locators.md)           | Suggest built-in locators over `page.locator()`                    |     | 🔧  |     |
+| [prefer-locator](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-locator.md)                           | Suggest locators over page methods                                 |     |     |     |
 | [prefer-strict-equal](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-strict-equal.md)                 | Suggest using `toStrictEqual()`                                    |     |     | 💡  |
 | [prefer-to-be](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-be.md)                               | Suggest using `toBe()`                                             |     | 🔧  |     |
 | [prefer-to-contain](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-contain.md)                     | Suggest using `toContain()`                                        |     | 🔧  |     |
diff --git a/docs/rules/prefer-locator.md b/docs/rules/prefer-locator.md
new file mode 100644
index 0000000..14efbc0
--- /dev/null
+++ b/docs/rules/prefer-locator.md
@@ -0,0 +1,33 @@
+# Suggest using `page.locator()` (`prefer-locator`)
+
+Suggest using locators and their associated methods instead of page methods for
+performing actions.
+
+## Rule details
+
+This rule triggers a warning if page methods are used, instead of locators.
+
+The following patterns are considered warnings:
+
+```javascript
+page.click('css=button')
+await page.click('css=button')
+await page.dblclick('xpath=//button')
+await page.fill('input[type="password"]', 'password')
+
+await page.frame('frame-name').click('css=button')
+```
+
+The following pattern are **not** warnings:
+
+```javascript
+const locator = page.locator('css=button')
+await page.getByRole('password').fill('password')
+await page.getByLabel('User Name').fill('John')
+await page.getByRole('button', { name: 'Sign in' }).click()
+await page.locator('input[type="password"]').fill('password')
+await page.locator('css=button').click()
+await page.locator('xpath=//button').dblclick()
+
+await page.frameLocator('#my-iframe').getByText('Submit').click()
+```
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e6fb510..a405fc0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -115,8 +115,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/aix-ppc64@0.20.2:
-    resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
+  /@esbuild/aix-ppc64@0.21.5:
+    resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [aix]
@@ -133,8 +133,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/android-arm64@0.20.2:
-    resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
+  /@esbuild/android-arm64@0.21.5:
+    resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [android]
@@ -151,8 +151,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/android-arm@0.20.2:
-    resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
+  /@esbuild/android-arm@0.21.5:
+    resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
@@ -169,8 +169,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/android-x64@0.20.2:
-    resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
+  /@esbuild/android-x64@0.21.5:
+    resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [android]
@@ -187,8 +187,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/darwin-arm64@0.20.2:
-    resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
+  /@esbuild/darwin-arm64@0.21.5:
+    resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [darwin]
@@ -205,8 +205,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/darwin-x64@0.20.2:
-    resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
+  /@esbuild/darwin-x64@0.21.5:
+    resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [darwin]
@@ -223,8 +223,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/freebsd-arm64@0.20.2:
-    resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
+  /@esbuild/freebsd-arm64@0.21.5:
+    resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [freebsd]
@@ -241,8 +241,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/freebsd-x64@0.20.2:
-    resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
+  /@esbuild/freebsd-x64@0.21.5:
+    resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [freebsd]
@@ -259,8 +259,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-arm64@0.20.2:
-    resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
+  /@esbuild/linux-arm64@0.21.5:
+    resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [linux]
@@ -277,8 +277,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-arm@0.20.2:
-    resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
+  /@esbuild/linux-arm@0.21.5:
+    resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [linux]
@@ -295,8 +295,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-ia32@0.20.2:
-    resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
+  /@esbuild/linux-ia32@0.21.5:
+    resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [linux]
@@ -313,8 +313,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-loong64@0.20.2:
-    resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
+  /@esbuild/linux-loong64@0.21.5:
+    resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
     engines: {node: '>=12'}
     cpu: [loong64]
     os: [linux]
@@ -331,8 +331,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-mips64el@0.20.2:
-    resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
+  /@esbuild/linux-mips64el@0.21.5:
+    resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
     engines: {node: '>=12'}
     cpu: [mips64el]
     os: [linux]
@@ -349,8 +349,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-ppc64@0.20.2:
-    resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
+  /@esbuild/linux-ppc64@0.21.5:
+    resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [linux]
@@ -367,8 +367,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-riscv64@0.20.2:
-    resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
+  /@esbuild/linux-riscv64@0.21.5:
+    resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
     engines: {node: '>=12'}
     cpu: [riscv64]
     os: [linux]
@@ -385,8 +385,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-s390x@0.20.2:
-    resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
+  /@esbuild/linux-s390x@0.21.5:
+    resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
     engines: {node: '>=12'}
     cpu: [s390x]
     os: [linux]
@@ -403,8 +403,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-x64@0.20.2:
-    resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
+  /@esbuild/linux-x64@0.21.5:
+    resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [linux]
@@ -421,8 +421,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/netbsd-x64@0.20.2:
-    resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
+  /@esbuild/netbsd-x64@0.21.5:
+    resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [netbsd]
@@ -439,8 +439,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/openbsd-x64@0.20.2:
-    resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
+  /@esbuild/openbsd-x64@0.21.5:
+    resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [openbsd]
@@ -457,8 +457,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/sunos-x64@0.20.2:
-    resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
+  /@esbuild/sunos-x64@0.21.5:
+    resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [sunos]
@@ -475,8 +475,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/win32-arm64@0.20.2:
-    resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
+  /@esbuild/win32-arm64@0.21.5:
+    resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [win32]
@@ -493,8 +493,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/win32-ia32@0.20.2:
-    resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
+  /@esbuild/win32-ia32@0.21.5:
+    resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [win32]
@@ -511,8 +511,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/win32-x64@0.20.2:
-    resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
+  /@esbuild/win32-x64@0.21.5:
+    resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [win32]
@@ -844,8 +844,8 @@ packages:
       config-chain: 1.1.13
     dev: true
 
-  /@rollup/rollup-android-arm-eabi@4.14.0:
-    resolution: {integrity: sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==}
+  /@rollup/rollup-android-arm-eabi@4.21.3:
+    resolution: {integrity: sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==}
     cpu: [arm]
     os: [android]
     requiresBuild: true
@@ -860,8 +860,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-android-arm64@4.14.0:
-    resolution: {integrity: sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==}
+  /@rollup/rollup-android-arm64@4.21.3:
+    resolution: {integrity: sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==}
     cpu: [arm64]
     os: [android]
     requiresBuild: true
@@ -876,8 +876,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-darwin-arm64@4.14.0:
-    resolution: {integrity: sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==}
+  /@rollup/rollup-darwin-arm64@4.21.3:
+    resolution: {integrity: sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==}
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
@@ -892,8 +892,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-darwin-x64@4.14.0:
-    resolution: {integrity: sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==}
+  /@rollup/rollup-darwin-x64@4.21.3:
+    resolution: {integrity: sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==}
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
@@ -908,8 +908,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm-gnueabihf@4.14.0:
-    resolution: {integrity: sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==}
+  /@rollup/rollup-linux-arm-gnueabihf@4.21.3:
+    resolution: {integrity: sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==}
     cpu: [arm]
     os: [linux]
     requiresBuild: true
@@ -924,8 +924,16 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm64-gnu@4.14.0:
-    resolution: {integrity: sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==}
+  /@rollup/rollup-linux-arm-musleabihf@4.21.3:
+    resolution: {integrity: sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm64-gnu@4.21.3:
+    resolution: {integrity: sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
@@ -940,8 +948,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm64-musl@4.14.0:
-    resolution: {integrity: sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==}
+  /@rollup/rollup-linux-arm64-musl@4.21.3:
+    resolution: {integrity: sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
@@ -956,16 +964,16 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-powerpc64le-gnu@4.14.0:
-    resolution: {integrity: sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==}
-    cpu: [ppc64le]
+  /@rollup/rollup-linux-powerpc64le-gnu@4.21.3:
+    resolution: {integrity: sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==}
+    cpu: [ppc64]
     os: [linux]
     requiresBuild: true
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-riscv64-gnu@4.14.0:
-    resolution: {integrity: sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==}
+  /@rollup/rollup-linux-riscv64-gnu@4.21.3:
+    resolution: {integrity: sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==}
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
@@ -980,16 +988,16 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-s390x-gnu@4.14.0:
-    resolution: {integrity: sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==}
+  /@rollup/rollup-linux-s390x-gnu@4.21.3:
+    resolution: {integrity: sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==}
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-x64-gnu@4.14.0:
-    resolution: {integrity: sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==}
+  /@rollup/rollup-linux-x64-gnu@4.21.3:
+    resolution: {integrity: sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
@@ -1004,8 +1012,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-linux-x64-musl@4.14.0:
-    resolution: {integrity: sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==}
+  /@rollup/rollup-linux-x64-musl@4.21.3:
+    resolution: {integrity: sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
@@ -1020,8 +1028,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-win32-arm64-msvc@4.14.0:
-    resolution: {integrity: sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==}
+  /@rollup/rollup-win32-arm64-msvc@4.21.3:
+    resolution: {integrity: sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==}
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
@@ -1036,8 +1044,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-win32-ia32-msvc@4.14.0:
-    resolution: {integrity: sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==}
+  /@rollup/rollup-win32-ia32-msvc@4.21.3:
+    resolution: {integrity: sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==}
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
@@ -1052,8 +1060,8 @@ packages:
     dev: true
     optional: true
 
-  /@rollup/rollup-win32-x64-msvc@4.14.0:
-    resolution: {integrity: sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==}
+  /@rollup/rollup-win32-x64-msvc@4.21.3:
+    resolution: {integrity: sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==}
     cpu: [x64]
     os: [win32]
     requiresBuild: true
@@ -2094,35 +2102,35 @@ packages:
       '@esbuild/win32-x64': 0.19.9
     dev: true
 
-  /esbuild@0.20.2:
-    resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
+  /esbuild@0.21.5:
+    resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
     engines: {node: '>=12'}
     hasBin: true
     requiresBuild: true
     optionalDependencies:
-      '@esbuild/aix-ppc64': 0.20.2
-      '@esbuild/android-arm': 0.20.2
-      '@esbuild/android-arm64': 0.20.2
-      '@esbuild/android-x64': 0.20.2
-      '@esbuild/darwin-arm64': 0.20.2
-      '@esbuild/darwin-x64': 0.20.2
-      '@esbuild/freebsd-arm64': 0.20.2
-      '@esbuild/freebsd-x64': 0.20.2
-      '@esbuild/linux-arm': 0.20.2
-      '@esbuild/linux-arm64': 0.20.2
-      '@esbuild/linux-ia32': 0.20.2
-      '@esbuild/linux-loong64': 0.20.2
-      '@esbuild/linux-mips64el': 0.20.2
-      '@esbuild/linux-ppc64': 0.20.2
-      '@esbuild/linux-riscv64': 0.20.2
-      '@esbuild/linux-s390x': 0.20.2
-      '@esbuild/linux-x64': 0.20.2
-      '@esbuild/netbsd-x64': 0.20.2
-      '@esbuild/openbsd-x64': 0.20.2
-      '@esbuild/sunos-x64': 0.20.2
-      '@esbuild/win32-arm64': 0.20.2
-      '@esbuild/win32-ia32': 0.20.2
-      '@esbuild/win32-x64': 0.20.2
+      '@esbuild/aix-ppc64': 0.21.5
+      '@esbuild/android-arm': 0.21.5
+      '@esbuild/android-arm64': 0.21.5
+      '@esbuild/android-x64': 0.21.5
+      '@esbuild/darwin-arm64': 0.21.5
+      '@esbuild/darwin-x64': 0.21.5
+      '@esbuild/freebsd-arm64': 0.21.5
+      '@esbuild/freebsd-x64': 0.21.5
+      '@esbuild/linux-arm': 0.21.5
+      '@esbuild/linux-arm64': 0.21.5
+      '@esbuild/linux-ia32': 0.21.5
+      '@esbuild/linux-loong64': 0.21.5
+      '@esbuild/linux-mips64el': 0.21.5
+      '@esbuild/linux-ppc64': 0.21.5
+      '@esbuild/linux-riscv64': 0.21.5
+      '@esbuild/linux-s390x': 0.21.5
+      '@esbuild/linux-x64': 0.21.5
+      '@esbuild/netbsd-x64': 0.21.5
+      '@esbuild/openbsd-x64': 0.21.5
+      '@esbuild/sunos-x64': 0.21.5
+      '@esbuild/win32-arm64': 0.21.5
+      '@esbuild/win32-ia32': 0.21.5
+      '@esbuild/win32-x64': 0.21.5
     dev: true
 
   /escalade@3.1.1:
@@ -2343,7 +2351,7 @@ packages:
   /estree-walker@3.0.3:
     resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
     dependencies:
-      '@types/estree': 1.0.2
+      '@types/estree': 1.0.5
     dev: true
 
   /esutils@2.0.3:
@@ -3692,6 +3700,10 @@ packages:
     resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
     dev: true
 
+  /picocolors@1.1.0:
+    resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
+    dev: true
+
   /picomatch@2.3.1:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     engines: {node: '>=8.6'}
@@ -3754,13 +3766,13 @@ packages:
       yaml: 2.3.4
     dev: true
 
-  /postcss@8.4.38:
-    resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+  /postcss@8.4.47:
+    resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
     engines: {node: ^10 || ^12 || >=14}
     dependencies:
       nanoid: 3.3.7
-      picocolors: 1.0.0
-      source-map-js: 1.2.0
+      picocolors: 1.1.0
+      source-map-js: 1.2.1
     dev: true
 
   /prelude-ls@1.2.1:
@@ -3915,28 +3927,29 @@ packages:
     dependencies:
       glob: 7.2.3
 
-  /rollup@4.14.0:
-    resolution: {integrity: sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==}
+  /rollup@4.21.3:
+    resolution: {integrity: sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
     dependencies:
       '@types/estree': 1.0.5
     optionalDependencies:
-      '@rollup/rollup-android-arm-eabi': 4.14.0
-      '@rollup/rollup-android-arm64': 4.14.0
-      '@rollup/rollup-darwin-arm64': 4.14.0
-      '@rollup/rollup-darwin-x64': 4.14.0
-      '@rollup/rollup-linux-arm-gnueabihf': 4.14.0
-      '@rollup/rollup-linux-arm64-gnu': 4.14.0
-      '@rollup/rollup-linux-arm64-musl': 4.14.0
-      '@rollup/rollup-linux-powerpc64le-gnu': 4.14.0
-      '@rollup/rollup-linux-riscv64-gnu': 4.14.0
-      '@rollup/rollup-linux-s390x-gnu': 4.14.0
-      '@rollup/rollup-linux-x64-gnu': 4.14.0
-      '@rollup/rollup-linux-x64-musl': 4.14.0
-      '@rollup/rollup-win32-arm64-msvc': 4.14.0
-      '@rollup/rollup-win32-ia32-msvc': 4.14.0
-      '@rollup/rollup-win32-x64-msvc': 4.14.0
+      '@rollup/rollup-android-arm-eabi': 4.21.3
+      '@rollup/rollup-android-arm64': 4.21.3
+      '@rollup/rollup-darwin-arm64': 4.21.3
+      '@rollup/rollup-darwin-x64': 4.21.3
+      '@rollup/rollup-linux-arm-gnueabihf': 4.21.3
+      '@rollup/rollup-linux-arm-musleabihf': 4.21.3
+      '@rollup/rollup-linux-arm64-gnu': 4.21.3
+      '@rollup/rollup-linux-arm64-musl': 4.21.3
+      '@rollup/rollup-linux-powerpc64le-gnu': 4.21.3
+      '@rollup/rollup-linux-riscv64-gnu': 4.21.3
+      '@rollup/rollup-linux-s390x-gnu': 4.21.3
+      '@rollup/rollup-linux-x64-gnu': 4.21.3
+      '@rollup/rollup-linux-x64-musl': 4.21.3
+      '@rollup/rollup-win32-arm64-msvc': 4.21.3
+      '@rollup/rollup-win32-ia32-msvc': 4.21.3
+      '@rollup/rollup-win32-x64-msvc': 4.21.3
       fsevents: 2.3.3
     dev: true
 
@@ -4084,8 +4097,8 @@ packages:
     engines: {node: '>=14.16'}
     dev: true
 
-  /source-map-js@1.2.0:
-    resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+  /source-map-js@1.2.1:
+    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
     engines: {node: '>=0.10.0'}
     dev: true
 
@@ -4508,20 +4521,21 @@ packages:
       debug: 4.3.4
       pathe: 1.1.2
       picocolors: 1.0.0
-      vite: 5.2.8(@types/node@20.11.17)
+      vite: 5.4.6(@types/node@20.11.17)
     transitivePeerDependencies:
       - '@types/node'
       - less
       - lightningcss
       - sass
+      - sass-embedded
       - stylus
       - sugarss
       - supports-color
       - terser
     dev: true
 
-  /vite@5.2.8(@types/node@20.11.17):
-    resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==}
+  /vite@5.4.6(@types/node@20.11.17):
+    resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==}
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
@@ -4529,6 +4543,7 @@ packages:
       less: '*'
       lightningcss: ^1.21.0
       sass: '*'
+      sass-embedded: '*'
       stylus: '*'
       sugarss: '*'
       terser: ^5.4.0
@@ -4541,6 +4556,8 @@ packages:
         optional: true
       sass:
         optional: true
+      sass-embedded:
+        optional: true
       stylus:
         optional: true
       sugarss:
@@ -4549,9 +4566,9 @@ packages:
         optional: true
     dependencies:
       '@types/node': 20.11.17
-      esbuild: 0.20.2
-      postcss: 8.4.38
-      rollup: 4.14.0
+      esbuild: 0.21.5
+      postcss: 8.4.47
+      rollup: 4.21.3
     optionalDependencies:
       fsevents: 2.3.3
     dev: true
@@ -4599,13 +4616,14 @@ packages:
       strip-literal: 2.0.0
       tinybench: 2.6.0
       tinypool: 0.8.2
-      vite: 5.2.8(@types/node@20.11.17)
+      vite: 5.4.6(@types/node@20.11.17)
       vite-node: 1.3.1(@types/node@20.11.17)
       why-is-node-running: 2.2.2
     transitivePeerDependencies:
       - less
       - lightningcss
       - sass
+      - sass-embedded
       - stylus
       - sugarss
       - supports-color
diff --git a/src/index.ts b/src/index.ts
index c185547..e7312d8 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -30,6 +30,7 @@ import preferComparisonMatcher from './rules/prefer-comparison-matcher'
 import preferEqualityMatcher from './rules/prefer-equality-matcher'
 import preferHooksInOrder from './rules/prefer-hooks-in-order'
 import preferHooksOnTop from './rules/prefer-hooks-on-top'
+import preferLocator from './rules/prefer-locator'
 import preferLowercaseTitle from './rules/prefer-lowercase-title'
 import preferNativeLocators from './rules/prefer-native-locators'
 import preferStrictEqual from './rules/prefer-strict-equal'
@@ -81,6 +82,7 @@ const index = {
     'prefer-equality-matcher': preferEqualityMatcher,
     'prefer-hooks-in-order': preferHooksInOrder,
     'prefer-hooks-on-top': preferHooksOnTop,
+    'prefer-locator': preferLocator,
     'prefer-lowercase-title': preferLowercaseTitle,
     'prefer-native-locators': preferNativeLocators,
     'prefer-strict-equal': preferStrictEqual,
diff --git a/src/rules/prefer-locator.ts b/src/rules/prefer-locator.ts
new file mode 100644
index 0000000..e2ccab1
--- /dev/null
+++ b/src/rules/prefer-locator.ts
@@ -0,0 +1,65 @@
+import ESTree from 'estree'
+import { getStringValue, isPageMethod } from '../utils/ast'
+import { createRule } from '../utils/createRule'
+
+const pageMethods = new Set([
+  'click',
+  'dblclick',
+  'dispatchEvent',
+  'fill',
+  'focus',
+  'getAttribute',
+  'hover',
+  'innerHTML',
+  'innerText',
+  'inputValue',
+  'isChecked',
+  'isDisabled',
+  'isEditable',
+  'isEnabled',
+  'isHidden',
+  'isVisible',
+  'press',
+  'selectOption',
+  'setChecked',
+  'setInputFiles',
+  'tap',
+  'textContent',
+  'uncheck',
+])
+
+function isSupportedMethod(node: ESTree.CallExpression) {
+  if (node.callee.type !== 'MemberExpression') return false
+
+  const name = getStringValue(node.callee.property)
+  return pageMethods.has(name) && isPageMethod(node, name)
+}
+
+export default createRule({
+  create(context) {
+    return {
+      CallExpression(node) {
+        // Must be a method we care about
+        if (!isSupportedMethod(node)) return
+
+        context.report({
+          messageId: 'preferLocator',
+          node,
+        })
+      },
+    }
+  },
+  meta: {
+    docs: {
+      category: 'Best Practices',
+      description: 'Suggest locators over page methods',
+      recommended: false,
+      url: 'https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-locator.md',
+    },
+    messages: {
+      preferLocator: 'Prefer locator methods instead of page methods',
+    },
+    schema: [],
+    type: 'suggestion',
+  },
+})


Test patch:
diff --git a/src/rules/prefer-locator.test.ts b/src/rules/prefer-locator.test.ts
new file mode 100644
index 0000000..13135d4
--- /dev/null
+++ b/src/rules/prefer-locator.test.ts
@@ -0,0 +1,99 @@
+import { runRuleTester, test } from '../utils/rule-tester'
+import rule from './prefer-locator'
+
+runRuleTester('prefer-locator', rule, {
+  invalid: [
+    {
+      code: test(`await page.fill('input[type="password"]', 'password')`),
+      errors: [
+        {
+          column: 34,
+          endColumn: 81,
+          endLine: 1,
+          line: 1,
+          messageId: 'preferLocator',
+        },
+      ],
+      output: null,
+    },
+    {
+      code: test(`await page.dblclick('xpath=//button')`),
+      errors: [
+        {
+          column: 34,
+          endColumn: 65,
+          endLine: 1,
+          line: 1,
+          messageId: 'preferLocator',
+        },
+      ],
+      output: null,
+    },
+    {
+      code: `page.click('xpath=//button')`,
+      errors: [
+        {
+          column: 1,
+          endColumn: 29,
+          endLine: 1,
+          line: 1,
+          messageId: 'preferLocator',
+        },
+      ],
+      output: null,
+    },
+    {
+      code: test(`await page.frame('frame-name').click('css=button')`),
+      errors: [
+        {
+          column: 34,
+          endColumn: 78,
+          endLine: 1,
+          line: 1,
+          messageId: 'preferLocator',
+        },
+      ],
+      output: null,
+    },
+    {
+      code: `page.frame('frame-name').click('css=button')`,
+      errors: [
+        {
+          column: 1,
+          endColumn: 45,
+          endLine: 1,
+          line: 1,
+          messageId: 'preferLocator',
+        },
+      ],
+      output: null,
+    },
+  ],
+  valid: [
+    {
+      code: `const locator = page.locator('input[type="password"]')`,
+    },
+    {
+      code: test(
+        `await page.locator('input[type="password"]').fill('password')`,
+      ),
+    },
+    {
+      code: test(`await page.locator('xpath=//button').dblclick()`),
+    },
+    {
+      code: `page.locator('xpath=//button').click()`,
+    },
+    {
+      code: test(
+        `await page.frameLocator('#my-iframe').locator('css=button').click()`,
+      ),
+    },
+    {
+      code: test(`await page.evaluate('1 + 2')`),
+    },
+    {
+      code: `page.frame('frame-name')`,
+    },
+  ],
+})