sass 3.3.0.rc.3 → 3.3.0.rc.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -13
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/ext/mkrf_conf.rb +9 -5
  5. data/lib/sass/plugin/compiler.rb +1 -0
  6. data/lib/sass/script/parser.rb +1 -1
  7. data/lib/sass/script/value/list.rb +13 -4
  8. data/lib/sass/selector/sequence.rb +1 -1
  9. data/test/sass/functions_test.rb +4 -0
  10. data/test/sass/scss/scss_test.rb +18 -0
  11. metadata +231 -270
  12. data/vendor/listen/CHANGELOG.md +0 -228
  13. data/vendor/listen/CONTRIBUTING.md +0 -38
  14. data/vendor/listen/Gemfile +0 -30
  15. data/vendor/listen/Guardfile +0 -8
  16. data/vendor/listen/LICENSE +0 -20
  17. data/vendor/listen/README.md +0 -315
  18. data/vendor/listen/Rakefile +0 -47
  19. data/vendor/listen/Vagrantfile +0 -96
  20. data/vendor/listen/lib/listen.rb +0 -40
  21. data/vendor/listen/lib/listen/adapter.rb +0 -214
  22. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -112
  23. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -85
  24. data/vendor/listen/lib/listen/adapters/linux.rb +0 -113
  25. data/vendor/listen/lib/listen/adapters/polling.rb +0 -67
  26. data/vendor/listen/lib/listen/adapters/windows.rb +0 -87
  27. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  28. data/vendor/listen/lib/listen/directory_record.rb +0 -371
  29. data/vendor/listen/lib/listen/listener.rb +0 -225
  30. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  31. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  32. data/vendor/listen/lib/listen/version.rb +0 -3
  33. data/vendor/listen/listen.gemspec +0 -22
  34. data/vendor/listen/spec/listen/adapter_spec.rb +0 -183
  35. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  36. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  37. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  38. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  39. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  40. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  41. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1225
  42. data/vendor/listen/spec/listen/listener_spec.rb +0 -169
  43. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
  44. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  45. data/vendor/listen/spec/listen_spec.rb +0 -73
  46. data/vendor/listen/spec/spec_helper.rb +0 -21
  47. data/vendor/listen/spec/support/adapter_helper.rb +0 -629
  48. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  49. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  50. data/vendor/listen/spec/support/listeners_helper.rb +0 -156
  51. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -1,371 +0,0 @@
1
- require 'set'
2
- require 'find'
3
- require 'digest/sha1'
4
-
5
- module Listen
6
-
7
- # The directory record stores information about
8
- # a directory and keeps track of changes to
9
- # the structure of its childs.
10
- #
11
- class DirectoryRecord
12
- attr_reader :directory, :paths, :sha1_checksums
13
-
14
- DEFAULT_IGNORED_DIRECTORIES = %w[.rbx .bundle .git .svn log tmp vendor]
15
-
16
- DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store]
17
-
18
- # Defines the used precision based on the type of mtime returned by the
19
- # system (whether its in milliseconds or just seconds)
20
- #
21
- begin
22
- HIGH_PRECISION_SUPPORTED = File.mtime(__FILE__).to_f.to_s[-2..-1] != '.0'
23
- rescue
24
- HIGH_PRECISION_SUPPORTED = false
25
- end
26
-
27
- # Data structure used to save meta data about a path
28
- #
29
- MetaData = Struct.new(:type, :mtime)
30
-
31
- # Class methods
32
- #
33
- class << self
34
-
35
- # Creates the ignoring patterns from the default ignored
36
- # directories and extensions. It memoizes the generated patterns
37
- # to avoid unnecessary computation.
38
- #
39
- def generate_default_ignoring_patterns
40
- @@default_ignoring_patterns ||= Array.new.tap do |default_patterns|
41
- # Add directories
42
- ignored_directories = DEFAULT_IGNORED_DIRECTORIES.map { |d| Regexp.escape(d) }
43
- default_patterns << %r{^(?:#{ignored_directories.join('|')})/}
44
-
45
- # Add extensions
46
- ignored_extensions = DEFAULT_IGNORED_EXTENSIONS.map { |e| Regexp.escape(e) }
47
- default_patterns << %r{(?:#{ignored_extensions.join('|')})$}
48
- end
49
- end
50
- end
51
-
52
- # Initializes a directory record.
53
- #
54
- # @option [String] directory the directory to keep track of
55
- #
56
- def initialize(directory)
57
- raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)
58
-
59
- @directory = directory
60
- @ignoring_patterns = Set.new
61
- @filtering_patterns = Set.new
62
- @sha1_checksums = Hash.new
63
-
64
- @ignoring_patterns.merge(DirectoryRecord.generate_default_ignoring_patterns)
65
- end
66
-
67
- # Returns the ignoring patterns in the record
68
- #
69
- # @return [Array<Regexp>] the ignoring patterns
70
- #
71
- def ignoring_patterns
72
- @ignoring_patterns.to_a
73
- end
74
-
75
- # Returns the filtering patterns used in the record to know
76
- # which paths should be stored.
77
- #
78
- # @return [Array<Regexp>] the filtering patterns
79
- #
80
- def filtering_patterns
81
- @filtering_patterns.to_a
82
- end
83
-
84
- # Adds ignoring patterns to the record.
85
- #
86
- # @example Ignore some paths
87
- # ignore %r{^ignored/path/}, /man/
88
- #
89
- # @param [Regexp] regexp a pattern for ignoring paths
90
- #
91
- def ignore(*regexps)
92
- @ignoring_patterns.merge(regexps)
93
- end
94
-
95
- # Replaces ignoring patterns in the record.
96
- #
97
- # @example Ignore only these paths
98
- # ignore! %r{^ignored/path/}, /man/
99
- #
100
- # @param [Regexp] regexp a pattern for ignoring paths
101
- #
102
- def ignore!(*regexps)
103
- @ignoring_patterns.replace(regexps)
104
- end
105
-
106
- # Adds filtering patterns to the listener.
107
- #
108
- # @example Filter some files
109
- # ignore /\.txt$/, /.*\.zip/
110
- #
111
- # @param [Regexp] regexp a pattern for filtering paths
112
- #
113
- def filter(*regexps)
114
- @filtering_patterns.merge(regexps)
115
- end
116
-
117
- # Replaces filtering patterns in the listener.
118
- #
119
- # @example Filter only these files
120
- # ignore /\.txt$/, /.*\.zip/
121
- #
122
- # @param [Regexp] regexp a pattern for filtering paths
123
- #
124
- def filter!(*regexps)
125
- @filtering_patterns.replace(regexps)
126
- end
127
-
128
- # Returns whether a path should be ignored or not.
129
- #
130
- # @param [String] path the path to test.
131
- #
132
- # @return [Boolean]
133
- #
134
- def ignored?(path)
135
- path = relative_to_base(path)
136
- @ignoring_patterns.any? { |pattern| pattern =~ path }
137
- end
138
-
139
- # Returns whether a path should be filtered or not.
140
- #
141
- # @param [String] path the path to test.
142
- #
143
- # @return [Boolean]
144
- #
145
- def filtered?(path)
146
- # When no filtering patterns are set, ALL files are stored.
147
- return true if @filtering_patterns.empty?
148
-
149
- path = relative_to_base(path)
150
- @filtering_patterns.any? { |pattern| pattern =~ path }
151
- end
152
-
153
- # Finds the paths that should be stored and adds them
154
- # to the paths' hash.
155
- #
156
- def build
157
- @paths = Hash.new { |h, k| h[k] = Hash.new }
158
- important_paths { |path| insert_path(path) }
159
- end
160
-
161
- # Detects changes in the passed directories, updates
162
- # the record with the new changes and returns the changes
163
- #
164
- # @param [Array] directories the list of directories scan for changes
165
- # @param [Hash] options
166
- # @option options [Boolean] recursive scan all sub-directories recursively
167
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
168
- #
169
- # @return [Hash<Array>] the changes
170
- #
171
- def fetch_changes(directories, options = {})
172
- @changes = { :modified => [], :added => [], :removed => [] }
173
- directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first
174
-
175
- directories.each do |directory|
176
- next unless directory[@directory] # Path is or inside directory
177
- detect_modifications_and_removals(directory, options)
178
- detect_additions(directory, options)
179
- end
180
-
181
- @changes
182
- end
183
-
184
- # Converts an absolute path to a path that's relative to the base directory.
185
- #
186
- # @param [String] path the path to convert
187
- #
188
- # @return [String] the relative path
189
- #
190
- def relative_to_base(path)
191
- return nil unless path[@directory]
192
- path = path.force_encoding("BINARY") if path.respond_to?(:force_encoding)
193
- path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
194
- end
195
-
196
- private
197
-
198
- # Detects modifications and removals recursively in a directory.
199
- #
200
- # @note Modifications detection begins by checking the modification time (mtime)
201
- # of files and then by checking content changes (using SHA1-checksum)
202
- # when the mtime of files is not changed.
203
- #
204
- # @param [String] directory the path to analyze
205
- # @param [Hash] options
206
- # @option options [Boolean] recursive scan all sub-directories recursively
207
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
208
- #
209
- def detect_modifications_and_removals(directory, options = {})
210
- @paths[directory].each do |basename, meta_data|
211
- path = File.join(directory, basename)
212
-
213
- case meta_data.type
214
- when 'Dir'
215
- if File.directory?(path)
216
- detect_modifications_and_removals(path, options) if options[:recursive]
217
- else
218
- detect_modifications_and_removals(path, { :recursive => true }.merge(options))
219
- @paths[directory].delete(basename)
220
- @paths.delete("#{directory}/#{basename}")
221
- end
222
- when 'File'
223
- if File.exist?(path)
224
- new_mtime = mtime_of(path)
225
-
226
- # First check if we are in the same second (to update checksums)
227
- # before checking the time difference
228
- if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < new_mtime
229
- # Update the sha1 checksum of the file
230
- insert_sha1_checksum(path)
231
-
232
- # Update the meta data of the file
233
- meta_data.mtime = new_mtime
234
- @paths[directory][basename] = meta_data
235
-
236
- @changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
237
- end
238
- else
239
- @paths[directory].delete(basename)
240
- @sha1_checksums.delete(path)
241
- @changes[:removed] << (options[:relative_paths] ? relative_to_base(path) : path)
242
- end
243
- end
244
- end
245
- end
246
-
247
- # Detects additions in a directory.
248
- #
249
- # @param [String] directory the path to analyze
250
- # @param [Hash] options
251
- # @option options [Boolean] recursive scan all sub-directories recursively
252
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
253
- #
254
- def detect_additions(directory, options = {})
255
- # Don't process removed directories
256
- return unless File.exist?(directory)
257
-
258
- Find.find(directory) do |path|
259
- next if path == @directory
260
-
261
- if File.directory?(path)
262
- # Add a trailing slash to directories when checking if a directory is
263
- # ignored to optimize finding them as Find.find doesn't.
264
- if ignored?(path + File::SEPARATOR) || (directory != path && (!options[:recursive] && existing_path?(path)))
265
- Find.prune # Don't look any further into this directory.
266
- else
267
- insert_path(path)
268
- end
269
- elsif !ignored?(path) && filtered?(path) && !existing_path?(path)
270
- if File.file?(path)
271
- @changes[:added] << (options[:relative_paths] ? relative_to_base(path) : path)
272
- insert_path(path)
273
- end
274
- end
275
- end
276
- end
277
-
278
- # Returns whether or not a file's content has been modified by
279
- # comparing the SHA1-checksum to a stored one.
280
- # Ensure that the SHA1-checksum is inserted to the sha1_checksums
281
- # array for later comparaison if false.
282
- #
283
- # @param [String] path the file path
284
- #
285
- def content_modified?(path)
286
- @sha1_checksum = sha1_checksum(path)
287
- if @sha1_checksums[path] == @sha1_checksum || !@sha1_checksums.key?(path)
288
- insert_sha1_checksum(path)
289
- false
290
- else
291
- true
292
- end
293
- end
294
-
295
- # Inserts a SHA1-checksum path in @SHA1-checksums hash.
296
- #
297
- # @param [String] path the SHA1-checksum path to insert in @sha1_checksums.
298
- #
299
- def insert_sha1_checksum(path)
300
- if @sha1_checksum ||= sha1_checksum(path)
301
- @sha1_checksums[path] = @sha1_checksum
302
- @sha1_checksum = nil
303
- end
304
- end
305
-
306
- # Returns the SHA1-checksum for the file path.
307
- #
308
- # @param [String] path the file path
309
- #
310
- def sha1_checksum(path)
311
- Digest::SHA1.file(path).to_s
312
- rescue Errno::EACCES, Errno::ENOENT, Errno::ENXIO, Errno::EOPNOTSUPP
313
- nil
314
- end
315
-
316
- # Traverses the base directory looking for paths that should
317
- # be stored; thus paths that are filters or not ignored.
318
- #
319
- # @yield [path] an important path
320
- #
321
- def important_paths
322
- Find.find(@directory) do |path|
323
- next if path == @directory
324
-
325
- if File.directory?(path)
326
- # Add a trailing slash to directories when checking if a directory is
327
- # ignored to optimize finding them as Find.find doesn't.
328
- if ignored?(path + File::SEPARATOR)
329
- Find.prune # Don't look any further into this directory.
330
- else
331
- yield(path)
332
- end
333
- elsif !ignored?(path) && filtered?(path)
334
- yield(path)
335
- end
336
- end
337
- end
338
-
339
- # Inserts a path with its type (Dir or File) in paths hash.
340
- #
341
- # @param [String] path the path to insert in @paths.
342
- #
343
- def insert_path(path)
344
- meta_data = MetaData.new
345
- meta_data.type = File.directory?(path) ? 'Dir' : 'File'
346
- meta_data.mtime = mtime_of(path) unless meta_data.type == 'Dir' # mtimes of dirs are not used yet
347
- @paths[File.dirname(path)][File.basename(path)] = meta_data
348
- rescue Errno::ENOENT
349
- end
350
-
351
- # Returns whether or not a path exists in the paths hash.
352
- #
353
- # @param [String] path the path to check
354
- #
355
- # @return [Boolean]
356
- #
357
- def existing_path?(path)
358
- @paths[File.dirname(path)][File.basename(path)] != nil
359
- end
360
-
361
- # Returns the modification time of a file based on the precision defined by the system
362
- #
363
- # @param [String] file the file for which the mtime must be returned
364
- #
365
- # @return [Fixnum, Float] the mtime of the file
366
- #
367
- def mtime_of(file)
368
- File.lstat(file).mtime.send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
369
- end
370
- end
371
- end
@@ -1,225 +0,0 @@
1
- require 'pathname'
2
-
3
- module Listen
4
- class Listener
5
- attr_reader :directory, :directory_record, :adapter
6
-
7
- # The default value for using relative paths in the callback.
8
- DEFAULT_TO_RELATIVE_PATHS = false
9
-
10
- # Initializes the directory listener.
11
- #
12
- # @param [String] directory the directory to listen to
13
- # @param [Hash] options the listen options
14
- # @option options [Regexp] ignore a pattern for ignoring paths
15
- # @option options [Regexp] filter a pattern for filtering paths
16
- # @option options [Float] latency the delay between checking for changes in seconds
17
- # @option options [Boolean] relative_paths whether or not to use relative-paths in the callback
18
- # @option options [Boolean] force_polling whether to force the polling adapter or not
19
- # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
20
- #
21
- # @yield [modified, added, removed] the changed files
22
- # @yieldparam [Array<String>] modified the list of modified files
23
- # @yieldparam [Array<String>] added the list of added files
24
- # @yieldparam [Array<String>] removed the list of removed files
25
- #
26
- def initialize(directory, options = {}, &block)
27
- @block = block
28
- @directory = Pathname.new(directory).realpath.to_s
29
- @directory_record = DirectoryRecord.new(@directory)
30
- @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS
31
-
32
- @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths]
33
- @directory_record.ignore(*options.delete(:ignore)) if options[:ignore]
34
- @directory_record.filter(*options.delete(:filter)) if options[:filter]
35
-
36
- @adapter_options = options
37
- end
38
-
39
- # Starts the listener by initializing the adapter and building
40
- # the directory record concurrently, then it starts the adapter to watch
41
- # for changes.
42
- #
43
- # @param [Boolean] blocking whether or not to block the current thread after starting
44
- #
45
- def start(blocking = true)
46
- t = Thread.new { @directory_record.build }
47
- @adapter = initialize_adapter
48
- t.join
49
- @adapter.start(blocking)
50
- end
51
-
52
- # Stops the listener.
53
- #
54
- def stop
55
- @adapter.stop
56
- end
57
-
58
- # Pauses the listener.
59
- #
60
- # @return [Listen::Listener] the listener
61
- #
62
- def pause
63
- @adapter.paused = true
64
- self
65
- end
66
-
67
- # Unpauses the listener.
68
- #
69
- # @return [Listen::Listener] the listener
70
- #
71
- def unpause
72
- @directory_record.build
73
- @adapter.paused = false
74
- self
75
- end
76
-
77
- # Returns whether the listener is paused or not.
78
- #
79
- # @return [Boolean] adapter paused status
80
- #
81
- def paused?
82
- !!@adapter && @adapter.paused == true
83
- end
84
-
85
- # Adds ignoring patterns to the listener.
86
- #
87
- # @param (see Listen::DirectoryRecord#ignore)
88
- #
89
- # @return [Listen::Listener] the listener
90
- #
91
- def ignore(*regexps)
92
- @directory_record.ignore(*regexps)
93
- self
94
- end
95
-
96
- # Replaces ignoring patterns in the listener.
97
- #
98
- # @param (see Listen::DirectoryRecord#ignore!)
99
- #
100
- # @return [Listen::Listener] the listener
101
- #
102
- def ignore!(*regexps)
103
- @directory_record.ignore!(*regexps)
104
- self
105
- end
106
-
107
- # Adds filtering patterns to the listener.
108
- #
109
- # @param (see Listen::DirectoryRecord#filter)
110
- #
111
- # @return [Listen::Listener] the listener
112
- #
113
- def filter(*regexps)
114
- @directory_record.filter(*regexps)
115
- self
116
- end
117
-
118
- # Replacing filtering patterns in the listener.
119
- #
120
- # @param (see Listen::DirectoryRecord#filter!)
121
- #
122
- # @return [Listen::Listener] the listener
123
- #
124
- def filter!(*regexps)
125
- @directory_record.filter!(*regexps)
126
- self
127
- end
128
-
129
- # Sets the latency for the adapter. This is a helper method
130
- # to simplify changing the latency directly from the listener.
131
- #
132
- # @example Wait 0.5 seconds each time before checking changes
133
- # latency 0.5
134
- #
135
- # @param [Float] seconds the amount of delay, in seconds
136
- #
137
- # @return [Listen::Listener] the listener
138
- #
139
- def latency(seconds)
140
- @adapter_options[:latency] = seconds
141
- self
142
- end
143
-
144
- # Sets whether the use of the polling adapter
145
- # should be forced or not.
146
- #
147
- # @example Forcing the use of the polling adapter
148
- # force_polling true
149
- #
150
- # @param [Boolean] value whether to force the polling adapter or not
151
- #
152
- # @return [Listen::Listener] the listener
153
- #
154
- def force_polling(value)
155
- @adapter_options[:force_polling] = value
156
- self
157
- end
158
-
159
- # Sets whether the paths in the callback should be
160
- # relative or absolute.
161
- #
162
- # @example Enabling relative paths in the callback
163
- # relative_paths true
164
- #
165
- # @param [Boolean] value whether to enable relative paths in the callback or not
166
- #
167
- # @return [Listen::Listener] the listener
168
- #
169
- def relative_paths(value)
170
- @use_relative_paths = value
171
- self
172
- end
173
-
174
- # Defines a custom polling fallback message of disable it.
175
- #
176
- # @example Disabling the polling fallback message
177
- # polling_fallback_message false
178
- #
179
- # @param [String, Boolean] value to change polling fallback message or remove it
180
- #
181
- # @return [Listen::Listener] the listener
182
- #
183
- def polling_fallback_message(value)
184
- @adapter_options[:polling_fallback_message] = value
185
- self
186
- end
187
-
188
- # Sets the callback that gets called on changes.
189
- #
190
- # @example Assign a callback to be called on changes
191
- # callback = lambda { |modified, added, removed| ... }
192
- # change &callback
193
- #
194
- # @param [Proc] block the callback proc
195
- #
196
- # @return [Listen::Listener] the listener
197
- #
198
- def change(&block) # modified, added, removed
199
- @block = block
200
- self
201
- end
202
-
203
- # Runs the callback passing it the changes if there are any.
204
- #
205
- # @param (see Listen::DirectoryRecord#fetch_changes)
206
- #
207
- def on_change(directories, options = {})
208
- changes = @directory_record.fetch_changes(directories, options.merge(
209
- :relative_paths => @use_relative_paths
210
- ))
211
- unless changes.values.all? { |paths| paths.empty? }
212
- @block.call(changes[:modified],changes[:added],changes[:removed])
213
- end
214
- end
215
-
216
- private
217
-
218
- # Initializes an adapter passing it the callback and adapters' options.
219
- #
220
- def initialize_adapter
221
- callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
222
- Adapter.select_and_initialize(@directory, @adapter_options, &callback)
223
- end
224
- end
225
- end