haml 4.0.7 → 5.0.4
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 +5 -5
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +54 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +96 -4
- data/FAQ.md +4 -14
- data/Gemfile +19 -0
- data/MIT-LICENSE +1 -1
- data/README.md +80 -42
- data/REFERENCE.md +116 -64
- data/Rakefile +46 -54
- data/TODO +24 -0
- data/benchmark.rb +66 -0
- data/haml.gemspec +38 -0
- data/lib/haml/.gitattributes +1 -0
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +223 -0
- data/lib/haml/attribute_parser.rb +148 -0
- data/lib/haml/buffer.rb +22 -132
- data/lib/haml/compiler.rb +89 -298
- 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 +38 -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 +42 -60
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +19 -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 +132 -89
- data/lib/haml/options.rb +41 -47
- data/lib/haml/parser.rb +278 -216
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +38 -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 +121 -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/yard/default/.gitignore +1 -0
- data/yard/default/fulldoc/html/css/common.sass +15 -0
- data/yard/default/layout/html/footer.erb +12 -0
- metadata +50 -111
- data/test/engine_test.rb +0 -2013
- data/test/erb/_av_partial_1.erb +0 -12
- data/test/erb/_av_partial_2.erb +0 -8
- data/test/erb/action_view.erb +0 -62
- data/test/erb/standard.erb +0 -55
- data/test/filters_test.rb +0 -254
- 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/gemfiles/Gemfile.rails-4.0.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/helper_test.rb +0 -583
- data/test/markaby/standard.mab +0 -52
- data/test/mocks/article.rb +0 -6
- data/test/parser_test.rb +0 -105
- data/test/results/content_for_layout.xhtml +0 -12
- data/test/results/eval_suppressed.xhtml +0 -9
- data/test/results/helpers.xhtml +0 -70
- data/test/results/helpful.xhtml +0 -10
- data/test/results/just_stuff.xhtml +0 -70
- data/test/results/list.xhtml +0 -12
- data/test/results/nuke_inner_whitespace.xhtml +0 -40
- data/test/results/nuke_outer_whitespace.xhtml +0 -148
- data/test/results/original_engine.xhtml +0 -20
- data/test/results/partial_layout.xhtml +0 -5
- data/test/results/partial_layout_erb.xhtml +0 -5
- data/test/results/partials.xhtml +0 -21
- data/test/results/render_layout.xhtml +0 -3
- data/test/results/silent_script.xhtml +0 -74
- data/test/results/standard.xhtml +0 -162
- data/test/results/tag_parsing.xhtml +0 -23
- data/test/results/very_basic.xhtml +0 -5
- data/test/results/whitespace_handling.xhtml +0 -90
- data/test/template_test.rb +0 -354
- data/test/templates/_av_partial_1.haml +0 -9
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2.haml +0 -5
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/_layout.erb +0 -3
- data/test/templates/_layout_for_partial.haml +0 -3
- data/test/templates/_partial.haml +0 -8
- data/test/templates/_text_area.haml +0 -3
- data/test/templates/_text_area_helper.html.haml +0 -4
- data/test/templates/action_view.haml +0 -47
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/breakage.haml +0 -8
- data/test/templates/content_for_layout.haml +0 -8
- data/test/templates/eval_suppressed.haml +0 -11
- data/test/templates/helpers.haml +0 -55
- data/test/templates/helpful.haml +0 -11
- data/test/templates/just_stuff.haml +0 -85
- data/test/templates/list.haml +0 -12
- data/test/templates/nuke_inner_whitespace.haml +0 -32
- data/test/templates/nuke_outer_whitespace.haml +0 -144
- data/test/templates/original_engine.haml +0 -17
- data/test/templates/partial_layout.haml +0 -3
- data/test/templates/partial_layout_erb.erb +0 -4
- data/test/templates/partialize.haml +0 -1
- data/test/templates/partials.haml +0 -12
- data/test/templates/render_layout.haml +0 -2
- data/test/templates/silent_script.haml +0 -45
- data/test/templates/standard.haml +0 -43
- data/test/templates/standard_ugly.haml +0 -43
- data/test/templates/tag_parsing.haml +0 -21
- data/test/templates/very_basic.haml +0 -4
- data/test/templates/whitespace_handling.haml +0 -87
- data/test/test_helper.rb +0 -81
- data/test/util_test.rb +0 -63
data/lib/haml/compiler.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
require 'haml/attribute_builder'
|
|
3
|
+
require 'haml/attribute_compiler'
|
|
4
|
+
require 'haml/temple_line_counter'
|
|
2
5
|
|
|
3
6
|
module Haml
|
|
4
7
|
class Compiler
|
|
@@ -7,15 +10,21 @@ module Haml
|
|
|
7
10
|
attr_accessor :options
|
|
8
11
|
|
|
9
12
|
def initialize(options)
|
|
10
|
-
@options = options
|
|
11
|
-
@output_tabs = 0
|
|
13
|
+
@options = Options.wrap(options)
|
|
12
14
|
@to_merge = []
|
|
13
|
-
@
|
|
15
|
+
@temple = [:multi]
|
|
16
|
+
@node = nil
|
|
17
|
+
@filters = Filters.defined.merge(options[:filters])
|
|
18
|
+
@attribute_compiler = AttributeCompiler.new(@options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def call(node)
|
|
22
|
+
compile(node)
|
|
23
|
+
@temple
|
|
14
24
|
end
|
|
15
25
|
|
|
16
26
|
def compile(node)
|
|
17
|
-
parent
|
|
18
|
-
@node = node
|
|
27
|
+
parent, @node = @node, node
|
|
19
28
|
if node.children.empty?
|
|
20
29
|
send(:"compile_#{node.type}")
|
|
21
30
|
else
|
|
@@ -25,79 +34,16 @@ module Haml
|
|
|
25
34
|
@node = parent
|
|
26
35
|
end
|
|
27
36
|
|
|
28
|
-
if RUBY_VERSION < "1.9"
|
|
29
|
-
# The source code that is evaluated to produce the Haml document.
|
|
30
|
-
#
|
|
31
|
-
# In Ruby 1.9, this is automatically converted to the correct encoding
|
|
32
|
-
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
|
33
|
-
#
|
|
34
|
-
# @return [String]
|
|
35
|
-
def precompiled
|
|
36
|
-
@precompiled
|
|
37
|
-
end
|
|
38
|
-
else
|
|
39
|
-
def precompiled
|
|
40
|
-
encoding = Encoding.find(@options[:encoding])
|
|
41
|
-
return @precompiled.force_encoding(encoding) if encoding == Encoding::BINARY
|
|
42
|
-
return @precompiled.encode(encoding)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def precompiled_with_return_value
|
|
47
|
-
precompiled + ";" + precompiled_method_return_value
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Returns the precompiled string with the preamble and postamble.
|
|
51
|
-
#
|
|
52
|
-
# Initializes to ActionView::OutputBuffer when available; this is necessary
|
|
53
|
-
# to avoid ordering issues with partial layouts in Rails. If not available,
|
|
54
|
-
# initializes to nil.
|
|
55
|
-
def precompiled_with_ambles(local_names)
|
|
56
|
-
preamble = <<END.gsub("\n", ";")
|
|
57
|
-
begin
|
|
58
|
-
extend Haml::Helpers
|
|
59
|
-
_hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, #{options.for_buffer.inspect})
|
|
60
|
-
_erbout = _hamlout.buffer
|
|
61
|
-
@output_buffer = output_buffer ||= ActionView::OutputBuffer.new rescue nil
|
|
62
|
-
END
|
|
63
|
-
postamble = <<END.gsub("\n", ";")
|
|
64
|
-
#{precompiled_method_return_value}
|
|
65
|
-
ensure
|
|
66
|
-
@haml_buffer = @haml_buffer.upper if @haml_buffer
|
|
67
|
-
end
|
|
68
|
-
END
|
|
69
|
-
preamble + locals_code(local_names) + precompiled + postamble
|
|
70
|
-
end
|
|
71
|
-
|
|
72
37
|
private
|
|
73
38
|
|
|
74
|
-
# Returns the string used as the return value of the precompiled method.
|
|
75
|
-
# This method exists so it can be monkeypatched to return modified values.
|
|
76
|
-
def precompiled_method_return_value
|
|
77
|
-
"_erbout"
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def locals_code(names)
|
|
81
|
-
names = names.keys if Hash == names
|
|
82
|
-
|
|
83
|
-
names.map do |name|
|
|
84
|
-
# Can't use || because someone might explicitly pass in false with a symbol
|
|
85
|
-
sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
|
|
86
|
-
str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
|
|
87
|
-
"#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local}"
|
|
88
|
-
end.join(';') + ';'
|
|
89
|
-
end
|
|
90
|
-
|
|
91
39
|
def compile_root
|
|
92
|
-
@dont_indent_next_line = @dont_tab_up_next_text = false
|
|
93
40
|
@output_line = 1
|
|
94
|
-
|
|
95
|
-
yield
|
|
41
|
+
yield if block_given?
|
|
96
42
|
flush_merged_text
|
|
97
43
|
end
|
|
98
44
|
|
|
99
45
|
def compile_plain
|
|
100
|
-
push_text
|
|
46
|
+
push_text("#{@node.value[:text]}\n")
|
|
101
47
|
end
|
|
102
48
|
|
|
103
49
|
def nuke_inner_whitespace?(node)
|
|
@@ -119,15 +65,11 @@ END
|
|
|
119
65
|
end
|
|
120
66
|
|
|
121
67
|
def compile_silent_script
|
|
122
|
-
return if @options
|
|
68
|
+
return if @options.suppress_eval
|
|
123
69
|
push_silent(@node.value[:text])
|
|
124
70
|
keyword = @node.value[:keyword]
|
|
125
71
|
|
|
126
72
|
if block_given?
|
|
127
|
-
# Store these values because for conditional statements,
|
|
128
|
-
# we want to restore them for each branch
|
|
129
|
-
@node.value[:dont_indent_next_line] = @dont_indent_next_line
|
|
130
|
-
@node.value[:dont_tab_up_next_text] = @dont_tab_up_next_text
|
|
131
73
|
yield
|
|
132
74
|
push_silent("end", :can_suppress) unless @node.value[:dont_push_end]
|
|
133
75
|
elsif keyword == "end"
|
|
@@ -137,10 +79,6 @@ END
|
|
|
137
79
|
@node.parent.value[:dont_push_end] = true
|
|
138
80
|
end
|
|
139
81
|
# Don't restore dont_* for end because it isn't a conditional branch.
|
|
140
|
-
elsif Parser::MID_BLOCK_KEYWORDS.include?(keyword)
|
|
141
|
-
# Restore dont_* for this conditional branch
|
|
142
|
-
@dont_indent_next_line = @node.parent.value[:dont_indent_next_line]
|
|
143
|
-
@dont_tab_up_next_text = @node.parent.value[:dont_tab_up_next_text]
|
|
144
82
|
end
|
|
145
83
|
end
|
|
146
84
|
|
|
@@ -152,117 +90,84 @@ END
|
|
|
152
90
|
# Get rid of whitespace outside of the tag if we need to
|
|
153
91
|
rstrip_buffer! if t[:nuke_outer_whitespace]
|
|
154
92
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
(t[:nuke_inner_whitespace] && block_given?)
|
|
158
|
-
|
|
159
|
-
if @options[:suppress_eval]
|
|
160
|
-
object_ref = "nil"
|
|
93
|
+
if @options.suppress_eval
|
|
94
|
+
object_ref = :nil
|
|
161
95
|
parse = false
|
|
162
96
|
value = t[:parse] ? nil : t[:value]
|
|
163
|
-
|
|
164
|
-
preserve_script = false
|
|
97
|
+
dynamic_attributes = Haml::Parser::DynamicAttributes.new
|
|
165
98
|
else
|
|
166
99
|
object_ref = t[:object_ref]
|
|
167
100
|
parse = t[:parse]
|
|
168
101
|
value = t[:value]
|
|
169
|
-
|
|
170
|
-
preserve_script = t[:preserve_script]
|
|
102
|
+
dynamic_attributes = t[:dynamic_attributes]
|
|
171
103
|
end
|
|
172
104
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
open_tag = prerender_tag(t[:name], t[:self_closing], t[:attributes])
|
|
178
|
-
if tag_closed
|
|
179
|
-
open_tag << "#{value}</#{t[:name]}>"
|
|
180
|
-
open_tag << "\n" unless t[:nuke_outer_whitespace]
|
|
181
|
-
elsif !(parse || t[:nuke_inner_whitespace] ||
|
|
182
|
-
(t[:self_closing] && t[:nuke_outer_whitespace]))
|
|
183
|
-
open_tag << "\n"
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
push_merged_text(open_tag,
|
|
187
|
-
tag_closed || t[:self_closing] || t[:nuke_inner_whitespace] ? 0 : 1,
|
|
188
|
-
!t[:nuke_outer_whitespace])
|
|
105
|
+
if @options[:trace]
|
|
106
|
+
t[:attributes].merge!({"data-trace" => @options.filename.split('/views').last << ":" << @node.line.to_s})
|
|
107
|
+
end
|
|
189
108
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if
|
|
194
|
-
|
|
195
|
-
elsif attributes_hashes.size == 1
|
|
196
|
-
attributes_hashes = ", #{attributes_hashes.first}"
|
|
109
|
+
push_text("<#{t[:name]}")
|
|
110
|
+
push_temple(@attribute_compiler.compile(t[:attributes], object_ref, dynamic_attributes))
|
|
111
|
+
push_text(
|
|
112
|
+
if t[:self_closing] && @options.xhtml?
|
|
113
|
+
" />#{"\n" unless t[:nuke_outer_whitespace]}"
|
|
197
114
|
else
|
|
198
|
-
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
push_merged_text "<#{t[:name]}", 0, !t[:nuke_outer_whitespace]
|
|
202
|
-
push_generated_script(
|
|
203
|
-
"_hamlout.attributes(#{inspect_obj(t[:attributes])}, #{object_ref}#{attributes_hashes})")
|
|
204
|
-
concat_merged_text(
|
|
205
|
-
if t[:self_closing] && @options.xhtml?
|
|
206
|
-
" />" + (t[:nuke_outer_whitespace] ? "" : "\n")
|
|
207
|
-
else
|
|
208
|
-
">" + ((if t[:self_closing] && @options.html?
|
|
209
|
-
t[:nuke_outer_whitespace]
|
|
210
|
-
else
|
|
211
|
-
!block_given? || t[:preserve_tag] || t[:nuke_inner_whitespace]
|
|
212
|
-
end) ? "" : "\n")
|
|
213
|
-
end)
|
|
214
|
-
|
|
215
|
-
if value && !parse
|
|
216
|
-
concat_merged_text("#{value}</#{t[:name]}>#{t[:nuke_outer_whitespace] ? "" : "\n"}")
|
|
217
|
-
elsif !t[:nuke_inner_whitespace] && !t[:self_closing]
|
|
218
|
-
@to_merge << [:text, '', 1]
|
|
115
|
+
">#{"\n" unless (t[:self_closing] && @options.html?) ? t[:nuke_outer_whitespace] : (!block_given? || t[:preserve_tag] || t[:nuke_inner_whitespace])}"
|
|
219
116
|
end
|
|
117
|
+
)
|
|
220
118
|
|
|
221
|
-
|
|
119
|
+
if value && !parse
|
|
120
|
+
push_text("#{value}</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}")
|
|
222
121
|
end
|
|
223
122
|
|
|
224
123
|
return if t[:self_closing]
|
|
225
124
|
|
|
226
125
|
if value.nil?
|
|
227
|
-
@output_tabs += 1 unless t[:nuke_inner_whitespace]
|
|
228
126
|
yield if block_given?
|
|
229
|
-
@output_tabs -= 1 unless t[:nuke_inner_whitespace]
|
|
230
127
|
rstrip_buffer! if t[:nuke_inner_whitespace]
|
|
231
|
-
|
|
232
|
-
t[:nuke_inner_whitespace] ? 0 : -1, !t[:nuke_inner_whitespace])
|
|
233
|
-
@dont_indent_next_line = t[:nuke_outer_whitespace]
|
|
128
|
+
push_text("</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}")
|
|
234
129
|
return
|
|
235
130
|
end
|
|
236
131
|
|
|
237
132
|
if parse
|
|
238
133
|
push_script(value, t.merge(:in_tag => true))
|
|
239
|
-
|
|
134
|
+
push_text("</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}")
|
|
240
135
|
end
|
|
241
136
|
end
|
|
242
137
|
|
|
243
138
|
def compile_comment
|
|
244
|
-
|
|
139
|
+
condition = "#{@node.value[:conditional]}>" if @node.value[:conditional]
|
|
140
|
+
revealed = @node.value[:revealed]
|
|
141
|
+
|
|
142
|
+
open = "<!--#{condition}#{'<!-->' if revealed}"
|
|
143
|
+
|
|
144
|
+
close = "#{'<!--' if revealed}#{'<![endif]' if condition}-->"
|
|
245
145
|
|
|
246
|
-
# Render it statically if possible
|
|
247
146
|
unless block_given?
|
|
248
|
-
push_text("#{open}
|
|
147
|
+
push_text("#{open} ")
|
|
148
|
+
|
|
149
|
+
if @node.value[:parse]
|
|
150
|
+
push_script(@node.value[:text], :in_tag => true, :nuke_inner_whitespace => true)
|
|
151
|
+
else
|
|
152
|
+
push_text(@node.value[:text])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
push_text(" #{close}\n")
|
|
249
156
|
return
|
|
250
157
|
end
|
|
251
158
|
|
|
252
|
-
push_text(open
|
|
253
|
-
@output_tabs += 1
|
|
159
|
+
push_text("#{open}\n")
|
|
254
160
|
yield if block_given?
|
|
255
|
-
|
|
256
|
-
push_text(@node.value[:conditional] ? "<![endif]-->" : "-->", -1)
|
|
161
|
+
push_text("#{close}\n")
|
|
257
162
|
end
|
|
258
163
|
|
|
259
164
|
def compile_doctype
|
|
260
165
|
doctype = text_for_doctype
|
|
261
|
-
push_text
|
|
166
|
+
push_text("#{doctype}\n") if doctype
|
|
262
167
|
end
|
|
263
168
|
|
|
264
169
|
def compile_filter
|
|
265
|
-
unless filter =
|
|
170
|
+
unless filter = @filters[@node.value[:name]]
|
|
266
171
|
name = @node.value[:name]
|
|
267
172
|
if ["maruku", "textile"].include?(name)
|
|
268
173
|
raise Error.new(Error.message(:install_haml_contrib, name), @node.line - 1)
|
|
@@ -276,7 +181,7 @@ END
|
|
|
276
181
|
def text_for_doctype
|
|
277
182
|
if @node.value[:type] == "xml"
|
|
278
183
|
return nil if @options.html?
|
|
279
|
-
wrapper = @options
|
|
184
|
+
wrapper = @options.attr_wrapper
|
|
280
185
|
return "<?xml version=#{wrapper}1.0#{wrapper} encoding=#{wrapper}#{@node.value[:encoding] || "utf-8"}#{wrapper} ?>"
|
|
281
186
|
end
|
|
282
187
|
|
|
@@ -315,83 +220,52 @@ END
|
|
|
315
220
|
flush_merged_text
|
|
316
221
|
return if can_suppress && @options.suppress_eval?
|
|
317
222
|
newline = (text == "end") ? ";" : "\n"
|
|
318
|
-
@
|
|
319
|
-
@output_line
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
# Adds `text` to `@buffer` with appropriate tabulation
|
|
323
|
-
# without parsing it.
|
|
324
|
-
def push_merged_text(text, tab_change = 0, indent = true)
|
|
325
|
-
text = !indent || @dont_indent_next_line || @options[:ugly] ? text : "#{' ' * @output_tabs}#{text}"
|
|
326
|
-
@to_merge << [:text, text, tab_change]
|
|
327
|
-
@dont_indent_next_line = false
|
|
223
|
+
@temple << [:code, "#{resolve_newlines}#{text}#{newline}"]
|
|
224
|
+
@output_line = @output_line + text.count("\n") + newline.count("\n")
|
|
328
225
|
end
|
|
329
226
|
|
|
330
|
-
#
|
|
331
|
-
def
|
|
332
|
-
@to_merge << [:text, text
|
|
227
|
+
# Adds `text` to `@buffer`.
|
|
228
|
+
def push_text(text)
|
|
229
|
+
@to_merge << [:text, text]
|
|
333
230
|
end
|
|
334
231
|
|
|
335
|
-
def
|
|
336
|
-
|
|
232
|
+
def push_temple(temple)
|
|
233
|
+
flush_merged_text
|
|
234
|
+
@temple.concat([[:newline]] * resolve_newlines.count("\n"))
|
|
235
|
+
@temple << temple
|
|
236
|
+
@output_line += TempleLineCounter.count_lines(temple)
|
|
337
237
|
end
|
|
338
238
|
|
|
339
239
|
def flush_merged_text
|
|
340
240
|
return if @to_merge.empty?
|
|
341
241
|
|
|
342
|
-
|
|
343
|
-
mtabs = 0
|
|
344
|
-
@to_merge.each do |type, val, tabs|
|
|
242
|
+
@to_merge.each do |type, val|
|
|
345
243
|
case type
|
|
346
244
|
when :text
|
|
347
|
-
|
|
348
|
-
mtabs += tabs
|
|
245
|
+
@temple << [:static, val]
|
|
349
246
|
when :script
|
|
350
|
-
|
|
351
|
-
val = "_hamlout.adjust_tabs(#{mtabs}); " + val
|
|
352
|
-
end
|
|
353
|
-
str << "\#{#{val}}"
|
|
354
|
-
mtabs = 0
|
|
247
|
+
@temple << [:dynamic, val]
|
|
355
248
|
else
|
|
356
249
|
raise SyntaxError.new("[HAML BUG] Undefined entry in Haml::Compiler@to_merge.")
|
|
357
250
|
end
|
|
358
251
|
end
|
|
359
252
|
|
|
360
|
-
unless str.empty?
|
|
361
|
-
@precompiled <<
|
|
362
|
-
if @options[:ugly]
|
|
363
|
-
"_hamlout.buffer << \"#{str}\";"
|
|
364
|
-
else
|
|
365
|
-
"_hamlout.push_text(\"#{str}\", #{mtabs}, #{@dont_tab_up_next_text.inspect});"
|
|
366
|
-
end
|
|
367
|
-
end
|
|
368
253
|
@to_merge = []
|
|
369
|
-
@dont_tab_up_next_text = false
|
|
370
254
|
end
|
|
371
255
|
|
|
372
256
|
# Causes `text` to be evaluated in the context of
|
|
373
257
|
# the scope object and the result to be added to `@buffer`.
|
|
374
258
|
#
|
|
375
|
-
# If `opts[:preserve_script]` is true, Haml::Helpers#
|
|
259
|
+
# If `opts[:preserve_script]` is true, Haml::Helpers#find_and_preserve is run on
|
|
376
260
|
# the result before it is added to `@buffer`
|
|
377
261
|
def push_script(text, opts = {})
|
|
378
262
|
return if @options.suppress_eval?
|
|
379
263
|
|
|
380
|
-
|
|
381
|
-
args.map! {|name| opts[name.to_sym]}
|
|
382
|
-
args << !block_given? << @options[:ugly]
|
|
383
|
-
|
|
384
|
-
no_format = @options[:ugly] &&
|
|
385
|
-
!(opts[:preserve_script] || opts[:preserve_tag] || opts[:escape_html])
|
|
386
|
-
output_expr = "(#{text}\n)"
|
|
387
|
-
static_method = "_hamlout.#{static_method_name(:format_script, *args)}"
|
|
388
|
-
|
|
389
|
-
# Prerender tabulation unless we're in a tag
|
|
390
|
-
push_merged_text '' unless opts[:in_tag]
|
|
264
|
+
no_format = !(opts[:preserve_script] || opts[:preserve_tag] || opts[:escape_html])
|
|
391
265
|
|
|
392
266
|
unless block_given?
|
|
393
|
-
push_generated_script(no_format ? "#{text}\n" : "
|
|
394
|
-
|
|
267
|
+
push_generated_script(no_format ? "(#{text}\n).to_s" : build_script_formatter("(#{text}\n)", opts))
|
|
268
|
+
push_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace]
|
|
395
269
|
return
|
|
396
270
|
end
|
|
397
271
|
|
|
@@ -399,117 +273,35 @@ END
|
|
|
399
273
|
push_silent "haml_temp = #{text}"
|
|
400
274
|
yield
|
|
401
275
|
push_silent('end', :can_suppress) unless @node.value[:dont_push_end]
|
|
402
|
-
@
|
|
403
|
-
concat_merged_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace] || @options[:ugly]
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
def push_generated_script(text)
|
|
407
|
-
@to_merge << [:script, resolve_newlines + text]
|
|
408
|
-
@output_line += text.count("\n")
|
|
276
|
+
@temple << [:dynamic, no_format ? 'haml_temp.to_s;' : build_script_formatter('haml_temp', opts)]
|
|
409
277
|
end
|
|
410
278
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
quote_escape = attr_wrapper == '"' ? """ : "'"
|
|
416
|
-
other_quote_char = attr_wrapper == '"' ? "'" : '"'
|
|
417
|
-
join_char = hyphenate_data_attrs ? '-' : '_'
|
|
418
|
-
|
|
419
|
-
attributes.each do |key, value|
|
|
420
|
-
if value.is_a?(Hash)
|
|
421
|
-
data_attributes = attributes.delete(key)
|
|
422
|
-
data_attributes = flatten_data_attributes(data_attributes, '', join_char)
|
|
423
|
-
data_attributes = build_data_keys(data_attributes, hyphenate_data_attrs, key)
|
|
424
|
-
attributes = data_attributes.merge(attributes)
|
|
425
|
-
end
|
|
279
|
+
def build_script_formatter(text, opts)
|
|
280
|
+
text = "(#{text}).to_s"
|
|
281
|
+
if opts[:escape_html]
|
|
282
|
+
text = "::Haml::Helpers.html_escape(#{text})"
|
|
426
283
|
end
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
next if value.nil?
|
|
430
|
-
|
|
431
|
-
value = filter_and_join(value, ' ') if attr == 'class'
|
|
432
|
-
value = filter_and_join(value, '_') if attr == 'id'
|
|
433
|
-
|
|
434
|
-
if value == true
|
|
435
|
-
next " #{attr}" if is_html
|
|
436
|
-
next " #{attr}=#{attr_wrapper}#{attr}#{attr_wrapper}"
|
|
437
|
-
elsif value == false
|
|
438
|
-
next
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
escaped =
|
|
442
|
-
if escape_attrs == :once
|
|
443
|
-
Haml::Helpers.escape_once(value.to_s)
|
|
444
|
-
elsif escape_attrs
|
|
445
|
-
Haml::Helpers.html_escape(value.to_s)
|
|
446
|
-
else
|
|
447
|
-
value.to_s
|
|
448
|
-
end
|
|
449
|
-
value = Haml::Helpers.preserve(escaped)
|
|
450
|
-
if escape_attrs
|
|
451
|
-
# We want to decide whether or not to escape quotes
|
|
452
|
-
value.gsub!(/"|"/, '"')
|
|
453
|
-
this_attr_wrapper = attr_wrapper
|
|
454
|
-
if value.include? attr_wrapper
|
|
455
|
-
if value.include? other_quote_char
|
|
456
|
-
value.gsub!(attr_wrapper, quote_escape)
|
|
457
|
-
else
|
|
458
|
-
this_attr_wrapper = other_quote_char
|
|
459
|
-
end
|
|
460
|
-
end
|
|
461
|
-
else
|
|
462
|
-
this_attr_wrapper = attr_wrapper
|
|
463
|
-
end
|
|
464
|
-
" #{attr}=#{this_attr_wrapper}#{value}#{this_attr_wrapper}"
|
|
284
|
+
if opts[:nuke_inner_whitespace]
|
|
285
|
+
text = "(#{text}).strip"
|
|
465
286
|
end
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
return "" if value == ""
|
|
471
|
-
value = [value] unless value.is_a?(Array)
|
|
472
|
-
value = value.flatten.collect {|item| item ? item.to_s : nil}.compact.join(separator)
|
|
473
|
-
return !value.empty? && value
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def self.build_data_keys(data_hash, hyphenate, attr_name="data")
|
|
477
|
-
Hash[data_hash.map do |name, value|
|
|
478
|
-
if name == nil
|
|
479
|
-
[attr_name, value]
|
|
480
|
-
elsif hyphenate
|
|
481
|
-
["#{attr_name}-#{name.to_s.gsub(/_/, '-')}", value]
|
|
482
|
-
else
|
|
483
|
-
["#{attr_name}-#{name}", value]
|
|
484
|
-
end
|
|
485
|
-
end]
|
|
486
|
-
end
|
|
487
|
-
|
|
488
|
-
def self.flatten_data_attributes(data, key, join_char, seen = [])
|
|
489
|
-
return {key => data} unless data.is_a?(Hash)
|
|
490
|
-
|
|
491
|
-
return {key => nil} if seen.include? data.object_id
|
|
492
|
-
seen << data.object_id
|
|
493
|
-
|
|
494
|
-
data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, array|
|
|
495
|
-
k, v = array
|
|
496
|
-
joined = key == '' ? k : [key, k].join(join_char)
|
|
497
|
-
hash.merge! flatten_data_attributes(v, joined, join_char, seen)
|
|
287
|
+
if opts[:preserve_tag]
|
|
288
|
+
text = "_hamlout.fix_textareas!(::Haml::Helpers.preserve(#{text}))"
|
|
289
|
+
elsif opts[:preserve_script]
|
|
290
|
+
text = "_hamlout.fix_textareas!(::Haml::Helpers.find_and_preserve(#{text}, _hamlout.options[:preserve]))"
|
|
498
291
|
end
|
|
292
|
+
"#{text};"
|
|
499
293
|
end
|
|
500
294
|
|
|
501
|
-
def
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
@options.html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
|
|
505
|
-
"<#{name}#{attributes_string}#{self_close && @options.xhtml? ? ' /' : ''}>"
|
|
295
|
+
def push_generated_script(text)
|
|
296
|
+
@to_merge << [:script, resolve_newlines + text]
|
|
297
|
+
@output_line += text.count("\n")
|
|
506
298
|
end
|
|
507
299
|
|
|
508
300
|
def resolve_newlines
|
|
509
301
|
diff = @node.line - @output_line
|
|
510
302
|
return "" if diff <= 0
|
|
511
303
|
@output_line = @node.line
|
|
512
|
-
"\n" *
|
|
304
|
+
"\n" * diff
|
|
513
305
|
end
|
|
514
306
|
|
|
515
307
|
# Get rid of and whitespace at the end of the buffer
|
|
@@ -518,7 +310,6 @@ END
|
|
|
518
310
|
last = @to_merge[index]
|
|
519
311
|
if last.nil?
|
|
520
312
|
push_silent("_hamlout.rstrip!", false)
|
|
521
|
-
@dont_tab_up_next_text = true
|
|
522
313
|
return
|
|
523
314
|
end
|
|
524
315
|
|