我在 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”而不是上面的分配语句中的“something”传入。
有谁知道如何将变量传递到标签调用中?
我最近使用 Jekyll 0.11.2 和 Liquid 2.3.0 非常简单地解决了这个问题,方法是将变量的 name 作为标签参数传递。
{% assign v = 'art' %}
{% link_to_article v %}
您还可以在循环中传递控件变量的名称,如上面的
article
。
在
Liquid::Tag.initialize
中,@markup
是第二个参数,即标签名称后面的字符串。分配的变量在 context
的顶层可用。
def render(context)
"/#{context[@markup.strip]}/"
end
这显然只允许传递一个参数。更复杂的解决方案将解析像
x: 2, y: 3
这样的参数。
这解决了我的问题
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 上面的答案更丰富的例子
这看起来不可能,我的解决方案是将变量名称传递给标签,然后从标签渲染的上下文中获取它。就像这样:
{% 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
如果有一个可以用文字和变量调用的标签就好了
{% assign v = 'art' %}
{% link_to_article v %}
或
{% 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
这并不能严格回答问题,但它可能会帮助其他刚接触 Liquid 的人(比如我自己)并尝试这样的事情。不要实现自定义 tag,而是考虑实现 custom filter。变量在传递到过滤器之前会被解析。
红宝石代码:
module MyFilters
def link_to_article(input, text)
"<a href='https://example.org/article/#{input}'>#{text}</a>"
end
end
Liquid::Template.register_filter(MyFilters)
液体模板:
{% 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' }}
您可以像 Liquid 本身一样解析变量,例如查看
assign
中的表达式:link。
这是一个示例自定义标签,它将整个标记计算为表达式:
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)
您可能想要使用正则表达式从复杂的标记中提取表达式。