sass 3.3.0.alpha.354 → 3.3.0.alpha.364

Sign up to get free protection for your applications and to get access to all the features.
data/REVISION CHANGED
@@ -1 +1 @@
1
- 77ed5f71b755020c48ab0243b667a064b0510efb
1
+ 4e515ab6a46507013fcbe426a5ecfa061b4ae571
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.0.alpha.354
1
+ 3.3.0.alpha.364
data/VERSION_DATE CHANGED
@@ -1 +1 @@
1
- 05 October 2013 01:29:09 GMT
1
+ 05 October 2013 16:04:57 GMT
@@ -1,28 +1,80 @@
1
1
  require 'set'
2
2
 
3
3
  module Sass
4
- # The lexical environment for SassScript.
5
- # This keeps track of variable, mixin, and function definitions.
6
- #
7
- # A new environment is created for each level of Sass nesting.
8
- # This allows variables to be lexically scoped.
9
- # The new environment refers to the environment in the upper scope,
10
- # so it has access to variables defined in enclosing scopes,
11
- # but new variables are defined locally.
12
- #
13
- # Environment also keeps track of the {Engine} options
14
- # so that they can be made available to {Sass::Script::Functions}.
15
- class Environment
16
- # The enclosing environment,
17
- # or nil if this is the global environment.
18
- #
19
- # @return [Environment]
20
- attr_reader :parent
4
+
5
+ # The abstract base class for lexical environments for SassScript.
6
+ class BaseEnvironment
7
+ class << self
8
+ # Note: when updating this,
9
+ # update sass/yard/inherited_hash.rb as well.
10
+ def inherited_hash_accessor(name)
11
+ inherited_hash_reader(name)
12
+ inherited_hash_writer(name)
13
+ end
14
+
15
+ def inherited_hash_reader(name)
16
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
17
+ def #{name}(name)
18
+ _#{name}(name.tr('_', '-'))
19
+ end
20
+
21
+ def _#{name}(name)
22
+ (@#{name}s && @#{name}s[name]) || @parent && @parent._#{name}(name)
23
+ end
24
+ protected :_#{name}
25
+ RUBY
26
+ end
27
+
28
+ def inherited_hash_writer(name)
29
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
30
+ def set_#{name}(name, value)
31
+ name = name.tr('_', '-')
32
+ @#{name}s[name] = value unless try_set_#{name}(name, value)
33
+ end
34
+
35
+ def try_set_#{name}(name, value)
36
+ @#{name}s ||= {}
37
+ if @#{name}s.include?(name)
38
+ @#{name}s[name] = value
39
+ true
40
+ elsif @parent
41
+ @parent.try_set_#{name}(name, value)
42
+ else
43
+ false
44
+ end
45
+ end
46
+ protected :try_set_#{name}
47
+
48
+ def set_local_#{name}(name, value)
49
+ @#{name}s ||= {}
50
+ @#{name}s[name.tr('_', '-')] = value
51
+ end
52
+ RUBY
53
+ end
54
+ end
55
+
56
+ # The options passed to the Sass Engine.
21
57
  attr_reader :options
58
+
59
+ # [Environment] The caller environment
22
60
  attr_writer :caller
61
+
62
+ # [Environment] The content environment
23
63
  attr_writer :content
24
64
  attr_writer :selector
25
65
 
66
+ # variable
67
+ # Script::Value
68
+ inherited_hash_reader :var
69
+
70
+ # mixin
71
+ # Sass::Callable
72
+ inherited_hash_reader :mixin
73
+
74
+ # function
75
+ # Sass::Callable
76
+ inherited_hash_reader :function
77
+
26
78
  # @param options [{Symbol => Object}] The options hash. See
27
79
  # {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
28
80
  # @param parent [Environment] See \{#parent}
@@ -38,7 +90,7 @@ module Sass
38
90
  @caller || (@parent && @parent.caller)
39
91
  end
40
92
 
41
- # The content passed to this environmnet. This is naturally only set
93
+ # The content passed to this environment. This is naturally only set
42
94
  # for mixin body environments with content passed in.
43
95
  # @return {Environment?}
44
96
  def content
@@ -70,62 +122,59 @@ module Sass
70
122
  def stack
71
123
  @stack || global_env.stack
72
124
  end
125
+ end
73
126
 
74
- private
75
-
76
- class << self
77
-
78
- private
79
-
80
- UNDERSCORE, DASH = '_', '-'
81
-
82
- # Note: when updating this,
83
- # update sass/yard/inherited_hash.rb as well.
84
- def inherited_hash(name)
85
- class_eval <<RUBY, __FILE__, __LINE__ + 1
86
- def #{name}(name)
87
- _#{name}(name.tr(UNDERSCORE, DASH))
88
- end
89
-
90
- def _#{name}(name)
91
- (@#{name}s && @#{name}s[name]) || @parent && @parent._#{name}(name)
92
- end
93
- protected :_#{name}
94
-
95
- def set_#{name}(name, value)
96
- name = name.tr(UNDERSCORE, DASH)
97
- @#{name}s[name] = value unless try_set_#{name}(name, value)
98
- end
99
-
100
- def try_set_#{name}(name, value)
101
- @#{name}s ||= {}
102
- if @#{name}s.include?(name)
103
- @#{name}s[name] = value
104
- true
105
- elsif @parent
106
- @parent.try_set_#{name}(name, value)
107
- else
108
- false
109
- end
110
- end
111
- protected :try_set_#{name}
112
-
113
- def set_local_#{name}(name, value)
114
- @#{name}s ||= {}
115
- @#{name}s[name.tr(UNDERSCORE, DASH)] = value
116
- end
117
- RUBY
118
- end
119
- end
127
+ # The lexical environment for SassScript.
128
+ # This keeps track of variable, mixin, and function definitions.
129
+ #
130
+ # A new environment is created for each level of Sass nesting.
131
+ # This allows variables to be lexically scoped.
132
+ # The new environment refers to the environment in the upper scope,
133
+ # so it has access to variables defined in enclosing scopes,
134
+ # but new variables are defined locally.
135
+ #
136
+ # Environment also keeps track of the {Engine} options
137
+ # so that they can be made available to {Sass::Script::Functions}.
138
+ class Environment < BaseEnvironment
139
+ # The enclosing environment,
140
+ # or nil if this is the global environment.
141
+ #
142
+ # @return [Environment]
143
+ attr_reader :parent
120
144
 
121
145
  # variable
122
146
  # Script::Value
123
- inherited_hash :var
147
+ inherited_hash_writer :var
148
+
124
149
  # mixin
125
150
  # Sass::Callable
126
- inherited_hash :mixin
151
+ inherited_hash_writer :mixin
152
+
127
153
  # function
128
154
  # Sass::Callable
129
- inherited_hash :function
155
+ inherited_hash_writer :function
156
+ end
157
+
158
+ # A read-only wrapper for a lexical environment for SassScript.
159
+ class ReadOnlyEnvironment < BaseEnvironment
160
+ # The read-only environment of the caller of this environment's mixin or function.
161
+ #
162
+ # @see BaseEnvironment#caller
163
+ # @return {ReadOnlyEnvironment}
164
+ def caller
165
+ return @caller if @caller
166
+ env = super
167
+ @caller ||= env.is_a?(ReadOnlyEnvironment) ? env : ReadOnlyEnvironment.new(env, env.options)
168
+ end
169
+
170
+ # The read-only content passed to this environment.
171
+ #
172
+ # @see BaseEnvironment#content
173
+ # @return {ReadOnlyEnvironment}
174
+ def content
175
+ return @content if @content
176
+ env = super
177
+ @content ||= env.is_a?(ReadOnlyEnvironment) ? env : ReadOnlyEnvironment.new(env, env.options)
178
+ end
130
179
  end
131
180
  end
@@ -207,6 +207,18 @@ module Sass::Script
207
207
  # \{#feature_exists feature-exists($feature)}
208
208
  # : Returns whether a feature exists in the current Sass runtime.
209
209
  #
210
+ # \{#variable_exists variable-exists($name)}
211
+ # : Returns whether a variable with the given name exists in the current scope.
212
+ #
213
+ # \{#global_variable_exists global-variable-exists($name)}
214
+ # : Returns whether a variable with the given name exists in the global scope.
215
+ #
216
+ # \{#function_exists function-exists($name)}
217
+ # : Returns whether a function with the given name exists.
218
+ #
219
+ # \{#mixin_exists mixin-exists($name)}
220
+ # : Returns whether a mixin with the given name exists.
221
+ #
210
222
  # \{#type_of type-of($value)}
211
223
  # : Returns the type of a value.
212
224
  #
@@ -2033,6 +2045,79 @@ module Sass::Script
2033
2045
  end
2034
2046
  declare :counters, [], :var_args => true
2035
2047
 
2048
+ # Check whether a variable with the given name exists in the current
2049
+ # scope or in the global scope.
2050
+ #
2051
+ # @example
2052
+ # $a-false-value: false;
2053
+ # variable-exists(a-false-value) => true
2054
+ #
2055
+ # variable-exists(nonexistent) => false
2056
+ # @param name [Sass::Script::String] The name of the variable to
2057
+ # check. The name should not include the `$`.
2058
+ # @return [Sass::Script::Bool] Whether the variable is defined in
2059
+ # the current scope.
2060
+ def variable_exists(name)
2061
+ assert_type name, :String
2062
+ Sass::Script::Value::Bool.new(environment.caller.var(name.value))
2063
+ end
2064
+ declare :variable_exists, [:name]
2065
+
2066
+ # Check whether a variable with the given name exists in the global
2067
+ # scope (at the top level of the file).
2068
+ #
2069
+ # @example
2070
+ # $a-false-value: false;
2071
+ # global-variable-exists(a-false-value) => true
2072
+ #
2073
+ # .foo {
2074
+ # $some-var: false;
2075
+ # @if global-variable-exists(some-var) { /* false, doesn't run */ }
2076
+ # }
2077
+ # @param name [Sass::Script::String] The name of the variable to
2078
+ # check. The name should not include the `$`.
2079
+ # @return [Sass::Script::Bool] Whether the variable is defined in
2080
+ # the global scope.
2081
+ def global_variable_exists(name)
2082
+ assert_type name, :String
2083
+ Sass::Script::Value::Bool.new(environment.global_env.var(name.value))
2084
+ end
2085
+ declare :global_variable_exists, [:name]
2086
+
2087
+ # Check whether a function with the given name exists.
2088
+ #
2089
+ # @example
2090
+ # function-exists(lighten) => true
2091
+ #
2092
+ # @function myfunc { @return "something"; }
2093
+ # function-exists(myfunc) => true
2094
+ # @param name [Sass::Script::String] The name of the function to
2095
+ # check.
2096
+ # @return [Sass::Script::Bool] Whether the function is defined.
2097
+ def function_exists(name)
2098
+ assert_type name, :String
2099
+ exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
2100
+ exists ||= environment.function(name.value)
2101
+ Sass::Script::Value::Bool.new(exists)
2102
+ end
2103
+ declare :function_exists, [:name]
2104
+
2105
+ # Check whether a mixin with the given name exists.
2106
+ #
2107
+ # @example
2108
+ # mixin-exists(nonexistent) => false
2109
+ #
2110
+ # @mixin red-text { color: red; }
2111
+ # mixin-exists(red-text) => true
2112
+ # @param name [Sass::Script::String] The name of the mixin to
2113
+ # check.
2114
+ # @return [Sass::Script::Bool] Whether the mixin is defined.
2115
+ def mixin_exists(name)
2116
+ assert_type name, :String
2117
+ Sass::Script::Value::Bool.new(environment.mixin(name.value))
2118
+ end
2119
+ declare :mixin_exists, [:name]
2120
+
2036
2121
  private
2037
2122
 
2038
2123
  # This method implements the pattern of transforming a numeric value into
@@ -131,6 +131,7 @@ module Sass::Script::Tree
131
131
 
132
132
  if Sass::Script::Functions.callable?(ruby_name)
133
133
  local_environment = Sass::Environment.new(environment.global_env, environment.options)
134
+ local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
134
135
  opts(Sass::Script::Functions::EvaluationContext.new(
135
136
  local_environment).send(ruby_name, *args))
136
137
  else
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
3
  require File.dirname(__FILE__) + '/../test_helper'
4
+ require File.dirname(__FILE__) + '/test_helper'
4
5
  require 'sass/script'
6
+ require 'mock_importer'
5
7
 
6
8
  module Sass::Script::Functions
7
9
  def no_kw_args
@@ -1450,6 +1452,100 @@ WARNING
1450
1452
  assert_error_message "$color: 3px is not a color for `lighten'", "call(lighten, 3px, 5%)"
1451
1453
  end
1452
1454
 
1455
+ def test_variable_exists
1456
+ assert_equal <<CSS, render(<<SCSS)
1457
+ .test {
1458
+ false: false;
1459
+ true: true;
1460
+ true: true;
1461
+ true: true;
1462
+ true: true; }
1463
+ CSS
1464
+ $global-var: has-value;
1465
+ .test {
1466
+ false: variable-exists(foo);
1467
+ $foo: has-value;
1468
+ true: variable-exists(foo);
1469
+ true: variable-exists($name: foo);
1470
+ true: variable-exists(global-var);
1471
+ true: variable-exists($name: global-var);
1472
+ }
1473
+ SCSS
1474
+ end
1475
+
1476
+ def test_global_variable_exists
1477
+ assert_equal <<CSS, render(<<SCSS)
1478
+ .test {
1479
+ false: false;
1480
+ false: false;
1481
+ true: true;
1482
+ true: true;
1483
+ false: false;
1484
+ true: true;
1485
+ true: true; }
1486
+ CSS
1487
+ $g: something;
1488
+ $h: null;
1489
+ $false: global-variable-exists(foo);
1490
+ $true: global-variable-exists(g);
1491
+ $named: global-variable-exists($name: g);
1492
+ .test {
1493
+ $foo: locally-defined;
1494
+ false: global-variable-exists(foo);
1495
+ false: global-variable-exists(foo2);
1496
+ true: global-variable-exists(g);
1497
+ true: global-variable-exists(h);
1498
+ false: $false;
1499
+ true: $true;
1500
+ true: $named;
1501
+ }
1502
+ SCSS
1503
+ end
1504
+
1505
+ def test_function_exists
1506
+ # built-ins
1507
+ assert_equal "true", evaluate("function-exists(lighten)")
1508
+ # with named argument
1509
+ assert_equal "true", evaluate("function-exists($name: lighten)")
1510
+ # user-defined
1511
+ assert_equal <<CSS, render(<<SCSS)
1512
+ .test {
1513
+ foo-exists: true;
1514
+ bar-exists: false; }
1515
+ CSS
1516
+ @function foo() { @return "foo" }
1517
+ .test {
1518
+ foo-exists: function-exists(foo);
1519
+ bar-exists: function-exists(bar);
1520
+ }
1521
+ SCSS
1522
+ end
1523
+
1524
+ def test_mixin_exists
1525
+ assert_equal "false", evaluate("mixin-exists(foo)")
1526
+ # with named argument
1527
+ assert_equal "false", evaluate("mixin-exists($name: foo)")
1528
+ assert_equal <<CSS, render(<<SCSS)
1529
+ .test {
1530
+ foo-exists: true;
1531
+ bar-exists: false; }
1532
+ CSS
1533
+ @mixin foo() { foo: exists }
1534
+ .test {
1535
+ foo-exists: mixin-exists(foo);
1536
+ bar-exists: mixin-exists(bar);
1537
+ }
1538
+ SCSS
1539
+ end
1540
+
1541
+ def test_existence_functions_check_argument_type
1542
+ assert_error_message("2px is not a string for `function-exists'", "function-exists(2px)")
1543
+ assert_error_message("2px is not a string for `mixin-exists'", "mixin-exists(2px)")
1544
+ assert_error_message("2px is not a string for `global-variable-exists'", "global-variable-exists(2px)")
1545
+ assert_error_message("2px is not a string for `variable-exists'", "variable-exists(2px)")
1546
+ end
1547
+
1548
+
1453
1549
  ## Regression Tests
1454
1550
 
1455
1551
  def test_saturation_bounds
@@ -1457,8 +1553,8 @@ WARNING
1457
1553
  end
1458
1554
 
1459
1555
  private
1460
- def env(hash = {})
1461
- env = Sass::Environment.new
1556
+ def env(hash = {}, parent = nil)
1557
+ env = Sass::Environment.new(parent)
1462
1558
  hash.each {|k, v| env.set_var(k, v)}
1463
1559
  env
1464
1560
  end
@@ -1473,6 +1569,13 @@ WARNING
1473
1569
  Sass::Script::Parser.parse(value, 0, 0).perform(environment)
1474
1570
  end
1475
1571
 
1572
+ def render(sass, options = {})
1573
+ options[:syntax] ||= :scss
1574
+ munge_filename options
1575
+ options[:importer] ||= MockImporter.new
1576
+ Sass::Engine.new(sass, options).render
1577
+ end
1578
+
1476
1579
  def assert_error_message(message, value)
1477
1580
  evaluate(value)
1478
1581
  flunk("Error message expected but not raised: #{message}")
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass
3
3
  version: !ruby/object:Gem::Version
4
- hash: 592302537
4
+ hash: 592302549
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 3
9
9
  - 0
10
10
  - alpha
11
- - 354
12
- version: 3.3.0.alpha.354
11
+ - 364
12
+ version: 3.3.0.alpha.364
13
13
  platform: ruby
14
14
  authors:
15
15
  - Nathan Weizenbaum
@@ -19,7 +19,7 @@ autorequire:
19
19
  bindir: bin
20
20
  cert_chain: []
21
21
 
22
- date: 2013-10-04 00:00:00 -04:00
22
+ date: 2013-10-05 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency