1

I am currently trying to develop a plugin for Jekyll that would help use Cloudinary for responsive images. Current source is in my Github repo, I will make it a gem later when/if it works.

This plugin has two features:

  • a Liquid tag to define Cloudinary images like {% cloudinary [preset] path/to/img.jpg [attr="value"] %}
  • a Converter to optionnaly automate transformation of standard Markdown/Kramdown syntax for images into this Liquid tag: ![alt text](path/to/img.jpg){:caption="caption text"} becomes {% cloudinary path/to/img.jpg alt="alt text" caption="caption text" %}

Currently, both features work as intended, but they're not "chained". If I use the Liquid tag in my Markdown, it is evaluated. If I put a standard Markdown image, it is converted to the {% cloudinary … %} Liquid tag, but this tag is not evaluated.

I suspect the two features are not run in the right order, so I want to make sure the Converter is executed before the Liquid tag is evaluated.

But I didn't yet understand how to use the priority flag.

If I uncomment the priority :normal line in my plugin, and run bundle exec jekyll serve, I get this error:

$ bundle exec jekyll serve
Configuration file: /Users/nhoizey/Dropbox/Personnel/Devs/nicolas-hoizey.com/_config.yml
jekyll 3.1.6 | Error:  undefined method `priority' for Jekyll::CloudinaryTag:Class
Did you mean?  print

Any idea?

EDIT (July 11th):

I have now split it into to plugins.

The Converter is still in my site's _plugins folder: https://github.com/nhoizey/nicolas-hoizey.com/blob/52c92a38410e133890eea6044a033cb20344b971/_plugins/cloudinaryfy.rb#L26

Jekyll doesn't complain with this "priority" flag.

The Liquid tag is now a true autonomous plugin gem named jekyll-cloudinary: https://nhoizey.github.io/jekyll-cloudinary/

If I put the "priority" flag in this plugin, I still get the error:

$ bundle exec jekyll serve                                                                                 bundler: failed to load command: jekyll (/usr/local/bin/jekyll)
Bundler::GemRequireError: There was an error while trying to load the gem 'jekyll-cloudinary'.
Gem Load Error is: undefined method `priority' for Jekyll::Cloudinary::CloudinaryTag:Class
Did you mean?  print
Backtrace for gem load error is:
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll/cloudinary.rb:5:in `<class:CloudinaryTag>'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll/cloudinary.rb:4:in `<module:Cloudinary>'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll/cloudinary.rb:2:in `<module:Jekyll>'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll/cloudinary.rb:1:in `<top (required)>'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll-cloudinary.rb:1:in `require'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-cloudinary-1.2.2/lib/jekyll-cloudinary.rb:1:in `<top (required)>'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `require'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `block (2 levels) in require'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `each'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `block in require'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `each'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `require'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:102:in `require'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-3.1.6/lib/jekyll/plugin_manager.rb:34:in `require_from_bundler'
/usr/local/lib/ruby/gems/2.3.0/gems/jekyll-3.1.6/bin/jekyll:9:in `<top (required)>'
/usr/local/bin/jekyll:22:in `load'
/usr/local/bin/jekyll:22:in `<top (required)>'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli/exec.rb:63:in `load'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli/exec.rb:63:in `kernel_load'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli/exec.rb:24:in `run'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli.rb:304:in `exec'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli.rb:11:in `start'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/exe/bundle:27:in `block in <top (required)>'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/friendly_errors.rb:98:in `with_friendly_errors'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/exe/bundle:19:in `<top (required)>'
/usr/local/bin/bundle:22:in `load'
/usr/local/bin/bundle:22:in `<main>'
Bundler Error Backtrace:

  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:89:in `rescue in block (2 levels) in require'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:85:in `block (2 levels) in require'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `each'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `block in require'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `each'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `require'
  /usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:102:in `require'
  /usr/local/lib/ruby/gems/2.3.0/gems/jekyll-3.1.6/lib/jekyll/plugin_manager.rb:34:in `require_from_bundler'
  /usr/local/lib/ruby/gems/2.3.0/gems/jekyll-3.1.6/bin/jekyll:9:in `<top (required)>'
  /usr/local/bin/jekyll:22:in `load'
  /usr/local/bin/jekyll:22:in `<top (required)>'

Why is it working for one plugin but not the other?

How can I make sure the cloudinarify Converter plugin runs before the jekyll-cloudinary Liquid tag is interpreted?

Nicolas Hoizey
  • 1,629
  • 1
  • 15
  • 24

1 Answers1

3

The priority flag was introduced for subclasses of Jekyll::Plugin in order to give plugin authors the ability to explicitly give ordering information to Jekyll. Plugin subsclasses are instantiated and sorted by priority when a new Jekyll::Site is instantiated. If you want your cloudfoundry plugin to be run before or after another plugin, you modify its priority so it will come before the other plugin in terms of processing.

This is only valid for subclasses of Jekyll::Plugin, which includes Jekyll::Converter and Jekyll::Generator. This is why it works for your converter, but not for your Liquid::Tag – liquid tags do not have the idea of a priority because they do not compete.

For example, take the case of a site which has a category generator plugin and a sitemap plugin. The sitemap plugin author wants to ensure that any generated pages are present in the sitemap (all content should be in the sitemap!), so it sets priority :low. The category generator plugin author may want to ensure it runs before any other generator, such as a sitemap generator, so it sets priority :high. This ensures the category generator plugin is run before the sitemap plugin such that the compiled sitemap has the category pages in it.

The default priority is :normal. In descending order of precedence, there is:

  • :highest
  • :high
  • :normal
  • :low
  • :lowest
parkr
  • 803
  • 6
  • 14
  • Thanks a lot for the detailed answer. Now that I know that my `Liquid::Tag` "do not compete", is there a way to make it work **after** my `Jekyll:Converter`? If I try to explain the sequence I need: normal Markdown image syntax -(`Jekyll::Converter`)-> Liquid tag syntax -(`Liquid::Tag`)-> HTML. I don't know if they are currently run in the other order, or even in parallel… do I have to call the Kramdown converter myself at the end of my own Converter? I found this: http://stackoverflow.com/questions/19169849/how-to-get-markdown-processed-content-in-jekyll-tag-plugin/35799486#35799486 – Nicolas Hoizey Jul 11 '16 at 20:14
  • @NicolasHoizey Liquid always runs first, so your tag should be run before the document is converted **unless** you put the tag in the layout. The process is in `Jekyll::Rendered#run`: [liquid on the doc](https://github.com/jekyll/jekyll/blob/4b5126dda7f1e00d2701404b4f1ec2d155f40857/lib/jekyll/renderer.rb#L62), [convert doc](https://github.com/jekyll/jekyll/blob/4b5126dda7f1e00d2701404b4f1ec2d155f40857/lib/jekyll/renderer.rb#L66), then [run doc through its layouts with liquid only](https://github.com/jekyll/jekyll/blob/4b5126dda7f1e00d2701404b4f1ec2d155f40857/lib/jekyll/renderer.rb#L71). – parkr Jul 11 '16 at 20:41
  • ok, so I'll try to call my Liquid tag interpreter directly in my Converter, thanks again for the answers. I think these could enhance the Jekyll documentation. – Nicolas Hoizey Jul 11 '16 at 21:10
  • Oh well, I just discovered this old issue… :-/ https://github.com/jekyll/jekyll/issues/889 – Nicolas Hoizey Jul 11 '16 at 22:12
  • 1
    Not quite true that plugins don't compete. If you're writing a plugin designed to *extend* another plugin, you need to ensure it loads after it! – Convincible Oct 04 '19 at 15:01