# frozen_string_literal: false begin require 'erubis/tiny' rescue LoadError require 'erb' end require 'set' require 'stringio' require 'strscan' module Haml # A module containing various useful functions. module Util extend self # Silence all output to STDERR within a block. # # @yield A block in which no output will be printed to STDERR def silence_warnings the_real_stderr, $stderr = $stderr, StringIO.new yield ensure $stderr = the_real_stderr end ## Rails XSS Safety # 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. # # @return [Boolean] def rails_xss_safe? false end # 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. # # @param text [String, nil] # @return [String, nil] `text`, marked as HTML-safe def html_safe(text) return unless text text.html_safe end # 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. # # @param str [String] The string of which to check the encoding # @yield [msg] A block in which an encoding error can be raised. # Only yields if there is an encoding error # @yieldparam msg [String] The error message to be raised # @return [String] `str`, potentially with encoding gotchas like BOMs removed 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 <