diff --git a/features/include_tag.feature b/features/include_tag.feature index 587784dc..5f0e5799 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -55,3 +55,14 @@ Feature: Include tags When I run jekyll Then the _site directory should exist And I should see "one two" in "_site/index.html" + + Scenario: Include a file with variables and filters + Given I have an _includes directory + And I have an "_includes/one.html" file that contains "one included" + And I have a configuration file with: + | key | value | + | include_file | one | + And I have an "index.html" page that contains "{% include {{ site.include_file | append: '.html' }} %}" + When I run jekyll + Then the _site directory should exist + And I should see "one included" in "_site/index.html" diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 49033ab0..5c679dc1 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -14,12 +14,19 @@ module Jekyll SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}" VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/ + VARIABLE_SYNTAX = /(?\{\{\s*(?[\w\-\.]+)\s*(\|.*)?\}\})(?.*)/ INCLUDES_DIR = '_includes' def initialize(tag_name, markup, tokens) super - @file, @params = markup.strip.split(' ', 2); + matched = markup.strip.match(VARIABLE_SYNTAX) + if matched + @file = matched['variable'].strip + @params = matched['params'].strip + else + @file, @params = markup.strip.split(' ', 2); + end validate_params if @params end @@ -48,7 +55,7 @@ module Jekyll raise ArgumentError.new <<-eos Invalid syntax for include tag. File contains invalid characters or sequences: - #{@file} + #{file} Valid syntax: @@ -79,10 +86,11 @@ eos context.registers[:site].file_read_opts end - def retrieve_variable(context) - if /\{\{([\w\-\.]+)\}\}/ =~ @file - raise ArgumentError.new("No variable #{$1} was found in include tag") if context[$1].nil? - context[$1] + # Render the variable if required + def render_variable(context) + if @file.match(VARIABLE_SYNTAX) + partial = Liquid::Template.parse(@file) + partial.render!(context) end end @@ -90,7 +98,7 @@ eos dir = File.join(context.registers[:site].source, INCLUDES_DIR) validate_dir(dir, context.registers[:site].safe) - file = retrieve_variable(context) || @file + file = render_variable(context) || @file validate_file_name(file) path = File.join(dir, file) @@ -116,9 +124,9 @@ eos def validate_file(file, safe) if !File.exists?(file) - raise IOError.new "Included file '#{@file}' not found in '#{INCLUDES_DIR}' directory" + raise IOError.new "Included file '#{file}' not found" elsif File.symlink?(file) && safe - raise IOError.new "The included file '#{INCLUDES_DIR}/#{@file}' should not be a symlink" + raise IOError.new "The included file '#{file}' should not be a symlink" end end diff --git a/site/docs/templates.md b/site/docs/templates.md index 7cf2a865..67b30123 100644 --- a/site/docs/templates.md +++ b/site/docs/templates.md @@ -209,9 +209,7 @@ root of your source directory. This will embed the contents of The name of the file you wish to embed can be literal (as in the example above), or you can use a variable, using liquid-like variable syntax as in - {% raw %}{% include {{my_variable}} %}{% endraw %}. - - Note that unlike usual liquid variable syntax, you cannot have spaces inside the curly braces. + {% raw %}{% include {{ my_variable }} %}{% endraw %}.

diff --git a/test/source/_includes/include.html b/test/source/_includes/include.html new file mode 100644 index 00000000..201a102c --- /dev/null +++ b/test/source/_includes/include.html @@ -0,0 +1 @@ +included diff --git a/test/source/_posts/2013-12-17-include-variable-filters.markdown b/test/source/_posts/2013-12-17-include-variable-filters.markdown new file mode 100644 index 00000000..3d66e879 --- /dev/null +++ b/test/source/_posts/2013-12-17-include-variable-filters.markdown @@ -0,0 +1,21 @@ +--- +title: Post +layout: post +include1: include.html +include2: include +include3: INCLUDE +include4: params +--- + +Liquid tests +- 1 {% include {{ page.include1 }} %} +- 2 {% include {{ page.include2 | append: '.html' }} %} +- 3 {% include {{ page.include3 | downcase | append: '.html' }} %} + +Whitespace tests +- 4 {% include {{page.include1}} %} +- 5 {% include {{ page.include1}} %} +- 6 {% include {{ page.include3 | downcase | append: '.html'}} %} + +Parameters test +- 7 {% include {{ page.include4 | append: '.html' }} var1='foo' var2='bar' %} diff --git a/test/test_generated_site.rb b/test/test_generated_site.rb index 801675bf..866f753c 100644 --- a/test/test_generated_site.rb +++ b/test/test_generated_site.rb @@ -14,7 +14,7 @@ class TestGeneratedSite < Test::Unit::TestCase end should "ensure post count is as expected" do - assert_equal 36, @site.posts.size + assert_equal 37, @site.posts.size end should "insert site.posts into the index" do diff --git a/test/test_tags.rb b/test/test_tags.rb index b21f4931..926c7f18 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -471,5 +471,35 @@ CONTENT end end + context "include tag with variable and liquid filters" do + setup do + stub(Jekyll).configuration do + Jekyll::Configuration::DEFAULTS.deep_merge({'pygments' => true}).deep_merge({'source' => source_dir, 'destination' => dest_dir}) + end + + site = Site.new(Jekyll.configuration) + post = Post.new(site, source_dir, '', "2013-12-17-include-variable-filters.markdown") + layouts = { "default" => Layout.new(site, source_dir('_layouts'), "simple.html")} + post.render(layouts, {"site" => {"posts" => []}}) + @content = post.content + end + + should "include file as variable with liquid filters" do + assert_match %r{1 included}, @content + assert_match %r{2 included}, @content + assert_match %r{3 included}, @content + end + + should "include file as variable and liquid filters with arbitrary whitespace" do + assert_match %r{4 included}, @content + assert_match %r{5 included}, @content + assert_match %r{6 included}, @content + end + + should "include file as variable and filters with additional parameters" do + assert_match '
  • var1 = foo
  • ', @content + assert_match '
  • var2 = bar
  • ', @content + end + end end end