Module: Haml::Util
Overview
A module containing various useful functions.
Class Method Summary collapse
-
.escape_html_safe(html)
TODO: Remove unescape_interpolation’s workaround and get rid of
respond_to?
.
Instance Method Summary collapse
-
#balance(scanner, start, finish, count = 0) ⇒ (String, String)
Moves a scanner through a balanced pair of characters.
-
#check_encoding(str) {|msg| ... } ⇒ String
Checks that the encoding of a string is valid and cleans up potential encoding gotchas like the UTF-8 BOM.
-
#check_haml_encoding(str) {|msg| ... } ⇒ String
Like #check_encoding, but also checks for a Ruby-style
-# coding:
comment at the beginning of the template and uses that encoding if it exists. -
#contains_interpolation?(str) ⇒ Boolean
-
#handle_interpolation(str) {|scan| ... } ⇒ String
Scans through a string looking for the interoplation-opening
#{
and, when it’s found, yields the scanner to the calling code so it can handle it properly. -
#human_indentation(indentation) ⇒ String
Formats a string for use in error messages about indentation.
-
#inspect_obj(obj) ⇒ String
Like
Object#inspect
, but preserves non-ASCII characters rather than escaping them. -
#rails_xss_safe? ⇒ Boolean
Whether or not ActionView’s XSS protection is available and enabled, as is the default for Rails 3.0+, and optional for version 2.3.5+.
-
#silence_warnings { ... }
Silence all output to STDERR within a block.
-
#unescape_interpolation(str, escape_html = nil)
Class Method Details
.escape_html_safe(html)
TODO: Remove unescape_interpolation’s workaround and get rid of respond_to?
.
30 31 32 33 |
# File 'lib/haml/util.rb', line 30
def self.escape_html_safe(html)
html = html.to_s
(html.respond_to?(:html_safe?) && html.html_safe?) ? html : escape_html(html)
end
|
Instance Method Details
#balance(scanner, start, finish, count = 0) ⇒ (String, String)
Moves a scanner through a balanced pair of characters. For example:
Foo (Bar (Baz bang) bop) (Bang (bop bip))
^ ^
from to
172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/haml/util.rb', line 172
def balance(scanner, start, finish, count = 0)
str = ''.dup
scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
while scanner.scan(regexp)
str << scanner.matched
count += 1 if scanner.matched[-1] == start
count -= 1 if scanner.matched[-1] == finish
return [str.strip, scanner.rest] if count == 0
end
end
|
#check_encoding(str) {|msg| ... } ⇒ String
Checks that the encoding of a string is valid and cleans up potential encoding gotchas like the UTF-8 BOM. If it’s not, yields an error string describing the invalid character and the line on which it occurs.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/haml/util.rb', line 66
def check_encoding(str)
if str.valid_encoding?
# Get rid of the Unicode BOM if possible
# Shortcut for UTF-8 which might be the majority case
if str.encoding == Encoding::UTF_8
return str.gsub(/\A\uFEFF/, '')
elsif str.encoding.name =~ /^UTF-(16|32)(BE|LE)?$/
return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding)), '')
else
return str
end
end
encoding = str.encoding
newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding(Encoding::ASCII_8BIT))
str.force_encoding(Encoding::ASCII_8BIT).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
return str
end
|
#check_haml_encoding(str) {|msg| ... } ⇒ String
Like #check_encoding, but also checks for a Ruby-style -# coding:
comment
at the beginning of the template and uses that encoding if it exists.
The Haml encoding rules are simple.
If a -# coding:
comment exists,
we assume that that’s the original encoding of the document.
Otherwise, we use whatever encoding Ruby has.
Haml uses the same rules for parsing coding comments as Ruby.
This means that it can understand Emacs-style comments
(e.g. -*- encoding: "utf-8" -*-
),
and also that it cannot understand non-ASCII-compatible encodings
such as UTF-16
and UTF-32
.
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/haml/util.rb', line 113
def check_haml_encoding(str, &block)
str = str.dup if str.frozen?
bom, encoding = parse_haml_magic_comment(str)
if encoding; str.force_encoding(encoding)
elsif bom; str.force_encoding(Encoding::UTF_8)
end
return check_encoding(str, &block)
end
|
#contains_interpolation?(str) ⇒ Boolean
201 202 203 |
# File 'lib/haml/util.rb', line 201
def contains_interpolation?(str)
/#[\{$@]/ === str
end
|
#handle_interpolation(str) {|scan| ... } ⇒ String
Scans through a string looking for the interoplation-opening #{
and, when it’s found, yields the scanner to the calling code
so it can handle it properly.
The scanner will have any backslashes immediately in front of the #{
as the second capture group (scan[2]
),
and the text prior to that as the first (scan[1]
).
151 152 153 154 155 |
# File 'lib/haml/util.rb', line 151
def handle_interpolation(str)
scan = StringScanner.new(str)
yield scan while scan.scan(/(.*?)(\\*)#([\{@$])/)
scan.rest
end
|
#human_indentation(indentation) ⇒ String
Formats a string for use in error messages about indentation.
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/haml/util.rb', line 188
def human_indentation(indentation)
if !indentation.include?(?\t)
noun = 'space'
elsif !indentation.include?(?\s)
noun = 'tab'
else
return indentation.inspect
end
singular = indentation.length == 1
"#{indentation.length} #{noun}#{'s' unless singular}"
end
|
#inspect_obj(obj) ⇒ String
Like Object#inspect
, but preserves non-ASCII characters rather than escaping them.
This is necessary so that the precompiled Haml template can be #encode
d into @options[:encoding]
before being evaluated.
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/haml/util.rb', line 130
def inspect_obj(obj)
case obj
when String
%Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.dump[1...-1]}}"!
when Symbol
":#{inspect_obj(obj.to_s)}"
else
obj.inspect
end
end
|
#rails_xss_safe? ⇒ Boolean
Whether or not ActionView’s XSS protection is available and enabled, as is the default for Rails 3.0+, and optional for version 2.3.5+. Overridden in haml/template.rb if this is the case.
52 53 54 |
# File 'lib/haml/util.rb', line 52
def rails_xss_safe?
false
end
|
#silence_warnings { ... }
Silence all output to STDERR within a block.
38 39 40 41 42 43 |
# File 'lib/haml/util.rb', line 38
def silence_warnings
the_real_stderr, $stderr = $stderr, StringIO.new
yield
ensure
$stderr = the_real_stderr
end
|
#unescape_interpolation(str, escape_html = nil)
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/haml/util.rb', line 205
def unescape_interpolation(str, escape_html = nil)
res = ''.dup
rest = Haml::Util.handle_interpolation str.dump do |scan|
escapes = (scan[2].size - 1) / 2
char = scan[3] # '{', '@' or '$'
res << scan.matched[0...-3 - escapes]
if escapes % 2 == 1
res << "\##{char}"
else
interpolated = if char == '{'
balance(scan, ?{, ?}, 1)[0][0...-1]
else
scan.scan(/\w+/)
end
content = eval("\"#{interpolated}\"")
content = "#{char}#{content}" if char == '@' || char == '$'
content = "Haml::Util.escape_html_safe((#{content}).to_s)" if escape_html
res << "\#{#{content}}"
end
end
res + rest
end
|