Skip to content

Commit 067e90c

Browse files
committed
Add rules, test codes
1 parent f8f377f commit 067e90c

File tree

16 files changed

+193
-0
lines changed

16 files changed

+193
-0
lines changed

Diff for: .node-version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18.16.1

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
392392
| [svelte/no-reactive-reassign](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-reactive-reassign/) | disallow reassigning reactive values | |
393393
| [svelte/no-shorthand-style-property-overrides](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: |
394394
| [svelte/no-store-async](https://sveltejs.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 | |
395+
| [svelte/no-undefined-print](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-undefined-print/) | Disallow from printing `undefined` | :star: |
395396
| [svelte/no-unknown-style-directive-property](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: |
396397
| [svelte/require-store-callbacks-use-set-param](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | store callbacks must use `set` param | |
397398
| [svelte/require-store-reactive-access](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-reactive-access/) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :wrench: |

Diff for: docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
2929
| [svelte/no-reactive-reassign](./rules/no-reactive-reassign.md) | disallow reassigning reactive values | |
3030
| [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: |
3131
| [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 | |
32+
| [svelte/no-undefined-print](./rules/no-undefined-print.md) | Disallow from printing `undefined` | :star: |
3233
| [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: |
3334
| [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | |
3435
| [svelte/require-store-reactive-access](./rules/require-store-reactive-access.md) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :wrench: |

Diff for: docs/rules/no-undefined-print.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-undefined-print'
5+
description: 'Disallow from printing `undefined`'
6+
since: 'v0.0.1'
7+
---
8+
9+
# svelte/no-undefined-print
10+
11+
> Disallow from printing `undefined`
12+
13+
- :gear: This rule is included in `"plugin:svelte/recommended"`.
14+
15+
## :book: Rule Details
16+
17+
This rule reports all uses of `{@html}` in order to reduce the risk of injecting potentially unsafe / unescaped html into the browser leading to Cross-Site Scripting (XSS) attacks.
18+
19+
<ESLintCodeBlock>
20+
21+
<!--eslint-skip-->
22+
23+
```svelte
24+
<script>
25+
/* eslint svelte/no-at-html-tags: "error" */
26+
</script>
27+
28+
<!-- ✓ GOOD -->
29+
{foo}
30+
31+
<!-- ✗ BAD -->
32+
{@html foo}
33+
```
34+
35+
</ESLintCodeBlock>
36+
37+
## :wrench: Options
38+
39+
Nothing.
40+
41+
## :mute: When Not To Use It
42+
43+
If you are certain the content passed to `{@html}` is sanitized HTML you can disable this rule.
44+
45+
## :books: Further Reading
46+
47+
- [Svelte - Tutorial > 1. Introduction / HTML tags](https://svelte.dev/tutorial/html-tags)
48+
49+
## :rocket: Version
50+
51+
This rule was introduced in eslint-plugin-svelte v0.0.1
52+
53+
## :mag: Implementation
54+
55+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/src/rules/no-undefined-print.ts)
56+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/tests/src/rules/no-undefined-print.ts)

Diff for: packages/eslint-plugin-svelte/src/configs/flat/recommended.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const config: Linter.FlatConfig[] = [
1919
'svelte/no-not-function-handler': 'error',
2020
'svelte/no-object-in-text-mustaches': 'error',
2121
'svelte/no-shorthand-style-property-overrides': 'error',
22+
'svelte/no-undefined-print': 'error',
2223
'svelte/no-unknown-style-directive-property': 'error',
2324
'svelte/no-unused-svelte-ignore': 'error',
2425
'svelte/system': 'error',

Diff for: packages/eslint-plugin-svelte/src/configs/recommended.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const config: Linter.Config = {
1919
'svelte/no-not-function-handler': 'error',
2020
'svelte/no-object-in-text-mustaches': 'error',
2121
'svelte/no-shorthand-style-property-overrides': 'error',
22+
'svelte/no-undefined-print': 'error',
2223
'svelte/no-unknown-style-directive-property': 'error',
2324
'svelte/no-unused-svelte-ignore': 'error',
2425
'svelte/system': 'error',

Diff for: packages/eslint-plugin-svelte/src/rule-types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ export interface RuleOptions {
224224
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-trailing-spaces/
225225
*/
226226
'svelte/no-trailing-spaces'?: Linter.RuleEntry<SvelteNoTrailingSpaces>
227+
/**
228+
* Disallow from printing `undefined`
229+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-undefined-print/
230+
*/
231+
'svelte/no-undefined-print'?: Linter.RuleEntry<[]>
227232
/**
228233
* disallow unknown `style:property`
229234
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { AST } from 'svelte-eslint-parser';
2+
import { createRule } from '../utils';
3+
4+
export default createRule('no-undefined-print', {
5+
meta: {
6+
docs: {
7+
description: 'Disallow from printing `undefined`',
8+
category: 'Possible Errors',
9+
recommended: true
10+
},
11+
schema: [],
12+
messages: {
13+
unexpected: 'Unexpected `undefined`.'
14+
},
15+
type: 'problem'
16+
},
17+
create(context) {
18+
return {
19+
'SvelteMustacheTag[kind=text]'(node: AST.SvelteMustacheTag) {
20+
if (node.expression.type === 'Identifier' && node.expression.name === 'undefined') {
21+
context.report({
22+
node,
23+
messageId: 'unexpected'
24+
});
25+
}
26+
27+
if (node.expression.type === 'LogicalExpression' && node.expression.operator === '||') {
28+
const left = node.expression.left;
29+
const right = node.expression.right;
30+
31+
if (left.type === 'Identifier' && right.type === 'Literal' && right.value === undefined) {
32+
context.report({
33+
node,
34+
messageId: 'unexpected'
35+
});
36+
}
37+
}
38+
39+
if (node.expression.type === 'LogicalExpression' && node.expression.operator === '??') {
40+
const left = node.expression.left;
41+
const right = node.expression.right;
42+
43+
if (left.type === 'Identifier' && right.type === 'Literal' && right.value === undefined) {
44+
context.report({
45+
node,
46+
messageId: 'unexpected'
47+
});
48+
}
49+
}
50+
51+
if (node.expression.type === 'ConditionalExpression') {
52+
const consequent = node.expression.consequent;
53+
const alternate = node.expression.alternate;
54+
55+
if (
56+
(consequent.type === 'Literal' && consequent.value === undefined) ||
57+
(alternate.type === 'Literal' && alternate.value === undefined)
58+
) {
59+
context.report({
60+
node,
61+
messageId: 'unexpected'
62+
});
63+
}
64+
}
65+
}
66+
};
67+
}
68+
});

Diff for: packages/eslint-plugin-svelte/src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import noStoreAsync from '../rules/no-store-async';
4444
import noSvelteInternal from '../rules/no-svelte-internal';
4545
import noTargetBlank from '../rules/no-target-blank';
4646
import noTrailingSpaces from '../rules/no-trailing-spaces';
47+
import noUndefinedPrint from '../rules/no-undefined-print';
4748
import noUnknownStyleDirectiveProperty from '../rules/no-unknown-style-directive-property';
4849
import noUnusedClassName from '../rules/no-unused-class-name';
4950
import noUnusedSvelteIgnore from '../rules/no-unused-svelte-ignore';
@@ -109,6 +110,7 @@ export const rules = [
109110
noSvelteInternal,
110111
noTargetBlank,
111112
noTrailingSpaces,
113+
noUndefinedPrint,
112114
noUnknownStyleDirectiveProperty,
113115
noUnusedClassName,
114116
noUnusedSvelteIgnore,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: 'Unexpected `undefined`aa.'
2+
line: 52
3+
column: 44
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let string = `this string contains some <strong>HTML!!!</strong>`;
3+
</script>
4+
5+
<p>{@html string}</p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
let user = {
3+
firstname: 'Ada',
4+
lastname: 'Lovelace'
5+
};
6+
</script>
7+
8+
<input bind:value={user.firstname} />
9+
<input bind:value={user.lastname} />
10+
11+
{@debug}
12+
13+
<h1>Hello {user.firstname}!</h1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
let user = {
3+
firstname: 'Ada',
4+
lastname: 'Lovelace'
5+
};
6+
</script>
7+
8+
<input bind:value={user.firstname} />
9+
<input bind:value={user.lastname} />
10+
11+
{@debug user}
12+
13+
<h1>Hello {user.firstname}!</h1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let string;
3+
</script>
4+
5+
<p>{string}</p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let string = 'abc';
3+
</script>
4+
5+
<p>{string}</p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { RuleTester } from '../../utils/eslint-compat';
2+
import rule from '../../../src/rules/no-undefined-print';
3+
import { loadTestCases } from '../../utils/utils';
4+
5+
const tester = new RuleTester({
6+
languageOptions: {
7+
ecmaVersion: 2020,
8+
sourceType: 'module'
9+
}
10+
});
11+
12+
tester.run('no-undefined-print', rule as any, loadTestCases('no-undefined-print'));

0 commit comments

Comments
 (0)