Skip to content

Commit 6f1cc06

Browse files
committed
implement rule
1 parent 3feb974 commit 6f1cc06

File tree

6 files changed

+194
-4
lines changed

6 files changed

+194
-4
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ These rules extend the rules provided by ESLint itself, or other plugins to work
382382
| Rule ID | Description | |
383383
|:--------|:------------|:---|
384384
| [svelte/no-inner-declarations](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-inner-declarations/) | disallow variable or `function` declarations in nested blocks | :star: |
385+
| [svelte/no-restricted-html-elements](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-restricted-html-elements/) | (no description) | |
385386
| [svelte/no-trailing-spaces](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-trailing-spaces/) | disallow trailing whitespace at the end of lines | :wrench: |
386387

387388
## Experimental

docs/rules.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,11 @@ These rules relate to style guidelines, and are therefore quite subjective:
9292

9393
These rules extend the rules provided by ESLint itself, or other plugins to work well in Svelte:
9494

95-
| Rule ID | Description | |
96-
| :--------------------------------------------------------------- | :------------------------------------------------------------ | :------- |
97-
| [svelte/no-inner-declarations](./rules/no-inner-declarations.md) | disallow variable or `function` declarations in nested blocks | :star: |
98-
| [svelte/no-trailing-spaces](./rules/no-trailing-spaces.md) | disallow trailing whitespace at the end of lines | :wrench: |
95+
| Rule ID | Description | |
96+
| :--------------------------------------------------------------------------- | :------------------------------------------------------------ | :------- |
97+
| [svelte/no-inner-declarations](./rules/no-inner-declarations.md) | disallow variable or `function` declarations in nested blocks | :star: |
98+
| [svelte/no-restricted-html-elements](./rules/no-restricted-html-elements.md) | (no description) | |
99+
| [svelte/no-trailing-spaces](./rules/no-trailing-spaces.md) | disallow trailing whitespace at the end of lines | :wrench: |
99100

100101
## Experimental
101102

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "svelte/no-restricted-html-elements"
5+
description: ""
6+
---
7+
8+
# svelte/no-restricted-html-elements
9+
10+
> This rule reports to usage of resticted HTML elements.
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 to usage of resticted HTML elements.
17+
18+
<ESLintCodeBlock>
19+
20+
<!--eslint-skip-->
21+
22+
```svelte
23+
<script>
24+
/* eslint svelte/no-restricted-html-elements: ["error", ["h1", "h2", "h3", "h4", "h5", "h6"]] */
25+
</script>
26+
27+
<!-- ✓ GOOD -->
28+
<div>
29+
<p>Hi!</p>
30+
</div>
31+
32+
<!-- ✗ BAD -->
33+
<h1>foo</h1>
34+
35+
<div>
36+
<h2>bar</h2>
37+
</div>
38+
```
39+
40+
</ESLintCodeBlock>
41+
42+
---
43+
44+
<ESLintCodeBlock>
45+
46+
<!--eslint-skip-->
47+
48+
```svelte
49+
<script>
50+
/* eslint svelte/no-restricted-html-elements: ["error", { "elements": ["marquee"], "message": "Do not use deprecated HTML tags" }] */
51+
</script>
52+
53+
<!-- ✓ GOOD -->
54+
<div>
55+
<p>Hi!</p>
56+
</div>
57+
58+
<!-- ✗ BAD -->
59+
<marquee>foo</marquee>
60+
61+
<div>
62+
<marquee>bar</marquee>
63+
</div>
64+
```
65+
66+
</ESLintCodeBlock>
67+
68+
## :wrench: Options
69+
70+
This rule takes a list of strings, where each string is an HTML element name to be restricted:
71+
72+
```json
73+
{
74+
"svelte/no-restricted-html-elements": [
75+
"error",
76+
["h1", "h2", "h3", "h4", "h5", "h6"]
77+
]
78+
}
79+
```
80+
81+
Alternatively, the rule also accepts objects.
82+
83+
```json
84+
{
85+
"svelte/no-restricted-html-elements": [
86+
"error",
87+
{
88+
"elements": ["h1", "h2", "h3", "h4", "h5", "h6"],
89+
"message": "Prefer use of our custom <Heading /> component"
90+
},
91+
{
92+
"elements": ["marquee"],
93+
"message": "Do not use deprecated HTML tags"
94+
}
95+
]
96+
}
97+
```
98+
99+
## :mag: Implementation
100+
101+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/src/rules/no-restricted-html-elements.ts)
102+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/tests/src/rules/no-restricted-html-elements.ts)
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { createRule } from "../utils"
2+
3+
export default createRule("no-restricted-html-elements", {
4+
meta: {
5+
docs: {
6+
description: "disallow specific HTML elements",
7+
category: "Extension Rules",
8+
recommended: false,
9+
},
10+
schema: {
11+
type: "array",
12+
items: {
13+
oneOf: [
14+
{
15+
type: "array",
16+
items: {
17+
type: ["string"],
18+
},
19+
uniqueItems: true,
20+
minItems: 1,
21+
},
22+
{
23+
type: "object",
24+
properties: {
25+
elements: {
26+
type: "array",
27+
items: {
28+
type: ["string"],
29+
},
30+
uniqueItems: true,
31+
minItems: 1,
32+
},
33+
message: { type: "string", minLength: 1 },
34+
},
35+
additionalProperties: false,
36+
},
37+
],
38+
},
39+
uniqueItems: true,
40+
minItems: 0,
41+
},
42+
messages: {},
43+
type: "suggestion",
44+
},
45+
create(context) {
46+
return {
47+
SvelteElement(node) {
48+
if (node.kind !== "html") return
49+
const { name } = node
50+
if (name.type !== "SvelteName") return
51+
for (const option of context.options) {
52+
const message =
53+
option.message ||
54+
`Unexpected use of forbidden HTML element ${name.name}.`
55+
const elements = option.elements || option
56+
for (const element of elements) {
57+
if (element === name.name) {
58+
context.report({
59+
message,
60+
node: node.startTag,
61+
})
62+
}
63+
}
64+
}
65+
},
66+
}
67+
},
68+
})

src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import noObjectInTextMustaches from "../rules/no-object-in-text-mustaches"
3434
import noReactiveFunctions from "../rules/no-reactive-functions"
3535
import noReactiveLiterals from "../rules/no-reactive-literals"
3636
import noReactiveReassign from "../rules/no-reactive-reassign"
37+
import noRestrictedHtmlElements from "../rules/no-restricted-html-elements"
3738
import noShorthandStylePropertyOverrides from "../rules/no-shorthand-style-property-overrides"
3839
import noSpacesAroundEqualSignsInAttribute from "../rules/no-spaces-around-equal-signs-in-attribute"
3940
import noStoreAsync from "../rules/no-store-async"
@@ -93,6 +94,7 @@ export const rules = [
9394
noReactiveFunctions,
9495
noReactiveLiterals,
9596
noReactiveReassign,
97+
noRestrictedHtmlElements,
9698
noShorthandStylePropertyOverrides,
9799
noSpacesAroundEqualSignsInAttribute,
98100
noStoreAsync,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { RuleTester } from "eslint"
2+
import rule from "../../../src/rules/no-restricted-html-elements"
3+
import { loadTestCases } from "../../utils/utils"
4+
5+
const tester = new RuleTester({
6+
parserOptions: {
7+
ecmaVersion: 2020,
8+
sourceType: "module",
9+
},
10+
})
11+
12+
tester.run(
13+
"no-restricted-html-elements",
14+
rule as any,
15+
loadTestCases("no-restricted-html-elements"),
16+
)

0 commit comments

Comments
 (0)