【问题标题】:How do you sort site.tags by post count in Jekyll?你如何在 Jekyll 中按帖子计数对 site.tags 进行排序?
【发布时间】:2014-09-02 06:10:28
【问题描述】:

抱歉,我是 Ruby 新手,但我正在尝试向我的模板添加一个液体标签,我可以循环显示五个最受欢迎标签的列表。

由于某种原因,这个插件在我使用时只输出一个标签。

这是我放入 mu 插件的内容:

module Jekyll
  class PopularTags < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
    end

    def render(context)
      tags = context.registers[:site].tags
      return tags.sort_by { |tag, posts| posts.count }
    end
  end
end
Liquid::Template.register_tag('popular_tags', Jekyll::PopularTags)

这是我在模板中输入的内容:

{% popular_tags %}

【问题讨论】:

  • 尝试检查 popular_tags 返回的内容,同时在不带参数的初始化时调用 super 味道不好。
  • 当它离开 ruby​​ 方法时,它被正确排序。
  • 好的,我正在取得进展。现在我似乎无法在 for 循环中循环标记,但如果我只是将其转储到 Liquid 中,它就在那里,已排序。

标签: ruby jekyll


【解决方案1】:

实际上,从我目前阅读的内容来看,Jekyll 中的标签插件应该像标签一样使用,而不是像变量一样使用。所以在这种情况下,你确实应该在你的模板中使用它:

{% popular_tags %}

但你班级的行为似乎是错误的。它不应该返回变量/散列,它应该返回将显示的 HTML 代码,而不是 popular_tags 标记

例如,您可以这样做:

module Jekyll
  class PopularTags < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
    end

    def render(context)
      tags = context.registers[:site].tags

      html = "<ul>"
      sorted = tags.sort_by { |t,posts| posts.count }
      sorted.each do |t, posts|
        html << "<li>TAG: #{t} (#{posts.count})</li>"
      end
      html << "</ul>"

      html
    end
  end
end

Liquid::Template.register_tag('popular_tags', Jekyll::PopularTags)

希望这会有所帮助。我刚刚尝试过,它按预期工作。如果您想首先显示最常用的标签,只需更改sort_by 行,并使用-posts.count 而不是posts.count

你可以看看this other plugin source code,可能对你有帮助。

【讨论】:

  • 非常感谢,这有帮助。我试图将标记保留在插件和模板中,我认为它属于。那么如何在 Jekyll 中为模板提供变量呢?
  • 老实说,我不知道。我自己并没有使用 Jekyll,只是快速浏览了一下以提供帮助。也许你的popular_tags 可以返回一个序列化的数组或特定格式的字符串,你可以在你的视图中拆分,但我不确定这是否是实现这一目标的一种非常干净的方法。
【解决方案2】:

也可以在没有插件的情况下执行此操作,这意味着它将在GitHub Pages 上工作。

我已经在my blog 上做类似的(也没有插件),我正在显示一个带有帖子计数的标签列表,按字母顺序排序。 The source code is here.

修改它以便按帖子数排序并不费力:

{% capture tags %}
  {% for tag in site.tags %}
    {{ tag[1].size | plus: 1000 }}#{{ tag[0] }}#{{ tag[1].size }}
  {% endfor %}
{% endcapture %}
{% assign sortedtags = tags | split:' ' | sort %}
{% for tag in sortedtags reversed %}
    {% assign tagitems = tag | split: '#' %}
    <li><a href="/tags/#{{ tagitems[1] }}">{{ tagitems[1] }} ({{ tagitems[2] }})</a></li>
{% endfor %}

我想有一些必要的解释:

tag[0] 是标签的名称。
tag[1] 是一个包含标签帖子的数组,所以tag[1].size 是帖子数。

  1. 基本上,我们需要捕获像tag[1].size#tag[0] 这样的东西,这会产生这样的字符串:

    3#TagWithThreePosts 1#TagWithOnePost 2#TagWithTwoPosts
    
  2. 然后,在{% assign sortedtags = ... 行中,我们再次对其进行拆分并对其进行排序,因此结果是一个排序后的字符串数组:

    • 1#TagWithOnePost
    • 2#TagWithTwoPosts
    • 3#TagWithThreePosts
  3. 在最后一个循环中,我们以反向(=降序)顺序循环,除以# 以获得标签名称和帖子计数,并显示链接。

唯一的问题是标签包含 10 个或更多帖子。
由于我们正在对字符串进行排序,因此第 2 步的结果如下所示:

  • 1#TagWithOnePost
  • 10#TagWithTenPosts错误的顺序,因为它是一个字符串!
  • 2#TagWithTwoPosts
  • 3#TagWithThreePosts

为了解决这个问题,我在帖子计数中添加了 1000 以进行排序。所以1#...10#... 变成了1001#...1010#...,它们的顺序是正确的。

我仍然想显示实际的帖子编号(不添加 1000),所以我将其作为第三项附加到 {% capture tags %} 部分:

{{ tag[1].size | plus: 1000 }}#{{ tag[0] }}#{{ tag[1].size }}

顺便说一句,我正在链接到一个标签页面(/tags/#blah,例如单个页面上所有标签的所有帖子),我也以类似的方式实现了它,described here

【讨论】:

  • 太酷了!是否也可以根据帖子计数对标签进行排序?
  • 这很漂亮,但它不适用于带有空格的标签
  • 这非常好,但它不适用于@mpchadwick 添加的带有空格的标签,并且它不会以这种方式按字母顺序对标签进行排序。由于颠倒了两者之间的列表,它确实颠倒了字母顺序。我修复了这两个问题并将解决方案发布在我的博客上:gungorbudak.com/blog/2017/12/08/…。这不是一个公认的答案,但它真的很好,所以我仍在分享。谢谢!
  • @GungorBudak,另一种解决方案是将plus: 1000改为minus: 1000
  • 这非常聪明,也是唯一对我有用的解决方案。我试过编写自定义液体过滤器无济于事,我不想安装插件。 @mpchadwick:fwiw,我通过使用{{ tag[0] | slugify }} 进行排序解决了这个问题。您甚至可以稍后通过将其作为另一个项目添加到返回的已排序元组中来恢复原始 tag[0] 值。
猜你喜欢
  • 2014-12-06
  • 2022-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 2021-10-05
  • 2014-03-20
  • 2016-07-22
相关资源
最近更新 更多