-->

Click

【色付きで分かりやすい!】ソースコードをハイライト表示させる方法

2020/08/22

Coding


はじめに

 

この記事はプログラムのソースコードを色付きで表示するシンタックスハイライト(Syntax Highlighting)の使用方法の説明です。

 

はてなブログのシンタックスハイライトは少し残念な仕様で使い勝手が悪かったことと、Bloggerは、そもそもシンタックスハイライトが標準装備されてなかったので「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で使用するモジュール

「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」と「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のソースコードを表示しますので、似たような表示にしたい方は参考にして見て下さい。

はてなブログ用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;
	}
}


Blogger用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.6;

    -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;    /*追加*/

}

/* 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;
    border: 1px solid #555;
}

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: "Font Awesome 5 Free";
	content: "\f121";
    padding-right: 0.3em;
}


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: .9em;    /*.8emから変更*/
    padding: 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: .9em;
    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;
	}
	code[class*="language-"],
	pre[class*="language-"] {
        line-height: 1.5;
    }
}

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

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

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

 

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

 

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


まとめ

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


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


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

 

気軽に足跡残してね!

この記事が「気になった・参考になった」と感じた方は、リアクションボタンか、ツイッターで♡いいねを押して、足跡を残して頂けると嬉しいです。

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

Advertisements

Author

自分の写真
このブログのヒーローヘッダーは「きれいなお姉さん」がブラウザのアクセプト比に合わせてランダムに表示されます。
\ Follow me! /

Follower

Labels

PC (8) Internet (7) Blog (6) Windows10 (6) Repair (5) WebDesign (5) YouTube (5) Blogger (4) hatenablog (4) Cooking (3) Review (3) SEO (3) CSS (2) Domain (2) GitHub (2) HDD (2) HTTPS (2) JavaScript (2) MFI (2) Anime (1) Beer (1) Browsersync (1) Coding (1) Customize (1) Editor (1) Git (1) Google (1) Monitor (1) New Year (1) Node.js (1) Nomad Code (1) Smart Watch (1) Twitter (1) iPhone (1) nodist (1)

Sponsored Links

QooQ