@a11yfred/neighbor 0.3.0 → 1.0.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/CHANGELOG.md +59 -7
- package/CONTRIBUTING.md +10 -10
- package/README.md +101 -31
- package/RULES-CONTENT.md +296 -0
- package/RULES-CSS.md +61 -0
- package/RULES-MARKUP.md +156 -0
- package/RULES.md +55 -0
- package/lib/content-rules.js +858 -0
- package/lib/helpers-angular.js +146 -146
- package/lib/helpers-jsx.js +193 -193
- package/lib/helpers-vue.js +151 -151
- package/lib/helpers.js +37 -37
- package/lib/rules.js +2413 -2413
- package/lib/ulam-rules.js +301 -301
- package/neighbor-content.mjs +80 -0
- package/neighbor-eslint-angular.mjs +68 -68
- package/neighbor-eslint-vue.mjs +48 -48
- package/neighbor-eslint.mjs +56 -56
- package/neighbor-stylelint.mjs +257 -256
- package/package.json +18 -5
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @a11yfred/neighbor - Content linting plugin
|
|
3
|
+
*
|
|
4
|
+
* Flags accessibility and inclusion problems in web and app copy: ableist
|
|
5
|
+
* language, disability metaphors, English idioms that exclude ESL readers,
|
|
6
|
+
* vague link text, directional layout references, unexplained abbreviations,
|
|
7
|
+
* ALL CAPS prose, and vague error messages.
|
|
8
|
+
*
|
|
9
|
+
* These rules operate on string literals and JSX text in JavaScript,
|
|
10
|
+
* TypeScript, JSX, and TSX files. They target the gap between markup
|
|
11
|
+
* accessibility (jsx-a11y, neighbor ESLint) and prose accessibility -
|
|
12
|
+
* no existing a11y linting tool covers this space.
|
|
13
|
+
*
|
|
14
|
+
* Entry point: @a11yfred/neighbor/content
|
|
15
|
+
*
|
|
16
|
+
* ─── Rule methodology ────────────────────────────────────────────────────────
|
|
17
|
+
*
|
|
18
|
+
* A rule is included only when all three conditions hold:
|
|
19
|
+
* 1. A WCAG Success Criterion directly applies, OR the rule appears in ≥3
|
|
20
|
+
* independent authoritative style guides.
|
|
21
|
+
* 2. The rule can be expressed as a finite, deterministic pattern (string
|
|
22
|
+
* match, token count, or AST shape) - no NLP, no runtime context.
|
|
23
|
+
* 3. Expert consensus is unambiguous across sources. No credible authority
|
|
24
|
+
* argues the opposite.
|
|
25
|
+
*
|
|
26
|
+
* Rules that require subjective reading (tone, full cultural sensitivity
|
|
27
|
+
* beyond a term list) or are under active community debate are excluded.
|
|
28
|
+
*
|
|
29
|
+
* ─── Sources ────────────────────────────────────────────────────────────────
|
|
30
|
+
*
|
|
31
|
+
* International accessible writing guides:
|
|
32
|
+
* United States plain language.gov, digital.gov/guides/plain-language
|
|
33
|
+
* United States advocacy.sba.gov - SBA Content Style Guide
|
|
34
|
+
* United Kingdom gov.uk/guidance/publishing-accessible-documents
|
|
35
|
+
* United Kingdom accessibility-manual.dwp.gov.uk/best-practice/writing-content
|
|
36
|
+
* Australia stylemanual.gov.au/accessible-and-inclusive-content
|
|
37
|
+
* Canada accessible.canada.ca/guidelines-creating-accessible-documents
|
|
38
|
+
* Global (W3C) w3.org/WAI/tips/writing/ - primary authority
|
|
39
|
+
* Global (W3C) wcag.com/authors/
|
|
40
|
+
*
|
|
41
|
+
* Disability language authorities:
|
|
42
|
+
* NCDJ cronkite.asu.edu/ncdj/disability-language-style-guide
|
|
43
|
+
* AP Stylebook amdisrights.org/ap-stylebook-primer-on-disability
|
|
44
|
+
* ADA Nat. Network adata.org/factsheet/ADANN-writing
|
|
45
|
+
* APA Style apastyle.apa.org/style-grammar-guidelines/bias-free-language/disability
|
|
46
|
+
* SIGACCESS sigaccess.org/…/accessible-writing-guide/
|
|
47
|
+
* Nicolas Steenhout incl.ca/disability-language-is-a-nuanced-thing/ - Nothing About Us Without Us; language as community choice
|
|
48
|
+
* Léonie Watson tink.uk - "There is no right or wrong answer because it is a matter of personal choice, and the choice depends on context." (cited by Steenhout)
|
|
49
|
+
*
|
|
50
|
+
* Technical writing:
|
|
51
|
+
* Google Dev Style developers.google.com/style/accessibility
|
|
52
|
+
* Section 508 section508.gov/create/alternative-text/
|
|
53
|
+
*
|
|
54
|
+
* UX and content design:
|
|
55
|
+
* UX Content Co. uxcontent.com/accessible-ux-writing-a-guide-for-inclusive-content-design/
|
|
56
|
+
* A11y Collective a11y-collective.com/blog/accessible-writing/
|
|
57
|
+
* SJSU Writing Ctr sjsu.edu/writingcenter/docs/handouts/Accessible Writing Strategies.pdf
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
import { CONTENT_RULE_FACTORIES, buildContentRecommendedRules } from './lib/content-rules.js'
|
|
61
|
+
|
|
62
|
+
const NS = '@a11yfred/neighbor/content'
|
|
63
|
+
|
|
64
|
+
const rules = Object.fromEntries(
|
|
65
|
+
Object.entries(CONTENT_RULE_FACTORIES).map(([name, factory]) => [name, factory()])
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const plugin = { meta: { name: NS }, rules }
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
...plugin,
|
|
72
|
+
configs: {
|
|
73
|
+
recommended: {
|
|
74
|
+
plugins: {
|
|
75
|
+
[NS]: plugin,
|
|
76
|
+
},
|
|
77
|
+
rules: buildContentRecommendedRules(NS),
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
}
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @a11yfred/neighbor
|
|
3
|
-
*
|
|
4
|
-
* Flags the same ARIA anti-patterns as neighbor-eslint.mjs but for Angular
|
|
5
|
-
* component templates. Requires @angular-eslint/template-parser.
|
|
6
|
-
*
|
|
7
|
-
* Rules that require ancestor walking (no-log-with-interactive-children,
|
|
8
|
-
* no-menu-role-on-nav, no-heading-inside-interactive) are limited because
|
|
9
|
-
* @angular-eslint/template-parser does not attach parent references to nodes.
|
|
10
|
-
* Those rules will still fire for direct matches but cannot walk the tree.
|
|
11
|
-
*
|
|
12
|
-
* Usage in eslint.config.js:
|
|
13
|
-
* import angularTemplateParser from '@angular-eslint/template-parser'
|
|
14
|
-
* import neighbor from '@a11yfred/neighbor/angular'
|
|
15
|
-
*
|
|
16
|
-
* export default [
|
|
17
|
-
* {
|
|
18
|
-
* files: ['**\/*.html'],
|
|
19
|
-
* languageOptions: { parser: angularTemplateParser },
|
|
20
|
-
* plugins: { '@a11yfred/neighbor': neighbor },
|
|
21
|
-
* rules: neighbor.configs.recommended.rules,
|
|
22
|
-
* },
|
|
23
|
-
* ]
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { h } from './lib/helpers-angular.js'
|
|
27
|
-
import { buildRules, buildRecommendedRules, buildPortabilityRules } from './lib/rules.js'
|
|
28
|
-
import { buildUlamRulesAngular, buildUlamRecommendedRulesFramework } from './lib/ulam-rules.js'
|
|
29
|
-
|
|
30
|
-
const NS = '@a11yfred/neighbor'
|
|
31
|
-
const rules = { ...buildRules(h), ...buildUlamRulesAngular() }
|
|
32
|
-
const plugin = { meta: { name: `${NS}/angular` }, rules }
|
|
33
|
-
|
|
34
|
-
let angularA11y = null
|
|
35
|
-
try { angularA11y = (await import('@angular-eslint/eslint-plugin-template')).default } catch {}
|
|
36
|
-
|
|
37
|
-
const ANGULAR_A11Y_RULES = [
|
|
38
|
-
'alt-text', 'click-events-have-key-events', 'elements-content',
|
|
39
|
-
'interactive-supports-focus', 'label-has-associated-control',
|
|
40
|
-
'mouse-events-have-key-events', 'no-autofocus', 'no-distracting-elements',
|
|
41
|
-
'no-positive-tabindex', 'role-has-required-aria', 'table-scope', 'valid-aria',
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
function getAngularA11yRules(plugin) {
|
|
45
|
-
const out = {}
|
|
46
|
-
for (const rule of ANGULAR_A11Y_RULES) {
|
|
47
|
-
if (plugin.rules?.[rule]) out[`@angular-eslint/template/${rule}`] = 'error'
|
|
48
|
-
}
|
|
49
|
-
return out
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export default {
|
|
53
|
-
...plugin,
|
|
54
|
-
configs: {
|
|
55
|
-
recommended: {
|
|
56
|
-
plugins: {
|
|
57
|
-
[NS]: plugin,
|
|
58
|
-
...(angularA11y ? { '@angular-eslint/template': angularA11y } : {}),
|
|
59
|
-
},
|
|
60
|
-
rules: {
|
|
61
|
-
...(angularA11y ? getAngularA11yRules(angularA11y) : {}),
|
|
62
|
-
...buildRecommendedRules(NS),
|
|
63
|
-
...buildPortabilityRules(NS),
|
|
64
|
-
...buildUlamRecommendedRulesFramework(NS),
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @a11yfred/neighbor - ESLint plugin (Angular templates)
|
|
3
|
+
*
|
|
4
|
+
* Flags the same ARIA anti-patterns as neighbor-eslint.mjs but for Angular
|
|
5
|
+
* component templates. Requires @angular-eslint/template-parser.
|
|
6
|
+
*
|
|
7
|
+
* Rules that require ancestor walking (no-log-with-interactive-children,
|
|
8
|
+
* no-menu-role-on-nav, no-heading-inside-interactive) are limited because
|
|
9
|
+
* @angular-eslint/template-parser does not attach parent references to nodes.
|
|
10
|
+
* Those rules will still fire for direct matches but cannot walk the tree.
|
|
11
|
+
*
|
|
12
|
+
* Usage in eslint.config.js:
|
|
13
|
+
* import angularTemplateParser from '@angular-eslint/template-parser'
|
|
14
|
+
* import neighbor from '@a11yfred/neighbor/angular'
|
|
15
|
+
*
|
|
16
|
+
* export default [
|
|
17
|
+
* {
|
|
18
|
+
* files: ['**\/*.html'],
|
|
19
|
+
* languageOptions: { parser: angularTemplateParser },
|
|
20
|
+
* plugins: { '@a11yfred/neighbor': neighbor },
|
|
21
|
+
* rules: neighbor.configs.recommended.rules,
|
|
22
|
+
* },
|
|
23
|
+
* ]
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { h } from './lib/helpers-angular.js'
|
|
27
|
+
import { buildRules, buildRecommendedRules, buildPortabilityRules } from './lib/rules.js'
|
|
28
|
+
import { buildUlamRulesAngular, buildUlamRecommendedRulesFramework } from './lib/ulam-rules.js'
|
|
29
|
+
|
|
30
|
+
const NS = '@a11yfred/neighbor'
|
|
31
|
+
const rules = { ...buildRules(h), ...buildUlamRulesAngular() }
|
|
32
|
+
const plugin = { meta: { name: `${NS}/angular` }, rules }
|
|
33
|
+
|
|
34
|
+
let angularA11y = null
|
|
35
|
+
try { angularA11y = (await import('@angular-eslint/eslint-plugin-template')).default } catch {}
|
|
36
|
+
|
|
37
|
+
const ANGULAR_A11Y_RULES = [
|
|
38
|
+
'alt-text', 'click-events-have-key-events', 'elements-content',
|
|
39
|
+
'interactive-supports-focus', 'label-has-associated-control',
|
|
40
|
+
'mouse-events-have-key-events', 'no-autofocus', 'no-distracting-elements',
|
|
41
|
+
'no-positive-tabindex', 'role-has-required-aria', 'table-scope', 'valid-aria',
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
function getAngularA11yRules(plugin) {
|
|
45
|
+
const out = {}
|
|
46
|
+
for (const rule of ANGULAR_A11Y_RULES) {
|
|
47
|
+
if (plugin.rules?.[rule]) out[`@angular-eslint/template/${rule}`] = 'error'
|
|
48
|
+
}
|
|
49
|
+
return out
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default {
|
|
53
|
+
...plugin,
|
|
54
|
+
configs: {
|
|
55
|
+
recommended: {
|
|
56
|
+
plugins: {
|
|
57
|
+
[NS]: plugin,
|
|
58
|
+
...(angularA11y ? { '@angular-eslint/template': angularA11y } : {}),
|
|
59
|
+
},
|
|
60
|
+
rules: {
|
|
61
|
+
...(angularA11y ? getAngularA11yRules(angularA11y) : {}),
|
|
62
|
+
...buildRecommendedRules(NS),
|
|
63
|
+
...buildPortabilityRules(NS),
|
|
64
|
+
...buildUlamRecommendedRulesFramework(NS),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}
|
package/neighbor-eslint-vue.mjs
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @a11yfred/neighbor
|
|
3
|
-
*
|
|
4
|
-
* Flags the same ARIA anti-patterns as neighbor-eslint.mjs but for Vue templates.
|
|
5
|
-
* Requires vue-eslint-parser as the project's ESLint parser for .vue files.
|
|
6
|
-
*
|
|
7
|
-
* Usage in eslint.config.js:
|
|
8
|
-
* import vueParser from 'vue-eslint-parser'
|
|
9
|
-
* import neighbor from '@a11yfred/neighbor/vue'
|
|
10
|
-
*
|
|
11
|
-
* export default [
|
|
12
|
-
* {
|
|
13
|
-
* files: ['**\/*.vue'],
|
|
14
|
-
* languageOptions: { parser: vueParser },
|
|
15
|
-
* plugins: { '@a11yfred/neighbor': neighbor },
|
|
16
|
-
* rules: neighbor.configs.recommended.rules,
|
|
17
|
-
* },
|
|
18
|
-
* ]
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import { h } from './lib/helpers-vue.js'
|
|
22
|
-
import { buildRules, buildRecommendedRules, buildPortabilityRules } from './lib/rules.js'
|
|
23
|
-
import { buildUlamRulesVue, buildUlamRecommendedRulesFramework } from './lib/ulam-rules.js'
|
|
24
|
-
|
|
25
|
-
const NS = '@a11yfred/neighbor'
|
|
26
|
-
const rules = { ...buildRules(h), ...buildUlamRulesVue() }
|
|
27
|
-
const plugin = { meta: { name: `${NS}/vue` }, rules }
|
|
28
|
-
|
|
29
|
-
let vueA11y = null
|
|
30
|
-
try { vueA11y = (await import('eslint-plugin-vuejs-accessibility')).default } catch {}
|
|
31
|
-
|
|
32
|
-
export default {
|
|
33
|
-
...plugin,
|
|
34
|
-
configs: {
|
|
35
|
-
recommended: {
|
|
36
|
-
plugins: {
|
|
37
|
-
[NS]: plugin,
|
|
38
|
-
...(vueA11y ? { 'vuejs-accessibility': vueA11y } : {}),
|
|
39
|
-
},
|
|
40
|
-
rules: {
|
|
41
|
-
...(vueA11y ? vueA11y.configs['flat/recommended'].rules : {}),
|
|
42
|
-
...buildRecommendedRules(NS),
|
|
43
|
-
...buildPortabilityRules(NS),
|
|
44
|
-
...buildUlamRecommendedRulesFramework(NS),
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @a11yfred/neighbor - ESLint plugin (Vue SFCs)
|
|
3
|
+
*
|
|
4
|
+
* Flags the same ARIA anti-patterns as neighbor-eslint.mjs but for Vue templates.
|
|
5
|
+
* Requires vue-eslint-parser as the project's ESLint parser for .vue files.
|
|
6
|
+
*
|
|
7
|
+
* Usage in eslint.config.js:
|
|
8
|
+
* import vueParser from 'vue-eslint-parser'
|
|
9
|
+
* import neighbor from '@a11yfred/neighbor/vue'
|
|
10
|
+
*
|
|
11
|
+
* export default [
|
|
12
|
+
* {
|
|
13
|
+
* files: ['**\/*.vue'],
|
|
14
|
+
* languageOptions: { parser: vueParser },
|
|
15
|
+
* plugins: { '@a11yfred/neighbor': neighbor },
|
|
16
|
+
* rules: neighbor.configs.recommended.rules,
|
|
17
|
+
* },
|
|
18
|
+
* ]
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { h } from './lib/helpers-vue.js'
|
|
22
|
+
import { buildRules, buildRecommendedRules, buildPortabilityRules } from './lib/rules.js'
|
|
23
|
+
import { buildUlamRulesVue, buildUlamRecommendedRulesFramework } from './lib/ulam-rules.js'
|
|
24
|
+
|
|
25
|
+
const NS = '@a11yfred/neighbor'
|
|
26
|
+
const rules = { ...buildRules(h), ...buildUlamRulesVue() }
|
|
27
|
+
const plugin = { meta: { name: `${NS}/vue` }, rules }
|
|
28
|
+
|
|
29
|
+
let vueA11y = null
|
|
30
|
+
try { vueA11y = (await import('eslint-plugin-vuejs-accessibility')).default } catch {}
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
...plugin,
|
|
34
|
+
configs: {
|
|
35
|
+
recommended: {
|
|
36
|
+
plugins: {
|
|
37
|
+
[NS]: plugin,
|
|
38
|
+
...(vueA11y ? { 'vuejs-accessibility': vueA11y } : {}),
|
|
39
|
+
},
|
|
40
|
+
rules: {
|
|
41
|
+
...(vueA11y ? vueA11y.configs['flat/recommended'].rules : {}),
|
|
42
|
+
...buildRecommendedRules(NS),
|
|
43
|
+
...buildPortabilityRules(NS),
|
|
44
|
+
...buildUlamRecommendedRulesFramework(NS),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
package/neighbor-eslint.mjs
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @a11yfred/neighbor
|
|
3
|
-
*
|
|
4
|
-
* Flags ARIA patterns that are widely derided, semantically wrong, or have
|
|
5
|
-
* poor/no AT support
|
|
6
|
-
*
|
|
7
|
-
* Sources and credits:
|
|
8
|
-
* Adrian Roselli adrianroselli.com
|
|
9
|
-
* Heydon Pickering heydonworks.com, inclusive-components.design
|
|
10
|
-
* Scott O'Hara scottohara.me
|
|
11
|
-
* Patrick Lauke splintered.co.uk, patrickhlauke.github.io/aria
|
|
12
|
-
* Karl Groves karlgroves.com
|
|
13
|
-
* Marcy Sutton marcysutton.com
|
|
14
|
-
* Eric Eggert yatil.net
|
|
15
|
-
* WAI-ARIA APG w3.org/WAI/ARIA/apg
|
|
16
|
-
* ARIA 1.2 spec w3.org/TR/wai-aria-1.2
|
|
17
|
-
*
|
|
18
|
-
* Rules already covered by jsx-a11y recommended (not duplicated here):
|
|
19
|
-
* aria-hidden on focusable → jsx-a11y/no-aria-hidden-on-focusable
|
|
20
|
-
* presentation/none on interactive → jsx-a11y/no-interactive-element-to-noninteractive-role
|
|
21
|
-
* redundant role → jsx-a11y/no-redundant-roles
|
|
22
|
-
* prefer semantic element → jsx-a11y/prefer-tag-over-role
|
|
23
|
-
* invalid role value → jsx-a11y/aria-role
|
|
24
|
-
* invalid aria prop → jsx-a11y/aria-props
|
|
25
|
-
* tabindex > 0 → jsx-a11y/tabindex-no-positive
|
|
26
|
-
* tabindex on non-interactive → jsx-a11y/no-noninteractive-tabindex
|
|
27
|
-
* img missing alt → jsx-a11y/alt-text
|
|
28
|
-
* input missing label → jsx-a11y/label-has-associated-control
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
|
32
|
-
import { h } from './lib/helpers-jsx.js'
|
|
33
|
-
import { buildRules, buildRecommendedRules } from './lib/rules.js'
|
|
34
|
-
import { buildUlamRules, buildUlamRecommendedRules } from './lib/ulam-rules.js'
|
|
35
|
-
|
|
36
|
-
const NS = '@a11yfred/neighbor'
|
|
37
|
-
const rules = { ...buildRules(h), ...buildUlamRules() }
|
|
38
|
-
|
|
39
|
-
const plugin = { meta: { name: NS }, rules }
|
|
40
|
-
|
|
41
|
-
export default {
|
|
42
|
-
...plugin,
|
|
43
|
-
configs: {
|
|
44
|
-
recommended: {
|
|
45
|
-
plugins: {
|
|
46
|
-
[NS]: plugin,
|
|
47
|
-
'jsx-a11y': jsxA11y,
|
|
48
|
-
},
|
|
49
|
-
rules: {
|
|
50
|
-
...jsxA11y.configs.recommended.rules,
|
|
51
|
-
...buildRecommendedRules(NS),
|
|
52
|
-
...buildUlamRecommendedRules(NS),
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @a11yfred/neighbor - ESLint plugin (React / JSX)
|
|
3
|
+
*
|
|
4
|
+
* Flags ARIA patterns that are widely derided, semantically wrong, or have
|
|
5
|
+
* poor/no AT support - but are not caught by eslint-plugin-jsx-a11y recommended.
|
|
6
|
+
*
|
|
7
|
+
* Sources and credits:
|
|
8
|
+
* Adrian Roselli adrianroselli.com
|
|
9
|
+
* Heydon Pickering heydonworks.com, inclusive-components.design
|
|
10
|
+
* Scott O'Hara scottohara.me
|
|
11
|
+
* Patrick Lauke splintered.co.uk, patrickhlauke.github.io/aria
|
|
12
|
+
* Karl Groves karlgroves.com
|
|
13
|
+
* Marcy Sutton marcysutton.com
|
|
14
|
+
* Eric Eggert yatil.net
|
|
15
|
+
* WAI-ARIA APG w3.org/WAI/ARIA/apg
|
|
16
|
+
* ARIA 1.2 spec w3.org/TR/wai-aria-1.2
|
|
17
|
+
*
|
|
18
|
+
* Rules already covered by jsx-a11y recommended (not duplicated here):
|
|
19
|
+
* aria-hidden on focusable → jsx-a11y/no-aria-hidden-on-focusable
|
|
20
|
+
* presentation/none on interactive → jsx-a11y/no-interactive-element-to-noninteractive-role
|
|
21
|
+
* redundant role → jsx-a11y/no-redundant-roles
|
|
22
|
+
* prefer semantic element → jsx-a11y/prefer-tag-over-role
|
|
23
|
+
* invalid role value → jsx-a11y/aria-role
|
|
24
|
+
* invalid aria prop → jsx-a11y/aria-props
|
|
25
|
+
* tabindex > 0 → jsx-a11y/tabindex-no-positive
|
|
26
|
+
* tabindex on non-interactive → jsx-a11y/no-noninteractive-tabindex
|
|
27
|
+
* img missing alt → jsx-a11y/alt-text
|
|
28
|
+
* input missing label → jsx-a11y/label-has-associated-control
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
|
32
|
+
import { h } from './lib/helpers-jsx.js'
|
|
33
|
+
import { buildRules, buildRecommendedRules } from './lib/rules.js'
|
|
34
|
+
import { buildUlamRules, buildUlamRecommendedRules } from './lib/ulam-rules.js'
|
|
35
|
+
|
|
36
|
+
const NS = '@a11yfred/neighbor'
|
|
37
|
+
const rules = { ...buildRules(h), ...buildUlamRules() }
|
|
38
|
+
|
|
39
|
+
const plugin = { meta: { name: NS }, rules }
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
...plugin,
|
|
43
|
+
configs: {
|
|
44
|
+
recommended: {
|
|
45
|
+
plugins: {
|
|
46
|
+
[NS]: plugin,
|
|
47
|
+
'jsx-a11y': jsxA11y,
|
|
48
|
+
},
|
|
49
|
+
rules: {
|
|
50
|
+
...jsxA11y.configs.recommended.rules,
|
|
51
|
+
...buildRecommendedRules(NS),
|
|
52
|
+
...buildUlamRecommendedRules(NS),
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}
|