haml 4.1.0.beta.1 → 5.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +36 -6
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +81 -48
- data/REFERENCE.md +86 -50
- data/Rakefile +28 -41
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +214 -0
- data/lib/haml/attribute_parser.rb +112 -0
- data/lib/haml/buffer.rb +24 -126
- data/lib/haml/compiler.rb +62 -281
- data/lib/haml/engine.rb +16 -23
- data/lib/haml/error.rb +2 -0
- data/lib/haml/escapable.rb +48 -0
- data/lib/haml/exec.rb +23 -12
- data/lib/haml/filters.rb +3 -4
- data/lib/haml/generator.rb +36 -0
- data/lib/haml/helpers.rb +61 -48
- data/lib/haml/helpers/action_view_extensions.rb +1 -1
- data/lib/haml/helpers/action_view_mods.rb +32 -50
- data/lib/haml/helpers/safe_erubi_template.rb +26 -0
- data/lib/haml/helpers/safe_erubis_template.rb +2 -0
- data/lib/haml/helpers/xss_mods.rb +17 -12
- data/lib/haml/options.rb +32 -36
- data/lib/haml/parser.rb +61 -38
- data/lib/haml/{template/plugin.rb → plugin.rb} +5 -2
- data/lib/haml/railtie.rb +14 -6
- data/lib/haml/template.rb +11 -6
- data/lib/haml/temple_engine.rb +119 -0
- data/lib/haml/temple_line_counter.rb +28 -0
- data/lib/haml/util.rb +17 -112
- data/lib/haml/version.rb +1 -1
- data/test/attribute_parser_test.rb +105 -0
- data/test/engine_test.rb +202 -106
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +7 -1
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +57 -71
- 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 +156 -109
- data/test/options_test.rb +21 -0
- data/test/parser_test.rb +49 -4
- 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 +21 -48
- data/test/template_test_helper.rb +38 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/standard_ugly.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +10 -10
- data/test/util_test.rb +1 -48
- metadata +49 -35
- data/lib/haml/temple.rb +0 -85
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -4
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/standard_ugly.haml +0 -43
@@ -6,13 +6,16 @@ module Haml
|
|
6
6
|
|
7
7
|
def compile(template)
|
8
8
|
options = Haml::Template.options.dup
|
9
|
-
if
|
9
|
+
if template.respond_to?(:type)
|
10
10
|
options[:mime_type] = template.type
|
11
11
|
elsif template.respond_to? :mime_type
|
12
12
|
options[:mime_type] = template.mime_type
|
13
13
|
end
|
14
14
|
options[:filename] = template.identifier
|
15
|
-
Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles(
|
15
|
+
Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles(
|
16
|
+
[],
|
17
|
+
after_preamble: '@output_buffer = output_buffer ||= ActionView::OutputBuffer.new if defined?(ActionView::OutputBuffer)',
|
18
|
+
)
|
16
19
|
end
|
17
20
|
|
18
21
|
def self.call(template)
|
data/lib/haml/railtie.rb
CHANGED
@@ -7,9 +7,15 @@ if defined?(ActiveSupport)
|
|
7
7
|
end
|
8
8
|
|
9
9
|
require 'haml/template/options'
|
10
|
-
ActiveSupport.on_load(:
|
11
|
-
|
12
|
-
|
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
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -21,9 +27,11 @@ module Haml
|
|
21
27
|
if defined?(::Sass::Rails::SassTemplate) && app.config.assets.enabled
|
22
28
|
require "haml/sass_rails_filter"
|
23
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]
|
33
|
+
end
|
34
|
+
end
|
24
35
|
end
|
25
36
|
end
|
26
37
|
end
|
27
|
-
|
28
|
-
require "haml/helpers/safe_erubis_template"
|
29
|
-
Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
|
data/lib/haml/template.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
require 'haml/template/options'
|
2
|
-
|
3
|
-
|
4
|
-
require 'haml/helpers/
|
2
|
+
if defined?(ActiveSupport)
|
3
|
+
ActiveSupport.on_load(:action_view) do
|
4
|
+
require 'haml/helpers/action_view_mods'
|
5
|
+
require 'haml/helpers/action_view_extensions'
|
6
|
+
end
|
7
|
+
else
|
8
|
+
require 'haml/helpers/action_view_mods'
|
9
|
+
require 'haml/helpers/action_view_extensions'
|
10
|
+
end
|
5
11
|
require 'haml/helpers/xss_mods'
|
6
12
|
require 'haml/helpers/action_view_xss_mods'
|
7
13
|
|
8
14
|
module Haml
|
9
|
-
class
|
15
|
+
class TempleEngine
|
10
16
|
def precompiled_method_return_value_with_haml_xss
|
11
17
|
"::Haml::Util.html_safe(#{precompiled_method_return_value_without_haml_xss})"
|
12
18
|
end
|
@@ -26,7 +32,6 @@ module Haml
|
|
26
32
|
end
|
27
33
|
|
28
34
|
|
29
|
-
Haml::Template.options[:ugly] = defined?(Rails) ? !Rails.env.development? : true
|
30
35
|
Haml::Template.options[:escape_html] = true
|
31
36
|
|
32
|
-
require 'haml/
|
37
|
+
require 'haml/plugin'
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'temple'
|
2
|
+
require 'haml/escapable'
|
3
|
+
require 'haml/generator'
|
4
|
+
|
5
|
+
module Haml
|
6
|
+
class TempleEngine < Temple::Engine
|
7
|
+
define_options(
|
8
|
+
attr_wrapper: "'",
|
9
|
+
autoclose: %w(area base basefont br col command embed frame
|
10
|
+
hr img input isindex keygen link menuitem meta
|
11
|
+
param source track wbr),
|
12
|
+
encoding: nil,
|
13
|
+
escape_attrs: true,
|
14
|
+
escape_html: false,
|
15
|
+
filename: '(haml)',
|
16
|
+
format: :html5,
|
17
|
+
hyphenate_data_attrs: true,
|
18
|
+
line: 1,
|
19
|
+
mime_type: 'text/html',
|
20
|
+
preserve: %w(textarea pre code),
|
21
|
+
remove_whitespace: false,
|
22
|
+
suppress_eval: false,
|
23
|
+
cdata: false,
|
24
|
+
parser_class: ::Haml::Parser,
|
25
|
+
compiler_class: ::Haml::Compiler,
|
26
|
+
trace: false,
|
27
|
+
)
|
28
|
+
|
29
|
+
use :Parser, -> { options[:parser_class] }
|
30
|
+
use :Compiler, -> { options[:compiler_class] }
|
31
|
+
use Escapable
|
32
|
+
filter :ControlFlow
|
33
|
+
filter :MultiFlattener
|
34
|
+
filter :StaticMerger
|
35
|
+
use Generator
|
36
|
+
|
37
|
+
def compile(template)
|
38
|
+
initialize_encoding(template, options[:encoding])
|
39
|
+
@precompiled = call(template)
|
40
|
+
end
|
41
|
+
|
42
|
+
# The source code that is evaluated to produce the Haml document.
|
43
|
+
#
|
44
|
+
# This is automatically converted to the correct encoding
|
45
|
+
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
def precompiled
|
49
|
+
encoding = Encoding.find(@encoding || '')
|
50
|
+
return @precompiled.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT
|
51
|
+
return @precompiled.encode(encoding)
|
52
|
+
end
|
53
|
+
|
54
|
+
def precompiled_with_return_value
|
55
|
+
"#{precompiled};#{precompiled_method_return_value}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# The source code that is evaluated to produce the Haml document.
|
59
|
+
#
|
60
|
+
# This is automatically converted to the correct encoding
|
61
|
+
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
def precompiled_with_ambles(local_names, after_preamble: '')
|
65
|
+
preamble = <<END.tr!("\n", ';')
|
66
|
+
begin
|
67
|
+
extend Haml::Helpers
|
68
|
+
_hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, #{Options.new(options).for_buffer.inspect})
|
69
|
+
_erbout = _hamlout.buffer
|
70
|
+
#{after_preamble}
|
71
|
+
END
|
72
|
+
postamble = <<END.tr!("\n", ';')
|
73
|
+
#{precompiled_method_return_value}
|
74
|
+
ensure
|
75
|
+
@haml_buffer = @haml_buffer.upper if @haml_buffer
|
76
|
+
end
|
77
|
+
END
|
78
|
+
"#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}"
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def initialize_encoding(template, given_value)
|
84
|
+
if given_value
|
85
|
+
@encoding = given_value
|
86
|
+
else
|
87
|
+
@encoding = Encoding.default_internal || template.encoding
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns the string used as the return value of the precompiled method.
|
92
|
+
# This method exists so it can be monkeypatched to return modified values.
|
93
|
+
def precompiled_method_return_value
|
94
|
+
"_erbout"
|
95
|
+
end
|
96
|
+
|
97
|
+
def locals_code(names)
|
98
|
+
names = names.keys if Hash === names
|
99
|
+
|
100
|
+
names.each_with_object('') do |name, code|
|
101
|
+
# Can't use || because someone might explicitly pass in false with a symbol
|
102
|
+
sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
|
103
|
+
str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
|
104
|
+
code << "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def inspect_obj(obj)
|
109
|
+
case obj
|
110
|
+
when String
|
111
|
+
%Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
|
112
|
+
when Symbol
|
113
|
+
":#{inspect_obj(obj.to_s)}"
|
114
|
+
else
|
115
|
+
obj.inspect
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Haml
|
2
|
+
# A module to count lines of expected code. This would be faster than actual code generation
|
3
|
+
# and counting newlines in it.
|
4
|
+
module TempleLineCounter
|
5
|
+
class UnexpectedExpression < StandardError; end
|
6
|
+
|
7
|
+
def self.count_lines(exp)
|
8
|
+
type, *args = exp
|
9
|
+
case type
|
10
|
+
when :multi
|
11
|
+
args.map { |a| count_lines(a) }.reduce(:+) || 0
|
12
|
+
when :dynamic, :code
|
13
|
+
args.first.count("\n")
|
14
|
+
when :static
|
15
|
+
0 # It has not real newline "\n" but escaped "\\n".
|
16
|
+
when :case
|
17
|
+
arg, *cases = args
|
18
|
+
arg.count("\n") + cases.map do |cond, e|
|
19
|
+
(cond == :else ? 0 : cond.count("\n")) + count_lines(e)
|
20
|
+
end.reduce(:+)
|
21
|
+
when :escape
|
22
|
+
count_lines(args[1])
|
23
|
+
else
|
24
|
+
raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/haml/util.rb
CHANGED
@@ -14,38 +14,6 @@ module Haml
|
|
14
14
|
module Util
|
15
15
|
extend self
|
16
16
|
|
17
|
-
# Computes the powerset of the given array.
|
18
|
-
# This is the set of all subsets of the array.
|
19
|
-
#
|
20
|
-
# @example
|
21
|
-
# powerset([1, 2, 3]) #=>
|
22
|
-
# Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
|
23
|
-
# @param arr [Enumerable]
|
24
|
-
# @return [Set<Set>] The subsets of `arr`
|
25
|
-
def powerset(arr)
|
26
|
-
arr.inject([Set.new].to_set) do |powerset, el|
|
27
|
-
new_powerset = Set.new
|
28
|
-
powerset.each do |subset|
|
29
|
-
new_powerset << subset
|
30
|
-
new_powerset << subset + [el]
|
31
|
-
end
|
32
|
-
new_powerset
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Returns information about the caller of the previous method.
|
37
|
-
#
|
38
|
-
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
39
|
-
# @return [[String, Fixnum, (String, nil)]] An array containing the filename, line, and method name of the caller.
|
40
|
-
# The method name may be nil
|
41
|
-
def caller_info(entry = caller[1])
|
42
|
-
info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
|
43
|
-
info[1] = info[1].to_i
|
44
|
-
# This is added by Rubinius to designate a block, but we don't care about it.
|
45
|
-
info[2].sub!(/ \{\}\Z/, '') if info[2]
|
46
|
-
info
|
47
|
-
end
|
48
|
-
|
49
17
|
# Silence all output to STDERR within a block.
|
50
18
|
#
|
51
19
|
# @yield A block in which no output will be printed to STDERR
|
@@ -71,6 +39,9 @@ module Haml
|
|
71
39
|
# With older versions of the Rails XSS-safety mechanism,
|
72
40
|
# this destructively modifies the HTML-safety of `text`.
|
73
41
|
#
|
42
|
+
# It only works if you are using ActiveSupport or the parameter `text`
|
43
|
+
# implements the #html_safe method.
|
44
|
+
#
|
74
45
|
# @param text [String, nil]
|
75
46
|
# @return [String, nil] `text`, marked as HTML-safe
|
76
47
|
def html_safe(text)
|
@@ -81,7 +52,7 @@ module Haml
|
|
81
52
|
# Checks that the encoding of a string is valid
|
82
53
|
# and cleans up potential encoding gotchas like the UTF-8 BOM.
|
83
54
|
# If it's not, yields an error string describing the invalid character
|
84
|
-
# and the line on which it
|
55
|
+
# and the line on which it occurs.
|
85
56
|
#
|
86
57
|
# @param str [String] The string of which to check the encoding
|
87
58
|
# @yield [msg] A block in which an encoding error can be raised.
|
@@ -163,80 +134,6 @@ MSG
|
|
163
134
|
end
|
164
135
|
end
|
165
136
|
|
166
|
-
## Static Method Stuff
|
167
|
-
|
168
|
-
# The context in which the ERB for \{#def\_static\_method} will be run.
|
169
|
-
class StaticConditionalContext
|
170
|
-
# @param set [#include?] The set of variables that are defined for this context.
|
171
|
-
def initialize(set)
|
172
|
-
@set = set
|
173
|
-
end
|
174
|
-
|
175
|
-
# Checks whether or not a variable is defined for this context.
|
176
|
-
#
|
177
|
-
# @param name [Symbol] The name of the variable
|
178
|
-
# @return [Boolean]
|
179
|
-
def method_missing(name, *args, &block)
|
180
|
-
super unless args.empty? && block.nil?
|
181
|
-
@set.include?(name)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# This is used for methods in {Haml::Buffer} that need to be very fast,
|
186
|
-
# and take a lot of boolean parameters
|
187
|
-
# that are known at compile-time.
|
188
|
-
# Instead of passing the parameters in normally,
|
189
|
-
# a separate method is defined for every possible combination of those parameters;
|
190
|
-
# these are then called using \{#static\_method\_name}.
|
191
|
-
#
|
192
|
-
# To define a static method, an ERB template for the method is provided.
|
193
|
-
# All conditionals based on the static parameters
|
194
|
-
# are done as embedded Ruby within this template.
|
195
|
-
# For example:
|
196
|
-
#
|
197
|
-
# def_static_method(Foo, :my_static_method, [:foo, :bar], :baz, :bang, <<RUBY)
|
198
|
-
# <% if baz && bang %>
|
199
|
-
# return foo + bar
|
200
|
-
# <% elsif baz || bang %>
|
201
|
-
# return foo - bar
|
202
|
-
# <% else %>
|
203
|
-
# return 17
|
204
|
-
# <% end %>
|
205
|
-
# RUBY
|
206
|
-
#
|
207
|
-
# \{#static\_method\_name} can be used to call static methods.
|
208
|
-
#
|
209
|
-
# @overload def_static_method(klass, name, args, *vars, erb)
|
210
|
-
# @param klass [Module] The class on which to define the static method
|
211
|
-
# @param name [#to_s] The (base) name of the static method
|
212
|
-
# @param args [Array<Symbol>] The names of the arguments to the defined methods
|
213
|
-
# (**not** to the ERB template)
|
214
|
-
# @param vars [Array<Symbol>] The names of the static boolean variables
|
215
|
-
# to be made available to the ERB template
|
216
|
-
def def_static_method(klass, name, args, *vars)
|
217
|
-
erb = vars.pop
|
218
|
-
info = caller_info
|
219
|
-
powerset(vars).each do |set|
|
220
|
-
context = StaticConditionalContext.new(set).instance_eval {binding}
|
221
|
-
method_content = (defined?(Erubis::TinyEruby) && Erubis::TinyEruby || ERB).new(erb).result(context)
|
222
|
-
|
223
|
-
klass.class_eval(<<METHOD, info[0], info[1])
|
224
|
-
def #{static_method_name(name, *vars.map {|v| set.include?(v)})}(#{args.join(', ')})
|
225
|
-
#{method_content}
|
226
|
-
end
|
227
|
-
METHOD
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# Computes the name for a method defined via \{#def\_static\_method}.
|
232
|
-
#
|
233
|
-
# @param name [String] The base name of the static method
|
234
|
-
# @param vars [Array<Boolean>] The static variable assignment
|
235
|
-
# @return [String] The real name of the static method
|
236
|
-
def static_method_name(name, *vars)
|
237
|
-
:"#{name}_#{vars.map {|v| !!v}.join('_')}"
|
238
|
-
end
|
239
|
-
|
240
137
|
# Scans through a string looking for the interoplation-opening `#{`
|
241
138
|
# and, when it's found, yields the scanner to the calling code
|
242
139
|
# so it can handle it properly.
|
@@ -249,7 +146,7 @@ METHOD
|
|
249
146
|
# @return [String] The text remaining in the scanner after all `#{`s have been processed
|
250
147
|
def handle_interpolation(str)
|
251
148
|
scan = StringScanner.new(str)
|
252
|
-
yield scan while scan.scan(/(.*?)(\\*)
|
149
|
+
yield scan while scan.scan(/(.*?)(\\*)#([\{@$])/)
|
253
150
|
scan.rest
|
254
151
|
end
|
255
152
|
|
@@ -298,20 +195,28 @@ METHOD
|
|
298
195
|
end
|
299
196
|
|
300
197
|
def contains_interpolation?(str)
|
301
|
-
str
|
198
|
+
/#[\{$@]/ === str
|
302
199
|
end
|
303
200
|
|
304
201
|
def unescape_interpolation(str, escape_html = nil)
|
305
202
|
res = ''
|
306
203
|
rest = Haml::Util.handle_interpolation str.dump do |scan|
|
307
204
|
escapes = (scan[2].size - 1) / 2
|
205
|
+
char = scan[3] # '{', '@' or '$'
|
308
206
|
res << scan.matched[0...-3 - escapes]
|
309
207
|
if escapes % 2 == 1
|
310
|
-
res <<
|
208
|
+
res << "\##{char}"
|
311
209
|
else
|
312
|
-
|
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 == '$'
|
313
217
|
content = "Haml::Helpers.html_escape((#{content}))" if escape_html
|
314
|
-
|
218
|
+
|
219
|
+
res << "\#{#{content}}"
|
315
220
|
end
|
316
221
|
end
|
317
222
|
res + rest
|
data/lib/haml/version.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
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({}, '') }
|
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
|
+
end
|
24
|
+
|
25
|
+
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') }
|
29
|
+
end
|
30
|
+
|
31
|
+
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" } ') }
|
40
|
+
end
|
41
|
+
|
42
|
+
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') }
|
52
|
+
end
|
53
|
+
|
54
|
+
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 ') }
|
58
|
+
it { assert_parse({ 'foo' => '[1]' }, ' { "foo"=>[1] } ') }
|
59
|
+
it { assert_parse({ 'foo' => 'nya' }, " { 'foo' => nya } ") }
|
60
|
+
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, } ') }
|
66
|
+
it { assert_parse(nil, '%Q[f#{o}o] => bar ') }
|
67
|
+
end
|
68
|
+
|
69
|
+
if RUBY_VERSION >= '2.2.0'
|
70
|
+
describe '"foo": bar' do
|
71
|
+
it { assert_parse({ 'foo' => '()' }, '"foo":()') }
|
72
|
+
it { assert_parse({ 'foo' => 'nya' }, " 'foo': nya ") }
|
73
|
+
it { assert_parse({ 'foo' => '()' }, ' { "foo":() , }') }
|
74
|
+
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
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
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],], } ') }
|
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
|
+
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, }, } ') }
|
97
|
+
end
|
98
|
+
|
99
|
+
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,), } ') }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|