Skip to content

Commit c587629

Browse files
authoredFeb 9, 2025
feat: implemented the valid-style-parse rule (#1054)
1 parent 1395d5d commit c587629

17 files changed

+249
-1
lines changed
 

‎.changeset/stupid-penguins-smoke.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': minor
3+
---
4+
5+
feat: added the valid-style-parse rule

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
335335
| [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 | |
336336
| [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. | :star::wrench: |
337337
| [svelte/valid-compile](https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-compile/) | disallow warnings when compiling. | |
338+
| [svelte/valid-style-parse](https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-style-parse/) | require valid style element parsing | |
338339

339340
## Security Vulnerability
340341

‎docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
3232
| [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | |
3333
| [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. | :star::wrench: |
3434
| [svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | |
35+
| [svelte/valid-style-parse](./rules/valid-style-parse.md) | require valid style element parsing | |
3536

3637
## Security Vulnerability
3738

‎docs/rules/valid-style-parse.md

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/valid-style-parse'
5+
description: 'require valid style element parsing'
6+
---
7+
8+
# svelte/valid-style-parse
9+
10+
> require valid style element parsing
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
13+
14+
## :book: Rule Details
15+
16+
This rule reports issues with parsing of the `<style>` element by the svelte-eslint-parser.
17+
18+
<!--eslint-skip-->
19+
20+
```svelte
21+
<script>
22+
/* eslint svelte/valid-style-parse: ["error"] */
23+
</script>
24+
25+
<!-- ✓ GOOD -->
26+
<style>
27+
.class {
28+
font-weight: bold;
29+
}
30+
</style>
31+
```
32+
33+
```svelte
34+
<script>
35+
/* eslint svelte/valid-style-parse: ["error"] */
36+
</script>
37+
38+
<!-- ✓ GOOD -->
39+
<style lang="scss">
40+
.class {
41+
font-weight: bold;
42+
}
43+
</style>
44+
```
45+
46+
```svelte
47+
<script>
48+
/* eslint svelte/valid-style-parse: ["error"] */
49+
</script>
50+
51+
<!-- ✗ BAD -->
52+
<style>
53+
.class
54+
font-weight: bold;
55+
</style>
56+
```
57+
58+
```svelte
59+
<script>
60+
/* eslint svelte/valid-style-parse: ["error"] */
61+
</script>
62+
63+
<!-- ✗ BAD -->
64+
<style lang="unknown">
65+
.class {
66+
font-weight: bold;
67+
}
68+
</style>
69+
```
70+
71+
## :wrench: Options
72+
73+
Nothing.
74+
75+
## :mag: Implementation
76+
77+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/valid-style-parse.ts)
78+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/valid-style-parse.ts)

‎packages/eslint-plugin-svelte/src/rule-types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ export interface RuleOptions {
366366
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-prop-names-in-kit-pages/
367367
*/
368368
'svelte/valid-prop-names-in-kit-pages'?: Linter.RuleEntry<[]>
369+
/**
370+
* require valid style element parsing
371+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-style-parse/
372+
*/
373+
'svelte/valid-style-parse'?: Linter.RuleEntry<[]>
369374
}
370375

371376
/* ======= Declarations ======= */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { createRule } from '../utils/index.js';
2+
import { getCwd, getSourceCode } from '../utils/compat.js';
3+
4+
export default createRule('valid-style-parse', {
5+
meta: {
6+
docs: {
7+
description: 'require valid style element parsing',
8+
category: 'Possible Errors',
9+
recommended: false
10+
},
11+
schema: [],
12+
messages: {},
13+
type: 'problem'
14+
},
15+
create(context) {
16+
const sourceCode = getSourceCode(context);
17+
if (!sourceCode.parserServices.isSvelte) {
18+
return {};
19+
}
20+
const cwd = `${getCwd(context)}/`;
21+
22+
return {
23+
SvelteStyleElement(node) {
24+
const styleContext = sourceCode.parserServices.getStyleContext!();
25+
if (styleContext.status === 'parse-error') {
26+
context.report({
27+
loc: node.loc,
28+
message: `Error parsing style element. Error message: "${styleContext.error.message.replace(cwd, '')}"`
29+
});
30+
}
31+
if (styleContext.status === 'unknown-lang') {
32+
context.report({
33+
loc: node.loc,
34+
message: `Found unsupported style element language "${styleContext.sourceLang}"`
35+
});
36+
}
37+
}
38+
};
39+
}
40+
});

‎packages/eslint-plugin-svelte/src/utils/rules.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import system from '../rules/system.js';
7272
import validCompile from '../rules/valid-compile.js';
7373
import validEachKey from '../rules/valid-each-key.js';
7474
import validPropNamesInKitPages from '../rules/valid-prop-names-in-kit-pages.js';
75+
import validStyleParse from '../rules/valid-style-parse.js';
7576

7677
export const rules = [
7778
typescriptEslintNoUnnecessaryCondition,
@@ -143,5 +144,6 @@ export const rules = [
143144
system,
144145
validCompile,
145146
validEachKey,
146-
validPropNamesInKitPages
147+
validPropNamesInKitPages,
148+
validStyleParse
147149
] as RuleModule[];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- message: 'Error parsing style element. Error message:
2+
"tests/fixtures/rules/valid-style-parse/invalid/invalid-css01-input.svelte:4:11:
3+
Unknown word"'
4+
line: 7
5+
column: 1
6+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style>
8+
// This syntax is intentionally invalid CSS - this is to be used to test resiliency against invalid input
9+
.container {
10+
class .div-class/35
11+
# Weird comment
12+
color: red;
13+
14+
.span-class begin
15+
font-weight: bold;
16+
end
17+
}
18+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- message: 'Error parsing style element. Error message:
2+
"tests/fixtures/rules/valid-style-parse/invalid/invalid-scss01-input.svelte:4:11:
3+
Unknown word"'
4+
line: 7
5+
column: 1
6+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style lang="scss">
8+
// This syntax is intentionally invalid CSS - this is to be used to test resiliency against invalid input
9+
.container {
10+
class .div-class/35
11+
# Weird comment
12+
color: red;
13+
14+
.span-class begin
15+
font-weight: bold;
16+
end
17+
}
18+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Found unsupported style element language "invalid-lang"
2+
line: 7
3+
column: 1
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style lang="invalid-lang">
8+
// This syntax is intentionally invalid CSS - this is to be used to test resiliency against unknown style languages.
9+
.container {
10+
class .div-class/35
11+
# Weird comment
12+
color: red;
13+
14+
.span-class begin
15+
font-weight: bold;
16+
end
17+
}
18+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<a href="https://svelte.dev">Hello</a>
2+
3+
<span style="font-weight: bold;">World!</span>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<div class="div-class">Hello</div>
2+
3+
<span class="span-class">World!</span>
4+
5+
<style>
6+
.div-class {
7+
color: red;
8+
}
9+
10+
.span-class {
11+
font-weight: bold;
12+
}
13+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style lang="scss">
8+
.container {
9+
.div-class {
10+
// This is an inline comment
11+
color: red;
12+
}
13+
14+
.span-class {
15+
font-weight: bold;
16+
}
17+
}
18+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { RuleTester } from '../../utils/eslint-compat.js';
2+
import rule from '../../../src/rules/valid-style-parse.js';
3+
import { loadTestCases } from '../../utils/utils.js';
4+
5+
const tester = new RuleTester({
6+
languageOptions: {
7+
ecmaVersion: 2020,
8+
sourceType: 'module'
9+
}
10+
});
11+
12+
tester.run('valid-style-parse', rule as any, loadTestCases('valid-style-parse'));

0 commit comments

Comments
 (0)