artu-hnrq
artu-hnrq

Reputation: 1487

How to write valid HTML out of a liquid tag?

Contextualizing

I've been learning how to working with Jekyll and by now I'm trying to develop my first liquid tag. It purpose will be render my flair of a given StackExchange community.

This way, when I inject {% flair stackoverflow %} in a page, it should be replaced by the equivalent HTML. Here follows the code:

module Jekyll
    class FlairTag < Liquid::Tag

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

        def render(context)
            output = \
            "<a href=\"{{ #{@community}.url }}/users/{{ #{@community}.id }}/{{ site.data.stackexchange.user.nickname }}\">" \
                "<img src=\"https://stackexchange.com/users/flair/{{ site.data.stackexchange.user.id }}\" " \
                    "width=\"208\" height=\"58\" " \
                    "title=\"Profile for {{ site.data.stackexchange.user.nickname }} on {{ include.label }}\">" \
                    "alt=\"Profile for {{ site.data.stackexchange.user.nickname }} on {{ include.label }}\"" \
            "</a>"

            return output
        end
    end
end

Liquid::Template.register_tag('flair', Jekyll::FlairTag)

The Question

I've read here that returning a string containing the desired HTML code I would achieve my goal, however it hasn't occurred properly, I mean, it has not been the same as if I wrote the HTML directly in the page.

Is there something I'm missing out? Or would have another way to write out HTML code as the return of the ruby function / liquid tag?

Upvotes: 1

Views: 503

Answers (1)

David Jacquel
David Jacquel

Reputation: 52809

Your liquid expressions like {{ site.data.stackexchange.user.id }} will not be interpreted here. You need to use variables to output your datas.

As I'm guessing that you store your datas in a _data/stackoverflow.yml file that may look like :

url: https://stackoverflow.com
id: 2989289
user: artu-hnrq

This code will do the job :

module Jekyll
    class FlairTag < Liquid::Tag

        def initialize(tag_name, community, tokens)
            super
            # if this tag is called with {% flair stackoverflow %}
            # the "community" variable will be "stackoverflow "
            # in order to remove the trailing space, we strip the variable
            @community = community.strip
        end

        def render(context)
            site = context.registers[:site]
            data = site.data[@community]
            url  = data["url"]
            id   = data["id"]
            user = data["user"]
            alt  = "Profile for #{user} on #{@community}"

            output = %(
              <a href="#{url}/users/#{id}/#{user}">
                <img src="#{url}/users/flair/#{id}.png"
                     width="208" height="58"
                     title="#{alt}"
                     alt="#{alt}"
              </a>
            )
        end
    end
end

Liquid::Template.register_tag('flair', Jekyll::FlairTag)

Note : from my point of view if this snippet is located in a unique place on your site (cv, footer, ...) this can be achieved with a simple include.

There is nearly no performance gain if this tag doesn't need to be customized for each pages, and your code stays maintainable by someone with only html/liquid knowledge.

Upvotes: 1

Related Questions