haml 2.2.1 → 2.2.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.
- data/VERSION +1 -1
- data/extra/haml-mode.el +2 -3
- data/lib/haml/filters.rb +1 -1
- data/lib/haml/helpers.rb +23 -8
- data/lib/haml/html.rb +64 -45
- data/lib/haml/precompiler.rb +4 -1
- data/lib/sass/engine.rb +26 -31
- data/lib/sass/script/funcall.rb +1 -1
- data/lib/sass/script/functions.rb +2 -1
- data/lib/sass/script/lexer.rb +1 -0
- data/lib/sass/script/parser.rb +51 -1
- data/lib/sass/tree/mixin_def_node.rb +2 -2
- data/lib/sass/tree/mixin_node.rb +3 -3
- data/test/haml/engine_test.rb +13 -0
- data/test/haml/helper_test.rb +29 -1
- data/test/haml/template_test.rb +10 -2
- data/test/sass/engine_test.rb +40 -7
- data/test/sass/functions_test.rb +1 -0
- data/test/sass/plugin_test.rb +4 -2
- data/test/sass/script_test.rb +0 -15
- data/test/sass/templates/complex.sass +0 -2
- data/test/test_helper.rb +16 -1
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.2.
|
1
|
+
2.2.2
|
data/extra/haml-mode.el
CHANGED
@@ -603,9 +603,8 @@ If N is negative, will remove the spaces instead. Assumes all
|
|
603
603
|
lines in the region have indentation >= that of the first line."
|
604
604
|
(let ((ci (current-indentation)))
|
605
605
|
(save-excursion
|
606
|
-
(
|
607
|
-
|
608
|
-
nil (point) (mark)))))
|
606
|
+
(while (re-search-forward (concat "^" (make-string ci ?\s)) (mark) t)
|
607
|
+
(replace-match (make-string (max 0 (+ ci n)) ?\s))))))
|
609
608
|
|
610
609
|
(defun haml-electric-backspace (arg)
|
611
610
|
"Delete characters or back-dent the current line.
|
data/lib/haml/filters.rb
CHANGED
@@ -100,7 +100,7 @@ module Haml
|
|
100
100
|
if contains_interpolation?(text)
|
101
101
|
return if options[:suppress_eval]
|
102
102
|
|
103
|
-
push_script <<RUBY
|
103
|
+
push_script <<RUBY, :escape_html => false
|
104
104
|
find_and_preserve(#{filter.inspect}.render_with_options(#{unescape_interpolation(text)}, _hamlout.options))
|
105
105
|
RUBY
|
106
106
|
return
|
data/lib/haml/helpers.rb
CHANGED
@@ -14,8 +14,12 @@ module Haml
|
|
14
14
|
# when it shouldn't be.
|
15
15
|
class ErrorReturn
|
16
16
|
# @param message [String] The error message to raise when \{#to\_s} is called
|
17
|
-
def initialize(
|
18
|
-
@message =
|
17
|
+
def initialize(method)
|
18
|
+
@message = <<MESSAGE
|
19
|
+
#{method} outputs directly to the Haml template.
|
20
|
+
Disregard its return value and use the - operator,
|
21
|
+
or use capture_haml to get the value as a String.
|
22
|
+
MESSAGE
|
19
23
|
end
|
20
24
|
|
21
25
|
# Raises an error.
|
@@ -23,6 +27,21 @@ module Haml
|
|
23
27
|
# @raise [Haml::Error] The error
|
24
28
|
def to_s
|
25
29
|
raise Haml::Error.new(@message)
|
30
|
+
rescue Haml::Error => e
|
31
|
+
e.backtrace.shift
|
32
|
+
|
33
|
+
# If the ErrorReturn is used directly in the template,
|
34
|
+
# we don't want Haml's stuff to get into the backtrace,
|
35
|
+
# so we get rid of the format_script line.
|
36
|
+
#
|
37
|
+
# We also have to subtract one from the Haml line number
|
38
|
+
# since the value is passed to format_script the line after
|
39
|
+
# it's actually used.
|
40
|
+
if e.backtrace.first =~ /^\(eval\):\d+:in `format_script/
|
41
|
+
e.backtrace.shift
|
42
|
+
e.backtrace.first.gsub!(/^\(haml\):(\d+)/) {|s| "(haml):#{$1.to_i - 1}"}
|
43
|
+
end
|
44
|
+
raise e
|
26
45
|
end
|
27
46
|
|
28
47
|
# @return [String] A human-readable string representation
|
@@ -338,7 +357,7 @@ END
|
|
338
357
|
# @param text [#to_s] The text to output
|
339
358
|
def haml_concat(text = "")
|
340
359
|
haml_buffer.buffer << haml_indent << text.to_s << "\n"
|
341
|
-
|
360
|
+
ErrorReturn.new("haml_concat")
|
342
361
|
end
|
343
362
|
|
344
363
|
# @return [String] The indentation string for the current line
|
@@ -399,11 +418,7 @@ END
|
|
399
418
|
# @overload haml_tag(name, text, *flags, attributes = {})
|
400
419
|
# @param text [#to_s] The text within the tag
|
401
420
|
def haml_tag(name, *rest, &block)
|
402
|
-
ret = ErrorReturn.new(
|
403
|
-
haml_tag outputs directly to the Haml template.
|
404
|
-
Disregard its return value and use the - operator,
|
405
|
-
or use capture_haml to get the value as a String.
|
406
|
-
MESSAGE
|
421
|
+
ret = ErrorReturn.new("haml_tag")
|
407
422
|
|
408
423
|
name = name.to_s
|
409
424
|
text = rest.shift.to_s unless [Symbol, Hash, NilClass].any? {|t| rest.first.is_a? t}
|
data/lib/haml/html.rb
CHANGED
@@ -2,9 +2,60 @@ require File.dirname(__FILE__) + '/../haml'
|
|
2
2
|
|
3
3
|
require 'haml/engine'
|
4
4
|
require 'rubygems'
|
5
|
-
require 'hpricot'
|
6
5
|
require 'cgi'
|
7
6
|
|
7
|
+
module Haml
|
8
|
+
class HTML
|
9
|
+
# A module containing utility methods that every Hpricot node
|
10
|
+
# should have.
|
11
|
+
module Node
|
12
|
+
# Returns the Haml representation of the given node.
|
13
|
+
#
|
14
|
+
# @param tabs [Fixnum] The indentation level of the resulting Haml.
|
15
|
+
# @option options (see Haml::HTML#initialize)
|
16
|
+
def to_haml(tabs, options)
|
17
|
+
parse_text(self.to_s, tabs)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def tabulate(tabs)
|
23
|
+
' ' * tabs
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_text(text, tabs)
|
27
|
+
text.strip!
|
28
|
+
if text.empty?
|
29
|
+
String.new
|
30
|
+
else
|
31
|
+
lines = text.split("\n")
|
32
|
+
|
33
|
+
lines.map do |line|
|
34
|
+
line.strip!
|
35
|
+
"#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
|
36
|
+
end.join
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Haml monkeypatches various Hpricot classes
|
44
|
+
# to add methods for conversion to Haml.
|
45
|
+
module Hpricot
|
46
|
+
# @see Hpricot
|
47
|
+
module Node
|
48
|
+
include Haml::HTML::Node
|
49
|
+
end
|
50
|
+
|
51
|
+
# @see Hpricot
|
52
|
+
class BaseEle
|
53
|
+
include Haml::HTML::Node
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
require 'hpricot'
|
58
|
+
|
8
59
|
module Haml
|
9
60
|
# Converts HTML documents into Haml templates.
|
10
61
|
# Depends on [Hpricot](http://code.whytheluckystiff.net/hpricot/) for HTML parsing.
|
@@ -46,67 +97,35 @@ module Haml
|
|
46
97
|
end
|
47
98
|
alias_method :to_haml, :render
|
48
99
|
|
49
|
-
# Haml monkeypatches various Hpricot classes
|
50
|
-
# to add methods for conversion to Haml.
|
51
|
-
module ::Hpricot::Node
|
52
|
-
# Returns the Haml representation of the given node.
|
53
|
-
#
|
54
|
-
# @param tabs [Fixnum] The indentation level of the resulting Haml.
|
55
|
-
# @option options (see Haml::HTML#initialize)
|
56
|
-
def to_haml(tabs, options)
|
57
|
-
parse_text(self.to_s, tabs)
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def tabulate(tabs)
|
63
|
-
' ' * tabs
|
64
|
-
end
|
65
|
-
|
66
|
-
def parse_text(text, tabs)
|
67
|
-
text.strip!
|
68
|
-
if text.empty?
|
69
|
-
String.new
|
70
|
-
else
|
71
|
-
lines = text.split("\n")
|
72
|
-
|
73
|
-
lines.map do |line|
|
74
|
-
line.strip!
|
75
|
-
"#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
|
76
|
-
end.join
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
100
|
TEXT_REGEXP = /^(\s*).*$/
|
82
101
|
|
83
|
-
# @see Hpricot
|
102
|
+
# @see Hpricot
|
84
103
|
class ::Hpricot::Doc
|
85
|
-
# @see
|
104
|
+
# @see Haml::HTML::Node#to_haml
|
86
105
|
def to_haml(tabs, options)
|
87
106
|
(children || []).inject('') {|s, c| s << c.to_haml(0, options)}
|
88
107
|
end
|
89
108
|
end
|
90
109
|
|
91
|
-
# @see Hpricot
|
110
|
+
# @see Hpricot
|
92
111
|
class ::Hpricot::XMLDecl
|
93
|
-
# @see
|
112
|
+
# @see Haml::HTML::Node#to_haml
|
94
113
|
def to_haml(tabs, options)
|
95
114
|
"#{tabulate(tabs)}!!! XML\n"
|
96
115
|
end
|
97
116
|
end
|
98
117
|
|
99
|
-
# @see Hpricot
|
118
|
+
# @see Hpricot
|
100
119
|
class ::Hpricot::CData
|
101
|
-
# @see
|
120
|
+
# @see Haml::HTML::Node#to_haml
|
102
121
|
def to_haml(tabs, options)
|
103
122
|
"#{tabulate(tabs)}:cdata\n#{parse_text(self.content, tabs + 1)}"
|
104
123
|
end
|
105
124
|
end
|
106
125
|
|
107
|
-
# @see Hpricot
|
126
|
+
# @see Hpricot
|
108
127
|
class ::Hpricot::DocType
|
109
|
-
# @see
|
128
|
+
# @see Haml::HTML::Node#to_haml
|
110
129
|
def to_haml(tabs, options)
|
111
130
|
attrs = public_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
|
112
131
|
if attrs == nil
|
@@ -137,17 +156,17 @@ module Haml
|
|
137
156
|
end
|
138
157
|
end
|
139
158
|
|
140
|
-
# @see Hpricot
|
159
|
+
# @see Hpricot
|
141
160
|
class ::Hpricot::Comment
|
142
|
-
# @see
|
161
|
+
# @see Haml::HTML::Node#to_haml
|
143
162
|
def to_haml(tabs, options)
|
144
163
|
"#{tabulate(tabs)}/\n#{parse_text(self.content, tabs + 1)}"
|
145
164
|
end
|
146
165
|
end
|
147
166
|
|
148
|
-
# @see Hpricot
|
167
|
+
# @see Hpricot
|
149
168
|
class ::Hpricot::Elem
|
150
|
-
# @see
|
169
|
+
# @see Haml::HTML::Node#to_haml
|
151
170
|
def to_haml(tabs, options)
|
152
171
|
output = "#{tabulate(tabs)}"
|
153
172
|
if options[:rhtml] && name[0...5] == 'haml:'
|
data/lib/haml/precompiler.rb
CHANGED
@@ -571,7 +571,10 @@ END
|
|
571
571
|
attributes = {}
|
572
572
|
|
573
573
|
scanner.scan(/\(\s*/)
|
574
|
-
|
574
|
+
loop do
|
575
|
+
name, value = parse_new_attribute(scanner)
|
576
|
+
break if name.nil?
|
577
|
+
|
575
578
|
if name == false
|
576
579
|
text = (Haml::Shared.balance(line, ?(, ?)) || [line]).first
|
577
580
|
raise Haml::SyntaxError.new("Invalid attribute list: #{text.inspect}.", last_line - 1)
|
data/lib/sass/engine.rb
CHANGED
@@ -268,6 +268,7 @@ END
|
|
268
268
|
continued_rule, child = nil, continued_rule
|
269
269
|
end
|
270
270
|
|
271
|
+
check_for_no_children(child)
|
271
272
|
validate_and_append_child(parent, child, line, root)
|
272
273
|
end
|
273
274
|
|
@@ -294,6 +295,22 @@ END
|
|
294
295
|
end
|
295
296
|
end
|
296
297
|
|
298
|
+
def check_for_no_children(node)
|
299
|
+
return unless node.is_a?(Tree::RuleNode) && node.children.empty?
|
300
|
+
warning = (node.rules.size == 1) ? <<SHORT : <<LONG
|
301
|
+
WARNING:
|
302
|
+
Selector #{node.rules.first.inspect} doesn't have any properties and will not be rendered.
|
303
|
+
SHORT
|
304
|
+
|
305
|
+
WARNING:
|
306
|
+
Selector
|
307
|
+
#{node.rules.join("\n ")}
|
308
|
+
doesn't have any properties and will not be rendered.
|
309
|
+
LONG
|
310
|
+
|
311
|
+
warn(warning.strip)
|
312
|
+
end
|
313
|
+
|
297
314
|
def parse_line(parent, line, root)
|
298
315
|
case line.text[0]
|
299
316
|
when PROPERTY_CHAR
|
@@ -425,46 +442,24 @@ END
|
|
425
442
|
nil
|
426
443
|
end
|
427
444
|
|
428
|
-
# parses out the arguments between the commas and cleans up the mixin arguments
|
429
|
-
# returns nil if it fails to parse, otherwise an array.
|
430
|
-
def parse_mixin_arguments(arg_string)
|
431
|
-
arg_string = arg_string.strip
|
432
|
-
return [] if arg_string.empty?
|
433
|
-
return nil unless (arg_string[0] == ?( && arg_string[-1] == ?))
|
434
|
-
arg_string = arg_string[1...-1]
|
435
|
-
arg_string.split(",", -1).map {|a| a.strip}
|
436
|
-
end
|
437
|
-
|
438
445
|
def parse_mixin_definition(line)
|
439
446
|
name, arg_string = line.text.scan(/^=\s*([^(]+)(.*)$/).first
|
440
|
-
|
441
|
-
|
447
|
+
raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".", @line) if name.nil?
|
448
|
+
|
449
|
+
offset = line.offset + line.text.size - arg_string.size
|
450
|
+
args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_definition_arglist
|
442
451
|
default_arg_found = false
|
443
|
-
required_arg_count = 0
|
444
|
-
args.map! do |arg|
|
445
|
-
raise SyntaxError.new("Mixin arguments can't be empty.", @line) if arg.empty? || arg == "!"
|
446
|
-
unless arg[0] == Script::VARIABLE_CHAR
|
447
|
-
raise SyntaxError.new("Mixin argument \"#{arg}\" must begin with an exclamation point (!).", @line)
|
448
|
-
end
|
449
|
-
arg, default = arg.split(/\s*=\s*/, 2)
|
450
|
-
required_arg_count += 1 unless default
|
451
|
-
default_arg_found ||= default
|
452
|
-
raise SyntaxError.new("Invalid variable \"#{arg}\".", @line) unless arg =~ Script::VALIDATE
|
453
|
-
raise SyntaxError.new("Required arguments must not follow optional arguments \"#{arg}\".", @line) if default_arg_found && !default
|
454
|
-
default = parse_script(default, :offset => line.offset + line.text.index(default)) if default
|
455
|
-
[arg[1..-1], default]
|
456
|
-
end
|
457
452
|
Tree::MixinDefNode.new(name, args)
|
458
453
|
end
|
459
454
|
|
460
455
|
def parse_mixin_include(line, root)
|
461
456
|
name, arg_string = line.text.scan(/^\+\s*([^(]+)(.*)$/).first
|
462
|
-
|
463
|
-
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.", @line + 1) unless line.children.empty?
|
464
|
-
raise SyntaxError.new("Invalid mixin include \"#{line.text}\".", @line) if name.nil? || args.nil?
|
465
|
-
args.each {|a| raise SyntaxError.new("Mixin arguments can't be empty.", @line) if a.empty?}
|
457
|
+
raise SyntaxError.new("Invalid mixin include \"#{line.text}\".", @line) if name.nil?
|
466
458
|
|
467
|
-
|
459
|
+
offset = line.offset + line.text.size - arg_string.size
|
460
|
+
args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_include_arglist
|
461
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.", @line + 1) unless line.children.empty?
|
462
|
+
Tree::MixinNode.new(name, args)
|
468
463
|
end
|
469
464
|
|
470
465
|
def parse_script(script, options = {})
|
data/lib/sass/script/funcall.rb
CHANGED
@@ -42,7 +42,7 @@ module Sass
|
|
42
42
|
|
43
43
|
return Functions::EvaluationContext.new(environment.options).send(name, *args)
|
44
44
|
rescue ArgumentError => e
|
45
|
-
raise e unless e.backtrace.first =~ /:in `(#{name}|perform)'$/
|
45
|
+
raise e unless e.backtrace.first =~ /:in `(block in )?(#{name}|perform)'$/
|
46
46
|
raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
|
47
47
|
end
|
48
48
|
end
|
@@ -71,7 +71,8 @@ module Sass::Script
|
|
71
71
|
# A number between 0 and 255 inclusive
|
72
72
|
def rgb(red, green, blue)
|
73
73
|
[red.value, green.value, blue.value].each do |v|
|
74
|
-
|
74
|
+
next unless v < 0 || v > 255
|
75
|
+
raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
|
75
76
|
end
|
76
77
|
Color.new([red.value, green.value, blue.value])
|
77
78
|
end
|
data/lib/sass/script/lexer.rb
CHANGED
data/lib/sass/script/parser.rb
CHANGED
@@ -36,10 +36,42 @@ module Sass
|
|
36
36
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
37
37
|
def parse
|
38
38
|
expr = assert_expr :expr
|
39
|
-
|
39
|
+
assert_done
|
40
40
|
expr
|
41
41
|
end
|
42
42
|
|
43
|
+
# Parses the argument list for a mixin include.
|
44
|
+
#
|
45
|
+
# @return [Array<Script::Node>] The root nodes of the arguments.
|
46
|
+
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
47
|
+
def parse_mixin_include_arglist
|
48
|
+
args = []
|
49
|
+
|
50
|
+
if try_tok(:lparen)
|
51
|
+
args = arglist || args
|
52
|
+
assert_tok(:rparen)
|
53
|
+
end
|
54
|
+
assert_done
|
55
|
+
|
56
|
+
args
|
57
|
+
end
|
58
|
+
|
59
|
+
# Parses the argument list for a mixin definition.
|
60
|
+
#
|
61
|
+
# @return [Array<Script::Node>] The root nodes of the arguments.
|
62
|
+
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
63
|
+
def parse_mixin_definition_arglist
|
64
|
+
args = []
|
65
|
+
|
66
|
+
if try_tok(:lparen)
|
67
|
+
args = defn_arglist(false) || args
|
68
|
+
assert_tok(:rparen)
|
69
|
+
end
|
70
|
+
assert_done
|
71
|
+
|
72
|
+
args
|
73
|
+
end
|
74
|
+
|
43
75
|
# Parses a SassScript expression.
|
44
76
|
#
|
45
77
|
# @overload parse(str, line, offset, filename = nil)
|
@@ -120,6 +152,19 @@ END
|
|
120
152
|
end
|
121
153
|
end
|
122
154
|
|
155
|
+
def defn_arglist(must_have_default)
|
156
|
+
return unless c = try_tok(:const)
|
157
|
+
var = Script::Variable.new(c.value)
|
158
|
+
if try_tok(:single_eq)
|
159
|
+
val = assert_expr(:concat)
|
160
|
+
elsif must_have_default
|
161
|
+
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.", @line)
|
162
|
+
end
|
163
|
+
|
164
|
+
return [[var, val]] unless try_tok(:comma)
|
165
|
+
[[var, val], *defn_arglist(val)]
|
166
|
+
end
|
167
|
+
|
123
168
|
def arglist
|
124
169
|
return unless e = concat
|
125
170
|
return [e] unless try_tok(:comma)
|
@@ -167,6 +212,11 @@ END
|
|
167
212
|
peeked = @lexer.peek
|
168
213
|
peeked && names.include?(peeked.type) && @lexer.next
|
169
214
|
end
|
215
|
+
|
216
|
+
def assert_done
|
217
|
+
return if @lexer.done?
|
218
|
+
raise Sass::SyntaxError.new("Unexpected #{@lexer.peek.type} token.")
|
219
|
+
end
|
170
220
|
end
|
171
221
|
end
|
172
222
|
end
|
@@ -5,8 +5,8 @@ module Sass
|
|
5
5
|
# @see Sass::Tree
|
6
6
|
class MixinDefNode < Node
|
7
7
|
# @param name [String] The mixin name
|
8
|
-
# @param args [Array<(
|
9
|
-
# Each element is a tuple containing the
|
8
|
+
# @param args [Array<(Script::Node, Script::Node)>] The arguments for the mixin.
|
9
|
+
# Each element is a tuple containing the variable for argument
|
10
10
|
# and the parse tree for the default value of the argument
|
11
11
|
def initialize(name, args)
|
12
12
|
@name = name
|
data/lib/sass/tree/mixin_node.rb
CHANGED
@@ -32,14 +32,14 @@ Mixin #{@name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
|
|
32
32
|
END
|
33
33
|
|
34
34
|
environment = mixin.args.zip(@args).
|
35
|
-
inject(Sass::Environment.new(mixin.environment)) do |env, ((
|
36
|
-
env.set_local_var(name,
|
35
|
+
inject(Sass::Environment.new(mixin.environment)) do |env, ((var, default), value)|
|
36
|
+
env.set_local_var(var.name,
|
37
37
|
if value
|
38
38
|
value.perform(environment)
|
39
39
|
elsif default
|
40
40
|
default.perform(env)
|
41
41
|
end)
|
42
|
-
raise Sass::SyntaxError.new("Mixin #{@name} is missing parameter
|
42
|
+
raise Sass::SyntaxError.new("Mixin #{@name} is missing parameter #{var.inspect}.") unless env.var(var.name)
|
43
43
|
env
|
44
44
|
end
|
45
45
|
mixin.tree.map {|c| c.perform(environment)}.flatten
|
data/test/haml/engine_test.rb
CHANGED
@@ -425,6 +425,19 @@ HAML
|
|
425
425
|
assert_equal("<a href='#'></a>\n", render('%a(href="#")'))
|
426
426
|
end
|
427
427
|
|
428
|
+
def test_javascript_filter_with_dynamic_interp_and_escape_html
|
429
|
+
assert_equal(<<HTML, render(<<HAML, :escape_html => true))
|
430
|
+
<script type='text/javascript'>
|
431
|
+
//<![CDATA[
|
432
|
+
& < > &
|
433
|
+
//]]>
|
434
|
+
</script>
|
435
|
+
HTML
|
436
|
+
:javascript
|
437
|
+
& < > \#{"&"}
|
438
|
+
HAML
|
439
|
+
end
|
440
|
+
|
428
441
|
# HTML escaping tests
|
429
442
|
|
430
443
|
def test_ampersand_equals_should_escape
|
data/test/haml/helper_test.rb
CHANGED
@@ -8,6 +8,12 @@ class ActionView::Base
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
module Haml::Helpers
|
12
|
+
def something_that_uses_haml_concat
|
13
|
+
haml_concat('foo').to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
class HelperTest < Test::Unit::TestCase
|
12
18
|
Post = Struct.new('Post', :body)
|
13
19
|
|
@@ -221,7 +227,29 @@ HAML
|
|
221
227
|
def test_content_tag_nested
|
222
228
|
assert_equal "<span><div>something</div></span>", render("= nested_tag", :action_view).strip
|
223
229
|
end
|
224
|
-
|
230
|
+
|
231
|
+
def test_error_return
|
232
|
+
assert_raise(Haml::Error, <<MESSAGE) {render("= haml_concat 'foo'")}
|
233
|
+
haml_concat outputs directly to the Haml template.
|
234
|
+
Disregard its return value and use the - operator,
|
235
|
+
or use capture_haml to get the value as a String.
|
236
|
+
MESSAGE
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_error_return_line
|
240
|
+
render("%p foo\n= haml_concat 'foo'\n%p bar")
|
241
|
+
assert false, "Expected Haml::Error"
|
242
|
+
rescue Haml::Error => e
|
243
|
+
assert_equal 2, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_error_return_line_in_helper
|
247
|
+
render("- something_that_uses_haml_concat")
|
248
|
+
assert false, "Expected Haml::Error"
|
249
|
+
rescue Haml::Error => e
|
250
|
+
assert_equal 13, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
|
251
|
+
end
|
252
|
+
|
225
253
|
class ActsLikeTag
|
226
254
|
# We want to be able to have people include monkeypatched ActionView helpers
|
227
255
|
# without redefining is_haml?.
|
data/test/haml/template_test.rb
CHANGED
@@ -140,8 +140,16 @@ class TemplateTest < Test::Unit::TestCase
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def test_action_view_templates_render_correctly
|
143
|
-
|
144
|
-
|
143
|
+
proc = lambda do
|
144
|
+
@base.content_for(:layout) {'Lorem ipsum dolor sit amet'}
|
145
|
+
assert_renders_correctly 'content_for_layout'
|
146
|
+
end
|
147
|
+
|
148
|
+
if @base.respond_to?(:with_output_buffer)
|
149
|
+
@base.with_output_buffer("", &proc)
|
150
|
+
else
|
151
|
+
proc.call
|
152
|
+
end
|
145
153
|
end
|
146
154
|
|
147
155
|
def test_instance_variables_should_work_inside_templates
|
data/test/sass/engine_test.rb
CHANGED
@@ -65,14 +65,14 @@ class SassEngineTest < Test::Unit::TestCase
|
|
65
65
|
"a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
|
66
66
|
"a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
|
67
67
|
"a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
|
68
|
-
"=a(" => '
|
69
|
-
"=a(b)" => '
|
70
|
-
"=a(,)" => "
|
71
|
-
"=a(!)" => "
|
72
|
-
"=a(!foo bar)" => "
|
68
|
+
"=a(" => 'Expected rparen token, was end of text.',
|
69
|
+
"=a(b)" => 'Expected rparen token, was ident token.',
|
70
|
+
"=a(,)" => "Expected rparen token, was comma token.",
|
71
|
+
"=a(!)" => "Syntax error in '(!)' at character 4.",
|
72
|
+
"=a(!foo bar)" => "Expected rparen token, was ident token.",
|
73
73
|
"=foo\n bar: baz\n+foo" => ["Properties aren't allowed at the root of a document.", 2],
|
74
74
|
"a-\#{!b\n c: d" => ["Expected end_interpolation token, was end of text.", 1],
|
75
|
-
"=a(!b = 1, !c)" => "Required
|
75
|
+
"=a(!b = 1, !c)" => "Required argument !c must come before any optional arguments.",
|
76
76
|
"=a(!b = 1)\n :a= !b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
|
77
77
|
"=a(!b)\n :a= !b\ndiv\n +a" => "Mixin a is missing parameter !b.",
|
78
78
|
"@else\n a\n b: c" => ["@else must come after @if.", 1],
|
@@ -130,7 +130,7 @@ class SassEngineTest < Test::Unit::TestCase
|
|
130
130
|
define_method("test_exception (#{key.inspect})") do
|
131
131
|
line = 10
|
132
132
|
begin
|
133
|
-
Sass::Engine.new(key, :filename => __FILE__, :line => line).render
|
133
|
+
silence_warnings {Sass::Engine.new(key, :filename => __FILE__, :line => line).render}
|
134
134
|
rescue Sass::SyntaxError => err
|
135
135
|
value = [value] unless value.is_a?(Array)
|
136
136
|
|
@@ -704,8 +704,41 @@ a
|
|
704
704
|
SASS
|
705
705
|
end
|
706
706
|
|
707
|
+
def test_empty_selector_warning
|
708
|
+
assert_warning(<<END) {render("foo bar")}
|
709
|
+
WARNING:
|
710
|
+
Selector "foo bar" doesn't have any properties and will not be rendered.
|
711
|
+
END
|
712
|
+
|
713
|
+
assert_warning(<<END) {render(<<SASS)}
|
714
|
+
WARNING:
|
715
|
+
Selector
|
716
|
+
foo, bar, baz,
|
717
|
+
bang, bip, bop
|
718
|
+
doesn't have any properties and will not be rendered.
|
719
|
+
END
|
720
|
+
foo, bar, baz,
|
721
|
+
bang, bip, bop
|
722
|
+
SASS
|
723
|
+
end
|
724
|
+
|
707
725
|
# Regression tests
|
708
726
|
|
727
|
+
def test_parens_in_mixins
|
728
|
+
assert_equal(<<CSS, render(<<SASS))
|
729
|
+
.foo {
|
730
|
+
color: #01ff7f;
|
731
|
+
background-color: #000102; }
|
732
|
+
CSS
|
733
|
+
=foo(!c1, !c2 = rgb(0, 1, 2))
|
734
|
+
color = !c1
|
735
|
+
background-color = !c2
|
736
|
+
|
737
|
+
.foo
|
738
|
+
+foo(rgb(1,255,127))
|
739
|
+
SASS
|
740
|
+
end
|
741
|
+
|
709
742
|
def test_comment_beneath_prop
|
710
743
|
assert_equal(<<RESULT, render(<<SOURCE))
|
711
744
|
.box {
|
data/test/sass/functions_test.rb
CHANGED
@@ -91,6 +91,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
91
91
|
def test_rgb
|
92
92
|
assert_equal("#123456", evaluate("rgb(18, 52, 86)"))
|
93
93
|
assert_equal("#beaded", evaluate("rgb(190, 173, 237)"))
|
94
|
+
assert_equal("#00ff7f", evaluate("rgb(0, 255, 127)"))
|
94
95
|
|
95
96
|
assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'",
|
96
97
|
"rgb(256, 1, 1)")
|
data/test/sass/plugin_test.rb
CHANGED
@@ -22,8 +22,10 @@ class SassPluginTest < Test::Unit::TestCase
|
|
22
22
|
FileUtils.rm_r tempfile_loc(nil,"more_")
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
@@templates.each do |name|
|
26
|
+
define_method("test_template_renders_correctly (#{name})") do
|
27
|
+
assert_renders_correctly(name)
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
31
|
def test_no_update
|
data/test/sass/script_test.rb
CHANGED
@@ -243,21 +243,6 @@ WARN
|
|
243
243
|
Sass::Engine.new(sass, options).render
|
244
244
|
end
|
245
245
|
|
246
|
-
def assert_warning(message)
|
247
|
-
the_real_stderr, $stderr = $stderr, StringIO.new
|
248
|
-
yield
|
249
|
-
assert_equal message.strip, $stderr.string.strip
|
250
|
-
ensure
|
251
|
-
$stderr = the_real_stderr
|
252
|
-
end
|
253
|
-
|
254
|
-
def silence_warnings
|
255
|
-
the_real_stderr, $stderr = $stderr, StringIO.new
|
256
|
-
yield
|
257
|
-
ensure
|
258
|
-
$stderr = the_real_stderr
|
259
|
-
end
|
260
|
-
|
261
246
|
def env(hash = {})
|
262
247
|
env = Sass::Environment.new
|
263
248
|
hash.each {|k, v| env.set_var(k, v)}
|
data/test/test_helper.rb
CHANGED
@@ -7,7 +7,7 @@ $:.unshift lib_dir unless $:.include?(lib_dir)
|
|
7
7
|
require 'haml'
|
8
8
|
require 'sass'
|
9
9
|
|
10
|
-
Sass::RAILS_LOADED = true
|
10
|
+
Sass::RAILS_LOADED = true unless defined?(Sass::RAILS_LOADED)
|
11
11
|
|
12
12
|
# required because of Sass::Plugin
|
13
13
|
unless defined? RAILS_ROOT
|
@@ -26,4 +26,19 @@ class Test::Unit::TestCase
|
|
26
26
|
path = File.dirname(__FILE__) + "/../.sass-cache"
|
27
27
|
FileUtils.rm_r(path) if File.exist?(path)
|
28
28
|
end
|
29
|
+
|
30
|
+
def assert_warning(message)
|
31
|
+
the_real_stderr, $stderr = $stderr, StringIO.new
|
32
|
+
yield
|
33
|
+
assert_equal message.strip, $stderr.string.strip
|
34
|
+
ensure
|
35
|
+
$stderr = the_real_stderr
|
36
|
+
end
|
37
|
+
|
38
|
+
def silence_warnings
|
39
|
+
the_real_stderr, $stderr = $stderr, StringIO.new
|
40
|
+
yield
|
41
|
+
ensure
|
42
|
+
$stderr = the_real_stderr
|
43
|
+
end
|
29
44
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-07-
|
13
|
+
date: 2009-07-20 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|