@herb-tools/linter 0.4.0 → 0.4.1
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/README.md +1 -1
- package/dist/herb-lint.js +161 -101
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +215 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +213 -68
- package/dist/index.js.map +1 -1
- package/dist/package.json +4 -4
- package/dist/src/default-rules.js +8 -2
- package/dist/src/default-rules.js.map +1 -1
- package/dist/src/rules/html-aria-attribute-must-be-valid.js +24 -0
- package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -0
- package/dist/src/rules/html-aria-role-must-be-valid.js +21 -0
- package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -0
- package/dist/src/rules/html-no-duplicate-ids.js +25 -0
- package/dist/src/rules/html-no-duplicate-ids.js.map +1 -0
- package/dist/src/rules/index.js +3 -0
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/rule-utils.js +83 -8
- package/dist/src/rules/rule-utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +6 -0
- package/dist/types/rules/html-aria-role-must-be-valid.d.ts +6 -0
- package/dist/types/rules/html-no-duplicate-ids.d.ts +6 -0
- package/dist/types/rules/index.d.ts +3 -0
- package/dist/types/rules/rule-utils.d.ts +2 -0
- package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +6 -0
- package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +6 -0
- package/dist/types/src/rules/html-no-duplicate-ids.d.ts +6 -0
- package/dist/types/src/rules/index.d.ts +3 -0
- package/dist/types/src/rules/rule-utils.d.ts +2 -0
- package/docs/rules/README.md +4 -0
- package/docs/rules/html-aria-attribute-must-be-valid.md +45 -0
- package/docs/rules/html-aria-role-must-be-valid.md +45 -0
- package/docs/rules/html-no-duplicate-ids.md +49 -0
- package/package.json +4 -4
- package/src/default-rules.ts +8 -2
- package/src/rules/html-aria-attribute-must-be-valid.ts +42 -0
- package/src/rules/html-aria-role-must-be-valid.ts +30 -0
- package/src/rules/html-no-duplicate-ids.ts +39 -0
- package/src/rules/index.ts +3 -0
- package/src/rules/rule-utils.ts +98 -17
package/src/rules/rule-utils.ts
CHANGED
|
@@ -2,16 +2,15 @@ import {
|
|
|
2
2
|
Visitor
|
|
3
3
|
} from "@herb-tools/core"
|
|
4
4
|
|
|
5
|
-
import type {
|
|
6
|
-
ERBNode,
|
|
5
|
+
import type {
|
|
6
|
+
ERBNode,
|
|
7
7
|
HTMLAttributeNameNode,
|
|
8
|
-
HTMLAttributeNode,
|
|
9
|
-
HTMLAttributeValueNode,
|
|
10
|
-
HTMLOpenTagNode,
|
|
11
|
-
HTMLSelfCloseTagNode,
|
|
12
|
-
LiteralNode,
|
|
13
|
-
Location
|
|
14
|
-
Node
|
|
8
|
+
HTMLAttributeNode,
|
|
9
|
+
HTMLAttributeValueNode,
|
|
10
|
+
HTMLOpenTagNode,
|
|
11
|
+
HTMLSelfCloseTagNode,
|
|
12
|
+
LiteralNode,
|
|
13
|
+
Location
|
|
15
14
|
} from "@herb-tools/core"
|
|
16
15
|
import type { LintOffense, LintSeverity, } from "../types.js"
|
|
17
16
|
|
|
@@ -83,18 +82,36 @@ export function getAttributeName(attributeNode: HTMLAttributeNode): string | nul
|
|
|
83
82
|
* Gets the attribute value content from an HTMLAttributeValueNode
|
|
84
83
|
*/
|
|
85
84
|
export function getAttributeValue(attributeNode: HTMLAttributeNode): string | null {
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
const valueNode: HTMLAttributeValueNode | null = attributeNode.value as HTMLAttributeValueNode
|
|
86
|
+
|
|
87
|
+
if (valueNode === null) return null
|
|
88
|
+
|
|
89
|
+
if (valueNode.type !== "AST_HTML_ATTRIBUTE_VALUE_NODE" || !valueNode.children?.length) {
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let result = ""
|
|
94
|
+
|
|
95
|
+
for (const child of valueNode.children) {
|
|
96
|
+
switch (child.type) {
|
|
97
|
+
case "AST_ERB_CONTENT_NODE": {
|
|
98
|
+
const erbNode = child as ERBNode
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
if (erbNode.content) {
|
|
101
|
+
result += `${erbNode.tag_opening?.value}${erbNode.content.value}${erbNode.tag_closing?.value}`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
case "AST_LITERAL_NODE": {
|
|
108
|
+
result += (child as LiteralNode).content
|
|
109
|
+
break
|
|
110
|
+
}
|
|
94
111
|
}
|
|
95
112
|
}
|
|
96
113
|
|
|
97
|
-
return
|
|
114
|
+
return result
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
/**
|
|
@@ -171,6 +188,70 @@ export const HTML_BOOLEAN_ATTRIBUTES = new Set([
|
|
|
171
188
|
|
|
172
189
|
export const HEADING_TAGS = new Set(["h1", "h2", "h3", "h4", "h5", "h6"])
|
|
173
190
|
|
|
191
|
+
export const VALID_ARIA_ROLES = new Set([
|
|
192
|
+
"banner", "complementary", "contentinfo", "form", "main", "navigation", "region", "search",
|
|
193
|
+
"article", "cell", "columnheader", "definition", "directory", "document", "feed", "figure",
|
|
194
|
+
"group", "heading", "img", "list", "listitem", "math", "none", "note", "presentation",
|
|
195
|
+
"row", "rowgroup", "rowheader", "separator", "table", "term", "tooltip",
|
|
196
|
+
"alert", "alertdialog", "button", "checkbox", "combobox", "dialog", "grid", "gridcell", "link",
|
|
197
|
+
"listbox", "menu", "menubar", "menuitem", "menuitemcheckbox", "menuitemradio", "option",
|
|
198
|
+
"progressbar", "radio", "radiogroup", "scrollbar", "searchbox", "slider", "spinbutton",
|
|
199
|
+
"status", "switch", "tab", "tablist", "tabpanel", "textbox", "timer", "toolbar", "tree",
|
|
200
|
+
"treegrid", "treeitem",
|
|
201
|
+
"log", "marquee"
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
export const ARIA_ATTRIBUTES = new Set([
|
|
205
|
+
'aria-activedescendant',
|
|
206
|
+
'aria-atomic',
|
|
207
|
+
'aria-autocomplete',
|
|
208
|
+
'aria-busy',
|
|
209
|
+
'aria-checked',
|
|
210
|
+
'aria-colcount',
|
|
211
|
+
'aria-colindex',
|
|
212
|
+
'aria-colspan',
|
|
213
|
+
'aria-controls',
|
|
214
|
+
'aria-current',
|
|
215
|
+
'aria-describedby',
|
|
216
|
+
'aria-details',
|
|
217
|
+
'aria-disabled',
|
|
218
|
+
'aria-dropeffect',
|
|
219
|
+
'aria-errormessage',
|
|
220
|
+
'aria-expanded',
|
|
221
|
+
'aria-flowto',
|
|
222
|
+
'aria-grabbed',
|
|
223
|
+
'aria-haspopup',
|
|
224
|
+
'aria-hidden',
|
|
225
|
+
'aria-invalid',
|
|
226
|
+
'aria-keyshortcuts',
|
|
227
|
+
'aria-label',
|
|
228
|
+
'aria-labelledby',
|
|
229
|
+
'aria-level',
|
|
230
|
+
'aria-live',
|
|
231
|
+
'aria-modal',
|
|
232
|
+
'aria-multiline',
|
|
233
|
+
'aria-multiselectable',
|
|
234
|
+
'aria-orientation',
|
|
235
|
+
'aria-owns',
|
|
236
|
+
'aria-placeholder',
|
|
237
|
+
'aria-posinset',
|
|
238
|
+
'aria-pressed',
|
|
239
|
+
'aria-readonly',
|
|
240
|
+
'aria-relevant',
|
|
241
|
+
'aria-required',
|
|
242
|
+
'aria-roledescription',
|
|
243
|
+
'aria-rowcount',
|
|
244
|
+
'aria-rowindex',
|
|
245
|
+
'aria-rowspan',
|
|
246
|
+
'aria-selected',
|
|
247
|
+
'aria-setsize',
|
|
248
|
+
'aria-sort',
|
|
249
|
+
'aria-valuemax',
|
|
250
|
+
'aria-valuemin',
|
|
251
|
+
'aria-valuenow',
|
|
252
|
+
'aria-valuetext',
|
|
253
|
+
])
|
|
254
|
+
|
|
174
255
|
/**
|
|
175
256
|
* Checks if an element is inline
|
|
176
257
|
*/
|