jekyll-friend
jekyll-friend

Reputation: 61

Liquid tag for custom linking

I am starting to use Jekyll and Liquid and I have some trouble about it.

Suppose I want to do some Liquid tag inside Jekyll that makes links: when writing

...and according to {% cite my_link %} we have that...

then Jekyll searches the post whose caption (some YAML predefined information) is my_link and creates a link for it according to some style. To create this Liquid tag I suppose one has to start with something like

module Jekyll
   class Cite < Liquid::Tag
     def render(context)
        caption = ????????
        aux = site.posts | where: "lang", page.lang | where: "caption", "#{@caption}" | first
        return <a href="{{aux.cleanurl}}" class="{{aux.kind}}" title="{{aux.title}}"></a>
    end
  end
end

Liquid::Template.register_tag('cite', Jekyll::Cite)

First of all I do not know how to assign caption=my_link, that is, to extract the second part of {% cite my_link %}. Once we get it, will this code work or is it wrong?

Thank you very much for your help

Upvotes: 1

Views: 976

Answers (1)

David Jacquel
David Jacquel

Reputation: 52829

First question "how to assign caption=my_link" ?

You can read Jekyll Tags plugins documentation, and more important, Liquid Tag code.

In this last reference, you will learn that the initialize method is, by default, making a @markup variable available for other methods. This variable contains parameters passed to your tag.

So, once in render method you already have a @markup variable containing the desired value. You can then do caption = @markup. Note that this is only true for one parameter tags. For multiple parameters, you will have to use regular expressions on @markup to sort the pieces.

Second question : Will your code work ?

The answer is NO. Plugins are ruby code not Liquid.

Here's an example that can work :

module Jekyll
  class CiteTag < Liquid::Tag
    def render(context)

      # @markup is a Liquid token so, we convert it to string
      # then we remove spaces before and after
      caption = @markup.to_s.strip
      site = context.registers[:site]
      posts = site.collections['posts'].docs
      page = context.registers[:page]

      if defined? page['lang'] and !page['lang'].nil? then
        # if current page has a lang front matter varaible set (or a default)
        currentLang = page['lang']
      elsif defined? site.config['lang']
        # if no lang is defined in current page, fallback to site.lang
        currentLang = site.config['lang']
      else
        # if no site.lang is available we raise an error
        raise "No default 'lang' option defined in _config.yml"
      end

      # create a new array with posts selected on currentLang and caption variable
      selectedPosts = posts.select do |post|
        postLang = post.data['lang']
        postCaption = post.data['caption']
        sameLang = postLang == currentLang
        sameCaption = postCaption == caption
        sameLang and sameCaption
      end

      # select first post
      post = selectedPosts.first

      # print the link
      link = "<a href=\"#{site.baseurl}#{post.url}\" class=\"#{post.data['kind']}\" title=\"#{post.data['title']}\">#{post.data['title']}</a>"

    end
  end
end

Liquid::Template.register_tag('cite', Jekyll::CiteTag)

Note : you have to set a lang variable in _config.yml. eg : lang: 'en'.

Upvotes: 2

Related Questions