diff --git a/lib/hamlit/concerns/indentable.rb b/lib/hamlit/concerns/indentable.rb index 6a90e4d5..b78b8cd1 100644 --- a/lib/hamlit/concerns/indentable.rb +++ b/lib/hamlit/concerns/indentable.rb @@ -1,12 +1,12 @@ require 'hamlit/concerns/error' module Hamlit + EOF = -1 + module Concerns module Indentable include Concerns::Error - EOF = -1 - def reset_indent @current_indent = 0 end diff --git a/lib/hamlit/parser.rb b/lib/hamlit/parser.rb index 31c22f5d..1d606e0e 100644 --- a/lib/hamlit/parser.rb +++ b/lib/hamlit/parser.rb @@ -47,7 +47,19 @@ module Hamlit # Parse lines in current_indent and return ASTs. def parse_lines ast = [] - while next_indent == @current_indent + loop do + indent = next_indent + if indent != @current_indent + if indent != Hamlit::EOF && indent > @current_indent + ast << [:newline] + ast << syntax_error( + "inconsistent indentation: #{2 * @current_indent} spaces used for indentation, "\ + "but the rest of the document was indented using #{next_line[/\A +/].to_s.length} spaces" + ) + end + break + end + @current_lineno += 1 node = parse_line(current_line) if @outer_removal.include?(@current_indent) && ast.last == [:static, "\n"] diff --git a/spec/hamlit/engine/error_spec.rb b/spec/hamlit/engine/error_spec.rb index d0beb535..cd6dfd3f 100644 --- a/spec/hamlit/engine/error_spec.rb +++ b/spec/hamlit/engine/error_spec.rb @@ -6,5 +6,13 @@ describe Hamlit::Engine do "There's no Ruby code for = to evaluate.", ) end + + it 'raises syntax error for illegal indentation' do + expect { render_string(<<-HAML.unindent) }. + %a + %b + HAML + to raise_error(Hamlit::SyntaxError, 'inconsistent indentation: 2 spaces used for indentation, but the rest of the document was indented using 4 spaces') + end end end