ブロックエディタにシンタックスハイライト

wordpressでたまに必要になるよく使うコードを置いてます。

主に自分用です。
どこでも誰でも使えるものもあれば私(の環境)しか使えないものもあります。

スニペットとは「分かっている人が楽をするためのツール」です。
分からない人がコピペするためのものではありません。
コードの意味を理解してご利用ください。

使い方

ブロックエディタ―を使う場合は「カスタムHTML」を使います。

[★SC_CODE lang="php"]
echo 'ハロー';
echo 'ハロー';
echo 'ハロー';
[/SC_CODE★]

1行目の「 [ SC_CODE」 は、そのまま書いちゃうとショートコードが発動してしまうので、★を付けていますが実際には付けません。

勝手に実態参照になるのを停める

functions.php に追記

remove_filter ( 'the_content',  'wptexturize' );

ショートコードの登録

functions.php に追記

/**
 * シンタックスハイライト
 *
 * @see https://aulta.co.jp/technical/web-system-development/wordpress/techniques/syntax-highlighting-in-block-editor
 */
add_shortcode('SC_CODE', function( $atts, $content = '' ){

    if (! is_array($atts)) {
        $atts = array();
    }

    $atts += array(
        'lang' => null
    );

    $lang = $atts['lang'];

    $pre_attr = array();

    $pre_attr['class'] = array();
    $pre_attr['data-language'] = $lang;

    $pre_attr['class'][] = 'language-' . $lang;
    $pre_attr['class'][] = 'line-numbers';

    foreach (array(
        'data-start',
        'data-line'
    ) as $key) {
        if (! empty($atts[$key])) {
            $pre_attr[$key] = $atts[$key];
        }
    }

    // $pre_attr の組立て
    $pre_attr['class'] = implode(' ', $pre_attr['class']);

    $a = array();
    foreach ($pre_attr as $k => $v) {
        $a[] = $k . '="' . esc_attr($v) . '"';
    }
    $pre_attr = implode(' ', $a);

    $content = trim($content);
    $content = str_replace('[', '[', $content);
    $content = str_replace(']', ']', $content);

    // HTMLの組立て
    $ret = '';
    $ret .= '<pre ' . $pre_attr . '>';
    $ret .= '<code class="language-' . $lang . '">';
    $ret .= htmlspecialchars($content, ENT_QUOTES);
    $ret .= '</code>';
    $ret .= '</pre>';

    $ret = do_shortcode($ret);
    return $ret;
});

補足説明

WordPressでプログラムを書いていると、記号を書いたのに #&0000; みたいな形式に変換されます。それはそれで良いのですが、複数の連続した記号を1つの記号にまとめちゃう仕様があったりして困ったことになります。

例えば、ハイフンを2つ連続(--)すると「&#8212;」に、 シングルクォートを2つ連続('')すると「&#8221;」になります。
2文字なのに1文字にまとめられちゃってます。

ということで、この機能を止めます。▼です。

remove_filter ( 'the_content',  'wptexturize' );

ちなみに最初はこの機能を有効にしたまま自力で実態参照から元の文字列に戻そうとしたのですが、「情報が欠落していて不可能」という結論になりました。

例えば、カスタムHTMLに次のように書いたとします。
シングルクォートで囲んで ‘サンプル’ ってなるんですが、よく見ると開く記号と閉じる記号が異なる形なので普通のシングルクォートに戻す処理です。

$content = str_replace('‘', ''', $content);
$content = str_replace('’', ''', $content);

すると変換されて次のようになります。

$content = str_replace(&#8216;&#8216;&#8217;, &#8216;&#039;&#8217;, $content);
$content = str_replace(&#8216;&#8217;&#8217;, &#8216;&#039;&#8217;, $content);

まずは「&#8216;&#8216;&#8217;」の先頭と終わりの部分。

「&#8216;」はシングルクォートの開く側の記号です。
「&#8217;」はシングルクォートの閉じる側の記号です。

ここまでは分かります。

でも、間に挟まれてる「&#8216;」はダメです。

「&#8216;&amp;#8216;&#8217;」
こうなっていたら分かります。

ということで、「無理」との判断でおとなしく自動変換を停止する方向とします。