rcmdnk's blog

NEW

Octopressのプラグインの中で画像をちょっといじって 変換後の物を使いたい、と思って プラグインの中で新たなファイルを作って入れようとしたのですが、 きちんと新しいファイルを入れようと思ったら ちょっと手を加える必要があったことについて。

やりたいこと

こんな感じのプラグインを作ったとします。

new_file.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Jekyll

  class NewFile < Liquid::Tag
    @file = nil

    def initialize(tag_name, markup, tokens)
      @file = markup
      super
    end

    def render(context)
      site = context.registers[:site]
      local_file = site.source + @file['src'].sub(site.config['url'], '')
      if File.exist?(local_file)
        `cp #{local_file} #{local_file}.tmp`
      end
    end
  end
end
Liquid::Template.register_tag('new_file', Jekyll::Thumbnail)

単にタグで受けたファイルのバックアップ(.tmp)を作るだけのプラグイン。

このバックアップファイル自体もサイト(destination)へコピーしたい、という話です。

ちょっとsiteについての補足

ちょっと自分のために補足しておくと、 Liquid::Tagの中のrenderで受ける引数(上ではcontextの中からは

site = context.registers[:site]

という形でsiteの情報を取ってこれます。

_config.ymlで指定している様な値は、このsiteが持ってる configというオブジェクトがHashオブジェクトになっていて この中にあります。

site.config['url']

な感じで取れます。

もしくは

context['site.url']

の様に、contextの引数にsite+名前 を入れるとsite.config['名前']の物を取ってくることも出来ます。

site.sourceに関しては直接取ってきていますが、 これはSiteの定義を見れみると

jekyll/site.rb

上の方でconfigとかと一緒に定義されてるのが分かりますが、 中で_config.ymlsourceの値を入れています。

また、destの値にはdestinationの値が入っています。

上のままGenerateしてみる

上のプラグインをpluginsフォルダに入れてrake generateしみると、 コピーして作った*.tmpファイルの方は destinationの方のディレクトリに入っていません。

sourceの方には正しく生成されています。

試しにもう一度generateしてみると今度はdestinationにも入っています。

一度sourceの方を消してもう一度やってみると今度は destinationに入っていません。

どうもgenerateを始めた時点でのファイルだけをコピーして、 後から作ったものは見てない感じ。

そこで、最初こんな感じにスクリプトを変更してみました。

1
2
3
4
       if File.exist?(local_file)
         `cp #{local_file} #{local_file}.tmp`
+        `cp #{local_file}.tmp #{local_file.sub(site.source, site.dest)}.tmp`
       end

作ったファイルのパスの中のsourceな部分をdestに変換して そちらにもここでコピーを作ってしまう、という方法。

しかし、これやっても新しく作ったファイルをコピーされません。

ちょっと確認しながら見てみると、確かに1回コピーはされるのですが、 その後、他のファイルをコピーする時に一旦全部消されてコピーし直すので 上の様に途中でコピーしても意味がない模様。

上に挙げたsite.rbの中でprocessというメソッド内で、 最後にwriteするまえにcleanupしていて、まさにこれ。

ということで、generateする前にファイルリストを作って 最後に一旦destを掃除した後にファイルリストにあるものをコピーしてる、と言う感じなので そのリストに追加して上げれば良いだろう、ということだと思います。

statif_ciles

で、探して出てきたのがこれ。

plugins - How to generate files from Liquid blocks in Jekyll? - Stack Overflow

site.static_filesと言う値にそのままコピーされてく様なファイルが 詰められてる、とのことです。

なのでこのリストに新しく作ったファイルを詰めて上げれば 最後にコピーされます。

詰めるにはJekyll::StaticFileというオブジェクトの形で詰める必要があるので

site.static_files << Jekyll::StaticFile.new(site, site.source, path, filename)

な感じになります。上のをもう一度書き直すと、

new_file.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module Jekyll

  class NewFile < Liquid::Tag
    @file = nil

    def initialize(tag_name, markup, tokens)
      @file = markup
      super
    end

    def render(context)
      site = context.registers[:site]
      local_file = site.source + @file['src'].sub(site.config['url'], '')
      if File.exist?(local_file)
        `cp #{local_file} #{local_file}.tmp`
        site.static_files << Jekyll::StaticFile.new(site, site.source, local_file.split('/')[0..-2].join('/').sub(site.source), local_file.split('/')[-1])
      end
    end
  end
end
Liquid::Template.register_tag('new_file', Jekyll::Thumbnail)

最初の2つの引数はそのままでよいですが、 3つ目のpathには最後のファイル名と、最初に付いてるsourceのパス部分を 除いてやる必要があります。 (第二引数+第三引数+第四引数の形のパスを最終的に探して dest+第三引数+第四引数へコピーします。)

これでプラグイン内とかで新しいファイルを作っても最後に一緒にコピーされるようになります。

Sponsored Links
Sponsored Links

« Facebookのカウント取得を改善 Octopressでサムネイルを作るプラグインを作った »

}