テキストエリアのソースコードの強調表示に適した「CodeMirror」

テキストエリアのソースコードの強調表示に適した「CodeMirror」この記事で紹介する「CodeMirror」は、<textarea>タグを使ったテキストエリアに表示されるソースコードの強調表示に適したJavaスクリプトライブラリである。

公開中のWordPress用プラグイン「CodeMirror for CodeEditor」でも、このライブラリを使用している。

WP SyntaxHighlighter」でも、同様にソースコードを強調表示する「SyntaxHighlighter」と言うライブラリを使用しているが、「SyntaxHighlighter」が任意の場所のソースコードを対象しとているのに対して、「CodeMirror」は、<textarea>タグを使ったエディタ上のソースコードの強調表示に適している。

「WordPress」を例に上げると、「SyntaxHighlighter」が記事内のソースコードなどフロントエンドの強調表示に適しているのに対して、「CodeMirror」は、ダッシュボード上のテーマエディターやプラグインエディターに適していると言える。

テキストエディタでも、強調表示に対応したものが多いが、「CodeMirror」は、それと同様の事をウェブベースのテキストエディタ上で実現できる。

CodeMirrorによる強調表示

「CodeMirror」は、バージョン0.x系のリリースが続いた後に「CodeMirror 1.0」と「CodeMirror 2.0」が同時にリリースされているが、「1.0」と「2.x」ではAPIに違いがあるので互換性がない。

作者によると、今後は「CodeMirror 2.x」の方に力を入れていくようであるため、この記事では、「CodeMirror 2.x」について書く。

「CodeMirror」は、制限が少ないMITライセンスと互換性があり、様々なシステムの中で利用し易い。

「CodeMirror 2.x」には、コアのJavaスクリプト、コアのCSSの他、見た目を変えるための各テーマ用のCSS、各言語を定義したJavaスクリプトが含まれている。

ダウンロードファイルのうち、実際に必要なファイル群は、下記の通りである。

  • libフォルダ・・・基本的なJavaスクリプトとCSS。
  • themeフォルダ・・・各テーマ用CSS。
  • modeフォルダ・・・各言語を定義したJavaスクリプト。

ウェブサイトへの導入は、それほど難しくない。

まず、ヘッダ部分で下記のCSSとスクリプトを読み込む。パスは自身の環境に合わせて変更すること。

<link rel="stylesheet" href="lib/codemirror.css">
<link rel="stylesheet" href="theme/default.css">
<script src="lib/codemirror.js"></script>
<script src="mode/css/css.js"></script>
<script src="mode/javascript/javascript.js"></script>
<script src="mode/xml/xml.js"></script>
<script src="mode/htmlmixed/htmlmixed.js"></script>

「codemirror.css」は、コアのCSSであり、読み込みは必須。

上記の例では、テーマは「default」を使用しているが、他のテーマを使用する場合は、「default.css」に加えて、そのテーマのCSSを読み込むようにする。

「codemirror.js」が、コアのJavaスクリプトになる。

4行目以降で、言語を定義するJavaスクリプトファイルを読み込む。

例では、CSS、Javaスクリプトが混在したHTMLを強調表示するために「htmlmixed.js」を使っているが、この場合は「css.js」、「javascript.js」、「xml.js」の後で読み込む必要がある。

このように「CodeMirror」では、複数の言語が混在するテキストを強調表示することも出来る。

PHPなどC言語に近い構文を持つ言語をサポートする「clike.js」を使う際にも、Javaスクリプトを読み込む順序が問題になるが、言語を定義するJavaスクリプトと同じフォルダに実行サンプルの「index.html」が収まっているので、このソースを確認すると良いだろう。

続いて、ページの後半、テキストエリア部分より後ろに、下記を記述を追加する。

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
	mode: "text/html",
	theme: "default",
	indentUnit: 4,
	indentWithTabs: false,
	tabMode: "shift",
	enterMode: "keep",
	electricChars: false,
	lineNumbers: true,
	firstLineNumber: 1,
	gutter: false,
	fixedGutter:false,
	matchBrackets: true
});
</script>

2行目で、<textarea>タグのid属性の属性値を記述する。例では「code」になっている。

3行目以降は、パラメーターの定義である。

以下に、パラメーターの一部をまとめる。

  • mode・・・言語を言語名またはMINEタイプで指定。値:”javascript”、”text/javascript”等。
  • theme・・・テーマを指定。値:”default”/”cobalt”/”eclipse”/”elegant”/”neat”/”night”。
  • identUnit・・・タブによるインデントのサイズを半角スペースの数で指定。値:数値。
  • indentWithTabs・・・行の先頭の半角スペース8個分が1つのタブで置き換えられる。値:true/false。
  • tabMode・・・Tabキーを押した時の動作を指定。値:”classic”/”shift”/”indent”/”default”。
  • enterMode・・・改行した時の動作を指定。値:”indent”/”keep”/”flat”。
  • electricChars・・・構文上、意味を持つ「{ }」などが入力された際に、自動的にインデントする。値:true/false。
  • lineNumbers・・・行番号の表示、非表示。値:true/false。
  • firstLineNumber・・・行番号の開始番号。値:true/false。
  • gutter・・・「gutter」は、行番号の表示エリアを指すが、厳密には、行番号をクリックすることで印を付ける事が出来るマーカーエリアの表示、非常の指定。「true」ならlineNumbersが「false」の場合も「gutter」は表示される。値:true/false。
  • fixedGutter・・・「true」なら水平スクロールバーでスクロールしても、「gutter」は表示されたままになる。値:true/false。
  • matchBrackets・・・「true」なら「(」、「)」、「{」、「}」、「[」、「]」が選択された時に、対応する括弧と共に強調表示する。値:true/false。

なお、動作と記述は、配布サイトのデモページやダンロードファイルのdemoフォルダ内のファイルで確認できる。

以下のサンプルでは、ドロップダウンリストでテーマの変更、「Esc」または「F11」キーで、通常モード/フルスクリーンモードの切り替えが可能になっている。

<!doctype html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CodeMirror 2</title>
<link rel="stylesheet" href="lib/codemirror.css">
<link rel="stylesheet" href="theme/default.css">
<link rel="stylesheet" href="theme/neat.css">
<link rel="stylesheet" href="theme/elegant.css">
<link rel="stylesheet" href="theme/night.css">
<link rel="stylesheet" href="theme/cobalt.css">
<link rel="stylesheet" href="theme/eclipse.css">
<script src="lib/codemirror.js"></script>
<script src="mode/css/css.js"></script>
<script src="mode/javascript/javascript.js"></script>
<script src="mode/xml/xml.js"></script>
<script src="mode/htmlmixed/htmlmixed.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<style type="text/css">
	.CodeMirror {
		width: 800px;
		}
	.fullscreen {
		position: fixed;
		top: 50px;
		left: 0;
		width: 100%;
		height: 100%;
		z-index: 100;
	}
</style>
</head>
<body>
<p>Select a theme: <select onchange="selectTheme(this)">
	<option selected>default</option>
	<option>night</option>
	<option>neat</option>
	<option>elegant</option>
	<option>cobalt</option>
	<option>eclipse</option>
</select>
</p>
<form>
<textarea id="code" name="code">
<html style="color: green">
<!-- this is a comment -->
<head>
<title>HTML</title>
<style type="text/css">
	h1 {font-family: comic sans; color: #f0f;}
	div {background: yellow !important;}
	body {
	max-width: 50em;
	margin: 1em 2em 1em 5em;
	}
</style>
</head>
<body>
<h1>Sample Code</h1>
<div class="content">
	<p><a href="http://codemirror.net/">CodeMirror 2.x by Marijn Haverbeke and released under a MIT-style license.</a></p>
</div>
<script>
	function jsFunc(arg1, arg2) {
		if (arg1 && arg2) document.body.innerHTML = "achoo";
	}
</script>
</body>
</html></textarea>
</form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
	mode: "text/html",
	theme: "default",
	indentUnit: 4,
	indentWithTabs: false,
	tabMode: "classic",
	enterMode: "indent",
	electricChars: true,
	lineNumbers: true,
	firstLineNumber: 1,
	gutter: true,
	fixedGutter: true,
	matchBrackets: true,
	onKeyEvent: function(i, e) {
		// Hook into F11
		if ((e.keyCode == 122 || e.keyCode == 27) && e.type == 'keydown') {
			e.stop();
			return toggleFullscreenEditing();
		}
	},
	onGutterClick: function(cm, n) {
		var info = cm.lineInfo(n);
		if (info.markerText)
			cm.clearMarker(n);
		else
			cm.setMarker(n, "<span style=\"color: #900\">●</span> %N%");
		}
});

function selectTheme(node) {
	var theme = node.options[node.selectedIndex].innerHTML;
	editor.setOption("theme", theme);
}

function toggleFullscreenEditing() {
	var editorDiv = jQuery('.CodeMirror-scroll');
	if (!editorDiv.hasClass('fullscreen')) {
		toggleFullscreenEditing.beforeFullscreen = { height: editorDiv.height(), width: editorDiv.width() }
		editorDiv.addClass('fullscreen');
		editorDiv.height('100%');
		editorDiv.width('100%');
		editor.refresh();
	} else {
		editorDiv.removeClass('fullscreen');
		editorDiv.height(toggleFullscreenEditing.beforeFullscreen.height);
		editorDiv.width(toggleFullscreenEditing.beforeFullscreen.width);
		editor.refresh();
	}
}
</script>
</body>
</html>

フルスクリーンモードへの切り替えのために「onKeyEvent」、マーカーの表示のために「onGutterClick」というパラメーターを使用しているが、「CodeMirror」では、同様のパラメーターが他にも用意されており、イベント発生時の処理を定義出来るようになっている。

なお、フルスクリーンモードへの切り替えは、「jQuery」に依存している。

上記の例では、「jQuery」を「Google Libraries API」を利用してネットから読み込んでいるので、オフラインでは動作しない。



ネット・PCPermalink