sass 3.6.0 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
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,37 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../test_helper'
2
- require 'sass/engine'
3
-
4
- module ScssTestHelper
5
- def assert_parses(scss)
6
- assert_equal scss.rstrip, render(scss).rstrip
7
- end
8
-
9
- def assert_not_parses(expected, scss)
10
- raise "Template must include <err> where an error is expected" unless scss.include?("<err>")
11
-
12
- after, was = scss.split("<err>")
13
- line = after.count("\n") + 1
14
-
15
- after.gsub!(/\s*\n\s*$/, '')
16
- after.gsub!(/.*\n/, '')
17
- after = "..." + after[-15..-1] if after.size > 18
18
-
19
- was.gsub!(/^\s*\n\s*/, '')
20
- was.gsub!(/\n.*/, '')
21
- was = was[0...15] + "..." if was.size > 18
22
-
23
- to_render = scss.sub("<err>", "")
24
- render(to_render)
25
- assert(false, "Expected syntax error for:\n#{to_render}\n")
26
- rescue Sass::SyntaxError => err
27
- assert_equal("Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"",
28
- err.message)
29
- assert_equal line, err.sass_line
30
- end
31
-
32
- def render(scss, options = {})
33
- options[:syntax] ||= :scss
34
- munge_filename options
35
- Sass::Engine.new(scss, options).render
36
- end
37
- end
@@ -1,1063 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require File.dirname(__FILE__) + '/test_helper'
4
-
5
- class SourcemapTest < MiniTest::Test
6
- def test_to_json_requires_args
7
- _, sourcemap = render_with_sourcemap('')
8
- assert_raises(ArgumentError) {sourcemap.to_json({})}
9
- assert_raises(ArgumentError) {sourcemap.to_json({:css_path => 'foo'})}
10
- assert_raises(ArgumentError) {sourcemap.to_json({:sourcemap_path => 'foo'})}
11
- end
12
-
13
- def test_simple_mapping_scss
14
- assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON
15
- a {
16
- foo: bar;
17
- /* SOME COMMENT */
18
- font-size: 12px;
19
- }
20
- SCSS
21
- a {
22
- foo: bar;
23
- /* SOME COMMENT */
24
- font-size: 12px; }
25
-
26
- /*# sourceMappingURL=test.css.map */
27
- CSS
28
- {
29
- "version": 3,
30
- "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;EACV,kBAAkB;EAChB,SAAS,EAAE,IAAI",
31
- "sources": ["test_simple_mapping_scss_inline.scss"],
32
- "names": [],
33
- "file": "test.css"
34
- }
35
- JSON
36
- end
37
-
38
- def test_simple_mapping_sass
39
- silence_warnings {assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, :syntax => :sass}
40
- a
41
- foo: bar
42
- /* SOME COMMENT */
43
- :font-size 12px
44
- SASS
45
- a {
46
- foo: bar;
47
- /* SOME COMMENT */
48
- font-size: 12px; }
49
-
50
- /*# sourceMappingURL=test.css.map */
51
- CSS
52
- {
53
- "version": 3,
54
- "mappings": "AAAA,CAAC;EACC,GAAG,EAAE,GAAG;;EAEP,SAAS,EAAC,IAAI",
55
- "sources": ["test_simple_mapping_sass_inline.sass"],
56
- "names": [],
57
- "file": "test.css"
58
- }
59
- JSON
60
- end
61
-
62
- def test_simple_mapping_with_file_uris
63
- uri = Sass::Util.file_uri_from_path(File.absolute_path(filename_for_test(:scss)))
64
- assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON, :sourcemap => :file
65
- a {
66
- foo: bar;
67
- /* SOME COMMENT */
68
- font-size: 12px;
69
- }
70
- SCSS
71
- a {
72
- foo: bar;
73
- /* SOME COMMENT */
74
- font-size: 12px; }
75
-
76
- /*# sourceMappingURL=test.css.map */
77
- CSS
78
- {
79
- "version": 3,
80
- "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;EACV,kBAAkB;EAChB,SAAS,EAAE,IAAI",
81
- "sources": ["#{uri}"],
82
- "names": [],
83
- "file": "test.css"
84
- }
85
- JSON
86
- end
87
-
88
- def test_mapping_with_directory_scss
89
- options = {:filename => "scss/style.scss", :output => "css/style.css"}
90
- assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON, options
91
- a {
92
- foo: bar;
93
- /* SOME COMMENT */
94
- font-size: 12px;
95
- }
96
- SCSS
97
- a {
98
- foo: bar;
99
- /* SOME COMMENT */
100
- font-size: 12px; }
101
-
102
- /*# sourceMappingURL=style.css.map */
103
- CSS
104
- {
105
- "version": 3,
106
- "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;EACV,kBAAkB;EAChB,SAAS,EAAE,IAAI",
107
- "sources": ["../scss/style.scss"],
108
- "names": [],
109
- "file": "style.css"
110
- }
111
- JSON
112
- end
113
-
114
- def test_mapping_with_directory_sass
115
- options = {:filename => "sass/style.sass", :output => "css/style.css", :syntax => :sass}
116
- silence_warnings {assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, options}
117
- a
118
- foo: bar
119
- /* SOME COMMENT */
120
- :font-size 12px
121
- SASS
122
- a {
123
- foo: bar;
124
- /* SOME COMMENT */
125
- font-size: 12px; }
126
-
127
- /*# sourceMappingURL=style.css.map */
128
- CSS
129
- {
130
- "version": 3,
131
- "mappings": "AAAA,CAAC;EACC,GAAG,EAAE,GAAG;;EAEP,SAAS,EAAC,IAAI",
132
- "sources": ["../sass/style.sass"],
133
- "names": [],
134
- "file": "style.css"
135
- }
136
- JSON
137
- end
138
-
139
- def test_simple_charset_mapping_scss
140
- assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON
141
- a {
142
- fóó: bár;
143
- }
144
- SCSS
145
- @charset "UTF-8";
146
- a {
147
- fóó: bár; }
148
-
149
- /*# sourceMappingURL=test.css.map */
150
- CSS
151
- {
152
- "version": 3,
153
- "mappings": ";AAAA,CAAE;EACA,GAAG,EAAE,GAAG",
154
- "sources": ["test_simple_charset_mapping_scss_inline.scss"],
155
- "names": [],
156
- "file": "test.css"
157
- }
158
- JSON
159
- end
160
-
161
- def test_simple_charset_mapping_sass
162
- assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, :syntax => :sass
163
- a
164
- fóó: bár
165
- SASS
166
- @charset "UTF-8";
167
- a {
168
- fóó: bár; }
169
-
170
- /*# sourceMappingURL=test.css.map */
171
- CSS
172
- {
173
- "version": 3,
174
- "mappings": ";AAAA,CAAC;EACC,GAAG,EAAE,GAAG",
175
- "sources": ["test_simple_charset_mapping_sass_inline.sass"],
176
- "names": [],
177
- "file": "test.css"
178
- }
179
- JSON
180
- end
181
-
182
- def test_different_charset_than_encoding_scss
183
- assert_parses_with_sourcemap(<<SCSS.force_encoding("IBM866"), <<CSS, <<JSON)
184
- @charset "IBM866";
185
- f\x86\x86 {
186
- \x86: b;
187
- }
188
- SCSS
189
- @charset "UTF-8";
190
- fЖЖ {
191
- Ж: b; }
192
-
193
- /*# sourceMappingURL=test.css.map */
194
- CSS
195
- {
196
- "version": 3,
197
- "mappings": ";AACA,GAAI;EACF,CAAC,EAAE,CAAC",
198
- "sources": ["test_different_charset_than_encoding_scss_inline.scss"],
199
- "names": [],
200
- "file": "test.css"
201
- }
202
- JSON
203
- end
204
-
205
- def test_different_charset_than_encoding_sass
206
- assert_parses_with_sourcemap(<<SASS.force_encoding("IBM866"), <<CSS, <<JSON, :syntax => :sass)
207
- @charset "IBM866"
208
- f\x86\x86
209
- \x86: b
210
- SASS
211
- @charset "UTF-8";
212
- fЖЖ {
213
- Ж: b; }
214
-
215
- /*# sourceMappingURL=test.css.map */
216
- CSS
217
- {
218
- "version": 3,
219
- "mappings": ";AACA,GAAG;EACD,CAAC,EAAE,CAAC",
220
- "sources": ["test_different_charset_than_encoding_sass_inline.sass"],
221
- "names": [],
222
- "file": "test.css"
223
- }
224
- JSON
225
- end
226
-
227
- def test_import_sourcemap_scss
228
- assert_parses_with_mapping <<'SCSS', <<'CSS'
229
- @import {{1}}url(foo){{/1}},{{2}}url(moo) {{/2}}, {{3}}url(bar) {{/3}};
230
- @import {{4}}url(baz) screen print{{/4}};
231
- SCSS
232
- {{1}}@import url(foo){{/1}};
233
- {{2}}@import url(moo){{/2}};
234
- {{3}}@import url(bar){{/3}};
235
- {{4}}@import url(baz) screen print{{/4}};
236
-
237
- /*# sourceMappingURL=test.css.map */
238
- CSS
239
- end
240
-
241
- def test_import_sourcemap_sass
242
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
243
- @import {{1}}foo.css{{/1}},{{2}}moo.css{{/2}}, {{3}}bar.css{{/3}}
244
- @import {{4}}url(baz.css){{/4}}
245
- @import {{5}}url(qux.css) screen print{{/5}}
246
- SASS
247
- {{1}}@import url(foo.css){{/1}};
248
- {{2}}@import url(moo.css){{/2}};
249
- {{3}}@import url(bar.css){{/3}};
250
- {{4}}@import url(baz.css){{/4}};
251
- {{5}}@import url(qux.css) screen print{{/5}};
252
-
253
- /*# sourceMappingURL=test.css.map */
254
- CSS
255
- end
256
-
257
- def test_media_sourcemap_scss
258
- assert_parses_with_mapping <<'SCSS', <<'CSS'
259
- {{1}}@media screen, tv {{/1}}{
260
- {{2}}body {{/2}}{
261
- {{3}}max-width{{/3}}: {{4}}1070px{{/4}};
262
- }
263
- }
264
- SCSS
265
- {{1}}@media screen, tv{{/1}} {
266
- {{2}}body{{/2}} {
267
- {{3}}max-width{{/3}}: {{4}}1070px{{/4}}; } }
268
-
269
- /*# sourceMappingURL=test.css.map */
270
- CSS
271
- end
272
-
273
- def test_media_sourcemap_sass
274
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
275
- {{1}}@media screen, tv{{/1}}
276
- {{2}}body{{/2}}
277
- {{3}}max-width{{/3}}: {{4}}1070px{{/4}}
278
- SASS
279
- {{1}}@media screen, tv{{/1}} {
280
- {{2}}body{{/2}} {
281
- {{3}}max-width{{/3}}: {{4}}1070px{{/4}}; } }
282
-
283
- /*# sourceMappingURL=test.css.map */
284
- CSS
285
- end
286
-
287
- def test_interpolation_and_vars_sourcemap_scss
288
- assert_parses_with_mapping <<'SCSS', <<'CSS'
289
- $te: "te";
290
- $teal: {{5}}teal{{/5}};
291
- {{1}}p {{/1}}{
292
- {{2}}con#{$te}nt{{/2}}: {{3}}"I a#{$te} #{5 + 10} pies!"{{/3}};
293
- {{4}}color{{/4}}: $teal;
294
- }
295
-
296
- $name: foo;
297
- $attr: border;
298
- {{6}}p.#{$name} {{/6}}{
299
- {{7}}#{$attr}-color{{/7}}: {{8}}blue{{/8}};
300
- $font-size: 12px;
301
- $line-height: 30px;
302
- {{9}}font{{/9}}: {{10}}#{$font-size}/#{$line-height}{{/10}};
303
- }
304
- SCSS
305
- {{1}}p{{/1}} {
306
- {{2}}content{{/2}}: {{3}}"I ate 15 pies!"{{/3}};
307
- {{4}}color{{/4}}: {{5}}teal{{/5}}; }
308
-
309
- {{6}}p.foo{{/6}} {
310
- {{7}}border-color{{/7}}: {{8}}blue{{/8}};
311
- {{9}}font{{/9}}: {{10}}12px/30px{{/10}}; }
312
-
313
- /*# sourceMappingURL=test.css.map */
314
- CSS
315
- end
316
-
317
- def test_interpolation_and_vars_sourcemap_sass
318
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
319
- $te: "te"
320
- $teal: {{5}}teal{{/5}}
321
- {{1}}p{{/1}}
322
- {{2}}con#{$te}nt{{/2}}: {{3}}"I a#{$te} #{5 + 10} pies!"{{/3}}
323
- {{4}}color{{/4}}: $teal
324
-
325
- $name: foo
326
- $attr: border
327
- {{6}}p.#{$name}{{/6}}
328
- {{7}}#{$attr}-color{{/7}}: {{8}}blue{{/8}}
329
- $font-size: 12px
330
- $line-height: 30px
331
- {{9}}font{{/9}}: {{10}}#{$font-size}/#{$line-height}{{/10}}
332
- SASS
333
- {{1}}p{{/1}} {
334
- {{2}}content{{/2}}: {{3}}"I ate 15 pies!"{{/3}};
335
- {{4}}color{{/4}}: {{5}}teal{{/5}}; }
336
-
337
- {{6}}p.foo{{/6}} {
338
- {{7}}border-color{{/7}}: {{8}}blue{{/8}};
339
- {{9}}font{{/9}}: {{10}}12px/30px{{/10}}; }
340
-
341
- /*# sourceMappingURL=test.css.map */
342
- CSS
343
- end
344
-
345
- def test_selectors_properties_sourcemap_scss
346
- assert_parses_with_mapping <<'SCSS', <<'CSS'
347
- $width: 2px;
348
- $translucent-red: rgba(255, 0, 0, 0.5);
349
- {{1}}a {{/1}}{
350
- {{9}}.special {{/9}}{
351
- {{10}}color{{/10}}: {{11}}red{{/11}};
352
- {{12}}&:hover {{/12}}{
353
- {{13}}foo{{/13}}: {{14}}bar{{/14}};
354
- {{15}}cursor{{/15}}: {{16}}e + -resize{{/16}};
355
- {{17}}color{{/17}}: {{18}}opacify($translucent-red, 0.3){{/18}};
356
- }
357
- {{19}}&:after {{/19}}{
358
- {{20}}content{{/20}}: {{21}}"I ate #{5 + 10} pies #{$width} thick!"{{/21}};
359
- }
360
- }
361
- {{22}}&:active {{/22}}{
362
- {{23}}border{{/23}}: {{24}}$width solid black{{/24}};
363
- }
364
- {{2}}/* SOME COMMENT */{{/2}}
365
- {{3}}font{{/3}}: {{4}}2px/3px {{/4}}{
366
- {{5}}family{{/5}}: {{6}}fantasy{{/6}};
367
- {{7}}size{{/7}}: {{8}}1em + (2em * 3){{/8}};
368
- }
369
- }
370
- SCSS
371
- {{1}}a{{/1}} {
372
- {{2}}/* SOME COMMENT */{{/2}}
373
- {{3}}font{{/3}}: {{4}}2px/3px{{/4}};
374
- {{5}}font-family{{/5}}: {{6}}fantasy{{/6}};
375
- {{7}}font-size{{/7}}: {{8}}7em{{/8}}; }
376
- {{9}}a .special{{/9}} {
377
- {{10}}color{{/10}}: {{11}}red{{/11}}; }
378
- {{12}}a .special:hover{{/12}} {
379
- {{13}}foo{{/13}}: {{14}}bar{{/14}};
380
- {{15}}cursor{{/15}}: {{16}}e-resize{{/16}};
381
- {{17}}color{{/17}}: {{18}}rgba(255, 0, 0, 0.8){{/18}}; }
382
- {{19}}a .special:after{{/19}} {
383
- {{20}}content{{/20}}: {{21}}"I ate 15 pies 2px thick!"{{/21}}; }
384
- {{22}}a:active{{/22}} {
385
- {{23}}border{{/23}}: {{24}}2px solid black{{/24}}; }
386
-
387
- /*# sourceMappingURL=test.css.map */
388
- CSS
389
- end
390
-
391
- def test_selectors_properties_sourcemap_sass
392
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
393
- $width: 2px
394
- $translucent-red: rgba(255, 0, 0, 0.5)
395
- {{1}}a{{/1}}
396
- {{9}}.special{{/9}}
397
- {{10}}color{{/10}}: {{11}}red{{/11}}
398
- {{12}}&:hover{{/12}}
399
- {{13}}foo{{/13}}: {{14}}bar{{/14}}
400
- {{15}}cursor{{/15}}: {{16}}e + -resize{{/16}}
401
- {{17}}color{{/17}}: {{18}}opacify($translucent-red, 0.3){{/18}}
402
- {{19}}&:after{{/19}}
403
- {{20}}content{{/20}}: {{21}}"I ate #{5 + 10} pies #{$width} thick!"{{/21}}
404
- {{22}}&:active{{/22}}
405
- {{23}}border{{/23}}: {{24}}$width solid black{{/24}}
406
-
407
- {{2}}/* SOME COMMENT */{{/2}}
408
- {{3}}font{{/3}}: {{4}}2px/3px{{/4}}
409
- {{5}}family{{/5}}: {{6}}fantasy{{/6}}
410
- {{7}}size{{/7}}: {{8}}1em + (2em * 3){{/8}}
411
- SASS
412
- {{1}}a{{/1}} {
413
- {{2}}/* SOME COMMENT */{{/2}}
414
- {{3}}font{{/3}}: {{4}}2px/3px{{/4}};
415
- {{5}}font-family{{/5}}: {{6}}fantasy{{/6}};
416
- {{7}}font-size{{/7}}: {{8}}7em{{/8}}; }
417
- {{9}}a .special{{/9}} {
418
- {{10}}color{{/10}}: {{11}}red{{/11}}; }
419
- {{12}}a .special:hover{{/12}} {
420
- {{13}}foo{{/13}}: {{14}}bar{{/14}};
421
- {{15}}cursor{{/15}}: {{16}}e-resize{{/16}};
422
- {{17}}color{{/17}}: {{18}}rgba(255, 0, 0, 0.8){{/18}}; }
423
- {{19}}a .special:after{{/19}} {
424
- {{20}}content{{/20}}: {{21}}"I ate 15 pies 2px thick!"{{/21}}; }
425
- {{22}}a:active{{/22}} {
426
- {{23}}border{{/23}}: {{24}}2px solid black{{/24}}; }
427
-
428
- /*# sourceMappingURL=test.css.map */
429
- CSS
430
- end
431
-
432
- def test_extend_sourcemap_scss
433
- assert_parses_with_mapping <<'SCSS', <<'CSS'
434
- {{1}}.error {{/1}}{
435
- {{2}}border{{/2}}: {{3}}1px #ff00aa{{/3}};
436
- {{4}}background-color{{/4}}: {{5}}#fdd{{/5}};
437
- }
438
- {{6}}.seriousError {{/6}}{
439
- @extend .error;
440
- {{7}}border-width{{/7}}: {{8}}3px{{/8}};
441
- }
442
- SCSS
443
- {{1}}.error, .seriousError{{/1}} {
444
- {{2}}border{{/2}}: {{3}}1px #ff00aa{{/3}};
445
- {{4}}background-color{{/4}}: {{5}}#fdd{{/5}}; }
446
-
447
- {{6}}.seriousError{{/6}} {
448
- {{7}}border-width{{/7}}: {{8}}3px{{/8}}; }
449
-
450
- /*# sourceMappingURL=test.css.map */
451
- CSS
452
- end
453
-
454
- def test_extend_sourcemap_sass
455
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
456
- {{1}}.error{{/1}}
457
- {{2}}border{{/2}}: {{3}}1px #f00{{/3}}
458
- {{4}}background-color{{/4}}: {{5}}#fdd{{/5}}
459
-
460
- {{6}}.seriousError{{/6}}
461
- @extend .error
462
- {{7}}border-width{{/7}}: {{8}}3px{{/8}}
463
- SASS
464
- {{1}}.error, .seriousError{{/1}} {
465
- {{2}}border{{/2}}: {{3}}1px #f00{{/3}};
466
- {{4}}background-color{{/4}}: {{5}}#fdd{{/5}}; }
467
-
468
- {{6}}.seriousError{{/6}} {
469
- {{7}}border-width{{/7}}: {{8}}3px{{/8}}; }
470
-
471
- /*# sourceMappingURL=test.css.map */
472
- CSS
473
- end
474
-
475
- def test_for_sourcemap_scss
476
- assert_parses_with_mapping <<'SCSS', <<'CSS'
477
- @for $i from 1 through 3 {
478
- {{1}}{{4}}{{7}}.item-#{$i} {{/1}}{{/4}}{{/7}}{ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}; }
479
- }
480
- SCSS
481
- {{1}}.item-1{{/1}} {
482
- {{2}}width{{/2}}: {{3}}2em{{/3}}; }
483
-
484
- {{4}}.item-2{{/4}} {
485
- {{5}}width{{/5}}: {{6}}4em{{/6}}; }
486
-
487
- {{7}}.item-3{{/7}} {
488
- {{8}}width{{/8}}: {{9}}6em{{/9}}; }
489
-
490
- /*# sourceMappingURL=test.css.map */
491
- CSS
492
- end
493
-
494
- def test_for_sourcemap_sass
495
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
496
- @for $i from 1 through 3
497
- {{1}}{{4}}{{7}}.item-#{$i}{{/1}}{{/4}}{{/7}}
498
- {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}
499
- SASS
500
- {{1}}.item-1{{/1}} {
501
- {{2}}width{{/2}}: {{3}}2em{{/3}}; }
502
-
503
- {{4}}.item-2{{/4}} {
504
- {{5}}width{{/5}}: {{6}}4em{{/6}}; }
505
-
506
- {{7}}.item-3{{/7}} {
507
- {{8}}width{{/8}}: {{9}}6em{{/9}}; }
508
-
509
- /*# sourceMappingURL=test.css.map */
510
- CSS
511
- end
512
-
513
- def test_while_sourcemap_scss
514
- assert_parses_with_mapping <<'SCSS', <<'CSS'
515
- $i: 6;
516
- @while $i > 0 {
517
- {{1}}{{4}}{{7}}.item-#{$i} {{/1}}{{/4}}{{/7}}{ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}; }
518
- $i: $i - 2 !global;
519
- }
520
- SCSS
521
- {{1}}.item-6{{/1}} {
522
- {{2}}width{{/2}}: {{3}}12em{{/3}}; }
523
-
524
- {{4}}.item-4{{/4}} {
525
- {{5}}width{{/5}}: {{6}}8em{{/6}}; }
526
-
527
- {{7}}.item-2{{/7}} {
528
- {{8}}width{{/8}}: {{9}}4em{{/9}}; }
529
-
530
- /*# sourceMappingURL=test.css.map */
531
- CSS
532
- end
533
-
534
- def test_while_sourcemap_sass
535
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
536
- $i: 6
537
- @while $i > 0
538
- {{1}}{{4}}{{7}}.item-#{$i}{{/1}}{{/4}}{{/7}}
539
- {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}
540
- $i: $i - 2 !global
541
- SASS
542
- {{1}}.item-6{{/1}} {
543
- {{2}}width{{/2}}: {{3}}12em{{/3}}; }
544
-
545
- {{4}}.item-4{{/4}} {
546
- {{5}}width{{/5}}: {{6}}8em{{/6}}; }
547
-
548
- {{7}}.item-2{{/7}} {
549
- {{8}}width{{/8}}: {{9}}4em{{/9}}; }
550
-
551
- /*# sourceMappingURL=test.css.map */
552
- CSS
553
- end
554
-
555
- def test_each_sourcemap_scss
556
- assert_parses_with_mapping <<'SCSS', <<'CSS'
557
- @each $animal in puma, sea-slug, egret, salamander {
558
- {{1}}{{4}}{{7}}{{10}}.#{$animal}-icon {{/1}}{{/4}}{{/7}}{{/10}}{
559
- {{2}}{{5}}{{8}}{{11}}background-image{{/2}}{{/5}}{{/8}}{{/11}}: {{3}}{{6}}{{9}}{{12}}url('/images/#{$animal}.png'){{/3}}{{/6}}{{/9}}{{/12}};
560
- }
561
- }
562
- SCSS
563
- {{1}}.puma-icon{{/1}} {
564
- {{2}}background-image{{/2}}: {{3}}url("/images/puma.png"){{/3}}; }
565
-
566
- {{4}}.sea-slug-icon{{/4}} {
567
- {{5}}background-image{{/5}}: {{6}}url("/images/sea-slug.png"){{/6}}; }
568
-
569
- {{7}}.egret-icon{{/7}} {
570
- {{8}}background-image{{/8}}: {{9}}url("/images/egret.png"){{/9}}; }
571
-
572
- {{10}}.salamander-icon{{/10}} {
573
- {{11}}background-image{{/11}}: {{12}}url("/images/salamander.png"){{/12}}; }
574
-
575
- /*# sourceMappingURL=test.css.map */
576
- CSS
577
- end
578
-
579
- def test_each_sourcemap_sass
580
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
581
- @each $animal in puma, sea-slug, egret, salamander
582
- {{1}}{{4}}{{7}}{{10}}.#{$animal}-icon{{/1}}{{/4}}{{/7}}{{/10}}
583
- {{2}}{{5}}{{8}}{{11}}background-image{{/2}}{{/5}}{{/8}}{{/11}}: {{3}}{{6}}{{9}}{{12}}url('/images/#{$animal}.png'){{/3}}{{/6}}{{/9}}{{/12}}
584
- SASS
585
- {{1}}.puma-icon{{/1}} {
586
- {{2}}background-image{{/2}}: {{3}}url("/images/puma.png"){{/3}}; }
587
-
588
- {{4}}.sea-slug-icon{{/4}} {
589
- {{5}}background-image{{/5}}: {{6}}url("/images/sea-slug.png"){{/6}}; }
590
-
591
- {{7}}.egret-icon{{/7}} {
592
- {{8}}background-image{{/8}}: {{9}}url("/images/egret.png"){{/9}}; }
593
-
594
- {{10}}.salamander-icon{{/10}} {
595
- {{11}}background-image{{/11}}: {{12}}url("/images/salamander.png"){{/12}}; }
596
-
597
- /*# sourceMappingURL=test.css.map */
598
- CSS
599
- end
600
-
601
- def test_mixin_sourcemap_scss
602
- assert_parses_with_mapping <<'SCSS', <<'CSS'
603
- @mixin large-text {
604
- font: {
605
- {{2}}size{{/2}}: {{3}}20px{{/3}};
606
- {{4}}weight{{/4}}: {{5}}bold{{/5}};
607
- }
608
- {{6}}color{{/6}}: {{7}}#ff0000{{/7}};
609
- }
610
-
611
- {{1}}.page-title {{/1}}{
612
- @include large-text;
613
- {{8}}padding{{/8}}: {{9}}4px{{/9}};
614
- }
615
-
616
- @mixin dashed-border($color, $width: {{14}}1in{{/14}}) {
617
- border: {
618
- {{11}}{{18}}color{{/11}}{{/18}}: $color;
619
- {{13}}{{20}}width{{/13}}{{/20}}: $width;
620
- {{15}}{{22}}style{{/15}}{{/22}}: {{16}}{{23}}dashed{{/16}}{{/23}};
621
- }
622
- }
623
-
624
- {{10}}p {{/10}}{ @include dashed-border({{12}}blue{{/12}}); }
625
- {{17}}h1 {{/17}}{ @include dashed-border({{19}}blue{{/19}}, {{21}}2in{{/21}}); }
626
-
627
- @mixin box-shadow($shadows...) {
628
- {{25}}-moz-box-shadow{{/25}}: {{26}}$shadows{{/26}};
629
- {{27}}-webkit-box-shadow{{/27}}: {{28}}$shadows{{/28}};
630
- {{29}}box-shadow{{/29}}: {{30}}$shadows{{/30}};
631
- }
632
-
633
- {{24}}.shadows {{/24}}{
634
- @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
635
- }
636
- SCSS
637
- {{1}}.page-title{{/1}} {
638
- {{2}}font-size{{/2}}: {{3}}20px{{/3}};
639
- {{4}}font-weight{{/4}}: {{5}}bold{{/5}};
640
- {{6}}color{{/6}}: {{7}}#ff0000{{/7}};
641
- {{8}}padding{{/8}}: {{9}}4px{{/9}}; }
642
-
643
- {{10}}p{{/10}} {
644
- {{11}}border-color{{/11}}: {{12}}blue{{/12}};
645
- {{13}}border-width{{/13}}: {{14}}1in{{/14}};
646
- {{15}}border-style{{/15}}: {{16}}dashed{{/16}}; }
647
-
648
- {{17}}h1{{/17}} {
649
- {{18}}border-color{{/18}}: {{19}}blue{{/19}};
650
- {{20}}border-width{{/20}}: {{21}}2in{{/21}};
651
- {{22}}border-style{{/22}}: {{23}}dashed{{/23}}; }
652
-
653
- {{24}}.shadows{{/24}} {
654
- {{25}}-moz-box-shadow{{/25}}: {{26}}0px 4px 5px #666, 2px 6px 10px #999{{/26}};
655
- {{27}}-webkit-box-shadow{{/27}}: {{28}}0px 4px 5px #666, 2px 6px 10px #999{{/28}};
656
- {{29}}box-shadow{{/29}}: {{30}}0px 4px 5px #666, 2px 6px 10px #999{{/30}}; }
657
-
658
- /*# sourceMappingURL=test.css.map */
659
- CSS
660
- end
661
-
662
- def test_mixin_sourcemap_sass
663
- silence_warnings {assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass}
664
- =large-text
665
- :font
666
- {{2}}size{{/2}}: {{3}}20px{{/3}}
667
- {{4}}weight{{/4}}: {{5}}bold{{/5}}
668
- {{6}}color{{/6}}: {{7}}#ff0000{{/7}}
669
-
670
- {{1}}.page-title{{/1}}
671
- +large-text
672
- {{8}}padding{{/8}}: {{9}}4px{{/9}}
673
-
674
- =dashed-border($color, $width: {{14}}1in{{/14}})
675
- border:
676
- {{11}}{{18}}color{{/11}}{{/18}}: $color
677
- {{13}}{{20}}width{{/13}}{{/20}}: $width
678
- {{15}}{{22}}style{{/15}}{{/22}}: {{16}}{{23}}dashed{{/16}}{{/23}}
679
-
680
- {{10}}p{{/10}}
681
- +dashed-border({{12}}blue{{/12}})
682
-
683
- {{17}}h1{{/17}}
684
- +dashed-border({{19}}blue{{/19}}, {{21}}2in{{/21}})
685
-
686
- =box-shadow($shadows...)
687
- {{25}}-moz-box-shadow{{/25}}: {{26}}$shadows{{/26}}
688
- {{27}}-webkit-box-shadow{{/27}}: {{28}}$shadows{{/28}}
689
- {{29}}box-shadow{{/29}}: {{30}}$shadows{{/30}}
690
-
691
- {{24}}.shadows{{/24}}
692
- +box-shadow(0px 4px 5px #666, 2px 6px 10px #999)
693
- SASS
694
- {{1}}.page-title{{/1}} {
695
- {{2}}font-size{{/2}}: {{3}}20px{{/3}};
696
- {{4}}font-weight{{/4}}: {{5}}bold{{/5}};
697
- {{6}}color{{/6}}: {{7}}#ff0000{{/7}};
698
- {{8}}padding{{/8}}: {{9}}4px{{/9}}; }
699
-
700
- {{10}}p{{/10}} {
701
- {{11}}border-color{{/11}}: {{12}}blue{{/12}};
702
- {{13}}border-width{{/13}}: {{14}}1in{{/14}};
703
- {{15}}border-style{{/15}}: {{16}}dashed{{/16}}; }
704
-
705
- {{17}}h1{{/17}} {
706
- {{18}}border-color{{/18}}: {{19}}blue{{/19}};
707
- {{20}}border-width{{/20}}: {{21}}2in{{/21}};
708
- {{22}}border-style{{/22}}: {{23}}dashed{{/23}}; }
709
-
710
- {{24}}.shadows{{/24}} {
711
- {{25}}-moz-box-shadow{{/25}}: {{26}}0px 4px 5px #666, 2px 6px 10px #999{{/26}};
712
- {{27}}-webkit-box-shadow{{/27}}: {{28}}0px 4px 5px #666, 2px 6px 10px #999{{/28}};
713
- {{29}}box-shadow{{/29}}: {{30}}0px 4px 5px #666, 2px 6px 10px #999{{/30}}; }
714
-
715
- /*# sourceMappingURL=test.css.map */
716
- CSS
717
- end
718
-
719
- def test_function_sourcemap_scss
720
- assert_parses_with_mapping <<'SCSS', <<'CSS'
721
- $grid-width: 20px;
722
- $gutter-width: 5px;
723
-
724
- @function grid-width($n) {
725
- @return $n * $grid-width + ($n - 1) * $gutter-width;
726
- }
727
- {{1}}sidebar {{/1}}{ {{2}}width{{/2}}: {{3}}grid-width(5){{/3}}; }
728
- SCSS
729
- {{1}}sidebar{{/1}} {
730
- {{2}}width{{/2}}: {{3}}120px{{/3}}; }
731
-
732
- /*# sourceMappingURL=test.css.map */
733
- CSS
734
- end
735
-
736
- def test_function_sourcemap_sass
737
- assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
738
- $grid-width: 20px
739
- $gutter-width: 5px
740
-
741
- @function grid-width($n)
742
- @return $n * $grid-width + ($n - 1) * $gutter-width
743
-
744
- {{1}}sidebar{{/1}}
745
- {{2}}width{{/2}}: {{3}}grid-width(5){{/3}}
746
- SASS
747
- {{1}}sidebar{{/1}} {
748
- {{2}}width{{/2}}: {{3}}120px{{/3}}; }
749
-
750
- /*# sourceMappingURL=test.css.map */
751
- CSS
752
- end
753
-
754
- # Regression tests
755
-
756
- def test_properties_sass
757
- silence_warnings {assert_parses_with_mapping <<SASS, <<CSS, :syntax => :sass}
758
- {{1}}.foo{{/1}}
759
- :{{2}}name{{/2}} {{3}}value{{/3}}
760
- {{4}}name{{/4}}: {{5}}value{{/5}}
761
- :{{6}}name{{/6}} {{7}}value{{/7}}
762
- {{8}}name{{/8}}: {{9}}value{{/9}}
763
- SASS
764
- {{1}}.foo{{/1}} {
765
- {{2}}name{{/2}}: {{3}}value{{/3}};
766
- {{4}}name{{/4}}: {{5}}value{{/5}};
767
- {{6}}name{{/6}}: {{7}}value{{/7}};
768
- {{8}}name{{/8}}: {{9}}value{{/9}}; }
769
-
770
- /*# sourceMappingURL=test.css.map */
771
- CSS
772
- end
773
-
774
- def test_multiline_script_scss
775
- assert_parses_with_mapping <<SCSS, <<CSS, :syntax => :scss
776
- $var: {{3}}foo +
777
- bar{{/3}}; {{1}}x {{/1}}{ {{2}}y{{/2}}: $var }
778
- SCSS
779
- {{1}}x{{/1}} {
780
- {{2}}y{{/2}}: {{3}}foobar{{/3}}; }
781
-
782
- /*# sourceMappingURL=test.css.map */
783
- CSS
784
- end
785
-
786
- def test_multiline_interpolation_source_range
787
- engine = Sass::Engine.new(<<-SCSS, :cache => false, :syntax => :scss)
788
- p {
789
- filter: progid:DXImageTransform(
790
- '\#{123}');
791
- }
792
- SCSS
793
-
794
- interpolated = engine.to_tree.children.
795
- first.children.
796
- first.value.first.children[1]
797
- assert_equal "123", interpolated.to_sass
798
- range = interpolated.source_range
799
- assert_equal 3, range.start_pos.line
800
- assert_equal 14, range.start_pos.offset
801
- assert_equal 3, range.end_pos.line
802
- assert_equal 17, range.end_pos.offset
803
- end
804
-
805
- def test_list_source_range
806
- engine = Sass::Engine.new(<<-SCSS, :cache => false, :syntax => :scss)
807
- @each $a, $b in (1, 2), (2, 4), (3, 6) { }
808
- SCSS
809
- list = engine.to_tree.children.first.list
810
- assert_equal 1, list.source_range.start_pos.line
811
- assert_equal 1, list.source_range.end_pos.line
812
- assert_equal 16, list.source_range.start_pos.offset
813
- assert_equal 38, list.source_range.end_pos.offset
814
- end
815
-
816
- def test_map_source_range
817
- engine = Sass::Engine.new(<<-SCSS, :cache => false, :syntax => :scss)
818
- $margins: (sm: 4px, md: 8px, lg: 16px);
819
- SCSS
820
- expr = engine.to_tree.children.first.expr
821
- assert_equal 1, expr.source_range.start_pos.line
822
- assert_equal 1, expr.source_range.end_pos.line
823
- assert_equal 12, expr.source_range.start_pos.offset
824
- assert_equal 38, expr.source_range.end_pos.offset
825
- end
826
-
827
- def test_sources_array_is_uri_escaped
828
- map = Sass::Source::Map.new
829
- importer = Sass::Importers::Filesystem.new('.')
830
- map.add(
831
- Sass::Source::Range.new(
832
- Sass::Source::Position.new(0, 0),
833
- Sass::Source::Position.new(0, 10),
834
- 'source file.scss',
835
- importer),
836
- Sass::Source::Range.new(
837
- Sass::Source::Position.new(0, 0),
838
- Sass::Source::Position.new(0, 10),
839
- nil, nil))
840
-
841
- json = map.to_json(:css_path => 'output file.css', :sourcemap_path => 'output file.css.map')
842
- assert_equal json, <<JSON.rstrip
843
- {
844
- "version": 3,
845
- "mappings": "DADD,UAAU",
846
- "sources": ["source%20file.scss"],
847
- "names": [],
848
- "file": "output%20file.css"
849
- }
850
- JSON
851
- end
852
-
853
- def test_scss_comment_source_range
854
- assert_parses_with_mapping <<SCSS, <<CSS, :syntax => :scss
855
- $var: val; {{1}}/* text */{{/1}}
856
-
857
- {{2}}/* multiline
858
- comment */{{/2}}
859
- SCSS
860
- {{1}}/* text */{{/1}}
861
- {{2}}/* multiline
862
- comment */{{/2}}
863
-
864
- /*# sourceMappingURL=test.css.map */
865
- CSS
866
- end
867
-
868
- def test_sass_comment_source_range
869
- assert_parses_with_mapping <<SASS, <<CSS, :syntax => :sass
870
- {{1}}body{{/1}}
871
- {{2}}/* text */{{/2}}
872
-
873
- {{3}}/* multiline
874
- comment */{{/3}}
875
- SASS
876
- {{1}}body{{/1}} {
877
- {{2}}/* text */{{/2}} }
878
-
879
- {{3}}/* multiline
880
- * comment */{{/3}}
881
-
882
- /*# sourceMappingURL=test.css.map */
883
- CSS
884
- end
885
-
886
- def test_scss_comment_interpolation_source_range
887
- assert_parses_with_mapping <<SCSS, <<CSS, :syntax => :scss
888
- $var: 2; {{1}}/* two \#{$var} and four \#{2 * $var} */{{/1}}
889
-
890
- {{2}}/* multiline
891
- comment \#{ 2 + 2 } and \#{ 2 +
892
- 2 } */{{/2}}
893
- SCSS
894
- {{1}}/* two 2 and four 4 */{{/1}}
895
- {{2}}/* multiline
896
- comment 4 and 4 */{{/2}}
897
-
898
- /*# sourceMappingURL=test.css.map */
899
- CSS
900
- end
901
-
902
- def test_sass_comment_interpolation_source_range
903
- assert_parses_with_mapping <<SASS, <<CSS, :syntax => :sass
904
- $var: 2
905
- {{1}}/* two \#{$var} and four \#{2 * $var} */{{/1}}
906
-
907
- {{2}}/* multiline
908
- comment \#{ 2 + 2 } and \#{ 2 +
909
- 2 } */{{/2}}
910
- SASS
911
- {{1}}/* two 2 and four 4 */{{/1}}
912
- {{2}}/* multiline
913
- * comment 4 and 4 */{{/2}}
914
-
915
- /*# sourceMappingURL=test.css.map */
916
- CSS
917
- end
918
-
919
- private
920
-
921
- ANNOTATION_REGEX = /\{\{(\/?)([^}]+)\}\}/
922
-
923
- def build_ranges(text, file_name = nil)
924
- ranges = Hash.new {|h, k| h[k] = []}
925
- start_positions = {}
926
- text.split("\n").each_with_index do |line_text, line|
927
- line += 1 # lines shoud be 1-based
928
- while (match = line_text.match(ANNOTATION_REGEX))
929
- closing = !match[1].empty?
930
- name = match[2]
931
- match_offsets = match.offset(0)
932
- offset = match_offsets[0] + 1 # Offsets are 1-based in source maps.
933
- assert(!closing || start_positions[name], "Closing annotation #{name} found before opening one.")
934
- position = Sass::Source::Position.new(line, offset)
935
- if closing
936
- ranges[name] << Sass::Source::Range.new(
937
- start_positions[name], position, file_name,
938
- Sass::Importers::Filesystem.new('.'))
939
- start_positions.delete name
940
- else
941
- assert(!start_positions[name], "Overlapping range annotation #{name} encountered on line #{line}")
942
- start_positions[name] = position
943
- end
944
- line_text.slice!(match_offsets[0], match_offsets[1] - match_offsets[0])
945
- end
946
- end
947
- ranges
948
- end
949
-
950
- def build_mapping_from_annotations(source, css, source_file_name)
951
- source_ranges = build_ranges(source, source_file_name)
952
- target_ranges = build_ranges(css)
953
- map = Sass::Source::Map.new
954
- source_ranges.map do |(name, sources)|
955
- assert(sources.length == 1, "#{sources.length} source ranges encountered for annotation #{name}")
956
- assert(target_ranges[name], "No target ranges for annotation #{name}")
957
- target_ranges[name].map {|target_range| [sources.first, target_range]}
958
- end.
959
- flatten(1).
960
- sort_by {|(_, target)| [target.start_pos.line, target.start_pos.offset]}.
961
- each {|(s2, target)| map.add(s2, target)}
962
- map
963
- end
964
-
965
- def assert_parses_with_mapping(source, css, options={})
966
- options[:syntax] ||= :scss
967
- input_filename = filename_for_test(options[:syntax])
968
- mapping = build_mapping_from_annotations(source, css, input_filename)
969
- source.gsub!(ANNOTATION_REGEX, "")
970
- css.gsub!(ANNOTATION_REGEX, "")
971
- rendered, sourcemap = render_with_sourcemap(source, options)
972
- assert_equal css.rstrip, rendered.rstrip
973
- assert_sourcemaps_equal source, css, mapping, sourcemap
974
- end
975
-
976
- def assert_positions_equal(expected, actual, lines, message = nil)
977
- prefix = message ? message + ": " : ""
978
- expected_location = lines[expected.line - 1] + "\n" + ("-" * (expected.offset - 1)) + "^"
979
- actual_location = lines[actual.line - 1] + "\n" + ("-" * (actual.offset - 1)) + "^"
980
- assert_equal(expected.line, actual.line, prefix +
981
- "Expected #{expected.inspect}\n" +
982
- expected_location + "\n\n" +
983
- "But was #{actual.inspect}\n" +
984
- actual_location)
985
- assert_equal(expected.offset, actual.offset, prefix +
986
- "Expected #{expected.inspect}\n" +
987
- expected_location + "\n\n" +
988
- "But was #{actual.inspect}\n" +
989
- actual_location)
990
- end
991
-
992
- def assert_ranges_equal(expected, actual, lines, prefix)
993
- assert_positions_equal(expected.start_pos, actual.start_pos, lines, prefix + " start position")
994
- assert_positions_equal(expected.end_pos, actual.end_pos, lines, prefix + " end position")
995
- if expected.file.nil?
996
- assert_nil(actual.file)
997
- else
998
- assert_equal(expected.file, actual.file)
999
- end
1000
- end
1001
-
1002
- def assert_sourcemaps_equal(source, css, expected, actual)
1003
- assert_equal(expected.data.length, actual.data.length, <<MESSAGE)
1004
- Wrong number of mappings. Expected:
1005
- #{dump_sourcemap_as_expectation(source, css, expected).gsub(/^/, '| ')}
1006
-
1007
- Actual:
1008
- #{dump_sourcemap_as_expectation(source, css, actual).gsub(/^/, '| ')}
1009
- MESSAGE
1010
- source_lines = source.split("\n")
1011
- css_lines = css.split("\n")
1012
- expected.data.zip(actual.data) do |expected_mapping, actual_mapping|
1013
- assert_ranges_equal(expected_mapping.input, actual_mapping.input, source_lines, "Input")
1014
- assert_ranges_equal(expected_mapping.output, actual_mapping.output, css_lines, "Output")
1015
- end
1016
- end
1017
-
1018
- def assert_parses_with_sourcemap(source, css, sourcemap_json, options={})
1019
- rendered, sourcemap = render_with_sourcemap(source, options)
1020
- css_path = options[:output] || "test.css"
1021
- sourcemap_path = Sass::Util.sourcemap_name(css_path)
1022
- rendered_json = sourcemap.to_json(:css_path => css_path, :sourcemap_path => sourcemap_path, :type => options[:sourcemap])
1023
-
1024
- assert_equal css.rstrip, rendered.rstrip
1025
- assert_equal sourcemap_json.rstrip, rendered_json
1026
- end
1027
-
1028
- def render_with_sourcemap(source, options={})
1029
- options[:syntax] ||= :scss
1030
- munge_filename options
1031
- engine = Sass::Engine.new(source, options)
1032
- engine.options[:cache] = false
1033
- sourcemap_path = Sass::Util.sourcemap_name(options[:output] || "test.css")
1034
- engine.render_with_sourcemap File.basename(sourcemap_path)
1035
- end
1036
-
1037
- def dump_sourcemap_as_expectation(source, css, sourcemap)
1038
- mappings_to_annotations(source, sourcemap.data.map {|d| d.input}) + "\n\n" +
1039
- "=" * 20 + " maps to:\n\n" +
1040
- mappings_to_annotations(css, sourcemap.data.map {|d| d.output})
1041
- end
1042
-
1043
- def mappings_to_annotations(source, ranges)
1044
- additional_offsets = Hash.new(0)
1045
- lines = source.split("\n")
1046
-
1047
- add_annotation = lambda do |pos, str|
1048
- line_num = pos.line - 1
1049
- line = lines[line_num]
1050
- offset = pos.offset + additional_offsets[line_num] - 1
1051
- line << " " * (offset - line.length) if offset > line.length
1052
- line.insert(offset, str)
1053
- additional_offsets[line_num] += str.length
1054
- end
1055
-
1056
- ranges.each_with_index do |range, i|
1057
- add_annotation[range.start_pos, "{{#{i + 1}}}"]
1058
- add_annotation[range.end_pos, "{{/#{i + 1}}}"]
1059
- end
1060
-
1061
- return lines.join("\n")
1062
- end
1063
- end