Class: Jekyll::Tags::IncludeTag
- Inherits:
-
Liquid::Tag
- Object
- Liquid::Tag
- Jekyll::Tags::IncludeTag
- Defined in:
- lib/liquid/tags/jekyll.rb
Constant Summary collapse
- VALID_SYNTAX =
matches proper params format only 1(key-formatted str) = (2(double-quoted str) or 3(single-quoted str) 4(var-formatted str))
%r! ([\w-]+)\s*=\s* (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([a-z][\w'"\[\]\.-]*)) !x- VARIABLE_SYNTAX =
extracts filename as #variable and k/v pairs as #params
%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/\.-]+$!- INVALID_SEQUENCES =
%r![./]{2,}!
Instance Method Summary collapse
-
#initialize(tag_name, markup, tokens) ⇒ IncludeTag
constructor
A new instance of IncludeTag.
-
#load_cached_partial(path, context) ⇒ Object
# def add_include_to_dependency(site, path, context) if context.registers && context.registers.key?(“path”) site.regenerator.add_dependency( site.in_source_dir(context.registers[“path”]), path ) end end.
-
#locate_include_file(context, file, safe) ⇒ Object
Traverse includes dirs, setting paths for includes.
- #outside_site_source?(path, dir, safe) ⇒ Boolean
- #parse_params(context) ⇒ Object
-
#read_file(file, context) ⇒ Object
This method allows to modify the file content by inheriting from the class.
- #realpath_prefixed_with?(path, dir) ⇒ Boolean
-
#render(context) ⇒ Object
recall/render the included partial and place it in the parent doc.
-
#render_variable(context) ⇒ Object
Express the filename from the variable Passes along the context in which it was called, from the parent file.
- #syntax_example ⇒ Object
-
#tag_includes_dirs(context) ⇒ Object
Array of directories where includes are stored.
- #validate_file_name(file) ⇒ Object
- #validate_params ⇒ Object
Constructor Details
#initialize(tag_name, markup, tokens) ⇒ IncludeTag
Returns a new instance of IncludeTag.
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/liquid/tags/jekyll.rb', line 35 def initialize(tag_name, markup, tokens) super matched = markup.strip.match(VARIABLE_SYNTAX) if matched # include passes filename as variable @file = matched["variable"].strip # The file to include (as a var) @params = matched["params"].strip # The paired vars to load else # if the filename isn't a variable, just grab the first arg as filename and rest as params @file, @params = markup.strip.split(%r!\s+!, 2) end validate_params if @params @tag_name = tag_name end |
Instance Method Details
#load_cached_partial(path, context) ⇒ Object
# def add_include_to_dependency(site, path, context)
if context.registers[:page] && context.registers[:page].key?("path")
site.regenerator.add_dependency(
site.in_source_dir(context.registers[:page]["path"]),
path
)
end
end
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/liquid/tags/jekyll.rb', line 166 def load_cached_partial(path, context) context.registers[:cached_partials] ||= {} cached_partial = context.registers[:cached_partials] if cached_partial.key?(path) cached_partial[path] else unparsed_file = context.registers[:globals] .liquid_renderer .file(path) begin # Cache a version of the cached_partial[path] = unparsed_file.parse(read_file(path, context)) rescue Liquid::Error => e e.template_name = path e.markup_context = "included " if e.markup_context.nil? raise e end end end |
#locate_include_file(context, file, safe) ⇒ Object
Traverse includes dirs, setting paths for includes
120 121 122 123 124 125 126 127 |
# File 'lib/liquid/tags/jekyll.rb', line 120 def locate_include_file(context, file, safe) includes_dirs = ['_templates','_templates/liquid','_templates/liquid/ops','_templates/ops','theme/_includes','theme/_layouts'] includes_dirs.each do |dir| path = File.join(dir.to_s, file.to_s) return path if File.exist?(path) end raise IOError, (file, includes_dirs, safe) end |
#outside_site_source?(path, dir, safe) ⇒ Boolean
187 188 189 |
# File 'lib/liquid/tags/jekyll.rb', line 187 def outside_site_source?(path, dir, safe) safe && !realpath_prefixed_with?(path, dir) end |
#parse_params(context) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/liquid/tags/jekyll.rb', line 52 def parse_params(context) params = {} markup = @params while (match = VALID_SYNTAX.match(markup)) # run until syntax no longer matches parameters markup = markup[match.end(0)..-1] # set val by which group matched in VALID_SYNTAX # either a quoted string (2,3) or a variable (4) value = if match[2] match[2].gsub(%r!\\"!, '"') elsif match[3] match[3].gsub(%r!\\'!, "'") elsif match[4] # val is resolved context var context[match[4]] end params[match[1]] = value # inserts param end params # returns hash for the include scope end |
#read_file(file, context) ⇒ Object
This method allows to modify the file content by inheriting from the class.
198 199 200 |
# File 'lib/liquid/tags/jekyll.rb', line 198 def read_file(file, context) File.read(file) end |
#realpath_prefixed_with?(path, dir) ⇒ Boolean
191 192 193 194 195 |
# File 'lib/liquid/tags/jekyll.rb', line 191 def realpath_prefixed_with?(path, dir) File.exist?(path) && File.realpath(path).start_with?(dir) rescue StandardError false end |
#render(context) ⇒ Object
recall/render the included partial and place it in the parent doc
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/liquid/tags/jekyll.rb', line 130 def render(context) file = render_variable(context) || @file # use parsed variable filename unless passed explicit filename validate_file_name(file) path = locate_include_file(context, file, true) # ensure file exists in safe path return unless path # # ??????? # add_include_to_dependency(site, path, context) # # Load the partial if it's identical to one we've already loaded ??? partial = File.read(path) # reads the template file partial = Liquid::Template.parse(partial) # compiles template # setup and perform render context.stack do # create a hash object for any passed k/v pair args # by parsing passed parameters using the parent file's scope context["include"] = parse_params(context) if @params begin # render the include for output 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 |
#render_variable(context) ⇒ Object
Express the filename from the variable Passes along the context in which it was called, from the parent file
109 110 111 |
# File 'lib/liquid/tags/jekyll.rb', line 109 def render_variable(context) Liquid::Template.parse(@file).render(context) if @file =~ VARIABLE_SYNTAX end |
#syntax_example ⇒ Object
48 49 50 |
# File 'lib/liquid/tags/jekyll.rb', line 48 def syntax_example "{% #{@tag_name} file.ext param='value' param2='value' %}" end |
#tag_includes_dirs(context) ⇒ Object
Array of directories where includes are stored
114 115 116 117 |
# File 'lib/liquid/tags/jekyll.rb', line 114 def tag_includes_dirs(context) # context[:includes_dirs] ['_templates','_templates/liquid','_templates/liquid/ops','theme/_includes','_theme/layouts'] end |
#validate_file_name(file) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/liquid/tags/jekyll.rb', line 72 def validate_file_name(file) if file =~ INVALID_SEQUENCES || 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 |
#validate_params ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/liquid/tags/jekyll.rb', line 87 def validate_params unless @params =~ FULL_VALID_SYNTAX raise ArgumentError, <<-MSG Invalid syntax for include tag: #{@params} Valid syntax: #{syntax_example} MSG end end |