@codelaw/rules-html 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/NOTICE +24 -0
- package/README.md +162 -2
- package/codelaw-pack.toml +6 -0
- package/data/html/elements.json +4892 -0
- package/data/html/entities.json +1 -0
- package/data/html/input-attributes.json +227 -0
- package/package.json +14 -4
- package/presets/html/a11y.toml +29 -0
- package/presets/html/conventions.toml +6 -0
- package/presets/html/document.toml +8 -0
- package/presets/html/recommended.toml +67 -0
- package/rules/html/area-alt.md +48 -0
- package/rules/html/aria-hidden-body.md +39 -0
- package/rules/html/aria-label-misuse.md +42 -0
- package/rules/html/attribute-allowed-values.cases.md +31 -0
- package/rules/html/attribute-allowed-values.md +41 -0
- package/rules/html/attribute-misuse.md +39 -0
- package/rules/html/autocomplete-password.md +41 -0
- package/rules/html/button-type.cases.md +28 -0
- package/rules/html/button-type.md +35 -0
- package/rules/html/close-attr.md +33 -0
- package/rules/html/close-order.cases.md +38 -0
- package/rules/html/close-order.md +47 -0
- package/rules/html/deprecated.md +39 -0
- package/rules/html/doctype-html.md +36 -0
- package/rules/html/element-name.cases.md +21 -0
- package/rules/html/element-name.md +42 -0
- package/rules/html/element-permitted-content.cases.md +54 -0
- package/rules/html/element-permitted-content.md +45 -0
- package/rules/html/element-permitted-occurrences.md +45 -0
- package/rules/html/element-permitted-order.md +44 -0
- package/rules/html/element-permitted-parent.cases.md +11 -0
- package/rules/html/element-permitted-parent.md +43 -0
- package/rules/html/element-required-ancestor.md +45 -0
- package/rules/html/element-required-attributes.md +44 -0
- package/rules/html/element-required-content.cases.md +23 -0
- package/rules/html/element-required-content.md +43 -0
- package/rules/html/empty-heading.md +40 -0
- package/rules/html/empty-title.md +39 -0
- package/rules/html/fieldset-legend.md +44 -0
- package/rules/html/form-dup-name.cases.md +38 -0
- package/rules/html/form-dup-name.md +48 -0
- package/rules/html/form-submit.md +44 -0
- package/rules/html/heading-level.cases.md +26 -0
- package/rules/html/heading-level.md +44 -0
- package/rules/html/hidden-focusable.cases.md +23 -0
- package/rules/html/hidden-focusable.md +40 -0
- package/rules/html/img-alt.cases.md +22 -0
- package/rules/html/img-alt.md +44 -0
- package/rules/html/img-title.md +40 -0
- package/rules/html/input-attributes.md +34 -0
- package/rules/html/input-image-alt.md +39 -0
- package/rules/html/input-missing-label.md +40 -0
- package/rules/html/link-text.md +39 -0
- package/rules/html/long-title.md +40 -0
- package/rules/html/map-dup-name.md +40 -0
- package/rules/html/map-id-name.md +38 -0
- package/rules/html/meta-refresh.md +42 -0
- package/rules/html/missing-doctype.cases.md +24 -0
- package/rules/html/missing-doctype.md +43 -0
- package/rules/html/multiple-labeled-controls.md +40 -0
- package/rules/html/no-abstract-role.md +39 -0
- package/rules/html/no-autoplay.md +37 -0
- package/rules/html/no-conditional-comment.md +39 -0
- package/rules/html/no-deprecated-attr.md +39 -0
- package/rules/html/no-dup-attr.md +37 -0
- package/rules/html/no-dup-class.md +33 -0
- package/rules/html/no-duplicate-id.cases.md +23 -0
- package/rules/html/no-duplicate-id.md +42 -0
- package/rules/html/no-implicit-close.cases.md +38 -0
- package/rules/html/no-implicit-close.md +40 -0
- package/rules/html/no-implicit-input-type.md +34 -0
- package/rules/html/no-inline-script.md +42 -0
- package/rules/html/no-inline-style.cases.md +12 -0
- package/rules/html/no-inline-style.md +42 -0
- package/rules/html/no-missing-references.md +39 -0
- package/rules/html/no-multiple-main.md +40 -0
- package/rules/html/no-raw-characters.cases.md +84 -0
- package/rules/html/no-raw-characters.md +35 -0
- package/rules/html/no-redundant-aria-label.md +36 -0
- package/rules/html/no-redundant-for.md +34 -0
- package/rules/html/no-redundant-role.md +42 -0
- package/rules/html/no-utf8-bom.md +45 -0
- package/rules/html/prefer-button.md +39 -0
- package/rules/html/prefer-native-element.md +40 -0
- package/rules/html/prefer-tbody.md +41 -0
- package/rules/html/require-sri.md +41 -0
- package/rules/html/script-element.md +36 -0
- package/rules/html/script-type.md +33 -0
- package/rules/html/target-blank-rel.cases.md +35 -0
- package/rules/html/target-blank-rel.md +32 -0
- package/rules/html/tel-non-breaking.md +37 -0
- package/rules/html/text-content.md +39 -0
- package/rules/html/th-scope.md +47 -0
- package/rules/html/unique-landmark.md +41 -0
- package/rules/html/unrecognized-char-ref.cases.md +41 -0
- package/rules/html/unrecognized-char-ref.md +42 -0
- package/rules/html/valid-autocomplete.cases.md +42 -0
- package/rules/html/valid-autocomplete.md +42 -0
- package/rules/html/valid-for.md +40 -0
- package/rules/html/valid-id.md +40 -0
- package/rules/html/void-content.md +34 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# html/no-implicit-close — cases
|
|
2
|
+
|
|
3
|
+
### case: a paragraph closed by a following block
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<p>One
|
|
7
|
+
<div>Two</div>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
1:1 html/no-implicit-close
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```fixed
|
|
15
|
+
<p>One</p>
|
|
16
|
+
<div>Two</div>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### case: table cells closed by the next row
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<table>
|
|
23
|
+
<tr><td>1
|
|
24
|
+
<tr><td>2</td></tr>
|
|
25
|
+
</table>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```expect
|
|
29
|
+
2:3 html/no-implicit-close
|
|
30
|
+
2:7 html/no-implicit-close
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```fixed
|
|
34
|
+
<table>
|
|
35
|
+
<tr><td>1</td></tr>
|
|
36
|
+
<tr><td>2</td></tr>
|
|
37
|
+
</table>
|
|
38
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-implicit-close
|
|
3
|
+
title: "Elements are closed explicitly"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the end tag goes after the element's last content, so whitespace that followed it moves outside the element"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-implicit-close]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Elements whose end tag HTML lets you leave out (`<li>`, `<p>`, `<td>`, `<option>`, `<head>`, …) are closed with it anyway.
|
|
13
|
+
|
|
14
|
+
**Why:** Implied end tags make nesting hard to read, and an element closed by the next tag is easy to break when markup moves.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-implicit-close
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<ul>
|
|
28
|
+
<li>One
|
|
29
|
+
<li>Two
|
|
30
|
+
</ul>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Do
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<ul>
|
|
37
|
+
<li>One</li>
|
|
38
|
+
<li>Two</li>
|
|
39
|
+
</ul>
|
|
40
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-implicit-input-type
|
|
3
|
+
title: "<input> says what type it is"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "`type=\"text\"` is the default, but the field may have been meant as another type"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-implicit-input-type]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
An `<input>` has a `type` attribute.
|
|
13
|
+
|
|
14
|
+
**Why:** The default, `text`, is easy to leave by accident where `email`, `number` or `search` was meant.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-implicit-input-type
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<input name="q">
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<input type="text" name="q">
|
|
34
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-inline-script
|
|
3
|
+
title: "No inline event handlers or javascript: URLs"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the handler has to move into a script file"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [htmlhint/inline-script-disabled]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Elements don't have inline event handlers (`onclick`, `onload`, …) or `javascript:` URLs.
|
|
13
|
+
|
|
14
|
+
**Why:** Inline script mixes behaviour into markup, can't be cached or tested, and is blocked by a strict Content Security Policy.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-inline-script
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Give the element an id or class.
|
|
23
|
+
2. Attach the listener with `addEventListener` in a script file.
|
|
24
|
+
3. Replace a `javascript:` link with a `<button>`.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<button type="button" onclick="save()">Save</button>
|
|
34
|
+
<a href="javascript:void(0)">Menu</a>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<button type="button" id="save">Save</button>
|
|
41
|
+
<button type="button" id="menu">Menu</button>
|
|
42
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-inline-style
|
|
3
|
+
title: "No inline styles"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the styles need a class and a stylesheet rule"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
allowedProperties: { type: "string[]", default: ["display"], description: "properties an inline style may set" }
|
|
10
|
+
allowVariables: { type: "boolean", default: true, description: "let inline styles set custom properties (`--name`)" }
|
|
11
|
+
ported_from: [html-validate/no-inline-style, htmlhint/inline-style-disabled]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Elements don't have a `style` attribute, except one that only sets `display` or custom properties.
|
|
16
|
+
|
|
17
|
+
**Why:** Inline styles can't be reused, override stylesheets with high specificity, and are blocked by a strict Content Security Policy.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/no-inline-style
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Move the declarations into a stylesheet rule for a class.
|
|
26
|
+
2. Replace the `style` attribute with that class.
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
### HTML
|
|
31
|
+
|
|
32
|
+
#### Don't
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<p style="color: red; font-weight: bold">Warning</p>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Do
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<p class="warning">Warning</p>
|
|
42
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-missing-references
|
|
3
|
+
title: "Id references point at an element"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "either the id or the reference is wrong, and only the author knows which"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-missing-references]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Attributes that refer to ids — `for`, `form`, `list`, `headers`, `aria-labelledby`, `aria-describedby`, `aria-controls` and the others — name ids that exist in the document.
|
|
13
|
+
|
|
14
|
+
**Why:** A reference to a missing id silently does nothing: the label, description or relation is lost.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-missing-references
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Correct the reference, or add the element it should point at.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<input type="text" aria-describedby="hint">
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Do
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<input type="text" aria-describedby="hint">
|
|
38
|
+
<p id="hint">Use your work address.</p>
|
|
39
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-multiple-main
|
|
3
|
+
title: "One visible <main> per document"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which one is the main content is a design decision"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-multiple-main]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A document has at most one `<main>` without the `hidden` attribute.
|
|
13
|
+
|
|
14
|
+
**Why:** Assistive technology jumps to "the" main content; with two, users land on one and miss the other.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-multiple-main
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Keep one `<main>`; make the others `<section>`, `<aside>` or similar, or hide inactive ones with `hidden`.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<main>Feed</main>
|
|
32
|
+
<main>Sidebar</main>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<main>Feed</main>
|
|
39
|
+
<aside>Sidebar</aside>
|
|
40
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# html/no-raw-characters — cases
|
|
2
|
+
|
|
3
|
+
### case: a doctype tree-sitter cannot parse is not raw text
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<!DOCTYPE>
|
|
7
|
+
<p>Hi</p>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
(none)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### case: an unterminated reference is a raw ampersand
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<p>a  b</p>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```expect
|
|
21
|
+
1:5 html/no-raw-characters
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```fixed
|
|
25
|
+
<p>a&nbsp b</p>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### case: = in an unquoted attribute
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<a href=/x?a=1>x</a>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```expect
|
|
35
|
+
1:13 html/no-raw-characters
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```fixed
|
|
39
|
+
<a href=/x?a=1>x</a>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### case: quoted attribute values may hold anything
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<a href="/x?a=1&b=2">x</a>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```expect
|
|
49
|
+
(none)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### case: script content is not text
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<script>if (a < b && c) {}</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```expect
|
|
59
|
+
(none)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### case: template tags are left alone
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<p><%= user.name %></p>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```expect
|
|
69
|
+
(none)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### case: text tree-sitter cannot parse, with multi-byte characters
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<p>中文 & 日本語</p>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```expect
|
|
79
|
+
1:7 html/no-raw-characters
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```fixed
|
|
83
|
+
<p>中文 & 日本語</p>
|
|
84
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-raw-characters
|
|
3
|
+
title: "Special characters are escaped"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
options:
|
|
8
|
+
relaxed: { type: "boolean", default: false, description: "don't report `&`" }
|
|
9
|
+
ported_from: [html-validate/no-raw-characters, htmlhint/spec-char-escape]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Text doesn't contain a raw `<` or an `&` that could be read as a character reference, and an unquoted attribute value doesn't contain `"`, `'`, `<`, `=`, `>`, `` ` `` or such an `&`.
|
|
14
|
+
|
|
15
|
+
**Why:** The parser can read them as markup: `©=1` becomes `©=1`, and `<` may start a tag.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/no-raw-characters
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
### HTML
|
|
24
|
+
|
|
25
|
+
#### Don't
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<p>Fish & chips</p>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### Do
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<p>Fish & chips</p>
|
|
35
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-redundant-aria-label
|
|
3
|
+
title: "aria-label doesn't repeat the label"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/no-redundant-aria-label]
|
|
8
|
+
tags: [a11y]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A form control doesn't have an `aria-label` equal to the text of its `<label for>`.
|
|
13
|
+
|
|
14
|
+
**Why:** The label already names the control; the copy drifts out of date when only the visible label is edited.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-redundant-aria-label
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<label for="q">Search</label>
|
|
28
|
+
<input type="text" id="q" aria-label="Search">
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### Do
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<label for="q">Search</label>
|
|
35
|
+
<input type="text" id="q">
|
|
36
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-redundant-for
|
|
3
|
+
title: "A wrapping label has no for"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/no-redundant-for]
|
|
8
|
+
tags: [a11y]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `<label>` that wraps its control doesn't also point at it with `for`.
|
|
13
|
+
|
|
14
|
+
**Why:** Wrapping already associates them; the `for` is one more id reference to keep in sync.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-redundant-for
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<label for="q">Search <input type="text" id="q"></label>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<label>Search <input type="text" id="q"></label>
|
|
34
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-redundant-role
|
|
3
|
+
title: "No role the element already has"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/no-redundant-role]
|
|
8
|
+
tags: [a11y]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
An element's `role` is not the role it has anyway, such as `<ul role="list">`, `<button role="button">` or `<a href role="link">`.
|
|
13
|
+
|
|
14
|
+
**Why:** The attribute repeats the element and suggests the element was chosen for its looks.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-redundant-role
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<ul role="list">
|
|
28
|
+
<li>One</li>
|
|
29
|
+
</ul>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### Do
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<ul>
|
|
36
|
+
<li>One</li>
|
|
37
|
+
</ul>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Differences from the source
|
|
41
|
+
|
|
42
|
+
Some Safari versions drop the list role of a `<ul>` styled with `list-style: none`; `role="list"` is a known workaround. Turn the rule off for such lists.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-utf8-bom
|
|
3
|
+
title: "No UTF-8 byte-order mark"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the mark is in the file's bytes, outside the text a fix can edit; the editor's encoding setting removes it"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-utf8-bom]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
An HTML file doesn't start with a UTF-8 byte-order mark (`EF BB BF`).
|
|
13
|
+
|
|
14
|
+
**Why:** UTF-8 needs no byte-order mark. Served or concatenated, the mark can show up as stray characters, or break a server-side include or a `<!DOCTYPE>` that must come first.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-utf8-bom
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Save the file as UTF-8 without a byte-order mark. In VS Code, click the encoding in the status bar, choose *Save with Encoding*, then *UTF-8*.
|
|
23
|
+
2. Or strip it from the command line: `sed -i '1s/^\xEF\xBB\xBF//' <file>` (GNU sed).
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<!DOCTYPE html>
|
|
33
|
+
<html lang="en"><title>Home</title></html>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<!DOCTYPE html>
|
|
40
|
+
<html lang="en"><title>Home</title></html>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Differences from the source
|
|
44
|
+
|
|
45
|
+
Only the file itself is checked: an HTML region inside another file (a Markdown fence, a template) holds no byte-order mark of its own.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/prefer-button
|
|
3
|
+
title: "Buttons are <button> elements"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the element changes, so CSS and scripts that select `input` need updating"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/prefer-button]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Buttons are written as `<button>`, not `<input type="button">`, `submit`, `reset` or `image`.
|
|
13
|
+
|
|
14
|
+
**Why:** `<button>` can hold markup and is styled and labelled more consistently.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/prefer-button
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Replace the `<input>` with a `<button>` of the same type, moving `value` into the content.
|
|
23
|
+
2. Update the CSS selectors and scripts that targeted the input.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<input type="submit" value="Send">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<button type="submit">Send</button>
|
|
39
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/prefer-native-element
|
|
3
|
+
title: "Native elements instead of ARIA roles"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "swapping the element changes its styles and scripts"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/prefer-native-element]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
An element doesn't take a role a native element provides, such as `role="button"` on a `<div>` or `role="navigation"` on a `<div>`.
|
|
14
|
+
|
|
15
|
+
**Why:** Native elements bring keyboard handling, focus and semantics for free; a role brings only the announcement.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/prefer-native-element
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Replace the element with the native one the message names.
|
|
24
|
+
2. Remove the `role` and any keyboard handling the native element now provides.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<div role="button" tabindex="0">Save</div>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<button type="button">Save</button>
|
|
40
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/prefer-tbody
|
|
3
|
+
title: "Table rows are in <tbody>"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/prefer-tbody]
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A table's `<tr>` rows sit in a `<tbody>` (or `<thead>`/`<tfoot>`), not directly in `<table>`.
|
|
12
|
+
|
|
13
|
+
**Why:** Browsers insert the `<tbody>` anyway, so the markup doesn't match the DOM that CSS and scripts see.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: html/prefer-tbody
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### HTML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<table>
|
|
27
|
+
<tr><td>1</td></tr>
|
|
28
|
+
</table>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### Do
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<table>
|
|
35
|
+
<tbody><tr><td>1</td></tr></tbody>
|
|
36
|
+
</table>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Differences from the source
|
|
40
|
+
|
|
41
|
+
The fix is offered when the rows are next to each other; rows separated by other elements are only reported.
|