CMSで編集するコンテンツにアイコンを伴うリンクを入れたい

公開

受託案件の作業中、PowerCMSの本文フィールド内のコンテンツにおいて「リンク先がPDFの場合はPDFアイコンを表示させる」という要件がありました。この度携わった案件以外でも頻繁に発生する内容です。

PowerCMSのテンプレート実装が担当なのでHTML / CSS / JavaScriptは支給されたのですが、PDFアイコンが画像置換と隠しテキストで実装されていることに驚くとともに非常に難儀しました。TinyMCEで編集しているとclass指定のないspan要素は削除されたり、テキストを編集しようとすると隠しテキストまで編集フィールドに出てきたりするのです。ではHTMLを直さなければ…、となるのですが商流の都合で(以下略)。

実装方法を検討する中で2つの案が出ました。

  • CSSでアイコンを追加する
  • JavaScriptでアイコンを追加する

CSSでアイコンを追加する方法は『インクルーシブHTML + CSS & JavaScript』のP.58「自動化されたアイコン」でも紹介されており、「PDF形式」などのテキストを書くcontentプロパティはほとんどのスクリーンリーダーでサポートされていると書かれています。また「編集プロセスを複雑にしない」という点には同意します。ただ「ほとんどのスクリーンリーダーでサポートされている」というのが「アクセシビリティ サポーテッド」なのかということ、またWCAG 2.0 達成方法集の「F87: 達成基準 1.3.1 の失敗例 - CSS の :before 及び :after 疑似要素並びに 'content' プロパティを用いて、非装飾のコンテンツを挿入している」の内容に該当するのではないかということが気になりました。(ちなみにこの度の案件はJIS X 8341-3:2016の適合レベルA準拠を目標とし試験を実施することになっていました。)

JavaScriptを使用してアイコンをimg要素(もしくは支給HTMLの通り)で挿入する方法は一応上手くいくのですが、僕としては「HTMLに書こうよ」という気持ちがあります。JavaScriptが動作せずPDFアイコンが挿入されなかったとしてもリンクは利用できるので問題はなさそうな気もしますが…。(アイコンを付ける付けないはユーザビリティの話なのかなと考えております。)

あれこれ悩んだ結果、僕は「やはりHTMLにimg要素を書いてPDFアイコンを挿入するのが良いよね」という結論に至っています。つい先程ふと思い出して『WEB+DB PRESS Vol.95』の「実践アクセシビリティ」を読み返したのですが、img要素を利用するのが一番簡単で確実な方法として紹介されていました。

img要素でPDFアイコンを自動追加する

Web担当者様がPDFアイコンを挿入してくだされば良いのですが、上手くいかない場合もありそうです。(JIS X 8341-3:2016の適合レベルA準拠を目標とするのに教育が…と思いますが、大人の事情で以下略)そこでPowerCMS / PowerCMS Xのpre_saveフックを利用して、記事の保存時PDFリンクにPDFアイコンが入っていなければ自動で追加する機能を付けることを考えました。

以下のようなPHPを設計し、PDFリンクにPDFアイコンが含まれない場合はPDFアイコンを付与することができました。これを基にPowerCMS Xのプラグイン化は可能と思われます。

<?php
$html = <<<HTML
<p>つきましては、<a href="https://www.anothersky.pw/assets/docs/20190401_01.pdf">改元・10連休にかかる対応</a>をご確認ください。</p>
HTML;

$intro = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body>';
$outro = '</body></html>';

$dom = new DOMDocument;
$dom->loadHTML($intro . $html . $outro);

$pdfIcon = $dom->createElement('img');
$pdfIcon->setAttribute('src', '/common/images/icon_pdf.png');
$pdfIcon->setAttribute('alt', 'PDF形式');

$links = $dom->getElementsByTagName('a');
foreach ($links as $link) {
    $path = $link->getAttribute('href');
    if (preg_match('/\.pdf$/', $path)) {
        $existPDFIcon = false;
        $images = $link->getElementsByTagName('img');
        foreach ($images as $image) {
            if (preg_match('/icon_pdf\.png$/', $image->getAttribute('src'))) {
                $existPDFIcon = true;
            }
        }

        if (!$existPDFIcon) {
            $link->appendChild($pdfIcon);
        }
    }
}

$editedHTML = $dom->saveHTML();
$editedHTML = str_replace($intro, '', $editedHTML);
$editedHTML = str_replace($outro, '', $editedHTML);
echo $editedHTML;

ちなみに、ウェブアクセシビリティ基盤委員会のサイトで公開されている「アクセシビリティ・サポーテッド(AS)情報:H30-5」を見ると、「a要素内にテキストがあり、その後ろにimg要素があるケース」の見解が「要注意」となっています。先日「AS情報を作成するためのテストへご協力のお願い」でテストをした時の結果はどうだったかな…。(MacのFirefox + VoiceOverとWindows のFirefox + NVDAでテストをしました。)

ひとりでは難しい

できることはやりたい、良い感じに実装したい、でもやはりひとりでアクセシビリティ対応をするのは難しいと感じたこの頃です。持田さんにFacebookでこんなお言葉を頂きました。『和久さん風に言うと「正しいことをしたかったら上流になれ」なんてな。』

ちなみに先日のAccTalk in 大都会でお話ししたかったことの一つが本記事の内容でした。ここまで書いておいてJavaScriptを使う方法でも「ダメではないのかな」などと考えております。