sass 3.1.0 → 3.3.0

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 (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -1,6 +1,4 @@
1
- require 'sass/script/literal'
2
-
3
- module Sass::Script
1
+ module Sass::Script::Value
4
2
  # A SassScript object representing a number.
5
3
  # SassScript numbers can have decimal values,
6
4
  # and can also have units.
@@ -9,7 +7,7 @@ module Sass::Script
9
7
  #
10
8
  # Numbers can also have more complex units, such as `1px*em/in`.
11
9
  # These cannot be inputted directly in Sass code at the moment.
12
- class Number < Literal
10
+ class Number < Base
13
11
  # The Ruby value of the number.
14
12
  #
15
13
  # @return [Numeric]
@@ -17,7 +15,7 @@ module Sass::Script
17
15
 
18
16
  # A list of units in the numerator of the number.
19
17
  # For example, `1px*em/in*cm` would return `["px", "em"]`
20
- # @return [Array<String>]
18
+ # @return [Array<String>]
21
19
  attr_reader :numerator_units
22
20
 
23
21
  # A list of units in the denominator of the number.
@@ -35,19 +33,33 @@ module Sass::Script
35
33
  # @return [Boolean, nil]
36
34
  attr_accessor :original
37
35
 
38
- # The precision with which numbers will be printed to CSS files.
39
- # For example, if this is `1000.0`,
36
+ def self.precision
37
+ @precision ||= 5
38
+ end
39
+
40
+ # Sets the number of digits of precision
41
+ # For example, if this is `3`,
40
42
  # `3.1415926` will be printed as `3.142`.
41
- # @api public
42
- PRECISION = 1000.0
43
+ def self.precision=(digits)
44
+ @precision = digits.round
45
+ @precision_factor = 10.0**@precision
46
+ end
47
+
48
+ # the precision factor used in numeric output
49
+ # it is derived from the `precision` method.
50
+ def self.precision_factor
51
+ @precision_factor ||= 10.0**precision
52
+ end
43
53
 
44
54
  # Used so we don't allocate two new arrays for each new number.
45
55
  NO_UNITS = []
46
56
 
47
57
  # @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}
58
+ # @param numerator_units [::String, Array<::String>] See \{#numerator\_units}
59
+ # @param denominator_units [::String, Array<::String>] See \{#denominator\_units}
50
60
  def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
61
+ numerator_units = [numerator_units] if numerator_units.is_a?(::String)
62
+ denominator_units = [denominator_units] if denominator_units.is_a?(::String)
51
63
  super(value)
52
64
  @numerator_units = numerator_units
53
65
  @denominator_units = denominator_units
@@ -63,11 +75,11 @@ module Sass::Script
63
75
  # {Color}
64
76
  # : Adds this number to each of the RGB color channels.
65
77
  #
66
- # {Literal}
67
- # : See {Literal#plus}.
78
+ # {Value}
79
+ # : See {Value::Base#plus}.
68
80
  #
69
- # @param other [Literal] The right-hand side of the operator
70
- # @return [Literal] The result of the operation
81
+ # @param other [Value] The right-hand side of the operator
82
+ # @return [Value] The result of the operation
71
83
  # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
72
84
  def plus(other)
73
85
  if other.is_a? Number
@@ -85,11 +97,11 @@ module Sass::Script
85
97
  # {Number}
86
98
  # : Subtracts this number from the other, converting units if possible.
87
99
  #
88
- # {Literal}
89
- # : See {Literal#minus}.
100
+ # {Value}
101
+ # : See {Value::Base#minus}.
90
102
  #
91
- # @param other [Literal] The right-hand side of the operator
92
- # @return [Literal] The result of the operation
103
+ # @param other [Value] The right-hand side of the operator
104
+ # @return [Value] The result of the operation
93
105
  # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
94
106
  def minus(other)
95
107
  if other.is_a? Number
@@ -141,16 +153,16 @@ module Sass::Script
141
153
  # {Number}
142
154
  # : Divides this number by the other, converting units appropriately.
143
155
  #
144
- # {Literal}
145
- # : See {Literal#div}.
156
+ # {Value}
157
+ # : See {Value::Base#div}.
146
158
  #
147
- # @param other [Literal] The right-hand side of the operator
148
- # @return [Literal] The result of the operation
159
+ # @param other [Value] The right-hand side of the operator
160
+ # @return [Value] The result of the operation
149
161
  def div(other)
150
162
  if other.is_a? Number
151
163
  res = operate(other, :/)
152
- if self.original && other.original
153
- res.original = "#{self.original}/#{other.original}"
164
+ if original && other.original
165
+ res.original = "#{original}/#{other.original}"
154
166
  end
155
167
  res
156
168
  else
@@ -163,12 +175,9 @@ module Sass::Script
163
175
  # @param other [Number] The right-hand side of the operator
164
176
  # @return [Number] This number modulo the other
165
177
  # @raise [NoMethodError] if `other` is an invalid type
166
- # @raise [Sass::UnitConversionError] if `other` has any units
178
+ # @raise [Sass::UnitConversionError] if `other` has incompatible units
167
179
  def mod(other)
168
180
  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
181
  operate(other, :%)
173
182
  else
174
183
  raise NoMethodError.new(nil, :mod)
@@ -177,10 +186,10 @@ module Sass::Script
177
186
 
178
187
  # The SassScript `==` operation.
179
188
  #
180
- # @param other [Literal] The right-hand side of the operator
189
+ # @param other [Value] The right-hand side of the operator
181
190
  # @return [Boolean] Whether this number is equal to the other object
182
191
  def eq(other)
183
- return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
192
+ return Bool::FALSE unless other.is_a?(Sass::Script::Value::Number)
184
193
  this = self
185
194
  begin
186
195
  if unitless?
@@ -189,10 +198,21 @@ module Sass::Script
189
198
  other = other.coerce(@numerator_units, @denominator_units)
190
199
  end
191
200
  rescue Sass::UnitConversionError
192
- return Sass::Script::Bool.new(false)
201
+ return Bool::FALSE
193
202
  end
203
+ Bool.new(this.value == other.value)
204
+ end
205
+
206
+ def hash
207
+ [value, numerator_units, denominator_units].hash
208
+ end
194
209
 
195
- Sass::Script::Bool.new(this.value == other.value)
210
+ # Hash-equality works differently than `==` equality for numbers.
211
+ # Hash-equality must be transitive, so it just compares the exact value,
212
+ # numerator units, and denominator units.
213
+ def eql?(other)
214
+ value == other.value && numerator_units == other.numerator_units &&
215
+ denominator_units == other.denominator_units
196
216
  end
197
217
 
198
218
  # The SassScript `>` operation.
@@ -252,7 +272,14 @@ module Sass::Script
252
272
  # @return [String] The representation
253
273
  def inspect(opts = {})
254
274
  value = self.class.round(self.value)
255
- unitless? ? value.to_s : "#{value}#{unit_str}"
275
+ str = value.to_s
276
+
277
+ # Ruby will occasionally print in scientific notation if the number is
278
+ # small enough. That's technically valid CSS, but it's not well-supported
279
+ # and confusing.
280
+ str = ("%0.#{self.class.precision}f" % value).gsub(/0*$/, '') if str.include?('e')
281
+
282
+ unitless? ? str : "#{str}#{unit_str}"
256
283
  end
257
284
  alias_method :to_sass, :inspect
258
285
 
@@ -260,7 +287,7 @@ module Sass::Script
260
287
  # @raise [Sass::SyntaxError] if the number isn't an integer
261
288
  def to_i
262
289
  super unless int?
263
- return value
290
+ value
264
291
  end
265
292
 
266
293
  # @return [Boolean] Whether or not this number is an integer.
@@ -273,6 +300,24 @@ module Sass::Script
273
300
  @numerator_units.empty? && @denominator_units.empty?
274
301
  end
275
302
 
303
+ # Checks whether the number has the numerator unit specified.
304
+ #
305
+ # @example
306
+ # number = Sass::Script::Value::Number.new(10, "px")
307
+ # number.is_unit?("px") => true
308
+ # number.is_unit?(nil) => false
309
+ #
310
+ # @param unit [::String, nil] The unit the number should have or nil if the number
311
+ # should be unitless.
312
+ # @see Number#unitless? The unitless? method may be more readable.
313
+ def is_unit?(unit)
314
+ if unit
315
+ denominator_units.size == 0 && numerator_units.size == 1 && numerator_units.first == unit
316
+ else
317
+ unitless?
318
+ end
319
+ end
320
+
276
321
  # @return [Boolean] Whether or not this number has units that can be represented in CSS
277
322
  # (that is, zero or one \{#numerator\_units}).
278
323
  def legal_units?
@@ -297,9 +342,9 @@ module Sass::Script
297
342
  # current units
298
343
  def coerce(num_units, den_units)
299
344
  Number.new(if unitless?
300
- self.value
345
+ value
301
346
  else
302
- self.value * coercion_factor(@numerator_units, num_units) /
347
+ value * coercion_factor(@numerator_units, num_units) /
303
348
  coercion_factor(@denominator_units, den_units)
304
349
  end, num_units, den_units)
305
350
  end
@@ -307,12 +352,10 @@ module Sass::Script
307
352
  # @param other [Number] A number to decide if it can be compared with this number.
308
353
  # @return [Boolean] Whether or not this number can be compared with the other.
309
354
  def comparable_to?(other)
310
- begin
311
- operate(other, :+)
312
- true
313
- rescue Sass::UnitConversionError
314
- false
315
- end
355
+ operate(other, :+)
356
+ true
357
+ rescue Sass::UnitConversionError
358
+ false
316
359
  end
317
360
 
318
361
  # Returns a human readable representation of the units in this number.
@@ -337,11 +380,11 @@ module Sass::Script
337
380
  elsif num % 1 == 0.0
338
381
  num.to_i
339
382
  else
340
- (num * PRECISION).round / PRECISION
383
+ ((num * precision_factor).round / precision_factor).to_f
341
384
  end
342
385
  end
343
386
 
344
- OPERATIONS = [:+, :-, :<=, :<, :>, :>=]
387
+ OPERATIONS = [:+, :-, :<=, :<, :>, :>=, :%]
345
388
 
346
389
  def operate(other, operation)
347
390
  this = self
@@ -353,7 +396,7 @@ module Sass::Script
353
396
  end
354
397
  end
355
398
  # avoid integer division
356
- value = (:/ == operation) ? this.value.to_f : this.value
399
+ value = :/ == operation ? this.value.to_f : this.value
357
400
  result = value.send(operation, other.value)
358
401
 
359
402
  if result.is_a?(Numeric)
@@ -368,29 +411,33 @@ module Sass::Script
368
411
  from_units, to_units = sans_common_units(from_units, to_units)
369
412
 
370
413
  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('*')}'.")
414
+ raise Sass::UnitConversionError.new(
415
+ "Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
372
416
  end
373
417
 
374
- from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
418
+ from_units.zip(to_units).inject(1) {|m, p| m * conversion_factor(p[0], p[1])}
375
419
  end
376
420
 
377
421
  def compute_units(this, other, operation)
378
422
  case operation
379
423
  when :*
380
- [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
424
+ [this.numerator_units + other.numerator_units,
425
+ this.denominator_units + other.denominator_units]
381
426
  when :/
382
- [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
383
- else
427
+ [this.numerator_units + other.denominator_units,
428
+ this.denominator_units + other.numerator_units]
429
+ else
384
430
  [this.numerator_units, this.denominator_units]
385
431
  end
386
432
  end
387
433
 
388
434
  def normalize!
389
435
  return if unitless?
390
- @numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units)
436
+ @numerator_units, @denominator_units =
437
+ sans_common_units(@numerator_units, @denominator_units)
391
438
 
392
439
  @denominator_units.each_with_index do |d, i|
393
- if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
440
+ if convertable?(d) && (u = @numerator_units.find(&method(:convertable?)))
394
441
  @value /= conversion_factor(d, u)
395
442
  @denominator_units.delete_at(i)
396
443
  @numerator_units.delete_at(@numerator_units.index(u))
@@ -399,12 +446,15 @@ module Sass::Script
399
446
  end
400
447
 
401
448
  # 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
449
+ CONVERTABLE_UNITS = %w(in cm pc mm pt px).inject({}) {|m, v| m[v] = m.size; m}
450
+
451
+ # in cm pc mm pt px
452
+ CONVERSION_TABLE = [[1, 2.54, 6, 25.4, 72 , 96], # in
453
+ [nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
454
+ [nil, nil, 1, 4.23333333, 12 , 16], # pc
455
+ [nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
456
+ [nil, nil, nil, nil, 1 , 1.3333333333], # pt
457
+ [nil, nil, nil, nil, nil , 1]] # px
408
458
 
409
459
  def conversion_factor(from_unit, to_unit)
410
460
  res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
@@ -419,11 +469,14 @@ module Sass::Script
419
469
  def sans_common_units(units1, units2)
420
470
  units2 = units2.dup
421
471
  # 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)
472
+ units1 = units1.map do |u|
473
+ j = units2.index(u)
474
+ next u unless j
424
475
  units2.delete_at(j)
425
476
  nil
426
- end.compact, units2
477
+ end
478
+ units1.compact!
479
+ return units1, units2
427
480
  end
428
481
  end
429
482
  end
@@ -1,8 +1,6 @@
1
- require 'sass/script/literal'
2
-
3
- module Sass::Script
1
+ module Sass::Script::Value
4
2
  # A SassScript object representing a CSS string *or* a CSS identifier.
5
- class String < Literal
3
+ class String < Base
6
4
  # The Ruby value of the string.
7
5
  #
8
6
  # @return [String]
@@ -24,26 +22,26 @@ module Sass::Script
24
22
  @type = type
25
23
  end
26
24
 
27
- # @see Literal#plus
25
+ # @see Value#plus
28
26
  def plus(other)
29
- other_str = other.is_a?(Sass::Script::String) ? other.value : other.to_s
30
- Sass::Script::String.new(self.value + other_str, self.type)
27
+ other_str = other.is_a?(Sass::Script::Value::String) ? other.value : other.to_s
28
+ Sass::Script::Value::String.new(value + other_str, type)
31
29
  end
32
30
 
33
- # @see Node#to_s
31
+ # @see Value#to_s
34
32
  def to_s(opts = {})
35
33
  if @type == :identifier
36
- return @value.tr("\n", " ")
34
+ return @value.gsub(/\n\s*/, " ")
37
35
  end
38
36
 
39
37
  return "\"#{value.gsub('"', "\\\"")}\"" if opts[:quote] == %q{"}
40
38
  return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'}
41
39
  return "\"#{value}\"" unless value.include?('"')
42
40
  return "'#{value}'" unless value.include?("'")
43
- "\"#{value.gsub('"', "\\\"")}\"" #'
41
+ "\"#{value.gsub('"', "\\\"")}\"" # '
44
42
  end
45
43
 
46
- # @see Node#to_sass
44
+ # @see Value#to_sass
47
45
  def to_sass(opts = {})
48
46
  to_s
49
47
  end
@@ -0,0 +1,12 @@
1
+ module Sass::Script::Value; end
2
+
3
+ require 'sass/script/value/base'
4
+ require 'sass/script/value/string'
5
+ require 'sass/script/value/number'
6
+ require 'sass/script/value/color'
7
+ require 'sass/script/value/bool'
8
+ require 'sass/script/value/deprecated_false'
9
+ require 'sass/script/value/null'
10
+ require 'sass/script/value/list'
11
+ require 'sass/script/value/arg_list'
12
+ require 'sass/script/value/map'
data/lib/sass/script.rb CHANGED
@@ -1,10 +1,4 @@
1
- require 'strscan'
2
- require 'sass/script/node'
3
- require 'sass/script/variable'
4
- require 'sass/script/funcall'
5
- require 'sass/script/operation'
6
- require 'sass/script/literal'
7
- require 'sass/script/parser'
1
+ require 'sass/scss/rx'
8
2
 
9
3
  module Sass
10
4
  # SassScript is code that's embedded in Sass documents
@@ -13,7 +7,8 @@ module Sass
13
7
  # This module contains code that handles the parsing and evaluation of SassScript.
14
8
  module Script
15
9
  # The regular expression used to parse variables.
16
- MATCH = /^\$(#{Sass::SCSS::RX::IDENT})\s*:\s*(.+?)(!(?i:default))?$/
10
+ MATCH = /^\$(#{Sass::SCSS::RX::IDENT})\s*:\s*(.+?)
11
+ (!#{Sass::SCSS::RX::IDENT}(?:\s+!#{Sass::SCSS::RX::IDENT})*)?$/x
17
12
 
18
13
  # The regular expression used to validate variables without matching.
19
14
  VALIDATE = /^\$#{Sass::SCSS::RX::IDENT}$/
@@ -27,7 +22,7 @@ module Sass
27
22
  # Used for error reporting
28
23
  # @param options [{Symbol => Object}] An options hash;
29
24
  # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
30
- # @return [Script::Node] The root node of the parse tree
25
+ # @return [Script::Tree::Node] The root node of the parse tree
31
26
  def self.parse(value, line, offset, options = {})
32
27
  Parser.parse(value, line, offset, options)
33
28
  rescue Sass::SyntaxError => e
@@ -36,5 +31,36 @@ module Sass
36
31
  raise e
37
32
  end
38
33
 
34
+ require 'sass/script/functions'
35
+ require 'sass/script/parser'
36
+ require 'sass/script/tree'
37
+ require 'sass/script/value'
38
+
39
+ # @private
40
+ CONST_RENAMES = {
41
+ :Literal => Sass::Script::Value::Base,
42
+ :ArgList => Sass::Script::Value::ArgList,
43
+ :Bool => Sass::Script::Value::Bool,
44
+ :Color => Sass::Script::Value::Color,
45
+ :List => Sass::Script::Value::List,
46
+ :Null => Sass::Script::Value::Null,
47
+ :Number => Sass::Script::Value::Number,
48
+ :String => Sass::Script::Value::String,
49
+ :Node => Sass::Script::Tree::Node,
50
+ :Funcall => Sass::Script::Tree::Funcall,
51
+ :Interpolation => Sass::Script::Tree::Interpolation,
52
+ :Operation => Sass::Script::Tree::Operation,
53
+ :StringInterpolation => Sass::Script::Tree::StringInterpolation,
54
+ :UnaryOperation => Sass::Script::Tree::UnaryOperation,
55
+ :Variable => Sass::Script::Tree::Variable,
56
+ }
57
+
58
+ # @private
59
+ def self.const_missing(name)
60
+ klass = CONST_RENAMES[name]
61
+ super unless klass
62
+ CONST_RENAMES.each {|n, k| const_set(n, k)}
63
+ klass
64
+ end
39
65
  end
40
66
  end
@@ -7,21 +7,11 @@ module Sass
7
7
  # parent references, nested selectors, and so forth.
8
8
  # It does support all the same CSS hacks as the SCSS parser, though.
9
9
  class CssParser < StaticParser
10
- # Parse a selector, and return its value as a string.
11
- #
12
- # @return [String, nil] The parsed selector, or nil if no selector was parsed
13
- # @raise [Sass::SyntaxError] if there's a syntax error in the selector
14
- def parse_selector_string
15
- init_scanner!
16
- str {return unless selector}
17
- end
18
-
19
10
  private
20
11
 
12
+ def placeholder_selector; nil; end
21
13
  def parent_selector; nil; end
22
14
  def interpolation; nil; end
23
- def interp_string; tok(STRING); end
24
- def interp_ident(ident = IDENT); tok(ident); end
25
15
  def use_css_import?; true; end
26
16
 
27
17
  def block_child(context)
@@ -36,7 +26,7 @@ module Sass
36
26
  end
37
27
 
38
28
  def nested_properties!(node, space)
39
- expected('expression (e.g. 1px, bold)');
29
+ expected('expression (e.g. 1px, bold)')
40
30
  end
41
31
 
42
32
  @sass_script_parser = Class.new(Sass::Script::CssParser)