Module: Hamlit::HamlUtil
- Extended by:
- HamlUtil
- Included in:
- HamlBuffer, HamlCompiler, HamlParser, HamlUtil
- Defined in:
- lib/hamlit/parser/haml_util.rb,
lib/hamlit/rails_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 { ... } ⇒ Object
Silence all output to STDERR within a block.
-
#slow_unescape_interpolation(str, escape_html = nil) ⇒ Object
Original Haml::Util.unescape_interpolation ex) slow_unescape_interpolation(‘foo#barbaz“’, escape_html: true) #=> ”"foo#Hamlit::HamlHelpers.html_escape((bar))baz\""“.
-
#unescape_interpolation(str) ⇒ Object
Customized Haml::Util.unescape_interpolation to handle escape by Hamlit.
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/hamlit/parser/haml_util.rb', line 168 def balance(scanner, start, finish, count = 0) str = '' 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/hamlit/parser/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/hamlit/parser/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/hamlit/parser/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`), and the text prior to that as the first (`scan`).
147 148 149 150 151 |
# File 'lib/hamlit/parser/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/hamlit/parser/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/hamlit/parser/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` before being evaluated.
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/hamlit/parser/haml_util.rb', line 126 def inspect_obj(obj) case obj when String %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[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 |
# File 'lib/hamlit/parser/haml_util.rb', line 34 def rails_xss_safe?; true; end |
#silence_warnings { ... } ⇒ Object
Silence all output to STDERR within a block.
20 21 22 23 24 25 |
# File 'lib/hamlit/parser/haml_util.rb', line 20 def silence_warnings the_real_stderr, $stderr = $stderr, StringIO.new yield ensure $stderr = the_real_stderr end |
#slow_unescape_interpolation(str, escape_html = nil) ⇒ Object
Original Haml::Util.unescape_interpolation ex) slow_unescape_interpolation(‘foo#barbaz“’, escape_html: true)
#=> "\"foo\#{::Hamlit::HamlHelpers.html_escape((bar))}baz\\\"\""
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/hamlit/parser/haml_util.rb', line 204 def slow_unescape_interpolation(str, escape_html = nil) res = '' rest = ::Hamlit::HamlUtil.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 = "::Hamlit::HamlHelpers.html_escape((#{content}))" if escape_html res << "\#{#{content}}" end end res + rest end |
#unescape_interpolation(str) ⇒ Object
Customized Haml::Util.unescape_interpolation to handle escape by Hamlit. It wraps double quotes to given ‘str` with escaping `“`.
ex) unescape_interpolation(‘foo#barbaz“’) #=> ”"foo#barbaz\""“
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/hamlit/parser/haml_util.rb', line 232 def unescape_interpolation(str) res = '' rest = ::Hamlit::HamlUtil.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 == '$' res << "\#{#{content}}" end end res + rest end |