Jekyll の記事ファイルを Ruby で扱う

Jekyll の投稿を機械的に処理したかったので、Ruby でちょろっと書いてみました。

投稿ファイルの読み書き

Jekyll の投稿ファイルは次の手順で読み書きできます。

  1. Jekyll::Page.new にファイルのパスを渡して Jekyll::Page のインスタンスを作る。
  2. data メソッドで Front-matter の Hash を、content メソッドで内容を読み書きする。
  3. page.data.to_yaml + "---\n" + page.content をファイルに出力。

ロードした状態だと date が UTC になるので、必要に応じて地方時に変換します。

これを踏まえて、簡単なライブラリを書きました。

# _tools/process_posts.rb
require "yaml"
require "jekyll"

# file を読み込んで変換する
# block には 内容, メタデータ が渡される
# block の返り値が新しい内容となる
def process_post(file, &block)
  STDERR.puts "Process #{File.basename(file)}"
  page = Jekyll::Page.new(nil, "", "", File.expand_path(file))
  page.data["date"] = Time.at(page.data["date"].to_i) # UTC -> 地方時に
  page.content = yield(page.content, page.data)
  File.write(file, page.data.to_yaml + "---\n" + page.content)
end

# すべての post について process_post を実行する
def process_posts(&block)
  Dir.glob("#{__dir__}/../_posts/**/*.markdown") do |file|
    process_post(file, &block)
  end
end

使い方

上記ライブラリを使って、例えば、画像へのリンクをホスト名を含まない形に変換するスクリプトが書けます。

# _tools/fix_asset_url.rb
require_relative "process_posts"

process_posts do |content, data|
  content.gsub(%r{http://penguinlab\.jp/blog/wp-content/}, "/blog/wp-content/")
end

あるいは、タグをすべて小文字に変えるスクリプトなんかも書けます。

# _tools/downcase_tags
require_relative "process_posts"

process_posts do |content, data|
  data["tags"].each(&:downcase!)
  content
end

また、jekyll-import で WordPress からインポートすると、記事の中身がほぼ HTML なので、downmark_it を使って Markdown に変換しました。結構修正が必要でしたが...。