oreorenasass 3.4.4 → 3.4.5

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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +50 -70
  4. data/Rakefile +5 -26
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +12 -19
  10. data/lib/sass/cache_stores/base.rb +2 -2
  11. data/lib/sass/cache_stores/chain.rb +1 -2
  12. data/lib/sass/cache_stores/filesystem.rb +5 -1
  13. data/lib/sass/cache_stores/memory.rb +1 -1
  14. data/lib/sass/cache_stores/null.rb +2 -2
  15. data/lib/sass/callbacks.rb +0 -1
  16. data/lib/sass/css.rb +13 -11
  17. data/lib/sass/engine.rb +173 -424
  18. data/lib/sass/environment.rb +58 -148
  19. data/lib/sass/error.rb +14 -11
  20. data/lib/sass/exec.rb +703 -5
  21. data/lib/sass/importers/base.rb +6 -49
  22. data/lib/sass/importers/filesystem.rb +19 -44
  23. data/lib/sass/logger.rb +4 -1
  24. data/lib/sass/logger/base.rb +4 -2
  25. data/lib/sass/logger/log_level.rb +7 -3
  26. data/lib/sass/media.rb +23 -20
  27. data/lib/sass/plugin.rb +7 -7
  28. data/lib/sass/plugin/compiler.rb +145 -304
  29. data/lib/sass/plugin/configuration.rb +23 -18
  30. data/lib/sass/plugin/merb.rb +1 -1
  31. data/lib/sass/plugin/staleness_checker.rb +3 -3
  32. data/lib/sass/repl.rb +3 -3
  33. data/lib/sass/script.rb +8 -35
  34. data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
  35. data/lib/sass/script/bool.rb +18 -0
  36. data/lib/sass/script/color.rb +606 -0
  37. data/lib/sass/script/css_lexer.rb +4 -8
  38. data/lib/sass/script/css_parser.rb +2 -5
  39. data/lib/sass/script/funcall.rb +245 -0
  40. data/lib/sass/script/functions.rb +408 -1491
  41. data/lib/sass/script/interpolation.rb +79 -0
  42. data/lib/sass/script/lexer.rb +68 -172
  43. data/lib/sass/script/list.rb +85 -0
  44. data/lib/sass/script/literal.rb +221 -0
  45. data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
  46. data/lib/sass/script/{value/null.rb → null.rb} +7 -14
  47. data/lib/sass/script/{value/number.rb → number.rb} +75 -152
  48. data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
  49. data/lib/sass/script/parser.rb +110 -245
  50. data/lib/sass/script/string.rb +51 -0
  51. data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
  52. data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
  53. data/lib/sass/script/variable.rb +58 -0
  54. data/lib/sass/scss/css_parser.rb +3 -9
  55. data/lib/sass/scss/parser.rb +421 -450
  56. data/lib/sass/scss/rx.rb +11 -19
  57. data/lib/sass/scss/static_parser.rb +7 -321
  58. data/lib/sass/selector.rb +194 -68
  59. data/lib/sass/selector/abstract_sequence.rb +14 -29
  60. data/lib/sass/selector/comma_sequence.rb +25 -108
  61. data/lib/sass/selector/sequence.rb +66 -159
  62. data/lib/sass/selector/simple.rb +25 -23
  63. data/lib/sass/selector/simple_sequence.rb +63 -173
  64. data/lib/sass/shared.rb +1 -1
  65. data/lib/sass/supports.rb +15 -13
  66. data/lib/sass/tree/charset_node.rb +1 -1
  67. data/lib/sass/tree/comment_node.rb +3 -3
  68. data/lib/sass/tree/css_import_node.rb +11 -11
  69. data/lib/sass/tree/debug_node.rb +2 -2
  70. data/lib/sass/tree/directive_node.rb +4 -21
  71. data/lib/sass/tree/each_node.rb +8 -8
  72. data/lib/sass/tree/extend_node.rb +7 -14
  73. data/lib/sass/tree/for_node.rb +4 -4
  74. data/lib/sass/tree/function_node.rb +4 -9
  75. data/lib/sass/tree/if_node.rb +1 -1
  76. data/lib/sass/tree/import_node.rb +5 -4
  77. data/lib/sass/tree/media_node.rb +14 -4
  78. data/lib/sass/tree/mixin_def_node.rb +4 -4
  79. data/lib/sass/tree/mixin_node.rb +8 -21
  80. data/lib/sass/tree/node.rb +12 -54
  81. data/lib/sass/tree/prop_node.rb +20 -39
  82. data/lib/sass/tree/return_node.rb +2 -3
  83. data/lib/sass/tree/root_node.rb +3 -19
  84. data/lib/sass/tree/rule_node.rb +22 -35
  85. data/lib/sass/tree/supports_node.rb +13 -0
  86. data/lib/sass/tree/trace_node.rb +1 -2
  87. data/lib/sass/tree/variable_node.rb +3 -9
  88. data/lib/sass/tree/visitors/base.rb +8 -5
  89. data/lib/sass/tree/visitors/check_nesting.rb +19 -49
  90. data/lib/sass/tree/visitors/convert.rb +56 -74
  91. data/lib/sass/tree/visitors/cssize.rb +74 -202
  92. data/lib/sass/tree/visitors/deep_copy.rb +5 -10
  93. data/lib/sass/tree/visitors/extend.rb +7 -7
  94. data/lib/sass/tree/visitors/perform.rb +185 -278
  95. data/lib/sass/tree/visitors/set_options.rb +6 -20
  96. data/lib/sass/tree/visitors/to_css.rb +81 -234
  97. data/lib/sass/tree/warn_node.rb +2 -2
  98. data/lib/sass/tree/while_node.rb +2 -2
  99. data/lib/sass/util.rb +152 -522
  100. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  101. data/lib/sass/util/subset_map.rb +3 -4
  102. data/lib/sass/util/test.rb +1 -0
  103. data/lib/sass/version.rb +22 -20
  104. data/test/Gemfile +3 -0
  105. data/test/Gemfile.lock +10 -0
  106. data/test/sass/cache_test.rb +20 -62
  107. data/test/sass/callbacks_test.rb +1 -1
  108. data/test/sass/conversion_test.rb +2 -296
  109. data/test/sass/css2sass_test.rb +4 -23
  110. data/test/sass/engine_test.rb +354 -411
  111. data/test/sass/exec_test.rb +2 -2
  112. data/test/sass/extend_test.rb +145 -324
  113. data/test/sass/functions_test.rb +86 -873
  114. data/test/sass/importer_test.rb +21 -241
  115. data/test/sass/logger_test.rb +1 -1
  116. data/test/sass/more_results/more_import.css +1 -1
  117. data/test/sass/plugin_test.rb +26 -16
  118. data/test/sass/results/compact.css +1 -1
  119. data/test/sass/results/complex.css +4 -4
  120. data/test/sass/results/expanded.css +1 -1
  121. data/test/sass/results/import.css +1 -1
  122. data/test/sass/results/import_charset_ibm866.css +2 -2
  123. data/test/sass/results/mixins.css +17 -17
  124. data/test/sass/results/nested.css +1 -1
  125. data/test/sass/results/parent_ref.css +2 -2
  126. data/test/sass/results/script.css +3 -3
  127. data/test/sass/results/scss_import.css +1 -1
  128. data/test/sass/script_conversion_test.rb +7 -36
  129. data/test/sass/script_test.rb +53 -485
  130. data/test/sass/scss/css_test.rb +28 -143
  131. data/test/sass/scss/rx_test.rb +4 -4
  132. data/test/sass/scss/scss_test.rb +325 -2119
  133. data/test/sass/templates/scss_import.scss +1 -2
  134. data/test/sass/test_helper.rb +1 -1
  135. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  136. data/test/sass/util/subset_map_test.rb +2 -2
  137. data/test/sass/util_test.rb +1 -86
  138. data/test/test_helper.rb +8 -37
  139. metadata +19 -66
  140. data/lib/sass/exec/base.rb +0 -187
  141. data/lib/sass/exec/sass_convert.rb +0 -264
  142. data/lib/sass/exec/sass_scss.rb +0 -424
  143. data/lib/sass/features.rb +0 -47
  144. data/lib/sass/script/tree.rb +0 -16
  145. data/lib/sass/script/tree/funcall.rb +0 -306
  146. data/lib/sass/script/tree/interpolation.rb +0 -118
  147. data/lib/sass/script/tree/list_literal.rb +0 -77
  148. data/lib/sass/script/tree/literal.rb +0 -45
  149. data/lib/sass/script/tree/map_literal.rb +0 -64
  150. data/lib/sass/script/tree/selector.rb +0 -26
  151. data/lib/sass/script/tree/variable.rb +0 -57
  152. data/lib/sass/script/value.rb +0 -11
  153. data/lib/sass/script/value/base.rb +0 -240
  154. data/lib/sass/script/value/bool.rb +0 -35
  155. data/lib/sass/script/value/color.rb +0 -680
  156. data/lib/sass/script/value/helpers.rb +0 -262
  157. data/lib/sass/script/value/list.rb +0 -113
  158. data/lib/sass/script/value/map.rb +0 -70
  159. data/lib/sass/script/value/string.rb +0 -97
  160. data/lib/sass/selector/pseudo.rb +0 -256
  161. data/lib/sass/source/map.rb +0 -210
  162. data/lib/sass/source/position.rb +0 -39
  163. data/lib/sass/source/range.rb +0 -41
  164. data/lib/sass/stack.rb +0 -120
  165. data/lib/sass/tree/at_root_node.rb +0 -83
  166. data/lib/sass/tree/error_node.rb +0 -18
  167. data/lib/sass/tree/keyframe_rule_node.rb +0 -15
  168. data/lib/sass/util/cross_platform_random.rb +0 -19
  169. data/lib/sass/util/normalized_map.rb +0 -130
  170. data/lib/sass/util/ordered_hash.rb +0 -192
  171. data/test/sass/compiler_test.rb +0 -232
  172. data/test/sass/encoding_test.rb +0 -219
  173. data/test/sass/source_map_test.rb +0 -977
  174. data/test/sass/superselector_test.rb +0 -191
  175. data/test/sass/util/normalized_map_test.rb +0 -51
  176. data/test/sass/value_helpers_test.rb +0 -179
@@ -1,35 +0,0 @@
1
- module Sass::Script::Value
2
- # A SassScript object representing a boolean (true or false) value.
3
- class Bool < Base
4
- # The true value in SassScript.
5
- #
6
- # This is assigned before new is overridden below so that we use the default implementation.
7
- TRUE = new(true)
8
-
9
- # The false value in SassScript.
10
- #
11
- # This is assigned before new is overridden below so that we use the default implementation.
12
- FALSE = new(false)
13
-
14
- # We override object creation so that users of the core API
15
- # will not need to know that booleans are specific constants.
16
- #
17
- # @param value A ruby value that will be tested for truthiness.
18
- # @return [Bool] TRUE if value is truthy, FALSE if value is falsey
19
- def self.new(value)
20
- value ? TRUE : FALSE
21
- end
22
-
23
- # The Ruby value of the boolean.
24
- #
25
- # @return [Boolean]
26
- attr_reader :value
27
- alias_method :to_bool, :value
28
-
29
- # @return [String] "true" or "false"
30
- def to_s(opts = {})
31
- @value.to_s
32
- end
33
- alias_method :to_sass, :to_s
34
- end
35
- end
@@ -1,680 +0,0 @@
1
- module Sass::Script::Value
2
- # A SassScript object representing a CSS color.
3
- #
4
- # A color may be represented internally as RGBA, HSLA, or both.
5
- # It's originally represented as whatever its input is;
6
- # if it's created with RGB values, it's represented as RGBA,
7
- # and if it's created with HSL values, it's represented as HSLA.
8
- # Once a property is accessed that requires the other representation --
9
- # for example, \{#red} for an HSL color --
10
- # that component is calculated and cached.
11
- #
12
- # The alpha channel of a color is independent of its RGB or HSL representation.
13
- # It's always stored, as 1 if nothing else is specified.
14
- # If only the alpha channel is modified using \{#with},
15
- # the cached RGB and HSL values are retained.
16
- class Color < Base
17
- # @private
18
- #
19
- # Convert a ruby integer to a rgba components
20
- # @param color [Fixnum]
21
- # @return [Array<Fixnum>] Array of 4 numbers representing r,g,b and alpha
22
- def self.int_to_rgba(color)
23
- rgba = (0..3).map {|n| color >> (n << 3) & 0xff}.reverse
24
- rgba[-1] = rgba[-1] / 255.0
25
- rgba
26
- end
27
-
28
- ALTERNATE_COLOR_NAMES = Sass::Util.map_vals({
29
- 'aqua' => 0x00FFFFFF,
30
- 'darkgrey' => 0xA9A9A9FF,
31
- 'darkslategrey' => 0x2F4F4FFF,
32
- 'dimgrey' => 0x696969FF,
33
- 'fuchsia' => 0xFF00FFFF,
34
- 'grey' => 0x808080FF,
35
- 'lightgrey' => 0xD3D3D3FF,
36
- 'lightslategrey' => 0x778899FF,
37
- 'slategrey' => 0x708090FF,
38
- }, &method(:int_to_rgba))
39
-
40
- # A hash from color names to `[red, green, blue]` value arrays.
41
- COLOR_NAMES = Sass::Util.map_vals({
42
- 'aliceblue' => 0xF0F8FFFF,
43
- 'antiquewhite' => 0xFAEBD7FF,
44
- 'aquamarine' => 0x7FFFD4FF,
45
- 'azure' => 0xF0FFFFFF,
46
- 'beige' => 0xF5F5DCFF,
47
- 'bisque' => 0xFFE4C4FF,
48
- 'black' => 0x000000FF,
49
- 'blanchedalmond' => 0xFFEBCDFF,
50
- 'blue' => 0x0000FFFF,
51
- 'blueviolet' => 0x8A2BE2FF,
52
- 'brown' => 0xA52A2AFF,
53
- 'burlywood' => 0xDEB887FF,
54
- 'cadetblue' => 0x5F9EA0FF,
55
- 'chartreuse' => 0x7FFF00FF,
56
- 'chocolate' => 0xD2691EFF,
57
- 'coral' => 0xFF7F50FF,
58
- 'cornflowerblue' => 0x6495EDFF,
59
- 'cornsilk' => 0xFFF8DCFF,
60
- 'crimson' => 0xDC143CFF,
61
- 'cyan' => 0x00FFFFFF,
62
- 'darkblue' => 0x00008BFF,
63
- 'darkcyan' => 0x008B8BFF,
64
- 'darkgoldenrod' => 0xB8860BFF,
65
- 'darkgray' => 0xA9A9A9FF,
66
- 'darkgreen' => 0x006400FF,
67
- 'darkkhaki' => 0xBDB76BFF,
68
- 'darkmagenta' => 0x8B008BFF,
69
- 'darkolivegreen' => 0x556B2FFF,
70
- 'darkorange' => 0xFF8C00FF,
71
- 'darkorchid' => 0x9932CCFF,
72
- 'darkred' => 0x8B0000FF,
73
- 'darksalmon' => 0xE9967AFF,
74
- 'darkseagreen' => 0x8FBC8FFF,
75
- 'darkslateblue' => 0x483D8BFF,
76
- 'darkslategray' => 0x2F4F4FFF,
77
- 'darkturquoise' => 0x00CED1FF,
78
- 'darkviolet' => 0x9400D3FF,
79
- 'deeppink' => 0xFF1493FF,
80
- 'deepskyblue' => 0x00BFFFFF,
81
- 'dimgray' => 0x696969FF,
82
- 'dodgerblue' => 0x1E90FFFF,
83
- 'firebrick' => 0xB22222FF,
84
- 'floralwhite' => 0xFFFAF0FF,
85
- 'forestgreen' => 0x228B22FF,
86
- 'gainsboro' => 0xDCDCDCFF,
87
- 'ghostwhite' => 0xF8F8FFFF,
88
- 'gold' => 0xFFD700FF,
89
- 'goldenrod' => 0xDAA520FF,
90
- 'gray' => 0x808080FF,
91
- 'green' => 0x008000FF,
92
- 'greenyellow' => 0xADFF2FFF,
93
- 'honeydew' => 0xF0FFF0FF,
94
- 'hotpink' => 0xFF69B4FF,
95
- 'indianred' => 0xCD5C5CFF,
96
- 'indigo' => 0x4B0082FF,
97
- 'ivory' => 0xFFFFF0FF,
98
- 'khaki' => 0xF0E68CFF,
99
- 'lavender' => 0xE6E6FAFF,
100
- 'lavenderblush' => 0xFFF0F5FF,
101
- 'lawngreen' => 0x7CFC00FF,
102
- 'lemonchiffon' => 0xFFFACDFF,
103
- 'lightblue' => 0xADD8E6FF,
104
- 'lightcoral' => 0xF08080FF,
105
- 'lightcyan' => 0xE0FFFFFF,
106
- 'lightgoldenrodyellow' => 0xFAFAD2FF,
107
- 'lightgreen' => 0x90EE90FF,
108
- 'lightgray' => 0xD3D3D3FF,
109
- 'lightpink' => 0xFFB6C1FF,
110
- 'lightsalmon' => 0xFFA07AFF,
111
- 'lightseagreen' => 0x20B2AAFF,
112
- 'lightskyblue' => 0x87CEFAFF,
113
- 'lightslategray' => 0x778899FF,
114
- 'lightsteelblue' => 0xB0C4DEFF,
115
- 'lightyellow' => 0xFFFFE0FF,
116
- 'lime' => 0x00FF00FF,
117
- 'limegreen' => 0x32CD32FF,
118
- 'linen' => 0xFAF0E6FF,
119
- 'magenta' => 0xFF00FFFF,
120
- 'maroon' => 0x800000FF,
121
- 'mediumaquamarine' => 0x66CDAAFF,
122
- 'mediumblue' => 0x0000CDFF,
123
- 'mediumorchid' => 0xBA55D3FF,
124
- 'mediumpurple' => 0x9370DBFF,
125
- 'mediumseagreen' => 0x3CB371FF,
126
- 'mediumslateblue' => 0x7B68EEFF,
127
- 'mediumspringgreen' => 0x00FA9AFF,
128
- 'mediumturquoise' => 0x48D1CCFF,
129
- 'mediumvioletred' => 0xC71585FF,
130
- 'midnightblue' => 0x191970FF,
131
- 'mintcream' => 0xF5FFFAFF,
132
- 'mistyrose' => 0xFFE4E1FF,
133
- 'moccasin' => 0xFFE4B5FF,
134
- 'navajowhite' => 0xFFDEADFF,
135
- 'navy' => 0x000080FF,
136
- 'oldlace' => 0xFDF5E6FF,
137
- 'olive' => 0x808000FF,
138
- 'olivedrab' => 0x6B8E23FF,
139
- 'orange' => 0xFFA500FF,
140
- 'orangered' => 0xFF4500FF,
141
- 'orchid' => 0xDA70D6FF,
142
- 'palegoldenrod' => 0xEEE8AAFF,
143
- 'palegreen' => 0x98FB98FF,
144
- 'paleturquoise' => 0xAFEEEEFF,
145
- 'palevioletred' => 0xDB7093FF,
146
- 'papayawhip' => 0xFFEFD5FF,
147
- 'peachpuff' => 0xFFDAB9FF,
148
- 'peru' => 0xCD853FFF,
149
- 'pink' => 0xFFC0CBFF,
150
- 'plum' => 0xDDA0DDFF,
151
- 'powderblue' => 0xB0E0E6FF,
152
- 'purple' => 0x800080FF,
153
- 'red' => 0xFF0000FF,
154
- 'rebeccapurple' => 0x663399FF,
155
- 'rosybrown' => 0xBC8F8FFF,
156
- 'royalblue' => 0x4169E1FF,
157
- 'saddlebrown' => 0x8B4513FF,
158
- 'salmon' => 0xFA8072FF,
159
- 'sandybrown' => 0xF4A460FF,
160
- 'seagreen' => 0x2E8B57FF,
161
- 'seashell' => 0xFFF5EEFF,
162
- 'sienna' => 0xA0522DFF,
163
- 'silver' => 0xC0C0C0FF,
164
- 'skyblue' => 0x87CEEBFF,
165
- 'slateblue' => 0x6A5ACDFF,
166
- 'slategray' => 0x708090FF,
167
- 'snow' => 0xFFFAFAFF,
168
- 'springgreen' => 0x00FF7FFF,
169
- 'steelblue' => 0x4682B4FF,
170
- 'tan' => 0xD2B48CFF,
171
- 'teal' => 0x008080FF,
172
- 'thistle' => 0xD8BFD8FF,
173
- 'tomato' => 0xFF6347FF,
174
- 'transparent' => 0x00000000,
175
- 'turquoise' => 0x40E0D0FF,
176
- 'violet' => 0xEE82EEFF,
177
- 'wheat' => 0xF5DEB3FF,
178
- 'white' => 0xFFFFFFFF,
179
- 'whitesmoke' => 0xF5F5F5FF,
180
- 'yellow' => 0xFFFF00FF,
181
- 'yellowgreen' => 0x9ACD32FF
182
- }, &method(:int_to_rgba))
183
-
184
- # A hash from `[red, green, blue, alpha]` value arrays to color names.
185
- COLOR_NAMES_REVERSE = COLOR_NAMES.invert.freeze
186
-
187
- # We add the alternate color names after inverting because
188
- # different ruby implementations and versions vary on the ordering of the result of invert.
189
- COLOR_NAMES.update(ALTERNATE_COLOR_NAMES).freeze
190
-
191
- # The user's original representation of the color.
192
- #
193
- # @return [String]
194
- attr_reader :representation
195
-
196
- # Constructs an RGB or HSL color object,
197
- # optionally with an alpha channel.
198
- #
199
- # RGB values are clipped within 0 and 255.
200
- # Saturation and lightness values are clipped within 0 and 100.
201
- # The alpha value is clipped within 0 and 1.
202
- #
203
- # @raise [Sass::SyntaxError] if any color value isn't in the specified range
204
- #
205
- # @overload initialize(attrs)
206
- # The attributes are specified as a hash. This hash must contain either
207
- # `:hue`, `:saturation`, and `:value` keys, or `:red`, `:green`, and
208
- # `:blue` keys. It cannot contain both HSL and RGB keys. It may also
209
- # optionally contain an `:alpha` key, and a `:representation` key
210
- # indicating the original representation of the color that the user wrote
211
- # in their stylesheet.
212
- #
213
- # @param attrs [{Symbol => Numeric}] A hash of color attributes to values
214
- # @raise [ArgumentError] if not enough attributes are specified,
215
- # or both RGB and HSL attributes are specified
216
- #
217
- # @overload initialize(rgba, [representation])
218
- # The attributes are specified as an array.
219
- # This overload only supports RGB or RGBA colors.
220
- #
221
- # @param rgba [Array<Numeric>] A three- or four-element array
222
- # of the red, green, blue, and optionally alpha values (respectively)
223
- # of the color
224
- # @param representation [String] The original representation of the color
225
- # that the user wrote in their stylesheet.
226
- # @raise [ArgumentError] if not enough attributes are specified
227
- def initialize(attrs, representation = nil, allow_both_rgb_and_hsl = false)
228
- super(nil)
229
-
230
- if attrs.is_a?(Array)
231
- unless (3..4).include?(attrs.size)
232
- raise ArgumentError.new("Color.new(array) expects a three- or four-element array")
233
- end
234
-
235
- red, green, blue = attrs[0...3].map {|c| c.to_i}
236
- @attrs = {:red => red, :green => green, :blue => blue}
237
- @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
238
- @representation = representation
239
- else
240
- attrs = attrs.reject {|k, v| v.nil?}
241
- hsl = [:hue, :saturation, :lightness] & attrs.keys
242
- rgb = [:red, :green, :blue] & attrs.keys
243
- if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
244
- raise ArgumentError.new("Color.new(hash) may not have both HSL and RGB keys specified")
245
- elsif hsl.empty? && rgb.empty?
246
- raise ArgumentError.new("Color.new(hash) must have either HSL or RGB keys specified")
247
- elsif !hsl.empty? && hsl.size != 3
248
- raise ArgumentError.new("Color.new(hash) must have all three HSL values specified")
249
- elsif !rgb.empty? && rgb.size != 3
250
- raise ArgumentError.new("Color.new(hash) must have all three RGB values specified")
251
- end
252
-
253
- @attrs = attrs
254
- @attrs[:hue] %= 360 if @attrs[:hue]
255
- @attrs[:alpha] ||= 1
256
- @representation = @attrs.delete(:representation)
257
- end
258
-
259
- [:red, :green, :blue].each do |k|
260
- next if @attrs[k].nil?
261
- @attrs[k] = Sass::Util.restrict(@attrs[k].to_i, 0..255)
262
- end
263
-
264
- [:saturation, :lightness].each do |k|
265
- next if @attrs[k].nil?
266
- @attrs[k] = Sass::Util.restrict(@attrs[k], 0..100)
267
- end
268
-
269
- @attrs[:alpha] = Sass::Util.restrict(@attrs[:alpha], 0..1)
270
- end
271
-
272
- # Create a new color from a valid CSS hex string.
273
- #
274
- # The leading hash is optional.
275
- #
276
- # @return [Color]
277
- def self.from_hex(hex_string, alpha = nil)
278
- unless hex_string =~ /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i ||
279
- hex_string =~ /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i
280
- raise ArgumentError.new("#{hex_string.inspect} is not a valid hex color.")
281
- end
282
- red = $1.ljust(2, $1).to_i(16)
283
- green = $2.ljust(2, $2).to_i(16)
284
- blue = $3.ljust(2, $3).to_i(16)
285
-
286
- hex_string = '##{hex_string}' unless hex_string[0] == ?#
287
- attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
288
- attrs[:alpha] = alpha if alpha
289
- new(attrs)
290
- end
291
-
292
- # The red component of the color.
293
- #
294
- # @return [Fixnum]
295
- def red
296
- hsl_to_rgb!
297
- @attrs[:red]
298
- end
299
-
300
- # The green component of the color.
301
- #
302
- # @return [Fixnum]
303
- def green
304
- hsl_to_rgb!
305
- @attrs[:green]
306
- end
307
-
308
- # The blue component of the color.
309
- #
310
- # @return [Fixnum]
311
- def blue
312
- hsl_to_rgb!
313
- @attrs[:blue]
314
- end
315
-
316
- # The hue component of the color.
317
- #
318
- # @return [Numeric]
319
- def hue
320
- rgb_to_hsl!
321
- @attrs[:hue]
322
- end
323
-
324
- # The saturation component of the color.
325
- #
326
- # @return [Numeric]
327
- def saturation
328
- rgb_to_hsl!
329
- @attrs[:saturation]
330
- end
331
-
332
- # The lightness component of the color.
333
- #
334
- # @return [Numeric]
335
- def lightness
336
- rgb_to_hsl!
337
- @attrs[:lightness]
338
- end
339
-
340
- # The alpha channel (opacity) of the color.
341
- # This is 1 unless otherwise defined.
342
- #
343
- # @return [Fixnum]
344
- def alpha
345
- @attrs[:alpha].to_f
346
- end
347
-
348
- # Returns whether this color object is translucent;
349
- # that is, whether the alpha channel is non-1.
350
- #
351
- # @return [Boolean]
352
- def alpha?
353
- alpha < 1
354
- end
355
-
356
- # Returns the red, green, and blue components of the color.
357
- #
358
- # @return [Array<Fixnum>] A frozen three-element array of the red, green, and blue
359
- # values (respectively) of the color
360
- def rgb
361
- [red, green, blue].freeze
362
- end
363
-
364
- # Returns the red, green, blue, and alpha components of the color.
365
- #
366
- # @return [Array<Fixnum>] A frozen four-element array of the red, green,
367
- # blue, and alpha values (respectively) of the color
368
- def rgba
369
- [red, green, blue, alpha].freeze
370
- end
371
-
372
- # Returns the hue, saturation, and lightness components of the color.
373
- #
374
- # @return [Array<Fixnum>] A frozen three-element array of the
375
- # hue, saturation, and lightness values (respectively) of the color
376
- def hsl
377
- [hue, saturation, lightness].freeze
378
- end
379
-
380
- # Returns the hue, saturation, lightness, and alpha components of the color.
381
- #
382
- # @return [Array<Fixnum>] A frozen four-element array of the hue,
383
- # saturation, lightness, and alpha values (respectively) of the color
384
- def hsla
385
- [hue, saturation, lightness].freeze
386
- end
387
-
388
- # The SassScript `==` operation.
389
- # **Note that this returns a {Sass::Script::Value::Bool} object,
390
- # not a Ruby boolean**.
391
- #
392
- # @param other [Value] The right-hand side of the operator
393
- # @return [Bool] True if this value is the same as the other,
394
- # false otherwise
395
- def eq(other)
396
- Sass::Script::Value::Bool.new(
397
- other.is_a?(Color) && rgb == other.rgb && alpha == other.alpha)
398
- end
399
-
400
- def hash
401
- [rgb, alpha].hash
402
- end
403
-
404
- # Returns a copy of this color with one or more channels changed.
405
- # RGB or HSL colors may be changed, but not both at once.
406
- #
407
- # For example:
408
- #
409
- # Color.new([10, 20, 30]).with(:blue => 40)
410
- # #=> rgb(10, 40, 30)
411
- # Color.new([126, 126, 126]).with(:red => 0, :green => 255)
412
- # #=> rgb(0, 255, 126)
413
- # Color.new([255, 0, 127]).with(:saturation => 60)
414
- # #=> rgb(204, 51, 127)
415
- # Color.new([1, 2, 3]).with(:alpha => 0.4)
416
- # #=> rgba(1, 2, 3, 0.4)
417
- #
418
- # @param attrs [{Symbol => Numeric}]
419
- # A map of channel names (`:red`, `:green`, `:blue`,
420
- # `:hue`, `:saturation`, `:lightness`, or `:alpha`) to values
421
- # @return [Color] The new Color object
422
- # @raise [ArgumentError] if both RGB and HSL keys are specified
423
- def with(attrs)
424
- attrs = attrs.reject {|k, v| v.nil?}
425
- hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
426
- rgb = !([:red, :green, :blue] & attrs.keys).empty?
427
- if hsl && rgb
428
- raise ArgumentError.new("Cannot specify HSL and RGB values for a color at the same time")
429
- end
430
-
431
- if hsl
432
- [:hue, :saturation, :lightness].each {|k| attrs[k] ||= send(k)}
433
- elsif rgb
434
- [:red, :green, :blue].each {|k| attrs[k] ||= send(k)}
435
- else
436
- # If we're just changing the alpha channel,
437
- # keep all the HSL/RGB stuff we've calculated
438
- attrs = @attrs.merge(attrs)
439
- end
440
- attrs[:alpha] ||= alpha
441
-
442
- Color.new(attrs, nil, :allow_both_rgb_and_hsl)
443
- end
444
-
445
- # The SassScript `+` operation.
446
- # Its functionality depends on the type of its argument:
447
- #
448
- # {Number}
449
- # : Adds the number to each of the RGB color channels.
450
- #
451
- # {Color}
452
- # : Adds each of the RGB color channels together.
453
- #
454
- # {Value}
455
- # : See {Value::Base#plus}.
456
- #
457
- # @param other [Value] The right-hand side of the operator
458
- # @return [Color] The resulting color
459
- # @raise [Sass::SyntaxError] if `other` is a number with units
460
- def plus(other)
461
- if other.is_a?(Sass::Script::Value::Number) || other.is_a?(Sass::Script::Value::Color)
462
- piecewise(other, :+)
463
- else
464
- super
465
- end
466
- end
467
-
468
- # The SassScript `-` operation.
469
- # Its functionality depends on the type of its argument:
470
- #
471
- # {Number}
472
- # : Subtracts the number from each of the RGB color channels.
473
- #
474
- # {Color}
475
- # : Subtracts each of the other color's RGB color channels from this color's.
476
- #
477
- # {Value}
478
- # : See {Value::Base#minus}.
479
- #
480
- # @param other [Value] The right-hand side of the operator
481
- # @return [Color] The resulting color
482
- # @raise [Sass::SyntaxError] if `other` is a number with units
483
- def minus(other)
484
- if other.is_a?(Sass::Script::Value::Number) || other.is_a?(Sass::Script::Value::Color)
485
- piecewise(other, :-)
486
- else
487
- super
488
- end
489
- end
490
-
491
- # The SassScript `*` operation.
492
- # Its functionality depends on the type of its argument:
493
- #
494
- # {Number}
495
- # : Multiplies the number by each of the RGB color channels.
496
- #
497
- # {Color}
498
- # : Multiplies each of the RGB color channels together.
499
- #
500
- # @param other [Number, Color] The right-hand side of the operator
501
- # @return [Color] The resulting color
502
- # @raise [Sass::SyntaxError] if `other` is a number with units
503
- def times(other)
504
- if other.is_a?(Sass::Script::Value::Number) || other.is_a?(Sass::Script::Value::Color)
505
- piecewise(other, :*)
506
- else
507
- raise NoMethodError.new(nil, :times)
508
- end
509
- end
510
-
511
- # The SassScript `/` operation.
512
- # Its functionality depends on the type of its argument:
513
- #
514
- # {Number}
515
- # : Divides each of the RGB color channels by the number.
516
- #
517
- # {Color}
518
- # : Divides each of this color's RGB color channels by the other color's.
519
- #
520
- # {Value}
521
- # : See {Value::Base#div}.
522
- #
523
- # @param other [Value] The right-hand side of the operator
524
- # @return [Color] The resulting color
525
- # @raise [Sass::SyntaxError] if `other` is a number with units
526
- def div(other)
527
- if other.is_a?(Sass::Script::Value::Number) ||
528
- other.is_a?(Sass::Script::Value::Color)
529
- piecewise(other, :/)
530
- else
531
- super
532
- end
533
- end
534
-
535
- # The SassScript `%` operation.
536
- # Its functionality depends on the type of its argument:
537
- #
538
- # {Number}
539
- # : Takes each of the RGB color channels module the number.
540
- #
541
- # {Color}
542
- # : Takes each of this color's RGB color channels modulo the other color's.
543
- #
544
- # @param other [Number, Color] The right-hand side of the operator
545
- # @return [Color] The resulting color
546
- # @raise [Sass::SyntaxError] if `other` is a number with units
547
- def mod(other)
548
- if other.is_a?(Sass::Script::Value::Number) ||
549
- other.is_a?(Sass::Script::Value::Color)
550
- piecewise(other, :%)
551
- else
552
- raise NoMethodError.new(nil, :mod)
553
- end
554
- end
555
-
556
- # Returns a string representation of the color.
557
- # This is usually the color's hex value,
558
- # but if the color has a name that's used instead.
559
- #
560
- # @return [String] The string representation
561
- def to_s(opts = {})
562
- return smallest if options[:style] == :compressed
563
- return representation if representation
564
- return name if name
565
- alpha? ? rgba_str : hex_str
566
- end
567
- alias_method :to_sass, :to_s
568
-
569
- # Returns a string representation of the color.
570
- #
571
- # @return [String] The hex value
572
- def inspect
573
- alpha? ? rgba_str : hex_str
574
- end
575
-
576
- # Returns the color's name, if it has one.
577
- #
578
- # @return [String, nil]
579
- def name
580
- COLOR_NAMES_REVERSE[rgba]
581
- end
582
-
583
- private
584
-
585
- def smallest
586
- small_explicit_str = alpha? ? rgba_str : hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
587
- [representation, COLOR_NAMES_REVERSE[rgba], small_explicit_str].
588
- compact.min_by {|str| str.size}
589
- end
590
-
591
- def rgba_str
592
- split = options[:style] == :compressed ? ',' : ', '
593
- "rgba(#{rgb.join(split)}#{split}#{Number.round(alpha)})"
594
- end
595
-
596
- def hex_str
597
- red, green, blue = rgb.map {|num| num.to_s(16).rjust(2, '0')}
598
- "##{red}#{green}#{blue}"
599
- end
600
-
601
- def piecewise(other, operation)
602
- other_num = other.is_a? Number
603
- if other_num && !other.unitless?
604
- raise Sass::SyntaxError.new(
605
- "Cannot add a number with units (#{other}) to a color (#{self}).")
606
- end
607
-
608
- result = []
609
- (0...3).each do |i|
610
- res = rgb[i].send(operation, other_num ? other.value : other.rgb[i])
611
- result[i] = [[res, 255].min, 0].max
612
- end
613
-
614
- if !other_num && other.alpha != alpha
615
- raise Sass::SyntaxError.new("Alpha channels must be equal: #{self} #{operation} #{other}")
616
- end
617
-
618
- with(:red => result[0], :green => result[1], :blue => result[2])
619
- end
620
-
621
- def hsl_to_rgb!
622
- return if @attrs[:red] && @attrs[:blue] && @attrs[:green]
623
-
624
- h = @attrs[:hue] / 360.0
625
- s = @attrs[:saturation] / 100.0
626
- l = @attrs[:lightness] / 100.0
627
-
628
- # Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
629
- m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
630
- m1 = l * 2 - m2
631
- @attrs[:red], @attrs[:green], @attrs[:blue] = [
632
- hue_to_rgb(m1, m2, h + 1.0 / 3),
633
- hue_to_rgb(m1, m2, h),
634
- hue_to_rgb(m1, m2, h - 1.0 / 3)
635
- ].map {|c| (c * 0xff).round}
636
- end
637
-
638
- def hue_to_rgb(m1, m2, h)
639
- h += 1 if h < 0
640
- h -= 1 if h > 1
641
- return m1 + (m2 - m1) * h * 6 if h * 6 < 1
642
- return m2 if h * 2 < 1
643
- return m1 + (m2 - m1) * (2.0 / 3 - h) * 6 if h * 3 < 2
644
- m1
645
- end
646
-
647
- def rgb_to_hsl!
648
- return if @attrs[:hue] && @attrs[:saturation] && @attrs[:lightness]
649
- r, g, b = [:red, :green, :blue].map {|k| @attrs[k] / 255.0}
650
-
651
- # Algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
652
- max = [r, g, b].max
653
- min = [r, g, b].min
654
- d = max - min
655
-
656
- h =
657
- case max
658
- when min; 0
659
- when r; 60 * (g - b) / d
660
- when g; 60 * (b - r) / d + 120
661
- when b; 60 * (r - g) / d + 240
662
- end
663
-
664
- l = (max + min) / 2.0
665
-
666
- s =
667
- if max == min
668
- 0
669
- elsif l < 0.5
670
- d / (2 * l)
671
- else
672
- d / (2 - 2 * l)
673
- end
674
-
675
- @attrs[:hue] = h % 360
676
- @attrs[:saturation] = s * 100
677
- @attrs[:lightness] = l * 100
678
- end
679
- end
680
- end