haml 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +117 -5
- data/FAQ.md +7 -17
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +181 -86
- data/Rakefile +47 -51
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +215 -0
- data/lib/haml/attribute_parser.rb +144 -0
- data/lib/haml/buffer.rb +38 -128
- data/lib/haml/compiler.rb +88 -295
- data/lib/haml/engine.rb +25 -41
- data/lib/haml/error.rb +3 -0
- data/lib/haml/escapable.rb +49 -0
- data/lib/haml/exec.rb +33 -19
- data/lib/haml/filters.rb +20 -24
- data/lib/haml/generator.rb +41 -0
- data/lib/haml/helpers/action_view_extensions.rb +3 -2
- data/lib/haml/helpers/action_view_mods.rb +44 -66
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +27 -0
- data/lib/haml/helpers/safe_erubis_template.rb +16 -4
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +122 -58
- data/lib/haml/options.rb +39 -46
- data/lib/haml/parser.rb +278 -217
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -11
- data/lib/haml/sass_rails_filter.rb +17 -4
- data/lib/haml/template/options.rb +12 -2
- data/lib/haml/template.rb +12 -6
- data/lib/haml/temple_engine.rb +120 -0
- data/lib/haml/temple_line_counter.rb +29 -0
- data/lib/haml/util.rb +80 -199
- data/lib/haml/version.rb +2 -1
- data/lib/haml.rb +2 -1
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +306 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +11 -0
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
- data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
- data/test/helper_test.rb +282 -96
- data/test/options_test.rb +22 -0
- data/test/parser_test.rb +71 -4
- data/test/results/bemit.xhtml +4 -0
- data/test/results/eval_suppressed.xhtml +4 -4
- data/test/results/helpers.xhtml +43 -41
- data/test/results/helpful.xhtml +6 -3
- data/test/results/just_stuff.xhtml +21 -20
- data/test/results/list.xhtml +9 -9
- data/test/results/nuke_inner_whitespace.xhtml +22 -22
- data/test/results/nuke_outer_whitespace.xhtml +84 -92
- data/test/results/original_engine.xhtml +17 -17
- data/test/results/partial_layout.xhtml +4 -3
- data/test/results/partial_layout_erb.xhtml +4 -3
- data/test/results/partials.xhtml +11 -10
- data/test/results/silent_script.xhtml +63 -63
- data/test/results/standard.xhtml +156 -159
- data/test/results/tag_parsing.xhtml +19 -19
- data/test/results/very_basic.xhtml +2 -2
- data/test/results/whitespace_handling.xhtml +56 -50
- data/test/template_test.rb +44 -53
- data/test/template_test_helper.rb +38 -0
- data/test/templates/_text_area_helper.html.haml +4 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/partial_layout_erb.erb +1 -1
- data/test/templates/standard_ugly.haml +1 -0
- data/test/templates/with_bom.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +26 -12
- data/test/util_test.rb +6 -47
- metadata +88 -106
- data/lib/haml/helpers/rails_323_textarea_fix.rb +0 -24
- data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
- data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
- data/test/gemfiles/Gemfile.rails-master +0 -4
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/standard_ugly.haml +0 -43
    
        data/lib/haml/buffer.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module Haml
         | 
| 2 3 | 
             
              # This class is used only internally. It holds the buffer of HTML that
         | 
| 3 4 | 
             
              # is eventually output as the resulting document.
         | 
| @@ -90,15 +91,14 @@ module Haml | |
| 90 91 | 
             
                def initialize(upper = nil, options = {})
         | 
| 91 92 | 
             
                  @active     = true
         | 
| 92 93 | 
             
                  @upper      = upper
         | 
| 93 | 
            -
                  @options    =  | 
| 94 | 
            +
                  @options    = Options.buffer_defaults
         | 
| 95 | 
            +
                  @options    = @options.merge(options) unless options.empty?
         | 
| 94 96 | 
             
                  @buffer     = new_encoded_string
         | 
| 95 97 | 
             
                  @tabulation = 0
         | 
| 96 98 |  | 
| 97 99 | 
             
                  # The number of tabs that Engine thinks we should have
         | 
| 98 100 | 
             
                  # @real_tabs + @tabulation is the number of tabs actually output
         | 
| 99 101 | 
             
                  @real_tabs = 0
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  @preserve_pattern = /<[\s]*#{@options[:preserve].join("|")}/i
         | 
| 102 102 | 
             
                end
         | 
| 103 103 |  | 
| 104 104 | 
             
                # Appends text to the buffer, properly tabulated.
         | 
| @@ -117,8 +117,8 @@ module Haml | |
| 117 117 | 
             
                    text.sub!(tabs, '') if dont_tab_up
         | 
| 118 118 | 
             
                  end
         | 
| 119 119 |  | 
| 120 | 
            -
                  @buffer << text
         | 
| 121 120 | 
             
                  @real_tabs += tab_change
         | 
| 121 | 
            +
                  @buffer << text
         | 
| 122 122 | 
             
                end
         | 
| 123 123 |  | 
| 124 124 | 
             
                # Modifies the indentation of the document.
         | 
| @@ -129,82 +129,13 @@ module Haml | |
| 129 129 | 
             
                  @real_tabs += tab_change
         | 
| 130 130 | 
             
                end
         | 
| 131 131 |  | 
| 132 | 
            -
                Haml::Util.def_static_method(self, :format_script, [:result],
         | 
| 133 | 
            -
                                             :preserve_script, :in_tag, :preserve_tag, :escape_html,
         | 
| 134 | 
            -
                                             :nuke_inner_whitespace, :interpolated, :ugly, <<RUBY)
         | 
| 135 | 
            -
                  <% # Escape HTML here so that the safety of the string is preserved in Rails
         | 
| 136 | 
            -
                     result_name = escape_html ? "html_escape(result.to_s)" : "result.to_s" %>
         | 
| 137 | 
            -
                  <% unless ugly %>
         | 
| 138 | 
            -
                    # If we're interpolated,
         | 
| 139 | 
            -
                    # then the custom tabulation is handled in #push_text.
         | 
| 140 | 
            -
                    # The easiest way to avoid it here is to reset @tabulation.
         | 
| 141 | 
            -
                    <% if interpolated %>
         | 
| 142 | 
            -
                      old_tabulation = @tabulation
         | 
| 143 | 
            -
                      @tabulation = 0
         | 
| 144 | 
            -
                    <% end %>
         | 
| 145 | 
            -
             | 
| 146 | 
            -
                    <% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
         | 
| 147 | 
            -
                    tabulation = @real_tabs
         | 
| 148 | 
            -
                    <% end %>
         | 
| 149 | 
            -
                    result = <%= result_name %>.<% if nuke_inner_whitespace %>strip<% else %>rstrip<% end %>
         | 
| 150 | 
            -
                  <% else %>
         | 
| 151 | 
            -
                    result = <%= result_name %><% if nuke_inner_whitespace %>.strip<% end %>
         | 
| 152 | 
            -
                  <% end %>
         | 
| 153 | 
            -
             | 
| 154 | 
            -
                  <% if preserve_tag %>
         | 
| 155 | 
            -
                    result = Haml::Helpers.preserve(result)
         | 
| 156 | 
            -
                  <% elsif preserve_script %>
         | 
| 157 | 
            -
                    result = Haml::Helpers.find_and_preserve(result, options[:preserve])
         | 
| 158 | 
            -
                  <% end %>
         | 
| 159 | 
            -
             | 
| 160 | 
            -
                  <% if ugly %>
         | 
| 161 | 
            -
                    return result
         | 
| 162 | 
            -
                  <% else %>
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                    return result if self.instance_variable_get(:@preserve_pattern).match(result)
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                    <% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
         | 
| 167 | 
            -
                    has_newline = result.include?("\\n")
         | 
| 168 | 
            -
                    <% end %>
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                    <% if in_tag && !nuke_inner_whitespace %>
         | 
| 171 | 
            -
                      <% unless preserve_tag %> if !has_newline <% end %>
         | 
| 172 | 
            -
                      @real_tabs -= 1
         | 
| 173 | 
            -
                      <% if interpolated %> @tabulation = old_tabulation <% end %>
         | 
| 174 | 
            -
                      return result
         | 
| 175 | 
            -
                      <% unless preserve_tag %> end <% end %>
         | 
| 176 | 
            -
                    <% end %>
         | 
| 177 | 
            -
             | 
| 178 | 
            -
                    <% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
         | 
| 179 | 
            -
                    # Precompiled tabulation may be wrong
         | 
| 180 | 
            -
                    <% if !interpolated && !in_tag %>
         | 
| 181 | 
            -
                      result = tabs + result if @tabulation > 0
         | 
| 182 | 
            -
                    <% end %>
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                    if has_newline
         | 
| 185 | 
            -
                      result = result.gsub "\\n", "\\n" + tabs(tabulation)
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                      # Add tabulation if it wasn't precompiled
         | 
| 188 | 
            -
                      <% if in_tag && !nuke_inner_whitespace %> result = tabs(tabulation) + result <% end %>
         | 
| 189 | 
            -
                    end
         | 
| 190 | 
            -
             | 
| 191 | 
            -
                    <% if in_tag && !nuke_inner_whitespace %>
         | 
| 192 | 
            -
                      result = "\\n\#{result}\\n\#{tabs(tabulation-1)}"
         | 
| 193 | 
            -
                      @real_tabs -= 1
         | 
| 194 | 
            -
                    <% end %>
         | 
| 195 | 
            -
                    <% if interpolated %> @tabulation = old_tabulation <% end %>
         | 
| 196 | 
            -
                    result
         | 
| 197 | 
            -
                    <% end %>
         | 
| 198 | 
            -
                  <% end %>
         | 
| 199 | 
            -
            RUBY
         | 
| 200 | 
            -
             | 
| 201 132 | 
             
                def attributes(class_id, obj_ref, *attributes_hashes)
         | 
| 202 133 | 
             
                  attributes = class_id
         | 
| 203 134 | 
             
                  attributes_hashes.each do |old|
         | 
| 204 | 
            -
                     | 
| 135 | 
            +
                    AttributeBuilder.merge_attributes!(attributes, Hash[old.map {|k, v| [k.to_s, v]}])
         | 
| 205 136 | 
             
                  end
         | 
| 206 | 
            -
                   | 
| 207 | 
            -
                   | 
| 137 | 
            +
                  AttributeBuilder.merge_attributes!(attributes, parse_object_ref(obj_ref)) if obj_ref
         | 
| 138 | 
            +
                  AttributeBuilder.build_attributes(
         | 
| 208 139 | 
             
                    html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
         | 
| 209 140 | 
             
                end
         | 
| 210 141 |  | 
| @@ -219,58 +150,35 @@ RUBY | |
| 219 150 | 
             
                  buffer << buffer.slice!(capture_position..-1).rstrip
         | 
| 220 151 | 
             
                end
         | 
| 221 152 |  | 
| 222 | 
            -
                #  | 
| 223 | 
            -
                #  | 
| 224 | 
            -
                #  | 
| 225 | 
            -
                #
         | 
| 226 | 
            -
                # ids are concatenated with `"_"`,
         | 
| 227 | 
            -
                # and classes are concatenated with `" "`.
         | 
| 228 | 
            -
                # data hashes are simply merged.
         | 
| 153 | 
            +
                # Works like #{find_and_preserve}, but allows the first newline after a
         | 
| 154 | 
            +
                # preserved opening tag to remain unencoded, and then outdents the content.
         | 
| 155 | 
            +
                # This change was motivated primarily by the change in Rails 3.2.3 to emit
         | 
| 156 | 
            +
                # a newline after textarea helpers.
         | 
| 229 157 | 
             
                #
         | 
| 230 | 
            -
                #  | 
| 231 | 
            -
                #
         | 
| 232 | 
            -
                # @ | 
| 233 | 
            -
                 | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
                   | 
| 237 | 
            -
                   | 
| 238 | 
            -
                     | 
| 239 | 
            -
             | 
| 240 | 
            -
                     | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
                    # | 
| 246 | 
            -
                    from['class'] = (from['class'].to_s.split(' ') | to['class'].split(' ')).sort.join(' ')
         | 
| 247 | 
            -
                  elsif to['class'] || from['class']
         | 
| 248 | 
            -
                    from['class'] ||= to['class']
         | 
| 158 | 
            +
                # @param input [String] The text to process
         | 
| 159 | 
            +
                # @since Haml 4.0.1
         | 
| 160 | 
            +
                # @private
         | 
| 161 | 
            +
                def fix_textareas!(input)
         | 
| 162 | 
            +
                  return input unless toplevel? && input.include?('<textarea'.freeze)
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  pattern = /<(textarea)([^>]*)>(\n|
)(.*?)<\/textarea>/im
         | 
| 165 | 
            +
                  input.gsub!(pattern) do |s|
         | 
| 166 | 
            +
                    match = pattern.match(s)
         | 
| 167 | 
            +
                    content = match[4]
         | 
| 168 | 
            +
                    if match[3] == '
'
         | 
| 169 | 
            +
                      content.sub!(/\A /, ' ')
         | 
| 170 | 
            +
                    else
         | 
| 171 | 
            +
                      content.sub!(/\A[ ]*/, '')
         | 
| 172 | 
            +
                    end
         | 
| 173 | 
            +
                    "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
         | 
| 249 174 | 
             
                  end
         | 
| 250 | 
            -
             | 
| 251 | 
            -
                  from_data = from.delete('data') || {}
         | 
| 252 | 
            -
                  to_data = to.delete('data') || {}
         | 
| 253 | 
            -
             | 
| 254 | 
            -
                  # forces to_data & from_data into a hash
         | 
| 255 | 
            -
                  from_data = { nil => from_data } unless from_data.is_a?(Hash)
         | 
| 256 | 
            -
                  to_data = { nil => to_data } unless to_data.is_a?(Hash)
         | 
| 257 | 
            -
             | 
| 258 | 
            -
                  merged_data = to_data.merge(from_data)
         | 
| 259 | 
            -
             | 
| 260 | 
            -
                  to['data'] = merged_data unless merged_data.empty?
         | 
| 261 | 
            -
                  to.merge!(from)
         | 
| 175 | 
            +
                  input
         | 
| 262 176 | 
             
                end
         | 
| 263 177 |  | 
| 264 178 | 
             
                private
         | 
| 265 179 |  | 
| 266 | 
            -
                 | 
| 267 | 
            -
                   | 
| 268 | 
            -
                    ""
         | 
| 269 | 
            -
                  end
         | 
| 270 | 
            -
                else
         | 
| 271 | 
            -
                  def new_encoded_string
         | 
| 272 | 
            -
                    "".encode(Encoding.find(options[:encoding]))
         | 
| 273 | 
            -
                  end
         | 
| 180 | 
            +
                def new_encoded_string
         | 
| 181 | 
            +
                  "".encode(options[:encoding])
         | 
| 274 182 | 
             
                end
         | 
| 275 183 |  | 
| 276 184 | 
             
                @@tab_cache = {}
         | 
| @@ -308,18 +216,20 @@ RUBY | |
| 308 216 | 
             
                    id = "#{ prefix }_#{ id }"
         | 
| 309 217 | 
             
                  end
         | 
| 310 218 |  | 
| 311 | 
            -
                  {'id' => id, 'class' => class_name}
         | 
| 219 | 
            +
                  { 'id'.freeze => id, 'class'.freeze => class_name }
         | 
| 312 220 | 
             
                end
         | 
| 313 221 |  | 
| 314 222 | 
             
                # Changes a word from camel case to underscores.
         | 
| 315 223 | 
             
                # Based on the method of the same name in Rails' Inflector,
         | 
| 316 224 | 
             
                # but copied here so it'll run properly without Rails.
         | 
| 317 225 | 
             
                def underscore(camel_cased_word)
         | 
| 318 | 
            -
                  camel_cased_word.to_s. | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 226 | 
            +
                  word = camel_cased_word.to_s.dup
         | 
| 227 | 
            +
                  word.gsub!(/::/, '_')
         | 
| 228 | 
            +
                  word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         | 
| 229 | 
            +
                  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
         | 
| 230 | 
            +
                  word.tr!('-', '_')
         | 
| 231 | 
            +
                  word.downcase!
         | 
| 232 | 
            +
                  word
         | 
| 323 233 | 
             
                end
         | 
| 324 234 | 
             
              end
         | 
| 325 235 | 
             
            end
         |