Blogger 表示の高速化 III (KaTex と Prism.js)私のための覚え書き

published_with_changes 更新日: event_note 公開日:

labelBloggerカスタマイズ

軽いと話題の外部スクリプトへ変更してみます。
  • 数式のレンダリング(数式表示)の Mathjax を KaTex へ変えてみる
  • ソースコードのシンタックスハイライトを Google code prettify から Prism.js に変えてみる
の2件を行おうと思います。

Mathjax から $\KaTeX$

MathJax を使って数式表示をしているのですが、数式の表示に時間がかかる点が気になっていました。 KaTex は MathJax よりもかなり高速らしいので、調べてみると KaTex のサイトに比較アニメーションが載っており、これを見る限り圧倒的に速そうです。



導入にあたって、主に参考にしたブログはここの2件になります。

JekyllでMathJaxからKaTeXに移行した

JekyllでMathJaxからKaTeXに移行した

今まで MathJax というエンジンを使って $\LaTeX$ の数式を表示していましたが、記事を書いている最中に Jekyll + MathJax は非常にレスポンスが遅いので、数式のレンダリング速度を向上させるために $\KaTeX$ に移行しました。MathJax は SVG に対して、KaTeX は H...


KaTeXの導入

KaTeXの導入

Webページ内にあるLaTeXコードを実際の数式へとレンダリングしてくれるJavaScriptライブラリ"KaTeX"の導入方法を紹介.


実際に導入したスクリプト(CND版)はKaTexの本家の物を使いました。

Auto-render Extension · KaTeX

Auto-render Extension · KaTeX

This is an extension to automatically render all of the math inside of text. It

このようなタイトルと説明になっています。ノーマルのKaTexに比べて、デリミタ(数式を呼び出すための”区切り文字”)を追加するスクリプトです。

Auto-render Extension
This is an extension to automatically render all of the math inside of text. It searches all of the text nodes within a given element for the given delimiters, ignoring certain tags like <pre>, and renders the math in place.
これは、テキスト内のすべての数式を自動的にレンダリングするための拡張機能です。
<pre> などの特定のタグを無視して、特定の要素内のすべてのテキスト ノードを特定の区切り文字で検索し、数式を所定の位置にレンダリングします。

”renderMathInElement(document.body, {(改行)delimiters: [” に続けて、auto-render extension でデリミタを書くようです。スクリプトを詳しく見てみると、Mathjaxで使っていたものと同じ内容です。

  • Display モード(段落で数式を使う場合):$$ ~ $$, \[ ~ \]
  • Inline モード(文中で数式を使う場合)  :$ ~ $,\( ~ \)

最も重要なのは、Bloggerに導入する場合はテンプレートがHTMLではなくXMLなので、linkタグの終わりに ”/”を入れて閉じる必要があります。


<!-- katex-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous"/>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js" integrity="sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
          // customised options
          // • auto-render specific keys, e.g.:
          delimiters: [
              {left: '$$', right: '$$', display: true},
              {left: '$', right: '$', display: false},
              {left: '\\(', right: '\\)', display: false},
              {left: '\\[', right: '\\]', display: true}
          ],
          // • rendering keys, e.g.:
          throwOnError : false
        });
    });
</script>
<!-- KATEX auto-render extension End -->


Extensions & Libraries(拡張機能とライブラリ)の中から、Copy-tex : を追加しました。KaTeX でレンダリングされた要素を選択してコピーすると、その LaTeX ソースがクリップボードにコピーされる機能です。Mathjaxは右クリックで表示されたのですが、こちらはクリップボード経由でのエディタ表示ですから、ふたてまかかります。

Google Code-Prettify から Prism.js

ダウンロードとインストール

Prism.jsをインストールする方法は、↓このブログ記事が充実してたので、そのとおりに行おうとしたのですが、最初からつまずいてしまいました。

シンタックスハイライターPrism.jsの使い方と、必要なときにだけ動的に読み込む方法

シンタックスハイライターPrism.jsの使い方と、必要なときにだけ動的に読み込む方法

Web上にソースコードを見やすく掲載するシンタックスハイライターとして「Prism.js」が良さそうなので、備忘録としてそのセットアップ方法を使い方を記載しておきます。Prism.jsは20KB程度と軽いので常時読み込んでいても良いかもしれないのですが、まあ無駄な通信は極力省いた方が良いので「シンタックスハイライターが必要な場面でだけ、Prism.jsを動的に読み込む方法」もついでに紹介しておきます。

この記事によると、セットアップ手順は次の内容なのですが、3番目の項目で思考が止まりました。「自サイトってきっと、Google Blogger のことでしょうが、Blogger は画像しかアップロードできないです。」まさか、Google drive とか、Dorop Box じゃぁダメでしょうね。 

▼Prism.jsセットアップ(設置)の手順
Prism.jsのセットアップ(設置)に必要な手順は、以下の4つです。最初の「オプション選択」部分だけが独特で、後は特に迷う点はないと思います。

  1. Prism.jsの公式ウェブで、使いたいオプションを選択する
  2. 生成されたJavaScriptとCSSファイルをダウンロードする(計2ファイルのみ)
  3. 自分用のPrism.jsを自サイトに設置する
  4. シンタックスハイライトしたいページで一式を読み込む

CDNでインストール

挫折しないでさらに調べると、CNDでインストールできるようです。下記のブログは、とても分かりやすく、かつ詳しく説明されています。

Blogger.comにPrism.jsをCDNで導入する

Blogger.comにPrism.jsをCDNで導入する

SyntaxHighlighterを使ってきました( linuxBean14.04(113)SyntaxHighlighter v4のビルド-p--q )がもう更新もされておらず、ビルドもできないので今後はPrism.jsを使うことにします。ブログ大改造予定なのでとりあえずCDN...

Prism.js は必要なものを選んでインストールする方式なので、つぎのようにしました。

Themes: Coy 
Languages: Markup - markup, html, xml, svg, mathml, ssml, atom, rss
                  CSS - css
                  C-like - clike
                  JavaScript - javascript, js
Plugins: Line Highlight; 指定行をハイライト
             Line Numbers; 行番号を表示
             Show Language; 言語を表示
             Autoloader; 言語をオートロード。CDNで利用する場合に推奨
             Keep Markup; コード中のマークアップ(HTML)を保持
             Normalize Whitespace; 不要な空白削除やインデックスの最適化
             Toolbar; Show LanguageやCopy to Clipboardに使うツールバー
             Copy to Clipboard Button; コピーボタン

 

jsDelivrからこれらのスクリプトのURLを取得します。"Show/Configure Files"をクリックするとスクリプトのリストが表示されるので、上記ブログのとうりにやります。

最後に、テーマHTMLのテンプレートに取得したURLを貼り付けます。
linkタグもscriptタグも次のように、</head> の直上にまとめて置きましたが、問題なく動作しました。



<!-- Prism.js -->
<link href='https://cdn.jsdelivr.net/combine/npm/prismjs@1/themes/prism-coy.min.css,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.css,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.css,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.css' rel='stylesheet'/>
<!-- Prism.js -->
<script src='https://cdn.jsdelivr.net/combine/npm/prismjs@1/components/prism-core.min.js,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.js,npm/prismjs@1/plugins/show-language/prism-show-language.min.js,npm/prismjs@1/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.js,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.js,npm/prismjs@1/plugins/keep-markup/prism-keep-markup.min.js,npm/prismjs@1/plugins/normalize-whitespace/prism-normalize-whitespace.min.js'/>
<script src='https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js'/>

記事ブログへの書き込み用のタグ

<pre>タグと<code>タグを並べて次のように書きます。

<pre class="line-numbers"などのプラグイン><code class="language-言語">
~掲載するソースコード~
</code></pre>
Google Code-Prettify で表示していたソースコードを表示させるために、これまでのタグと比較してみます。

<pre class="prettyprint linenums:">
ここにソースコードを書く
</pre>

言語を自動で判定していたCode-Prettifyに比べて、Prism.jsは<code>タグで言語を指定しなければならないので、<pre>と<code>を両方を書かねばなりません。エディタを使って記事ごとに書き換えが必要です。

<pre>タグには、プラグインのオプションを追加で書けるようです。どのようなclass名が必要なのかは、各プラグインのページに記載があります。複数のプラグインを適用する場合は、半角空白で区切って列挙できます。これは次のようにしました。


  • class="line-numbers"は行番号の表示です。
  • 不要な空白削除やインデックスの最適化のためのプラグイン(Normalize Whitespace)がデフォルトでは働かないように data-remove-indent="false" としています。
  • style="white-space: pre-wrap;" は1行が長いときの折り返しです。
<pre class="line-numbers" data-remove-indent="false" style="white-space: pre-wrap;" ><code class="language-markup">

表示枠の設定

CSSで設定する場合(全てのPrism.jsに有効)

Code-Prettify では縦横の表示枠を決めてその中でスクロールできたのですが、そういったプラグインはありません。ただ、prism.js のサイトでは実現できています。

探してみると、そういった機能を実現するCSSが下記のブログで紹介されています。4行のCSSを加えるそうです。
JavaScript Prism.js, 表示する行数を変更する

JavaScript Prism.js, 表示する行数を変更する

ソースコードをハイライト表示するプラグイン、Prism.jsの表示サイズを変更します。作業はとてもかんたんです。CSSで指定します。JavaScriptはまったくいじりません。ただ細かい微調整が必要で、たんに行の高さ ✕ 行数にすればいいというものではありません。

私は、このCSSを ]]></b:skin> の直上に加えました。
pre[class*="language-"] > code{
    max-height: 32em;
    overflow: auto;
}

記事HTMLで設定する場合

CSSでテーマHTMLのCSSへ設定した場合には、当該テーマ中のすべてのブログ記事に強制的に有効になります。強制的の意味は、個別の記事とかあるいは、その記事の中の任意のソースコードごとに個別の設定ができなくなるという意味です。

例えば、CSSで30行表示のソースコードを全体設定しておいて、ある記事だけHTMLで10行表示のソースコードを作ることはできません。記事の表示用タグに <pre style="max-height: 10em;"> と !important 属性を付加してもダメでした。

CSSでの全体設定を行わず、ソースコードごとに個別設定をする場合には、次のようにすればできました。

<pre style="max-height: 10em;"><code class="language-markup"> 

必要なときだけ、Prism.js を読み込む

冒頭に載せた記事に「シンタックスハイライターが必要な場面でだけ、Prism.jsを動的に読み込む方法」が載っています。表示の高速化のためシンタックスハイライトをPrism.jsに反抗したので、必要なときだけCDNから読み込むことができるならば、一層の効果が期待できます。これを適用してみます。

説明を読むと、このような仕組みとのことです。

  1. ソースコードを書いた記事には、その識別のための目印(クラスと説明されています)を置く
  2. 目印が見つかると、Prism.jsを読み込む。これをJavaScript で作る。


1.の目印については、記事の書き込み用のタグを次のように変えます。どれか一つの書き込み用タグの<pre class="xxxxx" に "prism" を含んでいると、prism.js を読み込み、このデザインでソースコードを表示します。


<pre class="prism line-numbers"などのプラグイン><code class="language-言語">
~掲載するソースコード~
</code></pre>


2.は、上記のlinkタグとscriptタグからCDNのURLを引っ張りだしてきて、説明に沿って所定のコード位置に書き込んだJavaScript を作り、</body> の直上に置きます。

<script type="text/javascript">
	// Webページ内に「class="prism"」の指定されたpre要素が存在すれば
	if( document.querySelector('pre.prism') ) {
	   // ▼CSSファイルを動的に読み込む
	   var pmcss = document.createElement('link');
	   pmcss.rel = 'stylesheet';
	   pmcss.href = "https://cdn.jsdelivr.net/combine/npm/prismjs@1/themes/prism-coy.min.css,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.css,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.css,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.css";
	   document.head.appendChild(pmcss);
	   // ▼ファイルJavaScriptファイルを動的に読み込む
	   var pmjs = document.createElement("script");
	   pmjs.src = "https://cdn.jsdelivr.net/combine/npm/prismjs@1/components/prism-core.min.js,npm/prismjs@1/plugins/toolbar/prism-toolbar.min.js,npm/prismjs@1/plugins/show-language/prism-show-language.min.js,npm/prismjs@1/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js,npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.js,npm/prismjs@1/plugins/line-highlight/prism-line-highlight.min.js,npm/prismjs@1/plugins/keep-markup/prism-keep-markup.min.js,npm/prismjs@1/plugins/normalize-whitespace/prism-normalize-whitespace.min.js,npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js";
	   document.body.appendChild(pmjs);
	}
</script>

試しに、<pre class="prism line-numbers" と書いた記事と <pre class="line-numbers" と書いた記事で比較すると、ちゃんと狙いどおりの動作が確認できました。

<<後日記>>

これを組み込むと遅くなりました。ソースコードを15か所入れている記事では、PageSpeed Insightsがエラーになりました。閲覧するにも、完全に読み込むまでに30秒くらいかかってしまいます。これを組み込まないと、10秒ほどです。


Normalize Whitespaceの設定

特別に入れた Normalize Whitespace の使い方をメモしておきます。

デフォルトでは、プラグインはすべてのコード ブロックの先頭と末尾の空白をすべて削除します。また、各行の余分なインデントと末尾の空白も削除されます。

<pre>タグの中に、data-[setting]の書式で指定します。例:data-remove-indent="false"

remove-trailing; すべての行の末尾の空白を削除(デフォルト;true)

remove-indent; コードブロック全体がインデントされすぎている場合に余分なインデントを削除(デフォルト;true)

left-trim; コードブロックの先頭からすべてのホワイトスペースを削除(デフォルト;true)

right-trim; コードブロックの下部からすべての空白を削除(デフォルト;true)

break-lines; 長い行を一定の長さで改行 (デフォルトは 80 文字)

indent; 各行に一定の数のタブを追加

remove-initial-line-feed; コードブロックの先頭から改行を1つ削除

tabs-to-spaces; すべてのタブを特定の数のスペースに変換 (デフォルトは4スペース)

spaces-to-tabs; ある数のスペースをタブに変換 (デフォルトは4スペース)

 

チュートリアルサイト

Implement PrismJs Syntax Highlighting to your Blogger/BlogSpot

改善効果

今まで、PageSpeed Insights で見てきた同じページでパフォーマンス値を測ってみました。数式を多用しているページです。ソースコードは書いていません。

  • まだ。90台に行きません。
  • レンダリングを妨げるリソースにKaTexは出ていますが、Prism.jsは出てきません。
  • Font Awesome と Google Material Iconが課題です。


Powered by Blogger | Designed by QooQ

keyboard_double_arrow_down

keyboard_double_arrow_down