haml 4.0.6 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +49 -4
  4. data/FAQ.md +4 -14
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +85 -42
  7. data/REFERENCE.md +109 -58
  8. data/Rakefile +46 -54
  9. data/lib/haml/attribute_builder.rb +163 -0
  10. data/lib/haml/attribute_compiler.rb +215 -0
  11. data/lib/haml/attribute_parser.rb +144 -0
  12. data/lib/haml/buffer.rb +26 -136
  13. data/lib/haml/compiler.rb +87 -295
  14. data/lib/haml/engine.rb +25 -41
  15. data/lib/haml/error.rb +3 -0
  16. data/lib/haml/escapable.rb +49 -0
  17. data/lib/haml/exec.rb +33 -19
  18. data/lib/haml/filters.rb +18 -24
  19. data/lib/haml/generator.rb +41 -0
  20. data/lib/haml/helpers/action_view_extensions.rb +3 -2
  21. data/lib/haml/helpers/action_view_mods.rb +36 -58
  22. data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
  23. data/lib/haml/helpers/safe_erubi_template.rb +27 -0
  24. data/lib/haml/helpers/safe_erubis_template.rb +4 -1
  25. data/lib/haml/helpers/xss_mods.rb +18 -12
  26. data/lib/haml/helpers.rb +133 -90
  27. data/lib/haml/options.rb +38 -47
  28. data/lib/haml/parser.rb +278 -216
  29. data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
  30. data/lib/haml/railtie.rb +21 -12
  31. data/lib/haml/sass_rails_filter.rb +17 -4
  32. data/lib/haml/template/options.rb +12 -2
  33. data/lib/haml/template.rb +12 -6
  34. data/lib/haml/temple_engine.rb +120 -0
  35. data/lib/haml/temple_line_counter.rb +29 -0
  36. data/lib/haml/util.rb +80 -199
  37. data/lib/haml/version.rb +2 -1
  38. data/lib/haml.rb +1 -0
  39. data/test/attribute_parser_test.rb +101 -0
  40. data/test/engine_test.rb +287 -176
  41. data/test/filters_test.rb +32 -19
  42. data/test/gemfiles/Gemfile.rails-4.0.x +9 -3
  43. data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
  44. data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
  45. data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
  46. data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
  47. data/test/helper_test.rb +224 -112
  48. data/test/options_test.rb +22 -0
  49. data/test/parser_test.rb +71 -4
  50. data/test/results/bemit.xhtml +4 -0
  51. data/test/results/eval_suppressed.xhtml +4 -4
  52. data/test/results/helpers.xhtml +43 -41
  53. data/test/results/helpful.xhtml +6 -3
  54. data/test/results/just_stuff.xhtml +21 -20
  55. data/test/results/list.xhtml +9 -9
  56. data/test/results/nuke_inner_whitespace.xhtml +22 -22
  57. data/test/results/nuke_outer_whitespace.xhtml +84 -92
  58. data/test/results/original_engine.xhtml +17 -17
  59. data/test/results/partial_layout.xhtml +4 -3
  60. data/test/results/partial_layout_erb.xhtml +4 -3
  61. data/test/results/partials.xhtml +11 -10
  62. data/test/results/silent_script.xhtml +63 -63
  63. data/test/results/standard.xhtml +156 -159
  64. data/test/results/tag_parsing.xhtml +19 -19
  65. data/test/results/very_basic.xhtml +2 -2
  66. data/test/results/whitespace_handling.xhtml +77 -76
  67. data/test/template_test.rb +24 -56
  68. data/test/template_test_helper.rb +38 -0
  69. data/test/templates/bemit.haml +3 -0
  70. data/test/templates/just_stuff.haml +1 -0
  71. data/test/templates/standard_ugly.haml +1 -0
  72. data/test/templates/with_bom.haml +1 -0
  73. data/test/temple_line_counter_test.rb +40 -0
  74. data/test/test_helper.rb +26 -8
  75. data/test/util_test.rb +6 -47
  76. metadata +53 -36
  77. data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
  78. data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
  79. data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
  80. data/test/templates/_av_partial_1_ugly.haml +0 -9
  81. data/test/templates/_av_partial_2_ugly.haml +0 -5
  82. data/test/templates/action_view_ugly.haml +0 -47
  83. data/test/templates/standard_ugly.haml +0 -43
data/lib/haml/engine.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require 'forwardable'
2
3
 
3
4
  require 'haml/parser'
@@ -7,6 +8,7 @@ require 'haml/helpers'
7
8
  require 'haml/buffer'
8
9
  require 'haml/filters'
9
10
  require 'haml/error'
11
+ require 'haml/temple_engine'
10
12
 
11
13
  module Haml
12
14
  # This is the frontend for using Haml programmatically.
@@ -35,9 +37,6 @@ module Haml
35
37
  # @return [String]
36
38
  attr_accessor :indentation
37
39
 
38
- attr_accessor :compiler
39
- attr_accessor :parser
40
-
41
40
  # Tilt currently depends on these moved methods, provide a stable API
42
41
  def_delegators :compiler, :precompiled, :precompiled_method_return_value
43
42
 
@@ -58,19 +57,19 @@ module Haml
58
57
  raise Haml::Error.new(msg, line)
59
58
  end
60
59
 
61
- initialize_encoding options[:encoding]
62
-
63
- @parser = @options.parser_class.new(@template, @options)
64
- @compiler = @options.compiler_class.new(@options)
60
+ @temple_engine = TempleEngine.new(options)
61
+ @temple_engine.compile(@template)
62
+ end
65
63
 
66
- @compiler.compile(@parser.parse)
64
+ # Deprecated API for backword compatibility
65
+ def compiler
66
+ @temple_engine
67
67
  end
68
68
 
69
69
  # Processes the template and returns the result as a string.
70
70
  #
71
71
  # `scope` is the context in which the template is evaluated.
72
- # If it's a `Binding` or `Proc` object,
73
- # Haml uses it as the second argument to `Kernel#eval`;
72
+ # If it's a `Binding`, Haml uses it as the second argument to `Kernel#eval`;
74
73
  # otherwise, Haml just uses its `#instance_eval` context.
75
74
  #
76
75
  # Note that Haml modifies the evaluation context
@@ -95,23 +94,23 @@ module Haml
95
94
  # within the template.
96
95
  #
97
96
  # Due to some Ruby quirks,
98
- # if `scope` is a `Binding` or `Proc` object and a block is given,
97
+ # if `scope` is a `Binding` object and a block is given,
99
98
  # the evaluation context may not be quite what the user expects.
100
99
  # In particular, it's equivalent to passing `eval("self", scope)` as `scope`.
101
100
  # This won't have an effect in most cases,
102
101
  # but if you're relying on local variables defined in the context of `scope`,
103
102
  # they won't work.
104
103
  #
105
- # @param scope [Binding, Proc, Object] The context in which the template is evaluated
104
+ # @param scope [Binding, Object] The context in which the template is evaluated
106
105
  # @param locals [{Symbol => Object}] Local variables that will be made available
107
106
  # to the template
108
107
  # @param block [#to_proc] A block that can be yielded to within the template
109
108
  # @return [String] The rendered template
110
109
  def render(scope = Object.new, locals = {}, &block)
111
- parent = scope.instance_variable_defined?('@haml_buffer') ? scope.instance_variable_get('@haml_buffer') : nil
110
+ parent = scope.instance_variable_defined?(:@haml_buffer) ? scope.instance_variable_get(:@haml_buffer) : nil
112
111
  buffer = Haml::Buffer.new(parent, @options.for_buffer)
113
112
 
114
- if scope.is_a?(Binding) || scope.is_a?(Proc)
113
+ if scope.is_a?(Binding)
115
114
  scope_object = eval("self", scope)
116
115
  scope = scope_object.instance_eval{binding} if block_given?
117
116
  else
@@ -121,20 +120,16 @@ module Haml
121
120
 
122
121
  set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
123
122
 
124
- scope_object.instance_eval do
125
- extend Haml::Helpers
126
- @haml_buffer = buffer
127
- end
123
+ scope_object.extend(Haml::Helpers)
124
+ scope_object.instance_variable_set(:@haml_buffer, buffer)
128
125
  begin
129
- eval(@compiler.precompiled_with_return_value, scope, @options[:filename], @options[:line])
126
+ eval(@temple_engine.precompiled_with_return_value, scope, @options.filename, @options.line)
130
127
  rescue ::SyntaxError => e
131
128
  raise SyntaxError, e.message
132
129
  end
133
130
  ensure
134
131
  # Get rid of the current buffer
135
- scope_object.instance_eval do
136
- @haml_buffer = buffer.upper if buffer
137
- end
132
+ scope_object.instance_variable_set(:@haml_buffer, buffer.upper) if buffer
138
133
  end
139
134
  alias_method :to_html, :render
140
135
 
@@ -159,11 +154,11 @@ module Haml
159
154
  #
160
155
  # The proc doesn't take a block; any yields in the template will fail.
161
156
  #
162
- # @param scope [Binding, Proc, Object] The context in which the template is evaluated
157
+ # @param scope [Binding, Object] The context in which the template is evaluated
163
158
  # @param local_names [Array<Symbol>] The names of the locals that can be passed to the proc
164
159
  # @return [Proc] The proc that will run the template
165
160
  def render_proc(scope = Object.new, *local_names)
166
- if scope.is_a?(Binding) || scope.is_a?(Proc)
161
+ if scope.is_a?(Binding)
167
162
  scope_object = eval("self", scope)
168
163
  else
169
164
  scope_object = scope
@@ -171,8 +166,8 @@ module Haml
171
166
  end
172
167
 
173
168
  begin
174
- eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
175
- compiler.precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
169
+ eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" <<
170
+ @temple_engine.precompiled_with_ambles(local_names) << "}\n", scope, @options.filename, @options.line)
176
171
  rescue ::SyntaxError => e
177
172
  raise SyntaxError, e.message
178
173
  end
@@ -182,7 +177,7 @@ module Haml
182
177
  # that renders the template and returns the result as a string.
183
178
  #
184
179
  # If `object` is a class or module,
185
- # the method will instead by defined as an instance method.
180
+ # the method will instead be defined as an instance method.
186
181
  # For example:
187
182
  #
188
183
  # t = Time.now
@@ -219,25 +214,14 @@ module Haml
219
214
  def def_method(object, name, *local_names)
220
215
  method = object.is_a?(Module) ? :module_eval : :instance_eval
221
216
 
222
- object.send(method, "def #{name}(_haml_locals = {}); #{compiler.precompiled_with_ambles(local_names)}; end",
223
- @options[:filename], @options[:line])
217
+ object.send(method, "def #{name}(_haml_locals = {}); #{@temple_engine.precompiled_with_ambles(local_names)}; end",
218
+ @options.filename, @options.line)
224
219
  end
225
220
 
226
221
  private
227
222
 
228
- if RUBY_VERSION < "1.9"
229
- def initialize_encoding(given_value)
230
- end
231
- else
232
- def initialize_encoding(given_value)
233
- unless given_value
234
- @options.encoding = Encoding.default_internal || @template.encoding
235
- end
236
- end
237
- end
238
-
239
223
  def set_locals(locals, scope, scope_object)
240
- scope_object.send(:instance_variable_set, '@_haml_locals', locals)
224
+ scope_object.instance_variable_set :@_haml_locals, locals
241
225
  set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
242
226
  eval(set_locals, scope)
243
227
  end
data/lib/haml/error.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  # An exception raised by Haml code.
3
4
  class Error < StandardError
@@ -58,4 +59,6 @@ END
58
59
  # It's not particularly interesting,
59
60
  # except in that it's a subclass of {Haml::Error}.
60
61
  class SyntaxError < Error; end
62
+
63
+ class InvalidAttributeNameError < SyntaxError; end
61
64
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ # Like Temple::Filters::Escapable, but with support for escaping by
4
+ # Haml::Herlpers.html_escape and Haml::Herlpers.escape_once.
5
+ class Escapable < Temple::Filter
6
+ def initialize(*)
7
+ super
8
+ @escape_code = "::Haml::Helpers.html_escape((%s))"
9
+ @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
10
+ @once_escape_code = "::Haml::Helpers.escape_once((%s))"
11
+ @once_escaper = eval("proc {|v| #{@once_escape_code % 'v'} }")
12
+ @escape = false
13
+ end
14
+
15
+ def on_escape(flag, exp)
16
+ old = @escape
17
+ @escape = flag
18
+ compile(exp)
19
+ ensure
20
+ @escape = old
21
+ end
22
+
23
+ # The same as Haml::AttributeBuilder.build_attributes
24
+ def on_static(value)
25
+ [:static,
26
+ if @escape == :once
27
+ @once_escaper[value]
28
+ elsif @escape
29
+ @escaper[value]
30
+ else
31
+ value
32
+ end
33
+ ]
34
+ end
35
+
36
+ # The same as Haml::AttributeBuilder.build_attributes
37
+ def on_dynamic(value)
38
+ [:dynamic,
39
+ if @escape == :once
40
+ @once_escape_code % value
41
+ elsif @escape
42
+ @escape_code % value
43
+ else
44
+ "(#{value}).to_s"
45
+ end
46
+ ]
47
+ end
48
+ end
49
+ end
data/lib/haml/exec.rb CHANGED
@@ -1,5 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
- require 'fileutils'
3
3
  require 'rbconfig'
4
4
  require 'pp'
5
5
 
@@ -212,11 +212,6 @@ END
212
212
  @options[:output] = StringIO.new
213
213
  end
214
214
 
215
- opts.on('-t', '--style NAME',
216
- 'Output style. Can be indented (default) or ugly.') do |name|
217
- @options[:for_engine][:ugly] = true if name.to_sym == :ugly
218
- end
219
-
220
215
  opts.on('-f', '--format NAME',
221
216
  'Output format. Can be html5 (default), xhtml, or html4.') do |name|
222
217
  @options[:for_engine][:format] = name.to_sym
@@ -237,6 +232,11 @@ END
237
232
  @options[:for_engine][:attr_wrapper] = '"'
238
233
  end
239
234
 
235
+ opts.on('--remove-whitespace',
236
+ 'Remove whitespace surrounding and within tags') do
237
+ @options[:for_engine][:remove_whitespace] = true
238
+ end
239
+
240
240
  opts.on('--cdata',
241
241
  'Always add CDATA sections to javascript and css blocks.') do
242
242
  @options[:for_engine][:cdata] = true
@@ -260,15 +260,13 @@ END
260
260
  @options[:load_paths] << path
261
261
  end
262
262
 
263
- unless RUBY_VERSION < "1.9"
264
- opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
265
- external, internal = encoding.split(':')
266
- Encoding.default_external = external if external && !external.empty?
267
- Encoding.default_internal = internal if internal && !internal.empty?
268
- end
263
+ opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
264
+ external, internal = encoding.split(':')
265
+ Encoding.default_external = external if external && !external.empty?
266
+ Encoding.default_internal = internal if internal && !internal.empty?
269
267
  end
270
268
 
271
- opts.on('-d', '--debug', "Print out the precompiled Ruby source.") do
269
+ opts.on('-d', '--debug', "Print out the precompiled Ruby source, and show syntax errors in the Ruby code.") do
272
270
  @options[:debug] = true
273
271
  end
274
272
 
@@ -294,20 +292,28 @@ END
294
292
 
295
293
  begin
296
294
 
297
- engine = ::Haml::Engine.new(template, @options[:for_engine])
298
- if @options[:check_syntax]
299
- puts "Syntax OK"
295
+ if @options[:parse]
296
+ parser = ::Haml::Parser.new(::Haml::Options.new(@options))
297
+ pp parser.call(template)
300
298
  return
301
299
  end
302
300
 
303
- if @options[:parse]
304
- pp engine.parser.root
301
+ engine = ::Haml::Engine.new(template, @options[:for_engine])
302
+
303
+ if @options[:check_syntax]
304
+ puts "Syntax OK"
305
305
  return
306
306
  end
307
307
 
308
308
  if @options[:debug]
309
309
  puts engine.precompiled
310
- puts '=' * 100
310
+ error = validate_ruby(engine.precompiled)
311
+ if error
312
+ puts '=' * 100
313
+ puts error.message.split("\n")[0]
314
+ exit 1
315
+ end
316
+ return
311
317
  end
312
318
 
313
319
  result = engine.to_html
@@ -324,6 +330,14 @@ END
324
330
  output.write(result)
325
331
  output.close() if output.is_a? File
326
332
  end
333
+
334
+ def validate_ruby(code)
335
+ begin
336
+ eval("BEGIN {return nil}; #{code}")
337
+ rescue ::SyntaxError # Not to be confused with Haml::SyntaxError
338
+ $!
339
+ end
340
+ end
327
341
  end
328
342
  end
329
343
  end
data/lib/haml/filters.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  require "tilt"
2
3
 
3
4
  module Haml
@@ -59,7 +60,7 @@ module Haml
59
60
  end
60
61
 
61
62
  # Removes a filter from Haml. If the filter was removed, it returns
62
- # the that was remove Module upon success, or nil on failure. If you try
63
+ # the Module that was removed upon success, or nil on failure. If you try
63
64
  # to redefine a filter, Haml will raise an error. Use this method first to
64
65
  # explicitly remove the filter before redefining it.
65
66
  # @return Module The filter module that has been removed
@@ -163,10 +164,10 @@ module Haml
163
164
  if contains_interpolation?(text)
164
165
  return if options[:suppress_eval]
165
166
 
166
- text = unescape_interpolation(text).gsub(/(\\+)n/) do |s|
167
+ text = unescape_interpolation(text, options[:escape_html]).gsub(/(\\+)n/) do |s|
167
168
  escapes = $1.size
168
169
  next s if escapes % 2 == 0
169
- ("\\" * (escapes - 1)) + "\n"
170
+ "#{'\\' * (escapes - 1)}\n"
170
171
  end
171
172
  # We need to add a newline at the beginning to get the
172
173
  # filter lines to line up (since the Haml filter contains
@@ -174,7 +175,7 @@ module Haml
174
175
  # filter name). Then we need to escape the trailing
175
176
  # newline so that the whole filter block doesn't take up
176
177
  # too many.
177
- text = "\n" + text.sub(/\n"\Z/, "\\n\"")
178
+ text = %[\n#{text.sub(/\n"\Z/, "\\n\"")}]
178
179
  push_script <<RUBY.rstrip, :escape_html => false
179
180
  find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
180
181
  RUBY
@@ -182,12 +183,8 @@ RUBY
182
183
  end
183
184
 
184
185
  rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text, compiler.options), compiler.options[:preserve])
185
-
186
- if options[:ugly]
187
- push_text(rendered.rstrip)
188
- else
189
- push_text(rendered.rstrip.gsub("\n", "\n#{' ' * @output_tabs}"))
190
- end
186
+ rendered.rstrip!
187
+ push_text("#{rendered}\n")
191
188
  end
192
189
  end
193
190
  end
@@ -216,13 +213,10 @@ RUBY
216
213
  type = " type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}"
217
214
  end
218
215
 
219
- str = "<script#{type}>\n"
220
- str << " //<![CDATA[\n" if options[:cdata]
221
- str << "#{indent}#{text.rstrip.gsub("\n", "\n#{indent}")}\n"
222
- str << " //]]>\n" if options[:cdata]
223
- str << "</script>"
216
+ text = text.rstrip
217
+ text.gsub!("\n", "\n#{indent}")
224
218
 
225
- str
219
+ %!<script#{type}>\n#{" //<![CDATA[\n" if options[:cdata]}#{indent}#{text}\n#{" //]]>\n" if options[:cdata]}</script>!
226
220
  end
227
221
  end
228
222
 
@@ -240,13 +234,10 @@ RUBY
240
234
  type = " type=#{options[:attr_wrapper]}text/css#{options[:attr_wrapper]}"
241
235
  end
242
236
 
243
- str = "<style#{type}>\n"
244
- str << " /*<![CDATA[*/\n" if options[:cdata]
245
- str << "#{indent}#{text.rstrip.gsub("\n", "\n#{indent}")}\n"
246
- str << " /*]]>*/\n" if options[:cdata]
247
- str << "</style>"
237
+ text = text.rstrip
238
+ text.gsub!("\n", "\n#{indent}")
248
239
 
249
- str
240
+ %(<style#{type}>\n#{" /*<![CDATA[*/\n" if options[:cdata]}#{indent}#{text}\n#{" /*]]>*/\n" if options[:cdata]}</style>)
250
241
  end
251
242
  end
252
243
 
@@ -256,7 +247,10 @@ RUBY
256
247
 
257
248
  # @see Base#render
258
249
  def render(text)
259
- "<![CDATA[#{("\n" + text).rstrip.gsub("\n", "\n ")}\n]]>"
250
+ text = "\n#{text}"
251
+ text.rstrip!
252
+ text.gsub!("\n", "\n ")
253
+ "<![CDATA[#{text}\n]]>"
260
254
  end
261
255
  end
262
256
 
@@ -288,7 +282,7 @@ RUBY
288
282
  def compile(compiler, text)
289
283
  return if compiler.options[:suppress_eval]
290
284
  compiler.instance_eval do
291
- push_silent <<-FIRST.gsub("\n", ';') + text + <<-LAST.gsub("\n", ';')
285
+ push_silent <<-FIRST.tr("\n", ';') + text + <<-LAST.tr("\n", ';')
292
286
  begin
293
287
  haml_io = StringIO.new(_hamlout.buffer, 'a')
294
288
  FIRST
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ # Ruby code generator, which is a limited version of Temple::Generator.
4
+ # Limit methods since Haml doesn't need most of them.
5
+ class Generator
6
+ include Temple::Mixins::CompiledDispatcher
7
+ include Temple::Mixins::Options
8
+
9
+ define_options freeze_static: RUBY_VERSION >= '2.1'
10
+
11
+ def call(exp)
12
+ compile(exp)
13
+ end
14
+
15
+ def on_multi(*exp)
16
+ exp.map { |e| compile(e) }.join('; ')
17
+ end
18
+
19
+ def on_static(text)
20
+ concat(options[:freeze_static] ? "#{Util.inspect_obj(text)}.freeze" : Util.inspect_obj(text))
21
+ end
22
+
23
+ def on_dynamic(code)
24
+ concat(code)
25
+ end
26
+
27
+ def on_code(exp)
28
+ exp
29
+ end
30
+
31
+ def on_newline
32
+ "\n"
33
+ end
34
+
35
+ private
36
+
37
+ def concat(str)
38
+ "_hamlout.buffer << (#{str});"
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Haml
2
3
  module Helpers
3
4
  @@action_view_defined = true
@@ -32,7 +33,7 @@ module Haml
32
33
  #
33
34
  # @return [String] The class name for the current page
34
35
  def page_class
35
- controller.controller_name + " " + controller.action_name
36
+ "#{controller.controller_name} #{controller.action_name}"
36
37
  end
37
38
  alias_method :generate_content_class_names, :page_class
38
39
 
@@ -45,7 +46,7 @@ module Haml
45
46
  # @yield A block in which all input to `#haml_concat` is treated as raw.
46
47
  # @see Haml::Util#rails_xss_safe?
47
48
  def with_raw_haml_concat
48
- old = instance_variable_defined?('@_haml_concat_raw') ? @_haml_concat_raw : false
49
+ old = instance_variable_defined?(:@_haml_concat_raw) ? @_haml_concat_raw : false
49
50
  @_haml_concat_raw = true
50
51
  yield
51
52
  ensure
@@ -1,40 +1,40 @@
1
- module ActionView
2
- class Base
3
- def render_with_haml(*args, &block)
4
- options = args.first
5
-
6
- # If render :layout is used with a block, it concats rather than returning
7
- # a string so we need it to keep thinking it's Haml until it hits the
8
- # sub-render.
9
- if is_haml? && !(options.is_a?(Hash) && options[:layout] && block_given?)
10
- return non_haml { render_without_haml(*args, &block) }
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ module Helpers
4
+ module ActionViewMods
5
+ def render(*args, &block)
6
+ options = args.first
7
+
8
+ # If render :layout is used with a block, it concats rather than returning
9
+ # a string so we need it to keep thinking it's Haml until it hits the
10
+ # sub-render.
11
+ if is_haml? && !(options.is_a?(Hash) && options[:layout] && block_given?)
12
+ return non_haml { super }
13
+ end
14
+ super
11
15
  end
12
- render_without_haml(*args, &block)
13
- end
14
- alias_method :render_without_haml, :render
15
- alias_method :render, :render_with_haml
16
16
 
17
- def output_buffer_with_haml
18
- return haml_buffer.buffer if is_haml?
19
- output_buffer_without_haml
20
- end
21
- alias_method :output_buffer_without_haml, :output_buffer
22
- alias_method :output_buffer, :output_buffer_with_haml
17
+ def output_buffer
18
+ return haml_buffer.buffer if is_haml?
19
+ super
20
+ end
23
21
 
24
- def set_output_buffer_with_haml(new_buffer)
25
- if is_haml?
26
- if Haml::Util.rails_xss_safe? && new_buffer.is_a?(ActiveSupport::SafeBuffer)
27
- new_buffer = String.new(new_buffer)
22
+ def output_buffer=(new_buffer)
23
+ if is_haml?
24
+ if Haml::Util.rails_xss_safe? && new_buffer.is_a?(ActiveSupport::SafeBuffer)
25
+ new_buffer = String.new(new_buffer)
26
+ end
27
+ haml_buffer.buffer = new_buffer
28
+ else
29
+ super
28
30
  end
29
- haml_buffer.buffer = new_buffer
30
- else
31
- set_output_buffer_without_haml new_buffer
32
31
  end
33
32
  end
34
- alias_method :set_output_buffer_without_haml, :output_buffer=
35
- alias_method :output_buffer=, :set_output_buffer_with_haml
33
+ ActionView::Base.send(:prepend, ActionViewMods)
36
34
  end
35
+ end
37
36
 
37
+ module ActionView
38
38
  module Helpers
39
39
  module CaptureHelper
40
40
  def capture_with_haml(*args, &block)
@@ -42,12 +42,7 @@ module ActionView
42
42
  #double assignment is to avoid warnings
43
43
  _hamlout = _hamlout = eval('_hamlout', block.binding) # Necessary since capture_haml checks _hamlout
44
44
 
45
- str = capture_haml(*args, &block)
46
-
47
- # NonCattingString is present in Rails less than 3.1.0. When support
48
- # for 3.0 is dropped, this can be removed.
49
- return ActionView::NonConcattingString.new(str) if str && defined?(ActionView::NonConcattingString)
50
- return str
45
+ capture_haml(*args, &block)
51
46
  else
52
47
  capture_without_haml(*args, &block)
53
48
  end
@@ -60,7 +55,7 @@ module ActionView
60
55
  def content_tag_with_haml(name, *args, &block)
61
56
  return content_tag_without_haml(name, *args, &block) unless is_haml?
62
57
 
63
- preserve = haml_buffer.options[:preserve].include?(name.to_s)
58
+ preserve = haml_buffer.options.fetch(:preserve, %w[textarea pre code]).include?(name.to_s)
64
59
 
65
60
  if block_given? && block_is_haml?(block) && preserve
66
61
  return content_tag_without_haml(name, *args) {preserve(&block)}
@@ -87,11 +82,9 @@ module ActionView
87
82
  end
88
83
  end
89
84
 
90
- if ActionPack::VERSION::MAJOR == 4
91
- module Tags
92
- class TextArea
93
- include HamlSupport
94
- end
85
+ module Tags
86
+ class TextArea
87
+ include HamlSupport
95
88
  end
96
89
  end
97
90
 
@@ -118,7 +111,7 @@ module ActionView
118
111
  with_tabs(1) {oldproc.call(*args)}
119
112
  end
120
113
  end
121
- res = form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc) + "\n"
114
+ res = form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc) << "\n"
122
115
  res << "\n" if wrap_block
123
116
  res
124
117
  else
@@ -128,20 +121,5 @@ module ActionView
128
121
  alias_method :form_tag_without_haml, :form_tag
129
122
  alias_method :form_tag, :form_tag_with_haml
130
123
  end
131
-
132
- module FormHelper
133
- def form_for_with_haml(object_name, *args, &proc)
134
- wrap_block = block_given? && is_haml? && block_is_haml?(proc)
135
- if wrap_block
136
- oldproc = proc
137
- proc = proc {|*subargs| with_tabs(1) {oldproc.call(*subargs)}}
138
- end
139
- res = form_for_without_haml(object_name, *args, &proc)
140
- res << "\n" if wrap_block
141
- res
142
- end
143
- alias_method :form_for_without_haml, :form_for
144
- alias_method :form_for, :form_for_with_haml
145
- end
146
124
  end
147
- end
125
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActionView
2
3
  module Helpers
3
4
  module CaptureHelper
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require 'action_view'
3
+
4
+ module Haml
5
+ class ErubiTemplateHandler < ActionView::Template::Handlers::ERB::Erubi
6
+
7
+ def initialize(*args, &blk)
8
+ @newline_pending = 0
9
+ super
10
+ end
11
+ end
12
+
13
+ class SafeErubiTemplate < Tilt::ErubiTemplate
14
+ def prepare
15
+ @options.merge! engine_class: Haml::ErubiTemplateHandler
16
+ super
17
+ end
18
+
19
+ def precompiled_preamble(locals)
20
+ [super, "@output_buffer = ActionView::OutputBuffer.new;"].join("\n")
21
+ end
22
+
23
+ def precompiled_postamble(locals)
24
+ [super, '@output_buffer.to_s'].join("\n")
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require 'action_view'
3
+
1
4
  module Haml
2
5
 
3
6
  class ErubisTemplateHandler < ActionView::Template::Handlers::Erubis
@@ -26,4 +29,4 @@ module Haml
26
29
  [super, '@output_buffer.to_s'].join("\n")
27
30
  end
28
31
  end
29
- end
32
+ end