wordpress WordPressのショートコードでシンタックスハイライト

2013年4月14日

追加情報

WordPress 4.2.3 から以下のショートコードの方法では、シンタックスハイライトがうまく表示されない場合があります。

これは、セキュリティの問題で wp-includes の中の shortcodes.php が大幅に書き換えられたためです。

すでに以下の方法を使っている場合の暫定的な解決方法としては、shortcodes.php を WordPress 4.2.2 のもので書き換えることですが、これはセキュリティ上推奨されません(問題があります)。あくまで、臨時の解決方法になります。

関連記事:http://mervin.info/blog/shortcode-issue-in-wordpress-4-2-3-update/

WordPress におけるクロスサイトスクリプティングの脆弱性

【ご注意】WordPress 4.2.3 から以下の方法ではうまく表示されません。

google-code-prettify を使ってシンタックスハイライトする簡単な方法は、以下をヘッダー部分に記述して、表示する部分を pre 要素で囲み、pre 要素に「prettyprint」というクラスを指定する。

<script type="text/javascript" src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>

関連ページ:google-code-prettify を使ってシンタックスハイライト

但し、行番号や言語を指定するには毎回「<pre class=”prettyprint lang-html linenums”>」のように記述しなければならなかったり、WordPress では pre 要素の内容がうまく表示されないなどがあるため、ショートコードで簡単に記述できるようにする。

google-code-prettify からダウンロードしたファイルの中から「prettify.css」と「prettify.js」をテーマフォルダにアップロード(この例では、テーマフォルダ内にフォルダ「prettify」を作成。themes/テーマフォルダ/prettify/prettify.css、themes/テーマフォルダ/prettify/prettify.js)。

prettyPrint関数を呼び出す以下のJavaScript ファイルを作成し、上記フォルダにアップロード。

// prettyprint.js
jQuery(document).ready(function($) {
  prettyPrint();
});

また、個別ページのみで使用するので、以下を functions.php に記述して google-code-prettify の CSS と JavaScript ファイルを読み込むようにする。

function add_prettify_styles() {  //CSS(prettify.css)のロード
  if(is_admin()) return;  //管理画面にはスクリプトは追加しない
  if(is_single()) {  //個別ページの場合
    wp_enqueue_style( 'prettify_css',
      get_template_directory_uri().'/prettify/prettify.css',
      array(),
    );
  }
}
add_action('wp_print_styles', 'add_prettify_styles');

function add_prettify_scripts() {  //jQuery(prettify.jsとprettyprint.js)のロード
  if(is_admin()) return; //管理画面にはスクリプトは追加しない
  wp_enqueue_script('jquery'); //WordPress内蔵の jQuery をロード(省略可能)
  if(is_single()) { //個別ページの場合のみ
    wp_enqueue_script('prettify_js', //「prettify.js」をロード
      get_template_directory_uri(). '/prettify/prettify.js',
      array('jquery'),
    );
    wp_enqueue_script('prettyprint', //「prettyprint.js」をロード
      get_template_directory_uri(). '/js/prettyprint.js',
      array('prettify_js'),
    );
  }
}
add_action('wp_print_scripts', 'add_prettify_scripts');

functions.php にショートコードを作成する以下の記述を追加。
参考にしたサイト:google-code-prettifyをショートコードで利用する

//google-code-prettifyを使って表示するショートコード「code」の作成(シンタックスハイライト)
function shortcode_code( $atts, $content = null ) { 
  extract(shortcode_atts(array(  //ショートコードのパラメータをデフォルトとマージして、PHPのextractで変数に代入
    'linenums' => '1', // 開始行番号の指定(デフォルトは「1」)
    'lang' => '', // 言語の指定(デフォルトは「空」:指定なし)
  ),$atts));
  $class = 'prettyprint'; // シンタックスハイライトに必須のクラスを指定
  if(!$linenums == '0'){ // '0'の場合は行番号を非表示。
    $class .= ' linenums'; // '0'以外では行番号を表示(番号を指定しなければ「1」行目から)。
    if($linenums > 1) { // 1より大きい場合は、その番号からの行番号を表示。
      $class .= ':'. $linenums;
    }
  }
  if(!$lang == ''){
    $class .= ' lang-' .$lang; // 言語の指定
  }
  $content = htmlspecialchars( $content, ENT_QUOTES );  //  $content = esc_html( $content);だと「文字実態参照」の記述時にうまくいかない
  $content = str_replace( "t", "  ", $content );  // タブを半角スペース2つに置換
    return '<pre class="' . esc_attr($class) . '">' . trim($content) . '</pre>';
}
add_shortcode( 'code', 'shortcode_code' );

「wpautop」などのフィルターの前にショートコードの実行をする必要があるので、以下を functions.php に追加。
参考にしたサイト:WordPress: フィルターより前にショートコードを実行させる

function run_shortcode_code( $content ) {
  global $shortcode_tags;
  $orig_shortcode_tags = $shortcode_tags;  // 現在のショートコードの登録情報をすべてバックアップ
  remove_all_shortcodes();  // 現在のショートコードの登録情報を一時的にすべて削除
  add_shortcode( 'code', 'shortcode_code' );  // フィルターの前に実行するショートコードを登録
  $content = do_shortcode( $content );  // 登録したショートコードの実行
  $shortcode_tags = $orig_shortcode_tags;  // バックアップしておいたショートコードの登録情報を復元
  return $content;
}
add_filter( 'the_content', 'run_shortcode_code', 7 );

これで、以下のように編集画面に記述することで、簡単にコード等をシンタックスハイライトすることができる。
例:[code]プログラムコードをここに記述[/code]

また、開始行番号を指定したり、プログラム言語を指定するには以下のように記述する。
例:[code linenums = ’10’ lang = ‘html’]プログラムコードをここに記述[/code]

linenums :行番号(開始番号)の指定。何も指定しなければ1「1」から始まる。「0」を指定すると非表示。
lang :プログラミング言語を指定

また、デフォルトでは行番号の表示は「5」の倍数のみが表示されるので、全ての番号を表示するにはCSSファイル「prettify.css」の最後の方にある li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none;}の「list-style-type:none;」を「list-style-type:decimal;」にする。(または、この部分を削除かコメントアウトする)

ついでに、見栄えを変更するために以下を追加して行番号の横にラインを出力して色とパディングを調整。

li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{border-left:solid 1px #CCCC66; padding-left:0.5em;color: #999;}