From 5174590ac079ef98171a98b8000a75bcedfe783a Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Tue, 11 Jun 2024 17:37:25 +0900 Subject: [PATCH] Update no-exports-from-components rule to allow exceptions (#395) * Update no-exports-from-components rule to allow exceptions * Create many-carrots-doubt.md * fix --- .changeset/many-carrots-doubt.md | 5 +++++ docs/rules/no-exports-from-components.md | 8 +++++++ src/rules/no-exports-from-components.ts | 22 ++++++++++++++++++- .../valid/exceptions-01-input.astro | 11 ++++++++++ .../valid/exceptions-02-input.astro | 9 ++++++++ .../valid/exceptions-03-input.astro | 13 +++++++++++ 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 .changeset/many-carrots-doubt.md create mode 100644 tests/fixtures/rules/no-exports-from-components/valid/exceptions-01-input.astro create mode 100644 tests/fixtures/rules/no-exports-from-components/valid/exceptions-02-input.astro create mode 100644 tests/fixtures/rules/no-exports-from-components/valid/exceptions-03-input.astro diff --git a/.changeset/many-carrots-doubt.md b/.changeset/many-carrots-doubt.md new file mode 100644 index 00000000..9a34580b --- /dev/null +++ b/.changeset/many-carrots-doubt.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-astro": patch +--- + +Update `astro/no-exports-from-components` rule to allow exceptions diff --git a/docs/rules/no-exports-from-components.md b/docs/rules/no-exports-from-components.md index 0bdf5f9b..49c1c472 100644 --- a/docs/rules/no-exports-from-components.md +++ b/docs/rules/no-exports-from-components.md @@ -13,6 +13,10 @@ since: "v1.1.0" This rule reports value exports from Astro components. The use of typed exports are still allowed. +However, there are exceptions for specific named exports that are allowed: +- `getStaticPath`: This function can be exported for dynamic routing purposes. +- `prerender`: This constant can be exported to opt-in to pre-rendering in server mode. + @@ -22,6 +26,10 @@ The use of typed exports are still allowed. /* eslint astro/no-exports-from-components: "error" */ /* ✓ GOOD */ export type A = number | boolean +export const getStaticPath = () => { + // logic here +} +export const prerender = true; /* ✗ BAD */ export const x = 42 --- diff --git a/src/rules/no-exports-from-components.ts b/src/rules/no-exports-from-components.ts index 06a06ebe..26a09039 100644 --- a/src/rules/no-exports-from-components.ts +++ b/src/rules/no-exports-from-components.ts @@ -2,6 +2,8 @@ import type { TSESTree } from "@typescript-eslint/types" import { createRule } from "../utils" import { getSourceCode } from "../utils/compat" +const ALLOWED_EXPORTS = new Set(["getStaticPath", "prerender"]) + export default createRule("no-exports-from-components", { meta: { docs: { @@ -34,6 +36,20 @@ export default createRule("no-exports-from-components", { if (node.type.startsWith("TS") && !node.type.endsWith("Expression")) { return } + if ( + (node.type === "FunctionDeclaration" && + node.id && + ALLOWED_EXPORTS.has(node.id.name)) || + (node.type === "VariableDeclaration" && + node.declarations.every( + (decl) => + decl.id.type === "Identifier" && + ALLOWED_EXPORTS.has(decl.id.name), + )) + ) { + // Allow specific named exports + return + } context.report({ node, messageId: "disallowExport", @@ -56,7 +72,11 @@ export default createRule("no-exports-from-components", { if (node.exportKind === "type") return verifyDeclaration(node.declaration) for (const spec of node.specifiers) { - if (spec.exportKind === "type") return + if (spec.exportKind === "type") continue + if (ALLOWED_EXPORTS.has(spec.exported.name)) { + // Allow specific named exports + continue + } context.report({ node: spec, messageId: "disallowExport", diff --git a/tests/fixtures/rules/no-exports-from-components/valid/exceptions-01-input.astro b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-01-input.astro new file mode 100644 index 00000000..8bc4256b --- /dev/null +++ b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-01-input.astro @@ -0,0 +1,11 @@ +--- +// This file is used to test the exceptions for the `no-exports-from-components` rule. +// The following exports are allowed as exceptions. +export const getStaticPath = (): { param: unknown }[] => { + // logic here + return [{ param: "value" }] +} +export const prerender = true +--- + +
Hello World
diff --git a/tests/fixtures/rules/no-exports-from-components/valid/exceptions-02-input.astro b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-02-input.astro new file mode 100644 index 00000000..cabf0957 --- /dev/null +++ b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-02-input.astro @@ -0,0 +1,9 @@ +--- +// This file is used to test the exception for the `getStaticPath` function in the `no-exports-from-components` rule. +export async function getStaticPath(): Promise<{ param: unknown }[]> { + // logic here + return [] +} +--- + +
Hello World
diff --git a/tests/fixtures/rules/no-exports-from-components/valid/exceptions-03-input.astro b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-03-input.astro new file mode 100644 index 00000000..3cf1d31e --- /dev/null +++ b/tests/fixtures/rules/no-exports-from-components/valid/exceptions-03-input.astro @@ -0,0 +1,13 @@ +--- +// This file is used to test the exceptions for the `no-exports-from-components` rule. +// The following exports are allowed as exceptions. +const getStaticPath = (): { param: unknown }[] => { + // logic here + return [] +} +const prerender = true + +export { getStaticPath, prerender } +--- + +
Hello World