PrismでWagtailにシンタックスハイライトを導入する

Prismを使ってソースコードのシンタックスハイライトをする方法を紹介します。

PrismでWagtailにシンタックスハイライトを導入する

技術系のブログやメディアでは、プログラミングのソースコードを埋め込みたいことがあります。しかし、通常のコードをそのままHTML上で表示しても、形が崩れたり、色が単調で見づらくなることがあります。そんな時にはシンタックスハイライトを使うことで、エディタなどでの表示と同じように綺麗にコードを表示することができます。

当サイトWagtailBaseでも、ソースコードの表示にはPrismというシンタックスハイライトのライブラリを使っており、コードを読みやすくしています。今回は、Wagtailの管理画面上からこのようなソースコードを簡単に記事に追加できるような実装を紹介します。

# Pythonのシンタックスハイライトの例

def hello_world():
    print("Hello World")

hello_world() # "Hello World"と表示

Prismとは

Prismとは、広く人気のあるシンタックスハイライトのライブラリで、軽量かつ高速に動作し、無料で簡単に導入できるのが特徴です。複数の表示形式をサポートし、シンプルな記述で利用できるのでレベルを問わずおすすめできます。Prismのサイトを見ると表示のサンプルも載っているため、イメージを確認してみてください。

PrismをDjangoのプロジェクトに導入する

PrismはCSSファイルとJavaScriptファイルで構成されており、それぞれをDjangoのStaticファイルに取り入れることで、テンプレート上で利用できるようになります。まずはそれぞれのファイルをPrismのサイトからダウンロードしましょう。

Prismをダウンロードする際には、使用するテーマやハイライトする言語を指定する必要があります。テーマはPrismサイトのトップページで確認できるので、お好みのものを選ぶと良いでしょう。ハイライトする言語については、自分のサイトで利用する可能性があるものをチェックしておきましょう。

Compression levelは、ファイルを圧縮するかどうかの選択です。基本的にPrismのソースコードを修正する必要はないため、圧縮率の高いMinified versionの方を選択しておきましょう。

Prismのダウンロード

必要な内容にチェックをつけたら、ページの一番下からCSSファイルとJavaScriptファイルをダウンロードします。

PrismのCSSとJavaScriptをダウンロード

DjangoプロジェクトのStaticファイルに追加

ダウンロードしたファイルはDjangoのプロジェクトのStaticファイルに追加します。WagtailはDjangoをベースとしたCMSなので、同じ導入方法で大丈夫です。

ルートディレクトリのstaticフォルダの中に、cssjsというフォルダを作成し、それぞれのフォルダの中にダウンロードしたPrismのCSSファイルとJavaScriptファイルを置いてください。これで通常のStaticファイルと同様に、テンプレートからファイルを読み込むことができるようになります。

Wagtailにシンタックスハイライトを適用したCodeBlockを追加する

続いて、Prismのシンタックスハイライトを適用した形でソースコードをWagtailの管理画面から簡単に挿入できるようにしましょう。Wagtailで新しいブロックを追加するためには、モデルの追加とテンプレートの追加が必要になります。

今回は、記事ページのコンテンツをStreamFieldで作成し、その中にソースコードを記述できるCodeBlockを取り込む形で実装します。管理画面上では以下のように、言語の選択とコードを記述することで、テンプレート上でシンタックスハイライトを適用したソースコードを表示できるようになります。

CodeBlockのサンプル

CodeBlockモデルを追加する

まずはCodeBlockを定義しましょう。アプリケーション内にblocks.pyというファイルを作成して、StructBlockで中身を記述していきます。今回のサンプルでは、blogsアプリケーション内でCodeBlockを追加するようにしています。

# blogs/blocks.py

from wagtail.core import blocks


# Prism内で選択した言語
CODE_CHOICES = [
    ('python', 'python'),
    ('sql', 'sql'),
    ('javascript', 'javascript'),
    ('css', 'css'),
    ('markup', 'markup'),
    ('markdown', 'markdown'),
    ('html', 'html'),
    ('git', 'git'),
    ('bash', 'bash'),
]


# シンタックスハイライトを適用するソースコードのブロック
class CodeBlock(blocks.StructBlock):
    language = blocks.ChoiceBlock(choices=CODE_CHOICES, default="bash") # 利用する言語
    code = blocks.TextBlock() # ソースコード

    class Meta:
        template = "blogs/blocks/code_block.html" # ソースコードを表示するテンプレート
        icon = "openquote" # 管理画面上でのアイコン
        label = "Code" # 管理画面上での表示名

blocks.pyからCodeBlockをインポートして、記事ページのコンテンツで利用できるようにしましょう。これで管理画面からソースコードとハイライトする言語を選択して挿入できるようになります。

# blogs/models.py

from . import blocks


# 記事ページのモデル
class BlogDetailPage(Page):
    ...
    # 他のブロックと同様にCodeBlockを追加
    content = StreamField(
        [
            ...
            ("code", blocks.CodeBlock()), # CodeBlockを追加
        ],
        null=True,
        blank=True,
    )

    content_panels = Page.content_panels + [
        ...
        StreamFieldPanel("content"),
        ...
    ]

テンプレートを作成する

CodeBlockのモデルはできたので、対応するテンプレートを作成しましょう。今回はblogs/templates/blogs/blocks/code_block.htmlというファイルを作成します。Prismでは、language-htmllanguage-pythonといったクラスをcodeタグに付与することでシンタックスハイライトが適用されます。そのため、以下のサンプルのように、CodeBlockモデルで選択した言語がテンプレートに適用されるようにします。ソースコードの部分をprecodeタグで囲めばテンプレートの実装は完了です。

<!-- blogs/blocks/code_block.html -->

<section>
  <pre><code class="language-{{ self.language }}">{{ self.code }}</code></pre>
</section>

最後に、このCodeBlockのテンプレートを呼び出している記事ページ(BlogDetailPage)のテンプレート上からPrismのCSSファイルとJavaScriptファイルをインポートしましょう。これによってPrismのシンタックスハイライトが記事のコンテンツ内に表示されるCodeBlockに適用されます。

<!-- blogs/blog_detail_page.html -->

{% extends "base.html" %}

<!-- CSSとJavaScriptファイルをインポート -->
{% block extra_css %}
  <link rel="stylesheet" type="text/css" href="{% static 'css/prism.css' %}">
{% endblock %}

{% block extra_js %}
  <script type="text/javascript" src="{% static 'js/prism.js' %}"></script>
{% endblock %}

{% block content %}
<article>
    <section>
        <div>
            <!-- 記事ページのcontentの中ではCodeBlockが呼び出されている -->
            {{ self.content }}
        </div>
    </section>
</article>
{% endblock content %}

これでテンプレート上でPrismのシンタックスハイライトがあたったソースコードを表示することができるようになりました。シンタックスハイライトのテーマや使用する言語を変更したい場合には、もう一度Prismから条件にあったファイルをダウンロードしてStaticファイルを置き換え、blocks.pyで定義した選択できる言語のCODE_CHOICESを修正すればOKです。