haml 3.0.0.beta.3 → 3.0.0.rc.1

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.

Files changed (82) hide show
  1. data/.yardopts +2 -0
  2. data/REMEMBER +4 -11
  3. data/Rakefile +24 -2
  4. data/VERSION +1 -1
  5. data/lib/haml.rb +5 -2
  6. data/lib/haml/exec.rb +11 -4
  7. data/lib/haml/filters.rb +3 -0
  8. data/lib/haml/helpers.rb +2 -10
  9. data/lib/haml/helpers/action_view_extensions.rb +4 -2
  10. data/lib/haml/helpers/action_view_mods.rb +6 -4
  11. data/lib/haml/html.rb +0 -1
  12. data/lib/haml/precompiler.rb +37 -30
  13. data/lib/haml/railtie.rb +6 -2
  14. data/lib/haml/root.rb +4 -0
  15. data/lib/haml/template.rb +2 -0
  16. data/lib/haml/util.rb +74 -0
  17. data/lib/haml/util/subset_map.rb +101 -0
  18. data/lib/sass.rb +1 -0
  19. data/lib/sass/engine.rb +36 -31
  20. data/lib/sass/files.rb +1 -1
  21. data/lib/sass/plugin.rb +21 -0
  22. data/lib/sass/plugin/staleness_checker.rb +9 -9
  23. data/lib/sass/script.rb +1 -2
  24. data/lib/sass/script/color.rb +4 -3
  25. data/lib/sass/script/css_lexer.rb +11 -1
  26. data/lib/sass/script/css_parser.rb +4 -1
  27. data/lib/sass/script/funcall.rb +9 -0
  28. data/lib/sass/script/interpolation.rb +21 -0
  29. data/lib/sass/script/lexer.rb +30 -13
  30. data/lib/sass/script/node.rb +1 -1
  31. data/lib/sass/script/number.rb +4 -5
  32. data/lib/sass/script/parser.rb +13 -14
  33. data/lib/sass/script/string.rb +8 -2
  34. data/lib/sass/script/string_interpolation.rb +27 -4
  35. data/lib/sass/scss.rb +3 -0
  36. data/lib/sass/scss/css_parser.rb +5 -3
  37. data/lib/sass/scss/parser.rb +146 -64
  38. data/lib/sass/scss/rx.rb +9 -1
  39. data/lib/sass/scss/sass_parser.rb +11 -0
  40. data/lib/sass/scss/script_lexer.rb +2 -0
  41. data/lib/sass/scss/static_parser.rb +48 -0
  42. data/lib/sass/selector.rb +353 -0
  43. data/lib/sass/selector/abstract_sequence.rb +40 -0
  44. data/lib/sass/selector/comma_sequence.rb +80 -0
  45. data/lib/sass/selector/sequence.rb +194 -0
  46. data/lib/sass/selector/simple.rb +107 -0
  47. data/lib/sass/selector/simple_sequence.rb +161 -0
  48. data/lib/sass/tree/comment_node.rb +1 -0
  49. data/lib/sass/tree/debug_node.rb +1 -0
  50. data/lib/sass/tree/directive_node.rb +1 -0
  51. data/lib/sass/tree/extend_node.rb +60 -0
  52. data/lib/sass/tree/for_node.rb +1 -0
  53. data/lib/sass/tree/if_node.rb +2 -0
  54. data/lib/sass/tree/import_node.rb +2 -0
  55. data/lib/sass/tree/mixin_def_node.rb +1 -0
  56. data/lib/sass/tree/mixin_node.rb +21 -5
  57. data/lib/sass/tree/node.rb +59 -12
  58. data/lib/sass/tree/prop_node.rb +20 -21
  59. data/lib/sass/tree/root_node.rb +8 -17
  60. data/lib/sass/tree/rule_node.rb +49 -100
  61. data/lib/sass/tree/variable_node.rb +1 -0
  62. data/lib/sass/tree/warn_node.rb +1 -0
  63. data/lib/sass/tree/while_node.rb +1 -0
  64. data/test/haml/engine_test.rb +185 -3
  65. data/test/haml/helper_test.rb +25 -2
  66. data/test/haml/template_test.rb +2 -2
  67. data/test/haml/templates/helpers.haml +13 -0
  68. data/test/haml/util/subset_map_test.rb +91 -0
  69. data/test/haml/util_test.rb +25 -0
  70. data/test/sass/conversion_test.rb +23 -3
  71. data/test/sass/engine_test.rb +50 -7
  72. data/test/sass/extend_test.rb +1045 -0
  73. data/test/sass/results/complex.css +0 -1
  74. data/test/sass/results/script.css +1 -1
  75. data/test/sass/script_conversion_test.rb +16 -0
  76. data/test/sass/script_test.rb +37 -4
  77. data/test/sass/scss/css_test.rb +17 -3
  78. data/test/sass/scss/rx_test.rb +1 -1
  79. data/test/sass/scss/scss_test.rb +30 -0
  80. data/test/sass/templates/complex.sass +0 -2
  81. data/test/test_helper.rb +5 -0
  82. metadata +18 -4
data/.yardopts CHANGED
@@ -3,6 +3,8 @@
3
3
  --markup-provider maruku
4
4
  --default-return ""
5
5
  --title "Haml/Sass Documentation"
6
+ --query 'object.type != :classvariable'
7
+ --query 'object.type != :constant || @api && @api.text == "public"'
6
8
  --hide-void-return
7
9
  --protected
8
10
  --no-private
data/REMEMBER CHANGED
@@ -1,13 +1,6 @@
1
- Deprecate .foo& in stable
2
- Make .#{} work in extend
3
- Test newly-invalid selectors, including post-resolution parse errors in Sass
4
1
  Be smart about default namespaces (http://www.w3.org/TR/css3-namespace/#declaration)
5
- Don't conflict with Object#extend.
2
+ Pseudo-selectors should go to the end w/@extend
3
+ Extending nested selectors?
6
4
 
7
- http://camendesign.com/design/ provides some interesting formatting and nesting issues for sass-convert
8
- Charles Roper's example code for media queries doesn't fare well in css2sass either
9
-
10
- Add period to SCSS syntax errors?
11
- Better #{} in prop names
12
- Faster than Less
13
- Comma multiline for Haml
5
+ .hoverlink {@extend a; @extend :hover}
6
+ a.user:hover {text-decoration: underline}
data/Rakefile CHANGED
@@ -239,7 +239,7 @@ end
239
239
  begin
240
240
  require 'yard'
241
241
 
242
- namespace :yard do
242
+ namespace :doc do
243
243
  task :sass do
244
244
  require scope('lib/sass')
245
245
  Dir[scope("yard/default/**/*.sass")].each do |sass|
@@ -248,12 +248,27 @@ begin
248
248
  end
249
249
  end
250
250
  end
251
+
252
+ desc "List all undocumented methods and classes."
253
+ task :undocumented do
254
+ opts = ENV["YARD_OPTS"] || ""
255
+ ENV["YARD_OPTS"] = opts.dup + <<OPTS
256
+ --list --query "
257
+ object.docstring.blank? &&
258
+ !(object.type == :method && object.is_alias?)"
259
+ OPTS
260
+ Rake::Task['yard'].execute
261
+ end
251
262
  end
252
263
 
253
264
  YARD::Rake::YardocTask.new do |t|
254
265
  t.files = FileList.new(scope('lib/**/*.rb')) do |list|
255
266
  list.exclude('lib/haml/template/*.rb')
267
+ list.exclude('lib/haml/railtie.rb')
256
268
  list.exclude('lib/haml/helpers/action_view_mods.rb')
269
+ list.exclude('lib/haml/helpers/xss_mods.rb')
270
+ list.exclude('lib/sass/plugin/merb.rb')
271
+ list.exclude('lib/sass/plugin/rails.rb')
257
272
  end.to_a
258
273
  t.options << '--incremental' if Rake.application.top_level_tasks.include?('redoc')
259
274
  t.options += FileList.new(scope('yard/*.rb')).to_a.map {|f| ['-e', f]}.flatten
@@ -261,8 +276,15 @@ begin
261
276
  t.options << '--files' << files.join(',')
262
277
  t.options << '--template-path' << scope('yard')
263
278
  t.options << '--title' << ENV["YARD_TITLE"] if ENV["YARD_TITLE"]
279
+
280
+ t.before = lambda do
281
+ if ENV["YARD_OPTS"]
282
+ require 'shellwords'
283
+ t.options.concat(Shellwords.shellwords(ENV["YARD_OPTS"]))
284
+ end
285
+ end
264
286
  end
265
- Rake::Task['yard'].prerequisites.insert(0, 'yard:sass')
287
+ Rake::Task['yard'].prerequisites.insert(0, 'doc:sass')
266
288
  Rake::Task['yard'].instance_variable_set('@comment', nil)
267
289
 
268
290
  desc "Generate Documentation"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.0.beta.3
1
+ 3.0.0.rc.1
@@ -17,6 +17,7 @@ module Haml
17
17
 
18
18
  # A string representing the version of Haml.
19
19
  # A more fine-grained representation is available from Haml.version.
20
+ # @api public
20
21
  VERSION = version[:string] unless defined?(Haml::VERSION)
21
22
 
22
23
  # Initializes Haml for Rails.
@@ -37,5 +38,7 @@ module Haml
37
38
  end
38
39
 
39
40
  require 'haml/util'
40
- require 'haml/engine'
41
- require 'haml/railtie'
41
+ unless $0 =~ /sass(-convert)?$/
42
+ require 'haml/engine'
43
+ require 'haml/railtie'
44
+ end
@@ -115,7 +115,6 @@ module Haml
115
115
  @options[:input], @options[:output] = input, output
116
116
  end
117
117
 
118
- # @private
119
118
  COLORS = { :red => 31, :green => 32, :yellow => 33 }
120
119
 
121
120
  # Prints a status message about performing the given action,
@@ -298,7 +297,7 @@ END
298
297
  @options[:for_engine][:cache_location] = loc
299
298
  end
300
299
  opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
301
- @options[:for_engine][:cache] = false
300
+ @options[:for_engine][:read_cache] = false
302
301
  end
303
302
  end
304
303
 
@@ -569,8 +568,9 @@ END
569
568
  # @param args [Array<String>] The command-line arguments
570
569
  def initialize(args)
571
570
  super
571
+ require 'sass'
572
572
  @options[:for_tree] = {}
573
- @options[:for_engine] = {}
573
+ @options[:for_engine] = {:cache => false, :read_cache => true}
574
574
  end
575
575
 
576
576
  # Tells optparse how to parse the arguments.
@@ -630,7 +630,7 @@ END
630
630
  end
631
631
 
632
632
  opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
633
- @options[:for_engine][:cache] = false
633
+ @options[:for_engine][:read_cache] = false
634
634
  end
635
635
 
636
636
  super
@@ -654,6 +654,8 @@ END
654
654
  process_file(input, output)
655
655
  end
656
656
 
657
+ private
658
+
657
659
  def process_directory
658
660
  input = @options[:input] = @args.shift
659
661
  output = @options[:output] = @args.shift
@@ -665,6 +667,11 @@ END
665
667
  end
666
668
  @options[:output] ||= @options[:input]
667
669
 
670
+ if @options[:to] == @options[:from] && !@options[:in_place]
671
+ fmt = @options[:from]
672
+ raise "Error: converting from #{fmt} to #{fmt} without --in-place"
673
+ end
674
+
668
675
  ext = @options[:from]
669
676
  ext = :sass if ext == :sass2
670
677
  Dir.glob("#{@options[:input]}/**/*.#{ext}") do |f|
@@ -325,6 +325,9 @@ END
325
325
  ::RedCloth.new(text).to_html(:textile)
326
326
  end
327
327
  end
328
+ # An alias for the Textile filter,
329
+ # since the only available Textile parser is RedCloth.
330
+ # @api public
328
331
  RedCloth = Textile
329
332
  Filters.defined['redcloth'] = RedCloth
330
333
 
@@ -1,8 +1,3 @@
1
- if defined?(ActionView)
2
- require 'haml/helpers/action_view_mods'
3
- require 'haml/helpers/action_view_extensions'
4
- end
5
-
6
1
  module Haml
7
2
  # This module contains various helpful methods to make it easier to do various tasks.
8
3
  # {Haml::Helpers} is automatically included in the context
@@ -52,8 +47,7 @@ MESSAGE
52
47
 
53
48
  self.extend self
54
49
 
55
- @@action_view_defined = defined?(ActionView)
56
- @@force_no_action_view = false
50
+ @@action_view_defined = false
57
51
 
58
52
  # @return [Boolean] Whether or not ActionView is loaded
59
53
  def self.action_view?
@@ -500,7 +494,6 @@ MESSAGE
500
494
  end
501
495
 
502
496
  # Characters that need to be escaped to HTML entities from user input
503
- # @private
504
497
  HTML_ESCAPE = { '&'=>'&amp;', '<'=>'&lt;', '>'=>'&gt;', '"'=>'&quot;', "'"=>'&#039;', }
505
498
 
506
499
  # Returns a copy of `text` with ampersands, angle brackets and quotes
@@ -594,11 +587,10 @@ MESSAGE
594
587
  _erbout = _hamlout.buffer
595
588
  proc { |*args| proc.call(*args) }
596
589
  end
597
-
598
- include ActionViewExtensions if self.const_defined? "ActionViewExtensions"
599
590
  end
600
591
  end
601
592
 
593
+ # @private
602
594
  class Object
603
595
  # Haml overrides various `ActionView` helpers,
604
596
  # which call an \{#is\_haml?} method
@@ -1,7 +1,7 @@
1
- require 'haml/helpers/action_view_mods'
2
-
3
1
  module Haml
4
2
  module Helpers
3
+ @@action_view_defined = true
4
+
5
5
  # This module contains various useful helper methods
6
6
  # that either tie into ActionView or the rest of the ActionPack stack,
7
7
  # or are only useful in that context.
@@ -51,5 +51,7 @@ module Haml
51
51
  @_haml_concat_raw = old
52
52
  end
53
53
  end
54
+
55
+ include ActionViewExtensions
54
56
  end
55
57
  end
@@ -126,7 +126,11 @@ module ActionView
126
126
  end
127
127
 
128
128
  def content_tag(*args)
129
- content_tag_with_haml(*args)
129
+ html_tag = content_tag_with_haml(*args)
130
+ return html_tag unless respond_to?(:error_wrapping)
131
+ return error_wrapping(html_tag) if method(:error_wrapping).arity == 1
132
+ return html_tag unless object.respond_to?(:errors) && object.errors.respond_to?(:on)
133
+ return error_wrapping(html_tag, object.errors.on(@method_name))
130
134
  end
131
135
  end
132
136
 
@@ -156,9 +160,7 @@ module ActionView
156
160
  def form_for_with_haml(object_name, *args, &proc)
157
161
  if block_given? && is_haml?
158
162
  oldproc = proc
159
- proc = haml_bind_proc do |*args|
160
- with_tabs(1) {oldproc.call(*args)}
161
- end
163
+ proc = proc {|*args| with_tabs(1) {oldproc.call(*args)}}
162
164
  end
163
165
  res = form_for_without_haml(object_name, *args, &proc)
164
166
  res << "\n" if block_given? && is_haml?
@@ -146,7 +146,6 @@ module Haml
146
146
  end
147
147
  alias_method :to_haml, :render
148
148
 
149
- # @private
150
149
  TEXT_REGEXP = /^(\s*).*$/
151
150
 
152
151
  # @see Hpricot
@@ -8,60 +8,46 @@ module Haml
8
8
  include Haml::Util
9
9
 
10
10
  # Designates an XHTML/XML element.
11
- # @private
12
11
  ELEMENT = ?%
13
12
 
14
13
  # Designates a `<div>` element with the given class.
15
- # @private
16
14
  DIV_CLASS = ?.
17
15
 
18
16
  # Designates a `<div>` element with the given id.
19
- # @private
20
17
  DIV_ID = ?#
21
18
 
22
19
  # Designates an XHTML/XML comment.
23
- # @private
24
20
  COMMENT = ?/
25
21
 
26
22
  # Designates an XHTML doctype or script that is never HTML-escaped.
27
- # @private
28
23
  DOCTYPE = ?!
29
24
 
30
25
  # Designates script, the result of which is output.
31
- # @private
32
26
  SCRIPT = ?=
33
27
 
34
28
  # Designates script that is always HTML-escaped.
35
- # @private
36
29
  SANITIZE = ?&
37
30
 
38
31
  # Designates script, the result of which is flattened and output.
39
- # @private
40
32
  FLAT_SCRIPT = ?~
41
33
 
42
34
  # Designates script which is run but not output.
43
- # @private
44
35
  SILENT_SCRIPT = ?-
45
36
 
46
37
  # When following SILENT_SCRIPT, designates a comment that is not output.
47
- # @private
48
38
  SILENT_COMMENT = ?#
49
39
 
50
40
  # Designates a non-parsed line.
51
- # @private
52
41
  ESCAPE = ?\\
53
42
 
54
43
  # Designates a block of filtered text.
55
- # @private
56
44
  FILTER = ?:
57
45
 
58
46
  # Designates a non-parsed line. Not actually a character.
59
- # @private
60
47
  PLAIN_TEXT = -1
61
48
 
62
49
  # Keeps track of the ASCII values of the characters that begin a
63
50
  # specially-interpreted line.
64
- # @private
65
51
  SPECIAL_CHARACTERS = [
66
52
  ELEMENT,
67
53
  DIV_CLASS,
@@ -78,7 +64,6 @@ module Haml
78
64
 
79
65
  # The value of the character that designates that a line is part
80
66
  # of a multiline string.
81
- # @private
82
67
  MULTILINE_CHAR_VALUE = ?|
83
68
 
84
69
  # Regex to match keywords that appear in the middle of a Ruby block
@@ -94,15 +79,12 @@ module Haml
94
79
  #
95
80
  # The block is ended after `%p no!`, because `else`
96
81
  # is a member of this array.
97
- # @private
98
82
  MID_BLOCK_KEYWORD_REGEX = /^-\s*(#{%w[else elsif rescue ensure when end].join('|')})\b/
99
83
 
100
84
  # The Regex that matches a Doctype command.
101
- # @private
102
85
  DOCTYPE_REGEX = /(\d(?:\.\d)?)?[\s]*([a-z]*)/i
103
86
 
104
87
  # The Regex that matches a literal string or symbol value
105
- # @private
106
88
  LITERAL_VALUE_REGEX = /:(\w*)|(["'])((?![\\#]|\2).|\\.)*\2/
107
89
 
108
90
  private
@@ -146,6 +128,7 @@ END
146
128
  class Line < Struct.new(:text, :unstripped, :full, :index, :precompiler, :eod)
147
129
  alias_method :eod?, :eod
148
130
 
131
+ # @private
149
132
  def tabs
150
133
  line = self
151
134
  @tabs ||= precompiler.instance_eval do
@@ -252,6 +235,7 @@ You don't need to use "- end" in Haml. Un-indent to close a block:
252
235
  %p This line is un-indented, so it isn't part of the "if" block
253
236
  END
254
237
 
238
+ text = handle_ruby_multiline(text)
255
239
  push_silent(text[1..-1], true)
256
240
  newline_now
257
241
 
@@ -395,6 +379,7 @@ END
395
379
  # the result before it is added to `@buffer`
396
380
  def push_script(text, opts = {})
397
381
  raise SyntaxError.new("There's no Ruby code for = to evaluate.") if text.empty?
382
+ text = handle_ruby_multiline(text)
398
383
  return if options[:suppress_eval]
399
384
  opts[:escape_html] = options[:escape_html] if opts[:escape_html].nil?
400
385
 
@@ -781,10 +766,13 @@ END
781
766
  end.compact!
782
767
 
783
768
  raise SyntaxError.new("Illegal nesting: nesting within a self-closing tag is illegal.", @next_line.index) if block_opened? && self_closing
784
- raise SyntaxError.new("Illegal nesting: content can't be both given on the same line as %#{tag_name} and nested within it.", @next_line.index) if block_opened? && !value.empty?
785
769
  raise SyntaxError.new("There's no Ruby code for #{action} to evaluate.", last_line - 1) if parse && value.empty?
786
770
  raise SyntaxError.new("Self-closing tags can't have content.", last_line - 1) if self_closing && !value.empty?
787
771
 
772
+ if block_opened? && !value.empty? && !is_ruby_multiline?(value)
773
+ raise SyntaxError.new("Illegal nesting: content can't be both given on the same line as %#{tag_name} and nested within it.", @next_line.index)
774
+ end
775
+
788
776
  self_closing ||= !!(!block_opened? && value.empty? && @options[:autoclose].any? {|t| t === tag_name})
789
777
  value = nil if value.empty? && (block_opened? || self_closing)
790
778
 
@@ -984,18 +972,17 @@ END
984
972
  end
985
973
 
986
974
  def handle_multiline(line)
987
- if is_multiline?(line.text)
988
- line.text.slice!(-1)
989
- while new_line = raw_next_line.first
990
- break if new_line == :eod
991
- newline and next if new_line.strip.empty?
992
- break unless is_multiline?(new_line.strip)
993
- line.text << new_line.strip[0...-1]
994
- newline
995
- end
996
- un_next_line new_line
997
- resolve_newlines
975
+ return unless is_multiline?(line.text)
976
+ line.text.slice!(-1)
977
+ while new_line = raw_next_line.first
978
+ break if new_line == :eod
979
+ newline and next if new_line.strip.empty?
980
+ break unless is_multiline?(new_line.strip)
981
+ line.text << new_line.strip[0...-1]
982
+ newline
998
983
  end
984
+ un_next_line new_line
985
+ resolve_newlines
999
986
  end
1000
987
 
1001
988
  # Checks whether or not +line+ is in a multiline sequence.
@@ -1003,6 +990,26 @@ END
1003
990
  text && text.length > 1 && text[-1] == MULTILINE_CHAR_VALUE && text[-2] == ?\s
1004
991
  end
1005
992
 
993
+ def handle_ruby_multiline(text)
994
+ text = text.rstrip
995
+ return text unless is_ruby_multiline?(text)
996
+ un_next_line @next_line.full
997
+ begin
998
+ new_line = raw_next_line.first
999
+ break if new_line == :eod
1000
+ newline and next if new_line.strip.empty?
1001
+ text << " " << new_line.strip
1002
+ newline
1003
+ end while is_ruby_multiline?(new_line.strip)
1004
+ next_line
1005
+ resolve_newlines
1006
+ text
1007
+ end
1008
+
1009
+ def is_ruby_multiline?(text)
1010
+ text && text.length > 1 && text[-1] == ?, && text[-2] != ?? && text[-3..-2] != "?\\"
1011
+ end
1012
+
1006
1013
  def contains_interpolation?(str)
1007
1014
  str.include?('#{')
1008
1015
  end
@@ -3,10 +3,14 @@
3
3
  # Yehuda promises there will be soon,
4
4
  # and once there is we should switch to that.
5
5
 
6
- if defined?(Rails::Railtie)
6
+ if defined?(ActiveSupport) && Haml::Util.has?(:public_method, ActiveSupport, :on_load)
7
+ # Rails 3.0.0.beta.2+
8
+ ActiveSupport.on_load(:action_view) {Haml.init_rails(binding)}
9
+ elsif defined?(Rails::Railtie)
10
+ # Rails 3.0.0.beta1
7
11
  module Haml
8
12
  class Railtie < Rails::Railtie
9
- initializer :haml do
13
+ ActiveSupport.on_load(:action_view) do
10
14
  Haml.init_rails(binding)
11
15
  end
12
16
  end