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.
- data/FAQ +138 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +332 -0
- data/REVISION +1 -0
- data/Rakefile +184 -0
- data/VERSION +1 -0
- data/bin/css2sass +7 -0
- data/bin/haml +9 -0
- data/bin/html2haml +7 -0
- data/bin/sass +8 -0
- data/extra/haml-mode.el +434 -0
- data/extra/sass-mode.el +98 -0
- data/init.rb +8 -0
- data/lib/haml.rb +1025 -0
- data/lib/haml/buffer.rb +255 -0
- data/lib/haml/engine.rb +268 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +395 -0
- data/lib/haml/filters.rb +276 -0
- data/lib/haml/helpers.rb +465 -0
- data/lib/haml/helpers/action_view_extensions.rb +45 -0
- data/lib/haml/helpers/action_view_mods.rb +181 -0
- data/lib/haml/html.rb +218 -0
- data/lib/haml/precompiler.rb +896 -0
- data/lib/haml/shared.rb +45 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +72 -0
- data/lib/haml/util.rb +77 -0
- data/lib/haml/version.rb +47 -0
- data/lib/sass.rb +1062 -0
- data/lib/sass/css.rb +388 -0
- data/lib/sass/engine.rb +501 -0
- data/lib/sass/environment.rb +33 -0
- data/lib/sass/error.rb +35 -0
- data/lib/sass/plugin.rb +203 -0
- data/lib/sass/plugin/merb.rb +56 -0
- data/lib/sass/plugin/rails.rb +24 -0
- data/lib/sass/repl.rb +44 -0
- data/lib/sass/script.rb +38 -0
- data/lib/sass/script/bool.rb +13 -0
- data/lib/sass/script/color.rb +97 -0
- data/lib/sass/script/funcall.rb +28 -0
- data/lib/sass/script/functions.rb +122 -0
- data/lib/sass/script/lexer.rb +144 -0
- data/lib/sass/script/literal.rb +60 -0
- data/lib/sass/script/number.rb +231 -0
- data/lib/sass/script/operation.rb +30 -0
- data/lib/sass/script/parser.rb +142 -0
- data/lib/sass/script/string.rb +42 -0
- data/lib/sass/script/unary_operation.rb +21 -0
- data/lib/sass/script/variable.rb +20 -0
- data/lib/sass/tree/attr_node.rb +64 -0
- data/lib/sass/tree/comment_node.rb +30 -0
- data/lib/sass/tree/debug_node.rb +22 -0
- data/lib/sass/tree/directive_node.rb +50 -0
- data/lib/sass/tree/file_node.rb +27 -0
- data/lib/sass/tree/for_node.rb +29 -0
- data/lib/sass/tree/if_node.rb +27 -0
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +34 -0
- data/lib/sass/tree/node.rb +97 -0
- data/lib/sass/tree/rule_node.rb +120 -0
- data/lib/sass/tree/variable_node.rb +24 -0
- data/lib/sass/tree/while_node.rb +20 -0
- data/rails/init.rb +1 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +852 -0
- data/test/haml/helper_test.rb +224 -0
- data/test/haml/html2haml_test.rb +92 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/mocks/article.rb +6 -0
- data/test/haml/results/content_for_layout.xhtml +15 -0
- data/test/haml/results/eval_suppressed.xhtml +9 -0
- data/test/haml/results/filters.xhtml +62 -0
- data/test/haml/results/helpers.xhtml +93 -0
- data/test/haml/results/helpful.xhtml +10 -0
- data/test/haml/results/just_stuff.xhtml +68 -0
- data/test/haml/results/list.xhtml +12 -0
- data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
- data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
- data/test/haml/results/original_engine.xhtml +20 -0
- data/test/haml/results/partial_layout.xhtml +5 -0
- data/test/haml/results/partials.xhtml +21 -0
- data/test/haml/results/render_layout.xhtml +3 -0
- data/test/haml/results/silent_script.xhtml +74 -0
- data/test/haml/results/standard.xhtml +42 -0
- data/test/haml/results/tag_parsing.xhtml +23 -0
- data/test/haml/results/very_basic.xhtml +5 -0
- data/test/haml/results/whitespace_handling.xhtml +89 -0
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +54 -0
- data/test/haml/template_test.rb +204 -0
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
- data/test/haml/templates/_layout.erb +3 -0
- data/test/haml/templates/_layout_for_partial.haml +3 -0
- data/test/haml/templates/_partial.haml +8 -0
- data/test/haml/templates/_text_area.haml +3 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/action_view_ugly.haml +47 -0
- data/test/haml/templates/breakage.haml +8 -0
- data/test/haml/templates/content_for_layout.haml +10 -0
- data/test/haml/templates/eval_suppressed.haml +11 -0
- data/test/haml/templates/filters.haml +66 -0
- data/test/haml/templates/helpers.haml +95 -0
- data/test/haml/templates/helpful.haml +11 -0
- data/test/haml/templates/just_stuff.haml +83 -0
- data/test/haml/templates/list.haml +12 -0
- data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
- data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
- data/test/haml/templates/original_engine.haml +17 -0
- data/test/haml/templates/partial_layout.haml +3 -0
- data/test/haml/templates/partialize.haml +1 -0
- data/test/haml/templates/partials.haml +12 -0
- data/test/haml/templates/render_layout.haml +2 -0
- data/test/haml/templates/silent_script.haml +40 -0
- data/test/haml/templates/standard.haml +42 -0
- data/test/haml/templates/standard_ugly.haml +42 -0
- data/test/haml/templates/tag_parsing.haml +21 -0
- data/test/haml/templates/very_basic.haml +4 -0
- data/test/haml/templates/whitespace_handling.haml +87 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +193 -0
- data/test/sass/engine_test.rb +752 -0
- data/test/sass/functions_test.rb +96 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +208 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +87 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/import.css +29 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +152 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +309 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/import.sass +11 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +21 -0
- 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
|