HTMLやCSSのシンタックスハイライト表示を自分でつくる

ミニマルな個人サイト作成のための私的備忘録。学び直しと新たな学び。何かあれば書き足します。

何をどうするのか。

Webサイト上のコードを見やすくするために、テック系サイトによくあるようなシンタックスハイライト表示をしてみたいが、学びとして既存のプラグインを使用せずやってみたい。とは言ってもいろんなプログラミング言語に対応するのはハナから無理なのでひとまずHTMLとCSS用を作る

基本的に自分のサイトで使うだけなので超簡易的なもので良い。難しい部分は全部、ChatGPTClaudeなどAI大先生の力を借りる。

前処理

まず前提を決める。普通のテキストと目立つハイライトとコメントアウトの3色にする。

その上で、HTMLは以下のルールで書く。

Javascriptで作る

プログラムはJavascriptで作る。

何をやっているかはコード画面の中のコメント箇所を参考にどうぞ。基本的には、正規表現で色付けしたい場所を取得してHTMLタグを付加して返すという作業だ。

// すべての<pre><code>...</code></pre>要素を取得
const codeBlocks = document.querySelectorAll('pre > code');

// 以下より色付けしたい文字列を見つけてCSSのclassを付加
codeBlocks.forEach(block => {

	// code変数にblock要素の現在のHTML内容を代入
	let code = block.innerHTML;
	
	// 一応、様々なプログラムで使われる「//」で始まるコメントにマッチ
	code = code.replace(
	/(?<!:)\/\/.*/g, 
	'<span class="comment">$&</span>'
	);
	
	// HTMLタグ「<h1>」などにマッチ
	//難しい否定的先読みアサーション
	code = code.replace(
	/&lt;(?!!--[\s\S]+?--&gt;)[\s\S]+?&gt;/g,
	'<span class="htmltag">$&</span>'
	);

	// CSSコメント「/* ... */」のコメントにマッチ
	code = code.replace(
	/\/\*[\s\S]*?\*\//g,
	'<span class="comment">$&</span>'
	);
	
	// HTMLコメント「<!-- ... -->」にマッチ
	code = code.replace(
	/&lt;!--[\s\S]*?--&gt;/g,
	'<span class="comment">$&</span>'
	);
    
	// CSSプロパティ定義「width:」や「--変数名:」にマッチ
	code = code.replace(
	/(\b[a-zA-Z-]+:|--[a-zA-Z-]+:)/g,
	'<span class="cssproperty">$&</span>'
	);

	// htmlの特定の要素を差し替える
	block.innerHTML = code;
});

こんな感じに書き終えたら、分かりやすい適当な名前をつけて.jsファイルとして保存。

CSSの部分とテスト表示

CSSの部分。Javascriptにて設定した要素に対応するclassを忘れずに設定するのがポイント。span.commentspan.htmltagspan.cssproperty、の箇所だ。間違っていなければ以下は色付けして表示されているはずだ。

/* シングルラインコメントの色付けOK */
/*
 ----------------------------------
 マルチラインでのコメントの色付けOK
 問題ありません (^Д^)ギャハ!
 ----------------------------------
*/

/* まとめて色設定して管理を楽に */
:root {
	--background-main: #202020;
	--background-sub: #101010;
	--text-main: #ddd;
	--text-sub: #777;
	--text-code: #699;
}

/* 今回脇役タグのCSS設定は詳細省く */
body {
	color: var(--text-main);
	background-color: var(--background-main);
}

/* preとcodeのフォントと背景色 */
pre, code {
	font-family: monospace;
	background: var(--background-sub);
}

/* code無しのpre単体ではアスキーアートなど使う */
pre {
	margin: 1rem 0;
	padding: 1rem;
	line-height: 1.5;
	white-space:pre-wrap;
}

/* codeはpreの中に入れてコード表示に使うが単体でインラインでも使われる */
code {
	display: inline-block;
	font-size: 1rem;
	padding: 0 0.5rem;
}

/* Javascriptで設定したCSSのclassを設定 */
pre > code > span.comment {
	color: var(--text-sub); 
}
pre > code > span.htmltag {
	color: var(--text-code); 
}
pre > code > span.cssproperty {
	color: var(--text-code); 
}

これも名前をつけて.cssファイルとして保存。

HTMLの部分とテスト表示

HTMLタグなどの特殊文字をそのまま表示させるためには「<p> → &lt;p&gt;」みたいにエンコードをしないといけない。以下のような簡単にコピペでやってくれるサイトやツールを活用する。自分はJavascriptで簡単な変換ツールを作ってローカルでやっている。

作成したJavascriptとCSSへのリンクをHTMLに記述するのを忘れないように。さてうまくハイライト表示されているかな?

<!-- HTMLのコメントOK -->
<!--
	HTMLのコメント
	マルチラインに跨ってても色付けOK
-->
<html>
<head>
<!-- CSSを読み込む -->
<link rel="stylesheet" href="style.css">
</head>
<body>

<p>簡易シンタックスハイライトできてます<p>
<figure>
	<img src="test-01.png" alt="画像">
	<figcaption>テキストなどのコンテンツ</figcaption>
</figure>
<pre><code>
...
プログラムソースなど
...
</code></pre>

<!-- Javascriptを読み込む -->
<script src="codestyle.js"></script>

</body>
</html>

最後に

何の機能も無いが、既存のプラグインに頼らずともわずか3色でかなり見やすくなり、満足。

さらにプログラム言語別に分岐させて以下のようにCSSに追加していけば、それらにも個別に対応はできる。でもさすがに面倒だ。

<style>
	code.javascript { ... }
	code.python { ... }
</style>

<pre><code class="javascript">
	...
</code></pre>

<pre><code class="python">
	...
</code></pre>

環境にもよるし後に設定を更新して色やフォントが変わっているかもしれないが、今回のコード全般が以下の画像のような表示になっていたら成功だ。

追記: その後に色やタブ幅をCSSで変更した。

画像
誰だお前

プラグインサービス

なお、一般的には以下のような実用的なプラグインサービスを使うそうですわ。さんざん試行錯誤したあとの結論としては、今後は自分も普通にこれらを使いますわ。