Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Converters can run before liquid is evaluated [#889] #917

Closed
wants to merge 1 commit into from

5 participants

@jyruzicka

(A response to #889)

Specified converters can now be run before liquid tags are evaluated by including the method run_before_liquid!. Tests and docs have been updated to reflect this, and the PreIdentity converter has been added as a lowest-priority catch-all for pre-liquid converters. The new workflow is:

  1. Run pre-liquid converters
  2. Evaluate liquid tags
  3. Run post-liquid (default) converters

Note that this means that posts may go through two different converters - one pre-liquid and one post-liquid.


Converters are added to the post-liquid queue by default. This means that if you don't add any pre-liquid converters, behaviour should default to standard.


Unit tests run fine on my machine, and manual tests seem to show that everything is working well. Feedback appreciated.

@mattr-
Owner

I'm afraid I don't understand the reason for the pre-liquid identity converter. Could you fill me in on that?

@jyruzicka

@mattr Convertible#transform assumes that Convertible#convert will return a Converter. The role of Converters::Identity is (as I see it) to be the "backup" converter, to be returned if no other converters match the file.

In this branch, every Converter subclass is designated to run either before liquid tags are evaluated, or after. By default they'll run afterwards (as was the behaviour previously). Convertible#converter now takes an argument (:before or :after, defaults to :after) and will only retrieve converters that are designed to run either before or after liquid tags are evaluated (depending on said argument). Since Convertible#transform doesn't handle nil returns from converter well, Converters::PreIdentity is the "backup" converter for the pre-liquid conversion call.

(This also suggests that maybe transform should be able to deal with nil returns from converter?)

Does this explanation make sense? If you want I can add some comments to the PreIdentity class, further expanding on its role.

@mattr-
Owner
lib/jekyll/converter.rb
@@ -44,5 +44,29 @@ def pygments_prefix
def pygments_suffix
self.class.pygments_suffix
end
+
+ # Does this converter run before or after liquid tags are evaluated?
+ #
+ # Returns true if this converter will be run before liquid is processed.
+ def self.run_before_liquid?
+ @run_before_liquid || false

Sorry, this expression doesn't make much sense... Think with me, @run_before_liquid will be used only if it is setted, in other words nil == @run_before_liquid, right? But, internally, ruby considers nil as false, then you can use it in boolean expressions, making only if @run_befor_liquid... Then, making that above is like make the condition if @run_before_liquid || false, that doesn't make sense too, since the value after || will be used if, and only if, the value before || is false... Understand?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@kelvinst

This PR LGTM... :+1:
But, maybe you can add a cucumber test too, since it's some kind of new feature, I don't know if only shoulda is good enough for this...

@parkr, what do you think about?

@jyruzicka

@kelvinst Just been poking around inside cucumber this evening. I'm not sure I'm clever enough to test this with cucumber - as it stands I've only introduced an "identity" pre-liquid converter. By definition that's pretty hard to test since it should leave the page exactly as it was. Not sure if it's worth introducing a pre-liquid converter just to make cucumber work?

Have fixed converter.rb and the typo @dracula2000 spotted.

lib/jekyll/converters/pre_identity.rb
@@ -0,0 +1,22 @@
+module Jekyll
+ module Converters
+ # The default converter to run before parsing liquid tags
+ class PreIdentity < Converter
+ safe true
+ priority :lowest
+ run_before_liquid!

Why not inherit the Identity Converter and reduce this class to the line above only? Would spare some code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@maul-esel

I like this! :+1:

Just some minor notes:

  1. see my inline comment above
  2. It could probably be simplified to use only the symbols (:before or :after) or only the boolean (@run_before_liquid). Both seems like a bit of duplication to me.
  3. Your last commit introduced a file that isn't meant to be there, I think :smile:
@kelvinst
@jyruzicka

OK, I've made some changes to the Converter following @maul-esel 's comments. Currently passing unit tests but not some cucumber tests I believe. I may get time this weekend to poke around and work out exactly what's breaking.

@parkr
Owner

@jyruzicka Please also rebase on the current master, please :)

Jan-Yves Ruzicka Allow Converters to run before liquid tags are evaluated.
Converters can now be run before liquid tags are evaluated by including the method `run_before_liquid!`. Tests and docs have been updated to reflect this, and the `PreIdentity` converter has been added as a lowest-priority catch-all.
d03421c
@jyruzicka

Incredibly, I think I managed to rebase/git push -f without breaking anything.

@parkr
Owner

Nice one :)

@parkr parkr closed this
@parkr parkr reopened this
@parkr parkr closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 4, 2013
  1. @jyruzicka

    Allow Converters to run before liquid tags are evaluated.

    Jan-Yves Ruzicka authored jyruzicka committed
    Converters can now be run before liquid tags are evaluated by including the method `run_before_liquid!`. Tests and docs have been updated to reflect this, and the `PreIdentity` converter has been added as a lowest-priority catch-all.
This page is out of date. Refresh to see the latest.
View
1  jekyll.gemspec
@@ -85,6 +85,7 @@ Gem::Specification.new do |s|
lib/jekyll/converters/markdown/maruku_parser.rb
lib/jekyll/converters/markdown/rdiscount_parser.rb
lib/jekyll/converters/markdown/redcarpet_parser.rb
+ lib/jekyll/converters/pre_identity.rb
lib/jekyll/converters/textile.rb
lib/jekyll/convertible.rb
lib/jekyll/core_ext.rb
View
26 lib/jekyll/converter.rb
@@ -44,5 +44,31 @@ def pygments_prefix
def pygments_suffix
self.class.pygments_suffix
end
+
+ # Does this converter run before or after liquid tags are evaluated?
+ # Convertible expects Converters to return only true or false, so all
+ # untrue values are converted to false.
+ #
+ # Returns true if this converter will be run before liquid is processed.
+ def self.run_before_liquid?
+ @run_before_liquid || false
+ end
+
+ # Does this converter run before or after liquid tags are evalutated?
+ # Instance version of Converter.run_before_liquid?
+ #
+ # Returns true if this converter will be run before liquid is processed.
+ def run_before_liquid?
+ self.class.run_before_liquid?
+ end
+
+ # If called, this converter will be run before liquid tags are evaluated.
+ # This may be handy if your converter produces code that in turn needs to be run
+ # through liquid.
+ #
+ # Returns nothing
+ def self.run_before_liquid!
+ @run_before_liquid = true
+ end
end
end
View
26 lib/jekyll/converters/pre_identity.rb
@@ -0,0 +1,26 @@
+module Jekyll
+ module Converters
+ # The default converter to run before parsing liquid tags
+ # Converters need to be direct descendents of the Converter
+ # class, so we can't subclass Jekyll::Converters::Identity
+ class PreIdentity < Converter
+ run_before_liquid!
+
+ safe true
+
+ priority :lowest
+
+ def matches(ext)
+ true
+ end
+
+ def output_ext(ext)
+ ext
+ end
+
+ def convert(content)
+ content
+ end
+ end
+ end
+end
View
24 lib/jekyll/convertible.rb
@@ -44,10 +44,13 @@ def read_yaml(base, name)
end
# Transform the contents based on the content type.
+ #
+ # before_liquid - is this being run before liquid
+ # tags are parsed?
#
# Returns nothing.
- def transform
- self.content = converter.convert(self.content)
+ def transform(before_liquid=false)
+ self.content = converter(before_liquid).convert(self.content)
rescue => e
Jekyll.logger.error "Conversion error:", "There was an error converting" +
" '#{self.path}'."
@@ -59,15 +62,23 @@ def transform
# Returns the String extension for the output file.
# e.g. ".html" for an HTML output file.
def output_ext
- converter.output_ext(self.ext)
+ converter(false).output_ext(self.ext)
end
# Determine which converter to use based on this convertible's
# extension.
#
+ # run_before_liquid - select converters designed to run before
+ # liquid tags are parsed
+ #
# Returns the Converter instance.
- def converter
- @converter ||= self.site.converters.find { |c| c.matches(self.ext) }
+ def converter(before_liquid=false)
+ @converter ||= {}
+ @converter[before_liquid] ||= self.site.converters.find{ |c| c.run_before_liquid? == before_liquid && c.matches(self.ext)}
+ @converter[before_liquid] ||= self.site.converters.find {|c|
+ c.run_before_liquid? == before_liquid &&
+ c.matches(self.ext)
+ }
end
# Render Liquid in the content
@@ -126,10 +137,11 @@ def do_layout(payload, layouts)
payload["pygments_prefix"] = converter.pygments_prefix
payload["pygments_suffix"] = converter.pygments_suffix
+ self.transform(true)
self.content = self.render_liquid(self.content,
payload.merge({:file => self.name}),
info)
- self.transform
+ self.transform(false)
# output keeps track of what will finally be written
self.output = self.content
View
46 test/test_convertible.rb
@@ -48,4 +48,50 @@ class TestConvertible < Test::Unit::TestCase
end
end
end
+
+ context "pre- and post-liquid conversion" do
+ setup do
+ @convertible = OpenStruct.new
+ @convertible.extend Jekyll::Convertible
+ @convertible.ext = '.test'
+
+ @before_converter = stub!.run_before_liquid?{true}.subject
+ stub(@before_converter).matches{ true }
+ stub(@before_converter).convert("foo"){ "{%raw%}bar{%endraw%}" }
+
+ @after_converter = stub!.run_before_liquid?{false}.subject
+ stub(@after_converter).matches{ true }
+ stub(@after_converter ).convert("bar"){ "Passed!" }
+
+ @site = stub!.converters{ [@before_converter, @after_converter]}.subject
+
+ @convertible.site = @site
+ end
+
+ should "recognise correct converters" do
+ assert_equal(@before_converter,@convertible.converter(true))
+ assert_equal(@after_converter, @convertible.converter(false) )
+ end
+
+ should "be run on mulitple transforms" do
+ @convertible.content = "foo"
+
+ @convertible.transform(true)
+ assert_equal("{%raw%}bar{%endraw%}", @convertible.content)
+ @convertible.content = Liquid::Template.parse(@convertible.content).render!
+ assert_equal("bar", @convertible.content)
+ @convertible.transform(false)
+ assert_equal("Passed!", @convertible.content)
+ end
+
+ should "be run on do_layout" do
+ stub(@after_converter).pygments_prefix{""}
+ stub(@after_converter).pygments_suffix{""}
+
+ @convertible.content = "foo"
+ @convertible.data = {}
+ @convertible.do_layout({},{})
+ assert_equal("Passed!", @convertible.content)
+ end
+ end
end
Something went wrong with that request. Please try again.