はじめに
技術ブログや社内Wikiにコードサンプルを載せるとき、「言語ごとにハイライト用ライブラリを選定するのが面倒」「対応言語が少なくて結局CSSを自作する羽目になった」と感じたことはないでしょうか。コードの可読性はそのまま記事やドキュメントの信頼性に直結するため、ここで妥協したくないという方は多いはずです。
そんな悩みに対する答えの一つが、長年にわたって使われ続けている構文ハイライトライブラリ「Highlight.js」です。この記事では、Highlight.jsが今も選ばれ続ける理由と、実際に手を動かして試せる使い方を紹介します。
とはいえ、読むより触った方が早いと思います。textareaにコードを貼り付けると、Highlight.jsが即座に言語を自動検出してハイライトする様子を確認できるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
Highlight.jsとは
Highlight.jsは、ブラウザ上やNode.js環境でコードに構文ハイライトを適用するJavaScriptライブラリです。外部依存を持たず、180以上の言語に標準対応しているのが最大の特徴で、サードパーティ製の言語定義を追加すればさらに幅広い言語に対応できます。
主な特徴
- 自動言語検出 - 言語を指定しなくても、コードの内容から自動的に言語を推測してハイライトしてくれます
- 豊富なテーマ - 100種類近い配布テーマが用意されており、CSSを差し替えるだけで見た目を変更できます
- ゼロ依存 - 他のライブラリに依存しないため、既存のプロジェクトに組み込みやすい設計になっています
- ブラウザ・サーバー両対応 - フロントエンドでの動的ハイライトだけでなく、Node.js側でのビルド時ハイライトにも利用できます
インストール
npmまたはyarnからインストールできます。
npm install highlight.js
yarn add highlight.js
CDN経由で読み込む場合は、cdnjsやjsDelivr、unpkgのスクリプトタグをそのまま利用することも可能です。
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
Highlight.jsのサンプルを動かす
下のtextareaに好きなコードを貼り付けたり書き換えたりしてみてください。入力するたびにHighlight.jsのhljs.highlightAuto()が呼ばれ、言語を自動検出してハイライト済みのHTMLを組み立て直します。検出された言語名もその場で表示されるので、JavaScript・Python・SQLなど異なる言語を試して挙動の違いを確かめてみましょう。
まず、Highlight.jsで自動検出ハイライトを行う際の中心部分だけを抜き出すと、次のようになります。
import hljs from "highlight.js";
// 要素単位でまとめてハイライトしたい場合
document.querySelectorAll("pre code").forEach((block) => {
hljs.highlightElement(block);
});
// 文字列を直接ハイライトし、検出結果を受け取りたい場合
const { value, language } = hljs.highlightAuto(`
const greet = (name) => \`Hello, \${name}!\`;
`);
console.log(language); // 検出された言語名(例: "javascript")
console.log(value); // ハイライト済みのHTML文字列
実際に動かせるサンプルが以下です。テーマCSSはhighlight.js@11.12.0に合わせて同じバージョンのものを<link>で読み込んでいます。
textareaの中身をPythonのコード(def greet(name):など)に書き換えると、検出言語のラベルがpythonに切り替わるはずです。逆に短すぎるコードや言語特有のキーワードが少ないコードを入力すると、hljs.highlightAuto()が誤検出することもあります。その場合は次に紹介するhljs.highlight()で言語を明示的に指定するのが確実です。
基本的な使い方
もっともシンプルな使い方は、ページ内のすべての<pre><code>要素を自動でハイライトする方法です。
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github.min.css">
</head>
<body>
<pre><code class="language-javascript">
function greet(name) {
return `Hello, ${name}!`;
}
</code></pre>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
<script>
hljs.highlightAll();
</script>
</body>
</html>
npmでインストールした場合は、モジュールとして読み込んで使います。
import hljs from "highlight.js";
import "highlight.js/styles/github.css";
hljs.highlightAll();
言語を明示せずに自動検出させたい場合は、highlightAutoを使います。
import hljs from "highlight.js";
const code = `
const sum = (a, b) => a + b;
console.log(sum(1, 2));
`;
const result = hljs.highlightAuto(code);
console.log(result.language); // 検出された言語名
console.log(result.value); // ハイライト済みのHTML文字列
実践的なユースケース
Highlight.jsには自動検出以外にも、言語を明示的に指定したハイライト、テーマの動的切り替え、行番号付き表示といった実務でよく使うパターンがあります。ここではそれぞれを個別のサンプルで確認していきます。
言語を指定してハイライトする
自動検出は便利ですが、コードが短かったり複数言語の特徴が混在していたりすると誤検出することがあります。確実性を重視するなら、hljs.highlight(code, { language })で言語を明示的に指定しましょう。
import hljs from "highlight.js";
// 言語を明示することで検出ミスを防げる
const { value } = hljs.highlight(
"SELECT id, name FROM users WHERE active = true;",
{ language: "sql" }
);
console.log(value); // sql文法でハイライト済みのHTML
下のサンプルでは、セレクトボックスで言語(JavaScript / Python / SQL / HTML)を切り替えると、同じコード欄でも指定した言語の文法規則でハイライトし直されます。
セレクトボックスを「JavaScript」にしたままSQL文を入力すると、キーワードが正しく色分けされず崩れた表示になります。文法が言語ごとに異なるため、languageオプションはコードの中身と必ず一致させる必要があることが分かります。
テーマを切り替えて見た目を変える
Highlight.jsは配布されているテーマCSSを差し替えるだけで見た目を変更できます。JS側のロジックは一切変更せず、読み込む<link>のhrefだけを切り替える仕組みです。
// テーマの<link>要素を用意しておき、切り替え時にhrefだけ書き換える
const themeLink = document.querySelector("#hljs-theme");
function setTheme(name) {
themeLink.href = `https://cdn.jsdelivr.net/npm/highlight.js@11.12.0/styles/${name}.min.css`;
}
setTheme("github-dark"); // 例: ダークテーマに切り替え
ボタンを押すとgithub・github-dark・atom-one-dark・monokaiの4テーマを切り替えられるサンプルです。
monokaiボタンを押すと背景色が濃いグリーン系に変わり、githubボタンを押すと白背景の配色に戻ります。CSSを差し替えるだけで見た目が一新される点が、Highlight.jsのテーマの手軽さです。自作テーマを使いたい場合も、同じ構造のCSSファイルを用意してhrefを差し替えるだけで組み込めます。
行番号を表示する
Highlight.js本体には行番号を表示する機能は含まれていませんが、hljs.highlightElement()でハイライトした結果をCSSのカウンター機能と組み合わせることで、プラグインなしで行番号を実装できます。
// ハイライト後のHTMLを1行ずつ<span>で包み、CSSのcounterで行番号を振る
const lines = hljs.highlight(code, { language: "javascript" }).value.split("\n");
const numbered = lines.map((line) => `<span class="line">${line}</span>`).join("\n");
.line { counter-increment: line; display: block; }
.line::before {
content: counter(line);
display: inline-block;
width: 2em;
color: #6e7681;
}
下のサンプルでは、行を<span class="line">で包んでCSSカウンターを当てています。textareaの中身を書き換えると行数に応じて行番号も自動で増減します。
行を1行削除すると行番号も自動で詰まり、逆に空行を増やすと行番号もその分増えます。実務でも、CSSのcounter()を使ったこの方法ならプラグインを追加せずに行番号表示を実現できます。
サーバーサイドでハイライト済みHTMLを生成する
Node.jsのサーバーサイドでMarkdownをHTMLに変換する際、コードブロックにハイライトを適用する例を見てみましょう。ここではhighlight関数を使い、指定した言語で確実にハイライトを行います。
import hljs from "highlight.js";
function renderCodeBlock(code, language) {
if (language && hljs.getLanguage(language)) {
const { value } = hljs.highlight(code, { language });
return `<pre><code class="hljs language-${language}">${value}</code></pre>`;
}
const { value, language: detected } = hljs.highlightAuto(code);
return `<pre><code class="hljs language-${detected}">${value}</code></pre>`;
}
const sample = "SELECT id, name FROM users WHERE active = true;";
const html = renderCodeBlock(sample, "sql");
console.log(html);
このように、CMSやブログの静的サイトジェネレーターと組み合わせることで、記事投稿時にサーバー側でコードブロックをハイライト済みHTMLへ変換し、クライアントには余計なJavaScriptを送らずに済ませる構成が作れます。フロントエンドの表示速度を優先したい技術ブログやドキュメントサイトとの相性が良い使い方です。
まとめ
Highlight.jsは、ゼロ依存で180以上の言語に対応し、自動言語検出まで備えた息の長い構文ハイライトライブラリです。ブラウザでの動的な組み込みから、Node.js側でのビルド時ハイライトまで柔軟に対応できるため、「まずはシンプルに導入したい」という場面から「サーバーサイドで最適化したい」という場面まで幅広く使えます。コードを見せる場面で迷ったら、まずHighlight.jsを試してみてはいかがでしょうか。
