mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Unify filter and haml_comment parsing
* Fix bug in filter parsing A filter with no associated block wasn't being parsed properly, causing issues in any following code. * Dispatch haml_comment direct from process_line rather than silent_script. Syntactically it is a script with a comment, but the way it is handled is sufficiently different (especially with a block) to be dispatched as its own type. * Unify how haml_comment and filters are handled in the parser. Filters and comments with blocks are basically the same, the block isn't parsed (and so can have arbitrary indentation), so combine how they are handled in the parser. Remove special handling for haml_comment (e.g. @haml_comment variable), it now uses the same as filters (e.g. @flat). This means the text of the comment is now included in the parse tree (previously it was omitted). Fixes #840 and #838 (the latter more as a side effect).
This commit is contained in:
parent
5163269eb2
commit
b09e4589ad
2 changed files with 55 additions and 16 deletions
|
@ -90,7 +90,6 @@ module Haml
|
|||
|
||||
def initialize(template, options)
|
||||
@options = options
|
||||
@flat = false
|
||||
# Record the indent levels of "if" statements to validate the subsequent
|
||||
# elsif and else statements are indented at the appropriate level.
|
||||
@script_level_stack = []
|
||||
|
@ -109,7 +108,8 @@ module Haml
|
|||
|
||||
def parse
|
||||
@root = @parent = ParseNode.new(:root)
|
||||
@haml_comment = false
|
||||
@flat = false
|
||||
@filter_buffer = nil
|
||||
@indentation = nil
|
||||
@line = next_line
|
||||
|
||||
|
@ -129,13 +129,13 @@ module Haml
|
|||
end
|
||||
|
||||
@tab_up = nil
|
||||
process_line(@line) unless @line.text.empty? || @haml_comment
|
||||
if @parent.type != :haml_comment && (block_opened? || @tab_up)
|
||||
process_line(@line) unless @line.text.empty?
|
||||
if block_opened? || @tab_up
|
||||
@template_tabs += 1
|
||||
@parent = @parent.children.last
|
||||
end
|
||||
|
||||
if !@haml_comment && !flat? && @next_line.tabs - @line.tabs > 1
|
||||
if !flat? && @next_line.tabs - @line.tabs > 1
|
||||
raise SyntaxError.new(Error.message(:deeper_indenting, @next_line.tabs - @line.tabs), @next_line.index)
|
||||
end
|
||||
|
||||
|
@ -243,7 +243,9 @@ module Haml
|
|||
line.text = line.text[1..-1]
|
||||
push script(line)
|
||||
when FLAT_SCRIPT; push flat_script(line.strip!(1))
|
||||
when SILENT_SCRIPT; push silent_script(line)
|
||||
when SILENT_SCRIPT
|
||||
return push haml_comment(line.text[2..-1]) if line.text[1] == SILENT_COMMENT
|
||||
push silent_script(line)
|
||||
when FILTER; push filter(line.text[1..-1].downcase)
|
||||
when DOCTYPE
|
||||
return push doctype(line.text) if line.text[0, 3] == '!!!'
|
||||
|
@ -301,8 +303,6 @@ module Haml
|
|||
end
|
||||
|
||||
def silent_script(line)
|
||||
return haml_comment(line.text[2..-1]) if line.text[1] == SILENT_COMMENT
|
||||
|
||||
raise SyntaxError.new(Error.message(:no_end), line.index) if line.text[1..-1].strip == 'end'
|
||||
|
||||
line = handle_ruby_multiline(line)
|
||||
|
@ -343,7 +343,15 @@ module Haml
|
|||
end
|
||||
|
||||
def haml_comment(text)
|
||||
@haml_comment = block_opened?
|
||||
if filter_opened?
|
||||
@flat = true
|
||||
@filter_buffer = String.new
|
||||
@filter_buffer << "#{text}\n" unless text.empty?
|
||||
text = @filter_buffer
|
||||
# If we don't know the indentation by now, it'll be set in Line#tabs
|
||||
@flat_spaces = @indentation * (@template_tabs+1) if @indentation
|
||||
end
|
||||
|
||||
ParseNode.new(:haml_comment, @line.index + 1, :text => text)
|
||||
end
|
||||
|
||||
|
@ -469,10 +477,9 @@ module Haml
|
|||
def filter(name)
|
||||
raise Error.new(Error.message(:invalid_filter_name, name)) unless name =~ /^\w+$/
|
||||
|
||||
@filter_buffer = String.new
|
||||
|
||||
if filter_opened?
|
||||
@flat = true
|
||||
@filter_buffer = String.new
|
||||
# If we don't know the indentation by now, it'll be set in Line#tabs
|
||||
@flat_spaces = @indentation * (@template_tabs+1) if @indentation
|
||||
end
|
||||
|
@ -487,13 +494,17 @@ module Haml
|
|||
end
|
||||
|
||||
def close_filter(_)
|
||||
@flat = false
|
||||
@flat_spaces = nil
|
||||
@filter_buffer = nil
|
||||
close_flat_section
|
||||
end
|
||||
|
||||
def close_haml_comment(_)
|
||||
@haml_comment = false
|
||||
close_flat_section
|
||||
end
|
||||
|
||||
def close_flat_section
|
||||
@flat = false
|
||||
@flat_spaces = nil
|
||||
@filter_buffer = nil
|
||||
end
|
||||
|
||||
def close_silent_script(node)
|
||||
|
@ -772,7 +783,7 @@ module Haml
|
|||
# Same semantics as block_opened?, except that block_opened? uses Line#tabs,
|
||||
# which doesn't interact well with filter lines
|
||||
def filter_opened?
|
||||
@next_line.full =~ (@indentation ? /^#{@indentation * @template_tabs}/ : /^\s/)
|
||||
@next_line.full =~ (@indentation ? /^#{@indentation * (@template_tabs + 1)}/ : /^\s/)
|
||||
end
|
||||
|
||||
def flat?
|
||||
|
|
|
@ -133,6 +133,34 @@ module Haml
|
|||
end
|
||||
end
|
||||
|
||||
test "empty filter doesn't hide following lines" do
|
||||
root = parse "%p\n :plain\n %p\n"
|
||||
p_element = root.children[0]
|
||||
assert_equal 2, p_element.children.size
|
||||
assert_equal :filter, p_element.children[0].type
|
||||
assert_equal :tag, p_element.children[1].type
|
||||
end
|
||||
|
||||
# Previously blocks under a haml_comment would be rejected if any line was
|
||||
# indented by a value that wasn't a multiple of the document indentation.
|
||||
test "haml_comment accepts any indentation in content" do
|
||||
begin
|
||||
parse "-\#\n Indented two spaces\n Indented three spaces"
|
||||
rescue Haml::SyntaxError
|
||||
flunk "haml_comment should accept any combination of indentation"
|
||||
end
|
||||
end
|
||||
|
||||
test "block haml_comment includes text" do
|
||||
root = parse "-#\n Hello\n Hello\n"
|
||||
assert_equal "Hello\n Hello\n", root.children[0].value[:text]
|
||||
end
|
||||
|
||||
test "block haml_comment includes first line if present" do
|
||||
root = parse "-# First line\n Hello\n Hello\n"
|
||||
assert_equal " First line\nHello\n Hello\n", root.children[0].value[:text]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse(haml, options = nil)
|
||||
|
|
Loading…
Add table
Reference in a new issue