haml 3.0.25 → 3.1.0.alpha.2

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 (212) hide show
  1. data/.yardopts +1 -1
  2. data/CONTRIBUTING +0 -1
  3. data/EDGE_GEM_VERSION +1 -0
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +10 -175
  6. data/Rakefile +56 -84
  7. data/VERSION +1 -1
  8. data/VERSION_NAME +1 -1
  9. data/init.rb +1 -1
  10. data/lib/haml.rb +14 -12
  11. data/lib/haml/engine.rb +1 -1
  12. data/lib/haml/exec.rb +19 -316
  13. data/lib/haml/helpers/action_view_extensions.rb +1 -1
  14. data/lib/haml/html.rb +69 -76
  15. data/lib/haml/precompiler.rb +34 -41
  16. data/lib/haml/railtie.rb +4 -6
  17. data/lib/haml/template/plugin.rb +6 -16
  18. data/lib/haml/util.rb +91 -107
  19. data/lib/haml/version.rb +7 -0
  20. data/test/benchmark.rb +2 -9
  21. data/test/haml/engine_test.rb +195 -92
  22. data/test/haml/html2haml/erb_tests.rb +0 -14
  23. data/test/haml/util_test.rb +32 -0
  24. data/test/test_helper.rb +0 -39
  25. metadata +96 -324
  26. data/bin/css2sass +0 -13
  27. data/bin/sass +0 -8
  28. data/bin/sass-convert +0 -7
  29. data/extra/haml-mode.el +0 -753
  30. data/extra/sass-mode.el +0 -207
  31. data/lib/haml/util/subset_map.rb +0 -101
  32. data/lib/sass.rb +0 -29
  33. data/lib/sass/callbacks.rb +0 -52
  34. data/lib/sass/css.rb +0 -294
  35. data/lib/sass/engine.rb +0 -720
  36. data/lib/sass/environment.rb +0 -143
  37. data/lib/sass/error.rb +0 -198
  38. data/lib/sass/files.rb +0 -160
  39. data/lib/sass/less.rb +0 -382
  40. data/lib/sass/plugin.rb +0 -279
  41. data/lib/sass/plugin/configuration.rb +0 -221
  42. data/lib/sass/plugin/generic.rb +0 -15
  43. data/lib/sass/plugin/merb.rb +0 -37
  44. data/lib/sass/plugin/rack.rb +0 -47
  45. data/lib/sass/plugin/rails.rb +0 -32
  46. data/lib/sass/plugin/staleness_checker.rb +0 -123
  47. data/lib/sass/repl.rb +0 -58
  48. data/lib/sass/script.rb +0 -63
  49. data/lib/sass/script/bool.rb +0 -18
  50. data/lib/sass/script/color.rb +0 -491
  51. data/lib/sass/script/css_lexer.rb +0 -29
  52. data/lib/sass/script/css_parser.rb +0 -31
  53. data/lib/sass/script/funcall.rb +0 -77
  54. data/lib/sass/script/functions.rb +0 -861
  55. data/lib/sass/script/interpolation.rb +0 -70
  56. data/lib/sass/script/lexer.rb +0 -337
  57. data/lib/sass/script/literal.rb +0 -236
  58. data/lib/sass/script/node.rb +0 -112
  59. data/lib/sass/script/number.rb +0 -423
  60. data/lib/sass/script/operation.rb +0 -95
  61. data/lib/sass/script/parser.rb +0 -401
  62. data/lib/sass/script/string.rb +0 -67
  63. data/lib/sass/script/string_interpolation.rb +0 -93
  64. data/lib/sass/script/unary_operation.rb +0 -57
  65. data/lib/sass/script/variable.rb +0 -48
  66. data/lib/sass/scss.rb +0 -17
  67. data/lib/sass/scss/css_parser.rb +0 -46
  68. data/lib/sass/scss/parser.rb +0 -855
  69. data/lib/sass/scss/rx.rb +0 -126
  70. data/lib/sass/scss/sass_parser.rb +0 -11
  71. data/lib/sass/scss/script_lexer.rb +0 -15
  72. data/lib/sass/scss/script_parser.rb +0 -25
  73. data/lib/sass/scss/static_parser.rb +0 -40
  74. data/lib/sass/selector.rb +0 -361
  75. data/lib/sass/selector/abstract_sequence.rb +0 -62
  76. data/lib/sass/selector/comma_sequence.rb +0 -82
  77. data/lib/sass/selector/sequence.rb +0 -237
  78. data/lib/sass/selector/simple.rb +0 -113
  79. data/lib/sass/selector/simple_sequence.rb +0 -136
  80. data/lib/sass/tree/charset_node.rb +0 -37
  81. data/lib/sass/tree/comment_node.rb +0 -128
  82. data/lib/sass/tree/debug_node.rb +0 -36
  83. data/lib/sass/tree/directive_node.rb +0 -75
  84. data/lib/sass/tree/extend_node.rb +0 -65
  85. data/lib/sass/tree/for_node.rb +0 -55
  86. data/lib/sass/tree/if_node.rb +0 -69
  87. data/lib/sass/tree/import_node.rb +0 -102
  88. data/lib/sass/tree/mixin_def_node.rb +0 -48
  89. data/lib/sass/tree/mixin_node.rb +0 -111
  90. data/lib/sass/tree/node.rb +0 -464
  91. data/lib/sass/tree/prop_node.rb +0 -220
  92. data/lib/sass/tree/root_node.rb +0 -163
  93. data/lib/sass/tree/rule_node.rb +0 -261
  94. data/lib/sass/tree/variable_node.rb +0 -39
  95. data/lib/sass/tree/warn_node.rb +0 -42
  96. data/lib/sass/tree/while_node.rb +0 -36
  97. data/test/haml/util/subset_map_test.rb +0 -91
  98. data/test/sass/callbacks_test.rb +0 -61
  99. data/test/sass/conversion_test.rb +0 -1218
  100. data/test/sass/css2sass_test.rb +0 -364
  101. data/test/sass/data/hsl-rgb.txt +0 -319
  102. data/test/sass/engine_test.rb +0 -2267
  103. data/test/sass/extend_test.rb +0 -1348
  104. data/test/sass/functions_test.rb +0 -556
  105. data/test/sass/less_conversion_test.rb +0 -653
  106. data/test/sass/more_results/more1.css +0 -9
  107. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  108. data/test/sass/more_results/more_import.css +0 -29
  109. data/test/sass/more_templates/_more_partial.sass +0 -2
  110. data/test/sass/more_templates/more1.sass +0 -23
  111. data/test/sass/more_templates/more_import.sass +0 -11
  112. data/test/sass/plugin_test.rb +0 -433
  113. data/test/sass/results/alt.css +0 -4
  114. data/test/sass/results/basic.css +0 -9
  115. data/test/sass/results/compact.css +0 -5
  116. data/test/sass/results/complex.css +0 -86
  117. data/test/sass/results/compressed.css +0 -1
  118. data/test/sass/results/expanded.css +0 -19
  119. data/test/sass/results/import.css +0 -31
  120. data/test/sass/results/import_charset.css +0 -4
  121. data/test/sass/results/import_charset_1_8.css +0 -4
  122. data/test/sass/results/import_charset_ibm866.css +0 -4
  123. data/test/sass/results/line_numbers.css +0 -49
  124. data/test/sass/results/mixins.css +0 -95
  125. data/test/sass/results/multiline.css +0 -24
  126. data/test/sass/results/nested.css +0 -22
  127. data/test/sass/results/options.css +0 -1
  128. data/test/sass/results/parent_ref.css +0 -13
  129. data/test/sass/results/script.css +0 -16
  130. data/test/sass/results/scss_import.css +0 -31
  131. data/test/sass/results/scss_importee.css +0 -2
  132. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  133. data/test/sass/results/subdir/subdir.css +0 -3
  134. data/test/sass/results/units.css +0 -11
  135. data/test/sass/results/warn.css +0 -0
  136. data/test/sass/results/warn_imported.css +0 -0
  137. data/test/sass/script_conversion_test.rb +0 -314
  138. data/test/sass/script_test.rb +0 -470
  139. data/test/sass/scss/css_test.rb +0 -916
  140. data/test/sass/scss/rx_test.rb +0 -156
  141. data/test/sass/scss/scss_test.rb +0 -1122
  142. data/test/sass/scss/test_helper.rb +0 -37
  143. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  144. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  145. data/test/sass/templates/_partial.sass +0 -2
  146. data/test/sass/templates/alt.sass +0 -16
  147. data/test/sass/templates/basic.sass +0 -23
  148. data/test/sass/templates/bork1.sass +0 -2
  149. data/test/sass/templates/bork2.sass +0 -2
  150. data/test/sass/templates/bork3.sass +0 -2
  151. data/test/sass/templates/bork4.sass +0 -2
  152. data/test/sass/templates/compact.sass +0 -17
  153. data/test/sass/templates/complex.sass +0 -305
  154. data/test/sass/templates/compressed.sass +0 -15
  155. data/test/sass/templates/expanded.sass +0 -17
  156. data/test/sass/templates/import.sass +0 -12
  157. data/test/sass/templates/import_charset.sass +0 -7
  158. data/test/sass/templates/import_charset_1_8.sass +0 -4
  159. data/test/sass/templates/import_charset_ibm866.sass +0 -9
  160. data/test/sass/templates/importee.less +0 -2
  161. data/test/sass/templates/importee.sass +0 -19
  162. data/test/sass/templates/line_numbers.sass +0 -13
  163. data/test/sass/templates/mixin_bork.sass +0 -5
  164. data/test/sass/templates/mixins.sass +0 -76
  165. data/test/sass/templates/multiline.sass +0 -20
  166. data/test/sass/templates/nested.sass +0 -25
  167. data/test/sass/templates/nested_bork1.sass +0 -2
  168. data/test/sass/templates/nested_bork2.sass +0 -2
  169. data/test/sass/templates/nested_bork3.sass +0 -2
  170. data/test/sass/templates/nested_bork4.sass +0 -2
  171. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  172. data/test/sass/templates/options.sass +0 -2
  173. data/test/sass/templates/parent_ref.sass +0 -25
  174. data/test/sass/templates/script.sass +0 -101
  175. data/test/sass/templates/scss_import.scss +0 -11
  176. data/test/sass/templates/scss_importee.scss +0 -1
  177. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  178. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  179. data/test/sass/templates/subdir/subdir.sass +0 -6
  180. data/test/sass/templates/units.sass +0 -11
  181. data/test/sass/templates/warn.sass +0 -3
  182. data/test/sass/templates/warn_imported.sass +0 -4
  183. data/vendor/fssm/LICENSE +0 -20
  184. data/vendor/fssm/README.markdown +0 -55
  185. data/vendor/fssm/Rakefile +0 -59
  186. data/vendor/fssm/VERSION.yml +0 -5
  187. data/vendor/fssm/example.rb +0 -9
  188. data/vendor/fssm/fssm.gemspec +0 -77
  189. data/vendor/fssm/lib/fssm.rb +0 -33
  190. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  191. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  192. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  193. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  194. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  195. data/vendor/fssm/lib/fssm/path.rb +0 -91
  196. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  197. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  198. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  199. data/vendor/fssm/lib/fssm/support.rb +0 -63
  200. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  201. data/vendor/fssm/profile/prof-cache.rb +0 -40
  202. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  203. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  204. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  205. data/vendor/fssm/profile/prof.html +0 -2379
  206. data/vendor/fssm/spec/path_spec.rb +0 -75
  207. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  208. data/vendor/fssm/spec/root/file.css +0 -0
  209. data/vendor/fssm/spec/root/file.rb +0 -0
  210. data/vendor/fssm/spec/root/file.yml +0 -0
  211. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  212. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -1,58 +0,0 @@
1
- require 'readline'
2
-
3
- module Sass
4
- # Runs a SassScript read-eval-print loop.
5
- # It presents a prompt on the terminal,
6
- # reads in SassScript expressions,
7
- # evaluates them,
8
- # and prints the result.
9
- class Repl
10
- # @param options [{Symbol => Object}] An options hash.
11
- def initialize(options = {})
12
- @options = options
13
- end
14
-
15
- # Starts the read-eval-print loop.
16
- def run
17
- environment = Environment.new
18
- environment.set_var('important', Script::String.new('!important'))
19
- @line = 0
20
- loop do
21
- @line += 1
22
- unless text = Readline.readline('>> ')
23
- puts
24
- return
25
- end
26
-
27
- Readline::HISTORY << text
28
- parse_input(environment, text)
29
- end
30
- end
31
-
32
- private
33
-
34
- def parse_input(environment, text)
35
- case text
36
- when Script::MATCH
37
- name = $1
38
- guarded = $3 == '||=' || $4
39
- val = Script::Parser.parse($3, @line, text.size - $3.size)
40
-
41
- unless guarded && environment.var(name)
42
- environment.set_var(name, val.perform(environment))
43
- end
44
-
45
- p environment.var(name)
46
- else
47
- p Script::Parser.parse(text, @line, 0).perform(environment)
48
- end
49
- rescue Sass::SyntaxError => e
50
- puts "SyntaxError: #{e.message}"
51
- if @options[:trace]
52
- e.backtrace.each do |e|
53
- puts "\tfrom #{e}"
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,63 +0,0 @@
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'
8
-
9
- module Sass
10
- # SassScript is code that's embedded in Sass documents
11
- # to allow for property values to be computed from variables.
12
- #
13
- # This module contains code that handles the parsing and evaluation of SassScript.
14
- module Script
15
- # The regular expression used to parse variables.
16
- MATCH = /^[!\$](#{Sass::SCSS::RX::IDENT})\s*((?:\|\|)?=|:)\s*(.+?)(!(?i:default))?$/
17
-
18
- # The regular expression used to validate variables without matching.
19
- VALIDATE = /^[!\$]#{Sass::SCSS::RX::IDENT}$/
20
-
21
- # Parses a string of SassScript
22
- #
23
- # @param value [String] The SassScript
24
- # @param line [Fixnum] The number of the line on which the SassScript appeared.
25
- # Used for error reporting
26
- # @param offset [Fixnum] The number of characters in on `line` that the SassScript started.
27
- # Used for error reporting
28
- # @param options [{Symbol => Object}] An options hash;
29
- # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
30
- # @return [Script::Node] The root node of the parse tree
31
- def self.parse(value, line, offset, options = {})
32
- Parser.parse(value, line, offset, options)
33
- rescue Sass::SyntaxError => e
34
- e.message << ": #{value.inspect}." if e.message == "SassScript error"
35
- e.modify_backtrace(:line => line, :filename => options[:filename])
36
- raise e
37
- end
38
-
39
- # @private
40
- def self.var_warning(varname, line, offset, filename)
41
- Haml::Util.haml_warn <<MESSAGE
42
- DEPRECATION WARNING:
43
- On line #{line}, character #{offset}#{" of '#{filename}'" if filename}
44
- Variables with ! have been deprecated and will be removed in version 3.2.
45
- Use \"$#{varname}\" instead.
46
-
47
- You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
48
- MESSAGE
49
- end
50
-
51
- # @private
52
- def self.equals_warning(types, name, val, guarded, line, offset, filename)
53
- Haml::Util.haml_warn <<MESSAGE
54
- DEPRECATION WARNING:
55
- On line #{line}#{", character #{offset}" if offset}#{" of '#{filename}'" if filename}
56
- Setting #{types} with #{"||" if guarded}= has been deprecated and will be removed in version 3.2.
57
- Use "#{name}: #{val}#{" !default" if guarded}" instead.
58
-
59
- You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
60
- MESSAGE
61
- end
62
- end
63
- end
@@ -1,18 +0,0 @@
1
- require 'sass/script/literal'
2
-
3
- module Sass::Script
4
- # A SassScript object representing a boolean (true or false) value.
5
- class Bool < Literal
6
- # The Ruby value of the boolean.
7
- #
8
- # @return [Boolean]
9
- attr_reader :value
10
- alias_method :to_bool, :value
11
-
12
- # @return [String] "true" or "false"
13
- def to_s(opts = {})
14
- @value.to_s
15
- end
16
- alias_method :to_sass, :to_s
17
- end
18
- end
@@ -1,491 +0,0 @@
1
- require 'sass/script/literal'
2
-
3
- module Sass::Script
4
- # A SassScript object representing a CSS color.
5
- #
6
- # A color may be represented internally as RGBA, HSLA, or both.
7
- # It's originally represented as whatever its input is;
8
- # if it's created with RGB values, it's represented as RGBA,
9
- # and if it's created with HSL values, it's represented as HSLA.
10
- # Once a property is accessed that requires the other representation --
11
- # for example, \{#red} for an HSL color --
12
- # that component is calculated and cached.
13
- #
14
- # The alpha channel of a color is independent of its RGB or HSL representation.
15
- # It's always stored, as 1 if nothing else is specified.
16
- # If only the alpha channel is modified using \{#with},
17
- # the cached RGB and HSL values are retained.
18
- class Color < Literal
19
- class << self; include Haml::Util; end
20
-
21
- # A hash from color names to `[red, green, blue]` value arrays.
22
- HTML4_COLORS = map_vals({
23
- 'black' => 0x000000,
24
- 'silver' => 0xc0c0c0,
25
- 'gray' => 0x808080,
26
- 'white' => 0xffffff,
27
- 'maroon' => 0x800000,
28
- 'red' => 0xff0000,
29
- 'purple' => 0x800080,
30
- 'fuchsia' => 0xff00ff,
31
- 'green' => 0x008000,
32
- 'lime' => 0x00ff00,
33
- 'olive' => 0x808000,
34
- 'yellow' => 0xffff00,
35
- 'navy' => 0x000080,
36
- 'blue' => 0x0000ff,
37
- 'teal' => 0x008080,
38
- 'aqua' => 0x00ffff
39
- }) {|color| (0..2).map {|n| color >> (n << 3) & 0xff}.reverse}
40
- # A hash from `[red, green, blue]` value arrays to color names.
41
- HTML4_COLORS_REVERSE = map_hash(HTML4_COLORS) {|k, v| [v, k]}
42
-
43
- # Constructs an RGB or HSL color object,
44
- # optionally with an alpha channel.
45
- #
46
- # The RGB values must be between 0 and 255.
47
- # The saturation and lightness values must be between 0 and 100.
48
- # The alpha value must be between 0 and 1.
49
- #
50
- # @raise [Sass::SyntaxError] if any color value isn't in the specified range
51
- #
52
- # @overload initialize(attrs)
53
- # The attributes are specified as a hash.
54
- # This hash must contain either `:hue`, `:saturation`, and `:value` keys,
55
- # or `:red`, `:green`, and `:blue` keys.
56
- # It cannot contain both HSL and RGB keys.
57
- # It may also optionally contain an `:alpha` key.
58
- #
59
- # @param attrs [{Symbol => Numeric}] A hash of color attributes to values
60
- # @raise [ArgumentError] if not enough attributes are specified,
61
- # or both RGB and HSL attributes are specified
62
- #
63
- # @overload initialize(rgba)
64
- # The attributes are specified as an array.
65
- # This overload only supports RGB or RGBA colors.
66
- #
67
- # @param rgba [Array<Numeric>] A three- or four-element array
68
- # of the red, green, blue, and optionally alpha values (respectively)
69
- # of the color
70
- # @raise [ArgumentError] if not enough attributes are specified
71
- def initialize(attrs, allow_both_rgb_and_hsl = false)
72
- super(nil)
73
-
74
- if attrs.is_a?(Array)
75
- unless (3..4).include?(attrs.size)
76
- raise ArgumentError.new("Color.new(array) expects a three- or four-element array")
77
- end
78
-
79
- red, green, blue = attrs[0...3].map {|c| c.to_i}
80
- @attrs = {:red => red, :green => green, :blue => blue}
81
- @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
82
- else
83
- attrs = attrs.reject {|k, v| v.nil?}
84
- hsl = [:hue, :saturation, :lightness] & attrs.keys
85
- rgb = [:red, :green, :blue] & attrs.keys
86
- if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
87
- raise ArgumentError.new("Color.new(hash) may not have both HSL and RGB keys specified")
88
- elsif hsl.empty? && rgb.empty?
89
- raise ArgumentError.new("Color.new(hash) must have either HSL or RGB keys specified")
90
- elsif !hsl.empty? && hsl.size != 3
91
- raise ArgumentError.new("Color.new(hash) must have all three HSL values specified")
92
- elsif !rgb.empty? && rgb.size != 3
93
- raise ArgumentError.new("Color.new(hash) must have all three RGB values specified")
94
- end
95
-
96
- @attrs = attrs
97
- @attrs[:hue] %= 360 if @attrs[:hue]
98
- @attrs[:alpha] ||= 1
99
- end
100
-
101
- [:red, :green, :blue].each do |k|
102
- next if @attrs[k].nil?
103
- @attrs[k] = @attrs[k].to_i
104
- next if (0..255).include?(@attrs[k])
105
- raise Sass::SyntaxError.new("#{k.to_s.capitalize} value must be between 0 and 255")
106
- end
107
-
108
- [:saturation, :lightness].each do |k|
109
- next if @attrs[k].nil?
110
- @attrs[k] = 0 if @attrs[k] < 0.00001 && @attrs[k] > -0.00001
111
- @attrs[k] = 100 if @attrs[k] - 100 < 0.00001 && @attrs[k] - 100 > -0.00001
112
- next if (0..100).include?(@attrs[k])
113
- raise Sass::SyntaxError.new("#{k.to_s.capitalize} must be between 0 and 100")
114
- end
115
-
116
- unless (0..1).include?(@attrs[:alpha])
117
- raise Sass::SyntaxError.new("Alpha channel must be between 0 and 1")
118
- end
119
- end
120
-
121
- # The red component of the color.
122
- #
123
- # @return [Fixnum]
124
- def red
125
- hsl_to_rgb!
126
- @attrs[:red]
127
- end
128
-
129
- # The green component of the color.
130
- #
131
- # @return [Fixnum]
132
- def green
133
- hsl_to_rgb!
134
- @attrs[:green]
135
- end
136
-
137
- # The blue component of the color.
138
- #
139
- # @return [Fixnum]
140
- def blue
141
- hsl_to_rgb!
142
- @attrs[:blue]
143
- end
144
-
145
- # The hue component of the color.
146
- #
147
- # @return [Numeric]
148
- def hue
149
- rgb_to_hsl!
150
- @attrs[:hue]
151
- end
152
-
153
- # The saturation component of the color.
154
- #
155
- # @return [Numeric]
156
- def saturation
157
- rgb_to_hsl!
158
- @attrs[:saturation]
159
- end
160
-
161
- # The lightness component of the color.
162
- #
163
- # @return [Numeric]
164
- def lightness
165
- rgb_to_hsl!
166
- @attrs[:lightness]
167
- end
168
-
169
- # The alpha channel (opacity) of the color.
170
- # This is 1 unless otherwise defined.
171
- #
172
- # @return [Fixnum]
173
- def alpha
174
- @attrs[:alpha]
175
- end
176
-
177
- # Returns whether this color object is translucent;
178
- # that is, whether the alpha channel is non-1.
179
- #
180
- # @return [Boolean]
181
- def alpha?
182
- alpha < 1
183
- end
184
-
185
- # @deprecated This will be removed in version 3.2.
186
- # @see #rgb
187
- def value
188
- Haml::Util.haml_warn <<END
189
- DEPRECATION WARNING:
190
- The Sass::Script::Color #value attribute is deprecated and will be
191
- removed in version 3.2. Use the #rgb attribute instead.
192
- END
193
- rgb
194
- end
195
-
196
- # Returns the red, green, and blue components of the color.
197
- #
198
- # @return [Array<Fixnum>] A frozen three-element array of the red, green, and blue
199
- # values (respectively) of the color
200
- def rgb
201
- [red, green, blue].freeze
202
- end
203
-
204
- # Returns the hue, saturation, and lightness components of the color.
205
- #
206
- # @return [Array<Fixnum>] A frozen three-element array of the
207
- # hue, saturation, and lightness values (respectively) of the color
208
- def hsl
209
- [hue, saturation, lightness].freeze
210
- end
211
-
212
- # The SassScript `==` operation.
213
- # **Note that this returns a {Sass::Script::Bool} object,
214
- # not a Ruby boolean**.
215
- #
216
- # @param other [Literal] The right-hand side of the operator
217
- # @return [Bool] True if this literal is the same as the other,
218
- # false otherwise
219
- def eq(other)
220
- Sass::Script::Bool.new(
221
- other.is_a?(Color) && rgb == other.rgb && alpha == other.alpha)
222
- end
223
-
224
- # Returns a copy of this color with one or more channels changed.
225
- # RGB or HSL colors may be changed, but not both at once.
226
- #
227
- # For example:
228
- #
229
- # Color.new([10, 20, 30]).with(:blue => 40)
230
- # #=> rgb(10, 40, 30)
231
- # Color.new([126, 126, 126]).with(:red => 0, :green => 255)
232
- # #=> rgb(0, 255, 126)
233
- # Color.new([255, 0, 127]).with(:saturation => 60)
234
- # #=> rgb(204, 51, 127)
235
- # Color.new([1, 2, 3]).with(:alpha => 0.4)
236
- # #=> rgba(1, 2, 3, 0.4)
237
- #
238
- # @param attrs [{Symbol => Numeric}]
239
- # A map of channel names (`:red`, `:green`, `:blue`,
240
- # `:hue`, `:saturation`, `:lightness`, or `:alpha`) to values
241
- # @return [Color] The new Color object
242
- # @raise [ArgumentError] if both RGB and HSL keys are specified
243
- def with(attrs)
244
- attrs = attrs.reject {|k, v| v.nil?}
245
- hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
246
- rgb = !([:red, :green, :blue] & attrs.keys).empty?
247
- if hsl && rgb
248
- raise ArgumentError.new("Color#with may not have both HSL and RGB keys specified")
249
- end
250
-
251
- if hsl
252
- [:hue, :saturation, :lightness].each {|k| attrs[k] ||= send(k)}
253
- elsif rgb
254
- [:red, :green, :blue].each {|k| attrs[k] ||= send(k)}
255
- else
256
- # If we're just changing the alpha channel,
257
- # keep all the HSL/RGB stuff we've calculated
258
- attrs = @attrs.merge(attrs)
259
- end
260
- attrs[:alpha] ||= alpha
261
-
262
- Color.new(attrs, :allow_both_rgb_and_hsl)
263
- end
264
-
265
- # The SassScript `+` operation.
266
- # Its functionality depends on the type of its argument:
267
- #
268
- # {Number}
269
- # : Adds the number to each of the RGB color channels.
270
- #
271
- # {Color}
272
- # : Adds each of the RGB color channels together.
273
- #
274
- # {Literal}
275
- # : See {Literal#plus}.
276
- #
277
- # @param other [Literal] The right-hand side of the operator
278
- # @return [Color] The resulting color
279
- # @raise [Sass::SyntaxError] if `other` is a number with units
280
- def plus(other)
281
- if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
282
- piecewise(other, :+)
283
- else
284
- super
285
- end
286
- end
287
-
288
- # The SassScript `-` operation.
289
- # Its functionality depends on the type of its argument:
290
- #
291
- # {Number}
292
- # : Subtracts the number from each of the RGB color channels.
293
- #
294
- # {Color}
295
- # : Subtracts each of the other color's RGB color channels from this color's.
296
- #
297
- # {Literal}
298
- # : See {Literal#minus}.
299
- #
300
- # @param other [Literal] The right-hand side of the operator
301
- # @return [Color] The resulting color
302
- # @raise [Sass::SyntaxError] if `other` is a number with units
303
- def minus(other)
304
- if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
305
- piecewise(other, :-)
306
- else
307
- super
308
- end
309
- end
310
-
311
- # The SassScript `*` operation.
312
- # Its functionality depends on the type of its argument:
313
- #
314
- # {Number}
315
- # : Multiplies the number by each of the RGB color channels.
316
- #
317
- # {Color}
318
- # : Multiplies each of the RGB color channels together.
319
- #
320
- # @param other [Number, Color] The right-hand side of the operator
321
- # @return [Color] The resulting color
322
- # @raise [Sass::SyntaxError] if `other` is a number with units
323
- def times(other)
324
- if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
325
- piecewise(other, :*)
326
- else
327
- raise NoMethodError.new(nil, :times)
328
- end
329
- end
330
-
331
- # The SassScript `/` operation.
332
- # Its functionality depends on the type of its argument:
333
- #
334
- # {Number}
335
- # : Divides each of the RGB color channels by the number.
336
- #
337
- # {Color}
338
- # : Divides each of this color's RGB color channels by the other color's.
339
- #
340
- # {Literal}
341
- # : See {Literal#div}.
342
- #
343
- # @param other [Literal] The right-hand side of the operator
344
- # @return [Color] The resulting color
345
- # @raise [Sass::SyntaxError] if `other` is a number with units
346
- def div(other)
347
- if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
348
- piecewise(other, :/)
349
- else
350
- super
351
- end
352
- end
353
-
354
- # The SassScript `%` operation.
355
- # Its functionality depends on the type of its argument:
356
- #
357
- # {Number}
358
- # : Takes each of the RGB color channels module the number.
359
- #
360
- # {Color}
361
- # : Takes each of this color's RGB color channels modulo the other color's.
362
- #
363
- # @param other [Number, Color] The right-hand side of the operator
364
- # @return [Color] The resulting color
365
- # @raise [Sass::SyntaxError] if `other` is a number with units
366
- def mod(other)
367
- if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
368
- piecewise(other, :%)
369
- else
370
- raise NoMethodError.new(nil, :mod)
371
- end
372
- end
373
-
374
- # Returns a string representation of the color.
375
- # This is usually the color's hex value,
376
- # but if the color has a name that's used instead.
377
- #
378
- # @return [String] The string representation
379
- def to_s(opts = {})
380
- return rgba_str if alpha?
381
- return smallest if options[:style] == :compressed
382
- return HTML4_COLORS_REVERSE[rgb] if HTML4_COLORS_REVERSE[rgb]
383
- hex_str
384
- end
385
- alias_method :to_sass, :to_s
386
-
387
- # Returns a string representation of the color.
388
- #
389
- # @return [String] The hex value
390
- def inspect
391
- alpha? ? rgba_str : hex_str
392
- end
393
-
394
- private
395
-
396
- def smallest
397
- small_hex_str = hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
398
- return small_hex_str unless (color = HTML4_COLORS_REVERSE[rgb]) &&
399
- color.size <= small_hex_str.size
400
- return color
401
- end
402
-
403
- def rgba_str
404
- split = options[:style] == :compressed ? ',' : ', '
405
- "rgba(#{rgb.join(split)}#{split}#{Number.round(alpha)})"
406
- end
407
-
408
- def hex_str
409
- red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') }
410
- "##{red}#{green}#{blue}"
411
- end
412
-
413
- def piecewise(other, operation)
414
- other_num = other.is_a? Number
415
- if other_num && !other.unitless?
416
- raise Sass::SyntaxError.new("Cannot add a number with units (#{other}) to a color (#{self}).")
417
- end
418
-
419
- result = []
420
- for i in (0...3)
421
- res = rgb[i].send(operation, other_num ? other.value : other.rgb[i])
422
- result[i] = [ [res, 255].min, 0 ].max
423
- end
424
-
425
- if !other_num && other.alpha != alpha
426
- raise Sass::SyntaxError.new("Alpha channels must be equal: #{self} #{operation} #{other}")
427
- end
428
-
429
- with(:red => result[0], :green => result[1], :blue => result[2])
430
- end
431
-
432
- def hsl_to_rgb!
433
- return if @attrs[:red] && @attrs[:blue] && @attrs[:green]
434
-
435
- h = @attrs[:hue] / 360.0
436
- s = @attrs[:saturation] / 100.0
437
- l = @attrs[:lightness] / 100.0
438
-
439
- # Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
440
- m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
441
- m1 = l * 2 - m2
442
- @attrs[:red], @attrs[:green], @attrs[:blue] = [
443
- hue_to_rgb(m1, m2, h + 1.0/3),
444
- hue_to_rgb(m1, m2, h),
445
- hue_to_rgb(m1, m2, h - 1.0/3)
446
- ].map {|c| (c * 0xff).round}
447
- end
448
-
449
- def hue_to_rgb(m1, m2, h)
450
- h += 1 if h < 0
451
- h -= 1 if h > 1
452
- return m1 + (m2 - m1) * h * 6 if h * 6 < 1
453
- return m2 if h * 2 < 1
454
- return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
455
- return m1
456
- end
457
-
458
- def rgb_to_hsl!
459
- return if @attrs[:hue] && @attrs[:saturation] && @attrs[:lightness]
460
- r, g, b = [:red, :green, :blue].map {|k| @attrs[k] / 255.0}
461
-
462
- # Algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
463
- max = [r, g, b].max
464
- min = [r, g, b].min
465
- d = max - min
466
-
467
- h =
468
- case max
469
- when min; 0
470
- when r; 60 * (g-b)/d
471
- when g; 60 * (b-r)/d + 120
472
- when b; 60 * (r-g)/d + 240
473
- end
474
-
475
- l = (max + min)/2.0
476
-
477
- s =
478
- if max == min
479
- 0
480
- elsif l < 0.5
481
- d/(2*l)
482
- else
483
- d/(2 - 2*l)
484
- end
485
-
486
- @attrs[:hue] = h % 360
487
- @attrs[:saturation] = s * 100
488
- @attrs[:lightness] = l * 100
489
- end
490
- end
491
- end