0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

この記事では、ESLint の Flat Config にアクセシビリティ向けルールのプラグインである eslint-plugin-jsx-a11y を追加する手順について記載します。

開発環境

開発環境は以下の通りです。

  • Windows 11
  • VSCode
  • TypeScript 5.2.2
  • React 18.3.1
  • Vite 5.3.1
  • Node.js 20.15.0
  • npm 10.8.1
  • ESLint 8.57.0
  • Prettier 3.3.2
  • @eslint/js 9.6.0
  • eslint-config-prettier 9.1.0
  • eslint-plugin-jsx-a11y 6.9.0
  • eslint-plugin-react 7.34.3
  • globals 15.8.0
  • typescript-eslint 7.15.0

事前準備

プロジェクトに ESLint のインストール・設定をしておきます。
React / TypeScript 環境における詳細手順はこちら。

Prettier を追加する手順はこちら。

eslint-plugin-jsx-a11y のインストール

eslint-plugin-jsx-a11y をインストールします。

npm install eslint-plugin-jsx-a11y --save-dev

一括設定

eslint.config.jseslint-plugin-jsx-a11y をインポートして jsxA11y.flatConfigs.recommended を追加します。

eslint.config.js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
import pluginReactJSXRuntime from "eslint-plugin-react/configs/jsx-runtime.js";
import jsxA11y from "eslint-plugin-jsx-a11y"; // Add
import eslintConfigPrettier from "eslint-config-prettier";

export default [
  {
    files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
    settings: {
      react: {
        version: "detect",
      },
    },
  },
  { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReactConfig,
  pluginReactJSXRuntime,
  jsxA11y.flatConfigs.recommended, // Add
  eslintConfigPrettier,
];

動作確認

img タグの alt がない状態で、ESLint を実行してみます。

App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank" rel="noreferrer">
          {/* alt を削除 */}
          <img src={viteLogo} className="logo" />
        </a>
        <a href="https://react.dev" target="_blank" rel="noreferrer">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  );
}

export default App;

以下のエラーが表示されます。

13:11  error  img elements must have an alt prop, either with meaningful text, or an empty string for decorative images
jsx-a11y/alt-text

alt を追加するとエラーが消えます。

App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank" rel="noreferrer">
          {/* alt を追加 */}
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank" rel="noreferrer">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  );
}

export default App;

個別設定

eslint-plugin-jsx-a11y の各ルールを個別に設定することもできます。

  • pugins"jsx-a11y": jsxA11y を追加
  • rules"jsx-a11y/alt-text": "error" を追加
eslint.config.js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
import pluginReactJSXRuntime from "eslint-plugin-react/configs/jsx-runtime.js";
import jsxA11y from "eslint-plugin-jsx-a11y";
import eslintConfigPrettier from "eslint-config-prettier";

export default [
  {
    files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
    settings: {
      react: {
        version: "detect",
      },
    },
    plugins: {
      "jsx-a11y": jsxA11y, // Add
    },
    rules: {
      "jsx-a11y/alt-text": "error", // Add
    },
  },
  { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReactConfig,
  pluginReactJSXRuntime,
  eslintConfigPrettier,
];

参考

関連記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?