Merge pull request #1204 from maul-esel/include-params2
Support parameters for liquid include tags.
This commit is contained in:
commit
08f6f3c2ed
|
@ -0,0 +1,35 @@
|
|||
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 "<header>My awesome blog header: {{include.param}}</header>"
|
||||
And I have an "_includes/params.html" file that contains "Parameters:<ul>{% for param in include %}<li>{{param[0]}} = {{param[1]}}</li>{% endfor %}</ul>"
|
||||
And I have an "_includes/ignore.html" file that contains "<footer>My blog footer</footer>"
|
||||
And I have a _posts directory
|
||||
And I have the following post:
|
||||
| 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\"" 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 "<header>My awesome blog header: myparam</header>" 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 "<li>date = today</li>" in "_site/2013/03/21/list-multiple-parameters.html"
|
||||
And I should see "<li>start = tomorrow</li>" in "_site/2013/03/21/list-multiple-parameters.html"
|
||||
And I should not see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/dont-keep-parameters.html"
|
||||
But I should see "<header>My awesome blog header: </header>" in "_site/2013/03/21/dont-keep-parameters.html"
|
||||
And I should see "<li>cool = param with spaces</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>super = “quoted”</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>single = has “quotes”</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>escaped = ‘single’ quotes</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>param1_or_2 = value</li>" in "_site/2013/04/12/parameter-syntax.html"
|
||||
And I should see "<li>local = some text</li>" in "_site/2013/06/22/pass-a-variable.html"
|
||||
And I should see "<li>layout = default</li>" in "_site/2013/06/22/pass-a-variable.html"
|
|
@ -143,6 +143,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
|
||||
|
|
|
@ -1,9 +1,51 @@
|
|||
module Jekyll
|
||||
module Tags
|
||||
class IncludeTag < Liquid::Tag
|
||||
def initialize(tag_name, file, tokens)
|
||||
|
||||
MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
@file = file.strip
|
||||
@file, @params = markup.strip.split(' ', 2);
|
||||
end
|
||||
|
||||
def parse_params(context)
|
||||
validate_syntax
|
||||
|
||||
params = {}
|
||||
markup = @params
|
||||
|
||||
while match = MATCHER.match(markup) do
|
||||
markup = markup[match.end(0)..-1]
|
||||
|
||||
value = if match[2]
|
||||
match[2].gsub(/\\"/, '"')
|
||||
elsif match[3]
|
||||
match[3].gsub(/\\'/, "'")
|
||||
elsif match[4]
|
||||
context[match[4]]
|
||||
end
|
||||
|
||||
params[match[1]] = value
|
||||
end
|
||||
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)
|
||||
|
@ -22,7 +64,9 @@ module Jekyll
|
|||
if choices.include?(@file)
|
||||
source = File.read(@file)
|
||||
partial = Liquid::Template.parse(source)
|
||||
|
||||
context.stack do
|
||||
context['include'] = parse_params(context) if @params
|
||||
partial.render(context)
|
||||
end
|
||||
else
|
||||
|
|
|
@ -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
|
||||
`<source>/_includes/sig.md` into the calling file.
|
||||
|
||||
You can also pass parameters to an include:
|
||||
|
||||
{% highlight ruby %}
|
||||
{% raw %}{% include sig.textile param="value" %}{% endraw %}
|
||||
{% endhighlight %}
|
||||
|
||||
These parameters are available via Liquid in the include:
|
||||
|
||||
{% highlight ruby %}
|
||||
{% raw %}{{ include.param }}{% endraw %}
|
||||
{% endhighlight %}
|
||||
|
||||
### Code snippet highlighting
|
||||
|
||||
Jekyll has built in support for syntax highlighting of [over 100
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<span id='include-param'>{{include.param}}</span>
|
||||
|
||||
<ul id='param-list'>
|
||||
{% for param in include %}
|
||||
<li>{{param[0]}} = {{param[1]}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
|
@ -347,4 +347,94 @@ CONTENT
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "include tag with parameters" do
|
||||
context "with one parameter" do
|
||||
setup do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: Include tag parameters
|
||||
---
|
||||
|
||||
{% include sig.markdown myparam="test" %}
|
||||
|
||||
{% include params.html param="value" %}
|
||||
CONTENT
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
|
||||
end
|
||||
|
||||
should "correctly output include variable" do
|
||||
assert_match "<span id='include-param'>value</span>", @result.strip
|
||||
end
|
||||
|
||||
should "ignore parameters if unused" do
|
||||
assert_match "<hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n", @result
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameter syntax" do
|
||||
should "throw a SyntaxError" do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: Invalid parameter syntax
|
||||
---
|
||||
|
||||
{% include params.html param s="value" %}
|
||||
CONTENT
|
||||
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
|
||||
end
|
||||
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: Invalid parameter syntax
|
||||
---
|
||||
|
||||
{% include params.html params="value %}
|
||||
CONTENT
|
||||
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with several parameters" do
|
||||
setup do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: multiple include parameters
|
||||
---
|
||||
|
||||
{% include params.html param1="new_value" param2="another" %}
|
||||
CONTENT
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
|
||||
end
|
||||
|
||||
should "list all parameters" do
|
||||
assert_match '<li>param1 = new_value</li>', @result
|
||||
assert_match '<li>param2 = another</li>', @result
|
||||
end
|
||||
|
||||
should "not include previously used parameters" do
|
||||
assert_match "<span id='include-param' />", @result
|
||||
end
|
||||
end
|
||||
|
||||
context "without parameters" do
|
||||
setup do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: without parameters
|
||||
---
|
||||
|
||||
{% include params.html %}
|
||||
CONTENT
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
|
||||
end
|
||||
|
||||
should "include file with empty parameters" do
|
||||
assert_match "<span id='include-param' />", @result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue