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,155 @@
1
+ require 'set'
2
+
3
+ module Sass
4
+ # The lexical environment for SassScript.
5
+ # This keeps track of variable, mixin, and function definitions.
6
+ #
7
+ # A new environment is created for each level of Sass nesting.
8
+ # This allows variables to be lexically scoped.
9
+ # The new environment refers to the environment in the upper scope,
10
+ # so it has access to variables defined in enclosing scopes,
11
+ # but new variables are defined locally.
12
+ #
13
+ # Environment also keeps track of the {Engine} options
14
+ # so that they can be made available to {Sass::Script::Functions}.
15
+ class Environment
16
+ # The enclosing environment,
17
+ # or nil if this is the global environment.
18
+ #
19
+ # @return [Environment]
20
+ attr_reader :parent
21
+ attr_writer :options
22
+
23
+ # @param parent [Environment] See \{#parent}
24
+ def initialize(parent = nil)
25
+ @parent = parent
26
+ unless parent
27
+ @stack = []
28
+ @mixins_in_use = Set.new
29
+ set_var("important", Script::String.new("!important"))
30
+ end
31
+ end
32
+
33
+ # The options hash.
34
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
35
+ #
36
+ # @return [{Symbol => Object}]
37
+ def options
38
+ @options || parent_options || {}
39
+ end
40
+
41
+ # Push a new stack frame onto the mixin/include stack.
42
+ #
43
+ # @param frame_info [{Symbol => Object}]
44
+ # Frame information has the following keys:
45
+ #
46
+ # `:filename`
47
+ # : The name of the file in which the lexical scope changed.
48
+ #
49
+ # `:mixin`
50
+ # : The name of the mixin in which the lexical scope changed,
51
+ # or `nil` if it wasn't within in a mixin.
52
+ #
53
+ # `:line`
54
+ # : The line of the file on which the lexical scope changed. Never nil.
55
+ def push_frame(frame_info)
56
+ top_of_stack = stack.last
57
+ if top_of_stack && top_of_stack.delete(:prepared)
58
+ top_of_stack.merge!(frame_info)
59
+ else
60
+ stack.push(top_of_stack = frame_info)
61
+ end
62
+ mixins_in_use << top_of_stack[:mixin] if top_of_stack[:mixin] && !top_of_stack[:prepared]
63
+ end
64
+
65
+ # Like \{#push\_frame}, but next time a stack frame is pushed,
66
+ # it will be merged with this frame.
67
+ #
68
+ # @param frame_info [{Symbol => Object}] Same as for \{#push\_frame}.
69
+ def prepare_frame(frame_info)
70
+ push_frame(frame_info.merge(:prepared => true))
71
+ end
72
+
73
+ # Pop a stack frame from the mixin/include stack.
74
+ def pop_frame
75
+ stack.pop if stack.last && stack.last[:prepared]
76
+ popped = stack.pop
77
+ mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin]
78
+ end
79
+
80
+ # A list of stack frames in the mixin/include stack.
81
+ # The last element in the list is the most deeply-nested frame.
82
+ #
83
+ # @return [Array<{Symbol => Object}>] The stack frames,
84
+ # of the form passed to \{#push\_frame}.
85
+ def stack
86
+ @stack ||= @parent.stack
87
+ end
88
+
89
+ # A set of names of mixins currently present in the stack.
90
+ #
91
+ # @return [Set<String>] The mixin names.
92
+ def mixins_in_use
93
+ @mixins_in_use ||= @parent.mixins_in_use
94
+ end
95
+
96
+ private
97
+
98
+ def parent_options
99
+ @parent_options ||= @parent && @parent.options
100
+ end
101
+
102
+ class << self
103
+ private
104
+ UNDERSCORE, DASH = '_', '-'
105
+
106
+ # Note: when updating this,
107
+ # update sass/yard/inherited_hash.rb as well.
108
+ def inherited_hash(name)
109
+ class_eval <<RUBY, __FILE__, __LINE__ + 1
110
+ def #{name}(name)
111
+ _#{name}(name.tr(UNDERSCORE, DASH))
112
+ end
113
+
114
+ def _#{name}(name)
115
+ (@#{name}s && @#{name}s[name]) || @parent && @parent._#{name}(name)
116
+ end
117
+ protected :_#{name}
118
+
119
+ def set_#{name}(name, value)
120
+ name = name.tr(UNDERSCORE, DASH)
121
+ @#{name}s[name] = value unless try_set_#{name}(name, value)
122
+ end
123
+
124
+ def try_set_#{name}(name, value)
125
+ @#{name}s ||= {}
126
+ if @#{name}s.include?(name)
127
+ @#{name}s[name] = value
128
+ true
129
+ elsif @parent
130
+ @parent.try_set_#{name}(name, value)
131
+ else
132
+ false
133
+ end
134
+ end
135
+ protected :try_set_#{name}
136
+
137
+ def set_local_#{name}(name, value)
138
+ @#{name}s ||= {}
139
+ @#{name}s[name.tr(UNDERSCORE, DASH)] = value
140
+ end
141
+ RUBY
142
+ end
143
+ end
144
+
145
+ # variable
146
+ # Script::Literal
147
+ inherited_hash :var
148
+ # mixin
149
+ # Sass::Callable
150
+ inherited_hash :mixin
151
+ # function
152
+ # Sass::Callable
153
+ inherited_hash :function
154
+ end
155
+ end
@@ -0,0 +1,201 @@
1
+ module Sass
2
+ # An exception class that keeps track of
3
+ # the line of the Sass template it was raised on
4
+ # and the Sass file that was being parsed (if applicable).
5
+ #
6
+ # All Sass errors are raised as {Sass::SyntaxError}s.
7
+ #
8
+ # When dealing with SyntaxErrors,
9
+ # it's important to provide filename and line number information.
10
+ # This will be used in various error reports to users, including backtraces;
11
+ # see \{#sass\_backtrace} for details.
12
+ #
13
+ # Some of this information is usually provided as part of the constructor.
14
+ # New backtrace entries can be added with \{#add\_backtrace},
15
+ # which is called when an exception is raised between files (e.g. with `@import`).
16
+ #
17
+ # Often, a chunk of code will all have similar backtrace information -
18
+ # the same filename or even line.
19
+ # It may also be useful to have a default line number set.
20
+ # In those situations, the default values can be used
21
+ # by omitting the information on the original exception,
22
+ # and then calling \{#modify\_backtrace} in a wrapper `rescue`.
23
+ # When doing this, be sure that all exceptions ultimately end up
24
+ # with the information filled in.
25
+ class SyntaxError < StandardError
26
+ # The backtrace of the error within Sass files.
27
+ # This is an array of hashes containing information for a single entry.
28
+ # The hashes have the following keys:
29
+ #
30
+ # `:filename`
31
+ # : The name of the file in which the exception was raised,
32
+ # or `nil` if no filename is available.
33
+ #
34
+ # `:mixin`
35
+ # : The name of the mixin in which the exception was raised,
36
+ # or `nil` if it wasn't raised in a mixin.
37
+ #
38
+ # `:line`
39
+ # : The line of the file on which the error occurred. Never nil.
40
+ #
41
+ # This information is also included in standard backtrace format
42
+ # in the output of \{#backtrace}.
43
+ #
44
+ # @return [Aray<{Symbol => Object>}]
45
+ attr_accessor :sass_backtrace
46
+
47
+ # The text of the template where this error was raised.
48
+ #
49
+ # @return [String]
50
+ attr_accessor :sass_template
51
+
52
+ # @param msg [String] The error message
53
+ # @param attrs [{Symbol => Object}] The information in the backtrace entry.
54
+ # See \{#sass\_backtrace}
55
+ def initialize(msg, attrs = {})
56
+ @message = msg
57
+ @sass_backtrace = []
58
+ add_backtrace(attrs)
59
+ end
60
+
61
+ # The name of the file in which the exception was raised.
62
+ # This could be `nil` if no filename is available.
63
+ #
64
+ # @return [String, nil]
65
+ def sass_filename
66
+ sass_backtrace.first[:filename]
67
+ end
68
+
69
+ # The name of the mixin in which the error occurred.
70
+ # This could be `nil` if the error occurred outside a mixin.
71
+ #
72
+ # @return [Fixnum]
73
+ def sass_mixin
74
+ sass_backtrace.first[:mixin]
75
+ end
76
+
77
+ # The line of the Sass template on which the error occurred.
78
+ #
79
+ # @return [Fixnum]
80
+ def sass_line
81
+ sass_backtrace.first[:line]
82
+ end
83
+
84
+ # Adds an entry to the exception's Sass backtrace.
85
+ #
86
+ # @param attrs [{Symbol => Object}] The information in the backtrace entry.
87
+ # See \{#sass\_backtrace}
88
+ def add_backtrace(attrs)
89
+ sass_backtrace << attrs.reject {|k, v| v.nil?}
90
+ end
91
+
92
+ # Modify the top Sass backtrace entries
93
+ # (that is, the most deeply nested ones)
94
+ # to have the given attributes.
95
+ #
96
+ # Specifically, this goes through the backtrace entries
97
+ # from most deeply nested to least,
98
+ # setting the given attributes for each entry.
99
+ # If an entry already has one of the given attributes set,
100
+ # the pre-existing attribute takes precedence
101
+ # and is not used for less deeply-nested entries
102
+ # (even if they don't have that attribute set).
103
+ #
104
+ # @param attrs [{Symbol => Object}] The information to add to the backtrace entry.
105
+ # See \{#sass\_backtrace}
106
+ def modify_backtrace(attrs)
107
+ attrs = attrs.reject {|k, v| v.nil?}
108
+ # Move backwards through the backtrace
109
+ (0...sass_backtrace.size).to_a.reverse.each do |i|
110
+ entry = sass_backtrace[i]
111
+ sass_backtrace[i] = attrs.merge(entry)
112
+ attrs.reject! {|k, v| entry.include?(k)}
113
+ break if attrs.empty?
114
+ end
115
+ end
116
+
117
+ # @return [String] The error message
118
+ def to_s
119
+ @message
120
+ end
121
+
122
+ # Returns the standard exception backtrace,
123
+ # including the Sass backtrace.
124
+ #
125
+ # @return [Array<String>]
126
+ def backtrace
127
+ return nil if super.nil?
128
+ return super if sass_backtrace.all? {|h| h.empty?}
129
+ sass_backtrace.map do |h|
130
+ "#{h[:filename] || "(sass)"}:#{h[:line]}" +
131
+ (h[:mixin] ? ":in `#{h[:mixin]}'" : "")
132
+ end + super
133
+ end
134
+
135
+ # Returns a string representation of the Sass backtrace.
136
+ #
137
+ # @param default_filename [String] The filename to use for unknown files
138
+ # @see #sass_backtrace
139
+ # @return [String]
140
+ def sass_backtrace_str(default_filename = "an unknown file")
141
+ lines = self.message.split("\n")
142
+ msg = lines[0] + lines[1..-1].
143
+ map {|l| "\n" + (" " * "Syntax error: ".size) + l}.join
144
+ "Syntax error: #{msg}" +
145
+ Sass::Util.enum_with_index(sass_backtrace).map do |entry, i|
146
+ "\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
147
+ " of #{entry[:filename] || default_filename}" +
148
+ (entry[:mixin] ? ", in `#{entry[:mixin]}'" : "")
149
+ end.join
150
+ end
151
+
152
+ class << self
153
+ # Returns an error report for an exception in CSS format.
154
+ #
155
+ # @param e [Exception]
156
+ # @param options [{Symbol => Object}] The options passed to {Sass::Engine#initialize}
157
+ # @return [String] The error report
158
+ # @raise [Exception] `e`, if the
159
+ # {file:SASS_REFERENCE.md#full_exception-option `:full_exception`} option
160
+ # is set to false.
161
+ def exception_to_css(e, options)
162
+ raise e unless options[:full_exception]
163
+
164
+ header = header_string(e, options)
165
+
166
+ <<END
167
+ /*
168
+ #{header}
169
+
170
+ Backtrace:\n#{e.backtrace.join("\n")}
171
+ */
172
+ body:before {
173
+ white-space: pre;
174
+ font-family: monospace;
175
+ content: "#{header.gsub('"', '\"').gsub("\n", '\\A ')}"; }
176
+ END
177
+ end
178
+
179
+ private
180
+
181
+ def header_string(e, options)
182
+ unless e.is_a?(Sass::SyntaxError) && e.sass_line && e.sass_template
183
+ return "#{e.class}: #{e.message}"
184
+ end
185
+
186
+ line_offset = options[:line] || 1
187
+ line_num = e.sass_line + 1 - line_offset
188
+ min = [line_num - 6, 0].max
189
+ section = e.sass_template.rstrip.split("\n")[min ... line_num + 5]
190
+ return e.sass_backtrace_str if section.nil? || section.empty?
191
+
192
+ e.sass_backtrace_str + "\n\n" + Sass::Util.enum_with_index(section).
193
+ map {|line, i| "#{line_offset + min + i}: #{line}"}.join("\n")
194
+ end
195
+ end
196
+ end
197
+
198
+ # The class for Sass errors that are raised due to invalid unit conversions
199
+ # in SassScript.
200
+ class UnitConversionError < SyntaxError; end
201
+ end
@@ -0,0 +1,659 @@
1
+ require 'optparse'
2
+ require 'fileutils'
3
+
4
+ module Sass
5
+ # This module handles the various Sass executables (`sass` and `sass-convert`).
6
+ module Exec
7
+ # An abstract class that encapsulates the executable code for all three executables.
8
+ class Generic
9
+ # @param args [Array<String>] The command-line arguments
10
+ def initialize(args)
11
+ @args = args
12
+ @options = {}
13
+ end
14
+
15
+ # Parses the command-line arguments and runs the executable.
16
+ # Calls `Kernel#exit` at the end, so it never returns.
17
+ #
18
+ # @see #parse
19
+ def parse!
20
+ begin
21
+ parse
22
+ rescue Exception => e
23
+ raise e if @options[:trace] || e.is_a?(SystemExit)
24
+
25
+ $stderr.print "#{e.class}: " unless e.class == RuntimeError
26
+ $stderr.puts "#{e.message}"
27
+ $stderr.puts " Use --trace for backtrace."
28
+ exit 1
29
+ end
30
+ exit 0
31
+ end
32
+
33
+ # Parses the command-line arguments and runs the executable.
34
+ # This does not handle exceptions or exit the program.
35
+ #
36
+ # @see #parse!
37
+ def parse
38
+ @opts = OptionParser.new(&method(:set_opts))
39
+ @opts.parse!(@args)
40
+
41
+ process_result
42
+
43
+ @options
44
+ end
45
+
46
+ # @return [String] A description of the executable
47
+ def to_s
48
+ @opts.to_s
49
+ end
50
+
51
+ protected
52
+
53
+ # Finds the line of the source template
54
+ # on which an exception was raised.
55
+ #
56
+ # @param exception [Exception] The exception
57
+ # @return [String] The line number
58
+ def get_line(exception)
59
+ # SyntaxErrors have weird line reporting
60
+ # when there's trailing whitespace
61
+ return (exception.message.scan(/:(\d+)/).first || ["??"]).first if exception.is_a?(::SyntaxError)
62
+ (exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first
63
+ end
64
+
65
+ # Tells optparse how to parse the arguments
66
+ # available for all executables.
67
+ #
68
+ # This is meant to be overridden by subclasses
69
+ # so they can add their own options.
70
+ #
71
+ # @param opts [OptionParser]
72
+ def set_opts(opts)
73
+ opts.on('-s', '--stdin', :NONE, 'Read input from standard input instead of an input file') do
74
+ @options[:input] = $stdin
75
+ end
76
+
77
+ opts.on('--trace', :NONE, 'Show a full traceback on error') do
78
+ @options[:trace] = true
79
+ end
80
+
81
+ opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do
82
+ @options[:unix_newlines] = true if ::Sass::Util.windows?
83
+ end
84
+
85
+ opts.on_tail("-?", "-h", "--help", "Show this message") do
86
+ puts opts
87
+ exit
88
+ end
89
+
90
+ opts.on_tail("-v", "--version", "Print version") do
91
+ puts("Sass #{::Sass.version[:string]}")
92
+ exit
93
+ end
94
+ end
95
+
96
+ # Processes the options set by the command-line arguments.
97
+ # In particular, sets `@options[:input]` and `@options[:output]`
98
+ # to appropriate IO streams.
99
+ #
100
+ # This is meant to be overridden by subclasses
101
+ # so they can run their respective programs.
102
+ def process_result
103
+ input, output = @options[:input], @options[:output]
104
+ args = @args.dup
105
+ input ||=
106
+ begin
107
+ filename = args.shift
108
+ @options[:filename] = filename
109
+ open_file(filename) || $stdin
110
+ end
111
+ output ||= open_file(args.shift, 'w') || $stdout
112
+
113
+ @options[:input], @options[:output] = input, output
114
+ end
115
+
116
+ COLORS = { :red => 31, :green => 32, :yellow => 33 }
117
+
118
+ # Prints a status message about performing the given action,
119
+ # colored using the given color (via terminal escapes) if possible.
120
+ #
121
+ # @param name [#to_s] A short name for the action being performed.
122
+ # Shouldn't be longer than 11 characters.
123
+ # @param color [Symbol] The name of the color to use for this action.
124
+ # Can be `:red`, `:green`, or `:yellow`.
125
+ def puts_action(name, color, arg)
126
+ return if @options[:for_engine][:quiet]
127
+ printf color(color, "%11s %s\n"), name, arg
128
+ end
129
+
130
+ # Same as \{Kernel.puts}, but doesn't print anything if the `--quiet` option is set.
131
+ #
132
+ # @param args [Array] Passed on to \{Kernel.puts}
133
+ def puts(*args)
134
+ return if @options[:for_engine][:quiet]
135
+ Kernel.puts(*args)
136
+ end
137
+
138
+ # Wraps the given string in terminal escapes
139
+ # causing it to have the given color.
140
+ # If terminal esapes aren't supported on this platform,
141
+ # just returns the string instead.
142
+ #
143
+ # @param color [Symbol] The name of the color to use.
144
+ # Can be `:red`, `:green`, or `:yellow`.
145
+ # @param str [String] The string to wrap in the given color.
146
+ # @return [String] The wrapped string.
147
+ def color(color, str)
148
+ raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
149
+
150
+ # Almost any real Unix terminal will support color,
151
+ # so we just filter for Windows terms (which don't set TERM)
152
+ # and not-real terminals, which aren't ttys.
153
+ return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
154
+ return "\e[#{COLORS[color]}m#{str}\e[0m"
155
+ end
156
+
157
+ private
158
+
159
+ def open_file(filename, flag = 'r')
160
+ return if filename.nil?
161
+ flag = 'wb' if @options[:unix_newlines] && flag == 'w'
162
+ File.open(filename, flag)
163
+ end
164
+
165
+ def handle_load_error(err)
166
+ dep = err.message[/^no such file to load -- (.*)/, 1]
167
+ raise err if @options[:trace] || dep.nil? || dep.empty?
168
+ $stderr.puts <<MESSAGE
169
+ Required dependency #{dep} not found!
170
+ Run "gem install #{dep}" to get it.
171
+ Use --trace for backtrace.
172
+ MESSAGE
173
+ exit 1
174
+ end
175
+ end
176
+
177
+ # The `sass` executable.
178
+ class Sass < Generic
179
+ attr_reader :default_syntax
180
+
181
+ # @param args [Array<String>] The command-line arguments
182
+ def initialize(args)
183
+ super
184
+ @options[:for_engine] = {
185
+ :load_paths => ['.'] + (ENV['SASSPATH'] || '').split(File::PATH_SEPARATOR)
186
+ }
187
+ @default_syntax = :sass
188
+ end
189
+
190
+ protected
191
+
192
+ # Tells optparse how to parse the arguments.
193
+ #
194
+ # @param opts [OptionParser]
195
+ def set_opts(opts)
196
+ super
197
+
198
+ opts.banner = <<END
199
+ Usage: #{default_syntax} [options] [INPUT] [OUTPUT]
200
+
201
+ Description:
202
+ Converts SCSS or Sass files to CSS.
203
+
204
+ Options:
205
+ END
206
+
207
+ if @default_syntax == :sass
208
+ opts.on('--scss',
209
+ 'Use the CSS-superset SCSS syntax.') do
210
+ @options[:for_engine][:syntax] = :scss
211
+ end
212
+ else
213
+ opts.on('--sass',
214
+ 'Use the Indented syntax.') do
215
+ @options[:for_engine][:syntax] = :sass
216
+ end
217
+ end
218
+ opts.on('--watch', 'Watch files or directories for changes.',
219
+ 'The location of the generated CSS can be set using a colon:',
220
+ " #{@default_syntax} --watch input.#{@default_syntax}:output.css",
221
+ " #{@default_syntax} --watch input-dir:output-dir") do
222
+ @options[:watch] = true
223
+ end
224
+ opts.on('--update', 'Compile files or directories to CSS.',
225
+ 'Locations are set like --watch.') do
226
+ @options[:update] = true
227
+ end
228
+ opts.on('--stop-on-error', 'If a file fails to compile, exit immediately.',
229
+ 'Only meaningful for --watch and --update.') do
230
+ @options[:stop_on_error] = true
231
+ end
232
+ opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
233
+ require 'stringio'
234
+ @options[:check_syntax] = true
235
+ @options[:output] = StringIO.new
236
+ end
237
+ opts.on('-t', '--style NAME',
238
+ 'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
239
+ @options[:for_engine][:style] = name.to_sym
240
+ end
241
+ opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
242
+ @options[:for_engine][:quiet] = true
243
+ end
244
+ opts.on('--compass', 'Make Compass imports available and load project configuration.') do
245
+ @options[:compass] = true
246
+ end
247
+ opts.on('-g', '--debug-info',
248
+ 'Emit extra information in the generated CSS that can be used by the FireSass Firebug plugin.') do
249
+ @options[:for_engine][:debug_info] = true
250
+ end
251
+ opts.on('-l', '--line-numbers', '--line-comments',
252
+ 'Emit comments in the generated CSS indicating the corresponding source line.') do
253
+ @options[:for_engine][:line_numbers] = true
254
+ end
255
+ opts.on('-i', '--interactive',
256
+ 'Run an interactive SassScript shell.') do
257
+ @options[:interactive] = true
258
+ end
259
+ opts.on('-I', '--load-path PATH', 'Add a sass import path.') do |path|
260
+ @options[:for_engine][:load_paths] << path
261
+ end
262
+ opts.on('-r', '--require LIB', 'Require a Ruby library before running Sass.') do |lib|
263
+ require lib
264
+ end
265
+ opts.on('--cache-location PATH', 'The path to put cached Sass files. Defaults to .sass-cache.') do |loc|
266
+ @options[:for_engine][:cache_location] = loc
267
+ end
268
+ opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
269
+ @options[:for_engine][:cache] = false
270
+ end
271
+
272
+ unless ::Sass::Util.ruby1_8?
273
+ opts.on('-E encoding', 'Specify the default encoding for Sass files.') do |encoding|
274
+ Encoding.default_external = encoding
275
+ end
276
+ end
277
+ end
278
+
279
+ # Processes the options set by the command-line arguments,
280
+ # and runs the Sass compiler appropriately.
281
+ def process_result
282
+ require 'sass'
283
+
284
+ if !@options[:update] && !@options[:watch] &&
285
+ @args.first && colon_path?(@args.first)
286
+ if @args.size == 1
287
+ @args = split_colon_path(@args.first)
288
+ else
289
+ @options[:update] = true
290
+ end
291
+ end
292
+ load_compass if @options[:compass]
293
+ return interactive if @options[:interactive]
294
+ return watch_or_update if @options[:watch] || @options[:update]
295
+ super
296
+ @options[:for_engine][:filename] = @options[:filename]
297
+
298
+ begin
299
+ input = @options[:input]
300
+ output = @options[:output]
301
+
302
+ @options[:for_engine][:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
303
+ @options[:for_engine][:syntax] ||= @default_syntax
304
+ engine =
305
+ if input.is_a?(File) && !@options[:check_syntax]
306
+ ::Sass::Engine.for_file(input.path, @options[:for_engine])
307
+ else
308
+ # We don't need to do any special handling of @options[:check_syntax] here,
309
+ # because the Sass syntax checking happens alongside evaluation
310
+ # and evaluation doesn't actually evaluate any code anyway.
311
+ ::Sass::Engine.new(input.read(), @options[:for_engine])
312
+ end
313
+
314
+ input.close() if input.is_a?(File)
315
+
316
+ output.write(engine.render)
317
+ output.close() if output.is_a? File
318
+ rescue ::Sass::SyntaxError => e
319
+ raise e if @options[:trace]
320
+ raise e.sass_backtrace_str("standard input")
321
+ end
322
+ end
323
+
324
+ private
325
+
326
+ def load_compass
327
+ begin
328
+ require 'compass'
329
+ rescue LoadError
330
+ require 'rubygems'
331
+ begin
332
+ require 'compass'
333
+ rescue LoadError
334
+ puts "ERROR: Cannot load compass."
335
+ exit 1
336
+ end
337
+ end
338
+ Compass.add_project_configuration
339
+ Compass.configuration.project_path ||= Dir.pwd
340
+ @options[:for_engine][:load_paths] += Compass.configuration.sass_load_paths
341
+ end
342
+
343
+ def interactive
344
+ require 'sass/repl'
345
+ ::Sass::Repl.new(@options).run
346
+ end
347
+
348
+ def watch_or_update
349
+ require 'sass/plugin'
350
+ ::Sass::Plugin.options.merge! @options[:for_engine]
351
+ ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
352
+
353
+ raise <<MSG if @args.empty?
354
+ What files should I watch? Did you mean something like:
355
+ #{@default_syntax} --watch input.#{@default_syntax}:output.css
356
+ #{@default_syntax} --watch input-dir:output-dir
357
+ MSG
358
+
359
+ if !colon_path?(@args[0]) && probably_dest_dir?(@args[1])
360
+ flag = @options[:update] ? "--update" : "--watch"
361
+ err =
362
+ if !File.exist?(@args[1])
363
+ "doesn't exist"
364
+ elsif @args[1] =~ /\.css$/
365
+ "is a CSS file"
366
+ end
367
+ raise <<MSG if err
368
+ File #{@args[1]} #{err}.
369
+ Did you mean: #{@default_syntax} #{flag} #{@args[0]}:#{@args[1]}
370
+ MSG
371
+ end
372
+
373
+ dirs, files = @args.map {|name| split_colon_path(name)}.
374
+ partition {|i, _| File.directory? i}
375
+ files.map! {|from, to| [from, to || from.gsub(/\..*?$/, '.css')]}
376
+ dirs.map! {|from, to| [from, to || from]}
377
+ ::Sass::Plugin.options[:template_location] = dirs
378
+
379
+ ::Sass::Plugin.on_updating_stylesheet do |_, css|
380
+ if File.exists? css
381
+ puts_action :overwrite, :yellow, css
382
+ else
383
+ puts_action :create, :green, css
384
+ end
385
+ end
386
+
387
+ had_error = false
388
+ ::Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
389
+ ::Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
390
+ ::Sass::Plugin.on_compilation_error do |error, _, _|
391
+ raise error unless error.is_a?(::Sass::SyntaxError) && !@options[:stop_on_error]
392
+ had_error = true
393
+ puts_action :error, :red, "#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
394
+ end
395
+
396
+ if @options[:update]
397
+ ::Sass::Plugin.update_stylesheets(files)
398
+ exit 1 if had_error
399
+ return
400
+ end
401
+
402
+ puts ">>> Sass is watching for changes. Press Ctrl-C to stop."
403
+
404
+ ::Sass::Plugin.on_template_modified {|template| puts ">>> Change detected to: #{template}"}
405
+ ::Sass::Plugin.on_template_created {|template| puts ">>> New template detected: #{template}"}
406
+ ::Sass::Plugin.on_template_deleted {|template| puts ">>> Deleted template detected: #{template}"}
407
+
408
+ ::Sass::Plugin.watch(files)
409
+ end
410
+
411
+ def colon_path?(path)
412
+ !split_colon_path(path)[1].nil?
413
+ end
414
+
415
+ def split_colon_path(path)
416
+ one, two = path.split(':', 2)
417
+ if one && two && ::Sass::Util.windows? &&
418
+ one =~ /\A[A-Za-z]\Z/ && two =~ /\A[\/\\]/
419
+ # If we're on Windows and we were passed a drive letter path,
420
+ # don't split on that colon.
421
+ one2, two = two.split(':', 2)
422
+ one = one + ':' + one2
423
+ end
424
+ return one, two
425
+ end
426
+
427
+ # Whether path is likely to be meant as the destination
428
+ # in a source:dest pair.
429
+ def probably_dest_dir?(path)
430
+ return false unless path
431
+ return false if colon_path?(path)
432
+ return Dir.glob(File.join(path, "*.s[ca]ss")).empty?
433
+ end
434
+ end
435
+
436
+ class Scss < Sass
437
+ # @param args [Array<String>] The command-line arguments
438
+ def initialize(args)
439
+ super
440
+ @default_syntax = :scss
441
+ end
442
+ end
443
+
444
+ # The `sass-convert` executable.
445
+ class SassConvert < Generic
446
+ # @param args [Array<String>] The command-line arguments
447
+ def initialize(args)
448
+ super
449
+ require 'sass'
450
+ @options[:for_tree] = {}
451
+ @options[:for_engine] = {:cache => false, :read_cache => true}
452
+ end
453
+
454
+ # Tells optparse how to parse the arguments.
455
+ #
456
+ # @param opts [OptionParser]
457
+ def set_opts(opts)
458
+ opts.banner = <<END
459
+ Usage: sass-convert [options] [INPUT] [OUTPUT]
460
+
461
+ Description:
462
+ Converts between CSS, Sass, and SCSS files.
463
+ E.g. converts from SCSS to Sass,
464
+ or converts from CSS to SCSS (adding appropriate nesting).
465
+
466
+ Options:
467
+ END
468
+
469
+ opts.on('-F', '--from FORMAT',
470
+ 'The format to convert from. Can be css, scss, sass, less.',
471
+ 'By default, this is inferred from the input filename.',
472
+ 'If there is none, defaults to css.') do |name|
473
+ @options[:from] = name.downcase.to_sym
474
+ unless [:css, :scss, :sass, :less].include?(@options[:from])
475
+ raise "Unknown format for sass-convert --from: #{name}"
476
+ end
477
+ try_less_note if @options[:from] == :less
478
+ end
479
+
480
+ opts.on('-T', '--to FORMAT',
481
+ 'The format to convert to. Can be scss or sass.',
482
+ 'By default, this is inferred from the output filename.',
483
+ 'If there is none, defaults to sass.') do |name|
484
+ @options[:to] = name.downcase.to_sym
485
+ unless [:scss, :sass].include?(@options[:to])
486
+ raise "Unknown format for sass-convert --to: #{name}"
487
+ end
488
+ end
489
+
490
+ opts.on('-R', '--recursive',
491
+ 'Convert all the files in a directory. Requires --from and --to.') do
492
+ @options[:recursive] = true
493
+ end
494
+
495
+ opts.on('-i', '--in-place',
496
+ 'Convert a file to its own syntax.',
497
+ 'This can be used to update some deprecated syntax.') do
498
+ @options[:in_place] = true
499
+ end
500
+
501
+ opts.on('--dasherize', 'Convert underscores to dashes') do
502
+ @options[:for_tree][:dasherize] = true
503
+ end
504
+
505
+ opts.on('--old', 'Output the old-style ":prop val" property syntax.',
506
+ 'Only meaningful when generating Sass.') do
507
+ @options[:for_tree][:old] = true
508
+ end
509
+
510
+ opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
511
+ @options[:for_engine][:read_cache] = false
512
+ end
513
+
514
+ unless ::Sass::Util.ruby1_8?
515
+ opts.on('-E encoding', 'Specify the default encoding for Sass and CSS files.') do |encoding|
516
+ Encoding.default_external = encoding
517
+ end
518
+ end
519
+
520
+ super
521
+ end
522
+
523
+ # Processes the options set by the command-line arguments,
524
+ # and runs the CSS compiler appropriately.
525
+ def process_result
526
+ require 'sass'
527
+
528
+ if @options[:recursive]
529
+ process_directory
530
+ return
531
+ end
532
+
533
+ super
534
+ input = @options[:input]
535
+ raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)" if File.directory?(input)
536
+ output = @options[:output]
537
+ output = input if @options[:in_place]
538
+ process_file(input, output)
539
+ end
540
+
541
+ private
542
+
543
+ def process_directory
544
+ unless input = @options[:input] = @args.shift
545
+ raise "Error: directory required when using --recursive."
546
+ end
547
+
548
+ output = @options[:output] = @args.shift
549
+ raise "Error: --from required when using --recursive." unless @options[:from]
550
+ raise "Error: --to required when using --recursive." unless @options[:to]
551
+ raise "Error: '#{@options[:input]}' is not a directory" unless File.directory?(@options[:input])
552
+ if @options[:output] && File.exists?(@options[:output]) && !File.directory?(@options[:output])
553
+ raise "Error: '#{@options[:output]}' is not a directory"
554
+ end
555
+ @options[:output] ||= @options[:input]
556
+
557
+ from = @options[:from]
558
+ if @options[:to] == @options[:from] && !@options[:in_place]
559
+ fmt = @options[:from]
560
+ raise "Error: converting from #{fmt} to #{fmt} without --in-place"
561
+ end
562
+
563
+ ext = @options[:from]
564
+ Dir.glob("#{@options[:input]}/**/*.#{ext}") do |f|
565
+ output =
566
+ if @options[:in_place]
567
+ f
568
+ elsif @options[:output]
569
+ output_name = f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
570
+ output_name[0...@options[:input].size] = @options[:output]
571
+ output_name
572
+ else
573
+ f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
574
+ end
575
+
576
+ unless File.directory?(File.dirname(output))
577
+ puts_action :directory, :green, File.dirname(output)
578
+ FileUtils.mkdir_p(File.dirname(output))
579
+ end
580
+ puts_action :convert, :green, f
581
+ if File.exists?(output)
582
+ puts_action :overwrite, :yellow, output
583
+ else
584
+ puts_action :create, :green, output
585
+ end
586
+
587
+ input = open_file(f)
588
+ output = @options[:in_place] ? input : open_file(output, "w")
589
+ process_file(input, output)
590
+ end
591
+ end
592
+
593
+ def process_file(input, output)
594
+ if input.is_a?(File)
595
+ @options[:from] ||=
596
+ case input.path
597
+ when /\.scss$/; :scss
598
+ when /\.sass$/; :sass
599
+ when /\.less$/; :less
600
+ when /\.css$/; :css
601
+ end
602
+ elsif @options[:in_place]
603
+ raise "Error: the --in-place option requires a filename."
604
+ end
605
+
606
+ if output.is_a?(File)
607
+ @options[:to] ||=
608
+ case output.path
609
+ when /\.scss$/; :scss
610
+ when /\.sass$/; :sass
611
+ end
612
+ end
613
+
614
+ @options[:from] ||= :css
615
+ @options[:to] ||= :sass
616
+ @options[:for_engine][:syntax] = @options[:from]
617
+
618
+ out =
619
+ ::Sass::Util.silence_sass_warnings do
620
+ if @options[:from] == :css
621
+ require 'sass/css'
622
+ ::Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
623
+ elsif @options[:from] == :less
624
+ require 'sass/less'
625
+ try_less_note
626
+ input = input.read if input.is_a?(IO) && !input.is_a?(File) # Less is dumb
627
+ Less::Engine.new(input).to_tree.to_sass_tree.send("to_#{@options[:to]}", @options[:for_tree])
628
+ else
629
+ if input.is_a?(File)
630
+ ::Sass::Engine.for_file(input.path, @options[:for_engine])
631
+ else
632
+ ::Sass::Engine.new(input.read, @options[:for_engine])
633
+ end.to_tree.send("to_#{@options[:to]}", @options[:for_tree])
634
+ end
635
+ end
636
+
637
+ output = File.open(input.path, 'w') if @options[:in_place]
638
+ output.write(out)
639
+ rescue ::Sass::SyntaxError => e
640
+ raise e if @options[:trace]
641
+ file = " of #{e.sass_filename}" if e.sass_filename
642
+ raise "Error on line #{e.sass_line}#{file}: #{e.message}\n Use --trace for backtrace"
643
+ rescue LoadError => err
644
+ handle_load_error(err)
645
+ end
646
+
647
+ @@less_note_printed = false
648
+ def try_less_note
649
+ return if @@less_note_printed
650
+ @@less_note_printed = true
651
+ warn <<NOTE
652
+ * NOTE: Sass and Less are different languages, and they work differently.
653
+ * I'll do my best to translate, but some features -- especially mixins --
654
+ * should be checked by hand.
655
+ NOTE
656
+ end
657
+ end
658
+ end
659
+ end