Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3126329

Browse files
authored
New rule to flag invalid aria-label format (#418)
1 parentaadb4ce commit3126329

6 files changed

+126
-22
lines changed

‎README.md

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,27 +82,28 @@ This config will be interpreted in the following way:
8282
🔧 Automatically fixable by the[`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
8383
❌ Deprecated.
8484

85-
| Name                     | Description| 💼| 🔧||
86-
| :-------------------------------------------------------------------| :-----------------------------------------------------------------------------------------------------------------------| :-| :-| :-|
87-
|[a11y-no-generic-link-text](docs/rules/a11y-no-generic-link-text.md)| disallow generic link text||||
88-
|[array-foreach](docs/rules/array-foreach.md)| enforce`for..of` loops over`Array.forEach`||||
89-
|[async-currenttarget](docs/rules/async-currenttarget.md)| disallow`event.currentTarget` calls inside of async functions| 🔍|||
90-
|[async-preventdefault](docs/rules/async-preventdefault.md)| disallow`event.preventDefault` calls inside of async functions| 🔍|||
91-
|[authenticity-token](docs/rules/authenticity-token.md)| disallow usage of CSRF tokens in JavaScript| 🔐|||
92-
|[get-attribute](docs/rules/get-attribute.md)| disallow wrong usage of attribute names| 🔍| 🔧||
93-
|[js-class-name](docs/rules/js-class-name.md)| enforce a naming convention for js- prefixed classes| 🔐|||
94-
|[no-blur](docs/rules/no-blur.md)| disallow usage of`Element.prototype.blur()`| 🔍|||
95-
|[no-d-none](docs/rules/no-d-none.md)| disallow usage the`d-none` CSS class| 🔐|||
96-
|[no-dataset](docs/rules/no-dataset.md)| enforce usage of`Element.prototype.getAttribute` instead of`Element.prototype.datalist`| 🔍|||
97-
|[no-dynamic-script-tag](docs/rules/no-dynamic-script-tag.md)| disallow creating dynamic script tags||||
98-
|[no-implicit-buggy-globals](docs/rules/no-implicit-buggy-globals.md)| disallow implicit global variables||||
99-
|[no-inner-html](docs/rules/no-inner-html.md)| disallow`Element.prototype.innerHTML` in favor of`Element.prototype.textContent`| 🔍|||
100-
|[no-innerText](docs/rules/no-innerText.md)| disallow`Element.prototype.innerText` in favor of`Element.prototype.textContent`| 🔍| 🔧||
101-
|[no-then](docs/rules/no-then.md)| enforce using`async/await` syntax over Promises||||
102-
|[no-useless-passive](docs/rules/no-useless-passive.md)| disallow marking a event handler as passive when it has no effect| 🔍| 🔧||
103-
|[prefer-observers](docs/rules/prefer-observers.md)| disallow poorly performing event listeners| 🔍|||
104-
|[require-passive-events](docs/rules/require-passive-events.md)| enforce marking high frequency event handlers as passive| 🔍|||
105-
|[role-supports-aria-props](docs/rules/role-supports-aria-props.md)| Enforce that elements with explicit or implicit roles defined contain only`aria-*` properties supported by that`role`.| ⚛️|||
106-
|[unescaped-html-literal](docs/rules/unescaped-html-literal.md)| disallow unescaped HTML literals| 🔍|||
85+
| Name                             | Description| 💼| 🔧||
86+
| :-----------------------------------------------------------------------------------| :-----------------------------------------------------------------------------------------------------------------------| :-| :-| :-|
87+
|[a11y-aria-label-is-well-formatted](docs/rules/a11y-aria-label-is-well-formatted.md)|[aria-label] text should be formatted as you would visual text.| ⚛️|||
88+
|[a11y-no-generic-link-text](docs/rules/a11y-no-generic-link-text.md)| disallow generic link text||||
89+
|[array-foreach](docs/rules/array-foreach.md)| enforce`for..of` loops over`Array.forEach`||||
90+
|[async-currenttarget](docs/rules/async-currenttarget.md)| disallow`event.currentTarget` calls inside of async functions| 🔍|||
91+
|[async-preventdefault](docs/rules/async-preventdefault.md)| disallow`event.preventDefault` calls inside of async functions| 🔍|||
92+
|[authenticity-token](docs/rules/authenticity-token.md)| disallow usage of CSRF tokens in JavaScript| 🔐|||
93+
|[get-attribute](docs/rules/get-attribute.md)| disallow wrong usage of attribute names| 🔍| 🔧||
94+
|[js-class-name](docs/rules/js-class-name.md)| enforce a naming convention for js- prefixed classes| 🔐|||
95+
|[no-blur](docs/rules/no-blur.md)| disallow usage of`Element.prototype.blur()`| 🔍|||
96+
|[no-d-none](docs/rules/no-d-none.md)| disallow usage the`d-none` CSS class| 🔐|||
97+
|[no-dataset](docs/rules/no-dataset.md)| enforce usage of`Element.prototype.getAttribute` instead of`Element.prototype.datalist`| 🔍|||
98+
|[no-dynamic-script-tag](docs/rules/no-dynamic-script-tag.md)| disallow creating dynamic script tags||||
99+
|[no-implicit-buggy-globals](docs/rules/no-implicit-buggy-globals.md)| disallow implicit global variables||||
100+
|[no-inner-html](docs/rules/no-inner-html.md)| disallow`Element.prototype.innerHTML` in favor of`Element.prototype.textContent`| 🔍|||
101+
|[no-innerText](docs/rules/no-innerText.md)| disallow`Element.prototype.innerText` in favor of`Element.prototype.textContent`| 🔍| 🔧||
102+
|[no-then](docs/rules/no-then.md)| enforce using`async/await` syntax over Promises||||
103+
|[no-useless-passive](docs/rules/no-useless-passive.md)| disallow marking a event handler as passive when it has no effect| 🔍| 🔧||
104+
|[prefer-observers](docs/rules/prefer-observers.md)| disallow poorly performing event listeners| 🔍|||
105+
|[require-passive-events](docs/rules/require-passive-events.md)| enforce marking high frequency event handlers as passive| 🔍|||
106+
|[role-supports-aria-props](docs/rules/role-supports-aria-props.md)| Enforce that elements with explicit or implicit roles defined contain only`aria-*` properties supported by that`role`.| ⚛️|||
107+
|[unescaped-html-literal](docs/rules/unescaped-html-literal.md)| disallow unescaped HTML literals| 🔍|||
107108

108109
<!-- end auto-generated rules list-->
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#[aria-label] text should be formatted as you would visual text (`github/a11y-aria-label-is-well-formatted`)
2+
3+
💼 This rule is enabled in the ⚛️`react` config.
4+
5+
<!-- end auto-generated rule header-->
6+
7+
##Rule Details
8+
9+
`[aria-label]` content should be formatted in the same way you would visual text. Please use sentence case.
10+
11+
Do not connect the words like you would an ID. An`aria-label` is not an ID, and should be formatted as human-friendly text.
12+
13+
##Resources
14+
15+
-[Using aria-label](https://www.w3.org/WAI/tutorials/forms/labels/#using-aria-label)
16+
17+
##Examples
18+
19+
###**Incorrect** code for this rule 👎
20+
21+
```html
22+
<ahref="..."aria-label="learn more"></a>
23+
```
24+
25+
```html
26+
<ahref="..."aria-label="go-to-link"></a>
27+
```
28+
29+
###**Correct** code for this rule 👍
30+
31+
```html
32+
<ahref="..."aria-label="Learn more"></a>
33+
```
34+
35+
```html
36+
<ahref="..."aria-label="Homepage"></a>
37+
```
38+
39+
##Version

‎lib/configs/react.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module.exports = {
99
extends:['plugin:jsx-a11y/recommended'],
1010
rules:{
1111
'jsx-a11y/role-supports-aria-props':'off',// Override with github/role-supports-aria-props until https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/910 is resolved
12+
'github/a11y-aria-label-is-well-formatted':'error',
1213
'github/role-supports-aria-props':'error',
1314
'jsx-a11y/no-aria-hidden-on-focusable':'error',
1415
'jsx-a11y/anchor-ambiguous-text':[

‎lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module.exports={
22
rules:{
33
'a11y-no-generic-link-text':require('./rules/a11y-no-generic-link-text'),
4+
'a11y-aria-label-is-well-formatted':require('./rules/a11y-aria-label-is-well-formatted'),
45
'array-foreach':require('./rules/array-foreach'),
56
'async-currenttarget':require('./rules/async-currenttarget'),
67
'async-preventdefault':require('./rules/async-preventdefault'),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const{getProp}=require('jsx-ast-utils')
2+
3+
module.exports={
4+
meta:{
5+
docs:{
6+
description:'[aria-label] text should be formatted as you would visual text.',
7+
url:require('../url')(module),
8+
},
9+
schema:[],
10+
},
11+
12+
create(context){
13+
return{
14+
JSXOpeningElement:node=>{
15+
constprop=getProp(node.attributes,'aria-label')
16+
if(!prop)return
17+
18+
constpropValue=prop.value
19+
if(propValue.type!=='Literal')return
20+
21+
constariaLabel=propValue.value
22+
if(ariaLabel.match(/^[a-z]+.*$/)){
23+
context.report({
24+
node,
25+
message:'[aria-label] text should be formatted the same as you would visual text. Use sentence case.',
26+
})
27+
}
28+
},
29+
}
30+
},
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
construle=require('../lib/rules/a11y-aria-label-is-well-formatted')
2+
constRuleTester=require('eslint').RuleTester
3+
4+
construleTester=newRuleTester({
5+
parserOptions:{
6+
ecmaVersion:'latest',
7+
sourceType:'module',
8+
ecmaFeatures:{
9+
jsx:true,
10+
},
11+
},
12+
})
13+
14+
consterrorMessage='[aria-label] text should be formatted the same as you would visual text. Use sentence case.'
15+
16+
ruleTester.run('a11y-aria-label-is-well-formatted',rule,{
17+
valid:[
18+
{code:"<a aria-labelledby='someId' href='#'>Read more</a>;"},
19+
{code:"<a aria-label={someName} href='#'>Read more</a>;"},
20+
{code:"<a aria-label='This is a label'></a>;"},
21+
{code:"<a aria-label='Valid'></a>;"},
22+
{code:"<a aria-label='VALID'></a>;"},
23+
{code:'<Link aria-label="Valid" href="#">Read more</Link>'},
24+
],
25+
invalid:[
26+
{code:"<a aria-label='close modal'></a>;",errors:[{message:errorMessage}]},
27+
{code:"<a aria-label='submit'></a>;",errors:[{message:errorMessage}]},
28+
{code:"<a aria-label='submit.yml'></a>;",errors:[{message:errorMessage}]},
29+
{code:"<a aria-label='this-is-not-an-id'></a>;",errors:[{message:errorMessage}]},
30+
],
31+
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp