WordPress の記事内に JavaScript を書く

WordPress の記事内にちょっとした JavaScript を記述しようと思ったのだが、なかなかうまくいかなかったので、WordPress の動作と JavaScript を記述する方法を検証してみた。
※本記事は WordPress 3.7.1–ja を利用したときに掲載した記事です。

WordPress の処理

WordPress は記事内の文字列をそのまま出力しているわけではなく、整形して出力している。JavaScript を記述する上で影響のありそうな処理をまとめる。

  • 改行コードは<br/>に置き換える
  • & は> & に変換する

onclick ハンドラーや、<script/>タグなどは削られないようだ。
ただし、onclick ハンドラーを書いて Chrome で「プレビュー」ボタンを押すと、以下のような警告が表示される。

The XSS Auditor refused to execute a script in 'https://www.united-bears.co.jp/blog/?p=2049&preview=true' because its source code was found within the request. The auditor was enabled as the server sent neither an 'X-XSS-Protection' nor 'Content-Security-Policy' header.

Chrome のクロスサイトスクリプティング対策にひっかかって、ハンドラーの中身を消されてしまう。XSS Auditor の動作はきちんと調べていないので不明な点が多いのだが、「プレビュー」ボタンを押さずに URL を直接指定すれば動作する。警告の内容通り、リクエストに含まれる内容と HTML を比較し、リクエストに含まれる内容が直接出力された場合、チェックに引っかかるようだ。なお、対策は書いてあるとおり「X-XSS-Protection」か「Content-Security-Policy」ヘッダーを出力すればいいらしい。

JavaScript の記述

注意事項と対策

JavaScript を記述する際の注意事項は、2つ。

  • 無駄な改行コードを含めない。2つ以上改行コードが続くと<br/>に変換されてしまい、エラーになる
  • & を利用しない

最初の注意事項は、ソースコードが見にくくなる可能性があることを除けばなんの問題もない。2つめは少しやっかいだ。論理積(&)と、論理演算子(&&)が使えないからだ。

論理演算子の方は、if 文をネストするか ? 演算子を使えばよいだけなので、それほど難しくない(コードは汚くなるが)。

if(condition1 && condition2) { return true }
if(condition1) { if(condition2) { return true } }
return condition1 ? (condition2 ? true : false) : false;

論理積(&)を使えない問題は、ド・モルガンの法則でしのいだ。

return m & n;
return ~(~m | ~n);

JavaScript を記述した例

Chrome の XSS Auditor にひっかかると面倒なので(ほかのブラウザも引っかかるかもしれない)、タグにはイベントハンドラーを追加せず、<script/>タグに JavaScript を記述する方法を選んだ。WordPress には jQuery が含まれているので、jQuery も活用することにした。実際の例は、本ブログのツールカテゴリーにある。

一番単純な、「UNIX time と日時表記(地方時)の相互変換」の記事に記述された JavaScript を抜粋してみた。

<script type="text/javascript" src="/blog/wp-includes/js/jquery/jquery.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
var WEEK_DAY = ['日', '月', '火', '水', '木', '金', '土', '日'];
var now = new Date();
jQuery('#unixtime_now').html(now.getTime());
jQuery('#localtime_now').html(
now.getFullYear() + '/' +
('0' + (now.getMonth() + 1)).slice(-2) + '/' +
('0' + now.getDate()).slice(-2) +
'(' + WEEK_DAY[now.getDay()] + ') ' +
('0' + now.getHours()).slice(-2) + ':' +
('0' + now.getMinutes()).slice(-2) + ':' +
('0' + now.getSeconds()).slice(-2) + '.' +
('000' + now.getMilliseconds()).slice(-3)
);
jQuery('#show_unixtime').click(function() {
var result = jQuery('#unixtime_result');
result.html('');
var input = jQuery('#unixtime').val();
if(!input) {
result.html('ミリ秒を入力してください。');
return;
}
... 以下略
});
</script>

ちょっと見にくいが & を使えないことをのぞき、普通に JavaScript をかけるようだ。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.