Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling one jekyll plugin from another

I'm writing a jekyll plugin to create a custom tag. It takes an argument and spits out a string of HTML. I've got it mostly working - I can pass it arguments and get back HTML based on those arguments. Great.

Here's what has me stumped: I want to include the render of another plugin as part of my own.

My aspirational plugin is jekyll_icon_list, the plugin I want to use is jekyll-inline-svg. Here's the (abbreviated) code:

require 'jekyll_icon_list/version'
require 'jekyll'
require 'jekyll-inline-svg'

module JekyllIconList
  class IconList < Liquid::Tag
    def initialize(tag_name, raw_args, tokens)
      @raw_args = raw_args
      @tokens = tokens
      super
    end

    def parse_arguments(raw_args, settings)
        # (Unrelated stuff)
    end

    def generate_image(icon, settings, context)
      # (Unrelated stuff)

      # Problem Here: 
      Liquid::Tag.parse(
        'svg',
         icon,
        @tokens, 
        Liquid::ParseContext.new
      ).render(context)
    end

    def render(context)
      # Builds my HTML, using generate_image in the process        
    end
  end

end

Liquid::Template.register_tag('iconlist', JekyllIconList::IconList)

This doesn't throw any errors, but it also doesn't return anything at all.

Other things I've tried:

Jekyll::Tags::JekylInlineSvg.new( returns a private method error. Jekyll doesn't want me making my own tags directly.

'{% svg #{icon} %}' Returns exactly that literally with the icon substituted in; jekyll clearly doesn't parse the same file twice.

I'm trying to figure it out from Jekyll's source, but I'm not so practiced at reading source code and keep hitting dead ends. Can anyone point me in the right direction? Much appreciated.

like image 355
Robert Buchberger Avatar asked Sep 02 '25 15:09

Robert Buchberger


1 Answers

Answering my own question:

def build_svg(icon_filename)
  tag = "{% svg #{icon_filename} %}"
  liquid_parse(tag)
end

def liquid_parse(input)
  Liquid::Template.parse(input).render(@context)
end

Basically create a tiny template consisting of the tag you want to call, and hand it off to Liquid for parsing.

Below is the dirty way, which I used before I found the proper way:

Jekyll::Tags::JekyllInlineSvg.send(:new, 'svg', icon_filename, @tokens).render(context)
like image 186
Robert Buchberger Avatar answered Sep 05 '25 15:09

Robert Buchberger