From 73e589df5607726fb0379f6c5e18db5089562768 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Fri, 24 May 2013 15:44:04 +0200 Subject: [PATCH 01/18] add a cucumber feature for passing parameters to includes --- features/include_tag.feature | 30 +++++++++++++++++++++++ features/step_definitions/jekyll_steps.rb | 4 +++ 2 files changed, 34 insertions(+) create mode 100644 features/include_tag.feature diff --git a/features/include_tag.feature b/features/include_tag.feature new file mode 100644 index 00000000..9d301fcd --- /dev/null +++ b/features/include_tag.feature @@ -0,0 +1,30 @@ +Feature: Include tags + In order to share their content across several pages + As a hacker who likes to blog + I want to be able to include files in my blog posts + + Scenario: Include a file with parameters + Given I have an _includes directory + And I have an "_includes/header.html" file that contains "
My awesome blog header: {{include.param}}
" + And I have an "_includes/params.html" file that contains "Parameters:" + And I have an "_includes/ignore.html" file that contains "" + And I have a _posts directory + And I have the following post: + | title | date | layout | content | + | Include Files | 3/21/2013 | default | {% include header.html param="myparam" %} | + | Ignore params if unused | 3/21/2013 | default | {% include ignore.html date="today" %} | + | List multiple parameters | 3/21/2013 | default | {% include params.html date="today" start="tomorrow" %} | + | Dont keep parameters | 3/21/2013 | default | {% include ignore.html param="test" %}\n{% include header.html %} | + | Allow params with spaces and quotes | 4/07/2013 | default | {% include params.html cool="param with spaces" super="\"quoted\"" %} | + | Parameter syntax | 4/12/2013 | default | {% include params.html param1_or_2="value" %} | + When I run jekyll + Then the _site directory should exist + And I should see "
My awesome blog header: myparam
" in "_site/2013/03/21/include-files.html" + And I should not see "myparam" in "_site/2013/03/21/ignore-params-if-unused.html" + And I should see "
  • date = today
  • " in "_site/2013/03/21/list-multiple-parameters.html" + And I should see "
  • start = tomorrow
  • " in "_site/2013/03/21/list-multiple-parameters.html" + And I should not see "
    My awesome blog header: myparam
    " in "_site/2013/03/21/dont-keep-parameters.html" + But I should see "
    My awesome blog header:
    " in "_site/2013/03/21/dont-keep-parameters.html" + And I should see "
  • cool = param with spaces
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • super = “quoted”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • param1_or_2 = value
  • " in "_site/2013/04/12/parameter-syntax.html" diff --git a/features/step_definitions/jekyll_steps.rb b/features/step_definitions/jekyll_steps.rb index 7a1c7cd1..293bc2eb 100644 --- a/features/step_definitions/jekyll_steps.rb +++ b/features/step_definitions/jekyll_steps.rb @@ -136,6 +136,10 @@ Then /^I should see "(.*)" in "(.*)"$/ do |text, file| assert Regexp.new(text).match(File.open(file).readlines.join) end +Then /^I should not see "(.*)" in "(.*)"$/ do |text, file| + assert_no_match Regexp.new(text), File.read(file) +end + Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file| assert Regexp.new(Regexp.escape(text)).match(File.open(file).readlines.join) end From f612330565f55fa4ecc52b1fe57a71e8832f9691 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Fri, 24 May 2013 16:02:49 +0200 Subject: [PATCH 02/18] add support for parameters to {% include %} tags --- lib/jekyll/tags/include.rb | 66 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 3c2fa984..c4afac46 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -1,9 +1,70 @@ module Jekyll module Tags class IncludeTag < Liquid::Tag - def initialize(tag_name, file, tokens) + def initialize(tag_name, markup, tokens) super - @file = file.strip + markup.strip! + if markup.include?(' ') + separator = markup.index(' ') + @file = markup[0..separator].strip + parse_params(markup[separator..-1]) + else + @file = markup + end + end + + def parse_params(markup) + last_space = last_quote = pos = 0 + last_key = nil + in_quotes = false + @params = {} + + if !(/^(\s*\b\S+="(?:\\"|.)*?")*\s*$/ =~ markup) + raise SyntaxError.new <<-eos +Syntax error for 'include' while parsing the following markup: + + #{markup} + +Valid syntax: include param="value" +eos + end + + while pos = markup.index(/[=\"\s]/, pos) + str = markup[pos, 1] + if /\s/ =~ str + last_space = pos + elsif str == '=' + if !last_key.nil? + raise SyntaxError.new <<-eos +Syntax Error in tag 'include' (missing value) while parsing the following markup: + + #{markup} + +Valid syntax: include param="value" +eos + end + last_key = markup[last_space+1..pos-1] + elsif str == '"' and markup[pos-1, 1] != '\\' + in_quotes = !in_quotes + if !in_quotes + value = markup[last_quote+1..pos-1].gsub(/\\"/, '"') + @params[last_key] = value + last_key = nil + end + last_quote = pos + end + pos += 1 + end + + if in_quotes + raise SyntaxError.new <<-eos +Syntax Error in tag 'include' (unterminated value) while parsing the following markup: + + #{markup} + +Valid syntax: include param="value" +eos + end end def render(context) @@ -22,6 +83,7 @@ module Jekyll if choices.include?(@file) source = File.read(@file) partial = Liquid::Template.parse(source) + context['include'] = @params context.stack do partial.render(context) end From fad210100b1f7620bb1397d35b183d7cdcd2aea6 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Tue, 11 Jun 2013 16:08:47 +0200 Subject: [PATCH 03/18] document include tag parameters --- site/docs/templates.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/site/docs/templates.md b/site/docs/templates.md index c1e6a95a..ead0189f 100644 --- a/site/docs/templates.md +++ b/site/docs/templates.md @@ -192,6 +192,18 @@ Jekyll expects all include files to be placed in an `_includes` directory at the root of your source directory. This will embed the contents of `/_includes/sig.md` into the calling file. +You can also pass parameters to an include: + +{% highlight ruby %} +{{ "{% include sig.textile param=value " }}%} +{% endhighlight %} + +These parameters are available via Liquid in the include: + +{% highlight ruby %} +{{ "{{ include.param " }}}} +{% endhighlight %} + ### Code snippet highlighting Jekyll has built in support for syntax highlighting of [over 100 From 5a990f7854806f24bf0cc2d79529d56e1993b015 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Tue, 11 Jun 2013 16:11:56 +0200 Subject: [PATCH 04/18] add unit tests for include tag parameters --- test/source/_includes/params.html | 7 +++ test/test_tags.rb | 90 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/source/_includes/params.html diff --git a/test/source/_includes/params.html b/test/source/_includes/params.html new file mode 100644 index 00000000..65a00018 --- /dev/null +++ b/test/source/_includes/params.html @@ -0,0 +1,7 @@ +{{include.param}} + +
      + {% for param in include %} +
    • {{param[0]}} = {{param[1]}}
    • + {% endfor %} +
    \ No newline at end of file diff --git a/test/test_tags.rb b/test/test_tags.rb index fd2df409..d0992873 100644 --- a/test/test_tags.rb +++ b/test/test_tags.rb @@ -347,4 +347,94 @@ CONTENT end end end + + context "include tag with parameters" do + context "with one parameter" do + setup do + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + + should "correctly output include variable" do + assert_match "value", @result.strip + end + + should "ignore parameters if unused" do + assert_match "
    \n

    Tom Preston-Werner github.com/mojombo

    \n", @result + end + end + + context "with invalid parameter syntax" do + should "throw a SyntaxError" do + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + end + end + + context "with several parameters" do + setup do + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + + should "list all parameters" do + assert_match '
  • param1 = new_value
  • ', @result + assert_match '
  • param2 = another
  • ', @result + end + + should "not include previously used parameters" do + assert_match "", @result + end + end + + context "without parameters" do + setup do + content = < 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) + end + + should "include file with empty parameters" do + assert_match "", @result + end + end + end end From 1e15df070181857e7ff079f72e2bce6a977b0d9d Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Tue, 11 Jun 2013 16:28:50 +0200 Subject: [PATCH 05/18] fix cucumber feature to obey new date format --- features/include_tag.feature | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/features/include_tag.feature b/features/include_tag.feature index 9d301fcd..6dc3bf49 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -10,13 +10,13 @@ Feature: Include tags And I have an "_includes/ignore.html" file that contains "
    My blog footer
    " And I have a _posts directory And I have the following post: - | title | date | layout | content | - | Include Files | 3/21/2013 | default | {% include header.html param="myparam" %} | - | Ignore params if unused | 3/21/2013 | default | {% include ignore.html date="today" %} | - | List multiple parameters | 3/21/2013 | default | {% include params.html date="today" start="tomorrow" %} | - | Dont keep parameters | 3/21/2013 | default | {% include ignore.html param="test" %}\n{% include header.html %} | - | Allow params with spaces and quotes | 4/07/2013 | default | {% include params.html cool="param with spaces" super="\"quoted\"" %} | - | Parameter syntax | 4/12/2013 | default | {% include params.html param1_or_2="value" %} | + | title | date | layout | content | + | Include Files | 2013-03-21 | default | {% include header.html param="myparam" %} | + | Ignore params if unused | 2013-03-21 | default | {% include ignore.html date="today" %} | + | List multiple parameters | 2013-03-21 | default | {% include params.html date="today" start="tomorrow" %} | + | Dont keep parameters | 2013-03-21 | default | {% include ignore.html param="test" %}\n{% include header.html %} | + | Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" %} | + | Parameter syntax | 2013-04-12 | default | {% include params.html param1_or_2="value" %} | When I run jekyll Then the _site directory should exist And I should see "
    My awesome blog header: myparam
    " in "_site/2013/03/21/include-files.html" From 1b20a185ca4bd71add78d3881037f4b7d677158e Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Wed, 12 Jun 2013 18:14:03 +0200 Subject: [PATCH 06/18] fix liquid syntax in the docs --- site/docs/templates.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/docs/templates.md b/site/docs/templates.md index ead0189f..cab2dd7f 100644 --- a/site/docs/templates.md +++ b/site/docs/templates.md @@ -195,13 +195,13 @@ root of your source directory. This will embed the contents of You can also pass parameters to an include: {% highlight ruby %} -{{ "{% include sig.textile param=value " }}%} +{% raw %}{% include sig.textile param="value" %}{% endraw %} {% endhighlight %} These parameters are available via Liquid in the include: {% highlight ruby %} -{{ "{{ include.param " }}}} +{% raw %}{{ include.param }}{% endraw %} {% endhighlight %} ### Code snippet highlighting From 639acea0a7cd51c55cf9d406ac4a6273b95bfa21 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Thu, 13 Jun 2013 18:27:40 +0200 Subject: [PATCH 07/18] do parameter parsing with @imathis' incredible regex This also introduces single-quote support. --- lib/jekyll/tags/include.rb | 58 +++++++++++++------------------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index c4afac46..b5154d63 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -13,57 +13,37 @@ module Jekyll end end + MATCHER = /(?\w+)=(?:"(?[^"\\]*(?:\\.[^"\\]*)*)"|'(?[^'\\]*(?:\\.[^'\\]*)*)')/ + def parse_params(markup) - last_space = last_quote = pos = 0 - last_key = nil - in_quotes = false @params = {} + pos = 0 - if !(/^(\s*\b\S+="(?:\\"|.)*?")*\s*$/ =~ markup) + # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces + full_matcher = Regexp.compile('\A\s*(?:(?<=\s|\A)' + MATCHER.to_s + '\s*)*\z') + if not markup =~ full_matcher raise SyntaxError.new <<-eos -Syntax error for 'include' while parsing the following markup: +Invalid syntax for include tag: - #{markup} + #{markup} + +Valid syntax: + + {% include file.ext param='value' param2="value" %} -Valid syntax: include param="value" eos end - while pos = markup.index(/[=\"\s]/, pos) - str = markup[pos, 1] - if /\s/ =~ str - last_space = pos - elsif str == '=' - if !last_key.nil? - raise SyntaxError.new <<-eos -Syntax Error in tag 'include' (missing value) while parsing the following markup: + while match = MATCHER.match(markup, pos) do + pos = match.end(0) - #{markup} - -Valid syntax: include param="value" -eos - end - last_key = markup[last_space+1..pos-1] - elsif str == '"' and markup[pos-1, 1] != '\\' - in_quotes = !in_quotes - if !in_quotes - value = markup[last_quote+1..pos-1].gsub(/\\"/, '"') - @params[last_key] = value - last_key = nil - end - last_quote = pos + if match[:dvar] + value = match[:dvar].gsub(/\\"/, '"') + elsif match[:svar] + value = match[:svar].gsub(/\\'/, "'") end - pos += 1 - end - if in_quotes - raise SyntaxError.new <<-eos -Syntax Error in tag 'include' (unterminated value) while parsing the following markup: - - #{markup} - -Valid syntax: include param="value" -eos + @params[match[:param]] = value end end From 53dec6a4f66193ebf3107c4a30f053deb168e42e Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Thu, 13 Jun 2013 18:28:03 +0200 Subject: [PATCH 08/18] add single-quote cucumber testing --- features/include_tag.feature | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/include_tag.feature b/features/include_tag.feature index 6dc3bf49..617c8718 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -15,7 +15,7 @@ Feature: Include tags | Ignore params if unused | 2013-03-21 | default | {% include ignore.html date="today" %} | | List multiple parameters | 2013-03-21 | default | {% include params.html date="today" start="tomorrow" %} | | Dont keep parameters | 2013-03-21 | default | {% include ignore.html param="test" %}\n{% include header.html %} | - | Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" %} | + | Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} | | Parameter syntax | 2013-04-12 | default | {% include params.html param1_or_2="value" %} | When I run jekyll Then the _site directory should exist @@ -27,4 +27,6 @@ Feature: Include tags But I should see "
    My awesome blog header:
    " in "_site/2013/03/21/dont-keep-parameters.html" And I should see "
  • cool = param with spaces
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "
  • super = “quoted”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • single = has “quotes”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • escaped = ‘single’ quotes
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "
  • param1_or_2 = value
  • " in "_site/2013/04/12/parameter-syntax.html" From 0fa03d265100e345cf2bc9e25aa5323eee3d3cd5 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Thu, 13 Jun 2013 18:48:40 +0200 Subject: [PATCH 09/18] stupid Ruby 1.8.7 doesn't support named groups --- lib/jekyll/tags/include.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index b5154d63..ffc28e0b 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -13,7 +13,7 @@ module Jekyll end end - MATCHER = /(?\w+)=(?:"(?[^"\\]*(?:\\.[^"\\]*)*)"|'(?[^'\\]*(?:\\.[^'\\]*)*)')/ + MATCHER = /(\w+)=(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')/ def parse_params(markup) @params = {} @@ -37,13 +37,13 @@ eos while match = MATCHER.match(markup, pos) do pos = match.end(0) - if match[:dvar] - value = match[:dvar].gsub(/\\"/, '"') - elsif match[:svar] - value = match[:svar].gsub(/\\'/, "'") + if match[2] + value = match[2].gsub(/\\"/, '"') + elsif match[3] + value = match[3].gsub(/\\'/, "'") end - @params[match[:param]] = value + @params[match[1]] = value end end From 99721ee8aab2b08064dc56a9782997a403b21d2e Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Sat, 15 Jun 2013 18:19:52 +0200 Subject: [PATCH 10/18] To satisfy Ruby 1.8.7, use look-ahead instead of look-behind --- lib/jekyll/tags/include.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index ffc28e0b..0ad64bad 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -20,7 +20,7 @@ module Jekyll pos = 0 # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces - full_matcher = Regexp.compile('\A\s*(?:(?<=\s|\A)' + MATCHER.to_s + '\s*)*\z') + full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z') if not markup =~ full_matcher raise SyntaxError.new <<-eos Invalid syntax for include tag: From bdd84f275ea53da95b598e9c829ca66266199a3c Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Sat, 15 Jun 2013 18:28:26 +0200 Subject: [PATCH 11/18] Ruby 1.8.7 only supports 1 param to Regexp.match() --- 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 0ad64bad..54cee900 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -34,8 +34,8 @@ Valid syntax: eos end - while match = MATCHER.match(markup, pos) do - pos = match.end(0) + while match = MATCHER.match(markup) do + markup = markup[match.end(0)..-1] if match[2] value = match[2].gsub(/\\"/, '"') From 00ed567f9996c278a8d426b60711dfb124026429 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Sat, 22 Jun 2013 15:07:10 +0200 Subject: [PATCH 12/18] move regex to the top --- lib/jekyll/tags/include.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 54cee900..68636890 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -1,6 +1,9 @@ module Jekyll module Tags class IncludeTag < Liquid::Tag + + MATCHER = /(\w+)=(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')/ + def initialize(tag_name, markup, tokens) super markup.strip! @@ -13,8 +16,6 @@ module Jekyll end end - MATCHER = /(\w+)=(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')/ - def parse_params(markup) @params = {} pos = 0 From f8f678430540680fa71a7d0f2226664e4d363ebd Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Sat, 22 Jun 2013 15:30:10 +0200 Subject: [PATCH 13/18] move parameter parsing to render time --- lib/jekyll/tags/include.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 68636890..b98b6041 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -10,14 +10,14 @@ module Jekyll if markup.include?(' ') separator = markup.index(' ') @file = markup[0..separator].strip - parse_params(markup[separator..-1]) + @params = markup[separator..-1] else @file = markup end end def parse_params(markup) - @params = {} + params = {} pos = 0 # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces @@ -44,8 +44,9 @@ eos value = match[3].gsub(/\\'/, "'") end - @params[match[1]] = value + params[match[1]] = value end + params end def render(context) @@ -64,8 +65,9 @@ eos if choices.include?(@file) source = File.read(@file) partial = Liquid::Template.parse(source) - context['include'] = @params + context.stack do + context['include'] = parse_params(@params) if @params partial.render(context) end else From 2b01b06ec884ab149c619333ed94fdb89dea69fb Mon Sep 17 00:00:00 2001 From: imathis Date: Sat, 22 Jun 2013 15:46:19 +0200 Subject: [PATCH 14/18] Support passing Liquid variables to includes Change the regex matching to allow Liquid variables and object fields to be passed to the include. Use the render context to retrieve the variable value. Also, relax syntax checks by allowing surrounding spaces and dashes in parameter names. --- lib/jekyll/tags/include.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index b98b6041..6956f6a3 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -2,7 +2,7 @@ module Jekyll module Tags class IncludeTag < Liquid::Tag - MATCHER = /(\w+)=(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')/ + MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/ def initialize(tag_name, markup, tokens) super @@ -16,7 +16,7 @@ module Jekyll end end - def parse_params(markup) + def parse_params(markup, context) params = {} pos = 0 @@ -42,6 +42,8 @@ eos value = match[2].gsub(/\\"/, '"') elsif match[3] value = match[3].gsub(/\\'/, "'") + elsif match[4] + value = context[match[4]] end params[match[1]] = value @@ -67,7 +69,7 @@ eos partial = Liquid::Template.parse(source) context.stack do - context['include'] = parse_params(@params) if @params + context['include'] = parse_params(@params, context) if @params partial.render(context) end else From 656dcca3d293c312ea3efdf719427c9d1ef0bd86 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Sat, 22 Jun 2013 15:47:59 +0200 Subject: [PATCH 15/18] Add a cucumber test for passing variables --- features/include_tag.feature | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/include_tag.feature b/features/include_tag.feature index 617c8718..66f9d4a6 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -17,6 +17,7 @@ Feature: Include tags | Dont keep parameters | 2013-03-21 | default | {% include ignore.html param="test" %}\n{% include header.html %} | | Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} | | Parameter syntax | 2013-04-12 | default | {% include params.html param1_or_2="value" %} | + | Pass a variable | 2013-06-22 | default | {% assign var = 'some text' %}{% include params.html local=var layout=page.layout %} | When I run jekyll Then the _site directory should exist And I should see "
    My awesome blog header: myparam
    " in "_site/2013/03/21/include-files.html" @@ -30,3 +31,5 @@ Feature: Include tags And I should see "
  • single = has “quotes”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "
  • escaped = ‘single’ quotes
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "
  • param1_or_2 = value
  • " in "_site/2013/04/12/parameter-syntax.html" + And I should see "
  • local = some text
  • " in "_site/2013/06/22/pass-a-variable.html" + And I should see "
  • layout = default
  • " in "_site/2013/06/22/pass-a-variable.html" From ef22ebd7f180c6bd1e18762803bb4b97134a8cd2 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Fri, 5 Jul 2013 14:13:40 +0200 Subject: [PATCH 16/18] code improvements according to @parkr's suggestions --- lib/jekyll/tags/include.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 6956f6a3..38b20a7e 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -6,14 +6,7 @@ module Jekyll def initialize(tag_name, markup, tokens) super - markup.strip! - if markup.include?(' ') - separator = markup.index(' ') - @file = markup[0..separator].strip - @params = markup[separator..-1] - else - @file = markup - end + @file, @params = markup.strip.split(' ', 2); end def parse_params(markup, context) @@ -22,7 +15,7 @@ module Jekyll # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z') - if not markup =~ full_matcher + unless markup =~ full_matcher raise SyntaxError.new <<-eos Invalid syntax for include tag: From f72365da4fee5e69cb96d20dc61c7fbdafe0f198 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Mon, 8 Jul 2013 18:48:47 +0200 Subject: [PATCH 17/18] more code improvements Remove unused variable, extract validation to method (@mattr-). Do not require markup to be passed to parse_params as argument. --- lib/jekyll/tags/include.rb | 40 +++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 38b20a7e..5acb5391 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -9,24 +9,11 @@ module Jekyll @file, @params = markup.strip.split(' ', 2); end - def parse_params(markup, context) + def parse_params(context) + validate_syntax + params = {} - pos = 0 - - # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces - full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z') - unless markup =~ full_matcher - raise SyntaxError.new <<-eos -Invalid syntax for include tag: - - #{markup} - -Valid syntax: - - {% include file.ext param='value' param2="value" %} - -eos - end + markup = @params while match = MATCHER.match(markup) do markup = markup[match.end(0)..-1] @@ -44,6 +31,23 @@ eos params end + # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces + def validate_syntax + full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z') + unless @params =~ full_matcher + raise SyntaxError.new <<-eos +Invalid syntax for include tag: + + #{@params} + +Valid syntax: + + {% include file.ext param='value' param2="value" %} + +eos + end + end + def render(context) includes_dir = File.join(context.registers[:site].source, '_includes') @@ -62,7 +66,7 @@ eos partial = Liquid::Template.parse(source) context.stack do - context['include'] = parse_params(@params, context) if @params + context['include'] = parse_params(context) if @params partial.render(context) end else From 9d2849c56201d3e6322c309bf36606f4ef5f62a8 Mon Sep 17 00:00:00 2001 From: "maul.esel" Date: Mon, 8 Jul 2013 20:43:03 +0200 Subject: [PATCH 18/18] set value outside if/else block --- lib/jekyll/tags/include.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 5acb5391..ce1350b1 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -18,12 +18,12 @@ module Jekyll while match = MATCHER.match(markup) do markup = markup[match.end(0)..-1] - if match[2] - value = match[2].gsub(/\\"/, '"') + value = if match[2] + match[2].gsub(/\\"/, '"') elsif match[3] - value = match[3].gsub(/\\'/, "'") + match[3].gsub(/\\'/, "'") elsif match[4] - value = context[match[4]] + context[match[4]] end params[match[1]] = value