haml 4.0.7 → 5.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +36 -0
  3. data/.gitignore +19 -0
  4. data/.gitmodules +3 -0
  5. data/.yardopts +2 -3
  6. data/CHANGELOG.md +146 -4
  7. data/FAQ.md +4 -14
  8. data/Gemfile +16 -0
  9. data/MIT-LICENSE +2 -2
  10. data/README.md +90 -47
  11. data/REFERENCE.md +160 -74
  12. data/Rakefile +44 -63
  13. data/TODO +24 -0
  14. data/benchmark.rb +70 -0
  15. data/haml.gemspec +45 -0
  16. data/lib/haml/.gitattributes +1 -0
  17. data/lib/haml/attribute_builder.rb +219 -0
  18. data/lib/haml/attribute_compiler.rb +237 -0
  19. data/lib/haml/attribute_parser.rb +150 -0
  20. data/lib/haml/buffer.rb +12 -175
  21. data/lib/haml/compiler.rb +110 -320
  22. data/lib/haml/engine.rb +34 -41
  23. data/lib/haml/error.rb +28 -24
  24. data/lib/haml/escapable.rb +77 -0
  25. data/lib/haml/exec.rb +38 -20
  26. data/lib/haml/filters.rb +22 -27
  27. data/lib/haml/generator.rb +42 -0
  28. data/lib/haml/helpers/action_view_extensions.rb +4 -2
  29. data/lib/haml/helpers/action_view_mods.rb +45 -60
  30. data/lib/haml/helpers/action_view_xss_mods.rb +2 -0
  31. data/lib/haml/helpers/safe_erubi_template.rb +20 -0
  32. data/lib/haml/helpers/safe_erubis_template.rb +5 -1
  33. data/lib/haml/helpers/xss_mods.rb +23 -13
  34. data/lib/haml/helpers.rb +134 -89
  35. data/lib/haml/options.rb +63 -69
  36. data/lib/haml/parser.rb +319 -227
  37. data/lib/haml/plugin.rb +54 -0
  38. data/lib/haml/railtie.rb +43 -12
  39. data/lib/haml/sass_rails_filter.rb +18 -4
  40. data/lib/haml/template/options.rb +13 -2
  41. data/lib/haml/template.rb +13 -6
  42. data/lib/haml/temple_engine.rb +124 -0
  43. data/lib/haml/temple_line_counter.rb +30 -0
  44. data/lib/haml/util.rb +83 -202
  45. data/lib/haml/version.rb +3 -1
  46. data/lib/haml.rb +2 -0
  47. data/yard/default/.gitignore +1 -0
  48. data/yard/default/fulldoc/html/css/common.sass +15 -0
  49. data/yard/default/layout/html/footer.erb +12 -0
  50. metadata +73 -115
  51. data/lib/haml/template/plugin.rb +0 -41
  52. data/test/engine_test.rb +0 -2013
  53. data/test/erb/_av_partial_1.erb +0 -12
  54. data/test/erb/_av_partial_2.erb +0 -8
  55. data/test/erb/action_view.erb +0 -62
  56. data/test/erb/standard.erb +0 -55
  57. data/test/filters_test.rb +0 -254
  58. data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
  59. data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
  60. data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
  61. data/test/gemfiles/Gemfile.rails-4.0.x +0 -5
  62. data/test/haml-spec/LICENSE +0 -14
  63. data/test/haml-spec/README.md +0 -106
  64. data/test/haml-spec/lua_haml_spec.lua +0 -38
  65. data/test/haml-spec/perl_haml_test.pl +0 -81
  66. data/test/haml-spec/ruby_haml_test.rb +0 -23
  67. data/test/haml-spec/tests.json +0 -660
  68. data/test/helper_test.rb +0 -583
  69. data/test/markaby/standard.mab +0 -52
  70. data/test/mocks/article.rb +0 -6
  71. data/test/parser_test.rb +0 -105
  72. data/test/results/content_for_layout.xhtml +0 -12
  73. data/test/results/eval_suppressed.xhtml +0 -9
  74. data/test/results/helpers.xhtml +0 -70
  75. data/test/results/helpful.xhtml +0 -10
  76. data/test/results/just_stuff.xhtml +0 -70
  77. data/test/results/list.xhtml +0 -12
  78. data/test/results/nuke_inner_whitespace.xhtml +0 -40
  79. data/test/results/nuke_outer_whitespace.xhtml +0 -148
  80. data/test/results/original_engine.xhtml +0 -20
  81. data/test/results/partial_layout.xhtml +0 -5
  82. data/test/results/partial_layout_erb.xhtml +0 -5
  83. data/test/results/partials.xhtml +0 -21
  84. data/test/results/render_layout.xhtml +0 -3
  85. data/test/results/silent_script.xhtml +0 -74
  86. data/test/results/standard.xhtml +0 -162
  87. data/test/results/tag_parsing.xhtml +0 -23
  88. data/test/results/very_basic.xhtml +0 -5
  89. data/test/results/whitespace_handling.xhtml +0 -90
  90. data/test/template_test.rb +0 -354
  91. data/test/templates/_av_partial_1.haml +0 -9
  92. data/test/templates/_av_partial_1_ugly.haml +0 -9
  93. data/test/templates/_av_partial_2.haml +0 -5
  94. data/test/templates/_av_partial_2_ugly.haml +0 -5
  95. data/test/templates/_layout.erb +0 -3
  96. data/test/templates/_layout_for_partial.haml +0 -3
  97. data/test/templates/_partial.haml +0 -8
  98. data/test/templates/_text_area.haml +0 -3
  99. data/test/templates/_text_area_helper.html.haml +0 -4
  100. data/test/templates/action_view.haml +0 -47
  101. data/test/templates/action_view_ugly.haml +0 -47
  102. data/test/templates/breakage.haml +0 -8
  103. data/test/templates/content_for_layout.haml +0 -8
  104. data/test/templates/eval_suppressed.haml +0 -11
  105. data/test/templates/helpers.haml +0 -55
  106. data/test/templates/helpful.haml +0 -11
  107. data/test/templates/just_stuff.haml +0 -85
  108. data/test/templates/list.haml +0 -12
  109. data/test/templates/nuke_inner_whitespace.haml +0 -32
  110. data/test/templates/nuke_outer_whitespace.haml +0 -144
  111. data/test/templates/original_engine.haml +0 -17
  112. data/test/templates/partial_layout.haml +0 -3
  113. data/test/templates/partial_layout_erb.erb +0 -4
  114. data/test/templates/partialize.haml +0 -1
  115. data/test/templates/partials.haml +0 -12
  116. data/test/templates/render_layout.haml +0 -2
  117. data/test/templates/silent_script.haml +0 -45
  118. data/test/templates/standard.haml +0 -43
  119. data/test/templates/standard_ugly.haml +0 -43
  120. data/test/templates/tag_parsing.haml +0 -21
  121. data/test/templates/very_basic.haml +0 -4
  122. data/test/templates/whitespace_handling.haml +0 -87
  123. data/test/test_helper.rb +0 -81
  124. 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 = 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|&#x000A;)(.*?)<\/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
- if RUBY_VERSION < "1.9"
287
- def new_encoded_string
288
- ""
289
- end
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