如何使用Liquid列出目录中的文件?

35

我正在学习如何使用 Jekyll 和 Bootstrap; 在学习它们的同时,我决定在我的主页上添加一个图片轮播功能。

由于我非常懒惰,我不想硬编码布局中显示每张图片所需的路径,也不想使用数组来存储图片列表。

我想知道是否有任何标签可以要求 Jekyll 执行以下两个步骤:

  1. 查找特定目录
  2. 对于在该目录中找到的每个文件,重复一个代码块

基本上,我想写的东西大致类似于这段(想象中的)代码:

{% for file in directory %}
    <img src="{{ file.url }}" />
{% endfor %}
所以,例如,如果我有一个文件夹,里面有三个文件名为image01.jpg、image02.jpg和image03.jpg,我希望jekyll能为我构建以下HTML代码:
<img src="folder/image01.jpg" />
<img src="folder/image02.jpg" />
<img src="folder/image03.jpg" />

所以我看了一下这个参考页面,但是对于我的目的没有找到任何有用的信息。

请问您能否给我任何建议,如果可能的话,不涉及使用插件的建议?

提前感谢您。


这与 https://dev59.com/CmHVa4cB1Zd3GeqPqtv7 不同吗? - Ciro Santilli OurBigBook.com
9个回答

21
你可以使用这个插件。将这段代码复制粘贴到你的Jekyll项目根目录下的_plugins目录中的一个文件中。

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

然后,只需添加下面的几行即可使用。
{% loop_directory directory:images iterator:image filter:*.jpg sort:descending %}
   <img src="{{ image }}" />
{% endloop_directory %}

2
虽然需要添加插件,但这应该是正确的答案,因为它几乎完全符合 OP 想要做的事情。 - Kevin Chen

19

使用Jekyll集合API。截至2015-08-07,该API附带了一个重要的警告:

集合支持不稳定并且可能会更改

_config.yml中定义一个集合,并在您的根目录中创建一个名为_images的文件夹。

collections:
- images

在不需要为图像添加YAML front-matter的情况下,Jekyll将会:

集合中没有front matter的文件将被视为静态文件,只需将其复制到输出位置而不进行处理。

静态文件 具有以下属性:

  • file.path
  • file.extname

然后你页面上的代码将类似于以下内容(未经测试):

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

非常感谢您抽出时间回答我的问题。 - Cesco
1
你甚至不需要为此定义一个集合,对吧?请参见:https://talk.jekyllrb.com/t/iterate-for-loop-over-images-in-a-folder/1766/5 - Arrowcatch

14

没有插件也不是完全不可能,但是当然需要使用一些巧妙的方法。例如,您可以将图像路径放在 YAML 前置数据中,当 Jekyll 处理页面时它们就会可用。

---
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 %}

对于整站图片,您需要一个插件。但是如果您想让您的图片位于特定页面或文章中,这个应该可以满足您的需求。 :)

希望这能有所帮助!


非常感谢。这不完全是我想要的答案,但我认识到这比在布局中存储图像路径数组更好。 - Cesco

10

根据@raphael的回答,您可以使用以下代码列出jpg文件:

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

您可能想要删除一些换行符,以便在输出中获得一个单一的列表(而不是仅有一个元素的列表)。


1
您可以使用空格控制来消除编译时的换行,而不会使代码变得丑陋:{%- if condition -%}{%- endif -%}等。 - hzahnuwen

8

编辑(2015-11-09): Jekyll已经得到了一些更新,尤其是site.static_pages。请查看@raphael的答案以获取可能的解决方案。

如果不使用插件,则无法实现。您在Liquid模板中没有I/O功能。

如果您的图片有前置元数据,则它们可能会被Jekyll处理并存储在site.pages数组中,从而可以访问,但我不建议在图片上放置前置元数据(对于SVG可能有意义,但对于其他任何内容都不是这样)。

您最好写一个小的shell脚本来扫描您的文件夹中的图像并创建一个images.json文件。然后可以通过Ajax加载此文件。每次上传新文件时,您只需重新创建您的images.json文件(如果您使用Git,则可以将其作为pre-commit挂钩执行)。


1
我认为这不再适用了。请看下面我的回答。 - raphael
1
当我写这个答案时,site.static_pages 不存在 ;) 我已经在我的答案中添加了一个提示,说明 Jekyll 已经得到更新。 - Polygnome

3

Jekyll:DirectoryTag插件来自SillyLogger,它允许您在特定路径上迭代文件。目录标签会生成一个文件对象和一个forloop对象。如果文件符合标准的Jekyll格式YYYY-MM-DD-file-title,则这些属性将填充到该文件对象中。

例如,对于图像:

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

1

参考文档,你可以列出_post_data中的文件,只要在正文前有它的名称。
对于图片,我们需要通过_collection先放置它们。

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

0
如果您不想使用插件,另一种获取文件名的方法是直接修改Jekyll中的Ruby静态文件: 路径示例:C:\Ruby22-x64\lib\ruby\gems\x.x.x\gems\jekyll-x.x.x\lib\jekyll
编辑static_files.rb并更改:
def to_liquid
  {
    "extname"       => extname,
    "modified_time" => modified_time,
    "path"          => File.join("", relative_path)
  }
end

到:

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

现在您可以使用以下命令列出 DIR_NAME 目录中的每个“png”文件并获取其名称:

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

0
使用 site.pages:
{% for page in site.pages %}
* {{ page.path }}
{% endfor %}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接