sass 3.6.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.md +1 -1
  3. data/README.md +10 -0
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/lib/sass/script/css_parser.rb +4 -1
  7. data/lib/sass/script/functions.rb +15 -25
  8. data/lib/sass/script/lexer.rb +45 -7
  9. data/lib/sass/script/parser.rb +259 -93
  10. data/lib/sass/scss/parser.rb +43 -16
  11. data/lib/sass/scss/static_parser.rb +15 -15
  12. data/lib/sass/util.rb +31 -0
  13. metadata +8 -156
  14. data/Rakefile +0 -364
  15. data/test/sass-spec.yml +0 -3
  16. data/test/sass/cache_test.rb +0 -130
  17. data/test/sass/callbacks_test.rb +0 -60
  18. data/test/sass/compiler_test.rb +0 -225
  19. data/test/sass/conversion_test.rb +0 -2138
  20. data/test/sass/css2sass_test.rb +0 -523
  21. data/test/sass/css_variable_test.rb +0 -237
  22. data/test/sass/data/hsl-rgb.txt +0 -319
  23. data/test/sass/encoding_test.rb +0 -188
  24. data/test/sass/engine_test.rb +0 -3499
  25. data/test/sass/exec_test.rb +0 -95
  26. data/test/sass/extend_test.rb +0 -1679
  27. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  28. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  29. data/test/sass/functions_test.rb +0 -2021
  30. data/test/sass/importer_test.rb +0 -420
  31. data/test/sass/logger_test.rb +0 -57
  32. data/test/sass/mock_importer.rb +0 -49
  33. data/test/sass/more_results/more1.css +0 -9
  34. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  35. data/test/sass/more_results/more_import.css +0 -29
  36. data/test/sass/more_templates/_more_partial.sass +0 -2
  37. data/test/sass/more_templates/more1.sass +0 -23
  38. data/test/sass/more_templates/more_import.sass +0 -11
  39. data/test/sass/plugin_test.rb +0 -552
  40. data/test/sass/results/alt.css +0 -4
  41. data/test/sass/results/basic.css +0 -9
  42. data/test/sass/results/cached_import_option.css +0 -3
  43. data/test/sass/results/compact.css +0 -5
  44. data/test/sass/results/complex.css +0 -86
  45. data/test/sass/results/compressed.css +0 -1
  46. data/test/sass/results/expanded.css +0 -19
  47. data/test/sass/results/filename_fn.css +0 -3
  48. data/test/sass/results/if.css +0 -3
  49. data/test/sass/results/import.css +0 -31
  50. data/test/sass/results/import_charset.css +0 -5
  51. data/test/sass/results/import_charset_ibm866.css +0 -5
  52. data/test/sass/results/import_content.css +0 -1
  53. data/test/sass/results/line_numbers.css +0 -49
  54. data/test/sass/results/mixins.css +0 -95
  55. data/test/sass/results/multiline.css +0 -24
  56. data/test/sass/results/nested.css +0 -22
  57. data/test/sass/results/options.css +0 -1
  58. data/test/sass/results/parent_ref.css +0 -13
  59. data/test/sass/results/script.css +0 -16
  60. data/test/sass/results/scss_import.css +0 -31
  61. data/test/sass/results/scss_importee.css +0 -2
  62. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  63. data/test/sass/results/subdir/subdir.css +0 -3
  64. data/test/sass/results/units.css +0 -11
  65. data/test/sass/results/warn.css +0 -0
  66. data/test/sass/results/warn_imported.css +0 -0
  67. data/test/sass/script_conversion_test.rb +0 -365
  68. data/test/sass/script_test.rb +0 -1427
  69. data/test/sass/scss/css_test.rb +0 -1266
  70. data/test/sass/scss/rx_test.rb +0 -159
  71. data/test/sass/scss/scss_test.rb +0 -4238
  72. data/test/sass/scss/test_helper.rb +0 -37
  73. data/test/sass/source_map_test.rb +0 -1063
  74. data/test/sass/superselector_test.rb +0 -209
  75. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  76. data/test/sass/templates/_double_import_loop2.sass +0 -1
  77. data/test/sass/templates/_filename_fn_import.scss +0 -11
  78. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  79. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  80. data/test/sass/templates/_imported_content.sass +0 -3
  81. data/test/sass/templates/_partial.sass +0 -2
  82. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  83. data/test/sass/templates/alt.sass +0 -16
  84. data/test/sass/templates/basic.sass +0 -23
  85. data/test/sass/templates/bork1.sass +0 -2
  86. data/test/sass/templates/bork2.sass +0 -2
  87. data/test/sass/templates/bork3.sass +0 -2
  88. data/test/sass/templates/bork4.sass +0 -2
  89. data/test/sass/templates/bork5.sass +0 -3
  90. data/test/sass/templates/cached_import_option.scss +0 -3
  91. data/test/sass/templates/compact.sass +0 -17
  92. data/test/sass/templates/complex.sass +0 -305
  93. data/test/sass/templates/compressed.sass +0 -15
  94. data/test/sass/templates/double_import_loop1.sass +0 -1
  95. data/test/sass/templates/expanded.sass +0 -17
  96. data/test/sass/templates/filename_fn.scss +0 -18
  97. data/test/sass/templates/if.sass +0 -11
  98. data/test/sass/templates/import.sass +0 -12
  99. data/test/sass/templates/import_charset.sass +0 -9
  100. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  101. data/test/sass/templates/import_content.sass +0 -4
  102. data/test/sass/templates/importee.less +0 -2
  103. data/test/sass/templates/importee.sass +0 -19
  104. data/test/sass/templates/line_numbers.sass +0 -13
  105. data/test/sass/templates/mixin_bork.sass +0 -5
  106. data/test/sass/templates/mixins.sass +0 -76
  107. data/test/sass/templates/multiline.sass +0 -20
  108. data/test/sass/templates/nested.sass +0 -25
  109. data/test/sass/templates/nested_bork1.sass +0 -2
  110. data/test/sass/templates/nested_bork2.sass +0 -2
  111. data/test/sass/templates/nested_bork3.sass +0 -2
  112. data/test/sass/templates/nested_bork4.sass +0 -2
  113. data/test/sass/templates/nested_import.sass +0 -2
  114. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  115. data/test/sass/templates/options.sass +0 -2
  116. data/test/sass/templates/parent_ref.sass +0 -25
  117. data/test/sass/templates/same_name_different_ext.sass +0 -2
  118. data/test/sass/templates/same_name_different_ext.scss +0 -1
  119. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  120. data/test/sass/templates/script.sass +0 -101
  121. data/test/sass/templates/scss_import.scss +0 -12
  122. data/test/sass/templates/scss_importee.scss +0 -1
  123. data/test/sass/templates/single_import_loop.sass +0 -1
  124. data/test/sass/templates/subdir/import_up1.scss +0 -1
  125. data/test/sass/templates/subdir/import_up2.scss +0 -1
  126. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  127. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  128. data/test/sass/templates/subdir/subdir.sass +0 -6
  129. data/test/sass/templates/units.sass +0 -11
  130. data/test/sass/templates/warn.sass +0 -3
  131. data/test/sass/templates/warn_imported.sass +0 -4
  132. data/test/sass/test_helper.rb +0 -8
  133. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  134. data/test/sass/util/normalized_map_test.rb +0 -50
  135. data/test/sass/util/subset_map_test.rb +0 -90
  136. data/test/sass/util_test.rb +0 -393
  137. data/test/sass/value_helpers_test.rb +0 -178
  138. data/test/test_helper.rb +0 -149
@@ -1,49 +0,0 @@
1
- class MockImporter < Sass::Importers::Base
2
- def initialize(name = "mock")
3
- @name = name
4
- @imports = Hash.new({})
5
- end
6
-
7
- def find_relative(uri, base, options)
8
- nil
9
- end
10
-
11
- def find(uri, options)
12
- contents = @imports[uri][:contents]
13
- return unless contents
14
- options[:syntax] = @imports[uri][:syntax]
15
- options[:filename] = uri
16
- options[:importer] = self
17
- @imports[uri][:engine] = Sass::Engine.new(contents, options)
18
- end
19
-
20
- def mtime(uri, options)
21
- @imports[uri][:mtime]
22
- end
23
-
24
- def key(uri, options)
25
- ["mock", uri]
26
- end
27
-
28
- def to_s
29
- @name
30
- end
31
-
32
- # Methods for testing
33
-
34
- def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10)
35
- @imports[uri] = {
36
- :contents => contents,
37
- :mtime => mtime,
38
- :syntax => syntax
39
- }
40
- end
41
-
42
- def touch(uri)
43
- @imports[uri][:mtime] = Time.now
44
- end
45
-
46
- def engine(uri)
47
- @imports[uri][:engine]
48
- end
49
- end
@@ -1,9 +0,0 @@
1
- body { font: Arial; background: blue; }
2
-
3
- #page { width: 700px; height: 100; }
4
- #page #header { height: 300px; }
5
- #page #header h1 { font-size: 50px; color: blue; }
6
-
7
- #content.user.show #container.top #column.left { width: 100px; }
8
- #content.user.show #container.top #column.right { width: 600px; }
9
- #content.user.show #container.bottom { background: brown; }
@@ -1,26 +0,0 @@
1
- /* line 3, ../more_templates/more1.sass */
2
- body {
3
- font: Arial;
4
- background: blue; }
5
-
6
- /* line 7, ../more_templates/more1.sass */
7
- #page {
8
- width: 700px;
9
- height: 100; }
10
- /* line 10, ../more_templates/more1.sass */
11
- #page #header {
12
- height: 300px; }
13
- /* line 12, ../more_templates/more1.sass */
14
- #page #header h1 {
15
- font-size: 50px;
16
- color: blue; }
17
-
18
- /* line 18, ../more_templates/more1.sass */
19
- #content.user.show #container.top #column.left {
20
- width: 100px; }
21
- /* line 20, ../more_templates/more1.sass */
22
- #content.user.show #container.top #column.right {
23
- width: 600px; }
24
- /* line 22, ../more_templates/more1.sass */
25
- #content.user.show #container.bottom {
26
- background: brown; }
@@ -1,29 +0,0 @@
1
- @import url(basic.css);
2
- @import url(../results/complex.css);
3
- imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
4
-
5
- body { font: Arial; background: blue; }
6
-
7
- #page { width: 700px; height: 100; }
8
- #page #header { height: 300px; }
9
- #page #header h1 { font-size: 50px; color: blue; }
10
-
11
- #content.user.show #container.top #column.left { width: 100px; }
12
- #content.user.show #container.top #column.right { width: 600px; }
13
- #content.user.show #container.bottom { background: brown; }
14
-
15
- midrule { inthe: middle; }
16
-
17
- body { font: Arial; background: blue; }
18
-
19
- #page { width: 700px; height: 100; }
20
- #page #header { height: 300px; }
21
- #page #header h1 { font-size: 50px; color: blue; }
22
-
23
- #content.user.show #container.top #column.left { width: 100px; }
24
- #content.user.show #container.top #column.right { width: 600px; }
25
- #content.user.show #container.bottom { background: brown; }
26
-
27
- #foo { background-color: #baf; }
28
-
29
- nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
@@ -1,2 +0,0 @@
1
- #foo
2
- :background-color #baf
@@ -1,23 +0,0 @@
1
-
2
-
3
- body
4
- font: Arial
5
- background: blue
6
-
7
- #page
8
- width: 700px
9
- height: 100
10
- #header
11
- height: 300px
12
- h1
13
- font-size: 50px
14
- color: blue
15
-
16
- #content.user.show
17
- #container.top
18
- #column.left
19
- width: 100px
20
- #column.right
21
- width: 600px
22
- #container.bottom
23
- background: brown
@@ -1,11 +0,0 @@
1
- $preconst: hello
2
-
3
- =premixin
4
- pre-mixin: here
5
-
6
- @import importee, basic, basic.css, ../results/complex.css, more_partial
7
-
8
- nonimported
9
- myconst: $preconst
10
- otherconst: $postconst
11
- +postmixin
@@ -1,552 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
- require File.dirname(__FILE__) + '/test_helper'
3
- require 'sass/plugin'
4
- require 'fileutils'
5
-
6
- module Sass::Script::Functions
7
- def filename
8
- filename = options[:filename].gsub(%r{.*((/[^/]+){4})}, '\1')
9
- Sass::Script::Value::String.new(filename)
10
- end
11
-
12
- def whatever
13
- custom = options[:custom]
14
- whatever = custom && custom[:whatever]
15
- Sass::Script::Value::String.new(whatever || "incorrect")
16
- end
17
- end
18
-
19
- class SassPluginTest < MiniTest::Test
20
- @@templates = %w{
21
- complex script parent_ref import scss_import alt
22
- subdir/subdir subdir/nested_subdir/nested_subdir
23
- options import_content filename_fn import_charset
24
- import_charset_ibm866
25
- }
26
-
27
- @@cache_store = Sass::CacheStores::Memory.new
28
-
29
- def setup
30
- Sass::Util.retry_on_windows {FileUtils.mkdir_p tempfile_loc}
31
- Sass::Util.retry_on_windows {FileUtils.mkdir_p tempfile_loc(nil,"more_")}
32
- set_plugin_opts
33
- check_for_updates!
34
- reset_mtimes
35
- end
36
-
37
- def teardown
38
- clean_up_sassc
39
- Sass::Plugin.reset!
40
- Sass::Util.retry_on_windows {FileUtils.rm_r tempfile_loc}
41
- Sass::Util.retry_on_windows {FileUtils.rm_r tempfile_loc(nil,"more_")}
42
- end
43
-
44
- @@templates.each do |name|
45
- define_method("test_template_renders_correctly (#{name})") do
46
- silence_warnings {assert_renders_correctly(name)}
47
- end
48
- end
49
-
50
- def test_no_update
51
- File.delete(tempfile_loc('basic'))
52
- assert_needs_update 'basic'
53
- check_for_updates!
54
- assert_stylesheet_updated 'basic'
55
- end
56
-
57
- def test_update_needed_when_modified
58
- touch 'basic'
59
- assert_needs_update 'basic'
60
- check_for_updates!
61
- assert_stylesheet_updated 'basic'
62
- end
63
-
64
- def test_update_needed_when_dependency_modified
65
- touch 'basic'
66
- assert_needs_update 'import'
67
- check_for_updates!
68
- assert_stylesheet_updated 'basic'
69
- assert_stylesheet_updated 'import'
70
- end
71
-
72
- def test_update_needed_when_scss_dependency_modified
73
- touch 'scss_importee'
74
- assert_needs_update 'import'
75
- check_for_updates!
76
- assert_stylesheet_updated 'scss_importee'
77
- assert_stylesheet_updated 'import'
78
- end
79
-
80
- def test_scss_update_needed_when_dependency_modified
81
- touch 'basic'
82
- assert_needs_update 'scss_import'
83
- check_for_updates!
84
- assert_stylesheet_updated 'basic'
85
- assert_stylesheet_updated 'scss_import'
86
- end
87
-
88
- def test_update_needed_when_nested_import_dependency_modified
89
- touch 'basic'
90
- assert_needs_update 'nested_import'
91
- check_for_updates!
92
- assert_stylesheet_updated 'basic'
93
- assert_stylesheet_updated 'scss_import'
94
- end
95
-
96
- def test_no_updates_when_always_check_and_always_update_both_false
97
- Sass::Plugin.options[:always_update] = false
98
- Sass::Plugin.options[:always_check] = false
99
-
100
- touch 'basic'
101
- assert_needs_update 'basic'
102
- check_for_updates!
103
-
104
- # Check it's still stale
105
- assert_needs_update 'basic'
106
- end
107
-
108
- def test_full_exception_handling
109
- File.delete(tempfile_loc('bork1'))
110
- check_for_updates!
111
- File.open(tempfile_loc('bork1')) do |file|
112
- assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
113
- /*
114
- Error: Undefined variable: "$bork".
115
- on line 2 of #{template_loc('bork1')}
116
-
117
- 1: bork
118
- 2: bork: $bork
119
- CSS
120
- end
121
- File.delete(tempfile_loc('bork1'))
122
- end
123
-
124
- def test_full_exception_with_block_comment
125
- File.delete(tempfile_loc('bork5'))
126
- check_for_updates!
127
- File.open(tempfile_loc('bork5')) do |file|
128
- assert_equal(<<CSS.strip, file.read.split("\n")[0...7].join("\n"))
129
- /*
130
- Error: Undefined variable: "$bork".
131
- on line 3 of #{template_loc('bork5')}
132
-
133
- 1: bork
134
- 2: /* foo *\\/
135
- 3: bork: $bork
136
- CSS
137
- end
138
- File.delete(tempfile_loc('bork1'))
139
- end
140
-
141
- def test_single_level_import_loop
142
- File.delete(tempfile_loc('single_import_loop'))
143
- check_for_updates!
144
- File.open(tempfile_loc('single_import_loop')) do |file|
145
- assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
146
- /*
147
- Error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
148
- CSS
149
- end
150
- end
151
-
152
- def test_double_level_import_loop
153
- File.delete(tempfile_loc('double_import_loop1'))
154
- check_for_updates!
155
- File.open(tempfile_loc('double_import_loop1')) do |file|
156
- assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
157
- /*
158
- Error: An @import loop has been found:
159
- #{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
160
- #{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
161
- CSS
162
- end
163
- end
164
-
165
- def test_import_name_cleanup
166
- File.delete(tempfile_loc('subdir/import_up1'))
167
- check_for_updates!
168
- File.open(tempfile_loc('subdir/import_up1')) do |file|
169
- assert_equal(<<CSS.strip, file.read.split("\n")[0...5].join("\n"))
170
- /*
171
- Error: File to import not found or unreadable: ../subdir/import_up3.scss.
172
- Load path: #{template_loc}
173
- on line 1 of #{template_loc 'subdir/import_up2'}
174
- from line 1 of #{template_loc 'subdir/import_up1'}
175
- CSS
176
- end
177
- end
178
-
179
- def test_nonfull_exception_handling
180
- old_full_exception = Sass::Plugin.options[:full_exception]
181
- Sass::Plugin.options[:full_exception] = false
182
-
183
- File.delete(tempfile_loc('bork1'))
184
- assert_raises(Sass::SyntaxError) {check_for_updates!}
185
- ensure
186
- Sass::Plugin.options[:full_exception] = old_full_exception
187
- end
188
-
189
- def test_two_template_directories
190
- set_plugin_opts :template_location => {
191
- template_loc => tempfile_loc,
192
- template_loc(nil,'more_') => tempfile_loc(nil,'more_')
193
- }
194
- check_for_updates!
195
- ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
196
- end
197
-
198
- def test_two_template_directories_with_line_annotations
199
- set_plugin_opts :line_comments => true,
200
- :style => :nested,
201
- :template_location => {
202
- template_loc => tempfile_loc,
203
- template_loc(nil,'more_') => tempfile_loc(nil,'more_')
204
- }
205
- check_for_updates!
206
- assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
207
- end
208
-
209
- def test_doesnt_render_partials
210
- assert !File.exist?(tempfile_loc('_partial'))
211
- end
212
-
213
- def test_template_location_array
214
- assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
215
- end
216
-
217
- def test_add_template_location
218
- Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
219
- assert_equal(
220
- [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
221
- Sass::Plugin.template_location_array)
222
-
223
- touch 'more1', 'more_'
224
- touch 'basic'
225
- assert_needs_update "more1", "more_"
226
- assert_needs_update "basic"
227
- check_for_updates!
228
- assert_doesnt_need_update "more1", "more_"
229
- assert_doesnt_need_update "basic"
230
- end
231
-
232
- def test_remove_template_location
233
- Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
234
- Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
235
- assert_equal(
236
- [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
237
- Sass::Plugin.template_location_array)
238
-
239
- touch 'more1', 'more_'
240
- touch 'basic'
241
- assert_needs_update "more1", "more_"
242
- assert_needs_update "basic"
243
- check_for_updates!
244
- assert_doesnt_need_update "more1", "more_"
245
- assert_needs_update "basic"
246
- end
247
-
248
- def test_import_same_name
249
- assert_warning <<WARNING do
250
- WARNING: In #{template_loc}:
251
- There are multiple files that match the name "same_name_different_partiality.scss":
252
- _same_name_different_partiality.scss
253
- same_name_different_partiality.scss
254
- WARNING
255
- touch "_same_name_different_partiality"
256
- assert_needs_update "same_name_different_partiality"
257
- end
258
- end
259
-
260
- # Callbacks
261
-
262
- def test_updated_stylesheet_callback_for_updated_template
263
- Sass::Plugin.options[:always_update] = false
264
- touch 'basic'
265
- assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
266
- assert_callbacks(
267
- [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
268
- [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
269
- end
270
- end
271
-
272
- def test_updated_stylesheet_callback_for_fresh_template
273
- Sass::Plugin.options[:always_update] = false
274
- assert_no_callback :updated_stylesheet
275
- end
276
-
277
- def test_updated_stylesheet_callback_for_error_template
278
- Sass::Plugin.options[:always_update] = false
279
- touch 'bork1'
280
- assert_no_callback :updated_stylesheet
281
- end
282
-
283
- def test_not_updating_stylesheet_callback_for_fresh_template
284
- Sass::Plugin.options[:always_update] = false
285
- assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
286
- end
287
-
288
- def test_not_updating_stylesheet_callback_for_updated_template
289
- Sass::Plugin.options[:always_update] = false
290
- assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
291
- assert_no_callbacks(
292
- [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
293
- [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
294
- end
295
- end
296
-
297
- def test_not_updating_stylesheet_callback_with_never_update
298
- Sass::Plugin.options[:never_update] = true
299
- assert_no_callback :not_updating_stylesheet
300
- end
301
-
302
- def test_not_updating_stylesheet_callback_for_partial
303
- Sass::Plugin.options[:always_update] = false
304
- assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
305
- end
306
-
307
- def test_not_updating_stylesheet_callback_for_error
308
- Sass::Plugin.options[:always_update] = false
309
- touch 'bork1'
310
- assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
311
- end
312
-
313
- def test_compilation_error_callback
314
- Sass::Plugin.options[:always_update] = false
315
- touch 'bork1'
316
- assert_callback(:compilation_error,
317
- lambda {|e| e.message == 'Undefined variable: "$bork".'},
318
- template_loc("bork1"), tempfile_loc("bork1"))
319
- end
320
-
321
- def test_compilation_error_callback_for_file_access
322
- Sass::Plugin.options[:always_update] = false
323
- assert_callback(:compilation_error,
324
- lambda {|e| e.is_a?(Errno::ENOENT)},
325
- template_loc("nonexistent"), tempfile_loc("nonexistent")) do
326
- Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
327
- end
328
- end
329
-
330
- def test_creating_directory_callback
331
- Sass::Plugin.options[:always_update] = false
332
- dir = File.join(tempfile_loc, "subdir", "nested_subdir")
333
- FileUtils.rm_r dir
334
- assert_callback :creating_directory, dir
335
- end
336
-
337
- ## Regression
338
-
339
- def test_cached_dependencies_update
340
- FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
341
- set_plugin_opts :load_paths => [template_loc(nil, "more_")]
342
-
343
- touch 'basic', 'more_'
344
- assert_needs_update "import"
345
- check_for_updates!
346
- assert_renders_correctly("import")
347
- ensure
348
- FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
349
- end
350
-
351
- def test_cached_relative_import
352
- old_always_update = Sass::Plugin.options[:always_update]
353
- Sass::Plugin.options[:always_update] = true
354
- check_for_updates!
355
- assert_renders_correctly('subdir/subdir')
356
- ensure
357
- Sass::Plugin.options[:always_update] = old_always_update
358
- end
359
-
360
- def test_cached_if
361
- set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
362
- check_for_updates!
363
- assert_renders_correctly 'if'
364
- check_for_updates!
365
- assert_renders_correctly 'if'
366
- ensure
367
- set_plugin_opts
368
- end
369
-
370
- def test_cached_import_option
371
- set_plugin_opts :custom => {:whatever => "correct"}
372
- check_for_updates!
373
- assert_renders_correctly "cached_import_option"
374
-
375
- @@cache_store.reset!
376
- set_plugin_opts :custom => nil, :always_update => false
377
- check_for_updates!
378
- assert_renders_correctly "cached_import_option"
379
-
380
- set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
381
- check_for_updates!
382
- assert_renders_correctly "cached_import_option"
383
- ensure
384
- set_plugin_opts :custom => nil
385
- end
386
-
387
- private
388
-
389
- def assert_renders_correctly(*arguments)
390
- options = arguments.last.is_a?(Hash) ? arguments.pop : {}
391
- prefix = options[:prefix]
392
- result_name = arguments.shift
393
- tempfile_name = arguments.shift || result_name
394
-
395
- expected_str = File.read(result_loc(result_name, prefix))
396
- actual_str = File.read(tempfile_loc(tempfile_name, prefix))
397
- expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
398
- actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
399
- expected_lines = expected_str.split("\n")
400
- actual_lines = actual_str.split("\n")
401
-
402
- if actual_lines.first == "/*" && expected_lines.first != "/*"
403
- assert(false, actual_lines[0..actual_lines.each_with_index.find {|l, i| l == "*/"}.last].join("\n"))
404
- end
405
-
406
- expected_lines.zip(actual_lines).each_with_index do |pair, line|
407
- message = "template: #{result_name}\nline: #{line + 1}"
408
- assert_equal(pair.first, pair.last, message)
409
- end
410
- if expected_lines.size < actual_lines.size
411
- assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
412
- end
413
- end
414
-
415
- def assert_stylesheet_updated(name)
416
- assert_doesnt_need_update name
417
-
418
- # Make sure it isn't an exception
419
- expected_lines = File.read(result_loc(name)).split("\n")
420
- actual_lines = File.read(tempfile_loc(name)).split("\n")
421
- if actual_lines.first == "/*" && expected_lines.first != "/*"
422
- assert(false, actual_lines[0..actual_lines.each_with_index.find {|l, i| l == "*/"}.last].join("\n"))
423
- end
424
- end
425
-
426
- def assert_callback(name, *expected_args)
427
- run = false
428
- received_args = nil
429
- Sass::Plugin.send("on_#{name}") do |*args|
430
- received_args = args
431
- run ||= expected_args.zip(received_args).all? do |ea, ra|
432
- ea.respond_to?(:call) ? ea.call(ra) : ea == ra
433
- end
434
- end
435
-
436
- if block_given?
437
- Sass::Util.silence_sass_warnings {yield}
438
- else
439
- check_for_updates!
440
- end
441
-
442
- assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}\nHowever, it got:\n #{received_args.inspect}"
443
- end
444
-
445
- def assert_no_callback(name, *unexpected_args)
446
- Sass::Plugin.send("on_#{name}") do |*a|
447
- next unless unexpected_args.empty? || a == unexpected_args
448
-
449
- msg = "Expected #{name} callback not to be run"
450
- if !unexpected_args.empty?
451
- msg << " with arguments #{unexpected_args.inspect}"
452
- elsif !a.empty?
453
- msg << ",\n was run with arguments #{a.inspect}"
454
- end
455
-
456
- flunk msg
457
- end
458
-
459
- if block_given?
460
- yield
461
- else
462
- check_for_updates!
463
- end
464
- end
465
-
466
- def assert_callbacks(*args)
467
- return check_for_updates! if args.empty?
468
- assert_callback(*args.pop) {assert_callbacks(*args)}
469
- end
470
-
471
- def assert_no_callbacks(*args)
472
- return check_for_updates! if args.empty?
473
- assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
474
- end
475
-
476
- def check_for_updates!
477
- Sass::Util.silence_sass_warnings do
478
- Sass::Plugin.check_for_updates
479
- end
480
- end
481
-
482
- def assert_needs_update(*args)
483
- assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
484
- "Expected #{template_loc(*args)} to need an update.")
485
- end
486
-
487
- def assert_doesnt_need_update(*args)
488
- assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
489
- "Expected #{template_loc(*args)} not to need an update.")
490
- end
491
-
492
- def touch(*args)
493
- FileUtils.touch(template_loc(*args))
494
- end
495
-
496
- def reset_mtimes
497
- Sass::Plugin::StalenessChecker.dependencies_cache = {}
498
- atime = Time.now
499
- mtime = Time.now - 5
500
- Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each do |f|
501
- Sass::Util.retry_on_windows {File.utime(atime, mtime, f)}
502
- end
503
- end
504
-
505
- def template_loc(name = nil, prefix = nil)
506
- if name
507
- scss = absolutize "#{prefix}templates/#{name}.scss"
508
- File.exist?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
509
- else
510
- absolutize "#{prefix}templates"
511
- end
512
- end
513
-
514
- def tempfile_loc(name = nil, prefix = nil)
515
- if name
516
- absolutize "#{prefix}tmp/#{name}.css"
517
- else
518
- absolutize "#{prefix}tmp"
519
- end
520
- end
521
-
522
- def result_loc(name = nil, prefix = nil)
523
- if name
524
- absolutize "#{prefix}results/#{name}.css"
525
- else
526
- absolutize "#{prefix}results"
527
- end
528
- end
529
-
530
- def set_plugin_opts(overrides = {})
531
- Sass::Plugin.options.merge!(
532
- :template_location => template_loc,
533
- :css_location => tempfile_loc,
534
- :style => :compact,
535
- :always_update => true,
536
- :never_update => false,
537
- :full_exception => true,
538
- :cache_store => @@cache_store,
539
- :sourcemap => :none
540
- )
541
- Sass::Plugin.options.merge!(overrides)
542
- end
543
- end
544
-
545
- class Sass::Engine
546
- alias_method :old_render, :render
547
-
548
- def render
549
- raise "bork bork bork!" if @template[0] == "{bork now!}"
550
- old_render
551
- end
552
- end