haml-edge 2.3.99 → 2.3.100

Sign up to get free protection for your applications and to get access to all the features.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.99
1
+ 2.3.100
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.99
1
+ 2.3.100
data/lib/sass/engine.rb CHANGED
@@ -470,7 +470,8 @@ LONG
470
470
  raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".") if name.nil?
471
471
 
472
472
  offset = line.offset + line.text.size - arg_string.size
473
- args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_definition_arglist
473
+ args = Script::Parser.new(arg_string.strip, @line, offset, @options).
474
+ parse_mixin_definition_arglist
474
475
  default_arg_found = false
475
476
  Tree::MixinDefNode.new(name, args)
476
477
  end
@@ -480,7 +481,8 @@ LONG
480
481
  raise SyntaxError.new("Invalid mixin include \"#{line.text}\".") if name.nil?
481
482
 
482
483
  offset = line.offset + line.text.size - arg_string.size
483
- args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_include_arglist
484
+ args = Script::Parser.new(arg_string.strip, @line, offset, @options).
485
+ parse_mixin_include_arglist
484
486
  raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.",
485
487
  :line => @line + 1) unless line.children.empty?
486
488
  Tree::MixinNode.new(name, args)
@@ -489,7 +491,7 @@ LONG
489
491
  def parse_script(script, options = {})
490
492
  line = options[:line] || @line
491
493
  offset = options[:offset] || 0
492
- Script.parse(script, line, offset, @options[:filename])
494
+ Script.parse(script, line, offset, @options)
493
495
  end
494
496
  end
495
497
  end
@@ -249,15 +249,38 @@ END
249
249
  #
250
250
  # @return [String] The string representation
251
251
  def to_s
252
- return "rgba(#{rgb.join(', ')}, #{alpha % 1 == 0.0 ? alpha.to_i : alpha})" if alpha?
252
+ return rgba_str if alpha?
253
+ return smallest if options[:style] == :compressed
253
254
  return HTML4_COLORS_REVERSE[rgb] if HTML4_COLORS_REVERSE[rgb]
254
- red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') }
255
- "##{red}#{green}#{blue}"
255
+ hex_str
256
256
  end
257
257
  alias_method :inspect, :to_s
258
258
 
259
+ # Returns a string representation of the color.
260
+ #
261
+ # @return [String] The hex value
262
+ def inspect
263
+ alpha? ? rgba_str : hex_str
264
+ end
265
+
259
266
  private
260
267
 
268
+ def smallest
269
+ small_hex_str = hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
270
+ return small_hex_str unless (color = HTML4_COLORS_REVERSE[rgb]) &&
271
+ color.size <= small_hex_str.size
272
+ return color
273
+ end
274
+
275
+ def rgba_str
276
+ "rgba(#{rgb.join(', ')}, #{alpha % 1 == 0.0 ? alpha.to_i : alpha})"
277
+ end
278
+
279
+ def hex_str
280
+ red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') }
281
+ "##{red}#{green}#{blue}"
282
+ end
283
+
261
284
  def piecewise(other, operation)
262
285
  other_num = other.is_a? Number
263
286
  if other_num && !other.unitless?
@@ -41,11 +41,21 @@ module Sass
41
41
  return Script::String.new("#{name}(#{args.map {|a| a.perform(environment)}.join(', ')})")
42
42
  end
43
43
 
44
- return Functions::EvaluationContext.new(environment.options).send(ruby_name, *args)
44
+ result = Functions::EvaluationContext.new(environment.options).send(ruby_name, *args)
45
+ result.options = environment.options
46
+ return result
45
47
  rescue ArgumentError => e
46
48
  raise e unless e.backtrace.any? {|t| t =~ /:in `(block in )?(#{name}|perform)'$/}
47
49
  raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
48
50
  end
51
+
52
+ # Returns the arguments to the function.
53
+ #
54
+ # @return [Array<Node>]
55
+ # @see Node#children
56
+ def children
57
+ @args
58
+ end
49
59
  end
50
60
  end
51
61
  end
@@ -87,13 +87,18 @@ module Sass::Script
87
87
  #
88
88
  # Within one of the functions in this module,
89
89
  # methods of {EvaluationContext} can be used.
90
+ #
91
+ # ### Caveats
92
+ #
93
+ # When creating new {Literal} objects within functions,
94
+ # be aware that it's not safe to call {Literal#to_s #to_s}
95
+ # (or other methods that use the string representation)
96
+ # on those objects without first setting {Node#options= the #options attribute}.
90
97
  module Functions
91
98
  # The context in which methods in {Script::Functions} are evaluated.
92
99
  # That means that all instance methods of {EvaluationContext}
93
100
  # are available to use in functions.
94
101
  class EvaluationContext
95
- include Sass::Script::Functions
96
-
97
102
  # The options hash for the {Sass::Engine} that is processing the function call
98
103
  #
99
104
  # @return [{Symbol => Object}]
@@ -102,6 +107,10 @@ module Sass::Script
102
107
  # @param options [{Symbol => Object}] See \{#options}
103
108
  def initialize(options)
104
109
  @options = options
110
+
111
+ # We need to include this individually in each instance
112
+ # because of an icky Ruby restriction
113
+ class << self; include Sass::Script::Functions; end
105
114
  end
106
115
 
107
116
  # Asserts that the type of a given SassScript value
@@ -85,11 +85,13 @@ module Sass
85
85
  # Used for error reporting
86
86
  # @param offset [Fixnum] The number of characters in on which the SassScript appears.
87
87
  # Used for error reporting
88
- def initialize(str, line, offset, filename)
88
+ # @param options [{Symbol => Object}] An options hash;
89
+ # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
90
+ def initialize(str, line, offset, options)
89
91
  @scanner = str.is_a?(StringScanner) ? str : StringScanner.new(str)
90
92
  @line = line
91
93
  @offset = offset
92
- @filename = filename
94
+ @options = options
93
95
  @interpolation_stack = []
94
96
  @prev = nil
95
97
  end
@@ -31,6 +31,31 @@ module Sass::Script
31
31
  self
32
32
  end
33
33
 
34
+ # Returns an empty array.
35
+ #
36
+ # @return [Array<Node>] empty
37
+ # @see Node#children
38
+ def children
39
+ []
40
+ end
41
+
42
+ # Returns the options hash for this node.
43
+ #
44
+ # @return [{Symbol => Object}]
45
+ # @raise [Sass::SyntaxError] if the options hash hasn't been set.
46
+ # This should only happen when the literal was created
47
+ # outside of the parser and \{#to\_s} was called on it
48
+ def options
49
+ opts = super
50
+ return opts if opts
51
+ raise Sass::SyntaxError.new(<<MSG)
52
+ The #options attribute is not set on this #{self.class}.
53
+ This error is probably occurring because #to_s was called
54
+ on this literal within a custom Sass function without first
55
+ setting the #option attribute.
56
+ MSG
57
+ end
58
+
34
59
  # The SassScript `and` operation.
35
60
  #
36
61
  # @param other [Literal] The right-hand side of the operator
@@ -173,5 +198,13 @@ module Sass::Script
173
198
 
174
199
  # @raise [Sass::SyntaxError] if this literal isn't an integer
175
200
  def assert_int!; to_i; end
201
+
202
+ # Returns the string representation of this literal
203
+ # as it would be output to the CSS document.
204
+ #
205
+ # @return [String]
206
+ def to_s
207
+ raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
208
+ end
176
209
  end
177
210
  end
@@ -3,6 +3,21 @@ module Sass::Script
3
3
  #
4
4
  # Use \{#perform} to evaluate a parse tree.
5
5
  class Node
6
+ # The options hash for this node.
7
+ #
8
+ # @return [{Symbol => Object}]
9
+ attr_reader :options
10
+
11
+ # Sets the options hash for this node,
12
+ # as well as for all child nodes.
13
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
14
+ #
15
+ # @param options [{Symbol => Object}] The options
16
+ def options=(options)
17
+ @options = options
18
+ children.each {|c| c.options = options}
19
+ end
20
+
6
21
  # Evaluates the node.
7
22
  #
8
23
  # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
@@ -10,5 +25,12 @@ module Sass::Script
10
25
  def perform(environment)
11
26
  raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #perform.")
12
27
  end
28
+
29
+ # Returns all child nodes of this node.
30
+ #
31
+ # @return [Array<Node>]
32
+ def children
33
+ raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #children.")
34
+ end
13
35
  end
14
36
  end
@@ -35,11 +35,21 @@ module Sass::Script
35
35
  literal1 = @operand1.perform(environment)
36
36
  literal2 = @operand2.perform(environment)
37
37
  begin
38
- literal1.send(@operator, literal2)
38
+ res = literal1.send(@operator, literal2)
39
+ res.options = environment.options
40
+ res
39
41
  rescue NoMethodError => e
40
42
  raise e unless e.name.to_s == @operator.to_s
41
43
  raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{@operator} #{literal2}\".")
42
44
  end
43
45
  end
46
+
47
+ # Returns the operands for this operation.
48
+ #
49
+ # @return [Array<Node>]
50
+ # @see Node#children
51
+ def children
52
+ [@operand1, @operand2]
53
+ end
44
54
  end
45
55
  end
@@ -10,11 +10,11 @@ module Sass
10
10
  # Used for error reporting
11
11
  # @param offset [Fixnum] The number of characters in on which the SassScript appears.
12
12
  # Used for error reporting
13
- # @param filename [String] The name of the file in which the SassScript appears.
14
- # Used for error reporting
15
- def initialize(str, line, offset, filename = nil)
16
- @filename = filename
17
- @lexer = Lexer.new(str, line, offset, filename)
13
+ # @param options [{Symbol => Object}] An options hash;
14
+ # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
15
+ def initialize(str, line, offset, options = {})
16
+ @options = options
17
+ @lexer = Lexer.new(str, line, offset, options)
18
18
  end
19
19
 
20
20
  # Parses a SassScript expression within an interpolated segment (`#{}`).
@@ -27,6 +27,7 @@ module Sass
27
27
  def parse_interpolated
28
28
  expr = assert_expr :expr
29
29
  assert_tok :end_interpolation
30
+ expr.options = @options
30
31
  expr
31
32
  end
32
33
 
@@ -37,6 +38,7 @@ module Sass
37
38
  def parse
38
39
  expr = assert_expr :expr
39
40
  assert_done
41
+ expr.options = @options
40
42
  expr
41
43
  end
42
44
 
@@ -53,6 +55,7 @@ module Sass
53
55
  end
54
56
  assert_done
55
57
 
58
+ args.each {|a| a.options = @options}
56
59
  args
57
60
  end
58
61
 
@@ -69,6 +72,10 @@ module Sass
69
72
  end
70
73
  assert_done
71
74
 
75
+ args.each do |k, v|
76
+ k.options = @options
77
+ v.options = @options if v
78
+ end
72
79
  args
73
80
  end
74
81
 
@@ -138,9 +145,10 @@ RUBY
138
145
  return paren unless name = try_tok(:ident)
139
146
  # An identifier without arguments is just a string
140
147
  unless try_tok(:lparen)
148
+ filename = @options[:filename]
141
149
  warn(<<END)
142
150
  DEPRECATION WARNING:
143
- On line #{name.line}, character #{name.offset}#{" of '#{@filename}'" if @filename}
151
+ On line #{name.line}, character #{name.offset}#{" of '#{filename}'" if filename}
144
152
  Implicit strings have been deprecated and will be removed in version 2.4.
145
153
  '#{name.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
146
154
  END
@@ -30,5 +30,13 @@ module Sass::Script
30
30
  raise e unless e.name.to_s == operator.to_s
31
31
  raise Sass::SyntaxError.new("Undefined unary operation: \"#{@operator} #{literal}\".")
32
32
  end
33
+
34
+ # Returns the operand of the operation.
35
+ #
36
+ # @return [Array<Node>]
37
+ # @see Node#children
38
+ def children
39
+ [@operand]
40
+ end
33
41
  end
34
42
  end
@@ -26,6 +26,14 @@ module Sass
26
26
  (val = environment.var(name)) && (return val)
27
27
  raise SyntaxError.new("Undefined variable: \"!#{name}\".")
28
28
  end
29
+
30
+ # Returns an empty array.
31
+ #
32
+ # @return [Array<Node>] empty
33
+ # @see Node#children
34
+ def children
35
+ []
36
+ end
29
37
  end
30
38
  end
31
39
  end
data/lib/sass/script.rb CHANGED
@@ -28,14 +28,14 @@ module Sass
28
28
  # Used for error reporting
29
29
  # @param offset [Fixnum] The number of characters in on `line` that the SassScript started.
30
30
  # Used for error reporting
31
- # @param filename [String] The path to the file in which the SassScript appeared.
32
- # Used for error reporting
31
+ # @param options [{Symbol => Object}] An options hash;
32
+ # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
33
33
  # @return [Script::Node] The root node of the parse tree
34
- def self.parse(value, line, offset, filename = nil)
35
- Parser.parse(value, line, offset, filename)
34
+ def self.parse(value, line, offset, options = {})
35
+ Parser.parse(value, line, offset, options)
36
36
  rescue Sass::SyntaxError => e
37
37
  e.message << ": #{value.inspect}." if e.message == "SassScript error"
38
- e.modify_backtrace(:line => line, :filename => filename)
38
+ e.modify_backtrace(:line => line, :filename => options[:filename])
39
39
  raise e
40
40
  end
41
41
  end
@@ -3,6 +3,12 @@ require File.dirname(__FILE__) + '/../test_helper'
3
3
  require 'sass/engine'
4
4
  require 'stringio'
5
5
 
6
+ module Sass::Script::Functions::UserFunctions
7
+ def option(name)
8
+ Sass::Script::String.new(@options[name.value.to_sym].to_s)
9
+ end
10
+ end
11
+
6
12
  class SassEngineTest < Test::Unit::TestCase
7
13
  # A map of erroneous Sass documents to the error messages they should produce.
8
14
  # The error messages may be arrays;
@@ -2,6 +2,18 @@ require 'test/unit'
2
2
  require File.dirname(__FILE__) + '/../../lib/sass'
3
3
  require 'sass/script'
4
4
 
5
+ module Sass::Script::Functions::UserFunctions
6
+ def call_options_on_new_literal
7
+ str = Sass::Script::String.new("foo")
8
+ str.options[:foo]
9
+ str
10
+ end
11
+
12
+ def user_defined
13
+ Sass::Script::String.new("I'm a user-defined string!")
14
+ end
15
+ end
16
+
5
17
  class SassFunctionTest < Test::Unit::TestCase
6
18
  # Tests taken from:
7
19
  # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-h-rotating-b.htm
@@ -237,6 +249,19 @@ class SassFunctionTest < Test::Unit::TestCase
237
249
  assert_error_message("\"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
238
250
  end
239
251
 
252
+ def test_user_defined_function
253
+ assert_equal("I'm a user-defined string!", evaluate("user_defined()"))
254
+ end
255
+
256
+ def test_options_on_new_literals_fails
257
+ assert_error_message(<<MSG, "call-options-on-new-literal()")
258
+ The #options attribute is not set on this Sass::Script::String.
259
+ This error is probably occurring because #to_s was called
260
+ on this literal within a custom Sass function without first
261
+ setting the #option attribute.
262
+ MSG
263
+ end
264
+
240
265
  private
241
266
 
242
267
  def evaluate(value)
@@ -2,6 +2,13 @@
2
2
  require File.dirname(__FILE__) + '/../test_helper'
3
3
  require 'sass/engine'
4
4
 
5
+ module Sass::Script::Functions::UserFunctions
6
+ def assert_options(val)
7
+ val.options[:foo]
8
+ Sass::Script::String.new("Options defined!")
9
+ end
10
+ end
11
+
5
12
  class SassScriptTest < Test::Unit::TestCase
6
13
  include Sass::Script
7
14
 
@@ -72,6 +79,18 @@ class SassScriptTest < Test::Unit::TestCase
72
79
  assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2")
73
80
  end
74
81
 
82
+ def test_compressed_colors
83
+ assert_equal "#123456", resolve("#123456", :style => :compressed)
84
+ assert_equal "rgba(1, 2, 3, 0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed)
85
+ assert_equal "#123", resolve("#112233", :style => :compressed)
86
+ assert_equal "#000", resolve("black", :style => :compressed)
87
+ assert_equal "red", resolve("#f00", :style => :compressed)
88
+ assert_equal "blue", resolve("#00f", :style => :compressed)
89
+ assert_equal "navy", resolve("#000080", :style => :compressed)
90
+ assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
91
+ assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
92
+ end
93
+
75
94
  def test_implicit_strings
76
95
  silence_warnings do
77
96
  assert_equal Sass::Script::String.new("foo"), eval("foo")
@@ -157,6 +176,11 @@ WARN
157
176
  assert_equal 'blam(foo)', resolve('blam("foo")')
158
177
  end
159
178
 
179
+ def test_function_results_have_options
180
+ assert_equal "Options defined!", resolve("assert_options(abs(1))")
181
+ assert_equal "Options defined!", resolve("assert_options(round(1.2))")
182
+ end
183
+
160
184
  def test_hyphenated_variables
161
185
  assert_equal("a-b", resolve("!a-b", {}, env("a-b" => Sass::Script::String.new("a-b"))))
162
186
  end
@@ -266,6 +290,11 @@ WARN
266
290
  assert_equal "true", resolve("1.1cm == 11mm")
267
291
  end
268
292
 
293
+ def test_operations_have_options
294
+ assert_equal "Options defined!", resolve("assert_options(1 + 1)")
295
+ assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
296
+ end
297
+
269
298
  # Regression Tests
270
299
 
271
300
  def test_funcall_has_higher_precedence_than_color_name
@@ -288,8 +317,8 @@ WARN
288
317
 
289
318
  def eval(str, opts = {}, environment = env)
290
319
  munge_filename opts
291
- Sass::Script.parse(str, opts[:line] || 1,
292
- opts[:offset] || 0, opts[:filename]).perform(environment)
320
+ Sass::Script.parse(str, opts.delete(:line) || 1,
321
+ opts.delete(:offset) || 0, opts).perform(environment)
293
322
  end
294
323
 
295
324
  def render(sass, options = {})
data/test/test_helper.rb CHANGED
@@ -10,9 +10,8 @@ require 'sass'
10
10
  Sass::RAILS_LOADED = true unless defined?(Sass::RAILS_LOADED)
11
11
 
12
12
  module Sass::Script::Functions
13
- def option(name)
14
- Sass::Script::String.new(@options[name.value.to_sym].to_s)
15
- end
13
+ module UserFunctions; end
14
+ include UserFunctions
16
15
  end
17
16
 
18
17
  class Test::Unit::TestCase
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.99
4
+ version: 2.3.100
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-12-01 00:00:00 -05:00
13
+ date: 2009-12-03 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -46,9 +46,9 @@ extra_rdoc_files:
46
46
  - README.md
47
47
  - VERSION
48
48
  - REVISION
49
+ - VERSION_NAME
49
50
  - CONTRIBUTING
50
51
  - MIT-LICENSE
51
- - VERSION_NAME
52
52
  - EDGE_GEM_VERSION
53
53
  files:
54
54
  - rails/init.rb
@@ -245,9 +245,9 @@ files:
245
245
  - README.md
246
246
  - VERSION
247
247
  - REVISION
248
+ - VERSION_NAME
248
249
  - CONTRIBUTING
249
250
  - MIT-LICENSE
250
- - VERSION_NAME
251
251
  - EDGE_GEM_VERSION
252
252
  has_rdoc: true
253
253
  homepage: http://haml-lang.com/