-
-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathvalid-prop-names-in-kit-pages.ts
120 lines (108 loc) · 3.01 KB
/
valid-prop-names-in-kit-pages.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import type { AST } from 'svelte-eslint-parser';
import type { TSESTree } from '@typescript-eslint/types';
import { createRule } from '../utils/index.js';
import type { RuleContext } from '../types.js';
import { getSvelteVersion } from '../utils/svelte-context.js';
const EXPECTED_PROP_NAMES = ['data', 'errors', 'form', 'snapshot'];
const EXPECTED_PROP_NAMES_SVELTE5 = [...EXPECTED_PROP_NAMES, 'children'];
function checkProp(
node: TSESTree.VariableDeclarator,
context: RuleContext,
expectedPropNames: string[]
) {
if (node.id.type !== 'ObjectPattern') return;
for (const p of node.id.properties) {
if (
p.type === 'Property' &&
p.key.type === 'Identifier' &&
!expectedPropNames.includes(p.key.name)
) {
context.report({
node: p.key,
loc: p.key.loc,
messageId: 'unexpected'
});
}
}
}
function isModuleScript(node: AST.SvelteAttribute) {
// <script context="module">
if (
node.key.name === 'context' &&
node.value.some((v) => v.type === 'SvelteLiteral' && v.value === 'module')
) {
return true;
}
// <script module>
if (node.key.name === 'module' && node.value.length === 0) {
return true;
}
return false;
}
export default createRule('valid-prop-names-in-kit-pages', {
meta: {
docs: {
description: 'disallow props other than data or errors in SvelteKit page components.',
category: 'SvelteKit',
recommended: true
},
schema: [],
messages: {
unexpected: 'disallow props other than data or errors in SvelteKit page components.'
},
type: 'problem',
conditions: [
{
svelteKitFileTypes: ['+page.svelte', '+error.svelte', '+layout.svelte']
}
]
},
create(context) {
let isScript = false;
const isSvelte5 = getSvelteVersion() === '5';
const expectedPropNames = isSvelte5 ? EXPECTED_PROP_NAMES_SVELTE5 : EXPECTED_PROP_NAMES;
return {
// <script>
'Program > SvelteScriptElement > SvelteStartTag': (node: AST.SvelteStartTag) => {
// except for <script context="module">
isScript = !node.attributes.some((a) => a.type === 'SvelteAttribute' && isModuleScript(a));
},
// </script>
'Program > SvelteScriptElement:exit': () => {
isScript = false;
},
// Svelte3,4
'ExportNamedDeclaration > VariableDeclaration > VariableDeclarator': (
node: TSESTree.VariableDeclarator
) => {
if (!isScript) return;
// export let foo
if (node.id.type === 'Identifier') {
if (!expectedPropNames.includes(node.id.name)) {
context.report({
node,
loc: node.loc,
messageId: 'unexpected'
});
}
return;
}
// export let { xxx, yyy } = zzz
checkProp(node, context, expectedPropNames);
},
// Svelte5
// let { foo, bar } = $props();
'VariableDeclaration > VariableDeclarator': (node: TSESTree.VariableDeclarator) => {
if (!isScript) return;
if (
node.init?.type !== 'CallExpression' ||
node.init.callee?.type !== 'Identifier' ||
node.init.callee?.name !== '$props'
) {
return;
}
checkProp(node, context, expectedPropNames);
}
};
}
});