haml 3.1.0.alpha.14 → 3.1.0.alpha.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (222) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/haml.rb +3 -2
  4. data/lib/haml/exec.rb +0 -226
  5. data/lib/sass.rb +8 -0
  6. data/lib/sass/plugin.rb +8 -0
  7. data/lib/sass/rails2_shim.rb +9 -0
  8. data/lib/sass/rails3_shim.rb +16 -0
  9. data/vendor/sass/CONTRIBUTING +3 -0
  10. data/vendor/sass/MIT-LICENSE +20 -0
  11. data/vendor/sass/README.md +201 -0
  12. data/vendor/sass/Rakefile +363 -0
  13. data/vendor/sass/TODO +39 -0
  14. data/vendor/sass/VERSION +1 -0
  15. data/vendor/sass/VERSION_NAME +1 -0
  16. data/vendor/sass/bin/css2sass +13 -0
  17. data/vendor/sass/bin/sass +8 -0
  18. data/vendor/sass/bin/sass-convert +7 -0
  19. data/vendor/sass/doc-src/FAQ.md +35 -0
  20. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  21. data/vendor/sass/doc-src/SASS_CHANGELOG.md +1878 -0
  22. data/vendor/sass/doc-src/SASS_REFERENCE.md +1713 -0
  23. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  24. data/vendor/sass/ext/extconf.rb +10 -0
  25. data/vendor/sass/extra/update_watch.rb +13 -0
  26. data/vendor/sass/init.rb +18 -0
  27. data/vendor/sass/lib/sass.rb +71 -0
  28. data/vendor/sass/lib/sass/cache_store.rb +208 -0
  29. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  30. data/vendor/sass/lib/sass/css.rb +294 -0
  31. data/vendor/sass/lib/sass/engine.rb +792 -0
  32. data/vendor/sass/lib/sass/environment.rb +143 -0
  33. data/vendor/sass/lib/sass/error.rb +201 -0
  34. data/vendor/sass/lib/sass/exec.rb +619 -0
  35. data/vendor/sass/lib/sass/importers.rb +22 -0
  36. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  37. data/vendor/sass/lib/sass/importers/filesystem.rb +121 -0
  38. data/vendor/sass/lib/sass/less.rb +363 -0
  39. data/vendor/sass/lib/sass/plugin.rb +126 -0
  40. data/vendor/sass/lib/sass/plugin/compiler.rb +346 -0
  41. data/vendor/sass/lib/sass/plugin/configuration.rb +123 -0
  42. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  43. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  44. data/vendor/sass/lib/sass/plugin/rack.rb +47 -0
  45. data/vendor/sass/lib/sass/plugin/rails.rb +41 -0
  46. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +145 -0
  47. data/vendor/sass/lib/sass/railtie.rb +8 -0
  48. data/vendor/sass/lib/sass/repl.rb +58 -0
  49. data/vendor/sass/lib/sass/root.rb +7 -0
  50. data/vendor/sass/lib/sass/script.rb +63 -0
  51. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  52. data/vendor/sass/lib/sass/script/color.rb +491 -0
  53. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  54. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  55. data/vendor/sass/lib/sass/script/funcall.rb +76 -0
  56. data/vendor/sass/lib/sass/script/functions.rb +852 -0
  57. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  58. data/vendor/sass/lib/sass/script/lexer.rb +337 -0
  59. data/vendor/sass/lib/sass/script/literal.rb +236 -0
  60. data/vendor/sass/lib/sass/script/node.rb +112 -0
  61. data/vendor/sass/lib/sass/script/number.rb +423 -0
  62. data/vendor/sass/lib/sass/script/operation.rb +90 -0
  63. data/vendor/sass/lib/sass/script/parser.rb +392 -0
  64. data/vendor/sass/lib/sass/script/string.rb +67 -0
  65. data/vendor/sass/lib/sass/script/string_interpolation.rb +93 -0
  66. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  67. data/vendor/sass/lib/sass/script/variable.rb +48 -0
  68. data/vendor/sass/lib/sass/scss.rb +17 -0
  69. data/vendor/sass/lib/sass/scss/css_parser.rb +51 -0
  70. data/vendor/sass/lib/sass/scss/parser.rb +838 -0
  71. data/vendor/sass/lib/sass/scss/rx.rb +126 -0
  72. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  73. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  74. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  75. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  76. data/vendor/sass/lib/sass/selector.rb +361 -0
  77. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  78. data/vendor/sass/lib/sass/selector/comma_sequence.rb +82 -0
  79. data/vendor/sass/lib/sass/selector/sequence.rb +236 -0
  80. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  81. data/vendor/sass/lib/sass/selector/simple_sequence.rb +135 -0
  82. data/vendor/sass/lib/sass/shared.rb +78 -0
  83. data/vendor/sass/lib/sass/tree/comment_node.rb +128 -0
  84. data/vendor/sass/lib/sass/tree/debug_node.rb +36 -0
  85. data/vendor/sass/lib/sass/tree/directive_node.rb +75 -0
  86. data/vendor/sass/lib/sass/tree/extend_node.rb +65 -0
  87. data/vendor/sass/lib/sass/tree/for_node.rb +67 -0
  88. data/vendor/sass/lib/sass/tree/if_node.rb +81 -0
  89. data/vendor/sass/lib/sass/tree/import_node.rb +124 -0
  90. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +60 -0
  91. data/vendor/sass/lib/sass/tree/mixin_node.rb +123 -0
  92. data/vendor/sass/lib/sass/tree/node.rb +490 -0
  93. data/vendor/sass/lib/sass/tree/prop_node.rb +220 -0
  94. data/vendor/sass/lib/sass/tree/root_node.rb +125 -0
  95. data/vendor/sass/lib/sass/tree/rule_node.rb +273 -0
  96. data/vendor/sass/lib/sass/tree/variable_node.rb +39 -0
  97. data/vendor/sass/lib/sass/tree/warn_node.rb +42 -0
  98. data/vendor/sass/lib/sass/tree/while_node.rb +48 -0
  99. data/vendor/sass/lib/sass/util.rb +700 -0
  100. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  101. data/vendor/sass/lib/sass/version.rb +109 -0
  102. data/vendor/sass/rails/init.rb +1 -0
  103. data/vendor/sass/sass.gemspec +32 -0
  104. data/vendor/sass/test/sass/cache_test.rb +74 -0
  105. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  106. data/vendor/sass/test/sass/conversion_test.rb +1210 -0
  107. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  108. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  109. data/vendor/sass/test/sass/engine_test.rb +2305 -0
  110. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  111. data/vendor/sass/test/sass/functions_test.rb +565 -0
  112. data/vendor/sass/test/sass/importer_test.rb +104 -0
  113. data/vendor/sass/test/sass/less_conversion_test.rb +632 -0
  114. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  115. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  116. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  117. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  118. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  119. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  120. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  121. data/vendor/sass/test/sass/plugin_test.rb +430 -0
  122. data/vendor/sass/test/sass/results/alt.css +4 -0
  123. data/vendor/sass/test/sass/results/basic.css +9 -0
  124. data/vendor/sass/test/sass/results/compact.css +5 -0
  125. data/vendor/sass/test/sass/results/complex.css +86 -0
  126. data/vendor/sass/test/sass/results/compressed.css +1 -0
  127. data/vendor/sass/test/sass/results/expanded.css +19 -0
  128. data/vendor/sass/test/sass/results/import.css +31 -0
  129. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  130. data/vendor/sass/test/sass/results/mixins.css +95 -0
  131. data/vendor/sass/test/sass/results/multiline.css +24 -0
  132. data/vendor/sass/test/sass/results/nested.css +22 -0
  133. data/vendor/sass/test/sass/results/options.css +1 -0
  134. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  135. data/vendor/sass/test/sass/results/script.css +16 -0
  136. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  137. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  138. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  140. data/vendor/sass/test/sass/results/units.css +11 -0
  141. data/vendor/sass/test/sass/results/warn.css +0 -0
  142. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  143. data/vendor/sass/test/sass/script_conversion_test.rb +254 -0
  144. data/vendor/sass/test/sass/script_test.rb +470 -0
  145. data/vendor/sass/test/sass/scss/css_test.rb +897 -0
  146. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  147. data/vendor/sass/test/sass/scss/scss_test.rb +1088 -0
  148. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  149. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  150. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  151. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  152. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  153. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  154. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  155. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  156. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  157. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  158. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  159. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  160. data/vendor/sass/test/sass/templates/import.sass +12 -0
  161. data/vendor/sass/test/sass/templates/importee.less +2 -0
  162. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  163. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  164. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  165. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  166. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  167. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  168. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  169. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  170. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  171. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  172. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  173. data/vendor/sass/test/sass/templates/options.sass +2 -0
  174. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  175. data/vendor/sass/test/sass/templates/script.sass +101 -0
  176. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  177. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  178. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  179. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  180. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  181. data/vendor/sass/test/sass/templates/units.sass +11 -0
  182. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  183. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  184. data/vendor/sass/test/sass/test_helper.rb +8 -0
  185. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  186. data/vendor/sass/test/sass/util_test.rb +275 -0
  187. data/vendor/sass/test/test_helper.rb +64 -0
  188. data/vendor/sass/vendor/fssm/LICENSE +20 -0
  189. data/vendor/sass/vendor/fssm/README.markdown +55 -0
  190. data/vendor/sass/vendor/fssm/Rakefile +59 -0
  191. data/vendor/sass/vendor/fssm/VERSION.yml +5 -0
  192. data/vendor/sass/vendor/fssm/example.rb +9 -0
  193. data/vendor/sass/vendor/fssm/fssm.gemspec +77 -0
  194. data/vendor/sass/vendor/fssm/lib/fssm.rb +33 -0
  195. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  196. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  197. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  198. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  199. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +26 -0
  200. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +91 -0
  201. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +502 -0
  202. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  203. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +24 -0
  204. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +63 -0
  205. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +176 -0
  206. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +40 -0
  207. data/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  208. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +68 -0
  209. data/vendor/sass/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  210. data/vendor/sass/vendor/fssm/profile/prof.html +2379 -0
  211. data/vendor/sass/vendor/fssm/spec/path_spec.rb +75 -0
  212. data/vendor/sass/vendor/fssm/spec/root/duck/quack.txt +0 -0
  213. data/vendor/sass/vendor/fssm/spec/root/file.css +0 -0
  214. data/vendor/sass/vendor/fssm/spec/root/file.rb +0 -0
  215. data/vendor/sass/vendor/fssm/spec/root/file.yml +0 -0
  216. data/vendor/sass/vendor/fssm/spec/root/moo/cow.txt +0 -0
  217. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +14 -0
  218. data/vendor/sass/yard/callbacks.rb +29 -0
  219. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  220. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  221. data/vendor/sass/yard/inherited_hash.rb +41 -0
  222. metadata +219 -2
@@ -0,0 +1,112 @@
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 context in which this node was parsed,
12
+ # which determines how some operations are performed.
13
+ #
14
+ # Can be `:equals`, which means it's part of a `$var = val` or `prop = val` assignment,
15
+ # or `:default`, which means it's anywhere else
16
+ # (including `$var: val` and `prop: val` assignments,
17
+ # `#{}`-interpolations,
18
+ # and other script contexts such as `@if` conditions).
19
+ #
20
+ # @return [Symbol]
21
+ attr_reader :context
22
+
23
+ # The line of the document on which this node appeared.
24
+ #
25
+ # @return [Fixnum]
26
+ attr_accessor :line
27
+
28
+ # Sets the options hash for this node,
29
+ # as well as for all child nodes.
30
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
31
+ #
32
+ # @param options [{Symbol => Object}] The options
33
+ def options=(options)
34
+ @options = options
35
+ children.each {|c| c.options = options}
36
+ end
37
+
38
+ # Sets the context for this node,
39
+ # as well as for all child nodes.
40
+ #
41
+ # @param context [Symbol]
42
+ # @see #context
43
+ def context=(context)
44
+ @context = context
45
+ children.each {|c| c.context = context}
46
+ end
47
+
48
+ # Creates a new script node.
49
+ def initialize
50
+ @context = :default
51
+ end
52
+
53
+ # Evaluates the node.
54
+ #
55
+ # \{#perform} shouldn't be overridden directly;
56
+ # instead, override \{#\_perform}.
57
+ #
58
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
59
+ # @return [Literal] The SassScript object that is the value of the SassScript
60
+ def perform(environment)
61
+ _perform(environment)
62
+ rescue Sass::SyntaxError => e
63
+ e.modify_backtrace(:line => line)
64
+ raise e
65
+ end
66
+
67
+ # Returns all child nodes of this node.
68
+ #
69
+ # @return [Array<Node>]
70
+ def children
71
+ Sass::Util.abstract(self)
72
+ end
73
+
74
+ # Returns the text of this SassScript expression.
75
+ #
76
+ # @return [String]
77
+ def to_sass(opts = {})
78
+ Sass::Util.abstract(self)
79
+ end
80
+
81
+ protected
82
+
83
+ # Converts underscores to dashes if the :dasherize option is set.
84
+ def dasherize(s, opts)
85
+ if opts[:dasherize]
86
+ s.gsub(/_/,'-')
87
+ else
88
+ s
89
+ end
90
+ end
91
+
92
+ # Evaluates this node.
93
+ # Note that all {Literal} objects created within this method
94
+ # should have their \{#options} attribute set, probably via \{#opts}.
95
+ #
96
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
97
+ # @return [Literal] The SassScript object that is the value of the SassScript
98
+ # @see #perform
99
+ def _perform(environment)
100
+ Sass::Util.abstract(self)
101
+ end
102
+
103
+ # Sets the \{#options} field on the given literal and returns it
104
+ #
105
+ # @param literal [Literal]
106
+ # @return [Literal]
107
+ def opts(literal)
108
+ literal.options = options
109
+ literal
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,423 @@
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
+ # @param value [Numeric] The value of the number
45
+ # @param numerator_units [Array<String>] See \{#numerator\_units}
46
+ # @param denominator_units [Array<String>] See \{#denominator\_units}
47
+ def initialize(value, numerator_units = [], denominator_units = [])
48
+ super(value)
49
+ @numerator_units = numerator_units
50
+ @denominator_units = denominator_units
51
+ normalize!
52
+ end
53
+
54
+ # The SassScript `+` operation.
55
+ # Its functionality depends on the type of its argument:
56
+ #
57
+ # {Number}
58
+ # : Adds the two numbers together, converting units if possible.
59
+ #
60
+ # {Color}
61
+ # : Adds this number to each of the RGB color channels.
62
+ #
63
+ # {Literal}
64
+ # : See {Literal#plus}.
65
+ #
66
+ # @param other [Literal] The right-hand side of the operator
67
+ # @return [Literal] The result of the operation
68
+ # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
69
+ def plus(other)
70
+ if other.is_a? Number
71
+ operate(other, :+)
72
+ elsif other.is_a?(Color)
73
+ other.plus(self)
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ # The SassScript binary `-` operation (e.g. `$a - $b`).
80
+ # Its functionality depends on the type of its argument:
81
+ #
82
+ # {Number}
83
+ # : Subtracts this number from the other, converting units if possible.
84
+ #
85
+ # {Literal}
86
+ # : See {Literal#minus}.
87
+ #
88
+ # @param other [Literal] The right-hand side of the operator
89
+ # @return [Literal] The result of the operation
90
+ # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
91
+ def minus(other)
92
+ if other.is_a? Number
93
+ operate(other, :-)
94
+ else
95
+ super
96
+ end
97
+ end
98
+
99
+ # The SassScript unary `+` operation (e.g. `+$a`).
100
+ #
101
+ # @return [Number] The value of this number
102
+ def unary_plus
103
+ self
104
+ end
105
+
106
+ # The SassScript unary `-` operation (e.g. `-$a`).
107
+ #
108
+ # @return [Number] The negative value of this number
109
+ def unary_minus
110
+ Number.new(-value, numerator_units, denominator_units)
111
+ end
112
+
113
+ # The SassScript `*` operation.
114
+ # Its functionality depends on the type of its argument:
115
+ #
116
+ # {Number}
117
+ # : Multiplies the two numbers together, converting units appropriately.
118
+ #
119
+ # {Color}
120
+ # : Multiplies each of the RGB color channels by this number.
121
+ #
122
+ # @param other [Number, Color] The right-hand side of the operator
123
+ # @return [Number, Color] The result of the operation
124
+ # @raise [NoMethodError] if `other` is an invalid type
125
+ def times(other)
126
+ if other.is_a? Number
127
+ operate(other, :*)
128
+ elsif other.is_a? Color
129
+ other.times(self)
130
+ else
131
+ raise NoMethodError.new(nil, :times)
132
+ end
133
+ end
134
+
135
+ # The SassScript `/` operation.
136
+ # Its functionality depends on the type of its argument:
137
+ #
138
+ # {Number}
139
+ # : Divides this number by the other, converting units appropriately.
140
+ #
141
+ # {Literal}
142
+ # : See {Literal#div}.
143
+ #
144
+ # @param other [Literal] The right-hand side of the operator
145
+ # @return [Literal] The result of the operation
146
+ def div(other)
147
+ if other.is_a? Number
148
+ res = operate(other, :/)
149
+ if self.original && other.original && context != :equals
150
+ res.original = "#{self.original}/#{other.original}"
151
+ end
152
+ res
153
+ else
154
+ super
155
+ end
156
+ end
157
+
158
+ # The SassScript `%` operation.
159
+ #
160
+ # @param other [Number] The right-hand side of the operator
161
+ # @return [Number] This number modulo the other
162
+ # @raise [NoMethodError] if `other` is an invalid type
163
+ # @raise [Sass::UnitConversionError] if `other` has any units
164
+ def mod(other)
165
+ if other.is_a?(Number)
166
+ unless other.unitless?
167
+ raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.")
168
+ end
169
+ operate(other, :%)
170
+ else
171
+ raise NoMethodError.new(nil, :mod)
172
+ end
173
+ end
174
+
175
+ # The SassScript `==` operation.
176
+ #
177
+ # @param other [Literal] The right-hand side of the operator
178
+ # @return [Boolean] Whether this number is equal to the other object
179
+ def eq(other)
180
+ return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
181
+ this = self
182
+ begin
183
+ if unitless?
184
+ this = this.coerce(other.numerator_units, other.denominator_units)
185
+ else
186
+ other = other.coerce(numerator_units, denominator_units)
187
+ end
188
+ rescue Sass::UnitConversionError
189
+ return Sass::Script::Bool.new(false)
190
+ end
191
+
192
+ Sass::Script::Bool.new(this.value == other.value)
193
+ end
194
+
195
+ # The SassScript `>` operation.
196
+ #
197
+ # @param other [Number] The right-hand side of the operator
198
+ # @return [Boolean] Whether this number is greater than the other
199
+ # @raise [NoMethodError] if `other` is an invalid type
200
+ def gt(other)
201
+ raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
202
+ operate(other, :>)
203
+ end
204
+
205
+ # The SassScript `>=` operation.
206
+ #
207
+ # @param other [Number] The right-hand side of the operator
208
+ # @return [Boolean] Whether this number is greater than or equal to the other
209
+ # @raise [NoMethodError] if `other` is an invalid type
210
+ def gte(other)
211
+ raise NoMethodError.new(nil, :gte) unless other.is_a?(Number)
212
+ operate(other, :>=)
213
+ end
214
+
215
+ # The SassScript `<` operation.
216
+ #
217
+ # @param other [Number] The right-hand side of the operator
218
+ # @return [Boolean] Whether this number is less than the other
219
+ # @raise [NoMethodError] if `other` is an invalid type
220
+ def lt(other)
221
+ raise NoMethodError.new(nil, :lt) unless other.is_a?(Number)
222
+ operate(other, :<)
223
+ end
224
+
225
+ # The SassScript `<=` operation.
226
+ #
227
+ # @param other [Number] The right-hand side of the operator
228
+ # @return [Boolean] Whether this number is less than or equal to the other
229
+ # @raise [NoMethodError] if `other` is an invalid type
230
+ def lte(other)
231
+ raise NoMethodError.new(nil, :lte) unless other.is_a?(Number)
232
+ operate(other, :<=)
233
+ end
234
+
235
+ # @return [String] The CSS representation of this number
236
+ # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS
237
+ # (e.g. `px*in`)
238
+ def to_s
239
+ return original if original
240
+ raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
241
+ inspect
242
+ end
243
+
244
+ # Returns a readable representation of this number.
245
+ #
246
+ # This representation is valid CSS (and valid SassScript)
247
+ # as long as there is only one unit.
248
+ #
249
+ # @return [String] The representation
250
+ def inspect(opts = {})
251
+ "#{self.class.round(self.value)}#{unit_str}"
252
+ end
253
+ alias_method :to_sass, :inspect
254
+
255
+ # @return [Fixnum] The integer value of the number
256
+ # @raise [Sass::SyntaxError] if the number isn't an integer
257
+ def to_i
258
+ super unless int?
259
+ return value
260
+ end
261
+
262
+ # @return [Boolean] Whether or not this number is an integer.
263
+ def int?
264
+ value % 1 == 0.0
265
+ end
266
+
267
+ # @return [Boolean] Whether or not this number has no units.
268
+ def unitless?
269
+ numerator_units.empty? && denominator_units.empty?
270
+ end
271
+
272
+ # @return [Boolean] Whether or not this number has units that can be represented in CSS
273
+ # (that is, zero or one \{#numerator\_units}).
274
+ def legal_units?
275
+ (numerator_units.empty? || numerator_units.size == 1) && denominator_units.empty?
276
+ end
277
+
278
+ # Returns this number converted to other units.
279
+ # The conversion takes into account the relationship between e.g. mm and cm,
280
+ # as well as between e.g. in and cm.
281
+ #
282
+ # If this number has no units, it will simply return itself
283
+ # with the given units.
284
+ #
285
+ # An incompatible coercion, e.g. between px and cm, will raise an error.
286
+ #
287
+ # @param num_units [Array<String>] The numerator units to coerce this number into.
288
+ # See {\#numerator\_units}
289
+ # @param den_units [Array<String>] The denominator units to coerce this number into.
290
+ # See {\#denominator\_units}
291
+ # @return [Number] The number with the new units
292
+ # @raise [Sass::UnitConversionError] if the given units are incompatible with the number's
293
+ # current units
294
+ def coerce(num_units, den_units)
295
+ Number.new(if unitless?
296
+ self.value
297
+ else
298
+ self.value * coercion_factor(self.numerator_units, num_units) /
299
+ coercion_factor(self.denominator_units, den_units)
300
+ end, num_units, den_units)
301
+ end
302
+
303
+ # @param other [Number] A number to decide if it can be compared with this number.
304
+ # @return [Boolean] Whether or not this number can be compared with the other.
305
+ def comparable_to?(other)
306
+ begin
307
+ operate(other, :+)
308
+ true
309
+ rescue Sass::UnitConversionError
310
+ false
311
+ end
312
+ end
313
+
314
+ # Returns a human readable representation of the units in this number.
315
+ # For complex units this takes the form of:
316
+ # numerator_unit1 * numerator_unit2 / denominator_unit1 * denominator_unit2
317
+ # @return [String] a string that represents the units in this number
318
+ def unit_str
319
+ rv = numerator_units.sort.join("*")
320
+ if denominator_units.any?
321
+ rv << "/"
322
+ rv << denominator_units.sort.join("*")
323
+ end
324
+ rv
325
+ end
326
+
327
+ private
328
+
329
+ # @private
330
+ def self.round(num)
331
+ if num.is_a?(Float) && (num.infinite? || num.nan?)
332
+ num
333
+ elsif num % 1 == 0.0
334
+ num.to_i
335
+ else
336
+ (num * PRECISION).round / PRECISION
337
+ end
338
+ end
339
+
340
+ def operate(other, operation)
341
+ this = self
342
+ if [:+, :-, :<=, :<, :>, :>=].include?(operation)
343
+ if unitless?
344
+ this = this.coerce(other.numerator_units, other.denominator_units)
345
+ else
346
+ other = other.coerce(numerator_units, denominator_units)
347
+ end
348
+ end
349
+ # avoid integer division
350
+ value = (:/ == operation) ? this.value.to_f : this.value
351
+ result = value.send(operation, other.value)
352
+
353
+ if result.is_a?(Numeric)
354
+ Number.new(result, *compute_units(this, other, operation))
355
+ else # Boolean op
356
+ Bool.new(result)
357
+ end
358
+ end
359
+
360
+ def coercion_factor(from_units, to_units)
361
+ # get a list of unmatched units
362
+ from_units, to_units = sans_common_units(from_units, to_units)
363
+
364
+ if from_units.size != to_units.size || !convertable?(from_units | to_units)
365
+ raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
366
+ end
367
+
368
+ from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
369
+ end
370
+
371
+ def compute_units(this, other, operation)
372
+ case operation
373
+ when :*
374
+ [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
375
+ when :/
376
+ [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
377
+ else
378
+ [this.numerator_units, this.denominator_units]
379
+ end
380
+ end
381
+
382
+ def normalize!
383
+ return if unitless?
384
+ @numerator_units, @denominator_units = sans_common_units(numerator_units, denominator_units)
385
+
386
+ @denominator_units.each_with_index do |d, i|
387
+ if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
388
+ @value /= conversion_factor(d, u)
389
+ @denominator_units.delete_at(i)
390
+ @numerator_units.delete_at(@numerator_units.index(u))
391
+ end
392
+ end
393
+ end
394
+
395
+ # A hash of unit names to their index in the conversion table
396
+ CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
397
+ CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
398
+ [ nil, 1, 2.36220473, 10, 28.3464567], # cm
399
+ [ nil, nil, 1, 4.23333333, 12 ], # pc
400
+ [ nil, nil, nil, 1, 2.83464567], # mm
401
+ [ nil, nil, nil, nil, 1 ]] # pt
402
+
403
+ def conversion_factor(from_unit, to_unit)
404
+ res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
405
+ return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
406
+ res
407
+ end
408
+
409
+ def convertable?(units)
410
+ Array(units).all?(&CONVERTABLE_UNITS.method(:include?))
411
+ end
412
+
413
+ def sans_common_units(units1, units2)
414
+ units2 = units2.dup
415
+ # Can't just use -, because we want px*px to coerce properly to px*mm
416
+ return units1.map do |u|
417
+ next u unless j = units2.index(u)
418
+ units2.delete_at(j)
419
+ nil
420
+ end.compact, units2
421
+ end
422
+ end
423
+ end