haml 5.0.0.beta.2 → 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 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.