sass 3.3.0.rc.1 → 3.3.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass.rb +5 -0
  5. data/lib/sass/engine.rb +3 -5
  6. data/lib/sass/plugin.rb +0 -1
  7. data/lib/sass/plugin/compiler.rb +1 -2
  8. data/lib/sass/script/functions.rb +16 -2
  9. data/lib/sass/script/lexer.rb +22 -12
  10. data/lib/sass/script/parser.rb +27 -14
  11. data/lib/sass/script/tree/variable.rb +1 -1
  12. data/lib/sass/script/value/base.rb +1 -1
  13. data/lib/sass/script/value/color.rb +29 -17
  14. data/lib/sass/script/value/list.rb +1 -1
  15. data/lib/sass/script/value/number.rb +8 -1
  16. data/lib/sass/scss/parser.rb +2 -2
  17. data/lib/sass/selector/sequence.rb +18 -19
  18. data/lib/sass/selector/simple_sequence.rb +5 -5
  19. data/lib/sass/source/map.rb +1 -1
  20. data/lib/sass/tree/node.rb +25 -0
  21. data/lib/sass/tree/variable_node.rb +5 -0
  22. data/lib/sass/tree/visitors/base.rb +4 -7
  23. data/lib/sass/tree/visitors/check_nesting.rb +2 -2
  24. data/lib/sass/tree/visitors/perform.rb +12 -7
  25. data/lib/sass/util.rb +95 -50
  26. data/lib/sass/util/normalized_map.rb +63 -14
  27. data/lib/sass/util/ordered_hash.rb +9 -5
  28. data/lib/sass/version.rb +10 -12
  29. data/test/sass/engine_test.rb +37 -0
  30. data/test/sass/functions_test.rb +9 -2
  31. data/test/sass/importer_test.rb +3 -3
  32. data/test/sass/script_test.rb +12 -10
  33. data/test/sass/source_map_test.rb +8 -8
  34. data/test/sass/util/normalized_map_test.rb +22 -1
  35. data/test/sass/util_test.rb +18 -0
  36. data/test/test_helper.rb +16 -0
  37. data/vendor/listen/CHANGELOG.md +228 -0
  38. data/vendor/listen/CONTRIBUTING.md +38 -0
  39. data/vendor/listen/Gemfile +30 -0
  40. data/vendor/listen/Guardfile +8 -0
  41. data/vendor/listen/LICENSE +20 -0
  42. data/vendor/listen/README.md +315 -0
  43. data/vendor/listen/Rakefile +47 -0
  44. data/vendor/listen/Vagrantfile +96 -0
  45. data/vendor/listen/lib/listen.rb +40 -0
  46. data/vendor/listen/lib/listen/adapter.rb +214 -0
  47. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  48. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  49. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  50. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  51. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  52. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  53. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  54. data/vendor/listen/lib/listen/listener.rb +225 -0
  55. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  56. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  57. data/vendor/listen/lib/listen/version.rb +3 -0
  58. data/vendor/listen/listen.gemspec +22 -0
  59. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  60. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  61. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  62. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  63. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  64. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  65. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  66. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  67. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  68. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  69. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  70. data/vendor/listen/spec/listen_spec.rb +73 -0
  71. data/vendor/listen/spec/spec_helper.rb +21 -0
  72. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  73. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  74. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  75. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  76. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  77. metadata +318 -300
  78. data/test/Gemfile.lock +0 -10
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Listener do
4
+ let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object }
5
+ let(:watched_directory) { File.dirname(__FILE__) }
6
+
7
+ subject { described_class.new(watched_directory) }
8
+
9
+ before do
10
+ Listen::Adapter.stub(:select_and_initialize) { adapter }
11
+ # Don't build a record of the files inside the base directory.
12
+ subject.directory_record.stub(:build)
13
+ end
14
+
15
+ it_should_behave_like 'a listener to changes on a file-system'
16
+
17
+ describe '#initialize' do
18
+ context 'with no options' do
19
+ it 'sets the directory' do
20
+ subject.directory.should eq watched_directory
21
+ end
22
+
23
+ it 'converts the passed path into an absolute path - #21' do
24
+ described_class.new(File.join(watched_directory, '..')).directory.should eq File.expand_path('..', watched_directory)
25
+ end
26
+
27
+ it 'sets the option for using relative paths in the callback to the default one' do
28
+ subject.instance_variable_get(:@use_relative_paths).should eq described_class::DEFAULT_TO_RELATIVE_PATHS
29
+ end
30
+ end
31
+
32
+ context 'with custom options' do
33
+ subject { described_class.new(watched_directory, :ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/],
34
+ :latency => 0.5, :force_polling => true, :relative_paths => true) }
35
+
36
+ it 'passes the custom ignored paths to the directory record' do
37
+ subject.directory_record.ignoring_patterns.should include /\.ssh/
38
+ end
39
+
40
+ it 'passes the custom filters to the directory record' do
41
+ subject.directory_record.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/]
42
+ end
43
+
44
+ it 'sets the cutom option for using relative paths in the callback' do
45
+ subject.instance_variable_get(:@use_relative_paths).should be_true
46
+ end
47
+
48
+ it 'sets adapter_options' do
49
+ subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#start' do
55
+ it 'selects and initializes an adapter' do
56
+ Listen::Adapter.should_receive(:select_and_initialize).with(watched_directory, {}) { adapter }
57
+ subject.start
58
+ end
59
+
60
+ it 'builds the directory record' do
61
+ subject.directory_record.should_receive(:build)
62
+ subject.start
63
+ end
64
+ end
65
+
66
+ context 'with a started listener' do
67
+ before do
68
+ subject.stub(:initialize_adapter) { adapter }
69
+ subject.start
70
+ end
71
+
72
+ describe '#unpause' do
73
+ it 'rebuilds the directory record' do
74
+ subject.directory_record.should_receive(:build)
75
+ subject.unpause
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#ignore'do
81
+ it 'delegates the work to the directory record' do
82
+ subject.directory_record.should_receive(:ignore).with 'some_directory'
83
+ subject.ignore 'some_directory'
84
+ end
85
+ end
86
+
87
+ describe '#ignore!'do
88
+ it 'delegates the work to the directory record' do
89
+ subject.directory_record.should_receive(:ignore!).with 'some_directory'
90
+ subject.ignore! 'some_directory'
91
+ end
92
+ end
93
+
94
+ describe '#filter' do
95
+ it 'delegates the work to the directory record' do
96
+ subject.directory_record.should_receive(:filter).with /\.txt$/
97
+ subject.filter /\.txt$/
98
+ end
99
+ end
100
+
101
+ describe '#filter!' do
102
+ it 'delegates the work to the directory record' do
103
+ subject.directory_record.should_receive(:filter!).with /\.txt$/
104
+ subject.filter! /\.txt$/
105
+ end
106
+ end
107
+
108
+
109
+ describe '#on_change' do
110
+ let(:directories) { %w{dir1 dir2 dir3} }
111
+ let(:changes) { {:modified => [], :added => [], :removed => []} }
112
+ let(:callback) { Proc.new { @called = true } }
113
+
114
+ before do
115
+ @called = false
116
+ subject.directory_record.stub(:fetch_changes => changes)
117
+ end
118
+
119
+ it 'fetches the changes of the directory record' do
120
+ subject.directory_record.should_receive(:fetch_changes).with(
121
+ directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
122
+ )
123
+ subject.on_change(directories)
124
+ end
125
+
126
+ context 'with relative paths option set to true' do
127
+ subject { described_class.new(watched_directory, :relative_paths => true) }
128
+
129
+ it 'fetches the changes of the directory record' do
130
+ subject.directory_record.should_receive(:fetch_changes).with(directories, hash_including(:relative_paths => true))
131
+ subject.on_change(directories)
132
+ end
133
+ end
134
+
135
+ context 'with no changes to report' do
136
+ if RUBY_VERSION[/^1.8/]
137
+ it 'does not run the callback' do
138
+ subject.change(&callback)
139
+ subject.on_change(directories)
140
+ @called.should be_false
141
+ end
142
+ else
143
+ it 'does not run the callback' do
144
+ callback.should_not_receive(:call)
145
+ subject.change(&callback)
146
+ subject.on_change(directories)
147
+ end
148
+ end
149
+ end
150
+
151
+ context 'with changes to report' do
152
+ let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
153
+
154
+ if RUBY_VERSION[/^1.8/]
155
+ it 'runs the callback passing it the changes' do
156
+ subject.change(&callback)
157
+ subject.on_change(directories)
158
+ @called.should be_true
159
+ end
160
+ else
161
+ it 'runs the callback passing it the changes' do
162
+ callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
163
+ subject.change(&callback)
164
+ subject.on_change(directories)
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::MultiListener do
4
+ let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object }
5
+ let(:watched_directories) { [File.dirname(__FILE__), File.expand_path('../..', __FILE__)] }
6
+
7
+ subject { described_class.new(*watched_directories) }
8
+
9
+ before do
10
+ Listen::Adapter.stub(:select_and_initialize) { adapter }
11
+ # Don't build a record of the files inside the base directory.
12
+ Listen::DirectoryRecord.any_instance.stub(:build)
13
+ end
14
+
15
+ it_should_behave_like 'a listener to changes on a file-system'
16
+
17
+ describe '#initialize' do
18
+ context 'with no options' do
19
+ it 'sets the directories' do
20
+ subject.directories.should =~ watched_directories
21
+ end
22
+
23
+ it 'converts the passed paths into absolute paths - #21' do
24
+ paths = watched_directories.map { |d| File.join(d, '..') }
25
+ described_class.new(*paths).directories.should =~ watched_directories.map{ |d| File.expand_path('..', d) }
26
+ end
27
+ end
28
+
29
+ context 'with custom options' do
30
+ subject do
31
+ args = watched_directories << {:ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/], :latency => 0.5, :force_polling => true}
32
+ described_class.new(*args)
33
+ end
34
+
35
+ it 'passes the custom ignored paths to each directory record' do
36
+ subject.directories_records.each do |r|
37
+ r.ignoring_patterns.should include /\.ssh/
38
+ end
39
+ end
40
+
41
+ it 'passes the custom filters to each directory record' do
42
+ subject.directories_records.each do |r|
43
+ r.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/]
44
+ end
45
+ end
46
+
47
+ it 'sets adapter_options' do
48
+ subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#start' do
54
+ it 'selects and initializes an adapter' do
55
+ Listen::Adapter.should_receive(:select_and_initialize).with(watched_directories, {}) { adapter }
56
+ subject.start
57
+ end
58
+
59
+ it 'builds all directories records' do
60
+ subject.directories_records.each do |r|
61
+ r.should_receive(:build)
62
+ end
63
+ subject.start
64
+ end
65
+ end
66
+
67
+ context 'with a started listener' do
68
+ before do
69
+ subject.stub(:initialize_adapter) { adapter }
70
+ subject.start
71
+ end
72
+
73
+ describe '#unpause' do
74
+ it 'rebuilds all directories records' do
75
+ subject.directories_records.each do |r|
76
+ r.should_receive(:build)
77
+ end
78
+ subject.unpause
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#ignore' do
84
+ it 'delegates the work to each directory record' do
85
+ subject.directories_records.each do |r|
86
+ r.should_receive(:ignore).with 'some_directory'
87
+ end
88
+ subject.ignore 'some_directory'
89
+ end
90
+ end
91
+
92
+ describe '#ignore!' do
93
+ it 'delegates the work to each directory record' do
94
+ subject.directories_records.each do |r|
95
+ r.should_receive(:ignore!).with 'some_directory'
96
+ end
97
+ subject.ignore! 'some_directory'
98
+ end
99
+ end
100
+
101
+ describe '#filter' do
102
+ it 'delegates the work to each directory record' do
103
+ subject.directories_records.each do |r|
104
+ r.should_receive(:filter).with /\.txt$/
105
+ end
106
+ subject.filter /\.txt$/
107
+ end
108
+ end
109
+
110
+ describe '#filter!' do
111
+ it 'delegates the work to each directory record' do
112
+ subject.directories_records.each do |r|
113
+ r.should_receive(:filter!).with /\.txt$/
114
+ end
115
+ subject.filter! /\.txt$/
116
+ end
117
+ end
118
+
119
+ describe '#on_change' do
120
+ let(:directories) { %w{dir1 dir2 dir3} }
121
+ let(:changes) { {:modified => [], :added => [], :removed => []} }
122
+ let(:callback) { Proc.new { @called = true } }
123
+
124
+ before do
125
+ @called = false
126
+ subject.stub(:fetch_records_changes => changes)
127
+ end
128
+
129
+ it 'fetches the changes of all directories records' do
130
+ subject.unstub(:fetch_records_changes)
131
+
132
+ subject.directories_records.each do |record|
133
+ record.should_receive(:fetch_changes).with(
134
+ directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
135
+ ).and_return(changes)
136
+ end
137
+ subject.on_change(directories)
138
+ end
139
+
140
+ context 'with no changes to report' do
141
+ if RUBY_VERSION[/^1.8/]
142
+ it 'does not run the callback' do
143
+ subject.change(&callback)
144
+ subject.on_change(directories)
145
+ @called.should be_false
146
+ end
147
+ else
148
+ it 'does not run the callback' do
149
+ callback.should_not_receive(:call)
150
+ subject.change(&callback)
151
+ subject.on_change(directories)
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'with changes to report' do
157
+ let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
158
+
159
+ if RUBY_VERSION[/^1.8/]
160
+ it 'runs the callback passing it the changes' do
161
+ subject.change(&callback)
162
+ subject.on_change(directories)
163
+ @called.should be_true
164
+ end
165
+ else
166
+ it 'runs the callback passing it the changes' do
167
+ callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
168
+ subject.change(&callback)
169
+ subject.on_change(directories)
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ def run_in_two_threads(proc1, proc2)
4
+ t1 = Thread.new &proc1
5
+ sleep test_latency # t1 must run before t2
6
+ t2 = Thread.new { proc2.call; Thread.kill t1 }
7
+ t2.join(test_latency * 2)
8
+ ensure
9
+ Thread.kill t1 if t1
10
+ Thread.kill t2 if t2
11
+ end
12
+
13
+ describe Listen::Turnstile do
14
+ before { @called = false }
15
+
16
+ describe '#wait' do
17
+ context 'without a signal' do
18
+ it 'blocks one thread indefinitely' do
19
+ run_in_two_threads lambda {
20
+ subject.wait
21
+ @called = true
22
+ }, lambda {
23
+ sleep test_latency
24
+ }
25
+ @called.should be_false
26
+ end
27
+ end
28
+
29
+ context 'with a signal' do
30
+ it 'blocks one thread until it recieves a signal from another thread' do
31
+ run_in_two_threads lambda {
32
+ subject.wait
33
+ @called = true
34
+ }, lambda {
35
+ subject.signal
36
+ sleep test_latency
37
+ }
38
+ @called.should be_true
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#signal' do
44
+ context 'without a wait-call before' do
45
+ it 'does nothing' do
46
+ run_in_two_threads lambda {
47
+ subject.signal
48
+ @called = true
49
+ }, lambda {
50
+ sleep test_latency
51
+ }
52
+ @called.should be_true
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen do
4
+ describe '#to' do
5
+ context 'with one path to listen to' do
6
+ let(:listener) { mock(Listen::Listener) }
7
+ let(:listener_class) { Listen::Listener }
8
+
9
+ before { listener_class.stub(:new => listener) }
10
+
11
+ context 'without options' do
12
+ it 'creates an instance of Listner' do
13
+ listener_class.should_receive(:new).with('/path')
14
+ described_class.to('/path')
15
+ end
16
+ end
17
+
18
+ context 'with options' do
19
+ it 'creates an instance of Listner with the passed params' do
20
+ listener_class.should_receive(:new).with('/path', :filter => '**/*')
21
+ described_class.to('/path', :filter => '**/*')
22
+ end
23
+ end
24
+
25
+ context 'without a block' do
26
+ it 'returns the listener' do
27
+ described_class.to('/path', :filter => '**/*').should eq listener
28
+ end
29
+ end
30
+
31
+ context 'with a block' do
32
+ it 'starts the listner after creating it' do
33
+ listener.should_receive(:start)
34
+ described_class.to('/path', :filter => '**/*') { |modified, added, removed| }
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'with multiple paths to listen to' do
40
+ let(:multi_listener) { mock(Listen::MultiListener) }
41
+ let(:multi_listener_class) { Listen::MultiListener }
42
+
43
+ before { multi_listener_class.stub(:new => multi_listener) }
44
+
45
+ context 'without options' do
46
+ it 'creates an instance of MultiListner' do
47
+ multi_listener_class.should_receive(:new).with('path1', 'path2')
48
+ described_class.to('path1', 'path2')
49
+ end
50
+ end
51
+
52
+ context 'with options' do
53
+ it 'creates an instance of MultiListner with the passed params' do
54
+ multi_listener_class.should_receive(:new).with('path1', 'path2', :filter => '**/*')
55
+ described_class.to('path1', 'path2', :filter => '**/*')
56
+ end
57
+ end
58
+
59
+ context 'without a block' do
60
+ it 'returns a MultiListener instance created with the passed params' do
61
+ described_class.to('path1', 'path2', :filter => '**/*').should eq multi_listener
62
+ end
63
+ end
64
+
65
+ context 'with a block' do
66
+ it 'starts a MultiListener instance after creating it with the passed params' do
67
+ multi_listener.should_receive(:start)
68
+ described_class.to('path1', 'path2', :filter => '**/*') { |modified, added, removed| }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end