Merge pull request #1841 from jens-na/include-variable-liquid-filters

This commit is contained in:
Parker Moore 2013-12-25 22:11:33 -08:00
commit 6e8f31f406
7 changed files with 82 additions and 13 deletions

View File

@ -55,3 +55,14 @@ Feature: Include tags
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "one two" in "_site/index.html" 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"

View File

@ -14,12 +14,19 @@ module Jekyll
SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}" SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}"
VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/ VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
VARIABLE_SYNTAX = /(?<variable>\{\{\s*(?<name>[\w\-\.]+)\s*(\|.*)?\}\})(?<params>.*)/
INCLUDES_DIR = '_includes' INCLUDES_DIR = '_includes'
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
super 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 validate_params if @params
end end
@ -48,7 +55,7 @@ module Jekyll
raise ArgumentError.new <<-eos raise ArgumentError.new <<-eos
Invalid syntax for include tag. File contains invalid characters or sequences: Invalid syntax for include tag. File contains invalid characters or sequences:
#{@file} #{file}
Valid syntax: Valid syntax:
@ -79,10 +86,11 @@ eos
context.registers[:site].file_read_opts context.registers[:site].file_read_opts
end end
def retrieve_variable(context) # Render the variable if required
if /\{\{([\w\-\.]+)\}\}/ =~ @file def render_variable(context)
raise ArgumentError.new("No variable #{$1} was found in include tag") if context[$1].nil? if @file.match(VARIABLE_SYNTAX)
context[$1] partial = Liquid::Template.parse(@file)
partial.render!(context)
end end
end end
@ -90,7 +98,7 @@ eos
dir = File.join(context.registers[:site].source, INCLUDES_DIR) dir = File.join(context.registers[:site].source, INCLUDES_DIR)
validate_dir(dir, context.registers[:site].safe) validate_dir(dir, context.registers[:site].safe)
file = retrieve_variable(context) || @file file = render_variable(context) || @file
validate_file_name(file) validate_file_name(file)
path = File.join(dir, file) path = File.join(dir, file)
@ -116,9 +124,9 @@ eos
def validate_file(file, safe) def validate_file(file, safe)
if !File.exists?(file) 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 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
end end

View File

@ -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), 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 or you can use a variable, using liquid-like variable syntax as in
<code>{% raw %}{% include {{my_variable}} %}{% endraw %}</code>. <code>{% raw %}{% include {{ my_variable }} %}{% endraw %}</code>.
Note that unlike usual liquid variable syntax, you cannot have spaces inside the curly braces.
</p> </p>
</div> </div>

View File

@ -0,0 +1 @@
included

View File

@ -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' %}

View File

@ -14,7 +14,7 @@ class TestGeneratedSite < Test::Unit::TestCase
end end
should "ensure post count is as expected" do should "ensure post count is as expected" do
assert_equal 36, @site.posts.size assert_equal 37, @site.posts.size
end end
should "insert site.posts into the index" do should "insert site.posts into the index" do

View File

@ -471,5 +471,35 @@ CONTENT
end end
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 '<li>var1 = foo</li>', @content
assert_match '<li>var2 = bar</li>', @content
end
end
end end
end end