Ruby Liquid 模板引擎中的模数(或缺乏模数)

发布于 2024-08-21 23:14:41 字数 983 浏览 9 评论 0原文

我正在 Jekyll 网站上工作,并尝试输出嵌套在行 div 中的三列 div。 Liquid 使得这个使用他们的 cycle 过滤器非常简单:

{% for p in site.categories.post %}
    {% cycle 'add rows': '<div class="row">', nil, nil %}
        <div class="column">
            <a href="{{ p.url }}">{{ p.title }}</a>
        </div>
    {% cycle 'close rows': nil, nil, '</div>' %}
{% endfor %}

但是,这只在有 3、6、9 等帖子时才真正有效。当帖子总数不是三的倍数时,

永远不会关闭 - for 循环在结束标记可以作为以下内容的一部分输出之前结束关闭行循环。

在 Ruby、PHP 或任何其他语言中,我可以使用模运算符轻松修复此问题,因此除了 close rows 循环之外,我还会在 时输出 代码>如果site.categories.size % 3 == 0。然而,Liquid 因为它是一种安全的模板语言,所以不支持模数。

当帖子总数不是三的倍数时,我还能做些什么来正确关闭

I'm working on a Jekyll site and am trying to output three column divs nested in a row div. Liquid makes this pretty easy with their cycle filter:

{% for p in site.categories.post %}
    {% cycle 'add rows': '<div class="row">', nil, nil %}
        <div class="column">
            <a href="{{ p.url }}">{{ p.title }}</a>
        </div>
    {% cycle 'close rows': nil, nil, '</div>' %}
{% endfor %}

However, this only really works when there are 3, 6, 9, etc. posts. When the total number of posts is not a multiple of three, the <div class="row"> never gets closed--the for loop ends before the closing tag can be output as part of the close rows cycle.

In Ruby, PHP, or any other language I could easily fix this with a modulus operator, so in addition to close rows cycle I would output </div> when if site.categories.size % 3 == 0. However, Liquid, because it's a safe templating language, doesn't support the modulus.

What else can I do to properly close <div class="row"> when the total number of posts is not a multiple of three?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

ぺ禁宫浮华殁 2024-08-28 23:14:41

我发现这种方法非常有效!

{% assign mod = forloop.index0 | modulo:4 %}
{% if mod == 0 %}
   <!-- Do stuff -->
{% endif %}

I've found this way to work great!

{% assign mod = forloop.index0 | modulo:4 %}
{% if mod == 0 %}
   <!-- Do stuff -->
{% endif %}
水波映月 2024-08-28 23:14:41

对于您的具体示例,您可以使用 {% Cycle 'close rows': nil, '', '' %}{% endfor %} 之后。

For your specific example, you could use {% cycle 'close rows': nil, '</div>', '</div>' %} after the {% endfor %}.

二智少女猫性小仙女 2024-08-28 23:14:41

目前唯一的方法是编写一个液体过滤器来实现这一点。在代码中适当的位置注册过滤器(如果使用 Rails 和不使用 Rails,则在不同的位置)。

液体::Template.register_filter(LiquidFilters)

在您的项目/lib目录中添加liquid_filters.rb:

module LiquidFilters  
  # makes modulus operation available to templates
  def mod(data, param)
    data % param
  end  
end

之后您可以在模板中使用它,如下所示:
{{ 变量 | mod:5 }}

如果您需要将它用于某些逻辑,您可以捕获该值。

{% capture modulus %}{{ variable | mod:5 }}{% endcapture %}

只是我注意到捕获的值是一个字符串,因此为了比较它,您使用

{% if modulus == "0" %}
 ..
{% endif %}

The only way for now is to write a liquid filter to accomplish this. Register the filter somewhere in your code where it's appropriate (it's in different places if using with rails and without them).

Liquid::Template.register_filter(LiquidFilters)

In you projects /lib directory add liquid_filters.rb:

module LiquidFilters  
  # makes modulus operation available to templates
  def mod(data, param)
    data % param
  end  
end

After that you can use it like following in your templates:
{{ variable | mod:5 }}

And if you need to use it for some logic you can capture the value.

{% capture modulus %}{{ variable | mod:5 }}{% endcapture %}

Just I've noticed that captured value is a string so in order to compare it you use

{% if modulus == "0" %}
 ..
{% endif %}
听,心雨的声音 2024-08-28 23:14:41

我在 for 循环中使用了另一个技巧:在你的情况下没用,如果你只是想要一个模来确定你的行是否已经结束并且你需要一个新行,就像我一样,那么很有用。

在这个例子中,我将使用一行 4 项:

{% assign currentRow = 1 %}
# enter the for loop ... then, with 4 as the divisor:
{% if forloop.index == 4 * currentRow %}
  # do whatever you want
  {% assign currentRow = currentRow + 1 %}
{% endif %}
# exit the for loop

不是很好,但很简单。

I used another trick in a for loop : useless in your case, useful if you just want a modulo in order to find out if your line has ended and you need a new row, like I did.

In this example I'll go with a line of 4 items :

{% assign currentRow = 1 %}
# enter the for loop ... then, with 4 as the divisor:
{% if forloop.index == 4 * currentRow %}
  # do whatever you want
  {% assign currentRow = currentRow + 1 %}
{% endif %}
# exit the for loop

Not very nice, but easy.

岁吢 2024-08-28 23:14:41

我意识到这个问题已经为提问者解决了,但我最近在 Liquid 中遇到了这种情况,我想我会提供我的解决方案,以防它可以帮助有类似标记要求的人。

就我而言,我已经通过了一个 if 语句来验证至少有一个帖子,因此我在循环外创建了第一个“行”div。我也在 for 循环之后关闭它。这可以防止帖子少于三个的情况。

<div class="row">

    {% for p in posts %}
        <div class="column">
            <!-- Post code here -->
        </div>
        {% unless forloop.last %}
            {% cycle '', '', '</div><div class="row">' %}
        {% endunless %}
    {% endfor %}

</div>

每三篇帖子后,cycle 将关闭当前行并打开一个新行除非该帖子是 forloop 中的最后一篇,在这种情况下我们不想打开一个新行,并且让包装 将其关闭。

I realize the question has been solved for the asker, but I recently came upon this kind of situation in Liquid and thought I'd provide my solution in case it helps someone with similar markup requirements.

In my case, I've already passed an if statement verifying that there is at least one post, so I created the first "row" div outside the loop. I also close it after the for loop. This protects against a case where there are less than three posts.

<div class="row">

    {% for p in posts %}
        <div class="column">
            <!-- Post code here -->
        </div>
        {% unless forloop.last %}
            {% cycle '', '', '</div><div class="row">' %}
        {% endunless %}
    {% endfor %}

</div>

After every three posts, cycle will close the current row and open up a new one unless the post was the last one in the forloop, in which case we don't want to open a new row, and let the wrapping </div> close it up.

你在我安 2024-08-28 23:14:41

我从这篇文章中学到了很多东西,这是我在整个项目中使用的三种模式。它与 Bootstrap 配合也很好。只需更改以下代码中的列类即可。除了列之外,相同的模式还可以应用于模数有用的其他场景,例如奇偶行。希望它对某人有帮助 -

四列:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>', '</div>' %}
</div>

三列:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>' %}
</div>

两列:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>' %}
</div>

I learned a lot from this post, and these are three patterns I used throughout my project. It worked great with Bootstrap too. Just change the column class in the following code. Instead of columns, the same patterns can be applied to other scenarios where modulo is useful, such as odd-even rows. Hope it helps someone -

Four columns:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>', '</div>' %}
</div>

Three columns:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>' %}
</div>

Two columns:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>' %}
</div>
冰葑 2024-08-28 23:14:41

IIRC Liquid 不会阻止模运算,只会阻止 % 字符。您可以在不使用 % 运算符的情况下执行模数运算。例如,14.modulo(3) => 2 而不是 14 % 3

IIRC Liquid doesn't block the modulo operation, only the % character. You can perform a modulus without using the % operator. For example, 14.modulo(3) => 2 instead of 14 % 3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文