Repository: ota-meshi/eslint-plugin-astro
Pull request #67 (2022-07-28 10:07:32)

Add `astro/no-deprecated-astro-canonicalurl`  rule


Patch:
diff --git a/README.md b/README.md
index a40b9b4..0187ffe 100644
--- a/README.md
+++ b/README.md
@@ -304,6 +304,7 @@ These rules relate to possible syntax or logic errors in Astro component code:
 | Rule ID | Description |    |
 |:--------|:------------|:---|
 | [astro/no-conflict-set-directives](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-conflict-set-directives/) | disallow conflicting set directives and child contents | :star: |
+| [astro/no-deprecated-astro-canonicalurl](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-canonicalurl/) | disallow using deprecated `Astro.canonicalURL` | :star: |
 | [astro/no-deprecated-astro-fetchcontent](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-fetchcontent/) | disallow using deprecated `Astro.fetchContent()` | :star::wrench: |
 | [astro/no-deprecated-astro-resolve](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-resolve/) | disallow using deprecated `Astro.resolve()` | :star: |
 | [astro/no-unused-define-vars-in-style](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-unused-define-vars-in-style/) | disallow unused `define:vars={...}` in `style` tag | :star: |
diff --git a/docs/rules.md b/docs/rules.md
index 68128f3..a4a0511 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -14,6 +14,7 @@ These rules relate to possible syntax or logic errors in Astro component code:
 | Rule ID | Description |    |
 |:--------|:------------|:---|
 | [astro/no-conflict-set-directives](./rules/no-conflict-set-directives.md) | disallow conflicting set directives and child contents | :star: |
+| [astro/no-deprecated-astro-canonicalurl](./rules/no-deprecated-astro-canonicalurl.md) | disallow using deprecated `Astro.canonicalURL` | :star: |
 | [astro/no-deprecated-astro-fetchcontent](./rules/no-deprecated-astro-fetchcontent.md) | disallow using deprecated `Astro.fetchContent()` | :star::wrench: |
 | [astro/no-deprecated-astro-resolve](./rules/no-deprecated-astro-resolve.md) | disallow using deprecated `Astro.resolve()` | :star: |
 | [astro/no-unused-define-vars-in-style](./rules/no-unused-define-vars-in-style.md) | disallow unused `define:vars={...}` in `style` tag | :star: |
diff --git a/docs/rules/no-deprecated-astro-canonicalurl.md b/docs/rules/no-deprecated-astro-canonicalurl.md
new file mode 100644
index 0000000..19bdbf3
--- /dev/null
+++ b/docs/rules/no-deprecated-astro-canonicalurl.md
@@ -0,0 +1,47 @@
+---
+title: "astro/no-deprecated-astro-canonicalurl"
+description: "disallow using deprecated `Astro.canonicalURL`"
+setup: "import ESLintCodeBlock from '../docs-build/src/components/ESLintCodeBlockWrap.astro'"
+---
+
+# astro/no-deprecated-astro-canonicalurl
+
+> disallow using deprecated `Astro.canonicalURL`
+
+- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
+- :gear: This rule is included in `"plugin:astro/recommended"`.
+
+## :book: Rule Details
+
+This rule reports use of deprecated `Astro.canonicalURL`.
+
+<ESLintCodeBlock>
+
+<!--eslint-skip-->
+
+```astro
+---
+/* eslint astro/no-deprecated-astro-canonicalurl: "error" */
+
+/* ✓ GOOD */
+const canonicalURL = new URL(Astro.url.pathname, Astro.site);
+
+/* ✗ BAD */
+const canonicalURL = Astro.canonicalURL;
+---
+```
+
+</ESLintCodeBlock>
+
+## :wrench: Options
+
+Nothing.
+
+## :books: Further Reading
+
+- [Astro Documentation | Migration Guide > Astro 1.0 Release Candidate - Deprecated: `Astro.canonicalURL`](https://docs.astro.build/en/migrate/#deprecated-astrocanonicalurl)
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/src/rules/no-deprecated-astro-canonicalurl.ts)
+- [Test source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/tests/src/rules/no-deprecated-astro-canonicalurl.ts)
diff --git a/docs/rules/no-deprecated-astro-fetchcontent.md b/docs/rules/no-deprecated-astro-fetchcontent.md
index 98d8a5a..a60de30 100644
--- a/docs/rules/no-deprecated-astro-fetchcontent.md
+++ b/docs/rules/no-deprecated-astro-fetchcontent.md
@@ -24,10 +24,10 @@ This rule reports use of deprecated `Astro.fetchContent()`.
 ---
 /* eslint astro/no-deprecated-astro-fetchcontent: "error" */
 
-{/* ✓ GOOD */}
+/* ✓ GOOD */
 const posts = await Astro.glob('../pages/post/*.md');
 
-{/* ✗ BAD */}
+/* ✗ BAD */
 const posts_bad = await Astro.fetchContent('../pages/post/*.md');
 ---
 
diff --git a/package.json b/package.json
index 50ddd29..0240e0c 100644
--- a/package.json
+++ b/package.json
@@ -61,7 +61,7 @@
   },
   "devDependencies": {
     "@astrojs/compiler": "^0.22.0",
-    "@astrojs/svelte": "^0.4.0",
+    "@astrojs/svelte": "^0.5.0",
     "@ota-meshi/eslint-plugin": "^0.11.0",
     "@types/eslint": "^8.4.2",
     "@types/eslint-scope": "^3.7.3",
diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts
index 43e0ec5..bf699c5 100644
--- a/src/configs/recommended.ts
+++ b/src/configs/recommended.ts
@@ -7,6 +7,7 @@ export = {
   rules: {
     // eslint-plugin-astro rules
     "astro/no-conflict-set-directives": "error",
+    "astro/no-deprecated-astro-canonicalurl": "error",
     "astro/no-deprecated-astro-fetchcontent": "error",
     "astro/no-deprecated-astro-resolve": "error",
     "astro/no-unused-define-vars-in-style": "error",
diff --git a/src/rules/no-deprecated-astro-canonicalurl.ts b/src/rules/no-deprecated-astro-canonicalurl.ts
new file mode 100644
index 0000000..d9148bb
--- /dev/null
+++ b/src/rules/no-deprecated-astro-canonicalurl.ts
@@ -0,0 +1,40 @@
+import { READ, ReferenceTracker } from "eslint-utils"
+import { createRule } from "../utils"
+
+export default createRule("no-deprecated-astro-canonicalurl", {
+  meta: {
+    docs: {
+      description: "disallow using deprecated `Astro.canonicalURL`",
+      category: "Possible Errors",
+      recommended: true,
+    },
+    schema: [],
+    messages: {
+      deprecated:
+        "'Astro.canonicalURL' is deprecated. Use 'Astro.url' helper instead.",
+    },
+    type: "problem",
+  },
+  create(context) {
+    if (!context.parserServices.isAstro) {
+      return {}
+    }
+
+    return {
+      "Program:exit"() {
+        const tracker = new ReferenceTracker(context.getScope())
+        for (const { node, path } of tracker.iterateGlobalReferences({
+          Astro: {
+            canonicalURL: { [READ]: true },
+          },
+        })) {
+          context.report({
+            node,
+            messageId: "deprecated",
+            data: { name: path.join(".") },
+          })
+        }
+      },
+    }
+  },
+})
diff --git a/src/utils/rules.ts b/src/utils/rules.ts
index d784d03..f46afda 100644
--- a/src/utils/rules.ts
+++ b/src/utils/rules.ts
@@ -1,5 +1,6 @@
 import type { RuleModule } from "../types"
 import noConflictSetDirectives from "../rules/no-conflict-set-directives"
+import noDeprecatedAstroCanonicalurl from "../rules/no-deprecated-astro-canonicalurl"
 import noDeprecatedAstroFetchcontent from "../rules/no-deprecated-astro-fetchcontent"
 import noDeprecatedAstroResolve from "../rules/no-deprecated-astro-resolve"
 import noSetHtmlDirective from "../rules/no-set-html-directive"
@@ -13,6 +14,7 @@ import { buildA11yRules } from "../a11y"
 
 export const rules = [
   noConflictSetDirectives,
+  noDeprecatedAstroCanonicalurl,
   noDeprecatedAstroFetchcontent,
   noDeprecatedAstroResolve,
   noSetHtmlDirective,
diff --git a/tools/update-types-for-node.ts b/tools/update-types-for-node.ts
index 1f17757..05659d5 100644
--- a/tools/update-types-for-node.ts
+++ b/tools/update-types-for-node.ts
@@ -32,7 +32,7 @@ import type * as ESTree from "estree"
 export type ASTNode =
   | AST.AstroNode
   | AST.JSXNode
-  | ESTree.Node
+  | Exclude<ESTree.Node, { type: AST.JSXNode["type"] }>
   | Exclude<
       TSESTree.Node,
       { type: ESTree.Node["type"] } | { type: AST.JSXNode["type"] }


Test patch:
diff --git a/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-errors.json b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-errors.json
new file mode 100644
index 0000000..1fd7473
--- /dev/null
+++ b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-errors.json
@@ -0,0 +1,7 @@
+[
+  {
+    "message": "'Astro.canonicalURL' is deprecated. Use 'Astro.url' helper instead.",
+    "line": 3,
+    "column": 22
+  }
+]
diff --git a/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-input.astro b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-input.astro
new file mode 100644
index 0000000..e760c72
--- /dev/null
+++ b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/invalid/test01-input.astro
@@ -0,0 +1,5 @@
+---
+/* ✗ BAD */
+const canonicalURL = Astro.canonicalURL
+console.log(canonicalURL)
+---
diff --git a/tests/fixtures/rules/no-deprecated-astro-canonicalurl/valid/test01-input.astro b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/valid/test01-input.astro
new file mode 100644
index 0000000..a217f6d
--- /dev/null
+++ b/tests/fixtures/rules/no-deprecated-astro-canonicalurl/valid/test01-input.astro
@@ -0,0 +1,5 @@
+---
+/* ✓ GOOD */
+const canonicalURL = new URL(Astro.url.pathname, Astro.site)
+console.log(canonicalURL)
+---
diff --git a/tests/src/rules/no-deprecated-astro-canonicalurl.ts b/tests/src/rules/no-deprecated-astro-canonicalurl.ts
new file mode 100644
index 0000000..1deae0d
--- /dev/null
+++ b/tests/src/rules/no-deprecated-astro-canonicalurl.ts
@@ -0,0 +1,19 @@
+import { RuleTester } from "eslint"
+import rule from "../../../src/rules/no-deprecated-astro-canonicalurl"
+import { loadTestCases } from "../../utils/utils"
+
+const tester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 2020,
+    sourceType: "module",
+  },
+  globals: {
+    Astro: false,
+  },
+})
+
+tester.run(
+  "no-deprecated-astro-canonicalurl",
+  rule as any,
+  loadTestCases("no-deprecated-astro-canonicalurl"),
+)