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,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