この記事は最後に更新してから1年以上経過しています。
説明
管理ページの「テーマエディター」では4.9以降「CodeMirror」が利用されている。今回はこの「CodeMirror」をプラグインで活用できないか調べた話である。
ソースコードを眺める
「テーマエディター」のページを開くと、テーマのstyles.cssの内容を表示し、少し間をおいて行番号を表示しなおしている。このことからJavaScriptを使用していることが予想でき、そのあたりに着目して/wp-admin/theme-editor.phpを見ていくと、wp_enqueue_code_editor関数が見つかった。
さらにwp_enqueue_code_editor関数の中を見てみると、 wp_enqueue_script関数と wp_enqueue_style関数を使って'code-editor'を出力用のキューに入れている。この'code-editor'は/wp-includes/script-loader.phpで次のように指定されている。
$scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
$scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' );
$scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.0' );
$scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' );
$scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' );
$scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
$scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror', 'underscore' ) );
$scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'wp-util', 'wp-sanitize', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
どうやら'wp-codemirror'の名前で定義されている「CodeMirror」がエディターの本体で、関連するスクリプトも定義されているようだ。
「CodeMirror」はfromTextAreaメソッドを使用してエディターの初期化を行う。「テーマエディター」では/wp-admin/js/code-editor.jsで以下のように指定している。
codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror );
WordPressの管理ページ内にあるtextarea要素を変更する場合、wp_enqueue_code_editor関数を使用するのが手っ取り早いが、今回は下位レベルの'wp-codemirror'として登録されているものを使用して基本的な使い方を理解しようと思う。
「クイックドラフト」のtextarea要素を変更
最終的には自身のプラグインで「CodeMirror」を使いたいのだが、まずは身近にあるダッシュボードの「クイックドラフト」で試してみる。
「クイックドラフト」のtextarea要素を「CodeMirror」に変更するため、スクリプトとスタイルの組み込みには'admin_enqueue_scripts'アクションを使用するのだが、その前段階として'wp_dashboard_setup'アクションを使用し、ほかのページに影響を与えないようにする。
add_action( 'wp_dashboard_setup', 'textarea2_setup' );
function textarea2_setup() {
add_action( 'admin_enqueue_scripts', 'textarea2_enqueue' );
}
実際にスクリプトとスタイルを組み込むtextarea2_enqueue関数の内容は次の通り。'wp-codemirror'の名前で登録されているものを、それぞれwp_enqueue_script関数とwp_enqueue_style関数を使って出力キューに入れる。
function textarea2_enqueue() {
wp_enqueue_script( 'wp-codemirror' );
$inline_script = <<<EOT
window.addEventListener( 'load', function () {
const textarea2_editor = wp.CodeMirror.fromTextArea( document.getElementById( 'content' ), {
lineNumbers : true,
lineWrapping : true,
extraKeys : { 'Ctrl-F': 'findPersistent', 'Cmd-F': 'findPersistent' },
} );
textarea2_editor.display.input.getField().addEventListener( 'blur', function () {
textarea2_editor.save();
} );
} );
EOT;
wp_add_inline_script( 'wp-codemirror', $inline_script );
wp_enqueue_style( 'wp-codemirror' );
$inline_style = <<<EOT
.CodeMirror {
width : 100%;
height : 5.75rem;
border : 1px solid #ddd;
box-sizing : border-box;
margin-bottom : 8px;
}
EOT;
wp_add_inline_style( 'wp-codemirror', $inline_style );
}
wp_add_inline_script関数で追加しているスクリプトでは、loadイベントを使用し、CodeMirrorインスタンスを生成する。連想配列で指定しているパラメータは多いため、ここでは主なパラメータのみを紹介する(あくまで主観的)。
キー | 値の意味 | デフォルト値 |
---|---|---|
lineNumbers | 行番号を表示する場合はtrue、非表示はfalse | false |
firstLineNumber | 先頭の行番号 | 1 |
lineWrapping | 1行の文字数がエディターの幅を超えた際に折り返す場合はtrue、スクロールする場合はfalse | false |
extraKeys | 特別なキーアサインを指定 | なし |
dragDrop | ドラッグ&ドロップを許可する場合はtrue | true |
tabSize | タブ文字の幅 | 4 |
mode | モード(協調表示しない場合はnullを指定) | 'css' |
theme | テーマ名(ラッパーとなるdiv要素のclass名の一部)を指定(cm-s-〇〇〇〇) | 'default' |
readOnly | 読み込み専用の場合はtrue | false |
extraKeysにはキーの組み合わせとそのアクションを複数指定できる。上記の指定は、Ctrl+Fキーおよびcommand+Fキー押下時にエディター内のワード検索ボックスを表示する指定となる。
CodeMirrorインスタンスを生成した後にblurイベントについて記述している。これはCodeMirrorインスタンスで編集した内容と元のtextarea要素を同期するための「おまじない」で、フォーカスが外れたタイミングで同期を行い、「下書きとして保存」ボタンをクリックした際に正しく保存できるようにした。
wp_add_inline_style関数で追加したスタイルは、CodeMirrorエディターの外観用である。標準では少し高すぎるので、ここで高さと下マージンなどを調整している。実際に上記のコードを適用した画面がこちらである。
もとのtextarea要素のプレースホルダーが引き継がれ、行番号が表示されている。
まとめ・雑感
最後に「CodeMirror」を使ってみて気づいたことを1つ紹介。それは非表示のtextarea要素に対してCodeMirrorインスタンスを生成すると、行番号の表示が乱れてしまうことだ(この症状はブラウザ依存かもしれない)。これはtextarea要素が非表示の場合、行番号部分を表示する幅を正しく取得できないことが原因。対象のtextarea要素を表示状態に変更してからCodeMirrorインスタンスを生成することでこの問題は回避できる。
さて「CodeMirror」はcssやJavaScriptのLINT機能も備えており、必要に応じて追加可能である。今回はお試しということで基本機能のみを使ってみたが、実際に実装する際はそれらも検討したい。
最終更新 : 2019年11月05日 09:59
関連
お勧め
add_shortcode(2018年5月27日 更新)
get_user_setting(2022年1月31日 更新)
have_posts(2018年5月27日 更新)
in_category(2018年5月27日 更新)
add_feed(2024年6月24日 更新)