Search code examples
rubyjekyllliquid

Using Liquid custom tags to output multiple `span` elements`


I'm playing with Jekyll plugins and their ability to create custom tags and I've run into an issue extending my tag to accept a comma separated list.

I started with the following:

{% symbol R %}

And the matching plugin code:

module Jekyll
  class Symbol < Liquid::Tag
    def initialize(tag_name, text, tokens)
      super
      @text = text
    end 

    def render(context)
      "<span class='symbol-#{@text}'>#{@text}</span>"
    end
  end
end

Liquid::Template.register_tag('symbol', Jekyll::Symbol)

And the output on my page, as expected, is:

<span class="symbol-R">R</span>

What I'm trying to do now is amend this plugin so I can pass in a comma separated list, for example:

{% symbol R,G %}

I updated my plugin code to this:

module Jekyll
  class Symbol < Liquid::Tag
    def initialize(tag_name, text, tokens)
      super
      @text = text
    end 

    def render(context)
      symbol = @text.split(',').map(&:strip)

      symbol.each do |item|
        puts item # to test in terminal
        "<span class='symbol-#{@text}'>#{@text}</span>"
      end
    end
  end
end

Liquid::Template.register_tag('symbol', Jekyll::Symbol)

Terminal outputs correctly:

R
G

And my expectation was that I'd get the following on my page:

<span class="symbol-R">R</span><span class="symbol-G">G</span>

But all that shows up on the page is:

RG

Could I get some help in figuring this out? I feel like I'm super close... it's just the actual page rendering I'm clearly messing up on.


Solution

  • In Ruby your function will return the last expression that it executed. For you, this is the symbol.each do … end.

    each returns various things, but what it does not do by itself is return the contents of its block. For that, you want map:

    symbol.map do |item|
      puts item # to test in terminal
      "<span class='symbol-#{@text}'>#{@text}</span>"
    end