Cesco
Cesco

Reputation: 3870

How to list files in a directory with Liquid?

I'm trying to learn how to use Jekyll along with Bootstrap; while studying them, I decided that I'd like to have an image carousel on my homepage.

Since I'm really lazy I don't want to hard-code the paths needed to display every image inside the layout, and I wouldn't either prefer to use an array to store the list of images.

I was wondering if there's any tag that could ask Jekyll to do these two steps:

  1. Look inside a specific directory
  2. For each file you found in that directory, repeat a block of code

Basically what I'd like to write is something that vaguely resemble this piece of (imaginary) code:

{% for file in directory %}
    <img src="{{ file.url }}" />
{% endfor %}

So if, for example, I have a folder with three files named image01.jpg, image02.jpg, image03.jpg, I'd like that jekyll could build this HTML code for me:

<img src="folder/image01.jpg" />
<img src="folder/image02.jpg" />
<img src="folder/image03.jpg" />

So I had a look at this reference page but I haven't found anything useful for my purpose.

Please, could you give me any suggestion, and if possible, one that doesn't involve the use of a plugin?

Thank you in advance.

Upvotes: 35

Views: 14738

Answers (9)

Gabor Szarnyas
Gabor Szarnyas

Reputation: 5047

Based on @raphael's answer, you could use the following code to list jpg files:

{% for file in site.static_files %}
  {% if file.extname == ".jpg" -%}
     * [{{ file.path }}]({{ site.baseurl }}{{ file.path }})
  {%- endif %}
{% endfor %}

You'd probably like to remove some of the newline characters to get a single list in the output (instead of lists with only one element).

Upvotes: 10

kolypto
kolypto

Reputation: 35334

Use site.pages:

{% for page in site.pages %}
* {{ page.path }}
{% endfor %}

Upvotes: 0

eQ19
eQ19

Reputation: 10691

Refer to docs you can list files in _post, _data as long there is its name in front matter.
For images we need to put them first by _collection

{% for file_hash in site.post %}
{% assign file = file_hash[1] %}
{{ file.name }}
{% endfor %}

Upvotes: 1

gguen
gguen

Reputation: 11

If you don't want to use a plugin, another way to get the filename is to modify directly the ruby static_files in jekyll: Path ex: C:\Ruby22-x64\lib\ruby\gems\x.x.x\gems\jekyll-x.x.x\lib\jekyll

Edit static_files.rb and change:

def to_liquid
  {
    "extname"       => extname,
    "modified_time" => modified_time,
    "path"          => File.join("", relative_path)
  }
end

to:

def to_liquid
  {
    "extname"       => extname,
    "modified_time" => modified_time,
    "path"          => File.join("", relative_path),
    "name"          => @name
  }
end

You're now able to list each "png" file and get its name in a DIR_NAME directory using:

{% for file in site.static_files %}
  {% if file.extname == ".png" and file.path contains '/DIR_NAME/' %} 
   {{ file.name }}
  {% endif %}
{% endfor %}

Upvotes: 0

Polygnome
Polygnome

Reputation: 7795

edit (2015-11-09): Jekyll has since gotten some updates, especially site.static_pages. Check @raphael answer for a possible solution.

It is impossible without using a plugin. You do not have I/O capabilities inside Liquid Templates.

If your images have front matter, they might get processed by Jekyll and be stored in the site.pages array and thus being accessible, but I wouldn't recommend placing Front Matter on images (might make sense for SVGs, but not for anything else).

Your best bet is probably to write a little shell script that scans your folder for images and creates an images.json file. This file could then be loaded via Ajax. You'd just have to recreate your images.json file every time you upload a new file (if you are using Git, you could to that as a pre-commit hook).

Upvotes: 8

raphael
raphael

Reputation: 2823

Using the Jekyll collections API, which, as of 2015-08-07 came with the big warning

Collections support is unstable and may change

Define a collection in _config.yml and creates an _images folder in your root directory

collections:
- images

Without having to add YAML front-matter to your images, Jekyll will:

Files in collections that do not have front matter are treated as static files and simply copied to their output location without processing.

Static files have the following attributes:

  • file.path
  • file.extname

And then the code on your page would be something like (untested):

{% for image in site.images %}
     {% if image.extname == 'jpg' %}
         <img src="{{ file.url }}" />
     {% endif %}
{% endfor %}

Upvotes: 19

raphael
raphael

Reputation: 2823

The Jekyll:DirectoryTag plugin from SillyLogger

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.

For example with images

<ul>
  {% directory path: images/vacation exclude: private %}
    <li>
      <img src="{{ file.url }}"
           alt="{{ file.name }}"
           datetime="{{ file.date | date_to_xmlschema }}" />
    </li>
  {% enddirectory %}
</ul>

Upvotes: 3

jgatjens
jgatjens

Reputation: 688

You can use this plugin. Copy and paste this code in a file inside the _plugins directory at the root of your Jekyll project.

https://gist.github.com/jgatjens/8925165

Then to use it just add the lines below

{% loop_directory directory:images iterator:image filter:*.jpg sort:descending %}
   <img src="{{ image }}" />
{% endloop_directory %}

Upvotes: 21

Carlos Agarie
Carlos Agarie

Reputation: 4002

It's not completely impossible without a plugin, but of course you'll need to use some kludges. For example, you can put the image paths in your YAML front matter and they'll be available when Jekyll processes your page.

---
carousel_images:
  - images/img01.png
  - images/img02.png
  - images/img03.png
---

# Lots of page-related code.

{% for img in page.carousel_images %}
  # Do something.
{% endfor %}

For site-wide images, you'll need a plugin. But if you want your images to be located in a specific page or post, this should do. :)

Hope that helps!

Upvotes: 14

Related Questions