スキップしてメイン コンテンツに移動

MarkdownライブラリmarkedでGoogle Code Prettifyを使う

Google Code Prettify についての誤りを訂正しました。次のようなマークアップもサポートしています。<pre class="prettyprint"><code class="language-js">var a = 0;</code></pre>(2022/11/05)

language- について追記しています。(2022/04/27)

コードを微修正しました。(2022/04/09)

Javascript 製マークダウンコンパイラ marked のデフォルトのコードブロックの HTML 出力では、Google Code Prettify でハイライト出来ません。

Google Code Prettify 用の HTML を出力するべく marked のレンダラーを上書き設定する方法を紹介します。marked のバージョンは 4.0.12 です。

Google Code Prettify は動作するブラウザの下限が IE6, Firefox2 とご機嫌で使い続けていますが、流石に不満が出てきたので、IE5, Gecko 0.6 対応版を書いています。

マークアップの確認

~~~js
var a = 0;
~~~

デフォルト設定の marked は先のマークダウンから次の HTML を出力します。

<pre><code class="language-js">
var a = 0;
</code></pre>

一方で Google Code Prettify が要求する HTML は次の通りです。

<pre class="prettyprint lang-js"><code>
var a = 0;
</code></pre>

markedのレンダラーの上書き

markedの設定をする

まずはクラス名に記入する言語のプレフィックス部分が異なる為、 langPrefix プロパティで設定します。デフォルトの language- から prettyprint lang- にします。オプションに次のパラメータを渡します。

marked.setOptions({langPrefix : 'prettyprint lang-'});

レンダラーの上書き

そもそもクラス名を付す要素が異なりますので、const marked = require('marked').marked; に続けて、コードブロックのレンダラーの上書きをします。

オリジナルのレンダラーは、同一フォルダの helper.js から escape(code, true) 関数を使用していました。これを上書き関数でも使いたかったのですが、require してみると marked パッケージが js module だから駄目だよ、と怒られてしまいます。残念ながら、レンダラーが実際に使用している関数群は利用できませんでした。

仕方なくオリジナルのレンダラーの関数そのものを控えておいて、これをコールして、この戻り値を書き換える、という方法を取りました。次がコードの全てになります。

コード全体

const marked   = require( 'marked' ).marked;
const renderer = new marked.Renderer();

const originalRenderCode = renderer.code;

renderer.code = function(code, infostring, escaped){
  const classStart = '<pre><code class="';
  var html = originalRenderCode.call(this, code, infostring, escaped);

  if(0 <= html.indexOf(classStart)){
    const classEnd = html.indexOf('"', classStart.length);
    const langClass = html.substring(classStart.length, classEnd);
    html = html.replace(
      '<pre><code class="' + langClass + '">',
      '<pre class="' + langClass + '"><code>'
    );
  };
  return html;
};
marked.setOptions({renderer : renderer, langPrefix : 'prettyprint lang-'});

以上でマークダウンから出力したコードブロックを Google Code Prettify でハイライト出来るようになりました。デフォルトで <code> にクラス名を付けるのはやや解せませんが、カスタマイズが出来るので良しです。


デフォルトで <code> にクラス名を付けるのも language- を使うのも、HTML(WHATWG Living Standard)仕様中で提案されていることでした。Google Code Prettify 側の言語の決定方法を変更した方が良さそうです。(2022/04/27)

Google Code Prettify も提案に対応していました。(2022/11/05)

There is no formal way to indicate the language of computer code being marked up. Authors who wish to mark code elements with the language used, e.g. so that syntax highlighting scripts can use the right rules, can use the class attribute, e.g. by adding a class prefixed with "language-" to the element.


マークアップされるコンピュータ・コードの言語を示す正式な方法はありません。例えば、構文強調スクリプトが正しい規則を使用できるように、コード要素に使用言語をマークしたい場合は class 属性を使用することができます。例えば、要素に "language-" を先頭に持つクラスを追加する。