Ajout des librairies d'analyse de l'accessibilité : plugin eslint et axe-core/react (#2276)

* conf: Ajout du plugin eslint a11y

* feat: Ajoute le hook useAxeCoreAnalysis

* feat: Ajoute le script "start:axe-debugging"

* fix: Retire logique inutile du hook + converti les errors du plugin a11y en warn

* fix: Déplace le if à l'extérieur du hook

* feat: Sort l'import axe-core/react du useEffect + stocke axe dans une ref
pull/2277/head
Benjamin Arias 2022-09-09 13:12:46 +02:00 committed by GitHub
parent d922734f93
commit 20ca26b4f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 208 additions and 0 deletions

View File

@ -138,5 +138,19 @@ module.exports = {
],
},
},
// Accessibility rules on /site
{
files: ['site/**/*.{jsx,js,tsx,ts}'],
plugins: ['jsx-a11y'],
extends: ['plugin:jsx-a11y/strict'],
rules: {
'jsx-a11y/no-autofocus': 'warn',
'jsx-a11y/alt-text': 'warn',
'jsx-a11y/no-noninteractive-tabindex': 'warn',
'jsx-a11y/iframe-has-title': 'warn',
'jsx-a11y/click-events-have-key-events': 'warn',
'jsx-a11y/no-static-element-interactions': 'warn',
},
},
],
}

View File

@ -20,6 +20,7 @@
"lint:prettier": "yarn run prettier --check \"**/*.{js,jsx,ts,tsx,yaml,yml}\"",
"lint:prettier:fix": "yarn lint:prettier --write",
"lint:fix": "yarn lint:eslint:fix ; yarn lint:prettier:fix",
"lint:quiet": "yarn lint:eslintrc && yarn lint:eslint --quiet && yarn lint:prettier",
"lint": "yarn lint:eslintrc && yarn lint:eslint && yarn lint:prettier",
"postinstall": "yarn workspaces foreach -piv --exclude site run prepack",
"test": "CI=true yarn workspaces foreach run test",
@ -46,6 +47,7 @@
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jest": "^26.5.3",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-n": "^15.2.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.30.0",

View File

@ -21,6 +21,7 @@
"build:yaml-to-dts": "ts-node-esm scripts/build-yaml-to-dts.ts",
"postinstall": "node scripts/prepare.js",
"start": "vite dev",
"start:axe-debugging": "VITE_AXE_CORE_ENABLED=true vite dev",
"start:netlify": "sed 's|:SITE_EN|/infrance|g' netlify.base.toml | sed 's|:SITE_FR|/mon-entreprise|g' | sed 's|:API_URL|http://localhost:3004|g' | sed 's|\\[\\[redirects\\]\\]|\\[\\[redirects\\]\\]\\n force = true|g' > netlify.toml && HMR_CLIENT_PORT=8888 netlify dev",
"build": "NODE_OPTIONS='--max-old-space-size=6144'; yarn build:sitemap && vite build && yarn build:iframe-script",
"build:ssr": "NODE_OPTIONS='--max-old-space-size=4096'; vite build --ssr ./source/entry-server.tsx --outDir ./dist/server --emptyOutDir && echo '{\"module\": \"commonjs\"}' > dist/package.json",
@ -47,6 +48,7 @@
"build:storybook": "build-storybook"
},
"dependencies": {
"@axe-core/react": "^4.4.4",
"@internationalized/number": "^3.0.3",
"@react-aria/accordion": "^3.0.0-alpha.5",
"@react-aria/button": "^3.4.1",

View File

@ -24,6 +24,7 @@ import { useSelector } from 'react-redux'
import { Route, Routes } from 'react-router-dom'
import styled, { css } from 'styled-components'
import { useSaveAndRestoreScrollPosition } from './hooks/useSaveAndRestoreScrollPosition'
import { useAxeCoreAnalysis } from './hooks/useAxeCoreAnalysis'
import Accessibilité from './pages/Accessibilité'
import Budget from './pages/Budget/Budget'
import Créer from './pages/Creer'
@ -112,6 +113,11 @@ const App = () => {
useSaveAndRestoreScrollPosition()
if (!import.meta.env.PROD && import.meta.env.VITE_AXE_CORE_ENABLED) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useAxeCoreAnalysis()
}
return (
<StyledLayout isEmbeded={isEmbedded}>
{!isEmbedded && <Header />}

View File

@ -0,0 +1,40 @@
import React, { useEffect, useRef } from 'react'
import ReactDOM from 'react-dom'
export const useAxeCoreAnalysis = () => {
const axeRef = useRef<
| {
default: (
_React: any,
_ReactDOM: any,
_timeout: number
) => Promise<void>
}
| undefined
>()
const triggerAxeCoreAnalysis = async () => {
await axeRef.current?.default(React, ReactDOM, 1000)
}
// On importe axe-core/react uniquement si ce n'est pas déjà fait
if (!axeRef.current) {
import('@axe-core/react')
.then(async (axe) => {
axeRef.current = axe
await triggerAxeCoreAnalysis()
})
.catch((err) => {
// eslint-disable-next-line no-console
console.error(err)
})
}
// useEffect déclenché à chaque re-render du composant ou des enfants du composant
// où il est placé
useEffect(() => {
if (!axeRef.current) return
void triggerAxeCoreAnalysis()
})
}

144
yarn.lock
View File

@ -287,6 +287,16 @@ __metadata:
languageName: node
linkType: hard
"@axe-core/react@npm:^4.4.4":
version: 4.4.4
resolution: "@axe-core/react@npm:4.4.4"
dependencies:
axe-core: ^4.4.1
requestidlecallback: ^0.3.0
checksum: 1328066d39ddf6960c8affd43266e5c068c05a23b64dde8c5d3bad7c8742e93a86f355ffd16f38989bbfcb87ba719d4a26eff267410f3d9f2a2b9a8ffea93041
languageName: node
linkType: hard
"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.5.5, @babel/code-frame@npm:^7.8.3":
version: 7.16.7
resolution: "@babel/code-frame@npm:7.16.7"
@ -2880,6 +2890,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime-corejs3@npm:^7.10.2":
version: 7.19.0
resolution: "@babel/runtime-corejs3@npm:7.19.0"
dependencies:
core-js-pure: ^3.20.2
regenerator-runtime: ^0.13.4
checksum: 810c983462430b948af83e1e6bcc06ca14dad59a257d7dc453779cdc1fbc7d9a6d75d608591a1eeb90c71c7fce1c2279a87c5bc848c5ac58eef831ecad596a9f
languageName: node
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.4, @babel/runtime@npm:^7.17.0, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.5.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2":
version: 7.17.8
resolution: "@babel/runtime@npm:7.17.8"
@ -2889,6 +2909,15 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.18.9":
version: 7.19.0
resolution: "@babel/runtime@npm:7.19.0"
dependencies:
regenerator-runtime: ^0.13.4
checksum: fa69c351bb05e1db3ceb9a02fdcf620c234180af68cdda02152d3561015f6d55277265d3109815992f96d910f3db709458cae4f8df1c3def66f32e0867d82294
languageName: node
linkType: hard
"@babel/runtime@npm:^7.17.8":
version: 7.18.6
resolution: "@babel/runtime@npm:7.18.6"
@ -10117,6 +10146,16 @@ __metadata:
languageName: node
linkType: hard
"aria-query@npm:^4.2.2":
version: 4.2.2
resolution: "aria-query@npm:4.2.2"
dependencies:
"@babel/runtime": ^7.10.2
"@babel/runtime-corejs3": ^7.10.2
checksum: 38401a9a400f26f3dcc24b84997461a16b32869a9893d323602bed8da40a8bcc0243b8d2880e942249a1496cea7a7de769e93d21c0baa439f01e1ee936fed665
languageName: node
linkType: hard
"aria-query@npm:^5.0.0":
version: 5.0.0
resolution: "aria-query@npm:5.0.0"
@ -10355,6 +10394,13 @@ __metadata:
languageName: node
linkType: hard
"ast-types-flow@npm:^0.0.7":
version: 0.0.7
resolution: "ast-types-flow@npm:0.0.7"
checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4
languageName: node
linkType: hard
"ast-types@npm:^0.14.2":
version: 0.14.2
resolution: "ast-types@npm:0.14.2"
@ -10467,6 +10513,13 @@ __metadata:
languageName: node
linkType: hard
"axe-core@npm:^4.4.1, axe-core@npm:^4.4.3":
version: 4.4.3
resolution: "axe-core@npm:4.4.3"
checksum: c3ea000d9ace3ba0bc747c8feafc24b0de62a0f7d93021d0f77b19c73fca15341843510f6170da563d51535d6cfb7a46c5fc0ea36170549dbb44b170208450a2
languageName: node
linkType: hard
"axios@npm:^0.25.0":
version: 0.25.0
resolution: "axios@npm:0.25.0"
@ -10476,6 +10529,13 @@ __metadata:
languageName: node
linkType: hard
"axobject-query@npm:^2.2.0":
version: 2.2.0
resolution: "axobject-query@npm:2.2.0"
checksum: 96b8c7d807ca525f41ad9b286186e2089b561ba63a6d36c3e7d73dc08150714660995c7ad19cda05784458446a0793b45246db45894631e13853f48c1aa3117f
languageName: node
linkType: hard
"babel-loader@npm:^8.0.0":
version: 8.2.5
resolution: "babel-loader@npm:8.2.5"
@ -12548,6 +12608,13 @@ __metadata:
languageName: node
linkType: hard
"core-js-pure@npm:^3.20.2":
version: 3.25.0
resolution: "core-js-pure@npm:3.25.0"
checksum: 041cef3c4fa03b30eea6aa8539db00a02ea264e8542b9b787428f43e727e67050c742f46dbd75bc9ab544524a54e1ee55d8b23602dc8a2da485a3741a5f95df7
languageName: node
linkType: hard
"core-js-pure@npm:^3.8.1":
version: 3.23.3
resolution: "core-js-pure@npm:3.23.3"
@ -13069,6 +13136,13 @@ __metadata:
languageName: node
linkType: hard
"damerau-levenshtein@npm:^1.0.8":
version: 1.0.8
resolution: "damerau-levenshtein@npm:1.0.8"
checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de
languageName: node
linkType: hard
"dashdash@npm:^1.12.0":
version: 1.14.1
resolution: "dashdash@npm:1.14.1"
@ -14878,6 +14952,29 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-jsx-a11y@npm:^6.6.1":
version: 6.6.1
resolution: "eslint-plugin-jsx-a11y@npm:6.6.1"
dependencies:
"@babel/runtime": ^7.18.9
aria-query: ^4.2.2
array-includes: ^3.1.5
ast-types-flow: ^0.0.7
axe-core: ^4.4.3
axobject-query: ^2.2.0
damerau-levenshtein: ^1.0.8
emoji-regex: ^9.2.2
has: ^1.0.3
jsx-ast-utils: ^3.3.2
language-tags: ^1.0.5
minimatch: ^3.1.2
semver: ^6.3.0
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
checksum: baae7377f0e25a0cc9b34dc333a3dc6ead9ee8365e445451eff554c3ca267a0a6cb88127fe90395c578ab1b92cfed246aef7dc8d2b48b603389e10181799e144
languageName: node
linkType: hard
"eslint-plugin-n@npm:^15.2.0":
version: 15.2.4
resolution: "eslint-plugin-n@npm:15.2.4"
@ -19270,6 +19367,16 @@ __metadata:
languageName: node
linkType: hard
"jsx-ast-utils@npm:^3.3.2":
version: 3.3.3
resolution: "jsx-ast-utils@npm:3.3.3"
dependencies:
array-includes: ^3.1.5
object.assign: ^4.1.3
checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745
languageName: node
linkType: hard
"junk@npm:^3.1.0":
version: 3.1.0
resolution: "junk@npm:3.1.0"
@ -19504,6 +19611,22 @@ __metadata:
languageName: node
linkType: hard
"language-subtag-registry@npm:~0.3.2":
version: 0.3.22
resolution: "language-subtag-registry@npm:0.3.22"
checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a
languageName: node
linkType: hard
"language-tags@npm:^1.0.5":
version: 1.0.5
resolution: "language-tags@npm:1.0.5"
dependencies:
language-subtag-registry: ~0.3.2
checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf
languageName: node
linkType: hard
"latest-version@npm:^5.1.0":
version: 5.1.0
resolution: "latest-version@npm:5.1.0"
@ -21676,6 +21799,18 @@ __metadata:
languageName: node
linkType: hard
"object.assign@npm:^4.1.3":
version: 4.1.4
resolution: "object.assign@npm:4.1.4"
dependencies:
call-bind: ^1.0.2
define-properties: ^1.1.4
has-symbols: ^1.0.3
object-keys: ^1.1.1
checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864
languageName: node
linkType: hard
"object.entries@npm:^1.1.0, object.entries@npm:^1.1.5":
version: 1.1.5
resolution: "object.entries@npm:1.1.5"
@ -24372,6 +24507,13 @@ __metadata:
languageName: node
linkType: hard
"requestidlecallback@npm:^0.3.0":
version: 0.3.0
resolution: "requestidlecallback@npm:0.3.0"
checksum: 2405aef711b516e326ff18849b24ad2c0e623d2b60397bdc7919fa40d8575fce0a16a563a53f94ec89d255325a99e5deee952e6024584a5179cbbabb4469f0e8
languageName: node
linkType: hard
"require-directory@npm:^2.1.1":
version: 2.1.1
resolution: "require-directory@npm:2.1.1"
@ -24724,6 +24866,7 @@ __metadata:
eslint-plugin-cypress: ^2.12.1
eslint-plugin-import: ^2.26.0
eslint-plugin-jest: ^26.5.3
eslint-plugin-jsx-a11y: ^6.6.1
eslint-plugin-n: ^15.2.0
eslint-plugin-promise: ^6.0.0
eslint-plugin-react: ^7.30.0
@ -25208,6 +25351,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "site@workspace:site"
dependencies:
"@axe-core/react": ^4.4.4
"@internationalized/number": ^3.0.3
"@react-aria/accordion": ^3.0.0-alpha.5
"@react-aria/button": ^3.4.1