diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9638395..a56c472 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,6 +27,12 @@ jobs: run: npm ci --ignore-scripts - name: Build Project run: npm run build + - name: Generate llms.txt files + run: npm run generate-llms + - name: Copy llms.txt files to dist + run: | + cp llms.txt dist/ + cp llms-full.txt dist/ - name: Upload Pages Artifact uses: actions/upload-pages-artifact@v3 with: @@ -66,4 +72,4 @@ jobs: aws-region: ap-northeast-1 - name: Upload to S3 run: | - aws s3 sync artifact s3://${{ env.AWS_S3_BUCKET_NAME }}/accessibility-guidelines --exclude "*" --include "*.html" --delete + aws s3 sync artifact s3://${{ env.AWS_S3_BUCKET_NAME }}/accessibility-guidelines --exclude "*" --include "*.html" --include "*.txt" --delete diff --git a/llms-full.txt b/llms-full.txt new file mode 100644 index 0000000..500808f --- /dev/null +++ b/llms-full.txt @@ -0,0 +1,1844 @@ +# LIFULL Accessibility Guidelines + +> アクセシビリティに配慮したデザインと実装のためのガイドライン + +This file contains accessibility guidelines for designers and developers. + +## metadata +- url: https://lifull.github.io/accessibility-guidelines/ +- version: v3.0 +## 目次 + +- [ガイドラインについて](#ガイドラインについて) + - [アクセシブルなデザインパターン](#アクセシブルなデザインパターン) + - [代替テキストの考え方](#代替テキストの考え方) + - [はじめに](#はじめに) + - [利用方法](#利用方法) +- [デザインのガイドライン](#デザインのガイドライン) + - [自動再生するコンテンツ (レベル1)](#自動再生するコンテンツ) + - [閃光 (レベル1)](#閃光) + - [見出し (レベル1)](#見出し) + - [画像の代替テキスト (レベル1)](#画像の代替テキスト) + - [ページタイトル (レベル1)](#ページタイトル) + - [動画の字幕 (レベル1)](#動画の字幕) + - [音声のみのコンテンツ (レベル2)](#音声のみのコンテンツ) + - [グラフや図 (レベル2)](#グラフや図) + - [データ可視化 (レベル2)](#データ可視化) + - [テキスト画像 (レベル2)](#テキスト画像) + - [表 (レベル2)](#表) + - [動画コンテンツ(音声を含む) (レベル2)](#動画コンテンツ音声を含む) + - [リンクテキスト (レベル3)](#リンクテキスト) + - [コンテンツの順序 (レベル3)](#コンテンツの順序) + - [目次とサイトマップ (レベル3)](#目次とサイトマップ) + - [カスタムUIのキーボード操作 (レベル1)](#カスタムuiのキーボード操作) + - [定番のパターン (レベル1)](#定番のパターン) + - [キーボード操作 (レベル1)](#キーボード操作) + - [ホバーで表示されるコンテンツ (レベル2)](#ホバーで表示されるコンテンツ) + - [エラーメッセージ (レベル2)](#エラーメッセージ) + - [エラーメッセージの提示 (レベル2)](#エラーメッセージの提示) + - [フォームコントロールのラベル (レベル2)](#フォームコントロールのラベル) + - [シンプルなポインター操作 (レベル2)](#シンプルなポインター操作) + - [デバイスの向き (レベル3)](#デバイスの向き) + - [新しいタブで開くリンク (レベル3)](#新しいタブで開くリンク) + - [予測可能なパターン (レベル3)](#予測可能なパターン) + - [時間制限 (レベル3)](#時間制限) + - [ユーザー認証 (レベル3)](#ユーザー認証) + - [フォーカスインジケーター (レベル1)](#フォーカスインジケーター) + - [リンクの判別 (レベル1)](#リンクの判別) + - [状態の判別 (レベル1)](#状態の判別) + - [レスポンシブデザイン (レベル2)](#レスポンシブデザイン) + - [ターゲットサイズ (レベル2)](#ターゲットサイズ) + - [テキストの色コントラスト (レベル2)](#テキストの色コントラスト) + - [テキストの均等割付 (レベル2)](#テキストの均等割付) + - [アイコンやUIコンポーネントの色コントラスト (レベル2)](#アイコンやuiコンポーネントの色コントラスト) +- [実装のガイドライン](#実装のガイドライン) + - [背景画像 (レベル1)](#背景画像) + - [見出し (レベル1)](#見出し) + - [画像の代替テキスト (レベル1)](#画像の代替テキスト) + - [ページの言語 (レベル1)](#ページの言語) + - [ページタイトル (レベル1)](#ページタイトル) + - [調整可能な文字サイズ (レベル2)](#調整可能な文字サイズ) + - [グループ化された画像 (レベル2)](#グループ化された画像) + - [ランドマーク領域 (レベル2)](#ランドマーク領域) + - [意味のある順序 (レベル2)](#意味のある順序) + - [改行と空白文字 (レベル2)](#改行と空白文字) + - [正しい構文と文法 (レベル3)](#正しい構文と文法) + - [フォームコントロールのラベル (レベル1)](#フォームコントロールのラベル) + - [ラベルのないコントロール (レベル1)](#ラベルのないコントロール) + - [コピー&ペーストの許容 (レベル2)](#コピーペーストの許容) + - [フォームコントロールのグループ化 (レベル2)](#フォームコントロールのグループ化) + - [入力目的の特定 (レベル2)](#入力目的の特定) + - [フォームコントロールの説明文 (レベル3)](#フォームコントロールの説明文) + - [ズームの許容 (レベル1)](#ズームの許容) + - [フォーカスインジケーター (レベル1)](#フォーカスインジケーター) + - [挿入されるコンテンツ (レベル1)](#挿入されるコンテンツ) + - [ボタンの使用 (レベル1)](#ボタンの使用) + - [ホバーで表示されるコンテンツ (レベル2)](#ホバーで表示されるコンテンツ) + - [文脈に応じたフォーカス (レベル2)](#文脈に応じたフォーカス) + - [Escapeキー操作 (レベル2)](#escapeキー操作) + - [外部コンテンツおよびUIライブラリ (レベル2)](#外部コンテンツおよびuiライブラリ) + - [隠されているコンテンツ (レベル2)](#隠されているコンテンツ) + - [WAI-ARIA (レベル2)](#waiaria) + - [背後のコンテンツ (レベル3)](#背後のコンテンツ) + - [ダウンイベントの使用 (レベル3)](#ダウンイベントの使用) + - [ドラッグ操作の中断 (レベル3)](#ドラッグ操作の中断) + - [ステータスの通知 (レベル3)](#ステータスの通知) + +## ガイドラインについて + +### アクセシブルなデザインパターン + +アクセシブルなデザインパターン + + アクセシブルなデザイン・実装方法が確立された定番のデザインパターンを紹介します。ここでのアクセシビリティへの配慮とは、キーボードで操作でき、スクリーンリーダーに UI の役割や状態が十分に伝わることを指しています。 + + ガイドライン「[定番のパターン](/accessibility-guidelines/design-forms-and-interactions.html#established-pattern)」にあるように、独自の UI を考案しデザインする前に、ここにラインナップされたパターンを利用して目的が達成できるかどうかを検討してください。 + + **利用上の注意** + + ここにラインナップされたUIを採用する前に、**HTMLのみで実現できるかどうかを検討してください**。たとえばDisclosureパターンには`details`要素が使えます。Spinbuttonパターンには`type="number"`を持つ`input`要素が使えます。 + + また、**HTMLの要素を本来と違う使い方をすることは避けてください**。たとえば、チェックボックスを領域の開閉に使わないでください。`select`要素をメニュー代わり(ソート順の切り替えなど)に使わないでください。 + + ## パターン集 + + | パターン名 | 説明 | + | :------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | [Accordion (Sections With Show/Hide Functionality)](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) | アコーディオンは、縦に積み重なったインタラクティブな見出しのセットで、それぞれがコンテンツのセクションを表すタイトル、コンテンツスニペット、サムネイルを含んでいます。 | + | [Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) | アラートは、ユーザーのタスクを中断させることなく、ユーザーの注意を引くような方法で、簡潔で重要なメッセージを表示する要素です。 | + | [Alert and Message Dialogs](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) | アラートダイアログは、重要なメッセージを伝え、応答を得るためにユーザーのワークフローを中断させるモーダルダイアログである。 | + | [Breadcrumb](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/) | パンくずリストとは、現在のページの親ページへのリンクを階層的に並べたものである。 | + | [Button](https://www.w3.org/WAI/ARIA/apg/patterns/button/) | **HTML の button 要素を使用することを強く推奨します**。ボタンは、フォームの送信、ダイアログの表示、アクションのキャンセル、削除など、ユーザーがアクションやイベントを実行できるようにするウィジェットです。 | + | [Carousel (Slide Show or Image Rotator)](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/) | カルーセルは、1 つまたは複数のスライドのサブセットを順次表示することによって、スライドと呼ばれるアイテムのセットを提示します。 | + | [Checkbox](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/) | WAI-ARIA は、2 種類のチェックボックスウィジェットをサポートしています。デュアルステートでは、ユーザはチェック済みと未チェックという 2 つの選択肢を切り替えられ、トライステートでは、部分チェック済みという第 3 の状態を追加でサポートします。 | + | [Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) | コンボボックスは、入力ウィジェットにポップアップがついたもので、ユーザーが可能な値のコレクションからコンボボックスの値を選択することができます。 | + | [Dialog (Modal)](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/) | ダイアログは、プライマリウィンドウまたは他のダイアログウィンドウにオーバーレイ表示されるウィンドウです。 | + | [Disclosure (Show/Hide)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) | ディスクロージャーは、コンテンツを折りたたみ(非表示)または展開(表示)することができるウィジェットです。 | + | [Feed](https://www.w3.org/WAI/ARIA/apg/patterns/feed/) | フィードは、ユーザーがスクロールすると自動的に新しいコンテンツがロードされるページのセクションです。 | + | [Grids : Interactive Tabular Data and Layout Containers](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) | グリッドウィジェットは、矢印キー、ホームキー、エンドキーなどのナビゲーションキーを使って、その中に含まれる情報やインタラクティブな要素を移動できるようにするコンテナです。 | + | [Link](https://www.w3.org/WAI/ARIA/apg/patterns/link/) | **HTML の a 要素を使用することを強く推奨します**。リンクウィジェットは、リソースへのインタラクティブなリファレンスを提供します。 | + | [Listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/) | リストボックスウィジェットは、オプションのリストを表示し、ユーザがそのうちの 1 つまたは複数を選択できるようにします。 | + | [Menu or Menu bar](https://www.w3.org/WAI/ARIA/apg/patterns/menu/) | メニューは、一連のアクションや機能など、ユーザに選択肢のリストを提供するウィジェットです。 | + | [Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/) | メニューボタンは、メニューを開くためのボタンです。 | + | [Meter](https://www.w3.org/WAI/ARIA/apg/patterns/meter/) | メーターは、定義された範囲内で変化する数値のグラフィック表示です。 | + | [Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton/) | ラジオグループ ラジオボタンと呼ばれるチェック可能なボタンのセットで、一度に 1 つ以上のボタンをチェックすることができない。 | + | [Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider/) | スライダーは、ユーザーがある範囲内の値を選択するための入力です。 | + | [Slider (Multi-Thumb)](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb/) | マルチサムスライダーは、関連する値のグループ内の値をそれぞれ設定する 2 つ以上のサム(親指)を持つスライダーです。 | + | [Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) | スピンボタンは、その値を離散的な値のセットまたは範囲に制限する入力ウィジェットです。 | + | [Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) | スイッチは、ユーザーがオンとオフの 2 つの値から 1 つを選択できる入力ウィジェットです。 | + | [Table](https://www.w3.org/WAI/ARIA/apg/patterns/table/) | **HTML の table 要素を使用することを強く推奨します**。WAI-ARIA のテーブルは、HTML のテーブル要素と同様に、1 つ以上のセルを含む 1 つ以上の行からなる静的な表形式構造で、対話型ウィジェットではありません。 | + | [Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/) | タブは、タブパネルと呼ばれるコンテンツのレイヤーセクションのセットで、一度に 1 つのパネルを表示します。 | + | [Toolbar](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) | ツールバーは、ボタン、メニューボタン、チェックボックスなどのコントロール群をグループ化するためのコンテナである。 | + | [Tooltip Widget](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) | **ツールチップはタッチ端末でのアクセスしにくさがあるため非推奨です**。ツールチップは、キーボードフォーカスが当たったときや、マウスがその要素に重なったときに、その要素に関連する情報を表示するポップアップである。 | + | [Tree View](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/) | ツリービューウィジェットは、階層化されたリストを表示します。 | + | [Treegrid](https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/) | ツリーグリッドウィジェットは、編集可能な表形式の情報からなる階層的なデータグリッドを表示する。 | + | [Window Splitter](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) | ウィンドウスプリッターは、ウィンドウの 2 つのセクション(ペイン)間の移動可能なセパレータで、ユーザーがペインの相対的なサイズを変更できるようにするものです。 | + +### 代替テキストの考え方 + +代替テキストの考え方 + + この文書は許諾に基づいて[WebAIM: Alternative Text](https://webaim.org/techniques/alttext/)を日本語訳したものです。再利用にあたっては原著を参照してください。 + + --- + + ## はじめに + + 代替テキストとは、ウェブページの非テキストコンテンツをテキストで置き換えたものです。この記事は[画像](https://webaim.org/techniques/images)に焦点を当てていますが、その原則はマルチメディアや他の非テキストコンテンツにも適用されます。 + + 代替テキストにはいくつかの機能があります。 + + - スクリーンリーダーは、画像の代わりに代替テキストを表示し、視覚障害や特定の認知障害を持つユーザーが画像の内容や機能を認識できるようにします。 + - 画像の読み込みに失敗したり、ユーザーが画像をブロックしている場合、ブラウザは画像の代わりに代替テキストを視覚的に表示します。 + - 検索エンジンは代替テキストを利用し、ページの目的と内容の評価に反映させます。 + + 画像に**何が写っているか**を認識する技術は進歩していますが、アルゴリズムだけでは、ページ全体の文脈の中で画像が**何を意味しているか**を理解することはできません。カエデの葉はカナダを表しているのかもしれませんし、単に木の葉を表しているのかもしれません。ウェブページの作者は、画像の**内容**や**機能**を表す代替テキストを提供しなければなりません。 + + 代替テキストの提供には、2つの方法があります。 + + - ``要素の`alt`属性で指定する。 + - 画像の近くにある目に見える本文の中に表示する。または、同等のテキストを簡潔に表示できない場合、代替テキストを別のページに表示し、画像または画像に隣接するテキストリンクからリンクさせることができる。 + + このように、代替テキストは、`alt`属性だけではありません。 + + **すべての**画像には、`alt=""`(「空白」の代替テキストと呼ばれることもある)であっても、`alt`属性を付ける必要があります。 + + ## コンテキストがすべて + + エレン・オチョアの画像を見てみましょう。 + + この画像は、その使われ方によって、全く異なる代替テキストを必要とする場合があります。 + + ### ノート + + 代替テキストの原則を説明するために、この記事内のほとんどの画像には`alt="example image"`が指定されています。しかし、画像のコンテンツは通常、ページのコンテキスト内で表示されます。 + + ### 例1 + + ヒスパニック系女性として初めて宇宙へ行き、その後、ジョンソン宇宙センターでヒスパニック系初の所長を務めたエレン・オチョアは、ロールモデルとして広く知られています。 + + 例1の画像の`alt`テキストには何を選ぶか? + + - `"宇宙飛行士エレン・オチョア"` + - `"宇宙飛行士エレン・オチョアの画像"` + - `"エレン・オチョア、宇宙に行った最初のヒスパニック系女性"` + - 空の`alt`属性 (`alt=""`) + + まず、その**内容**と**機能**を考えてみましょう。画像は、リンクされている場合(あるいは``の中に``がある場合)、あるいは``の中にある場合のみ機能を持ちます。この場合、画像は機能を持ちません。 + + 画像の内容を評価し、要約することは、より困難な場合があります。画像の内容が周囲のテキストで表現されている場合は、`alt=""`で十分かもしれません。 + + 上の例では、画像のコンテンツが、これがエレン・オチョアであることをユーザーに伝えています。また、彼女の服装から、彼女が宇宙飛行士であることがわかりますが、これは、彼女の功績を考えると、とても意味のあることです。 + + **このことから、`alt="宇宙飛行士エレン・オチョア"` をお勧めします。** + + "宇宙飛行士エレン・オチョアの画像" は、画像を画像として説明する冗長なものです。 + + "エレン・オチョア、宇宙に行った最初のヒスパニック系女性" は、画像の一部ではない情報を含み、また本文と冗長になっています。 + + 空の`alt`属性も適切ではありません。本文にエレン・オチョアという名前があっても、視覚ユーザは画像の内容から直接それを知ることができます。したがって、画像は内容を伝えるものであり、空の`alt`属性以上のものが必要です。 + + #### 重要 + + `alt`属性は、通常、次のようにします。 + + - コンテンツと機能を**正確に**表現し、**同等**であること。 + - **簡潔であること**。内容(もしあれば)と機能(もしあれば)は、正確さを犠牲にすることなく、可能な限り簡潔に表現する必要があります。通常は数語でよいが、まれに短文や2文が適切な場合もある。 + - 画像の近くにあるテキストと同じ情報を提供したり、**冗長にならないように**する。 + - **「…の画像」、「…のグラフィック」などのフレーズを含めない**。スクリーンリーダーはすでに`alt`テキストと一緒に「グラフィック」とアナウンスしているので、これは冗長になります。画像が写真やイラストであることなどが重要な内容である場合は、代替テキストに含めると便利な場合があります。 + + ### 例2 + + **宇宙飛行士エレン・オチョア** + + ヒスパニック系女性として初めて宇宙へ行き、その後、ジョンソン宇宙センターでヒスパニック系初の所長を務めたエレン・オチョアは、ロールモデルとして広く知られています。 + + 例2の画像には、どのような`alt`テキストを選ぶのでしょうか? + + - `"画像"` + - `"エレン・オチョア"` + - 空の`alt`属性(alt="") + + **この場合、画像の内容は隣接するテキストで表示されるため、`alt=""`が最適です**。 + + "エレン・オチョア" は冗長になります。`"画像"`は有用な情報を提供しません。 + + ## 機能的な画像 + + 画像は、コンテンツを提供するだけでなく、ナビゲーションなどの重要な機能を提供するために使われることが多いのです。 + + ### 例3 + + **宇宙飛行士エレン・オチョア** + + この画像はリンクされている(そしてそのリンク内の唯一のコンテンツである)ことに注意してください。あなたなら、どんな`alt`テキストを選びますか? + + - `"もっと読む"` + - `"宇宙飛行士エレン・オチョア"` + - `"宇宙飛行士エレン・オチョアのウィキペディアの項目"` + - 空の`alt`属性(`alt=""`) + + 画像もリンクである以上、機能があります。**リンク内の**隣接するテキストにはリンクの機能が記述されていないため、画像の`alt`属性で伝える必要があります。 + + **ですから、`alt="宇宙飛行士エレン・オチョア"`が最適な選択です**。スクリーンリーダーは通常、「リンク、画像、宇宙飛行士エレン・オチョア、宇宙飛行士エレン・オチョア」と読みます。冗長ですが、リンクされた画像の機能を適切に説明するために必要です。特に、スクリーンリーダーのユーザーがリンクでナビゲートする場合など、隣接するテキストから切り離してアクセスする場合は、このような冗長性が必要になります。 + + "宇宙飛行士エレン・オチョアのウィキペディアの項目"は、画像によって伝達される内容**以外の**内容、つまりリンクがウィキペディアに行くという事実を提供します。 + + "もっと読む"は、特に文脈から外れていると、十分な情報を提供しません。 + + 空白の`alt`テキストは、ここでは決して適切ではありません。リンクやボタンの中にあるコンテンツが画像**だけ**である場合、スクリーンリーダーが判断する材料は`alt`テキストだけです。テキストが空であったり、欠けていたりすると、スクリーンリーダーは、画像のファイル名やリンク先のページのURLを読み取り、それがユーザーの役に立つことを期待するかもしれませんが、必ずしもそうとは限りません。 + + 次の例のように、画像とテキストのキャプションの両方が1つのリンクに含まれていれば、すべてのユーザーにとってよりアクセスしやすくなります。 + + **宇宙飛行士エレン・オチョア** + + リンクされた画像のコンテンツと機能の両方がリンク内のテキストとして表示されるため、重複を避けるために画像には`alt=""`が付けられます。スクリーンリーダーは、通常、「リンク、宇宙飛行士エレン・オチョア」と読み、先の例よりもはるかに効率的です。 + + 可能な限り、`alt`属性に「…へのリンク」「…へはここをクリック」などを使用するのは避けてください。スクリーンリーダーはすでにリンクをリンクとして読み上げています。 + + ### 例4 + + 採用応募書類のダウンロード + + 例4のアイコン画像には、どのような`alt`テキストを選択しますか?アイコンはリンクの中にあることに注意してください。 + + - `"採用応募"` + - `"PDF"` + - `"PDFアイコン"` + - 画像の内容は文脈で示されるため、`alt=""`が適切 + + **"PDF" が最適です。これはアイコンの内容を伝えるもので、それ以上でも以下でもありません**。 + + "採用応募 "は冗長になります。機能("採用応募書類のダウンロード")はリンクのテキストで示されるので、`alt`属性に再び含める必要はありません。 + + "PDFアイコン"は、画像がどのようなものかを説明していますが、この文脈では最も適切なものではありません。「アイコン」はここでは冗長です。(このアイコンを別の文脈で使用する場合、それがアイコンであることをユーザーに知らせることが重要な場合があります)。 + + 空の`alt`テキストは、画像が示す重要な情報、つまりリンク先がPDF文書であることを省略してしまいます。 + + アイコンのみで隣接するテキストなしでリンクする場合、「採用応募書類をPDF形式でダウンロードする」のように、`alt`テキストは、リンクと画像の組み合わせのコンテンツと機能を完全に伝える必要があります。「PDF形式」だけではリンクされたアイコンとして十分ではありません。ページに多くのPDFリンクとアイコンが含まれている場合は特にです。スクリーンリーダーのユーザーがリンクされたアイコンの中を移動すると、「PDF形式、PDF形式、PDF形式...」と聞こえてしまうからです。 + + ## 装飾的な画像 + + 装飾的な画像とは... + + - 重要な内容を表示しないもの。 + - レイアウトや情報提供以外の目的で使用され + - 機能を持たないもの(例:リンクではない)。 + + 装飾的な画像には、`alt=""`を付けるべきです。 + + ### 例5 + + 例5の水平セパレータ画像には、どのような`alt`テキストを選びますか? + + - `"装飾的なライン"` + - `"フッターの始まり"` + - `"セパレーター"` + - `alt=""` + + この画像は、ドキュメントのセクション間の区切りを伝えるものですが、すでにテキストで提示されている構造を視覚的に補強しているに過ぎません。 + + **この画像は追加の内容を伝えるものではないので、`alt=""`が最も適切な選択です。** + + #### ノート + + 画像が装飾のためだけに使われる場合、その画像をページのコンテンツから取り除き、代わりにCSSの背景画像として定義するのが最善です。こうすることで、代替テキストの必要性が完全になくなり、ページの意味的・構造的な流れから画像を取り除くことができます。 + + ### 例6 + + 私たちのビジネスは、あなたが地球上で見つけることができる最高のサービスを約束します。私たちのチームは、契約交渉のプロセスを通じて優れた顧客サービスを提供するために専門的に訓練されています。 + + お客様の満足が私たちの最優先事項であり、保証されるか、あるいはお金をお返しします。 + + 例6にある画像の適切な`alt`属性は何でしょうか? + + - `"握手"` + - `"契約を完了させるために握手するビジネスマン"` + - `alt=""` + - `"私たちはプロフェッショナルなサービスを保証します"` + + **画像は関連する内容や重要な内容を伝えていないため、ここでは空の`alt`テキストが最適です**。考えてみてください。もし画像が削除されたら、重要なコンテンツは失われるでしょうか?この場合、おそらくそうではないでしょう。このような画像の多くは、視覚的に有益なコンテンツを提供していないにもかかわらず、スクリーンリーダーのユーザーに対して無意味で冗長な`alt`テキストを強要しています。 + + "握手" と "契約を完了させるために握手するビジネスマン" は画像を説明していますが、これは余分な情報です。 + + "私たちはプロフェッショナルなサービスを保証します" は正しくない。これもウェブでよく見られる間違いです。`alt`を使って、他のどこにも「当てはまらない」余計な情報(または検索エンジン向けの情報)を挿入しているのです。コーダーの論理的根拠は、冗長性を避けることかもしれませんが、なぜそうするのでしょうか。 + + #### ノート + + 多くの場合、「この画像を使えないとしたら、その代わりに何を置くか?」と尋ねることができます。もしその答えが「何もない」なら、`alt=""`で十分でしょう。 + + ## 高度な画像 + + 場合によっては、`alt`テキストの決定がより主観的になることがあります。スクリーンリーダーを使用した場合と使用しない場合のユーザーテストは、いくつかのアイデアを生み出すのに役立ちます。 + + ### フォーム画像ボタン + + ラスタライズされたテキストを表示するだけのフォーム画像ボタンは、テキストに置き換えられ、CSSでスタイルが設定されるべきです。画像が避けられない場合は、ボタンの機能を説明する`alt`属性が必要です。`alt`テキストは、"検索", "送信", "登録", "注文を確定" などのように、ボタンが作動したときに何をするのかを説明する必要があります。例えば、``は、サイト内検索フォームの画像ボタンとして適切かもしれません。 + + ### イメージ・マップ + + クライアント・サイドのイメージ``を使う場合、メイン・イメージの`alt`属性は、イメージ・マップのホット・スポットでは表示されないが、イメージ内に表示される内容を伝えなければなりません。例えば、ニューヨーク州の地図で、各郡の``がある場合、`alt="ニューヨークの郡"`となります。メイン画像が内容を伝えず、主にホットスポットのコンテナである場合、`alt=""`が適切です。 + + 各``は機能を提供するため、同等の`alt`属性を持つ必要があります。ニューヨークの郡のイメージマップの場合、それぞれの``は郡の名前を含むでしょう。 + + 対照的に、**サーバーサイドの**イメージ・マップ(マウス・クリックの座標をサーバーに戻して解釈する)は、スクリーンリーダーが認識できず、キーボードやスクリーンリーダーのユーザーには操作不能です。サーバーサイド・イメージマップは、クライアントサイド・イメージマップに置き換えるべきでしょう。 + + ### CSS画像 + + CSS画像は、代替テキストを必要としない装飾的な画像のために使用する必要があります。内容を伝える画像は、一般にCSSで定義すべきではありません。ページコンテンツ内に配置する。CSSや他の背景画像に直接代替テキストを追加することはできないため、背景画像が内容を示す場合は、その内容をページマークアップの中でアクセスできるようにする必要があります。上記の例4のPDFアイコン画像をCSSの背景画像で表示した場合、テキスト置換のテクニックを使って、リンク内のコンテンツを表示させることができます。 + + ```html + 採用応募書類のダウンロード (PDF) + ``` + + 次に、CSSを使用して、「(PDF)」のテキスト(`span class="pdficon"`要素)を[画面外に](https://webaim.org/techniques/css/invisiblecontent/)配置します。視覚ユーザーにはPDFの背景画像が見え、スクリーンリーダー・ユーザーには画面外の「(PDF)」テキストが聞こえます。 + + ### ロゴ + + 多くのWebサイトでは、メインブランドのロゴをホームページにリンクしています。画像には、会社名(`alt="Acme Company"`)などの代替テキストを提供すれば、通常は十分でしょう。ロゴ」という言葉(`alt="Acme Company Logo"`)は、通常、画像の内容や機能にとって重要な部分ではありません。同様に、画像がホームページにリンクしていることを示す(`alt="Acme Company home page"`)ことも、通常は必要ありません。なぜなら、これは一般的な慣例だからです。ウェブページの一番上にある「リンク、グラフィック、アクメカンパニー」を聞けば、スクリーンリーダーのユーザーは、それがホームページにリンクしたロゴであると認識すれば十分なのです。 + + ### 複雑な画像 + + 複雑な画像(チャート、グラフ、地図など)の代替案が、簡潔な`alt`属性(おそらく数文の長さ)に収まらない場合、代替テキストを別の場所に提供する必要があります。この場合、同じページ内の隣接するデータテーブルか、画像を掲載しているページからリンクされた別のウェブページになります。リンクは画像に隣接していてもよいし、画像そのものを説明ページにリンクさせてもよい。画像の代替テキストは、その画像の一般的な内容を記述する必要があります。 + + ```html + 販売データを見る + ``` + + #### longdescに関するノート + + `longdesc`属性は非推奨で、使用しないでください。これは、長い説明ページへの参照を作成する HTML4 属性でしたが、スクリーンリーダーでは決してうまくサポートされていませんでした。 + + #### 例7 + + この絵では、画家エマニュエル・ロイツェは、光、色、形、遠近法、比率、動きを使って構図を作り上げました。 + + 例7の画像には、どのような`alt`テキストを選ぶのでしょうか? + + - `"ジョージ・ワシントン"` + - `"ジョージ・ワシントンの絵画"` + - `"デラウェア川を渡るジョージ・ワシントンの絵画"` + - `"光と色を使って構図を作ることを示した古典的な絵画"` + - `"デラウェア川を渡るジョージ・ワシントンの絵画。渦巻く波が船を取り囲み、そこで威厳あるジョージ・ワシントンは、警戒する軍隊を戦いに導くために、嵐の中から川の向こうの光線を前方に見ている。"` + + 画像はリンクされていないので、機能はありません。次に、画像の内容が周囲のテキストで表現されているかどうかを判断する必要があります。この場合、そうではありません(少なくとも完全ではありません)。しかし、この画像はもっと難しい。 + + "ジョージ・ワシントン" はおそらく不適切です。 + + "ジョージ・ワシントンの絵画" の方が良いのですが、この場合、写真や他の画像タイプとは異なる絵画であることを表現するのは適切ですが、同等と見なすには十分な内容を提供できているとは言えません。 + + "デラウェア川を渡るジョージ・ワシントンの絵画" は、ユーザーがコンテンツそのものを識別するのに役立つような、より多くの情報を提供しています。代替テキストは、目の見えないユーザーのためだけのものではないことを忘れないでください。多くの目の見えるユーザーは、「ジョージ・ワシントン」だけでは十分な説明になっていないのに対し、この説明を見れば、問題の特定の絵画を識別することができます。 + + 最後の(冗長な)オプションは、主題よりも技法が重要な場合に適切かもしれません。また、絵画の詳細な調査が必要な場合にも適切ですが、このレベルの詳細については、おそらく本文で説明した方がよいでしょう。 + + **たったひとつの**正しい答えはありません。最適な代替テキストは、画像の文脈と意図された内容によって異なります。 + + ### Figureとfigcaption + + ``要素は、``と``を含むように設計され、自己充足的 (self-contained) で、典型的には文書の主要な流れから単一のユニットとして参照されます。``は、文書の意味に影響を与えることなく、文書の主要な流れから切り離すことができます。 + + ``は、その含まれる``との意味的な関連付けを作成し、図についての要約や追加情報を提供したり、図を含む文書に関連付けたりすることができます。しかし、``はまだaltテキストを必要とし、冗長性を避けるために、この情報は``を介して伝達されるべきではありません。 + + ## 結論 + + ウェブアクセシビリティに影響を与える最大の問題の一つであるにもかかわらず、ウェブに代替テキストを実装するための多様で不正確な方法を依然として見続けています。開発コミュニティが同等の代替テキストを完全に受け入れることができれば、ウェブはよりアクセシブルな場所になるはずです。 + + --- + + *Ellen Ochoa Image Credit: NASA, Public domain, via Wikimedia Commons.* + +### はじめに + +ガイドラインについて + はじめに + + LIFULLアクセシビリティガイドラインの概要、特色、項目の見方などを説明しています。 + + ## アクセシビリティとは + + アクセシビリティは、プロダクトやサービス、情報、環境が、できるだけ多くの人々にとって利用可能であることを意味します。これには、障害者だけでなく、高齢者や一時的な障害を持つ人、そしてさまざまな状況や環境で利用する人々も含まれます。アクセシビリティを考慮することで、プロダクトやサービスはより幅広いユーザーや状況、環境で使いやすくなります。 + + ## LIFULLアクセシビリティガイドラインとは + + LIFULLアクセシビリティガイドラインは、LIFULLの全てのプロダクトやサービスを利用しやすくするために策定されました。LIFULLのプロダクトに関わる全ての人が対象です。ガイドラインを読み、背景を知り、自らの作業に取り入れていただくことを期待しています。 + + 近年、アクセシビリティへの取り組みはより重要になっています。現在、私たちの取り組みは途中段階にありますが、弊社のコーポレートメッセージ「あらゆるLIFEを、FULLに。」を実現するために、アクセシビリティの向上を積極的に目指しています。 + + ### 特徴 + + LIFULLアクセシビリティガイドラインはいくつかのコンセプトに基づいて編成されています。 + + #### 工程に応じた項目 + + 自分がやるべきことがわかるよう、ガイドラインの項目は工程(≒職種)ごとに分けられています。 + + #### 優先度が明確 + + ガイドラインの項目には優先度を記載し、対応すべき順序を明確にしています。優先度について詳しくは[レベルとは何か?](/accessibility-guidelines/usage.html#レベルとは何か)を参照してください。 + + #### わかりやすい記述 + + 初学者でも理解できるように、図表や例を使って具体的に記述しています。ガイドラインが必要とされる背景や、恩恵を受けるユーザーについて記述しています。 + + #### 関連リソースへのアクセス + + 理解の促進に役立つリソースや、関連するリソースへのリンクを設けています。 + + ### 各項目の構成 + + ガイドラインの各項目は次のような構成になっています。 + + チェック項目 + ガイドライン項目が満たされているかどうかを素早く確認するためのチェック項目です。 + 説明 + 「〜とは」という見出しから始まるセクションは、ガイドライン項目の説明です。ガイドラインが必要な理由や対象ユーザーについての知識、用語解説などを含みます。 + レベル + ガイドライン項目の優先度を示しています。詳しくは[レベルとは何か?](/accessibility-guidelines/usage.html#レベルとは何か)を参照してください。 + 具体例 + ガイドラインを満たしていない例や満たした場合の具体的な例を紹介しています。 + 参考情報 + ガイドラインの理解を深めるための有用なツールや文書など、外部リソースへのリンクを紹介しています。 + + ## 「障害者」表記について + + 一般に、「害」という漢字にマイナスイメージがあるとして、「障がい者」や「障碍者」と表記するほうが好ましいとされることがあります。しかし、「障害者」のほうが好ましいとする意見も存在し、人や組織によって意見が分かれています。LIFULLアクセシビリティガイドラインでは、中央省庁の表記に従って「障害者」に統一しています。ただし、表記については会社としての統一見解ではないことをご了承ください。 + + 参考:[「障害」の表記に関する国語分科会の考え方(令和3年3月12日文化審議会国語分科会)](https://www.bunka.go.jp/seisaku/bunkashingikai/kokugo/hokoku/pdf/92880801_03.pdf) + + ## アクセス解析に伴う情報取得について + + 当ウェブサイトでは、Google Analyticsを使用してアクセス解析を行っております。Google Analyticsは、ウェブサイト利用状況を収集・分析するためのツールであり、この情報はウェブサイトの改善や利便性の向上に役立てられます。なお、収集されるデータは匿名化されており、特定の個人を識別するものではありません。 + + 収集された情報は、当社のプライバシーポリシーに則り、適切に取り扱われます。詳細については、[Google のサービスを使用するサイトやアプリから収集した情報の Google による使用](https://policies.google.com/technologies/partner-sites?hl=ja)および[当社のプライバシーポリシー](https://lifull.com/privacy/)をご参照ください。 + +### 利用方法 + +ガイドラインについて + 利用方法 + + LIFULLアクセシビリティガイドラインを効果的に活用する方法を解説します。 + + ## ガイドラインの使い方 + + LIFULLアクセシビリティガイドラインは、プロダクトやサービスをアクセシブルにするための手引書です。以下の手順でガイドラインを効果的に活用しましょう。 + + ### ガイドラインの活用手順 + + #### 1. ガイドライン全体を把握する + + まずは、ガイドライン全体をざっと読んで、アクセシビリティに関する基本的な理解を深めましょう。各項目には説明や具体例、参考情報が記載されているので、自分にとって特に関連性の高い部分を重点的に読み進めてください。 + + #### 2. 自分の業務に関連する項目を確認する + + ガイドラインは工程(≒職種)ごとに大きく分かれています。自分の業務に関連する項目を特定し、それらに重点を置いて理解を深めましょう。また、チーム内で協力してアクセシビリティを向上させるために、他の職種に関する項目も把握しておくと良いでしょう。 + + #### 3. 目標とするレベルを決める + + レベルはガイドライン項目の優先順位です。「レベルの選び方」を参考にしながら、プロダクトやプロジェクトで目標とするレベルを決定してください。 + + #### 4. 目標レベルに従って対応を計画する + + 各ガイドライン項目には対応するレベルが明記されています。これを参考にして、対応が必要な項目をリストアップし、実施の順序を決めましょう。リソースや状況に応じて、適切な対応策を選んでください。 + + #### 5. ガイドラインに沿った改善を実施する + + 対応が決まったら、具体的な改善を実施しましょう。ガイドラインに記載されている具体例や参考情報を活用しながら、アクセシビリティを向上させていくことが重要です。 + + #### 6. 継続的な改善を行う + + プロダクトやサービスのアクセシビリティ向上は、一度で完了するものではありません。ユーザーからのフィードバックや自身で気づいた課題をバックログに取り込み、継続的に改善していくことが大切です。 + + 各手順において、社内に在籍する専門家の知識やリソースを活用できます。アクセシビリティ推進グループに積極的に声をかけてみてください。 + + ## レベルについて + + ### レベルとは何か? + + レベルは、ガイドラインの重要度、コスト、LIFULLの制作事情を総合的に判断した、**ガイドライン項目の優先順位**です。 + + #### レベル1…必ず達成 + + ユーザーに大きな影響があり、どのサービスでも必ず達成したい重要なタスクです。レベル1に対応できていない場合、特定の状況にあるユーザーが完全にアクセスできない状況が生じることがあります。これはほとんどの場合、「バグ」とみなされるべきものです。 + + #### レベル2…可能な限り達成 + + レベル1に次いで重要で、できるだけ達成してほしいタスクです。これにより、より多くのユーザーがコンテンツにアクセスしやすくなります。項目によってはレベル1と同様の重要性を持つこともありますが、対応の難易度やLIFULLでの実情を考慮してレベルを下げている場合があります。 + + #### レベル3…できれば考慮 + + できれば考慮してもらいたいタスクです。これにより、WCAGのA, AAの達成基準がおおむねカバーされます。レベル3を達成すると、さらに多くのユーザーにとって使いやすいプロダクトやサービスを実現できます。 + + ### レベルの選び方 + + プロダクトやプロジェクトごとに目標レベルを設定し、そのレベルに合わせてガイドラインを満たすデザインと実装を行ってください。 + + 選択したレベルに基づいて、原則としてそのレベルで必要とされるガイドライン項目をすべて満たすようにしてください。 + + #### 既存のプロダクトやサービスへの適用 + + 既存のプロダクトやサービスにLIFULLアクセシビリティガイドラインを適用する場合、以下の「[レベル選びのモデルケース](#レベル選びのモデルケース)」から類似ケースを探して参考にしてください。適用時点で既にリリースされている部分に関する問題が多くても心配はいりません。今後の継続的な改善のなかで対応していきましょう。 + + #### 新規プロダクトやサービスへの適用 + + 新規プロダクトやサービスにLIFULLアクセシビリティガイドラインを適用する場合、下記の「[レベル選びのモデルケース](#レベル選びのモデルケース)」から類似ケースを探して参考にしてください。 + + #### 改修プロジェクトへの適用 + + プロダクトやサービスレベルで既に目標レベルが設定されている場合は、そのレベルに従ってください。目標がまだ設定されていなくても、UIの追加や改善を含む改修案件がある場合は、以下の「[レベル選びのモデルケース](#レベル選びのモデルケース)」から類似ケースを探して参考にしてください。 + + ### レベル選びのモデルケース + + 注:以下のモデルケースは、考え方を示すための例であり、実際に採用されたものではなく、必ずしも同様の判断を求めるものではありません。 + + **LIFULL HOME** + + 多くのアクセスが見込まれるため、様々なユーザーが利用することが想定されます。テキスト中心の情報検索・閲覧がサービスの核であるため、アクセシビリティへの配慮を妨げる要素はほとんどありません。一方で、企業の基幹サービスであるため、開発の迅速さも重要です。 + + **総合して、レベル2を目標とします**。レベル3の項目については、容易に実施できるものから取り入れます。 + + ただし、物件情報はユーザー生成コンテンツであり、画像に適切な代替テキストを用意することは難しいです。クライアントに代替テキストを提供してもらうための仕組みや業界慣習が不十分で、現実的ではありません。そのため、物件情報に関連する画像の代替テキストは対象外とします。 + + **サービスの紹介や問合せ導線を含むプロモーションサイト** + + 情報提供が主な目的のウェブサイトであり、サービス利用に関わる重要な導線です。インタラクティブな要素として問合せフォームがありますが、一般的なメールフォームで、複雑なインタラクションやサーバーサイド機能は必要ありません。サービス説明に動画コンテンツを含む場合、動画字幕作成のノウハウが不足していることが懸念されますが、取り組めば実現可能と考えられます。 + + **総合して、レベル2を目標とします**。 + + **企業の顔となる静的ウェブサイト(コーポレートサイト、IRサイトなど)** + + コーポレートサイトやIRサイト、採用サイトは、企業の取り組みが具現化されていると外部から認識される企業の顔です。情報提供が主な目的のウェブサイトであり、複雑なインタラクションやサーバーサイド機能は必要ありません。ブランディングやメッセージを伝えるために、動画やアニメーションによる演出を行いますが、アクセシビリティとの両立は十分可能です。 + + **総合して、レべル3を目標とします**。現時点で達成できていない項目については、計画的に改善を重ねます。IRサイトや採用サイトで利用している外部サービスのアクセシビリティについては、サービス提供元に改善要望を提案したり、別のサービスへの移行を検討します。 + + **外部委託による読み物系サイト・特集サイト** + + ほとんど動的な要素がない静的ウェブサイトです。事業部内にデザイナーやエンジニアがいないため、デザイン・実装および記事の執筆は外部委託しています。委託先は特別にアクセシビリティの知識が豊富ではありません。 + + **総合して、レベル1を目標とします**。デザインや実装のために、アクセシビリティガイドラインのコピーを委託先に送り、遵守を求めます。記事についても、記事コンテンツ向けアクセシビリティガイドラインに沿って執筆するよう求めます。デザインや実装のレビューや受入テストについては、アクセシビリティ推進グループに相談し進め方を確認します。 + + **VR/ARを活用した先進的なプロジェクト** + + VR/ARを用いて、業界内であまり例のない実験的なインタラクションを実現するプロジェクトです。実験的な要素が強く、普遍的な価値向上よりも、話題性や革新性をアピールすることが重要です。VR/ARによる空間的な体験の代替コンテンツ作成は、試行錯誤の末にできるかどうか微妙であり、プロジェクトの中で研究開発して提供することは現実的ではありません。 + + **総合して、目標とするレベルは定めません**。 + + **MVPによる検証フェーズのプロダクト** + + プロダクトが問題を解決するかどうか、市場がプロダクトを受け入れるかどうかを迅速に検証することが最も重要なプロジェクトです。プロダクトが提供できる根本的な価値を評価することが目的であり、ユーザビリティやアクセシビリティは二の次になることが共通認識となっています。 + + **総合して、目標とするレベルは定めません**。ただし、検証フェーズが終了しプロダクトが成功した場合、アクセシビリティを向上させるための改善計画を立てるものとします。 + + ## フィードバックの方法 + + 誤字脱字や内容の妥当性、わかりやすさや事例の推薦など、さまざまな観点からのフィードバックを歓迎しています。フィードバックを送るには、[GitHubリポジトリ](https://github.com/lifull/accessibility-guidelines)に起票してください。 + +## デザインのガイドライン + +### 自動再生するコンテンツ (レベル1) + +**チェック項目** + +**チェック項目** + +画面内に自動再生するコンテンツがあることで、特定のユーザーがウェブページの利用が困難になることがあります。以下はその一例です。 + +- 注意欠陥障害をもつユーザーは動き続けるコンテンツに注意を取られ、ページのほかの部分を利用できなくなることがあります。 +- 情報の取得に時間がかかる人は、コンテンツを読み終わる前に表示が切り替わってしまうかもしれません。 +- コンテンツの変化に伴い、フォーカスがリセットされたり音声が途切れたりすることによって、スクリーンリーダー利用上の妨げになることがあります。 + +具体例①:自動再生する映像 + +
+
+
+
+
+
+
+
+
+```
+
+`img`要素を装飾画像とするために空の`alt`属性を使用する。`alt`属性値そのものを省略すると、環境によって読み上げられ方が定まらない。
+
+✓ 良い例: `aria-hidden="true"`を使用する
+
+```html
+
+```
+
+`svg`要素やアイコンフォントを装飾画像とするために`aria-hidden="true"`を使用する。
+
+具体例③ イメージマップ
+
+✓ 良い例: `area`要素に`alt`属性を使用する
+
+```html
+
+
+```
+
+イメージマップの`area`要素に代替テキストを指定するために`alt`属性を使用する。
+
+詳細: [画像の代替テキスト](https://lifull.github.io/accessibility-guidelines/impl/image-alternative)
+
+### ページの言語 (レベル1)
+
+**チェック項目:** html要素にlang属性を使ってページ言語を明示する
+
+**チェック項目:** 部分的に別の言語のテキストが挿入される場合、その部分を囲む要素にlang属性を使って言語を明示する
+
+lang 属性を使うとページの全体や一部分に対して書かれている言語を明示することができます。機械がこれを読み取ることでテキストを適切に処理できるようになります。
+
+詳細: [ページの言語](https://lifull.github.io/accessibility-guidelines/impl/language-of-page)
+
+### ページタイトル (レベル1)
+
+**チェック項目:** 設計資料に記載されたタイトルをtitle要素に指定する
+
+**チェック項目:** 設計資料にタイトルが記載されていない場合、サイト内で一意になるタイトル案を作成し、コンテンツオーナーと相談する
+
+ページタイトルはブラウザーのタブや検索結果に表示されたり、スクリーンリーダーによって読み上げられます。ページの内容を把握するための重要な手がかりとしてページタイトルは重要です。
+
+詳細: [ページタイトル](https://lifull.github.io/accessibility-guidelines/impl/page-title)
+
+### 調整可能な文字サイズ (レベル2)
+
+**チェック項目:** ユーザー設定を反映できるようにルート要素への相対(rem)単位で文字サイズを指定する
+
+ユーザーの視力や認知特性に合わせるために、ブラウザーのデフォルトの文字サイズを大きく設定しているユーザーがいます。ウェブサイトが文字サイズをpx単位で指定していると、ブラウザーの文字サイズの設定が無視されてしまいます。
+
+詳細: [調整可能な文字サイズ](https://lifull.github.io/accessibility-guidelines/impl/adjustable-text-size)
+
+### グループ化された画像 (レベル2)
+
+**チェック項目:** グループ化された画像に代替テキストを設定する
+
+複数の画像の並びがひとまとまりの情報を表現する場合、個別の画像に代替テキストを設定すると理解が難しくなる場合があります。
+
+具体例①:評価メーター
+
+✗ 悪い例: 個別の画像に代替テキストを設定する
+
+```html
+カスタマーレビュー
+
+
+
+
+
+
+
+```
+
+連続して読み上げると「星1星1星1星0.5」となり、伝えたい情報が伝わらない。
+
+✓ 良い例: 先頭の画像に代替テキストを設定する
+
+```html
+カスタマーレビュー
+
+
+
+
+
+
+
+```
+
+先頭の画像に数値の情報をまとめて設定し、残りの画像には空の文字列を設定する(=装飾画像とする)ことで、数値の情報を伝えられる。
+
+✓ 良い例: 画像の並びをひとまとまりの画像として扱う
+
+```html
+カスタマーレビュー
+
+
+
+
+
+
+
+```
+
+`role="img"`属性を使用し、その要素をひとまとまりの画像として扱う。
+
+詳細: [グループ化された画像](https://lifull.github.io/accessibility-guidelines/impl/grouped-images)
+
+### ランドマーク領域 (レベル2)
+
+**チェック項目:** サイト共通ヘッダーをheader要素を使ってマークアップする
+
+**チェック項目:** サイト共通フッターをfooter要素を使ってマークアップする
+
+**チェック項目:** ヘッダー、フッターを除く領域をmain要素を使ってマークアップする
+
+**チェック項目:** パンくずナビゲーションをnav要素を使ってマークアップする
+
+ページの主たる領域をランドマークとしてマークアップすると、スクリーンリーダー利用者の使い勝手を向上させることができます。
+
+詳細: [ランドマーク領域](https://lifull.github.io/accessibility-guidelines/impl/landmark-region)
+
+### 意味のある順序 (レベル2)
+
+**チェック項目:** 意味の通る順序でコンテンツをマークアップし、スタイルシートでレイアウトする
+
+スクリーンリーダー等の支援技術は、DOM上の要素順に従ってコンテンツを読み上げます。スタイルシートやスクリプトを使ってレイアウトを調整していると、視覚的な順序と意味順序、読み上げの順序がバラバラになってしまうことがあり、混乱を招くかもしれません。
+
+原則として、スタイルシートを無効化しても意味の通る順序でマークアップし、スタイルシートでレイアウトを実現するようにしてください。これによって視覚的な順序と読み上げの順序が一致しなくなり、支援技術による利用が著しく阻害されると思われる場合、デザイナーと話し合ってみてください。
+
+詳細: [意味のある順序](https://lifull.github.io/accessibility-guidelines/impl/meaningful-sequence)
+
+### 改行と空白文字 (レベル2)
+
+**チェック項目:** 単語内の文字間隔を制御するために、CSS のletter-spacingを使用する
+
+ゆったりとした文字間隔を実現するためにスペース文字を文字間に挿入すると、スクリーンリーダーは語句を適切に検出できなくなり、うまく読み上げられなくなってしまいます。
+
+詳細: [改行と空白文字](https://lifull.github.io/accessibility-guidelines/impl/whitespace-character)
+
+### 正しい構文と文法 (レベル3)
+
+**チェック項目:** 仕様に準拠したHTMLやCSSを記述する
+
+**チェック項目:** HTMLの構文と文法をチェックするために[Nu Html Checker](https://validator.w3.org/nu/)を使用する
+
+**チェック項目:** CSSの構文と文法をチェックするために[The W3C CSS Validation Service](https://jigsaw.w3.org/css-validator/)を使用する
+
+仕様に定められた構文と文法に準拠して HTML や CSS を記述することで、将来のウェブ技術の拡張や新しいユーザーエージェントに対して堅牢になります。
+
+詳細: [正しい構文と文法](https://lifull.github.io/accessibility-guidelines/impl/syntax-and-grammar)
+
+### フォームコントロールのラベル (レベル1)
+
+**チェック項目:** label要素をつかってフォームコントロールとラベルを関連付ける
+
+テキスト入力欄やチェックボックス、`select`要素など、HTMLに定義されているユーザーの入力を受け付ける要素(フォームコントロール)は全て名前を持つ必要があります。名前は、スクリーンリーダー利用者がフォームコントロールにフォーカスを合わせたときに読み上げられます。
+
+`label`要素を使うと、フォームコントロールに名前を付けられると同時にクリックやタップで選択できる範囲が広がるため、ユーザビリティ面にもメリットがあります。
+
+具体例①:テキスト入力欄
+
+✓ 良い例: ラベルとテキスト入力欄を一つの`label`要素に含める
+
+```html
+
+```
+
+ラベルと入力欄を`label`要素で囲むと、入力欄の名前が「お名前」に設定されます。
+
+✓ 良い例: テキスト入力欄に`id`を付与し、`label`要素の`for`属性で参照する
+
+```html
+
+
+```
+
+テキスト入力欄に`id`を付与し、`label`要素の`for`属性で参照することで、入力欄の名前が「お名前」に設定されます。ラベルとコントロールを隣同士に置けない場合などに便利です。
+
+具体例②:チェックボックス
+
+✓ 良い例: チェックボックスとラベルを一つの`label`要素に含める
+
+```html
+
+```
+
+チェックボックスラベルを`label`要素で囲むと、チェックボックスの名前が「メールを受取る」に設定されます。
+
+✓ 良い例: チェックボックスに`id`を付与し、`label`要素の`for`属性で参照する
+
+```html
+
+
+```
+
+チェックボックスに`id`を付与し、`label`要素の`for`属性で参照することで、チェックボックスの名前が「メールを受取る」に設定されます。ラベルとコントロールを隣同士に置けない場合などに便利です。
+
+詳細: [フォームコントロールのラベル](https://lifull.github.io/accessibility-guidelines/impl/label-for-control)
+
+### ラベルのないコントロール (レベル1)
+
+**チェック項目:** コントロールにラベルがなく、資料に名前の指定もない場合、名前の案を考え、コンテンツオーナーと認識をそろえる
+
+**チェック項目:** aria-labelledby属性もしくはaria-label属性をつかってフォームコントロールに名前を指定する
+
+デザイン上の理由でフォームコントロールのラベルが画面上から省略されている場合でも、フォームコントロールは名前を持つ必要があります。
+
+ラベルのないコントロールに名前を付ける方法は2通りあります。`aria-labelledby`を使うと、ページ中の任意の要素のテキストをコントロールの名前として使用できます。`aria-label`属性はコントロールに直接名前を指定できます。
+
+`aria-labelledby`属性を優先して使用するようにしてください。`aria-label`属性は利用状況によってはうまく機能しません。たとえばウェブページを機械翻訳にかけたときに翻訳されない場合があります。
+
+具体例:ラベルのない検索フィールド
+
+✓ 良い例: `aria-labelledby`属性を使用する
+
+```html
+
+```
+
+コントロールに`aria-labelledby`属性を付与し、コントロールの名前を含む要素(不可視でも構わない)の`id`を指定する。
+
+✓ 良い例: `aria-label`属性を使用する
+
+```html
+
+```
+
+`aria-label`属性を使用し、コントロールに名前を直接指定する。
+
+詳細: [ラベルのないコントロール](https://lifull.github.io/accessibility-guidelines/impl/labelless-control)
+
+### コピー&ペーストの許容 (レベル2)
+
+**チェック項目:** コピー&ペーストを禁止しない
+
+特定の認知障害を持つユーザーは、ユーザー名とパスワードの記憶に苦労することがあるため、コピー&ペーストが禁止されているログインフォームなどが利用できないことがあります。
+
+詳細: [コピー&ペーストの許容](https://lifull.github.io/accessibility-guidelines/impl/allow-copy-paste)
+
+### フォームコントロールのグループ化 (レベル2)
+
+**チェック項目:** フォームコントロールをグルーピングするためにfieldset要素を使用する
+
+意味的にまとまりのある複数のフォームコントロールがある場合、それらをグループとしてマークアップしてください。スクリーンリーダーで当該フォームコントロールを操作するとき、所属するグループの名前も同時に読み上げられるようになり、文脈への理解が進みます。
+
+具体例:性別の回答欄
+
+✓ 良い例: `fieldset`要素で選択肢を囲う。
+
+```html
+
+```
+
+詳細: [フォームコントロールのグループ化](https://lifull.github.io/accessibility-guidelines/impl/grouped-form-control)
+
+### 入力目的の特定 (レベル2)
+
+**チェック項目:** type属性とautocomplete属性を指定する
+
+**チェック項目:** 数字キーボードを表示するためにinputmode属性を使用する
+
+`input`要素の`type`属性や`autocomplete`属性を使用して入力フィールドの目的を特定しておくと、目的に応じたソフトウェアキーボードが表示されたり、ブラウザーに保存された値の補完機能を利用できるようになったりします。
+
+補完機能を提供することで、入力時にかかる認知負荷を下げることができます。ログイン画面の入力項目のような記憶を要する場所に設定することは特に重要です。
+
+具体例①:クレジットカード番号の入力欄
+
+✗ 悪い例: 数字キーボードを表示するために`type="number"`を用いる
+
+```html
+
+```
+
+数字キーボードを表示する目的のために`type="number"`や`type="tel"`を用いるのは誤り。
+
+✓ 良い例: 補完種別を指定するために`autocomplete`属性を用いる。
+
+```html
+
+```
+
+✓ 良い例: 入力方式を指定するために`inputmode`を用いる。
+
+```html
+
+```
+
+詳細: [入力目的の特定](https://lifull.github.io/accessibility-guidelines/impl/identify-input-purpose)
+
+### フォームコントロールの説明文 (レベル3)
+
+**チェック項目:** aria-describedby属性をつかってフォームコントロールに説明文を指定する
+
+フォームコントロールと説明文をプログラムが解釈できるように紐づけると、スクリーンリーダー利用者は、フォーカスをフォームコントロールから移動することなく説明の内容を取得できるようになります。
+
+具体例①:フォームコントロールの説明文
+
+✓ 良い例: `aria-describedby`属性をつかってコントロールと説明文を紐づける
+
+```
+
+具体例②:フォームコントロールのエラー
+
+✓ 良い例: `aria-describedby`属性をつかってコントロールとエラーメッセージを紐づける
+
+```
+
+
+ 複数の`id`値をスペース区切りで指定することで、複数の要素にまたがる説明文およびエラーメッセージをコントロールに紐づけられる。
+
+詳細: [フォームコントロールの説明文](https://lifull.github.io/accessibility-guidelines/impl/form-control-description)
+
+### ズームの許容 (レベル1)
+
+**チェック項目:** viewportメタデータにuser-scalable=noやmaximum-scaleを指定しない
+
+ロービジョンのユーザーを含む一部のユーザーにとっては、画面を任意の大きさにズームして表示できることは極めて重要です。そのような人にとって、ウェブサイトがズームを禁止しているとウェブサイトを利用できなくなることがあります。ズームされると大多数のユーザーに致命的な問題が起きない限り、ズームを許容してください。
+
+##### ヒント:入力フィールドにフォーカスしたときに画面がズームしないようにする
+
+iOS Safariにおいて、ユーザーが入力フィールドにフォーカスすると画面が自動的にズームすることがあります。入力フィールドの文字サイズを16px以上にすることでこの挙動を抑止できます。
+
+詳細: [ズームの許容](https://lifull.github.io/accessibility-guidelines/impl/allow-zoom)
+
+### フォーカスインジケーター (レベル1)
+
+**チェック項目:** フォーカスインジケーターを非表示にしない
+
+**チェック項目:** フォーカスインジケーターを抑制するためにHTMLElement.blur()を用いない
+
+**チェック項目:** フォーカスを受け取ったUIが他の要素によって完全に隠されてはいけない
+
+フォーカスインジケーターが不可視にされていると、キーボードユーザーはフォーカスの現在位置がわからず、操作を続けることができなくなってしまいます。
+
+また、フォーカスインジケーターを取り除くために`HTMLElement.blur()`を使用すると、フォーカス位置が失われ、キーボード操作を再度先頭からやり直さなければいけなくなってしまうかもしれません。
+
+##### ヒント:キーボード操作時だけフォーカスのスタイルを適用する
+
+`:focus`疑似クラスを使用すると、マウスやタッチ操作で選択したときにもスタイルが適用されます。キーボード操作時のみスタイルを適用したい場合、かわりに`:focus-visible`疑似クラスを使用します。
+
+##### ヒント:フォーカスを受け取ったUIが追従コンテンツによって隠されないようにする
+
+ページをTabキーで下に移動すると、フォーカスの当たった要素が表示領域に収まるようにスクロールを伴いますが、追従ヘッダ等がある場合、それによってフォーカスされたUIが隠れてしまうケースがあります。このような場合、`scroll-padding`プロパティを設定することで要素の重なりを回避することができます。
+
+##### ヒント:Cookieの利用同意を求めるモーダルダイアログにフォーカスを移動する
+
+Cookie利用同意のポップアップはしばしばダイアログとして実装され、ページの読み込み後すぐに表示されます。 このダイアログを背面と対話可能なモードレスダイアログとして実装すると、背面のUIがダイアログに完全に隠され、操作が困難になる可能性があります。この問題を回避するため、ダイアログはモーダルとして実装し、閉じるまでフォーカスが外側のコンテンツに移動しないようにすることが推奨されます。
+
+詳細: [フォーカスインジケーター](https://lifull.github.io/accessibility-guidelines/impl/focus-indicator)
+
+### 挿入されるコンテンツ (レベル1)
+
+**チェック項目:** 動的に追加・表示されるコンテンツのDOMノードをトリガーの直後に配置する
+
+サブメニューやモーダルダイアログ、ディスクロージャー、「もっと見る」による追加読み込みなど、コンテンツが動的に追加・表示されるUIについて、そのコンテンツのDOMノードは操作の起点(トリガー)の直後になるようにしてください。トリガーの直後にコンテンツが挿入されることで、キーボードやスクリーンリーダーを使用したときに、トリガーの操作後に自然な流れで操作や読み上げを続けることができます。
+
+JavaScriptによってフォーカス位置を制御できる場合、このガイドラインは必須ではありません。
+
+詳細: [挿入されるコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/inserted-content)
+
+### ボタンの使用 (レベル1)
+
+**チェック項目:** トリガーとなるコンポーネントをbutton要素でマークアップする
+
+ユーザーのクリックやタップを起点にしてインタラクションが発生する場合、他に適切な要素がなければ、トリガーの要素には`button`要素を使用してください。
+
+`button`要素はデフォルトでキーボードフォーカスを受け取り、スペースバーを含むキーボード操作によってクリックイベントを発生させることができます。`a`要素や`span`要素にJavaScriptでこれらの挙動を模倣して作るのは実装面・テスト面で大きなコストになりえます。
+
+##### ヒント:ボタンが持つデフォルトスタイルをリセットする
+
+```css
+button {
+ margin: 0;
+ padding: 0;
+ color: inherit;
+ background: none;
+ font-size: 100%;
+ line-height: inherit;
+ font-family: inherit;
+ font-weight: inherit;
+ text-transform: none;
+}
+```
+
+詳細: [ボタンの使用](https://lifull.github.io/accessibility-guidelines/impl/use-button)
+
+### ホバーで表示されるコンテンツ (レベル2)
+
+**チェック項目:** ホバーやフォーカスで表示されるコンテンツは明示的に閉じられるまで表示し続ける
+
+ホバーやフォーカスがコンテンツ表示のトリガーとなっている場合、ユーザーによって明示的に閉じられるまでそのコンテンツを表示し続けてください。トリガーからポインターやフォーカスが外れた時点でコンテンツを非表示にしたり、時限式に閉じることは避けてください。
+
+明示的に閉じる操作とは例えば次のような操作です。
+
+- Escapeキーが押される
+- 表示されたコンテンツの中の閉じるボタンが選択される
+- トリガーとコンテンツの両方からポインターが外れ、0.5秒以上が経過する
+- トリガーとコンテンツとは無関係の場所がクリックされる
+
+詳細: [ホバーで表示されるコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/content-on-hover)
+
+### 文脈に応じたフォーカス (レベル2)
+
+**チェック項目:** モーダルコンテンツを開いたとき、開かれたコンテンツにフォーカスを移動する
+
+**チェック項目:** モーダルコンテンツを閉じたとき、開くために使用したボタンにフォーカスを戻す
+
+**チェック項目:** コンテンツを追加で読み込む操作をしたとき、読み込まれたコンテンツにフォーカスを移動する
+
+**チェック項目:** ページ内リンクを模したスクロール操作をしたとき、スクロール先にフォーカスを移動する
+
+キーボードやスクリーンリーダーなどのシーケンシャルな操作体系の環境でスムーズに操作を行えるように、ユーザーの操作に応じた適切な位置にフォーカスを移動してください。
+
+詳細: [文脈に応じたフォーカス](https://lifull.github.io/accessibility-guidelines/impl/contextual-focus)
+
+### Escapeキー操作 (レベル2)
+
+**チェック項目:** Escapeキーでポップアップメニューやダイアログ、ツールチップを閉じられるようにする
+
+Escapeキーは「現在のコンテキストから抜ける」ための慣習的に用いられているキー操作です。ポップアップメニューやダイアログ、ツールチップなど、一時的に、ほかのコンテンツより前面に表示されるコンテンツをEscapeキーで閉じられるようにしてください。
+
+詳細: [Escapeキー操作](https://lifull.github.io/accessibility-guidelines/impl/escape-key)
+
+### 外部コンテンツおよびUIライブラリ (レベル2)
+
+**チェック項目:** iframeで埋め込まれる外部コンテンツがアクセシブルなことを確認する
+
+**チェック項目:** アクセシビリティに配慮された外部UIライブラリを採用する
+
+アクセシビリティはページ全体として評価されるため、採用している外部のUIライブラリや、iframeとして埋め込んでいる外部コンテンツもアクセシビリティに配慮したつくりになっている必要があります。
+
+詳細: [外部コンテンツおよびUIライブラリ](https://lifull.github.io/accessibility-guidelines/impl/external-content-and-library)
+
+### 隠されているコンテンツ (レベル2)
+
+**チェック項目:** 非表示コンテンツにdisplay: noneやvisibility: hiddenも併用する
+
+**チェック項目:** display: noneやvisibility: hiddenが指定できない場合、非表示コンテンツにaria-hidden="true"を指定し、非表示コンテンツが含むインタラクティブ要素にtabindex="-1"を指定する
+
+DOMツリー上には存在するものの非表示にされているコンテンツは、意図的にそうしていない限り、キーボードや支援技術からもアクセスできないようにしてください。
+
+キーボードや支援技術からもアクセスできてしまう非表示コンテンツとは、例えば次ような方法で非表示にしたコンテンツです。
+
+- `opacity`を`0`にする
+- `overflow: hidden`と`width`や`height`、`clip`を使ってコンテンツの一部分または全部を切り取る
+- `position`や`transform`などを使って画面外ないし親要素の範囲外に追いやる
+
+詳細: [隠されているコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/hidden-content)
+
+### WAI-ARIA (レベル2)
+
+**チェック項目:** [APG](https://www.w3.org/WAI/ARIA/apg/)を参考に適切な役割、ステート、プロパティの値を設定する
+
+**チェック項目:** APGを参考に適切なキーボードインタラクションを実装する
+
+インタラクションを含むUIはHTMLのセマンティクスに加えてWAI-ARIAを実装することでアクセシビリティを高められることがあります。
+
+WAI-ARIAに定義された役割やステート、プロパティは、想定されていない使われ方をすると逆にアクセシビリティを損なうことがあります。使い方について不明瞭な箇所があれば、社内のエキスパートに相談してください。
+
+詳細: [WAI-ARIA](https://lifull.github.io/accessibility-guidelines/impl/wai-aria)
+
+### 背後のコンテンツ (レベル3)
+
+**チェック項目:** 背後に隠されたコンテンツにキーボードフォーカスを移せないようにする
+
+**チェック項目:** 背後に隠されたコンテンツを支援技術からも隠す
+
+ダイアログなどのモーダルコンテンツが表示されているとき、背後に隠されたコンテンツはキーボードや支援技術からアクセスされないようにしてください。
+
+詳細: [背後のコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/backside-content)
+
+### ダウンイベントの使用 (レベル3)
+
+**チェック項目:** mousedown, pointerdown, touchstartを機能実行のトリガーにしない
+
+ダウンイベント(`mousedown`, `pointerdown`, `touchstart`)を機能実行のトリガーにしていると、細かい動作が苦手なユーザーは意図せず機能を実行してしまうことがあります。かわりにアップイベント(`mouseup`, `pointerup`, `touchend`)や、`click`, `input`, `change`のような、より意図に近いイベントを用いるようにしてください。
+
+詳細: [ダウンイベントの使用](https://lifull.github.io/accessibility-guidelines/impl/down-event)
+
+### ドラッグ操作の中断 (レベル3)
+
+**チェック項目:** ドラッグ操作を中止できるようにする
+
+UIがドラッグアンドドロップ操作を求めるとき、ドラッグの途中で操作を中止する手段を設けてください。中止する手段の例としては次のようなものがあります。
+
+- ドロップエリアは画面の中の一部分であり、それ以外の箇所にドロップしても何も起こらない
+- ドロップ操作をした後、簡単な操作で元に戻すことができる
+- ドラッグ中にEscapeキーを押すとドラッグ操作を中止できる
+
+詳細: [ドラッグ操作の中断](https://lifull.github.io/accessibility-guidelines/impl/drag-operation-interruption)
+
+### ステータスの通知 (レベル3)
+
+**チェック項目:** ARIAライブリージョンを適切に使用し、状態変化や通知メッセージを支援技術に伝える
+
+**チェック項目:** スクリーンリーダーを使用して動作検証を行う
+
+アプリケーションの状態変化や通知メッセージをUIに表示する場合、スクリーンリーダー等の支援技術にも同様の情報を伝える必要があります。WAI-ARIAのライブリージョンを使うことで実現可能です。
+
+詳細: [ステータスの通知](https://lifull.github.io/accessibility-guidelines/impl/status-announcement)
+
diff --git a/llms.txt b/llms.txt
new file mode 100644
index 0000000..2394b64
--- /dev/null
+++ b/llms.txt
@@ -0,0 +1,103 @@
+# LIFULL Accessibility Guidelines
+
+> アクセシビリティに配慮したデザインと実装のためのガイドライン
+
+This file contains accessibility guidelines for designers and developers.
+
+## metadata
+- url: https://lifull.github.io/accessibility-guidelines/
+- version: v3.0
+## ガイドラインについて
+
+- [はじめに](https://lifull.github.io/accessibility-guidelines/introduction.html)
+- [利用方法](https://lifull.github.io/accessibility-guidelines/usage.html)
+
+## デザインのガイドライン
+
+### コンテンツ
+
+- [自動再生するコンテンツ](https://lifull.github.io/accessibility-guidelines/design/autostart-content) (レベル1: 必ず達成)
+- [閃光](https://lifull.github.io/accessibility-guidelines/design/flash) (レベル1: 必ず達成)
+- [見出し](https://lifull.github.io/accessibility-guidelines/design/heading) (レベル1: 必ず達成)
+- [画像の代替テキスト](https://lifull.github.io/accessibility-guidelines/design/image-alternative) (レベル1: 必ず達成)
+- [ページタイトル](https://lifull.github.io/accessibility-guidelines/design/page-title) (レベル1: 必ず達成)
+- [動画の字幕](https://lifull.github.io/accessibility-guidelines/design/video-caption) (レベル1: 必ず達成)
+- [音声のみのコンテンツ](https://lifull.github.io/accessibility-guidelines/design/audio-only) (レベル2: 可能な限り達成)
+- [グラフや図](https://lifull.github.io/accessibility-guidelines/design/chart-and-diagram) (レベル2: 可能な限り達成)
+- [データ可視化](https://lifull.github.io/accessibility-guidelines/design/data-visualization) (レベル2: 可能な限り達成)
+- [テキスト画像](https://lifull.github.io/accessibility-guidelines/design/image-of-text) (レベル2: 可能な限り達成)
+- [表](https://lifull.github.io/accessibility-guidelines/design/table) (レベル2: 可能な限り達成)
+- [動画コンテンツ(音声を含む)](https://lifull.github.io/accessibility-guidelines/design/video-and-audio) (レベル2: 可能な限り達成)
+- [リンクテキスト](https://lifull.github.io/accessibility-guidelines/design/link-text) (レベル3: できれば考慮)
+- [コンテンツの順序](https://lifull.github.io/accessibility-guidelines/design/order-of-content) (レベル3: できれば考慮)
+- [目次とサイトマップ](https://lifull.github.io/accessibility-guidelines/design/sitemap) (レベル3: できれば考慮)
+
+### フォーム・インタラクション
+
+- [カスタムUIのキーボード操作](https://lifull.github.io/accessibility-guidelines/design/keyboard) (レベル1: 必ず達成)
+- [定番のパターン](https://lifull.github.io/accessibility-guidelines/design/established-pattern) (レベル1: 必ず達成)
+- [キーボード操作](https://lifull.github.io/accessibility-guidelines/design/keyboard) (レベル1: 必ず達成)
+- [ホバーで表示されるコンテンツ](https://lifull.github.io/accessibility-guidelines/design/content-on-hover) (レベル2: 可能な限り達成)
+- [エラーメッセージ](https://lifull.github.io/accessibility-guidelines/design/error-message) (レベル2: 可能な限り達成)
+- [エラーメッセージの提示](https://lifull.github.io/accessibility-guidelines/design/error-presentation) (レベル2: 可能な限り達成)
+- [フォームコントロールのラベル](https://lifull.github.io/accessibility-guidelines/design/form-control-label) (レベル2: 可能な限り達成)
+- [シンプルなポインター操作](https://lifull.github.io/accessibility-guidelines/design/simple-pointer) (レベル2: 可能な限り達成)
+- [デバイスの向き](https://lifull.github.io/accessibility-guidelines/design/device-orientation) (レベル3: できれば考慮)
+- [新しいタブで開くリンク](https://lifull.github.io/accessibility-guidelines/design/link-opens-in-new-tab) (レベル3: できれば考慮)
+- [予測可能なパターン](https://lifull.github.io/accessibility-guidelines/design/predictable-pattern) (レベル3: できれば考慮)
+- [時間制限](https://lifull.github.io/accessibility-guidelines/design/time-limit) (レベル3: できれば考慮)
+- [ユーザー認証](https://lifull.github.io/accessibility-guidelines/design/user-authentication) (レベル3: できれば考慮)
+
+### ビジュアル
+
+- [フォーカスインジケーター](https://lifull.github.io/accessibility-guidelines/design/focus-indicator) (レベル1: 必ず達成)
+- [リンクの判別](https://lifull.github.io/accessibility-guidelines/design/link-identification) (レベル1: 必ず達成)
+- [状態の判別](https://lifull.github.io/accessibility-guidelines/design/state-identification) (レベル1: 必ず達成)
+- [レスポンシブデザイン](https://lifull.github.io/accessibility-guidelines/design/responsive-design) (レベル2: 可能な限り達成)
+- [ターゲットサイズ](https://lifull.github.io/accessibility-guidelines/design/target-size) (レベル2: 可能な限り達成)
+- [テキストの色コントラスト](https://lifull.github.io/accessibility-guidelines/design/text-contrast) (レベル2: 可能な限り達成)
+- [テキストの均等割付](https://lifull.github.io/accessibility-guidelines/design/text-justify) (レベル2: 可能な限り達成)
+- [アイコンやUIコンポーネントの色コントラスト](https://lifull.github.io/accessibility-guidelines/design/ui-contrast) (レベル2: 可能な限り達成)
+
+## 実装のガイドライン
+
+### マークアップ
+
+- [背景画像](https://lifull.github.io/accessibility-guidelines/impl/background-image) (レベル1: 必ず達成)
+- [見出し](https://lifull.github.io/accessibility-guidelines/impl/heading) (レベル1: 必ず達成)
+- [画像の代替テキスト](https://lifull.github.io/accessibility-guidelines/impl/image-alternative) (レベル1: 必ず達成)
+- [ページの言語](https://lifull.github.io/accessibility-guidelines/impl/language-of-page) (レベル1: 必ず達成)
+- [ページタイトル](https://lifull.github.io/accessibility-guidelines/impl/page-title) (レベル1: 必ず達成)
+- [調整可能な文字サイズ](https://lifull.github.io/accessibility-guidelines/impl/adjustable-text-size) (レベル2: 可能な限り達成)
+- [グループ化された画像](https://lifull.github.io/accessibility-guidelines/impl/grouped-images) (レベル2: 可能な限り達成)
+- [ランドマーク領域](https://lifull.github.io/accessibility-guidelines/impl/landmark-region) (レベル2: 可能な限り達成)
+- [意味のある順序](https://lifull.github.io/accessibility-guidelines/impl/meaningful-sequence) (レベル2: 可能な限り達成)
+- [改行と空白文字](https://lifull.github.io/accessibility-guidelines/impl/whitespace-character) (レベル2: 可能な限り達成)
+- [正しい構文と文法](https://lifull.github.io/accessibility-guidelines/impl/syntax-and-grammar) (レベル3: できれば考慮)
+
+### フォーム
+
+- [フォームコントロールのラベル](https://lifull.github.io/accessibility-guidelines/impl/label-for-control) (レベル1: 必ず達成)
+- [ラベルのないコントロール](https://lifull.github.io/accessibility-guidelines/impl/labelless-control) (レベル1: 必ず達成)
+- [コピー&ペーストの許容](https://lifull.github.io/accessibility-guidelines/impl/allow-copy-paste) (レベル2: 可能な限り達成)
+- [フォームコントロールのグループ化](https://lifull.github.io/accessibility-guidelines/impl/grouped-form-control) (レベル2: 可能な限り達成)
+- [入力目的の特定](https://lifull.github.io/accessibility-guidelines/impl/identify-input-purpose) (レベル2: 可能な限り達成)
+- [フォームコントロールの説明文](https://lifull.github.io/accessibility-guidelines/impl/form-control-description) (レベル3: できれば考慮)
+
+### インタラクション
+
+- [ズームの許容](https://lifull.github.io/accessibility-guidelines/impl/allow-zoom) (レベル1: 必ず達成)
+- [フォーカスインジケーター](https://lifull.github.io/accessibility-guidelines/impl/focus-indicator) (レベル1: 必ず達成)
+- [挿入されるコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/inserted-content) (レベル1: 必ず達成)
+- [ボタンの使用](https://lifull.github.io/accessibility-guidelines/impl/use-button) (レベル1: 必ず達成)
+- [ホバーで表示されるコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/content-on-hover) (レベル2: 可能な限り達成)
+- [文脈に応じたフォーカス](https://lifull.github.io/accessibility-guidelines/impl/contextual-focus) (レベル2: 可能な限り達成)
+- [Escapeキー操作](https://lifull.github.io/accessibility-guidelines/impl/escape-key) (レベル2: 可能な限り達成)
+- [外部コンテンツおよびUIライブラリ](https://lifull.github.io/accessibility-guidelines/impl/external-content-and-library) (レベル2: 可能な限り達成)
+- [隠されているコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/hidden-content) (レベル2: 可能な限り達成)
+- [WAI-ARIA](https://lifull.github.io/accessibility-guidelines/impl/wai-aria) (レベル2: 可能な限り達成)
+- [背後のコンテンツ](https://lifull.github.io/accessibility-guidelines/impl/backside-content) (レベル3: できれば考慮)
+- [ダウンイベントの使用](https://lifull.github.io/accessibility-guidelines/impl/down-event) (レベル3: できれば考慮)
+- [ドラッグ操作の中断](https://lifull.github.io/accessibility-guidelines/impl/drag-operation-interruption) (レベル3: できれば考慮)
+- [ステータスの通知](https://lifull.github.io/accessibility-guidelines/impl/status-announcement) (レベル3: できれば考慮)
+
diff --git a/package-lock.json b/package-lock.json
index 5d2c757..907bb12 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "accessibility-guidelines",
+ "name": "lifull-accessibility-guidelines",
"version": "1.0.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "version": "1.0.1",
+ "name": "lifull-accessibility-guidelines",
"dependencies": {
"@astrojs/markdown-remark": "^2.1.3",
"@astrojs/mdx": "^0.18.3",
@@ -2253,6 +2253,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
"integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
+ "license": "MIT",
"dependencies": {
"js-yaml": "^3.13.1",
"kind-of": "^6.0.2",
diff --git a/package.json b/package.json
index 89f1c61..3972c57 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,8 @@
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
- "preview": "astro preview"
+ "preview": "astro preview",
+ "generate-llms": "node ./scripts/generate-llms-txt.js"
},
"dependencies": {
"@astrojs/markdown-remark": "^2.1.3",
diff --git a/scripts/README.md b/scripts/README.md
new file mode 100644
index 0000000..6f237da
--- /dev/null
+++ b/scripts/README.md
@@ -0,0 +1,148 @@
+# llms.txt Generator
+
+このディレクトリには、LIFULL Accessibility Guidelines用のllms.txtファイルを生成するためのスクリプトが含まれています。
+
+## 概要
+
+llms.txtジェネレーターは、MDXファイルからアクセシビリティガイドラインの内容を抽出し、AI言語モデルが利用しやすい形式のファイルを生成します。
+
+## ファイル構成
+
+```text
+scripts/
+├── generate-llms-txt.js # メインスクリプト(エントリーポイント)
+├── llms-generator.js # メインジェネレータークラス
+├── config.js # 設定ファイル
+├── logger.js # ログ機能
+├── parsers/ # パーサーモジュール
+│ ├── file-parser.js # ファイル操作ユーティリティ
+│ ├── mdx-parser.js # MDXファイルパーサー
+│ ├── component-parser.js # Astroコンポーネントパーサー
+│ ├── code-block-parser.js # コードブロックパーサー
+│ └── url-generator.js # URL生成ユーティリティ
+└── generators/ # コンテンツ生成モジュール
+ └── content-generator.js # llms.txtコンテンツ生成
+```
+
+## 使用方法
+
+### 基本的な使用方法
+
+```bash
+# package.jsonで定義されたスクリプトを使用
+npm run generate-llms
+
+# または直接実行
+node scripts/generate-llms-txt.js
+```
+
+### プログラムからの使用
+
+```javascript
+const LlmsGenerator = require('./scripts/llms-generator');
+
+// 基本的な使用
+const generator = new LlmsGenerator();
+await generator.generate();
+
+// オプションを指定
+const generator = new LlmsGenerator({
+ verbose: true, // 詳細なログを表示
+ silent: false // 静寂モード
+});
+await generator.generate();
+```
+
+## 生成されるファイル
+
+- `llms.txt` - 簡易版(ガイドライン一覧とリンクのみ)
+- `llms-full.txt` - 完全版(全コンテンツを含む)
+
+## 設定
+
+設定は `config.js` で管理されています:
+
+```javascript
+module.exports = {
+ // ファイルパス
+ paths: {
+ guidelines: '../src/content/guidelines',
+ pages: '../src/pages',
+ output: '../llms.txt',
+ outputFull: '../llms-full.txt'
+ },
+
+ // サイトメタデータ
+ metadata: {
+ title: 'LIFULL Accessibility Guidelines',
+ version: 'v3.0'
+ },
+
+ // その他の設定...
+};
+```
+
+## 機能
+
+### パーサー機能
+
+- **MDXファイル解析**: フロントマターとコンテンツの分離
+- **Astroコンポーネント処理**: Checkpoint、Cases、Case、Levelコンポーネントの解析
+- **コードブロック抽出**: HTMLコード例の正確な抽出
+- **日本語URL対応**: アンカーIDの生成で日本語文字をサポート
+
+### コンテンツ生成
+
+- **階層構造**: エリア(デザイン/実装)とカテゴリーによる整理
+- **目次生成**: 完全版では自動的に目次を生成
+- **レベル表示**: ガイドラインの重要度レベルを表示
+- **URLリンク**: 各ガイドラインへの直接リンク
+
+### エラーハンドリング
+
+- **詳細なログ**: verbose モードで詳細な処理状況を表示
+- **例外処理**: ファイル読み込みやパース処理のエラーを適切に処理
+- **依存関係チェック**: 必要なnpmパッケージの自動インストール
+
+## 開発・メンテナンス
+
+### 新しいコンポーネントの追加
+
+新しいAstroコンポーネントを処理に追加する場合:
+
+1. `parsers/component-parser.js` に解析ロジックを追加
+2. `config.js` に必要な設定を追加
+3. テストを実行して動作確認
+
+### 設定の変更
+
+設定変更は `config.js` を編集してください。変更後は以下をテスト:
+
+```bash
+npm run generate-llms
+```
+
+### デバッグ
+
+詳細なログを確認したい場合:
+
+```javascript
+const generator = new LlmsGenerator({ verbose: true });
+await generator.generate();
+```
+
+## トラブルシューティング
+
+### よくある問題
+
+1. **依存関係エラー**: `npm install` を実行
+2. **パスエラー**: `config.js` のパス設定を確認
+3. **MDXパースエラー**: ファイルの構文を確認
+
+### ログレベル
+
+- **info**: 一般的な進行状況
+- **verbose**: 詳細な処理状況(verbose モード時のみ)
+- **warn**: 警告メッセージ
+- **error**: エラーメッセージ
+- **success**: 成功メッセージ
diff --git a/scripts/config.js b/scripts/config.js
new file mode 100644
index 0000000..b299081
--- /dev/null
+++ b/scripts/config.js
@@ -0,0 +1,76 @@
+/**
+ * Configuration for llms.txt generation
+ */
+
+module.exports = {
+ // File paths
+ paths: {
+ guidelines: '../src/content/guidelines',
+ pages: '../src/pages',
+ output: '../llms.txt',
+ outputFull: '../llms-full.txt'
+ },
+
+ // Base URL for the site
+ baseUrl: 'https://lifull.github.io/accessibility-guidelines',
+
+ // Site metadata
+ metadata: {
+ title: 'LIFULL Accessibility Guidelines',
+ description: 'アクセシビリティに配慮したデザインと実装のためのガイドライン',
+ englishDescription: 'This file contains accessibility guidelines for designers and developers.',
+ version: 'v3.0'
+ },
+
+ // Pages to include in different versions
+ pages: {
+ full: ['introduction.mdx', 'usage.mdx', 'alternative-text.mdx', 'accessible-patterns.mdx'],
+ simplified: ['introduction.mdx', 'usage.mdx']
+ },
+
+ // Category name mappings
+ categoryNames: {
+ contents: 'コンテンツ',
+ 'forms-and-interactions': 'フォーム・インタラクション',
+ visual: 'ビジュアル',
+ markup: 'マークアップ',
+ forms: 'フォーム',
+ interactions: 'インタラクション'
+ },
+
+ // Area name mappings
+ areaNames: {
+ design: 'デザイン',
+ impl: '実装'
+ },
+
+ // Level descriptions
+ levelDescriptions: {
+ 1: '必ず達成',
+ 2: '可能な限り達成',
+ 3: 'できれば考慮'
+ },
+
+ // Type labels for examples
+ typeLabels: {
+ good: '✓ 良い例',
+ bad: '✗ 悪い例'
+ },
+
+ // Regular expressions for content cleaning
+ regex: {
+ imports: /import[\s\S]*?from\s+["'].*?["'];?\s*/g,
+ jsxComments: /\{\/\*[\s\S]*?\*\/\}/g,
+ backticks: /`([^`]+)`/g,
+ frontmatterTitle: /#### 「\{frontmatter\.title\}」とは/g,
+ checkpointHeader: /#### チェック項目/g,
+ referenceSection: /##### 参考情報[\s\S]*$/g,
+ multipleNewlines: /\n\s*\n\s*\n/g,
+ htmlTags: /<[^>]*>/g,
+ markdownHeaders: /#{1,6}\s*/,
+ japaneseChars: /[^\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF\w\s]/g,
+ spaces: /\s+/g,
+ dashes: /-+/g,
+ leadingTrailingDashes: /^-+|-+$/g
+ }
+};
\ No newline at end of file
diff --git a/scripts/generate-llms-txt.js b/scripts/generate-llms-txt.js
new file mode 100755
index 0000000..e23297a
--- /dev/null
+++ b/scripts/generate-llms-txt.js
@@ -0,0 +1,30 @@
+#!/usr/bin/env node
+
+/**
+ * LIFULL Accessibility Guidelines - llms.txt Generator
+ *
+ * This script generates llms.txt files by parsing MDX files in the accessibility guidelines.
+ * It follows the format described at https://github.com/AnswerDotAI/llms-txt
+ *
+ * The script has been refactored into modular components for better maintainability:
+ * - config.js: Configuration and constants
+ * - parsers/: File parsing utilities
+ * - generators/: Content generation utilities
+ * - llms-generator.js: Main generator class
+ */
+
+const LlmsGenerator = require('./llms-generator');
+
+// Main execution
+if (require.main === module) {
+ LlmsGenerator.run()
+ .then(() => {
+ process.exit(0);
+ })
+ .catch(error => {
+ console.error('Error generating llms files:', error.message);
+ process.exit(1);
+ });
+}
+
+module.exports = LlmsGenerator;
\ No newline at end of file
diff --git a/scripts/generators/content-generator.js b/scripts/generators/content-generator.js
new file mode 100644
index 0000000..48554a7
--- /dev/null
+++ b/scripts/generators/content-generator.js
@@ -0,0 +1,249 @@
+/**
+ * Content generation utilities for llms.txt files
+ */
+
+const config = require('../config');
+const UrlGenerator = require('../parsers/url-generator');
+
+class ContentGenerator {
+ /**
+ * Generate the header section for llms.txt files
+ * @returns {string} Header content
+ */
+ static generateHeader() {
+ const { title, description, englishDescription, version } = config.metadata;
+
+ return [
+ `# ${title}`,
+ '',
+ `> ${description}`,
+ '',
+ englishDescription,
+ '',
+ '## metadata',
+ `- url: ${config.baseUrl}/`,
+ `- version: ${version}`,
+ ''
+ ].join('\n');
+ }
+
+ /**
+ * Generate table of contents for full version
+ * @param {Array} pages - Array of page data
+ * @param {Object} guidelines - Guidelines grouped by area and category
+ * @returns {string} Table of contents
+ */
+ static generateTableOfContents(pages, guidelines) {
+ let toc = '## 目次\n\n';
+
+ // Add pages to TOC
+ if (pages.length > 0) {
+ toc += '- [ガイドラインについて](#ガイドラインについて)\n';
+ pages.forEach(page => {
+ const anchorId = UrlGenerator.generateAnchorId(page.title);
+ toc += ` - [${page.title}](#${anchorId})\n`;
+ });
+ }
+
+ // Add guidelines to TOC
+ for (const area in guidelines) {
+ const areaName = UrlGenerator.getAreaName(area);
+ toc += `- [${areaName}のガイドライン](#${areaName.replace(/\s/g, '')}のガイドライン)\n`;
+
+ for (const category in guidelines[area]) {
+ this._sortGuidelinesByLevel(guidelines[area][category]);
+
+ guidelines[area][category].forEach(guideline => {
+ const anchorId = UrlGenerator.generateAnchorId(guideline.title, guideline.level);
+ toc += ` - [${guideline.title} (レベル${guideline.level})](#${anchorId})\n`;
+ });
+ }
+ }
+
+ return toc + '\n';
+ }
+
+ /**
+ * Generate pages section content
+ * @param {Array} pages - Array of page data
+ * @param {boolean} isFullVersion - Whether this is for the full version
+ * @returns {string} Pages content
+ */
+ static generatePagesContent(pages, isFullVersion = true) {
+ if (pages.length === 0) return '';
+
+ if (isFullVersion) {
+ return this._generateFullPagesContent(pages);
+ } else {
+ return this._generateSimplifiedPagesContent(pages);
+ }
+ }
+
+ /**
+ * Generate full pages content with details
+ * @private
+ * @param {Array} pages - Array of page data
+ * @returns {string} Full pages content
+ */
+ static _generateFullPagesContent(pages) {
+ let content = '## ガイドラインについて\n\n';
+
+ pages.forEach(page => {
+ const anchorId = UrlGenerator.generateAnchorId(page.title);
+ content += `### ${page.title}\n\n`;
+ content += `${page.content}\n\n`;
+ });
+
+ return content;
+ }
+
+ /**
+ * Generate simplified pages content with links only
+ * @private
+ * @param {Array} pages - Array of page data
+ * @returns {string} Simplified pages content
+ */
+ static _generateSimplifiedPagesContent(pages) {
+ let content = '## ガイドラインについて\n\n';
+
+ // Sort pages to ensure consistent order
+ const sortedPages = this._sortPages(pages);
+
+ sortedPages.forEach(page => {
+ const pageUrl = UrlGenerator.generatePageUrl(page.fileName);
+ content += `- [${page.title}](${pageUrl})\n`;
+ });
+
+ return content + '\n';
+ }
+
+ /**
+ * Generate guidelines section content
+ * @param {Object} guidelines - Guidelines grouped by area and category
+ * @param {boolean} isFullVersion - Whether this is for the full version
+ * @returns {string} Guidelines content
+ */
+ static generateGuidelinesContent(guidelines, isFullVersion = true) {
+ let content = '';
+
+ for (const area in guidelines) {
+ const areaName = UrlGenerator.getAreaName(area);
+ content += `## ${areaName}のガイドライン\n\n`;
+
+ if (isFullVersion) {
+ content += this._generateFullGuidelinesContent(area, guidelines[area]);
+ } else {
+ content += this._generateSimplifiedGuidelinesContent(area, guidelines[area]);
+ }
+ }
+
+ return content;
+ }
+
+ /**
+ * Generate full guidelines content with details
+ * @private
+ * @param {string} area - Area key
+ * @param {Object} categories - Categories within the area
+ * @returns {string} Full guidelines content
+ */
+ static _generateFullGuidelinesContent(area, categories) {
+ let content = '';
+
+ for (const category in categories) {
+ this._sortGuidelinesByLevel(categories[category]);
+
+ categories[category].forEach(guideline => {
+ const guidelineUrl = UrlGenerator.generateUrlPath(area, guideline.slug);
+ const anchorId = UrlGenerator.generateAnchorId(guideline.title, guideline.level);
+
+ content += `### ${guideline.title} (レベル${guideline.level})\n\n`;
+ content += `${guideline.content}\n\n`;
+ content += `詳細: [${guideline.title}](${guidelineUrl})\n\n`;
+ });
+ }
+
+ return content;
+ }
+
+ /**
+ * Generate simplified guidelines content with categories
+ * @private
+ * @param {string} area - Area key
+ * @param {Object} categories - Categories within the area
+ * @returns {string} Simplified guidelines content
+ */
+ static _generateSimplifiedGuidelinesContent(area, categories) {
+ let content = '';
+
+ for (const category in categories) {
+ const categoryName = UrlGenerator.getCategoryName(category);
+ content += `### ${categoryName}\n\n`;
+
+ this._sortGuidelinesByLevel(categories[category]);
+
+ categories[category].forEach(guideline => {
+ const guidelineUrl = UrlGenerator.generateUrlPath(area, guideline.slug);
+ const levelText = UrlGenerator.getLevelDescription(guideline.level);
+
+ content += `- [${guideline.title}](${guidelineUrl}) (レベル${guideline.level}: ${levelText})\n`;
+ });
+
+ content += '\n';
+ }
+
+ return content;
+ }
+
+ /**
+ * Sort guidelines by level
+ * @private
+ * @param {Array} guidelines - Array of guidelines
+ */
+ static _sortGuidelinesByLevel(guidelines) {
+ guidelines.sort((a, b) => a.level - b.level);
+ }
+
+ /**
+ * Sort pages for consistent ordering
+ * @private
+ * @param {Array} pages - Array of page data
+ * @returns {Array} Sorted pages
+ */
+ static _sortPages(pages) {
+ const order = { 'introduction.mdx': 0, 'usage.mdx': 1 };
+ return pages.sort((a, b) => {
+ return (order[a.fileName] || 999) - (order[b.fileName] || 999);
+ });
+ }
+
+ /**
+ * Group guidelines by area and category
+ * @param {Array} guidelineFiles - Array of parsed guideline files
+ * @returns {Object} Guidelines grouped by area and category
+ */
+ static groupGuidelines(guidelineFiles) {
+ const guidelines = {};
+
+ guidelineFiles.forEach(({ title, area, category, level, content, slug }) => {
+ if (!guidelines[area]) {
+ guidelines[area] = {};
+ }
+
+ if (!guidelines[area][category]) {
+ guidelines[area][category] = [];
+ }
+
+ guidelines[area][category].push({
+ title,
+ level,
+ content,
+ slug
+ });
+ });
+
+ return guidelines;
+ }
+}
+
+module.exports = ContentGenerator;
\ No newline at end of file
diff --git a/scripts/llms-generator.js b/scripts/llms-generator.js
new file mode 100644
index 0000000..ba899b5
--- /dev/null
+++ b/scripts/llms-generator.js
@@ -0,0 +1,190 @@
+/**
+ * Main llms.txt generator class
+ */
+
+const path = require('path');
+const config = require('./config');
+const MdxParser = require('./parsers/mdx-parser');
+const ContentGenerator = require('./generators/content-generator');
+const FileParser = require('./parsers/file-parser');
+const Logger = require('./logger');
+
+class LlmsGenerator {
+ constructor(options = {}) {
+ this.guidelinesPath = path.resolve(__dirname, config.paths.guidelines);
+ this.pagesPath = path.resolve(__dirname, config.paths.pages);
+ this.outputPath = path.resolve(__dirname, config.paths.output);
+ this.outputFullPath = path.resolve(__dirname, config.paths.outputFull);
+
+ // Initialize logger
+ this.logger = new Logger({
+ verbose: options.verbose || false,
+ silent: options.silent || false
+ });
+ }
+
+ /**
+ * Generate both llms.txt and llms-full.txt files
+ * @returns {Promise