haml 3.2.0.beta.2 → 3.2.0.beta.3

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.

@@ -5,23 +5,30 @@
5
5
  * HTML5 is now the default output format rather than XHTML. This was already
6
6
  the default on Rails 3+, so many users will notice no difference.
7
7
 
8
+ * The :sass filter now wraps its output in a script tag, as do the new :less and
9
+ :scss filters. The :coffee filter wraps its output in a script tag.
10
+
11
+ * Haml now supports only Rails 3 and above, and Ruby 1.8.7 and above. If you
12
+ still need support for Rails 2 and Ruby 1.8.6, please use Haml 3.1.x which
13
+ will continue to be maintained for bug fixes.
14
+
8
15
  * The :javascript and :css filters no longer add CDATA tags when the format is
9
16
  html4 or html5. This can be overridden by setting the `cdata` option to
10
17
  `true`. CDATA tags are always added when the format is xhtml.
11
18
 
12
19
  * HTML2Haml has been extracted to a separate gem, creatively named "html2haml".
13
20
 
21
+ * The `:erb` filter now uses Rails's safe output buffer to provide XSS safety.
22
+
14
23
  * Haml's internals have been refactored to move the parser, compiler and options
15
24
  handling into independent classes, rather than including them all in the
16
25
  Engine module. You can also specify your own custom Haml parser or compiler
17
26
  class in Haml::Options in order to extend or modify Haml reasonably easily.
18
27
 
19
- * The :sass filter now wraps its output in a script tag, as do the new :less and
20
- :scss filters. The :coffee filter wraps its output in a script tag.
21
-
22
- * Haml now supports only Rails 3 and above, and Ruby 1.8.7 and above. If you
23
- still need support for Rails 2 and Ruby 1.8.6, please use Haml 3.1.x which
24
- will continue to be maintained for bug fixes.
28
+ * Add an {file:REFERENCE.md#hyphenate_data_attrs-option `:hyphenate_data_attrs`
29
+ option} that converts underscores to hyphens in your HTML5 data keys. This is
30
+ a language change from 3.1 and is enabled by default.
31
+ (thanks to [Andrew Smith](https://github.com/fullsailor))
25
32
 
26
33
  * Added `remove_whitespace` option to always remove all whitespace around Haml
27
34
  tags. (thanks to [Tim van der Horst](https://github.com/vdh))
@@ -54,11 +61,6 @@
54
61
  * Performance improvements.
55
62
  (thanks to [Chris Heald](https://github.com/cheald))
56
63
 
57
- * Add an {file:REFERENCE.md#hyphenate_data_attrs-option `:hyphenate_data_attrs`
58
- option} that converts underscores to hyphens in your HTML5 data keys. This is
59
- a language change from 3.1 and is enabled by default.
60
- (thanks to [Andrew Smith](https://github.com/fullsailor))
61
-
62
64
  * Helper `list_of` takes an extra argument that is rendered into list item
63
65
  attributes.
64
66
  (thanks [Iain Barnett](http://iainbarnett.me.uk/))
@@ -2,11 +2,12 @@ require 'haml/version'
2
2
 
3
3
  # The module that contains everything Haml-related:
4
4
  #
5
+ # * {Haml::Parser} is Haml's parser.
6
+ # * {Haml::Compiler} is Haml's compiler.
7
+ # * {Haml::Engine} is the class used to render Haml within Ruby code.
8
+ # * {Haml::Options} is where Haml's runtime options are defined.
5
9
  # * {Haml::Engine} is the class used to render Haml within Ruby code.
6
- # * {Haml::Helpers} contains Ruby helpers available within Haml templates.
7
- # * {Haml::Template} interfaces with web frameworks (Rails in particular).
8
10
  # * {Haml::Error} is raised when Haml encounters an error.
9
- # * {Haml::HTML} handles conversion of HTML to Haml.
10
11
  #
11
12
  # Also see the {file:REFERENCE.md full Haml reference}.
12
13
  module Haml
@@ -0,0 +1,20 @@
1
+ module Haml
2
+ class SafeErubisTemplate < Tilt::ErubisTemplate
3
+
4
+ def initialize_engine
5
+ end
6
+
7
+ def prepare
8
+ @options.merge! :engine_class => ActionView::Template::Handlers::Erubis
9
+ super
10
+ end
11
+
12
+ def precompiled_preamble(locals)
13
+ [super, "@output_buffer = output_buffer ||= nil || ActionView::OutputBuffer.new;"]
14
+ end
15
+
16
+ def precompiled_postamble(locals)
17
+ [super, '@output_buffer.to_s']
18
+ end
19
+ end
20
+ end
@@ -77,7 +77,7 @@ module Haml
77
77
  START_BLOCK_KEYWORDS = %w[if begin case unless]
78
78
  # Try to parse assignments to block starters as best as possible
79
79
  START_BLOCK_KEYWORD_REGEX = /(?:\w+(?:,\s*\w+)*\s*=\s*)?(#{START_BLOCK_KEYWORDS.join('|')})/
80
- BLOCK_KEYWORD_REGEX = /^-\s*(?:(#{MID_BLOCK_KEYWORDS.join('|')})|#{START_BLOCK_KEYWORD_REGEX.source})\b/
80
+ BLOCK_KEYWORD_REGEX = /^-?\s*(?:(#{MID_BLOCK_KEYWORDS.join('|')})|#{START_BLOCK_KEYWORD_REGEX.source})\b/
81
81
 
82
82
  # The Regex that matches a Doctype command.
83
83
  DOCTYPE_REGEX = /(\d(?:\.\d)?)?[\s]*([a-z]*)\s*([^ ]+)?/i
@@ -269,8 +269,11 @@ module Haml
269
269
  text = handle_ruby_multiline(text)
270
270
  escape_html = @options[:escape_html] if escape_html.nil?
271
271
 
272
+ keyword = block_keyword(text)
273
+ check_push_script_stack(keyword)
274
+
272
275
  ParseNode.new(:script, @index, :text => text, :escape_html => escape_html,
273
- :preserve => preserve)
276
+ :preserve => preserve, :keyword => keyword)
274
277
  end
275
278
 
276
279
  def flat_script(text, escape_html = nil)
@@ -286,16 +289,22 @@ module Haml
286
289
  text = handle_ruby_multiline(text)
287
290
  keyword = block_keyword(text)
288
291
 
289
- if ["if", "case", "unless"].include?(keyword)
290
- @script_level_stack.push(@line.tabs)
291
- @tab_up = true
292
- end
292
+ check_push_script_stack(keyword)
293
293
 
294
- if ["else", "elsif"].include?(keyword)
294
+ if ["else", "elsif", "when"].include?(keyword)
295
295
  if @script_level_stack.empty?
296
296
  raise Haml::SyntaxError.new(Error.message(:missing_if, keyword), @line.index)
297
- elsif @script_level_stack.last != @line.tabs
298
- message = Error.message(:bad_script_indent, keyword, @script_level_stack.last, @line.tabs)
297
+ end
298
+
299
+ if keyword == 'when' and !@script_level_stack.last[2]
300
+ if @script_level_stack.last[1] + 1 == @line.tabs
301
+ @script_level_stack.last[1] += 1
302
+ end
303
+ @script_level_stack.last[2] = true
304
+ end
305
+
306
+ if @script_level_stack.last[1] != @line.tabs
307
+ message = Error.message(:bad_script_indent, keyword, @script_level_stack.last[1], @line.tabs)
299
308
  raise Haml::SyntaxError.new(message, @line.index)
300
309
  end
301
310
  end
@@ -304,6 +313,16 @@ module Haml
304
313
  :text => text[1..-1], :keyword => keyword)
305
314
  end
306
315
 
316
+ def check_push_script_stack(keyword)
317
+ if ["if", "case", "unless"].include?(keyword)
318
+ # @script_level_stack contents are arrays of form
319
+ # [:keyword, stack_level, other_info]
320
+ @script_level_stack.push([keyword.to_sym, @line.tabs])
321
+ @script_level_stack.last << false if keyword == 'case'
322
+ @tab_up = true
323
+ end
324
+ end
325
+
307
326
  def haml_comment(text)
308
327
  @haml_comment = block_opened?
309
328
  ParseNode.new(:haml_comment, @index, :text => text)
@@ -458,6 +477,8 @@ module Haml
458
477
  first.children = []
459
478
  end
460
479
 
480
+ alias :close_script :close_silent_script
481
+
461
482
  # This is a class method so it can be accessed from {Haml::Helpers}.
462
483
  #
463
484
  # Iterates through the classes and ids supplied through `.`
@@ -6,3 +6,6 @@ if defined?(ActiveSupport)
6
6
  end
7
7
  end
8
8
  end
9
+
10
+ require "haml/helpers/safe_erubis_template"
11
+ Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
@@ -1,3 +1,3 @@
1
1
  module Haml
2
- VERSION = "3.2.0.beta.2"
2
+ VERSION = "3.2.0.beta.3"
3
3
  end
@@ -122,13 +122,18 @@ class ErbFilterTest < MiniTest::Unit::TestCase
122
122
  assert_equal(html, render(haml))
123
123
  end
124
124
 
125
-
126
125
  test "should evaluate in the same context as Haml" do
127
126
  haml = ":erb\n <%= foo %>"
128
127
  html = "bar\n"
129
128
  scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding}
130
129
  assert_equal(html, render(haml, :scope => scope))
131
130
  end
131
+
132
+ test "should use Rails's XSS safety features" do
133
+ assert_equal("&lt;img&gt;\n", render(":erb\n <%= '<img>' %>"))
134
+ assert_equal("<img>\n", render(":erb\n <%= '<img>'.html_safe %>"))
135
+ end
136
+
132
137
  end
133
138
 
134
139
  class JavascriptFilterTest < MiniTest::Unit::TestCase
@@ -66,6 +66,33 @@ module Haml
66
66
  flunk 'else clause after if containing unless should be accepted'
67
67
  end
68
68
  end
69
+
70
+ test "loud script with else is accepted" do
71
+ begin
72
+ parse "= if true\n - 'A'\n-else\n - 'B'"
73
+ assert true
74
+ rescue SyntaxError
75
+ flunk 'loud script (=) should allow else'
76
+ end
77
+ end
78
+
79
+ test "else after nested loud script is accepted" do
80
+ begin
81
+ parse "-if true\n =if true\n - 'A'\n-else\n B"
82
+ assert true
83
+ rescue SyntaxError
84
+ flunk 'else after nested loud script should be accepted'
85
+ end
86
+ end
87
+
88
+ test "case with indented whens should allow else" do
89
+ begin
90
+ parse "- foo = 1\n-case foo\n -when 1\n A\n -else\n B"
91
+ assert true
92
+ rescue SyntaxError
93
+ flunk 'case with indented whens should allow else'
94
+ end
95
+ end
69
96
 
70
97
  private
71
98
 
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: 3.2.0.beta.2
4
+ version: 3.2.0.beta.3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-08-10 00:00:00.000000000 Z
14
+ date: 2012-08-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: tilt
@@ -107,6 +107,7 @@ files:
107
107
  - lib/haml/helpers/action_view_extensions.rb
108
108
  - lib/haml/helpers/action_view_mods.rb
109
109
  - lib/haml/helpers/rails_323_textarea_fix.rb
110
+ - lib/haml/helpers/safe_erubis_template.rb
110
111
  - lib/haml/helpers/xss_mods.rb
111
112
  - lib/haml/helpers.rb
112
113
  - lib/haml/options.rb