after work Lab

少しHでニッチなWebデザインのカスタマイズBlogです

簡単だった!ソースコードに色を付けハイライト表示させる方法

 

はじめに

 

この記事は「はてなブログをカスタマイズして良くするプロジェクト」第1弾で、お題はプログラムのソースコードを色付きで表示するシンタックスハイライト(Syntax Highlighting)の使用方法の説明です。

 

はてなブログのシンタックスハイライトは少し残念な仕様で使い勝手が悪かったため、「prism.js」を導入し見やすいソースコードを表示できるようにしました。

 

同じようなことをやりたい方は是非参考にしてみて下さい。

 

 

シンタックスハイライトとは

 

下のサンプルのように、シンタックスハイライトは意味があるの文字列や構文に色を付けることで、ソースコードの可読性を向上させるものです。

 

<!DOCTYPE html>
<html lang="en">
<head>

<script>
	// Just a lil’ script to show off that inline JS gets highlighted
	window.console && console.log('foo');
</script>
<meta charset="utf-8" />
<link rel="icon" href="favicon.png" />
<title>Prism</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
<script src="scripts/prefixfree.min.js"></script>

<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
<script src="https://www.google-analytics.com/ga.js" async></script>
</head>

 

なお、別に色を付けなくてもコードの実行には全く影響ありません。

 

なぜシンタックスハイライトを導入するのか

 

動機は単純で、ソースコードをシンタックスハイライト表示したら何となくカッコイイからです。(笑)

 

と言うのは半分冗談ですが、読者ファーストを考慮したら、ソースコードは見やすいに越したことはないからです。

 

はてなブログのシンタックスハイライトはどこが残念なのか


はてなブログでは「スーパーpre記法」という「はてな記法」を使って表示することが出来ますが、>||と||の2本のパイプの間に構文を記述するようになってます。

 

最初表示したサンプルはスーパーpre記法で作ったものですが、これが結構面倒臭いんです。

 

残念な所その1

 ブログは見たまま編集で書いてますが、スーパーpre記法を使う場合は、ソースコードを一度はてな記法で作成し、これをコピペしなければならないのです。

 

残念な所その2

 はてな記法はHTMLの知識がない人向けの記述法なので初心者には便利なのかも知れませんが、少し凝ったことをやろうとすると逆に出来なく不便です。

 

例えば、好みに合わせてシンタックスハイライトの色を変更しようとするとメチャ面倒臭いのです。

 

 

大げさに言うと、はてな独自の機能はガラパゴス化しており、メリットは少なく老害(レスポンス低下)になっていると思ってます。(少し言い過ぎかな。。。)

 

“あトん”ははてなブログと心中するつもりはないので、何かあった時生き残れるように「はてなブログの残念な所」を出来る範囲で見直すことにしました。

 

 

シンタックスハイライトについて、何か良い方法が無いかなーと探していたら、外部ツールの利用で簡単に表示できることが分かりました。

 

そこでさっそく当ブログでシンタックスハイライト表示ができる環境を整えて見ました。

 

どのシンタックスハイライターが良いのか

 

Webで検索すると「highlight.js」「google-code-prettify」「EnlighterJS」「prism.js」等の導入記事を多数見つけることができました。

 

行番号表示、言語表示、テキストコピーが出来るものを条件にすると「prism.js」はプラグインでサクッと設定できることが分かりました。

 

prism.jsの使用方法

 

まずは公式ページに行って「DOWNLOAD」をクリックして下さい。

 

シンタックスハイライターprism.js

 

prism.jsで使用するモジュール

 

「Compression level(非圧縮/圧縮)」「Themes(テーマ)」「Languages(言語)」「Plugins(プラグイン)」の4つカテゴリがありますが、必要なモジュールを選択しダウンロードするようになってます。

 

Compression level(非圧縮/圧縮)

 ソースコードをカスタマイズしないのであれば、Compression levelはMinified versionを選択して下さい。

 

 

Themes(テーマ)

 Themes(テーマ)はお好みのものをお選び下さい。

 

“あトん”はコーディングに使っているエディターがSublme Textなので、同じ雰囲気の「Okaidia」を選択しました。

 

Languages(言語)

 Languages(言語)は、デフォルトでMarkup HTML XML SVG MathML CSS C-like JavaScriptが選択されてますが、必要に応じて使用する言語を追加して下さい。

 

当ブログではJSONSass (Scss)を追加しました。

 

Plugins(プラグイン)

Plugins(プラグイン)は利便性が高く利用頻度が多いものを選択して下さい。

 

当ブログではLine Numbers(行番号表示)、Show Language(言語表示)、Copy to Clipboard Button(テキストコピー)を入れました。

 

 

以上でモジュールの選択は終了となりますが、たくさんのモジュールを入れたにも関わらず、トータルの容量は26KB未満の軽量サイズでした。

 

 

最後に、 JavaScriptとCSSのDOWNLOADボタンをクリックし、「prism.js」と「prism.css」を保存して下さい。

 

prism.jsの実行方法

ダウンロードした「prism.js」と「prism.css」はCDN(Content Delivery Network)に置いて外部参照するか、サイト内に埋め込むことで実行できます。

 

ちなみにこの記事では本文にprism.jsを埋め込んでます。(後日外部参照に変更するかも知れません)

 

2020年2月19日追記

prism.jsは埋め込みだと調子が悪い場合があるので、外部参照に変えました。

 

ちなみに公式ホームページには「prism.js」と「prism.css」が利用できるCDNサイトのリンクが貼られてますが、最新バージョンではなかったので利用しておりません。

 

 

ソースコードを表示するお手前

ソースコードは<pre><code></code></pre>要素の間に記述し、HTMLで記事に埋め込んで下さい。

 

「prism.js」でソースコードに行番号を表示する時は<pre>タグにclass=”line-numbers”を入れ、使用言語を表示する時は<code>タグにclass=”language-言語名”を入れて下さい。

 

<pre class="line-numbers">
	<code class="language-HTML(言語名)">
	 <!-- ソースコード start-->
	 <p>段落1</p>
	 <p>段落2</p>
	 <!-- ソースコード end-->
	</code>
</pre>

 

CSSのカスタマイズ

言語表示は左上に固定表示としました。また、max-height60vhに設定し、行数が多いソースコードはスクロール表示になるように変えました。

 

今回使用したCSSのソースコードを表示しますので、似たような表示にしたい方は参考にして見て下さい。

 

/* PrismJS 1.18.0
https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript+json+scss&plugins=line-numbers+show-language+toolbar+copy-to-clipboard */
/**
 * okaidia theme for JavaScript, CSS and HTML
 * Loosely based on Monokai textmate theme by http://www.monokai.nl/
 * @author ocodia
 */

code[class*="language-"],
pre[class*="language-"] {
    color: #f8f8f2;
    background: none;
    text-shadow: 0 1px rgba(0, 0, 0, 0.3);
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
    font-size: 1.4rem; /*1emから変更*/
    text-align: left;
    white-space: pre;
    word-spacing: normal;
    word-break: normal;
    word-wrap: normal;
    line-height: 1.5;

    -moz-tab-size: 4;
    -o-tab-size: 4;
    tab-size: 4;

    -webkit-hyphens: none;
    -moz-hyphens: none;
    -ms-hyphens: none;
    hyphens: none;

    max-height: 60vh;    /*追加*/
    overflow: auto;    /*追加*/
    border: 1px solid #555;    /*追加*/
}

/* Code blocks */
pre[class*="language-"] {
    padding: 1em;
    margin: 3em 0 0.5em;    /*.5em 0から変更*/
    overflow: auto;
    border-radius: 0em 0em 0.3em 0.3em;    /*0.3emから変更*/
}

:not(pre)>code[class*="language-"],
pre[class*="language-"] {
    background: #272822;
}

/* Inline code */
:not(pre)>code[class*="language-"] {
    padding: .1em;
    border-radius: .3em;
    white-space: normal;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
    color: slategray;
}

.token.punctuation {
    color: #f8f8f2;
}

.token.namespace {
    opacity: .7;
}

.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
    color: #f92672;
}

.token.boolean,
.token.number {
    color: #ae81ff;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
    color: #a6e22e;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
    color: #f8f8f2;
}

.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
    color: #e6db74;
}

.token.keyword {
    color: #66d9ef;
}

.token.regex,
.token.important {
    color: #fd971f;
}

.token.important,
.token.bold {
    font-weight: bold;
}

.token.italic {
    font-style: italic;
}

.token.entity {
    cursor: help;
}

pre[class*="language-"].line-numbers {
    position: relative;
    padding-left: 3.8em;
    counter-reset: linenumber;
}

pre[class*="language-"].line-numbers>code {
    position: relative;
    white-space: inherit;
}

.line-numbers .line-numbers-rows {
    position: absolute;
    pointer-events: none;
    font-size: 100%;
    top: 0;
    left: -3.8em;
    width: 3em;
    /* works for line-numbers below 1000 lines */
    letter-spacing: -1px;
    border-right: 1px solid #555;    /*#999から変更*/

    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;

    line-height: 1.6;    /*スマホで行番号がずれるので現状合わせで修正 1.6*/

}

.line-numbers-rows>span {
    pointer-events: none;
    display: block;
    counter-increment: linenumber;
}

.line-numbers-rows>span:before {
    content: counter(linenumber);
    color: #999;
    display: block;
    padding-right: 0.8em;
    text-align: right;
}

div.code-toolbar {
    position: relative;
}

/* toolbarの位置変更で削除
div.code-toolbar > .toolbar {
	position: absolute;
	top: .3em;
	right: .2em;
	transition: opacity 0.3s ease-in-out;
	opacity: 0;
}
*/

/*言語の頭にビッグアイコン追加*/
div.code-toolbar>.toolbar span:before{
	font-family: blogicon;
	content: "\f038" + " ";
}

/*
div.code-toolbar>.toolbar a, div.code-toolbar>.toolbar span:before{
	font-family: blogicon;
	content: "\f038";
}*/

div.code-toolbar:hover>.toolbar {
    opacity: 1;
}

/* Separate line b/c rules are thrown out if selector is invalid.
   IE11 and old Edge versions don't support :focus-within. */
div.code-toolbar:focus-within>.toolbar {
    opacity: 1;
}

div.code-toolbar>.toolbar .toolbar-item {
    display: inline-block;
}

div.code-toolbar>.toolbar a {
    cursor: pointer;
}

div.code-toolbar>.toolbar button {
    background: none;
    border: 0;
    color: inherit;
    font: inherit;
    line-height: normal;
    overflow: visible;
    padding: 0;
    -webkit-user-select: none;
    /* for button */
    -moz-user-select: none;
    -ms-user-select: none;
}

/*div.code-toolbar > .toolbar button,*/
div.code-toolbar>.toolbar a,
div.code-toolbar>.toolbar span {
    color: #bbb;
    font-size: .6em;    /*.8emから変更*/
    padding: 0 .5em;    /*0 .5emから変更*/
    /*background: #f5f2f0; ダブっているので削除*/
    background: #272822;    /*rgba(224, 224, 224, 0.2)から変更*/
    /*box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); 削除*/
    border-radius: .3em 0.3em 0em 0em;    /*.5emから変更[上][右][下][左]*/
    border: 1px solid #555;    /*追加*/
    font-weight: bold;    /*追加*/
}

/*言語の表示を左上に移動*/
div.code-toolbar>.toolbar span {
    position: absolute;
    top: -1.8em;
    left: 0em;
    width: 100%;
}

/*コピーコマンドを右上に移動*/
div.code-toolbar>.toolbar button {
    position: absolute;
    top: -1.7em;
    right: 0.2em;
    color: #bbb;
    font-size: .6em;
    padding: 0 .5em;
}

/*div.code-toolbar > .toolbar span:hover, hover解除*/
div.code-toolbar>.toolbar a:hover,
div.code-toolbar>.toolbar a:focus,
div.code-toolbar>.toolbar button:hover,
div.code-toolbar>.toolbar button:focus,
div.code-toolbar>.toolbar span:focus {
    color: aqua;    /*inheritから変更*/
    text-decoration: none;
    transform: scale(1.2); /*追加*/
    transition: 0.2s ease-in-out; /*追加*/
}

/*PC用に追加*/
@media screen and (min-width:600px) {
    .line-numbers .line-numbers-rows {
        line-height: 1.5;
    }

    div.code-toolbar>.toolbar span {
    top: -2.0em;
	}
}

ソースコードのエスケープ処理

HTMLを記述する場合、<>等の5種類の文字列はタグ等のコードに勘違いされるため、特殊文字に変換(エスケープ処理)しないと正しく表示できないので注意が必要です。

 

記号名 文字列 特殊文字
小なり記号 < &lt;
大なり記号 > &gt;
アンパサンド & &amp;
ダブルクオーテーション " &quot;
アポストロフィ ' &#039;

 

エディッターで変換していたらメチャ時間がかかるので、“あトん”はWEB制作便利ツールHTMLエスケープツールを使ってます。

 

 変換前の欄に変換したいソースコードをペーストすると、<pre>タグ<code>タグ付きでソースコードが変換されます。

 

 

まとめ

 シンタックスハイライトでソースコードを表示すると、色付きできれいに表示されるのでコードを読む時のストレスが少なくなると思います。


prism.jsはテーマを簡単に着せ替えでき、多種の言語に対応しており、プラグインも豊富です。現時点で一番お手軽なシンタックスハイライターではないでしょうか。


プログラミングを知らない人が見ると、ド素人のソースコードでも、まるでプログラミングが出来るかのようなブラシーボ効果を得ることができるかも知れませんね。 

 

♡いいねはこちら

この記事が「面白かった・参考になった」と感じた方は、♡いいねを押して頂けると嬉しいです。

 この記事のツイートを♡いいねする

 

それでは今回の記事はこれでおしまいです。

 

2020年1月18日 追記

スマホだと行数が多いソースコードは行番号がズレて表示されることが分かりました。

 

スマホでソースコードを見る人は少ないと思いますが、見っともないので、line-heightを調整して力づくで直しました。(笑)

 

また、Copyボタンがソースコードに被っていたので、一番右上に移動しました。