Skip to content

feat: no-not-data-props-in-kit-pages #283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
5 changes: 5 additions & 0 deletions .changeset/purple-coats-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-svelte": minor
---

feat: add `svelte/no-not-data-props-in-kit-pages` rule
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,13 @@ These rules relate to possible syntax or logic errors in Svelte code:
| [svelte/no-dupe-style-properties](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-style-properties/) | disallow duplicate style properties | :star: |
| [svelte/no-dynamic-slot-name](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name/) | disallow dynamic slot name | :star::wrench: |
| [svelte/no-export-load-in-svelte-module-in-kit-pages](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-export-load-in-svelte-module-in-kit-pages/) | disallow exporting load functions in `*.svelte` module in Svelte Kit page components. | |
| [svelte/no-not-data-props-in-kit-pages](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-not-data-props-in-kit-pages/) | disallow props other than data or errors in Svelte Kit page components. | |
| [svelte/no-not-function-handler](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-not-function-handler/) | disallow use of not function in event handler | :star: |
| [svelte/no-object-in-text-mustaches](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-object-in-text-mustaches/) | disallow objects in text mustache interpolation | :star: |
| [svelte/no-shorthand-style-property-overrides](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: |
| [svelte/no-store-async](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-store-async/) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | |
| [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/) | (no description) | |
| [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: |

## Security Vulnerability
Expand Down
3 changes: 2 additions & 1 deletion docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ These rules relate to possible syntax or logic errors in Svelte code:
| [svelte/no-dupe-style-properties](./rules/no-dupe-style-properties.md) | disallow duplicate style properties | :star: |
| [svelte/no-dynamic-slot-name](./rules/no-dynamic-slot-name.md) | disallow dynamic slot name | :star::wrench: |
| [svelte/no-export-load-in-svelte-module-in-kit-pages](./rules/no-export-load-in-svelte-module-in-kit-pages.md) | disallow exporting load functions in `*.svelte` module in Svelte Kit page components. | |
| [svelte/no-not-data-props-in-kit-pages](./rules/no-not-data-props-in-kit-pages.md) | disallow props other than data or errors in Svelte Kit page components. | |
| [svelte/no-not-function-handler](./rules/no-not-function-handler.md) | disallow use of not function in event handler | :star: |
| [svelte/no-object-in-text-mustaches](./rules/no-object-in-text-mustaches.md) | disallow objects in text mustache interpolation | :star: |
| [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: |
| [svelte/no-store-async](./rules/no-store-async.md) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | |
| [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) | (no description) | |
| [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: |

## Security Vulnerability
Expand Down
61 changes: 61 additions & 0 deletions docs/rules/no-not-data-props-in-kit-pages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
pageClass: "rule-details"
sidebarDepth: 0
title: "svelte/no-not-data-props-in-kit-pages"
description: "disallow props other than data or errors in Svelte Kit page components."
---

# svelte/no-not-data-props-in-kit-pages

> disallow props other than data or errors in Svelte Kit page components.

- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>

## :book: Rule Details

This rule reports unexpected exported variables at `<script>`.<br>
At SvelteKit v1.0.0-next.405, instead of having multiple props corresponding to the props returned from a load function, page components now have a single data prop.

<script>
const config = {settings: {
kit: {
files: {
routes: "",
},
},
},
}
</script>

<ESLintCodeBlock config="{config}">

<!--eslint-skip-->

```svelte
<script>
/* eslint svelte/no-not-data-props-in-kit-pages: "error" */
/** ✓ GOOD */
export let data
export let errors
/** ✗ BAD */
export let foo
export let bar
</script>

{foo}, {bar}
```

</ESLintCodeBlock>

## :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/no-not-data-props-in-kit-pages.ts)
- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/no-not-data-props-in-kit-pages.ts)
4 changes: 3 additions & 1 deletion docs/rules/require-store-callbacks-use-set-param.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ description: "store callbacks must use `set` param"

# svelte/require-store-callbacks-use-set-param

> Store callbacks must use `set` param.
> store callbacks must use `set` param

- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>

## :book: Rule Details

Expand Down
62 changes: 62 additions & 0 deletions src/rules/no-not-data-props-in-kit-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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("no-not-data-props-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 {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think isKitPageComponent needs to be changed to be more strict.
I think we need to check if the file name starts with +.
For filenames that don't start with +, it may just be a component.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added check logic and fixed tests.

let isScript = false
return {
// <script>
[`Program > SvelteScriptElement > SvelteStartTag`]: (
node: AST.SvelteStartTag,
) => {
// except for <script context="module">
isScript = !node.attributes.some(
(a) =>
a.type === "SvelteAttribute" &&
a.key.name === "context" &&
a.value.some(
(v) => v.type === "SvelteLiteral" && v.value === "module",
),
)
},

// </script>
"Program > SvelteScriptElement:exit": () => {
isScript = false
},

// export let xxx
[`ExportNamedDeclaration > VariableDeclaration > VariableDeclarator > Identifier`]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not enough to just check the Identifier.

export let {a, b} = obj

I think it's better to select a VariableDeclarator and report an node.id other than Identifire, or something other than data or error.

"ExportNamedDeclaration > VariableDeclaration > VariableDeclarator"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh export let { data, errors } = { data: {}, errors: {} } is correct way.

https://svelte.dev/repl/61922177a5944a5294e9551787479d6a?version=3.52.0

I updated the logic, so could you please review it again?

(node: ESTree.Identifier) => {
if (!isScript) return {}
const { name } = node
if (EXPECTED_PROP_NAMES.includes(name)) return {}
return context.report({
node,
loc: node.loc!,
messageId: "unexpected",
})
},
}
},
})
2 changes: 2 additions & 0 deletions src/utils/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import noDynamicSlotName from "../rules/no-dynamic-slot-name"
import noExportLoadInSvelteModuleInKitPages from "../rules/no-export-load-in-svelte-module-in-kit-pages"
import noExtraReactiveCurlies from "../rules/no-extra-reactive-curlies"
import noInnerDeclarations from "../rules/no-inner-declarations"
import noNotDataPropsInKitPages from "../rules/no-not-data-props-in-kit-pages"
import noNotFunctionHandler from "../rules/no-not-function-handler"
import noObjectInTextMustaches from "../rules/no-object-in-text-mustaches"
import noReactiveFunctions from "../rules/no-reactive-functions"
Expand Down Expand Up @@ -63,6 +64,7 @@ export const rules = [
noExportLoadInSvelteModuleInKitPages,
noExtraReactiveCurlies,
noInnerDeclarations,
noNotDataPropsInKitPages,
noNotFunctionHandler,
noObjectInTextMustaches,
noReactiveFunctions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"settings": {
"kit": {
"files": {
"routes": "tests/fixtures"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
export let foo
export let bar
</script>

{foo}, {bar}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"settings": {
"kit": {
"files": {
"routes": "tests/fixtures"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
export let data
export let errors
export let foo
export let bar
</script>

{data}, {errors}, {foo}, {bar}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
export let data
export let errors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this and noticed that errors is also allowed.
So I think it would be better to change the rule name (no-not-data-props-in-kit-pages) from what I suggested 😓.

Do you have any good ideas?
For example, how about a name like valid-prop-names-in-kit-pages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the rule name according to your suggestion!

</script>

{data}, {errors}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script context="module">
export let data
export let errors
export let foo
export let bar
</script>

{data}, {errors}, {foo}, {bar}
16 changes: 16 additions & 0 deletions tests/src/rules/no-not-data-props-in-kit-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { RuleTester } from "eslint"
import rule from "../../../src/rules/no-not-data-props-in-kit-pages"
import { loadTestCases } from "../../utils/utils"

const tester = new RuleTester({
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
},
})

tester.run(
"no-not-data-props-in-kit-pages",
rule as any,
loadTestCases("no-not-data-props-in-kit-pages"),
)