Jekyll(Octopress)で画像パスを勝手に指定してくれるLiquidタグの作成

2016 年 1 月 18 日 by 山平

前回、Jekyll(Octopress)の記事生成時に、記事用のディレクトリと、画像用のディレクトリを作成しました。

折角、画像用のディレクトリを作成しても、パスの指定までは面倒見てくれないので、あまり便利になった実感が沸きません。

そこで今回は、画像のパスを勝手に指定してくれるように手を加えていきます。

Jekyllでは、テンプレートエンジンにLiquidを利用しているので、Liquidタグを追加する形で拡張すれば良いとのこと。

簡単そうなのでサクサク作って…と思いきや、画像のURLをうまく指定するのが難しいことに気がつきました。
そこで、前回のnew_post2コマンドを少し直して、実装を楽にします。

以下、Rakefileの抜粋です。

RUBY:
  1. images_dir      = "images"    # directory for blog images
  2.  
  3. require 'yaml'
  4. desc "Begin a new post in #{"config.yml[post2_dir_format]"}/#{posts_dir}"
  5. task :new_post2, :title do |t, args|
  6. if args.title
  7. title = args.title
  8. else
  9. title = get_stdin("Enter a title for your post: ")
  10. end
  11. raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)
  12. jekyll_config = YAML.load_file('_config.yml')
  13. time = Time.now
  14. filename = "#{time.strftime('%Y-%m-%d')}-#{title.to_url}"
  15. _dir = time.strftime(jekyll_config['post2_dir_format'])
  16. posts_dir_ex = File.join(posts_dir, _dir, filename).gsub(/\/$/, '')
  17. image_dir_ex = File.join(images_dir, _dir, filename).gsub(/\/$/, '')
  18. mkdir_p "#{source_dir}/#{posts_dir_ex}"
  19. mkdir_p "#{source_dir}/#{image_dir_ex}"
  20. filename = "#{source_dir}/#{posts_dir_ex}/#{time.strftime('%Y-%m-%d')}-#{title.to_url}.#{new_post_ext}"
  21. if File.exist?(filename)
  22. abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
  23. end
  24. puts "Creating new post: #{filename}"
  25. open(filename, 'w') do |post|
  26. post.puts "---"
  27. post.puts "layout: post"
  28. post.puts "title: \"#{title.gsub(/&/,'&')}\""
  29. post.puts "date: #{time.strftime('%Y-%m-%d %H:%M:%S %z')}"
  30. post.puts "comments: true"
  31. post.puts "categories: "
  32. post.puts "image_dir: /#{image_dir_ex}"
  33. post.puts "---"
  34. end
  35. `gedit #{filename}`
  36. `nautilus #{source_dir}/#{image_dir_ex}`
  37. end

要は、画像ディレクトリを作成したタイミングでYAML Front Matterにディレクトリパスを追加することで、pageオブジェクトでアクセスできるようにします。
これで実装が簡単になったはずなので、さっそく作ってみます。

RUBY:
  1. module Jekyll
  2. class HomeImageTag <Liquid::Tag
  3. def initialize(tag_name, markup, tokens)
  4. _p = markup.strip.split(/\s/)
  5. @src = _p.shift
  6. @alt = _p.join(" ").strip
  7. super
  8. end
  9.  
  10. def render(context)
  11. page = context['page']
  12. path = File.join(page['image_dir'], @src)
  13. return <<-"EOD"
  14. <img src="#{path}" alt="#{@alt}" />
  15. EOD
  16. end
  17. end
  18. end
  19.  
  20. Liquid::Template.register_tag('home_img', Jekyll::HomeImageTag)

このコマンドで「rake new_post2[hoge]」とすると、YAML Front Matter「img_dir」が追加されたエントリの雛形が作成されます。
ここに作成した「hime_img」Liquidタグを書いていきます。
使うときは「home_img」タグに画像のファイル名とaltテキストを指定するだけです。
比較用にマークダウンでも画像を指定しています。

---
layout: post
title: "hoge"
date: 2015-12-13 22:25:20 +0900
comments: true
categories:
image_dir: /images/2015/1213/2015-12-13-hoge
---
markdown:
![hoge hoge ho](/images/2015/1213/2015-12-13-hoge/test.png)
plugin:
{% home_img test.png hoge hoge ho %}

マークダウンでパスを指定した場合と同じ画像が表示されています。

result

出力されるHTMLも大丈夫そうです。
HTML:
  1. </div>
  2. <div><div class="entry-content"></div>
  3. <div><p></div>
  4. <div>markdown:</div>
  5. <div><img src="/images/2015/1213/2015-12-13-hoge/test.png" alt="hoge hoge ho"></div>
  6. <div></p></div>
  7. <div><p></div>
  8. <div>plugin:</div>
  9. <div><img src="/images/2015/1213/2015-12-13-hoge/test.png" alt="hoge hoge ho"></div>
  10. <div></p></div>
  11. <div></div></div>
  12. </div>

ここまでできると欲が出てマークダウンを拡張したくなります。
まだいい感じに実装できるイメージが掴めていないので、もう少し調査が必要です。
今回は以上です。

タグ: , , , ,

TrackBack