gh-pagesとhexo(サブディレクトリ下での使用)

hexoをサブディレクトリ下で使用したい

githubで静的サイトジェネレータを使ったblogもどきを複数運用したい。githubには

  • <ユーザ名>.github.io
  • <組織名>.github.io
  • <ユーザ名>.github.io/<プロジェクト名>

の3通りの方法でWebサイトを作れるのだが、今回は3番目の場合について。
hexoのgithubを見るとサブディレクトリに関するissueが定期的に上がるが、自分も引っかかった。

TL;DR

theme側の_config.ymlに書かれている項目のうち上書きしたいものを、プロジェクトの_config.yml内theme_configに記述していけば良い。

1
2
3
4
theme_config:
menu:
Home: /<project>/
Archives: /<project>/archives

基本設定

hexoでサブディレクトリを扱う場合には_config.ymlに以下のような設定を行えば良い。

1
2
3
4
5
6
7
url: http://<your id>.github.io/<project>
root: /<project>/

deploy:
type: git
repo: git@github.com:<your id>/<project>.git
branch: gh-pages

また、theme側の設定では以下のような設定になっていることが多い。

1
2
3
menu:
Home: /
Archives: /archives

この場合、当然Homeはhttp://<your id>.github.io/を指し示す。
theme側の_config.ymlに書かれている通りなので正しい挙動なのだが、これではサブディレクトリに関する設定をtheme側でも行わなくてはいけないことになる。

  • themeをgitのsubmoduleとして管理している場合にはわざわざforkしなくてはいけない。
  • ルートに関する設定を複数箇所で指定するのは面倒。

これを

1
2
3
menu:
Home: .
Archives: archives

などとすると一見うまくいくように見えるが、個別の記事を表示するとうまくいかない。
例えば/<project>/2015/08/10/sample.htmlのような記事からArchivesをクリックすると/<project>/2015/08/10/archivesに飛んでしまう。

プロジェクトの設定とテーマの設定では後者が優先される

menu項目は大抵の場合theme側の_config.ymlに記述されているが、プロジェクト自体の_config.ymlでmenuを設定しても上書きすることはできない。
例えば以下のような設定を行ったとする。

themeの_config.yml

1
2
3
menu:
Home: /
Archives: /archives

プロジェクトの_config.yml

1
2
3
menu:
Home: /subdirectory
Archives: /subdirectory/archives

この時、直感的にはプロジェクト側の設定が優先されそうだが、実際にはtheme側の設定が優先されてしまう。

theme_configという設定項目を利用する

hexoのドキュメントを見ても記述されていなかったように思うのだがソースコードを追っていくと、theme_configという項目が最優先されることがわかった。
具体的には/lib/hexo/index.js内で

Locals.prototype.theme = _.extend({}, config, theme.config, config.theme_config);

とある。_.extend()はlodashの提供するメソッドで、複数の引数をとりそれぞれの連想配列をマージする。その際に重複したキーはどんどん更新される。
どういうことかというと、プロジェクト側に以下のように設定することで、themeの設定を上書きすることができる。

1
2
3
4
theme_config:
menu:
Home: /subdirectory
Archives: /subdirectory/archives

この設定はtheme側の_config.ymlより優先されるので、theme側の設定をいじらずに済むことがわかった。