merbjedi-haml 2.1.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 (177) hide show
  1. data/FAQ +138 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +332 -0
  4. data/REVISION +1 -0
  5. data/Rakefile +184 -0
  6. data/VERSION +1 -0
  7. data/bin/css2sass +7 -0
  8. data/bin/haml +9 -0
  9. data/bin/html2haml +7 -0
  10. data/bin/sass +8 -0
  11. data/extra/haml-mode.el +434 -0
  12. data/extra/sass-mode.el +98 -0
  13. data/init.rb +8 -0
  14. data/lib/haml.rb +1025 -0
  15. data/lib/haml/buffer.rb +255 -0
  16. data/lib/haml/engine.rb +268 -0
  17. data/lib/haml/error.rb +22 -0
  18. data/lib/haml/exec.rb +395 -0
  19. data/lib/haml/filters.rb +276 -0
  20. data/lib/haml/helpers.rb +465 -0
  21. data/lib/haml/helpers/action_view_extensions.rb +45 -0
  22. data/lib/haml/helpers/action_view_mods.rb +181 -0
  23. data/lib/haml/html.rb +218 -0
  24. data/lib/haml/precompiler.rb +896 -0
  25. data/lib/haml/shared.rb +45 -0
  26. data/lib/haml/template.rb +51 -0
  27. data/lib/haml/template/patch.rb +58 -0
  28. data/lib/haml/template/plugin.rb +72 -0
  29. data/lib/haml/util.rb +77 -0
  30. data/lib/haml/version.rb +47 -0
  31. data/lib/sass.rb +1062 -0
  32. data/lib/sass/css.rb +388 -0
  33. data/lib/sass/engine.rb +501 -0
  34. data/lib/sass/environment.rb +33 -0
  35. data/lib/sass/error.rb +35 -0
  36. data/lib/sass/plugin.rb +203 -0
  37. data/lib/sass/plugin/merb.rb +56 -0
  38. data/lib/sass/plugin/rails.rb +24 -0
  39. data/lib/sass/repl.rb +44 -0
  40. data/lib/sass/script.rb +38 -0
  41. data/lib/sass/script/bool.rb +13 -0
  42. data/lib/sass/script/color.rb +97 -0
  43. data/lib/sass/script/funcall.rb +28 -0
  44. data/lib/sass/script/functions.rb +122 -0
  45. data/lib/sass/script/lexer.rb +144 -0
  46. data/lib/sass/script/literal.rb +60 -0
  47. data/lib/sass/script/number.rb +231 -0
  48. data/lib/sass/script/operation.rb +30 -0
  49. data/lib/sass/script/parser.rb +142 -0
  50. data/lib/sass/script/string.rb +42 -0
  51. data/lib/sass/script/unary_operation.rb +21 -0
  52. data/lib/sass/script/variable.rb +20 -0
  53. data/lib/sass/tree/attr_node.rb +64 -0
  54. data/lib/sass/tree/comment_node.rb +30 -0
  55. data/lib/sass/tree/debug_node.rb +22 -0
  56. data/lib/sass/tree/directive_node.rb +50 -0
  57. data/lib/sass/tree/file_node.rb +27 -0
  58. data/lib/sass/tree/for_node.rb +29 -0
  59. data/lib/sass/tree/if_node.rb +27 -0
  60. data/lib/sass/tree/mixin_def_node.rb +18 -0
  61. data/lib/sass/tree/mixin_node.rb +34 -0
  62. data/lib/sass/tree/node.rb +97 -0
  63. data/lib/sass/tree/rule_node.rb +120 -0
  64. data/lib/sass/tree/variable_node.rb +24 -0
  65. data/lib/sass/tree/while_node.rb +20 -0
  66. data/rails/init.rb +1 -0
  67. data/test/benchmark.rb +99 -0
  68. data/test/haml/engine_test.rb +852 -0
  69. data/test/haml/helper_test.rb +224 -0
  70. data/test/haml/html2haml_test.rb +92 -0
  71. data/test/haml/markaby/standard.mab +52 -0
  72. data/test/haml/mocks/article.rb +6 -0
  73. data/test/haml/results/content_for_layout.xhtml +15 -0
  74. data/test/haml/results/eval_suppressed.xhtml +9 -0
  75. data/test/haml/results/filters.xhtml +62 -0
  76. data/test/haml/results/helpers.xhtml +93 -0
  77. data/test/haml/results/helpful.xhtml +10 -0
  78. data/test/haml/results/just_stuff.xhtml +68 -0
  79. data/test/haml/results/list.xhtml +12 -0
  80. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  81. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  82. data/test/haml/results/original_engine.xhtml +20 -0
  83. data/test/haml/results/partial_layout.xhtml +5 -0
  84. data/test/haml/results/partials.xhtml +21 -0
  85. data/test/haml/results/render_layout.xhtml +3 -0
  86. data/test/haml/results/silent_script.xhtml +74 -0
  87. data/test/haml/results/standard.xhtml +42 -0
  88. data/test/haml/results/tag_parsing.xhtml +23 -0
  89. data/test/haml/results/very_basic.xhtml +5 -0
  90. data/test/haml/results/whitespace_handling.xhtml +89 -0
  91. data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  92. data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  93. data/test/haml/rhtml/action_view.rhtml +62 -0
  94. data/test/haml/rhtml/standard.rhtml +54 -0
  95. data/test/haml/template_test.rb +204 -0
  96. data/test/haml/templates/_av_partial_1.haml +9 -0
  97. data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
  98. data/test/haml/templates/_av_partial_2.haml +5 -0
  99. data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
  100. data/test/haml/templates/_layout.erb +3 -0
  101. data/test/haml/templates/_layout_for_partial.haml +3 -0
  102. data/test/haml/templates/_partial.haml +8 -0
  103. data/test/haml/templates/_text_area.haml +3 -0
  104. data/test/haml/templates/action_view.haml +47 -0
  105. data/test/haml/templates/action_view_ugly.haml +47 -0
  106. data/test/haml/templates/breakage.haml +8 -0
  107. data/test/haml/templates/content_for_layout.haml +10 -0
  108. data/test/haml/templates/eval_suppressed.haml +11 -0
  109. data/test/haml/templates/filters.haml +66 -0
  110. data/test/haml/templates/helpers.haml +95 -0
  111. data/test/haml/templates/helpful.haml +11 -0
  112. data/test/haml/templates/just_stuff.haml +83 -0
  113. data/test/haml/templates/list.haml +12 -0
  114. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  115. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  116. data/test/haml/templates/original_engine.haml +17 -0
  117. data/test/haml/templates/partial_layout.haml +3 -0
  118. data/test/haml/templates/partialize.haml +1 -0
  119. data/test/haml/templates/partials.haml +12 -0
  120. data/test/haml/templates/render_layout.haml +2 -0
  121. data/test/haml/templates/silent_script.haml +40 -0
  122. data/test/haml/templates/standard.haml +42 -0
  123. data/test/haml/templates/standard_ugly.haml +42 -0
  124. data/test/haml/templates/tag_parsing.haml +21 -0
  125. data/test/haml/templates/very_basic.haml +4 -0
  126. data/test/haml/templates/whitespace_handling.haml +87 -0
  127. data/test/linked_rails.rb +12 -0
  128. data/test/sass/css2sass_test.rb +193 -0
  129. data/test/sass/engine_test.rb +752 -0
  130. data/test/sass/functions_test.rb +96 -0
  131. data/test/sass/more_results/more1.css +9 -0
  132. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  133. data/test/sass/more_results/more_import.css +29 -0
  134. data/test/sass/more_templates/_more_partial.sass +2 -0
  135. data/test/sass/more_templates/more1.sass +23 -0
  136. data/test/sass/more_templates/more_import.sass +11 -0
  137. data/test/sass/plugin_test.rb +208 -0
  138. data/test/sass/results/alt.css +4 -0
  139. data/test/sass/results/basic.css +9 -0
  140. data/test/sass/results/compact.css +5 -0
  141. data/test/sass/results/complex.css +87 -0
  142. data/test/sass/results/compressed.css +1 -0
  143. data/test/sass/results/expanded.css +19 -0
  144. data/test/sass/results/import.css +29 -0
  145. data/test/sass/results/line_numbers.css +49 -0
  146. data/test/sass/results/mixins.css +95 -0
  147. data/test/sass/results/multiline.css +24 -0
  148. data/test/sass/results/nested.css +22 -0
  149. data/test/sass/results/parent_ref.css +13 -0
  150. data/test/sass/results/script.css +16 -0
  151. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  152. data/test/sass/results/subdir/subdir.css +3 -0
  153. data/test/sass/results/units.css +11 -0
  154. data/test/sass/script_test.rb +152 -0
  155. data/test/sass/templates/_partial.sass +2 -0
  156. data/test/sass/templates/alt.sass +16 -0
  157. data/test/sass/templates/basic.sass +23 -0
  158. data/test/sass/templates/bork.sass +2 -0
  159. data/test/sass/templates/bork2.sass +2 -0
  160. data/test/sass/templates/compact.sass +17 -0
  161. data/test/sass/templates/complex.sass +309 -0
  162. data/test/sass/templates/compressed.sass +15 -0
  163. data/test/sass/templates/expanded.sass +17 -0
  164. data/test/sass/templates/import.sass +11 -0
  165. data/test/sass/templates/importee.sass +19 -0
  166. data/test/sass/templates/line_numbers.sass +13 -0
  167. data/test/sass/templates/mixins.sass +76 -0
  168. data/test/sass/templates/multiline.sass +20 -0
  169. data/test/sass/templates/nested.sass +25 -0
  170. data/test/sass/templates/parent_ref.sass +25 -0
  171. data/test/sass/templates/script.sass +101 -0
  172. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  173. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  174. data/test/sass/templates/subdir/subdir.sass +6 -0
  175. data/test/sass/templates/units.sass +11 -0
  176. data/test/test_helper.rb +21 -0
  177. metadata +273 -0
@@ -0,0 +1,97 @@
1
+ require 'sass/script/literal'
2
+
3
+ module Sass::Script
4
+ class Color < Literal # :nodoc:
5
+ class << self; include Haml::Util; end
6
+
7
+ HTML4_COLORS = map_vals({
8
+ 'black' => 0x000000,
9
+ 'silver' => 0xc0c0c0,
10
+ 'gray' => 0x808080,
11
+ 'white' => 0xffffff,
12
+ 'maroon' => 0x800000,
13
+ 'red' => 0xff0000,
14
+ 'purple' => 0x800080,
15
+ 'fuchsia' => 0xff00ff,
16
+ 'green' => 0x008000,
17
+ 'lime' => 0x00ff00,
18
+ 'olive' => 0x808000,
19
+ 'yellow' => 0xffff00,
20
+ 'navy' => 0x000080,
21
+ 'blue' => 0x0000ff,
22
+ 'teal' => 0x008080,
23
+ 'aqua' => 0x00ffff
24
+ }) {|color| (0..2).map {|n| color >> (n << 3) & 0xff}.reverse}
25
+ HTML4_COLORS_REVERSE = map_hash(HTML4_COLORS) {|k, v| [v, k]}
26
+
27
+ def initialize(rgb)
28
+ rgb = rgb.map {|c| c.to_i}
29
+ raise Sass::SyntaxError.new("Color values must be between 0 and 255") if rgb.any? {|c| c < 0 || c > 255}
30
+ super(rgb)
31
+ end
32
+
33
+ def plus(other)
34
+ if other.is_a? Sass::Script::String
35
+ Sass::Script::String.new(self.to_s + other.to_s)
36
+ else
37
+ piecewise(other, :+)
38
+ end
39
+ end
40
+
41
+ def minus(other)
42
+ if other.is_a? Sass::Script::String
43
+ raise NoMethodError.new(nil, :minus)
44
+ else
45
+ piecewise(other, :-)
46
+ end
47
+ end
48
+
49
+ def times(other)
50
+ if other.is_a? Sass::Script::String
51
+ raise NoMethodError.new(nil, :times)
52
+ else
53
+ piecewise(other, :*)
54
+ end
55
+ end
56
+
57
+ def div(other)
58
+ if other.is_a? Sass::Script::String
59
+ raise NoMethodError.new(nil, :div)
60
+ else
61
+ piecewise(other, :/)
62
+ end
63
+ end
64
+
65
+ def mod(other)
66
+ if other.is_a? Sass::Script::String
67
+ raise NoMethodError.new(nil, :mod)
68
+ else
69
+ piecewise(other, :%)
70
+ end
71
+ end
72
+
73
+ def to_s
74
+ return HTML4_COLORS_REVERSE[@value] if HTML4_COLORS_REVERSE[@value]
75
+ red, green, blue = @value.map { |num| num.to_s(16).rjust(2, '0') }
76
+ "##{red}#{green}#{blue}"
77
+ end
78
+ alias_method :inspect, :to_s
79
+
80
+ private
81
+
82
+ def piecewise(other, operation)
83
+ other_num = other.is_a? Number
84
+ other_val = other.value
85
+ if other_num && !other.unitless?
86
+ raise Sass::SyntaxError.new("Cannot add a number with units (#{other}) to a color (#{self}).")
87
+ end
88
+
89
+ rgb = []
90
+ for i in (0...3)
91
+ res = @value[i].send(operation, other_num ? other_val : other_val[i])
92
+ rgb[i] = [ [res, 255].min, 0 ].max
93
+ end
94
+ Color.new(rgb)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,28 @@
1
+ module Sass
2
+ module Script
3
+ class Funcall # :nodoc:
4
+ attr_reader :name, :args
5
+
6
+ def initialize(name, args)
7
+ @name = name
8
+ @args = args
9
+ end
10
+
11
+ def inspect
12
+ "#{name}(#{args.map {|a| a.inspect}.join(', ')})"
13
+ end
14
+
15
+ def perform(environment)
16
+ args = self.args.map {|a| a.perform(environment)}
17
+ unless Haml::Util.has?(:public_instance_method, Functions, name) && name !~ /^__/
18
+ return Script::String.new("#{name}(#{args.map {|a| a.perform(environment)}.join(', ')})")
19
+ end
20
+
21
+ return Functions.send(name, *args)
22
+ rescue ArgumentError => e
23
+ raise e unless e.backtrace.first =~ /:in `(#{name}|perform)'$/
24
+ raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,122 @@
1
+ module Sass::Script
2
+ # Methods in this module are accessible from the Sass script context.
3
+ # For example, you can write
4
+ #
5
+ # color = hsl(120, 100%, 50%)
6
+ #
7
+ # and it will call Sass::Script::Functions#hsl.
8
+ #
9
+ # You can add your own functions to this module,
10
+ # but there are a few things to keep in mind.
11
+ # First of all, the arguments passed are (currently undocumented) Sass::Script::Literal objects,
12
+ # Literal objects are also the expected return values.
13
+ #
14
+ # Second, making Ruby functions accessible from Sass introduces the temptation
15
+ # to do things like database access within stylesheets.
16
+ # This temptation must be resisted.
17
+ # Keep in mind that Sass stylesheets are only compiled once
18
+ # at a somewhat indeterminate time
19
+ # and then left as static CSS files.
20
+ # Any dynamic CSS should be left in <style> tags in the HTML.
21
+ #
22
+ # The following functions are provided:
23
+ # * +hsl+ - converts an <tt>hsl(hue, saturation, lightness)</tt> triplet into a color.
24
+ #
25
+ # The +hue+ value should be between 0 and 360 inclusive,
26
+ # saturation and lightness must be between <tt>0%</tt> to <tt>100%</tt> inclusive.
27
+ # The percent sign is optional.
28
+ # * +percentage+ - converts a unitless number to a css percentage.
29
+ #
30
+ # Example: <tt>percentage(14px / 7px) => 200%</tt>
31
+ # * +round+ - Rounds a number to the nearest whole number.
32
+ #
33
+ # Example: <tt>round(10.4px) => 10px</tt>
34
+ # * +ceil+ - Rounds a number up to the nearest whole number.
35
+ #
36
+ # Example: <tt>ceil(10.4px) => 11px</tt>
37
+ # * +floor+ - Rounds a number down to the nearest whole number.
38
+ #
39
+ # Example: <tt>floor(10.6px) => 10px</tt>
40
+ # * +abs+ - Returns the absolute value of a number.
41
+ #
42
+ # Example: <tt>abs(-10px) => 10px</tt>
43
+ module Functions
44
+ instance_methods.each { |m| undef_method m unless m.to_s =~ /^__/ }
45
+ extend self
46
+
47
+ # Creates a Sass::Script::Color object from hue, saturation, and lightness.
48
+ # As per the CSS3 spec (http://www.w3.org/TR/css3-color/#hsl-color),
49
+ # hue is in degrees,
50
+ # and saturation and lightness are percentages.
51
+ def hsl(h, s, l)
52
+ original_s = s
53
+ original_l = l
54
+ # This algorithm is from http://www.w3.org/TR/css3-color#hsl-color
55
+ h, s, l = [h, s, l].map { |a| a.value }
56
+ raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") if s < 0 || s > 100
57
+ raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") if l < 0 || l > 100
58
+
59
+ h = (h % 360) / 360.0
60
+ s /= 100.0
61
+ l /= 100.0
62
+
63
+ m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
64
+ m1 = l * 2 - m2
65
+ Color.new([hue_to_rgb(m1, m2, h + 1.0/3),
66
+ hue_to_rgb(m1, m2, h),
67
+ hue_to_rgb(m1, m2, h - 1.0/3)].map { |c| (c * 0xff).round })
68
+ end
69
+
70
+ # Converts a unitless number into a percent and multiplies the number by 100.
71
+ # E.g. percentage(100px / 50px) => 200%
72
+ # Some may find this more natural than: 100% * 100px / 50px
73
+ def percentage(value)
74
+ unless value.is_a?(Sass::Script::Number) && value.unitless?
75
+ raise ArgumentError.new("#{value} is not a unitless number")
76
+ end
77
+ Sass::Script::Number.new(value.value * 100, ['%'])
78
+ end
79
+
80
+ # Rounds a number to the nearest whole number.
81
+ def round(value)
82
+ numeric_transformation(value) {|n| n.round}
83
+ end
84
+
85
+ # Rounds up to the nearest whole number.
86
+ def ceil(value)
87
+ numeric_transformation(value) {|n| n.ceil}
88
+ end
89
+
90
+ # Rounds down to the nearest whole number.
91
+ def floor(value)
92
+ numeric_transformation(value) {|n| n.floor}
93
+ end
94
+
95
+ # Returns the absolute value of a number.
96
+ def abs(value)
97
+ numeric_transformation(value) {|n| n.abs}
98
+ end
99
+
100
+ private
101
+
102
+ # This method implements the pattern of transforming a numeric value into
103
+ # another numeric value with the same units.
104
+ # It yields a number to a block to perform the operation and return a number
105
+ def numeric_transformation(value)
106
+ unless value.is_a?(Sass::Script::Number)
107
+ calling_function = caller.first.scan(/`([^']+)'/).first.first
108
+ raise Sass::SyntaxError.new("#{value} is not a number for `#{calling_function}'")
109
+ end
110
+ Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
111
+ end
112
+
113
+ def hue_to_rgb(m1, m2, h)
114
+ h += 1 if h < 0
115
+ h -= 1 if h > 1
116
+ return m1 + (m2 - m1) * h * 6 if h * 6 < 1
117
+ return m2 if h * 2 < 1
118
+ return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
119
+ return m1
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,144 @@
1
+ require 'strscan'
2
+
3
+ module Sass
4
+ module Script
5
+ class Lexer # :nodoc:
6
+ Token = Struct.new(:type, :value, :line, :offset)
7
+
8
+ OPERATORS = {
9
+ '+' => :plus,
10
+ '-' => :minus,
11
+ '*' => :times,
12
+ '/' => :div,
13
+ '%' => :mod,
14
+ '(' => :lparen,
15
+ ')' => :rparen,
16
+ ',' => :comma,
17
+ 'and' => :and,
18
+ 'or' => :or,
19
+ 'not' => :not,
20
+ '==' => :eq,
21
+ '!=' => :neq,
22
+ '>=' => :gte,
23
+ '<=' => :lte,
24
+ '>' => :gt,
25
+ '<' => :lt,
26
+ '}' => :right_bracket,
27
+ }
28
+
29
+ # We'll want to match longer names first
30
+ # so that > and < don't clobber >= and <=
31
+ OP_NAMES = OPERATORS.keys.sort_by {|o| -o.size}
32
+
33
+ REGULAR_EXPRESSIONS = {
34
+ :whitespace => /\s*/,
35
+ :variable => /!(\w+)/,
36
+ :ident => /(\\.|[^\s\\+\-*\/%(),=!])+/,
37
+ :string => /["}]((?:\\.|\#[^{]|[^"\\#])*)(?:"|#\{)/,
38
+ :number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
39
+ :color => /\##{"([0-9a-fA-F]{1,2})" * 3}|(#{Color::HTML4_COLORS.keys.join("|")})/,
40
+ :bool => /(true|false)\b/,
41
+ :op => %r{(#{Regexp.union(*OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + (s =~ /\w$/ ? '(?:\b|$)' : ''))})})}
42
+ }
43
+
44
+ def initialize(str, line, offset)
45
+ @scanner = str.is_a?(StringScanner) ? str : StringScanner.new(str)
46
+ @line = line
47
+ @offset = offset
48
+ @to_emit = []
49
+ end
50
+
51
+ def token
52
+ if @tok
53
+ @tok, tok = nil, @tok
54
+ return tok
55
+ end
56
+
57
+ return if done?
58
+
59
+ value = @to_emit.shift || variable || string || number || color || bool || op || ident
60
+ unless value
61
+ raise SyntaxError.new("Syntax error in '#{@scanner.string}' at character #{current_position}.")
62
+ end
63
+ Token.new(value.first, value.last, @line, last_match_position)
64
+ end
65
+
66
+ def peek
67
+ @tok ||= token
68
+ end
69
+
70
+ def done?
71
+ whitespace
72
+ @scanner.eos? && @tok.nil? && @to_emit.empty?
73
+ end
74
+
75
+ def rest
76
+ @scanner.rest
77
+ end
78
+
79
+ private
80
+
81
+ def emit(*value)
82
+ @to_emit.push value
83
+ end
84
+
85
+ def whitespace
86
+ @scanner.scan(REGULAR_EXPRESSIONS[:whitespace])
87
+ end
88
+
89
+ def variable
90
+ return unless @scanner.scan(REGULAR_EXPRESSIONS[:variable])
91
+ [:const, @scanner[1]]
92
+ end
93
+
94
+ def ident
95
+ return unless s = @scanner.scan(REGULAR_EXPRESSIONS[:ident])
96
+ [:ident, s.gsub(/\\(.)/, '\1')]
97
+ end
98
+
99
+ def string
100
+ return unless @scanner.scan(REGULAR_EXPRESSIONS[:string])
101
+ emit(:right_bracket) if @scanner.matched[0] == ?}
102
+ emit(:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1")))
103
+ emit(:begin_interpolation) if @scanner.matched[-2..-1] == '#{'
104
+ @to_emit.shift
105
+ end
106
+
107
+ def number
108
+ return unless @scanner.scan(REGULAR_EXPRESSIONS[:number])
109
+ value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
110
+ value = -value if @scanner[1]
111
+ [:number, Script::Number.new(value, Array(@scanner[4]))]
112
+ end
113
+
114
+ def color
115
+ return unless @scanner.scan(REGULAR_EXPRESSIONS[:color])
116
+ value = if @scanner[4]
117
+ color = Color::HTML4_COLORS[@scanner[4].downcase]
118
+ else
119
+ (1..3).map {|i| @scanner[i]}.map {|num| num.ljust(2, num).to_i(16)}
120
+ end
121
+ [:color, Script::Color.new(value)]
122
+ end
123
+
124
+ def bool
125
+ return unless s = @scanner.scan(REGULAR_EXPRESSIONS[:bool])
126
+ [:bool, Script::Bool.new(s == 'true')]
127
+ end
128
+
129
+ def op
130
+ return unless op = @scanner.scan(REGULAR_EXPRESSIONS[:op])
131
+ [OPERATORS[op]]
132
+ end
133
+
134
+ protected
135
+
136
+ def current_position
137
+ @offset + @scanner.pos + 1
138
+ end
139
+ def last_match_position
140
+ current_position - @scanner.matchedsize
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,60 @@
1
+ class Sass::Script::Literal # :nodoc:
2
+ require 'sass/script/string'
3
+ require 'sass/script/number'
4
+ require 'sass/script/color'
5
+ require 'sass/script/bool'
6
+
7
+ attr_reader :value
8
+
9
+ def initialize(value = nil)
10
+ @value = value
11
+ end
12
+
13
+ def perform(environment)
14
+ self
15
+ end
16
+
17
+ def and(other)
18
+ to_bool ? other : self
19
+ end
20
+
21
+ def or(other)
22
+ to_bool ? self : other
23
+ end
24
+
25
+ def eq(other)
26
+ Sass::Script::Bool.new(self.class == other.class && self.value == other.value)
27
+ end
28
+
29
+ def neq(other)
30
+ Sass::Script::Bool.new(!eq(other).to_bool)
31
+ end
32
+
33
+ def unary_not
34
+ Sass::Script::Bool.new(!to_bool)
35
+ end
36
+
37
+ def concat(other)
38
+ Sass::Script::String.new("#{self.to_s} #{other.to_s}")
39
+ end
40
+
41
+ def comma(other)
42
+ Sass::Script::String.new("#{self.to_s}, #{other.to_s}")
43
+ end
44
+
45
+ def inspect
46
+ value.inspect
47
+ end
48
+
49
+ def to_bool
50
+ true
51
+ end
52
+
53
+ def ==(other)
54
+ eq(other).to_bool
55
+ end
56
+
57
+ def to_i
58
+ raise Sass::SyntaxError.new("#{self.inspect} is not an integer.")
59
+ end
60
+ end