haml_ejs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+