sass 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -0,0 +1,51 @@
1
+ module Sass
2
+ module Importers
3
+ # This importer emits a deprecation warning the first time it is used to
4
+ # import a file. It is used to deprecate the current working
5
+ # directory from the list of automatic sass load paths.
6
+ class DeprecatedPath < Filesystem
7
+ # @param root [String] The absolute, expanded path to the folder that is deprecated.
8
+ def initialize(root)
9
+ @specified_root = root
10
+ @warning_given = false
11
+ super
12
+ end
13
+
14
+ # @see Sass::Importers::Base#find
15
+ def find(*args)
16
+ found = super
17
+ if found && !@warning_given
18
+ @warning_given = true
19
+ Sass::Util.sass_warn deprecation_warning
20
+ end
21
+ found
22
+ end
23
+
24
+ # @see Base#directories_to_watch
25
+ def directories_to_watch
26
+ # The current working directory was not watched in Sass 3.2,
27
+ # so we continue not to watch it while it's deprecated.
28
+ []
29
+ end
30
+
31
+ # @see Sass::Importers::Base#to_s
32
+ def to_s
33
+ "#{@root} (DEPRECATED)"
34
+ end
35
+
36
+ protected
37
+
38
+ # @return [String] The deprecation warning that will be printed the first
39
+ # time an import occurs.
40
+ def deprecation_warning
41
+ path = @specified_root == "." ? "the current working directory" : @specified_root
42
+ <<WARNING
43
+ DEPRECATION WARNING: Importing from #{path} will not be
44
+ automatic in future versions of Sass. To avoid future errors, you can add it
45
+ to your environment explicitly by setting `SASS_PATH=#{@specified_root}`, by using the -I command
46
+ line option, or by changing your Sass configuration options.
47
+ WARNING
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,11 +1,10 @@
1
- require 'pathname'
1
+ require 'set'
2
2
 
3
3
  module Sass
4
4
  module Importers
5
5
  # The default importer, used for any strings found in the load path.
6
6
  # Simply loads Sass files from the filesystem using the default logic.
7
7
  class Filesystem < Base
8
-
9
8
  attr_accessor :root
10
9
 
11
10
  # Creates a new filesystem importer that imports files relative to a given path.
@@ -13,7 +12,8 @@ module Sass
13
12
  # @param root [String] The root path.
14
13
  # This importer will import files relative to this path.
15
14
  def initialize(root)
16
- @root = root
15
+ @root = File.expand_path(root)
16
+ @same_name_warnings = Set.new
17
17
  end
18
18
 
19
19
  # @see Base#find_relative
@@ -28,7 +28,7 @@ module Sass
28
28
 
29
29
  # @see Base#mtime
30
30
  def mtime(name, options)
31
- file, s = find_real_file(@root, name)
31
+ file, _ = Sass::Util.destructure(find_real_file(@root, name, options))
32
32
  File.mtime(file) if file
33
33
  rescue Errno::ENOENT
34
34
  nil
@@ -37,7 +37,7 @@ module Sass
37
37
  # @see Base#key
38
38
  def key(name, options)
39
39
  [self.class.name + ":" + File.dirname(File.expand_path(name)),
40
- File.basename(name)]
40
+ File.basename(name)]
41
41
  end
42
42
 
43
43
  # @see Base#to_s
@@ -45,14 +45,47 @@ 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
+
56
+ # @see Base#directories_to_watch
57
+ def directories_to_watch
58
+ [root]
59
+ end
60
+
61
+ # @see Base#watched_file?
62
+ def watched_file?(filename)
63
+ filename =~ /\.s[ac]ss$/ &&
64
+ filename.start_with?(root + File::SEPARATOR)
65
+ end
66
+
67
+ def public_url(name, sourcemap_directory = nil)
68
+ if sourcemap_directory.nil?
69
+ warn_about_public_url(name)
70
+ else
71
+ file_pathname = Sass::Util.pathname(Sass::Util.absolute_path(name, @root)).cleanpath
72
+ sourcemap_pathname = Sass::Util.pathname(sourcemap_directory).cleanpath
73
+ begin
74
+ file_pathname.relative_path_from(sourcemap_pathname).to_s
75
+ rescue ArgumentError # when a relative path cannot be constructed
76
+ warn_about_public_url(name)
77
+ nil
78
+ end
79
+ end
80
+ end
81
+
48
82
  protected
49
83
 
50
84
  # If a full uri is passed, this removes the root from it
51
85
  # otherwise returns the name unchanged
52
86
  def remove_root(name)
53
- root = @root.end_with?('/') ? @root : @root + '/'
54
- if name.index(root) == 0
55
- name[root.length..-1]
87
+ if name.index(@root + "/") == 0
88
+ name[(@root.length + 1)..-1]
56
89
  else
57
90
  name
58
91
  end
@@ -77,31 +110,77 @@ module Sass
77
110
  # The first element of each pair is a filename to look for;
78
111
  # the second element is the syntax that file would be in (`:sass` or `:scss`).
79
112
  def possible_files(name)
113
+ name = escape_glob_characters(name)
80
114
  dirname, basename, extname = split(name)
81
115
  sorted_exts = extensions.sort
82
116
  syntax = extensions[extname]
83
117
 
84
- return [["#{dirname}/{_,}#{basename}.#{extensions.invert[syntax]}", syntax]] if syntax
85
- sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
118
+ if syntax
119
+ ret = [["#{dirname}/{_,}#{basename}.#{extensions.invert[syntax]}", syntax]]
120
+ else
121
+ ret = sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
122
+ end
123
+
124
+ # JRuby chokes when trying to import files from JARs when the path starts with './'.
125
+ ret.map {|f, s| [f.sub(/^\.\//, ''), s]}
86
126
  end
87
127
 
128
+ def escape_glob_characters(name)
129
+ name.gsub(/[\*\[\]\{\}\?]/) do |char|
130
+ "\\#{char}"
131
+ end
132
+ end
88
133
 
89
- REDUNDANT_DIRECTORY = %r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}
134
+ REDUNDANT_DIRECTORY = /#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}/
90
135
  # Given a base directory and an `@import`ed name,
91
136
  # finds an existant file that matches the name.
92
137
  #
93
138
  # @param dir [String] The directory relative to which to search.
94
139
  # @param name [String] The filename to search for.
95
140
  # @return [(String, Symbol)] A filename-syntax pair.
96
- def find_real_file(dir, name)
97
- for (f,s) in possible_files(remove_root(name))
98
- path = (dir == ".") ? f : "#{dir}/#{f}"
99
- if full_path = Dir[path].first
100
- full_path.gsub!(REDUNDANT_DIRECTORY,File::SEPARATOR)
101
- return full_path, s
141
+ def find_real_file(dir, name, options)
142
+ # on windows 'dir' can be in native File::ALT_SEPARATOR form
143
+ dir = dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless File::ALT_SEPARATOR.nil?
144
+
145
+ found = possible_files(remove_root(name)).map do |f, s|
146
+ path = (dir == "." || Sass::Util.pathname(f).absolute?) ? f :
147
+ "#{escape_glob_characters(dir)}/#{f}"
148
+ Dir[path].map do |full_path|
149
+ full_path.gsub!(REDUNDANT_DIRECTORY, File::SEPARATOR)
150
+ [Sass::Util.pathname(full_path).cleanpath.to_s, s]
102
151
  end
103
152
  end
104
- nil
153
+ found = Sass::Util.flatten(found, 1)
154
+ return if found.empty?
155
+
156
+ if found.size > 1 && !@same_name_warnings.include?(found.first.first)
157
+ found.each {|(f, _)| @same_name_warnings << f}
158
+ relative_to = Sass::Util.pathname(dir)
159
+ if options[:_from_import_node]
160
+ # If _line exists, we're here due to an actual import in an
161
+ # import_node and we want to print a warning for a user writing an
162
+ # ambiguous import.
163
+ candidates = found.map do |(f, _)|
164
+ " " + Sass::Util.pathname(f).relative_path_from(relative_to).to_s
165
+ end.join("\n")
166
+ raise Sass::SyntaxError.new(<<MESSAGE)
167
+ It's not clear which file to import for '@import "#{name}"'.
168
+ Candidates:
169
+ #{candidates}
170
+ Please delete or rename all but one of these files.
171
+ MESSAGE
172
+ else
173
+ # Otherwise, we're here via StalenessChecker, and we want to print a
174
+ # warning for a user running `sass --watch` with two ambiguous files.
175
+ candidates = found.map {|(f, _)| " " + File.basename(f)}.join("\n")
176
+ Sass::Util.sass_warn <<WARNING
177
+ WARNING: In #{File.dirname(name)}:
178
+ There are multiple files that match the name "#{File.basename(name)}":
179
+ #{candidates}
180
+ WARNING
181
+ end
182
+ end
183
+ found.first
105
184
  end
106
185
 
107
186
  # Splits a filename into three parts, a directory part, a basename, and an extension
@@ -109,25 +188,33 @@ module Sass
109
188
  def split(name)
110
189
  extension = nil
111
190
  dirname, basename = File.dirname(name), File.basename(name)
112
- if basename =~ /^(.*)\.(#{extensions.keys.map{|e| Regexp.escape(e)}.join('|')})$/
191
+ if basename =~ /^(.*)\.(#{extensions.keys.map {|e| Regexp.escape(e)}.join('|')})$/
113
192
  basename = $1
114
193
  extension = $2
115
194
  end
116
195
  [dirname, basename, extension]
117
196
  end
118
197
 
119
- def hash
120
- @root.hash
121
- end
122
-
123
- def eql?(other)
124
- root.eql?(other.root)
198
+ # Issues a warning about being unable to determine a public url.
199
+ #
200
+ # @param uri [String] A URI known to be valid for this importer.
201
+ # @return [NilClass] nil
202
+ def warn_about_public_url(uri)
203
+ @warnings_issued ||= Set.new
204
+ unless @warnings_issued.include?(uri)
205
+ Sass::Util.sass_warn <<WARNING
206
+ WARNING: Couldn't determine public URL for "#{uri}" while generating sourcemap.
207
+ Without a public URL, there's nothing for the source map to link to.
208
+ WARNING
209
+ @warnings_issued << uri
210
+ end
211
+ nil
125
212
  end
126
213
 
127
214
  private
128
215
 
129
216
  def _find(dir, name, options)
130
- full_filename, syntax = find_real_file(dir, name)
217
+ full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
131
218
  return unless full_filename && File.readable?(full_filename)
132
219
 
133
220
  options[:syntax] = syntax
@@ -135,10 +222,6 @@ module Sass
135
222
  options[:importer] = self
136
223
  Sass::Engine.new(File.read(full_filename), options)
137
224
  end
138
-
139
- def join(base, path)
140
- Pathname.new(base).join(path).to_s
141
- end
142
225
  end
143
226
  end
144
227
  end
@@ -20,3 +20,4 @@ end
20
20
 
21
21
  require 'sass/importers/base'
22
22
  require 'sass/importers/filesystem'
23
+ require 'sass/importers/deprecated_path'
@@ -0,0 +1,30 @@
1
+ require 'sass/logger/log_level'
2
+
3
+ class Sass::Logger::Base
4
+ include Sass::Logger::LogLevel
5
+
6
+ attr_accessor :log_level
7
+ attr_accessor :disabled
8
+
9
+ log_level :trace
10
+ log_level :debug
11
+ log_level :info
12
+ log_level :warn
13
+ log_level :error
14
+
15
+ def initialize(log_level = :debug)
16
+ self.log_level = log_level
17
+ end
18
+
19
+ def logging_level?(level)
20
+ !disabled && self.class.log_level?(level, log_level)
21
+ end
22
+
23
+ def log(level, message)
24
+ _log(level, message) if logging_level?(level)
25
+ end
26
+
27
+ def _log(level, message)
28
+ Kernel.warn(message)
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ module Sass
2
+ module Logger
3
+ module LogLevel
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def inherited(subclass)
10
+ subclass.log_levels = subclass.superclass.log_levels.dup
11
+ end
12
+
13
+ attr_writer :log_levels
14
+
15
+ def log_levels
16
+ @log_levels ||= {}
17
+ end
18
+
19
+ def log_level?(level, min_level)
20
+ log_levels[level] >= log_levels[min_level]
21
+ end
22
+
23
+ def log_level(name, options = {})
24
+ if options[:prepend]
25
+ level = log_levels.values.min
26
+ level = level.nil? ? 0 : level - 1
27
+ else
28
+ level = log_levels.values.max
29
+ level = level.nil? ? 0 : level + 1
30
+ end
31
+ log_levels.update(name => level)
32
+ define_logger(name)
33
+ end
34
+
35
+ def define_logger(name, options = {})
36
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
37
+ def #{name}(message)
38
+ #{options.fetch(:to, :log)}(#{name.inspect}, message)
39
+ end
40
+ RUBY
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ module Sass::Logger; end
2
+
3
+ require "sass/logger/log_level"
4
+ require "sass/logger/base"
5
+
6
+ module Sass
7
+ class << self
8
+ attr_accessor :logger
9
+ end
10
+
11
+ self.logger = Sass::Logger::Base.new
12
+ end
data/lib/sass/media.rb ADDED
@@ -0,0 +1,213 @@
1
+ # A namespace for the `@media` query parse tree.
2
+ module Sass::Media
3
+ # A comma-separated list of queries.
4
+ #
5
+ # media_query [ ',' S* media_query ]*
6
+ class QueryList
7
+ # The queries contained in this list.
8
+ #
9
+ # @return [Array<Query>]
10
+ attr_accessor :queries
11
+
12
+ # @param queries [Array<Query>] See \{#queries}
13
+ def initialize(queries)
14
+ @queries = queries
15
+ end
16
+
17
+ # Merges this query list with another. The returned query list
18
+ # queries for the intersection between the two inputs.
19
+ #
20
+ # Both query lists should be resolved.
21
+ #
22
+ # @param other [QueryList]
23
+ # @return [QueryList?] The merged list, or nil if there is no intersection.
24
+ def merge(other)
25
+ new_queries = queries.map {|q1| other.queries.map {|q2| q1.merge(q2)}}.flatten.compact
26
+ return if new_queries.empty?
27
+ QueryList.new(new_queries)
28
+ end
29
+
30
+ # Returns the CSS for the media query list.
31
+ #
32
+ # @return [String]
33
+ def to_css
34
+ queries.map {|q| q.to_css}.join(', ')
35
+ end
36
+
37
+ # Returns the Sass/SCSS code for the media query list.
38
+ #
39
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
40
+ # @return [String]
41
+ def to_src(options)
42
+ queries.map {|q| q.to_src(options)}.join(', ')
43
+ end
44
+
45
+ # Returns a representation of the query as an array of strings and
46
+ # potentially {Sass::Script::Tree::Node}s (if there's interpolation in it).
47
+ # When the interpolation is resolved and the strings are joined together,
48
+ # this will be the string representation of this query.
49
+ #
50
+ # @return [Array<String, Sass::Script::Tree::Node>]
51
+ def to_a
52
+ Sass::Util.intersperse(queries.map {|q| q.to_a}, ', ').flatten
53
+ end
54
+
55
+ # Returns a deep copy of this query list and all its children.
56
+ #
57
+ # @return [QueryList]
58
+ def deep_copy
59
+ QueryList.new(queries.map {|q| q.deep_copy})
60
+ end
61
+ end
62
+
63
+ # A single media query.
64
+ #
65
+ # [ [ONLY | NOT]? S* media_type S* | expression ] [ AND S* expression ]*
66
+ class Query
67
+ # The modifier for the query.
68
+ #
69
+ # When parsed as Sass code, this contains strings and SassScript nodes. When
70
+ # parsed as CSS, it contains a single string (accessible via
71
+ # \{#resolved_modifier}).
72
+ #
73
+ # @return [Array<String, Sass::Script::Tree::Node>]
74
+ attr_accessor :modifier
75
+
76
+ # The type of the query (e.g. `"screen"` or `"print"`).
77
+ #
78
+ # When parsed as Sass code, this contains strings and SassScript nodes. When
79
+ # parsed as CSS, it contains a single string (accessible via
80
+ # \{#resolved_type}).
81
+ #
82
+ # @return [Array<String, Sass::Script::Tree::Node>]
83
+ attr_accessor :type
84
+
85
+ # The trailing expressions in the query.
86
+ #
87
+ # When parsed as Sass code, each expression contains strings and SassScript
88
+ # nodes. When parsed as CSS, each one contains a single string.
89
+ #
90
+ # @return [Array<Array<String, Sass::Script::Tree::Node>>]
91
+ attr_accessor :expressions
92
+
93
+ # @param modifier [Array<String, Sass::Script::Tree::Node>] See \{#modifier}
94
+ # @param type [Array<String, Sass::Script::Tree::Node>] See \{#type}
95
+ # @param expressions [Array<Array<String, Sass::Script::Tree::Node>>] See \{#expressions}
96
+ def initialize(modifier, type, expressions)
97
+ @modifier = modifier
98
+ @type = type
99
+ @expressions = expressions
100
+ end
101
+
102
+ # See \{#modifier}.
103
+ # @return [String]
104
+ def resolved_modifier
105
+ # modifier should contain only a single string
106
+ modifier.first || ''
107
+ end
108
+
109
+ # See \{#type}.
110
+ # @return [String]
111
+ def resolved_type
112
+ # type should contain only a single string
113
+ type.first || ''
114
+ end
115
+
116
+ # Merges this query with another. The returned query queries for
117
+ # the intersection between the two inputs.
118
+ #
119
+ # Both queries should be resolved.
120
+ #
121
+ # @param other [Query]
122
+ # @return [Query?] The merged query, or nil if there is no intersection.
123
+ def merge(other)
124
+ m1, t1 = resolved_modifier.downcase, resolved_type.downcase
125
+ m2, t2 = other.resolved_modifier.downcase, other.resolved_type.downcase
126
+ t1 = t2 if t1.empty?
127
+ t2 = t1 if t2.empty?
128
+ if (m1 == 'not') ^ (m2 == 'not')
129
+ return if t1 == t2
130
+ type = m1 == 'not' ? t2 : t1
131
+ mod = m1 == 'not' ? m2 : m1
132
+ elsif m1 == 'not' && m2 == 'not'
133
+ # CSS has no way of representing "neither screen nor print"
134
+ return unless t1 == t2
135
+ type = t1
136
+ mod = 'not'
137
+ elsif t1 != t2
138
+ return
139
+ else # t1 == t2, neither m1 nor m2 are "not"
140
+ type = t1
141
+ mod = m1.empty? ? m2 : m1
142
+ end
143
+ Query.new([mod], [type], other.expressions + expressions)
144
+ end
145
+
146
+ # Returns the CSS for the media query.
147
+ #
148
+ # @return [String]
149
+ def to_css
150
+ css = ''
151
+ css << resolved_modifier
152
+ css << ' ' unless resolved_modifier.empty?
153
+ css << resolved_type
154
+ css << ' and ' unless resolved_type.empty? || expressions.empty?
155
+ css << expressions.map do |e|
156
+ # It's possible for there to be script nodes in Expressions even when
157
+ # we're converting to CSS in the case where we parsed the document as
158
+ # CSS originally (as in css_test.rb).
159
+ e.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.to_sass : c.to_s}.join
160
+ end.join(' and ')
161
+ css
162
+ end
163
+
164
+ # Returns the Sass/SCSS code for the media query.
165
+ #
166
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
167
+ # @return [String]
168
+ def to_src(options)
169
+ src = ''
170
+ src << Sass::Media._interp_to_src(modifier, options)
171
+ src << ' ' unless modifier.empty?
172
+ src << Sass::Media._interp_to_src(type, options)
173
+ src << ' and ' unless type.empty? || expressions.empty?
174
+ src << expressions.map do |e|
175
+ Sass::Media._interp_to_src(e, options)
176
+ end.join(' and ')
177
+ src
178
+ end
179
+
180
+ # @see \{MediaQuery#to\_a}
181
+ def to_a
182
+ res = []
183
+ res += modifier
184
+ res << ' ' unless modifier.empty?
185
+ res += type
186
+ res << ' and ' unless type.empty? || expressions.empty?
187
+ res += Sass::Util.intersperse(expressions, ' and ').flatten
188
+ res
189
+ end
190
+
191
+ # Returns a deep copy of this query and all its children.
192
+ #
193
+ # @return [Query]
194
+ def deep_copy
195
+ Query.new(
196
+ modifier.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c},
197
+ type.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c},
198
+ expressions.map {|e| e.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}})
199
+ end
200
+ end
201
+
202
+ # Converts an interpolation array to source.
203
+ #
204
+ # @param interp [Array<String, Sass::Script::Tree::Node>] The interpolation array to convert.
205
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
206
+ # @return [String]
207
+ def self._interp_to_src(interp, options)
208
+ interp.map do |r|
209
+ next r if r.is_a?(String)
210
+ "\#{#{r.to_sass(options)}}"
211
+ end.join
212
+ end
213
+ end