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 +4 -4
- data/CHANGELOG.md +7 -1
- data/Rakefile +15 -11
- data/lib/haml.rb +1 -0
- data/lib/haml/attribute_compiler.rb +10 -9
- data/lib/haml/attribute_parser.rb +78 -46
- data/lib/haml/buffer.rb +7 -20
- data/lib/haml/compiler.rb +23 -13
- data/lib/haml/engine.rb +1 -0
- data/lib/haml/error.rb +1 -0
- data/lib/haml/escapable.rb +1 -0
- data/lib/haml/exec.rb +3 -2
- data/lib/haml/filters.rb +1 -0
- data/lib/haml/generator.rb +5 -0
- data/lib/haml/helpers.rb +1 -0
- data/lib/haml/helpers/action_view_extensions.rb +1 -0
- data/lib/haml/helpers/action_view_mods.rb +2 -1
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +1 -0
- data/lib/haml/helpers/safe_erubis_template.rb +2 -1
- data/lib/haml/helpers/xss_mods.rb +1 -0
- data/lib/haml/options.rb +1 -0
- data/lib/haml/parser.rb +43 -9
- data/lib/haml/plugin.rb +1 -0
- data/lib/haml/railtie.rb +19 -25
- data/lib/haml/sass_rails_filter.rb +17 -4
- data/lib/haml/template.rb +1 -0
- data/lib/haml/template/options.rb +12 -2
- data/lib/haml/temple_engine.rb +1 -0
- data/lib/haml/temple_line_counter.rb +1 -0
- data/lib/haml/util.rb +1 -1
- data/lib/haml/version.rb +2 -1
- data/test/attribute_parser_test.rb +48 -52
- data/test/engine_test.rb +6 -0
- data/test/options_test.rb +4 -3
- data/test/results/bemit.xhtml +4 -0
- data/test/template_test.rb +1 -1
- data/test/templates/bemit.haml +3 -0
- data/test/test_helper.rb +3 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fa1e64aca629e46493a148b6159feb77763ba0d
|
4
|
+
data.tar.gz: 912f3565b782829c0651604333a0d5fd823c45a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8e860a0fc047d158a7a1d08f349a5555ae9a0afd578327c16cca624c3c0425a323e40cc3185f8ba8fede3ed79d24babb44f634969a69707a46f27d92b925b15
|
7
|
+
data.tar.gz: f3e66b26cf401ac0081721f44322a4fe39c0b0c486d6b4b0dd7e665e483be86f6f1769a0c94ed00b2646e3d76fb7be0ebe2e40c75943c0a5774e38cb3f17a4e2
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Haml Changelog
|
2
2
|
|
3
|
-
## 5.0.0
|
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
|
data/lib/haml.rb
CHANGED
@@ -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
|
31
|
+
# @param dynamic_attributes [DynamicAttributes]
|
31
32
|
# @return [String] Attributes rendering code
|
32
|
-
def self.runtime_build(attributes, object_ref,
|
33
|
-
"_hamlout.attributes(#{Haml::Util.inspect_obj(attributes)}, #{object_ref},#{
|
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
|
49
|
+
# @param dynamic_attributes [DynamicAttributes]
|
49
50
|
# @return [Array] Temple expression
|
50
|
-
def compile(attributes, object_ref,
|
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,
|
53
|
+
return [:dynamic, AttributeCompiler.runtime_build(attributes, object_ref, dynamic_attributes)]
|
53
54
|
end
|
54
55
|
|
55
|
-
parsed_hashes =
|
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,
|
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
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
22
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
40
|
-
|
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 :
|
43
|
-
|
44
|
-
when :
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
67
|
+
when :on_tstring_beg # `"key":`, `'key':` or `"key" =>`
|
68
|
+
key = tokens.shift[TEXT]
|
53
69
|
next_token = tokens.shift
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
83
|
-
case type
|
115
|
+
case token[TYPE]
|
84
116
|
when :on_comma
|
85
|
-
if
|
86
|
-
|
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
|
-
|
123
|
+
open_tokens[:array] += 1
|
92
124
|
when :on_rbracket
|
93
|
-
|
125
|
+
open_tokens[:array] -= 1
|
94
126
|
when :on_lbrace
|
95
|
-
|
127
|
+
open_tokens[:block] += 1
|
96
128
|
when :on_rbrace
|
97
|
-
|
129
|
+
open_tokens[:block] -= 1
|
98
130
|
when :on_lparen
|
99
|
-
|
131
|
+
open_tokens[:paren] += 1
|
100
132
|
when :on_rparen
|
101
|
-
|
102
|
-
when
|
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
|
-
|
140
|
+
block.call(attr_tokens) unless attr_tokens.empty?
|
109
141
|
end
|
110
142
|
end
|
111
143
|
end
|
data/lib/haml/buffer.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Haml
|
2
3
|
# This class is used only internally. It holds the buffer of HTML that
|
3
4
|
# is eventually output as the resulting document.
|
@@ -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|
)(.*?)<\/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(
|
181
|
+
"".encode(options[:encoding])
|
195
182
|
end
|
196
183
|
|
197
184
|
@@tab_cache = {}
|
data/lib/haml/compiler.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
283
|
-
|
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)
|
data/lib/haml/engine.rb
CHANGED
data/lib/haml/error.rb
CHANGED
data/lib/haml/escapable.rb
CHANGED
data/lib/haml/exec.rb
CHANGED
@@ -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(
|
296
|
-
pp parser.
|
296
|
+
parser = ::Haml::Parser.new(::Haml::Options.new(@options))
|
297
|
+
pp parser.call(template)
|
297
298
|
return
|
298
299
|
end
|
299
300
|
|
data/lib/haml/filters.rb
CHANGED
data/lib/haml/generator.rb
CHANGED
@@ -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)
|
data/lib/haml/helpers.rb
CHANGED
@@ -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
|
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)}
|
data/lib/haml/options.rb
CHANGED
data/lib/haml/parser.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
:
|
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
|
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
|
data/lib/haml/plugin.rb
CHANGED
data/lib/haml/railtie.rb
CHANGED
@@ -1,35 +1,29 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
7
|
-
scope
|
8
|
-
|
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
|
data/lib/haml/template.rb
CHANGED
@@ -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
|
-
|
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 [
|
23
|
+
# @return [Haml::Template::Options<Symbol => Object>]
|
14
24
|
attr_accessor :options
|
15
25
|
end
|
16
26
|
end
|
data/lib/haml/temple_engine.rb
CHANGED
data/lib/haml/util.rb
CHANGED
data/lib/haml/version.rb
CHANGED
@@ -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, '
|
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(
|
47
|
-
it { assert_parse(
|
48
|
-
it { assert_parse(
|
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' }, '
|
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
|
data/test/engine_test.rb
CHANGED
@@ -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))
|
data/test/options_test.rb
CHANGED
@@ -9,11 +9,12 @@ module Haml
|
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
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
|
-
|
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
|
data/test/template_test.rb
CHANGED
@@ -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
|
data/test/test_helper.rb
CHANGED
@@ -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
|
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-
|
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:
|
241
|
+
version: '0'
|
240
242
|
requirements: []
|
241
243
|
rubyforge_project:
|
242
|
-
rubygems_version: 2.6.
|
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.
|