-
-
Save jgatjens/8925165 to your computer and use it in GitHub Desktop.
#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 | |
result = [] | |
context.stack do | |
# remove filename extension | |
images.each { |pathname| | |
context[@attributes['iterator']] = File.basename(pathname, @attributes['filter'].sub('*', '')) | |
result << render_all(@nodelist, context) | |
} | |
# return pathname | |
# images.each_with_index do |item, index| | |
# context[@attributes['iterator']] = item | |
# result << render_all(@nodelist, context) | |
# end | |
end | |
result | |
end | |
end | |
end | |
Liquid::Template.register_tag('loop_directory', Jekyll::LoopDirectoryTag) |
this is working well for me, THANKS!
I am trying to work out how to send the number of files in the directory as well (result.length ??). Can you point me in the right direction on what code to add? I'm a ruby noob.
mikeritter - basic instructions:
add the file above to the plug-ins folder
restart your jekyll server
add lines 2-4 to your html page
- remove the # preceding the line
- change the directory if needed
- I changed filter:.jpg to filter: so it finds all files (not just .jpg, which is case sensitive as well)
- try adding this line so you can see what the plug-in is outputting: {{ image }}
Linking back: the StackOverflow question this came from
@jgatjens this is an amazing plugin and should probably be probably be part of liquid!
I'm trying to pass a variable subdirectory to loop through but can't get it to work. Something like this:
{% loop_directory directory:{{page.url | remove_first: "/"}}thumbnail
I'm looking through stackoverflow questions on passing variables as arguments in liquid, but can't get any to work.
@planemad, were you able to get this working? This seems like a common use case. I am trying to solve the same problem as well.
For now I am using the solution presented here.
I get a
> jekyll serve --trace
Configuration file: /home/skuzzymiglet/ysgol/gwefan-jekyll/_config.yml
Source: /home/skuzzymiglet/ysgol/gwefan-jekyll
Destination: /home/skuzzymiglet/ysgol/gwefan-jekyll/_site
Incremental build: disabled. Enable with --incremental
Generating...
Liquid Exception: undefined method `render_all' for #<Jekyll::LoopDirectoryTag:0x000056284e5f07e0> in index.md
Traceback (most recent call last):
41: from /home/skuzzymiglet/.gem/ruby/2.6.0/bin/jekyll:23:in `<main>'
40: from /home/skuzzymiglet/.gem/ruby/2.6.0/bin/jekyll:23:in `load'
39: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/exe/jekyll:15:in `<top (required)>'
38: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/mercenary-0.3.6/lib/mercenary.rb:19:in `program'
37: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/mercenary-0.3.6/lib/mercenary/program.rb:42:in `go'
36: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `execute'
35: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `each'
34: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `block in execute'
33: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/commands/serve.rb:86:in `block (2 levels) in init_with_program'
32: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/command.rb:89:in `process_with_graceful_fail'
31: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/command.rb:89:in `each'
30: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/command.rb:89:in `block in process_with_graceful_fail'
29: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/commands/build.rb:36:in `process'
28: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/commands/build.rb:65:in `build'
27: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/command.rb:28:in `process_site'
26: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:76:in `process'
25: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:202:in `render'
24: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:515:in `render_pages'
23: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:515:in `each'
22: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:516:in `block in render_pages'
21: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/site.rb:523:in `render_regenerated'
20: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/renderer.rb:63:in `run'
19: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/renderer.rb:80:in `render_document'
18: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/renderer.rb:127:in `render_liquid'
17: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:32:in `render!'
16: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:60:in `measure_time'
15: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:33:in `block in render!'
14: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:53:in `measure_bytes'
13: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:34:in `block (2 levels) in render!'
12: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:49:in `measure_counts'
11: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/jekyll-4.0.0/lib/jekyll/liquid_renderer/file.rb:35:in `block (3 levels) in render!'
10: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/template.rb:220:in `render!'
9: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/template.rb:207:in `render'
8: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/template.rb:242:in `with_profiling'
7: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/template.rb:208:in `block in render'
6: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/block_body.rb:82:in `render'
5: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/block_body.rb:103:in `render_node_to_output'
4: from /home/skuzzymiglet/ysgol/gwefan-jekyll/_plugins/loop_dir.rb:52:in `render'
3: from /home/skuzzymiglet/.gem/ruby/2.6.0/gems/liquid-4.0.3/lib/liquid/context.rb:123:in `stack'
2: from /home/skuzzymiglet/ysgol/gwefan-jekyll/_plugins/loop_dir.rb:56:in `block in render'
1: from /home/skuzzymiglet/ysgol/gwefan-jekyll/_plugins/loop_dir.rb:56:in `each'
/home/skuzzymiglet/ysgol/gwefan-jekyll/_plugins/loop_dir.rb:58:in `block (2 levels) in render': undefined method `render_all' for #<Jekyll::LoopDirectoryTag:0x000056284e5f07e0> (NoMethodError)
my index.md:
---
layout: default
title: "Happy Jekylling!"
---
## You're ready to go!
{% loop_directory directory:images iterator:image filter:*.jpg sort:descending %}
<img src="{{ image }}" />
{% endloop_directory %}
Clean, jekyll new --blank
site
@skuzzymiglet do you have some repo with the code to see what's going on there?
i have come across the same problem. seems like Liquid::Block
does not provide the render_all
method anymore. Even the regular Liquid::Block::render()
method is marked "For backwards compatibility". Likewise, the whole API for liquid blocks has changed.
I will have a more in-depth look into the problem, but never having wrote a liquid/jekyll module myself, it will not be very successful, i fear.
For a simpler version that works well with the built-in for
block and works with current versions of liquid, see https://gitlab.com/baldrian/klimacamp-augsburg/-/blob/91244ae327380714e6d62778598a4bc69917c557/_plugins/list_files.rb. It creates a Page object for each of the files that were found, so if you don't want that, remove the .map do ... end
part (you can also remove the site = ...
and source = ...
lines as well as the comment in that case) – without the map call, you'll get a list of filenames instead of a list of pages. See https://gitlab.com/baldrian/klimacamp-augsburg/-/blob/91244ae327380714e6d62778598a4bc69917c557/feeds/pressemitteilungen.xml#L14-15 for an example usage.
I can't seem to get it work.
my directory for the image folder is /images under root directory.
The frontmatter in the post, I have "photos: /images"
and in my layout html, I have:
{% loop_directory directory: {{ page.photos }} iterator:image filter:*.jpg sort:descending %}
<img src="{{ image }}" />
{% endloop_directory %}
but nothing's showing. What did I do wrong?
@meiadvanture this is like 8 years old or more, try this tho:
{% loop_directory directory:images iterator:image filter:*.jpg sort:descending %}
<img src="{{ image }}" />
{% endloop_directory %}
Not sure about your {{ page.photos }}
try it without that first and see.
Please add a README.md with install instructions for noobs and maybe even build testing if you're feeling adventurous.
I am trying following Jekyll's plugin instructions but not getting anywhere.