haml 4.0.0 → 5.0.0
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 +7 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +117 -5
- data/FAQ.md +7 -17
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +181 -86
- data/Rakefile +47 -51
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +215 -0
- data/lib/haml/attribute_parser.rb +144 -0
- data/lib/haml/buffer.rb +38 -128
- data/lib/haml/compiler.rb +88 -295
- 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 +33 -19
- data/lib/haml/filters.rb +20 -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 +44 -66
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +27 -0
- data/lib/haml/helpers/safe_erubis_template.rb +16 -4
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +122 -58
- data/lib/haml/options.rb +39 -46
- data/lib/haml/parser.rb +278 -217
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -11
- 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 +120 -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 +2 -1
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +306 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +11 -0
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
- data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
- data/test/helper_test.rb +282 -96
- data/test/options_test.rb +22 -0
- data/test/parser_test.rb +71 -4
- data/test/results/bemit.xhtml +4 -0
- data/test/results/eval_suppressed.xhtml +4 -4
- data/test/results/helpers.xhtml +43 -41
- data/test/results/helpful.xhtml +6 -3
- data/test/results/just_stuff.xhtml +21 -20
- data/test/results/list.xhtml +9 -9
- data/test/results/nuke_inner_whitespace.xhtml +22 -22
- data/test/results/nuke_outer_whitespace.xhtml +84 -92
- data/test/results/original_engine.xhtml +17 -17
- data/test/results/partial_layout.xhtml +4 -3
- data/test/results/partial_layout_erb.xhtml +4 -3
- data/test/results/partials.xhtml +11 -10
- data/test/results/silent_script.xhtml +63 -63
- data/test/results/standard.xhtml +156 -159
- data/test/results/tag_parsing.xhtml +19 -19
- data/test/results/very_basic.xhtml +2 -2
- data/test/results/whitespace_handling.xhtml +56 -50
- data/test/template_test.rb +44 -53
- data/test/template_test_helper.rb +38 -0
- data/test/templates/_text_area_helper.html.haml +4 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/partial_layout_erb.erb +1 -1
- data/test/templates/standard_ugly.haml +1 -0
- data/test/templates/with_bom.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +26 -12
- data/test/util_test.rb +6 -47
- metadata +88 -106
- data/lib/haml/helpers/rails_323_textarea_fix.rb +0 -24
- 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-master +0 -4
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- 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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@compiler = @options.compiler_class.new(@options)
|
60
|
+
@temple_engine = TempleEngine.new(options)
|
61
|
+
@temple_engine.compile(@template)
|
62
|
+
end
|
65
63
|
|
66
|
-
|
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
|
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`
|
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,
|
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?(
|
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)
|
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.
|
125
|
-
|
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(@
|
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.
|
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,
|
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)
|
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
|
-
|
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
|
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 = {}); #{
|
223
|
-
@options
|
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.
|
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
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
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
|
-
|
298
|
-
|
299
|
-
|
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
|
-
|
304
|
-
|
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
|
-
|
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
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
220
|
-
|
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
|
-
|
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
|
-
|
244
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
@@ -385,6 +379,8 @@ RUBY
|
|
385
379
|
module Erb
|
386
380
|
class << self
|
387
381
|
def precompiled(text)
|
382
|
+
#workaround for https://github.com/rtomayko/tilt/pull/183
|
383
|
+
require 'erubis' if (defined?(::Erubis) && !defined?(::Erubis::Eruby))
|
388
384
|
super.sub(/^#coding:.*?\n/, '')
|
389
385
|
end
|
390
386
|
end
|
@@ -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
|
36
|
+
"#{controller.controller_name} #{controller.action_name}"
|
36
37
|
end
|
37
38
|
alias_method :generate_content_class_names, :page_class
|
38
39
|
|
@@ -45,8 +46,8 @@ 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
|
49
|
+
old = instance_variable_defined?(:@_haml_concat_raw) ? @_haml_concat_raw : false
|
48
50
|
@_haml_concat_raw = true
|
49
|
-
old = @_haml_concat_raw
|
50
51
|
yield
|
51
52
|
ensure
|
52
53
|
@_haml_concat_raw = old
|
@@ -1,60 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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)
|
41
41
|
if Haml::Helpers.block_is_haml?(block)
|
42
42
|
#double assignment is to avoid warnings
|
43
43
|
_hamlout = _hamlout = eval('_hamlout', block.binding) # Necessary since capture_haml checks _hamlout
|
44
|
-
|
45
|
-
|
46
|
-
str =
|
47
|
-
if !buffer.empty?
|
48
|
-
buffer
|
49
|
-
elsif value.is_a?(String)
|
50
|
-
value
|
51
|
-
else
|
52
|
-
''
|
53
|
-
end
|
54
|
-
# NonCattingString is present in Rails less than 3.1.0. When support
|
55
|
-
# for 3.0 is dropped, this can be removed.
|
56
|
-
return ActionView::NonConcattingString.new(str) if defined?(ActionView::NonConcattingString)
|
57
|
-
return str
|
44
|
+
|
45
|
+
capture_haml(*args, &block)
|
58
46
|
else
|
59
47
|
capture_without_haml(*args, &block)
|
60
48
|
end
|
@@ -67,7 +55,7 @@ module ActionView
|
|
67
55
|
def content_tag_with_haml(name, *args, &block)
|
68
56
|
return content_tag_without_haml(name, *args, &block) unless is_haml?
|
69
57
|
|
70
|
-
preserve = haml_buffer.options
|
58
|
+
preserve = haml_buffer.options.fetch(:preserve, %w[textarea pre code]).include?(name.to_s)
|
71
59
|
|
72
60
|
if block_given? && block_is_haml?(block) && preserve
|
73
61
|
return content_tag_without_haml(name, *args) {preserve(&block)}
|
@@ -82,8 +70,7 @@ module ActionView
|
|
82
70
|
alias_method :content_tag, :content_tag_with_haml
|
83
71
|
end
|
84
72
|
|
85
|
-
|
86
|
-
# Already includes TagHelper
|
73
|
+
module HamlSupport
|
87
74
|
include Haml::Helpers
|
88
75
|
|
89
76
|
def haml_buffer
|
@@ -93,6 +80,16 @@ module ActionView
|
|
93
80
|
def is_haml?
|
94
81
|
@template_object.send :is_haml?
|
95
82
|
end
|
83
|
+
end
|
84
|
+
|
85
|
+
module Tags
|
86
|
+
class TextArea
|
87
|
+
include HamlSupport
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class InstanceTag
|
92
|
+
include HamlSupport
|
96
93
|
|
97
94
|
def content_tag(*args, &block)
|
98
95
|
html_tag = content_tag_with_haml(*args, &block)
|
@@ -114,7 +111,7 @@ module ActionView
|
|
114
111
|
with_tabs(1) {oldproc.call(*args)}
|
115
112
|
end
|
116
113
|
end
|
117
|
-
res = form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc)
|
114
|
+
res = form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc) << "\n"
|
118
115
|
res << "\n" if wrap_block
|
119
116
|
res
|
120
117
|
else
|
@@ -124,24 +121,5 @@ module ActionView
|
|
124
121
|
alias_method :form_tag_without_haml, :form_tag
|
125
122
|
alias_method :form_tag, :form_tag_with_haml
|
126
123
|
end
|
127
|
-
|
128
|
-
module FormHelper
|
129
|
-
def form_for_with_haml(object_name, *args, &proc)
|
130
|
-
wrap_block = block_given? && is_haml? && block_is_haml?(proc)
|
131
|
-
if wrap_block
|
132
|
-
oldproc = proc
|
133
|
-
proc = proc {|*subargs| with_tabs(1) {oldproc.call(*subargs)}}
|
134
|
-
end
|
135
|
-
res = form_for_without_haml(object_name, *args, &proc)
|
136
|
-
res << "\n" if wrap_block
|
137
|
-
res
|
138
|
-
end
|
139
|
-
alias_method :form_for_without_haml, :form_for
|
140
|
-
alias_method :form_for, :form_for_with_haml
|
141
|
-
end
|
142
124
|
end
|
143
125
|
end
|
144
|
-
|
145
|
-
if ((ActionPack::VERSION::MAJOR == 3) && (ActionPack::VERSION::MINOR >= 2) && (ActionPack::VERSION::TINY >= 3) || (ActionPack::VERSION::MAJOR == 4))
|
146
|
-
require "haml/helpers/rails_323_textarea_fix"
|
147
|
-
end
|