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,255 @@
1
+ # A visitor for converting a Sass tree into a source string.
2
+ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
3
+ # Runs the visitor on a tree.
4
+ #
5
+ # @param root [Tree::Node] The root node of the Sass tree.
6
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
7
+ # @param format [Symbol] `:sass` or `:scss`.
8
+ # @return [String] The Sass or SCSS source for the tree.
9
+ def self.visit(root, options, format)
10
+ new(options, format).send(:visit, root)
11
+ end
12
+
13
+ protected
14
+
15
+ def initialize(options, format)
16
+ @options = options
17
+ @format = format
18
+ @tabs = 0
19
+ end
20
+
21
+ def visit_children(parent)
22
+ @tabs += 1
23
+ return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
24
+ (@format == :sass ? "\n" : " {\n") + super.join.rstrip + (@format == :sass ? "\n" : " }\n")
25
+ ensure
26
+ @tabs -= 1
27
+ end
28
+
29
+ # Ensures proper spacing between top-level nodes.
30
+ def visit_root(node)
31
+ Sass::Util.enum_cons(node.children + [nil], 2).map do |child, nxt|
32
+ visit(child) +
33
+ if nxt &&
34
+ (child.is_a?(Sass::Tree::CommentNode) &&
35
+ child.line + child.value.count("\n") + 1 == nxt.line) ||
36
+ (child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
37
+ child.line + 1 == nxt.line) ||
38
+ (child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
39
+ child.line + 1 == nxt.line)
40
+ ""
41
+ else
42
+ "\n"
43
+ end
44
+ end.join.rstrip + "\n"
45
+ end
46
+
47
+ def visit_charset(node)
48
+ "#{tab_str}@charset \"#{node.name}\"#{semi}\n"
49
+ end
50
+
51
+ def visit_comment(node)
52
+ content = if @format == :sass
53
+ content = node.value.gsub(/\*\/$/, '').rstrip
54
+ if content =~ /\A[ \t]/
55
+ # Re-indent SCSS comments like this:
56
+ # /* foo
57
+ # bar
58
+ # baz */
59
+ content.gsub!(/^/, ' ')
60
+ content.sub!(/\A([ \t]*)\/\*/, '/*\1')
61
+ end
62
+
63
+ content =
64
+ unless content.include?("\n")
65
+ content
66
+ else
67
+ content.gsub!(/\n( \*|\/\/)/, "\n ")
68
+ spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
69
+ sep = node.silent ? "\n//" : "\n *"
70
+ if spaces >= 2
71
+ content.gsub(/\n /, sep)
72
+ else
73
+ content.gsub(/\n#{' ' * spaces}/, sep)
74
+ end
75
+ end
76
+
77
+ content.gsub!(/\A\/\*/, '//') if node.silent
78
+ content.gsub!(/^/, tab_str)
79
+ content.rstrip + "\n"
80
+ else
81
+ spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max)
82
+ content = if node.silent
83
+ node.value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
84
+ else
85
+ node.value
86
+ end.gsub(/^/, spaces) + "\n"
87
+ content
88
+ end
89
+ if node.loud
90
+ if node.silent
91
+ content.gsub!(%r{^\s*(//!?)}, '//!')
92
+ else
93
+ content.sub!(%r{^\s*(/\*)}, '/*!')
94
+ end
95
+ end
96
+ content
97
+ end
98
+
99
+ def visit_debug(node)
100
+ "#{tab_str}@debug #{node.expr.to_sass(@options)}#{semi}\n"
101
+ end
102
+
103
+ def visit_directive(node)
104
+ res = "#{tab_str}#{node.value}"
105
+ return res + "#{semi}\n" unless node.has_children
106
+ res + yield + "\n"
107
+ end
108
+
109
+ def visit_each(node)
110
+ "#{tab_str}@each $#{dasherize(node.var)} in #{node.list.to_sass(@options)}#{yield}"
111
+ end
112
+
113
+ def visit_extend(node)
114
+ "#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}\n"
115
+ end
116
+
117
+ def visit_for(node)
118
+ "#{tab_str}@for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " +
119
+ "#{node.exclusive ? "to" : "through"} #{node.to.to_sass(@options)}#{yield}"
120
+ end
121
+
122
+ def visit_function(node)
123
+ args = node.args.map do |v, d|
124
+ d ? "#{v.to_sass(@options)}: #{d.to_sass(@options)}" : v.to_sass(@options)
125
+ end.join(", ")
126
+
127
+ "#{tab_str}@function #{dasherize(node.name)}(#{args})#{yield}"
128
+ end
129
+
130
+ def visit_if(node)
131
+ name =
132
+ if !@is_else; "if"
133
+ elsif node.expr; "else if"
134
+ else; "else"
135
+ end
136
+ str = "#{tab_str}@#{name}"
137
+ str << " #{node.expr.to_sass(@options)}" if node.expr
138
+ str << yield
139
+ @is_else = true
140
+ str << visit(node.else) if node.else
141
+ str
142
+ ensure
143
+ @is_else = false
144
+ end
145
+
146
+ def visit_import(node)
147
+ quote = @format == :scss ? '"' : ''
148
+ "#{tab_str}@import #{quote}#{node.imported_filename}#{quote}#{semi}\n"
149
+ end
150
+
151
+ def visit_media(node)
152
+ "#{tab_str}@media #{node.query}#{yield}"
153
+ end
154
+
155
+ def visit_mixindef(node)
156
+ args =
157
+ if node.args.empty?
158
+ ""
159
+ else
160
+ '(' + node.args.map do |v, d|
161
+ if d
162
+ "#{v.to_sass(@options)}: #{d.to_sass(@options)}"
163
+ else
164
+ v.to_sass(@options)
165
+ end
166
+ end.join(", ") + ')'
167
+ end
168
+
169
+ "#{tab_str}#{@format == :sass ? '=' : '@mixin '}#{dasherize(node.name)}#{args}#{yield}"
170
+ end
171
+
172
+ def visit_mixin(node)
173
+ unless node.args.empty? && node.keywords.empty?
174
+ args = node.args.map {|a| a.to_sass(@options)}.join(", ")
175
+ keywords = node.keywords.map {|k, v| "$#{dasherize(k)}: #{v.to_sass(@options)}"}.join(', ')
176
+ arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
177
+ end
178
+ "#{tab_str}#{@format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{semi}\n"
179
+ end
180
+
181
+ def visit_prop(node)
182
+ res = tab_str + node.declaration(@options, @format)
183
+ return res + semi + "\n" if node.children.empty?
184
+ res + yield.rstrip + semi + "\n"
185
+ end
186
+
187
+ def visit_return(node)
188
+ "#{tab_str}@return #{node.expr.to_sass(@options)}#{semi}\n"
189
+ end
190
+
191
+ def visit_rule(node)
192
+ if @format == :sass
193
+ name = selector_to_sass(node.rule)
194
+ name = "\\" + name if name[0] == ?:
195
+ name.gsub(/^/, tab_str) + yield
196
+ elsif @format == :scss
197
+ name = selector_to_scss(node.rule)
198
+ res = name + yield
199
+ if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.silent
200
+ res.slice!(-3..-1)
201
+ res << "\n" << tab_str << "}\n"
202
+ end
203
+ res
204
+ end
205
+ end
206
+
207
+ def visit_variable(node)
208
+ "#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}#{' !default' if node.guarded}#{semi}\n"
209
+ end
210
+
211
+ def visit_warn(node)
212
+ "#{tab_str}@warn #{node.expr.to_sass(@options)}#{semi}\n"
213
+ end
214
+
215
+ def visit_while(node)
216
+ "#{tab_str}@while #{node.expr.to_sass(@options)}#{yield}"
217
+ end
218
+
219
+ private
220
+
221
+ def selector_to_src(sel)
222
+ @format == :sass ? selector_to_sass(sel) : selector_to_scss(sel)
223
+ end
224
+
225
+ def selector_to_sass(sel)
226
+ sel.map do |r|
227
+ if r.is_a?(String)
228
+ r.gsub(/(,[ \t]*)?\n\s*/) {$1 ? $1 + "\n" : " "}
229
+ else
230
+ "\#{#{r.to_sass(@options)}}"
231
+ end
232
+ end.join
233
+ end
234
+
235
+ def selector_to_scss(sel)
236
+ sel.map {|r| r.is_a?(String) ? r : "\#{#{r.to_sass(@options)}}"}.
237
+ join.gsub(/^[ \t]*/, tab_str)
238
+ end
239
+
240
+ def semi
241
+ @format == :sass ? "" : ";"
242
+ end
243
+
244
+ def tab_str
245
+ ' ' * @tabs
246
+ end
247
+
248
+ def dasherize(s)
249
+ if @options[:dasherize]
250
+ s.gsub('_', '-')
251
+ else
252
+ s
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,175 @@
1
+ # A visitor for converting a static Sass tree into a static CSS tree.
2
+ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
3
+ # @param root [Tree::Node] The root node of the tree to visit.
4
+ # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
5
+ # *and* the extensions defined for this tree
6
+ def self.visit(root); super; end
7
+
8
+ protected
9
+
10
+ # Returns the immediate parent of the current node.
11
+ # @return [Tree::Node]
12
+ attr_reader :parent
13
+
14
+ def initialize
15
+ @extends = Sass::Util::SubsetMap.new
16
+ end
17
+
18
+ # If an exception is raised, this adds proper metadata to the backtrace.
19
+ def visit(node)
20
+ super(node.dup)
21
+ rescue Sass::SyntaxError => e
22
+ e.modify_backtrace(:filename => node.filename, :line => node.line)
23
+ raise e
24
+ end
25
+
26
+ # Keeps track of the current parent node.
27
+ def visit_children(parent)
28
+ with_parent parent do
29
+ parent.children = super.flatten
30
+ parent
31
+ end
32
+ end
33
+
34
+ # Runs a block of code with the current parent node
35
+ # replaced with the given node.
36
+ #
37
+ # @param parent [Tree::Node] The new parent for the duration of the block.
38
+ # @yield A block in which the parent is set to `parent`.
39
+ # @return [Object] The return value of the block.
40
+ def with_parent(parent)
41
+ old_parent, @parent = @parent, parent
42
+ yield
43
+ ensure
44
+ @parent = old_parent
45
+ end
46
+
47
+ # In Ruby 1.8, ensures that there's only one `@charset` directive
48
+ # and that it's at the top of the document.
49
+ #
50
+ # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
51
+ # *and* the extensions defined for this tree
52
+ def visit_root(node)
53
+ yield
54
+
55
+ # In Ruby 1.9 we can make all @charset nodes invisible
56
+ # and infer the final @charset from the encoding of the final string.
57
+ if Sass::Util.ruby1_8? && parent.nil?
58
+ charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
59
+ node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
60
+ node.children.unshift charset if charset
61
+ end
62
+
63
+ return node, @extends
64
+ rescue Sass::SyntaxError => e
65
+ e.sass_template ||= node.template
66
+ raise e
67
+ end
68
+
69
+ # Registers an extension in the `@extends` subset map.
70
+ def visit_extend(node)
71
+ node.resolved_selector.members.each do |seq|
72
+ if seq.members.size > 1
73
+ raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
74
+ end
75
+
76
+ sseq = seq.members.first
77
+ if !sseq.is_a?(Sass::Selector::SimpleSequence)
78
+ raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
79
+ end
80
+
81
+ sel = sseq.members
82
+ parent.resolved_rules.members.each do |seq|
83
+ if !seq.members.last.is_a?(Sass::Selector::SimpleSequence)
84
+ raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
85
+ end
86
+
87
+ @extends[sel] = seq
88
+ end
89
+ end
90
+
91
+ []
92
+ end
93
+
94
+ # Modifies exception backtraces to include the imported file.
95
+ def visit_import(node)
96
+ # Don't use #visit_children to avoid adding the import node to the list of parents.
97
+ node.children.map {|c| visit(c)}.flatten
98
+ rescue Sass::SyntaxError => e
99
+ e.modify_backtrace(:filename => node.children.first.filename)
100
+ e.add_backtrace(:filename => node.filename, :line => node.line)
101
+ raise e
102
+ end
103
+
104
+ # Bubbles the `@media` directive up through RuleNodes
105
+ # and merges it with other `@media` directives.
106
+ def visit_media(node)
107
+ if parent.is_a?(Sass::Tree::RuleNode)
108
+ new_rule = parent.dup
109
+ new_rule.children = node.children
110
+ node.children = with_parent(node) {Array(visit(new_rule))}
111
+ # If the last child is actually the end of the group,
112
+ # the parent's cssize will set it properly
113
+ node.children.last.group_end = false unless node.children.empty?
114
+ else
115
+ yield
116
+ end
117
+
118
+ media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
119
+ node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
120
+ media.each {|n| n.query = "#{node.query} and #{n.query}"}
121
+ (node.children.empty? ? [] : [node]) + media
122
+ end
123
+
124
+ # Asserts that all the mixin's children are valid in their new location.
125
+ def visit_mixin(node)
126
+ # Don't use #visit_children to avoid adding the mixin node to the list of parents.
127
+ node.children.map {|c| visit(c)}.flatten
128
+ rescue Sass::SyntaxError => e
129
+ e.modify_backtrace(:mixin => node.name, :filename => node.filename, :line => node.line)
130
+ e.add_backtrace(:filename => node.filename, :line => node.line)
131
+ raise e
132
+ end
133
+
134
+ # Converts nested properties into flat properties
135
+ # and updates the indentation of the prop node based on the nesting level.
136
+ def visit_prop(node)
137
+ if parent.is_a?(Sass::Tree::PropNode)
138
+ node.resolved_name = "#{parent.resolved_name}-#{node.resolved_name}"
139
+ node.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if node.style == :nested
140
+ end
141
+
142
+ yield
143
+
144
+ result = node.children.dup
145
+ if !node.resolved_value.empty? || node.children.empty?
146
+ node.send(:check!)
147
+ result.unshift(node)
148
+ end
149
+
150
+ result
151
+ end
152
+
153
+ # Resolves parent references and nested selectors,
154
+ # and updates the indentation of the rule node based on the nesting level.
155
+ def visit_rule(node)
156
+ parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil
157
+ # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
158
+ node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules)
159
+
160
+ yield
161
+
162
+ rules = node.children.select {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode)}
163
+ props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode) || c.invisible?}
164
+
165
+ unless props.empty?
166
+ node.children = props
167
+ rules.each {|r| r.tabs += 1} if node.style == :nested
168
+ rules.unshift(node)
169
+ end
170
+
171
+ rules.last.group_end = true unless parent.is_a?(Sass::Tree::RuleNode) || rules.empty?
172
+
173
+ rules
174
+ end
175
+ end
@@ -0,0 +1,301 @@
1
+ # A visitor for converting a dynamic Sass tree into a static Sass tree.
2
+ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
3
+ # @param root [Tree::Node] The root node of the tree to visit.
4
+ # @param environment [Sass::Environment] The lexical environment.
5
+ # @return [Tree::Node] The resulting tree of static nodes.
6
+ def self.visit(root, environment = Sass::Environment.new)
7
+ new(environment).send(:visit, root)
8
+ end
9
+
10
+ protected
11
+
12
+ def initialize(env)
13
+ @environment = env
14
+ end
15
+
16
+ # If an exception is raised, this add proper metadata to the backtrace.
17
+ def visit(node)
18
+ super(node.dup)
19
+ rescue Sass::SyntaxError => e
20
+ e.modify_backtrace(:filename => node.filename, :line => node.line)
21
+ raise e
22
+ end
23
+
24
+ # Keeps track of the current environment.
25
+ def visit_children(parent)
26
+ with_environment Sass::Environment.new(@environment) do
27
+ parent.children = super.flatten
28
+ parent
29
+ end
30
+ end
31
+
32
+ # Runs a block of code with the current environment replaced with the given one.
33
+ #
34
+ # @param env [Sass::Environment] The new environment for the duration of the block.
35
+ # @yield A block in which the environment is set to `env`.
36
+ # @return [Object] The return value of the block.
37
+ def with_environment(env)
38
+ old_env, @environment = @environment, env
39
+ yield
40
+ ensure
41
+ @environment = old_env
42
+ end
43
+
44
+ # Sets the options on the environment if this is the top-level root.
45
+ def visit_root(node)
46
+ @environment.options = node.options if @environment.options.nil? || @environment.options.empty?
47
+ yield
48
+ rescue Sass::SyntaxError => e
49
+ e.sass_template ||= node.template
50
+ raise e
51
+ end
52
+
53
+ # Removes this node from the tree if it's a silent comment.
54
+ def visit_comment(node)
55
+ return [] if node.invisible?
56
+ if node.evaluated?
57
+ node.value.gsub!(/(^|[^\\])\#\{([^}]*)\}/) do |md|
58
+ $1+Sass::Script.parse($2, node.line, 0, node.options).perform(@environment).to_s
59
+ end
60
+ node.value = run_interp([Sass::Script::String.new(node.value)])
61
+ end
62
+ node
63
+ end
64
+
65
+ # Prints the expression to STDERR.
66
+ def visit_debug(node)
67
+ res = node.expr.perform(@environment)
68
+ res = res.value if res.is_a?(Sass::Script::String)
69
+ if node.filename
70
+ $stderr.puts "#{node.filename}:#{node.line} DEBUG: #{res}"
71
+ else
72
+ $stderr.puts "Line #{node.line} DEBUG: #{res}"
73
+ end
74
+ []
75
+ end
76
+
77
+ # Runs the child nodes once for each value in the list.
78
+ def visit_each(node)
79
+ list = node.list.perform(@environment)
80
+
81
+ with_environment Sass::Environment.new(@environment) do
82
+ list.to_a.map do |v|
83
+ @environment.set_local_var(node.var, v)
84
+ node.children.map {|c| visit(c)}
85
+ end.flatten
86
+ end
87
+ end
88
+
89
+ # Runs SassScript interpolation in the selector,
90
+ # and then parses the result into a {Sass::Selector::CommaSequence}.
91
+ def visit_extend(node)
92
+ parser = Sass::SCSS::CssParser.new(run_interp(node.selector), node.line)
93
+ node.resolved_selector = parser.parse_selector(node.filename)
94
+ node
95
+ end
96
+
97
+ # Runs the child nodes once for each time through the loop, varying the variable each time.
98
+ def visit_for(node)
99
+ from = node.from.perform(@environment)
100
+ to = node.to.perform(@environment)
101
+ from.assert_int!
102
+ to.assert_int!
103
+
104
+ to = to.coerce(from.numerator_units, from.denominator_units)
105
+ range = Range.new(from.to_i, to.to_i, node.exclusive)
106
+
107
+ with_environment Sass::Environment.new(@environment) do
108
+ range.map do |i|
109
+ @environment.set_local_var(node.var,
110
+ Sass::Script::Number.new(i, from.numerator_units, from.denominator_units))
111
+ node.children.map {|c| visit(c)}
112
+ end.flatten
113
+ end
114
+ end
115
+
116
+ # Loads the function into the environment.
117
+ def visit_function(node)
118
+ @environment.set_function(node.name,
119
+ Sass::Callable.new(node.name, node.args, @environment, node.children))
120
+ []
121
+ end
122
+
123
+ # Runs the child nodes if the conditional expression is true;
124
+ # otherwise, tries the else nodes.
125
+ def visit_if(node)
126
+ if node.expr.nil? || node.expr.perform(@environment).to_bool
127
+ yield
128
+ node.children
129
+ elsif node.else
130
+ visit(node.else)
131
+ else
132
+ []
133
+ end
134
+ end
135
+
136
+ # Returns a static DirectiveNode if this is importing a CSS file,
137
+ # or parses and includes the imported Sass file.
138
+ def visit_import(node)
139
+ if path = node.css_import?
140
+ return Sass::Tree::DirectiveNode.new("@import url(#{path})")
141
+ end
142
+
143
+ @environment.push_frame(:filename => node.filename, :line => node.line)
144
+ root = node.imported_file.to_tree
145
+ node.children = root.children.map {|c| visit(c)}.flatten
146
+ node
147
+ rescue Sass::SyntaxError => e
148
+ e.modify_backtrace(:filename => node.imported_file.options[:filename])
149
+ e.add_backtrace(:filename => node.filename, :line => node.line)
150
+ raise e
151
+ ensure
152
+ @environment.pop_frame
153
+ end
154
+
155
+ # Loads a mixin into the environment.
156
+ def visit_mixindef(node)
157
+ @environment.set_mixin(node.name,
158
+ Sass::Callable.new(node.name, node.args, @environment, node.children))
159
+ []
160
+ end
161
+
162
+ # Runs a mixin.
163
+ def visit_mixin(node)
164
+ handle_include_loop!(node) if @environment.mixins_in_use.include?(node.name)
165
+
166
+ original_env = @environment
167
+ original_env.push_frame(:filename => node.filename, :line => node.line)
168
+ original_env.prepare_frame(:mixin => node.name)
169
+ raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin = @environment.mixin(node.name)
170
+
171
+ passed_args = node.args.dup
172
+ passed_keywords = node.keywords.dup
173
+
174
+ raise Sass::SyntaxError.new(<<END.gsub("\n", "")) if mixin.args.size < passed_args.size
175
+ Mixin #{node.name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
176
+ but #{node.args.size} #{node.args.size == 1 ? 'was' : 'were'} passed.
177
+ END
178
+
179
+ passed_keywords.each do |name, value|
180
+ # TODO: Make this fast
181
+ unless mixin.args.find {|(var, default)| var.underscored_name == name}
182
+ raise Sass::SyntaxError.new("Mixin #{node.name} doesn't have an argument named $#{name}")
183
+ end
184
+ end
185
+
186
+ environment = mixin.args.zip(passed_args).
187
+ inject(Sass::Environment.new(mixin.environment)) do |env, ((var, default), value)|
188
+ env.set_local_var(var.name,
189
+ if value
190
+ value.perform(@environment)
191
+ elsif kv = passed_keywords[var.underscored_name]
192
+ kv.perform(@environment)
193
+ elsif default
194
+ default.perform(env)
195
+ end)
196
+ raise Sass::SyntaxError.new("Mixin #{node.name} is missing parameter #{var.inspect}.") unless env.var(var.name)
197
+ env
198
+ end
199
+
200
+ with_environment(environment) {node.children = mixin.tree.map {|c| visit(c)}.flatten}
201
+ node
202
+ rescue Sass::SyntaxError => e
203
+ if original_env # Don't add backtrace info if this is an @include loop
204
+ e.modify_backtrace(:mixin => node.name, :line => node.line)
205
+ e.add_backtrace(:line => node.line)
206
+ end
207
+ raise e
208
+ ensure
209
+ original_env.pop_frame if original_env
210
+ end
211
+
212
+ # Runs any SassScript that may be embedded in a property.
213
+ def visit_prop(node)
214
+ node.resolved_name = run_interp(node.name)
215
+ val = node.value.perform(@environment)
216
+ node.resolved_value = val.to_s
217
+ yield
218
+ end
219
+
220
+ # Returns the value of the expression.
221
+ def visit_return(node)
222
+ throw :_sass_return, node.expr.perform(@environment)
223
+ end
224
+
225
+ # Runs SassScript interpolation in the selector,
226
+ # and then parses the result into a {Sass::Selector::CommaSequence}.
227
+ def visit_rule(node)
228
+ parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.line)
229
+ node.parsed_rules ||= parser.parse_selector(node.filename)
230
+ yield
231
+ end
232
+
233
+ # Loads the new variable value into the environment.
234
+ def visit_variable(node)
235
+ return [] if node.guarded && !@environment.var(node.name).nil?
236
+ val = node.expr.perform(@environment)
237
+ @environment.set_var(node.name, val)
238
+ []
239
+ end
240
+
241
+ # Prints the expression to STDERR with a stylesheet trace.
242
+ def visit_warn(node)
243
+ @environment.push_frame(:filename => node.filename, :line => node.line)
244
+ res = node.expr.perform(@environment)
245
+ res = res.value if res.is_a?(Sass::Script::String)
246
+ msg = "WARNING: #{res}\n"
247
+ @environment.stack.reverse.each_with_index do |entry, i|
248
+ msg << " #{i == 0 ? "on" : "from"} line #{entry[:line]}" <<
249
+ " of #{entry[:filename] || "an unknown file"}"
250
+ msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
251
+ msg << "\n"
252
+ end
253
+ Sass::Util.sass_warn msg
254
+ []
255
+ ensure
256
+ @environment.pop_frame
257
+ end
258
+
259
+ # Runs the child nodes until the continuation expression becomes false.
260
+ def visit_while(node)
261
+ children = []
262
+ with_environment Sass::Environment.new(@environment) do
263
+ children += node.children.map {|c| visit(c)} while node.expr.perform(@environment).to_bool
264
+ end
265
+ children.flatten
266
+ end
267
+
268
+ def visit_directive(node)
269
+ if node.value['#{']
270
+ node.value = run_interp(Sass::Engine.parse_interp(node.value, node.line, 0, node.options))
271
+ end
272
+ yield
273
+ node
274
+ end
275
+
276
+ private
277
+
278
+ def run_interp(text)
279
+ text.map do |r|
280
+ next r if r.is_a?(String)
281
+ val = r.perform(@environment)
282
+ # Interpolated strings should never render with quotes
283
+ next val.value if val.is_a?(Sass::Script::String)
284
+ val.to_s
285
+ end.join.strip
286
+ end
287
+
288
+ def handle_include_loop!(node)
289
+ msg = "An @include loop has been found:"
290
+ mixins = @environment.stack.map {|s| s[:mixin]}.compact
291
+ if mixins.size == 2 && mixins[0] == mixins[1]
292
+ raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself")
293
+ end
294
+
295
+ mixins << node.name
296
+ msg << "\n" << Sass::Util.enum_cons(mixins, 2).map do |m1, m2|
297
+ " #{m1} includes #{m2}"
298
+ end.join("\n")
299
+ raise Sass::SyntaxError.new(msg)
300
+ end
301
+ end