sass 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -0,0 +1,887 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../test_helper'
4
+ require File.dirname(__FILE__) + '/test_helper'
5
+
6
+ class SourcemapTest < Test::Unit::TestCase
7
+ def test_to_json_requires_args
8
+ _, sourcemap = render_with_sourcemap('')
9
+ assert_raise(ArgumentError) {sourcemap.to_json({})}
10
+ assert_raise(ArgumentError) {sourcemap.to_json({:css_path => 'foo'})}
11
+ assert_raise(ArgumentError) {sourcemap.to_json({:sourcemap_path => 'foo'})}
12
+ end
13
+
14
+ def test_simple_mapping_scss
15
+ assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON
16
+ a {
17
+ foo: bar;
18
+ /* SOME COMMENT */
19
+ font-size: 12px;
20
+ }
21
+ SCSS
22
+ a {
23
+ foo: bar;
24
+ /* SOME COMMENT */
25
+ font-size: 12px; }
26
+
27
+ /*# sourceMappingURL=test.css.map */
28
+ CSS
29
+ {
30
+ "version": 3,
31
+ "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;;EAER,SAAS,EAAE,IAAI",
32
+ "sources": ["test_simple_mapping_scss_inline.scss"],
33
+ "names": [],
34
+ "file": "test.css"
35
+ }
36
+ JSON
37
+ end
38
+
39
+ def test_simple_mapping_sass
40
+ assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, :syntax => :sass
41
+ a
42
+ foo: bar
43
+ /* SOME COMMENT */
44
+ :font-size 12px
45
+ SASS
46
+ a {
47
+ foo: bar;
48
+ /* SOME COMMENT */
49
+ font-size: 12px; }
50
+
51
+ /*# sourceMappingURL=test.css.map */
52
+ CSS
53
+ {
54
+ "version": 3,
55
+ "mappings": "AAAA,CAAC;EACC,GAAG,EAAE,GAAG;;EAEP,SAAS,EAAC,IAAI",
56
+ "sources": ["test_simple_mapping_sass_inline.sass"],
57
+ "names": [],
58
+ "file": "test.css"
59
+ }
60
+ JSON
61
+ end
62
+
63
+ def test_mapping_with_directory_scss
64
+ options = {:filename => "scss/style.scss", :output => "css/style.css"}
65
+ assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON, options
66
+ a {
67
+ foo: bar;
68
+ /* SOME COMMENT */
69
+ font-size: 12px;
70
+ }
71
+ SCSS
72
+ a {
73
+ foo: bar;
74
+ /* SOME COMMENT */
75
+ font-size: 12px; }
76
+
77
+ /*# sourceMappingURL=style.css.map */
78
+ CSS
79
+ {
80
+ "version": 3,
81
+ "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;;EAER,SAAS,EAAE,IAAI",
82
+ "sources": ["../scss/style.scss"],
83
+ "names": [],
84
+ "file": "style.css"
85
+ }
86
+ JSON
87
+ end
88
+
89
+ def test_mapping_with_directory_sass
90
+ options = {:filename => "sass/style.sass", :output => "css/style.css", :syntax => :sass}
91
+ assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, options
92
+ a
93
+ foo: bar
94
+ /* SOME COMMENT */
95
+ :font-size 12px
96
+ SASS
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,CAAC;EACC,GAAG,EAAE,GAAG;;EAEP,SAAS,EAAC,IAAI",
107
+ "sources": ["../sass/style.sass"],
108
+ "names": [],
109
+ "file": "style.css"
110
+ }
111
+ JSON
112
+ end
113
+
114
+ unless Sass::Util.ruby1_8?
115
+ def test_simple_charset_mapping_scss
116
+ assert_parses_with_sourcemap <<SCSS, <<CSS, <<JSON
117
+ a {
118
+ fóó: bár;
119
+ }
120
+ SCSS
121
+ @charset "UTF-8";
122
+ a {
123
+ fóó: bár; }
124
+
125
+ /*# sourceMappingURL=test.css.map */
126
+ CSS
127
+ {
128
+ "version": 3,
129
+ "mappings": ";AAAA,CAAE;EACA,GAAG,EAAE,GAAG",
130
+ "sources": ["test_simple_charset_mapping_scss_inline.scss"],
131
+ "names": [],
132
+ "file": "test.css"
133
+ }
134
+ JSON
135
+ end
136
+
137
+ def test_simple_charset_mapping_sass
138
+ assert_parses_with_sourcemap <<SASS, <<CSS, <<JSON, :syntax => :sass
139
+ a
140
+ fóó: bár
141
+ SASS
142
+ @charset "UTF-8";
143
+ a {
144
+ fóó: bár; }
145
+
146
+ /*# sourceMappingURL=test.css.map */
147
+ CSS
148
+ {
149
+ "version": 3,
150
+ "mappings": ";AAAA,CAAC;EACC,GAAG,EAAE,GAAG",
151
+ "sources": ["test_simple_charset_mapping_sass_inline.sass"],
152
+ "names": [],
153
+ "file": "test.css"
154
+ }
155
+ JSON
156
+ end
157
+
158
+ def test_different_charset_than_encoding_scss
159
+ assert_parses_with_sourcemap(<<SCSS.force_encoding("IBM866"), <<CSS.force_encoding("IBM866"), <<JSON)
160
+ @charset "IBM866";
161
+ f\x86\x86 {
162
+ \x86: b;
163
+ }
164
+ SCSS
165
+ @charset "IBM866";
166
+ f\x86\x86 {
167
+ \x86: b; }
168
+
169
+ /*# sourceMappingURL=test.css.map */
170
+ CSS
171
+ {
172
+ "version": 3,
173
+ "mappings": ";AACA,GAAI;EACF,CAAC,EAAE,CAAC",
174
+ "sources": ["test_different_charset_than_encoding_scss_inline.scss"],
175
+ "names": [],
176
+ "file": "test.css"
177
+ }
178
+ JSON
179
+ end
180
+
181
+ def test_different_charset_than_encoding_sass
182
+ assert_parses_with_sourcemap(<<SASS.force_encoding("IBM866"), <<CSS.force_encoding("IBM866"), <<JSON, :syntax => :sass)
183
+ @charset "IBM866"
184
+ f\x86\x86
185
+ \x86: b
186
+ SASS
187
+ @charset "IBM866";
188
+ f\x86\x86 {
189
+ \x86: b; }
190
+
191
+ /*# sourceMappingURL=test.css.map */
192
+ CSS
193
+ {
194
+ "version": 3,
195
+ "mappings": ";AACA,GAAG;EACD,CAAC,EAAE,CAAC",
196
+ "sources": ["test_different_charset_than_encoding_sass_inline.sass"],
197
+ "names": [],
198
+ "file": "test.css"
199
+ }
200
+ JSON
201
+ end
202
+ end
203
+
204
+ def test_import_sourcemap_scss
205
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
206
+ @import {{1}}url(foo){{/1}},{{2}}url(moo) {{/2}}, {{3}}url(bar) {{/3}};
207
+ @import {{4}}url(baz) screen print{{/4}};
208
+ SCSS
209
+ {{1}}@import url(foo){{/1}};
210
+ {{2}}@import url(moo){{/2}};
211
+ {{3}}@import url(bar){{/3}};
212
+ {{4}}@import url(baz) screen print{{/4}};
213
+
214
+ /*# sourceMappingURL=test.css.map */
215
+ CSS
216
+ end
217
+
218
+ def test_import_sourcemap_sass
219
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
220
+ @import {{1}}foo.css{{/1}},{{2}}moo.css{{/2}}, {{3}}bar.css{{/3}}
221
+ @import {{4}}url(baz.css){{/4}}
222
+ @import {{5}}url(qux.css) screen print{{/5}}
223
+ SASS
224
+ {{1}}@import url(foo.css){{/1}};
225
+ {{2}}@import url(moo.css){{/2}};
226
+ {{3}}@import url(bar.css){{/3}};
227
+ {{4}}@import url(baz.css){{/4}};
228
+ {{5}}@import url(qux.css) screen print{{/5}};
229
+
230
+ /*# sourceMappingURL=test.css.map */
231
+ CSS
232
+ end
233
+
234
+ def test_media_sourcemap_scss
235
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
236
+ {{1}}@media screen, tv {{/1}}{
237
+ {{2}}body {{/2}}{
238
+ {{3}}max-width{{/3}}: {{4}}1070px{{/4}};
239
+ }
240
+ }
241
+ SCSS
242
+ {{1}}@media screen, tv{{/1}} {
243
+ {{2}}body{{/2}} {
244
+ {{3}}max-width{{/3}}: {{4}}1070px{{/4}}; } }
245
+
246
+ /*# sourceMappingURL=test.css.map */
247
+ CSS
248
+ end
249
+
250
+ def test_media_sourcemap_sass
251
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
252
+ {{1}}@media screen, tv{{/1}}
253
+ {{2}}body{{/2}}
254
+ {{3}}max-width{{/3}}: {{4}}1070px{{/4}}
255
+ SASS
256
+ {{1}}@media screen, tv{{/1}} {
257
+ {{2}}body{{/2}} {
258
+ {{3}}max-width{{/3}}: {{4}}1070px{{/4}}; } }
259
+
260
+ /*# sourceMappingURL=test.css.map */
261
+ CSS
262
+ end
263
+
264
+ def test_interpolation_and_vars_sourcemap_scss
265
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
266
+ $te: "te";
267
+ $teal: {{5}}teal{{/5}};
268
+ {{1}}p {{/1}}{
269
+ {{2}}con#{$te}nt{{/2}}: {{3}}"I a#{$te} #{5 + 10} pies!"{{/3}};
270
+ {{4}}color{{/4}}: $teal;
271
+ }
272
+
273
+ $name: foo;
274
+ $attr: border;
275
+ {{6}}p.#{$name} {{/6}}{
276
+ {{7}}#{$attr}-color{{/7}}: {{8}}blue{{/8}};
277
+ $font-size: 12px;
278
+ $line-height: 30px;
279
+ {{9}}font{{/9}}: {{10}}#{$font-size}/#{$line-height}{{/10}};
280
+ }
281
+ SCSS
282
+ {{1}}p{{/1}} {
283
+ {{2}}content{{/2}}: {{3}}"I ate 15 pies!"{{/3}};
284
+ {{4}}color{{/4}}: {{5}}teal{{/5}}; }
285
+
286
+ {{6}}p.foo{{/6}} {
287
+ {{7}}border-color{{/7}}: {{8}}blue{{/8}};
288
+ {{9}}font{{/9}}: {{10}}12px/30px{{/10}}; }
289
+
290
+ /*# sourceMappingURL=test.css.map */
291
+ CSS
292
+ end
293
+
294
+ def test_interpolation_and_vars_sourcemap_sass
295
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
296
+ $te: "te"
297
+ $teal: {{5}}teal{{/5}}
298
+ {{1}}p{{/1}}
299
+ {{2}}con#{$te}nt{{/2}}: {{3}}"I a#{$te} #{5 + 10} pies!"{{/3}}
300
+ {{4}}color{{/4}}: $teal
301
+
302
+ $name: foo
303
+ $attr: border
304
+ {{6}}p.#{$name}{{/6}}
305
+ {{7}}#{$attr}-color{{/7}}: {{8}}blue{{/8}}
306
+ $font-size: 12px
307
+ $line-height: 30px
308
+ {{9}}font{{/9}}: {{10}}#{$font-size}/#{$line-height}{{/10}}
309
+ SASS
310
+ {{1}}p{{/1}} {
311
+ {{2}}content{{/2}}: {{3}}"I ate 15 pies!"{{/3}};
312
+ {{4}}color{{/4}}: {{5}}teal{{/5}}; }
313
+
314
+ {{6}}p.foo{{/6}} {
315
+ {{7}}border-color{{/7}}: {{8}}blue{{/8}};
316
+ {{9}}font{{/9}}: {{10}}12px/30px{{/10}}; }
317
+
318
+ /*# sourceMappingURL=test.css.map */
319
+ CSS
320
+ end
321
+
322
+ def test_selectors_properties_sourcemap_scss
323
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
324
+ $width: 2px;
325
+ $translucent-red: rgba(255, 0, 0, 0.5);
326
+ {{1}}a {{/1}}{
327
+ {{8}}.special {{/8}}{
328
+ {{9}}color{{/9}}: {{10}}red{{/10}};
329
+ {{11}}&:hover {{/11}}{
330
+ {{12}}foo{{/12}}: {{13}}bar{{/13}};
331
+ {{14}}cursor{{/14}}: {{15}}e + -resize{{/15}};
332
+ {{16}}color{{/16}}: {{17}}opacify($translucent-red, 0.3){{/17}};
333
+ }
334
+ {{18}}&:after {{/18}}{
335
+ {{19}}content{{/19}}: {{20}}"I ate #{5 + 10} pies #{$width} thick!"{{/20}};
336
+ }
337
+ }
338
+ {{21}}&:active {{/21}}{
339
+ {{22}}color{{/22}}: {{23}}#010203 + #040506{{/23}};
340
+ {{24}}border{{/24}}: {{25}}$width solid black{{/25}};
341
+ }
342
+ /* SOME COMMENT */
343
+ {{2}}font{{/2}}: {{3}}2px/3px {{/3}}{
344
+ {{4}}family{{/4}}: {{5}}fantasy{{/5}};
345
+ {{6}}size{{/6}}: {{7}}1em + (2em * 3){{/7}};
346
+ }
347
+ }
348
+ SCSS
349
+ {{1}}a{{/1}} {
350
+ /* SOME COMMENT */
351
+ {{2}}font{{/2}}: {{3}}2px/3px{{/3}};
352
+ {{4}}font-family{{/4}}: {{5}}fantasy{{/5}};
353
+ {{6}}font-size{{/6}}: {{7}}7em{{/7}}; }
354
+ {{8}}a .special{{/8}} {
355
+ {{9}}color{{/9}}: {{10}}red{{/10}}; }
356
+ {{11}}a .special:hover{{/11}} {
357
+ {{12}}foo{{/12}}: {{13}}bar{{/13}};
358
+ {{14}}cursor{{/14}}: {{15}}e-resize{{/15}};
359
+ {{16}}color{{/16}}: {{17}}rgba(255, 0, 0, 0.8){{/17}}; }
360
+ {{18}}a .special:after{{/18}} {
361
+ {{19}}content{{/19}}: {{20}}"I ate 15 pies 2px thick!"{{/20}}; }
362
+ {{21}}a:active{{/21}} {
363
+ {{22}}color{{/22}}: {{23}}#050709{{/23}};
364
+ {{24}}border{{/24}}: {{25}}2px solid black{{/25}}; }
365
+
366
+ /*# sourceMappingURL=test.css.map */
367
+ CSS
368
+ end
369
+
370
+ def test_selectors_properties_sourcemap_sass
371
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
372
+ $width: 2px
373
+ $translucent-red: rgba(255, 0, 0, 0.5)
374
+ {{1}}a{{/1}}
375
+ {{8}}.special{{/8}}
376
+ {{9}}color{{/9}}: {{10}}red{{/10}}
377
+ {{11}}&:hover{{/11}}
378
+ {{12}}foo{{/12}}: {{13}}bar{{/13}}
379
+ {{14}}cursor{{/14}}: {{15}}e + -resize{{/15}}
380
+ {{16}}color{{/16}}: {{17}}opacify($translucent-red, 0.3){{/17}}
381
+ {{18}}&:after{{/18}}
382
+ {{19}}content{{/19}}: {{20}}"I ate #{5 + 10} pies #{$width} thick!"{{/20}}
383
+ {{21}}&:active{{/21}}
384
+ {{22}}color{{/22}}: {{23}}#010203 + #040506{{/23}}
385
+ {{24}}border{{/24}}: {{25}}$width solid black{{/25}}
386
+
387
+ /* SOME COMMENT */
388
+ {{2}}font{{/2}}: {{3}}2px/3px{{/3}}
389
+ {{4}}family{{/4}}: {{5}}fantasy{{/5}}
390
+ {{6}}size{{/6}}: {{7}}1em + (2em * 3){{/7}}
391
+ SASS
392
+ {{1}}a{{/1}} {
393
+ /* SOME COMMENT */
394
+ {{2}}font{{/2}}: {{3}}2px/3px{{/3}};
395
+ {{4}}font-family{{/4}}: {{5}}fantasy{{/5}};
396
+ {{6}}font-size{{/6}}: {{7}}7em{{/7}}; }
397
+ {{8}}a .special{{/8}} {
398
+ {{9}}color{{/9}}: {{10}}red{{/10}}; }
399
+ {{11}}a .special:hover{{/11}} {
400
+ {{12}}foo{{/12}}: {{13}}bar{{/13}};
401
+ {{14}}cursor{{/14}}: {{15}}e-resize{{/15}};
402
+ {{16}}color{{/16}}: {{17}}rgba(255, 0, 0, 0.8){{/17}}; }
403
+ {{18}}a .special:after{{/18}} {
404
+ {{19}}content{{/19}}: {{20}}"I ate 15 pies 2px thick!"{{/20}}; }
405
+ {{21}}a:active{{/21}} {
406
+ {{22}}color{{/22}}: {{23}}#050709{{/23}};
407
+ {{24}}border{{/24}}: {{25}}2px solid black{{/25}}; }
408
+
409
+ /*# sourceMappingURL=test.css.map */
410
+ CSS
411
+ end
412
+
413
+ def test_extend_sourcemap_scss
414
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
415
+ {{1}}.error {{/1}}{
416
+ {{2}}border{{/2}}: {{3}}1px #ff00aa{{/3}};
417
+ {{4}}background-color{{/4}}: {{5}}#fdd{{/5}};
418
+ }
419
+ {{6}}.seriousError {{/6}}{
420
+ @extend .error;
421
+ {{7}}border-width{{/7}}: {{8}}3px{{/8}};
422
+ }
423
+ SCSS
424
+ {{1}}.error, .seriousError{{/1}} {
425
+ {{2}}border{{/2}}: {{3}}1px #ff00aa{{/3}};
426
+ {{4}}background-color{{/4}}: {{5}}#fdd{{/5}}; }
427
+
428
+ {{6}}.seriousError{{/6}} {
429
+ {{7}}border-width{{/7}}: {{8}}3px{{/8}}; }
430
+
431
+ /*# sourceMappingURL=test.css.map */
432
+ CSS
433
+ end
434
+
435
+ def test_extend_sourcemap_sass
436
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
437
+ {{1}}.error{{/1}}
438
+ {{2}}border{{/2}}: {{3}}1px #f00{{/3}}
439
+ {{4}}background-color{{/4}}: {{5}}#fdd{{/5}}
440
+
441
+ {{6}}.seriousError{{/6}}
442
+ @extend .error
443
+ {{7}}border-width{{/7}}: {{8}}3px{{/8}}
444
+ SASS
445
+ {{1}}.error, .seriousError{{/1}} {
446
+ {{2}}border{{/2}}: {{3}}1px red{{/3}};
447
+ {{4}}background-color{{/4}}: {{5}}#ffdddd{{/5}}; }
448
+
449
+ {{6}}.seriousError{{/6}} {
450
+ {{7}}border-width{{/7}}: {{8}}3px{{/8}}; }
451
+
452
+ /*# sourceMappingURL=test.css.map */
453
+ CSS
454
+ end
455
+
456
+ def test_for_sourcemap_scss
457
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
458
+ @for $i from 1 through 3 {
459
+ {{1}}{{4}}{{7}}.item-#{$i} {{/1}}{{/4}}{{/7}}{ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}; }
460
+ }
461
+ SCSS
462
+ {{1}}.item-1{{/1}} {
463
+ {{2}}width{{/2}}: {{3}}2em{{/3}}; }
464
+
465
+ {{4}}.item-2{{/4}} {
466
+ {{5}}width{{/5}}: {{6}}4em{{/6}}; }
467
+
468
+ {{7}}.item-3{{/7}} {
469
+ {{8}}width{{/8}}: {{9}}6em{{/9}}; }
470
+
471
+ /*# sourceMappingURL=test.css.map */
472
+ CSS
473
+ end
474
+
475
+ def test_for_sourcemap_sass
476
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
477
+ @for $i from 1 through 3
478
+ {{1}}{{4}}{{7}}.item-#{$i}{{/1}}{{/4}}{{/7}}
479
+ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}
480
+ SASS
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_while_sourcemap_scss
495
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
496
+ $i: 6;
497
+ @while $i > 0 {
498
+ {{1}}{{4}}{{7}}.item-#{$i} {{/1}}{{/4}}{{/7}}{ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}; }
499
+ $i: $i - 2 !global;
500
+ }
501
+ SCSS
502
+ {{1}}.item-6{{/1}} {
503
+ {{2}}width{{/2}}: {{3}}12em{{/3}}; }
504
+
505
+ {{4}}.item-4{{/4}} {
506
+ {{5}}width{{/5}}: {{6}}8em{{/6}}; }
507
+
508
+ {{7}}.item-2{{/7}} {
509
+ {{8}}width{{/8}}: {{9}}4em{{/9}}; }
510
+
511
+ /*# sourceMappingURL=test.css.map */
512
+ CSS
513
+ end
514
+
515
+ def test_while_sourcemap_sass
516
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
517
+ $i: 6
518
+ @while $i > 0
519
+ {{1}}{{4}}{{7}}.item-#{$i}{{/1}}{{/4}}{{/7}}
520
+ {{2}}{{5}}{{8}}width{{/2}}{{/5}}{{/8}}: {{3}}{{6}}{{9}}2em * $i{{/3}}{{/6}}{{/9}}
521
+ $i: $i - 2 !global
522
+ SASS
523
+ {{1}}.item-6{{/1}} {
524
+ {{2}}width{{/2}}: {{3}}12em{{/3}}; }
525
+
526
+ {{4}}.item-4{{/4}} {
527
+ {{5}}width{{/5}}: {{6}}8em{{/6}}; }
528
+
529
+ {{7}}.item-2{{/7}} {
530
+ {{8}}width{{/8}}: {{9}}4em{{/9}}; }
531
+
532
+ /*# sourceMappingURL=test.css.map */
533
+ CSS
534
+ end
535
+
536
+ def test_each_sourcemap_scss
537
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
538
+ @each $animal in puma, sea-slug, egret, salamander {
539
+ {{1}}{{4}}{{7}}{{10}}.#{$animal}-icon {{/1}}{{/4}}{{/7}}{{/10}}{
540
+ {{2}}{{5}}{{8}}{{11}}background-image{{/2}}{{/5}}{{/8}}{{/11}}: {{3}}{{6}}{{9}}{{12}}url('/images/#{$animal}.png'){{/3}}{{/6}}{{/9}}{{/12}};
541
+ }
542
+ }
543
+ SCSS
544
+ {{1}}.puma-icon{{/1}} {
545
+ {{2}}background-image{{/2}}: {{3}}url("/images/puma.png"){{/3}}; }
546
+
547
+ {{4}}.sea-slug-icon{{/4}} {
548
+ {{5}}background-image{{/5}}: {{6}}url("/images/sea-slug.png"){{/6}}; }
549
+
550
+ {{7}}.egret-icon{{/7}} {
551
+ {{8}}background-image{{/8}}: {{9}}url("/images/egret.png"){{/9}}; }
552
+
553
+ {{10}}.salamander-icon{{/10}} {
554
+ {{11}}background-image{{/11}}: {{12}}url("/images/salamander.png"){{/12}}; }
555
+
556
+ /*# sourceMappingURL=test.css.map */
557
+ CSS
558
+ end
559
+
560
+ def test_each_sourcemap_sass
561
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
562
+ @each $animal in puma, sea-slug, egret, salamander
563
+ {{1}}{{4}}{{7}}{{10}}.#{$animal}-icon{{/1}}{{/4}}{{/7}}{{/10}}
564
+ {{2}}{{5}}{{8}}{{11}}background-image{{/2}}{{/5}}{{/8}}{{/11}}: {{3}}{{6}}{{9}}{{12}}url('/images/#{$animal}.png'){{/3}}{{/6}}{{/9}}{{/12}}
565
+ SASS
566
+ {{1}}.puma-icon{{/1}} {
567
+ {{2}}background-image{{/2}}: {{3}}url("/images/puma.png"){{/3}}; }
568
+
569
+ {{4}}.sea-slug-icon{{/4}} {
570
+ {{5}}background-image{{/5}}: {{6}}url("/images/sea-slug.png"){{/6}}; }
571
+
572
+ {{7}}.egret-icon{{/7}} {
573
+ {{8}}background-image{{/8}}: {{9}}url("/images/egret.png"){{/9}}; }
574
+
575
+ {{10}}.salamander-icon{{/10}} {
576
+ {{11}}background-image{{/11}}: {{12}}url("/images/salamander.png"){{/12}}; }
577
+
578
+ /*# sourceMappingURL=test.css.map */
579
+ CSS
580
+ end
581
+
582
+ def test_mixin_sourcemap_scss
583
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
584
+ @mixin large-text {
585
+ font: {
586
+ {{2}}size{{/2}}: {{3}}20px{{/3}};
587
+ {{4}}weight{{/4}}: {{5}}bold{{/5}};
588
+ }
589
+ {{6}}color{{/6}}: {{7}}#ff0000{{/7}};
590
+ }
591
+
592
+ {{1}}.page-title {{/1}}{
593
+ @include large-text;
594
+ {{8}}padding{{/8}}: {{9}}4px{{/9}};
595
+ }
596
+
597
+ @mixin dashed-border($color, $width: {{14}}1in{{/14}}) {
598
+ border: {
599
+ {{11}}{{18}}color{{/11}}{{/18}}: $color;
600
+ {{13}}{{20}}width{{/13}}{{/20}}: $width;
601
+ {{15}}{{22}}style{{/15}}{{/22}}: {{16}}{{23}}dashed{{/16}}{{/23}};
602
+ }
603
+ }
604
+
605
+ {{10}}p {{/10}}{ @include dashed-border({{12}}blue{{/12}}); }
606
+ {{17}}h1 {{/17}}{ @include dashed-border({{19}}blue{{/19}}, {{21}}2in{{/21}}); }
607
+
608
+ @mixin box-shadow($shadows...) {
609
+ {{25}}-moz-box-shadow{{/25}}: {{26}}$shadows{{/26}};
610
+ {{27}}-webkit-box-shadow{{/27}}: {{28}}$shadows{{/28}};
611
+ {{29}}box-shadow{{/29}}: {{30}}$shadows{{/30}};
612
+ }
613
+
614
+ {{24}}.shadows {{/24}}{
615
+ @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
616
+ }
617
+ SCSS
618
+ {{1}}.page-title{{/1}} {
619
+ {{2}}font-size{{/2}}: {{3}}20px{{/3}};
620
+ {{4}}font-weight{{/4}}: {{5}}bold{{/5}};
621
+ {{6}}color{{/6}}: {{7}}#ff0000{{/7}};
622
+ {{8}}padding{{/8}}: {{9}}4px{{/9}}; }
623
+
624
+ {{10}}p{{/10}} {
625
+ {{11}}border-color{{/11}}: {{12}}blue{{/12}};
626
+ {{13}}border-width{{/13}}: {{14}}1in{{/14}};
627
+ {{15}}border-style{{/15}}: {{16}}dashed{{/16}}; }
628
+
629
+ {{17}}h1{{/17}} {
630
+ {{18}}border-color{{/18}}: {{19}}blue{{/19}};
631
+ {{20}}border-width{{/20}}: {{21}}2in{{/21}};
632
+ {{22}}border-style{{/22}}: {{23}}dashed{{/23}}; }
633
+
634
+ {{24}}.shadows{{/24}} {
635
+ {{25}}-moz-box-shadow{{/25}}: {{26}}0px 4px 5px #666666, 2px 6px 10px #999999{{/26}};
636
+ {{27}}-webkit-box-shadow{{/27}}: {{28}}0px 4px 5px #666666, 2px 6px 10px #999999{{/28}};
637
+ {{29}}box-shadow{{/29}}: {{30}}0px 4px 5px #666666, 2px 6px 10px #999999{{/30}}; }
638
+
639
+ /*# sourceMappingURL=test.css.map */
640
+ CSS
641
+ end
642
+
643
+ def test_mixin_sourcemap_sass
644
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
645
+ =large-text
646
+ :font
647
+ {{2}}size{{/2}}: {{3}}20px{{/3}}
648
+ {{4}}weight{{/4}}: {{5}}bold{{/5}}
649
+ {{6}}color{{/6}}: {{7}}#ff0000{{/7}}
650
+
651
+ {{1}}.page-title{{/1}}
652
+ +large-text
653
+ {{8}}padding{{/8}}: {{9}}4px{{/9}}
654
+
655
+ =dashed-border($color, $width: {{14}}1in{{/14}})
656
+ border:
657
+ {{11}}{{18}}color{{/11}}{{/18}}: $color
658
+ {{13}}{{20}}width{{/13}}{{/20}}: $width
659
+ {{15}}{{22}}style{{/15}}{{/22}}: {{16}}{{23}}dashed{{/16}}{{/23}}
660
+
661
+ {{10}}p{{/10}}
662
+ +dashed-border({{12}}blue{{/12}})
663
+
664
+ {{17}}h1{{/17}}
665
+ +dashed-border({{19}}blue{{/19}}, {{21}}2in{{/21}})
666
+
667
+ =box-shadow($shadows...)
668
+ {{25}}-moz-box-shadow{{/25}}: {{26}}$shadows{{/26}}
669
+ {{27}}-webkit-box-shadow{{/27}}: {{28}}$shadows{{/28}}
670
+ {{29}}box-shadow{{/29}}: {{30}}$shadows{{/30}}
671
+
672
+ {{24}}.shadows{{/24}}
673
+ +box-shadow(0px 4px 5px #666, 2px 6px 10px #999)
674
+ SASS
675
+ {{1}}.page-title{{/1}} {
676
+ {{2}}font-size{{/2}}: {{3}}20px{{/3}};
677
+ {{4}}font-weight{{/4}}: {{5}}bold{{/5}};
678
+ {{6}}color{{/6}}: {{7}}red{{/7}};
679
+ {{8}}padding{{/8}}: {{9}}4px{{/9}}; }
680
+
681
+ {{10}}p{{/10}} {
682
+ {{11}}border-color{{/11}}: {{12}}blue{{/12}};
683
+ {{13}}border-width{{/13}}: {{14}}1in{{/14}};
684
+ {{15}}border-style{{/15}}: {{16}}dashed{{/16}}; }
685
+
686
+ {{17}}h1{{/17}} {
687
+ {{18}}border-color{{/18}}: {{19}}blue{{/19}};
688
+ {{20}}border-width{{/20}}: {{21}}2in{{/21}};
689
+ {{22}}border-style{{/22}}: {{23}}dashed{{/23}}; }
690
+
691
+ {{24}}.shadows{{/24}} {
692
+ {{25}}-moz-box-shadow{{/25}}: {{26}}0px 4px 5px #666666, 2px 6px 10px #999999{{/26}};
693
+ {{27}}-webkit-box-shadow{{/27}}: {{28}}0px 4px 5px #666666, 2px 6px 10px #999999{{/28}};
694
+ {{29}}box-shadow{{/29}}: {{30}}0px 4px 5px #666666, 2px 6px 10px #999999{{/30}}; }
695
+
696
+ /*# sourceMappingURL=test.css.map */
697
+ CSS
698
+ end
699
+
700
+ def test_function_sourcemap_scss
701
+ assert_parses_with_mapping <<'SCSS', <<'CSS'
702
+ $grid-width: 20px;
703
+ $gutter-width: 5px;
704
+
705
+ @function grid-width($n) {
706
+ @return $n * $grid-width + ($n - 1) * $gutter-width;
707
+ }
708
+ {{1}}sidebar {{/1}}{ {{2}}width{{/2}}: {{3}}grid-width(5){{/3}}; }
709
+ SCSS
710
+ {{1}}sidebar{{/1}} {
711
+ {{2}}width{{/2}}: {{3}}120px{{/3}}; }
712
+
713
+ /*# sourceMappingURL=test.css.map */
714
+ CSS
715
+ end
716
+
717
+ def test_function_sourcemap_sass
718
+ assert_parses_with_mapping <<'SASS', <<'CSS', :syntax => :sass
719
+ $grid-width: 20px
720
+ $gutter-width: 5px
721
+
722
+ @function grid-width($n)
723
+ @return $n * $grid-width + ($n - 1) * $gutter-width
724
+
725
+ {{1}}sidebar{{/1}}
726
+ {{2}}width{{/2}}: {{3}}grid-width(5){{/3}}
727
+ SASS
728
+ {{1}}sidebar{{/1}} {
729
+ {{2}}width{{/2}}: {{3}}120px{{/3}}; }
730
+
731
+ /*# sourceMappingURL=test.css.map */
732
+ CSS
733
+ end
734
+
735
+ # Regression tests
736
+
737
+ def test_properties_sass
738
+ assert_parses_with_mapping <<SASS, <<CSS, :syntax => :sass
739
+ {{1}}.foo{{/1}}
740
+ :{{2}}name{{/2}} {{3}}value{{/3}}
741
+ {{4}}name{{/4}}: {{5}}value{{/5}}
742
+ :{{6}}name{{/6}} {{7}}value{{/7}}
743
+ {{8}}name{{/8}}: {{9}}value{{/9}}
744
+ SASS
745
+ {{1}}.foo{{/1}} {
746
+ {{2}}name{{/2}}: {{3}}value{{/3}};
747
+ {{4}}name{{/4}}: {{5}}value{{/5}};
748
+ {{6}}name{{/6}}: {{7}}value{{/7}};
749
+ {{8}}name{{/8}}: {{9}}value{{/9}}; }
750
+
751
+ /*# sourceMappingURL=test.css.map */
752
+ CSS
753
+ end
754
+
755
+ private
756
+
757
+ ANNOTATION_REGEX = /\{\{(\/?)([^}]+)\}\}/
758
+
759
+ def build_ranges(text, file_name = nil)
760
+ ranges = Hash.new {|h, k| h[k] = []}
761
+ start_positions = {}
762
+ text.split("\n").each_with_index do |line_text, line|
763
+ line += 1 # lines shoud be 1-based
764
+ while (match = line_text.match(ANNOTATION_REGEX))
765
+ closing = !match[1].empty?
766
+ name = match[2]
767
+ match_offsets = match.offset(0)
768
+ offset = match_offsets[0] + 1 # Offsets are 1-based in source maps.
769
+ assert(!closing || start_positions[name], "Closing annotation #{name} found before opening one.")
770
+ position = Sass::Source::Position.new(line, offset)
771
+ if closing
772
+ ranges[name] << Sass::Source::Range.new(
773
+ start_positions[name], position, file_name,
774
+ Sass::Importers::Filesystem.new('.'))
775
+ start_positions.delete name
776
+ else
777
+ assert(!start_positions[name], "Overlapping range annotation #{name} encountered on line #{line}")
778
+ start_positions[name] = position
779
+ end
780
+ line_text.slice!(match_offsets[0], match_offsets[1] - match_offsets[0])
781
+ end
782
+ end
783
+ ranges
784
+ end
785
+
786
+ def build_mapping_from_annotations(source, css, source_file_name)
787
+ source_ranges = build_ranges(source, source_file_name)
788
+ target_ranges = build_ranges(css)
789
+ map = Sass::Source::Map.new
790
+ Sass::Util.flatten(source_ranges.map do |(name, sources)|
791
+ assert(sources.length == 1, "#{sources.length} source ranges encountered for annotation #{name}")
792
+ assert(target_ranges[name], "No target ranges for annotation #{name}")
793
+ target_ranges[name].map {|target_range| [sources.first, target_range]}
794
+ end, 1).
795
+ sort_by {|(_, target)| [target.start_pos.line, target.start_pos.offset]}.
796
+ each {|(s2, target)| map.add(s2, target)}
797
+ map
798
+ end
799
+
800
+ def assert_parses_with_mapping(source, css, options={})
801
+ options[:syntax] ||= :scss
802
+ input_filename = filename_for_test(options[:syntax])
803
+ mapping = build_mapping_from_annotations(source, css, input_filename)
804
+ source.gsub!(ANNOTATION_REGEX, "")
805
+ css.gsub!(ANNOTATION_REGEX, "")
806
+ rendered, sourcemap = render_with_sourcemap(source, options)
807
+ assert_equal css.rstrip, rendered.rstrip
808
+ assert_sourcemaps_equal source, css, mapping, sourcemap
809
+ end
810
+
811
+ def assert_positions_equal(expected, actual, lines, message = nil)
812
+ prefix = message ? message + ": " : ""
813
+ assert_equal(expected.line, actual.line, prefix +
814
+ "Expected #{expected.inspect} but was #{actual.inspect}")
815
+ assert_equal(expected.offset, actual.offset, prefix +
816
+ "Expected #{expected.inspect} but was #{actual.inspect}\n" +
817
+ lines[actual.line - 1] + "\n" + ("-" * (actual.offset - 1)) + "^")
818
+ end
819
+
820
+ def assert_ranges_equal(expected, actual, lines, prefix)
821
+ assert_positions_equal(expected.start_pos, actual.start_pos, lines, prefix + " start position")
822
+ assert_positions_equal(expected.end_pos, actual.end_pos, lines, prefix + " end position")
823
+ assert_equal(expected.file, actual.file)
824
+ end
825
+
826
+ def assert_sourcemaps_equal(source, css, expected, actual)
827
+ assert_equal(expected.data.length, actual.data.length, <<MESSAGE)
828
+ Wrong number of mappings. Expected:
829
+ #{dump_sourcemap_as_expectation(source, css, expected).gsub(/^/, '| ')}
830
+
831
+ Actual:
832
+ #{dump_sourcemap_as_expectation(source, css, actual).gsub(/^/, '| ')}
833
+ MESSAGE
834
+ source_lines = source.split("\n")
835
+ css_lines = css.split("\n")
836
+ expected.data.zip(actual.data) do |expected_mapping, actual_mapping|
837
+ assert_ranges_equal(expected_mapping.input, actual_mapping.input, source_lines, "Input")
838
+ assert_ranges_equal(expected_mapping.output, actual_mapping.output, css_lines, "Output")
839
+ end
840
+ end
841
+
842
+ def assert_parses_with_sourcemap(source, css, sourcemap_json, options={})
843
+ rendered, sourcemap = render_with_sourcemap(source, options)
844
+ css_path = options[:output] || "test.css"
845
+ sourcemap_path = Sass::Util.sourcemap_name(css_path)
846
+ rendered_json = sourcemap.to_json(:css_path => css_path, :sourcemap_path => sourcemap_path)
847
+
848
+ assert_equal css.rstrip, rendered.rstrip
849
+ assert_equal sourcemap_json.rstrip, rendered_json
850
+ end
851
+
852
+ def render_with_sourcemap(source, options={})
853
+ options[:syntax] ||= :scss
854
+ munge_filename options
855
+ engine = Sass::Engine.new(source, options)
856
+ engine.options[:cache] = false
857
+ sourcemap_path = Sass::Util.sourcemap_name(options[:output] || "test.css")
858
+ engine.render_with_sourcemap File.basename(sourcemap_path)
859
+ end
860
+
861
+ def dump_sourcemap_as_expectation(source, css, sourcemap)
862
+ mappings_to_annotations(source, sourcemap.data.map {|d| d.input}) + "\n\n" +
863
+ "=" * 20 + " maps to:\n\n" +
864
+ mappings_to_annotations(css, sourcemap.data.map {|d| d.output})
865
+ end
866
+
867
+ def mappings_to_annotations(source, ranges)
868
+ additional_offsets = Hash.new(0)
869
+ lines = source.split("\n")
870
+
871
+ add_annotation = lambda do |pos, str|
872
+ line_num = pos.line - 1
873
+ line = lines[line_num]
874
+ offset = pos.offset + additional_offsets[line_num] - 1
875
+ line << " " * (offset - line.length) if offset > line.length
876
+ line.insert(offset, str)
877
+ additional_offsets[line_num] += str.length
878
+ end
879
+
880
+ ranges.each_with_index do |range, i|
881
+ add_annotation[range.start_pos, "{{#{i + 1}}}"]
882
+ add_annotation[range.end_pos, "{{/#{i + 1}}}"]
883
+ end
884
+
885
+ return lines.join("\n")
886
+ end
887
+ end