haml 4.1.0.beta.1 → 5.0.0.beta.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/.yardopts +1 -1
- data/CHANGELOG.md +36 -6
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +81 -48
- data/REFERENCE.md +86 -50
- data/Rakefile +28 -41
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +214 -0
- data/lib/haml/attribute_parser.rb +112 -0
- data/lib/haml/buffer.rb +24 -126
- data/lib/haml/compiler.rb +62 -281
- data/lib/haml/engine.rb +16 -23
- data/lib/haml/error.rb +2 -0
- data/lib/haml/escapable.rb +48 -0
- data/lib/haml/exec.rb +23 -12
- data/lib/haml/filters.rb +3 -4
- data/lib/haml/generator.rb +36 -0
- data/lib/haml/helpers.rb +61 -48
- data/lib/haml/helpers/action_view_extensions.rb +1 -1
- data/lib/haml/helpers/action_view_mods.rb +32 -50
- data/lib/haml/helpers/safe_erubi_template.rb +26 -0
- data/lib/haml/helpers/safe_erubis_template.rb +2 -0
- data/lib/haml/helpers/xss_mods.rb +17 -12
- data/lib/haml/options.rb +32 -36
- data/lib/haml/parser.rb +61 -38
- data/lib/haml/{template/plugin.rb → plugin.rb} +5 -2
- data/lib/haml/railtie.rb +14 -6
- data/lib/haml/template.rb +11 -6
- data/lib/haml/temple_engine.rb +119 -0
- data/lib/haml/temple_line_counter.rb +28 -0
- data/lib/haml/util.rb +17 -112
- data/lib/haml/version.rb +1 -1
- data/test/attribute_parser_test.rb +105 -0
- data/test/engine_test.rb +202 -106
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +7 -1
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +57 -71
- 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 +156 -109
- data/test/options_test.rb +21 -0
- data/test/parser_test.rb +49 -4
- 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 +77 -76
- data/test/template_test.rb +21 -48
- data/test/template_test_helper.rb +38 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/standard_ugly.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +10 -10
- data/test/util_test.rb +1 -48
- metadata +49 -35
- data/lib/haml/temple.rb +0 -85
- data/test/gemfiles/Gemfile.rails-3.2.x +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
@@ -7,6 +7,7 @@ require 'haml/helpers'
|
|
7
7
|
require 'haml/buffer'
|
8
8
|
require 'haml/filters'
|
9
9
|
require 'haml/error'
|
10
|
+
require 'haml/temple_engine'
|
10
11
|
|
11
12
|
module Haml
|
12
13
|
# This is the frontend for using Haml programmatically.
|
@@ -35,9 +36,6 @@ module Haml
|
|
35
36
|
# @return [String]
|
36
37
|
attr_accessor :indentation
|
37
38
|
|
38
|
-
attr_accessor :compiler
|
39
|
-
attr_accessor :parser
|
40
|
-
|
41
39
|
# Tilt currently depends on these moved methods, provide a stable API
|
42
40
|
def_delegators :compiler, :precompiled, :precompiled_method_return_value
|
43
41
|
|
@@ -58,12 +56,13 @@ module Haml
|
|
58
56
|
raise Haml::Error.new(msg, line)
|
59
57
|
end
|
60
58
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@compiler = @options.compiler_class.new(@options)
|
59
|
+
@temple_engine = TempleEngine.new(options)
|
60
|
+
@temple_engine.compile(@template)
|
61
|
+
end
|
65
62
|
|
66
|
-
|
63
|
+
# Deprecated API for backword compatibility
|
64
|
+
def compiler
|
65
|
+
@temple_engine
|
67
66
|
end
|
68
67
|
|
69
68
|
# Processes the template and returns the result as a string.
|
@@ -107,7 +106,7 @@ module Haml
|
|
107
106
|
# @param block [#to_proc] A block that can be yielded to within the template
|
108
107
|
# @return [String] The rendered template
|
109
108
|
def render(scope = Object.new, locals = {}, &block)
|
110
|
-
parent = scope.instance_variable_defined?(
|
109
|
+
parent = scope.instance_variable_defined?(:@haml_buffer) ? scope.instance_variable_get(:@haml_buffer) : nil
|
111
110
|
buffer = Haml::Buffer.new(parent, @options.for_buffer)
|
112
111
|
|
113
112
|
if scope.is_a?(Binding)
|
@@ -121,15 +120,15 @@ module Haml
|
|
121
120
|
set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
|
122
121
|
|
123
122
|
scope_object.extend(Haml::Helpers)
|
124
|
-
scope_object.instance_variable_set(
|
123
|
+
scope_object.instance_variable_set(:@haml_buffer, buffer)
|
125
124
|
begin
|
126
|
-
eval(@
|
125
|
+
eval(@temple_engine.precompiled_with_return_value, scope, @options.filename, @options.line)
|
127
126
|
rescue ::SyntaxError => e
|
128
127
|
raise SyntaxError, e.message
|
129
128
|
end
|
130
129
|
ensure
|
131
130
|
# Get rid of the current buffer
|
132
|
-
scope_object.instance_variable_set(
|
131
|
+
scope_object.instance_variable_set(:@haml_buffer, buffer.upper) if buffer
|
133
132
|
end
|
134
133
|
alias_method :to_html, :render
|
135
134
|
|
@@ -166,8 +165,8 @@ module Haml
|
|
166
165
|
end
|
167
166
|
|
168
167
|
begin
|
169
|
-
eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};"
|
170
|
-
|
168
|
+
eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" <<
|
169
|
+
@temple_engine.precompiled_with_ambles(local_names) << "}\n", scope, @options.filename, @options.line)
|
171
170
|
rescue ::SyntaxError => e
|
172
171
|
raise SyntaxError, e.message
|
173
172
|
end
|
@@ -177,7 +176,7 @@ module Haml
|
|
177
176
|
# that renders the template and returns the result as a string.
|
178
177
|
#
|
179
178
|
# If `object` is a class or module,
|
180
|
-
# the method will instead
|
179
|
+
# the method will instead be defined as an instance method.
|
181
180
|
# For example:
|
182
181
|
#
|
183
182
|
# t = Time.now
|
@@ -214,20 +213,14 @@ module Haml
|
|
214
213
|
def def_method(object, name, *local_names)
|
215
214
|
method = object.is_a?(Module) ? :module_eval : :instance_eval
|
216
215
|
|
217
|
-
object.send(method, "def #{name}(_haml_locals = {}); #{
|
216
|
+
object.send(method, "def #{name}(_haml_locals = {}); #{@temple_engine.precompiled_with_ambles(local_names)}; end",
|
218
217
|
@options.filename, @options.line)
|
219
218
|
end
|
220
219
|
|
221
220
|
private
|
222
221
|
|
223
|
-
def initialize_encoding(given_value)
|
224
|
-
unless given_value
|
225
|
-
@options.encoding = Encoding.default_internal || @template.encoding
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
222
|
def set_locals(locals, scope, scope_object)
|
230
|
-
scope_object.instance_variable_set
|
223
|
+
scope_object.instance_variable_set :@_haml_locals, locals
|
231
224
|
set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
|
232
225
|
eval(set_locals, scope)
|
233
226
|
end
|
data/lib/haml/error.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Haml
|
2
|
+
# Like Temple::Filters::Escapable, but with support for escaping by
|
3
|
+
# Haml::Herlpers.html_escape and Haml::Herlpers.escape_once.
|
4
|
+
class Escapable < Temple::Filter
|
5
|
+
def initialize(*)
|
6
|
+
super
|
7
|
+
@escape_code = "::Haml::Helpers.html_escape((%s))"
|
8
|
+
@escaper = eval("proc {|v| #{@escape_code % 'v'} }")
|
9
|
+
@once_escape_code = "::Haml::Helpers.escape_once((%s))"
|
10
|
+
@once_escaper = eval("proc {|v| #{@once_escape_code % 'v'} }")
|
11
|
+
@escape = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_escape(flag, exp)
|
15
|
+
old = @escape
|
16
|
+
@escape = flag
|
17
|
+
compile(exp)
|
18
|
+
ensure
|
19
|
+
@escape = old
|
20
|
+
end
|
21
|
+
|
22
|
+
# The same as Haml::AttributeBuilder.build_attributes
|
23
|
+
def on_static(value)
|
24
|
+
[:static,
|
25
|
+
if @escape == :once
|
26
|
+
@once_escaper[value]
|
27
|
+
elsif @escape
|
28
|
+
@escaper[value]
|
29
|
+
else
|
30
|
+
value
|
31
|
+
end
|
32
|
+
]
|
33
|
+
end
|
34
|
+
|
35
|
+
# The same as Haml::AttributeBuilder.build_attributes
|
36
|
+
def on_dynamic(value)
|
37
|
+
[:dynamic,
|
38
|
+
if @escape == :once
|
39
|
+
@once_escape_code % value
|
40
|
+
elsif @escape
|
41
|
+
@escape_code % value
|
42
|
+
else
|
43
|
+
"(#{value}).to_s"
|
44
|
+
end
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/haml/exec.rb
CHANGED
@@ -211,11 +211,6 @@ END
|
|
211
211
|
@options[:output] = StringIO.new
|
212
212
|
end
|
213
213
|
|
214
|
-
opts.on('-t', '--style NAME',
|
215
|
-
'Output style. Can be indented (default) or ugly.') do |name|
|
216
|
-
@options[:for_engine][:ugly] = true if name.to_sym == :ugly
|
217
|
-
end
|
218
|
-
|
219
214
|
opts.on('-f', '--format NAME',
|
220
215
|
'Output format. Can be html5 (default), xhtml, or html4.') do |name|
|
221
216
|
@options[:for_engine][:format] = name.to_sym
|
@@ -270,7 +265,7 @@ END
|
|
270
265
|
Encoding.default_internal = internal if internal && !internal.empty?
|
271
266
|
end
|
272
267
|
|
273
|
-
opts.on('-d', '--debug', "Print out the precompiled Ruby source.") do
|
268
|
+
opts.on('-d', '--debug', "Print out the precompiled Ruby source, and show syntax errors in the Ruby code.") do
|
274
269
|
@options[:debug] = true
|
275
270
|
end
|
276
271
|
|
@@ -296,20 +291,28 @@ END
|
|
296
291
|
|
297
292
|
begin
|
298
293
|
|
299
|
-
|
300
|
-
|
301
|
-
|
294
|
+
if @options[:parse]
|
295
|
+
parser = ::Haml::Parser.new(template, ::Haml::Options.new(@options))
|
296
|
+
pp parser.parse
|
302
297
|
return
|
303
298
|
end
|
304
299
|
|
305
|
-
|
306
|
-
|
300
|
+
engine = ::Haml::Engine.new(template, @options[:for_engine])
|
301
|
+
|
302
|
+
if @options[:check_syntax]
|
303
|
+
puts "Syntax OK"
|
307
304
|
return
|
308
305
|
end
|
309
306
|
|
310
307
|
if @options[:debug]
|
311
308
|
puts engine.precompiled
|
312
|
-
|
309
|
+
error = validate_ruby(engine.precompiled)
|
310
|
+
if error
|
311
|
+
puts '=' * 100
|
312
|
+
puts error.message.split("\n")[0]
|
313
|
+
exit 1
|
314
|
+
end
|
315
|
+
return
|
313
316
|
end
|
314
317
|
|
315
318
|
result = engine.to_html
|
@@ -326,6 +329,14 @@ END
|
|
326
329
|
output.write(result)
|
327
330
|
output.close() if output.is_a? File
|
328
331
|
end
|
332
|
+
|
333
|
+
def validate_ruby(code)
|
334
|
+
begin
|
335
|
+
eval("BEGIN {return nil}; #{code}")
|
336
|
+
rescue ::SyntaxError # Not to be confused with Haml::SyntaxError
|
337
|
+
$!
|
338
|
+
end
|
339
|
+
end
|
329
340
|
end
|
330
341
|
end
|
331
342
|
end
|
data/lib/haml/filters.rb
CHANGED
@@ -59,7 +59,7 @@ module Haml
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# Removes a filter from Haml. If the filter was removed, it returns
|
62
|
-
# the that was
|
62
|
+
# the Module that was removed upon success, or nil on failure. If you try
|
63
63
|
# to redefine a filter, Haml will raise an error. Use this method first to
|
64
64
|
# explicitly remove the filter before redefining it.
|
65
65
|
# @return Module The filter module that has been removed
|
@@ -163,7 +163,7 @@ module Haml
|
|
163
163
|
if contains_interpolation?(text)
|
164
164
|
return if options[:suppress_eval]
|
165
165
|
|
166
|
-
text = unescape_interpolation(text).gsub(/(\\+)n/) do |s|
|
166
|
+
text = unescape_interpolation(text, options[:escape_html]).gsub(/(\\+)n/) do |s|
|
167
167
|
escapes = $1.size
|
168
168
|
next s if escapes % 2 == 0
|
169
169
|
"#{'\\' * (escapes - 1)}\n"
|
@@ -183,8 +183,7 @@ RUBY
|
|
183
183
|
|
184
184
|
rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text, compiler.options), compiler.options[:preserve])
|
185
185
|
rendered.rstrip!
|
186
|
-
|
187
|
-
push_text(rendered)
|
186
|
+
push_text("#{rendered}\n")
|
188
187
|
end
|
189
188
|
end
|
190
189
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Haml
|
2
|
+
# Ruby code generator, which is a limited version of Temple::Generator.
|
3
|
+
# Limit methods since Haml doesn't need most of them.
|
4
|
+
class Generator
|
5
|
+
include Temple::Mixins::CompiledDispatcher
|
6
|
+
include Temple::Mixins::Options
|
7
|
+
|
8
|
+
define_options freeze_static: RUBY_VERSION >= '2.1'
|
9
|
+
|
10
|
+
def call(exp)
|
11
|
+
compile(exp)
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_multi(*exp)
|
15
|
+
exp.map { |e| compile(e) }.join('; ')
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_static(text)
|
19
|
+
concat(options[:freeze_static] ? "#{Util.inspect_obj(text)}.freeze" : Util.inspect_obj(text))
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_dynamic(code)
|
23
|
+
concat(code)
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_code(exp)
|
27
|
+
exp
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def concat(str)
|
33
|
+
"_hamlout.buffer << (#{str});"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/haml/helpers.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
module Haml
|
2
4
|
# This module contains various helpful methods to make it easier to do various tasks.
|
3
5
|
# {Haml::Helpers} is automatically included in the context
|
@@ -106,7 +108,11 @@ MESSAGE
|
|
106
108
|
# @yield The block within which to escape newlines
|
107
109
|
def find_and_preserve(input = nil, tags = haml_buffer.options[:preserve], &block)
|
108
110
|
return find_and_preserve(capture_haml(&block), input || tags) if block
|
109
|
-
|
111
|
+
tags = tags.each_with_object('') do |t, s|
|
112
|
+
s << '|' unless s.empty?
|
113
|
+
s << Regexp.escape(t)
|
114
|
+
end
|
115
|
+
re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im
|
110
116
|
input.to_s.gsub(re) do |s|
|
111
117
|
s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
|
112
118
|
"<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
|
@@ -193,19 +199,20 @@ MESSAGE
|
|
193
199
|
# @yield [item] A block which contains Haml code that goes within list items
|
194
200
|
# @yieldparam item An element of `enum`
|
195
201
|
def list_of(enum, opts={}, &block)
|
196
|
-
opts_attributes = opts.
|
197
|
-
enum.
|
202
|
+
opts_attributes = opts.each_with_object('') {|(k, v), s| s << " #{k}='#{v}'"}
|
203
|
+
enum.each_with_object('') do |i, ret|
|
198
204
|
result = capture_haml(i, &block)
|
199
205
|
|
200
|
-
|
206
|
+
if result.count("\n") > 1
|
201
207
|
result.gsub!("\n", "\n ")
|
202
|
-
"\n #{result.strip}\n"
|
208
|
+
result = "\n #{result.strip!}\n"
|
203
209
|
else
|
204
|
-
result.strip
|
210
|
+
result.strip!
|
205
211
|
end
|
206
212
|
|
207
|
-
|
208
|
-
|
213
|
+
ret << "\n" unless ret.empty?
|
214
|
+
ret << %Q!<li#{opts_attributes}>#{result}</li>!
|
215
|
+
end
|
209
216
|
end
|
210
217
|
|
211
218
|
# Returns a hash containing default assignments for the `xmlns`, `lang`, and `xml:lang`
|
@@ -379,8 +386,7 @@ MESSAGE
|
|
379
386
|
captured = (value.is_a?(String) ? value : nil)
|
380
387
|
end
|
381
388
|
|
382
|
-
|
383
|
-
return (haml_buffer.options[:ugly] ? captured : prettify(captured))
|
389
|
+
captured
|
384
390
|
end
|
385
391
|
ensure
|
386
392
|
haml_buffer.capture_position = nil
|
@@ -390,13 +396,34 @@ MESSAGE
|
|
390
396
|
#
|
391
397
|
# @param text [#to_s] The text to output
|
392
398
|
def haml_concat(text = "")
|
393
|
-
|
394
|
-
|
399
|
+
haml_internal_concat text
|
400
|
+
ErrorReturn.new("haml_concat")
|
401
|
+
end
|
402
|
+
|
403
|
+
# Internal method to write directly to the buffer with control of
|
404
|
+
# whether the first line should be indented, and if there should be a
|
405
|
+
# final newline.
|
406
|
+
#
|
407
|
+
# Lines added will have the proper indentation. This can be controlled
|
408
|
+
# for the first line.
|
409
|
+
#
|
410
|
+
# Used by #haml_concat and #haml_tag.
|
411
|
+
#
|
412
|
+
# @param text [#to_s] The text to output
|
413
|
+
# @param newline [Boolean] Whether to add a newline after the text
|
414
|
+
# @param indent [Boolean] Whether to add indentation to the first line
|
415
|
+
def haml_internal_concat(text = "", newline = true, indent = true)
|
416
|
+
if haml_buffer.tabulation == 0
|
417
|
+
haml_buffer.buffer << "#{text}#{"\n" if newline}"
|
395
418
|
else
|
396
|
-
haml_buffer.buffer << %[#{haml_indent}#{text.to_s.gsub("\n", "\n#{haml_indent}")}\n]
|
419
|
+
haml_buffer.buffer << %[#{haml_indent if indent}#{text.to_s.gsub("\n", "\n#{haml_indent}")}#{"\n" if newline}]
|
397
420
|
end
|
398
|
-
ErrorReturn.new("haml_concat")
|
399
421
|
end
|
422
|
+
private :haml_internal_concat
|
423
|
+
|
424
|
+
# Allows writing raw content. `haml_internal_concat_raw` isn't
|
425
|
+
# effected by XSS mods. Used by #haml_tag to write the actual tags.
|
426
|
+
alias :haml_internal_concat_raw :haml_internal_concat
|
400
427
|
|
401
428
|
# @return [String] The indentation string for the current line
|
402
429
|
def haml_indent
|
@@ -470,14 +497,14 @@ MESSAGE
|
|
470
497
|
attrs.keys.each {|key| attrs[key.to_s] = attrs.delete(key)} unless attrs.empty?
|
471
498
|
name, attrs = merge_name_and_attributes(name.to_s, attrs)
|
472
499
|
|
473
|
-
attributes = Haml::
|
500
|
+
attributes = Haml::AttributeBuilder.build_attributes(haml_buffer.html?,
|
474
501
|
haml_buffer.options[:attr_wrapper],
|
475
502
|
haml_buffer.options[:escape_attrs],
|
476
503
|
haml_buffer.options[:hyphenate_data_attrs],
|
477
504
|
attrs)
|
478
505
|
|
479
506
|
if text.nil? && block.nil? && (haml_buffer.options[:autoclose].include?(name) || flags.include?(:/))
|
480
|
-
|
507
|
+
haml_internal_concat_raw "<#{name}#{attributes}#{' /' if haml_buffer.options[:format] == :xhtml}>"
|
481
508
|
return ret
|
482
509
|
end
|
483
510
|
|
@@ -487,17 +514,19 @@ MESSAGE
|
|
487
514
|
end
|
488
515
|
|
489
516
|
tag = "<#{name}#{attributes}>"
|
517
|
+
end_tag = "</#{name}>"
|
490
518
|
if block.nil?
|
491
519
|
text = text.to_s
|
492
520
|
if text.include?("\n")
|
493
|
-
|
521
|
+
haml_internal_concat_raw tag
|
494
522
|
tab_up
|
495
|
-
|
523
|
+
haml_internal_concat text
|
496
524
|
tab_down
|
497
|
-
|
525
|
+
haml_internal_concat_raw end_tag
|
498
526
|
else
|
499
|
-
tag
|
500
|
-
|
527
|
+
haml_internal_concat_raw tag, false
|
528
|
+
haml_internal_concat text, false, false
|
529
|
+
haml_internal_concat_raw end_tag, true, false
|
501
530
|
end
|
502
531
|
return ret
|
503
532
|
end
|
@@ -507,22 +536,23 @@ MESSAGE
|
|
507
536
|
end
|
508
537
|
|
509
538
|
if flags.include?(:<)
|
510
|
-
tag
|
511
|
-
|
539
|
+
haml_internal_concat_raw tag, false
|
540
|
+
haml_internal_concat "#{capture_haml(&block).strip}", false, false
|
541
|
+
haml_internal_concat_raw end_tag, true, false
|
512
542
|
return ret
|
513
543
|
end
|
514
544
|
|
515
|
-
|
545
|
+
haml_internal_concat_raw tag
|
516
546
|
tab_up
|
517
547
|
block.call
|
518
548
|
tab_down
|
519
|
-
|
549
|
+
haml_internal_concat_raw end_tag
|
520
550
|
|
521
551
|
ret
|
522
552
|
end
|
523
553
|
|
524
554
|
# Conditionally wrap a block in an element. If `condition` is `true` then
|
525
|
-
# this method renders the tag described by the
|
555
|
+
# this method renders the tag described by the arguments in `tag` (using
|
526
556
|
# \{#haml_tag}) with the given block inside, otherwise it just renders the block.
|
527
557
|
#
|
528
558
|
# For example,
|
@@ -565,9 +595,9 @@ MESSAGE
|
|
565
595
|
end
|
566
596
|
|
567
597
|
# Characters that need to be escaped to HTML entities from user input
|
568
|
-
HTML_ESCAPE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => '&#
|
598
|
+
HTML_ESCAPE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''' }
|
569
599
|
|
570
|
-
HTML_ESCAPE_REGEX = /[
|
600
|
+
HTML_ESCAPE_REGEX = /['"><&]/
|
571
601
|
|
572
602
|
# Returns a copy of `text` with ampersands, angle brackets and quotes
|
573
603
|
# escaped into HTML entities.
|
@@ -579,11 +609,10 @@ MESSAGE
|
|
579
609
|
# @param text [String] The string to sanitize
|
580
610
|
# @return [String] The sanitized string
|
581
611
|
def html_escape(text)
|
582
|
-
text
|
583
|
-
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
612
|
+
ERB::Util.html_escape(text)
|
584
613
|
end
|
585
614
|
|
586
|
-
HTML_ESCAPE_ONCE_REGEX = /[
|
615
|
+
HTML_ESCAPE_ONCE_REGEX = /['"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
|
587
616
|
|
588
617
|
# Escapes HTML entities in `text`, but without escaping an ampersand
|
589
618
|
# that is already part of an escaped entity.
|
@@ -622,7 +651,7 @@ MESSAGE
|
|
622
651
|
# skip merging if no ids or classes found in name
|
623
652
|
return name, attributes_hash unless name =~ /^(.+?)?([\.#].*)$/
|
624
653
|
|
625
|
-
return $1 || "div",
|
654
|
+
return $1 || "div", AttributeBuilder.merge_attributes!(
|
626
655
|
Haml::Parser.parse_class_and_id($2), attributes_hash)
|
627
656
|
end
|
628
657
|
|
@@ -659,22 +688,6 @@ MESSAGE
|
|
659
688
|
_erbout = _erbout = _hamlout.buffer
|
660
689
|
proc { |*args| proc.call(*args) }
|
661
690
|
end
|
662
|
-
|
663
|
-
def prettify(text)
|
664
|
-
text = text.split(/^/)
|
665
|
-
text.delete('')
|
666
|
-
|
667
|
-
min_tabs = nil
|
668
|
-
text.each do |line|
|
669
|
-
tabs = line.index(/[^ ]/) || line.length
|
670
|
-
min_tabs ||= tabs
|
671
|
-
min_tabs = min_tabs > tabs ? tabs : min_tabs
|
672
|
-
end
|
673
|
-
|
674
|
-
text.map do |line|
|
675
|
-
line.slice(min_tabs, line.length)
|
676
|
-
end.join
|
677
|
-
end
|
678
691
|
end
|
679
692
|
end
|
680
693
|
|