在给定的分类中生成页面列表(而非文章)

55

我正在使用Jekyll作为网站(而非博客)的静态生成器,希望在我的索引页上自动生成所有页面的列表。具体来说,我想有不同的分类,并分别列出每个分类中的所有文章。如果你难以理解,这里有一个例子。在Jekyll(例如GitHub Pages)中是否有方法可以实现这一点?我看过变量文档页面,但那似乎是针对博客文章格式的。


这是我所描述的一个例子,如果你跟不上的话。顺便说一句,那个页面不是自动生成的 - 我手动添加条目,当我认为它们已经完成并且质量很高时。 - gwern
我刚决定做同样的事情,gwern。 - Mike
4个回答

92

在建立自己的网站时,我也遇到了这个问题,并找到了一个(在我看来)简单且强大的解决方案。

问题

给定站点上的一个页面子集(不是文章),按其类别在标题下列出它们。例如:给定我们认为是“资源”页面的一组页面(或参考页面,或您想要显示的任何逻辑分组的页面),我们希望将它们列在它们的类别下面(例如 代码、解释等)。

解决方案

为了获得我们想要的行为,我们必须在三个地方进行修改:

  • _config.yml
  • resources.md
  • resource-file-X.md

_config.yml

_config.yml中,我们必须添加一个列表,其中包含所有将出现在资源文件中的类别/关键字/标签(或您想要称之为的任何内容)。以下是我的配置示例:

category-list: [code, editors, math, unix]

变量名可以随意定义,我选择了category-list,但请确保在resource.md文件中使用相同的变量名。

注意:在列表中放置项目的顺序就是它们将在resource.md页面上列出的顺序。

resource-file-X.md

这些是您想要在resources.md页面上索引和链接的文件。您只需要在每个文件的顶部添加两个文件变量即可。第一个是指示此文件是资源文件。

resource: true

第二个步骤是指定您希望将此文件归类为哪些类别。您可以将其归类为尽可能多的类别,如果您想让某个页面未被索引,请留下空白列表。我在C语言中处理EINTR时的参考资料具有以下类别:

categories: [code, unix]

资源.md

这个文件将会根据它们各自的类别生成页面列表。你只需要在此文件(或任何你想要列表所在的文件)中添加以下代码:

{% for cat in site.category-list %}
### {{ cat }}
<ul>
  {% for page in site.pages %}
    {% if page.resource == true %}
      {% for pc in page.categories %}
        {% if pc == cat %}
          <li><a href="{{ page.url }}">{{ page.title }}</a></li>
        {% endif %}   <!-- cat-match-p -->
      {% endfor %}  <!-- page-category -->
    {% endif %}   <!-- resource-p -->
  {% endfor %}  <!-- page -->
</ul>
{% endfor %}  <!-- cat -->

代码解析

这里是关于它如何工作的简要说明:

  • 循环遍历在_config.yml中指定的每个类别。
  • 显示具有该类别名称的标题。
  • 为属于该类别的页面启动无序列表。
  • 循环遍历站点上的页面。
  • 如果该页面是一个资源文件,并且由文件变量resource指示,那么对于文件所属的每个类别,如果其中之一与当前列出的类别匹配,则显示链接到该页面。

注意:在_config.yml中修改的变量category-list和资源文件中的categories可以被称为任何你想要的东西,只要确保在生成列表的文件中使用相同的变量。

另请注意:当您修改_config.yml时,即使使用了--watch选项,也必须完全重新启动Jekyll,您必须停止并重新启动它。我花了一段时间才弄清楚为什么我的更改没有生效!

最终产品

您可以在我的网站上的资源页面上查看最终产品,尽管我今天刚刚把它组合起来,所以在撰写本文时,它远未完成,但您可以在主页上查看我的简历。


这个 ressource 文件到底是什么?我应该把它放在哪里?谢谢。 - giac
资源和资源名称-x.md文件放在哪里? - Jwan622
2
抱歉回复晚了,我可能错过了通知。@giacomoV,“资源”这个术语完全是任意的,那只是我所使用的用例,你可以将其替换为“食谱”,“代码实验室”,“教程”等等。几乎任何不是Jekyll中定义的“文章”的东西都可以。希望这样说得清楚:P - m-renaud
@Jwan622 我通常将 resource-name-x.md 文件放在 /resource 的子目录中,例如 /resource/codelabs/{foo,bar,baz}-codelab.md。文件 resource.md 通常最终成为 /resource/index.md。 - m-renaud

18

使用液态模板的 "contains" 属性可以更清晰地完成此操作:

在 _config.yml 中添加您的分类索引

categories: [fruit, meat, vegetable, cheese, drink]
在您的page.md文件中,在front matter中添加一个或多个_config.yml中可用的类别。
---
layout: page
title: Orange juice
description: Orange juice is juice from oranges. It's made by squeezing oranges.
categories: [fruit, drink]
---

在您的模板中获取所有水果类别页面时,您需要执行以下操作:

{% for page in site.pages %}
  {% if page.categories contains 'fruit' %}
    <div class="item">
      <h3>{{page.title}}</h3>
      <p>{{page.description}}</p>
    </div>
  {% endif %}
{% endfor %}

这实际上没有实现 OP 所要求的内容。它还需要您手动定义 _config 中的所有类别,这很繁琐。 - Bob Liberatore

2
你应该区分页面和文章(帖子)。按类别排序列出所有文章并不是问题。你可以通过遍历site.categories来实现。它包含类别名称和该类别中的所有文章列表。
列出所有页面也是可能的。你可以遍历site.pages。但是页面没有属于特定类别(只有文章才有)。
当我看你发布的示例时,使用文章上的类别,然后通过遍历site.categories似乎是正确的方法。这将确切地获得所需的输出。

1
这确实是Jekyll提供的功能限制,但它不符合我的需求。我想通过编写一个bash脚本来构建网站,然后调用一个Haskell脚本按类别插入页面链接。 - Mike
1
使用文章锁定了我不想要的一堆东西(需要使用特定的命名格式,将它们全部放在同一个目录中,强制我使用“post”布局),但是在Jekyll中没有办法在页面上使用分类。 - Mike
你既不需要将它们全部保存在同一个目录中,也不必强制使用“post”布局。默认情况下,文章将使用“post”布局,但是您可以通过YAML Front Matter为每篇文章单独指定布局(实际上,在jekyll < 1.0中这是强制性的)。没错,您需要使用特定的命名约定,但这真的是游戏规则的破坏者吗? - Polygnome
你甚至可以通过使用草稿并在你的_config.yml中设置 show_drafts: true 来解决命名问题 ;) - Polygnome

1

有一些变化/简化是可能的(来自felipesk的回答)。可能是由于Jekyll的改进。

_config.yml不需要索引

如果页面列表不在页面中列出,而是在文档中列出,您也可以将类别添加到文档中:

---
layout: doc
title: Fruit List
categories: [fruit]
---

然后像这样使用它:
{% for p in site.pages %}
   {% if p.categories contains page.category %}
     * [{{ p.title }}]({{ p.url | absolute_url }})
        <small>{{ p.excerpt }}</small>
   {% endif %}
{% endfor %}

使用帖子,这甚至可以更短:

{% for post in site.categories[page.category] %}
  * [{{ post.title }}]({{ post.url | absolute_url }})  
      <small>{{ post.excerpt }}</small>
{% endfor %}

这为什么只对文章有效,我还没想明白。 有趣的是,只要你混合使用文档/页面/文章,这个代码片段就可以在任何地方使用! 所以只需将其添加为_includes并像下面这样使用即可:
## Further Reading
{% include pages-list.md %}

我使用主题Minimal Mistakes



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