class Liquid::BlockBody
Constants
- ContentOfVariable
- FullToken
- FullTokenPossiblyInvalid
- LiquidTagToken
- TAGSTART
- VARSTART
- WhitespaceOrNothing
Attributes
Public Class Methods
Source
# File lib/liquid/block_body.rb, line 17 def initialize @nodelist = [] @blank = true end
Source
# File lib/liquid/block_body.rb, line 76 def self.raise_missing_tag_terminator(token, parse_context) raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect) end
@api private
Source
# File lib/liquid/block_body.rb, line 81 def self.raise_missing_variable_terminator(token, parse_context) raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect) end
@api private
Source
# File lib/liquid/block_body.rb, line 86 def self.render_node(context, output, node) node.render_to_output_buffer(context, output) rescue => exc blank_tag = !node.instance_of?(Variable) && node.blank? rescue_render_node(context, output, node.line_number, exc, blank_tag) end
@api private
Source
# File lib/liquid/block_body.rb, line 94 def self.rescue_render_node(context, output, line_number, exc, blank_tag) case exc when MemoryError raise when UndefinedVariable, UndefinedDropMethod, UndefinedFilter context.handle_error(exc, line_number) else error_message = context.handle_error(exc, line_number) unless blank_tag # conditional for backwards compatibility output << error_message end end end
@api private
Source
# File lib/liquid/block_body.rb, line 71 def self.unknown_tag_in_liquid_tag(tag, parse_context) Block.raise_unknown_tag(tag, 'liquid', '%}', parse_context) end
@api private
Public Instance Methods
Source
# File lib/liquid/block_body.rb, line 34 def freeze @nodelist.freeze super end
Calls superclass method
Source
# File lib/liquid/block_body.rb, line 22 def parse(tokenizer, parse_context, &block) raise FrozenError, "can't modify frozen Liquid::BlockBody" if frozen? parse_context.line_number = tokenizer.line_number if tokenizer.for_liquid_tag parse_for_liquid_tag(tokenizer, parse_context, &block) else parse_for_document(tokenizer, parse_context, &block) end end
Source
# File lib/liquid/block_body.rb, line 209 def remove_blank_strings raise "remove_blank_strings only support being called on a blank block body" unless @blank @nodelist.reject! { |node| node.instance_of?(String) } end
Remove blank strings in the block body for a control flow tag (e.g. ‘if`, `for`, `case`, `unless`) with a blank body.
For
example, in a conditional assignment like the following
“‘ {% if size > max_size %}
{% assign size = max_size %}
{% endif %} “‘
we assume the intention wasn’t to output the blank spaces in the ‘if` tag’s block body, so this method will remove them to reduce the render output size.
Note that it is now preferred to use the ‘liquid` tag for this use case.
Source
# File lib/liquid/block_body.rb, line 214 def render(context) render_to_output_buffer(context, +'') end
Source
# File lib/liquid/block_body.rb, line 218 def render_to_output_buffer(context, output) freeze unless frozen? context.resource_limits.increment_render_score(@nodelist.length) idx = 0 while (node = @nodelist[idx]) if node.instance_of?(String) output << node else render_node(context, output, node) # If we get an Interrupt that means the block must stop processing. An # Interrupt is any command that stops block execution such as {% break %} # or {% continue %}. These tags may also occur through Block or Include tags. break if context.interrupt? # might have happened in a for-block end idx += 1 context.resource_limits.increment_write_score(output) end output end
Source
# File lib/liquid/block_body.rb, line 176 def whitespace_handler(token, parse_context) if token[2] == WhitespaceControl previous_token = @nodelist.last if previous_token.is_a?(String) first_byte = previous_token.getbyte(0) previous_token.rstrip! if previous_token.empty? && parse_context[:bug_compatible_whitespace_trimming] && first_byte previous_token << first_byte end end end parse_context.trim_whitespace = (token[-3] == WhitespaceControl) end
Private Instance Methods
Source
# File lib/liquid/block_body.rb, line 248 def create_variable(token, parse_context) if token.end_with?("}}") i = 2 i = 3 if token[i] == "-" parse_end = token.length - 3 parse_end -= 1 if token[parse_end] == "-" markup_end = parse_end - i + 1 markup = markup_end <= 0 ? "" : token.slice(i, markup_end) return Variable.new(markup, parse_context) end BlockBody.raise_missing_variable_terminator(token, parse_context) end
Source
# File lib/liquid/block_body.rb, line 119 def handle_invalid_tag_token(token, parse_context) if token.end_with?('%}') yield token, token else BlockBody.raise_missing_tag_terminator(token, parse_context) end end
Source
# File lib/liquid/block_body.rb, line 127 def parse_for_document(tokenizer, parse_context, &block) while (token = tokenizer.shift) next if token.empty? case when token.start_with?(TAGSTART) whitespace_handler(token, parse_context) unless token =~ FullToken return handle_invalid_tag_token(token, parse_context, &block) end tag_name = Regexp.last_match(2) markup = Regexp.last_match(4) if parse_context.line_number # newlines inside the tag should increase the line number, # particularly important for multiline {% liquid %} tags parse_context.line_number += Regexp.last_match(1).count("\n") + Regexp.last_match(3).count("\n") end if tag_name == 'liquid' parse_liquid_tag(markup, parse_context) next end unless (tag = parse_context.environment.tag_for_name(tag_name)) # end parsing if we reach an unknown tag and let the caller decide # determine how to proceed return yield tag_name, markup end new_tag = tag.parse(tag_name, markup, tokenizer, parse_context) @blank &&= new_tag.blank? @nodelist << new_tag when token.start_with?(VARSTART) whitespace_handler(token, parse_context) @nodelist << create_variable(token, parse_context) @blank = false else if parse_context.trim_whitespace token.lstrip! end parse_context.trim_whitespace = false @nodelist << token @blank &&= token.match?(WhitespaceOrNothing) end parse_context.line_number = tokenizer.line_number end yield nil, nil end
Source
# File lib/liquid/block_body.rb, line 39 def parse_for_liquid_tag(tokenizer, parse_context) while (token = tokenizer.shift) unless token.empty? || token.match?(WhitespaceOrNothing) unless token =~ LiquidTagToken # line isn't empty but didn't match tag syntax, yield and let the # caller raise a syntax error return yield token, token end tag_name = Regexp.last_match(1) markup = Regexp.last_match(2) if tag_name == 'liquid' parse_context.line_number -= 1 next parse_liquid_tag(markup, parse_context) end unless (tag = parse_context.environment.tag_for_name(tag_name)) # end parsing if we reach an unknown tag and let the caller decide # determine how to proceed return yield tag_name, markup end new_tag = tag.parse(tag_name, markup, tokenizer, parse_context) @blank &&= new_tag.blank? @nodelist << new_tag end parse_context.line_number = tokenizer.line_number end yield nil, nil end
Source
# File lib/liquid/block_body.rb, line 108 def parse_liquid_tag(markup, parse_context) liquid_tag_tokenizer = parse_context.new_tokenizer( markup, start_line_number: parse_context.line_number, for_liquid_tag: true ) parse_for_liquid_tag(liquid_tag_tokenizer, parse_context) do |end_tag_name, _end_tag_markup| if end_tag_name BlockBody.unknown_tag_in_liquid_tag(end_tag_name, parse_context) end end end
Source
# File lib/liquid/block_body.rb, line 264 def raise_missing_tag_terminator(token, parse_context) BlockBody.raise_missing_tag_terminator(token, parse_context) end
@deprecated Use {.raise_missing_tag_terminator} instead
Source
# File lib/liquid/block_body.rb, line 269 def raise_missing_variable_terminator(token, parse_context) BlockBody.raise_missing_variable_terminator(token, parse_context) end
@deprecated Use {.raise_missing_variable_terminator} instead
Source
# File lib/liquid/block_body.rb, line 244 def render_node(context, output, node) BlockBody.render_node(context, output, node) end