Published 2020-12-30. Last modified 2020-01-02.
Time to read: about 2 minutes.
Here are templates for you to start writing your next Jekyll plugin in Ruby. Templates are provided for custom Jekyll filters, generators, tags and block tags. These templates all:
- Set up their own custom logger as described in my previous blog post.
- Provide the Jekyll
site
,page
andmode
variables in all the places you need them but don't have them available in scope. Note that generators are only invoked once for the entire site, when all the pages have been scanned and the site structure is available for processing, but unlike the other templates generators do not have access to thepage
variable because they are invoked on a per-site basis, not a per-page basis. It is common for generators to include code that loops through various collections of pages. - Come with documentation boilerplate for processing with yard.
You can view the rendered documentation.
Code Download Options
You have options for how you might download these F/OSS Jekyll plugin templates. Pick an option and save to your _plugins/
directory of your Jekyll-powered site. Your download options are:
- Download a zip file containing all the F/OSS Jekyll plugins I publish.
- Copy the following code to your clipboard by clicking on the clipboard icon at the top right of the code container, then save the code to
_plugins/
directory of your Jekyll-powered site.
jekyll_filter_template.rb
This Jekyll filter template converts strings passed to it to upper case. Yard docs are here.
# frozen_string_literal: true # @author Copyright 2020 {https://www.mslinn.com Michael Slinn} # @license SPDX-License-Identifier: Apache-2.0 # Template for Jekyll filters. module JekyllFilterTemplate require_relative 'logger_factory' # include the source of logger_factory.rb into this program @log = LoggerFactory.new.create_logger('my_filter_template', Jekyll.configuration({}), :warn, $stderr) # Accessor allows classes in this module to use the logger def self.log @log end # Describe the filter here. # @param input_strings [Array<String>] State what this parameter is for. # @return [String] # @example Describe an example of how to use it. # {{ 1234 | my_filter_template }} def my_filter_template(input_strings) JekyllFilterTemplate.log.info "input_strings = #{input_strings}, upcased = #{input_strings.upcase}".cyan input_strings.upcase end end Liquid::Template.register_filter(JekyllFilterTemplate)
Output
Given this markup in an HTML file:
{{ "Hello, world!" | my_filter_template }}
This is what is rendered to the web page after being passed through the filter:
HELLO, WORLD!jekyll_generator_template.rb
# frozen_string_literal: true # @author Copyright 2020 {https://www.mslinn.com Michael Slinn} # @license SPDX-License-Identifier: Apache-2.0 # Describe this Jekyll generator here. class JekyllGeneratorTemplate < Jekyll::Generator require_relative 'logger_factory' def initialize(config) super(config) @log = LoggerFactory.new.create_logger('my_generator_template', config, :warn, $stderr) end # Method prescribed by the Jekyll plugin lifecycle. # @param site [Jekyll.Site] Automatically provided by Jekyll plugin mechanism # @return [void] def generate(site) @config = site.config @mode = @config['env']['JEKYLL_ENV'] @log.info "mode=#{@mode}".green end end
Output
Generators do not display anything on the generated web site. They can create files containing pages in a directory. Generators usually log information to the console whenever a problem occurs, or progress needs to be shown.
jekyll_tag_template.rb
# frozen_string_literal: true # @author Copyright 2020 {https://www.mslinn.com Michael Slinn} # @license SPDX-License-Identifier: Apache-2.0 # # Module-level description goes here. # # @example Heading for this example # Describe what this example does # {% my_tag_template "parameter" %} # # @example Heading for this example # Describe what this example does # {% my_tag_template "parameter" %} module MyTagTemplate # Start of custom logger definition require_relative 'logger_factory' # include the source of logger_factory.rb into this program @log = LoggerFactory.new.create_logger('my_tag_template', Jekyll.configuration({}), :warn, $stderr) # This accessor allows classes in this module to use the logger. def self.log @log end # End of custom logger definition # This class implements the Jekyll tag functionality class MyTag < Liquid::Tag # Constructor. # @param tag_name [String] is the name of the tag, which we already know. # @param arguments [Hash, String, Liquid::Tag::Parser] the arguments from the tag. # @param tokens [Liquid::ParseContext] tokenized command line # @return [void] def initialize(tag_name, arguments, tokens) super(tag_name, arguments, tokens) MyTagTemplate.log.info "tag_name [#{tag_name.class}] = '#{tag_name}' [#{tag_name.class}]".green MyTagTemplate.log.info "arguments [#{arguments.class}] = '#{arguments}'".green # @site = context.registers[:site] # This variable is handy but not required # @config = @site.config # This variable is handy but not required # @mode = @config['env']['JEKYLL_ENV'] # This variable is handy but not required # MyTagTemplate.log.info "mode=#{@mode}".green @arguments = arguments @arguments = '' if @arguments.nil? || @arguments.empty? end # Method prescribed by the Jekyll plugin lifecycle. # @return [String] def render(context) @site = context.registers[:site] @config = @site.config @mode = @config['env']['JEKYLL_ENV'] MyTagTemplate.log.info "mode='#{@mode}'".green @page = context.registers[:page] MyTagTemplate.log.info "page.path='#{@page.path}'".green MyTagTemplate.log.info "page.url='#{@page.url}'".green <<~HEREDOC <p style="color: green; background-color: yellow; padding: 1em; border: solid thin grey;"> #{@arguments} </p> HEREDOC end end private # Describe the function's purpose # This is a link {https://domain.com with some text}. # @param parameter [String] Describe this parameter's purpose # @return [String, nil] Describe the return value def my_private_function(parameter) log.info "my_private_function.parameter=#{parameter}" end # parse, or return the args # @note you can pass in parsed args # @return [Liquid::Tag::Parser] def parse_args(args) return args if args.is_a?(Liquid::Tag::Parser) || args.is_a?(Hash) Liquid::Tag::Parser.new( @args ) end end Liquid::Template.register_tag(MyTagTemplate.log.progname, MyTagTemplate::MyTag)
Output
Given this markup in an HTML file:
{% my_tag_template This is a little song I wrote, I hope you sing it note for note... %}
This is how it looks after the block tag is rendered to the page:
This is a little song I wrote, I hope you sing it note for note...
jekyll_block_template.rb
# frozen_string_literal: true # @author Copyright 2020 {https://www.mslinn.com Michael Slinn} # @license SPDX-License-Identifier: Apache-2.0 # # Module-level description goes here. # # @example Heading for this example # Describe what this example does # {% my_block_template "parameter" %} # Hello, world! # {% endmy_block_template %} # # @example Heading for this example # Describe what this example does # {% my_block_template "parameter" %} # Hello, world! # {% endmy_block_template %} module MyBlockTagTemplate # Start of custom logger definition require_relative 'logger_factory' # include the source of logger_factory.rb into this program @log = LoggerFactory.new.create_logger('my_block_template', Jekyll.configuration({}), :warn, $stderr) # This accessor allows classes in this module to use the logger. def self.log @log end # End of custom logger definition # This class implements the Jekyll tag functionality class MyBlock < Liquid::Block # Constructor. # @param tag_name [String] the name of the tag, which we already know. # @param text [Hash, String, Liquid::Tag::Parser] the arguments from the tag. # @param tokens [Liquid::ParseContext] parsed and tokenized command line # @return [void] def initialize(tag_name, arguments, tokens) super(tag_name, arguments, tokens) MyTagTemplate.log.info "tag_name [#{tag_name.class}] = '#{tag_name}' [#{tag_name.class}]".green MyTagTemplate.log.info "arguments [#{arguments.class}] = '#{arguments}'".green @arguments = arguments @arguments = '' if @arguments.nil? || @arguments.empty? end # Method prescribed by the Jekyll plugin lifecycle. # @return [String] def render(context) content = super # This magically underdocumented assignment somehow returns the text within the block. @site = context.registers[:site] @config = @site.config @mode = @config['env']['JEKYLL_ENV'] MyBlockTagTemplate.log.info "mode='#{@mode}'".green @page = context.registers[:page] MyBlockTagTemplate.log.info "page.path='#{@page.path}'".green MyBlockTagTemplate.log.info "page.url='#{@page.url}'".green <<~HEREDOC <p style="color: green; background-color: yellow; padding: 1em; border: solid thin grey;"> #{content} </p> HEREDOC end end end Liquid::Template.register_tag(MyBlockTagTemplate.log.progname, MyBlockTagTemplate::MyBlock)
Output
Given this markup in an HTML file:
{% my_block_template %}Hello, world!{% endmy_block_template %}
This is how it looks after the block tag is rendered to the page:
Hello, world!