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,245 @@
1
+ module Sass::Script
2
+ # The abstract superclass for SassScript objects.
3
+ #
4
+ # Many of these methods, especially the ones that correspond to SassScript operations,
5
+ # are designed to be overridden by subclasses which may change the semantics somewhat.
6
+ # The operations listed here are just the defaults.
7
+ class Literal < Node
8
+ require 'sass/script/string'
9
+ require 'sass/script/number'
10
+ require 'sass/script/color'
11
+ require 'sass/script/bool'
12
+ require 'sass/script/list'
13
+
14
+ # Returns the Ruby value of the literal.
15
+ # The type of this value varies based on the subclass.
16
+ #
17
+ # @return [Object]
18
+ attr_reader :value
19
+
20
+ # Creates a new literal.
21
+ #
22
+ # @param value [Object] The object for \{#value}
23
+ def initialize(value = nil)
24
+ @value = value
25
+ super()
26
+ end
27
+
28
+ # Returns an empty array.
29
+ #
30
+ # @return [Array<Node>] empty
31
+ # @see Node#children
32
+ def children
33
+ []
34
+ end
35
+
36
+ # Returns the options hash for this node.
37
+ #
38
+ # @return [{Symbol => Object}]
39
+ # @raise [Sass::SyntaxError] if the options hash hasn't been set.
40
+ # This should only happen when the literal was created
41
+ # outside of the parser and \{#to\_s} was called on it
42
+ def options
43
+ opts = super
44
+ return opts if opts
45
+ raise Sass::SyntaxError.new(<<MSG)
46
+ The #options attribute is not set on this #{self.class}.
47
+ This error is probably occurring because #to_s was called
48
+ on this literal within a custom Sass function without first
49
+ setting the #option attribute.
50
+ MSG
51
+ end
52
+
53
+ # The SassScript `and` operation.
54
+ #
55
+ # @param other [Literal] The right-hand side of the operator
56
+ # @return [Literal] The result of a logical and:
57
+ # `other` if this literal isn't a false {Bool},
58
+ # and this literal otherwise
59
+ def and(other)
60
+ to_bool ? other : self
61
+ end
62
+
63
+ # The SassScript `or` operation.
64
+ #
65
+ # @param other [Literal] The right-hand side of the operator
66
+ # @return [Literal] The result of the logical or:
67
+ # this literal if it isn't a false {Bool},
68
+ # and `other` otherwise
69
+ def or(other)
70
+ to_bool ? self : other
71
+ end
72
+
73
+ # The SassScript `==` operation.
74
+ # **Note that this returns a {Sass::Script::Bool} object,
75
+ # not a Ruby boolean**.
76
+ #
77
+ # @param other [Literal] The right-hand side of the operator
78
+ # @return [Bool] True if this literal is the same as the other,
79
+ # false otherwise
80
+ def eq(other)
81
+ Sass::Script::Bool.new(self.class == other.class && self.value == other.value)
82
+ end
83
+
84
+ # The SassScript `!=` operation.
85
+ # **Note that this returns a {Sass::Script::Bool} object,
86
+ # not a Ruby boolean**.
87
+ #
88
+ # @param other [Literal] The right-hand side of the operator
89
+ # @return [Bool] False if this literal is the same as the other,
90
+ # true otherwise
91
+ def neq(other)
92
+ Sass::Script::Bool.new(!eq(other).to_bool)
93
+ end
94
+
95
+ # The SassScript `==` operation.
96
+ # **Note that this returns a {Sass::Script::Bool} object,
97
+ # not a Ruby boolean**.
98
+ #
99
+ # @param other [Literal] The right-hand side of the operator
100
+ # @return [Bool] True if this literal is the same as the other,
101
+ # false otherwise
102
+ def unary_not
103
+ Sass::Script::Bool.new(!to_bool)
104
+ end
105
+
106
+ # The SassScript default operation (e.g. `$a $b`, `"foo" "bar"`).
107
+ #
108
+ # @param other [Literal] The right-hand side of the operator
109
+ # @return [Script::String] A string containing both literals
110
+ # separated by a space
111
+ def space(other)
112
+ Sass::Script::String.new("#{self.to_s} #{other.to_s}")
113
+ end
114
+
115
+ # The SassScript `,` operation (e.g. `$a, $b`, `"foo", "bar"`).
116
+ #
117
+ # @param other [Literal] The right-hand side of the operator
118
+ # @return [Script::String] A string containing both literals
119
+ # separated by `", "`
120
+ def comma(other)
121
+ Sass::Script::String.new("#{self.to_s},#{' ' unless options[:style] == :compressed}#{other.to_s}")
122
+ end
123
+
124
+ # The SassScript `=` operation
125
+ # (used for proprietary MS syntax like `alpha(opacity=20)`).
126
+ #
127
+ # @param other [Literal] The right-hand side of the operator
128
+ # @return [Script::String] A string containing both literals
129
+ # separated by `"="`
130
+ def single_eq(other)
131
+ Sass::Script::String.new("#{self.to_s}=#{other.to_s}")
132
+ end
133
+
134
+ # The SassScript `+` operation.
135
+ #
136
+ # @param other [Literal] The right-hand side of the operator
137
+ # @return [Script::String] A string containing both literals
138
+ # without any separation
139
+ def plus(other)
140
+ if other.is_a?(Sass::Script::String)
141
+ return Sass::Script::String.new(self.to_s + other.value, other.type)
142
+ end
143
+ Sass::Script::String.new(self.to_s + other.to_s)
144
+ end
145
+
146
+ # The SassScript `-` operation.
147
+ #
148
+ # @param other [Literal] The right-hand side of the operator
149
+ # @return [Script::String] A string containing both literals
150
+ # separated by `"-"`
151
+ def minus(other)
152
+ Sass::Script::String.new("#{self.to_s}-#{other.to_s}")
153
+ end
154
+
155
+ # The SassScript `/` operation.
156
+ #
157
+ # @param other [Literal] The right-hand side of the operator
158
+ # @return [Script::String] A string containing both literals
159
+ # separated by `"/"`
160
+ def div(other)
161
+ Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
162
+ end
163
+
164
+ # The SassScript unary `+` operation (e.g. `+$a`).
165
+ #
166
+ # @param other [Literal] The right-hand side of the operator
167
+ # @return [Script::String] A string containing the literal
168
+ # preceded by `"+"`
169
+ def unary_plus
170
+ Sass::Script::String.new("+#{self.to_s}")
171
+ end
172
+
173
+ # The SassScript unary `-` operation (e.g. `-$a`).
174
+ #
175
+ # @param other [Literal] The right-hand side of the operator
176
+ # @return [Script::String] A string containing the literal
177
+ # preceded by `"-"`
178
+ def unary_minus
179
+ Sass::Script::String.new("-#{self.to_s}")
180
+ end
181
+
182
+ # The SassScript unary `/` operation (e.g. `/$a`).
183
+ #
184
+ # @param other [Literal] The right-hand side of the operator
185
+ # @return [Script::String] A string containing the literal
186
+ # preceded by `"/"`
187
+ def unary_div
188
+ Sass::Script::String.new("/#{self.to_s}")
189
+ end
190
+
191
+ # @return [String] A readable representation of the literal
192
+ def inspect
193
+ value.inspect
194
+ end
195
+
196
+ # @return [Boolean] `true` (the Ruby boolean value)
197
+ def to_bool
198
+ true
199
+ end
200
+
201
+ # Compares this object with another.
202
+ #
203
+ # @param other [Object] The object to compare with
204
+ # @return [Boolean] Whether or not this literal is equivalent to `other`
205
+ def ==(other)
206
+ eq(other).to_bool
207
+ end
208
+
209
+ # @return [Fixnum] The integer value of this literal
210
+ # @raise [Sass::SyntaxError] if this literal isn't an integer
211
+ def to_i
212
+ raise Sass::SyntaxError.new("#{self.inspect} is not an integer.")
213
+ end
214
+
215
+ # @raise [Sass::SyntaxError] if this literal isn't an integer
216
+ def assert_int!; to_i; end
217
+
218
+ # Returns the value of this literal as a list.
219
+ # Single literals are considered the same as single-element lists.
220
+ #
221
+ # @return [Array<Literal>] The of this literal as a list
222
+ def to_a
223
+ [self]
224
+ end
225
+
226
+ # Returns the string representation of this literal
227
+ # as it would be output to the CSS document.
228
+ #
229
+ # @return [String]
230
+ def to_s(opts = {})
231
+ raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
232
+ end
233
+ alias_method :to_sass, :to_s
234
+
235
+ protected
236
+
237
+ # Evaluates the literal.
238
+ #
239
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
240
+ # @return [Literal] This literal
241
+ def _perform(environment)
242
+ self
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,91 @@
1
+ module Sass::Script
2
+ # The abstract superclass for SassScript parse tree nodes.
3
+ #
4
+ # Use \{#perform} to evaluate a parse tree.
5
+ class Node
6
+ # The options hash for this node.
7
+ #
8
+ # @return [{Symbol => Object}]
9
+ attr_reader :options
10
+
11
+ # The line of the document on which this node appeared.
12
+ #
13
+ # @return [Fixnum]
14
+ attr_accessor :line
15
+
16
+ # Sets the options hash for this node,
17
+ # as well as for all child nodes.
18
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
19
+ #
20
+ # @param options [{Symbol => Object}] The options
21
+ def options=(options)
22
+ @options = options
23
+ children.each do |c|
24
+ if c.is_a? Hash
25
+ c.values.each {|v| v.options = options }
26
+ else
27
+ c.options = options
28
+ end
29
+ end
30
+ end
31
+
32
+ # Evaluates the node.
33
+ #
34
+ # \{#perform} shouldn't be overridden directly;
35
+ # instead, override \{#\_perform}.
36
+ #
37
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
38
+ # @return [Literal] The SassScript object that is the value of the SassScript
39
+ def perform(environment)
40
+ _perform(environment)
41
+ rescue Sass::SyntaxError => e
42
+ e.modify_backtrace(:line => line)
43
+ raise e
44
+ end
45
+
46
+ # Returns all child nodes of this node.
47
+ #
48
+ # @return [Array<Node>]
49
+ def children
50
+ Sass::Util.abstract(self)
51
+ end
52
+
53
+ # Returns the text of this SassScript expression.
54
+ #
55
+ # @return [String]
56
+ def to_sass(opts = {})
57
+ Sass::Util.abstract(self)
58
+ end
59
+
60
+ protected
61
+
62
+ # Converts underscores to dashes if the :dasherize option is set.
63
+ def dasherize(s, opts)
64
+ if opts[:dasherize]
65
+ s.gsub(/_/,'-')
66
+ else
67
+ s
68
+ end
69
+ end
70
+
71
+ # Evaluates this node.
72
+ # Note that all {Literal} objects created within this method
73
+ # should have their \{#options} attribute set, probably via \{#opts}.
74
+ #
75
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
76
+ # @return [Literal] The SassScript object that is the value of the SassScript
77
+ # @see #perform
78
+ def _perform(environment)
79
+ Sass::Util.abstract(self)
80
+ end
81
+
82
+ # Sets the \{#options} field on the given literal and returns it
83
+ #
84
+ # @param literal [Literal]
85
+ # @return [Literal]
86
+ def opts(literal)
87
+ literal.options = options
88
+ literal
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,429 @@
1
+ require 'sass/script/literal'
2
+
3
+ module Sass::Script
4
+ # A SassScript object representing a number.
5
+ # SassScript numbers can have decimal values,
6
+ # and can also have units.
7
+ # For example, `12`, `1px`, and `10.45em`
8
+ # are all valid values.
9
+ #
10
+ # Numbers can also have more complex units, such as `1px*em/in`.
11
+ # These cannot be inputted directly in Sass code at the moment.
12
+ class Number < Literal
13
+ # The Ruby value of the number.
14
+ #
15
+ # @return [Numeric]
16
+ attr_reader :value
17
+
18
+ # A list of units in the numerator of the number.
19
+ # For example, `1px*em/in*cm` would return `["px", "em"]`
20
+ # @return [Array<String>]
21
+ attr_reader :numerator_units
22
+
23
+ # A list of units in the denominator of the number.
24
+ # For example, `1px*em/in*cm` would return `["in", "cm"]`
25
+ # @return [Array<String>]
26
+ attr_reader :denominator_units
27
+
28
+ # The original representation of this number.
29
+ # For example, although the result of `1px/2px` is `0.5`,
30
+ # the value of `#original` is `"1px/2px"`.
31
+ #
32
+ # This is only non-nil when the original value should be used as the CSS value,
33
+ # as in `font: 1px/2px`.
34
+ #
35
+ # @return [Boolean, nil]
36
+ attr_accessor :original
37
+
38
+ # The precision with which numbers will be printed to CSS files.
39
+ # For example, if this is `1000.0`,
40
+ # `3.1415926` will be printed as `3.142`.
41
+ # @api public
42
+ PRECISION = 1000.0
43
+
44
+ # Used so we don't allocate two new arrays for each new number.
45
+ NO_UNITS = []
46
+
47
+ # @param value [Numeric] The value of the number
48
+ # @param numerator_units [Array<String>] See \{#numerator\_units}
49
+ # @param denominator_units [Array<String>] See \{#denominator\_units}
50
+ def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
51
+ super(value)
52
+ @numerator_units = numerator_units
53
+ @denominator_units = denominator_units
54
+ normalize!
55
+ end
56
+
57
+ # The SassScript `+` operation.
58
+ # Its functionality depends on the type of its argument:
59
+ #
60
+ # {Number}
61
+ # : Adds the two numbers together, converting units if possible.
62
+ #
63
+ # {Color}
64
+ # : Adds this number to each of the RGB color channels.
65
+ #
66
+ # {Literal}
67
+ # : See {Literal#plus}.
68
+ #
69
+ # @param other [Literal] The right-hand side of the operator
70
+ # @return [Literal] The result of the operation
71
+ # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
72
+ def plus(other)
73
+ if other.is_a? Number
74
+ operate(other, :+)
75
+ elsif other.is_a?(Color)
76
+ other.plus(self)
77
+ else
78
+ super
79
+ end
80
+ end
81
+
82
+ # The SassScript binary `-` operation (e.g. `$a - $b`).
83
+ # Its functionality depends on the type of its argument:
84
+ #
85
+ # {Number}
86
+ # : Subtracts this number from the other, converting units if possible.
87
+ #
88
+ # {Literal}
89
+ # : See {Literal#minus}.
90
+ #
91
+ # @param other [Literal] The right-hand side of the operator
92
+ # @return [Literal] The result of the operation
93
+ # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
94
+ def minus(other)
95
+ if other.is_a? Number
96
+ operate(other, :-)
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ # The SassScript unary `+` operation (e.g. `+$a`).
103
+ #
104
+ # @return [Number] The value of this number
105
+ def unary_plus
106
+ self
107
+ end
108
+
109
+ # The SassScript unary `-` operation (e.g. `-$a`).
110
+ #
111
+ # @return [Number] The negative value of this number
112
+ def unary_minus
113
+ Number.new(-value, @numerator_units, @denominator_units)
114
+ end
115
+
116
+ # The SassScript `*` operation.
117
+ # Its functionality depends on the type of its argument:
118
+ #
119
+ # {Number}
120
+ # : Multiplies the two numbers together, converting units appropriately.
121
+ #
122
+ # {Color}
123
+ # : Multiplies each of the RGB color channels by this number.
124
+ #
125
+ # @param other [Number, Color] The right-hand side of the operator
126
+ # @return [Number, Color] The result of the operation
127
+ # @raise [NoMethodError] if `other` is an invalid type
128
+ def times(other)
129
+ if other.is_a? Number
130
+ operate(other, :*)
131
+ elsif other.is_a? Color
132
+ other.times(self)
133
+ else
134
+ raise NoMethodError.new(nil, :times)
135
+ end
136
+ end
137
+
138
+ # The SassScript `/` operation.
139
+ # Its functionality depends on the type of its argument:
140
+ #
141
+ # {Number}
142
+ # : Divides this number by the other, converting units appropriately.
143
+ #
144
+ # {Literal}
145
+ # : See {Literal#div}.
146
+ #
147
+ # @param other [Literal] The right-hand side of the operator
148
+ # @return [Literal] The result of the operation
149
+ def div(other)
150
+ if other.is_a? Number
151
+ res = operate(other, :/)
152
+ if self.original && other.original
153
+ res.original = "#{self.original}/#{other.original}"
154
+ end
155
+ res
156
+ else
157
+ super
158
+ end
159
+ end
160
+
161
+ # The SassScript `%` operation.
162
+ #
163
+ # @param other [Number] The right-hand side of the operator
164
+ # @return [Number] This number modulo the other
165
+ # @raise [NoMethodError] if `other` is an invalid type
166
+ # @raise [Sass::UnitConversionError] if `other` has any units
167
+ def mod(other)
168
+ if other.is_a?(Number)
169
+ unless other.unitless?
170
+ raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.")
171
+ end
172
+ operate(other, :%)
173
+ else
174
+ raise NoMethodError.new(nil, :mod)
175
+ end
176
+ end
177
+
178
+ # The SassScript `==` operation.
179
+ #
180
+ # @param other [Literal] The right-hand side of the operator
181
+ # @return [Boolean] Whether this number is equal to the other object
182
+ def eq(other)
183
+ return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
184
+ this = self
185
+ begin
186
+ if unitless?
187
+ this = this.coerce(other.numerator_units, other.denominator_units)
188
+ else
189
+ other = other.coerce(@numerator_units, @denominator_units)
190
+ end
191
+ rescue Sass::UnitConversionError
192
+ return Sass::Script::Bool.new(false)
193
+ end
194
+
195
+ Sass::Script::Bool.new(this.value == other.value)
196
+ end
197
+
198
+ # The SassScript `>` operation.
199
+ #
200
+ # @param other [Number] The right-hand side of the operator
201
+ # @return [Boolean] Whether this number is greater than the other
202
+ # @raise [NoMethodError] if `other` is an invalid type
203
+ def gt(other)
204
+ raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
205
+ operate(other, :>)
206
+ end
207
+
208
+ # The SassScript `>=` operation.
209
+ #
210
+ # @param other [Number] The right-hand side of the operator
211
+ # @return [Boolean] Whether this number is greater than or equal to the other
212
+ # @raise [NoMethodError] if `other` is an invalid type
213
+ def gte(other)
214
+ raise NoMethodError.new(nil, :gte) unless other.is_a?(Number)
215
+ operate(other, :>=)
216
+ end
217
+
218
+ # The SassScript `<` operation.
219
+ #
220
+ # @param other [Number] The right-hand side of the operator
221
+ # @return [Boolean] Whether this number is less than the other
222
+ # @raise [NoMethodError] if `other` is an invalid type
223
+ def lt(other)
224
+ raise NoMethodError.new(nil, :lt) unless other.is_a?(Number)
225
+ operate(other, :<)
226
+ end
227
+
228
+ # The SassScript `<=` operation.
229
+ #
230
+ # @param other [Number] The right-hand side of the operator
231
+ # @return [Boolean] Whether this number is less than or equal to the other
232
+ # @raise [NoMethodError] if `other` is an invalid type
233
+ def lte(other)
234
+ raise NoMethodError.new(nil, :lte) unless other.is_a?(Number)
235
+ operate(other, :<=)
236
+ end
237
+
238
+ # @return [String] The CSS representation of this number
239
+ # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS
240
+ # (e.g. `px*in`)
241
+ def to_s(opts = {})
242
+ return original if original
243
+ raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
244
+ inspect
245
+ end
246
+
247
+ # Returns a readable representation of this number.
248
+ #
249
+ # This representation is valid CSS (and valid SassScript)
250
+ # as long as there is only one unit.
251
+ #
252
+ # @return [String] The representation
253
+ def inspect(opts = {})
254
+ value = self.class.round(self.value)
255
+ unitless? ? value.to_s : "#{value}#{unit_str}"
256
+ end
257
+ alias_method :to_sass, :inspect
258
+
259
+ # @return [Fixnum] The integer value of the number
260
+ # @raise [Sass::SyntaxError] if the number isn't an integer
261
+ def to_i
262
+ super unless int?
263
+ return value
264
+ end
265
+
266
+ # @return [Boolean] Whether or not this number is an integer.
267
+ def int?
268
+ value % 1 == 0.0
269
+ end
270
+
271
+ # @return [Boolean] Whether or not this number has no units.
272
+ def unitless?
273
+ @numerator_units.empty? && @denominator_units.empty?
274
+ end
275
+
276
+ # @return [Boolean] Whether or not this number has units that can be represented in CSS
277
+ # (that is, zero or one \{#numerator\_units}).
278
+ def legal_units?
279
+ (@numerator_units.empty? || @numerator_units.size == 1) && @denominator_units.empty?
280
+ end
281
+
282
+ # Returns this number converted to other units.
283
+ # The conversion takes into account the relationship between e.g. mm and cm,
284
+ # as well as between e.g. in and cm.
285
+ #
286
+ # If this number has no units, it will simply return itself
287
+ # with the given units.
288
+ #
289
+ # An incompatible coercion, e.g. between px and cm, will raise an error.
290
+ #
291
+ # @param num_units [Array<String>] The numerator units to coerce this number into.
292
+ # See {\#numerator\_units}
293
+ # @param den_units [Array<String>] The denominator units to coerce this number into.
294
+ # See {\#denominator\_units}
295
+ # @return [Number] The number with the new units
296
+ # @raise [Sass::UnitConversionError] if the given units are incompatible with the number's
297
+ # current units
298
+ def coerce(num_units, den_units)
299
+ Number.new(if unitless?
300
+ self.value
301
+ else
302
+ self.value * coercion_factor(@numerator_units, num_units) /
303
+ coercion_factor(@denominator_units, den_units)
304
+ end, num_units, den_units)
305
+ end
306
+
307
+ # @param other [Number] A number to decide if it can be compared with this number.
308
+ # @return [Boolean] Whether or not this number can be compared with the other.
309
+ def comparable_to?(other)
310
+ begin
311
+ operate(other, :+)
312
+ true
313
+ rescue Sass::UnitConversionError
314
+ false
315
+ end
316
+ end
317
+
318
+ # Returns a human readable representation of the units in this number.
319
+ # For complex units this takes the form of:
320
+ # numerator_unit1 * numerator_unit2 / denominator_unit1 * denominator_unit2
321
+ # @return [String] a string that represents the units in this number
322
+ def unit_str
323
+ rv = @numerator_units.sort.join("*")
324
+ if @denominator_units.any?
325
+ rv << "/"
326
+ rv << @denominator_units.sort.join("*")
327
+ end
328
+ rv
329
+ end
330
+
331
+ private
332
+
333
+ # @private
334
+ def self.round(num)
335
+ if num.is_a?(Float) && (num.infinite? || num.nan?)
336
+ num
337
+ elsif num % 1 == 0.0
338
+ num.to_i
339
+ else
340
+ (num * PRECISION).round / PRECISION
341
+ end
342
+ end
343
+
344
+ OPERATIONS = [:+, :-, :<=, :<, :>, :>=]
345
+
346
+ def operate(other, operation)
347
+ this = self
348
+ if OPERATIONS.include?(operation)
349
+ if unitless?
350
+ this = this.coerce(other.numerator_units, other.denominator_units)
351
+ else
352
+ other = other.coerce(@numerator_units, @denominator_units)
353
+ end
354
+ end
355
+ # avoid integer division
356
+ value = (:/ == operation) ? this.value.to_f : this.value
357
+ result = value.send(operation, other.value)
358
+
359
+ if result.is_a?(Numeric)
360
+ Number.new(result, *compute_units(this, other, operation))
361
+ else # Boolean op
362
+ Bool.new(result)
363
+ end
364
+ end
365
+
366
+ def coercion_factor(from_units, to_units)
367
+ # get a list of unmatched units
368
+ from_units, to_units = sans_common_units(from_units, to_units)
369
+
370
+ if from_units.size != to_units.size || !convertable?(from_units | to_units)
371
+ raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
372
+ end
373
+
374
+ from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
375
+ end
376
+
377
+ def compute_units(this, other, operation)
378
+ case operation
379
+ when :*
380
+ [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
381
+ when :/
382
+ [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
383
+ else
384
+ [this.numerator_units, this.denominator_units]
385
+ end
386
+ end
387
+
388
+ def normalize!
389
+ return if unitless?
390
+ @numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units)
391
+
392
+ @denominator_units.each_with_index do |d, i|
393
+ if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
394
+ @value /= conversion_factor(d, u)
395
+ @denominator_units.delete_at(i)
396
+ @numerator_units.delete_at(@numerator_units.index(u))
397
+ end
398
+ end
399
+ end
400
+
401
+ # A hash of unit names to their index in the conversion table
402
+ CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
403
+ CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
404
+ [ nil, 1, 2.36220473, 10, 28.3464567], # cm
405
+ [ nil, nil, 1, 4.23333333, 12 ], # pc
406
+ [ nil, nil, nil, 1, 2.83464567], # mm
407
+ [ nil, nil, nil, nil, 1 ]] # pt
408
+
409
+ def conversion_factor(from_unit, to_unit)
410
+ res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
411
+ return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
412
+ res
413
+ end
414
+
415
+ def convertable?(units)
416
+ Array(units).all? {|u| CONVERTABLE_UNITS.include?(u)}
417
+ end
418
+
419
+ def sans_common_units(units1, units2)
420
+ units2 = units2.dup
421
+ # Can't just use -, because we want px*px to coerce properly to px*mm
422
+ return units1.map do |u|
423
+ next u unless j = units2.index(u)
424
+ units2.delete_at(j)
425
+ nil
426
+ end.compact, units2
427
+ end
428
+ end
429
+ end