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..c1a4268e 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 in '#{INCLUDES_DIR}' directory" 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 '#{INCLUDES_DIR}/#{file}' should not be a symlink" end end 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..3b3db878 --- /dev/null +++ b/test/source/_posts/2013-12-17-include-variable-filters.markdown @@ -0,0 +1,22 @@ +--- +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' }} %} +- 4 {% include {{ page.include2 | append: '.html' }} %} + +Whitespace tests +- 5 {% include {{page.include1}} %} +- 6 {% include {{ page.include1}} %} +- 7 {% include {{ page.include3 | downcase | append: '.html'}} %} + +Parameters test +- 8 {% 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..01aa9be6 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -471,5 +471,36 @@ 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 + assert_match %r{4 included}, @content + end + + should "include file as variable and liquid filters with arbitrary whitespace" do + assert_match %r{5 included}, @content + assert_match %r{6 included}, @content + assert_match %r{7 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