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,216 @@
1
+ # A visitor for converting a Sass tree into CSS.
2
+ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
3
+ protected
4
+
5
+ def initialize
6
+ @tabs = 0
7
+ end
8
+
9
+ def visit(node)
10
+ super
11
+ rescue Sass::SyntaxError => e
12
+ e.modify_backtrace(:filename => node.filename, :line => node.line)
13
+ raise e
14
+ end
15
+
16
+ def with_tabs(tabs)
17
+ old_tabs, @tabs = @tabs, tabs
18
+ yield
19
+ ensure
20
+ @tabs = old_tabs
21
+ end
22
+
23
+ def visit_root(node)
24
+ result = String.new
25
+ node.children.each do |child|
26
+ next if child.invisible?
27
+ child_str = visit(child)
28
+ result << child_str + (node.style == :compressed ? '' : "\n")
29
+ end
30
+ result.rstrip!
31
+ return "" if result.empty?
32
+ result << "\n"
33
+ unless Sass::Util.ruby1_8? || result.ascii_only?
34
+ if node.children.first.is_a?(Sass::Tree::CharsetNode)
35
+ begin
36
+ encoding = node.children.first.name
37
+ # Default to big-endian encoding, because we have to decide somehow
38
+ encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i
39
+ result = result.encode(Encoding.find(encoding))
40
+ rescue EncodingError
41
+ end
42
+ end
43
+
44
+ result = "@charset \"#{result.encoding.name}\";#{
45
+ node.style == :compressed ? '' : "\n"
46
+ }".encode(result.encoding) + result
47
+ end
48
+ result
49
+ rescue Sass::SyntaxError => e
50
+ e.sass_template ||= node.template
51
+ raise e
52
+ end
53
+
54
+ def visit_charset(node)
55
+ "@charset \"#{node.name}\";"
56
+ end
57
+
58
+ def visit_comment(node)
59
+ return if node.invisible?
60
+ spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max)
61
+
62
+ content = node.value.gsub(/^/, spaces).gsub(%r{^(\s*)//(.*)$}) do |md|
63
+ "#{$1}/*#{$2} */"
64
+ end
65
+ if content =~ /[^\\]\#\{.*\}/
66
+ Sass::Util.sass_warn <<MESSAGE
67
+ WARNING:
68
+ On line #{node.line}#{" of '#{node.filename}'" if node.filename}
69
+ Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
70
+ Please escape the interpolation by adding a backslash before the hash sign.
71
+ MESSAGE
72
+ elsif content =~ /\\\#\{.*\}/
73
+ content.gsub!(/\\(\#\{.*\})/, '\1')
74
+ end
75
+ content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && !node.loud
76
+ content
77
+ end
78
+
79
+ def visit_directive(node)
80
+ return node.value + ";" unless node.has_children
81
+ return node.value + " {}" if node.children.empty?
82
+ result = if node.style == :compressed
83
+ "#{node.value}{"
84
+ else
85
+ "#{' ' * @tabs}#{node.value} {" + (node.style == :compact ? ' ' : "\n")
86
+ end
87
+ was_prop = false
88
+ first = true
89
+ node.children.each do |child|
90
+ next if child.invisible?
91
+ if node.style == :compact
92
+ if child.is_a?(Sass::Tree::PropNode)
93
+ with_tabs(first || was_prop ? 0 : @tabs + 1) {result << visit(child) << ' '}
94
+ else
95
+ result[-1] = "\n" if was_prop
96
+ rendered = with_tabs(@tabs + 1) {visit(child).dup}
97
+ rendered = rendered.lstrip if first
98
+ result << rendered.rstrip + "\n"
99
+ end
100
+ was_prop = child.is_a?(Sass::Tree::PropNode)
101
+ first = false
102
+ elsif node.style == :compressed
103
+ result << (was_prop ? ";" : "") << with_tabs(0) {visit(child)}
104
+ was_prop = child.is_a?(Sass::Tree::PropNode)
105
+ else
106
+ result << with_tabs(@tabs + 1) {visit(child)} + "\n"
107
+ end
108
+ end
109
+ result.rstrip + if node.style == :compressed
110
+ "}"
111
+ else
112
+ (node.style == :expanded ? "\n" : " ") + "}\n"
113
+ end
114
+ end
115
+
116
+ def visit_media(node)
117
+ str = with_tabs(@tabs + node.tabs) {visit_directive(node)}
118
+ str.gsub!(/\n\Z/, '') unless node.style == :compressed || node.group_end
119
+ str
120
+ end
121
+
122
+ def visit_prop(node)
123
+ tab_str = ' ' * (@tabs + node.tabs)
124
+ if node.style == :compressed
125
+ "#{tab_str}#{node.resolved_name}:#{node.resolved_value}#{'!important' if node.important}"
126
+ else
127
+ "#{tab_str}#{node.resolved_name}: #{node.resolved_value}#{' !important' if node.important};"
128
+ end
129
+ end
130
+
131
+ def visit_rule(node)
132
+ with_tabs(@tabs + node.tabs) do
133
+ rule_separator = node.style == :compressed ? ',' : ', '
134
+ line_separator =
135
+ case node.style
136
+ when :nested, :expanded; "\n"
137
+ when :compressed; ""
138
+ else; " "
139
+ end
140
+ rule_indent = ' ' * @tabs
141
+ per_rule_indent, total_indent = [:nested, :expanded].include?(node.style) ? [rule_indent, ''] : ['', rule_indent]
142
+
143
+ joined_rules = node.resolved_rules.members.map do |seq|
144
+ rule_part = seq.to_a.join
145
+ rule_part.gsub!(/\s*([^,])\s*\n\s*/m, '\1 ') if node.style == :compressed
146
+ rule_part
147
+ end.join(rule_separator)
148
+
149
+ joined_rules.sub!(/\A\s*/, per_rule_indent)
150
+ joined_rules.gsub!(/\s*\n\s*/, "#{line_separator}#{per_rule_indent}")
151
+ total_rule = total_indent << joined_rules
152
+
153
+ to_return = ''
154
+ old_spaces = ' ' * @tabs
155
+ spaces = ' ' * (@tabs + 1)
156
+ if node.style != :compressed
157
+ if node.options[:debug_info]
158
+ to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
159
+ elsif node.options[:line_comments]
160
+ to_return << "#{old_spaces}/* line #{node.line}"
161
+
162
+ if node.filename
163
+ relative_filename = if node.options[:css_filename]
164
+ begin
165
+ Pathname.new(node.filename).relative_path_from(
166
+ Pathname.new(File.dirname(node.options[:css_filename]))).to_s
167
+ rescue ArgumentError
168
+ nil
169
+ end
170
+ end
171
+ relative_filename ||= node.filename
172
+ to_return << ", #{relative_filename}"
173
+ end
174
+
175
+ to_return << " */\n"
176
+ end
177
+ end
178
+
179
+ if node.style == :compact
180
+ properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(' ')}
181
+ to_return << "#{total_rule} { #{properties} }#{"\n" if node.group_end}"
182
+ elsif node.style == :compressed
183
+ properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(';')}
184
+ to_return << "#{total_rule}{#{properties}}"
185
+ else
186
+ properties = with_tabs(@tabs + 1) {node.children.map {|a| visit(a)}.join("\n")}
187
+ end_props = (node.style == :expanded ? "\n" + old_spaces : ' ')
188
+ to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n" if node.group_end}"
189
+ end
190
+
191
+ to_return
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ def debug_info_rule(debug_info, options)
198
+ node = Sass::Tree::DirectiveNode.new("@media -sass-debug-info")
199
+ debug_info.map {|k, v| [k.to_s, v.to_s]}.sort.each do |k, v|
200
+ rule = Sass::Tree::RuleNode.new([""])
201
+ rule.resolved_rules = Sass::Selector::CommaSequence.new(
202
+ [Sass::Selector::Sequence.new(
203
+ [Sass::Selector::SimpleSequence.new(
204
+ [Sass::Selector::Element.new(k.to_s.gsub(/[^\w-]/, "\\\\\\0"), nil)])
205
+ ])
206
+ ])
207
+ prop = Sass::Tree::PropNode.new([""], "", false, :new)
208
+ prop.resolved_name = "font-family"
209
+ prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
210
+ rule << prop
211
+ node << rule
212
+ end
213
+ node.options = options.merge(:debug_info => false, :line_comments => false, :style => :compressed)
214
+ node
215
+ end
216
+ end
@@ -0,0 +1,18 @@
1
+ module Sass
2
+ module Tree
3
+ # A dynamic node representing a Sass `@warn` statement.
4
+ #
5
+ # @see Sass::Tree
6
+ class WarnNode < Node
7
+ # The expression to print.
8
+ # @return [Script::Node]
9
+ attr_reader :expr
10
+
11
+ # @param expr [Script::Node] The expression to print
12
+ def initialize(expr)
13
+ @expr = expr
14
+ super()
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A dynamic node representing a Sass `@while` loop.
5
+ #
6
+ # @see Sass::Tree
7
+ class WhileNode < Node
8
+ # The parse tree for the continuation expression.
9
+ # @return [Script::Node]
10
+ attr_reader :expr
11
+
12
+ # @param expr [Script::Node] See \{#expr}
13
+ def initialize(expr)
14
+ @expr = expr
15
+ super()
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,669 @@
1
+ require 'erb'
2
+ require 'set'
3
+ require 'enumerator'
4
+ require 'stringio'
5
+ require 'strscan'
6
+ require 'rbconfig'
7
+
8
+ require 'sass/root'
9
+ require 'sass/util/subset_map'
10
+
11
+ module Sass
12
+ # A module containing various useful functions.
13
+ module Util
14
+ extend self
15
+
16
+ # An array of ints representing the Ruby version number.
17
+ # @api public
18
+ RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
19
+
20
+ # The Ruby engine we're running under. Defaults to `"ruby"`
21
+ # if the top-level constant is undefined.
22
+ # @api public
23
+ RUBY_ENGINE = defined?(::RUBY_ENGINE) ? ::RUBY_ENGINE : "ruby"
24
+
25
+ # Returns the path of a file relative to the Sass root directory.
26
+ #
27
+ # @param file [String] The filename relative to the Sass root
28
+ # @return [String] The filename relative to the the working directory
29
+ def scope(file)
30
+ File.join(Sass::ROOT_DIR, file)
31
+ end
32
+
33
+ # Converts an array of `[key, value]` pairs to a hash.
34
+ #
35
+ # @example
36
+ # to_hash([[:foo, "bar"], [:baz, "bang"]])
37
+ # #=> {:foo => "bar", :baz => "bang"}
38
+ # @param arr [Array<(Object, Object)>] An array of pairs
39
+ # @return [Hash] A hash
40
+ def to_hash(arr)
41
+ Hash[arr.compact]
42
+ end
43
+
44
+ # Maps the keys in a hash according to a block.
45
+ #
46
+ # @example
47
+ # map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
48
+ # #=> {"foo" => "bar", "baz" => "bang"}
49
+ # @param hash [Hash] The hash to map
50
+ # @yield [key] A block in which the keys are transformed
51
+ # @yieldparam key [Object] The key that should be mapped
52
+ # @yieldreturn [Object] The new value for the key
53
+ # @return [Hash] The mapped hash
54
+ # @see #map_vals
55
+ # @see #map_hash
56
+ def map_keys(hash)
57
+ to_hash(hash.map {|k, v| [yield(k), v]})
58
+ end
59
+
60
+ # Maps the values in a hash according to a block.
61
+ #
62
+ # @example
63
+ # map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
64
+ # #=> {:foo => :bar, :baz => :bang}
65
+ # @param hash [Hash] The hash to map
66
+ # @yield [value] A block in which the values are transformed
67
+ # @yieldparam value [Object] The value that should be mapped
68
+ # @yieldreturn [Object] The new value for the value
69
+ # @return [Hash] The mapped hash
70
+ # @see #map_keys
71
+ # @see #map_hash
72
+ def map_vals(hash)
73
+ to_hash(hash.map {|k, v| [k, yield(v)]})
74
+ end
75
+
76
+ # Maps the key-value pairs of a hash according to a block.
77
+ #
78
+ # @example
79
+ # map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
80
+ # #=> {"foo" => :bar, "baz" => :bang}
81
+ # @param hash [Hash] The hash to map
82
+ # @yield [key, value] A block in which the key-value pairs are transformed
83
+ # @yieldparam [key] The hash key
84
+ # @yieldparam [value] The hash value
85
+ # @yieldreturn [(Object, Object)] The new value for the `[key, value]` pair
86
+ # @return [Hash] The mapped hash
87
+ # @see #map_keys
88
+ # @see #map_vals
89
+ def map_hash(hash, &block)
90
+ to_hash(hash.map(&block))
91
+ end
92
+
93
+ # Computes the powerset of the given array.
94
+ # This is the set of all subsets of the array.
95
+ #
96
+ # @example
97
+ # powerset([1, 2, 3]) #=>
98
+ # Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
99
+ # @param arr [Enumerable]
100
+ # @return [Set<Set>] The subsets of `arr`
101
+ def powerset(arr)
102
+ arr.inject([Set.new].to_set) do |powerset, el|
103
+ new_powerset = Set.new
104
+ powerset.each do |subset|
105
+ new_powerset << subset
106
+ new_powerset << subset + [el]
107
+ end
108
+ new_powerset
109
+ end
110
+ end
111
+
112
+ # Restricts a number to falling within a given range.
113
+ # Returns the number if it falls within the range,
114
+ # or the closest value in the range if it doesn't.
115
+ #
116
+ # @param value [Numeric]
117
+ # @param range [Range<Numeric>]
118
+ # @return [Numeric]
119
+ def restrict(value, range)
120
+ [[value, range.first].max, range.last].min
121
+ end
122
+
123
+ # Concatenates all strings that are adjacent in an array,
124
+ # while leaving other elements as they are.
125
+ #
126
+ # @example
127
+ # merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
128
+ # #=> [1, "foobar", 2, "baz"]
129
+ # @param arr [Array]
130
+ # @return [Array] The enumerable with strings merged
131
+ def merge_adjacent_strings(arr)
132
+ # Optimize for the common case of one element
133
+ return arr if arr.size < 2
134
+ arr.inject([]) do |a, e|
135
+ if e.is_a?(String)
136
+ if a.last.is_a?(String)
137
+ a.last << e
138
+ else
139
+ a << e.dup
140
+ end
141
+ else
142
+ a << e
143
+ end
144
+ a
145
+ end
146
+ end
147
+
148
+ # Intersperses a value in an enumerable, as would be done with `Array#join`
149
+ # but without concatenating the array together afterwards.
150
+ #
151
+ # @param enum [Enumerable]
152
+ # @param val
153
+ # @return [Array]
154
+ def intersperse(enum, val)
155
+ enum.inject([]) {|a, e| a << e << val}[0...-1]
156
+ end
157
+
158
+ # Substitutes a sub-array of one array with another sub-array.
159
+ #
160
+ # @param ary [Array] The array in which to make the substitution
161
+ # @param from [Array] The sequence of elements to replace with `to`
162
+ # @param to [Array] The sequence of elements to replace `from` with
163
+ def substitute(ary, from, to)
164
+ res = ary.dup
165
+ i = 0
166
+ while i < res.size
167
+ if res[i...i+from.size] == from
168
+ res[i...i+from.size] = to
169
+ end
170
+ i += 1
171
+ end
172
+ res
173
+ end
174
+
175
+ # Destructively strips whitespace from the beginning and end
176
+ # of the first and last elements, respectively,
177
+ # in the array (if those elements are strings).
178
+ #
179
+ # @param arr [Array]
180
+ # @return [Array] `arr`
181
+ def strip_string_array(arr)
182
+ arr.first.lstrip! if arr.first.is_a?(String)
183
+ arr.last.rstrip! if arr.last.is_a?(String)
184
+ arr
185
+ end
186
+
187
+ # Return an array of all possible paths through the given arrays.
188
+ #
189
+ # @param arrs [Array<Array>]
190
+ # @return [Array<Arrays>]
191
+ #
192
+ # @example
193
+ # paths([[1, 2], [3, 4], [5]]) #=>
194
+ # # [[1, 3, 5],
195
+ # # [2, 3, 5],
196
+ # # [1, 4, 5],
197
+ # # [2, 4, 5]]
198
+ def paths(arrs)
199
+ arrs.inject([[]]) do |paths, arr|
200
+ flatten(arr.map {|e| paths.map {|path| path + [e]}}, 1)
201
+ end
202
+ end
203
+
204
+ # Computes a single longest common subsequence for `x` and `y`.
205
+ # If there are more than one longest common subsequences,
206
+ # the one returned is that which starts first in `x`.
207
+ #
208
+ # @param x [Array]
209
+ # @param y [Array]
210
+ # @yield [a, b] An optional block to use in place of a check for equality
211
+ # between elements of `x` and `y`.
212
+ # @yieldreturn [Object, nil] If the two values register as equal,
213
+ # this will return the value to use in the LCS array.
214
+ # @return [Array] The LCS
215
+ def lcs(x, y, &block)
216
+ x = [nil, *x]
217
+ y = [nil, *y]
218
+ block ||= proc {|a, b| a == b && a}
219
+ lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
220
+ end
221
+
222
+ # Returns information about the caller of the previous method.
223
+ #
224
+ # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
225
+ # @return [[String, Fixnum, (String, nil)]] An array containing the filename, line, and method name of the caller.
226
+ # The method name may be nil
227
+ def caller_info(entry = caller[1])
228
+ info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
229
+ info[1] = info[1].to_i
230
+ # This is added by Rubinius to designate a block, but we don't care about it.
231
+ info[2].sub!(/ \{\}\Z/, '') if info[2]
232
+ info
233
+ end
234
+
235
+ # Returns whether one version string represents a more recent version than another.
236
+ #
237
+ # @param v1 [String] A version string.
238
+ # @param v2 [String] Another version string.
239
+ # @return [Boolean]
240
+ def version_gt(v1, v2)
241
+ # Construct an array to make sure the shorter version is padded with nil
242
+ Array.new([v1.length, v2.length].max).zip(v1.split("."), v2.split(".")) do |_, p1, p2|
243
+ p1 ||= "0"
244
+ p2 ||= "0"
245
+ release1 = p1 =~ /^[0-9]+$/
246
+ release2 = p2 =~ /^[0-9]+$/
247
+ if release1 && release2
248
+ # Integer comparison if both are full releases
249
+ p1, p2 = p1.to_i, p2.to_i
250
+ next if p1 == p2
251
+ return p1 > p2
252
+ elsif !release1 && !release2
253
+ # String comparison if both are prereleases
254
+ next if p1 == p2
255
+ return p1 > p2
256
+ else
257
+ # If only one is a release, that one is newer
258
+ return release1
259
+ end
260
+ end
261
+ end
262
+
263
+ # Returns whether one version string represents the same or a more
264
+ # recent version than another.
265
+ #
266
+ # @param v1 [String] A version string.
267
+ # @param v2 [String] Another version string.
268
+ # @return [Boolean]
269
+ def version_geq(v1, v2)
270
+ version_gt(v1, v2) || !version_gt(v2, v1)
271
+ end
272
+
273
+ # Throws a NotImplementedError for an abstract method.
274
+ #
275
+ # @param obj [Object] `self`
276
+ # @raise [NotImplementedError]
277
+ def abstract(obj)
278
+ raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
279
+ end
280
+
281
+ # Silence all output to STDERR within a block.
282
+ #
283
+ # @yield A block in which no output will be printed to STDERR
284
+ def silence_warnings
285
+ the_real_stderr, $stderr = $stderr, StringIO.new
286
+ yield
287
+ ensure
288
+ $stderr = the_real_stderr
289
+ end
290
+
291
+ @@silence_warnings = false
292
+ # Silences all Sass warnings within a block.
293
+ #
294
+ # @yield A block in which no Sass warnings will be printed
295
+ def silence_sass_warnings
296
+ old_silence_warnings = @@silence_warnings
297
+ @@silence_warnings = true
298
+ yield
299
+ ensure
300
+ @@silence_warnings = old_silence_warnings
301
+ end
302
+
303
+ # The same as `Kernel#warn`, but is silenced by \{#silence\_sass\_warnings}.
304
+ #
305
+ # @param msg [String]
306
+ def sass_warn(msg)
307
+ return if @@silence_warnings
308
+ warn(msg)
309
+ end
310
+
311
+ ## Cross Rails Version Compatibility
312
+
313
+ # Returns the root of the Rails application,
314
+ # if this is running in a Rails context.
315
+ # Returns `nil` if no such root is defined.
316
+ #
317
+ # @return [String, nil]
318
+ def rails_root
319
+ if defined?(::Rails.root)
320
+ return ::Rails.root.to_s if ::Rails.root
321
+ raise "ERROR: Rails.root is nil!"
322
+ end
323
+ return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
324
+ return nil
325
+ end
326
+
327
+ # Returns the environment of the Rails application,
328
+ # if this is running in a Rails context.
329
+ # Returns `nil` if no such environment is defined.
330
+ #
331
+ # @return [String, nil]
332
+ def rails_env
333
+ return ::Rails.env.to_s if defined?(::Rails.env)
334
+ return RAILS_ENV.to_s if defined?(RAILS_ENV)
335
+ return nil
336
+ end
337
+
338
+ # Returns whether this environment is using ActionPack
339
+ # version 3.0.0 or greater.
340
+ #
341
+ # @return [Boolean]
342
+ def ap_geq_3?
343
+ ap_geq?("3.0.0.beta1")
344
+ end
345
+
346
+ # Returns whether this environment is using ActionPack
347
+ # of a version greater than or equal to that specified.
348
+ #
349
+ # @param version [String] The string version number to check against.
350
+ # Should be greater than or equal to Rails 3,
351
+ # because otherwise ActionPack::VERSION isn't autoloaded
352
+ # @return [Boolean]
353
+ def ap_geq?(version)
354
+ # The ActionPack module is always loaded automatically in Rails >= 3
355
+ return false unless defined?(ActionPack) && defined?(ActionPack::VERSION) &&
356
+ defined?(ActionPack::VERSION::STRING)
357
+
358
+ version_geq(ActionPack::VERSION::STRING, version)
359
+ end
360
+
361
+ # Returns an ActionView::Template* class.
362
+ # In pre-3.0 versions of Rails, most of these classes
363
+ # were of the form `ActionView::TemplateFoo`,
364
+ # while afterwards they were of the form `ActionView;:Template::Foo`.
365
+ #
366
+ # @param name [#to_s] The name of the class to get.
367
+ # For example, `:Error` will return `ActionView::TemplateError`
368
+ # or `ActionView::Template::Error`.
369
+ def av_template_class(name)
370
+ return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
371
+ return ActionView::Template.const_get(name.to_s)
372
+ end
373
+
374
+ ## Cross-OS Compatibility
375
+
376
+ # Whether or not this is running on Windows.
377
+ #
378
+ # @return [Boolean]
379
+ def windows?
380
+ RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
381
+ end
382
+
383
+ # Whether or not this is running on IronRuby.
384
+ #
385
+ # @return [Boolean]
386
+ def ironruby?
387
+ RUBY_ENGINE == "ironruby"
388
+ end
389
+
390
+ ## Cross-Ruby-Version Compatibility
391
+
392
+ # Whether or not this is running under Ruby 1.8 or lower.
393
+ #
394
+ # Note that IronRuby counts as Ruby 1.8,
395
+ # because it doesn't support the Ruby 1.9 encoding API.
396
+ #
397
+ # @return [Boolean]
398
+ def ruby1_8?
399
+ # IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
400
+ # We have to fall back to 1.8 behavior.
401
+ ironruby? || (Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
402
+ end
403
+
404
+ # Whether or not this is running under Ruby 1.8.6 or lower.
405
+ # Note that lower versions are not officially supported.
406
+ #
407
+ # @return [Boolean]
408
+ def ruby1_8_6?
409
+ ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
410
+ end
411
+
412
+ # Checks that the encoding of a string is valid in Ruby 1.9
413
+ # and cleans up potential encoding gotchas like the UTF-8 BOM.
414
+ # If it's not, yields an error string describing the invalid character
415
+ # and the line on which it occurrs.
416
+ #
417
+ # @param str [String] The string of which to check the encoding
418
+ # @yield [msg] A block in which an encoding error can be raised.
419
+ # Only yields if there is an encoding error
420
+ # @yieldparam msg [String] The error message to be raised
421
+ # @return [String] `str`, potentially with encoding gotchas like BOMs removed
422
+ def check_encoding(str)
423
+ if ruby1_8?
424
+ return str.gsub(/\A\xEF\xBB\xBF/, '') # Get rid of the UTF-8 BOM
425
+ elsif str.valid_encoding?
426
+ # Get rid of the Unicode BOM if possible
427
+ if str.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?$/
428
+ return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding.name)), '')
429
+ else
430
+ return str
431
+ end
432
+ end
433
+
434
+ encoding = str.encoding
435
+ newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
436
+ str.force_encoding("binary").split(newlines).each_with_index do |line, i|
437
+ begin
438
+ line.encode(encoding)
439
+ rescue Encoding::UndefinedConversionError => e
440
+ yield <<MSG.rstrip, i + 1
441
+ Invalid #{encoding.name} character #{e.error_char.dump}
442
+ MSG
443
+ end
444
+ end
445
+ return str
446
+ end
447
+
448
+ # Like {\#check\_encoding}, but also checks for a `@charset` declaration
449
+ # at the beginning of the file and uses that encoding if it exists.
450
+ #
451
+ # The Sass encoding rules are simple.
452
+ # If a `@charset` declaration exists,
453
+ # we assume that that's the original encoding of the document.
454
+ # Otherwise, we use whatever encoding Ruby has.
455
+ # Then we convert that to UTF-8 to process internally.
456
+ # The UTF-8 end result is what's returned by this method.
457
+ #
458
+ # @param str [String] The string of which to check the encoding
459
+ # @yield [msg] A block in which an encoding error can be raised.
460
+ # Only yields if there is an encoding error
461
+ # @yieldparam msg [String] The error message to be raised
462
+ # @return [(String, Encoding)] The original string encoded as UTF-8,
463
+ # and the source encoding of the string (or `nil` under Ruby 1.8)
464
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
465
+ # cannot be converted to UTF-8
466
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
467
+ def check_sass_encoding(str, &block)
468
+ return check_encoding(str, &block), nil if ruby1_8?
469
+ # We allow any printable ASCII characters but double quotes in the charset decl
470
+ bin = str.dup.force_encoding("BINARY")
471
+ encoding = Sass::Util::ENCODINGS_TO_CHECK.find do |enc|
472
+ bin =~ Sass::Util::CHARSET_REGEXPS[enc]
473
+ end
474
+ charset, bom = $1, $2
475
+ if charset
476
+ charset = charset.force_encoding(encoding).encode("UTF-8")
477
+ if endianness = encoding[/[BL]E$/]
478
+ begin
479
+ Encoding.find(charset + endianness)
480
+ charset << endianness
481
+ rescue ArgumentError # Encoding charset + endianness doesn't exist
482
+ end
483
+ end
484
+ str.force_encoding(charset)
485
+ elsif bom
486
+ str.force_encoding(encoding)
487
+ end
488
+
489
+ str = check_encoding(str, &block)
490
+ return str.encode("UTF-8"), str.encoding
491
+ end
492
+
493
+ unless ruby1_8?
494
+ # @private
495
+ def _enc(string, encoding)
496
+ string.encode(encoding).force_encoding("BINARY")
497
+ end
498
+
499
+ # We could automatically add in any non-ASCII-compatible encodings here,
500
+ # but there's not really a good way to do that
501
+ # without manually checking that each encoding
502
+ # encodes all ASCII characters properly,
503
+ # which takes long enough to affect the startup time of the CLI.
504
+ ENCODINGS_TO_CHECK = %w[UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE]
505
+
506
+ CHARSET_REGEXPS = Hash.new do |h, e|
507
+ h[e] =
508
+ begin
509
+ # /\A(?:\uFEFF)?@charset "(.*?)"|\A(\uFEFF)/
510
+ Regexp.new(/\A(?:#{_enc("\uFEFF", e)})?#{
511
+ _enc('@charset "', e)}(.*?)#{_enc('"', e)}|\A(#{
512
+ _enc("\uFEFF", e)})/)
513
+ rescue
514
+ # /\A@charset "(.*?)"/
515
+ Regexp.new(/\A#{_enc('@charset "', e)}(.*?)#{_enc('"', e)}/)
516
+ end
517
+ end
518
+ end
519
+
520
+ # Checks to see if a class has a given method.
521
+ # For example:
522
+ #
523
+ # Sass::Util.has?(:public_instance_method, String, :gsub) #=> true
524
+ #
525
+ # Method collections like `Class#instance_methods`
526
+ # return strings in Ruby 1.8 and symbols in Ruby 1.9 and on,
527
+ # so this handles checking for them in a compatible way.
528
+ #
529
+ # @param attr [#to_s] The (singular) name of the method-collection method
530
+ # (e.g. `:instance_methods`, `:private_methods`)
531
+ # @param klass [Module] The class to check the methods of which to check
532
+ # @param method [String, Symbol] The name of the method do check for
533
+ # @return [Boolean] Whether or not the given collection has the given method
534
+ def has?(attr, klass, method)
535
+ klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
536
+ end
537
+
538
+ # A version of `Enumerable#enum_with_index` that works in Ruby 1.8 and 1.9.
539
+ #
540
+ # @param enum [Enumerable] The enumerable to get the enumerator for
541
+ # @return [Enumerator] The with-index enumerator
542
+ def enum_with_index(enum)
543
+ ruby1_8? ? enum.enum_with_index : enum.each_with_index
544
+ end
545
+
546
+ # A version of `Enumerable#enum_cons` that works in Ruby 1.8 and 1.9.
547
+ #
548
+ # @param enum [Enumerable] The enumerable to get the enumerator for
549
+ # @param n [Fixnum] The size of each cons
550
+ # @return [Enumerator] The consed enumerator
551
+ def enum_cons(enum, n)
552
+ ruby1_8? ? enum.enum_cons(n) : enum.each_cons(n)
553
+ end
554
+
555
+ # A version of `Enumerable#enum_slice` that works in Ruby 1.8 and 1.9.
556
+ #
557
+ # @param enum [Enumerable] The enumerable to get the enumerator for
558
+ # @param n [Fixnum] The size of each slice
559
+ # @return [Enumerator] The consed enumerator
560
+ def enum_slice(enum, n)
561
+ ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
562
+ end
563
+
564
+ # Returns the ASCII code of the given character.
565
+ #
566
+ # @param c [String] All characters but the first are ignored.
567
+ # @return [Fixnum] The ASCII code of `c`.
568
+ def ord(c)
569
+ ruby1_8? ? c[0] : c.ord
570
+ end
571
+
572
+ # Flattens the first `n` nested arrays in a cross-version manner.
573
+ #
574
+ # @param arr [Array] The array to flatten
575
+ # @param n [Fixnum] The number of levels to flatten
576
+ # @return [Array] The flattened array
577
+ def flatten(arr, n)
578
+ return arr.flatten(n) unless ruby1_8_6?
579
+ return arr if n == 0
580
+ arr.inject([]) {|res, e| e.is_a?(Array) ? res.concat(flatten(e, n - 1)) : res << e}
581
+ end
582
+
583
+ # Returns the hash code for a set in a cross-version manner.
584
+ # Aggravatingly, this is order-dependent in Ruby 1.8.6.
585
+ #
586
+ # @param set [Set]
587
+ # @return [Fixnum] The order-independent hashcode of `set`
588
+ def set_hash(set)
589
+ return set.hash unless ruby1_8_6?
590
+ set.map {|e| e.hash}.uniq.sort.hash
591
+ end
592
+
593
+ # Tests the hash-equality of two sets in a cross-version manner.
594
+ # Aggravatingly, this is order-dependent in Ruby 1.8.6.
595
+ #
596
+ # @param set1 [Set]
597
+ # @param set2 [Set]
598
+ # @return [Boolean] Whether or not the sets are hashcode equal
599
+ def set_eql?(set1, set2)
600
+ return set1.eql?(set2) unless ruby1_8_6?
601
+ set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
602
+ end
603
+
604
+ # Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them under Ruby 1.9.2.
605
+ # This is necessary so that the precompiled Haml template can be `#encode`d into `@options[:encoding]`
606
+ # before being evaluated.
607
+ #
608
+ # @param obj {Object}
609
+ # @return {String}
610
+ def inspect_obj(obj)
611
+ return obj.inspect unless version_geq(::RUBY_VERSION, "1.9.2")
612
+ return ':' + inspect_obj(obj.to_s) if obj.is_a?(Symbol)
613
+ return obj.inspect unless obj.is_a?(String)
614
+ '"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
615
+ end
616
+
617
+ ## Static Method Stuff
618
+
619
+ # The context in which the ERB for \{#def\_static\_method} will be run.
620
+ class StaticConditionalContext
621
+ # @param set [#include?] The set of variables that are defined for this context.
622
+ def initialize(set)
623
+ @set = set
624
+ end
625
+
626
+ # Checks whether or not a variable is defined for this context.
627
+ #
628
+ # @param name [Symbol] The name of the variable
629
+ # @return [Boolean]
630
+ def method_missing(name, *args, &block)
631
+ super unless args.empty? && block.nil?
632
+ @set.include?(name)
633
+ end
634
+ end
635
+
636
+ private
637
+
638
+ # Calculates the memoization table for the Least Common Subsequence algorithm.
639
+ # Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
640
+ def lcs_table(x, y)
641
+ c = Array.new(x.size) {[]}
642
+ x.size.times {|i| c[i][0] = 0}
643
+ y.size.times {|j| c[0][j] = 0}
644
+ (1...x.size).each do |i|
645
+ (1...y.size).each do |j|
646
+ c[i][j] =
647
+ if yield x[i], y[j]
648
+ c[i-1][j-1] + 1
649
+ else
650
+ [c[i][j-1], c[i-1][j]].max
651
+ end
652
+ end
653
+ end
654
+ return c
655
+ end
656
+
657
+ # Computes a single longest common subsequence for arrays x and y.
658
+ # Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
659
+ def lcs_backtrace(c, x, y, i, j, &block)
660
+ return [] if i == 0 || j == 0
661
+ if v = yield(x[i], y[j])
662
+ return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
663
+ end
664
+
665
+ return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
666
+ return lcs_backtrace(c, x, y, i-1, j, &block)
667
+ end
668
+ end
669
+ end