diff --git a/.changeset/purple-coats-vanish.md b/.changeset/purple-coats-vanish.md new file mode 100644 index 000000000..5f6e9477d --- /dev/null +++ b/.changeset/purple-coats-vanish.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-svelte": minor +--- + +feat: add `svelte/valid-prop-names-in-kit-pages` rule diff --git a/README.md b/README.md index 6fb2aef0e..22714ad4c 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-unknown-style-directive-property](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: | | [svelte/require-store-callbacks-use-set-param](https://ota-meshi.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | store callbacks must use `set` param | | | [svelte/valid-compile](https://ota-meshi.github.io/eslint-plugin-svelte/rules/valid-compile/) | disallow warnings when compiling. | :star: | +| [svelte/valid-prop-names-in-kit-pages](https://ota-meshi.github.io/eslint-plugin-svelte/rules/valid-prop-names-in-kit-pages/) | disallow props other than data or errors in Svelte Kit page components. | | ## Security Vulnerability diff --git a/docs/rules.md b/docs/rules.md index 49d86c64e..bc5e7a401 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -27,6 +27,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: | | [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | | | [svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | :star: | +| [svelte/valid-prop-names-in-kit-pages](./rules/valid-prop-names-in-kit-pages.md) | disallow props other than data or errors in Svelte Kit page components. | | ## Security Vulnerability diff --git a/docs/rules/valid-prop-names-in-kit-pages.md b/docs/rules/valid-prop-names-in-kit-pages.md new file mode 100644 index 000000000..8f1e659c0 --- /dev/null +++ b/docs/rules/valid-prop-names-in-kit-pages.md @@ -0,0 +1,65 @@ +--- +pageClass: "rule-details" +sidebarDepth: 0 +title: "svelte/valid-prop-names-in-kit-pages" +description: "disallow props other than data or errors in Svelte Kit page components." +--- + +# svelte/valid-prop-names-in-kit-pages + +> disallow props other than data or errors in Svelte Kit page components. + +- :exclamation: **_This rule has not been released yet._** + +## :book: Rule Details + +This rule reports unexpected exported variables at ` + + + + + +```svelte + + +{foo}, {bar} +``` + + + +## :wrench: Options + +Nothing. But if use are using not default routes folder, please set configuration according to the [user guide](../user-guide.md#settings-kit). + +## :books: Further Reading + +- [SvelteKit Migration Guide (v1.0.0-next.405)](https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292707) + +## :mag: Implementation + +- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/valid-prop-names-in-kit-pages.ts) +- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/valid-prop-names-in-kit-pages.ts) diff --git a/src/rules/valid-prop-names-in-kit-pages.ts b/src/rules/valid-prop-names-in-kit-pages.ts new file mode 100644 index 000000000..c4a7b78c4 --- /dev/null +++ b/src/rules/valid-prop-names-in-kit-pages.ts @@ -0,0 +1,83 @@ +import type { AST } from "svelte-eslint-parser" +import type * as ESTree from "estree" +import { createRule } from "../utils" +import { isKitPageComponent } from "../utils/svelte-kit" + +const EXPECTED_PROP_NAMES = ["data", "errors"] + +export default createRule("valid-prop-names-in-kit-pages", { + meta: { + docs: { + description: + "disallow props other than data or errors in Svelte Kit page components.", + category: "Possible Errors", + // TODO Switch to recommended in the major version. + recommended: false, + }, + schema: [], + messages: { + unexpected: + "disallow props other than data or errors in Svelte Kit page components.", + }, + type: "problem", + }, + create(context) { + if (!isKitPageComponent(context)) return {} + let isScript = false + return { + // + "Program > SvelteScriptElement:exit": () => { + isScript = false + }, + + "ExportNamedDeclaration > VariableDeclaration > VariableDeclarator": ( + node: ESTree.VariableDeclarator, + ) => { + if (!isScript) return + + // export let foo + if (node.id.type === "Identifier") { + if (!EXPECTED_PROP_NAMES.includes(node.id.name)) { + context.report({ + node, + loc: node.loc!, + messageId: "unexpected", + }) + } + return + } + + // export let { xxx, yyy } = zzz + if (node.id.type !== "ObjectPattern") return + for (const p of node.id.properties) { + if ( + p.type === "Property" && + p.value.type === "Identifier" && + !EXPECTED_PROP_NAMES.includes(p.value.name) + ) { + context.report({ + node: p.value, + loc: p.value.loc!, + messageId: "unexpected", + }) + } + } + }, + } + }, +}) diff --git a/src/utils/rules.ts b/src/utils/rules.ts index 5308fb190..bdade6697 100644 --- a/src/utils/rules.ts +++ b/src/utils/rules.ts @@ -42,6 +42,7 @@ import sortAttributes from "../rules/sort-attributes" import spacedHtmlComment from "../rules/spaced-html-comment" import system from "../rules/system" import validCompile from "../rules/valid-compile" +import validPropNamesInKitPages from "../rules/valid-prop-names-in-kit-pages" export const rules = [ typescriptEslintNoUnnecessaryCondition, @@ -87,4 +88,5 @@ export const rules = [ spacedHtmlComment, system, validCompile, + validPropNamesInKitPages, ] as RuleModule[] diff --git a/src/utils/svelte-kit.ts b/src/utils/svelte-kit.ts index 8cd7c5f1c..bc842e2af 100644 --- a/src/utils/svelte-kit.ts +++ b/src/utils/svelte-kit.ts @@ -23,7 +23,12 @@ export function isKitPageComponent(context: RuleContext): boolean { "src/routes" const filePath = context.getFilename() const projectRootDir = getProjectRootDir(context.getFilename()) ?? "" - return filePath.startsWith(path.join(projectRootDir, routes)) + const fileName = filePath.split("/").pop() || filePath + return ( + filePath.startsWith(path.join(projectRootDir, routes)) && + // MEMO: check only `+` and file extension for maintainability + Boolean(/^\+.+\.svelte$/.test(fileName)) + ) } /** diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test01-errors.yaml b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test01-errors.yaml similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test01-errors.yaml rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test01-errors.yaml diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test01-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test01-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test01-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test01-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test02-errors.yaml b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test02-errors.yaml similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test02-errors.yaml rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test02-errors.yaml diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test02-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test02-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/test02-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/invalid/+test02-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test01-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test01-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test01-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test01-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test010-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test010-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test010-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test010-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test02-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test02-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test02-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test02-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test03-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test03-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test03-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test03-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test04-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test04-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test04-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test04-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test05-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test05-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test05-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test05-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test06-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test06-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test06-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test06-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test07-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test07-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test07-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test07-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test08-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test08-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test08-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test08-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test09-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test09-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/test09-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/+test09-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/test01-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/+test01-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/test01-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/+test01-input.svelte diff --git a/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/test02-input.svelte b/tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/+test02-input.svelte similarity index 100% rename from tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/test02-input.svelte rename to tests/fixtures/rules/no-export-load-in-svelte-module-in-kit-pages/valid/not-page/+test02-input.svelte diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-errors.yaml b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-errors.yaml new file mode 100644 index 000000000..e94d50d8a --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-errors.yaml @@ -0,0 +1,24 @@ +- message: disallow props other than data or errors in Svelte Kit page components. + line: 2 + column: 14 + suggestions: null +- message: disallow props other than data or errors in Svelte Kit page components. + line: 3 + column: 14 + suggestions: null +- message: disallow props other than data or errors in Svelte Kit page components. + line: 4 + column: 16 + suggestions: null +- message: disallow props other than data or errors in Svelte Kit page components. + line: 4 + column: 21 + suggestions: null +- message: disallow props other than data or errors in Svelte Kit page components. + line: 5 + column: 22 + suggestions: null +- message: disallow props other than data or errors in Svelte Kit page components. + line: 5 + column: 37 + suggestions: null diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-input.svelte new file mode 100644 index 000000000..94e5a9825 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/+test001-input.svelte @@ -0,0 +1,8 @@ + + +{foo}, {bar} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/_config.json b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/_config.json new file mode 100644 index 000000000..cb23d3be3 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/invalid/_config.json @@ -0,0 +1,11 @@ +{ + "settings": { + "svelte": { + "kit": { + "files": { + "routes": "tests/fixtures" + } + } + } + } +} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test001-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test001-input.svelte new file mode 100644 index 000000000..e11d91ba2 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test001-input.svelte @@ -0,0 +1,6 @@ + + +{data}, {errors} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test002-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test002-input.svelte new file mode 100644 index 000000000..3766ef750 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test002-input.svelte @@ -0,0 +1,8 @@ + + +{data}, {errors}, {foo}, {bar} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test003-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test003-input.svelte new file mode 100644 index 000000000..97e93f8a9 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test003-input.svelte @@ -0,0 +1,5 @@ + + +{data}, {errors} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte new file mode 100644 index 000000000..07c10e198 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte @@ -0,0 +1,5 @@ + + +{data}, {errors} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/_config.json b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/_config.json new file mode 100644 index 000000000..cb23d3be3 --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/_config.json @@ -0,0 +1,11 @@ +{ + "settings": { + "svelte": { + "kit": { + "files": { + "routes": "tests/fixtures" + } + } + } + } +} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/not-page/test01-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/not-page/test01-input.svelte new file mode 100644 index 000000000..7f159168a --- /dev/null +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/not-page/test01-input.svelte @@ -0,0 +1,8 @@ + + +{data}, {errors}, {foo}, {bar} diff --git a/tests/src/rules/valid-prop-names-in-kit-pages.ts b/tests/src/rules/valid-prop-names-in-kit-pages.ts new file mode 100644 index 000000000..8a4e20ac2 --- /dev/null +++ b/tests/src/rules/valid-prop-names-in-kit-pages.ts @@ -0,0 +1,16 @@ +import { RuleTester } from "eslint" +import rule from "../../../src/rules/valid-prop-names-in-kit-pages" +import { loadTestCases } from "../../utils/utils" + +const tester = new RuleTester({ + parserOptions: { + ecmaVersion: 2020, + sourceType: "module", + }, +}) + +tester.run( + "valid-prop-names-in-kit-pages", + rule as any, + loadTestCases("valid-prop-names-in-kit-pages"), +)