feed

2013年11月20日, 編集履歴

GitHub Pagesでカスタム404ページを配置する

 このウェブサイトは現在GitHub Pagesでホストされている。

 なにも設定していない場合、404ページ——すなわち存在しないURLをリクエストされたときに表示するページは、GitHub Pagesのディフォルト404ページになる。ディフォルト404ページは、このウェブサイト自体とは直接関連のない情報を表示するだけなので、そのままでは都合が悪い。最低限、このウェブサイトのトップページへ誘導するリンクくらいは置いておくべきだろう。

 GitHub Pagesではもちろん、自分で404ページを用意することができる。参照情報はGitHub Pagesのヘルプ「Custom 404 Pages」にある。
 一言で言えば、ウェブサイトを管理するリポジトリィのルートに404.htmlというファイルを配置すれば良い。そうすれば、存在しないURLへのリクエストが発生したときにそのファイルが表示されるようになる。

 というわけで404.htmlを配置した。

2013年11月18日, 編集履歴

Jekyllの最新記事と関連記事

 Jekyllのsite変数はpostsrelated_postsメンバを持つ。postsは全ブログ記事が新しい順に入っており、related_postsは処理中のブログ記事に関連している記事が最大10件分入っている。

<ul>
  {% for post in site.posts limit:5 %}
  <li><a href="{{ post.url }}">{{ post.title }}</a></li>
  {% endfor %}
</ul>

のように書くと、最新のブログ記事へのリンクを5件、リストに出力する。ポイントはfor文のlimit:5site.postsには全記事分の情報が入っているので、limit:5のようにすると5件に制限できる。

 related_postsも同じような使い方ができる。しかし、ディフォルトではrelated_postsには単に最新記事が10件分入っているだけである。ビルド時に--lsiオプションを付けると精度が上がるらしいが、どういうアルゴリズムになっているのかはよく解らない。さらにこのウェブサイトはGitHub Pages上でのビルドとホストしているが、その場合は--lsiオプションは使えない(ローカルでビルドして、その生成物をアップロードする方法ならば可)。
 ディフォルトでも、せめて同じカテゴリィや同じタグを付けた記事が入っていれば使いようがあるのだが……。

2013年11月17日, 編集履歴

JekyllのPagination設定(2013年11月30日追記)

 JekyllのPaginationとは、一ページ中にブログ記事がいくつか羅列してあり、一番下まで行くと「前の記事へ」「次の記事へ」などと前後の記事羅列ページへのリンクが貼ってあり、当該前後ページでまた記事が羅列されているという、よくあるアレである。

_config.ymlの設定

 Paginationを設定するにはまず_config.ymlに、

paginate: 5
paginate_path: "blog/page:num"

のように記述する。上記の場合、一ページ中に羅列される記事数は5件。paginate_path: "blog/page:num"で指定したblogディレクトリィの中にあるindex.htmlファイルが最初のページとなる。blog/index.html内では変数paginatorを使い、記事羅列ページを作成する(したがって、blog/index.htmlはJekyll(Liquid)の変換対象ファイルでなければならないので、YAML Front-matterが必要となる)。
 以降のページは、そのblog/index.htmlがテンプレート的な扱いとなり、blog/page2/index.htmlblog/page3/index.html、…と作られる(page1は作られないことに注意)。

記事の出力

 paginatorposts変数を持っており、そのページ内で羅列される件数分(この場合は5件)の記事情報が保持されている。blog/index.html内で以下のように記述すれば、5件分の記事が出力される。

{% for post in paginator.posts %}
<article>
  <p class="date">{{ post.date | date: "%Y年%m月%d日" }}</p>
  <h1><a href="{{ post.url }}">{{ post.title }}</a></h1>
  {{ post.content }}
</article>
{% endfor %}

 上記は各記事の全文を出力している。全文が必要ない場合はpost.contentの代わりにpost.excerptを使う。

 blog/page2/index.html以降ではblog/index.htmlがテンプレート的に使われて同じ形態のファイルが出力される。paginator.postsには、そのページが出力するべき記事情報が入っている。全記事数が12件でpaginate: 5指定の場合、最初のページ(blog/index.html)では最新5件分、2ページ目(blog/page2/index.html)で次の5件分、3ページ目(blog/page3/index.html)で最後の2件分がpaginator.postsに入っている。paginatorが持つその他の変数も出力するページにあわせて変化する。

前後ページへのリンク出力

 前後ページへのリンクにはpaginator.previous_pagepaginator.next_pageを使う。これらには前後のページ番号(なければnil)が入っている。以下のようにblog/index.htmlに書いた場合、前後ページへのリンクのリストが出力される。

<ul>
  {% if paginator.previous_page %}<li><a href="/blog/{% if paginator.previous_page != 1 %}page{{ paginator.previous_page }}/{% endif %}">前の記事</a></li>{% endif %}
  {% if paginator.next_page %}<li><a href="/blog/page{{ paginator.next_page }}/">次の記事</a></li>{% endif %}
</ul>

 ひとつ注意が必要なのは、2ページ目以降のパスはblog/page2/index.html、…であるが、最初のページのパスはblog/index.htmlであって、blog/page1/index.htmlではないということである。したがって、paginator.previous_page1のときとそれ以外で処理を分ける必要がある。

追記(2013年11月30日)

 前節「前後ページへのリンク出力」について、previous_pageは日付上では新しい方向のページ番号を、next_pageは古い方向のページ番号を意味する。前節のように、変数名に合わせてそれぞれのリンク文字列を「前の〜」「次の〜」とすると、(考え方にもよるが、私は)気持ち悪い。
 なので、リンク文字列をそれぞれ「新しい〜」「古い〜」と改めた。


<ul>
  {% if paginator.previous_page %}<li><a href="/blog/{% if paginator.previous_page != 1 %}page{{ paginator.previous_page }}/{% endif %}">新しい記事</a></li>{% endif %}
  {% if paginator.next_page %}<li><a href="/blog/page{{ paginator.next_page }}/">古い記事</a></li>{% endif %}
</ul>

2013年11月13日, 編集履歴

JekyllのMarkdown設定(2013年11月18日追記)

 Jekyllを使ってウェブサイトとブログの再構築をした。その際に用いたMarkdown用の設定メモ。
 現時点での_config.ymlファイルのMarkdown関係の設定は以下。

markdown: redcarpet
redcarpet:
  extensions: ["autolink", "hard_wrap"]

 生の設定ファイルはgenjiapp.github.io/_config.yml at master

Markdownレンダラの変更

 JekyllのディフォルトのMarkdownレンダラはMaruku。これをRedcarpetに変更した。なぜ変更したか。きっかけは、MarukuではTwitterの埋め込みコード(以下のようなもの)

<blockquote class="twitter-tweet"><p>ヘウレーカ! JekyllでコンテンツをHTMLで書いて良いことと、レイアウト側だけではなくコンテンツ側でも include が使えることに気がついて、蒙が啓けた気がする</p>&mdash; Genji (@genji_tw) <a href="https://twitter.com/genji_tw/statuses/398471861828206592">November 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

がうまく変換できずエラーを吐くことに気がついたから。_config.ymlmarkdown: redcarpetと指定することで、MarkdownレンダラをMarukuからRedcarpetに変更できる。Redcarpetなら上記の埋め込みコードを正常に処理できる。

Redcarpetの拡張設定

 指定した拡張はautolinkhard_wrapの2つ。

 autolinkは http://genjiapp.com/ のような文字列を自動でリンクに変換してくれる。

 次にhard_wrap。Markdownは標準では空行を挿入しないと改段落にならない(ブラウザでの表示で行分けされない)。つまり、

あめんぼあかいな
あいうえお

ほげほげ

とMarkdownを書くと、変換後のHTMLは

<p>あめんぼあかいなあいうえお</p>
<p>ほげほげ</p>

のようになる。Markdown上での単なる改行は改段落とはならずひとつの<p>タグに纏められ(「あめんぼあかいなあいうえお」が一行で表示される)、空行を挟んで新しい<p>タグが始まる。これは他の軽量マークアップ言語でもよくある仕様である。個人的な趣味でこの仕様があまり好きではない。
 hard_wrapを有効にすると上記のMarkdownは

<p>あめんぼあかいな<br/>あいうえお</p>
<p>ほげほげ</p>

のように変換される。Markdown上での改行が変換後に改段落されないのは同様であるが、改行部分に<br/>タグが挿入されるようになる(ブラウザでの表示において行分けされる)。
 HTMLの<p>タグひとつが日本語の意味段落に相当し、形式段落を<br/>で作るというイメージである。

追記(2013年11月18日)

 当初、Redcarpetの拡張設定はもうひとつ、no_intra_emphasisを指定していた。そして記事中では以下のようなことを書いた。

 Markdownは標準では複数のアンダーバー_間の文字列をHTML変換時に強調タグ<em>でくくる。これの何が問題かというと、プログラムの変数名等でありがちなhoge_foo_barのような文字列が意図せず強調されてしまう。no_intra_emphasisはその動作を抑制する。

 Markdownの強調構文にはアンダーバーを使う方法ともうひとつ、アスタリスク*を使う方法がある。ここで私が誤解していたのが、no_intra_emphasisはアンダーバーを使う強調構文のみが対象であると思い込んでいたことである。しかしno_intra_emphasisはアスタリスクを使う構文でも同様に作用する。

 これの何が問題かというと、分かち書きをしない日本語文中では、余分な空白を入れないと強調構文が使えなくなるということである。つまり、

ほげほげ*強調*ふーばー

と書いても、

<p>ほげほげ*強調*ふーばー</p>

と出力される。強調構文にするには、余分な空白を挿入して

ほげほげ *強調* ふーばー

としなければならなくなる。そうすると出力にも当然余分な空白が入り込む。それはイヤなのでno_intra_emphasisは外すことにした。
 プログラムの変数名等でアンダーバーが意図しない強調になってしまうという問題は、インラインコード/コードブロック構文中なら関係ないと気づいた。コード片を書くときは元々インラインコード/コードブロック構文を使っていたので、そもそもno_intra_emphasisは必要ないという結論に至った。

2013年11月13日, 編集履歴

Jekyllを使ってウェブサイトを再構築

 Jekyllという静的ウェブサイト&ブログ生成システムとGitHub Pagesを用いて、ウェブサイトを再構築しました。
 以前からウェブページのホスティングにはGitHubが提供するGitHub Pagesというホスティングサーヴィスを利用してローカルで作成したHTML等をアップロードしていましたが、今回はそれに加えてJekyllという静的ウェブサイト&ブログ生成システムを用いました。

 GitHub Pagesでは、完全なウェブページをそのままアップロードする他にも、Jekyllというシステムを用いる方法が提供されています。
 JekyllはテンプレートとなるHTMLのガワを用意しておき、Markdown等を用いたコンテンツ文書を(HTML断片に変換して)流し込むことで静的なウェブページを生成します。ブログ等のように同じデザインのページを多く生成する必要がある場合に役立ちます。
 GitHub PagesのホスティングサーヴィスはJekyllを内蔵しており、構成ファイルをリポジトリィにプッシュすることで、自動的に静的なウェブサイトを生成してくれます。

 Jekyllを使ってウェブサイトの再構築をしようと思ったきっかけは、ブログを以前から使用していたGoogleのBloggerから移行し、新しく別のブログを始めたかったからです。Bloggerから離れたい理由はGoogleへの不信感ですが、それ以外にもブラウザ上のウェブインターフェイスで文章を書くのがやりづらいという理由もあります。しょーもないことをたくさん書いてある過去のブログ記事を抹消したいという思いもあります(なので旧ブログはそのうち閉鎖します)。
 他のよくあるブログサーヴィスに移行したところで、ウェブインターフェイスからは離れられません。であれば、元々利用していたGitHub Pagesが内蔵するJekyllを用いてブログを書こう、ブログをJekyllで書くならばウェブサイトの方もJekyllで管理しよう、というのが今回の再構築の理由です。

余談

 Jekyllの使い方を紹介しているページ等では、コンテンツ文書をMarkdown等の軽量マークアップ言語で書き、それをテンプレートに流し込んでいます。テンプレートではHTMLのガワを記述し、複数のテンプレート間で共通する構成要素があればそれを部品化してincludeしています。それがJekyllの基本的な使い方なので、当然そのように書きます。
 ブログ記事以外のページを書くときに、そこではたと困りました。テンプレートに流し込むシンプルな構成のブログ記事であればMarkdownで書けますが、ペラいちのページを単純なMarkdownの流し込みで表現するのは難しいです。Markdownはシンプルな構成の文書を書く際には有用ですが、HTMLの表現力を100%使うことはできません。
 異なるデザインの複数ページを作る場合(このウェブサイトの場合は各アプリケーションの紹介ページのような)はテンプレートを使い回しにくいので、各ページごとに専用のテンプレートを作成しなければならないのだろうか? それとも完全にふつうのHTMLを書くしかないのだろうか?

 悩むことしばし。

ヘウレーカ! JekyllでコンテンツをHTMLで書いて良いことと、レイアウト側だけではなくコンテンツ側でも include が使えることに気がついて、蒙が啓けた気がする

— Genji (@genji_tw) November 7, 2013

 コンテンツ文書を書くのにMarkdownではなく、HTMLが使えることに気づきました。さらに、includeコマンドをテンプレート文書だけではなく、コンテンツ文書にも書くことができることに気付き、問題は解決しました。
 通常はテンプレート内で使うことが多いであろうincludeコマンドをHTMLで書くコンテンツ文書内でも多用して、アプリケーション紹介ページ等を作成しました。このウェブサイトはGitHub Pagesでホスティングしているので、リポジトリィを見れば、どういう設定でどういう構成になっているのかが解ります。