haml-edge 2.3.99 → 2.3.100

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/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/