@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.
Files changed (103) hide show
  1. package/LICENSE +23 -0
  2. package/NOTICE +24 -0
  3. package/README.md +162 -2
  4. package/codelaw-pack.toml +6 -0
  5. package/data/html/elements.json +4892 -0
  6. package/data/html/entities.json +1 -0
  7. package/data/html/input-attributes.json +227 -0
  8. package/package.json +14 -4
  9. package/presets/html/a11y.toml +29 -0
  10. package/presets/html/conventions.toml +6 -0
  11. package/presets/html/document.toml +8 -0
  12. package/presets/html/recommended.toml +67 -0
  13. package/rules/html/area-alt.md +48 -0
  14. package/rules/html/aria-hidden-body.md +39 -0
  15. package/rules/html/aria-label-misuse.md +42 -0
  16. package/rules/html/attribute-allowed-values.cases.md +31 -0
  17. package/rules/html/attribute-allowed-values.md +41 -0
  18. package/rules/html/attribute-misuse.md +39 -0
  19. package/rules/html/autocomplete-password.md +41 -0
  20. package/rules/html/button-type.cases.md +28 -0
  21. package/rules/html/button-type.md +35 -0
  22. package/rules/html/close-attr.md +33 -0
  23. package/rules/html/close-order.cases.md +38 -0
  24. package/rules/html/close-order.md +47 -0
  25. package/rules/html/deprecated.md +39 -0
  26. package/rules/html/doctype-html.md +36 -0
  27. package/rules/html/element-name.cases.md +21 -0
  28. package/rules/html/element-name.md +42 -0
  29. package/rules/html/element-permitted-content.cases.md +54 -0
  30. package/rules/html/element-permitted-content.md +45 -0
  31. package/rules/html/element-permitted-occurrences.md +45 -0
  32. package/rules/html/element-permitted-order.md +44 -0
  33. package/rules/html/element-permitted-parent.cases.md +11 -0
  34. package/rules/html/element-permitted-parent.md +43 -0
  35. package/rules/html/element-required-ancestor.md +45 -0
  36. package/rules/html/element-required-attributes.md +44 -0
  37. package/rules/html/element-required-content.cases.md +23 -0
  38. package/rules/html/element-required-content.md +43 -0
  39. package/rules/html/empty-heading.md +40 -0
  40. package/rules/html/empty-title.md +39 -0
  41. package/rules/html/fieldset-legend.md +44 -0
  42. package/rules/html/form-dup-name.cases.md +38 -0
  43. package/rules/html/form-dup-name.md +48 -0
  44. package/rules/html/form-submit.md +44 -0
  45. package/rules/html/heading-level.cases.md +26 -0
  46. package/rules/html/heading-level.md +44 -0
  47. package/rules/html/hidden-focusable.cases.md +23 -0
  48. package/rules/html/hidden-focusable.md +40 -0
  49. package/rules/html/img-alt.cases.md +22 -0
  50. package/rules/html/img-alt.md +44 -0
  51. package/rules/html/img-title.md +40 -0
  52. package/rules/html/input-attributes.md +34 -0
  53. package/rules/html/input-image-alt.md +39 -0
  54. package/rules/html/input-missing-label.md +40 -0
  55. package/rules/html/link-text.md +39 -0
  56. package/rules/html/long-title.md +40 -0
  57. package/rules/html/map-dup-name.md +40 -0
  58. package/rules/html/map-id-name.md +38 -0
  59. package/rules/html/meta-refresh.md +42 -0
  60. package/rules/html/missing-doctype.cases.md +24 -0
  61. package/rules/html/missing-doctype.md +43 -0
  62. package/rules/html/multiple-labeled-controls.md +40 -0
  63. package/rules/html/no-abstract-role.md +39 -0
  64. package/rules/html/no-autoplay.md +37 -0
  65. package/rules/html/no-conditional-comment.md +39 -0
  66. package/rules/html/no-deprecated-attr.md +39 -0
  67. package/rules/html/no-dup-attr.md +37 -0
  68. package/rules/html/no-dup-class.md +33 -0
  69. package/rules/html/no-duplicate-id.cases.md +23 -0
  70. package/rules/html/no-duplicate-id.md +42 -0
  71. package/rules/html/no-implicit-close.cases.md +38 -0
  72. package/rules/html/no-implicit-close.md +40 -0
  73. package/rules/html/no-implicit-input-type.md +34 -0
  74. package/rules/html/no-inline-script.md +42 -0
  75. package/rules/html/no-inline-style.cases.md +12 -0
  76. package/rules/html/no-inline-style.md +42 -0
  77. package/rules/html/no-missing-references.md +39 -0
  78. package/rules/html/no-multiple-main.md +40 -0
  79. package/rules/html/no-raw-characters.cases.md +84 -0
  80. package/rules/html/no-raw-characters.md +35 -0
  81. package/rules/html/no-redundant-aria-label.md +36 -0
  82. package/rules/html/no-redundant-for.md +34 -0
  83. package/rules/html/no-redundant-role.md +42 -0
  84. package/rules/html/no-utf8-bom.md +45 -0
  85. package/rules/html/prefer-button.md +39 -0
  86. package/rules/html/prefer-native-element.md +40 -0
  87. package/rules/html/prefer-tbody.md +41 -0
  88. package/rules/html/require-sri.md +41 -0
  89. package/rules/html/script-element.md +36 -0
  90. package/rules/html/script-type.md +33 -0
  91. package/rules/html/target-blank-rel.cases.md +35 -0
  92. package/rules/html/target-blank-rel.md +32 -0
  93. package/rules/html/tel-non-breaking.md +37 -0
  94. package/rules/html/text-content.md +39 -0
  95. package/rules/html/th-scope.md +47 -0
  96. package/rules/html/unique-landmark.md +41 -0
  97. package/rules/html/unrecognized-char-ref.cases.md +41 -0
  98. package/rules/html/unrecognized-char-ref.md +42 -0
  99. package/rules/html/valid-autocomplete.cases.md +42 -0
  100. package/rules/html/valid-autocomplete.md +42 -0
  101. package/rules/html/valid-for.md +40 -0
  102. package/rules/html/valid-id.md +40 -0
  103. 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,12 @@
1
+ # html/no-inline-style — cases
2
+
3
+ ### case: display and custom properties are allowed by default
4
+
5
+ ```html
6
+ <p style="display: none">a</p>
7
+ <p style="--gap: 4px">b</p>
8
+ ```
9
+
10
+ ```expect
11
+ (none)
12
+ ```
@@ -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&nbsp b</p>
18
+ ```
19
+
20
+ ```expect
21
+ 1:5 html/no-raw-characters
22
+ ```
23
+
24
+ ```fixed
25
+ <p>a&amp;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&equals;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>中文 &amp; 日本語</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: `&copy=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 &amp; 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.