-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
86 changed files
with
20,742 additions
and
35,471 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
module Jekyll | ||
module Tags | ||
class IncludeAbsoluteTagError < StandardError | ||
attr_accessor :path | ||
|
||
def initialize(msg, path) | ||
super(msg) | ||
@path = path | ||
end | ||
end | ||
|
||
class IncludeAbsoluteTag < Liquid::Tag | ||
VALID_SYNTAX = %r! | ||
([\w-]+)\s*=\s* | ||
(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+)) | ||
!x | ||
VARIABLE_SYNTAX = %r! | ||
(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+) | ||
(?<params>.*) | ||
!mx | ||
|
||
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z! | ||
VALID_FILENAME_CHARS = %r!^[\w/\.-]+$! | ||
|
||
def initialize(tag_name, markup, tokens) | ||
super | ||
matched = markup.strip.match(VARIABLE_SYNTAX) | ||
if matched | ||
@file = matched["variable"].strip | ||
@params = matched["params"].strip | ||
else | ||
@file, @params = markup.strip.split(%r!\s+!, 2) | ||
end | ||
validate_params if @params | ||
@tag_name = tag_name | ||
end | ||
|
||
def syntax_example | ||
"{% #{@tag_name} 'file.ext' param='value' param2='value' %}" | ||
end | ||
|
||
def parse_params(context) | ||
params = {} | ||
markup = @params | ||
|
||
while (match = VALID_SYNTAX.match(markup)) | ||
markup = markup[match.end(0)..-1] | ||
|
||
value = if match[2] | ||
match[2].gsub(%r!\\"!, '"') | ||
elsif match[3] | ||
match[3].gsub(%r!\\'!, "'") | ||
elsif match[4] | ||
context[match[4]] | ||
end | ||
|
||
params[match[1]] = value | ||
end | ||
params | ||
end | ||
|
||
def validate_file_name(file) | ||
if file !~ VALID_FILENAME_CHARS | ||
raise ArgumentError, <<-MSG | ||
Invalid syntax for include tag. File contains invalid characters or sequences: | ||
#{file} | ||
Valid syntax: | ||
#{syntax_example} | ||
MSG | ||
end | ||
end | ||
|
||
def validate_params | ||
unless @params =~ FULL_VALID_SYNTAX | ||
raise ArgumentError, <<-MSG | ||
Invalid syntax for include tag: | ||
#{@params} | ||
Valid syntax: | ||
#{syntax_example} | ||
MSG | ||
end | ||
end | ||
|
||
# Grab file read opts in the context | ||
def file_read_opts(context) | ||
context.registers[:site].file_read_opts | ||
end | ||
|
||
# Render the variable if required | ||
def render_variable(context) | ||
if @file =~ VARIABLE_SYNTAX | ||
partial = context.registers[:site] | ||
.liquid_renderer | ||
.file("(variable)") | ||
.parse(@file) | ||
partial.render!(context) | ||
end | ||
end | ||
|
||
def render(context) | ||
site = context.registers[:site] | ||
|
||
file = render_variable(context) || @file | ||
# strip leading and trailing quote's | ||
file = file.gsub!(/\A'|'\Z/, '') | ||
validate_file_name(file) | ||
|
||
source = File.expand_path(context.registers[:site].config['source']).freeze | ||
path = File.join(source, file) | ||
return unless path | ||
|
||
partial = Liquid::Template.parse(read_file(path, context)) | ||
|
||
context.stack do | ||
context["include"] = parse_params(context) if @params | ||
begin | ||
partial.render!(context) | ||
rescue Liquid::Error => e | ||
e.template_name = path | ||
e.markup_context = "included " if e.markup_context.nil? | ||
raise e | ||
end | ||
end | ||
end | ||
|
||
def valid_include_file?(path, dir, safe) | ||
!outside_site_source?(path, dir, safe) && File.file?(path) | ||
end | ||
|
||
def outside_site_source?(path, dir, safe) | ||
safe && !realpath_prefixed_with?(path, dir) | ||
end | ||
|
||
def realpath_prefixed_with?(path, dir) | ||
File.exist?(path) && File.realpath(path).start_with?(dir) | ||
rescue StandardError | ||
false | ||
end | ||
|
||
# This method allows to modify the file content by inheriting from the class. | ||
def read_file(file, context) | ||
File.read(file, **file_read_opts(context)) | ||
end | ||
|
||
private | ||
|
||
def could_not_locate_message(file, includes_dirs, safe) | ||
message = "Could not locate the included file '#{file}' in any of "\ | ||
"#{includes_dirs}. Ensure it exists in one of those directories and" | ||
message + if safe | ||
" is not a symlink as those are not allowed in safe mode." | ||
else | ||
", if it is a symlink, does not point outside your site source." | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
Liquid::Template.register_tag("include_absolute", Jekyll::Tags::IncludeAbsoluteTag) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.