Merge pull request #1490 from penibelst/allow-include-read-override

Extract include tag read file in a method
This commit is contained in:
Matt Rogers 2013-09-18 19:34:45 -07:00
commit 793eb96a77
2 changed files with 56 additions and 29 deletions

View File

@ -2,20 +2,28 @@ module Jekyll
module Tags
class IncludeTag < Liquid::Tag
MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}"
VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
INCLUDES_DIR = '_includes'
def initialize(tag_name, markup, tokens)
super
@file, @params = markup.strip.split(' ', 2);
validate_syntax
end
def validate_syntax
validate_file_name
validate_params if @params
end
def parse_params(context)
validate_syntax
params = {}
markup = @params
while match = MATCHER.match(markup) do
while match = VALID_SYNTAX.match(markup) do
markup = markup[match.end(0)..-1]
value = if match[2]
@ -31,32 +39,49 @@ module Jekyll
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
def validate_file_name
if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
raise ArgumentError.new <<-eos
Invalid syntax for include tag. File contains invalid characters or sequences:
#{@file}
Valid syntax:
#{SYNTAX_EXAMPLE}
eos
end
end
def validate_params
full_valid_syntax = Regexp.compile('\A\s*(?:' + VALID_SYNTAX.to_s + '(?=\s|\z)\s*)*\z')
unless @params =~ full_valid_syntax
raise ArgumentError.new <<-eos
Invalid syntax for include tag:
#{@params}
Valid syntax:
{% include file.ext param='value' param2="value" %}
#{SYNTAX_EXAMPLE}
eos
end
end
def render(context)
includes_dir = File.join(context.registers[:site].source, '_includes')
if error = validate_file(includes_dir)
dir = File.join(context.registers[:site].source, INCLUDES_DIR)
if error = validate_dir(dir, context.registers[:site].safe)
return error
end
source = File.read(File.join(includes_dir, @file))
partial = Liquid::Template.parse(source)
file = File.join(dir, @file)
if error = validate_file(dir, context.registers[:site].safe)
return error
end
partial = Liquid::Template.parse(source(file))
context.stack do
context['include'] = parse_params(context) if @params
@ -64,26 +89,28 @@ eos
end
end
def validate_file(includes_dir)
if File.symlink?(includes_dir)
return "Includes directory '#{includes_dir}' cannot be a symlink"
def validate_dir(dir, safe)
if File.symlink?(dir) && safe
"Includes directory '#{dir}' cannot be a symlink"
end
end
if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
return "Include file '#{@file}' contains invalid characters or sequences"
end
file = File.join(includes_dir, @file)
def validate_file(file, safe)
if !File.exists?(file)
return "Included file #{@file} not found in _includes directory"
elsif File.symlink?(file)
return "The included file '_includes/#{@file}' should not be a symlink"
"Included file '#{@file}' not found in '#{INCLUDES_DIR}' directory"
elsif File.symlink?(file) && safe
"The included file '#{INCLUDES_DIR}/#{@file}' should not be a symlink"
end
end
def blank?
false
end
# This method allows to modify the file content by inheriting from the class.
def source(file)
File.read(file)
end
end
end
end

View File

@ -373,7 +373,7 @@ CONTENT
end
context "with invalid parameter syntax" do
should "throw a SyntaxError" do
should "throw a ArgumentError" do
content = <<CONTENT
---
title: Invalid parameter syntax
@ -381,7 +381,7 @@ title: Invalid parameter syntax
{% include params.html param s="value" %}
CONTENT
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do
assert_raise ArgumentError, 'Did not raise exception on invalid "include" syntax' do
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end
@ -392,7 +392,7 @@ title: Invalid parameter syntax
{% include params.html params="value %}
CONTENT
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do
assert_raise ArgumentError, '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