diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index 9d7b752..e0ad332 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -10,7 +10,7 @@ module Liquid end def parse(tokens) - @body = BlockBody.new + @body = new_body while parse_body(@body, tokens) end end @@ -55,8 +55,14 @@ module Liquid @block_delimiter ||= "end#{block_name}" end - protected + private + # @api public + def new_body + parse_context.new_block_body + end + + # @api public def parse_body(body, tokens) if parse_context.depth >= MAX_DEPTH raise StackLevelError, "Nesting too deep" diff --git a/lib/liquid/block_body.rb b/lib/liquid/block_body.rb index 18b3062..e2ebf7a 100644 --- a/lib/liquid/block_body.rb +++ b/lib/liquid/block_body.rb @@ -58,6 +58,28 @@ module Liquid Block.raise_unknown_tag(tag, 'liquid', '%}', parse_context) end + # @api private + 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 + 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 + def self.render_node(context, output, node) + node.render_to_output_buffer(context, output) + rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e + context.handle_error(e, node.line_number) + rescue MemoryError + raise + rescue ::StandardError => e + line_number = node.is_a?(String) ? nil : node.line_number + output << context.handle_error(e, line_number) + end + private def parse_liquid_tag(markup, parse_context) liquid_tag_tokenizer = Tokenizer.new(markup, 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| @@ -74,7 +96,7 @@ module Liquid when token.start_with?(TAGSTART) whitespace_handler(token, parse_context) unless token =~ FullToken - raise_missing_tag_terminator(token, parse_context) + BlockBody.raise_missing_tag_terminator(token, parse_context) end tag_name = Regexp.last_match(2) markup = Regexp.last_match(4) @@ -179,14 +201,7 @@ module Liquid private def render_node(context, output, node) - node.render_to_output_buffer(context, output) - rescue UndefinedVariable, UndefinedDropMethod, UndefinedFilter => e - context.handle_error(e, node.line_number) - rescue MemoryError - raise - rescue ::StandardError => e - line_number = node.is_a?(String) ? nil : node.line_number - output << context.handle_error(e, line_number) + BlockBody.render_node(context, output, node) end def create_variable(token, parse_context) @@ -194,15 +209,17 @@ module Liquid markup = content.first return Variable.new(markup, parse_context) end - raise_missing_variable_terminator(token, parse_context) + BlockBody.raise_missing_variable_terminator(token, parse_context) end + # @deprecated Use {.raise_missing_tag_terminator} instead def raise_missing_tag_terminator(token, parse_context) - raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect) + BlockBody.raise_missing_tag_terminator(token, parse_context) end + # @deprecated Use {.raise_missing_variable_terminator} instead def raise_missing_variable_terminator(token, parse_context) - raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect) + BlockBody.raise_missing_variable_terminator(token, parse_context) end def registered_tags diff --git a/lib/liquid/document.rb b/lib/liquid/document.rb index e160886..e0818ec 100644 --- a/lib/liquid/document.rb +++ b/lib/liquid/document.rb @@ -1,15 +1,26 @@ # frozen_string_literal: true module Liquid - class Document < BlockBody + class Document def self.parse(tokens, parse_context) - doc = new + doc = new(parse_context) doc.parse(tokens, parse_context) doc end + attr_reader :parse_context, :body + + def initialize(parse_context) + @parse_context = parse_context + @body = new_body + end + + def nodelist + @body.nodelist + end + def parse(tokens, parse_context) - super do |end_tag_name, _end_tag_params| + @body.parse(tokens, parse_context) do |end_tag_name, _end_tag_params| unknown_tag(end_tag_name, parse_context) if end_tag_name end rescue SyntaxError => e @@ -25,5 +36,19 @@ module Liquid raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag) end end + + def render_to_output_buffer(context, output) + @body.render_to_output_buffer(context, output) + end + + def render(context) + @body.render(context) + end + + private + + def new_body + parse_context.new_block_body + end end end diff --git a/lib/liquid/parse_context.rb b/lib/liquid/parse_context.rb index 83d4e0f..4724ec2 100644 --- a/lib/liquid/parse_context.rb +++ b/lib/liquid/parse_context.rb @@ -19,6 +19,10 @@ module Liquid @options[option_key] end + def new_block_body + Liquid::BlockBody.new + end + def partial=(value) @partial = value @options = value ? partial_options : @template_options diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index f6e0e70..0b48bf1 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -19,7 +19,7 @@ module Liquid end def parse(tokens) - body = BlockBody.new + body = new_body body = @blocks.last.attachment while parse_body(body, tokens) if blank? @blocks.each { |condition| condition.attachment.remove_blank_strings } @@ -59,7 +59,7 @@ module Liquid private def record_when_condition(markup) - body = BlockBody.new + body = new_body while markup unless markup =~ WhenSyntax @@ -80,7 +80,7 @@ module Liquid end block = ElseCondition.new - block.attach(BlockBody.new) + block.attach(new_body) @blocks << block end diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index bb03392..6f66ebd 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -54,7 +54,7 @@ module Liquid super @from = @limit = nil parse_with_selected_parser(markup) - @for_block = BlockBody.new + @for_block = new_body @else_block = nil end @@ -74,7 +74,7 @@ module Liquid def unknown_tag(tag, markup, tokens) return super unless tag == 'else' - @else_block = BlockBody.new + @else_block = new_body end def render_to_output_buffer(context, output) diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index 43c8b0a..1b4de55 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -64,7 +64,7 @@ module Liquid end @blocks.push(block) - block.attach(BlockBody.new) + block.attach(new_body) end def lax_parse(markup)