Class: Jekyll::Tags::TemplateBlock
- Inherits:
-
Liquid::Block
- Object
- Liquid::Block
- Jekyll::Tags::TemplateBlock
- Includes:
- Liquid::StandardFilters
- Defined in:
- lib/jekyll/jolt.rb
Constant Summary collapse
- CONTEXT_NAME =
"template"
- CONTEXT_CACHE_NAME =
:cached_templates
- CONTEXT_DATA_NAME =
:template_data
- CONTEXT_SCOPE_NAME =
:template_data_scope
- CONTEXT_STORE_NAME =
:template_data_store
- PROPS_NAME =
"props"
- TEMPLATE_DIR =
"_templates"
- LIQUID_SYNTAX_REGEXP =
/(#{Liquid::QuotedFragment}+)?/
- PROPS_REGEXP =
/#{PROPS_NAME}\./
- WHITESPACE_REGEXP =
%r!^\s*!m
- YAML_FRONT_MATTER_REGEXP =
%r!(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
Instance Method Summary collapse
-
#add_template_to_dependency(path) ⇒ Object
add_template_to_dependency(path = String) source: github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb.
-
#blank? ⇒ Boolean
blank? Description: Override’s Liquid’s default blank checker.
-
#evaluate_props ⇒ Object
evaluate_props Description: Evaluates props that are being passed into the template.
-
#get_front_matter(content) ⇒ Object
get_front_matter(content = String) Returns: A hash of data parsed from the content’s YAML.
-
#initialize(tag_name, markup, tokens) ⇒ TemplateBlock
constructor
initialize Description: Extends Liquid’s default initialize method.
-
#load_cached_template(path) ⇒ Object
load_cached_template(path = String) source: github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb Returns: Liquid template from Jekyll’s cache.
-
#load_template ⇒ Object
load_template() Description: Extends Liquid’s default load_template method.
-
#prop(data, value = "") ⇒ Object
prop(data = Hash, value = String) Description: Returns the props value.
-
#prop?(variable = "") ⇒ Boolean
prop? Description: Determines if the variable is a template.props key Return: Boolean.
-
#render(context) ⇒ Object
render Description: Extends Liquid’s default render method.
-
#render_template(template, content) ⇒ Object
render_template(template = Liquid::Template, content = String) Description: Serializes the context to be rendered by Liquid.
-
#reset_template_data ⇒ Object
reset_template_data() Description: Works with store_template_data.
-
#sanitize(content) ⇒ Object
sanitize(content = String) Description: Renders the content as markdown or HTML based on the “parse” attribute.
-
#store_template_data ⇒ Object
store_template_data() Description: Works with reset_template_data.
-
#strip_front_matter(content) ⇒ Object
strip_front_matter(content = String) Description: Removes the YAML front-matter content.
-
#template_content(template_name) ⇒ Object
template_content(template_name = String) Description: Opens, reads, and returns template content as string.
-
#template_path(path) ⇒ Object
template_path(path = String) Returns: A full file path of the template.
-
#template_store_data(data = {}) ⇒ Object
template_store_data(data = Array) Description: Stores/updates the template data in cache Returns: Hash of the template store data.
-
#unindent(content) ⇒ Object
unindent(content = String) Description: Removes initial indentation.
-
#update_attributes(data) ⇒ Object
update_attributes(data = Hash) Description: Merges data with @attributes.
Constructor Details
#initialize(tag_name, markup, tokens) ⇒ TemplateBlock
initialize Description: Extends Liquid’s default initialize method.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/jekyll/jolt.rb', line 28 def initialize(tag_name, markup, tokens) super if markup =~ LIQUID_SYNTAX_REGEXP @attributes = {} @context = false @id = rand(36**8).to_s(36).freeze @props = {} @sanitize = false @site = false @template_name = $1.freeze @compressor = HtmlCompressor::Compressor.new({ :remove_comments => true }).freeze # Parse parameters # Source: https://gist.github.com/jgatjens/8925165 markup.scan(Liquid::TagAttributes) do |key, value| if (value =~ PROPS_REGEXP) != nil @props[key] = @attributes[key] = value else @props[key] = @attributes[key] = Liquid::Expression.parse(value) end end end end |
Instance Method Details
#add_template_to_dependency(path) ⇒ Object
add_template_to_dependency(path = String) source: github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb
231 232 233 234 235 236 237 238 |
# File 'lib/jekyll/jolt.rb', line 231 def add_template_to_dependency(path) if @context.registers[:page] && @context.registers[:page].key?("path") @site.regenerator.add_dependency( @site.in_source_dir(@context.registers[:page]["path"]), template_path(path) ) end end |
#blank? ⇒ Boolean
blank? Description: Override’s Liquid’s default blank checker. This allows for templates to be used without passing inner content.
59 60 61 |
# File 'lib/jekyll/jolt.rb', line 59 def blank? false end |
#evaluate_props ⇒ Object
evaluate_props Description: Evaluates props that are being passed into the template.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/jekyll/jolt.rb', line 101 def evaluate_props() store = @context.registers[CONTEXT_STORE_NAME] data = store[@id] index = data[:index] if (index > 0) parent = store[store.keys[index - 1]] # Update the data scope @context[CONTEXT_SCOPE_NAME] = parent data.each do |key, value| if prop?(value) value = prop(parent, value) if value @props[key] = value end end end end end |
#get_front_matter(content) ⇒ Object
get_front_matter(content = String) Returns: A hash of data parsed from the content’s YAML
321 322 323 324 325 326 327 328 329 330 |
# File 'lib/jekyll/jolt.rb', line 321 def get_front_matter(content) # Strip leading white-spaces content = unindent(content) if content =~ YAML_FRONT_MATTER_REGEXP front_matter = Regexp.last_match(0) values = SafeYAML.load(front_matter) else Hash.new end end |
#load_cached_template(path) ⇒ Object
load_cached_template(path = String) source: github.com/jekyll/jekyll/blob/e509cf2139d1a7ee11090b09721344608ecf48f6/lib/jekyll/tags/include.rb Returns: Liquid template from Jekyll’s cache.
243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/jekyll/jolt.rb', line 243 def load_cached_template(path) @context.registers[CONTEXT_CACHE_NAME] ||= {} cached_templates = @context.registers[CONTEXT_CACHE_NAME] unless cached_templates.key?(path) cached_templates[path] = load_template() end template = cached_templates[path] update_attributes(template["data"]) template["template"] end |
#load_template ⇒ Object
load_template() Description: Extends Liquid’s default load_template method. Also provides extra enhancements:
-
parses and sets template front-matter content
Returns: Template class
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/jekyll/jolt.rb', line 274 def load_template() file = @site .liquid_renderer .file(template_path(@template_name)) content = template_content(@template_name) template = Hash.new data = get_front_matter(content) markup = strip_front_matter(content) if content template["data"] = data template["template"] = file.parse(markup) template end end |
#prop(data, value = "") ⇒ Object
prop(data = Hash, value = String) Description: Returns the props value
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/jekyll/jolt.rb', line 87 def prop(data, value = "") index = data[:index] value = data[value.gsub(PROPS_REGEXP, "")] if value and prop?(value) and index > 0 store = @context.registers[CONTEXT_STORE_NAME] previous_scope = store[store.keys[index - 1]] prop(previous_scope, value) else value end end |
#prop?(variable = "") ⇒ Boolean
prop? Description: Determines if the variable is a template.props key Return: Boolean
81 82 83 |
# File 'lib/jekyll/jolt.rb', line 81 def prop?(variable = "") (variable =~ PROPS_REGEXP) != nil end |
#render(context) ⇒ Object
render Description: Extends Liquid’s default render method. This method also adds additional features:
-
YAML front-matter parsing and handling
-
properly handles indentation and whitespace (resolves rendering issues)
-
ability to parse content as markdown vs. html
-
supports custom attributes to be used in template
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/jekyll/jolt.rb', line 128 def render(context) @context = context @site = @context.registers[:site] template_store_data(@attributes) # This allows for Jekyll intelligently re-render markup during # incremental builds. add_template_to_dependency(@template_name) # Loading the template from cache/template directory template = load_cached_template(@template_name) # Props must be evaluated before super is initialized. # This allows for props to be evaluated before they're parsed by Liquid. evaluate_props() content = super # Return the parsed/normalized content render_template(template, content) end |
#render_template(template, content) ⇒ Object
render_template(template = Liquid::Template, content = String) Description: Serializes the context to be rendered by Liquid. Also resets the context to ensure template data doesn’t leak from the scope. Returns: String
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/jekyll/jolt.rb', line 155 def render_template(template, content) # Define the default template attributes # Source: # https://github.com/Shopify/liquid/blob/9a7778e52c37965f7b47673da09cfb82856a6791/lib/liquid/tags/include.rb @context[CONTEXT_NAME] = Hash.new # Add props update_attributes(@props) # Parse and extend template's front-matter with content front-matter update_attributes(get_front_matter(content)) # Update the template's store data template_store_data(@attributes) # Setting context's template attributes from @attributes # This allows for @attributes to be used within the template as # {{ template.atttribute_name }} if @attributes.length @attributes.each do |key, value| val = @context.evaluate(value) @context[CONTEXT_NAME][key] = val # Adjust sanitize if parse: html if (key == "parse") && (val == "html") @sanitize = true end end end # puts @attributes @context[CONTEXT_NAME]["content"] = sanitize(strip_front_matter(content)) store_template_data() content = @compressor.compress(template.render(@context)) reset_template_data() content end |
#reset_template_data ⇒ Object
reset_template_data() Description: Works with store_template_data. This is a work-around to ensure data stays in scope and isn’t leaked from child->parent template.
215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/jekyll/jolt.rb', line 215 def reset_template_data() @context.registers[CONTEXT_DATA_NAME] ||= {} store = @context.registers[CONTEXT_DATA_NAME] if store.keys.length if store.keys[0] == @id # Resets template data @context.registers[CONTEXT_DATA_NAME] = false @context.registers[CONTEXT_SCOPE_NAME] = false else @context[CONTEXT_NAME] = store[store.keys[0]] end end end |
#sanitize(content) ⇒ Object
sanitize(content = String) Description: Renders the content as markdown or HTML based on the “parse” attribute. Returns: Content (string).
296 297 298 299 300 301 302 303 |
# File 'lib/jekyll/jolt.rb', line 296 def sanitize(content) unless @sanitize converter = @site.find_converter_instance(::Jekyll::Converters::Markdown) converter.convert(unindent(content)) else unindent(content) end end |
#store_template_data ⇒ Object
store_template_data() Description: Works with reset_template_data. This is a work-around to ensure data stays in scope and isn’t leaked from child->parent template.
204 205 206 207 208 209 |
# File 'lib/jekyll/jolt.rb', line 204 def store_template_data() @context.registers[CONTEXT_DATA_NAME] ||= {} unless @context.registers[CONTEXT_DATA_NAME].key?(@id) @context.registers[CONTEXT_DATA_NAME][@id] = @context[CONTEXT_NAME] end end |
#strip_front_matter(content) ⇒ Object
strip_front_matter(content = String) Description: Removes the YAML front-matter content. Returns: Template content, with front-matter removed.
335 336 337 338 339 340 341 342 343 344 |
# File 'lib/jekyll/jolt.rb', line 335 def strip_front_matter(content) # Strip leading white-spaces content = unindent(content) if content =~ YAML_FRONT_MATTER_REGEXP front_matter = Regexp.last_match(0) # Returns content with stripped front-matter content.gsub!(front_matter, "") end content end |
#template_content(template_name) ⇒ Object
template_content(template_name = String) Description: Opens, reads, and returns template content as string. Returns: Template content
265 266 267 |
# File 'lib/jekyll/jolt.rb', line 265 def template_content(template_name) File.read(template_path(template_name).strip) end |
#template_path(path) ⇒ Object
template_path(path = String) Returns: A full file path of the template
258 259 260 |
# File 'lib/jekyll/jolt.rb', line 258 def template_path(path) File.join(@site.source.to_s, TEMPLATE_DIR, path.to_s) end |
#template_store_data(data = {}) ⇒ Object
template_store_data(data = Array) Description: Stores/updates the template data in cache Returns: Hash of the template store data
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/jekyll/jolt.rb', line 66 def template_store_data(data = {}) @context.registers[CONTEXT_STORE_NAME] ||= {} unless @context.registers[CONTEXT_STORE_NAME].key?(@id) @context.registers[CONTEXT_STORE_NAME][@id] = { "id": @id, "index": @context.registers[CONTEXT_STORE_NAME].length, "template_name": @template_name } end @context.registers[CONTEXT_STORE_NAME][@id] = @context.registers[CONTEXT_STORE_NAME][@id].merge(data) end |
#unindent(content) ⇒ Object
unindent(content = String) Description: Removes initial indentation. Returns: Content (string).
308 309 310 311 312 313 314 315 316 317 |
# File 'lib/jekyll/jolt.rb', line 308 def unindent(content) # Remove initial whitespace content.gsub!(/\A^\s*\n/, "") # Remove indentations if content =~ WHITESPACE_REGEXP indentation = Regexp.last_match(0).length content.gsub!(/^\ {#{indentation}}/, "") end content end |
#update_attributes(data) ⇒ Object
update_attributes(data = Hash) Description: Merges data with @attributes.
194 195 196 197 198 |
# File 'lib/jekyll/jolt.rb', line 194 def update_attributes(data) if data @attributes.merge!(data) end end |