haml 4.0.7 → 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 +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +42 -4
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +108 -57
- data/Rakefile +46 -54
- 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 +22 -132
- data/lib/haml/compiler.rb +87 -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 +18 -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 +36 -58
- 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 +4 -1
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +133 -90
- data/lib/haml/options.rb +38 -47
- data/lib/haml/parser.rb +278 -216
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -12
- 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 +1 -0
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +287 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +9 -3
- 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 +224 -112
- 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 +77 -76
- data/test/template_test.rb +24 -56
- data/test/template_test_helper.rb +38 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- 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 -8
- data/test/util_test.rb +6 -47
- metadata +53 -43
- 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/haml-spec/LICENSE +0 -14
- data/test/haml-spec/README.md +0 -106
- data/test/haml-spec/lua_haml_spec.lua +0 -38
- data/test/haml-spec/perl_haml_test.pl +0 -81
- data/test/haml-spec/ruby_haml_test.rb +0 -23
- data/test/haml-spec/tests.json +0 -660
- 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/util.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'erubis/tiny'
|
3
5
|
rescue LoadError
|
@@ -12,38 +14,6 @@ module Haml
|
|
12
14
|
module Util
|
13
15
|
extend self
|
14
16
|
|
15
|
-
# Computes the powerset of the given array.
|
16
|
-
# This is the set of all subsets of the array.
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# powerset([1, 2, 3]) #=>
|
20
|
-
# Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
|
21
|
-
# @param arr [Enumerable]
|
22
|
-
# @return [Set<Set>] The subsets of `arr`
|
23
|
-
def powerset(arr)
|
24
|
-
arr.inject([Set.new].to_set) do |powerset, el|
|
25
|
-
new_powerset = Set.new
|
26
|
-
powerset.each do |subset|
|
27
|
-
new_powerset << subset
|
28
|
-
new_powerset << subset + [el]
|
29
|
-
end
|
30
|
-
new_powerset
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Returns information about the caller of the previous method.
|
35
|
-
#
|
36
|
-
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
37
|
-
# @return [[String, Fixnum, (String, nil)]] An array containing the filename, line, and method name of the caller.
|
38
|
-
# The method name may be nil
|
39
|
-
def caller_info(entry = caller[1])
|
40
|
-
info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
|
41
|
-
info[1] = info[1].to_i
|
42
|
-
# This is added by Rubinius to designate a block, but we don't care about it.
|
43
|
-
info[2].sub!(/ \{\}\Z/, '') if info[2]
|
44
|
-
info
|
45
|
-
end
|
46
|
-
|
47
17
|
# Silence all output to STDERR within a block.
|
48
18
|
#
|
49
19
|
# @yield A block in which no output will be printed to STDERR
|
@@ -54,19 +24,6 @@ module Haml
|
|
54
24
|
$stderr = the_real_stderr
|
55
25
|
end
|
56
26
|
|
57
|
-
# Returns an ActionView::Template* class.
|
58
|
-
# In pre-3.0 versions of Rails, most of these classes
|
59
|
-
# were of the form `ActionView::TemplateFoo`,
|
60
|
-
# while afterwards they were of the form `ActionView;:Template::Foo`.
|
61
|
-
#
|
62
|
-
# @param name [#to_s] The name of the class to get.
|
63
|
-
# For example, `:Error` will return `ActionView::TemplateError`
|
64
|
-
# or `ActionView::Template::Error`.
|
65
|
-
def av_template_class(name)
|
66
|
-
return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
|
67
|
-
return ActionView::Template.const_get(name.to_s)
|
68
|
-
end
|
69
|
-
|
70
27
|
## Rails XSS Safety
|
71
28
|
|
72
29
|
# Whether or not ActionView's XSS protection is available and enabled,
|
@@ -82,6 +39,9 @@ module Haml
|
|
82
39
|
# With older versions of the Rails XSS-safety mechanism,
|
83
40
|
# this destructively modifies the HTML-safety of `text`.
|
84
41
|
#
|
42
|
+
# It only works if you are using ActiveSupport or the parameter `text`
|
43
|
+
# implements the #html_safe method.
|
44
|
+
#
|
85
45
|
# @param text [String, nil]
|
86
46
|
# @return [String, nil] `text`, marked as HTML-safe
|
87
47
|
def html_safe(text)
|
@@ -89,174 +49,89 @@ module Haml
|
|
89
49
|
text.html_safe
|
90
50
|
end
|
91
51
|
|
92
|
-
# Checks that the encoding of a string is valid
|
52
|
+
# Checks that the encoding of a string is valid
|
93
53
|
# and cleans up potential encoding gotchas like the UTF-8 BOM.
|
94
54
|
# If it's not, yields an error string describing the invalid character
|
95
|
-
# and the line on which it
|
55
|
+
# and the line on which it occurs.
|
96
56
|
#
|
97
57
|
# @param str [String] The string of which to check the encoding
|
98
58
|
# @yield [msg] A block in which an encoding error can be raised.
|
99
59
|
# Only yields if there is an encoding error
|
100
60
|
# @yieldparam msg [String] The error message to be raised
|
101
61
|
# @return [String] `str`, potentially with encoding gotchas like BOMs removed
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding.name)), '')
|
113
|
-
else
|
114
|
-
return str
|
115
|
-
end
|
62
|
+
def check_encoding(str)
|
63
|
+
if str.valid_encoding?
|
64
|
+
# Get rid of the Unicode BOM if possible
|
65
|
+
# Shortcut for UTF-8 which might be the majority case
|
66
|
+
if str.encoding == Encoding::UTF_8
|
67
|
+
return str.gsub(/\A\uFEFF/, '')
|
68
|
+
elsif str.encoding.name =~ /^UTF-(16|32)(BE|LE)?$/
|
69
|
+
return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding)), '')
|
70
|
+
else
|
71
|
+
return str
|
116
72
|
end
|
73
|
+
end
|
117
74
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
75
|
+
encoding = str.encoding
|
76
|
+
newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding(Encoding::ASCII_8BIT))
|
77
|
+
str.force_encoding(Encoding::ASCII_8BIT).split(newlines).each_with_index do |line, i|
|
78
|
+
begin
|
79
|
+
line.encode(encoding)
|
80
|
+
rescue Encoding::UndefinedConversionError => e
|
81
|
+
yield <<MSG.rstrip, i + 1
|
125
82
|
Invalid #{encoding.name} character #{e.error_char.dump}
|
126
83
|
MSG
|
127
|
-
end
|
128
84
|
end
|
129
|
-
return str
|
130
85
|
end
|
86
|
+
return str
|
131
87
|
end
|
132
88
|
|
133
|
-
|
134
|
-
|
135
|
-
# at the beginning of the template and uses that encoding if it exists.
|
136
|
-
#
|
137
|
-
# The Haml encoding rules are simple.
|
138
|
-
# If a `-# coding:` comment exists,
|
139
|
-
# we assume that that's the original encoding of the document.
|
140
|
-
# Otherwise, we use whatever encoding Ruby has.
|
141
|
-
#
|
142
|
-
# Haml uses the same rules for parsing coding comments as Ruby.
|
143
|
-
# This means that it can understand Emacs-style comments
|
144
|
-
# (e.g. `-*- encoding: "utf-8" -*-`),
|
145
|
-
# and also that it cannot understand non-ASCII-compatible encodings
|
146
|
-
# such as `UTF-16` and `UTF-32`.
|
147
|
-
#
|
148
|
-
# @param str [String] The Haml template of which to check the encoding
|
149
|
-
# @yield [msg] A block in which an encoding error can be raised.
|
150
|
-
# Only yields if there is an encoding error
|
151
|
-
# @yieldparam msg [String] The error message to be raised
|
152
|
-
# @return [String] The original string encoded properly
|
153
|
-
# @raise [ArgumentError] if the document declares an unknown encoding
|
154
|
-
def check_haml_encoding(str, &block)
|
155
|
-
check_encoding(str, &block)
|
156
|
-
end
|
157
|
-
else
|
158
|
-
def check_haml_encoding(str, &block)
|
159
|
-
str = str.dup if str.frozen?
|
160
|
-
|
161
|
-
bom, encoding = parse_haml_magic_comment(str)
|
162
|
-
if encoding; str.force_encoding(encoding)
|
163
|
-
elsif bom; str.force_encoding("UTF-8")
|
164
|
-
end
|
165
|
-
|
166
|
-
return check_encoding(str, &block)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
if RUBY_VERSION < "1.9.2"
|
171
|
-
def inspect_obj(obj)
|
172
|
-
return obj.inspect
|
173
|
-
end
|
174
|
-
else
|
175
|
-
# Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them under Ruby 1.9.2.
|
176
|
-
# This is necessary so that the precompiled Haml template can be `#encode`d into `@options[:encoding]`
|
177
|
-
# before being evaluated.
|
178
|
-
#
|
179
|
-
# @param obj {Object}
|
180
|
-
# @return {String}
|
181
|
-
def inspect_obj(obj)
|
182
|
-
return ':' + inspect_obj(obj.to_s) if obj.is_a?(Symbol)
|
183
|
-
return obj.inspect unless obj.is_a?(String)
|
184
|
-
'"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
## Static Method Stuff
|
189
|
-
|
190
|
-
# The context in which the ERB for \{#def\_static\_method} will be run.
|
191
|
-
class StaticConditionalContext
|
192
|
-
# @param set [#include?] The set of variables that are defined for this context.
|
193
|
-
def initialize(set)
|
194
|
-
@set = set
|
195
|
-
end
|
196
|
-
|
197
|
-
# Checks whether or not a variable is defined for this context.
|
198
|
-
#
|
199
|
-
# @param name [Symbol] The name of the variable
|
200
|
-
# @return [Boolean]
|
201
|
-
def method_missing(name, *args, &block)
|
202
|
-
super unless args.empty? && block.nil?
|
203
|
-
@set.include?(name)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
# This is used for methods in {Haml::Buffer} that need to be very fast,
|
208
|
-
# and take a lot of boolean parameters
|
209
|
-
# that are known at compile-time.
|
210
|
-
# Instead of passing the parameters in normally,
|
211
|
-
# a separate method is defined for every possible combination of those parameters;
|
212
|
-
# these are then called using \{#static\_method\_name}.
|
89
|
+
# Like {\#check\_encoding}, but also checks for a Ruby-style `-# coding:` comment
|
90
|
+
# at the beginning of the template and uses that encoding if it exists.
|
213
91
|
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
# def_static_method(Foo, :my_static_method, [:foo, :bar], :baz, :bang, <<RUBY)
|
220
|
-
# <% if baz && bang %>
|
221
|
-
# return foo + bar
|
222
|
-
# <% elsif baz || bang %>
|
223
|
-
# return foo - bar
|
224
|
-
# <% else %>
|
225
|
-
# return 17
|
226
|
-
# <% end %>
|
227
|
-
# RUBY
|
92
|
+
# The Haml encoding rules are simple.
|
93
|
+
# If a `-# coding:` comment exists,
|
94
|
+
# we assume that that's the original encoding of the document.
|
95
|
+
# Otherwise, we use whatever encoding Ruby has.
|
228
96
|
#
|
229
|
-
#
|
97
|
+
# Haml uses the same rules for parsing coding comments as Ruby.
|
98
|
+
# This means that it can understand Emacs-style comments
|
99
|
+
# (e.g. `-*- encoding: "utf-8" -*-`),
|
100
|
+
# and also that it cannot understand non-ASCII-compatible encodings
|
101
|
+
# such as `UTF-16` and `UTF-32`.
|
230
102
|
#
|
231
|
-
# @
|
232
|
-
# @
|
233
|
-
#
|
234
|
-
# @
|
235
|
-
#
|
236
|
-
# @
|
237
|
-
|
238
|
-
|
239
|
-
erb = vars.pop
|
240
|
-
info = caller_info
|
241
|
-
powerset(vars).each do |set|
|
242
|
-
context = StaticConditionalContext.new(set).instance_eval {binding}
|
243
|
-
method_content = (defined?(Erubis::TinyEruby) && Erubis::TinyEruby || ERB).new(erb).result(context)
|
103
|
+
# @param str [String] The Haml template of which to check the encoding
|
104
|
+
# @yield [msg] A block in which an encoding error can be raised.
|
105
|
+
# Only yields if there is an encoding error
|
106
|
+
# @yieldparam msg [String] The error message to be raised
|
107
|
+
# @return [String] The original string encoded properly
|
108
|
+
# @raise [ArgumentError] if the document declares an unknown encoding
|
109
|
+
def check_haml_encoding(str, &block)
|
110
|
+
str = str.dup if str.frozen?
|
244
111
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
end
|
249
|
-
METHOD
|
112
|
+
bom, encoding = parse_haml_magic_comment(str)
|
113
|
+
if encoding; str.force_encoding(encoding)
|
114
|
+
elsif bom; str.force_encoding(Encoding::UTF_8)
|
250
115
|
end
|
116
|
+
|
117
|
+
return check_encoding(str, &block)
|
251
118
|
end
|
252
119
|
|
253
|
-
#
|
120
|
+
# Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them.
|
121
|
+
# This is necessary so that the precompiled Haml template can be `#encode`d into `@options[:encoding]`
|
122
|
+
# before being evaluated.
|
254
123
|
#
|
255
|
-
# @param
|
256
|
-
# @
|
257
|
-
|
258
|
-
|
259
|
-
|
124
|
+
# @param obj {Object}
|
125
|
+
# @return {String}
|
126
|
+
def inspect_obj(obj)
|
127
|
+
case obj
|
128
|
+
when String
|
129
|
+
%Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
|
130
|
+
when Symbol
|
131
|
+
":#{inspect_obj(obj.to_s)}"
|
132
|
+
else
|
133
|
+
obj.inspect
|
134
|
+
end
|
260
135
|
end
|
261
136
|
|
262
137
|
# Scans through a string looking for the interoplation-opening `#{`
|
@@ -271,7 +146,7 @@ METHOD
|
|
271
146
|
# @return [String] The text remaining in the scanner after all `#{`s have been processed
|
272
147
|
def handle_interpolation(str)
|
273
148
|
scan = StringScanner.new(str)
|
274
|
-
yield scan while scan.scan(/(.*?)(\\*)
|
149
|
+
yield scan while scan.scan(/(.*?)(\\*)#([\{@$])/)
|
275
150
|
scan.rest
|
276
151
|
end
|
277
152
|
|
@@ -283,10 +158,8 @@ METHOD
|
|
283
158
|
# from to
|
284
159
|
#
|
285
160
|
# @param scanner [StringScanner] The string scanner to move
|
286
|
-
# @param start [
|
287
|
-
#
|
288
|
-
# @param finish [Character] The character closing the balanced pair.
|
289
|
-
# A `Fixnum` in 1.8, a `String` in 1.9
|
161
|
+
# @param start [String] The character opening the balanced pair.
|
162
|
+
# @param finish [String] The character closing the balanced pair.
|
290
163
|
# @param count [Fixnum] The number of opening characters matched
|
291
164
|
# before calling this method
|
292
165
|
# @return [(String, String)] The string matched within the balanced pair
|
@@ -322,20 +195,28 @@ METHOD
|
|
322
195
|
end
|
323
196
|
|
324
197
|
def contains_interpolation?(str)
|
325
|
-
str
|
198
|
+
/#[\{$@]/ === str
|
326
199
|
end
|
327
200
|
|
328
201
|
def unescape_interpolation(str, escape_html = nil)
|
329
202
|
res = ''
|
330
203
|
rest = Haml::Util.handle_interpolation str.dump do |scan|
|
331
204
|
escapes = (scan[2].size - 1) / 2
|
205
|
+
char = scan[3] # '{', '@' or '$'
|
332
206
|
res << scan.matched[0...-3 - escapes]
|
333
207
|
if escapes % 2 == 1
|
334
|
-
res <<
|
208
|
+
res << "\##{char}"
|
335
209
|
else
|
336
|
-
|
210
|
+
interpolated = if char == '{'
|
211
|
+
balance(scan, ?{, ?}, 1)[0][0...-1]
|
212
|
+
else
|
213
|
+
scan.scan(/\w+/)
|
214
|
+
end
|
215
|
+
content = eval('"' + interpolated + '"')
|
216
|
+
content.prepend(char) if char == '@' || char == '$'
|
337
217
|
content = "Haml::Helpers.html_escape((#{content}))" if escape_html
|
338
|
-
|
218
|
+
|
219
|
+
res << "\#{#{content}}"
|
339
220
|
end
|
340
221
|
end
|
341
222
|
res + rest
|
@@ -350,7 +231,7 @@ METHOD
|
|
350
231
|
# Whether the document begins with a UTF-8 BOM,
|
351
232
|
# and the declared encoding of the document (or nil if none is declared)
|
352
233
|
def parse_haml_magic_comment(str)
|
353
|
-
scanner = StringScanner.new(str.dup.force_encoding(
|
234
|
+
scanner = StringScanner.new(str.dup.force_encoding(Encoding::ASCII_8BIT))
|
354
235
|
bom = scanner.scan(/\xEF\xBB\xBF/n)
|
355
236
|
return bom unless scanner.scan(/-\s*#\s*/n)
|
356
237
|
if coding = try_parse_haml_emacs_magic_comment(scanner)
|
data/lib/haml/version.rb
CHANGED
data/lib/haml.rb
CHANGED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AttributeParserTeset < Haml::TestCase
|
4
|
+
describe '.parse' do
|
5
|
+
def assert_parse(expected, haml)
|
6
|
+
actual = Haml::AttributeParser.parse(haml)
|
7
|
+
if expected.nil?
|
8
|
+
assert_nil actual
|
9
|
+
else
|
10
|
+
assert_equal expected, actual
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if Haml::AttributeParser.available?
|
15
|
+
it { assert_parse(nil, '') }
|
16
|
+
it { assert_parse({}, '{}') }
|
17
|
+
|
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 } }') }
|
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] = {}') }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'dynamic key' do
|
32
|
+
it { assert_parse(nil, '{foo => bar}') }
|
33
|
+
it { assert_parse(nil, '{[] => bar}') }
|
34
|
+
it { assert_parse(nil, '{[1,2,3] => bar}') }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'foo: bar' do
|
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"}') }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe ':foo => bar' do
|
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}') }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '"foo" => bar' do
|
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 }') }
|
57
|
+
it { assert_parse({ 'foo' => '[1]' }, ' { "foo"=>[1] } ') }
|
58
|
+
it { assert_parse({ 'foo' => 'nya' }, " { 'foo' => nya } ") }
|
59
|
+
it { assert_parse({ 'foo' => 'bar' }, ' { %q[foo] => 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, }') }
|
65
|
+
it { assert_parse(nil, '%Q[f#{o}o] => bar ') }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'multi lines' do
|
69
|
+
it { assert_parse({ 'a' => 'b', 'c' => 'd' }, "{a: b,\nc: d}") }
|
70
|
+
end
|
71
|
+
|
72
|
+
if RUBY_VERSION >= '2.2.0'
|
73
|
+
describe '"foo": bar' do
|
74
|
+
it { assert_parse({ 'foo' => '()' }, '{"foo":()}') }
|
75
|
+
it { assert_parse({ 'foo' => 'nya' }, " {'foo': nya} ") }
|
76
|
+
it { assert_parse({ 'foo' => '()' }, ' { "foo":() , }') }
|
77
|
+
it { assert_parse({ 'foo' => 'nya' }, " { 'foo': nya , }") }
|
78
|
+
it { assert_parse(nil, '{"f#{o}o": bar}') }
|
79
|
+
it { assert_parse(nil, '{"#{f}oo": bar}') }
|
80
|
+
it { assert_parse(nil, '{"#{foo}": bar}') }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'nested array' do
|
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
|
+
end
|
89
|
+
|
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
|
+
end
|
95
|
+
|
96
|
+
describe 'nested method' do
|
97
|
+
it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, '{ foo: bar(a, b), hoge: piyo(a, b,), }') }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|