Module: Haml::Util
- Extended by:
- Util
- Defined in:
- lib/haml/util.rb,
lib/haml/template.rb
Overview
A module containing various useful functions.
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. -
#html_safe(text) ⇒ String?
Returns the given text, marked as being HTML-safe.
-
#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)
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
168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/haml/util.rb', line 168
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.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/haml/util.rb', line 62
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
.
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/haml/util.rb', line 109
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
197 198 199 |
# File 'lib/haml/util.rb', line 197
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]
).
147 148 149 150 151 |
# File 'lib/haml/util.rb', line 147
def handle_interpolation(str)
scan = StringScanner.new(str)
yield scan while scan.scan(/(.*?)(\\*)#([\{@$])/)
scan.rest
end
|
#html_safe(text) ⇒ String?
Returns the given text, marked as being HTML-safe.
With older versions of the Rails XSS-safety mechanism,
this destructively modifies the HTML-safety of text
.
It only works if you are using ActiveSupport or the parameter text
implements the #html_safe method.
47 48 49 50 |
# File 'lib/haml/util.rb', line 47
def html_safe(text)
return unless text
text.html_safe
end
|
#human_indentation(indentation) ⇒ String
Formats a string for use in error messages about indentation.
184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/haml/util.rb', line 184
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.
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/haml/util.rb', line 126
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.
34 35 36 |
# File 'lib/haml/util.rb', line 34
def rails_xss_safe?
false
end
|
#silence_warnings { ... }
Silence all output to STDERR within a block.
20 21 22 23 24 25 |
# File 'lib/haml/util.rb', line 20
def silence_warnings
the_real_stderr, $stderr = $stderr, StringIO.new
yield
ensure
$stderr = the_real_stderr
end
|
#unescape_interpolation(str, escape_html = nil)
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/haml/util.rb', line 201
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.prepend(char) if char == '@' || char == '$'
content = "Haml::Helpers.html_escape((#{content}))" if escape_html
res << "\#{#{content}}"
end
end
res + rest
end
|