Return list of files in directory from Jekyll plug

2019-06-16 03:46发布

I can't figure out how to create a filter or tag in a jekyll plugin, so that I can return a directory and loop over its contents. I found these:

http://pastebin.com/LRfMVN5Y

http://snippets.dzone.com/posts/show/302

So far I have:

module Jekyll
  class FilesTag < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
      @text = text
    end

    def render(context)
        #"#{@text} #{Time.now}"
        Dir.glob("images/*").each { |i| "#{i}" }
        #Dir.glob("images/*")
        #Hash[*Dir.glob("images/*").collect { |v| [v, v*2] }.flatten]
    end
  end
end

Liquid::Template.register_tag('files', Jekyll::FilesTag)

I can successfully return the list of images as a string and print it with:

{% files test_string %}

But for the life of me, I can't loop over the array, no matter how I return the array/hash from Dir.glob. I just want to be able to do:

{% for image in files %}
    image
{% endfor %}

I'm going to need to be able to return arrays of things constantly for the various collections I'll be using on the site. I just need a barebones plugin to build upon.

Thanks!


UPDATE: I partially solved it. This method works but requires using endloop_directory instead of endfor, which seems a bit ugly to me. Also, the filter is unable to take a parameter like *.{jpg,png} because there is no way to escape the {} in the html. Open to suggestions on how to pass a regex string in an attribute...

#usage:
#{% loop_directory directory:images iterator:image filter:*.jpg sort:descending %}
#   <img src="{{ image }}" />
#{% endloop_directory %}
module Jekyll
    class LoopDirectoryTag < Liquid::Block

        include Liquid::StandardFilters
        Syntax = /(#{Liquid::QuotedFragment}+)?/

        def initialize(tag_name, markup, tokens)
            @attributes = {}

            @attributes['directory'] = '';
            @attributes['iterator'] = 'item';
            @attributes['filter'] = 'item';
            @attributes['sort'] = 'ascending';

            # Parse parameters
            if markup =~ Syntax
                markup.scan(Liquid::TagAttributes) do |key, value|
                    @attributes[key] = value
                end
            else
                raise SyntaxError.new("Bad options given to 'loop_directory' plugin.")
            end

            #if @attributes['directory'].nil?
            #   raise SyntaxError.new("You did not specify a directory for loop_directory.")
            #end

            super
        end

        def render(context)
            context.registers[:loop_directory] ||= Hash.new(0)

            images = Dir.glob(File.join(@attributes['directory'], @attributes['filter']))

            if @attributes['sort'].casecmp( "descending" ) == 0
                # Find files and sort them reverse-lexically. This means
                # that files whose names begin with YYYYMMDD are sorted newest first.
                images.sort! {|x,y| y <=> x }
            else
                # sort normally in ascending order
                images.sort!
            end

            length = images.length
            result = []

            context.stack do
                images.each_with_index do |item, index|
                    context[@attributes['iterator']] = item
                    context['forloop'] =
                    {
                        'name' => @attributes['iterator'],
                        'length' => length,
                        'index' => index + 1,
                        'index0' => index,
                        'rindex' => length - index,
                        'rindex0' => length - index - 1,
                        'first' => (index == 0),
                        'last' => (index == length - 1) 
                    }

                    result << render_all(@nodelist, context)
                end
            end

            result
        end
    end
end

Liquid::Template.register_tag('loop_directory', Jekyll::LoopDirectoryTag)

3条回答
Melony?
2楼-- · 2019-06-16 04:03

I found a plugin here: How to list files in a directory with Liquid? that might do the trick:

Jekyll::DirectoryTag This tag lets you iterate over files at a particular path. The directory tag yields a file object and a forloop object. If files conform to the standard Jekyll format, YYYY-MM-DD-file-title, then those attributes will be populated on that file object.

https://github.com/sillylogger/jekyll-directory

查看更多
太酷不给撩
3楼-- · 2019-06-16 04:03

Is there a specific reason you're using Jekyll? It seems like you want something more dynamic, whereas Jekyll is designed to generate flat HTML files.

You might be happier using something like Sinatra, where you can do something very straightforward to grab the list of files and iterate over them in a template.

查看更多
Fickle 薄情
4楼-- · 2019-06-16 04:16

There is a Pull Request on the Github Master Branch for this feature waiting to be merged into the Jekyll 1.0.0beta; they are just waiting for final approval from the creator TPW.

You can view the code and copy it for your own use now, and keep an eye out for when in gets merged. Then you can download the merged Jekyll with that feature and use it without a plugin, by doing:

gem install jekyll --pre

Which will get you the edge version from Github.

Here's the PR - New Liquid tag for listing files: directory:

https://github.com/mojombo/jekyll/pull/585

查看更多
登录 后发表回答