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

2016 年 1 月 18 日 by 山平

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

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

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

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

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

以下、Rakefileの抜粋です。

images_dir      = "images"    # directory for blog images

require 'yaml'
desc "Begin a new post in #{"config.yml[post2_dir_format]"}/#{posts_dir}"
task :new_post2, :title do |t, args|
if args.title
title = args.title
else
title = get_stdin("Enter a title for your post: ")
end
raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)
jekyll_config = YAML.load_file('_config.yml')
time = Time.now
filename = "#{time.strftime('%Y-%m-%d')}-#{title.to_url}"
_dir = time.strftime(jekyll_config['post2_dir_format'])
posts_dir_ex = File.join(posts_dir, _dir, filename).gsub(/\/$/, '')
image_dir_ex = File.join(images_dir, _dir, filename).gsub(/\/$/, '')
mkdir_p "#{source_dir}/#{posts_dir_ex}"
mkdir_p "#{source_dir}/#{image_dir_ex}"
filename = "#{source_dir}/#{posts_dir_ex}/#{time.strftime('%Y-%m-%d')}-#{title.to_url}.#{new_post_ext}"
if File.exist?(filename)
abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
end
puts "Creating new post: #{filename}"
open(filename, 'w') do |post|
post.puts "---"
post.puts "layout: post"
post.puts "title: \"#{title.gsub(/&/,'&')}\""
post.puts "date: #{time.strftime('%Y-%m-%d %H:%M:%S %z')}"
post.puts "comments: true"
post.puts "categories: "
post.puts "image_dir: /#{image_dir_ex}"
post.puts "---"
end
`gedit #{filename}`
`nautilus #{source_dir}/#{image_dir_ex}`
end

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

module Jekyll
class HomeImageTag < Liquid::Tag
def initialize(tag_name, markup, tokens)
_p = markup.strip.split(/\s/)
@src = _p.shift
@alt = _p.join(" ").strip
super
end

def render(context)
page = context['page']
path = File.join(page['image_dir'], @src)
return <<-"EOD"
<img src="#{path}" alt="#{@alt}" />
EOD
end
end
end

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も大丈夫そうです。
</div>
<div>
<div>&lt;div class="entry-content"&gt;</div>
<div>&lt;p&gt;</div>
<div>markdown:</div>
<div>&lt;img src="/images/2015/1213/2015-12-13-hoge/test.png" alt="hoge hoge ho"&gt;</div>
<div>&lt;/p&gt;</div>
<div>&lt;p&gt;</div>
<div>plugin:</div>
<div>&lt;img src="/images/2015/1213/2015-12-13-hoge/test.png" alt="hoge hoge ho"&gt;</div>
<div>&lt;/p&gt;</div>
<div>&lt;/div&gt;</div>
</div>
<div>
ここまでできると欲が出てマークダウンを拡張したくなります。
まだいい感じに実装できるイメージが掴めていないので、もう少し調査が必要です。
今回は以上です。

タグ: , , , ,

TrackBack