Skip to content

Lint ルール ​

lint がワークフローにどう組み込まれるかは Lint にあります。このページは ID、スコープ、条件の表です。

スコープ ​

指摘はそれぞれ次の 3 つのどれかについてのもので、どのコマンドが報告するかもそこから決まります。

  • slide: 1 枚のファイル、または script.md のそのセクション。指摘にはその枚の slug が入ります。dekc check <slug> が報告するのはこれだけで、その枚の分だけです。
  • deck: デッキの全スライドが共有するファイル。theme.css、フロントマター、voice/voice.toml、script.md 全体(長さ、最初のスライドより上の見出し)です。slug は入りません。
  • project: dek.toml。コマンドが対象にするデッキがいくつあっても、プロジェクトで 1 回だけ見つかります。

dekc lint は 3 つすべてを報告します。共有ファイルと各スライドのファイルの両方を読むルールはスコープを 2 つ持ちます。theme.css の DEK014 はデッキの指摘、slides/<id>.css の DEK014 はスライドの指摘です。dekc build と dekc ls が数えるのは dekc lint と同じ指摘から rumdl を除いたものです。rumdl の Markdown スタイルのチェックは dekc lint でだけ動きます。dekc ls はプロジェクトの指摘を各デッキの行ではなく専用の project 行に出します。

ルール ​

IDスコープ条件--fix
DEK001slidescript.md のセクションに対応する HTML が slides/ にない骨格を作る
DEK002slideslides/ の HTML、スタイルシート、スクリプトに対応するセクションが script.md にない—
DEK003slidedata-step がその枚のビート id でも有効な位置でもない—
DEK004slideセクション id がデッキ内で重複、またはビート id がセクション内で重複—
DEK005slide同じ枚に data-morph 名が重複、または予約された名前(slide、root、none、auto、match-element)—
DEK006slidedata-slug がセクション id と一致しない—
DEK007slideslides/ のファイルに <section class="slide"> がなく、何も描かれない—
DEK008project, deckdek.toml(voice = { … } のようなインラインテーブルも含む)や frontmatter にある、dek が読まないキー。または dek.toml が設定しているのにデッキが持たず、従っていないデッキ設定。hint がおそらく意図したキー、または frontmatter に足す行を示す。警告—
DEK009slideslides/ の 1 ファイルに <section class="slide"> が 2 つ以上ある。表示されるのは最初の 1 つだけ—
DEK010slideテーマにも、その枚のスタイルシートにも定義のないクラス。またはマークアップに書いた実行時の状態クラス(is-current、is-shown)。これはプレイヤーが付けるもの—
DEK011slideスライド内の <style>、style=、<script>、スライドの中の <link>(完全な文書の head にあるものは head ごと捨てられる)、イベントハンドラ属性(onclick= など)、スクリプトが動く URL(javascript:、vbscript:、HTML を入れた data:、<iframe> や <object> に入れた SVG)—
DEK012deck, slideテーマに .slide の下にないセレクタ(トップレベルでも、@media などのアットルールの中でも。.slide のルールに入れ子にしたルールはその下にある)、またはスライドのスタイルシートにスライドの外まで届くルール(::view-transition-*、:root、html、body、.slide から ~ や + で兄弟へ進むもの、ページ全体に何かを登録するアットルール @font-face・@import・@property・@counter-style・@page・@font-palette-values・@font-feature-values)。どの指摘も行番号と、そのルールを置くべき場所を示す—
DEK013deckテーマのクラス数が frontmatter の max_classes(既定 40)を超過。実行時の状態クラス is-current と is-shown は数えない。語彙ではなくプレイヤーのもの—
DEK014deck, slideトークンの外に書いた生のデザインの値。色(16 進、関数、色名、システムカラー)、フォントファミリー(font-family でも font ショートハンドでも)、絶対・ビューポート・コンテナ・ルート基準の単位の長さ、時間、書き下したイージング。テーマでもスライドのスタイルシートでも、入れ子のルールも含む。カスタムプロパティがトークンになるのは、トークンを置く場所、つまり .slide かビュー遷移の上だけ。content: "#fff" のような文字列はテキストで、値ではない。スライドの表示属性(fill、stroke、color、stop-color、font-family、<font face>、bgcolor)に書いた生の色やファミリーも対象。属性は var() を取れないので、hint は slides/<id>.css へ移すよう案内する。fill="none" と currentColor は通る—
DEK015deck必須トークンが .slide に無い—
DEK016slide動かせないスライドのスクリプト。import、名前付き export、default export がないかオブジェクトでない、関数でない draw、構文エラー、トップレベルの await や例外、スライドのビートにない motion のキーや 0 以上のミリ秒でない値、終わらないトップレベル、.ts ではなく .js で置かれたスクリプト—
DEK017slide同じ t で同じ画面を描かないスライドのスクリプト。タイマー、requestAnimationFrame、Date、performance.now、Math.random を使っている。または、クラスで要素を探している(querySelector、closest、matches、getElementsByClassName)。または文書全体を参照するもの(document.querySelector、document.getElementById、document.body など)。1 枚しかない静止画のページでは正しい要素が見つかるが、全スライドを持つビルドしたデッキでは別のスライドの要素に届く—
DEK018deckデッキに theme.css がなく、スタイルなしで表示され、テーマの規則も検査できない—
DEK019slideテーマにもスライド自身のスタイルシートにも定義のない data-layout。テーマがレイアウトを 1 つ以上定義しているときに検査する—
DEK020deck, slideリモート URL(CDN、リモート画像)。URL を持つどの属性でも、theme.css やスライドのスタイルシートの url() や @import でも—
DEK021deck, slideデッキが読み込むファイルが存在しない。画像、srcset の候補、動画、音声、字幕トラック、ポスター、フレーム、オブジェクト、theme.css やスライドのスタイルシートの url()。プロジェクトの assets/ にあれば、hint がデッキへのコピーを示す—
DEK022deck, slideデッキディレクトリの外に出るパス—
DEK023deck, slideデッキが読み込むローカルのファイル(src、srcset、poster など、または theme.css やスライドのスタイルシートの url())が assets/ で始まらない—
DEK024slide読むもののない見出し。テキストも画像も aria-label もない。最初のスライド以外で id だけの ## 見出しを書くとこうなる。警告—
DEK025slideid のあるビートを数字の data-step で指している。警告—
DEK026slide同じセレクタの同じ宣言が、3 枚以上のスライドのスタイルシートにある。警告—
DEK027deckscript.md を読めない。フロントマター、正しい {#id} のない見出し、スライドより前のビート。問題ごとに 1 件—
DEK028slide前後どちらのスライドにもない data-morph 名。何も morph しない。警告—
DEK029slidearia-hidden="true" の下にある文字。図のラベルや SVG の <text> などで、lint はこれを測らない。描かれない <title> と <desc> は数えない。読めない文字の見本はそこに置くのが正しいので、警告—
DEK030slide描画したとき、要素か文字が聞き手に見える枠の外へはみ出す(どのビートでも)。または overflow が visible でない祖先に文字が切られる—
DEK031slideコントラスト比が 4.5:1 未満。WCAG の large text(24px 以上、または 18.66px 以上の太字)は 3:1 未満—
DEK033slide2 つの文字が重なって描かれる。疑似要素が描くノンブルやランニングヘッドも含む—
DEK032slideスライドスクリプトの draw が、ビートの終わりを描くときにおかしなふるまいをする。例外を投げる、スライドの外のページを書き換える、ビートの始まりを描いたあとに終わりを違う絵で描く—
DEK034slideスクリーンリーダーが何も言えない絵。alt のない <img>、文字も名前もない <svg>、名前のない role="img" の要素。alt=""、aria-hidden="true"、role="presentation" か role="none" は飾りの表明として通る—
DEK040slide読み辞書にない ASCII の単語。警告—
DEK041deckトークの長さが duration の予算から大きく外れている。Timeline があればナレーションの実尺、なければ字数からの見積もりで比べる。警告—
DEK042slide見える内容(リスト、コード、表)はあるのに喋る段落がないビート。警告—
DEK043deckvoice.toml の [beats] のキーが、どのスライドにもビートにも当たらない。警告—
DEK044deck, slidescript.md の # や #### の見出し。意味を持つのは ##(スライド)と ###(ビート)だけなので、それ以外は台本として読み上げられる。警告—
DEK045deckvoice/voice.toml か voice/dict.toml を読めない。それを要する検査は飛ばし、lint の残りは実行する。警告—

条件 ​

  • DEK030 から DEK033 は --visual のときだけ動き、Playwright が必要です。どちらも各ビートの終わり、つまりアニメーションとトランジションをすべて最後まで進めた姿を測ります。静止画に写るものを参照してください。
  • DEK040、DEK042、DEK043、DEK045 は voice/ のあるデッキだけに適用されます。DEK044 はすべてのデッキに適用されます。dekc cues は voice/ の有無に関わらず DEK042 を報告します。
  • DEK041 は duration のあるデッキに適用されます。Timeline があればナレーションを測り(許容幅 20%)、なければ字数からの見積もりを使います(許容幅 35%)。data には actualSeconds、budgetSeconds、source(timeline か estimate)が入ります。
  • DEK008、DEK024 から DEK026、DEK028、DEK029、DEK040 から DEK045 は警告です。"severity": "warning" として報告し、lint を失敗させません。それ以外のルールはすべて error です。声のせいでライブ専用デッキが失敗することはありません。

補足 ​

DEK001 / DEK002 ​

DEK001 は script.md の該当する見出しを指し、data.expected に探した HTML のパスが入ります。--fix は先に sync します。骨格を作り、手付かずの骨格のままで横に何もない孤児は消し、手を入れたスライドには触れません。残った DEK002 は、あなたの手が入ったファイルです。セクションのない HTML が 1 件、自分の HTML を持たないセクション(HTML がないか、生成された骨格のまま)が 1 件なら改名を疑い、両方の診断に run `dekc mv <old> <new>` を hint として付けます。このコマンドは、script.md を先に書き換えていてもいなくても動きます。候補が 2 件以上あるときは、新しいセクションやファイルの削除を勧める代わりに、孤児の hint が候補になるセクションごとの dekc mv を台本の順に並べます。候補が 1 件でもあれば、孤児の data.renames に候補のセクションが入ります。

DEK003 ​

解決できない参照です。要素のないビートは問題なく、位置が連続している必要もありません。hint には、そのスライドで使える id と位置が並びます。

DEK005 ​

data-morph の名前は同じ枚の中で一意でなければなりません。view-transition-name になるので、ブラウザは遷移の両側にちょうど 1 つずつの要素を必要とします。別々の枚に同じ名前を付けるのが本来の使い方です。

使えない名前もあります。プレイヤーはスライドの枠に slide、ブラウザはページ全体に root という名前を付けているので、どちらかを付けるとページの切り替えそのものとぶつかります。none、auto、match-element は view-transition-name のキーワードなので、その要素は引き継がれません。

DEK010 ​

theme.css にそのクラスを定義すれば解消します。その枚でしか使わないなら slides/<id>.css に定義します。共有の語彙を増やすのは設計判断で、lint はその判断が目に見えるようにします。DEK013 はその判断の回数に上限を置きます。スライドのスタイルシートは数えません。hint には定義済みのクラスが並びます。定義済みのクラスの打ち間違い(2文字以内の違い)と見なせるときは、先頭に did you mean slide-title? が付き、data.suggestion にその名前が入ります。slides/<id>.ts から要素を探すためだけのクラスなら、代わりに data-* 属性を使ってください。

is-current と is-shown は語彙ではなく状態です。プレイヤーは画面に出ている枚に is-current を、ビートが進んだ data-step の要素に is-shown を付け、また外します。マークアップに書くと、プレイヤーが決める前にその状態を名乗ってしまうので、DEK010 が data.state: true を付けて報告し、hint は取り除くよう案内します。theme.css か slides/<id>.css で、.slide.is-current [data-step].is-shown のように選んでください。dekc theme はこの 2 つをクラスとは別に並べ、hint にはクラスだけが並びます。

DEK014 / DEK015 ​

hint には、その値の代わりに使えるテーマのトークンが入ります。色なら色のトークン、font-size なら --size-* といった具合です。挙げるのは .slide に公開されたトークンだけです。テーマのもの、スライドのスタイルシートではそのファイル自身のものも含みます。1 つのレイアウトや 1 つの要素、@media の中でだけ設定したトークンは、すべてのルールには届かないからです。theme.css で合うものがなければ、.slide にトークンを足すよう案内します。スライドのスタイルシートでは、この枚のトークンにする書き方も案内します。slides/<id>.css の先頭に .slide { --<name>: 260px; } と書く形で、1 枚でしか使わない値をテーマに入れる必要はありません。

値は CSS が読むとおり、構成要素ごとに読みます。そのため -12px は 12px と同じ長さで、色名は色を取るプロパティでだけ色として数えます。grid-area の tan は領域の名前です。生の値を書けるのは、.slide、.slide[data-layout="split"] のような .slide の複合セレクタ、::view-transition-* 疑似要素の上での --* プロパティへの代入だけです。それ以外のルールで設定したカスタムプロパティは、生の値をルールの外へ運んでしまうので、hint は .slide へ移すよう案内します。ただし、.chance { --seal-box: 120px } で 1 枚のカードの印だけを大きくするように、テーマかその枚の .slide が設定するトークンを部品で変えているルールは、.slide へ移すと変更が失われます。そのときの hint は、ルールの名前を付けた値を .slide に置き(--seal-box-chance: 120px)、ルールのトークンをそれに向ける(--seal-box: var(--seal-box-chance))よう案内します。この形は通ります。data.token にその名前が入ります。単位なしの 0、thin、%、fr、要素自身のフォントに従う単位(em、ch、lh、ex)は通ります。ease-out のようなイージングのキーワードも通ります。cubic-bezier()、steps()、linear() はトークンにする必要があり、hint はイージングを持つトークンを挙げます。生のフォールバック付き var() は通りません。契約の 13 トークンはすべて .slide に公開する必要があります。追加のトークンは歓迎します。

DEK011 ​

見つけた箇所ごとに一件ずつ、行と列つきで報告するので、一度の実行でインラインのスタイルとスクリプトがすべて並びます。data は見つけたものを表します。要素なら { "kind": "element", "name": "style" }、属性なら { "kind": "attribute", "name": "onclick", "value": "go()" } です。スライドは入力を受け取らないので、イベントハンドラには移し先がありません。動きは slides/<id>.ts に書きます。

DEK016 / DEK017 ​

DEK016 はスクリプトが動かないこと、DEK017 は動くものの t 以外に依存している、またはテーマが名前を変えうるクラスで要素を探していることを表します。どちらもスクリプトのファイルを指し、DEK017 は行も示します。import のあるスクリプトも import を除いて評価するので、motion のキーは同じ実行の中で検査されます。

DEK020 / DEK021 / DEK022 / DEK023 ​

自己完結の規約です。リモートも、プロジェクト直下も、隣のデッキも参照できません。ローカルのファイルは assets/ で始めます。シンボリックリンクはリンク先で判定します。assets/ にあってもデッキの外を指すものは DEK022 で、ビルドも開発サーバもそれを読みません。dekc build が全アセットをインライン化でき、プロジェクト直下で立てた開発サーバがそれらを配信できるのは、この制約があるからです。

URL を持つ属性と、ページがその URL をどう扱うかは一つの表で決まります。リソースはスライドを描くために読み込まれるもので、src、srcset の各候補、poster、<object> の data、SVG の <image> と <use> の href です。リソースは存在し(DEK021)、assets/... と書く(DEK023)必要があります。リンクはたどられるだけのもので、<a>、<area>、<link> の href です。リンクもローカルかつデッキの中でなければなりません(DEK020、DEK022)。スライドを読む 2 つの場所、デッキと slides/ のどちらから見てもです。そのため <a href="../other-deck/"> は DEK022 です。http: と https: は、スラッシュがあってもなくてもリモートです。file: の URL は 1 台のマシンにしかないファイルを指し、どのデッキから見ても外にあります(DEK022)。スタイルシートでは、image-set() が文字列で取るアドレスも url() と同じく扱います。どの URL も、それぞれの行と列で報告します。

DEK024 ​

dekc sync は section id をスライドに書きません。そのため id だけの ## 見出し(## architecture)は、スケルトンの <h2 class="slide-title"> が空になります。最初のスライドだけはデッキのタイトルが入ります。ファイルがまだそのスケルトンのままなら、hint は script.md で ## アーキテクチャ {#architecture} のように見出しにタイトルを書き、dekc sync を実行するよう示します。sync がスケルトンを書き直し、id とファイル名はそのままです。id だけの見出しは、引用のようにタイトルのないスライドを意図していることもあるので、hint はもう一つの直し方も示します。スライドから要素を消すことです。消せばそのファイルはあなたのものになり、sync はもう触れません。スライドを編集した後なら、hint は見出しのテキストを書くか、要素を消すよう示します。スライドのスクリプトが描画時に見出しを埋めることもあるので、警告です。

DEK025 ​

data-step の数字は「この枚の k 番目のビート」という意味なので、その上にビートを挿入すると、エラーもなく別のビートに紐付きます。その位置のビートに id があれば、id は同じものを指したまま動かないので、hint がその id を示します(use data-step="turn")。lint が見られるのは今の台本だけです。挿入したあとなら、示される id はいまその位置にあるビートなので、狙ったビートかどうか確かめてください。id のないビートには位置以外の名前がないので、何も報告しません。安定させたいときは {#id} を付けてください。data には step と id が入ります。

DEK026 ​

3 枚がそれぞれ自分のスタイルシートに書いた宣言は、テーマに足りていない直しです。1 枚ずつ受け持つエージェントは、次の枚でも同じ直しをします。セレクタは、その枚のスコープが読むとおりに比べるので、.card と .slide .card は同じセレクタ、.slide > .card は別のセレクタです。@media の中のルールは、同じ @media の中の同じルールとだけ比べます。指摘は各枚の dekc check に、セレクタごとに 1 件出ます。その枚がそこで共有している宣言と、そのどれかを共有しているすべての枚を挙げ、data には selector、declarations、slides が入ります。hint は、ルールを theme.css が持つべき形、つまり .slide の下に書いて示します(.card は .slide .card になり、テーマのスコープの規則 DEK012 を通ります)。そのうえで、各枚から消すよう案内します。移すと、そのセレクタのクラスを使っていて自分では設定していない枚も変わります。hint はそうした枚を名指しし、data.alsoReaches にも並べます。3 枚が打ち消している既定値と、それに頼っている枚とを見比べて決められます。キーフレームは枚ごとに改名されて別のものになるので、対象外です。

DEK027 ​

読めない台本に照らしてデッキのほかの部分は確かめられないので、読めるようになるまでは、これがそのデッキの診断のすべてです。問題は 1 回の実行ですべて、それぞれの行と直し方つきで報告します。フロントマターと見出しは別々に読み、読めない見出しもスライドを開くので、その下のビートまで報告されることはありません。dekc lint は、デッキの中でもプロジェクトのルートでも、どこで実行しても報告し、開発サーバもすべて表示します。dekc build のようにデッキがないと動けないコマンドは、同じメッセージと hint で最初の 1 件で止まります。

DEK028 ​

morph は、要素を次に出るスライドの同じ名前の要素へ運びます。数えるのはすぐ前とすぐ後のスライドだけです。2 枚離れた相手は、同時に画面に出ることがありません。前後のどちらにもない名前はただのフェードになります。書き間違いとの区別は lint には付かないので、属性の位置に警告を出します。前後のスライドに、1〜2 文字違いで、この枚のほかの要素の相手になっていない名前があれば、hint はそれを意図したのか尋ねます(did you mean "p-99", as in slides/b.html?)。なければ、相手を置くべき前後のファイルを示すか、属性を外すよう案内します。予約された名前は DEK005 に任せます。data には morph と、前後のスライドの slug を並べた neighbors が入ります。

DEK030 ​

診断は、原因のある場所に向けます。原因はコントラストと同じやり方で探します。まずスライドスクリプトの draw の変更を戻し、次にその枚の CSS を外し、そのたびに測り直します。draw を戻すと収まる要素はスクリプトの問題で、パスは slides/<id>.ts、data.origin は "script" です。CSS を外すと収まる要素はそのスタイルシートの問題で、slides/<id>.css、"slide" です。どちらを外してもはみ出す要素は、内容そのものがスライドに対して多すぎます。slides/<id>.html、"content" で、hint はそのスライドの中で直す方法だけを示します。内容を削る、ビートやスライドに分ける、slides/<id>.css で大きさを調整する、のいずれかです。すべてのスライドに影響するテーマのトークンの変更は勧めません。文字のない要素は、わざとはみ出す装飾かもしれないので、そうなら aria-hidden="true" を付けるよう hint が案内します。

メッセージには、要素、そのテキストの冒頭、越えた辺、何ピクセル越えたかが入ります。子は親が収まっている辺についてだけ報告されるので、下にはみ出したリストは 1 件です。複数のビートで同じ指摘は、ビートを並べた 1 件の診断になります。箱だけでなく文字列も測るので、URL のように折り返せない文字列は箱が収まっていても数えます。

はみ出しの基準は枠です。スライドの CSS でどれだけ高さを伸ばしても、拡大しても、プレイヤーが見せるのは論理サイズのスライドだけだからです。スライドの中の祖先が overflow: hidden などで切った文字も、同じように、切った祖先の名前つきで報告します。p.note "…" is cut off by div.card past its bottom edge by 40px のようになり、data.clip がその祖先です。省略記号や行数の制限は、作者が求めた切り詰めなので通ります。

装飾 ​

aria-hidden="true" を付けた要素は、中身と疑似要素も含めて装飾とみなし、DEK030 も DEK031 も測りません。スライドの外へわざとはみ出す光彩や、読めないほど薄い文字の見本を見せるスライドは、こう書きます。この印には代償があり、それが乱用の歯止めになります。スクリーンリーダーが読み飛ばすので、聞き手に読んでほしい文字には付けません。

DEK031 ​

閾値は WCAG AA に従います。本文は 4.5:1、大きな文字は 3:1。大きな文字とは、計算後の font-size が 24px 以上、または 18.66px 以上で font-weight が 700 以上のものです。淡い色の大きな数字は通り、同じ色の本文は落ちます。閾値は変更できません。メッセージには要素、そのテキスト、前景色と背景色が入ります。

コントラストは、スタイルではなく描画されたピクセルから測ります。各ビートを 4 通りに描きます。文字をそのままにしたもの、すべての文字を透明にしたもの、白で塗ったもの、黒で塗ったものです。白と黒の描画の差から、文字の色に関係なくグリフのある場所がわかり、その中の画素ごとに、文字の色と下にある色を比べます。グラデーション、背景画像、光の装飾、重なった要素、opacity、ブレンドモード、どの書き方の色も、描かれたとおりに測られます。

文字自身の text-shadow は、文字を引き立てることはあっても、読みにくくする側には数えません。影を落とす文字があれば、影をすべて消したものをもう 1 通り描き、文字の画素ごとに、影と、影の後ろにあるもののうち、よりはっきり読めるほうと比べます。白いスライドの白い文字を読めるようにする光彩は効きます。一方、別の色でずらして落とした影にグリフの半分が乗っていても、比は下がりません。mix-blend-mode で下の色と混ぜた文字は、聞き手に見えるとおり、混ざった色で比べます。混ぜずに描くのは、グリフの場所を求める白と黒の描画だけです。

読むのは、グリフがいちばん濃く覆っている画素だけです。それぞれ、画素全体を覆ったときの色に戻してから比べるので、アンチエイリアスで比が下がることはなく、細いハイフンも本来の色で測れます。報告する比は、それらの画素のうち、悪い方から 2% を除いたすべてが達している値です。グラデーションの上の文字は、いちばん読みにくい部分で判定されます。fg と bg はその画素での 2 色です。2 つの文字が重なっている部分は、ほかに画素がない場合を除いて、どちらの判定にも使いません。counter() から描くノンブルやランニングヘッドのように、::before や ::after が描く文字も、ほかの文字と同じように測り、section.slide::after のように報告します。content に文字か数字があるか、counter()・counters()・attr() から作るときに文字とみなします。引用符や矢印だけのもの、光彩、罫線は背景として扱います。疑似要素は DEK030 の対象になりません。SVG の <text> も、ほかの文字と同じように測ります。

基準に届かない文字があると、ページを 1 層ずつ外しながら測り直し、下げた層に診断の path と hint を向けます。まず、スライドスクリプトの draw が属性に加えた変更、とくにインラインの色を元に戻します。それで基準を超えるなら原因は draw です。draw がインラインで付けた色はどのスタイルシートにも勝つので、直し先は slides/<id>.ts になり、data.origin は "script" です。次に、その枚の slides/<id>.css を外します。それで超えるなら直し先は slides/<id>.css のままで、data.origin は "slide" です。それでも届かなければ、テーマだけでそう描かれています。直し先は theme.css で、data.origin は "theme" です。そこで一度直せば、同じ組み合わせを使うすべての枚に反映されます。スクリプトも自分の CSS も持たない枚は、色をすべてテーマに任せています。

DEK032 ​

スクリーンショット、サムネイル、PDF、--visual が測るページなど、静止画はどれも各スライドをビートの終わりの姿で描きます。描きながら、その draw を確かめます。どれも画素を測っただけでは、そういう見た目を意図したスライドと区別できないので、起きたことそのものを、起きるすべてのビートと一緒に報告します(data.kind)。

  • throw:例外を投げた。スライドは draw が走る前のままになります。
  • reach:スライドの外のページを書き換えた。document から要素を探す draw は、1 枚だけのページでは自分の要素を見つけます。なので --visual は、ビルドしたデッキと同じく全スライドを 1 ページに並べたものも描き、そこで別のスライドの要素に届くことを見つけます。
  • seek:ビートの始まりを描いてから終わりを描くと、最初に描いた終わりと違う絵になった。呼び出しをまたいで状態を持っているので、動画やスクリーンショットや発表者ビューのシークでは再現できません。

発表中の画面はスライドが何をしても止まりません。直す場所は slides/<id>.ts です。data には kind、message、steps が入ります。

DEK033 ​

2 つの文字の行が、縦横それぞれ数ピクセル以上、かつ小さいほうの 5 分の 1 以上重なると、重なって描かれていて、どちらも読めません。1 つの文を 2 つの要素に分けて書いたときのように、接しているだけの行は通ります。::before や ::after が描くノンブルやランニングヘッドも対象で、レイアウト上の箱ではなくグリフが覆う箱で判定します。全幅のランニングヘッドなら、箱は行全体になってしまうからです。箱の重なりで候補になった文字は、それぞれ単独で描いて、グリフが見えている場所を確かめます。グリフが 1 画素も見えていない文字は、重なる相手の文字がほぼ同じ箱に行を収めて、その場所を引き継いでいれば、置き換えられたものとして何とも重なりません。1 つのマスに重ねた数字を、ビートごとに前の数字の上へ箱を塗って数え上げるときは、見えているのは最後の数字だけです。それ以外、たとえばラベルの並びの上に置いた吹き出しに隠れた文字は、聞き手には見えなくなるので、重なりとして報告します。箱に一部だけ隠れた文字も、聞き手には欠けて見えるので、重なりとして報告します。hint は、内容を動かすのか、場所を空けるのかを示します。data には box、other、それぞれの文字、steps が入ります。

DEK034 ​

絵は、スクリーンリーダーが読み上げる言葉の要る内容か、そうでないと表明した飾りか、のどちらかです。lint はそのどちらなのかを判断できず、言葉の良し悪しも判断しません。どの絵にもどちらかであることを求めます。ビルドした HTML は、その言葉を聞き手のスクリーンリーダーにそのまま渡し、dekc pptx は各スライドの画像の代替テキストにします。

  • <img> には alt を付けます。alt="" は飾りで、テーマの full-bleed レイアウトの見本がそう書いています。それ以外の alt は絵が示すものです。aria-label、aria-labelledby、title でも名前になります。
  • 図の <text> のラベルや <title> のように、文字を持つ <svg> はそのまま読まれるので通ります。読むものが何もない SVG には role="img" と aria-label を付けるか、飾りなら aria-hidden="true" を付けます。hint が aria-hidden を勧めるのは文字のない SVG だけなので、従っても DEK029 は出ません。
  • role="img" の要素は、SVG も含めて 1 枚の絵になり、中の文字はスクリーンリーダーに読まれなくなります。なので名前が要ります。aria-label、aria-labelledby、SVG なら <title> です。中に文字があるときは、hint はロールを外して文字を読ませる道も示します。
  • aria-hidden="true" の下にあるもの、role="presentation" か role="none" の要素は飾りとして通ります。SVG の中の SVG は、外側の絵の一部です。

絵 1 つにつき 1 件、そのタグの位置で報告します。data には tag、<img> なら src、role="img" についての指摘なら role が入ります。<video>、<iframe>、<object> は検査しません。動画の代わりになるのは字幕で、それが正しいことを示す属性はありません。フレームやオブジェクトは自己完結したデッキではまれで、ルールがあっても邪魔になるほうが多いからです。

DEK042 ​

喋りになるのは段落だけです。リスト、コード、表しかないビートは、ナレーションでは pause.beat ミリ秒で通過します。空のビートと引用だけのビートは意図的な間として扱い、警告しません。

MIT License