haml 5.0.0.beta.2 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 056cc654414c29999474b5115839d33e5ebc9a20
4
- data.tar.gz: e56a16b4d053d863af5e9a89200d413d7901f3f7
3
+ metadata.gz: 7fa1e64aca629e46493a148b6159feb77763ba0d
4
+ data.tar.gz: 912f3565b782829c0651604333a0d5fd823c45a1
5
5
  SHA512:
6
- metadata.gz: 7dbf54da5889f0477f6122eb5178310a1e0167f0aaed5f6b495efc6de108183a228bda85ae5a10c46862443e10d30836351d826bdda86d4ebede4b5221ed6b19
7
- data.tar.gz: 5d77752a502ab13aaac1e1af68876ff9084913d4a82491c0e790ae851d8975931a478fd59779d5acb92587ebfbff93de4d33411945e0c3a726e5d7fd68902732
6
+ metadata.gz: d8e860a0fc047d158a7a1d08f349a5555ae9a0afd578327c16cca624c3c0425a323e40cc3185f8ba8fede3ed79d24babb44f634969a69707a46f27d92b925b15
7
+ data.tar.gz: f3e66b26cf401ac0081721f44322a4fe39c0b0c486d6b4b0dd7e665e483be86f6f1769a0c94ed00b2646e3d76fb7be0ebe2e40c75943c0a5774e38cb3f17a4e2
@@ -1,6 +1,9 @@
1
1
  # Haml Changelog
2
2
 
3
- ## 5.0.0 (Unreleased)
3
+ ## 5.0.0
4
+
5
+ Released on April 26, 2017
6
+ ([diff](https://github.com/haml/haml/compare/4.0.7...5.0.0)).
4
7
 
5
8
  * Haml now requires Ruby 2.0.0 or above.
6
9
  * Rails 3 is no longer supported, matching the official
@@ -18,9 +21,12 @@
18
21
  to the source Haml file from which it was generated. Thanks [Alex Babkin](https://github.com/ababkin).
19
22
  * Fix #@foo and #$foo style interpolation that was not working in html_safe mode. (Akira Matsuda)
20
23
  * Add `haml_tag_if` to render a block, conditionally wrapped in another element (Matt Wildig)
24
+ * Escape Ruby script interpolated in filters. (Matt Wildig)
21
25
  * The `haml` command's debug option (`-d`) no longer executes the Haml code, but
22
26
  rather checks the generated Ruby syntax for errors.
23
27
  * Support Rails 5.1 Erubi template handler.
28
+ * Support Sprockets 3. Thanks [Sam Davies](https://github.com/samphilipd) and [Jeremy Venezia](https://github.com/jvenezia).
29
+ * Allow `@` as tag's class name. Thanks [Joe Bartlett](https://github.com/redoPop).
24
30
  * Raise `Haml::InvalidAttributeNameError` when attribute name includes invalid characters. (Takashi Kokubun)
25
31
  * Drop dynamic quotes support and always escape `'` for `escape_html`/`escape_attrs` instead.
26
32
  Also, escaped results are slightly changed and always unified to the same characters. (Takashi Kokubun)
data/Rakefile CHANGED
@@ -4,6 +4,21 @@ require "bundler/gem_tasks"
4
4
 
5
5
  task :default => :test
6
6
 
7
+ # FIXME: Redefining :test task to run test/options_test.rb in isolated process since it depends on whether Rails is loaded or not.
8
+ # Remove this task when we finished changing escape_html option to be true by default.
9
+ isolated_test = Rake::TestTask.new do |t|
10
+ t.libs << 'test'
11
+ t.test_files = %w[test/options_test.rb]
12
+ t.warning = true
13
+ t.verbose = true
14
+ end
15
+ Rake::TestTask.new do |t|
16
+ t.libs << 'test'
17
+ t.test_files = Dir['test/*_test.rb'] + Dir['test/haml-spec/*_test.rb'] - isolated_test.file_list
18
+ t.warning = true
19
+ t.verbose = true
20
+ end
21
+
7
22
  CLEAN.replace %w(pkg doc coverage .yardoc test/haml vendor)
8
23
 
9
24
  desc "Benchmark Haml against ERB. TIMES=n sets the number of runs, default is 1000."
@@ -11,17 +26,6 @@ task :benchmark do
11
26
  sh "ruby benchmark.rb #{ENV['TIMES']}"
12
27
  end
13
28
 
14
- Rake::TestTask.new do |t|
15
- t.libs << 'lib' << 'test'
16
- # haml-spec tests are explicitly added after other tests so they don't
17
- # interfere with the Haml loading process which can cause test failures
18
- files = Dir["test/*_test.rb"]
19
- files.concat(Dir['test/haml-spec/*_test.rb'])
20
- t.test_files = files
21
- t.warning = true
22
- t.verbose = true
23
- end
24
-
25
29
  task :set_coverage_env do
26
30
  ENV["COVERAGE"] = "true"
27
31
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'haml/version'
2
3
 
3
4
  # The module that contains everything Haml-related:
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'haml/attribute_parser'
2
3
 
3
4
  module Haml
@@ -27,10 +28,10 @@ module Haml
27
28
  #
28
29
  # @param attributes [Hash]
29
30
  # @param object_ref [String,:nil]
30
- # @param attributes_hashes [Array<String>]
31
+ # @param dynamic_attributes [DynamicAttributes]
31
32
  # @return [String] Attributes rendering code
32
- def self.runtime_build(attributes, object_ref, attributes_hashes)
33
- "_hamlout.attributes(#{Haml::Util.inspect_obj(attributes)}, #{object_ref},#{attributes_hashes.join(', ')})"
33
+ def self.runtime_build(attributes, object_ref, dynamic_attributes)
34
+ "_hamlout.attributes(#{Haml::Util.inspect_obj(attributes)}, #{object_ref},#{dynamic_attributes.to_literal})"
34
35
  end
35
36
 
36
37
  # @param options [Haml::Options]
@@ -45,16 +46,16 @@ module Haml
45
46
  #
46
47
  # @param attributes [Hash]
47
48
  # @param object_ref [String,:nil]
48
- # @param attributes_hashes [Array<String>]
49
+ # @param dynamic_attributes [DynamicAttributes]
49
50
  # @return [Array] Temple expression
50
- def compile(attributes, object_ref, attributes_hashes)
51
+ def compile(attributes, object_ref, dynamic_attributes)
51
52
  if object_ref != :nil || !AttributeParser.available?
52
- return [:dynamic, AttributeCompiler.runtime_build(attributes, object_ref, attributes_hashes)]
53
+ return [:dynamic, AttributeCompiler.runtime_build(attributes, object_ref, dynamic_attributes)]
53
54
  end
54
55
 
55
- parsed_hashes = attributes_hashes.map do |attribute_hash|
56
+ parsed_hashes = [dynamic_attributes.new, dynamic_attributes.old].compact.map do |attribute_hash|
56
57
  unless (hash = AttributeParser.parse(attribute_hash))
57
- return [:dynamic, AttributeCompiler.runtime_build(attributes, object_ref, attributes_hashes)]
58
+ return [:dynamic, AttributeCompiler.runtime_build(attributes, object_ref, dynamic_attributes)]
58
59
  end
59
60
  hash
60
61
  end
@@ -69,7 +70,7 @@ module Haml
69
70
 
70
71
  private
71
72
 
72
- # Returns array of AttributeValue instnces from static attributes and dynamic attributes_hashes. For each key,
73
+ # Returns array of AttributeValue instances from static attributes and dynamic_attributes. For each key,
73
74
  # the values' order in returned value is preserved in the same order as Haml::Buffer#attributes's merge order.
74
75
  #
75
76
  # @param attributes [{ String => String }]
@@ -1,27 +1,35 @@
1
+ # frozen_string_literal: true
1
2
  begin
2
3
  require 'ripper'
3
4
  rescue LoadError
4
5
  end
5
6
 
6
7
  module Haml
8
+ # Haml::AttriubuteParser parses Hash literal to { String (key name) => String (value literal) }.
7
9
  module AttributeParser
8
10
  class UnexpectedTokenError < StandardError; end
9
11
  class UnexpectedKeyError < StandardError; end
10
12
 
13
+ # Indices in Ripper tokens
14
+ TYPE = 1
15
+ TEXT = 2
16
+
17
+ IGNORED_TYPES = %i[on_sp on_ignored_nl]
18
+
11
19
  class << self
20
+ # @return [Boolean] - return true if AttributeParser.parse can be used.
12
21
  def available?
13
22
  defined?(Ripper) && Temple::StaticAnalyzer.available?
14
23
  end
15
24
 
16
- def parse(text)
17
- exp = wrap_bracket(text)
18
- return if Temple::StaticAnalyzer.syntax_error?(exp)
25
+ # @param [String] exp - Old attributes literal or Hash literal generated from new attributes.
26
+ # @return [Hash<String, String>,nil] - Return parsed attribute Hash whose values are Ruby literals, or return nil if argument is not a single Hash literal.
27
+ def parse(exp)
28
+ return nil unless hash_literal?(exp)
19
29
 
20
30
  hash = {}
21
- tokens = Ripper.lex(exp)[1..-2] || []
22
- each_attr(tokens) do |attr_tokens|
23
- key = parse_key!(attr_tokens)
24
- hash[key] = attr_tokens.map(&:last).join.strip
31
+ each_attribute(exp) do |key, value|
32
+ hash[key] = value
25
33
  end
26
34
  hash
27
35
  rescue UnexpectedTokenError, UnexpectedKeyError
@@ -30,82 +38,106 @@ module Haml
30
38
 
31
39
  private
32
40
 
33
- def wrap_bracket(text)
34
- text = text.strip
35
- return text if text[0] == '{'
36
- "{#{text}}"
41
+ # @param [String] exp - Ruby expression
42
+ # @return [Boolean] - Return true if exp is a single Hash literal
43
+ def hash_literal?(exp)
44
+ return false if Temple::StaticAnalyzer.syntax_error?(exp)
45
+ sym, body = Ripper.sexp(exp)
46
+ sym == :program && body.is_a?(Array) && body.size == 1 && body[0] && body[0][0] == :hash
37
47
  end
38
48
 
39
- def parse_key!(tokens)
40
- _, type, str = tokens.shift
49
+ # @param [Array] tokens - Ripper tokens. Scanned tokens will be destructively removed from this argument.
50
+ # @return [String] - attribute name in String
51
+ def shift_key!(tokens)
52
+ while !tokens.empty? && IGNORED_TYPES.include?(tokens.first[TYPE])
53
+ tokens.shift # ignore spaces
54
+ end
55
+
56
+ _, type, first_text = tokens.shift
41
57
  case type
42
- when :on_sp
43
- parse_key!(tokens)
44
- when :on_label
45
- str.tr(':', '')
46
- when :on_symbeg
47
- _, _, key = tokens.shift
48
- assert_type!(tokens.shift, :on_tstring_end) if str != ':'
49
- skip_until_hash_rocket!(tokens)
58
+ when :on_label # `key:`
59
+ first_text.tr(':', '')
60
+ when :on_symbeg # `:key =>`, `:'key' =>` or `:"key" =>`
61
+ key = tokens.shift[TEXT]
62
+ if first_text != ':' # `:'key'` or `:"key"`
63
+ expect_string_end!(tokens.shift)
64
+ end
65
+ shift_hash_rocket!(tokens)
50
66
  key
51
- when :on_tstring_beg
52
- _, _, key = tokens.shift
67
+ when :on_tstring_beg # `"key":`, `'key':` or `"key" =>`
68
+ key = tokens.shift[TEXT]
53
69
  next_token = tokens.shift
54
- unless next_token[1] == :on_label_end
55
- assert_type!(next_token, :on_tstring_end)
56
- skip_until_hash_rocket!(tokens)
70
+ if next_token[TYPE] != :on_label_end # on_label_end is `":` or `':`, so `"key" =>`
71
+ expect_string_end!(next_token)
72
+ shift_hash_rocket!(tokens)
57
73
  end
58
74
  key
59
75
  else
60
- raise UnexpectedKeyError
76
+ raise UnexpectedKeyError.new("unexpected token is given!: #{first_text} (#{type})")
61
77
  end
62
78
  end
63
79
 
64
- def assert_type!(token, type)
65
- raise UnexpectedTokenError if token[1] != type
80
+ # @param [Array] token - Ripper token
81
+ def expect_string_end!(token)
82
+ if token[TYPE] != :on_tstring_end
83
+ raise UnexpectedTokenError
84
+ end
66
85
  end
67
86
 
68
- def skip_until_hash_rocket!(tokens)
87
+ # @param [Array] tokens - Ripper tokens
88
+ def shift_hash_rocket!(tokens)
69
89
  until tokens.empty?
70
90
  _, type, str = tokens.shift
71
91
  break if type == :on_op && str == '=>'
72
92
  end
73
93
  end
74
94
 
75
- def each_attr(tokens)
95
+ # @param [String] hash_literal
96
+ # @param [Proc] block - that takes [String, String] as arguments
97
+ def each_attribute(hash_literal, &block)
98
+ all_tokens = Ripper.lex(hash_literal.strip)
99
+ all_tokens = all_tokens[1...-1] || [] # strip tokens for brackets
100
+
101
+ each_balaned_tokens(all_tokens) do |tokens|
102
+ key = shift_key!(tokens)
103
+ value = tokens.map(&:last).join.strip
104
+ block.call(key, value)
105
+ end
106
+ end
107
+
108
+ # @param [Array] tokens - Ripper tokens
109
+ # @param [Proc] block - that takes balanced Ripper tokens as arguments
110
+ def each_balaned_tokens(tokens, &block)
76
111
  attr_tokens = []
77
- array_open = 0
78
- brace_open = 0
79
- paren_open = 0
112
+ open_tokens = Hash.new { |h, k| h[k] = 0 }
80
113
 
81
114
  tokens.each do |token|
82
- _, type, _ = token
83
- case type
115
+ case token[TYPE]
84
116
  when :on_comma
85
- if array_open == 0 && brace_open == 0 && paren_open == 0
86
- yield(attr_tokens)
117
+ if open_tokens.values.all?(&:zero?)
118
+ block.call(attr_tokens)
87
119
  attr_tokens = []
88
120
  next
89
121
  end
90
122
  when :on_lbracket
91
- array_open += 1
123
+ open_tokens[:array] += 1
92
124
  when :on_rbracket
93
- array_open -= 1
125
+ open_tokens[:array] -= 1
94
126
  when :on_lbrace
95
- brace_open += 1
127
+ open_tokens[:block] += 1
96
128
  when :on_rbrace
97
- brace_open -= 1
129
+ open_tokens[:block] -= 1
98
130
  when :on_lparen
99
- paren_open += 1
131
+ open_tokens[:paren] += 1
100
132
  when :on_rparen
101
- paren_open -= 1
102
- when :on_sp
133
+ open_tokens[:paren] -= 1
134
+ when *IGNORED_TYPES
103
135
  next if attr_tokens.empty?
104
136
  end
105
137
 
106
138
  attr_tokens << token
107
139
  end
108
- yield(attr_tokens) unless attr_tokens.empty?
140
+ block.call(attr_tokens) unless attr_tokens.empty?
109
141
  end
110
142
  end
111
143
  end
@@ -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.
@@ -128,17 +129,6 @@ module Haml
128
129
  @real_tabs += tab_change
129
130
  end
130
131
 
131
- # the number of arguments here is insane, but passing in an options hash instead of named arguments
132
- # causes a significant performance regression
133
- def format_script(result, preserve_script, in_tag, preserve_tag, escape_html, nuke_inner_whitespace, interpolated)
134
- result_name = escape_html ? html_escape(result.to_s) : result.to_s
135
-
136
- result = nuke_inner_whitespace ? result_name.strip : result_name
137
- result = preserve(result, preserve_script, preserve_tag)
138
- fix_textareas!(result) if toplevel? && result.include?('<textarea')
139
- result
140
- end
141
-
142
132
  def attributes(class_id, obj_ref, *attributes_hashes)
143
133
  attributes = class_id
144
134
  attributes_hashes.each do |old|
@@ -160,14 +150,6 @@ module Haml
160
150
  buffer << buffer.slice!(capture_position..-1).rstrip
161
151
  end
162
152
 
163
- private
164
-
165
- def preserve(result, preserve_script, preserve_tag)
166
- return Haml::Helpers.preserve(result) if preserve_tag
167
- return Haml::Helpers.find_and_preserve(result, options[:preserve]) if preserve_script
168
- result
169
- end
170
-
171
153
  # Works like #{find_and_preserve}, but allows the first newline after a
172
154
  # preserved opening tag to remain unencoded, and then outdents the content.
173
155
  # This change was motivated primarily by the change in Rails 3.2.3 to emit
@@ -177,6 +159,8 @@ module Haml
177
159
  # @since Haml 4.0.1
178
160
  # @private
179
161
  def fix_textareas!(input)
162
+ return input unless toplevel? && input.include?('<textarea'.freeze)
163
+
180
164
  pattern = /<(textarea)([^>]*)>(\n|&#x000A;)(.*?)<\/textarea>/im
181
165
  input.gsub!(pattern) do |s|
182
166
  match = pattern.match(s)
@@ -188,10 +172,13 @@ module Haml
188
172
  end
189
173
  "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
190
174
  end
175
+ input
191
176
  end
192
177
 
178
+ private
179
+
193
180
  def new_encoded_string
194
- "".encode(Encoding.find(options[:encoding]))
181
+ "".encode(options[:encoding])
195
182
  end
196
183
 
197
184
  @@tab_cache = {}
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'haml/attribute_builder'
2
3
  require 'haml/attribute_compiler'
3
4
  require 'haml/temple_line_counter'
@@ -92,13 +93,13 @@ module Haml
92
93
  object_ref = :nil
93
94
  parse = false
94
95
  value = t[:parse] ? nil : t[:value]
95
- attributes_hashes = []
96
+ dynamic_attributes = Haml::Parser::DynamicAttributes.new
96
97
  preserve_script = false
97
98
  else
98
99
  object_ref = t[:object_ref]
99
100
  parse = t[:parse]
100
101
  value = t[:value]
101
- attributes_hashes = t[:attributes_hashes]
102
+ dynamic_attributes = t[:dynamic_attributes]
102
103
  preserve_script = t[:preserve_script]
103
104
  end
104
105
 
@@ -107,7 +108,7 @@ module Haml
107
108
  end
108
109
 
109
110
  push_text("<#{t[:name]}")
110
- push_temple(@attribute_compiler.compile(t[:attributes], object_ref, attributes_hashes))
111
+ push_temple(@attribute_compiler.compile(t[:attributes], object_ref, dynamic_attributes))
111
112
  push_text(
112
113
  if t[:self_closing] && @options.xhtml?
113
114
  " />#{"\n" unless t[:nuke_outer_whitespace]}"
@@ -231,8 +232,7 @@ module Haml
231
232
 
232
233
  def push_temple(temple)
233
234
  flush_merged_text
234
- newlines = resolve_newlines
235
- @temple << [:code, newlines] unless newlines.empty?
235
+ @temple.concat([[:newline]] * resolve_newlines.count("\n"))
236
236
  @temple << temple
237
237
  @output_line += TempleLineCounter.count_lines(temple)
238
238
  end
@@ -262,15 +262,10 @@ module Haml
262
262
  def push_script(text, opts = {})
263
263
  return if @options.suppress_eval?
264
264
 
265
- args = [:preserve_script, :in_tag, :preserve_tag, :escape_html, :nuke_inner_whitespace]
266
- args.map! {|name| !!opts[name]}
267
- args << !block_given?
268
-
269
265
  no_format = !(opts[:preserve_script] || opts[:preserve_tag] || opts[:escape_html])
270
266
 
271
267
  unless block_given?
272
- format_script_method = "_hamlout.format_script((#{text}\n),#{args.join(',')});"
273
- push_generated_script(no_format ? "(#{text}\n).to_s" : format_script_method)
268
+ push_generated_script(no_format ? "(#{text}\n).to_s" : build_script_formatter("(#{text}\n)", opts))
274
269
  push_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace]
275
270
  return
276
271
  end
@@ -279,8 +274,23 @@ module Haml
279
274
  push_silent "haml_temp = #{text}"
280
275
  yield
281
276
  push_silent('end', :can_suppress) unless @node.value[:dont_push_end]
282
- format_script_method = "_hamlout.format_script(haml_temp,#{args.join(',')});"
283
- @temple << [:dynamic, no_format ? "haml_temp.to_s;" : format_script_method]
277
+ @temple << [:dynamic, no_format ? 'haml_temp.to_s;' : build_script_formatter('haml_temp', opts)]
278
+ end
279
+
280
+ def build_script_formatter(text, opts)
281
+ text = "(#{text}).to_s"
282
+ if opts[:escape_html]
283
+ text = "::Haml::Helpers.html_escape(#{text})"
284
+ end
285
+ if opts[:nuke_inner_whitespace]
286
+ text = "(#{text}).strip"
287
+ end
288
+ if opts[:preserve_tag]
289
+ text = "::Haml::Helpers.preserve(#{text})"
290
+ elsif opts[:preserve_script]
291
+ text = "::Haml::Helpers.find_and_preserve(#{text}, _hamlout.options[:preserve])"
292
+ end
293
+ "_hamlout.fix_textareas!(#{text});"
284
294
  end
285
295
 
286
296
  def push_generated_script(text)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'forwardable'
2
3
 
3
4
  require 'haml/parser'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # An exception raised by Haml code.
3
4
  class Error < StandardError
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # Like Temple::Filters::Escapable, but with support for escaping by
3
4
  # Haml::Herlpers.html_escape and Haml::Herlpers.escape_once.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
3
  require 'rbconfig'
3
4
  require 'pp'
@@ -292,8 +293,8 @@ END
292
293
  begin
293
294
 
294
295
  if @options[:parse]
295
- parser = ::Haml::Parser.new(template, ::Haml::Options.new(@options))
296
- pp parser.parse
296
+ parser = ::Haml::Parser.new(::Haml::Options.new(@options))
297
+ pp parser.call(template)
297
298
  return
298
299
  end
299
300
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require "tilt"
2
3
 
3
4
  module Haml
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # Ruby code generator, which is a limited version of Temple::Generator.
3
4
  # Limit methods since Haml doesn't need most of them.
@@ -27,6 +28,10 @@ module Haml
27
28
  exp
28
29
  end
29
30
 
31
+ def on_newline
32
+ "\n"
33
+ end
34
+
30
35
  private
31
36
 
32
37
  def concat(str)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'erb'
2
3
 
3
4
  module Haml
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  module Helpers
3
4
  @@action_view_defined = true
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  module Helpers
3
4
  module ActionViewMods
@@ -54,7 +55,7 @@ module ActionView
54
55
  def content_tag_with_haml(name, *args, &block)
55
56
  return content_tag_without_haml(name, *args, &block) unless is_haml?
56
57
 
57
- preserve = haml_buffer.options[:preserve].include?(name.to_s)
58
+ preserve = haml_buffer.options.fetch(:preserve, %w[textarea pre code]).include?(name.to_s)
58
59
 
59
60
  if block_given? && block_is_haml?(block) && preserve
60
61
  return content_tag_without_haml(name, *args) {preserve(&block)}
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActionView
2
3
  module Helpers
3
4
  module CaptureHelper
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'action_view'
2
3
 
3
4
  module Haml
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'action_view'
2
3
 
3
4
  module Haml
@@ -28,4 +29,4 @@ module Haml
28
29
  [super, '@output_buffer.to_s'].join("\n")
29
30
  end
30
31
  end
31
- end
32
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  module Helpers
3
4
  # This module overrides Haml helpers to work properly
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # This class encapsulates all of the configuration options that Haml
3
4
  # understands. Please see the {file:REFERENCE.md#options Haml Reference} to
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'strscan'
2
3
 
3
4
  module Haml
@@ -204,6 +205,30 @@ module Haml
204
205
  end
205
206
  end
206
207
 
208
+ # @param [String] new - Hash literal including dynamic values.
209
+ # @param [String] old - Hash literal including dynamic values or Ruby literal of multiple Hashes which MUST be interpreted as method's last arguments.
210
+ class DynamicAttributes < Struct.new(:new, :old)
211
+ def old=(value)
212
+ unless value =~ /\A{.*}\z/m
213
+ raise ArgumentError.new('Old attributes must start with "{" and end with "}"')
214
+ end
215
+ super
216
+ end
217
+
218
+ # This will be a literal for Haml::Buffer#attributes's last argument, `attributes_hashes`.
219
+ def to_literal
220
+ [new, stripped_old].compact.join(', ')
221
+ end
222
+
223
+ private
224
+
225
+ # For `%foo{ { foo: 1 }, bar: 2 }`, :old is "{ { foo: 1 }, bar: 2 }" and this method returns " { foo: 1 }, bar: 2 " for last argument.
226
+ def stripped_old
227
+ return nil if old.nil?
228
+ old.sub!(/\A{/, '').sub!(/}\z/m, '')
229
+ end
230
+ end
231
+
207
232
  # Processes and deals with lowering indentation.
208
233
  def process_indent(line)
209
234
  return unless line.tabs <= @template_tabs && @template_tabs > 0
@@ -396,22 +421,20 @@ module Haml
396
421
  end
397
422
 
398
423
  attributes = Parser.parse_class_and_id(attributes)
399
- attributes_list = []
424
+ dynamic_attributes = DynamicAttributes.new
400
425
 
401
426
  if attributes_hashes[:new]
402
427
  static_attributes, attributes_hash = attributes_hashes[:new]
403
428
  AttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
404
- attributes_list << attributes_hash
429
+ dynamic_attributes.new = attributes_hash
405
430
  end
406
431
 
407
432
  if attributes_hashes[:old]
408
433
  static_attributes = parse_static_hash(attributes_hashes[:old])
409
434
  AttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
410
- attributes_list << attributes_hashes[:old] unless static_attributes || @options.suppress_eval
435
+ dynamic_attributes.old = attributes_hashes[:old] unless static_attributes || @options.suppress_eval
411
436
  end
412
437
 
413
- attributes_list.compact!
414
-
415
438
  raise SyntaxError.new(Error.message(:illegal_nesting_self_closing), @next_line.index) if block_opened? && self_closing
416
439
  raise SyntaxError.new(Error.message(:no_ruby_code, action), last_line - 1) if parse && value.empty?
417
440
  raise SyntaxError.new(Error.message(:self_closing_content), last_line - 1) if self_closing && !value.empty?
@@ -426,7 +449,7 @@ module Haml
426
449
  line = handle_ruby_multiline(line) if parse
427
450
 
428
451
  ParseNode.new(:tag, line.index + 1, :name => tag_name, :attributes => attributes,
429
- :attributes_hashes => attributes_list, :self_closing => self_closing,
452
+ :dynamic_attributes => dynamic_attributes, :self_closing => self_closing,
430
453
  :nuke_inner_whitespace => nuke_inner_whitespace,
431
454
  :nuke_outer_whitespace => nuke_outer_whitespace, :object_ref => object_ref,
432
455
  :escape_html => escape_html, :preserve_tag => preserve_tag,
@@ -532,7 +555,7 @@ module Haml
532
555
  attributes = {}
533
556
  return attributes if list.empty?
534
557
 
535
- list.scan(/([#.])([-:_a-zA-Z0-9]+)/) do |type, property|
558
+ list.scan(/([#.])([-:_a-zA-Z0-9\@]+)/) do |type, property|
536
559
  case type
537
560
  when '.'
538
561
  if attributes[CLASS_KEY]
@@ -547,10 +570,16 @@ module Haml
547
570
  attributes
548
571
  end
549
572
 
573
+ # This method doesn't use Haml::AttributeParser because currently it depends on Ripper and Rubinius doesn't provide it.
574
+ # Ideally this logic should be placed in Haml::AttributeParser instead of here and this method should use it.
575
+ #
576
+ # @param [String] text - Hash literal or text inside old attributes
577
+ # @return [Hash,nil] - Return nil if text is not static Hash literal
550
578
  def parse_static_hash(text)
551
579
  attributes = {}
552
580
  return attributes if text.empty?
553
581
 
582
+ text = text[1...-1] # strip brackets
554
583
  scanner = StringScanner.new(text)
555
584
  scanner.scan(/\s+/)
556
585
  until scanner.eos?
@@ -565,7 +594,7 @@ module Haml
565
594
 
566
595
  # Parses a line into tag_name, attributes, attributes_hash, object_ref, action, value
567
596
  def parse_tag(text)
568
- match = text.scan(/%([-:\w]+)([-:\w.#]*)(.+)?/)[0]
597
+ match = text.scan(/%([-:\w]+)([-:\w.#\@]*)(.+)?/)[0]
569
598
  raise SyntaxError.new(Error.message(:invalid_tag, text)) unless match
570
599
 
571
600
  tag_name, attributes, rest = match
@@ -616,6 +645,9 @@ module Haml
616
645
  nuke_inner_whitespace, action, value, last_line || @line.index + 1]
617
646
  end
618
647
 
648
+ # @return [String] attributes_hash - Hash literal starting with `{` and ending with `}`
649
+ # @return [String] rest
650
+ # @return [Integer] last_line
619
651
  def parse_old_attributes(text)
620
652
  text = text.dup
621
653
  last_line = @line.index + 1
@@ -633,10 +665,12 @@ module Haml
633
665
  raise e
634
666
  end
635
667
 
636
- attributes_hash = attributes_hash[1...-1] if attributes_hash
637
668
  return attributes_hash, rest, last_line
638
669
  end
639
670
 
671
+ # @return [Array<Hash,String,nil>] - [static_attributs (Hash), dynamic_attributes (nil or String starting with `{` and ending with `}`)]
672
+ # @return [String] rest
673
+ # @return [Integer] last_line
640
674
  def parse_new_attributes(text)
641
675
  scanner = StringScanner.new(text)
642
676
  last_line = @line.index + 1
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
 
3
4
  # This module makes Haml work with Rails using the template handler API.
@@ -1,35 +1,29 @@
1
- if defined?(ActiveSupport)
2
- # check for a compatible Rails version when Haml is loaded
3
- if (activesupport_spec = Gem.loaded_specs['activesupport'])
4
- if activesupport_spec.version.to_s < '3.2'
5
- raise Exception.new("\n\n** Haml now requires Rails 3.2 and later. Use Haml version 4.0.4\n\n")
6
- end
7
- end
1
+ # frozen_string_literal: true
2
+ require 'haml/template/options'
8
3
 
9
- require 'haml/template/options'
10
- ActiveSupport.on_load(:action_view) do
11
- require "haml/template"
12
-
13
- if defined? Erubi
14
- require "haml/helpers/safe_erubi_template"
15
- Haml::Filters::Erb.template_class = Haml::SafeErubiTemplate
16
- else
17
- require "haml/helpers/safe_erubis_template"
18
- Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
19
- end
4
+ # check for a compatible Rails version when Haml is loaded
5
+ if (activesupport_spec = Gem.loaded_specs['activesupport'])
6
+ if activesupport_spec.version.to_s < '3.2'
7
+ raise Exception.new("\n\n** Haml now requires Rails 3.2 and later. Use Haml version 4.0.4\n\n")
20
8
  end
21
9
  end
22
10
 
23
11
  module Haml
24
12
  class Railtie < ::Rails::Railtie
25
13
  initializer :haml do |app|
26
- require "haml/template"
27
- if defined?(::Sass::Rails::SassTemplate) && app.config.assets.enabled
28
- require "haml/sass_rails_filter"
29
- end
30
- Haml::Options.buffer_defaults.keys.each do |key|
31
- if Haml::Template.options.key?(key)
32
- Haml::Options.buffer_defaults[key] = Haml::Template.options[key]
14
+ ActiveSupport.on_load(:action_view) do
15
+ require "haml/template"
16
+
17
+ if defined?(::Sass::Rails::SassTemplate) && app.config.assets.enabled
18
+ require "haml/sass_rails_filter"
19
+ end
20
+
21
+ if defined? Erubi
22
+ require "haml/helpers/safe_erubi_template"
23
+ Haml::Filters::Erb.template_class = Haml::SafeErubiTemplate
24
+ else
25
+ require "haml/helpers/safe_erubis_template"
26
+ Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
33
27
  end
34
28
  end
35
29
  end
@@ -1,11 +1,24 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  module Filters
3
4
  # This is an extension of Sass::Rails's SassTemplate class that allows
4
5
  # Rails's asset helpers to be used inside Haml Sass filter.
5
6
  class SassRailsTemplate < ::Sass::Rails::SassTemplate
6
- def render(scope=Object.new, locals={}, &block)
7
- scope = ::Rails.application.assets.context_class.new(::Rails.application.assets, "/", "/")
8
- super
7
+ if Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('3.0.0')
8
+ def render(scope=Object.new, locals={}, &block)
9
+ environment = ::Sprockets::Railtie.build_environment(Rails.application)
10
+ scope = environment.context_class.new(
11
+ environment: environment,
12
+ filename: "/",
13
+ metadata: {}
14
+ )
15
+ super
16
+ end
17
+ else
18
+ def render(scope=Object.new, locals={}, &block)
19
+ scope = ::Rails.application.assets.context_class.new(::Rails.application.assets, "/", "/")
20
+ super
21
+ end
9
22
  end
10
23
 
11
24
  def sass_options(scope)
@@ -30,4 +43,4 @@ module Haml
30
43
  register_tilt_filter "Sass", :extend => "Css", :template_class => SassRailsTemplate
31
44
  register_tilt_filter "Scss", :extend => "Css", :template_class => ScssRailsTemplate
32
45
  end
33
- end
46
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'haml/template/options'
2
3
  if defined?(ActiveSupport)
3
4
  ActiveSupport.on_load(:action_view) do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # We keep options in its own self-contained file
2
3
  # so that we can load it independently in Rails 3,
3
4
  # where the full template stuff is lazy-loaded.
@@ -6,11 +7,20 @@ module Haml
6
7
  module Template
7
8
  extend self
8
9
 
9
- @options = {}
10
+ class Options < Hash
11
+ def []=(key, value)
12
+ super
13
+ if Haml::Options.buffer_defaults.key?(key)
14
+ Haml::Options.buffer_defaults[key] = value
15
+ end
16
+ end
17
+ end
18
+
19
+ @options = ::Haml::Template::Options.new
10
20
  # The options hash for Haml when used within Rails.
11
21
  # See {file:REFERENCE.md#options the Haml options documentation}.
12
22
  #
13
- # @return [{Symbol => Object}]
23
+ # @return [Haml::Template::Options<Symbol => Object>]
14
24
  attr_accessor :options
15
25
  end
16
26
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'temple'
2
3
  require 'haml/escapable'
3
4
  require 'haml/generator'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # A module to count lines of expected code. This would be faster than actual code generation
3
4
  # and counting newlines in it.
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: false
2
2
 
3
3
  begin
4
4
  require 'erubis/tiny'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
- VERSION = "5.0.0.beta.2"
3
+ VERSION = "5.0.0"
3
4
  end
@@ -12,93 +12,89 @@ class AttributeParserTeset < Haml::TestCase
12
12
  end
13
13
 
14
14
  if Haml::AttributeParser.available?
15
- it { assert_parse({}, '') }
15
+ it { assert_parse(nil, '') }
16
16
  it { assert_parse({}, '{}') }
17
17
 
18
18
  describe 'invalid hash' do
19
- it { assert_parse(nil, ' hash ') }
20
- it { assert_parse(nil, 'hash, foo: bar') }
21
- it { assert_parse(nil, ' {hash} ') }
22
- it { assert_parse(nil, ' { hash, foo: bar } ') }
19
+ it { assert_parse(nil, '{hash}') }
20
+ it { assert_parse(nil, '{hash, foo: bar}') }
21
+ it { assert_parse(nil, '{ {hash} }') }
22
+ it { assert_parse(nil, '{ { hash, foo: bar } }') }
23
+ it { assert_parse(nil, '{}.merge({})') }
24
+ end
25
+
26
+ describe 'non single hash' do
27
+ it { assert_parse(nil, '{ a: 0 };{}') }
28
+ it { assert_parse(nil, '{ a: 0 }[nil] = {}') }
23
29
  end
24
30
 
25
31
  describe 'dynamic key' do
26
- it { assert_parse(nil, 'foo => bar') }
27
- it { assert_parse(nil, '[] => bar') }
28
- it { assert_parse(nil, '[1,2,3] => bar') }
32
+ it { assert_parse(nil, '{foo => bar}') }
33
+ it { assert_parse(nil, '{[] => bar}') }
34
+ it { assert_parse(nil, '{[1,2,3] => bar}') }
29
35
  end
30
36
 
31
37
  describe 'foo: bar' do
32
- it { assert_parse({ '_' => '1' }, '_:1,') }
33
- it { assert_parse({ 'foo' => 'bar' }, ' foo: bar ') }
34
- it { assert_parse({ 'a' => 'b', 'c' => ':d' }, 'a: b, c: :d') }
35
- it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, 'a: [], c: "d"') }
36
- it { assert_parse({ '_' => '1' }, ' { _:1, } ') }
37
- it { assert_parse({ 'foo' => 'bar' }, ' { foo: bar } ') }
38
- it { assert_parse({ 'a' => 'b', 'c' => ':d' }, ' { a: b, c: :d } ') }
39
- it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, ' { a: [], c: "d" } ') }
38
+ it { assert_parse({ '_' => '1' }, '{_:1,}') }
39
+ it { assert_parse({ 'foo' => 'bar' }, '{ foo: bar }') }
40
+ it { assert_parse({ 'a' => 'b', 'c' => ':d' }, '{a: b, c: :d}') }
41
+ it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, '{a: [], c: "d"}') }
40
42
  end
41
43
 
42
44
  describe ':foo => bar' do
43
- it { assert_parse({ 'foo' => ':bar' }, ' :foo => :bar ') }
44
- it { assert_parse({ '_' => '"foo"' }, ':_=>"foo"') }
45
- it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ':a => [], c: "", :b => "#{3}"') }
46
- it { assert_parse({ 'foo' => ':bar' }, ' { :foo => :bar } ') }
47
- it { assert_parse({ '_' => '"foo"' }, ' { :_=>"foo" } ') }
48
- it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ' { :a => [], c: "", :b => "#{3}" } ') }
49
- it { assert_parse(nil, ':"f#{o}o" => bar') }
50
- it { assert_parse(nil, ':"#{f}oo" => bar') }
51
- it { assert_parse(nil, ':"#{foo}" => bar') }
45
+ it { assert_parse({ 'foo' => ':bar' }, '{ :foo => :bar }') }
46
+ it { assert_parse({ '_' => '"foo"' }, '{:_=>"foo"}') }
47
+ it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, '{:a => [], c: "", :b => "#{3}"}') }
48
+ it { assert_parse(nil, '{:"f#{o}o" => bar}') }
49
+ it { assert_parse(nil, '{:"#{f}oo" => bar}') }
50
+ it { assert_parse(nil, '{:"#{foo}" => bar}') }
52
51
  end
53
52
 
54
53
  describe '"foo" => bar' do
55
- it { assert_parse({ 'foo' => '[1]' }, '"foo"=>[1]') }
56
- it { assert_parse({ 'foo' => 'nya' }, " 'foo' => nya ") }
57
- it { assert_parse({ 'foo' => 'bar' }, '%q[foo] => bar ') }
54
+ it { assert_parse({ 'foo' => '[1]' }, '{"foo"=>[1]}') }
55
+ it { assert_parse({ 'foo' => 'nya' }, "{ 'foo' => nya }") }
56
+ it { assert_parse({ 'foo' => 'bar' }, '{%q[foo] => bar }') }
58
57
  it { assert_parse({ 'foo' => '[1]' }, ' { "foo"=>[1] } ') }
59
58
  it { assert_parse({ 'foo' => 'nya' }, " { 'foo' => nya } ") }
60
59
  it { assert_parse({ 'foo' => 'bar' }, ' { %q[foo] => bar } ') }
61
- it { assert_parse(nil, '"f#{o}o" => bar') }
62
- it { assert_parse(nil, '"#{f}oo" => bar') }
63
- it { assert_parse(nil, '"#{foo}" => bar') }
64
- it { assert_parse({ 'f#{o}o' => 'bar' }, '%q[f#{o}o] => bar ') }
65
- it { assert_parse({ 'f#{o}o' => 'bar' }, ' { %q[f#{o}o] => bar, } ') }
60
+ it { assert_parse(nil, '{"f#{o}o" => bar}') }
61
+ it { assert_parse(nil, '{"#{f}oo" => bar}') }
62
+ it { assert_parse(nil, '{"#{foo}" => bar}') }
63
+ it { assert_parse({ 'f#{o}o' => 'bar' }, '{ %q[f#{o}o] => bar }') }
64
+ it { assert_parse({ 'f#{o}o' => 'bar' }, '{ %q[f#{o}o] => bar, }') }
66
65
  it { assert_parse(nil, '%Q[f#{o}o] => bar ') }
67
66
  end
68
67
 
68
+ describe 'multi lines' do
69
+ it { assert_parse({ 'a' => 'b', 'c' => 'd' }, "{a: b,\nc: d}") }
70
+ end
71
+
69
72
  if RUBY_VERSION >= '2.2.0'
70
73
  describe '"foo": bar' do
71
- it { assert_parse({ 'foo' => '()' }, '"foo":()') }
72
- it { assert_parse({ 'foo' => 'nya' }, " 'foo': nya ") }
74
+ it { assert_parse({ 'foo' => '()' }, '{"foo":()}') }
75
+ it { assert_parse({ 'foo' => 'nya' }, " {'foo': nya} ") }
73
76
  it { assert_parse({ 'foo' => '()' }, ' { "foo":() , }') }
74
77
  it { assert_parse({ 'foo' => 'nya' }, " { 'foo': nya , }") }
75
- it { assert_parse(nil, '"f#{o}o": bar') }
76
- it { assert_parse(nil, '"#{f}oo": bar') }
77
- it { assert_parse(nil, '"#{foo}": bar') }
78
+ it { assert_parse(nil, '{"f#{o}o": bar}') }
79
+ it { assert_parse(nil, '{"#{f}oo": bar}') }
80
+ it { assert_parse(nil, '{"#{foo}": bar}') }
78
81
  end
79
82
  end
80
83
 
81
84
  describe 'nested array' do
82
- it { assert_parse({ 'foo' => '[1,2,]' }, 'foo: [1,2,],') }
83
- it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, 'foo: [1,2,[3,4],5],') }
84
- it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, 'foo: [1,2,[3,4],5],bar: [[1,2],],') }
85
- it { assert_parse({ 'foo' => '[1,2,]' }, ' { foo: [1,2,], } ') }
86
- it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, ' { foo: [1,2,[3,4],5], } ') }
87
- it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, ' { foo: [1,2,[3,4],5],bar: [[1,2],], } ') }
85
+ it { assert_parse({ 'foo' => '[1,2,]' }, '{foo: [1,2,],}') }
86
+ it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, '{foo: [1,2,[3,4],5],}') }
87
+ it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, '{foo: [1,2,[3,4],5],bar: [[1,2],],}') }
88
88
  end
89
89
 
90
90
  describe 'nested hash' do
91
- it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, 'foo: { }, bar: {}') }
92
- it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, 'foo: { bar: baz, hoge: fuga, }, ') }
93
- it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, 'data: { confirm: true, disable: false }, :hello => { world: foo, },') }
94
- it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, ' { foo: { }, bar: {} } ') }
95
- it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, ' { foo: { bar: baz, hoge: fuga, }, } ') }
96
- it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, ' { data: { confirm: true, disable: false }, :hello => { world: foo, }, } ') }
91
+ it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, '{foo: { }, bar: {}}') }
92
+ it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, '{foo: { bar: baz, hoge: fuga, }, }') }
93
+ it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, '{data: { confirm: true, disable: false }, :hello => { world: foo, },}') }
97
94
  end
98
95
 
99
96
  describe 'nested method' do
100
- it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, 'foo: bar(a, b), hoge: piyo(a, b,),') }
101
- it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, ' { foo: bar(a, b), hoge: piyo(a, b,), } ') }
97
+ it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, '{ foo: bar(a, b), hoge: piyo(a, b,), }') }
102
98
  end
103
99
  end
104
100
  end
@@ -1555,6 +1555,12 @@ HAML
1555
1555
  HAML
1556
1556
  end
1557
1557
 
1558
+ def test_hash_method_call_in_attributes
1559
+ assert_equal(%Q{<a foo='bar' hoge='fuga'></a>\n}, render(<<-HAML))
1560
+ - hash = {:hoge => :fuga}
1561
+ %a{{foo: 'bar'}.merge(hash)}
1562
+ HAML
1563
+ end
1558
1564
 
1559
1565
  def test_html5_data_attributes_with_nested_hash
1560
1566
  assert_equal("<div data-a-b='c'></div>\n", render(<<-HAML))
@@ -9,11 +9,12 @@ module Haml
9
9
  )
10
10
  end
11
11
 
12
- def test_buffer_defaults_values_are_default_options
12
+ def test_buffer_defaults_values_are_the_same_as_rails_defaults
13
+ rails_defaults = Haml::Options.defaults.merge(Haml::Template.options)
13
14
  Haml::Options.buffer_option_keys.each do |key|
14
15
  assert_equal(
15
- Haml::Options.defaults[key],
16
- Haml::Options.buffer_defaults[key],
16
+ rails_defaults[key],
17
+ Haml::Options.buffer_defaults[key], "key: #{key}"
17
18
  )
18
19
  end
19
20
  end
@@ -0,0 +1,4 @@
1
+ <div class='o-media@md c-user c-user--premium'>
2
+ <img alt='' class='o-media__img@md c-user__photo c-avatar' src='' />
3
+ <p class='o-media__body@md c-user__bio'>...</p>
4
+ </div>
@@ -8,7 +8,7 @@ class TemplateTest < Haml::TestCase
8
8
  TEMPLATES = %w{ very_basic standard helpers
9
9
  whitespace_handling original_engine list helpful
10
10
  silent_script tag_parsing just_stuff partials
11
- nuke_outer_whitespace nuke_inner_whitespace
11
+ nuke_outer_whitespace nuke_inner_whitespace bemit
12
12
  render_layout partial_layout partial_layout_erb}
13
13
 
14
14
  def setup
@@ -0,0 +1,3 @@
1
+ .o-media@md.c-user.c-user--premium
2
+ %img.o-media__img@md.c-user__photo.c-avatar{src: '', alt: ''}
3
+ %p.o-media__body@md.c-user__bio ...
@@ -26,6 +26,7 @@ if defined?(I18n.enforce_available_locales)
26
26
  end
27
27
 
28
28
  class TestApp < Rails::Application
29
+ config.eager_load = false
29
30
  config.root = ""
30
31
  end
31
32
  Rails.application = TestApp
@@ -39,6 +40,8 @@ $VERBOSE = true
39
40
  require 'haml'
40
41
  require 'haml/template'
41
42
 
43
+ TestApp.initialize!
44
+
42
45
  Haml::Template.options[:format] = :xhtml
43
46
 
44
47
  BASE_TEST_CLASS = if defined?(Minitest::Test)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.beta.2
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Natalie Weizenbaum
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2017-02-26 00:00:00.000000000 Z
14
+ date: 2017-04-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: temple
@@ -166,6 +166,7 @@ files:
166
166
  - test/mocks/article.rb
167
167
  - test/options_test.rb
168
168
  - test/parser_test.rb
169
+ - test/results/bemit.xhtml
169
170
  - test/results/content_for_layout.xhtml
170
171
  - test/results/eval_suppressed.xhtml
171
172
  - test/results/helpers.xhtml
@@ -194,6 +195,7 @@ files:
194
195
  - test/templates/_text_area.haml
195
196
  - test/templates/_text_area_helper.html.haml
196
197
  - test/templates/action_view.haml
198
+ - test/templates/bemit.haml
197
199
  - test/templates/breakage.haml
198
200
  - test/templates/content_for_layout.haml
199
201
  - test/templates/eval_suppressed.haml
@@ -234,12 +236,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
234
236
  version: 2.0.0
235
237
  required_rubygems_version: !ruby/object:Gem::Requirement
236
238
  requirements:
237
- - - ">"
239
+ - - ">="
238
240
  - !ruby/object:Gem::Version
239
- version: 1.3.1
241
+ version: '0'
240
242
  requirements: []
241
243
  rubyforge_project:
242
- rubygems_version: 2.6.10
244
+ rubygems_version: 2.6.11
243
245
  signing_key:
244
246
  specification_version: 4
245
247
  summary: An elegant, structured (X)HTML/XML templating engine.