haml 4.0.7 → 4.1.0.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -23
- data/README.md +3 -2
- data/REFERENCE.md +24 -9
- data/Rakefile +5 -4
- data/lib/haml/buffer.rb +27 -26
- data/lib/haml/compiler.rb +71 -70
- data/lib/haml/engine.rb +16 -26
- data/lib/haml/exec.rb +9 -7
- data/lib/haml/filters.rb +16 -22
- data/lib/haml/helpers.rb +97 -74
- data/lib/haml/helpers/action_view_extensions.rb +2 -2
- data/lib/haml/helpers/action_view_mods.rb +10 -3
- data/lib/haml/options.rb +6 -14
- data/lib/haml/parser.rb +184 -182
- data/lib/haml/util.rb +67 -78
- data/lib/haml/version.rb +1 -1
- data/test/engine_test.rb +80 -71
- data/test/gemfiles/Gemfile.rails-3.0.x +1 -1
- data/test/gemfiles/Gemfile.rails-3.1.x +1 -1
- data/test/gemfiles/Gemfile.rails-3.2.x +1 -1
- data/test/gemfiles/Gemfile.rails-4.0.x +1 -1
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +101 -0
- data/test/helper_test.rb +85 -33
- data/test/parser_test.rb +22 -0
- data/test/template_test.rb +1 -29
- data/test/templates/with_bom.haml +1 -0
- data/test/test_helper.rb +4 -0
- data/test/util_test.rb +7 -1
- metadata +39 -44
- 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/lib/haml/engine.rb
CHANGED
@@ -69,8 +69,7 @@ module Haml
|
|
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,14 +94,14 @@ 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
|
@@ -111,7 +110,7 @@ module Haml
|
|
111
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(@compiler.precompiled_with_return_value, scope, @options
|
126
|
+
eval(@compiler.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
|
@@ -172,7 +167,7 @@ module Haml
|
|
172
167
|
|
173
168
|
begin
|
174
169
|
eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
|
175
|
-
compiler.precompiled_with_ambles(local_names) + "}\n", scope, @options
|
170
|
+
compiler.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
|
@@ -220,24 +215,19 @@ module Haml
|
|
220
215
|
method = object.is_a?(Module) ? :module_eval : :instance_eval
|
221
216
|
|
222
217
|
object.send(method, "def #{name}(_haml_locals = {}); #{compiler.precompiled_with_ambles(local_names)}; end",
|
223
|
-
@options
|
218
|
+
@options.filename, @options.line)
|
224
219
|
end
|
225
220
|
|
226
221
|
private
|
227
222
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
else
|
232
|
-
def initialize_encoding(given_value)
|
233
|
-
unless given_value
|
234
|
-
@options.encoding = Encoding.default_internal || @template.encoding
|
235
|
-
end
|
223
|
+
def initialize_encoding(given_value)
|
224
|
+
unless given_value
|
225
|
+
@options.encoding = Encoding.default_internal || @template.encoding
|
236
226
|
end
|
237
227
|
end
|
238
228
|
|
239
229
|
def set_locals(locals, scope, scope_object)
|
240
|
-
scope_object.
|
230
|
+
scope_object.instance_variable_set '@_haml_locals', locals
|
241
231
|
set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
|
242
232
|
eval(set_locals, scope)
|
243
233
|
end
|
data/lib/haml/exec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'optparse'
|
2
|
-
require 'fileutils'
|
3
2
|
require 'rbconfig'
|
4
3
|
require 'pp'
|
5
4
|
|
@@ -237,6 +236,11 @@ END
|
|
237
236
|
@options[:for_engine][:attr_wrapper] = '"'
|
238
237
|
end
|
239
238
|
|
239
|
+
opts.on('--remove-whitespace',
|
240
|
+
'Remove whitespace surrounding and within tags') do
|
241
|
+
@options[:for_engine][:remove_whitespace] = true
|
242
|
+
end
|
243
|
+
|
240
244
|
opts.on('--cdata',
|
241
245
|
'Always add CDATA sections to javascript and css blocks.') do
|
242
246
|
@options[:for_engine][:cdata] = true
|
@@ -260,12 +264,10 @@ END
|
|
260
264
|
@options[:load_paths] << path
|
261
265
|
end
|
262
266
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
Encoding.default_internal = internal if internal && !internal.empty?
|
268
|
-
end
|
267
|
+
opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
|
268
|
+
external, internal = encoding.split(':')
|
269
|
+
Encoding.default_external = external if external && !external.empty?
|
270
|
+
Encoding.default_internal = internal if internal && !internal.empty?
|
269
271
|
end
|
270
272
|
|
271
273
|
opts.on('-d', '--debug', "Print out the precompiled Ruby source.") do
|
data/lib/haml/filters.rb
CHANGED
@@ -166,7 +166,7 @@ module Haml
|
|
166
166
|
text = unescape_interpolation(text).gsub(/(\\+)n/) do |s|
|
167
167
|
escapes = $1.size
|
168
168
|
next s if escapes % 2 == 0
|
169
|
-
|
169
|
+
"#{'\\' * (escapes - 1)}\n"
|
170
170
|
end
|
171
171
|
# We need to add a newline at the beginning to get the
|
172
172
|
# filter lines to line up (since the Haml filter contains
|
@@ -174,7 +174,7 @@ module Haml
|
|
174
174
|
# filter name). Then we need to escape the trailing
|
175
175
|
# newline so that the whole filter block doesn't take up
|
176
176
|
# too many.
|
177
|
-
text =
|
177
|
+
text = %[\n#{text.sub(/\n"\Z/, "\\n\"")}]
|
178
178
|
push_script <<RUBY.rstrip, :escape_html => false
|
179
179
|
find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
|
180
180
|
RUBY
|
@@ -182,12 +182,9 @@ RUBY
|
|
182
182
|
end
|
183
183
|
|
184
184
|
rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text, compiler.options), compiler.options[:preserve])
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
else
|
189
|
-
push_text(rendered.rstrip.gsub("\n", "\n#{' ' * @output_tabs}"))
|
190
|
-
end
|
185
|
+
rendered.rstrip!
|
186
|
+
rendered.gsub!("\n", "\n#{' ' * @output_tabs}") unless options[:ugly]
|
187
|
+
push_text(rendered)
|
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
|
data/lib/haml/helpers.rb
CHANGED
@@ -117,17 +117,20 @@ MESSAGE
|
|
117
117
|
# HTML entities so they'll render correctly in
|
118
118
|
# whitespace-sensitive tags without screwing up the indentation.
|
119
119
|
#
|
120
|
-
# @overload
|
120
|
+
# @overload preserve(input)
|
121
121
|
# Escapes newlines within a string.
|
122
122
|
#
|
123
123
|
# @param input [String] The string within which to escape all newlines
|
124
|
-
# @overload
|
124
|
+
# @overload preserve
|
125
125
|
# Escapes newlines within a block of Haml code.
|
126
126
|
#
|
127
127
|
# @yield The block within which to escape newlines
|
128
128
|
def preserve(input = nil, &block)
|
129
129
|
return preserve(capture_haml(&block)) if block
|
130
|
-
input.to_s.chomp("\n")
|
130
|
+
s = input.to_s.chomp("\n")
|
131
|
+
s.gsub!(/\n/, '
')
|
132
|
+
s.delete!("\r")
|
133
|
+
s
|
131
134
|
end
|
132
135
|
alias_method :flatten, :preserve
|
133
136
|
|
@@ -195,7 +198,7 @@ MESSAGE
|
|
195
198
|
result = capture_haml(i, &block)
|
196
199
|
|
197
200
|
if result.count("\n") > 1
|
198
|
-
result
|
201
|
+
result.gsub!("\n", "\n ")
|
199
202
|
result = "\n #{result.strip}\n"
|
200
203
|
else
|
201
204
|
result = result.strip
|
@@ -219,7 +222,11 @@ MESSAGE
|
|
219
222
|
# @param lang [String] The value of `xml:lang` and `lang`
|
220
223
|
# @return [{#to_s => String}] The attribute hash
|
221
224
|
def html_attrs(lang = 'en-US')
|
222
|
-
|
225
|
+
if haml_buffer.options[:format] == :xhtml
|
226
|
+
{:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
|
227
|
+
else
|
228
|
+
{:lang => lang}
|
229
|
+
end
|
223
230
|
end
|
224
231
|
|
225
232
|
# Increments the number of tabs the buffer automatically adds
|
@@ -365,17 +372,25 @@ MESSAGE
|
|
365
372
|
position = haml_buffer.buffer.length
|
366
373
|
|
367
374
|
haml_buffer.capture_position = position
|
368
|
-
|
375
|
+
block.call(*args)
|
369
376
|
|
370
377
|
captured = haml_buffer.buffer.slice!(position..-1)
|
371
|
-
|
372
|
-
|
373
|
-
|
378
|
+
return captured if haml_buffer.options[:ugly]
|
379
|
+
# Note that the "reject" is needed for rbx 1.2.4, which includes empty
|
380
|
+
# strings in the returned array when splitting by /^/.
|
381
|
+
captured = captured.split(/^/)
|
382
|
+
captured.delete('')
|
383
|
+
|
384
|
+
min_tabs = nil
|
385
|
+
captured.each do |line|
|
386
|
+
tabs = line.index(/[^ ]/) || line.length
|
387
|
+
min_tabs ||= tabs
|
388
|
+
min_tabs = min_tabs > tabs ? tabs : min_tabs
|
374
389
|
end
|
375
390
|
|
376
|
-
|
377
|
-
|
378
|
-
|
391
|
+
captured.map do |line|
|
392
|
+
line.slice(min_tabs, line.length)
|
393
|
+
end.join
|
379
394
|
end
|
380
395
|
ensure
|
381
396
|
haml_buffer.capture_position = nil
|
@@ -386,10 +401,9 @@ MESSAGE
|
|
386
401
|
# @param text [#to_s] The text to output
|
387
402
|
def haml_concat(text = "")
|
388
403
|
unless haml_buffer.options[:ugly] || haml_indent == 0
|
389
|
-
haml_buffer.buffer << haml_indent
|
390
|
-
text.to_s.gsub("\n", "\n" + haml_indent) << "\n"
|
404
|
+
haml_buffer.buffer << %[#{haml_indent}#{text.to_s.gsub("\n", "\n#{haml_indent}")}\n]
|
391
405
|
else
|
392
|
-
haml_buffer.buffer << text
|
406
|
+
haml_buffer.buffer << "#{text}\n"
|
393
407
|
end
|
394
408
|
ErrorReturn.new("haml_concat")
|
395
409
|
end
|
@@ -473,7 +487,7 @@ MESSAGE
|
|
473
487
|
attrs)
|
474
488
|
|
475
489
|
if text.nil? && block.nil? && (haml_buffer.options[:autoclose].include?(name) || flags.include?(:/))
|
476
|
-
haml_concat "<#{name}#{attributes}
|
490
|
+
haml_concat "<#{name}#{attributes}#{' /' if haml_buffer.options[:format] == :xhtml}>"
|
477
491
|
return ret
|
478
492
|
end
|
479
493
|
|
@@ -492,7 +506,7 @@ MESSAGE
|
|
492
506
|
tab_down
|
493
507
|
haml_concat "</#{name}>"
|
494
508
|
else
|
495
|
-
tag << text
|
509
|
+
tag << "#{text}</#{name}>"
|
496
510
|
haml_concat tag
|
497
511
|
end
|
498
512
|
return ret
|
@@ -503,7 +517,7 @@ MESSAGE
|
|
503
517
|
end
|
504
518
|
|
505
519
|
if flags.include?(:<)
|
506
|
-
tag << capture_haml(&block).strip
|
520
|
+
tag << "#{capture_haml(&block).strip}</#{name}>"
|
507
521
|
haml_concat tag
|
508
522
|
return ret
|
509
523
|
end
|
@@ -517,53 +531,78 @@ MESSAGE
|
|
517
531
|
ret
|
518
532
|
end
|
519
533
|
|
534
|
+
# Conditionally wrap a block in an element. If `condition` is `true` then
|
535
|
+
# this method renders the tag described by the argumants in `tag` (using
|
536
|
+
# \{#haml_tag}) with the given block inside, otherwise it just renders the block.
|
537
|
+
#
|
538
|
+
# For example,
|
539
|
+
#
|
540
|
+
# - haml_tag_if important, '.important' do
|
541
|
+
# %p
|
542
|
+
# A (possibly) important paragraph.
|
543
|
+
#
|
544
|
+
# will produce
|
545
|
+
#
|
546
|
+
# <div class='important'>
|
547
|
+
# <p>
|
548
|
+
# A (possibly) important paragraph.
|
549
|
+
# </p>
|
550
|
+
# </div>
|
551
|
+
#
|
552
|
+
# if `important` is truthy, and just
|
553
|
+
#
|
554
|
+
# <p>
|
555
|
+
# A (possibly) important paragraph.
|
556
|
+
# </p>
|
557
|
+
#
|
558
|
+
# otherwise.
|
559
|
+
#
|
560
|
+
# Like \{#haml_tag}, `haml_tag_if` outputs directly to the buffer and its
|
561
|
+
# return value should not be used. Use \{#capture_haml} if you need to use
|
562
|
+
# its results as a string.
|
563
|
+
#
|
564
|
+
# @param condition The condition to test to determine whether to render
|
565
|
+
# the enclosing tag
|
566
|
+
# @param tag Definition of the enclosing tag. See \{#haml_tag} for details
|
567
|
+
# (specifically the form that takes a block)
|
568
|
+
def haml_tag_if(condition, *tag)
|
569
|
+
if condition
|
570
|
+
haml_tag(*tag){ yield }
|
571
|
+
else
|
572
|
+
yield
|
573
|
+
end
|
574
|
+
ErrorReturn.new("haml_tag_if")
|
575
|
+
end
|
576
|
+
|
520
577
|
# Characters that need to be escaped to HTML entities from user input
|
521
|
-
HTML_ESCAPE = { '&'=>'&', '<'=>'<', '>'=>'>', '"'=>'"', "'"=>'''
|
578
|
+
HTML_ESCAPE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''' }
|
522
579
|
|
523
580
|
HTML_ESCAPE_REGEX = /[\"><&]/
|
524
581
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
def html_escape(text)
|
538
|
-
text = text.to_s
|
539
|
-
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
540
|
-
end
|
541
|
-
else
|
542
|
-
def html_escape(text)
|
543
|
-
text = text.to_s
|
544
|
-
text.gsub(HTML_ESCAPE_REGEX) {|s| HTML_ESCAPE[s]}
|
545
|
-
end
|
582
|
+
# Returns a copy of `text` with ampersands, angle brackets and quotes
|
583
|
+
# escaped into HTML entities.
|
584
|
+
#
|
585
|
+
# Note that if ActionView is loaded and XSS protection is enabled
|
586
|
+
# (as is the default for Rails 3.0+, and optional for version 2.3.5+),
|
587
|
+
# this won't escape text declared as "safe".
|
588
|
+
#
|
589
|
+
# @param text [String] The string to sanitize
|
590
|
+
# @return [String] The sanitized string
|
591
|
+
def html_escape(text)
|
592
|
+
text = text.to_s
|
593
|
+
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
546
594
|
end
|
547
595
|
|
548
|
-
HTML_ESCAPE_ONCE_REGEX = /[\"><]|&(?!(?:[a-zA-Z]
|
549
|
-
|
550
|
-
if RUBY_VERSION >= '1.9'
|
551
|
-
# Include docs here so they are picked up by Yard
|
596
|
+
HTML_ESCAPE_ONCE_REGEX = /[\"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
|
552
597
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
end
|
562
|
-
else
|
563
|
-
def escape_once(text)
|
564
|
-
text = text.to_s
|
565
|
-
text.gsub(HTML_ESCAPE_ONCE_REGEX){|s| HTML_ESCAPE[s]}
|
566
|
-
end
|
598
|
+
# Escapes HTML entities in `text`, but without escaping an ampersand
|
599
|
+
# that is already part of an escaped entity.
|
600
|
+
#
|
601
|
+
# @param text [String] The string to sanitize
|
602
|
+
# @return [String] The sanitized string
|
603
|
+
def escape_once(text)
|
604
|
+
text = text.to_s
|
605
|
+
text.gsub(HTML_ESCAPE_ONCE_REGEX, HTML_ESCAPE)
|
567
606
|
end
|
568
607
|
|
569
608
|
# Returns whether or not the current template is a Haml template.
|
@@ -630,22 +669,6 @@ MESSAGE
|
|
630
669
|
_erbout = _erbout = _hamlout.buffer
|
631
670
|
proc { |*args| proc.call(*args) }
|
632
671
|
end
|
633
|
-
|
634
|
-
def prettify(text)
|
635
|
-
text = text.split(/^/)
|
636
|
-
text.delete('')
|
637
|
-
|
638
|
-
min_tabs = nil
|
639
|
-
text.each do |line|
|
640
|
-
tabs = line.index(/[^ ]/) || line.length
|
641
|
-
min_tabs ||= tabs
|
642
|
-
min_tabs = min_tabs > tabs ? tabs : min_tabs
|
643
|
-
end
|
644
|
-
|
645
|
-
text.map do |line|
|
646
|
-
line.slice(min_tabs, line.length)
|
647
|
-
end.join
|
648
|
-
end
|
649
672
|
end
|
650
673
|
end
|
651
674
|
|