@codelaw/rules-html 0.0.0-stage → 0.2.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 +166 -2
- package/codelaw-pack.toml +6 -0
- package/corpus.toml +76 -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,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/input-image-alt
|
|
3
|
+
title: "Image buttons have alt text"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the text needs a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/wcag/h36]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
An `<input type="image">` has non-empty `alt` text.
|
|
14
|
+
|
|
15
|
+
**Why:** The `alt` is the button's only name for screen readers and when the image doesn't load.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/input-image-alt
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Add `alt` saying what the button does.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<input type="image" src="go.png">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<input type="image" src="go.png" alt="Search">
|
|
39
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/input-missing-label
|
|
3
|
+
title: "Form controls have a label"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the label text needs a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/input-missing-label, htmlhint/input-requires-label]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Every visible `<input>`, `<select>` and `<textarea>` has a label: a `<label for>`, a wrapping `<label>`, `aria-label` or `aria-labelledby`, with text.
|
|
13
|
+
|
|
14
|
+
**Why:** Without a label, screen readers announce the control as "edit text" with no hint of what to enter.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/input-missing-label
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Add a `<label for>` with text, or wrap the control in a `<label>`.
|
|
23
|
+
2. If a visible label is impossible, add `aria-label`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<input type="text" name="q">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<label for="q">Search</label>
|
|
39
|
+
<input type="text" id="q" name="q">
|
|
40
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/link-text
|
|
3
|
+
title: "Links have text"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the link text needs a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/wcag/h30]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A link with `href` has text that says where it goes: content, an image with `alt`, or `aria-label`.
|
|
14
|
+
|
|
15
|
+
**Why:** Screen readers announce a link by its text; without it the user hears only "link".
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/link-text
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Give the link text, an image with `alt`, or an `aria-label`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<a href="/cart"><img src="cart.png" alt=""></a>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<a href="/cart"><img src="cart.png" alt="Cart"></a>
|
|
39
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/long-title
|
|
3
|
+
title: "Page titles are short"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "shortening a title needs a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
maxlength: { type: "integer", default: 70, description: "the longest title allowed, in characters" }
|
|
10
|
+
ported_from: [html-validate/long-title]
|
|
11
|
+
since: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
The `<title>` text is at most 70 characters.
|
|
15
|
+
|
|
16
|
+
**Why:** Search results and browser tabs cut long titles, often before the words that matter.
|
|
17
|
+
|
|
18
|
+
```codelaw
|
|
19
|
+
native: html/long-title
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How to fix
|
|
23
|
+
|
|
24
|
+
1. Shorten the title to what identifies the page.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<title>Acme Corporation — Products, Services, Pricing, Support, Downloads and Contact Details</title>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<title>Pricing — Acme</title>
|
|
40
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/map-dup-name
|
|
3
|
+
title: "Image maps have unique names"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "renaming a map means updating the `usemap` that points at it"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/map-dup-name]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
No two `<map>` elements share a `name`.
|
|
13
|
+
|
|
14
|
+
**Why:** An image's `usemap` picks one by name, so the other map is unreachable.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/map-dup-name
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Rename one map and the `usemap` attributes that refer to it.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<map name="nav"></map>
|
|
32
|
+
<map name="nav"></map>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<map name="nav"></map>
|
|
39
|
+
<map name="footer-nav"></map>
|
|
40
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/map-id-name
|
|
3
|
+
title: "A map's id and name match"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which of the two names is right depends on what refers to the map"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/map-id-name]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
When a `<map>` has both `id` and `name`, they are the same.
|
|
13
|
+
|
|
14
|
+
**Why:** HTML requires them to match; tools that look maps up by `id` and browsers that use `name` would find different maps.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/map-id-name
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Make `id` and `name` equal, and update references to the one you changed.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<map id="nav" name="menu"></map>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Do
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<map id="nav" name="nav"></map>
|
|
38
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/meta-refresh
|
|
3
|
+
title: "Meta refresh redirects at once"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "redirecting at once or removing the refresh changes the page's behaviour"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
allowLongDelay: { type: "boolean", default: false, description: "allow delays over 20 hours (72,000 seconds)" }
|
|
10
|
+
ported_from: [html-validate/meta-refresh]
|
|
11
|
+
tags: [a11y]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
A `<meta http-equiv="refresh">` redirects immediately (`0;url=…`); it doesn't wait, and doesn't reload the page.
|
|
16
|
+
|
|
17
|
+
**Why:** A timed refresh moves on before slower readers and screen-reader users have finished; a reload without a URL repeats forever.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/meta-refresh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Make the refresh instant with `0;url=…`.
|
|
26
|
+
2. Or replace it with a link the user follows when ready.
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
### HTML
|
|
31
|
+
|
|
32
|
+
#### Don't
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<meta http-equiv="refresh" content="5;url=/next">
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Do
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<meta http-equiv="refresh" content="0;url=/next">
|
|
42
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# html/missing-doctype — cases
|
|
2
|
+
|
|
3
|
+
### case: a fragment is not a document
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<div>
|
|
7
|
+
<p>Partial</p>
|
|
8
|
+
</div>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```expect
|
|
12
|
+
(none)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### case: a malformed doctype still counts
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<!DOCTYPE>
|
|
19
|
+
<html lang="en"></html>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```expect
|
|
23
|
+
(none)
|
|
24
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/missing-doctype
|
|
3
|
+
title: "The document has a doctype"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "leaving quirks mode can change the page's layout"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/missing-doctype]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A document starts with `<!DOCTYPE html>`.
|
|
13
|
+
|
|
14
|
+
**Why:** Without it browsers render in quirks mode, which lays the page out differently from the standard.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/missing-doctype
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<html lang="en">
|
|
28
|
+
<title>Home</title>
|
|
29
|
+
</html>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### Do
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<!DOCTYPE html>
|
|
36
|
+
<html lang="en">
|
|
37
|
+
<title>Home</title>
|
|
38
|
+
</html>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Differences from the source
|
|
42
|
+
|
|
43
|
+
Only files with an `<html>` element are checked: a fragment or template partial is not a document, and gets no doctype of its own.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/multiple-labeled-controls
|
|
3
|
+
title: "A label labels one control"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "each control needs its own label text"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/multiple-labeled-controls]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A `<label>` is associated with at most one control, by nesting or by `for`.
|
|
14
|
+
|
|
15
|
+
**Why:** A label names one control; assistive technology announces the others without the right name.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/multiple-labeled-controls
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Give each control its own `<label>`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<label>Name <input type="text" name="first"> <input type="text" name="last"></label>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<label>First name <input type="text" name="first"></label>
|
|
39
|
+
<label>Last name <input type="text" name="last"></label>
|
|
40
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-abstract-role
|
|
3
|
+
title: "No abstract ARIA roles"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the concrete role depends on what the element is"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-abstract-role]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`role` does not name one of ARIA's abstract roles (`widget`, `input`, `landmark`, `section`, `command`, …).
|
|
14
|
+
|
|
15
|
+
**Why:** Abstract roles only organise the ARIA specification; browsers don't map them, so the element gets no role at all.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/no-abstract-role
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Use the concrete role that describes the element, or a native element.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<div role="landmark">News</div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<div role="region" aria-label="News">News</div>
|
|
39
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-autoplay
|
|
3
|
+
title: "Media does not play by itself"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the media no longer starts on load"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
include: { type: "string[]", default: ["audio", "video"], description: "elements on which `autoplay` is reported" }
|
|
10
|
+
ported_from: [html-validate/no-autoplay]
|
|
11
|
+
tags: [a11y]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
`<audio>` and `<video>` don't have `autoplay`.
|
|
16
|
+
|
|
17
|
+
**Why:** Sound that starts by itself talks over screen readers and startles users; WCAG asks that users control playback.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/no-autoplay
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### HTML
|
|
26
|
+
|
|
27
|
+
#### Don't
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<video src="intro.mp4" autoplay controls></video>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Do
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<video src="intro.mp4" controls></video>
|
|
37
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-conditional-comment
|
|
3
|
+
title: "No Internet Explorer conditional comments"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "whether the markup inside is still needed is the author's call"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-conditional-comment]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
The document has no conditional comments (`<!--[if IE]>…<![endif]-->`).
|
|
13
|
+
|
|
14
|
+
**Why:** Only Internet Explorer 9 and older read them; every current browser treats them as comments, so the markup inside is dead.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-conditional-comment
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Delete the conditional comment, or move markup that is still needed out of it.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!--[if lt IE 9]><script src="html5shiv.js"></script><![endif]-->
|
|
32
|
+
<p>Hello</p>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<p>Hello</p>
|
|
39
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-deprecated-attr
|
|
3
|
+
title: "No obsolete attributes"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the replacement is usually CSS, which needs a class and a rule"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-deprecated-attr]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Elements don't use attributes HTML has made obsolete, such as `align`, `bgcolor`, `border` on `<img>`, or `name` on `<a>`.
|
|
13
|
+
|
|
14
|
+
**Why:** Browsers support them unevenly; CSS and current attributes do the same job reliably.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/no-deprecated-attr
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Replace presentational attributes with a class and CSS.
|
|
23
|
+
2. Replace other obsolete attributes with their current equivalent (for example `id` for `<a name>`).
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<img src="a.png" alt="Chart" align="left">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<img src="a.png" alt="Chart" class="float-left">
|
|
39
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-dup-attr
|
|
3
|
+
title: "No attribute written twice"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/no-dup-attr, htmlhint/attr-no-duplication]
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
An element does not have the same attribute twice (names compare without case).
|
|
12
|
+
|
|
13
|
+
**Why:** Browsers keep the first one and silently drop the rest, which is rarely what the author meant.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: html/no-dup-attr
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### HTML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<input type="text" name="q" name="search">
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Do
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<input type="text" name="q">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Differences from the source
|
|
36
|
+
|
|
37
|
+
The fix removes the later copies, keeping what browsers already use. Check that the first value is the one you meant.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-dup-class
|
|
3
|
+
title: "No class listed twice"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/no-dup-class]
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A `class` attribute lists each class once.
|
|
12
|
+
|
|
13
|
+
**Why:** The repeat does nothing, and suggests a merge went wrong.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: html/no-dup-class
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### HTML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<p class="lead lead">Text</p>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Do
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<p class="lead">Text</p>
|
|
33
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# html/no-duplicate-id — cases
|
|
2
|
+
|
|
3
|
+
### case: ids in separate templates do not clash
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<template><p id="a"></p></template>
|
|
7
|
+
<template><p id="a"></p></template>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
(none)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### case: template code is not compared
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<p id="{{ id }}"></p>
|
|
18
|
+
<p id="{{ id }}"></p>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```expect
|
|
22
|
+
(none)
|
|
23
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/no-duplicate-id
|
|
3
|
+
title: "Ids are unique in the document"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "renaming an id breaks the CSS, scripts and links that use it"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/no-dup-id, htmlhint/id-unique]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
No two elements in the document have the same `id`. Ids inside a `<template>` only need to be unique within it.
|
|
14
|
+
|
|
15
|
+
**Why:** `getElementById`, `label for`, `aria-labelledby` and fragment links all find the first element with the id and miss the others.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/no-duplicate-id
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Decide which element keeps the id.
|
|
24
|
+
2. Rename the other one, and update the CSS, scripts, `for`, `aria-*` and links that refer to it.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<h2 id="intro">Intro</h2>
|
|
34
|
+
<p id="intro">Text</p>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<h2 id="intro">Intro</h2>
|
|
41
|
+
<p id="intro-text">Text</p>
|
|
42
|
+
```
|