haml_ejs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (358) hide show
  1. data/.yardopts +11 -0
  2. data/CONTRIBUTING +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +68 -0
  5. data/Rakefile +419 -0
  6. data/VERSION +1 -0
  7. data/VERSION_NAME +1 -0
  8. data/bin/haml +9 -0
  9. data/bin/html2haml +7 -0
  10. data/extra/update_watch.rb +13 -0
  11. data/init.rb +18 -0
  12. data/lib/haml.rb +49 -0
  13. data/lib/haml/buffer.rb +297 -0
  14. data/lib/haml/compiler.rb +486 -0
  15. data/lib/haml/engine.rb +312 -0
  16. data/lib/haml/error.rb +22 -0
  17. data/lib/haml/exec.rb +362 -0
  18. data/lib/haml/filters.rb +388 -0
  19. data/lib/haml/haml_ejs.rb +57 -0
  20. data/lib/haml/helpers.rb +608 -0
  21. data/lib/haml/helpers/action_view_extensions.rb +57 -0
  22. data/lib/haml/helpers/action_view_mods.rb +257 -0
  23. data/lib/haml/helpers/xss_mods.rb +165 -0
  24. data/lib/haml/html.rb +412 -0
  25. data/lib/haml/html/erb.rb +141 -0
  26. data/lib/haml/parser.rb +760 -0
  27. data/lib/haml/railtie.rb +19 -0
  28. data/lib/haml/root.rb +7 -0
  29. data/lib/haml/shared.rb +78 -0
  30. data/lib/haml/template.rb +99 -0
  31. data/lib/haml/template/options.rb +16 -0
  32. data/lib/haml/template/patch.rb +58 -0
  33. data/lib/haml/template/plugin.rb +123 -0
  34. data/lib/haml/util.rb +842 -0
  35. data/lib/haml/version.rb +109 -0
  36. data/lib/sass.rb +8 -0
  37. data/lib/sass/plugin.rb +10 -0
  38. data/lib/sass/rails2_shim.rb +9 -0
  39. data/lib/sass/rails3_shim.rb +16 -0
  40. data/rails/init.rb +1 -0
  41. data/test/benchmark.rb +91 -0
  42. data/test/gemfiles/Gemfile.rails-2.0.x +8 -0
  43. data/test/gemfiles/Gemfile.rails-2.0.x.lock +38 -0
  44. data/test/gemfiles/Gemfile.rails-2.1.x +8 -0
  45. data/test/gemfiles/Gemfile.rails-2.1.x.lock +38 -0
  46. data/test/gemfiles/Gemfile.rails-2.2.x +8 -0
  47. data/test/gemfiles/Gemfile.rails-2.2.x.lock +38 -0
  48. data/test/gemfiles/Gemfile.rails-2.3.x +8 -0
  49. data/test/gemfiles/Gemfile.rails-2.3.x.lock +40 -0
  50. data/test/gemfiles/Gemfile.rails-3.0.x +8 -0
  51. data/test/gemfiles/Gemfile.rails-3.0.x.lock +85 -0
  52. data/test/gemfiles/Gemfile.rails-3.1.x +8 -0
  53. data/test/gemfiles/Gemfile.rails-3.1.x.lock +98 -0
  54. data/test/gemfiles/Gemfile.rails-xss-2.3.x +9 -0
  55. data/test/gemfiles/Gemfile.rails-xss-2.3.x.lock +42 -0
  56. data/test/haml-ejs/haml-ejs_test.rb +22 -0
  57. data/test/haml-ejs/templates/conditional.input +3 -0
  58. data/test/haml-ejs/templates/conditional.output +3 -0
  59. data/test/haml-ejs/templates/conditional_and_interpolation.input +2 -0
  60. data/test/haml-ejs/templates/conditional_and_interpolation.output +3 -0
  61. data/test/haml-ejs/templates/conditional_else.input +5 -0
  62. data/test/haml-ejs/templates/conditional_else.output +5 -0
  63. data/test/haml-ejs/templates/conditional_else_elsif.input +7 -0
  64. data/test/haml-ejs/templates/conditional_else_elsif.output +7 -0
  65. data/test/haml-ejs/templates/conditional_elsif.input +5 -0
  66. data/test/haml-ejs/templates/conditional_elsif.output +5 -0
  67. data/test/haml-ejs/templates/conditional_unless.input +3 -0
  68. data/test/haml-ejs/templates/conditional_unless.output +3 -0
  69. data/test/haml-ejs/templates/conditional_unless_else.input +5 -0
  70. data/test/haml-ejs/templates/conditional_unless_else.output +5 -0
  71. data/test/haml-ejs/templates/conditional_unless_elsif_else.input +5 -0
  72. data/test/haml-ejs/templates/conditional_unless_elsif_else.output +5 -0
  73. data/test/haml-ejs/templates/interpolation.input +2 -0
  74. data/test/haml-ejs/templates/interpolation.output +1 -0
  75. data/test/haml-ejs/templates/iteration.input +2 -0
  76. data/test/haml-ejs/templates/iteration.output +3 -0
  77. data/test/haml-ejs/templates/suite.input +26 -0
  78. data/test/haml-ejs/templates/suite.output +27 -0
  79. data/test/haml/engine_test.rb +1925 -0
  80. data/test/haml/erb/_av_partial_1.erb +12 -0
  81. data/test/haml/erb/_av_partial_2.erb +8 -0
  82. data/test/haml/erb/action_view.erb +62 -0
  83. data/test/haml/erb/standard.erb +55 -0
  84. data/test/haml/helper_test.rb +454 -0
  85. data/test/haml/html2haml/erb_tests.rb +440 -0
  86. data/test/haml/html2haml_test.rb +336 -0
  87. data/test/haml/markaby/standard.mab +52 -0
  88. data/test/haml/mocks/article.rb +6 -0
  89. data/test/haml/results/content_for_layout.xhtml +12 -0
  90. data/test/haml/results/eval_suppressed.xhtml +9 -0
  91. data/test/haml/results/filters.xhtml +62 -0
  92. data/test/haml/results/helpers.xhtml +70 -0
  93. data/test/haml/results/helpful.xhtml +10 -0
  94. data/test/haml/results/just_stuff.xhtml +70 -0
  95. data/test/haml/results/list.xhtml +12 -0
  96. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  97. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  98. data/test/haml/results/original_engine.xhtml +20 -0
  99. data/test/haml/results/partial_layout.xhtml +5 -0
  100. data/test/haml/results/partials.xhtml +21 -0
  101. data/test/haml/results/render_layout.xhtml +3 -0
  102. data/test/haml/results/silent_script.xhtml +74 -0
  103. data/test/haml/results/standard.xhtml +162 -0
  104. data/test/haml/results/tag_parsing.xhtml +23 -0
  105. data/test/haml/results/very_basic.xhtml +5 -0
  106. data/test/haml/results/whitespace_handling.xhtml +89 -0
  107. data/test/haml/spec/README.md +97 -0
  108. data/test/haml/spec/lua_haml_spec.lua +30 -0
  109. data/test/haml/spec/ruby_haml_test.rb +19 -0
  110. data/test/haml/spec/tests.json +534 -0
  111. data/test/haml/spec_test.rb +44 -0
  112. data/test/haml/template_test.rb +419 -0
  113. data/test/haml/templates/_av_partial_1.haml +9 -0
  114. data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
  115. data/test/haml/templates/_av_partial_2.haml +5 -0
  116. data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
  117. data/test/haml/templates/_layout.erb +3 -0
  118. data/test/haml/templates/_layout_for_partial.haml +3 -0
  119. data/test/haml/templates/_partial.haml +8 -0
  120. data/test/haml/templates/_text_area.haml +3 -0
  121. data/test/haml/templates/action_view.haml +47 -0
  122. data/test/haml/templates/action_view_ugly.haml +47 -0
  123. data/test/haml/templates/breakage.haml +8 -0
  124. data/test/haml/templates/content_for_layout.haml +8 -0
  125. data/test/haml/templates/eval_suppressed.haml +11 -0
  126. data/test/haml/templates/filters.haml +66 -0
  127. data/test/haml/templates/helpers.haml +55 -0
  128. data/test/haml/templates/helpful.haml +11 -0
  129. data/test/haml/templates/just_stuff.haml +85 -0
  130. data/test/haml/templates/list.haml +12 -0
  131. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  132. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  133. data/test/haml/templates/original_engine.haml +17 -0
  134. data/test/haml/templates/partial_layout.haml +10 -0
  135. data/test/haml/templates/partialize.haml +1 -0
  136. data/test/haml/templates/partials.haml +12 -0
  137. data/test/haml/templates/render_layout.haml +2 -0
  138. data/test/haml/templates/silent_script.haml +40 -0
  139. data/test/haml/templates/standard.haml +43 -0
  140. data/test/haml/templates/standard_ugly.haml +43 -0
  141. data/test/haml/templates/tag_parsing.haml +21 -0
  142. data/test/haml/templates/very_basic.haml +4 -0
  143. data/test/haml/templates/whitespace_handling.haml +87 -0
  144. data/test/haml/util_test.rb +300 -0
  145. data/test/linked_rails.rb +42 -0
  146. data/test/test_helper.rb +75 -0
  147. data/vendor/sass/CONTRIBUTING +3 -0
  148. data/vendor/sass/MIT-LICENSE +20 -0
  149. data/vendor/sass/README.md +201 -0
  150. data/vendor/sass/Rakefile +339 -0
  151. data/vendor/sass/TODO +39 -0
  152. data/vendor/sass/VERSION +1 -0
  153. data/vendor/sass/VERSION_NAME +1 -0
  154. data/vendor/sass/bin/sass +8 -0
  155. data/vendor/sass/bin/sass-convert +7 -0
  156. data/vendor/sass/bin/scss +8 -0
  157. data/vendor/sass/doc-src/FAQ.md +35 -0
  158. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  159. data/vendor/sass/doc-src/SASS_CHANGELOG.md +2214 -0
  160. data/vendor/sass/doc-src/SASS_REFERENCE.md +1957 -0
  161. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  162. data/vendor/sass/ext/extconf.rb +10 -0
  163. data/vendor/sass/extra/update_watch.rb +13 -0
  164. data/vendor/sass/init.rb +18 -0
  165. data/vendor/sass/lib/sass.rb +72 -0
  166. data/vendor/sass/lib/sass/cache_stores.rb +15 -0
  167. data/vendor/sass/lib/sass/cache_stores/base.rb +84 -0
  168. data/vendor/sass/lib/sass/cache_stores/chain.rb +33 -0
  169. data/vendor/sass/lib/sass/cache_stores/filesystem.rb +58 -0
  170. data/vendor/sass/lib/sass/cache_stores/memory.rb +47 -0
  171. data/vendor/sass/lib/sass/cache_stores/null.rb +25 -0
  172. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  173. data/vendor/sass/lib/sass/css.rb +294 -0
  174. data/vendor/sass/lib/sass/engine.rb +862 -0
  175. data/vendor/sass/lib/sass/environment.rb +155 -0
  176. data/vendor/sass/lib/sass/error.rb +201 -0
  177. data/vendor/sass/lib/sass/exec.rb +659 -0
  178. data/vendor/sass/lib/sass/importers.rb +22 -0
  179. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  180. data/vendor/sass/lib/sass/importers/filesystem.rb +144 -0
  181. data/vendor/sass/lib/sass/less.rb +382 -0
  182. data/vendor/sass/lib/sass/plugin.rb +136 -0
  183. data/vendor/sass/lib/sass/plugin/compiler.rb +358 -0
  184. data/vendor/sass/lib/sass/plugin/configuration.rb +125 -0
  185. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  186. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  187. data/vendor/sass/lib/sass/plugin/rack.rb +60 -0
  188. data/vendor/sass/lib/sass/plugin/rails.rb +47 -0
  189. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +173 -0
  190. data/vendor/sass/lib/sass/railtie.rb +9 -0
  191. data/vendor/sass/lib/sass/repl.rb +58 -0
  192. data/vendor/sass/lib/sass/root.rb +7 -0
  193. data/vendor/sass/lib/sass/script.rb +40 -0
  194. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  195. data/vendor/sass/lib/sass/script/color.rb +480 -0
  196. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  197. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  198. data/vendor/sass/lib/sass/script/funcall.rb +162 -0
  199. data/vendor/sass/lib/sass/script/functions.rb +1343 -0
  200. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  201. data/vendor/sass/lib/sass/script/lexer.rb +334 -0
  202. data/vendor/sass/lib/sass/script/list.rb +76 -0
  203. data/vendor/sass/lib/sass/script/literal.rb +245 -0
  204. data/vendor/sass/lib/sass/script/node.rb +91 -0
  205. data/vendor/sass/lib/sass/script/number.rb +429 -0
  206. data/vendor/sass/lib/sass/script/operation.rb +91 -0
  207. data/vendor/sass/lib/sass/script/parser.rb +467 -0
  208. data/vendor/sass/lib/sass/script/string.rb +51 -0
  209. data/vendor/sass/lib/sass/script/string_interpolation.rb +94 -0
  210. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  211. data/vendor/sass/lib/sass/script/variable.rb +54 -0
  212. data/vendor/sass/lib/sass/scss.rb +17 -0
  213. data/vendor/sass/lib/sass/scss/css_parser.rb +46 -0
  214. data/vendor/sass/lib/sass/scss/parser.rb +920 -0
  215. data/vendor/sass/lib/sass/scss/rx.rb +127 -0
  216. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  217. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  218. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  219. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  220. data/vendor/sass/lib/sass/selector.rb +361 -0
  221. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  222. data/vendor/sass/lib/sass/selector/comma_sequence.rb +81 -0
  223. data/vendor/sass/lib/sass/selector/sequence.rb +233 -0
  224. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  225. data/vendor/sass/lib/sass/selector/simple_sequence.rb +134 -0
  226. data/vendor/sass/lib/sass/shared.rb +78 -0
  227. data/vendor/sass/lib/sass/tree/charset_node.rb +22 -0
  228. data/vendor/sass/lib/sass/tree/comment_node.rb +77 -0
  229. data/vendor/sass/lib/sass/tree/debug_node.rb +18 -0
  230. data/vendor/sass/lib/sass/tree/directive_node.rb +23 -0
  231. data/vendor/sass/lib/sass/tree/each_node.rb +24 -0
  232. data/vendor/sass/lib/sass/tree/extend_node.rb +29 -0
  233. data/vendor/sass/lib/sass/tree/for_node.rb +36 -0
  234. data/vendor/sass/lib/sass/tree/function_node.rb +27 -0
  235. data/vendor/sass/lib/sass/tree/if_node.rb +65 -0
  236. data/vendor/sass/lib/sass/tree/import_node.rb +68 -0
  237. data/vendor/sass/lib/sass/tree/media_node.rb +32 -0
  238. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +27 -0
  239. data/vendor/sass/lib/sass/tree/mixin_node.rb +32 -0
  240. data/vendor/sass/lib/sass/tree/node.rb +204 -0
  241. data/vendor/sass/lib/sass/tree/prop_node.rb +155 -0
  242. data/vendor/sass/lib/sass/tree/return_node.rb +18 -0
  243. data/vendor/sass/lib/sass/tree/root_node.rb +28 -0
  244. data/vendor/sass/lib/sass/tree/rule_node.rb +129 -0
  245. data/vendor/sass/lib/sass/tree/variable_node.rb +30 -0
  246. data/vendor/sass/lib/sass/tree/visitors/base.rb +75 -0
  247. data/vendor/sass/lib/sass/tree/visitors/check_nesting.rb +134 -0
  248. data/vendor/sass/lib/sass/tree/visitors/convert.rb +255 -0
  249. data/vendor/sass/lib/sass/tree/visitors/cssize.rb +175 -0
  250. data/vendor/sass/lib/sass/tree/visitors/perform.rb +301 -0
  251. data/vendor/sass/lib/sass/tree/visitors/to_css.rb +216 -0
  252. data/vendor/sass/lib/sass/tree/warn_node.rb +18 -0
  253. data/vendor/sass/lib/sass/tree/while_node.rb +18 -0
  254. data/vendor/sass/lib/sass/util.rb +669 -0
  255. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  256. data/vendor/sass/lib/sass/version.rb +112 -0
  257. data/vendor/sass/rails/init.rb +1 -0
  258. data/vendor/sass/sass.gemspec +32 -0
  259. data/vendor/sass/test/sass/cache_test.rb +74 -0
  260. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  261. data/vendor/sass/test/sass/conversion_test.rb +1203 -0
  262. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  263. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  264. data/vendor/sass/test/sass/engine_test.rb +2469 -0
  265. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  266. data/vendor/sass/test/sass/functions_test.rb +1025 -0
  267. data/vendor/sass/test/sass/importer_test.rb +82 -0
  268. data/vendor/sass/test/sass/less_conversion_test.rb +653 -0
  269. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  270. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  271. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  272. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  273. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  274. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  275. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  276. data/vendor/sass/test/sass/plugin_test.rb +469 -0
  277. data/vendor/sass/test/sass/results/alt.css +4 -0
  278. data/vendor/sass/test/sass/results/basic.css +9 -0
  279. data/vendor/sass/test/sass/results/compact.css +5 -0
  280. data/vendor/sass/test/sass/results/complex.css +86 -0
  281. data/vendor/sass/test/sass/results/compressed.css +1 -0
  282. data/vendor/sass/test/sass/results/expanded.css +19 -0
  283. data/vendor/sass/test/sass/results/if.css +3 -0
  284. data/vendor/sass/test/sass/results/import.css +31 -0
  285. data/vendor/sass/test/sass/results/import_charset.css +4 -0
  286. data/vendor/sass/test/sass/results/import_charset_1_8.css +4 -0
  287. data/vendor/sass/test/sass/results/import_charset_ibm866.css +4 -0
  288. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  289. data/vendor/sass/test/sass/results/mixins.css +95 -0
  290. data/vendor/sass/test/sass/results/multiline.css +24 -0
  291. data/vendor/sass/test/sass/results/nested.css +22 -0
  292. data/vendor/sass/test/sass/results/options.css +1 -0
  293. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  294. data/vendor/sass/test/sass/results/script.css +16 -0
  295. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  296. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  297. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  298. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  299. data/vendor/sass/test/sass/results/units.css +11 -0
  300. data/vendor/sass/test/sass/results/warn.css +0 -0
  301. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  302. data/vendor/sass/test/sass/script_conversion_test.rb +283 -0
  303. data/vendor/sass/test/sass/script_test.rb +496 -0
  304. data/vendor/sass/test/sass/scss/css_test.rb +916 -0
  305. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  306. data/vendor/sass/test/sass/scss/scss_test.rb +1249 -0
  307. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  308. data/vendor/sass/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  309. data/vendor/sass/test/sass/templates/_imported_charset_utf8.sass +4 -0
  310. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  311. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  312. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  313. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  314. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  315. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  316. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  317. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  318. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  319. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  320. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  321. data/vendor/sass/test/sass/templates/if.sass +11 -0
  322. data/vendor/sass/test/sass/templates/import.sass +12 -0
  323. data/vendor/sass/test/sass/templates/import_charset.sass +7 -0
  324. data/vendor/sass/test/sass/templates/import_charset_1_8.sass +4 -0
  325. data/vendor/sass/test/sass/templates/import_charset_ibm866.sass +9 -0
  326. data/vendor/sass/test/sass/templates/importee.less +2 -0
  327. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  328. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  329. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  330. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  331. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  332. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  333. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  334. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  335. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  336. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  337. data/vendor/sass/test/sass/templates/nested_import.sass +2 -0
  338. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  339. data/vendor/sass/test/sass/templates/options.sass +2 -0
  340. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  341. data/vendor/sass/test/sass/templates/script.sass +101 -0
  342. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  343. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  344. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  345. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  346. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  347. data/vendor/sass/test/sass/templates/units.sass +11 -0
  348. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  349. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  350. data/vendor/sass/test/sass/test_helper.rb +8 -0
  351. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  352. data/vendor/sass/test/sass/util_test.rb +254 -0
  353. data/vendor/sass/test/test_helper.rb +69 -0
  354. data/vendor/sass/yard/callbacks.rb +29 -0
  355. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  356. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  357. data/vendor/sass/yard/inherited_hash.rb +41 -0
  358. metadata +458 -0
@@ -0,0 +1,2469 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'test_helper'
4
+ require 'sass/test_helper'
5
+ require 'sass/engine'
6
+ require 'stringio'
7
+ require 'mock_importer'
8
+ require 'pathname'
9
+
10
+ module Sass::Script::Functions::UserFunctions
11
+ def option(name)
12
+ Sass::Script::String.new(@options[name.value.to_sym].to_s)
13
+ end
14
+ end
15
+
16
+ class SassEngineTest < Test::Unit::TestCase
17
+ FAKE_FILE_NAME = __FILE__.gsub(/rb$/,"sass")
18
+ # A map of erroneous Sass documents to the error messages they should produce.
19
+ # The error messages may be arrays;
20
+ # if so, the second element should be the line number that should be reported for the error.
21
+ # If this isn't provided, the tests will assume the line number should be the last line of the document.
22
+ EXCEPTION_MAP = {
23
+ "$a: 1 + " => 'Invalid CSS after "1 +": expected expression (e.g. 1px, bold), was ""',
24
+ "$a: 1 + 2 +" => 'Invalid CSS after "1 + 2 +": expected expression (e.g. 1px, bold), was ""',
25
+ "$a: 1 + 2 + %" => 'Invalid CSS after "1 + 2 + ": expected expression (e.g. 1px, bold), was "%"',
26
+ "$a: foo(\"bar\"" => 'Invalid CSS after "foo("bar"": expected ")", was ""',
27
+ "$a: 1 }" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}"',
28
+ "$a: 1 }foo\"" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}foo""',
29
+ ":" => 'Invalid property: ":".',
30
+ ": a" => 'Invalid property: ": a".',
31
+ "a\n :b" => <<MSG,
32
+ Invalid property: ":b" (no value).
33
+ If ":b" should be a selector, use "\\:b" instead.
34
+ MSG
35
+ "a\n b:" => 'Invalid property: "b:" (no value).',
36
+ "a\n :b: c" => 'Invalid property: ":b: c".',
37
+ "a\n :b:c d" => 'Invalid property: ":b:c d".',
38
+ "a\n :b c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
39
+ "a\n b: c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
40
+ ".foo ^bar\n a: b" => ['Invalid CSS after ".foo ": expected selector, was "^bar"', 1],
41
+ "a\n @extend .foo ^bar" => 'Invalid CSS after ".foo ": expected selector, was "^bar"',
42
+ "a: b" => 'Properties are only allowed within rules, directives, or other properties.',
43
+ ":a b" => 'Properties are only allowed within rules, directives, or other properties.',
44
+ "$" => 'Invalid variable: "$".',
45
+ "$a" => 'Invalid variable: "$a".',
46
+ "$ a" => 'Invalid variable: "$ a".',
47
+ "$a b" => 'Invalid variable: "$a b".',
48
+ "$a: 1b + 2c" => "Incompatible units: 'c' and 'b'.",
49
+ "$a: 1b < 2c" => "Incompatible units: 'c' and 'b'.",
50
+ "$a: 1b > 2c" => "Incompatible units: 'c' and 'b'.",
51
+ "$a: 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
52
+ "$a: 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
53
+ "a\n b: 1b * 2c" => "2b*c isn't a valid CSS value.",
54
+ "a\n b: 1b % 2c" => "Cannot modulo by a number with units: 2c.",
55
+ "$a: 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).",
56
+ "$a: #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).",
57
+ "& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
58
+ "a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.",
59
+ "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
60
+ "@import foo.sass" => "File to import not found or unreadable: foo.sass.",
61
+ "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
62
+ "@import foo.sass" => <<MSG,
63
+ File to import not found or unreadable: foo.sass.
64
+ Load path: .
65
+ MSG
66
+ "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
67
+ "foo\n @import foo.css" => "CSS import directives may only be used at the root of a document.",
68
+ "@if true\n @import foo" => "Import directives may not be used within control directives or mixins.",
69
+ "@mixin foo\n @import foo" => "Import directives may not be used within control directives or mixins.",
70
+ '$foo: "bar" "baz" !' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "!"},
71
+ '$foo: "bar" "baz" $' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "$"},
72
+ "=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
73
+ "=foo\n :color red\n.bar\n +bang_bop" => "Undefined mixin 'bang_bop'.",
74
+ "=foo\n :color red\n.bar\n +bang-bop" => "Undefined mixin 'bang-bop'.",
75
+ ".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2],
76
+ "=foo\n :color red\n.bar\n +foo\n :color red" => "Illegal nesting: Nothing may be nested beneath mixin directives.",
77
+ " a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
78
+ " \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
79
+ "a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3],
80
+ "a\n b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 4],
81
+ "a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs.", 3],
82
+ "a\n b: c\n b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 3],
83
+ "a\n b: c\n a\n d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 4],
84
+ "a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
85
+ "a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
86
+ "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
87
+ "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""',
88
+ "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"',
89
+ "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"',
90
+ "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"',
91
+ "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"',
92
+ "=foo\n bar: baz\n+foo" => ["Properties are only allowed within rules, directives, or other properties.", 2],
93
+ "a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
94
+ "=a($b: 1, $c)" => "Required argument $c must come before any optional arguments.",
95
+ "=a($b: 1)\n a: $b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
96
+ "=a($b: 1)\n a: $b\ndiv\n +a(1,$c: 3)" => "Mixin a doesn't have an argument named $c",
97
+ "=a($b)\n a: $b\ndiv\n +a" => "Mixin a is missing parameter $b.",
98
+ "@function foo()\n 1 + 2" => "Functions can only contain variable declarations and control directives.",
99
+ "@function foo()\n foo: bar" => "Functions can only contain variable declarations and control directives.",
100
+ "@function foo()\n foo: bar\n @return 3" => ["Functions can only contain variable declarations and control directives.", 2],
101
+ "@function foo\n @return 1" => ['Invalid CSS after "": expected "(", was ""', 1],
102
+ "@function foo(\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ""', 1],
103
+ "@function foo(b)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "b)"', 1],
104
+ "@function foo(,)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ",)"', 1],
105
+ "@function foo($)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', 1],
106
+ "@function foo()\n @return" => 'Invalid @return: expected expression.',
107
+ "@function foo()\n @return 1\n $var: val" => 'Illegal nesting: Nothing may be nested beneath return directives.',
108
+ "foo\n @function bar()\n @return 1" => ['Functions may only be defined at the root of a document.', 2],
109
+ "@function foo($a)\n @return 1\na\n b: foo()" => 'Function foo is missing parameter $a.',
110
+ "@function foo()\n @return 1\na\n b: foo(2)" => 'Wrong number of arguments (1 for 0) for `foo\'',
111
+ "@return 1" => '@return may only be used within a function.',
112
+ "@if true\n @return 1" => '@return may only be used within a function.',
113
+ "@mixin foo\n @return 1\n@include foo" => ['@return may only be used within a function.', 2],
114
+ "@else\n a\n b: c" => ["@else must come after @if.", 1],
115
+ "@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
116
+ "@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
117
+ "a\n $b: 12\nc\n d: $b" => 'Undefined variable: "$b".',
118
+ "=foo\n $b: 12\nc\n +foo\n d: $b" => 'Undefined variable: "$b".',
119
+ "c\n d: $b-foo" => 'Undefined variable: "$b-foo".',
120
+ "c\n d: $b_foo" => 'Undefined variable: "$b_foo".',
121
+ '@for $a from "foo" to 1' => '"foo" is not an integer.',
122
+ '@for $a from 1 to "2"' => '"2" is not an integer.',
123
+ '@for $a from 1 to "foo"' => '"foo" is not an integer.',
124
+ '@for $a from 1 to 1.232323' => '1.232 is not an integer.',
125
+ '@for $a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
126
+ '@if' => "Invalid if directive '@if': expected expression.",
127
+ '@while' => "Invalid while directive '@while': expected expression.",
128
+ '@debug' => "Invalid debug directive '@debug': expected expression.",
129
+ %Q{@debug "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath debug directives.",
130
+ '@warn' => "Invalid warn directive '@warn': expected expression.",
131
+ %Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.",
132
+ "/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.",
133
+ '+foo(1 + 1: 2)' => 'Invalid CSS after "(1 + 1": expected comma, was ": 2)"',
134
+ '+foo($var: )' => 'Invalid CSS after "($var: ": expected mixin argument, was ")"',
135
+ '+foo($var: a, $var: b)' => 'Keyword argument "$var" passed more than once',
136
+ '+foo($var-var: a, $var_var: b)' => 'Keyword argument "$var-var" passed more than once',
137
+ '+foo($var_var: a, $var-var: b)' => 'Keyword argument "$var_var" passed more than once',
138
+ "a\n b: foo(1 + 1: 2)" => 'Invalid CSS after "foo(1 + 1": expected comma, was ": 2)"',
139
+ "a\n b: foo($var: )" => 'Invalid CSS after "foo($var: ": expected function argument, was ")"',
140
+ "a\n b: foo($var: a, $var: b)" => 'Keyword argument "$var" passed more than once',
141
+ "a\n b: foo($var-var: a, $var_var: b)" => 'Keyword argument "$var-var" passed more than once',
142
+ "a\n b: foo($var_var: a, $var-var: b)" => 'Keyword argument "$var_var" passed more than once',
143
+ "@if foo\n @extend .bar" => ["Extend directives may only be used within rules.", 2],
144
+ "$var: true\n@while $var\n @extend .bar\n $var: false" => ["Extend directives may only be used within rules.", 3],
145
+ "@for $i from 0 to 1\n @extend .bar" => ["Extend directives may only be used within rules.", 2],
146
+ "@mixin foo\n @extend .bar\n@include foo" => ["Extend directives may only be used within rules.", 2],
147
+
148
+ # Regression tests
149
+ "a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
150
+ "& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
151
+ "a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
152
+ }
153
+
154
+ def teardown
155
+ clean_up_sassc
156
+ end
157
+
158
+ def test_basic_render
159
+ renders_correctly "basic", { :style => :compact }
160
+ end
161
+
162
+ def test_empty_render
163
+ assert_equal "", render("")
164
+ end
165
+
166
+ def test_multiple_calls_to_render
167
+ sass = Sass::Engine.new("a\n b: c")
168
+ assert_equal sass.render, sass.render
169
+ end
170
+
171
+ def test_alternate_styles
172
+ renders_correctly "expanded", { :style => :expanded }
173
+ renders_correctly "compact", { :style => :compact }
174
+ renders_correctly "nested", { :style => :nested }
175
+ renders_correctly "compressed", { :style => :compressed }
176
+ end
177
+
178
+ def test_compile
179
+ assert_equal "div { hello: world; }\n", Sass.compile("$who: world\ndiv\n hello: $who", :syntax => :sass, :style => :compact)
180
+ assert_equal "div { hello: world; }\n", Sass.compile("$who: world; div { hello: $who }", :style => :compact)
181
+ end
182
+
183
+ def test_compile_file
184
+ FileUtils.mkdir_p(absolutize("tmp"))
185
+ open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
186
+ open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
187
+ assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.sass"), :style => :compact)
188
+ assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.scss"), :style => :compact)
189
+ ensure
190
+ FileUtils.rm_rf(absolutize("tmp"))
191
+ end
192
+
193
+ def test_compile_file_to_css_file
194
+ FileUtils.mkdir_p(absolutize("tmp"))
195
+ open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
196
+ open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
197
+ Sass.compile_file(absolutize("tmp/test_compile_file.sass"), absolutize("tmp/test_compile_file_sass.css"), :style => :compact)
198
+ Sass.compile_file(absolutize("tmp/test_compile_file.scss"), absolutize("tmp/test_compile_file_scss.css"), :style => :compact)
199
+ assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_sass.css"))
200
+ assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_scss.css"))
201
+ ensure
202
+ FileUtils.rm_rf(absolutize("tmp"))
203
+ end
204
+
205
+ def test_flexible_tabulation
206
+ assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
207
+ render("p\n a: b\n q\n c: d\n"))
208
+ assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
209
+ render("p\n\ta: b\n\tq\n\t\tc: d\n"))
210
+ end
211
+
212
+ EXCEPTION_MAP.each do |key, value|
213
+ define_method("test_exception (#{key.inspect})") do
214
+ line = 10
215
+ begin
216
+ silence_warnings {Sass::Engine.new(key, :filename => FAKE_FILE_NAME, :line => line).render}
217
+ rescue Sass::SyntaxError => err
218
+ value = [value] unless value.is_a?(Array)
219
+
220
+ assert_equal(value.first.rstrip, err.message, "Line: #{key}")
221
+ assert_equal(FAKE_FILE_NAME, err.sass_filename)
222
+ assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
223
+ assert_match(/#{Regexp.escape(FAKE_FILE_NAME)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
224
+ else
225
+ assert(false, "Exception not raised for\n#{key}")
226
+ end
227
+ end
228
+ end
229
+
230
+ def test_exception_line
231
+ to_render = <<SASS
232
+ rule
233
+ :prop val
234
+ // comment!
235
+
236
+ :broken
237
+ SASS
238
+ begin
239
+ Sass::Engine.new(to_render).render
240
+ rescue Sass::SyntaxError => err
241
+ assert_equal(5, err.sass_line)
242
+ else
243
+ assert(false, "Exception not raised for '#{to_render}'!")
244
+ end
245
+ end
246
+
247
+ def test_exception_location
248
+ to_render = <<SASS
249
+ rule
250
+ :prop val
251
+ // comment!
252
+
253
+ :broken
254
+ SASS
255
+ begin
256
+ Sass::Engine.new(to_render, :filename => FAKE_FILE_NAME, :line => (__LINE__-7)).render
257
+ rescue Sass::SyntaxError => err
258
+ assert_equal(FAKE_FILE_NAME, err.sass_filename)
259
+ assert_equal((__LINE__-6), err.sass_line)
260
+ else
261
+ assert(false, "Exception not raised for '#{to_render}'!")
262
+ end
263
+ end
264
+
265
+ def test_imported_exception
266
+ [1, 2, 3, 4].each do |i|
267
+ begin
268
+ Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
269
+ rescue Sass::SyntaxError => err
270
+ assert_equal(2, err.sass_line)
271
+ assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
272
+
273
+ assert_hash_has(err.sass_backtrace.first,
274
+ :filename => err.sass_filename, :line => err.sass_line)
275
+
276
+ assert_nil(err.sass_backtrace[1][:filename])
277
+ assert_equal(1, err.sass_backtrace[1][:line])
278
+
279
+ assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
280
+ assert_equal("(sass):1", err.backtrace[1])
281
+ else
282
+ assert(false, "Exception not raised for imported template: bork#{i}")
283
+ end
284
+ end
285
+ end
286
+
287
+ def test_double_imported_exception
288
+ [1, 2, 3, 4].each do |i|
289
+ begin
290
+ Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
291
+ rescue Sass::SyntaxError => err
292
+ assert_equal(2, err.sass_line)
293
+ assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
294
+
295
+ assert_hash_has(err.sass_backtrace.first,
296
+ :filename => err.sass_filename, :line => err.sass_line)
297
+
298
+ assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
299
+ assert_equal(2, err.sass_backtrace[1][:line])
300
+
301
+ assert_nil(err.sass_backtrace[2][:filename])
302
+ assert_equal(1, err.sass_backtrace[2][:line])
303
+
304
+ assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
305
+ assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
306
+ assert_equal("(sass):1", err.backtrace[2])
307
+ else
308
+ assert(false, "Exception not raised for imported template: bork#{i}")
309
+ end
310
+ end
311
+ end
312
+
313
+ def test_mixin_exception
314
+ render(<<SASS)
315
+ =error-mixin($a)
316
+ color: $a * 1em * 1px
317
+
318
+ =outer-mixin($a)
319
+ +error-mixin($a)
320
+
321
+ .error
322
+ +outer-mixin(12)
323
+ SASS
324
+ assert(false, "Exception not raised")
325
+ rescue Sass::SyntaxError => err
326
+ assert_equal(2, err.sass_line)
327
+ assert_equal(filename_for_test, err.sass_filename)
328
+ assert_equal("error-mixin", err.sass_mixin)
329
+
330
+ assert_hash_has(err.sass_backtrace.first, :line => err.sass_line,
331
+ :filename => err.sass_filename, :mixin => err.sass_mixin)
332
+ assert_hash_has(err.sass_backtrace[1], :line => 5,
333
+ :filename => filename_for_test, :mixin => "outer-mixin")
334
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
335
+ :filename => filename_for_test, :mixin => nil)
336
+
337
+ assert_equal("#{filename_for_test}:2:in `error-mixin'", err.backtrace.first)
338
+ assert_equal("#{filename_for_test}:5:in `outer-mixin'", err.backtrace[1])
339
+ assert_equal("#{filename_for_test}:8", err.backtrace[2])
340
+ end
341
+
342
+ def test_mixin_callsite_exception
343
+ render(<<SASS)
344
+ =one-arg-mixin($a)
345
+ color: $a
346
+
347
+ =outer-mixin($a)
348
+ +one-arg-mixin($a, 12)
349
+
350
+ .error
351
+ +outer-mixin(12)
352
+ SASS
353
+ assert(false, "Exception not raised")
354
+ rescue Sass::SyntaxError => err
355
+ assert_hash_has(err.sass_backtrace.first, :line => 5,
356
+ :filename => filename_for_test, :mixin => "one-arg-mixin")
357
+ assert_hash_has(err.sass_backtrace[1], :line => 5,
358
+ :filename => filename_for_test, :mixin => "outer-mixin")
359
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
360
+ :filename => filename_for_test, :mixin => nil)
361
+ end
362
+
363
+ def test_mixin_exception_cssize
364
+ render(<<SASS)
365
+ =parent-ref-mixin
366
+ & foo
367
+ a: b
368
+
369
+ =outer-mixin
370
+ +parent-ref-mixin
371
+
372
+ +outer-mixin
373
+ SASS
374
+ assert(false, "Exception not raised")
375
+ rescue Sass::SyntaxError => err
376
+ assert_hash_has(err.sass_backtrace.first, :line => 2,
377
+ :filename => filename_for_test, :mixin => "parent-ref-mixin")
378
+ assert_hash_has(err.sass_backtrace[1], :line => 6,
379
+ :filename => filename_for_test, :mixin => "outer-mixin")
380
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
381
+ :filename => filename_for_test, :mixin => nil)
382
+ end
383
+
384
+ def test_mixin_and_import_exception
385
+ Sass::Engine.new("@import nested_mixin_bork", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
386
+ assert(false, "Exception not raised")
387
+ rescue Sass::SyntaxError => err
388
+ assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace.first[:filename])
389
+ assert_hash_has(err.sass_backtrace.first, :mixin => "error-mixin", :line => 4)
390
+
391
+ assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[1][:filename])
392
+ assert_hash_has(err.sass_backtrace[1], :mixin => "outer-mixin", :line => 2)
393
+
394
+ assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[2][:filename])
395
+ assert_hash_has(err.sass_backtrace[2], :mixin => nil, :line => 5)
396
+
397
+ assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace[3][:filename])
398
+ assert_hash_has(err.sass_backtrace[3], :mixin => nil, :line => 6)
399
+
400
+ assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1)
401
+ end
402
+
403
+ def test_basic_mixin_loop_exception
404
+ render <<SASS
405
+ @mixin foo
406
+ @include foo
407
+ @include foo
408
+ SASS
409
+ assert(false, "Exception not raised")
410
+ rescue Sass::SyntaxError => err
411
+ assert_equal("An @include loop has been found: foo includes itself", err.message)
412
+ assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 2)
413
+ end
414
+
415
+ def test_double_mixin_loop_exception
416
+ render <<SASS
417
+ @mixin foo
418
+ @include bar
419
+ @mixin bar
420
+ @include foo
421
+ @include foo
422
+ SASS
423
+ assert(false, "Exception not raised")
424
+ rescue Sass::SyntaxError => err
425
+ assert_equal(<<MESSAGE.rstrip, err.message)
426
+ An @include loop has been found:
427
+ foo includes bar
428
+ bar includes foo
429
+ MESSAGE
430
+ assert_hash_has(err.sass_backtrace[0], :mixin => "bar", :line => 4)
431
+ assert_hash_has(err.sass_backtrace[1], :mixin => "foo", :line => 2)
432
+ end
433
+
434
+ def test_deep_mixin_loop_exception
435
+ render <<SASS
436
+ @mixin foo
437
+ @include bar
438
+
439
+ @mixin bar
440
+ @include baz
441
+
442
+ @mixin baz
443
+ @include foo
444
+
445
+ @include foo
446
+ SASS
447
+ assert(false, "Exception not raised")
448
+ rescue Sass::SyntaxError => err
449
+ assert_equal(<<MESSAGE.rstrip, err.message)
450
+ An @include loop has been found:
451
+ foo includes bar
452
+ bar includes baz
453
+ baz includes foo
454
+ MESSAGE
455
+ assert_hash_has(err.sass_backtrace[0], :mixin => "baz", :line => 8)
456
+ assert_hash_has(err.sass_backtrace[1], :mixin => "bar", :line => 5)
457
+ assert_hash_has(err.sass_backtrace[2], :mixin => "foo", :line => 2)
458
+ end
459
+
460
+ def test_exception_css_with_offset
461
+ opts = {:full_exception => true, :line => 362}
462
+ render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
463
+ rescue Sass::SyntaxError => e
464
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..15].join("\n"))
465
+ /*
466
+ Syntax error: Invalid property: "e:" (no value).
467
+ on line 383 of test_exception_css_with_offset_inline.sass
468
+
469
+ 378: a
470
+ 379: b: c
471
+ 380: a
472
+ 381: b: c
473
+ 382: d
474
+ 383: e:
475
+ 384: f
476
+ 385: g: h
477
+ 386: f
478
+ 387: g: h
479
+ 388: f
480
+ CSS
481
+ else
482
+ assert(false, "Exception not raised for test_exception_css_with_offset")
483
+ end
484
+
485
+ def test_exception_css_with_mixins
486
+ opts = {:full_exception => true}
487
+ render(<<SASS, opts)
488
+ =error-mixin($a)
489
+ color: $a * 1em * 1px
490
+
491
+ =outer-mixin($a)
492
+ +error-mixin($a)
493
+
494
+ .error
495
+ +outer-mixin(12)
496
+ SASS
497
+ rescue Sass::SyntaxError => e
498
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..13].join("\n"))
499
+ /*
500
+ Syntax error: 12em*px isn't a valid CSS value.
501
+ on line 2 of test_exception_css_with_mixins_inline.sass, in `error-mixin'
502
+ from line 5 of test_exception_css_with_mixins_inline.sass, in `outer-mixin'
503
+ from line 8 of test_exception_css_with_mixins_inline.sass
504
+
505
+ 1: =error-mixin($a)
506
+ 2: color: $a * 1em * 1px
507
+ 3:
508
+ 4: =outer-mixin($a)
509
+ 5: +error-mixin($a)
510
+ 6:
511
+ 7: .error
512
+ CSS
513
+ else
514
+ assert(false, "Exception not raised")
515
+ end
516
+
517
+ def test_cssize_exception_css
518
+ opts = {:full_exception => true}
519
+ render(<<SASS, opts)
520
+ .filler
521
+ stuff: "stuff!"
522
+
523
+ a: b
524
+
525
+ .more.filler
526
+ a: b
527
+ SASS
528
+ rescue Sass::SyntaxError => e
529
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..11].join("\n"))
530
+ /*
531
+ Syntax error: Properties are only allowed within rules, directives, or other properties.
532
+ on line 4 of test_cssize_exception_css_inline.sass
533
+
534
+ 1: .filler
535
+ 2: stuff: "stuff!"
536
+ 3:
537
+ 4: a: b
538
+ 5:
539
+ 6: .more.filler
540
+ 7: a: b
541
+ CSS
542
+ else
543
+ assert(false, "Exception not raised")
544
+ end
545
+
546
+ def test_css_import
547
+ assert_equal("@import url(./fonts.css);\n", render("@import \"./fonts.css\""))
548
+ end
549
+
550
+ def test_http_import
551
+ assert_equal("@import url(http://fonts.googleapis.com/css?family=Droid+Sans);\n",
552
+ render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\""))
553
+ end
554
+
555
+ def test_http_import_with_interpolation
556
+ assert_equal("@import url(http://fonts.googleapis.com/css?family=Droid+Sans);\n",
557
+ render("$family: unquote(\"Droid+Sans\")\n@import \"http://fonts.googleapis.com/css?family=\#{$family}\"\n"))
558
+ assert_equal("@import url(\"http://fonts.googleapis.com/css?family=Droid+Sans\");\n",
559
+ render("$family: unquote(\"Droid+Sans\")\n@import url(\"http://fonts.googleapis.com/css?family=\#{$family}\")\n"))
560
+ end
561
+
562
+ def test_url_import
563
+ assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass)"))
564
+ end
565
+
566
+ def test_sass_import
567
+ sassc_file = sassc_path("importee")
568
+ assert !File.exists?(sassc_file)
569
+ renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
570
+ assert File.exists?(sassc_file)
571
+ end
572
+
573
+ def test_sass_pathname_import
574
+ sassc_file = sassc_path("importee")
575
+ assert !File.exists?(sassc_file)
576
+ renders_correctly("import",
577
+ :style => :compact,
578
+ :load_paths => [Pathname.new(File.dirname(__FILE__) + "/templates")])
579
+ assert File.exists?(sassc_file)
580
+ end
581
+
582
+ def test_nonexistent_extensionless_import
583
+ assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
584
+ File to import not found or unreadable: nonexistent.
585
+ Load path: .
586
+ ERR
587
+ assert_equal("@import url(nonexistent.css);\n", render("@import nonexistent"))
588
+ end
589
+ end
590
+
591
+ def test_no_cache
592
+ assert !File.exists?(sassc_path("importee"))
593
+ renders_correctly("import", {
594
+ :style => :compact, :cache => false,
595
+ :load_paths => [File.dirname(__FILE__) + "/templates"],
596
+ })
597
+ assert !File.exists?(sassc_path("importee"))
598
+ end
599
+
600
+ def test_import_in_rule
601
+ assert_equal(<<CSS, render(<<SASS, :load_paths => [File.dirname(__FILE__) + '/templates/']))
602
+ .foo #foo {
603
+ background-color: #bbaaff; }
604
+
605
+ .bar {
606
+ a: b; }
607
+ .bar #foo {
608
+ background-color: #bbaaff; }
609
+ CSS
610
+ .foo
611
+ @import partial
612
+
613
+ .bar
614
+ a: b
615
+ @import partial
616
+ SASS
617
+ end
618
+
619
+ def test_nested_import_with_toplevel_constructs
620
+ Sass::Engine.new(".foo\n @import importee", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
621
+ rescue Sass::SyntaxError => err
622
+ assert_equal(3, err.sass_line)
623
+ assert_match(/(\/|^)importee\.sass$/, err.sass_filename)
624
+
625
+ assert_hash_has(err.sass_backtrace.first,
626
+ :filename => err.sass_filename, :line => err.sass_line)
627
+
628
+ assert_nil(err.sass_backtrace[1][:filename])
629
+ assert_equal(2, err.sass_backtrace[1][:line])
630
+
631
+ assert_match(/(\/|^)importee\.sass:3$/, err.backtrace.first)
632
+ assert_equal("(sass):2", err.backtrace[1])
633
+ else
634
+ assert(false, "Exception not raised for importing mixins nested")
635
+ end
636
+
637
+ def test_units
638
+ renders_correctly "units"
639
+ end
640
+
641
+ def test_default_function
642
+ assert_equal(<<CSS, render(<<SASS))
643
+ foo {
644
+ bar: url("foo.png"); }
645
+ CSS
646
+ foo
647
+ bar: url("foo.png")
648
+ SASS
649
+ assert_equal("foo {\n bar: url(); }\n", render("foo\n bar: url()\n"));
650
+ end
651
+
652
+ def test_string_minus
653
+ assert_equal("foo {\n bar: baz-boom-bat; }\n", render(%Q{foo\n bar: baz-boom-bat}))
654
+ assert_equal("foo {\n bar: -baz-boom; }\n", render(%Q{foo\n bar: -baz-boom}))
655
+ end
656
+
657
+ def test_string_div
658
+ assert_equal("foo {\n bar: baz/boom/bat; }\n", render(%Q{foo\n bar: baz/boom/bat}))
659
+ assert_equal("foo {\n bar: /baz/boom; }\n", render(%Q{foo\n bar: /baz/boom}))
660
+ end
661
+
662
+ def test_basic_multiline_selector
663
+ assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
664
+ render("#foo #bar,\n#baz #boom\n :foo bar"))
665
+ assert_equal("#foo #bar,\n#foo #baz {\n foo: bar; }\n",
666
+ render("#foo\n #bar,\n #baz\n :foo bar"))
667
+ assert_equal("#foo,\n#bar {\n foo: bar; }\n #foo #baz,\n #bar #baz {\n foo: bar; }\n",
668
+ render("#foo,\n#bar\n :foo bar\n #baz\n :foo bar"))
669
+ assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
670
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compact))
671
+
672
+ assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
673
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compressed))
674
+
675
+ assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
676
+ render("#foo #bar,,\n,#baz #boom,\n :foo bar"))
677
+
678
+ assert_equal("#bip #bop {\n foo: bar; }\n",
679
+ render("#bip #bop,, ,\n :foo bar"))
680
+ end
681
+
682
+ def test_complex_multiline_selector
683
+ renders_correctly "multiline"
684
+ end
685
+
686
+ def test_colon_only
687
+ begin
688
+ render("a\n b: c", :property_syntax => :old)
689
+ rescue Sass::SyntaxError => e
690
+ assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
691
+ e.message)
692
+ assert_equal(2, e.sass_line)
693
+ else
694
+ assert(false, "SyntaxError not raised for :property_syntax => :old")
695
+ end
696
+
697
+ begin
698
+ render("a\n :b c", :property_syntax => :new)
699
+ assert_equal(2, e.sass_line)
700
+ rescue Sass::SyntaxError => e
701
+ assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
702
+ e.message)
703
+ else
704
+ assert(false, "SyntaxError not raised for :property_syntax => :new")
705
+ end
706
+ end
707
+
708
+ def test_pseudo_elements
709
+ assert_equal(<<CSS, render(<<SASS))
710
+ ::first-line {
711
+ size: 10em; }
712
+ CSS
713
+ ::first-line
714
+ size: 10em
715
+ SASS
716
+ end
717
+
718
+ def test_directive
719
+ assert_equal("@a b;\n", render("@a b"))
720
+
721
+ assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
722
+ assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
723
+ assert_equal("@a {\n b: c;\n}\n", render("@a\n :b c", :style => :expanded))
724
+ assert_equal("@a{b:c}\n", render("@a\n :b c", :style => :compressed))
725
+
726
+ assert_equal("@a {\n b: c;\n d: e; }\n",
727
+ render("@a\n :b c\n :d e"))
728
+ assert_equal("@a { b: c; d: e; }\n",
729
+ render("@a\n :b c\n :d e", :style => :compact))
730
+ assert_equal("@a {\n b: c;\n d: e;\n}\n",
731
+ render("@a\n :b c\n :d e", :style => :expanded))
732
+ assert_equal("@a{b:c;d:e}\n",
733
+ render("@a\n :b c\n :d e", :style => :compressed))
734
+
735
+ assert_equal("@a {\n #b {\n c: d; } }\n",
736
+ render("@a\n #b\n :c d"))
737
+ assert_equal("@a { #b { c: d; } }\n",
738
+ render("@a\n #b\n :c d", :style => :compact))
739
+ assert_equal("@a {\n #b {\n c: d;\n }\n}\n",
740
+ render("@a\n #b\n :c d", :style => :expanded))
741
+ assert_equal("@a{#b{c:d}}\n",
742
+ render("@a\n #b\n :c d", :style => :compressed))
743
+
744
+ assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n",
745
+ render("@a\n #b\n :a b\n #c\n :d e"))
746
+ assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n",
747
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compact))
748
+ assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n",
749
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :expanded))
750
+ assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
751
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compressed))
752
+
753
+ assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n",
754
+ render("@a\n #foo, \n #bar\n :b c"))
755
+ assert_equal("@a { #foo, #bar { b: c; } }\n",
756
+ render("@a\n #foo, \n #bar\n :b c", :style => :compact))
757
+ assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n",
758
+ render("@a\n #foo, \n #bar\n :b c", :style => :expanded))
759
+ assert_equal("@a{#foo,#bar{b:c}}\n",
760
+ render("@a\n #foo, \n #bar\n :b c", :style => :compressed))
761
+
762
+ to_render = <<END
763
+ @a
764
+ :b c
765
+ #d
766
+ :e f
767
+ :g h
768
+ END
769
+ rendered = <<END
770
+ @a { b: c;
771
+ #d { e: f; }
772
+ g: h; }
773
+ END
774
+ assert_equal(rendered, render(to_render, :style => :compact))
775
+
776
+ assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
777
+ end
778
+
779
+ def test_property_hacks
780
+ assert_equal(<<CSS, render(<<SASS))
781
+ foo {
782
+ _name: val;
783
+ *name: val;
784
+ #name: val;
785
+ .name: val;
786
+ name/**/: val;
787
+ name/*\\**/: val;
788
+ name: val; }
789
+ CSS
790
+ foo
791
+ _name: val
792
+ *name: val
793
+ #name: val
794
+ .name: val
795
+ name/**/: val
796
+ name/*\\**/: val
797
+ name: val
798
+ SASS
799
+ end
800
+
801
+ def test_properties_with_space_after_colon
802
+ assert_equal <<CSS, render(<<SASS)
803
+ foo {
804
+ bar: baz;
805
+ bizz: bap; }
806
+ CSS
807
+ foo
808
+ bar : baz
809
+ bizz : bap
810
+ SASS
811
+ end
812
+
813
+ def test_line_annotations
814
+ assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
815
+ /* line 2, test_line_annotations_inline.sass */
816
+ foo bar { foo: bar; }
817
+ /* line 5, test_line_annotations_inline.sass */
818
+ foo baz { blip: blop; }
819
+
820
+ /* line 9, test_line_annotations_inline.sass */
821
+ floodle { flop: blop; }
822
+
823
+ /* line 18, test_line_annotations_inline.sass */
824
+ bup { mix: on; }
825
+ /* line 15, test_line_annotations_inline.sass */
826
+ bup mixin { moop: mup; }
827
+
828
+ /* line 22, test_line_annotations_inline.sass */
829
+ bip hop, skip hop { a: b; }
830
+ CSS
831
+ foo
832
+ bar
833
+ foo: bar
834
+
835
+ baz
836
+ blip: blop
837
+
838
+
839
+ floodle
840
+
841
+ flop: blop
842
+
843
+ =mxn
844
+ mix: on
845
+ mixin
846
+ moop: mup
847
+
848
+ bup
849
+ +mxn
850
+
851
+ bip, skip
852
+ hop
853
+ a: b
854
+ SASS
855
+ end
856
+
857
+ def test_line_annotations_with_filename
858
+ renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"]
859
+ end
860
+
861
+ def test_debug_info
862
+ esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_inline.sass"))
863
+
864
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compact))
865
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000032}}
866
+ foo bar { foo: bar; }
867
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000035}}
868
+ foo baz { blip: blop; }
869
+
870
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000039}}
871
+ floodle { flop: blop; }
872
+
873
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000318}}
874
+ bup { mix: on; }
875
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000315}}
876
+ bup mixin { moop: mup; }
877
+
878
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000322}}
879
+ bip hop, skip hop { a: b; }
880
+ CSS
881
+ foo
882
+ bar
883
+ foo: bar
884
+
885
+ baz
886
+ blip: blop
887
+
888
+
889
+ floodle
890
+
891
+ flop: blop
892
+
893
+ =mxn
894
+ mix: on
895
+ mixin
896
+ moop: mup
897
+
898
+ bup
899
+ +mxn
900
+
901
+ bip, skip
902
+ hop
903
+ a: b
904
+ SASS
905
+ end
906
+
907
+ def test_debug_info_without_filename
908
+ assert_equal(<<CSS, Sass::Engine.new(<<SASS, :debug_info => true).render)
909
+ @media -sass-debug-info{filename{font-family:}line{font-family:\\000031}}
910
+ foo {
911
+ a: b; }
912
+ CSS
913
+ foo
914
+ a: b
915
+ SASS
916
+ end
917
+
918
+ def test_debug_info_with_compressed
919
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compressed))
920
+ foo{a:b}
921
+ CSS
922
+ foo
923
+ a: b
924
+ SASS
925
+ end
926
+
927
+ def test_debug_info_with_line_annotations
928
+ esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_with_line_annotations_inline.sass"))
929
+
930
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :line_comments => true))
931
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000031}}
932
+ foo {
933
+ a: b; }
934
+ CSS
935
+ foo
936
+ a: b
937
+ SASS
938
+ end
939
+
940
+ def test_empty_first_line
941
+ assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
942
+ end
943
+
944
+ def test_escaped_rule
945
+ assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b"))
946
+ assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e"))
947
+ end
948
+
949
+ def test_cr_newline
950
+ assert_equal("foo {\n a: b;\n c: d;\n e: f; }\n", render("foo\r a: b\r\n c: d\n\r e: f"))
951
+ end
952
+
953
+ def test_property_with_content_and_nested_props
954
+ assert_equal(<<CSS, render(<<SASS))
955
+ foo {
956
+ a: b;
957
+ a-c: d;
958
+ a-c-e: f; }
959
+ CSS
960
+ foo
961
+ a: b
962
+ c: d
963
+ e: f
964
+ SASS
965
+
966
+ assert_equal(<<CSS, render(<<SASS))
967
+ foo {
968
+ a: b;
969
+ a-c-e: f; }
970
+ CSS
971
+ foo
972
+ a: b
973
+ c:
974
+ e: f
975
+ SASS
976
+ end
977
+
978
+ def test_guarded_assign
979
+ assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b\n$foo: c !default\nfoo\n a: $foo}))
980
+ assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b !default\nfoo\n a: $foo}))
981
+ end
982
+
983
+ def test_mixins
984
+ renders_correctly "mixins", { :style => :expanded }
985
+ end
986
+
987
+ def test_directive_style_mixins
988
+ assert_equal <<CSS, render(<<SASS)
989
+ bar {
990
+ prop: baz; }
991
+ CSS
992
+ @mixin foo($arg)
993
+ prop: $arg
994
+
995
+ bar
996
+ @include foo(baz)
997
+ SASS
998
+ end
999
+
1000
+ def test_mixins_dont_interfere_with_sibling_combinator
1001
+ assert_equal("foo + bar {\n a: b; }\nfoo + baz {\n c: d; }\n",
1002
+ render("foo\n +\n bar\n a: b\n baz\n c: d"))
1003
+ end
1004
+
1005
+ def test_mixin_args
1006
+ assert_equal("blat {\n baz: hi; }\n", render(<<SASS))
1007
+ =foo($bar)
1008
+ baz: $bar
1009
+ blat
1010
+ +foo(hi)
1011
+ SASS
1012
+ assert_equal("blat {\n baz: 3; }\n", render(<<SASS))
1013
+ =foo($a, $b)
1014
+ baz: $a + $b
1015
+ blat
1016
+ +foo(1, 2)
1017
+ SASS
1018
+ assert_equal("blat {\n baz: 4;\n baz: 3;\n baz: 5;\n bang: 3; }\n", render(<<SASS))
1019
+ =foo($c: (6 + 4) / 2)
1020
+ baz: $c
1021
+ $c: 3
1022
+ blat
1023
+ +foo($c + 1)
1024
+ +foo(($c + 3)/2)
1025
+ +foo
1026
+ bang: $c
1027
+ SASS
1028
+ end
1029
+
1030
+ def test_default_values_for_mixin_arguments
1031
+ assert_equal("white {\n color: white; }\n\nblack {\n color: black; }\n", render(<<SASS))
1032
+ =foo($a: #FFF)
1033
+ :color $a
1034
+ white
1035
+ +foo
1036
+ black
1037
+ +foo(#000)
1038
+ SASS
1039
+ assert_equal(<<CSS, render(<<SASS))
1040
+ one {
1041
+ color: white;
1042
+ padding: 1px;
1043
+ margin: 4px; }
1044
+
1045
+ two {
1046
+ color: white;
1047
+ padding: 2px;
1048
+ margin: 5px; }
1049
+
1050
+ three {
1051
+ color: white;
1052
+ padding: 2px;
1053
+ margin: 3px; }
1054
+ CSS
1055
+ $a: 5px
1056
+ =foo($a, $b: 1px, $c: 3px + $b)
1057
+ :color $a
1058
+ :padding $b
1059
+ :margin $c
1060
+ one
1061
+ +foo(#fff)
1062
+ two
1063
+ +foo(#fff, 2px)
1064
+ three
1065
+ +foo(#fff, 2px, 3px)
1066
+ SASS
1067
+ end
1068
+
1069
+ def test_hyphen_underscore_insensitive_mixins
1070
+ assert_equal(<<CSS, render(<<SASS))
1071
+ a {
1072
+ b: 12;
1073
+ c: foo; }
1074
+ CSS
1075
+ =mixin-hyphen
1076
+ b: 12
1077
+
1078
+ =mixin_under
1079
+ c: foo
1080
+
1081
+ a
1082
+ +mixin_hyphen
1083
+ +mixin-under
1084
+ SASS
1085
+ end
1086
+
1087
+ def test_css_identifier_mixin
1088
+ assert_equal(<<CSS, render(<<SASS))
1089
+ a {
1090
+ foo: 12; }
1091
+ CSS
1092
+ =\\{foo\\(12\\)($a)
1093
+ foo: $a
1094
+
1095
+ a
1096
+ +\\{foo\\(12\\)(12)
1097
+ SASS
1098
+ end
1099
+
1100
+ def test_basic_function
1101
+ assert_equal(<<CSS, render(<<SASS))
1102
+ bar {
1103
+ a: 3; }
1104
+ CSS
1105
+ @function foo()
1106
+ @return 1 + 2
1107
+
1108
+ bar
1109
+ a: foo()
1110
+ SASS
1111
+ end
1112
+
1113
+ def test_function_args
1114
+ assert_equal(<<CSS, render(<<SASS))
1115
+ bar {
1116
+ a: 3; }
1117
+ CSS
1118
+ @function plus($var1, $var2)
1119
+ @return $var1 + $var2
1120
+
1121
+ bar
1122
+ a: plus(1, 2)
1123
+ SASS
1124
+ end
1125
+
1126
+ def test_function_arg_default
1127
+ assert_equal(<<CSS, render(<<SASS))
1128
+ bar {
1129
+ a: 3; }
1130
+ CSS
1131
+ @function plus($var1, $var2: 2)
1132
+ @return $var1 + $var2
1133
+
1134
+ bar
1135
+ a: plus(1)
1136
+ SASS
1137
+ end
1138
+
1139
+ def test_function_arg_keyword
1140
+ assert_equal(<<CSS, render(<<SASS))
1141
+ bar {
1142
+ a: 1bar; }
1143
+ CSS
1144
+ @function plus($var1: 1, $var2: 2)
1145
+ @return $var1 + $var2
1146
+
1147
+ bar
1148
+ a: plus($var2: bar)
1149
+ SASS
1150
+ end
1151
+
1152
+ def test_function_with_if
1153
+ assert_equal(<<CSS, render(<<SASS))
1154
+ bar {
1155
+ a: foo;
1156
+ b: bar; }
1157
+ CSS
1158
+ @function my-if($cond, $val1, $val2)
1159
+ @if $cond
1160
+ @return $val1
1161
+ @else
1162
+ @return $val2
1163
+
1164
+ bar
1165
+ a: my-if(true, foo, bar)
1166
+ b: my-if(false, foo, bar)
1167
+ SASS
1168
+ end
1169
+
1170
+ def test_function_with_var
1171
+ assert_equal(<<CSS, render(<<SASS))
1172
+ bar {
1173
+ a: 1; }
1174
+ CSS
1175
+ @function foo($val1, $val2)
1176
+ $intermediate: $val1 + $val2
1177
+ @return $intermediate/3
1178
+
1179
+ bar
1180
+ a: foo(1, 2)
1181
+ SASS
1182
+ end
1183
+
1184
+ def test_interpolation
1185
+ assert_equal("a-1 {\n b-2-3: c-3; }\n", render(<<SASS))
1186
+ $a: 1
1187
+ $b: 2
1188
+ $c: 3
1189
+ a-\#{$a}
1190
+ b-\#{$b}-\#{$c}: c-\#{$a + $b}
1191
+ SASS
1192
+ end
1193
+
1194
+ def test_complex_property_interpolation
1195
+ assert_equal(<<CSS, render(<<SASS))
1196
+ a-1 {
1197
+ b-2 3-fizzap18: c-3; }
1198
+ CSS
1199
+ $a: 1
1200
+ $b: 2
1201
+ $c: 3
1202
+ a-\#{$a}
1203
+ b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
1204
+ SASS
1205
+ end
1206
+
1207
+ def test_if_directive
1208
+ assert_equal("a {\n b: 1; }\n", render(<<SASS))
1209
+ $var: true
1210
+ a
1211
+ @if $var
1212
+ b: 1
1213
+ @if not $var
1214
+ b: 2
1215
+ SASS
1216
+ end
1217
+
1218
+ def test_for
1219
+ assert_equal(<<CSS, render(<<SASS))
1220
+ a-0 {
1221
+ two-i: 0; }
1222
+
1223
+ a-1 {
1224
+ two-i: 2; }
1225
+
1226
+ a-2 {
1227
+ two-i: 4; }
1228
+
1229
+ a-3 {
1230
+ two-i: 6; }
1231
+
1232
+ b-1 {
1233
+ j-1: 0; }
1234
+
1235
+ b-2 {
1236
+ j-1: 1; }
1237
+
1238
+ b-3 {
1239
+ j-1: 2; }
1240
+
1241
+ b-4 {
1242
+ j-1: 3; }
1243
+ CSS
1244
+ $a: 3
1245
+ @for $i from 0 to $a + 1
1246
+ a-\#{$i}
1247
+ two-i: 2 * $i
1248
+
1249
+ @for $j from 1 through 4
1250
+ b-\#{$j}
1251
+ j-1: $j - 1
1252
+ SASS
1253
+ end
1254
+
1255
+ def test_while
1256
+ assert_equal(<<CSS, render(<<SASS))
1257
+ a-5 {
1258
+ blooble: gloop; }
1259
+
1260
+ a-4 {
1261
+ blooble: gloop; }
1262
+
1263
+ a-3 {
1264
+ blooble: gloop; }
1265
+
1266
+ a-2 {
1267
+ blooble: gloop; }
1268
+
1269
+ a-1 {
1270
+ blooble: gloop; }
1271
+ CSS
1272
+ $a: 5
1273
+ @while $a != 0
1274
+ a-\#{$a}
1275
+ blooble: gloop
1276
+ $a: $a - 1
1277
+ SASS
1278
+ end
1279
+
1280
+ def test_else
1281
+ assert_equal(<<CSS, render(<<SASS))
1282
+ a {
1283
+ t1: t;
1284
+ t2: t;
1285
+ t3: t;
1286
+ t4: t; }
1287
+ CSS
1288
+ a
1289
+ @if true
1290
+ t1: t
1291
+ @else
1292
+ f1: f
1293
+
1294
+ @if false
1295
+ f2: f
1296
+ @else
1297
+ t2: t
1298
+
1299
+ @if false
1300
+ f3: f1
1301
+ @else if 1 + 1 == 3
1302
+ f3: f2
1303
+ @else
1304
+ t3: t
1305
+
1306
+ @if false
1307
+ f4: f1
1308
+ @else if 1 + 1 == 2
1309
+ t4: t
1310
+ @else
1311
+ f4: f2
1312
+
1313
+ @if false
1314
+ f5: f1
1315
+ @else if false
1316
+ f5: f2
1317
+ SASS
1318
+ end
1319
+
1320
+ def test_each
1321
+ assert_equal(<<CSS, render(<<SASS))
1322
+ a {
1323
+ b: 1px;
1324
+ b: 2px;
1325
+ b: 3px;
1326
+ b: 4px;
1327
+ c: foo;
1328
+ c: bar;
1329
+ c: baz;
1330
+ c: bang;
1331
+ d: blue; }
1332
+ CSS
1333
+ a
1334
+ @each $number in 1px 2px 3px 4px
1335
+ b: $number
1336
+ @each $str in foo, bar, baz, bang
1337
+ c: $str
1338
+ @each $single in blue
1339
+ d: $single
1340
+ SASS
1341
+ end
1342
+
1343
+ def test_variable_reassignment
1344
+ assert_equal(<<CSS, render(<<SASS))
1345
+ a {
1346
+ b: 1;
1347
+ c: 2; }
1348
+ CSS
1349
+ $a: 1
1350
+ a
1351
+ b: $a
1352
+ $a: 2
1353
+ c: $a
1354
+ SASS
1355
+ end
1356
+
1357
+ def test_variable_scope
1358
+ assert_equal(<<CSS, render(<<SASS))
1359
+ a {
1360
+ b-1: c;
1361
+ b-2: c;
1362
+ d: 12; }
1363
+
1364
+ b {
1365
+ d: 17; }
1366
+ CSS
1367
+ $i: 12
1368
+ a
1369
+ @for $i from 1 through 2
1370
+ b-\#{$i}: c
1371
+ d: $i
1372
+
1373
+ =foo
1374
+ $i: 17
1375
+
1376
+ b
1377
+ +foo
1378
+ d: $i
1379
+ SASS
1380
+ end
1381
+
1382
+ def test_hyphen_underscore_insensitive_variables
1383
+ assert_equal(<<CSS, render(<<SASS))
1384
+ a {
1385
+ b: c; }
1386
+
1387
+ d {
1388
+ e: 13;
1389
+ f: foobar; }
1390
+ CSS
1391
+ $var-hyphen: 12
1392
+ $var_under: foo
1393
+
1394
+ a
1395
+ $var_hyphen: 1 + $var_hyphen
1396
+ $var-under: $var-under + bar
1397
+ b: c
1398
+
1399
+ d
1400
+ e: $var-hyphen
1401
+ f: $var_under
1402
+ SASS
1403
+ end
1404
+
1405
+ def test_css_identifier_variable
1406
+ assert_equal(<<CSS, render(<<SASS))
1407
+ a {
1408
+ b: 12; }
1409
+ CSS
1410
+ $\\{foo\\(12\\): 12
1411
+
1412
+ a
1413
+ b: $\\{foo\\(12\\)
1414
+ SASS
1415
+ end
1416
+
1417
+ def test_important
1418
+ assert_equal(<<CSS, render(<<SASS))
1419
+ a {
1420
+ b: 12px !important; }
1421
+ CSS
1422
+ $foo: 12px
1423
+ a
1424
+ b: $foo !important
1425
+ SASS
1426
+ end
1427
+
1428
+ def test_argument_error
1429
+ assert_raise(Sass::SyntaxError) { render("a\n b: hsl(1)") }
1430
+ end
1431
+
1432
+ def test_comments_at_the_top_of_a_document
1433
+ render(<<SASS)
1434
+ //
1435
+ This is a comment that
1436
+ continues to the second line.
1437
+ foo
1438
+ bar: baz
1439
+ SASS
1440
+ end
1441
+
1442
+ def test_loud_comments_containing_a_comment_close
1443
+ actual_css = render(<<SASS)
1444
+ /*
1445
+ This is a comment that
1446
+ continues to the second line. */
1447
+ foo
1448
+ bar: baz
1449
+ SASS
1450
+ assert_equal(<<CSS, actual_css)
1451
+ /* This is a comment that
1452
+ * continues to the second line. */
1453
+ foo {
1454
+ bar: baz; }
1455
+ CSS
1456
+ end
1457
+
1458
+ def test_loud_comments_with_starred_lines
1459
+ assert_equal(<<CSS, render(<<SASS))
1460
+ /* This is a comment that
1461
+ * continues to the second line.
1462
+ * And even to the third! */
1463
+ CSS
1464
+ /* This is a comment that
1465
+ * continues to the second line.
1466
+ * And even to the third!
1467
+ SASS
1468
+ end
1469
+
1470
+ def test_loud_comments_with_no_space_after_starred_lines
1471
+ assert_equal(<<CSS, render(<<SASS))
1472
+ /*bip bop
1473
+ *beep boop
1474
+ *bap blimp */
1475
+ CSS
1476
+ /*bip bop
1477
+ *beep boop
1478
+ *bap blimp
1479
+ SASS
1480
+ end
1481
+
1482
+ def test_comment_indentation_at_beginning_of_doc
1483
+ assert_equal <<CSS, render(<<SASS)
1484
+ /* foo
1485
+ * bar
1486
+ * baz */
1487
+ foo {
1488
+ a: b; }
1489
+ CSS
1490
+ /* foo
1491
+ bar
1492
+ baz
1493
+ foo
1494
+ a: b
1495
+ SASS
1496
+ end
1497
+
1498
+ def test_unusual_comment_indentation
1499
+ assert_equal <<CSS, render(<<SASS)
1500
+ foo {
1501
+ /* foo
1502
+ * bar
1503
+ * baz */ }
1504
+ CSS
1505
+ foo
1506
+ /* foo
1507
+ bar
1508
+ baz
1509
+ SASS
1510
+ end
1511
+
1512
+ def test_loud_comment_with_close
1513
+ assert_equal <<CSS, render(<<SASS)
1514
+ foo {
1515
+ /* foo
1516
+ * bar */ }
1517
+ CSS
1518
+ foo
1519
+ /* foo
1520
+ bar */
1521
+ SASS
1522
+ end
1523
+
1524
+ def test_loud_comment_with_separate_line_close
1525
+ assert_equal <<CSS, render(<<SASS)
1526
+ foo {
1527
+ /* foo
1528
+ * bar
1529
+ */ }
1530
+ CSS
1531
+ foo
1532
+ /* foo
1533
+ * bar
1534
+ */
1535
+ SASS
1536
+ end
1537
+
1538
+ def test_loud_comment_in_compressed_mode
1539
+ assert_equal <<CSS, render(<<SASS, :style => :compressed)
1540
+ foo{color:blue;/* foo
1541
+ * bar
1542
+ */}
1543
+ CSS
1544
+ foo
1545
+ color: blue
1546
+ /*! foo
1547
+ * bar
1548
+ */
1549
+ SASS
1550
+ end
1551
+ def test_loud_comment_in_silent_comment
1552
+ assert_equal <<CSS, render(<<SASS, :style => :compressed)
1553
+ foo{color:blue;/* foo */
1554
+ /* bar */
1555
+ /* */
1556
+ /* bip */
1557
+ /* baz */}
1558
+ CSS
1559
+ foo
1560
+ color: blue
1561
+ //! foo
1562
+ //! bar
1563
+ //!
1564
+ bip
1565
+ baz
1566
+ SASS
1567
+ end
1568
+
1569
+ def test_loud_comment_is_evaluated
1570
+ assert_equal <<CSS, render(<<SASS)
1571
+ /*
1572
+ * Hue: 327.216deg */
1573
+ CSS
1574
+ /*!
1575
+ Hue: \#{hue(#f836a0)}
1576
+ SASS
1577
+ end
1578
+
1579
+ def test_attribute_selector_with_spaces
1580
+ assert_equal(<<CSS, render(<<SASS))
1581
+ a b[foo=bar] {
1582
+ c: d; }
1583
+ CSS
1584
+ a
1585
+ b[foo = bar]
1586
+ c: d
1587
+ SASS
1588
+ end
1589
+
1590
+ def test_quoted_colon
1591
+ assert_equal(<<CSS, render(<<SASS))
1592
+ a b[foo="bar: baz"] {
1593
+ c: d; }
1594
+ CSS
1595
+ a
1596
+ b[foo="bar: baz"]
1597
+ c: d
1598
+ SASS
1599
+ end
1600
+
1601
+ def test_quoted_comma
1602
+ assert_equal(<<CSS, render(<<SASS))
1603
+ a b[foo="bar, baz"] {
1604
+ c: d; }
1605
+ CSS
1606
+ a
1607
+ b[foo="bar, baz"]
1608
+ c: d
1609
+ SASS
1610
+ end
1611
+
1612
+ def test_quoted_ampersand
1613
+ assert_equal(<<CSS, render(<<SASS))
1614
+ a b[foo="bar & baz"] {
1615
+ c: d; }
1616
+ CSS
1617
+ a
1618
+ b[foo="bar & baz"]
1619
+ c: d
1620
+ SASS
1621
+ end
1622
+
1623
+ def test_empty_selector_warning
1624
+ assert_warning(<<END) {render("foo bar")}
1625
+ WARNING on line 1 of test_empty_selector_warning_inline.sass:
1626
+ This selector doesn't have any properties and will not be rendered.
1627
+ END
1628
+ end
1629
+
1630
+ def test_root_level_pseudo_class_with_new_properties
1631
+ assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1632
+ :focus {
1633
+ outline: 0; }
1634
+ CSS
1635
+ :focus
1636
+ outline: 0
1637
+ SASS
1638
+ end
1639
+
1640
+ def test_pseudo_class_with_new_properties
1641
+ assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1642
+ p :focus {
1643
+ outline: 0; }
1644
+ CSS
1645
+ p
1646
+ :focus
1647
+ outline: 0
1648
+ SASS
1649
+ end
1650
+
1651
+ def test_nil_option
1652
+ assert_equal(<<CSS, render(<<SASS, :format => nil))
1653
+ foo {
1654
+ a: b; }
1655
+ CSS
1656
+ foo
1657
+ a: b
1658
+ SASS
1659
+ end
1660
+
1661
+ def test_interpolation_in_raw_functions
1662
+ assert_equal(<<CSS, render(<<SASS))
1663
+ foo {
1664
+ filter: progid:Microsoft.foo.bar.Baz(flip=foobar, bang=#00ff00cc); }
1665
+ CSS
1666
+ foo
1667
+ filter: progid:Microsoft.foo.bar.Baz(flip=\#{foo + bar}, bang=#00ff00cc)
1668
+ SASS
1669
+ end
1670
+
1671
+ # SassScript string behavior
1672
+
1673
+ def test_plus_preserves_quotedness
1674
+ assert_equal(<<CSS, render(<<SASS))
1675
+ foo {
1676
+ a: "foo1";
1677
+ b: "1foo";
1678
+ c: foo1;
1679
+ d: 1foo;
1680
+ e: "foobar";
1681
+ f: foobar; }
1682
+ CSS
1683
+ foo
1684
+ a: "foo" + 1
1685
+ b: 1 + "foo"
1686
+ c: foo + 1
1687
+ d: 1 + foo
1688
+ e: "foo" + bar
1689
+ f: foo + "bar"
1690
+ SASS
1691
+ end
1692
+
1693
+ def test_colon_properties_preserve_quotedness
1694
+ assert_equal(<<CSS, render(<<SASS))
1695
+ foo {
1696
+ a: "foo";
1697
+ b: bar;
1698
+ c: "foo" bar;
1699
+ d: foo, "bar"; }
1700
+ CSS
1701
+ foo
1702
+ a: "foo"
1703
+ b: bar
1704
+ c: "foo" bar
1705
+ d: foo, "bar"
1706
+ SASS
1707
+ end
1708
+
1709
+ def test_colon_variables_preserve_quotedness
1710
+ assert_equal(<<CSS, render(<<SASS))
1711
+ foo {
1712
+ a: "foo";
1713
+ b: bar; }
1714
+ CSS
1715
+ $a: "foo"
1716
+ $b: bar
1717
+
1718
+ foo
1719
+ a: $a
1720
+ b: $b
1721
+ SASS
1722
+ end
1723
+
1724
+ def test_colon_args_preserve_quotedness
1725
+ assert_equal(<<CSS, render(<<SASS))
1726
+ foo {
1727
+ a: "foo";
1728
+ b: bar;
1729
+ c: "foo" bar;
1730
+ d: foo, "bar"; }
1731
+ CSS
1732
+ =foo($a: "foo", $b: bar, $c: "foo" bar, $d: (foo, "bar"))
1733
+ foo
1734
+ a: $a
1735
+ b: $b
1736
+ c: $c
1737
+ d: $d
1738
+
1739
+ +foo
1740
+ SASS
1741
+ end
1742
+
1743
+ def test_interpolation_unquotes_strings
1744
+ assert_equal(<<CSS, render(<<SASS))
1745
+ .foo-bar {
1746
+ a: b; }
1747
+ CSS
1748
+ .foo-\#{"bar"}
1749
+ a: b
1750
+ SASS
1751
+
1752
+ assert_equal(<<CSS, render(<<SASS))
1753
+ .foo {
1754
+ a: b c; }
1755
+ CSS
1756
+ .foo
1757
+ a: b \#{"c"}
1758
+ SASS
1759
+ end
1760
+
1761
+ def test_interpolation_unquotes_strings_in_vars
1762
+ assert_equal(<<CSS, render(<<SASS))
1763
+ .foo-bar {
1764
+ a: b; }
1765
+ CSS
1766
+ $var: "bar"
1767
+
1768
+ .foo-\#{$var}
1769
+ a: b
1770
+ SASS
1771
+ end
1772
+
1773
+ def test_interpolation_doesnt_deep_unquote_strings
1774
+ assert_equal(<<CSS, render(<<SASS))
1775
+ .foo- "bar" "baz" {
1776
+ a: b; }
1777
+ CSS
1778
+ .foo-\#{"bar" "baz"}
1779
+ a: b
1780
+ SASS
1781
+ end
1782
+
1783
+ def test_warn_directive
1784
+ expected_warning = <<EXPECTATION
1785
+ WARNING: this is a warning
1786
+ on line 4 of test_warn_directive_inline.sass
1787
+
1788
+ WARNING: this is a mixin warning
1789
+ on line 2 of test_warn_directive_inline.sass, in `foo'
1790
+ from line 7 of test_warn_directive_inline.sass
1791
+ EXPECTATION
1792
+ assert_warning expected_warning do
1793
+ assert_equal <<CSS, render(<<SASS)
1794
+ bar {
1795
+ c: d; }
1796
+ CSS
1797
+ =foo
1798
+ @warn "this is a mixin warning"
1799
+
1800
+ @warn "this is a warning"
1801
+ bar
1802
+ c: d
1803
+ +foo
1804
+ SASS
1805
+ end
1806
+ end
1807
+
1808
+ def test_warn_directive_when_quiet
1809
+ assert_warning "" do
1810
+ assert_equal <<CSS, render(<<SASS, :quiet => true)
1811
+ CSS
1812
+ @warn "this is a warning"
1813
+ SASS
1814
+ end
1815
+ end
1816
+
1817
+ def test_warn_with_imports
1818
+ expected_warning = <<WARN
1819
+ WARNING: In the main file
1820
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn.sass
1821
+
1822
+ WARNING: Imported
1823
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn_imported.sass
1824
+ from line 2 of #{File.dirname(__FILE__)}/templates/warn.sass
1825
+
1826
+ WARNING: In an imported mixin
1827
+ on line 4 of #{File.dirname(__FILE__)}/templates/warn_imported.sass, in `emits-a-warning'
1828
+ from line 3 of #{File.dirname(__FILE__)}/templates/warn.sass
1829
+ WARN
1830
+ assert_warning expected_warning do
1831
+ renders_correctly "warn", :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"]
1832
+ end
1833
+ end
1834
+
1835
+ def test_media_bubbling
1836
+ assert_equal <<CSS, render(<<SASS)
1837
+ .foo {
1838
+ a: b; }
1839
+ @media bar {
1840
+ .foo {
1841
+ c: d; } }
1842
+ .foo .baz {
1843
+ e: f; }
1844
+ @media bip {
1845
+ .foo .baz {
1846
+ g: h; } }
1847
+
1848
+ .other {
1849
+ i: j; }
1850
+ CSS
1851
+ .foo
1852
+ a: b
1853
+ @media bar
1854
+ c: d
1855
+ .baz
1856
+ e: f
1857
+ @media bip
1858
+ g: h
1859
+
1860
+ .other
1861
+ i: j
1862
+ SASS
1863
+
1864
+ assert_equal <<CSS, render(<<SASS, :style => :compact)
1865
+ .foo { a: b; }
1866
+ @media bar { .foo { c: d; } }
1867
+ .foo .baz { e: f; }
1868
+ @media bip { .foo .baz { g: h; } }
1869
+
1870
+ .other { i: j; }
1871
+ CSS
1872
+ .foo
1873
+ a: b
1874
+ @media bar
1875
+ c: d
1876
+ .baz
1877
+ e: f
1878
+ @media bip
1879
+ g: h
1880
+
1881
+ .other
1882
+ i: j
1883
+ SASS
1884
+
1885
+ assert_equal <<CSS, render(<<SASS, :style => :expanded)
1886
+ .foo {
1887
+ a: b;
1888
+ }
1889
+ @media bar {
1890
+ .foo {
1891
+ c: d;
1892
+ }
1893
+ }
1894
+ .foo .baz {
1895
+ e: f;
1896
+ }
1897
+ @media bip {
1898
+ .foo .baz {
1899
+ g: h;
1900
+ }
1901
+ }
1902
+
1903
+ .other {
1904
+ i: j;
1905
+ }
1906
+ CSS
1907
+ .foo
1908
+ a: b
1909
+ @media bar
1910
+ c: d
1911
+ .baz
1912
+ e: f
1913
+ @media bip
1914
+ g: h
1915
+
1916
+ .other
1917
+ i: j
1918
+ SASS
1919
+ end
1920
+
1921
+ def test_double_media_bubbling
1922
+ assert_equal <<CSS, render(<<SASS)
1923
+ @media bar and baz {
1924
+ .foo {
1925
+ c: d; } }
1926
+ CSS
1927
+ @media bar
1928
+ @media baz
1929
+ .foo
1930
+ c: d
1931
+ SASS
1932
+
1933
+ assert_equal <<CSS, render(<<SASS)
1934
+ @media bar {
1935
+ .foo {
1936
+ a: b; } }
1937
+ @media bar and baz {
1938
+ .foo {
1939
+ c: d; } }
1940
+ CSS
1941
+ .foo
1942
+ @media bar
1943
+ a: b
1944
+ @media baz
1945
+ c: d
1946
+ SASS
1947
+ end
1948
+
1949
+ def test_rule_media_rule_bubbling
1950
+ assert_equal <<CSS, render(<<SASS)
1951
+ @media bar {
1952
+ .foo {
1953
+ a: b;
1954
+ e: f; }
1955
+ .foo .baz {
1956
+ c: d; } }
1957
+ CSS
1958
+ .foo
1959
+ @media bar
1960
+ a: b
1961
+ .baz
1962
+ c: d
1963
+ e: f
1964
+ SASS
1965
+ end
1966
+
1967
+ def test_nested_media_around_properties
1968
+ assert_equal <<CSS, render(<<SASS)
1969
+ .outside {
1970
+ color: red;
1971
+ background: blue; }
1972
+ @media print {
1973
+ .outside {
1974
+ color: black; } }
1975
+ @media print and nested {
1976
+ .outside .inside {
1977
+ border: 1px solid black; } }
1978
+ .outside .middle {
1979
+ display: block; }
1980
+ CSS
1981
+ .outside
1982
+ color: red
1983
+ @media print
1984
+ color: black
1985
+ .inside
1986
+ @media nested
1987
+ border: 1px solid black
1988
+ background: blue
1989
+ .middle
1990
+ display: block
1991
+ SASS
1992
+ end
1993
+
1994
+ def test_media_with_parent_references
1995
+ sass_str = <<SASS
1996
+ .outside
1997
+ @media print
1998
+ &.inside
1999
+ border: 1px solid black
2000
+ SASS
2001
+ css_str = <<CSS
2002
+ @media print {
2003
+ .outside.inside {
2004
+ border: 1px solid black; } }
2005
+ CSS
2006
+ assert_equal css_str, render(sass_str)
2007
+ end
2008
+
2009
+ # Regression tests
2010
+
2011
+ def test_parens_in_mixins
2012
+ assert_equal(<<CSS, render(<<SASS))
2013
+ .foo {
2014
+ color: #01ff7f;
2015
+ background-color: #000102; }
2016
+ CSS
2017
+ =foo($c1, $c2: rgb(0, 1, 2))
2018
+ color: $c1
2019
+ background-color: $c2
2020
+
2021
+ .foo
2022
+ +foo(rgb(1,255,127))
2023
+ SASS
2024
+ end
2025
+
2026
+ def test_comment_beneath_prop
2027
+ assert_equal(<<RESULT, render(<<SOURCE))
2028
+ .box {
2029
+ border-style: solid; }
2030
+ RESULT
2031
+ .box
2032
+ :border
2033
+ //:color black
2034
+ :style solid
2035
+ SOURCE
2036
+
2037
+ assert_equal(<<RESULT, render(<<SOURCE))
2038
+ .box {
2039
+ /* :color black */
2040
+ border-style: solid; }
2041
+ RESULT
2042
+ .box
2043
+ :border
2044
+ /* :color black
2045
+ :style solid
2046
+ SOURCE
2047
+
2048
+ assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2049
+ .box{border-style:solid}
2050
+ RESULT
2051
+ .box
2052
+ :border
2053
+ /*:color black
2054
+ :style solid
2055
+ SOURCE
2056
+ end
2057
+
2058
+ def test_compressed_comment_beneath_directive
2059
+ assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2060
+ @foo{a:b}
2061
+ RESULT
2062
+ @foo
2063
+ a: b
2064
+ /*b: c
2065
+ SOURCE
2066
+ end
2067
+
2068
+ def test_comment_with_crazy_indentation
2069
+ assert_equal(<<CSS, render(<<SASS))
2070
+ /* This is a loud comment:
2071
+ * Where the indentation is wonky. */
2072
+ .comment {
2073
+ width: 1px; }
2074
+ CSS
2075
+ /*
2076
+ This is a loud comment:
2077
+ Where the indentation is wonky.
2078
+ //
2079
+ This is a silent comment:
2080
+ Where the indentation is wonky.
2081
+ .comment
2082
+ width: 1px
2083
+ SASS
2084
+ end
2085
+
2086
+ def test_plus_with_space
2087
+ assert_equal(<<CSS, render(<<SASS))
2088
+ a + b {
2089
+ color: green; }
2090
+ CSS
2091
+ a
2092
+ + b
2093
+ color: green
2094
+ SASS
2095
+ end
2096
+
2097
+ def test_empty_line_comment
2098
+ assert_equal(<<CSS, render(<<SASS))
2099
+ /* Foo
2100
+ *
2101
+ * Bar */
2102
+ CSS
2103
+ /*
2104
+ Foo
2105
+
2106
+ Bar
2107
+ SASS
2108
+ end
2109
+
2110
+ def test_empty_comment
2111
+ assert_equal(<<CSS, render(<<SASS))
2112
+ /* */
2113
+ a {
2114
+ /* */
2115
+ b: c; }
2116
+ CSS
2117
+ /*
2118
+ a
2119
+ /*
2120
+ b: c
2121
+ SASS
2122
+ end
2123
+
2124
+ def test_options_available_in_environment
2125
+ assert_equal(<<CSS, render(<<SASS))
2126
+ a {
2127
+ b: nested; }
2128
+ CSS
2129
+ a
2130
+ b: option("style")
2131
+ SASS
2132
+ end
2133
+
2134
+ def test_mixin_no_arg_error
2135
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable (e.g. $foo), was ")"') do
2136
+ render(<<SASS)
2137
+ =foo($bar,)
2138
+ bip: bap
2139
+ SASS
2140
+ end
2141
+ end
2142
+
2143
+ def test_import_with_commas_in_url
2144
+ assert_equal <<CSS, render(<<SASS)
2145
+ @import url(foo.css?bar,baz);
2146
+ CSS
2147
+ @import url(foo.css?bar,baz)
2148
+ SASS
2149
+ end
2150
+
2151
+ def test_mixin_with_keyword_args
2152
+ assert_equal <<CSS, render(<<SASS)
2153
+ .mixed {
2154
+ required: foo;
2155
+ arg1: default-val1;
2156
+ arg2: non-default-val2; }
2157
+ CSS
2158
+ =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2159
+ required: $required
2160
+ arg1: $arg1
2161
+ arg2: $arg2
2162
+ .mixed
2163
+ +a-mixin(foo, $arg2: non-default-val2)
2164
+ SASS
2165
+ end
2166
+
2167
+ def test_mixin_with_keyword_arg_variable_value
2168
+ assert_equal <<CSS, render(<<SASS)
2169
+ .mixed {
2170
+ required: foo;
2171
+ arg1: default-val1;
2172
+ arg2: a-value; }
2173
+ CSS
2174
+ =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2175
+ required: $required
2176
+ arg1: $arg1
2177
+ arg2: $arg2
2178
+ .mixed
2179
+ $a-value: a-value
2180
+ +a-mixin(foo, $arg2: $a-value)
2181
+ SASS
2182
+ end
2183
+
2184
+ def test_mixin_keyword_args_handle_variable_underscore_dash_equivalence
2185
+ assert_equal <<CSS, render(<<SASS)
2186
+ .mixed {
2187
+ required: foo;
2188
+ arg1: non-default-val1;
2189
+ arg2: non-default-val2; }
2190
+ CSS
2191
+ =a-mixin($required, $arg-1: default-val1, $arg_2: default-val2)
2192
+ required: $required
2193
+ arg1: $arg_1
2194
+ arg2: $arg-2
2195
+ .mixed
2196
+ +a-mixin(foo, $arg-2: non-default-val2, $arg_1: non-default-val1)
2197
+ SASS
2198
+ end
2199
+
2200
+ def test_passing_required_args_as_a_keyword_arg
2201
+ assert_equal <<CSS, render(<<SASS)
2202
+ .mixed {
2203
+ required: foo;
2204
+ arg1: default-val1;
2205
+ arg2: default-val2; }
2206
+ CSS
2207
+ =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2208
+ required: $required
2209
+ arg1: $arg1
2210
+ arg2: $arg2
2211
+ .mixed
2212
+ +a-mixin($required: foo)
2213
+ SASS
2214
+ end
2215
+
2216
+ def test_passing_all_as_keyword_args_in_opposite_order
2217
+ assert_equal <<CSS, render(<<SASS)
2218
+ .mixed {
2219
+ required: foo;
2220
+ arg1: non-default-val1;
2221
+ arg2: non-default-val2; }
2222
+ CSS
2223
+ =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2224
+ required: $required
2225
+ arg1: $arg1
2226
+ arg2: $arg2
2227
+ .mixed
2228
+ +a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo)
2229
+ SASS
2230
+ end
2231
+
2232
+ def test_function_output_with_comma
2233
+ assert_equal <<CSS, render(<<SASS)
2234
+ foo {
2235
+ a: b(c), d(e); }
2236
+ CSS
2237
+ foo
2238
+ a: b(c), d(e)
2239
+ SASS
2240
+ end
2241
+
2242
+ def test_interpolation_with_comma
2243
+ assert_equal <<CSS, render(<<SASS)
2244
+ foo {
2245
+ a: foo, bar; }
2246
+ CSS
2247
+ $foo: foo
2248
+ foo
2249
+ a: \#{$foo}, bar
2250
+ SASS
2251
+ end
2252
+
2253
+ def test_string_interpolation_with_comma
2254
+ assert_equal <<CSS, render(<<SASS)
2255
+ foo {
2256
+ a: "bip foo bap", bar; }
2257
+ CSS
2258
+ $foo: foo
2259
+ foo
2260
+ a: "bip \#{$foo} bap", bar
2261
+ SASS
2262
+ end
2263
+
2264
+ def test_unknown_directive
2265
+ assert_equal <<CSS, render(<<SASS)
2266
+ @baz {
2267
+ c: d; }
2268
+ CSS
2269
+ @baz
2270
+ c: d
2271
+ SASS
2272
+ end
2273
+
2274
+ def test_comment_interpolation_warning
2275
+ assert_warning(<<END) {render("/* \#{foo}")}
2276
+ WARNING:
2277
+ On line 1 of 'test_comment_interpolation_warning_inline.sass'
2278
+ Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
2279
+ Please escape the interpolation by adding a backslash before the hash sign.
2280
+ END
2281
+ end
2282
+
2283
+ def test_loud_comment_interpolations_can_be_escaped
2284
+ assert_equal <<CSS, render(<<SASS)
2285
+ /* \#{foo} */
2286
+ CSS
2287
+ /* \\\#{foo}
2288
+ SASS
2289
+ assert_equal <<CSS, render(<<SASS)
2290
+ /* \#{foo} */
2291
+ CSS
2292
+ /*! \\\#{foo}
2293
+ SASS
2294
+ end
2295
+
2296
+ # Encodings
2297
+
2298
+ unless Sass::Util.ruby1_8?
2299
+ def test_encoding_error
2300
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
2301
+ assert(false, "Expected exception")
2302
+ rescue Sass::SyntaxError => e
2303
+ assert_equal(3, e.sass_line)
2304
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
2305
+ end
2306
+
2307
+ def test_ascii_incompatible_encoding_error
2308
+ template = "foo\nbar\nb_z".encode("utf-16le")
2309
+ template[9] = "\xFE".force_encoding("utf-16le")
2310
+ render(template)
2311
+ assert(false, "Expected exception")
2312
+ rescue Sass::SyntaxError => e
2313
+ assert_equal(3, e.sass_line)
2314
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
2315
+ end
2316
+
2317
+ def test_same_charset_as_encoding
2318
+ assert_renders_encoded(<<CSS, <<SASS)
2319
+ @charset "UTF-8";
2320
+ fóó {
2321
+ a: b; }
2322
+ CSS
2323
+ @charset "utf-8"
2324
+ fóó
2325
+ a: b
2326
+ SASS
2327
+ end
2328
+
2329
+ def test_different_charset_than_encoding
2330
+ assert_renders_encoded(<<CSS.force_encoding("IBM866"), <<SASS)
2331
+ @charset "IBM866";
2332
+ fóó {
2333
+ a: b; }
2334
+ CSS
2335
+ @charset "ibm866"
2336
+ fóó
2337
+ a: b
2338
+ SASS
2339
+ end
2340
+
2341
+ def test_different_encoding_than_system
2342
+ assert_renders_encoded(<<CSS.encode("IBM866"), <<SASS.encode("IBM866"))
2343
+ @charset "IBM866";
2344
+ тАЬ {
2345
+ a: b; }
2346
+ CSS
2347
+ тАЬ
2348
+ a: b
2349
+ SASS
2350
+ end
2351
+
2352
+ def test_multibyte_charset
2353
+ assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("UTF-8"))
2354
+ @charset "UTF-16LE";
2355
+ fóó {
2356
+ a: b; }
2357
+ CSS
2358
+ @charset "utf-16le"
2359
+ fóó
2360
+ a: b
2361
+ SASS
2362
+ end
2363
+
2364
+ def test_multibyte_charset_without_endian_specifier
2365
+ assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("UTF-8"))
2366
+ @charset "UTF-32BE";
2367
+ fóó {
2368
+ a: b; }
2369
+ CSS
2370
+ @charset "utf-32"
2371
+ fóó
2372
+ a: b
2373
+ SASS
2374
+ end
2375
+
2376
+ def test_utf8_bom
2377
+ assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
2378
+ @charset "UTF-8";
2379
+ fóó {
2380
+ a: b; }
2381
+ CSS
2382
+ \uFEFFfóó
2383
+ a: b
2384
+ SASS
2385
+ end
2386
+
2387
+ def test_utf16le_bom
2388
+ assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
2389
+ @charset "UTF-16LE";
2390
+ fóó {
2391
+ a: b; }
2392
+ CSS
2393
+ \uFEFFfóó
2394
+ a: b
2395
+ SASS
2396
+ end
2397
+
2398
+ def test_utf32be_bom
2399
+ assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("BINARY"))
2400
+ @charset "UTF-32BE";
2401
+ fóó {
2402
+ a: b; }
2403
+ CSS
2404
+ \uFEFFfóó
2405
+ a: b
2406
+ SASS
2407
+ end
2408
+ end
2409
+
2410
+ def test_original_filename_set
2411
+ importer = MockImporter.new
2412
+ importer.add_import("imported", "div{color:red}")
2413
+
2414
+ original_filename = filename_for_test
2415
+ engine = Sass::Engine.new('@import "imported"; div{color:blue}',
2416
+ :filename => original_filename, :load_paths => [importer], :syntax => :scss)
2417
+ engine.render
2418
+
2419
+ assert_equal original_filename, engine.options[:original_filename]
2420
+ assert_equal original_filename, importer.engine("imported").options[:original_filename]
2421
+ end
2422
+
2423
+
2424
+ private
2425
+
2426
+ def assert_hash_has(hash, expected)
2427
+ expected.each {|k, v| assert_equal(v, hash[k])}
2428
+ end
2429
+
2430
+ def assert_renders_encoded(css, sass)
2431
+ result = render(sass)
2432
+ assert_equal css.encoding, result.encoding
2433
+ assert_equal css, result
2434
+ end
2435
+
2436
+ def render(sass, options = {})
2437
+ munge_filename options
2438
+ Sass::Engine.new(sass, options).render
2439
+ end
2440
+
2441
+ def renders_correctly(name, options={})
2442
+ sass_file = load_file(name, "sass")
2443
+ css_file = load_file(name, "css")
2444
+ options[:filename] ||= filename(name, "sass")
2445
+ options[:syntax] ||= :sass
2446
+ options[:css_filename] ||= filename(name, "css")
2447
+ css_result = Sass::Engine.new(sass_file, options).render
2448
+ assert_equal css_file, css_result
2449
+ end
2450
+
2451
+ def load_file(name, type = "sass")
2452
+ @result = ''
2453
+ File.new(filename(name, type)).each_line { |l| @result += l }
2454
+ @result
2455
+ end
2456
+
2457
+ def filename(name, type)
2458
+ File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
2459
+ end
2460
+
2461
+ def sassc_path(template)
2462
+ sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
2463
+ engine = Sass::Engine.new("", :filename => sassc_path,
2464
+ :importer => Sass::Importers::Filesystem.new("."))
2465
+ key = engine.send(:sassc_key)
2466
+ File.join(engine.options[:cache_location], key)
2467
+ end
2468
+ end
2469
+