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"),
+)