Bloggerでコードブロックをスタイリング




highlight.jsを使ってbloggerでいい感じにコードブロックをスタイリングする。

highlight.jsはhtmlの<pre><code>コードブロックに内包される言語を解析して、スタイリングしてくれるjavascriptのオープンライブラリだ。

はじめる


公式 | Usage / CDNのエントリー向けコードスニペット



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>

<!-- and it's easy to individually load additional languages -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>

<script>hljs.highlightAll();</script>

  • スクリプトhighlight.min.js<code>コードブロックに含まれる言語解析スクリプトで、解析結果を<code>ブロックにclass="language-bash hljs"のようにclass名として付記してくれる。highlight.min.jsはメジャーどころの言語をカバーするエントリー向けの実装が収納されている。
  • 未対応の言語はgo.min.js(GoLangの場合)など必要に応じて追加の言語をインクルードして拡張できる。
    • 対応言語をカスタマイズして静的ファイルとしてダウンロードできるので、自ホストからホスティングもできる。Download a Custom Build
    • hljs.highlightAll();で解析実行する。

これが
<pre><code>{ コード部 }</code></pre>

hljs.highlightAll();でこうなる
<pre><code data-highlighted="yes" class="hljs language-php">{ コード部 }</code></pre>

  • スタイルシートdefault.min.cssはそのclass名のスタイルシートだ。demoから好みのスタイルを探してdefault部分を置き換えてスタイルを適応することができる。

好みのスタイルにする


demoからスタイルを吟味して使いなれたvscodeと思しきvs2015.min.cssをセレクト。



<link href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs2015.min.css' rel='stylesheet'/>

<!-- stackeditでマークダウンをhtmlにエクスポートしたやつ -->
<pre class="language-php"><code class="language-php"><span class="token php language-php"><span class="token delimiter important"><?=</span> ClassName<span class="token punctuation">:</span><span class="token punctuation">:</span>constant_field_name <span class="token delimiter important">?></span></span>

こんなかんじになる

ファイルタイプを付記する

ファイルタイプを付記してこんな感じにする


highlight.min.js解析スクリプトはラベルまで面倒見てくれないのでHEXOとhighlight.jsでシンタックスハイライトし、ついでにファイル名も表示する様を参考にJSでファイルタイプのラベルを補完する。


highlightjsで当てられたスタイルクラスlangage-phpのハイフンをセパレータにしてファイルタイプをラベリングするJS実装を入れる。



document.addEventListener('DOMContentLoaded', () => {

    // highlightjsがpre codeブロックにスタイルクラスをあてる
    hljs.highlightAll();

    // コードブロック解析
    Array.prototype.slice.call(document.querySelectorAll('pre code')).forEach( code => {

        // highlightjsが適用したスタイルクラス(language-{filetype})をもとに{filetype}をdata属性に補完
        Array.prototype.slice.call(code.classList).forEach( className => {
            const asFileType = className.split('language-')[1];
            if (asFileType) code.setAttribute('data-filename', asFileType);
        });

        // コードボディ部を折り返しなしでオーバーフロースクロールなコンテナでラップする
        const wrapperDiv = document.createElement('div');
        wrapperDiv.classList.add('code-wrapper');
        wrapperDiv.innerHTML = code.innerHTML;
        code.innerHTML = '';
        code.appendChild(wrapperDiv);

    });

    // ついでにインラインコードブロックにスタイルクラスを当てる
    let allCodeTags = document.querySelectorAll('code');
    let filteredCodeTags = Array.from(allCodeTags).filter(el => el.parentElement.tagName.toLowerCase() !== 'pre');
    filteredCodeTags.forEach(el => {
        el.classList.add('inline-code');
    });

});



ラベルの表示とコードブロックのスタイリング


/* 疑似要素でコードブロックにファイルタイプをディスプレイ */
pre code.hljs[data-filename]::before {
    content: attr(data-filename);
    padding: 0.3em 1em;
    color: #fff;
    font-size: 0.9em;
    background-color: rgba(255, 255, 255, 0.2);
    border-bottom-right-radius: 8px;
}

/* コードブロックのスタイルを好みに調整 */
pre code.hljs {
    /* ラベルはコードブロックの外辺に沿わせたいのでhljsスタイルクラスを上書いてパディングを無効化 */
    padding: 0 !important;
    /* コードブロックは丸みをもたせてフォントサイズは標準に引き上げ */
    border-radius: 8px;
    font-size: 1em;
}

/* ラップしたコード部 */
pre code.hljs .code-wrapper {
    padding: 1em;
    overflow-x: scroll;
}

/* インラインコードブロック */
.inline-code {
    border: none;
    background-color: #eee;
    border-radius: 4px;
    vertical-align: middle;
    padding: 4px 8px;
    margin: 0 4px;
}
Share:

0 Comments:

コメントを投稿