20

I'd like to make changes to the Jekyll Only First Paragraph plugin to make the generation of a 'read more ' link a configurable option.

To do this I'd need to be able to access the Jekyll site config inside the plugin's AssetFilter. With the configuration available I can make the change. I don't know how to make the site configuration available to the plugin.

The code below demonstrates where I'd like site.config available:

require 'nokogiri'

module Jekyll
  module AssetFilter
    def only_first_p(post)
      # site.config needs to be available here to modify the output based on the configuration

      output = "<p>"
      output << Nokogiri::HTML(post["content"]).at_css("p").inner_html
      output << %{</p><a class="readmore" href="#{post["url"]}">Read more</a>}

      output
    end
  end
end

Liquid::Template.register_filter(Jekyll::AssetFilter)


Can this be achieved?

Jon Cram
  • 16,609
  • 24
  • 76
  • 107
  • May I suggest changing the title of this question to "Get Jekyll Configuration Inside Plugin" or something that has the word "Plugin" in it. The more generic term should help other folks find it easier. – Alan W. Smith Jul 12 '12 at 09:36
  • Title changed, good suggestion – Jon Cram Jul 16 '12 at 12:30

3 Answers3

24

Overview

You can access Jekyll config options in plugins with:

Jekyll.configuration({})['KEY_NAME']

If the config key contains nested levels, the format is:

Jekyll.configuration({})['KEY_LEVEL_1']['KEY_LEVEL_2']

Example

If a _config.yml contains:

testvar: new value

custom_root:
    second_level: sub level data

A basic example that simply outputs those values would look like:

require 'nokogiri'

module Jekyll
  module AssetFilter
    def only_first_p(post)

      @c_value = Jekyll.configuration({})['testvar']
      @c_value_nested = Jekyll.configuration({})['custom_root']['second_level']

      output = "<p>"

      ### Confirm you got the config values
      output << "<br />"
      output << "c_value: " + @c_value + "<br />"
      output << "c_value_nested: " + @c_value_nested + "<br />"
      output << "<br />"
      ###

      output << Nokogiri::HTML(post["content"]).at_css("p").inner_html
      output << %{</p><a class="readmore" href="#{post["url"]}">Read more</a>}

      output
    end
  end
end

Liquid::Template.register_filter(Jekyll::AssetFilter)

Of course, you would want to put checks in that verify that the config key/values are defined before trying to use them. That's left as an exercise for the reader.


Another Possible Option

The "Liquid filters" section of the Jekyll Plugins Wiki Page contains the following:

In Jekyll you can access the site object through registers. As an example, you can access the global configuration (_config.yml) like this: @context.registers[:site].config['cdn'].

I haven't spent the time to get that to work, but it might be worth checking out as well.

Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
  • 1
    You're welcome. Also, your timing was excellent. I'm building my first plugin and ran into the same need to access config options. I spent hours last week figuring it out. Sharing the solution makes the time spent even more worth it. – Alan W. Smith Jul 14 '12 at 10:17
  • 4
    A problem with the `Jekyll.configuration({})` solution might be that the entire "loading configuration from YAML file" process is carried out for every invocation. This generated lots of log output for me with Jekyll 1.0-rc1, so I went with the "context" solution. – fresskoma Apr 17 '13 at 12:30
  • 5
    The `context.registers[:site].config['cdn']` worked great for me! – mhulse Jan 01 '14 at 23:42
  • I was going to edit that answer to change the "might be worth" to "is definitely worth" :) Meanwhile, note that `@context.registers[:site]` returns the object corresponding to the entire site, so you can also access things like the number of posts on the site - `@context.registers[:site].posts.count`. Enjoy! – sameers Sep 02 '14 at 21:36
  • Link updated for "Liquid filters" section : https://github.com/jekyll/jekyll/blob/master/docs/_docs/plugins.md#protip-access-the-site-object-using-liquid Or : https://jekyllrb.com/docs/plugins/ – CrazyMax Jan 15 '17 at 09:04
  • 1
    How can I use `context.registers[:site].config['cdn']` with nested configurations? – KargWare Jan 09 '20 at 08:36
  • @KargWare - That's probably worth of creating it's own question so that other folks can find it easily. – Alan W. Smith Jan 10 '20 at 19:51
  • Hey Alan. I can create a own question. But do you know if it is possible? – KargWare Jan 10 '20 at 22:14
  • @KargWare - Afraid I'm not sure one way or the other. – Alan W. Smith Jan 14 '20 at 15:13
17

Jekyll.configuration({})['KEY_NAME'] will break the --config command line option because it will always load the configurations from the _config.yml file. Another bad side effect is that it will read the _config.yml file again.

context.registers[:site].config['KEY_NAME'] is the correct answer because it will get the key from the configurations already loaded by Jekyll.

basex
  • 490
  • 4
  • 11
3

If you are working with Generators (which are also plugins), it is possible to get the configuration like this:

class MyPlugin < Jekyll::Generator
  def generate(site)
    puts site.config["max_posts"] # max_posts as defined in _config.yml

You'll get the site as an argument, and the .config is accessible as an hash.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Christian
  • 7,062
  • 5
  • 36
  • 39