• モデレーター IKEDA Yuriko

    (@lilyfan)


    2.7 から導入される予定の post_class() 関数がとんでもない仕様であることが判明しました。

    新機能として、投稿に割り当てられるカテゴリー/タグ名をもとにした CSS クラス名が付与されます。これによって、カテゴリーごとにデザインを変更するといったことが自在になります。
    しかし、CSS クラス名はカテゴリー/タグスラッグをもとに生成されるため、日本語名だと、不正な CSS クラス名になってしまいます。

    例: 「携帯」カテゴリー → category-%e6%90%ba%e5%b8%af となる

    しかし、CSS のクラス名は、[-_a-zA-Z0-9] と、ASCII 以外の Unicode 文字しか認められていません。% 記号は不可です。これでは CSS 違反となってしまいます。

    とりあえずチケット8446を発行しました。ただ、妥当な解決案としては「スラッグではなくカテゴリー ID を使う」という方法しかなく、これは重大な機能変更となるため、フォーラムでも報告させていただきます。(バックスラッシュでエスケープするのは可能ですが、ユーザーから見ると使いにくいですよね)

    これの修正が 2.8 とかに先送りされたりするようでは、「WordPress は I18N 軽視がひどい」ということで、真剣に「WordPress ME 復活」を検討せねばならないかもしれません……。(とはいえ、自作プラグインのメンテナンスがおいついてない現状で ME 2.7 を作るなんて時間がありませんが 😉

15件の返信を表示中 - 1 - 15件目 (全22件中)
  • モデレーター IKEDA Yuriko

    (@lilyfan)

    とりあえずチケット8446を発行しました。

    やはりというか、予想通りというか、重大性を理解していない markjaquith 氏に 2.8 に先送りされてしまいました……。あわてて 2.7 に戻そうとしましたが、現時点では 2.7.1 にしか戻せませんでした。
    tai さん、tenpura さん、Nao さんなどにお願いですが、直接開発者に連絡して、この ticket を 2.7 に戻すよう手配できないでしょうか。

    このままだと、カテゴリー/タグスラッグが日本語 (を URL エンコードしたもの) になっていると、軒並み HTML 違反が発生してしまいます (CSS クラス名が不正なため)。

    ticket の方で書かれている解決案も正しくありません。Unicode 文字列を使うのは正しいですが、attribute_escpape() は不正な CSS 名を作ります (% 記号はエスケープされず、# 記号を出力してしまう可能性があるため)。

    # WP 開発者が I18N の重要性を理解していないのは、いつもながらとしても、CSS 規約もきちんと理解していないのはちょっと困るな〜〜。

    モデレーター Seisuke Kuraishi

    (@tenpura)

    tai さん、tenpura さん、Nao さんなどにお願いですが、直接開発者に連絡して、この ticket を 2.7 に戻すよう手配できないでしょうか。

    問題点も認識されチケットでいくつかの解決策も述べられていますのでもう少し待って様子を見るしかないのではないでしょうか。

    現状では各 slug を個別に編集して ascii 文字の名前に書き換えれば問題の回避はできますよね。

    出力例: category-keitai

    実際デザインの切り分けには ID よりこちらの形の方が便利ですし、サイトを再構築した際などに ID がずれてしまっても心配が要りません。

    さしあたって WP Multibyte Patch に ON/OFF 可能な形で slug 部分を ID に変える機能を組み込んでもいいのですが利便性と汎用性を考えると正直どうすべきか悩んでしまいます。
    Unicode 文字の出力も場合によっては不便が起りそうなのでベストとは思えないんですよね。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    問題点も認識されチケットでいくつかの解決策も述べられていますのでもう少し待って様子を見るしかないのではないでしょうか。

    現状のまま新機能が導入されると、この機能をもとにしたテーマやプラグインが出てくるわけで、仕様変更するとしたら 2.7 リリース前の今しかタイミングがないんですよね……。
    一旦リリースされてしまうと「すでにある機能との互換性を重視する」ことが必要となるため、大きな仕様変更は不可能になります。ですので、「どうしても、カテゴリー/タグ ID を使わざるを得ない」という判断を下せるのは、今しかないのです。

    だからこそ、こうやって大騒ぎしているわけです。

    ユーザーの利便性を考えると、slug ないし、それを urldecode した Unicode 文字列を使うのが妥当でしょう。slug のうち % 文字をバックスラッシュでエスケープする、というのは見た目が汚ないのでやりたくありません。それならば、まだ ID の方がはるかにましです。

    現状では各 slug を個別に編集して ascii 文字の名前に書き換えれば問題の回避はできますよね。

    カテゴリーはともかく、タグをいちいち ASCII 文字列のスラッグに変更するのは不可能に近いです。この問題はかなり根が深いんですよ!!

    実際デザインの切り分けには ID よりこちらの形の方が便利ですし、サイトを再構築した際などに ID がずれてしまっても心配が要りません。

    ticket にも書いた通り、そのメリットは十分理解しています。ただし、正当な HTML を出力するという WordPress の特徴を殺してまで導入する機能か? と言われると、わたしの答えは「No」だということです。

    Unicode 文字の出力も場合によっては不便が起りそうなのでベストとは思えないんですよね。

    わたしが気にしているのは、不便よりも脆弱性の温床になるのではないか、ということです。セキュリティーのためにも、CSS クラス名用のエスケープ関数を作る必要があると思います。

    少なくとも Firefox では Unicode 文字列のクラス名を認識するようです (*)。Safari, Opera は未確認です (Internet Explorer は確認する気が起きません ;-)。

    (*) style.css に「.テスト {color:red;}」と書いて、HTML 側で class=”テスト” と書くと、文字色がきちんと赤になります。

    さしあたって WP Multibyte Patch に ON/OFF 可能な形で slug 部分を ID に変える機能を組み込んでもいいのですが利便性と汎用性を考えると正直どうすべきか悩んでしまいます。

    クラス名を挿入する関数は post_class() で、ここにはフィルターがあるので、WP Multibyte Patch で実装しなくても、独立したプラグインを作ればいいかと思います。2.7 リリースに合わせてわたしが作る(!)という手もあります 😉

    モデレーター Seisuke Kuraishi

    (@tenpura)

    2.7 は先ほどリリースされてしまいましたね…

    クラス名を挿入する関数は post_class() で、ここにはフィルターがあるので、WP Multibyte Patch で実装しなくても、独立したプラグインを作ればいいかと思います。2.7 リリースに合わせてわたしが作る(!)という手もあります 😉

    チケットの解決策のプロトタイプが出来ればそれに越したことはないと思いますので是非お願いします。

    素のままだとさすがによろしくないので私の方でも WP Multibyte Patch になんらかの対策コードを入れようと思います。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    2.7 は先ほどリリースされてしまいましたね…

    あうー。RC2 が出たから、リリースまで数日はかかると思っていたのにーー。

    素のままだとさすがによろしくないので私の方でも WP Multibyte Patch になんらかの対策コードを入れようと思います。

    いろいろ確認してみましたが、div class=”category-%e6%90%ba%e5%b8%af” となっていても、W3C の Markup Validation Service は通ってしまいます (XHTML 違反ではない??)。
    しかし、style.css に、% つきのクラスを作った場合 (*) は、CSS Validation Service ではエラーが出ますし、ブラウザーでも有効なクラス指定として認識されません (Firefox 3, Safari 3 で確認)。

    (*) たとえば、以下のような場合。

    .category-%e6%90%ba%e5%b8%af {
    background:blue;
    color:white;
    }

    したがって、現状の 2.7 では、カテゴリー/タグスラッグに %nn という URL エンコードを含んでいる場合は、クラス/タグごとの CSS 切り替え機能が働かない、ということになります。これは 2.7 のバグと言えますね。ぜひとも 2.7.1 で直しましょう!!

    % をバックスラッシュでエスケープした場合は、CSS Validator は通るものの、ブラウザーでの認識がされません。したがって、% をエスケープするという対策は意味がなさそうです。
    % を消してしまう/アンダースコア等に置換するという対策も考えられますが、他のスラッグと衝突してしまう可能性があるため、あまり好ましくないと思います。やはり、urldecode() して、クラス名に使えない文字を削除するという方法しかなさそうです。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    % をバックスラッシュでエスケープした場合は、CSS Validator は通るものの、ブラウザーでの認識がされません。したがって、% をエスケープするという対策は意味がなさそうです。

    さらに調査したところ、XHTML の方は % つきそのまま、CSS の方にだけバックスラッシュでエスケープすれば認識されました。

    XHTML 出力:

    <div class="post hentry category-%e6%90%ba%e5%b8%af" id="post-3">
    なんちゃら
    </div>

    style.css の記述

    .category-\%e6\%90\%ba\%e5\%b8\%af {
    background:blue;
    color:white;
    }

    →なんちゃら、の部分の背景が青くなる。

    なんか不思議ですが、これは正しい実装なんでしょうか?? CSS の方をエスケープするのはいいとして、XHTML の方もエスケープが必要な気がするんですが……。

    CSS の方にだけエスケープするのが正しい実装であるならば、WordPress コアの方は問題ないことになってしまいます。さらに調査が必要になってしまいました。

    とりあえず、回避案を1つ作ってみました。CSS クラス名として使えない文字のチェックがいい加減です。本当は ISO 10646 characters 161 and higher を残さないといけないため、Unicode 文字列として検査する必要がありますが、手抜きしてバイト列の 0x80-0xff を通すことにしています。この場合でも、XSS を埋め込むことは無理だと考えられるので大丈夫だとは思いますが……。

    function fix_post_class($classes, $class, $post_id) {
    	$num_classes = count($classes);
    	if ($num_classes < 1) {
    		return $classes;
    	}
    	for ($i = 0 ; $i < $num_classes ; $i++) {
    		if (strpos($classes[$i], '%') !== 0) {
    			$classes[$i] = preg_replace('/[^-_0-9a-zA-Z\x80-\xff]/', '', urldecode($classes[$i]));
    		}
    	}
    	return $classes;
    }
    
    add_filter('post_class', 'fix_post_class', 10, 3);

    class属性ってCDATAだと思っていたのでちょっと確認してみました。
    http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd
    XHTMLでもclass属性の値はCDATA型のようです。
    ID型やNMTOKN型と違って、結構緩いので’%’が入ってもいいみたいです。

    また、CCS1の仕様7.1の末尾にこんな記述があります。
    http://www.y-adagio.com/public/standards/css1/cssmain.htm#forward-compatible-parsing

    CSS1では,選択子(要素名,クラス及びID)は,A~Z,0~9 及びUnicode文字の161~255にダッシュ(-)を加えたものだけを含めることができる。ダッシュ又は数字で開始はできない。エスケープされた文字及び数字コード(次項参照)としてのUnicode文字も含むことができる。

    備考: HTMLのCLASS属性は,選択子のために許容される集合以外の多くの文字をクラス名として許す。 CSS1では,これらの文字は,エスケープされるか,又はUnicode番号として記述されなければならない。 (略) CSSの今後の版では,より多くの文字を直接入力できることが期待される。

    引っ張った規格はそれぞれ古くて緩い規格ですが(XHTML1.0 traditional/CCS1)、一応 %が使われるのは許されていて、セレクタとして使う時に\エスケープするのは有りのようです。

    # とりあえずざっと調べてみただけです。 XHTML1.1とかCCS2とかはまた後日。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    XHTMLでもclass属性の値はCDATA型のようです。
    ID型やNMTOKN型と違って、結構緩いので’%’が入ってもいいみたいです。

    むむ、ということは、HTML で許されるクラス名の文字種と、CSS のセレクタとして使える文字種が違うということになりますね。なんか不自然……。

    CSS2 については、神崎の解説が分かりやすいですね。「セレクタで使用できる文字

    とりあえず、% 文字列が入っていても *XHTML 的には* 問題ないことは分かりました。あとで trac の方はレベルを調整しておきます。(というか、このレベルの反論が trac ですぐ出てこない、というのもちょっと問題があるような……)

    でも、WordPress の機能としてそれはいいのか? となると疑問はあります。style.css に「.category-携帯 { なんちゃら }」と書くのと、「.category-\%e6\%90\%ba\%e5\%b8\%af { なんちゃら } 」と書くのと、どちらが分かりやすい/使いやすいか、という問題になってきます。

    CSS2の仕様の邦訳より

    CSS2では,要素名,クラス名,及び選択子のIDを含む識別子は,文字[A-Za-z0-9]及びISO 10646の文字符号161以上,さらにハイフン(-)だけ含むことができる。識別子は,ハイフン又は数字から始めることはできない。識別子は,エスケープされた文字及び任意のISO 10646文字を数値符号として含むことができる(次の項目を参照)。 例えば,識別子”B&W?”は,”B\&W\?”又は”B\26 W\3F”として書いてよい。

    となっているので、やはり”\%”も正しいようです。

    セレクタで使用できる文字では、

    「”使用できる文字は大小アルファベットと数字 [A-Za-z0-9] 、ASCII以外のUnicode文字、およびハイフン(-)とアンダースコア(_)に限る。識別名は数字もしくはハイフンと数字の組合せで始めることはできない。また、セレクタの要素型名、クラス名、ID名はハイフンで始めることはできない”」とされています。

    となっていますが、(邦訳を信じるなら)これは仕様の前半だけで後半の解釈が抜けているように見えます。(実装として \エスケープされたクラス名が使用できているのを見ると邦訳の内容が正しいんではないかと推測)

    どちらにしても、XHTML1.1ではclass属性の型がNMTOKENSに変更されたので%エンコーディングは使えないことになるかと思います。
    http://www.kanzaki.com/docs/html/xmodules.html#s_cmnatts

    今の仕様のままだとXHTML1.1をテンプレートで使うと英語圏でも問題になるのではないでしょうか。

    CSS2の仕様が心配なので原文を見てみました。
    http://www.w3.org/TR/CSS2/syndata.html#keywords

    In CSS2, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [A-Za-z0-9] and ISO 10646 characters 161 and higher, plus the hyphen (-); they cannot start with a hyphen or a digit. They can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier “B&W?” may be written as “B\&W\?” or “B\26 W\3F”.

    やはり\&みたいな使い方ができるようです。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    どちらにしても、XHTML1.1ではclass属性の型がNMTOKENSに変更されたので%エンコーディングは使えないことになるかと思います。

    となると、Unicode 文字列にする手もダメですね。% をコロンに置き換えるとかの手がよいでしょうか。post_class() のパラメーターに、XHTML 1.1 に従うかどうかの引数を追加して、これが true の場合は制約をきつくするとかの切り替えにせざるを得ないでしょう。

    モデレーター Naoko Takano

    (@nao)

    出遅れてしまいました、すみません。

    (*) style.css に「.テスト {color:red;}」と書いて、HTML 側で class=”テスト” と書くと、文字色がきちんと赤になります。

    とありますが、これがそのまま正しいのではないでしょうか?

    http://www.w3.org/International/tutorials/tutorial-char-enc/#Slide0510
    日本語は「Ideographic Description Characters」ですよね。

    http://www.atmarkit.co.jp/fxml/rensai/w3cread06/w3cread06.html

    ここでは、Nmtoken(名前トークン)は名前文字の列とする、と記述されている。名前文字は前回説明したと思うが、その文字を任意の回数繰り返したものである。例えば、“XML”はNmtokenになるし、“小泉純一郎”もNmtokenになる。しかし、名前文字に該当しない文字を含んでいるとNmtokenにならない。例えば、“Extensible Markup Language”は名前文字ではない空白文字を含んでいるので、Nmtokenにならない。この特徴によって、この後出てくるNmtokens、つまりNmtokenの複数形が成立するのである。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    とありますが、これがそのまま正しいのではないでしょうか?

    あれれ? NMTOKENS は日本語文字とかがダメと思っていました。ちょっと確認してみると、以下のようです。

    XML の定義における NMTOKENS などの定義

    [4]   	NameChar	   ::=   	Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
    [5]   	Name	   ::=   	(Letter | '_' | ':') (NameChar)*
    [6]   	Names	   ::=   	Name (#x20 Name)*
    [7]   	Nmtoken	   ::=   	(NameChar)+
    [8]   	Nmtokens	   ::=   	Nmtoken (#x20 Nmtoken)*

    ここで、Letter が以下のような定義になっています。確かに日本語文字列が OK そうですね。逆に言うと、NMTOKES かどうかのサニタイズを行うには、UCS2 に変換して以下のテーブルを使うのが正しそうです (もしくは、以下のテーブルを UTF-8 に変換して utf-8 モードの文字列処理をする??)。

    [84]   	Letter	   ::=   	BaseChar | Ideographic
    [85]   	BaseChar	   ::=   	[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]
    [86]   	Ideographic	   ::=   	[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]

    post_class()/get_post_class()のソースを見てみました。

    カテゴリとタグのslugをそのまま使っているみたいですね。
    それがなんか問題な気がするので、slugを使うのではなく、nameをつかってNMTOKENS用に変換するのがよいかなと思います。

    NMTOKENに使えるような文字列に変換する関数ってありますかね?

    モデレーター IKEDA Yuriko

    (@lilyfan)

    カテゴリとタグのslugをそのまま使っているみたいですね。

    そうなんです。そういうズボラなコーディングだからこそ、「I18N に関して無頓着だ」と激怒したわけで……。

    それがなんか問題な気がするので、slugを使うのではなく、nameをつかってNMTOKENS用に変換するのがよいかなと思います。

    name から生成すると、ascii 文字ばかりのカテゴリー/タグ名で問題が出そうです。例えば「Ktai Style」というタグの場合、slug は「ktai-style」となりますが、これは NMTOKEN として valid です。しかし、「Ktai Style」という tag name から NMTOKEN を作るとなると、スペースをどう処理するかが悩みます。けっきょく、slug を生成するときと同じアルゴリズムを採用することになり、それならば slug をいじった方が早いと思います。

    よって、わたしは slug を urldecode() して、NMTOKENS に使えない文字を削除するのが簡単で安全だろうと思ってます。

    NMTOKENに使えるような文字列に変換する関数ってありますかね?

    WordPress 自体は持っていないと思います。PHP の組み込み関数でもない気がします。PEAR パッケージを探ればあるかもしれませんが、未確認です (XML 系が有望な気もしますが)。

15件の返信を表示中 - 1 - 15件目 (全22件中)
  • トピック「post_class() が不正な CSS クラス名を生成」には新たに返信することはできません。