From 43ef9a2e4ffa09560e0cce232ae26bc25da0f3ac Mon Sep 17 00:00:00 2001 From: Jens Nazarenus Date: Sun, 8 Dec 2013 01:11:36 +0100 Subject: [PATCH 1/4] variables in include tag with filters --- features/include_tag.feature | 11 +++++++ lib/jekyll/tags/include.rb | 26 ++++++++++------ test/source/_includes/include.html | 1 + ...13-12-17-include-variable-filters.markdown | 22 +++++++++++++ test/test_generated_site.rb | 2 +- test/test_tags.rb | 31 +++++++++++++++++++ 6 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 test/source/_includes/include.html create mode 100644 test/source/_posts/2013-12-17-include-variable-filters.markdown 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 From f9ffbe0d6ad66919a9a85f422183382fafe7ded1 Mon Sep 17 00:00:00 2001 From: Jens Nazarenus Date: Thu, 19 Dec 2013 18:23:07 +0100 Subject: [PATCH 2/4] removed duplicate test scenario --- .../_posts/2013-12-17-include-variable-filters.markdown | 9 ++++----- test/test_tags.rb | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test/source/_posts/2013-12-17-include-variable-filters.markdown b/test/source/_posts/2013-12-17-include-variable-filters.markdown index 3b3db878..3d66e879 100644 --- a/test/source/_posts/2013-12-17-include-variable-filters.markdown +++ b/test/source/_posts/2013-12-17-include-variable-filters.markdown @@ -11,12 +11,11 @@ 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'}} %} +- 4 {% include {{page.include1}} %} +- 5 {% include {{ page.include1}} %} +- 6 {% include {{ page.include3 | downcase | append: '.html'}} %} Parameters test -- 8 {% include {{ page.include4 | append: '.html' }} var1='foo' var2='bar' %} +- 7 {% include {{ page.include4 | append: '.html' }} var1='foo' var2='bar' %} diff --git a/test/test_tags.rb b/test/test_tags.rb index 01aa9be6..926c7f18 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -488,13 +488,12 @@ CONTENT 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{4 included}, @content 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 From 10ee83d680c9ab049f306df8ff5c29f8223f939e Mon Sep 17 00:00:00 2001 From: Jens Nazarenus Date: Thu, 19 Dec 2013 18:23:21 +0100 Subject: [PATCH 3/4] edited raise message when validating included file --- lib/jekyll/tags/include.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index c1a4268e..5c679dc1 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -124,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 From 412fe8b8deee006114fa81308717b028beacc789 Mon Sep 17 00:00:00 2001 From: Jens Nazarenus Date: Thu, 19 Dec 2013 18:29:40 +0100 Subject: [PATCH 4/4] edited documentation for include tag --- site/docs/templates.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 %}.