@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,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/require-sri
|
|
3
|
+
title: "Scripts and stylesheets carry an integrity hash"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the hash must be computed from the exact file served"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
target: { type: "string", default: "all", description: "`all` checks every resource; `crossorigin` only those loaded from another origin" }
|
|
10
|
+
ported_from: [html-validate/require-sri]
|
|
11
|
+
since: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Every `<script src>` and `<link rel="stylesheet">` (and `modulepreload`, and `preload` of a script or style) has an `integrity` attribute.
|
|
15
|
+
|
|
16
|
+
**Why:** Subresource Integrity makes the browser refuse a file that changed on the CDN or in transit.
|
|
17
|
+
|
|
18
|
+
```codelaw
|
|
19
|
+
native: html/require-sri
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How to fix
|
|
23
|
+
|
|
24
|
+
1. Compute the file's hash, for example `openssl dgst -sha384 -binary lib.js | openssl base64 -A`.
|
|
25
|
+
2. Add `integrity="sha384-…"` and `crossorigin="anonymous"`.
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
### HTML
|
|
30
|
+
|
|
31
|
+
#### Don't
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<script src="https://cdn.example.com/lib.js"></script>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<script src="https://cdn.example.com/lib.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>
|
|
41
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/script-element
|
|
3
|
+
title: "<script> has an end tag"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the markup the open script swallowed starts being rendered"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/script-element]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `<script>` is closed with `</script>`, also when it has `src`; `<script … />` is not a closed script.
|
|
13
|
+
|
|
14
|
+
**Why:** HTML ignores the `/>`, so the browser reads everything up to the next `</script>` as script and the content in between disappears.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/script-element
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script src="app.js" />
|
|
28
|
+
<p>Hello</p>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### Do
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<script src="app.js"></script>
|
|
35
|
+
<p>Hello</p>
|
|
36
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/script-type
|
|
3
|
+
title: "No type on JavaScript scripts"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [html-validate/script-type]
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A `<script>` doesn't say `type="text/javascript"` or another JavaScript MIME type.
|
|
12
|
+
|
|
13
|
+
**Why:** JavaScript is the default; the attribute adds nothing, and legacy types such as `text/ecmascript` mislead.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: html/script-type
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### HTML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script type="text/javascript" src="app.js"></script>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Do
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<script src="app.js"></script>
|
|
33
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# html/target-blank-rel — cases
|
|
2
|
+
|
|
3
|
+
### case: noreferrer also prevents the opener
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<a href="/a" target="_blank" rel="noreferrer">a</a>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
(none)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: an existing rel gets noopener added
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<a href="/a" target="_blank" rel="external">a</a>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
1:14 html/target-blank-rel
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```fixed
|
|
24
|
+
<a href="/a" target="_blank" rel="external noopener">a</a>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### case: a link without href opens nothing
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<a target="_blank">a</a>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```expect
|
|
34
|
+
(none)
|
|
35
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/target-blank-rel
|
|
3
|
+
title: "Links that open a new tab set rel=\"noopener\""
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
since: 0.1.0
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
An `<a>` or `<area>` with `target="_blank"` and an `href` (or a `<form>` with an `action`) has `rel="noopener"` or `rel="noreferrer"`.
|
|
11
|
+
|
|
12
|
+
**Why:** Without it, older browsers give the opened page a handle on this one (`window.opener`), which it can use to redirect it.
|
|
13
|
+
|
|
14
|
+
```codelaw
|
|
15
|
+
native: html/target-blank-rel
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### HTML
|
|
21
|
+
|
|
22
|
+
#### Don't
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<a href="https://example.com" target="_blank">Example</a>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Do
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<a href="https://example.com" target="_blank" rel="noopener">Example</a>
|
|
32
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/tel-non-breaking
|
|
3
|
+
title: "Phone numbers don't wrap"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the text then contains non-breaking characters, which copy and search keep"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
ignoreClasses: { type: "string[]", default: [], description: "classes that already prevent wrapping" }
|
|
10
|
+
ignoreStyle: { type: "boolean", default: true, description: "skip links styled `white-space: nowrap` or `pre`" }
|
|
11
|
+
ported_from: [html-validate/tel-non-breaking]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
The text of a `tel:` link uses non-breaking spaces and hyphens.
|
|
16
|
+
|
|
17
|
+
**Why:** A phone number broken over two lines is hard to read and to copy.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/tel-non-breaking
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### HTML
|
|
26
|
+
|
|
27
|
+
#### Don't
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<a href="tel:5551234">555 1234</a>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Do
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<a href="tel:5551234">555 1234</a>
|
|
37
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/text-content
|
|
3
|
+
title: "Buttons have text"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the button's name needs a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/text-content]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A `<button>` has text a screen reader can announce: content, `aria-label`, `aria-labelledby`, or an image with `alt`.
|
|
14
|
+
|
|
15
|
+
**Why:** Without it the button is announced as just "button".
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/text-content
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Add visible text, or an `aria-label` that says what the button does.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<button type="button"><svg width="16" height="16"></svg></button>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<button type="button" aria-label="Close"><svg width="16" height="16"></svg></button>
|
|
39
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/th-scope
|
|
3
|
+
title: "Header cells in complex tables have scope"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "whether each header labels a row or a column is the author's call"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
strict: { type: "boolean", default: false, description: "check simple tables too" }
|
|
10
|
+
ported_from: [html-validate/wcag/h63]
|
|
11
|
+
tags: [a11y]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
In a table whose headers are not just the first row or just the first column, every `<th>` has `scope` (`row`, `col`, `rowgroup` or `colgroup`).
|
|
16
|
+
|
|
17
|
+
**Why:** Screen readers announce each cell with its headers; `scope` tells them which headers belong to which cells.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/th-scope
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Add `scope="col"` to column headers and `scope="row"` to row headers.
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
### HTML
|
|
30
|
+
|
|
31
|
+
#### Don't
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<table>
|
|
35
|
+
<tr><th>Name</th><th>Age</th></tr>
|
|
36
|
+
<tr><th>Ada</th><td>36</td></tr>
|
|
37
|
+
</table>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Do
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<table>
|
|
44
|
+
<tr><th scope="col">Name</th><th scope="col">Age</th></tr>
|
|
45
|
+
<tr><th scope="row">Ada</th><td>36</td></tr>
|
|
46
|
+
</table>
|
|
47
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/unique-landmark
|
|
3
|
+
title: "Repeated landmarks have distinct names"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the names need a human"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/unique-landmark]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
When a landmark appears more than once (two `<nav>`, two `<aside>`, …), each has a unique, non-empty `aria-label` or `aria-labelledby`.
|
|
14
|
+
|
|
15
|
+
**Why:** Screen-reader users jump between landmarks by name; two unnamed `<nav>` are indistinguishable.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/unique-landmark
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Give each landmark of the same kind its own `aria-label`, or point `aria-labelledby` at its heading.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<nav><a href="/">Home</a></nav>
|
|
33
|
+
<nav><a href="/help">Help</a></nav>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<nav aria-label="Main"><a href="/">Home</a></nav>
|
|
40
|
+
<nav aria-label="Footer"><a href="/help">Help</a></nav>
|
|
41
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# html/unrecognized-char-ref — cases
|
|
2
|
+
|
|
3
|
+
### case: numeric references are not looked up
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<p>© ©</p>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
(none)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: query strings in URLs may hold unterminated names
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<a href="/s?q=1©=2">x</a>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
(none)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### case: a legacy name without its semicolon
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<p>© 2024</p>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```expect
|
|
30
|
+
1:4 html/unrecognized-char-ref
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### case: an unknown name
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<p>&nbps;</p>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```expect
|
|
40
|
+
1:4 html/unrecognized-char-ref
|
|
41
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/unrecognized-char-ref
|
|
3
|
+
title: "Character references exist and are terminated"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the intended character is not always clear"
|
|
7
|
+
stability: preview
|
|
8
|
+
options:
|
|
9
|
+
ignoreCase: { type: "boolean", default: false, description: "compare names without case" }
|
|
10
|
+
requireSemicolon: { type: "boolean", default: true, description: "report references without `;`" }
|
|
11
|
+
ported_from: [html-validate/unrecognized-char-ref]
|
|
12
|
+
since: 0.1.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Every named character reference (`&name;`) is one HTML defines, and ends with `;`.
|
|
16
|
+
|
|
17
|
+
**Why:** An unknown reference is shown literally, and an unterminated one may be read with the text after it.
|
|
18
|
+
|
|
19
|
+
```codelaw
|
|
20
|
+
native: html/unrecognized-char-ref
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Correct the name, or escape the `&` as `&` if no reference was meant.
|
|
26
|
+
2. End the reference with `;`.
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
### HTML
|
|
31
|
+
|
|
32
|
+
#### Don't
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<p>Price: 5&euros; © 2024</p>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Do
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<p>Price: 5€ © 2024</p>
|
|
42
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# html/valid-autocomplete — cases
|
|
2
|
+
|
|
3
|
+
### case: a section and a hint before the field
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<input type="text" name="a" autocomplete="section-ship shipping address-line1">
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
(none)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: a multi-line field belongs on a textarea
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<input type="text" name="a" autocomplete="street-address">
|
|
17
|
+
<textarea name="b" autocomplete="street-address"></textarea>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```expect
|
|
21
|
+
1:43 html/valid-autocomplete
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### case: on and off are not combined with fields
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<input type="text" name="a" autocomplete="off">
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```expect
|
|
31
|
+
(none)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### case: form takes only on or off
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<form autocomplete="email"></form>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```expect
|
|
41
|
+
1:21 html/valid-autocomplete
|
|
42
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/valid-autocomplete
|
|
3
|
+
title: "autocomplete values are valid"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the right field name depends on what the field collects"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/valid-autocomplete]
|
|
9
|
+
tags: [a11y]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
`autocomplete` holds a valid token list: optional `section-*`, then `shipping`/`billing`, then `home`/`work`/… for contact fields, then one field name that fits the input type, then optional `webauthn`. `<form>` takes only `on` or `off`.
|
|
14
|
+
|
|
15
|
+
**Why:** Browsers ignore an invalid value, so autofill and password managers can't help the user.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
native: html/valid-autocomplete
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## How to fix
|
|
22
|
+
|
|
23
|
+
1. Pick the field name that describes the data (the WHATWG autofill list).
|
|
24
|
+
2. Order the tokens as described above, or use `off`.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<input type="email" name="email" autocomplete="mail">
|
|
34
|
+
<input type="number" name="n" autocomplete="email">
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<input type="email" name="email" autocomplete="email">
|
|
41
|
+
<input type="number" name="n" autocomplete="off">
|
|
42
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/valid-for
|
|
3
|
+
title: "A label points at a control"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "either the id or the element is wrong, and only the author knows which"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/valid-for]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `<label for>` refers to the id of a form control a label can name (`input`, `select`, `textarea`, `button`, `meter`, `output`, `progress`).
|
|
13
|
+
|
|
14
|
+
**Why:** Pointed at a `<div>` or `<span>`, the label names nothing, and clicking it does nothing.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/valid-for
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Point `for` at the control's id, or make the target a form control.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### HTML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<label for="name">Name</label>
|
|
32
|
+
<div id="name"></div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<label for="name">Name</label>
|
|
39
|
+
<input type="text" id="name">
|
|
40
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/valid-id
|
|
3
|
+
title: "Ids are well-formed"
|
|
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
|
+
options:
|
|
9
|
+
relaxed: { type: "boolean", default: false, description: "only require a non-empty id without whitespace" }
|
|
10
|
+
ported_from: [html-validate/valid-id]
|
|
11
|
+
since: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
An `id` is not empty and has no whitespace; it starts with a letter and uses only letters, digits, `-` and `_`.
|
|
15
|
+
|
|
16
|
+
**Why:** Whitespace makes the id unusable; other characters need escaping in CSS selectors and are easy to get wrong.
|
|
17
|
+
|
|
18
|
+
```codelaw
|
|
19
|
+
native: html/valid-id
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How to fix
|
|
23
|
+
|
|
24
|
+
1. Rename the id, and update everything that refers to it.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<div id="1st item"></div>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<div id="first-item"></div>
|
|
40
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: html/void-content
|
|
3
|
+
title: "Void elements have no end tag"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "`</br>` is read as a second line break, so removing it changes the rendering"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [html-validate/void-content]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Void elements (`<br>`, `<img>`, `<input>`, `<meta>`, …) are written without an end tag.
|
|
13
|
+
|
|
14
|
+
**Why:** They can't have content; browsers ignore most such end tags, and read `</br>` and `</p>` as new elements.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: html/void-content
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<input type="text" name="q"></input>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<input type="text" name="q">
|
|
34
|
+
```
|