在 Liquid 标签调用中使用 Liquid 变量

发布于 2024-12-12 01:19:16 字数 315 浏览 0 评论 0原文

我在 Liquid 中创建了一个自定义链接标签,并且我试图能够将 Liquid 变量传递到对该标签的调用中,如下所示

{{ assign id = 'something' }} // this value is actual dynamic while looping through data 
{% link_to article: id, text: 'Click Me!' %} // my custom tag

但是,这会导致文章参数按照分配作为“id”而不是“某物”传递上面的声明。

有谁知道如何将变量传递到标签调用中?

I made a custom link tag in Liquid and I am trying to be able to pass liquid variables into the call for that tag like so

{{ assign id = 'something' }} // this value is actual dynamic while looping through data 
{% link_to article: id, text: 'Click Me!' %} // my custom tag

However this results in the article parameter being passed in as 'id' instead of 'something' as per the assign statement above it.

Does anyone know how to pass variables into tag calls?

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

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

发布评论

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

评论(6

凡间太子 2024-12-19 01:19:16

我最近使用 Jekyll 0.11.2 和 Liquid 2.3.0 通过将变量的名称作为标签参数传递来非常简单地解决了这个问题。

{% assign v = 'art' %}
{% link_to_article v %}

您还可以在循环中传递控件变量的名称,如上面的 article

Liquid::Tag.initialize 中,@markup 是第二个参数,即标签名称后面的字符串。分配的变量在上下文的顶层可用。

def render(context)
  "/#{context[@markup.strip]}/"
end

这显然只允许传递一个参数。更复杂的解决方案将解析诸如 x: 2, y: 3 之类的参数。

I've recently solved this very simply with Jekyll 0.11.2 and Liquid 2.3.0 by passing the name of the variable as the tag parameter.

{% assign v = 'art' %}
{% link_to_article v %}

You can also pass the name of the control var while in a loop, like article above.

In Liquid::Tag.initialize, @markup is the second parameter, the string following the tag name. The assigned variables are available in the top level of the context.

def render(context)
  "/#{context[@markup.strip]}/"
end

This obviously only allows one param to be passed. A more complex solution would parse params like x: 2, y: 3.

醉城メ夜风 2024-12-19 01:19:16

这解决了我的问题 context[@markup.strip]

我的问题是我希望能够将变量传递给我的自定义 Liquid 标签,如下所示: {% get_menu main_menu navigation.html settings.theme.id %}

为了做到这一点,我首先拆分将变量字符串转换为每个空格字符上的不同变量。

class GetMenu < Liquid::Tag
    include ApplicationHelper
    def initialize(tag_name, variables, tokens)

        @variables = variables.split(" ")

        @menu_object = @variables[0]
        @file_name = @variables[1]
        @theme_id = @variables[2]

        super
    end

    def render(context)

        # This is where i use context[@theme_id.strip] to get the variable of "settings.theme.id"
        content = CodeFile.find_by(hierarchy: 'snippet', name: @file_name.to_s, theme_id: context[@theme_id.strip])

        @menu ||= Menu.find_by_slug(@menu_object)

        context.merge('menu' => @menu)

        Liquid::Template.parse(content.code).render(context)

    end

end

Liquid::Template.register_tag('get_menu', GetMenu)

*这只是一个比 Jonathan Julian 上面的答案更丰富的例子

This solved the case for me context[@markup.strip].

My problem was that i wanted to be able to pass a variable to my custom Liquid tag like this: {% get_menu main_menu navigation.html settings.theme.id %}

In order to do this i first split the variable string into different varaibles on every space character.

class GetMenu < Liquid::Tag
    include ApplicationHelper
    def initialize(tag_name, variables, tokens)

        @variables = variables.split(" ")

        @menu_object = @variables[0]
        @file_name = @variables[1]
        @theme_id = @variables[2]

        super
    end

    def render(context)

        # This is where i use context[@theme_id.strip] to get the variable of "settings.theme.id"
        content = CodeFile.find_by(hierarchy: 'snippet', name: @file_name.to_s, theme_id: context[@theme_id.strip])

        @menu ||= Menu.find_by_slug(@menu_object)

        context.merge('menu' => @menu)

        Liquid::Template.parse(content.code).render(context)

    end

end

Liquid::Template.register_tag('get_menu', GetMenu)

*This is just a more rich example that the answer above by Jonathan Julian

背叛残局 2024-12-19 01:19:16

看起来这不可能,我的解决方案是将变量名称传递给标签,然后从渲染标签的上下文中获取它。就像这样:

{% for article in category.articles %}
  {% link_to variable: article, text: title %}
{% endfor %}

在我的标签代码(压缩)中:

def render(context)
  uri = "article/#{context[@options[:variable]]['id']}"
  "<a href='#{uri}'>#{build_link_text context}</a>"
end

Doesn't look like this is possible, my solution was to just pass the variable name in to the tag and grab it out of the context the tag is being rendered in. Like so:

{% for article in category.articles %}
  {% link_to variable: article, text: title %}
{% endfor %}

in my tag code (condensed):

def render(context)
  uri = "article/#{context[@options[:variable]]['id']}"
  "<a href='#{uri}'>#{build_link_text context}</a>"
end
白况 2024-12-19 01:19:16

最好有一个可以用文字和变量(如

{% assign v = 'art' %}
{% link_to_article v %}

or

{% link_to_article 'art' %}

或 )

{% link_to_article "art" %}

调用的标签,当然也可以,

{% link_to_article include.article %}

为此,我提出了一个辅助函数

def get_value(context, expression)
  if (expression[0]=='"' and expression[-1]=='"') or (expression[0]=="'" and expression[-1]=="'")
    # it is a literal
    return expression[1..-2]
  else
    # it is a variable
    lookup_path = expression.split('.')
    result = context
    puts lookup_path
    lookup_path.each do |variable|
      result = result[variable] if result
    end
    return result
  end
end

在渲染中,只需调用辅助函数即可获取文字或变量的值。

def render(context)
  v = get_value(context, @markup.strip)
end

仅供参考,初始化程序如下所示:

def initialize(tag_name, markup, tokens)
  @markup = markup
  super
end

It would be great to have a tag that can be called with literals and variables like

{% assign v = 'art' %}
{% link_to_article v %}

or

{% link_to_article 'art' %}

or

{% link_to_article "art" %}

and also of course

{% link_to_article include.article %}

In order to so I propose a helper function

def get_value(context, expression)
  if (expression[0]=='"' and expression[-1]=='"') or (expression[0]=="'" and expression[-1]=="'")
    # it is a literal
    return expression[1..-2]
  else
    # it is a variable
    lookup_path = expression.split('.')
    result = context
    puts lookup_path
    lookup_path.each do |variable|
      result = result[variable] if result
    end
    return result
  end
end

And in the render just call the helper function to get the value of the literal or variable.

def render(context)
  v = get_value(context, @markup.strip)
end

FYI, the initialiser would look like this:

def initialize(tag_name, markup, tokens)
  @markup = markup
  super
end
夜无邪 2024-12-19 01:19:16

这并没有严格回答这个问题,但它可能会帮助其他刚接触 Liquid 的人(比如我自己)并尝试这样的事情。不要实现自定义标签,而是考虑实现自定义过滤器代替。变量在传递到过滤器之前会被解析。

Ruby 代码:

module MyFilters
  def link_to_article(input, text)
    "<a href='https://example.org/article/#{input}'>#{text}</a>"
  end
end

Liquid::Template.register_filter(MyFilters)

Liquid 模板:

{% assign id = 'something' %} 
{{ id | link_to_article: 'Click Me!' }}

输出:

<a href='https://example.org/article/something'>Click Me!</a>

您还可以使用变量作为参数。因此,以下内容将具有相同的输出:

{% assign id = 'something' %} 
{% assign text = 'Click Me!' %}
{{ id | link_to_article: text }}

并且过滤器可以有零个或多个(逗号分隔)参数:

{{ 'input' | filter_with_zero_parameters }}
{{ 'input' | filter_with_two_parameters: 'parameter 1', 'parameter 2' }}

This does not strictly answer the question, but it may help others who are new to Liquid (like myself) and try something like this. Instead of implementing a custom tag, consider implementing a custom filter instead. Variables are resolved before they are passed into filters.

Ruby code:

module MyFilters
  def link_to_article(input, text)
    "<a href='https://example.org/article/#{input}'>#{text}</a>"
  end
end

Liquid::Template.register_filter(MyFilters)

Liquid template:

{% assign id = 'something' %} 
{{ id | link_to_article: 'Click Me!' }}

Output:

<a href='https://example.org/article/something'>Click Me!</a>

You can also use variables as parameters. So the following would have the same output:

{% assign id = 'something' %} 
{% assign text = 'Click Me!' %}
{{ id | link_to_article: text }}

And filters can have zero or more (comma-separated) parameters:

{{ 'input' | filter_with_zero_parameters }}
{{ 'input' | filter_with_two_parameters: 'parameter 1', 'parameter 2' }}
自由范儿 2024-12-19 01:19:16

您可以像 Liquid 本身一样解析变量,例如查看 assign 中的表达式:链接

这是一个示例自定义标记,它将整个标记计算为表达式:

require 'liquid/variable'

module Jekyll
  class MyTag < Liquid::Tag
    def initialize(tag_name, markup, parse_context)
      super
      # Parse the variable
      @var = Liquid::Variable.new(markup.strip, parse_context)
    end

    def render(context)
      # Evaluate it within the usage context
      var = @var.render(context)
      "Variable: #{var}"
    end
  end
end

Liquid::Template.register_tag('mytag', Jekyll::MyTag)

您可能需要使用正则表达式从复杂标记中提取表达式。

这是一个执行此操作的简单函数。请注意,由于它使用正则表达式,因此它无法处理需要上下文无关语法的更复杂的表达式,例如包含多个嵌套括号的表达式。

def parse_markup(markup, parse_context)
  params = {}
  regex = /(\w+):\s*(\([^)]+\)|"[^"]+"|[^,]+)/

  markup.scan(regex) do |param_name, expression|
    params[param_name] = Liquid::Variable.new(expression.strip, parse_context)
  end

  params
end

这是一个使用它的简单标签:

require 'liquid/variable'

module Jekyll
  class MyTag < Liquid::Tag
    def initialize(tag_name, markup, parse_context)
      super
      # Parse all parameters
      @params = parse_markup(markup, parse_context)
    end

    def render(context)
      # Evaluate foo and bar
      foo = @params["foo"].render(context)
      bar = @params["bar"].render(context)
      
      "foo: #{foo}, bar: #{bar}"
    end
  end
end

Liquid::Template.register_tag('mytag', Jekyll::MyTag)

You can just parse the variable like Liquid itself does, see for instance how the expression in assign: link.

This is a sample custom tag that evaluates the entire markup as an expression:

require 'liquid/variable'

module Jekyll
  class MyTag < Liquid::Tag
    def initialize(tag_name, markup, parse_context)
      super
      # Parse the variable
      @var = Liquid::Variable.new(markup.strip, parse_context)
    end

    def render(context)
      # Evaluate it within the usage context
      var = @var.render(context)
      "Variable: #{var}"
    end
  end
end

Liquid::Template.register_tag('mytag', Jekyll::MyTag)

You may want to use regular expressions to carve out expressions from your complex markup.

Here's a simple function that does that. Note that, since it uses regular expressions, it can't handle more complex expressions that need a context-free grammar, such as those containing multiple nested parentheses.

def parse_markup(markup, parse_context)
  params = {}
  regex = /(\w+):\s*(\([^)]+\)|"[^"]+"|[^,]+)/

  markup.scan(regex) do |param_name, expression|
    params[param_name] = Liquid::Variable.new(expression.strip, parse_context)
  end

  params
end

Here's a simple tag that makes use of it:

require 'liquid/variable'

module Jekyll
  class MyTag < Liquid::Tag
    def initialize(tag_name, markup, parse_context)
      super
      # Parse all parameters
      @params = parse_markup(markup, parse_context)
    end

    def render(context)
      # Evaluate foo and bar
      foo = @params["foo"].render(context)
      bar = @params["bar"].render(context)
      
      "foo: #{foo}, bar: #{bar}"
    end
  end
end

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