haml 3.1.3 → 3.1.4

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 (134) hide show
  1. data/Rakefile +42 -17
  2. data/VERSION +1 -1
  3. data/lib/haml/compiler.rb +3 -3
  4. data/lib/haml/helpers/action_view_mods.rb +4 -3
  5. data/lib/haml/template.rb +3 -1
  6. data/test/gemfiles/Gemfile.rails-2.0.x +8 -0
  7. data/test/gemfiles/Gemfile.rails-2.0.x.lock +38 -0
  8. data/test/gemfiles/Gemfile.rails-2.1.x +8 -0
  9. data/test/gemfiles/Gemfile.rails-2.1.x.lock +38 -0
  10. data/test/gemfiles/Gemfile.rails-2.2.x +8 -0
  11. data/test/gemfiles/Gemfile.rails-2.2.x.lock +38 -0
  12. data/test/gemfiles/Gemfile.rails-2.3.x +8 -0
  13. data/test/gemfiles/Gemfile.rails-2.3.x.lock +40 -0
  14. data/test/gemfiles/Gemfile.rails-3.0.x +8 -0
  15. data/test/gemfiles/Gemfile.rails-3.0.x.lock +85 -0
  16. data/test/gemfiles/Gemfile.rails-3.1.x +8 -0
  17. data/test/gemfiles/Gemfile.rails-3.1.x.lock +98 -0
  18. data/test/gemfiles/Gemfile.rails-xss-2.3.x +9 -0
  19. data/test/gemfiles/Gemfile.rails-xss-2.3.x.lock +42 -0
  20. data/test/haml/engine_test.rb +19 -0
  21. data/test/haml/html2haml_test.rb +1 -1
  22. data/test/haml/template_test.rb +20 -2
  23. data/test/haml/templates/partial_layout.haml +4 -1
  24. data/test/linked_rails.rb +4 -4
  25. data/vendor/sass/VERSION +1 -1
  26. data/vendor/sass/doc-src/SASS_CHANGELOG.md +115 -2
  27. data/vendor/sass/doc-src/SASS_REFERENCE.md +12 -4
  28. data/vendor/sass/lib/sass.rb +1 -0
  29. data/vendor/sass/lib/sass/cache_stores/base.rb +3 -1
  30. data/vendor/sass/lib/sass/cache_stores/filesystem.rb +2 -0
  31. data/vendor/sass/lib/sass/css.rb +2 -1
  32. data/vendor/sass/lib/sass/engine.rb +39 -23
  33. data/vendor/sass/lib/sass/environment.rb +11 -0
  34. data/vendor/sass/lib/sass/exec.rb +14 -1
  35. data/vendor/sass/lib/sass/importers/base.rb +2 -1
  36. data/vendor/sass/lib/sass/importers/filesystem.rb +18 -13
  37. data/vendor/sass/lib/sass/less.rb +2 -2
  38. data/vendor/sass/lib/sass/logger.rb +15 -0
  39. data/vendor/sass/lib/sass/logger/base.rb +32 -0
  40. data/vendor/sass/lib/sass/logger/log_level.rb +49 -0
  41. data/vendor/sass/lib/sass/plugin.rb +4 -8
  42. data/vendor/sass/lib/sass/plugin/compiler.rb +42 -17
  43. data/vendor/sass/lib/sass/plugin/configuration.rb +0 -2
  44. data/vendor/sass/lib/sass/railtie.rb +1 -1
  45. data/vendor/sass/lib/sass/script/funcall.rb +14 -1
  46. data/vendor/sass/lib/sass/script/functions.rb +44 -1
  47. data/vendor/sass/lib/sass/script/interpolation.rb +9 -0
  48. data/vendor/sass/lib/sass/script/lexer.rb +6 -1
  49. data/vendor/sass/lib/sass/script/list.rb +7 -0
  50. data/vendor/sass/lib/sass/script/literal.rb +5 -0
  51. data/vendor/sass/lib/sass/script/node.rb +8 -0
  52. data/vendor/sass/lib/sass/script/number.rb +28 -5
  53. data/vendor/sass/lib/sass/script/operation.rb +8 -0
  54. data/vendor/sass/lib/sass/script/parser.rb +12 -5
  55. data/vendor/sass/lib/sass/script/string_interpolation.rb +9 -0
  56. data/vendor/sass/lib/sass/script/unary_operation.rb +7 -0
  57. data/vendor/sass/lib/sass/script/variable.rb +5 -0
  58. data/vendor/sass/lib/sass/scss/parser.rb +78 -38
  59. data/vendor/sass/lib/sass/scss/rx.rb +2 -1
  60. data/vendor/sass/lib/sass/scss/static_parser.rb +2 -2
  61. data/vendor/sass/lib/sass/shared.rb +1 -1
  62. data/vendor/sass/lib/sass/tree/comment_node.rb +24 -11
  63. data/vendor/sass/lib/sass/tree/debug_node.rb +1 -1
  64. data/vendor/sass/lib/sass/tree/each_node.rb +1 -1
  65. data/vendor/sass/lib/sass/tree/extend_node.rb +1 -1
  66. data/vendor/sass/lib/sass/tree/for_node.rb +2 -2
  67. data/vendor/sass/lib/sass/tree/function_node.rb +1 -1
  68. data/vendor/sass/lib/sass/tree/if_node.rb +1 -14
  69. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +1 -1
  70. data/vendor/sass/lib/sass/tree/mixin_node.rb +2 -2
  71. data/vendor/sass/lib/sass/tree/node.rb +2 -5
  72. data/vendor/sass/lib/sass/tree/prop_node.rb +2 -9
  73. data/vendor/sass/lib/sass/tree/return_node.rb +1 -1
  74. data/vendor/sass/lib/sass/tree/rule_node.rb +9 -2
  75. data/vendor/sass/lib/sass/tree/variable_node.rb +1 -1
  76. data/vendor/sass/lib/sass/tree/visitors/check_nesting.rb +17 -18
  77. data/vendor/sass/lib/sass/tree/visitors/convert.rb +10 -5
  78. data/vendor/sass/lib/sass/tree/visitors/deep_copy.rb +87 -0
  79. data/vendor/sass/lib/sass/tree/visitors/perform.rb +50 -19
  80. data/vendor/sass/lib/sass/tree/visitors/set_options.rb +97 -0
  81. data/vendor/sass/lib/sass/tree/visitors/to_css.rb +9 -15
  82. data/vendor/sass/lib/sass/tree/warn_node.rb +1 -1
  83. data/vendor/sass/lib/sass/tree/while_node.rb +1 -1
  84. data/vendor/sass/lib/sass/util.rb +58 -6
  85. data/vendor/sass/sass.gemspec +2 -1
  86. data/vendor/sass/test/Gemfile +4 -0
  87. data/vendor/sass/test/Gemfile.lock +19 -0
  88. data/vendor/sass/test/sass/cache_test.rb +15 -0
  89. data/vendor/sass/test/sass/conversion_test.rb +2 -6
  90. data/vendor/sass/test/sass/css2sass_test.rb +9 -0
  91. data/vendor/sass/test/sass/engine_test.rb +124 -26
  92. data/vendor/sass/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  93. data/vendor/sass/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  94. data/vendor/sass/test/sass/functions_test.rb +13 -0
  95. data/vendor/sass/test/sass/importer_test.rb +110 -0
  96. data/vendor/sass/test/sass/logger_test.rb +58 -0
  97. data/vendor/sass/test/sass/plugin_test.rb +16 -13
  98. data/vendor/sass/test/sass/script_conversion_test.rb +2 -0
  99. data/vendor/sass/test/sass/script_test.rb +18 -0
  100. data/vendor/sass/test/sass/scss/css_test.rb +7 -1
  101. data/vendor/sass/test/sass/scss/scss_test.rb +37 -13
  102. data/vendor/sass/test/sass/templates/bork5.sass +3 -0
  103. data/vendor/sass/test/sass/templates/nested_bork5.sass +2 -0
  104. data/vendor/sass/test/sass/test_helper.rb +1 -1
  105. data/vendor/sass/test/sass/util_test.rb +12 -0
  106. data/vendor/sass/vendor/fssm/Gemfile +3 -0
  107. data/vendor/sass/vendor/fssm/LICENSE +1 -1
  108. data/vendor/sass/vendor/fssm/README.markdown +55 -27
  109. data/vendor/sass/vendor/fssm/Rakefile +6 -54
  110. data/vendor/sass/vendor/fssm/example.rb +6 -3
  111. data/vendor/sass/vendor/fssm/fssm.gemspec +17 -70
  112. data/vendor/sass/vendor/fssm/lib/fssm.rb +7 -3
  113. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +1 -1
  114. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +2 -2
  115. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +2 -2
  116. data/vendor/sass/vendor/fssm/lib/fssm/backends/rbfsevent.rb +42 -0
  117. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +10 -10
  118. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +19 -9
  119. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +24 -21
  120. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +13 -479
  121. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +29 -11
  122. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +1 -1
  123. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +41 -12
  124. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +6 -6
  125. data/vendor/sass/vendor/fssm/lib/fssm/version.rb +3 -0
  126. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +3 -3
  127. data/vendor/sass/vendor/fssm/profile/prof-pathname-rubinius.rb +35 -0
  128. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +7 -7
  129. data/vendor/sass/vendor/fssm/spec/count_down_latch.rb +151 -0
  130. data/vendor/sass/vendor/fssm/spec/monitor_spec.rb +202 -0
  131. data/vendor/sass/vendor/fssm/spec/path_spec.rb +36 -15
  132. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +6 -6
  133. metadata +36 -5
  134. data/vendor/sass/vendor/fssm/VERSION.yml +0 -5
@@ -49,6 +49,8 @@ module Sass
49
49
  # @param obj [Object] The object to cache.
50
50
  def store(key, sha, root)
51
51
  _store(key, Sass::VERSION, sha, Marshal.dump(root))
52
+ rescue TypeError, LoadError => e
53
+ Sass::Util.sass_warn "Warning. Error encountered while saving cache #{path_to(key)}: #{e}"
52
54
  end
53
55
 
54
56
  # Retrieve a {Sass::Tree::RootNode}.
@@ -59,7 +61,7 @@ module Sass
59
61
  def retrieve(key, sha)
60
62
  contents = _retrieve(key, Sass::VERSION, sha)
61
63
  Marshal.load(contents) if contents
62
- rescue EOFError, TypeError, ArgumentError => e
64
+ rescue EOFError, TypeError, ArgumentError, LoadError => e
63
65
  Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
64
66
  end
65
67
 
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module Sass
2
4
  module CacheStores
3
5
  # A backend for the Sass cache using the filesystem.
@@ -75,7 +75,7 @@ module Sass
75
75
  #
76
76
  # @return [Tree::Node] The root node of the parsed tree
77
77
  def build_tree
78
- root = Sass::SCSS::CssParser.new(@template).parse
78
+ root = Sass::SCSS::CssParser.new(@template, @options[:filename]).parse
79
79
  expand_commas root
80
80
  parent_ref_rules root
81
81
  remove_parent_refs root
@@ -106,6 +106,7 @@ module Sass
106
106
  next child
107
107
  end
108
108
  child.rule.first.split(',').map do |rule|
109
+ next if rule.strip.empty?
109
110
  node = Tree::RuleNode.new([rule.strip])
110
111
  node.children = child.children
111
112
  node
@@ -28,6 +28,8 @@ require 'sass/tree/visitors/perform'
28
28
  require 'sass/tree/visitors/cssize'
29
29
  require 'sass/tree/visitors/convert'
30
30
  require 'sass/tree/visitors/to_css'
31
+ require 'sass/tree/visitors/deep_copy'
32
+ require 'sass/tree/visitors/set_options'
31
33
  require 'sass/tree/visitors/check_nesting'
32
34
  require 'sass/selector'
33
35
  require 'sass/environment'
@@ -88,7 +90,10 @@ module Sass
88
90
  #
89
91
  # `children`: `Array<Line>`
90
92
  # : The lines nested below this one.
91
- class Line < Struct.new(:text, :tabs, :index, :offset, :filename, :children)
93
+ #
94
+ # `comment_tab_str`: `String?`
95
+ # : The prefix indentation for this comment, if it is a comment.
96
+ class Line < Struct.new(:text, :tabs, :index, :offset, :filename, :children, :comment_tab_str)
92
97
  def comment?
93
98
  text[0] == COMMENT_CHAR && (text[1] == SASS_COMMENT_CHAR || text[1] == CSS_COMMENT_CHAR)
94
99
  end
@@ -105,6 +110,10 @@ module Sass
105
110
  # which is not output as a CSS comment.
106
111
  SASS_COMMENT_CHAR = ?/
107
112
 
113
+ # The character that indicates that a comment allows interpolation
114
+ # and should be preserved even in `:compressed` mode.
115
+ SASS_LOUD_COMMENT_CHAR = ?!
116
+
108
117
  # The character that follows the general COMMENT_CHAR and designates a CSS comment,
109
118
  # which is embedded in the CSS document.
110
119
  CSS_COMMENT_CHAR = ?*
@@ -307,7 +316,6 @@ module Sass
307
316
  sha = Digest::SHA1.hexdigest(@template)
308
317
 
309
318
  if root = @options[:cache_store].retrieve(key, sha)
310
- @options = root.options.merge(@options)
311
319
  root.options = @options
312
320
  return root
313
321
  end
@@ -316,7 +324,7 @@ module Sass
316
324
  check_encoding!
317
325
 
318
326
  if @options[:syntax] == :scss
319
- root = Sass::SCSS::Parser.new(@template).parse
327
+ root = Sass::SCSS::Parser.new(@template, @options[:filename]).parse
320
328
  else
321
329
  root = Tree::RootNode.new(@template)
322
330
  append_children(root, tree(tabulate(@template)).first, true)
@@ -326,7 +334,7 @@ module Sass
326
334
  if @options[:cache] && key && sha
327
335
  begin
328
336
  old_options = root.options
329
- root.options = {:importer => root.options[:importer]}
337
+ root.options = {}
330
338
  @options[:cache_store].store(key, sha, root)
331
339
  ensure
332
340
  root.options = old_options
@@ -419,7 +427,8 @@ but this line was indented by #{Sass::Shared.human_indentation line[/^\s*/]}.
419
427
  MSG
420
428
  end
421
429
 
422
- last.text << "\n" << $1
430
+ last.comment_tab_str ||= comment_tab_str
431
+ last.text << "\n" << line
423
432
  true
424
433
  end
425
434
 
@@ -485,8 +494,8 @@ MSG
485
494
  if child.is_a?(Tree::CommentNode) && child.silent
486
495
  if continued_comment &&
487
496
  child.line == continued_comment.line +
488
- continued_comment.value.count("\n") + 1
489
- continued_comment.value << "\n" << child.value
497
+ continued_comment.lines + 1
498
+ continued_comment.value += ["\n"] + child.value
490
499
  next
491
500
  end
492
501
 
@@ -537,7 +546,7 @@ WARNING
537
546
  when ?$
538
547
  parse_variable(line)
539
548
  when COMMENT_CHAR
540
- parse_comment(line.text)
549
+ parse_comment(line)
541
550
  when DIRECTIVE_CHAR
542
551
  parse_directive(parent, line, root)
543
552
  when ESCAPE_CHAR
@@ -558,7 +567,7 @@ WARNING
558
567
  def parse_property_or_rule(line)
559
568
  scanner = StringScanner.new(line.text)
560
569
  hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
561
- parser = Sass::SCSS::SassParser.new(scanner, @line)
570
+ parser = Sass::SCSS::SassParser.new(scanner, @options[:filename], @line)
562
571
 
563
572
  unless res = parser.parse_interp_ident
564
573
  return Tree::RuleNode.new(parse_interp(line.text))
@@ -581,15 +590,9 @@ WARNING
581
590
  if value.strip.empty?
582
591
  expr = Sass::Script::String.new("")
583
592
  else
584
- important = false
585
- if value =~ Sass::SCSS::RX::IMPORTANT
586
- important = true
587
- value = value.gsub(Sass::SCSS::RX::IMPORTANT,"")
588
- end
589
593
  expr = parse_script(value, :offset => line.offset + line.text.index(value))
590
-
591
594
  end
592
- Tree::PropNode.new(parse_interp(name), expr, important, prop)
595
+ Tree::PropNode.new(parse_interp(name), expr, prop)
593
596
  end
594
597
 
595
598
  def parse_variable(line)
@@ -605,11 +608,19 @@ WARNING
605
608
  end
606
609
 
607
610
  def parse_comment(line)
608
- if line[1] == CSS_COMMENT_CHAR || line[1] == SASS_COMMENT_CHAR
609
- silent = line[1] == SASS_COMMENT_CHAR
610
- Tree::CommentNode.new(
611
- format_comment_text(line[2..-1], silent),
612
- silent)
611
+ if line.text[1] == CSS_COMMENT_CHAR || line.text[1] == SASS_COMMENT_CHAR
612
+ silent = line.text[1] == SASS_COMMENT_CHAR
613
+ if loud = line.text[2] == SASS_LOUD_COMMENT_CHAR
614
+ value = self.class.parse_interp(line.text, line.index, line.offset, :filename => @filename)
615
+ value[0].slice!(2) # get rid of the "!"
616
+ else
617
+ value = [line.text]
618
+ end
619
+ value = with_extracted_values(value) do |str|
620
+ str = str.gsub(/^#{line.comment_tab_str}/m, '')[2..-1] # get rid of // or /*
621
+ format_comment_text(str, silent)
622
+ end
623
+ Tree::CommentNode.new(value, silent, loud)
613
624
  else
614
625
  Tree::RuleNode.new(parse_interp(line))
615
626
  end
@@ -750,6 +761,11 @@ WARNING
750
761
  break unless scanner.scan(/,\s*/)
751
762
  end
752
763
 
764
+ if scanner.scan(/;/)
765
+ raise SyntaxError.new("Invalid @import: expected end of line, was \";\".",
766
+ :line => @line)
767
+ end
768
+
753
769
  return values
754
770
  end
755
771
 
@@ -757,12 +773,12 @@ WARNING
757
773
  return if scanner.eos?
758
774
  unless (str = scanner.scan(Sass::SCSS::RX::STRING)) ||
759
775
  (uri = scanner.scan(Sass::SCSS::RX::URI))
760
- return Tree::ImportNode.new(scanner.scan(/[^,]+/))
776
+ return Tree::ImportNode.new(scanner.scan(/[^,;]+/))
761
777
  end
762
778
 
763
779
  val = scanner[1] || scanner[2]
764
780
  scanner.scan(/\s*/)
765
- if media = scanner.scan(/[^,].*/)
781
+ if media = scanner.scan(/[^,;].*/)
766
782
  Tree::DirectiveNode.new("@import #{str || uri} #{media}")
767
783
  elsif uri
768
784
  Tree::DirectiveNode.new("@import #{uri}")
@@ -93,6 +93,17 @@ module Sass
93
93
  @mixins_in_use ||= @parent.mixins_in_use
94
94
  end
95
95
 
96
+ def stack_trace
97
+ trace = []
98
+ stack.reverse.each_with_index do |entry, i|
99
+ msg = "#{i == 0 ? "on" : "from"} line #{entry[:line]}"
100
+ msg << " of #{entry[:filename] || "an unknown file"}"
101
+ msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
102
+ trace << msg
103
+ end
104
+ trace
105
+ end
106
+
96
107
  private
97
108
 
98
109
  def parent_options
@@ -229,6 +229,10 @@ END
229
229
  'Only meaningful for --watch and --update.') do
230
230
  @options[:stop_on_error] = true
231
231
  end
232
+ opts.on('-f', '--force', 'Recompile all Sass files, even if the CSS file is newer.',
233
+ 'Only meaningful for --update.') do
234
+ @options[:force] = true
235
+ end
232
236
  opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
233
237
  require 'stringio'
234
238
  @options[:check_syntax] = true
@@ -238,6 +242,10 @@ END
238
242
  'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
239
243
  @options[:for_engine][:style] = name.to_sym
240
244
  end
245
+ opts.on('--precision NUMBER_OF_DIGITS', Integer,
246
+ 'How many digits of precision to use when outputting decimal numbers. Defaults to 3.') do |precision|
247
+ ::Sass::Script::Number.precision = precision
248
+ end
241
249
  opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
242
250
  @options[:for_engine][:quiet] = true
243
251
  end
@@ -350,6 +358,11 @@ END
350
358
  ::Sass::Plugin.options.merge! @options[:for_engine]
351
359
  ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
352
360
 
361
+ if @options[:force]
362
+ raise "The --force flag may only be used with --update." unless @options[:update]
363
+ ::Sass::Plugin.options[:always_update] = true
364
+ end
365
+
353
366
  raise <<MSG if @args.empty?
354
367
  What files should I watch? Did you mean something like:
355
368
  #{@default_syntax} --watch input.#{@default_syntax}:output.css
@@ -372,7 +385,7 @@ MSG
372
385
 
373
386
  dirs, files = @args.map {|name| split_colon_path(name)}.
374
387
  partition {|i, _| File.directory? i}
375
- files.map! {|from, to| [from, to || from.gsub(/\..*?$/, '.css')]}
388
+ files.map! {|from, to| [from, to || from.gsub(/\.[^.]*?$/, '.css')]}
376
389
  dirs.map! {|from, to| [from, to || from]}
377
390
  ::Sass::Plugin.options[:template_location] = dirs
378
391
 
@@ -72,7 +72,8 @@ module Sass
72
72
  # If no such files exist, it should return nil.
73
73
  #
74
74
  # The {Sass::Engine} to be returned should be passed `options`,
75
- # with a few modifications. `:filename` and `:syntax` should be set appropriately,
75
+ # with a few modifications. `:syntax` should be set appropriately,
76
+ # `:filename` should be set to `uri`,
76
77
  # and `:importer` should be set to this importer.
77
78
  #
78
79
  # @param uri [String] The URI to import.
@@ -13,7 +13,7 @@ module Sass
13
13
  # @param root [String] The root path.
14
14
  # This importer will import files relative to this path.
15
15
  def initialize(root)
16
- @root = root
16
+ @root = File.expand_path(root)
17
17
  end
18
18
 
19
19
  # @see Base#find_relative
@@ -45,14 +45,21 @@ module Sass
45
45
  @root
46
46
  end
47
47
 
48
+ def hash
49
+ @root.hash
50
+ end
51
+
52
+ def eql?(other)
53
+ root.eql?(other.root)
54
+ end
55
+
48
56
  protected
49
57
 
50
58
  # If a full uri is passed, this removes the root from it
51
59
  # otherwise returns the name unchanged
52
60
  def remove_root(name)
53
- root = @root.end_with?('/') ? @root : @root + '/'
54
- if name.index(root) == 0
55
- name[root.length..-1]
61
+ if name.index(@root + "/") == 0
62
+ name[(@root.length + 1)..-1]
56
63
  else
57
64
  name
58
65
  end
@@ -77,6 +84,7 @@ module Sass
77
84
  # The first element of each pair is a filename to look for;
78
85
  # the second element is the syntax that file would be in (`:sass` or `:scss`).
79
86
  def possible_files(name)
87
+ name = escape_glob_characters(name)
80
88
  dirname, basename, extname = split(name)
81
89
  sorted_exts = extensions.sort
82
90
  syntax = extensions[extname]
@@ -85,6 +93,11 @@ module Sass
85
93
  sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
86
94
  end
87
95
 
96
+ def escape_glob_characters(name)
97
+ name.gsub(/[\*\[\]\{\}\?]/) do |char|
98
+ "\\#{char}"
99
+ end
100
+ end
88
101
 
89
102
  REDUNDANT_DIRECTORY = %r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}
90
103
  # Given a base directory and an `@import`ed name,
@@ -95,7 +108,7 @@ module Sass
95
108
  # @return [(String, Symbol)] A filename-syntax pair.
96
109
  def find_real_file(dir, name)
97
110
  for (f,s) in possible_files(remove_root(name))
98
- path = (dir == ".") ? f : "#{dir}/#{f}"
111
+ path = (dir == "." || Pathname.new(f).absolute?) ? f : "#{dir}/#{f}"
99
112
  if full_path = Dir[path].first
100
113
  full_path.gsub!(REDUNDANT_DIRECTORY,File::SEPARATOR)
101
114
  return full_path, s
@@ -116,14 +129,6 @@ module Sass
116
129
  [dirname, basename, extension]
117
130
  end
118
131
 
119
- def hash
120
- @root.hash
121
- end
122
-
123
- def eql?(other)
124
- root.eql?(other.root)
125
- end
126
-
127
132
  private
128
133
 
129
134
  def _find(dir, name, options)
@@ -31,7 +31,7 @@ module Less
31
31
  WARNING: Sass doesn't support mixing in selector sequences.
32
32
  Replacing "#{sel}" with "@extend #{base}"
33
33
  WARNING
34
- env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
34
+ env << Node::SassNode.new(Sass::Tree::CommentNode.new(["// #{sel};"], true, false))
35
35
  env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
36
36
  end
37
37
  end
@@ -225,7 +225,7 @@ WARNING
225
225
  class Property
226
226
  def to_sass_tree
227
227
  return if hide_in_sass
228
- Sass::Tree::PropNode.new([self], @value.to_sass_tree, false, :new)
228
+ Sass::Tree::PropNode.new([self], @value.to_sass_tree, :new)
229
229
  end
230
230
  end
231
231
 
@@ -0,0 +1,15 @@
1
+ module Sass::Logger
2
+
3
+ end
4
+
5
+ require "sass/logger/log_level"
6
+ require "sass/logger/base"
7
+
8
+ module Sass
9
+
10
+ class << self
11
+ attr_accessor :logger
12
+ end
13
+
14
+ self.logger = Sass::Logger::Base.new
15
+ end
@@ -0,0 +1,32 @@
1
+ require 'sass/logger/log_level'
2
+
3
+ class Sass::Logger::Base
4
+
5
+ include Sass::Logger::LogLevel
6
+
7
+ attr_accessor :log_level
8
+ attr_accessor :disabled
9
+
10
+ log_level :trace
11
+ log_level :debug
12
+ log_level :info
13
+ log_level :warn
14
+ log_level :error
15
+
16
+ def initialize(log_level = :debug)
17
+ self.log_level = log_level
18
+ end
19
+
20
+ def logging_level?(level)
21
+ !disabled && self.class.log_level?(level, log_level)
22
+ end
23
+
24
+ def log(level, message)
25
+ self._log(level, message) if logging_level?(level)
26
+ end
27
+
28
+ def _log(level, message)
29
+ Kernel::warn(message)
30
+ end
31
+
32
+ end
@@ -0,0 +1,49 @@
1
+ module Sass
2
+ module Logger
3
+ module LogLevel
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def inherited(subclass)
11
+ subclass.log_levels = subclass.superclass.log_levels.dup
12
+ end
13
+
14
+ def log_levels
15
+ @log_levels ||= {}
16
+ end
17
+
18
+ def log_levels=(levels)
19
+ @log_levels = levels
20
+ end
21
+
22
+ def log_level?(level, min_level)
23
+ log_levels[level] >= log_levels[min_level]
24
+ end
25
+
26
+ def log_level(name, options = {})
27
+ if options[:prepend]
28
+ level = log_levels.values.min
29
+ level = level.nil? ? 0 : level - 1
30
+ else
31
+ level = log_levels.values.max
32
+ level = level.nil? ? 0 : level + 1
33
+ end
34
+ log_levels.update(name => level)
35
+ define_logger(name)
36
+ end
37
+
38
+ def define_logger(name, options = {})
39
+ class_eval %Q{
40
+ def #{name}(message)
41
+ #{options.fetch(:to, :log)}(#{name.inspect}, message)
42
+ end
43
+ }
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end