haml 4.0.7 → 5.2.2
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/.github/workflows/test.yml +36 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/.yardopts +2 -3
- data/CHANGELOG.md +146 -4
- data/FAQ.md +4 -14
- data/Gemfile +16 -0
- data/MIT-LICENSE +2 -2
- data/README.md +90 -47
- data/REFERENCE.md +160 -74
- data/Rakefile +44 -63
- data/TODO +24 -0
- data/benchmark.rb +70 -0
- data/haml.gemspec +45 -0
- data/lib/haml/.gitattributes +1 -0
- data/lib/haml/attribute_builder.rb +219 -0
- data/lib/haml/attribute_compiler.rb +237 -0
- data/lib/haml/attribute_parser.rb +150 -0
- data/lib/haml/buffer.rb +12 -175
- data/lib/haml/compiler.rb +110 -320
- data/lib/haml/engine.rb +34 -41
- data/lib/haml/error.rb +28 -24
- data/lib/haml/escapable.rb +77 -0
- data/lib/haml/exec.rb +38 -20
- data/lib/haml/filters.rb +22 -27
- data/lib/haml/generator.rb +42 -0
- data/lib/haml/helpers/action_view_extensions.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +45 -60
- data/lib/haml/helpers/action_view_xss_mods.rb +2 -0
- data/lib/haml/helpers/safe_erubi_template.rb +20 -0
- data/lib/haml/helpers/safe_erubis_template.rb +5 -1
- data/lib/haml/helpers/xss_mods.rb +23 -13
- data/lib/haml/helpers.rb +134 -89
- data/lib/haml/options.rb +63 -69
- data/lib/haml/parser.rb +319 -227
- data/lib/haml/plugin.rb +54 -0
- data/lib/haml/railtie.rb +43 -12
- data/lib/haml/sass_rails_filter.rb +18 -4
- data/lib/haml/template/options.rb +13 -2
- data/lib/haml/template.rb +13 -6
- data/lib/haml/temple_engine.rb +124 -0
- data/lib/haml/temple_line_counter.rb +30 -0
- data/lib/haml/util.rb +83 -202
- data/lib/haml/version.rb +3 -1
- data/lib/haml.rb +2 -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 +73 -115
- data/lib/haml/template/plugin.rb +0 -41
- 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/buffer.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Haml
|
|
2
4
|
# This class is used only internally. It holds the buffer of HTML that
|
|
3
5
|
# is eventually output as the resulting document.
|
|
@@ -90,7 +92,8 @@ module Haml
|
|
|
90
92
|
def initialize(upper = nil, options = {})
|
|
91
93
|
@active = true
|
|
92
94
|
@upper = upper
|
|
93
|
-
@options =
|
|
95
|
+
@options = Options.buffer_defaults
|
|
96
|
+
@options = @options.merge(options) unless options.empty?
|
|
94
97
|
@buffer = new_encoded_string
|
|
95
98
|
@tabulation = 0
|
|
96
99
|
|
|
@@ -115,8 +118,8 @@ module Haml
|
|
|
115
118
|
text.sub!(tabs, '') if dont_tab_up
|
|
116
119
|
end
|
|
117
120
|
|
|
118
|
-
@buffer << text
|
|
119
121
|
@real_tabs += tab_change
|
|
122
|
+
@buffer << text
|
|
120
123
|
end
|
|
121
124
|
|
|
122
125
|
# Modifies the indentation of the document.
|
|
@@ -127,85 +130,6 @@ module Haml
|
|
|
127
130
|
@real_tabs += tab_change
|
|
128
131
|
end
|
|
129
132
|
|
|
130
|
-
Haml::Util.def_static_method(self, :format_script, [:result],
|
|
131
|
-
:preserve_script, :in_tag, :preserve_tag, :escape_html,
|
|
132
|
-
:nuke_inner_whitespace, :interpolated, :ugly, <<RUBY)
|
|
133
|
-
<% # Escape HTML here so that the safety of the string is preserved in Rails
|
|
134
|
-
result_name = escape_html ? "html_escape(result.to_s)" : "result.to_s" %>
|
|
135
|
-
<% unless ugly %>
|
|
136
|
-
# If we're interpolated,
|
|
137
|
-
# then the custom tabulation is handled in #push_text.
|
|
138
|
-
# The easiest way to avoid it here is to reset @tabulation.
|
|
139
|
-
<% if interpolated %>
|
|
140
|
-
old_tabulation = @tabulation
|
|
141
|
-
@tabulation = 0
|
|
142
|
-
<% end %>
|
|
143
|
-
|
|
144
|
-
<% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
|
|
145
|
-
tabulation = @real_tabs
|
|
146
|
-
<% end %>
|
|
147
|
-
result = <%= result_name %>.<% if nuke_inner_whitespace %>strip<% else %>rstrip<% end %>
|
|
148
|
-
<% else %>
|
|
149
|
-
result = <%= result_name %><% if nuke_inner_whitespace %>.strip<% end %>
|
|
150
|
-
<% end %>
|
|
151
|
-
|
|
152
|
-
<% if preserve_tag %>
|
|
153
|
-
result = Haml::Helpers.preserve(result)
|
|
154
|
-
<% elsif preserve_script %>
|
|
155
|
-
result = Haml::Helpers.find_and_preserve(result, options[:preserve])
|
|
156
|
-
<% end %>
|
|
157
|
-
|
|
158
|
-
<% if ugly %>
|
|
159
|
-
fix_textareas!(result) if toplevel? && result.include?('<textarea')
|
|
160
|
-
return result
|
|
161
|
-
<% else %>
|
|
162
|
-
<% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
|
|
163
|
-
has_newline = result.include?("\\n")
|
|
164
|
-
<% end %>
|
|
165
|
-
|
|
166
|
-
<% if in_tag && !nuke_inner_whitespace %>
|
|
167
|
-
<% unless preserve_tag %> if !has_newline <% end %>
|
|
168
|
-
@real_tabs -= 1
|
|
169
|
-
<% if interpolated %> @tabulation = old_tabulation <% end %>
|
|
170
|
-
return result
|
|
171
|
-
<% unless preserve_tag %> end <% end %>
|
|
172
|
-
<% end %>
|
|
173
|
-
|
|
174
|
-
<% if !(in_tag && preserve_tag && !nuke_inner_whitespace) %>
|
|
175
|
-
# Precompiled tabulation may be wrong
|
|
176
|
-
<% if !interpolated && !in_tag %>
|
|
177
|
-
result = tabs + result if @tabulation > 0
|
|
178
|
-
<% end %>
|
|
179
|
-
|
|
180
|
-
if has_newline
|
|
181
|
-
result = result.gsub "\\n", "\\n" + tabs(tabulation)
|
|
182
|
-
|
|
183
|
-
# Add tabulation if it wasn't precompiled
|
|
184
|
-
<% if in_tag && !nuke_inner_whitespace %> result = tabs(tabulation) + result <% end %>
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
fix_textareas!(result) if toplevel? && result.include?('<textarea')
|
|
188
|
-
|
|
189
|
-
<% if in_tag && !nuke_inner_whitespace %>
|
|
190
|
-
result = "\\n\#{result}\\n\#{tabs(tabulation-1)}"
|
|
191
|
-
@real_tabs -= 1
|
|
192
|
-
<% end %>
|
|
193
|
-
<% if interpolated %> @tabulation = old_tabulation <% end %>
|
|
194
|
-
result
|
|
195
|
-
<% end %>
|
|
196
|
-
<% end %>
|
|
197
|
-
RUBY
|
|
198
|
-
|
|
199
|
-
def attributes(class_id, obj_ref, *attributes_hashes)
|
|
200
|
-
attributes = class_id
|
|
201
|
-
attributes_hashes.each do |old|
|
|
202
|
-
self.class.merge_attrs(attributes, Hash[old.map {|k, v| [k.to_s, v]}])
|
|
203
|
-
end
|
|
204
|
-
self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
|
|
205
|
-
Compiler.build_attributes(
|
|
206
|
-
html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
133
|
# Remove the whitespace from the right side of the buffer string.
|
|
210
134
|
# Doesn't do anything if we're at the beginning of a capture_haml block.
|
|
211
135
|
def rstrip!
|
|
@@ -217,50 +141,6 @@ RUBY
|
|
|
217
141
|
buffer << buffer.slice!(capture_position..-1).rstrip
|
|
218
142
|
end
|
|
219
143
|
|
|
220
|
-
# Merges two attribute hashes.
|
|
221
|
-
# This is the same as `to.merge!(from)`,
|
|
222
|
-
# except that it merges id, class, and data attributes.
|
|
223
|
-
#
|
|
224
|
-
# ids are concatenated with `"_"`,
|
|
225
|
-
# and classes are concatenated with `" "`.
|
|
226
|
-
# data hashes are simply merged.
|
|
227
|
-
#
|
|
228
|
-
# Destructively modifies both `to` and `from`.
|
|
229
|
-
#
|
|
230
|
-
# @param to [{String => String}] The attribute hash to merge into
|
|
231
|
-
# @param from [{String => #to_s}] The attribute hash to merge from
|
|
232
|
-
# @return [{String => String}] `to`, after being merged
|
|
233
|
-
def self.merge_attrs(to, from)
|
|
234
|
-
from['id'] = Compiler.filter_and_join(from['id'], '_') if from['id']
|
|
235
|
-
if to['id'] && from['id']
|
|
236
|
-
to['id'] << '_' << from.delete('id').to_s
|
|
237
|
-
elsif to['id'] || from['id']
|
|
238
|
-
from['id'] ||= to['id']
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
from['class'] = Compiler.filter_and_join(from['class'], ' ') if from['class']
|
|
242
|
-
if to['class'] && from['class']
|
|
243
|
-
# Make sure we don't duplicate class names
|
|
244
|
-
from['class'] = (from['class'].to_s.split(' ') | to['class'].split(' ')).sort.join(' ')
|
|
245
|
-
elsif to['class'] || from['class']
|
|
246
|
-
from['class'] ||= to['class']
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
from_data = from.delete('data') || {}
|
|
250
|
-
to_data = to.delete('data') || {}
|
|
251
|
-
|
|
252
|
-
# forces to_data & from_data into a hash
|
|
253
|
-
from_data = { nil => from_data } unless from_data.is_a?(Hash)
|
|
254
|
-
to_data = { nil => to_data } unless to_data.is_a?(Hash)
|
|
255
|
-
|
|
256
|
-
merged_data = to_data.merge(from_data)
|
|
257
|
-
|
|
258
|
-
to['data'] = merged_data unless merged_data.empty?
|
|
259
|
-
to.merge!(from)
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
private
|
|
263
|
-
|
|
264
144
|
# Works like #{find_and_preserve}, but allows the first newline after a
|
|
265
145
|
# preserved opening tag to remain unencoded, and then outdents the content.
|
|
266
146
|
# This change was motivated primarily by the change in Rails 3.2.3 to emit
|
|
@@ -270,6 +150,8 @@ RUBY
|
|
|
270
150
|
# @since Haml 4.0.1
|
|
271
151
|
# @private
|
|
272
152
|
def fix_textareas!(input)
|
|
153
|
+
return input unless input.include?('<textarea'.freeze)
|
|
154
|
+
|
|
273
155
|
pattern = /<(textarea)([^>]*)>(\n|
)(.*?)<\/textarea>/im
|
|
274
156
|
input.gsub!(pattern) do |s|
|
|
275
157
|
match = pattern.match(s)
|
|
@@ -281,16 +163,13 @@ RUBY
|
|
|
281
163
|
end
|
|
282
164
|
"<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
|
|
283
165
|
end
|
|
166
|
+
input
|
|
284
167
|
end
|
|
285
168
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
else
|
|
291
|
-
def new_encoded_string
|
|
292
|
-
"".encode(Encoding.find(options[:encoding]))
|
|
293
|
-
end
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
def new_encoded_string
|
|
172
|
+
"".encode(options[:encoding])
|
|
294
173
|
end
|
|
295
174
|
|
|
296
175
|
@@tab_cache = {}
|
|
@@ -299,47 +178,5 @@ RUBY
|
|
|
299
178
|
tabs = [count + @tabulation, 0].max
|
|
300
179
|
@@tab_cache[tabs] ||= ' ' * tabs
|
|
301
180
|
end
|
|
302
|
-
|
|
303
|
-
# Takes an array of objects and uses the class and id of the first
|
|
304
|
-
# one to create an attributes hash.
|
|
305
|
-
# The second object, if present, is used as a prefix,
|
|
306
|
-
# just like you can do with `dom_id()` and `dom_class()` in Rails
|
|
307
|
-
def parse_object_ref(ref)
|
|
308
|
-
prefix = ref[1]
|
|
309
|
-
ref = ref[0]
|
|
310
|
-
# Let's make sure the value isn't nil. If it is, return the default Hash.
|
|
311
|
-
return {} if ref.nil?
|
|
312
|
-
class_name =
|
|
313
|
-
if ref.respond_to?(:haml_object_ref)
|
|
314
|
-
ref.haml_object_ref
|
|
315
|
-
else
|
|
316
|
-
underscore(ref.class)
|
|
317
|
-
end
|
|
318
|
-
ref_id =
|
|
319
|
-
if ref.respond_to?(:to_key)
|
|
320
|
-
key = ref.to_key
|
|
321
|
-
key.join('_') unless key.nil?
|
|
322
|
-
else
|
|
323
|
-
ref.id
|
|
324
|
-
end
|
|
325
|
-
id = "#{class_name}_#{ref_id || 'new'}"
|
|
326
|
-
if prefix
|
|
327
|
-
class_name = "#{ prefix }_#{ class_name}"
|
|
328
|
-
id = "#{ prefix }_#{ id }"
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
{'id' => id, 'class' => class_name}
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
# Changes a word from camel case to underscores.
|
|
335
|
-
# Based on the method of the same name in Rails' Inflector,
|
|
336
|
-
# but copied here so it'll run properly without Rails.
|
|
337
|
-
def underscore(camel_cased_word)
|
|
338
|
-
camel_cased_word.to_s.gsub(/::/, '_').
|
|
339
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
340
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
341
|
-
tr("-", "_").
|
|
342
|
-
downcase
|
|
343
|
-
end
|
|
344
181
|
end
|
|
345
182
|
end
|