rcmdnk's blog

CATegories

Octopressをアップデート したらカテゴリが全部小文字になって困った話。

Sponsored Links

問題となる変更点

Octopressの最新版では jekyll-2.1.0を使う様になったこと。 以前は(このサイト様に使ってたものは)jekyll-0.12.1でした。

JekyllのHistory を見ると

  • Ensure all Post categories are downcase (#842, #872)

の様に、1.0.0 / 2013-05-06 から全てCategoryがDowncaseになるようにしてある様です。

Ensure all categories are downcase. Fix for #842. · 73ca35e · jekyll/jekyll

これは、2つのポストで同じカテゴリー名を大文字小文字バラバラ (1つにCategory, もう一つにcategory、みたいな) で付けると起こる問題に対する対処です。

ビルドしてる最中は別々なものとして扱われて、 サイドバーのカテゴリーリストなんかにも2つとも表示されるのですが、 最終的に、カテゴリーページが設置されるディレクトリが.../category/index.html的な 小文字のディレクトリに収まる様に設定されてるので 1、 最終的にその2つのカテゴリーは同じところを指し示す事になります。

この時に、先に入ってたものが消される(逆かも)ので Categoryと付けられた物か、categoryと付けられたもの、 どちらかだけが.../category/index.html内にリンクを貼られます。

この問題を解決するため、予めカテゴリーは全て小文字にしてしまおう、 というのが上の変更です。

ただ、以前のOctopressは区別される状態だったので、 全部統一するように注意して大文字を使ってきました。

全部小文字でも別にそれ程悪くは無いのですが ちょっと気持ち悪いので以前みたくしてみます。

チェック

(上で既にどこが悪いか書いてますが、ここではまだ分かってないとして。。。)

Octopressをアップデートしたらカテゴリーがすべて小文字に表記される様になって しまったので どこで小文字になってるか探してみました。

まず、source/_layouts/post.html がhtmlに変換される時にページの大元になるのでその先頭に

source/_layouts/post.html
1
2
3
4
5
6
7
8
9
---
layout: default
single: true
---

  at top of post.html: post.categories = {{post.categories}}
  at top of post.html: page.categories = {{page.categories}}
<div><!-- post -->
<article class="hentry" role="article">

こんなかんじでcategoriesを書き出させてみせます。

すると、Categoryの記事にもcategoryの記事にも

1
2
3
4
5
6
  <div id="main">
    <div id="content">
      top of post.html: post.categories =
top of post.html: page.categories = Categories
<div><!-- post -->
<article class="hentry" role="article">

という記述が有り、 OctopressのプラグインとかではなくJekyllがyml設定からcategories(category) を引っ張ってっくる時に既に小文字にしている様子。

で、どうしたもんかと探していたらウェブで上のJekyllのHistoryページを見つけた、と。 (意味なし。。。)

対処

原因はJekyllの中の /lib/jekyll/post.rb の変更です。 (システムのrubyに直接インストールしてるなら、 Macなら/Library/Ruby/Gems/2.0.0/gems/jekyll-2.1.0/lib/jekyll/post.rbとか、 rvmでRubyをインストールしてるなら~/.rvm/gems/ruby-1.9.3/gems/jekyll-2.1.0/lib/jekyll/post.rb、とかにあります。)

こいつを、以前 Octopress Tips見出しの追加 でやってみたいに直接弄っても良いのですが、 そうもそうしなくても良さそうだったので下の様な方法で 2

やりかたは、上のファイルをpluginsにコピーしてきて変更するだけ。 関数とかの定義が順番に読みこまれて、最終的にpluginsに同じものがあればそれが 上書きしてくれるみたいです(この辺よくわかってない。。。)。

しかも、クラス全体とかでなくて、一部の関数だけ、とかでも良いみたいなので、

plugins/post.rb
1
2
3
4
5
6
7
8
9
10
module Jekyll
  class Post
    def populate_categories
      categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
      self.categories = (
        Array(categories) + categories_from_data
      ).map {|c| c.to_s.capitalize}.flatten.uniq
    end
  end
end

と、必要な関数だけかけばOK。 populate_categoriesで、downcaseとなってる箇所をcapitalizeに変えただけです。 これで、どんな単語が来ても、先頭の文字だけ大文字の文字列に全て変換されます。 この辺は好みですが、もし、iPhone的なのを入れたかったりする場合には、

1
2
3
   Array(categories) + categories_from_data
-).map {|c| c.to_s.capitalize}.flatten.uniq
+).flatten.uniq

な感じで何も変形せずに与える様にして(昔の振る舞いと同じ)、 カテゴリを定義する時に、必ず大文字小文字の違うものを作らないように注意すれば良いと思います。

post.rb の中を見ると、上の方でもう一箇所downcaseを使ってる箇所がありますが、 そこではディレクトリ名からカテゴリーを取って来るんですが、 このブログでは関係ない上に、上の関数の所でもう一度まとめて変換してるので 特に気にしなくてOK 3

これだけで十分ですが、もし、全部コピーしておいたほうが気分が良いという場合にも、 上の方にある、

MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/

等の定数の定義は消しておかないと、

$ rake generate
## Generating Site with Jekyll
identical source/stylesheets/screen.css
Configuration file: /octopress/_config.yml
/octopress/plugins/post.rb:7: warning: already initialized constant Jekyll::Post::MATCHER
/Library/Ruby/Gems/2.0.0/gems/jekyll-2.1.0/lib/jekyll/post.rb:7: warning: previous definition of MATCHER was here
/octopress/plugins/post.rb:9: warning: already initialized constant Jekyll::Post::EXCERPT_ATTRIBUTES_FOR_LIQUID
/Library/Ruby/Gems/2.0.0/gems/jekyll-2.1.0/lib/jekyll/post.rb:9: warning: previous definition of EXCERPT_ATTRIBUTES_FOR_LIQUID was here
/octopress/plugins/post.rb:23: warning: already initialized constant Jekyll::Post::ATTRIBUTES_FOR_LIQUID
/Library/Ruby/Gems/2.0.0/gems/jekyll-2.1.0/lib/jekyll/post.rb:23: warning: previous definition of ATTRIBUTES_FOR_LIQUID was here
...

みたいなWARNINGが毎回出てうざいことになります。(buildは出来ますが)

実際、どのファイルの関数が呼ばれてるかチェックするために、 /Library/Ruby/Gems/2.0.0/gems/jekyll-2.1.0/lib/jekyll/post.rb

jekyll-2.1.0/lib/jekyll/post.rb
1
2
3
4
5
6
7
8
@@ -49,2 +49,3 @@
     def initialize(site, source, dir, name)
+      puts "initialize in common"
       @site = site
@@ -79,2 +80,3 @@
     def populate_categories
+      puts "populate_categories in common"
       categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')

な感じで出力を加えて手元のpost.rbにも

plugins/post.rb
1
2
3
4
5
6
7
8
9
10
11
module Jekyll
  class Post
    def populate_categories
      puts "populate_tags in plugin!"
      categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
      self.categories = (
        Array(categories) + categories_from_data
      ).map {|c| c.to_s.capitalize}.flatten.uniq
    end
  end
end

putsを入れてみると、

$ rake generate
(in /octopress)
## Generating Site with Jekyll
identical source/stylesheets/screen.css
Configuration file: /octopress/_config.yml
            Source: source
       Destination: public
      Generating...
initialize in common
populate_tags in plugin!
initialize in common
populate_tags in plugin!
...

の様になって、initializeは通常のディレクトリの物が呼ばれていて populate_categoriesplugins/post.rbの物が呼ばれてる事が分かります。

出来たページも確かにCapitalizeなものになっています。 各ページのカテゴリの大文字小文字を変更してチェックしてみてもすべて 統一されて全部きちんとリンクされる様になったので前より便利。

tagの方

post.rb をみると、tagspopulate_tagsの中で追加しているので、

1
2
3
def populate_tags
  self.tags = Utils.pluralized_array_from_hash(data, "tag", "tags").map{|t| t.to_s.capitalize}.flatten.uniq
end

みたいにして、plugins/post.rbに加えてあげればTagも全て大文字から始まる文字列になります。

ただ、こちらにはiPhoneとかもあるしそのまま使おうかな、ということで今回は変更せず (デフォルトでもtagsはそのまま使うようになっています。)

Sponsored Links
  1. システムによっては大文字小文字がディレクトリやファイル名で区別されないための対処?

    ファイル名やディレクトリ名の大文字小文字

  2. この見出しの話はKramdownにしたので今は問題ないんですが、 rdiscountとか使ってて問題ある場合は、下に書くように直接 インストールしたファイルを変更しなくてもOctopress内で変更できます。

  3. もし、上に書いたように大文字小文字を入力のまま使いたくて、かつディレクトリをカテゴリに使ってる場合には上の方にあるdowncaseの部分も

    1
    2
    
    -self.categories = dir.downcase.split('/').reject { |x| x.empty? }
    +self.categories = dir.split('/').reject { |x| x.empty? }
    

    な感じで消しておかないといけません。

Sponsored Links

« Octopressをアップデート Octopressでの時間帯の地域の設定 »