出力スキーマ

これはrunDomRulesInPage(...) / runa11yCoreInPage(...)が返すオブジェクトの正確な形です(どちらを呼ぶべきかはINTEGRATION.mdを参照)。このページの例はすべて現在のエンジンの実際の出力(schemaVersion: "1.0.0")で、手書きしたものではありません。runa11yCoreAcrossFramesは、これを包む別の再帰的な形を返します。後述のフレームをまたぐ結果を参照してください。

トップレベルの結果

{
engine: {
tag: string,
version: string, // the @surea11y/core release that produced the result
schemaVersion: string,
locale: { requested: string, resolved: string, reason: string },
wcagVersion: "2.0" | "2.1" | "2.2",
wcagLevel?: "A" | "AA" | "AAA",
profile?: string, // "wcag22-aa", "en301549-v4.1.1", "en301549-v3.2.1", "section508", or a registered standard's own
mappings?: string[], // e.g. ["en301549"] or ["en301549:V3.2.1"]
profileExcludes?: { rules: string[], criteria: string[] },
optInRules?: string[],
outputDetail?: "findings",
packs?: string[], // name@version
environment: {
layout: boolean,
viewport?: { width: number, height: number }, // CSS px
devicePixelRatio?: number,
colorScheme?: "light" | "dark",
forcedColors?: "active" | "none",
forcedColorsCss?: true, // under forced colors, when the page's own CSS reacts to them
fonts?: "loaded" | "loading",
images?: "loaded" | "loading",
animationsSettled?: number,
internalsHook?: "early" | "late", // only where the page runs the internals hook
listenerHook?: "early" | "late", // only where the page runs the listener hook
liveRegionHook?: "early" | "late" // only where the page runs the live-region hook
}
},
url: string | null,
title: string | null,
timestamp: string | null,
perfStats: object | null,
contextSelector: string | string[] | null,
contextMatch: { elementCount: number, unmatchedSelectors: string[] } | null,
checksResults: CheckResult[],
rulesResults: CompositeResult[],
standards?: Array<{ key: string, standard: string, titleLang?: string, note?: string }>,
overriddenBuiltinIds: string[],
skippedCustomRules: Array<{ id: string | null, reason: string, excluded?: true }>,
skippedPacks?: Array<{ name: string | null, reason: string }>
}
フィールド意味
engine.tagエンジン自身の識別タグで、現在は"a11ycore"です。すべてのルール(組み込みもカスタムも)はmeta.tagsにこのタグを持ちます。ルールのruleId自体にはプレフィックスが付きません。
engine.version結果を生成した@surea11y/coreのリリースで、"1.11.1"のような値です。バグ報告で示すのはこの値で、2つのリリースの結果を見分けるのにも使えます。結果は形が変わらないままリリース間で変わることがあるため、これはschemaVersionとは別のものです。SARIFとEARLのレポーターは、ツールのバージョンが指定されていなければこの値を使います。
engine.schemaVersion結果スキーマのバージョン("1.0.0")です。このドキュメントで示す形に互換性のない変更が入れば上がるので、出力をプログラムで解析する場合はこの値に固定してください。安定・不安定なフィールドの一覧と、バージョンを上げる方針についてはAPI_STABILITY.mdを参照してください。
engine.localeスキャンで実際に使われた辞書です。requestedはトリム後のengineOptions.locale(何も渡さなかった場合や文字列以外を渡した場合は"en")、resolvedは実際に辞書が使われたロケール、reasonはその組み合わせになった理由です。ロケールのフォールバックはエラーにならず文字列単位で行われるため、ビルドに含まれていない言語を指定すると、エラーではなく英語のテキストになります。このフィールドを見れば、文字列を読まなくてもそれが分かります。1回のスキャンでは全体を通して1つの辞書を使うので、結果ごとに1回だけ報告されます。
engine.locale.reason"ok":指定した辞書が使われ、すべてのキーがそろっています。"primary-subtag":コードにサブタグが付いていて、それ専用の辞書がないため、ベース言語が使われました。"de-DE"は"de"に解決されます。"dictionary-not-loaded":プロジェクトとしてはその言語を提供していますが、このビルドには含まれておらず、辞書も渡されませんでした(ロケールの別ファイルなしでスタンドアロンのブラウザー用バンドルを使った場合)。"unknown-locale":プロジェクトにその言語の翻訳がそもそもありません。"partial-dictionary":辞書は使われましたが、英語にあるキーの一部が欠けているため、それらの文字列は英語にフォールバックしました。この値の集合は今後も増えうるものとして扱ってください。後のリリースで追加されることがあります。
engine.wcagVersionこのスキャンがどのバージョンのWCAGに照らしてチェックしたかを示します。engineOptions.wcagVersionの値、実行に適用されたパックのプロファイルのwcagVersion、導入バージョンタグから推定された値、またはデフォルトの"2.2"のいずれかです。SC 4.1.1(構文解析)については、それだけに対応するルールがfailにならない理由を示します。2.2ではこの達成基準が削除され、2.0と2.1の2023年の正誤表では常に満たされているものとして扱われるためです(後述のchecksResults[i].wcagVersionScopeを参照)。1回のスキャンでは全体を通して対象は1つなので、結果ごとに1回だけ報告されます。
engine.wcagLevel報告される達成基準を絞り込んだWCAGのレベルで、"A"、"AA"、"AAA"のいずれかです。指定されていて有効ならengineOptions.wcagLevel、そうでなければ選択が示すレベル(runOnly.wcag.level、またはプロファイルのタグも含め、選択のバージョン/レベルのタグが示す最も高いレベル)です。それより上のWCAGの集約はrulesResultsに含まれませんが、そのルールは実行されており、checksResultsに含まれます。選択がIDで指定した集約は、engineOptions.wcagLevelにかかわらず報告されます。全体のスキャンやルールだけを指定したスキャンのようにレベルがない場合は含まれず、その場合はすべてのレベルが報告されます。レポーターは、示す達成基準をこれで絞り込みます。チェックを指定するスキャンのレベルを示すを参照してください。
engine.profileengineOptions.profileがこの実行のルールを選んだ場合にだけ含まれ、プロファイル名を小文字で示します。プロファイルを要求しなかった場合はなく、要求しても適用されなかった場合(不明な名前、またはrunOnlyやengineOptionsのincludeが代わりにルールを選んだ場合)もありません。そのため、これがあることで、実行が本当にそのプロファイルを対象にしたことを確認できます。適合性プロファイルを参照してください。
engine.profileExcludes適用されたプロファイルがルールを除外する場合にだけ含まれます。{ rules, criteria }で、指定されたルールと、除外されるWCAGの達成基準です。指定されたルール、すべての達成基準が除外されるルール、除外される達成基準のWCAGの集約は実行されていません。プロファイルが残す達成基準もチェックするルールは実行され、その達成基準に数えられます。これはスキャンの範囲を狭めるもので、WCAGが求めることは変わりません。組み込みのプロファイルで何かを除外するものはありません。
engine.optInRulesengineOptions.optInRulesが、ほかの選択では実行されなかったオプトインルールを少なくとも1つ実行した場合にだけ含まれ、そのタグを列挙します。これがある場合、結果には対象の規格を超える要件のルールが含まれるため、不合格がWCAGの不合格とは限りません。すべてのルールを実行するを参照してください。
engine.mappings実行がmeta.normativeMappingsでWCAG以外の規格を示す場合(engineOptions.mappingsまたは規格のプロファイルによる)にだけ含まれます。正規の表記で列挙し、すべてのバージョンなら"en301549"、1つなら"en301549:V3.2.1"です。ない場合、どの結果もWCAGだけを示します。ほかの規格を参照してください。
engine.packsスキャンをengineOptions.packs付きで実行した場合にだけ含まれます。実行された各パックをname@versionの形で、名前順に並べたものです。パックを参照してください。
engine.outputDetailengineOptions.output.detailが'findings'の場合にだけ、"findings"として含まれます。検出箇所を1つも持たないpassまたはnotApplicableのチェック結果はそれぞれコンパクトになり、{ ruleId, outcome, type }と、ある場合はそのmarginまたはerrorだけになります。タイトル、説明、metaはカタログのものでどのページでも同じなので、含まれません。failとcantTellの結果、集約、engineは完全なままなので、判定は何も変わりません。レポーター(SARIF、JUnit、HTMLレポート、EARL、ベースラインの関数)は、コンパクトな結果をコアのカタログで補って完全な結果として読みます。カタログで補えない結果は完全なまま残ります。packs付きのスキャンのすべてのチェック結果、カスタムルールの結果、スキャンのmessagesがタイトルや説明を変えた結果です。空のページの結果は、約263 KBから90 KBになります。
engine.environmentページがレンダリングされた条件です。スキャンの開始時、どのルールも実行される前にページから読み取ります。text-spacing-content-lossのようにレイアウトを計測するルールは、同じマークアップでも、ビューポートの幅が違ったり、Webフォントがまだ読み込み中だったりすると別の判定結果になることがあるため、実行を再現するにはこの情報が必要です。layoutはページにレイアウトがあったかどうかです。jsdomなどのDOMエミュレーターではfalseになり、その場合、ビューポートなどのレンダリングのフィールドは、計測されたものを何も表さないため省略されます。並びうるのは、ページがフックを実行している場合のinternalsHook、listenerHook、liveRegionHookだけです。ブラウザーでは、viewportはCSSピクセル単位のinnerWidth/innerHeight、devicePixelRatioはページのデバイスピクセル比(ブラウザーのズームもここに表れます)、colorSchemeはprefers-color-schemeが一致する値、forcedColorsはforced-colors: activeが一致するかどうか(Windowsのハイコントラストや、Chromiumでエミュレートした強制カラーのもとでは"active"、それ以外は"none"。どちらの場合もルールはページ自身の色を計測します。LAYOUT_MEASUREMENT.mdを参照)、forcedColorsCssは、強制カラーのもとでページ自身のCSSがスキャンでは抑えられない形でそれに反応する場合(なお一致するforced-colorsメディアクエリや、なお強制パレットの色を取るGrayTextなどのシステムカラー)にtrueで、その場合コントラストの結果は強制カラーをオフにしたスキャンと異なることがあります。fontsはページのフォントフェイスのいずれかがまだ読み込み中なら"loading"、それ以外は"loaded"です。ページが報告できないフィールドは省略されます。これらを読み取っても非決定性は加わりません。DOMと同じく、入力だからです。実行間で比較できる結果が必要なら、スキャンの前にdocument.fonts.readyを待ってください。imagesは、いずれかの画像がまだ読み込み中なら"loading"、それ以外は"loaded"です。後から届いた画像は、レイアウトのルールが計測したものを動かすことがあるため、比較できる結果が必要なら、ページのloadイベントの後にスキャンしてください。loading="lazy"の画像は、読む人がスクロールするまで読み込まれないため除外されます。animationsSettledは、スキャンが静止させた実行中のアニメーションとトランジションの数です。スキャンの間、有限のもの(フェードインなど)は終了時点の状態で、無限に繰り返すもの(マーキーやスピナーなど)は開始時点の状態で読み取り、その後それぞれを元の位置に正確に戻します。そのため、フェードインの途中でスキャンしたページも、その後にスキャンしたページと同じ結果になります。スキャンは1つの同期タスクなので、静止させた状態がブラウザーに描画されることはありません。internalsHookは、スキャンしたドキュメントでページがオプトインの内部フック(internalsHookScript()。INTEGRATION.mdを参照)を実行している場合にだけ、レイアウトの有無にかかわらず含まれます。ページのスクリプトより前にインストールされ、今もページのattachInternalsであれば"early"で、スキャンはすべてのカスタム要素のElementInternalsを読み取っており、それを持たない要素について問いは生じません。ページのスクリプトより後にインストールされた場合、またはその後でページがattachInternalsを置き換えた場合は"late"で、フックより後に関連付けられた内部状態だけが読み取られています。フックがなければこのフィールドはなく、結果はこれまでと同じです。listenerHookは、オプトインのリスナーフック(listenerHookScript()。INTEGRATION.mdを参照)について同じことを示します。ページのスクリプトより前にインストールされ、今もページのaddEventListenerであれば"early"で、キーボードのルールはページがスクリプトから追加したすべてのリスナーを見ており、リスナーがなければ本当にないことが証明されます。ページのスクリプトより後にインストールされた場合、またはその後でページがaddEventListenerを置き換えた場合は"late"です。liveRegionHookは、ページがオプトインのライブリージョンフック(liveRegionHookScript()。INTEGRATION.mdを参照)を実行している場合にだけ含まれます。ドキュメントの読み込みが終わる前にインストールされていれば"early"で、それ以降のページのライブリージョンへの変更をすべて見ています。それ以外は"late"です。フレームをまたぐ結果では、各フレームがそれぞれ独自の値を持ちます。
url渡したpageUrl引数です。nullを渡したか省略した場合(または文字列以外を渡した場合。このときはconsole.warnも記録されます)はdocument.location.href、どちらも得られない場合はnullになります。
titleスキャン時点のdocument.title、またはnullです。
timestamp自動では生成されません。engineOptions.timestampに空でない文字列を渡した場合にだけ設定されます。エンジンは組み込みの時計を持ちません(決定論的であるための設計です)。結果にスキャンのタイムスタンプを入れたい場合は、自分で渡してください。
perfStatsengineOptions.perfStats: trueでない限りnullです。内部の所要時間やカウンターで、その形はこのドキュメントの対象外です。デバッグ専用として扱ってください。
contextSelector渡したcontextSelector引数(トリム済み)です。文字列、文字列の配列(複数領域のスキャン。エンジンオプションを参照)、または未指定・空の場合はnullになります。
contextMatchcontextSelectorがどう解決されたかを示します。指定がなかった場合はnullです。elementCountは一致した異なる要素の数で、これがスキャンの起点になります。unmatchedSelectorsは、どの要素にも一致しなかったセレクターを、渡したとおりの形で列挙します。カンマ区切りの文字列は、1回のquerySelectorAll呼び出しであるのと同じく、ここでも1つのセレクターとして扱われます。elementCountが0なら、何もスキャンされていません。ページにその範囲がなく、checksResultsとrulesResultsのエントリはすべてnotApplicableで、結果はページについて何も述べていません。検出結果のないスキャンとしてではなく、範囲が見つからなかったものとして報告してください。ブラウザーが解析できないセレクターは結果まで届かず、スキャンがcode: 'INVALID_CONTEXT_SELECTOR'付きのエラーを投げます(エンジンオプションを参照)。
checksResults実行されたアトミックルールごとに1件のエントリです(runOnlyで除外されなかったすべてのルール。エンジンオプションを参照)。読み込まれたルールはすべてエントリを生成し、判定結果がnotApplicableのものも含まれます。「違反だけ」のリストではありません。
rulesResults実行された複合ルール(集約ルール)ごとに1件のエントリです。複合ルールの結果とWCAG適合性との対応を参照してください。通常はWCAGの達成基準ごとに1件ですが、独自の集約を持つ規格のプロファイルで実行した場合は、それらも含まれます(meta.standardが設定されます)。選択が選んだ集約と、選択が単独で(IDなどで)指定したルールがチェックする達成基準の集約を含み、後者は一部だけチェックされたものでありえます(スキャンが報告する達成基準を参照)。どちらもなければ空の配列です。
standards結果がmeta.normativeMappingsのエントリーや集約のmeta.standardでWCAG以外の規格を示す場合にだけ含まれます。示している登録済みの規格(パックのものを含む)ごとに1つの{ key, standard, titleLang?, note? }を、登録簿の順に並べたものです。keyは規格のキー("en301549")、standardはそのエントリーが持つ名前("EN 301 549")、titleLangは、規格独自の集約のタイトルがスキャンの言語以外で書かれている場合のその言語、noteはHTMLレポートで規格独自の集約の上に表示される、スキャンの言語のテキストです。レポーターは登録簿の代わりにこれを読むため、保存した結果は、その環境がその規格を知っているかどうかにかかわらず、どこでレンダリングしても同じになります。カスタムルールだけが示す規格は列挙されません。
skippedPacksengineOptions.packsのパックが実行されなかった場合にだけ含まれます。それぞれ{ name, reason }の形で、パックに名前がなければnameはnullです。ページ内(runa11yCoreInPage)では、nameは指定されたname@versionで、理由はページがそのパックを実行しなかった訳を示します。指定されたセットとまったく同じものを登録したpackScriptの呼び出しがない、またはスクリプトが別のバージョンのコアで用意された、のどちらかです。それぞれconsole.warnでも記録されます。
overriddenBuiltinIdsengineOptions.customRulesのエントリが組み込みルールと同じidを持っていたため、このスキャンで組み込みの実装がカスタムの実装に置き換えられたルールのIDです(エンジンオプションを参照)。常に配列で、衝突がなければ空です。同名のカスタムルールは、意図した上書きであるのと同じくらい偶然の衝突である可能性もあるため、スキャン時にconsole.warnでも記録されます。
skippedCustomRules実行されなかったengineOptions.customRulesのエントリで、それぞれ{ id, reason }の形です(エントリにIDがなければidはnull)。理由は、IDがない、runInPageが関数でないかソースから再構築できない、metaが検証に通らない、別のカスタムルールがすでにそのIDを持っている、複合ルールのIDである、のいずれかです。あるいは、妥当なルールでも実行の選択に含まれない場合(プロファイルやWCAGの目標のもとで、best-practiceのタグを持つか、WCAGのタグを持たないルール)で、その場合のreasonはルールを選択する方法を示します。あるいは、選択の除外(excludeRuleIds、excludeTestIds、excludeTags、rules.excludeなど)が外したルールで、その場合のreasonはexcluded by the selection.になり、excluded: trueも付きます。そのため、ツールは理由を読まなくても、呼び出し側の選択と抜けを区別できます。常に配列で、すべてのカスタムルールが実行されれば空です。それぞれconsole.warnでも記録されますが、呼び出し側が外すよう求めた除外ルールは記録されません。ここに挙がったルールはどの結果にも含まれないため、ルールを除外したスキャンと、そのルールがpassになったスキャンを区別できます。

フレームをまたぐ結果(runa11yCoreAcrossFrames)

runa11yCoreAcrossFrames(INTEGRATION.mdを参照)は、通常のトップレベルの結果ではなく、別の再帰的な形を返します。

{
topFrame: <the normal top-level result shape above>,
frames: Array<
| { url: string | null, selector: string | null, title: string | null,
topFrame: <top-level result>, frames: [...same shape, recursively] }
| { url: string | null, selector: string | null, title: string | null, error: string }
>
}
  • topFrameは、関数が呼び出されたフレームについての、トップレベルの結果とまったく同じ形です。
  • framesには、スキャン範囲内(開いたシャドウルートを含み、範囲自体がフレームであればそれも含む)の直接の子である<iframe>/<frame>ごとに1件のエントリが入ります。ただし、ページが表示していないフレームと、excludeSelectorsが除外するフレームは、そのドキュメント全体とともに除かれます。各エントリはそのフレーム要素を示します。selectorは親のドキュメントにおける<iframe>/<frame>のCSSセレクター、titleはその要素のtitle属性またはnullで、同じドキュメントを読み込むフレームを見分けられます。urlはフレームが表示しているドキュメントで、まだ遷移していないフレームではそのsrcです。到達できる子(a11yCoreEnableFrameResponder()を呼び出したもの)は、それ自身の入れ子のframesまで再帰的に含む、完全な{ url, topFrame, frames }を返します。さらに深い孫フレームには、直接の親を経由してしか到達できないためです。到達できない子(ほとんどのサードパーティの埋め込みがこれに当たります。協力するレスポンダーがないか、タイムアウトした場合)は代わりに{ url, error }を返し、スキャンの残りは中断されません。
  • これはフラットなリストではなくツリーです。@surea11y/playwrightバインディングの.frames(true)とは意図的に異なります。そちらはPlaywrightのpage.frames()が入れ子の深さに関係なくすべてのフレームを返すので、フラットにできます。postMessageによる中継にはそのような全体の視点がないため、入れ子を構造で表しています。
  • レポーターはツリーをそのまま受け取ります。renderHtmlReport、renderSarifReport、renderJunitReport、buildBaselineEntries、matchBaseline、renderEarlReportは、ツリーのすべてのフレームを報告します。応答した各フレームはそれ自身の検出結果を、それ自身のドキュメントに位置付けて報告し、応答しなかった各フレームは未スキャンとして報告するため、カバレッジの抜けが合格と読まれることはありません。フレームはパスで示されます。ページからそのフレームに至るフレーム要素のselectorを、外側から順に並べたものです(#checkout → iframe:nth-of-type(2))。スキャン結果でもフレームをまたぐ結果でもないもの(配列、失敗したスキャンのnullやundefined)を渡されると、何も見つからなかったスキャンとして描画するのではなくTypeErrorを投げます。
  • バインディングのフレームのスキャンも受け取ります。ブラウザー用バインディングの.frames(true)は、各フレームが入れ子のエントリではなく単純な結果(または{ url, error })である{ topFrame, frames }を返します。レポーター、getMargins、flattenCrossFrameResultは、そうしたフレームをスキャン済みとして読み、selectorを持たないため['iframe']というパスで示します。
  • @surea11y/coreのflattenCrossFrameResult(result)は、レポーターが読むとおりにフレームを列挙します。[{ frame: { path, title, url }, result }]の形で、応答しなかったフレームではresultの代わりにerrorが入り、ページが先頭で、各フレームはその中のフレームより前に並びます。ページのpathは[]です。単純なスキャン結果は1件のエントリになります。

チェック結果(checksResults[i])

{
ruleId: string,
outcome: "pass" | "fail" | "cantTell" | "notApplicable",
outcomeNormalized: "pass" | "fail" | "cantTell" | "inapplicable",
severity: "minor" | "moderate" | "serious" | "critical",
ruleSeverity?: "minor" | "moderate" | "serious" | "critical", // the rule's own, when a profile gave it another
policyOutcome?: "pass" | "fail" | "cantTell" | "notApplicable", // what the rule found, when the policy made it cantTell
confidence: "high" | "medium" | "low",
type: "automatic" | "manual",
occurrences: Occurrence[],
title: string,
description: string,
i18n: { titleKey: string, descriptionKey: string, variantOfTitleKey?: string } | null,
meta: {
ruleId: string,
ruleInterfaceVersion: string,
ruleVersion: string,
normative: boolean,
atomic: boolean,
deprecated: boolean,
deprecation: object | null,
category: "perceivable" | "operable" | "understandable" | "robust" | null,
helpUrl: string, // where to read how to fix it; "" when there is none
tags: string[], // the rule's tags, its own and the engine's
normativeMappings: Array<{ standard: string, version: string, requirement: string, title: string,
conformanceLevel?: string, wcagSc?: string[], url?: string, understandingUrl?: string }>,
standard: string | null,
applicability: string,
expectation: string,
references: string[],
requirements: object | null,
mappings: object | null
},
engineOptions: object, // the resolved engineOptions this rule actually ran under
schemaVersion: string,
rollupIds: string[], // the rulesResults entries that group this rule in this run; [] if none
variantOf?: string, // a pack's variant only: the id of the rule it runs at other settings; i18n.variantOfTitleKey is that rule's titleKey
data?: object, // page-level data a rule reports whatever its outcome; see below
margin?: { // the closest a measurement came to its threshold while meeting it; see below
measure: string, // "contrast-ratio" | "overflow-px" | "target-size-px" | ... (open set)
unit: "px" | "ratio", // open set
limit: "min" | "max",
threshold: number,
value: number,
headroom: number, // >= 0
measuredCount: number,
selector?: string,
shadowHostSelectors?: string[], // as on an occurrence
structuralPath?: number[],
context?: object // rule-specific; not a stable contract
},
wcagVersionScope?: { // present only when the target WCAG version changed this outcome
target: "2.0" | "2.1" | "2.2",
removedSc: string[],
coercedFrom: "fail",
by?: "errata" // 2.0 or 2.1: their errata count the criterion as always satisfied
},
error?: string // present when the rule did not complete, or the engine noted a change — see below
}

注意点:

  • outcomeとoutcomeNormalized:outcomeNormalizedではnotApplicableが"inapplicable"になる点を除いて同一です。自分の用語とエンジン内部の用語のどちらにも合わせられるよう、両方を提供しています。
  • デフォルトのa11yポリシーでは、type: "manual"のルールはfailではなくcantTellを報告します。手動ルール自身のロジックがfailと判断した場合、エンジンはそれをcantTellに強制変換し、errorに説明を追記します。これは一元的に適用される仕組み(policy.coerceManualFailToCantTell。a11yポリシー契約ではデフォルトで有効です。POLICY.mdを参照)で、各ルールが気にかける必要はありません。このポリシーのもとでは、failは決定論的なtype: "automatic"の検出結果だけのためにあります。
  • meta.normativeMappingsは、チェック結果をWCAGの達成基準に結び付けるものです。空のリストは、この結果ではそのルールに正式な対応がないことを意味します。それはルールが自動か手動かを示すものではありません。それにはtypeを読んでください(例えばaria-allowed-roleは自動ルールで、WCAGとの対応がありません)。これらがどう集約されるかはWCAG適合性との対応を参照してください。このリストはWCAGだけのものではありません。スキャンが別の規格を要求した場合(engineOptions.mappings、または規格のプロファイル)、WCAGの各達成基準の後に、その規格で対応する要件が続きます。例えば、その達成基準を再掲するEN 301 549の条項です({ standard: "EN 301 549", version: "V3.2.1" | "V4.1.1", requirement: "9.1.1.1", title, wcagSc: ["1.1.1"] }。その達成基準を含むバージョンごとに1件)。また、ルールがWCAGのUnderstanding文書を引用することもあります(type: "Understanding")。requirementを達成基準として読む前に、standard(とtypeがないこと)で絞り込んでください。複合ルールのWCAGのエントリーは常に先頭です。EN 301 549を参照してください。
  • rollupIdsは、この実行でこのルールをまとめているrulesResults内の複合ルールを列挙します。選択がそのルールを単独で指定したために報告された複合ルールも含みます。空のリストは、そのルールの検出結果がどの集約にも現れないことを意味するため、rulesResultsだけを読む利用者には決して見えません。例えばheading-orderはどのWCAGの集約にも属していません。
  • wcagVersionScope:スキャンの対象WCAGバージョンによって、このルールのfailがcantTellに変わった場合にだけ含まれます。現時点では、SC 4.1.1(構文解析)に対応するルール(duplicate-id)がこれに当たります。2.2ではその達成基準が削除されたため、2.0と2.1では2023年の正誤表がHTMLとXMLについて常に満たされているものとして扱うためです(by: "errata")。4.1.1の文言を残す規格のプロファイル(en301549-v3.2.1、またはkeepsParsingを持つパックのプロファイル)では変更されません。removedScは該当する達成基準、targetはスキャンのバージョン、coercedFromはルール自身が報告した判定結果です。検出箇所はルール自身のもので、手を加えていません。捨てられたものは何もなく、変わったのは適合の判定だけです。それ以外の結果には含まれず、errorで報告されることもありません。何も問題は起きていないからです。WCAGバージョンによる絞り込みを参照してください。
  • data:判定結果にかかわらずページ全体について何かを報告するルールにだけ含まれます。現在、コアのルールでこれを使うものはありません。検出箇所のdata.detailsと同じく、安定した契約ではありません。
  • margin:カタログでmarginを宣言しているルール(getChecksCatalog()[i].margin、{ measure, unit, limit, band? })で、少なくとも1つの要素がルールのしきい値を満たし、宣言にbandがあればその範囲内に入った場合にだけ含まれます。band.relativeはしきい値に対する割合です。contrast-minimum、contrast-enhanced、link-in-text-blockは0.1で、必要な比の10%以内の比についてだけmarginを報告します(4.5:1に対して4.5〜4.95、3:1に対して3〜3.3)。band.absoluteはunitでの量です。target-size-minimumは6で30 pxまでのターゲットだけを、text-spacing-content-lossは8でボックスの端から6 px以内の行だけを報告します。21:1のテキストや48 pxのボタンは何にも近くないので、それを示すmarginはありません。しきい値を満たしつつ最もしきい値に近づいた要素を示すので、4.5:1に対して4.52:1でのpassや、テキストが切れるまであと0.4 pxでのpassを、余裕のあるpassと区別できます。判定結果に添えられる情報で、検出結果ではありません。検出箇所を追加、削除、変更することはなく、ベースライン、SARIF、JUnit、EARLはこれを無視します。一部の要素が合格していれば、failやcantTellの結果にも含まれます。limitは、値がしきい値に達する必要がある場合(コントラスト、サイズ)はmin、しきい値を下回る必要がある場合(はみ出し)はmaxです。headroomはしきい値の内側にどれだけ余裕があるかをunitで表したもので、minならvalue - threshold、maxならthreshold - valueとなり、負になることはありません。thresholdはその要素の判定に使われたしきい値で、要素ごとに異なることがあります(大きな文字なら3:1)。ピクセルは小数点以下1桁で示されます。CSSピクセルや、15pxのフォントの半分といったしきい値は小数になり、表示する側が人のために丸めるからです。比は丸めません。WCAGはコントラストを丸めないためです。同じ値の要素が複数あれば文書順で最初の要素が選ばれるので、同じページでは常に同じmarginになります。measureとunitはオープンな集合で、マイナーリリースで増えることがあります。contextはルール固有で、data.detailsと同じく安定した契約ではありません。getMargins(result)は、結果に含まれるすべてのmarginをruleId順に並べた[{ ruleId, ...margin }]として返します。フレームをまたぐ結果ではすべてのフレームのmarginを返し、子フレームのものには、そのフレームへのパスであるframeが付きます。
  • error:ルールが完了しなかった場合、またはルールが返したものの一部をエンジンが変更したり無視したりした場合に含まれます。例外を投げた(または結果でないものを返した)ルールは、必ずoutcome: "cantTell"、occurrences: []、例外メッセージを設定したerrorとして現れます。そのため、検出箇所がなくerrorを持つcantTellが、完了しなかったルールの見分け方です。エンジンは、壊れたルール1つでスキャン全体をクラッシュさせることはありません。それ以外の場合、errorはエンジンの注記を保持し、ルール自身が返したerrorがあればその後に|でつなげます。注記の対象は、上記の手動ルールの強制変換、集合の外にあるoutcomeやseverity、metaと異なるtype、オブジェクトでない検出箇所(除外されます)、ルールが返したpolicyOutcomeやruleSeverity(どちらもエンジンが設定するため採用されません)、閉じた集合の外にあるuncertainty.code、そして200段階の祖先をたどる処理が報告されたすべての要素に届かずに止まったためにcantTellに格下げされたfailです。これらの結果は検出箇所を保持します。ルールは完了しているからです。
  • policyOutcome:ポリシーのallowedOutcomesが、ルールの見つけた判定結果を許可しない場合に含まれます。その場合、結果はcantTellになり、ルール自身の判定結果がここに入り、errorは付きません。そのため、レポーターがこれを完了しなかったルールとして読むことはありません。
  • 各結果のengineOptionsは、渡したものそのままではなく、解決済みのオプションオブジェクト(ロケールやコントラストのデフォルトを適用した後のもの)です。あるルールが実際に何を受け取ったか、特に解決されたlocaleとcontrast.mode/contrast.rootCanvasFallbackを確認するのに役立ちます。呼び出し側が指定しなければcontrast.rootCanvasFallbackは白で、contrast.rootCanvasFallbackSetがどちらかを示します。呼び出し側が指定した色ならtrue、デフォルトならfalseです。スキャンが翻訳に使った辞書であるmessages(ブラウザー用バンドルのロケール用の別ファイル、または独自の文字列)は含まれません。これらは設定ではなくデータで、結果ごとにコピーを持たせるとスキャンが数十メガバイトになっていたためです。どの辞書が使われたかはengine.localeで分かります。さらに3つのオプションは、ルールが見たとおりの形で含まれます。結果をJSON.stringifyやstructuredClone(postMessage)で運べる単純なデータに保つためです。probesはルールが読む上限付きのコピーとして、customRulesは関数を除いた[{ id }](IDを持つカスタムルールごとに1件)として、styleSheetTextsはテキストを除いた[{ href }](渡したシートごとに1件)として含まれます。ページのCSSを結果ごとに繰り返すと、ルールの数だけ増えていたためです。

検出箇所(occurrences[i])

failには必ず1つ以上あります。要素を示さないカスタムルールのfailには、ドキュメント要素に1つ付きます(selector: "html"、理由コードFAIL_WITHOUT_OCCURRENCE)。通常はoutcomeがfailまたはcantTellのときにだけ含まれます。このエンジンは合格した要素を列挙せず、フラグを立てた要素だけを報告するため、passの結果はoccurrences: []になります。例外はコントラストのルールで、そのpassには、スキャンについて述べる検出箇所(対象となり計算できたテキストの量)がselectorを空にして1つ付きます。テキストがまったくないpassと、テキストの多いページでのpassを区別できるようにするためです。

唯一の例外がnotApplicableです。判定対象が何もなかったルールは、その理由を示す検出箇所を1つ付けることがあり、コントラストのルールは、背景を計算できるテキストが1つもなかった場合に実際にそうします。「チェックしたが、フラグを立てるものはなかった」と「チェックできなかった」の違いを、このエンジンは隠さずに報告します。このような検出箇所は要素ではなくスキャンについて述べるものなので、selectorは空です。outcomeを先に確認せずに、occurrences.lengthを違反の件数として読まないでください。

{
selector: string,
html: string,
structuralPath: number[] | null,
shadowHostSelectors?: string[],
summary: string,
hint: string,
i18n: { summaryKey: string, hintKey: string, params: object } | null,
occurrenceOutcome?: "fail" | "cantTell", // present when the rule graded its findings into tiers
uncertainty?: { // present only on a cantTell-tier occurrence
code: "not-computable" | "runtime-dependent" | "spec-only"
| "equivalence-unknown" | "judgement-required" | "out-of-scope",
needed?: string, // what would settle the question
evidence?: object // what the rule did establish, rule-specific
},
lean?: { // present only on a cantTell-tier occurrence, and only with evidence
toward: "pass" | "fail",
why: string, // localized: what in the page points that way
signals: { signal: string, value: string | number | boolean | null }[],
caution?: string, // localized: what could make it wrong
measured?: { agreed: number, cases: number, corpus?: string, coreVersion?: string },
i18n?: { whyKey?: string, cautionKey?: string, params?: object }
},
howToCheck?: { // present only on a cantTell-tier occurrence, when the rule says
steps: string[], // localized: what a person does, in order
passWhen: string, // localized: what they see if it passes
failWhen: string // localized: what they see if it fails
},
data?: { // absent on manual-review's page-level finding
visibilityFilter?: { eligible?: boolean, targetSet: string, accEligible: boolean | null, reasons: string[] },
details?: object // rule-specific, non-normative — see below
}
}
フィールド意味
selectorフラグが立った要素を指し戻せるように組み立てた、ベストエフォートのCSSセレクターです(RULE_AUTHORING.mdのhelpers.buildSelectorを参照)。ID、テストID、name、aria-labelを起点にするのは、非表示の要素、除外された要素、範囲外の要素も含めて、ドキュメント内のほかのどの要素もそれを持っていない場合だけです。querySelectorはそれをドキュメント全体に対して解決するためです。それ以外の場合、セレクターはパスになります。どのDOM構造でも一意であるとは保証されません。シャドウルート内の要素はそれ自身のツリーの中で名前が付けられ(その位置はstructuralPathが示します)、非常に深い要素のパスは上から短縮されます。テスト用と実際のページ255件で、39,857個のセレクターのうち15個が自身の要素をちょうど指していませんでしたが、すべてこうした種類のものでした。例外は、要素が存在しないことそのものが検出結果であるルールです。page-title-presentはhead > titleと、htmlとして<title>(missing)</title>を報告しますが、どちらもページ上には存在しません。どちらも定数なので、これらから作られるフィンガープリントは安定しています。ただし、ルールが実在するものを報告したことを確かめずに、selectorを解決可能なもの、htmlを実際のマークアップとして扱わないでください。シャドウツリー内の要素では、selectorはそのシャドウルートの中で解決され、そこまでのたどり方はshadowHostSelectorsが示します。
shadowHostSelectorsシャドウツリー内の要素にだけ含まれます。その要素に至るシャドウホストのセレクターを外側から順に並べたもので、それぞれ自分を含むツリーの中で解決されます。そのため、document.querySelector(s[0]).shadowRoot.querySelector(s[1])…shadowRoot.querySelector(selector)で要素が見つかります。同じ内容を持つ2つのコンポーネントはselectorが同じになり、ここで区別されます。selectorと同じく、検出結果の識別には含まれません。HTMLレポート、SARIF(logicalLocations)、JUnit、ベースラインのエントリーは、この2つを1つの位置として、ホスト、続いてセレクターを >>> でつないで示します(#card >>> img)。
htmlフラグが立った要素のouter HTMLのスニペットで、2,000文字で切り詰められます。要素を表示するのに役立ち、シャドウツリー内の要素ではshadowHostSelectorsと合わせて読みます。ページ全体を含む<html>、<head>、<body>では開始タグだけ(<html class="x">)になるため、ページ単位の検出結果は、ほかの内容が変わっても識別が保たれます。
structuralPathdocumentElementからフラグが立った要素までを、兄弟要素の中でのインデックスでたどったパスです(例:[1, 0, 2])。要素がdocumentElementそのものであれば[]、特定できなかった場合はnullになります。シャドウツリー内の要素はすべてnullです(その場合はshadowHostSelectorsとselectorを使ってください)。selectorだけに頼るより頑健に要素を特定でき、セレクター文字列なら壊れてしまうDOMの変更(IDやクラス名の変更など)にも耐えます。その代わり、実際のCSSセレクターとしては使えません。
summary人が読むための文で、解決されたロケールの言語でローカライズ済みです(「This button has no accessible name.」)。
hint人が読むための修正ガイダンスで、summaryと同じくローカライズ済みです。
i18nsummary/hintの元になった翻訳キーです。スキャンをやり直さずに、別のロケールで自分で表示し直したい場合に使えます。検出箇所がキーによるi18nを使っていない場合はnullです。
data.visibilityFilterほとんどの検出箇所に含まれます。ルールが使った対象判定のモデルのもとで、エンジンがこの要素を対象とみなした(またはみなさなかった)理由です。eligibleがその結果で(bypass-blocks-present、html-lang-attr-present、page-title-presentのページ単位の検出結果には含まれません)、targetSetはどのモデルによる判定かを示します('dom':DOM/CSS上の可視性そのもの。ほとんどのルールはこちら。'acc':アクセシビリティツリー上で対象となるかどうか)。accEligibleはtargetSetが'acc'のときだけeligibleと同じ値になり、それ以外はnullです。reasonsは、eligible: falseのときの機械可読な除外コードのリストです。
data.detailsルール固有の構造化データ(計算した指標、解決済みの参照など)です。規範的なものではありません。より詳しいUIの構築やデバッグには役立ちますが、outcome/severityの意味を変えることはありません。形はルールごとに異なるので、安定した契約ではなく、ベストエフォートの補足情報として扱ってください。唯一の例外がdata.details.reasonCodeで、これは安定しています。ルールの検出結果のうちどれであるかを識別し、ruleId、htmlとともに、ベースラインとSARIFのキーになるフィンガープリントを構成します。ルールはマイナーリリースで新しい理由コードを得たり、既存のコードを原因ごとに分けたりすることがあります。API_STABILITY.mdを参照してください。コントラストの失敗のサイズと比のフィールド(metrics.ratio、metrics.threshold、typographyのfontSizePx、fontSizePt、fontWeight、isBold、isLargeText)も安定しているので、レポートやパックはどの種類のテキストが失敗したかを判別できます。list-children-validの検出結果のelement、listitem-parent-validの検出結果のparentElement、aria-role-name-presentの検出結果のroleも同様に安定しており、どの種類のリストやウィジェットが失敗したかを示します。各ルールのページには、その検出結果が持つフィールドが「検出結果が報告する内容」の下に記載されています。
occurrenceOutcome検出結果を確実なfailの層と、レビューが必要なcantTellの層に分けて評価するルールで、この検出箇所がどちらの層に属するかを示します。1つの層しか報告しないルールでは省略され、その場合は結果自体のoutcomeが検出箇所の層になります。@surea11y/coreのoccurrenceOutcome(check, occurrence)は、どちらの場合でも、すべてのレポーターが読むとおりの層を返します。判定結果は常に層と一致します。failの層の検出箇所が1つでもあればfailになり、検出箇所がすべてcantTellの層であるfailはcantTellになるため、SARIF、JUnit、EARL、ベースラインは同じ答えを返します。カスタムルールやパックのルールが食い違うものを返した場合はエンジンが整合させます。デフォルトのポリシーでは、手動ルールがfailになることはありません。レポーターは、エンジンがこれを行う前に保存された結果も、そのengineOptionsが記録するポリシーのもとで同じ規則で読み、読んだものからWCAGの集約をまとめ直します。
uncertaintyこの検出結果を判定できなかった理由です。後述の不確実性コードを参照してください。
leanページがどちらかの根拠を示している場合に、この未判定の検出結果がどちらに傾いているかです。後述の傾きを参照してください。
howToCheckこの未判定の検出結果に人がどう答えるかです。後述の確認方法を参照してください。

不確実性コード

cantTellは、エンジンが判定しなかったことを示します。uncertaintyはその理由を閉じた語彙で示すので、利用側は要約の文字列を解析しなくても、理由に応じて処理を分けられます。含まれるのはcantTellの層の検出箇所だけです。failの層の検出箇所に付いていれば、ルールが判定したと同時に判定しなかったと主張することになるため、エンジンはそれを取り除きます。codeが下記のコードのいずれでもない不確実性も除かれ、ルールのerrorがそのコードを示します。

code意味典型的な例
not-computableルールが必要とする証拠を、この環境では読み取れませんでした。クロスオリジンのスタイルシート、値に解決されない背景色、解決できないsrc。
runtime-dependent実行時にスクリプトが決めるため、マークアップからは判断できません。ウィジェットが開いたときに生成する要素を指すaria-controls。
spec-only仕様違反ではあるものの、公開される名前、役割、値はその影響を受けないため、どの達成基準も不合格とは確定できません。省略時のデフォルト値が仕様で定められているARIA属性。
equivalence-unknown2つのものが同じ目的を果たしているかどうかが、マークアップからも内容からも判断できません。アクセシブルな名前は同じなのに、異なるリソースを埋め込んでいる2つのフレーム。
judgement-required問いそのものが、本質的に人間の判断を必要とします。サイズの小さいターゲットが必須かどうか。type: "manual"のルールはすべてこれに当たります。
out-of-scope検出結果自体は本物ですが、このスキャンが対象とする規格の範囲外です。対象のWCAGバージョンで削除された達成基準だけに対応するルール。

neededは、問いに決着をつけるには何が必要か、つまりレビュー担当者が実際に確認しに行くべきことを1文で述べます。evidenceにはルールが確定できたことが入るので、レビュー担当者はエンジンの作業を繰り返さず、その続きから始められます。その形はルール固有で、data.detailsと同様に安定した契約ではありません。一方、codeは安定した契約です。新しいコードがマイナーリリースで追加されることはありますが、既存のコードの意味は変わりません。知っているコードに応じて処理を分け、知らないコードはエラーではなく「レビューが必要」として扱ってください。

cantTellを報告しうる自動ルールはすべてこれを持ち、テストでそれを担保しているので、これを持たない新しいルールが入り込むことはありません。out-of-scopeコードはルールではなくエンジンが付けるもので、結果レベルのwcagVersionScopeを生じさせるのと同じ検出箇所に付きます。手動ルールはこれを持ちません。judgement-requiredはtype: "manual"がすでに意味していることなので、検出箇所ごとに繰り返しても、結果が示している以上のことは何も伝わらないからです。

傾き

cantTellでも、どちらか一方を指していることがあります。ページがその根拠を示している場合、leanがどちらかを示します。towardはその根拠から可能性が高い答え、whyは根拠が何か、signalsはルールが読み取った事実の一覧で、それぞれケバブケースの名前と単純な値からなるため、ツールはそれを表示したり重み付けしたりできます。cautionは、uncertainty.neededから明らかでない場合に、傾きが誤りになりうる要因を述べます。判定結果はcantTellのままです。傾きは助言であって判定ではなく、判定結果や層を読むものは何も変わりません。LEANS.mdは、レポートを読む人やツールを作る人のためのガイドで、どの検出結果がなぜ傾くのか、傾きをどう測定するのか、どこまで信頼できるのかを説明しています。

leanは、ルールに根拠がある場合にだけ含まれます。ないこと自体も情報です。これは人にしか判断できないということです。uncertaintyと同じくcantTellの層の検出箇所にだけ含まれます。エンジンは判定済みの検出箇所に付いたものを取り除き、形の正しくないもの(passとfail以外のtoward、またはwhyがないもの)も検出結果には手を付けずに取り除きます。measuredは、答えの分かっている5件以上のケースで傾きが数えられると現れます。正しかった回数(agreed)、ケースの数(cases)、ケースの出典となったコーパス(corpus、読み取った日付付き)、数えたコアのバージョン(coreVersion)です。数はW3C ACT Rulesのテストケースから、ルール、理由コード、方向ごとに数えたもので、エンジンが持っているため、どの入口から得た結果にも含まれます。数えられていない傾きや、ケースが5件に満たない傾きには含まれません。信頼度の数値はありません。現時点ではまだどの傾きにもありません。jsdomでの最初の集計では9件の傾きが見つかりましたが、5件のケースに達したものはありませんでした。

whyとcautionはスキャンのロケールで書かれています。i18nには、検出箇所のi18nがsummaryとhintについて持つのと同じように、それらのキーとパラメーターが入ります。エンジン自身が傾きを付ける検出結果が1つあります。対象のWCAGバージョンで削除された達成基準、または2023年の正誤表で満たされているとされる達成基準だけに対応するルールは、out-of-scopeの不確実性とともにpassに傾きます。

@surea11y/coreのreviewGroupOf(check, occurrence)は、レビューで検出箇所がどこに入るかを示します。'fail'、'leanFail'、'leanPass'、'open'(人にしか判断できない)のいずれかで、HTMLレポートのグループと同じです。leaningFailures(result, { wcagOnly })は、不適合に傾く検出結果、つまりleanFailAsによるゲートが数える検出結果を列挙します(JUnit、SARIF)。

新しい傾きはマイナーリリースでルールごとに追加され、測定で誤りが多すぎると分かった傾きは削除されることがあります。傾きは、あるかないかが変わりうる助言として扱い、検出結果の同一性の一部として扱わないでください。フィンガープリントには含まれません。

確認方法

cantTellは問いを人に渡します。howToCheckは、それにどう答えるかを示します。stepsは、検出結果が示す要素から始まる、順番に行う少数の操作(「Tab to the element.」「Watch whether the focus indicator stays on it.」)で、passWhenとfailWhenは、合格の場合と不合格の場合に何が見えるかを、不合格となる達成基準の名前とともに示します。cantTellを報告しうるコアのルールはすべて、理由コードごとにこれを書いており(ルールのmeta.review)、cantTellの層の各検出箇所には、そのコードのものがスキャンのロケールで付きます。バリアントの検出結果(variantOf)は、自身のものがなければベースのルールのものを受け取ります。パックのルールも英語で書くことができ(パックを参照)、その検出結果は、パックが分かっている場合、つまりengineOptions.packs付きのrunDomRulesInPageとaddHowToCheck(result, { packs })で受け取ります。判定済みの検出箇所、カスタムルールの検出結果、オーバーライド(overriddenBuiltinIdsにあるカスタムルールまたはパックのルール)の検出結果、何も書いていないパックのルールの検出結果には含まれません。

手順は、ページ内のエンジンではなく、スキャンの後にNodeで追加されます。エンジンはスキャンが開くすべてのページとフレームに注入されるため、どのルールも読まない何千もの文を持つ必要がないからです。runDomRulesInPageは自分の結果に追加します。ページ内で実行したruna11yCoreInPageの結果(バインディングや拡張機能のもの)には含まれません。addHowToCheck(result)は手順を加えたコピーを返し、howToCheckFor(ruleId, reasonCode, locale)は1つの検出結果の手順を返します。どちらもコアのレビュー用辞書をディスクから読むため、Nodeが必要です。コードがブラウザーで動くバインディング(Cypress)は、@surea11y/core/review/<locale>からインポートした辞書を使って@surea11y/core/how-to-checkのapplyHowToCheck(result, { en, fr })を呼び、同じ手順を得ます(バインディングでの方法はBINDING_AUTHORS_GUIDE.mdにあります)。HTMLレポート(renderHtmlReport)は、手順を持たない結果にNodeで追加します。ブラウザー(surea11y.report.js)では、結果が持っている手順を表示します。スキャンとは別の言語で結果を表示するツールは、addHowToCheckまたはapplyHowToCheckに{ locale }を渡します(addHowToCheck(result, { locale: 'de' })、または優先度の高い順のロケールのリスト。renderHtmlReportは受け取りません)。手順は、すでにあるものも含めてその言語で示され、そのロケールにない手順は英語になります。

手順は、ブラウザー、その開発者ツール(アクセシビリティツリー)、キーボード、場合によってはスクリーンリーダーを前提としています。問いに決着をつけるには何が必要かを1文で述べるuncertainty.neededと違い、どう決着をつけるかを述べます。傾きと同じく助言であって検出結果の同一性の一部ではなく、文言はどのリリースでも改善されることがあります。

複合ルールの結果(rulesResults[i])

複合ルールは、複数のアトミックルールを1つのWCAG達成基準に集約します(例:wcag-1.1.1-non-text-contentは21件のアトミックルールを集約します)。独自の集約を持つ規格のプロファイルでは、それらの集約もあり、規格の文言がtitleに、規格の名前がmeta.standardに入ります。形はチェック結果と同じ外枠で、data.detailsが複合ルール固有の内容になります。

{
ruleId: string, // e.g. "wcag-1.1.1-non-text-content"
outcome: "pass" | "fail" | "cantTell" | "notApplicable",
severity, confidence, type, title, description, meta, engineOptions, schemaVersion, // as on a check result, except that
// meta.normativeMappings names the criterion in a shorter form:
// { standard, requirement, level }
occurrences: [], // always empty — composites are rollups, not element-level findings
data: {
details: {
reasonCode: string, // e.g. "composite.rollup.fail.anyFail"
standard?: string, // a standard's own rollup only, with version and criterion
version?: string,
criterion?: string,
checksIds: string[], // every atomic ruleId it rolls up, custom rules mapped to its criteria included
customChecksIds?: string[], // the custom rules among them; absent when none
restatesWcag?: string[], // a standard's rollup that restates WCAG criteria (applicability: 'wcag'): those criteria
partial?: true, // a standard's requirement its rules don't check in full (partial: true)
contributors: Array<{ testId: string, outcome: string, severity?: string | null, custom?: true, notSelected?: true,
byReasonCode?: true, checkOutcome?: string, requirements?: string[] }>,
metrics: { failCount, cantTellCount, notApplicableCount, passCount, missingCount }
}
}
}

集約の優先順位(決定論的で、この順に適用されます):構成ルールにfailが1つでもあれば、複合ルールはfail。そうでなくcantTellが1つでもある(または構成ルールのいずれかがまったく実行されなかった、つまりmissingCount > 0)なら、複合ルールはcantTell。そうでなく構成ルールがすべてnotApplicableなら、複合ルールはnotApplicable。ただし、ルールが達成基準の当てはまるすべてのケースを見つける場合に限り、それ以外はcantTell(partialCoverage)です。それ以外はpassです。ただし、ルールが達成基準の求めることをすべてチェックする場合に限り、それ以外はcantTell(partialCheck)です。すべてをチェックするとされたWCAGの達成基準はまだないため、現時点でWCAGの集約がpassになることはありません。これが全体としての適合表明にとって何を意味するかはWCAG適合性との対応を参照してください。

規格独自の集約は、ルールを全体としてではなく検出結果ごとに判断することがあります(パックを参照)。その場合、構成ルールはbyReasonCode: trueを示し、outcomeはこの集約でのルールの判定結果(検出結果がすべて別の集約に属するfailは、ここではpass)、checkOutcomeはルール自身の判定結果です。集約に数えられる検出結果が、その集約のどの要件に属するかを示している場合、requirementsがそれらを列挙し、集約のmeta.normativeMappingsは、そのルールがチェックするすべての要件ではなく、それらの要件を示します。

WCAGの集約のルールは、それ自身のリストに加えて、実行されて(meta.wcagScまたはmeta.normativeMappingsのWCAGのエントリーを通じて)その達成基準のいずれかに対応するengineOptions.customRulesのすべてのルールです。それらは貢献したルールの中でcustom: trueが付き、customChecksIdsに列挙されるため、カスタムルールが判定結果を決めたことが読み手に分かります。規格独自の集約は、それ自身のリストを保ちます。

一部だけチェックされた達成基準。達成基準ではなくルールを指定するスキャン(includeRuleIds: ['link-name-present'])は、選択がその達成基準自体を選んでいない場合でも、それらのルールがチェックする達成基準の集約を受け取ります(スキャンが報告する達成基準を参照)。上の優先順位はほかと同じようにこれを決めるため、failのルールがあれば達成基準もfailになり、スキャンが選ばなかったルールがあるとpassにはなりません。そうしたルールはそれぞれoutcome: "missing"とnotSelected: trueを持つ構成ルールで、これまでどおりmissingCountに数えられます。それらが原因で集約がcantTellになる場合、そのreasonCodeはcomposite.rollup.cantTell.notSelectedChildで、HTMLレポートには「一部のみ確認」と、選択されなかったチェックの数が表示されます。composite.rollup.cantTell.missingChildは引き続き、プロファイルが除外したルール(engine.profileExcludes)のように、別の理由で実行されなかったルールを意味し、それにnotSelectedが付くことはありません。

reasonCode判定結果条件
composite.rollup.fail.anyFailfail構成ルールのいずれかがfailです。
composite.rollup.cantTell.anyCantTellcantTellfailのものはなく、cantTellのものがあります。
composite.rollup.cantTell.notSelectedChildcantTellfailやcantTellのものはなく、スキャンが選ばなかったために実行されなかったものがあります。一部だけチェックされた状態です。
composite.rollup.cantTell.missingChildcantTellfailやcantTellのものはなく、別の理由で実行されなかったものがあります。
composite.rollup.notApplicable.allInapplicablenotApplicableすべての構成ルールがnotApplicableで、ルールが達成基準の当てはまるすべてのケースを見つけます。
composite.rollup.cantTell.partialCoveragecantTellすべての構成ルールがnotApplicableですが、達成基準(またはpartialと示された規格の要件)は、ルールが探さないコンテンツにも当てはまりうるため、該当するものがないとは示されていません。
composite.rollup.cantTell.emptyCompositecantTell集約にルールがありません。
composite.rollup.cantTell.partialCheckcantTellfailもcantTellもなく、すべてがnotApplicableでもありませんが、ルールは達成基準(またはpartialと示された規格の要件)の求めることの一部しかチェックしません。残りは人が確認します。
composite.rollup.pass.otherwisepass上記以外の場合。

判定結果の値

判定結果意味type: "manual"で現れるか
failルールが、チェックする要件を満たしていないと報告しています。検出結果を解釈するには、その対応、確度、検出箇所を読んでください。デフォルトのポリシーでは、いいえ(cantTellに強制変換)
passルールの適用対象が存在し、どれにもフラグが立ちませんでした。はい
cantTell人間の判断が必要です。本当にあいまいな場合か、手動ルールによる参考情報の検出結果のどちらかです。はい
notApplicableこのページ/範囲には、ルールが適用される要素がありませんでした。はい

コアの組み込みルールでは、failは意図的に最も範囲が狭く、最も基準の高い判定結果にしてあります。決定論的で規範的な違反のためだけにあり、ルールのカバー範囲を広げるためにこれを薄めてはなりません。

重大度と確度の値

  • severity:minor < moderate < serious < critical。ユーザーへの影響についてのルール作成者の評価で、confidenceとは独立しています。プロファイルはルールに別の重大度を与えることができます(規格やパックのチェックリストにあるプロファイルのseverity)。その場合、結果にはプロファイルの重大度が表示され、ルール自身の重大度はruleSeverityとして保持され(このときだけ含まれます)、集約はプロファイルの重大度を使います。
  • confidence:low < medium < high。fail/cantTellの判定が正しいことに、エンジンがどれだけ確信を持っているかを示します。どちらも優先順位付けのための情報としてのメタデータで、outcomeの意味を変えることはありません。

failが常にconfidence: "high"とは限りませんが、それは矛盾ではありません。判定結果が表すのは判定の手順(推測せずに問いを解決したこと)であり、confidenceが表すのは、その判定の拠り所となったモデルです。いくつかの自動ルールは、それ自体が近似であるもの(厳選したWAI-ARIAのロールの表、ネイティブ要素のロールの対応、静的なマークアップから推定したアクセシビリティツリー)に対して決定論的に判定し、mediumを報告します。aria-required-children、aria-prohibited-children、aria-required-parent、aria-allowed-attr、form-control-programmatic-label-present、identical-iframes-same-purpose、svg-image-text-alternative-present、video-poster-text-alternative-present、target-size-minimum、text-spacing-content-lossです。confidenceはすべての結果に含まれるので、最も確実な不合格だけが欲しい利用側はこれで直接ゲートできます。policy.allowedConfidenceではこれはできません。許可されていない値は、判定結果を変えるのではなく、ルール自身のdefaultConfidenceに置き換えられるからです(POLICY.mdを参照)。

実例

<img src="logo.png">(altなし)と<button></button>(アクセシブルな名前なし)を、runOnly: { includeRuleIds: [...] }でこの2つのルールだけに絞ってスキャンします(エンジンオプションを参照。1.10.0以降は、ルールIDの配列をそのまま渡しても同じです)。

const result = runDomRulesInPage(
'https://example.test/',
null,
{},
{ includeRuleIds: ['img-alt-present', 'button-name-present'] }
);
{
"engine": {
"tag": "a11ycore",
"version": "1.14.0",
"schemaVersion": "1.0.0",
"locale": { "requested": "en", "resolved": "en", "reason": "ok" },
"wcagVersion": "2.2",
"environment": { "layout": false }
},
"url": "https://example.test/",
"title": "Example",
"timestamp": null,
"perfStats": null,
"contextSelector": null,
"contextMatch": null,
"checksResults": [
{
"ruleId": "button-name-present",
"outcome": "fail",
"severity": "serious",
"confidence": "high",
"type": "automatic",
"occurrences": [
{
"selector": "html > body > button",
"html": "<button></button>",
"structuralPath": [1, 1],
"summary": "This button has no accessible name.",
"hint": "Give the button visible text, or name it with aria-label, so screen reader users know what it does.",
"data": {
"visibilityFilter": { "eligible": true, "reasons": [], "targetSet": "acc", "accEligible": true },
"details": { "reasonCode": "name_missing" }
}
}
]
},
{
"ruleId": "img-alt-present",
"outcome": "fail",
"severity": "serious",
"confidence": "high",
"type": "automatic",
"occurrences": [
{
"selector": "html > body > img",
"html": "<img src=\"logo.png\">",
"structuralPath": [1, 0],
"summary": "This <img> has no alt attribute.",
"hint": "Add an alt attribute that says what the image shows, or alt=\"\" if the image is purely decorative.",
"data": {
"details": { "reasonCode": "TEXT_ALTERNATIVE_MISSING" },
"visibilityFilter": { "eligible": true, "reasons": [], "targetSet": "acc", "accEligible": true }
}
}
]
}
],
"rulesResults": [
{
"ruleId": "wcag-1.1.1-non-text-content",
"outcome": "fail",
"severity": "serious",
"title": "Non-text content: text alternatives",
"occurrences": [],
"data": {
"details": {
"reasonCode": "composite.rollup.fail.anyFail",
"checksIds": ["area-alt-present", "img-alt-decorative", "img-alt-quality", "..."],
"contributors": [
{ "testId": "area-alt-present", "outcome": "missing", "notSelected": true },
"...",
{ "testId": "img-alt-present", "outcome": "fail", "severity": "serious" },
"..."
],
"metrics": { "failCount": 1, "cantTellCount": 0, "notApplicableCount": 0, "passCount": 0, "missingCount": 20 }
}
}
},
{
"ruleId": "wcag-4.1.2-name",
"outcome": "fail",
"severity": "serious",
"title": "Name, role, value: accessible name",
"occurrences": [],
"data": {
"details": {
"reasonCode": "composite.rollup.fail.anyFail",
"metrics": { "failCount": 1, "cantTellCount": 0, "notApplicableCount": 0, "passCount": 0, "missingCount": 23 }
}
}
}
],
"overriddenBuiltinIds": [],
"skippedCustomRules": []
}

(読みやすさのために省略しています。実際の結果では、上に示した完全な形のとおり、すべてのエントリにtitle/description/i18n/meta/engineOptions/schemaVersionも含まれ、各集約のすべての構成ルールも含まれます。rulesResultsには、指定した2つのルールがチェックする達成基準が入ります。img-alt-presentの1.1.1とbutton-name-presentの4.1.2で、どちらもそのルールがfailなのでfailです。それらの達成基準のほかのルールは選ばれていないため、notSelected: true付きのmissingになります。failのルールがなければ、その達成基準はcantTell(notSelectedChild)、つまり一部だけチェックされた状態になります。各チェック結果のrollupIdsは、その集約を示します。)