【问题标题】:Filter popular posts by category in a collection in Jekyll using Liquid在 Jekyll 中使用 Liquid 按类别过滤热门帖子
【发布时间】:2023-12-25 11:12:01
【问题描述】:

我有一个插件,它可以根据页面浏览量在 Jekyll 的集合中生成热门帖子列表。在集合中,我有两个类别,我想按与原始帖子相同的类别过滤热门帖子。

这是我写的代码:

<ul>
  {% if page.path contains '_kb/cat1' %}
    {% assign popular_posts = site.popular_posts | where:"category","cat1" %}
    {% for page in popular_posts | limit:3 %}
      <li>
        <a href="{{ page.url }}" title="{{ page.title }}">{{ page.title }}</a>
      </li>
    {% endfor %}
  {% else %}
    {% assign popular_posts = site.popular_posts | where:"category","cat2" %}
    {% for page in popular_posts | limit:3 %}
      <li>
        <a href="{{ page.url }}" title="{{ page.title }}">{{ page.title }}</a>
      </li>
    {% endfor %}
  {% endif %}
</ul>
  1. 有什么方法可以让这段代码更简单?
  2. 如何从该列表中排除原始帖子?例如,如果我在热门帖子 1 上,我想显示热门帖子 2、​​3 和 4 的链接,而不是原始帖子本身。

我知道我可以在 Ruby 中使用 if post != self 之类的东西,但我不知道如何在 Liquid 中使用。我已经阅读了一些教程,但没有找到答案。这就是我在这里问的原因。

编辑:我尝试首先访问集合的属性,如下面的@matrixanomaly 建议的那样。但是现在它遍历集合中的每个文档,并给出与集合中文档数量相等的热门帖子列表的数量。这是我的代码。有没有办法将此循环限制为一个,即文档本身(或原始帖子)?

{% for collection in site.collections %}
  {% capture label %}{{ collection | first }}{% endcapture %}
  {% for doc in site.collections.[label].docs %}
    {% assign category = doc.category %}
    {% if page.category == category %}
      {% assign popular_posts = site.popular_posts | where:"category",category %}
      {% for node in popular_posts | limit:3 %}
        {% unless node.url == page.url %}
          <li>
            <a href="{{ node.url }}" title="{{ node.title }}">{{ node.title }}</a>
          </li>
        {% endunless %}
      {% endfor %}
    {% endif %}
  {% endfor %}
{% endfor %}

【问题讨论】:

  • 请在您尝试过的(使用该代码)和无效的方面付出一些努力。由于这个问题(以及您刚刚在 Jekyll 上发布的其他问题)似乎只是“我复制了这段代码,我不知道如何让它做我想做的事,请修复此代码或请给我代码做我喜欢做的事。
  • @matrixanomaly 嗨,李,感谢您的评论。我已经从问题中删除了我尝试过的代码,但它没有用。您可以在修订版*.com/posts/32039416/revisions 中看到它。这是我自己的代码,我没有在任何地方复制它。我知道我可以在 Ruby 中使用 if post != self 之类的东西,但我不知道如何在 Liquid 中使用。我已经阅读了一些教程,但没有找到答案。这就是我在这里问的原因。
  • 我没有注意到您所做的修改,感谢您强调这一点,我很抱歉假设您已将代码带到其他地方(您应该提及您已经编写了它并且您不确定如何从那里继续,因为您的其他问题主要是这里的一些代码)。很高兴知道你已经表现出努力。我花时间看了你的问题,我的答案如下。希望它对你有用!
  • 非常感谢!我只是假设您应该先尝试,然后再寻求帮助:)

标签: jekyll liquid


【解决方案1】:

我假设您正在尝试让您的代码显示与当前帖子相同类别的其他热门帖子。例如,如果您正在撰写有关 Java 的帖子,您希望显示有关 Java 的热门帖子,但当前帖子本身除外。

  1. 如果您已经在每个帖子中设置了类别,您可以使用 Jekyll 中提供的内置变量 page.categories 返回类别列表,例如,如果您在 @987654326 类别下有帖子@ 和 code,你会得到 ['work','code']Here's a list of page variables

而不是{% if page.path contains '_kb/cat1' %},您可以立即获得基于类别的热门帖子。这应该可以工作(我现在没有安装 Jekyll 来测试它)。

<ul>
<!-- uses categories of the current post -->
<!--I used theCategory to avoid confusion, use any variable you want -->
{% for theCategory in page.categories %} 
    {% assign popular_posts = site.popular_posts | where:"category", theCategory %} 
      {% for page in popular_posts | limit:3 %}
         <li>
         <a href="{{ page.url }}" title="{{ page.title }}">{{ page.title }}</a>
         </li>
      {% endfor %}
{% endfor %}
</ul>
  1. 您可以使用 2 种方法排除原始帖子。检查您正在迭代的帖子是否与当前帖子的idurltitle{% if popular_page.id != page.id %}page.url 之类的值相同,如页面变量中所示。第二种方法是使用unless 子句。

如图Liquid for Designers

{% if user.name != 'tobi' %}
  Hello non-tobi
{% endif %}
# Same as above
{% unless user.name == 'tobi' %}
  Hello non-tobi
{% endunless %}

我相信您的问题是,您重复使用了 page 变量,一旦您执行 {% for page in popular_posts %} 您将 page 设为局部变量,您将无法访问当前的帖子变量值。

您想要在最里面的循环中换出是:

{% for popular_post in popular_posts | limit:3 %} <!-- renamed variable -->
    {% unless popular_post.id == page.id %}
             <li>
             <a href="{{ page.url }}" title="{{ page.title }}">{{ page.title }}</a>
             </li>
    {% endunless %}   <!-- you can use if and endif also --->
{% endfor %}

编辑:由于上面的代码可能只显示3,丑陋的解决方法是使用limit:4,但是当当前帖子不受欢迎时,显示4个帖子的边缘情况,然后你可以这样做:

{% 分配 Popular_posts = site.popular_posts |其中“id”!= page.id %} {% for popular_post in popular_posts |限制:3 %} {% 除非 popular_post.id == page.id %}

  • {{ 页面标题 }}
  • {% 无尽 %} {% endfor %}

    我想这是嵌套条件的问题,因为我不确定 Liquid 是否允许在其过滤器中使用多个条件,但您想在执行 limit:3 之前过滤掉当前帖子。

    【讨论】:

    • 您好,李,非常感谢您的回复!不幸的是,我不能使用这部分 {% for theCategory in page.categories %},因为 Collections 中的帖子没有这样的变量。因此,我想我将不得不为 Collection 中的每个类别使用{% if page.category == 'cat1' %}。非常感谢您在第二部分的澄清!我明白为什么我有问题了。但是现在当我在一个受欢迎的帖子上时,我只有另外两个帖子的列表。我想展示 3 个帖子,但要显示下一个热门帖子,而不是原来的帖子。我将在我现在正在处理的代码下方发布。
    • 啊,我明白问题出在哪里了,因为您使用的是集合,在这种情况下,除了在单独的 frontmatter 中为每个集合创建一个 category 变量,如下所示:jekyllrb.com/docs/collections/#accessing-collection-attributes 你是做你正在做的事情可能会更好。至于只有 2 个帖子,添加 where 子句会起作用。 (更新答案)
    • 非常感谢!我还没有尝试过第二部分(带有where 子句)。但我尝试访问集合的category 属性,以使代码首先适用于所有集合。但是现在它遍历集合中的每个文档,并给出与集合中文档数量相等的热门帖子列表的数量。 (我将在答案中发布下面的代码。)
    • @jupiteror 由于您对 SO 还很陌生,因此我谦虚地建议您在其他人的答案有用/有帮助的情况下对其进行投票,然后如果他们确实解决了问题,请将其标记为一个答案。 :) 每个回答的人都会在您可能遇到的问题上投入时间,祝您好运。
    • 您好,我赞成您的回答,非常感谢您的努力。但是where "id" != page.id 在分配标签中不起作用。它给出了一个错误,说明参数数量错误,1 为 3。也许你知道我如何在插件中做到这一点?我在这里*.com/questions/32029534/… 发布了一个类似的问题。如果您能就逻辑提供一些建议(首先排序,然后按类别分组等),我将不胜感激。我会尝试自己编写代码。