Give a more descriptive error for templates with invalid byte sequences in 1.9.

This commit is contained in:
Nathan Weizenbaum 2009-09-23 15:32:08 -07:00
parent 60f9344b0d
commit 2c060d7f74
7 changed files with 75 additions and 1 deletions

View File

@ -17,6 +17,12 @@ in the generated class and id.
The Haml executable now has a `--double-quote-attributes` option (short form: `-q`)
that causes attributes to use a double-quote mark rather than single-quote.
### Ruby 1.9 Support
Haml now produces more descriptive errors when given a template
with invalid byte sequences for that template's encoding,
including the line number and the offending character.
## [2.2.4](http://github.com/nex3/haml/commit/2.2.4)
* Allow `end` to be used for silent script when it's followed by code.

View File

@ -16,6 +16,12 @@ In addition, when the `sass` executable encounters an error,
it now prints the filename where the error occurs,
as well as a backtrace of Sass imports.
### Ruby 1.9 Support
Sass now produces more descriptive errors when given a template
with invalid byte sequences for that template's encoding,
including the line number and the offending character.
### `css2sass` Error Handling
Several bug fixes and minor improvements have been made, including:

View File

@ -96,6 +96,8 @@ module Haml
@options[:encoding] = @options[:encoding].name
end
check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
# :eod is a special end-of-document marker
@template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
@template_index = 0
@ -111,7 +113,9 @@ module Haml
precompile
rescue Haml::Error => e
e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index
if @index || e.line
e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}"
end
raise
end

View File

@ -129,6 +129,22 @@ module Haml
Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9
end
def check_encoding(str)
return if ruby1_8?
return if str.valid_encoding?
encoding = str.encoding
newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
str.force_encoding("binary").split(newlines).each_with_index do |line, i|
begin
line.encode(encoding)
rescue Encoding::UndefinedConversionError => e
yield <<MSG.rstrip, i + 1
Invalid #{encoding.name} character #{e.error_char.dump}
MSG
end
end
end
# Checks to see if a class has a given method.
# For example:
#

View File

@ -156,6 +156,8 @@ module Sass
# @return [Sass::Tree::Node] The root of the parse tree.
# @raise [Sass::SyntaxError] if there's an error in the document
def to_tree
check_encoding(@template) {|msg, line| raise Sass::SyntaxError.new(msg, :line => line)}
root = Tree::RootNode.new(@template)
append_children(root, tree(tabulate(@template)).first, true)
root.options = @options

View File

@ -1061,6 +1061,24 @@ HAML
o.render
end
end
def test_encoding_error
render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
assert(false, "Expected exception")
rescue Haml::Error => e
assert_equal(3, e.line)
assert_equal('Invalid UTF-8 character "\xFE"', e.message)
end
def test_ascii_incompatible_encoding_error
template = "foo\nbar\nb_z".encode("utf-16le")
template[9] = "\xFE".force_encoding("utf-16le")
render(template)
assert(false, "Expected exception")
rescue Haml::Error => e
assert_equal(3, e.line)
assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
end
end
private

View File

@ -901,6 +901,28 @@ a
SASS
end
# Encodings
unless Haml::Util.ruby1_8?
def test_encoding_error
render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
assert(false, "Expected exception")
rescue Sass::SyntaxError => e
assert_equal(3, e.sass_line)
assert_equal('Invalid UTF-8 character "\xFE"', e.message)
end
def test_ascii_incompatible_encoding_error
template = "foo\nbar\nb_z".encode("utf-16le")
template[9] = "\xFE".force_encoding("utf-16le")
render(template)
assert(false, "Expected exception")
rescue Sass::SyntaxError => e
assert_equal(3, e.sass_line)
assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
end
end
private
def render(sass, options = {})