using Liquid variables inside of a liquid tag call

后端 未结 4 978
鱼传尺愫
鱼传尺愫 2020-12-01 21:08

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\' }} //          


        
相关标签:
4条回答
  • 2020-12-01 21:24

    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.

    0 讨论(0)
  • 2020-12-01 21:36

    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
    
    0 讨论(0)
  • 2020-12-01 21:38

    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
    
    0 讨论(0)
  • 2020-12-01 21:43

    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

    0 讨论(0)
提交回复
热议问题