98 lines
2.5 KiB
Ruby
98 lines
2.5 KiB
Ruby
module Liquid
|
|
|
|
class Block < Tag
|
|
|
|
def parse(tokens)
|
|
@nodelist ||= []
|
|
@nodelist.clear
|
|
|
|
while token = tokens.shift
|
|
|
|
case token
|
|
when /^#{TagStart}/
|
|
if token =~ /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/
|
|
|
|
# if we found the proper block delimitor just end parsing here and let the outer block
|
|
# proceed
|
|
if block_delimiter == $1
|
|
end_tag
|
|
return
|
|
end
|
|
|
|
# fetch the tag from registered blocks
|
|
if tag = Template.tags[$1]
|
|
@nodelist << tag.new($1, $2, tokens)
|
|
else
|
|
# this tag is not registered with the system
|
|
# pass it to the current block for special handling or error reporting
|
|
unknown_tag($1, $2, tokens)
|
|
end
|
|
else
|
|
raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
|
|
end
|
|
when /^#{VariableStart}/
|
|
@nodelist << create_variable(token)
|
|
when ''
|
|
# pass
|
|
else
|
|
@nodelist << token
|
|
end
|
|
end
|
|
|
|
# Make sure that its ok to end parsing in the current block.
|
|
# Effectively this method will throw and exception unless the current block is
|
|
# of type Document
|
|
assert_missing_delimitation!
|
|
end
|
|
|
|
def end_tag
|
|
end
|
|
|
|
def unknown_tag(tag, params, tokens)
|
|
case tag
|
|
when 'else'
|
|
raise SyntaxError, "#{block_name} tag does not expect else tag"
|
|
when 'end'
|
|
raise SyntaxError, "'end' is not a valid delimiter for #{block_name} tags. use #{block_delimiter}"
|
|
else
|
|
raise SyntaxError, "Unknown tag '#{tag}'"
|
|
end
|
|
end
|
|
|
|
def block_delimiter
|
|
"end#{block_name}"
|
|
end
|
|
|
|
def block_name
|
|
@tag_name
|
|
end
|
|
|
|
def create_variable(token)
|
|
token.scan(/^#{VariableStart}(.*)#{VariableEnd}$/) do |content|
|
|
return Variable.new(content.first)
|
|
end
|
|
raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ")
|
|
end
|
|
|
|
def render(context)
|
|
render_all(@nodelist, context)
|
|
end
|
|
|
|
protected
|
|
|
|
def assert_missing_delimitation!
|
|
raise SyntaxError.new("#{block_name} tag was never closed")
|
|
end
|
|
|
|
def render_all(list, context)
|
|
list.collect do |token|
|
|
begin
|
|
token.respond_to?(:render) ? token.render(context) : token
|
|
rescue Exception => e
|
|
context.handle_error(e)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|