sass 3.1.0.alpha.48 → 3.1.0.alpha.49

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.
@@ -13,7 +13,7 @@ module Sass::Tree
13
13
 
14
14
  # The name of the property
15
15
  # after any interpolated SassScript has been resolved.
16
- # Only set once \{Tree::Node#perform} has been called.
16
+ # Only set once \{Tree::Visitors::Perform} has been run.
17
17
  #
18
18
  # @return [String]
19
19
  attr_accessor :resolved_name
@@ -25,7 +25,7 @@ module Sass::Tree
25
25
 
26
26
  # The value of the property
27
27
  # after any interpolated SassScript has been resolved.
28
- # Only set once \{Tree::Node#perform} has been called.
28
+ # Only set once \{Tree::Visitors::Perform} has been run.
29
29
  #
30
30
  # @return [String]
31
31
  attr_accessor :resolved_value
@@ -74,73 +74,22 @@ module Sass::Tree
74
74
  "\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
75
75
  end
76
76
 
77
- protected
78
-
79
- # @see Node#to_src
80
- def to_src(tabs, opts, fmt)
81
- res = declaration(tabs, opts, fmt)
82
- return res + "#{semi fmt}\n" if children.empty?
83
- res + children_to_src(tabs, opts, fmt).rstrip + semi(fmt) + "\n"
84
- end
85
-
86
- # Computes the CSS for the property.
87
- #
88
- # @param tabs [Fixnum] The level of indentation for the CSS
89
- # @return [String] The resulting CSS
90
- def _to_s(tabs)
91
- tab_str = ' ' * (tabs - 1 + self.tabs)
92
- if style == :compressed
93
- "#{tab_str}#{resolved_name}:#{resolved_value}"
94
- else
95
- "#{tab_str}#{resolved_name}: #{resolved_value};"
96
- end
97
- end
98
-
99
- # Converts nested properties into flat properties.
77
+ # Computes the Sass or SCSS code for the variable declaration.
78
+ # This is like \{#to\_scss} or \{#to\_sass},
79
+ # except it doesn't print any child properties or a trailing semicolon.
100
80
  #
101
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
102
- # The extensions defined for this tree
103
- # @param parent [PropNode, nil] The parent node of this node,
104
- # or nil if the parent isn't a {PropNode}
105
- # @raise [Sass::SyntaxError] if the property uses invalid syntax
106
- def _cssize(extends, parent)
107
- node = super
108
- result = node.children.dup
109
- if !node.resolved_value.empty? || node.children.empty?
110
- node.send(:check!)
111
- result.unshift(node)
81
+ # @param opts [{Symbol => Object}] The options hash for the tree.
82
+ # @param fmt [Symbol] `:scss` or `:sass`.
83
+ def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
84
+ name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
85
+ if name[0] == ?:
86
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
112
87
  end
113
- result
114
- end
115
88
 
116
- # Updates the name and indentation of this node based on the parent name
117
- # and nesting level.
118
- #
119
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
120
- # The extensions defined for this tree
121
- # @param parent [PropNode, nil] The parent node of this node,
122
- # or nil if the parent isn't a {PropNode}
123
- def cssize!(extends, parent)
124
- self.resolved_name = "#{parent.resolved_name}-#{resolved_name}" if parent
125
- self.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if parent && style == :nested
126
- super
127
- end
128
-
129
- # Runs any SassScript that may be embedded in the property,
130
- # and invludes the parent property, if any.
131
- #
132
- # @param environment [Sass::Environment] The lexical environment containing
133
- # variable and mixin values
134
- def perform!(environment)
135
- @resolved_name = run_interp(@name, environment)
136
- val = @value.perform(environment)
137
- @resolved_value =
138
- if @value.context == :equals && val.is_a?(Sass::Script::String)
139
- val.value
140
- else
141
- val.to_s
142
- end
143
- super
89
+ old = opts[:old] && fmt == :sass
90
+ initial = old ? ':' : ''
91
+ mid = old ? '' : ':'
92
+ "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
144
93
  end
145
94
 
146
95
  # Returns an error message if the given child node is invalid,
@@ -167,18 +116,6 @@ module Sass::Tree
167
116
  end
168
117
  end
169
118
 
170
- def declaration(tabs = 0, opts = {:old => @prop_syntax == :old}, fmt = :sass)
171
- name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
172
- if name[0] == ?:
173
- raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
174
- end
175
-
176
- old = opts[:old] && fmt == :sass
177
- initial = old ? ':' : ''
178
- mid = old ? '' : ':'
179
- "#{' ' * tabs}#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
180
- end
181
-
182
119
  class << self
183
120
  # @private
184
121
  def val_to_sass(value, opts)
@@ -13,134 +13,14 @@ module Sass
13
13
  @template = template
14
14
  end
15
15
 
16
- # @see Node#to_s
17
- def to_s(*args)
18
- super
19
- rescue Sass::SyntaxError => e
20
- e.sass_template ||= @template
21
- raise e
22
- end
23
-
24
16
  # Runs the dynamic Sass code *and* computes the CSS for the tree.
25
- #
26
- # @see #perform
27
17
  # @see #to_s
28
18
  def render
29
- result, extends = perform(Environment.new).cssize
19
+ result, extends = Visitors::Cssize.visit(Visitors::Perform.visit(self))
30
20
  result = result.do_extend(extends) unless extends.empty?
31
21
  result.to_s
32
22
  end
33
23
 
34
- # @see Node#perform
35
- def perform(environment)
36
- environment.options = @options if environment.options.nil? || environment.options.empty?
37
- super
38
- rescue Sass::SyntaxError => e
39
- e.sass_template ||= @template
40
- raise e
41
- end
42
-
43
- # Like {Node#cssize}, except that this method
44
- # will create its own `extends` map if necessary,
45
- # and it returns that map along with the cssized tree.
46
- #
47
- # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
48
- # *and* the extensions defined for this tree
49
- def cssize(extends = Sass::Util::SubsetMap.new, parent = nil)
50
- return super(extends, parent), extends
51
- rescue Sass::SyntaxError => e
52
- e.sass_template ||= @template
53
- raise e
54
- end
55
-
56
- # @see \{Node#perform!}
57
- def perform!(environment)
58
- environment.options = @options if environment.options.nil? || environment.options.empty?
59
- super
60
- end
61
-
62
- # Converts a node to Sass code that will generate it.
63
- #
64
- # @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
65
- # @return [String] The Sass code corresponding to the node
66
- def to_sass(opts = {})
67
- to_src(opts, :sass)
68
- end
69
-
70
- # Converts a node to SCSS code that will generate it.
71
- #
72
- # @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
73
- # @return [String] The SCSS code corresponding to the node
74
- def to_scss(opts = {})
75
- to_src(opts, :scss)
76
- end
77
-
78
- protected
79
-
80
- # @see Node#to_src
81
- def to_src(opts, fmt)
82
- Sass::Util.enum_cons(children + [nil], 2).map do |child, nxt|
83
- child.send("to_#{fmt}", 0, opts) +
84
- if nxt &&
85
- (child.is_a?(CommentNode) && child.line + child.value.count("\n") + 1 == nxt.line) ||
86
- (child.is_a?(ImportNode) && nxt.is_a?(ImportNode) && child.line + 1 == nxt.line) ||
87
- (child.is_a?(VariableNode) && nxt.is_a?(VariableNode) && child.line + 1 == nxt.line)
88
- ""
89
- else
90
- "\n"
91
- end
92
- end.join.rstrip + "\n"
93
- end
94
-
95
- # Computes the CSS corresponding to this Sass tree.
96
- #
97
- # @param args [Array] ignored
98
- # @return [String] The resulting CSS
99
- # @see Sass::Tree
100
- def _to_s(*args)
101
- result = String.new
102
- children.each do |child|
103
- next if child.invisible?
104
- child_str = child.to_s(1)
105
- result << child_str + (style == :compressed ? '' : "\n")
106
- end
107
- result.rstrip!
108
- return "" if result.empty?
109
- result << "\n"
110
- unless Sass::Util.ruby1_8? || result.ascii_only?
111
- if children.first.is_a?(CharsetNode)
112
- begin
113
- encoding = children.first.name
114
- # Default to big-endian encoding, because we have to decide somehow
115
- encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i
116
- result = result.encode(Encoding.find(encoding))
117
- rescue EncodingError
118
- end
119
- end
120
-
121
- result = "@charset \"#{result.encoding.name}\";#{
122
- style == :compressed ? '' : "\n"
123
- }".encode(result.encoding) + result
124
- end
125
- result
126
- end
127
-
128
- # In Ruby 1.8, ensures that there's only one @charset directive
129
- # and that it's at the top of the document.
130
- #
131
- # @see Node#cssize
132
- def cssize!(extends, parent)
133
- super
134
-
135
- # In Ruby 1.9 we can make all @charset nodes invisible
136
- # and infer the final @charset from the encoding of the final string.
137
- if Sass::Util.ruby1_8? && parent.nil?
138
- charset = self.children.find {|c| c.is_a?(CharsetNode)}
139
- self.children.reject! {|c| c.is_a?(CharsetNode)}
140
- self.children.unshift charset if charset
141
- end
142
- end
143
-
144
24
  # Returns an error message if the given child node is invalid,
145
25
  # and false otherwise.
146
26
  #
@@ -27,7 +27,7 @@ module Sass::Tree
27
27
 
28
28
  # The CSS selector for this rule,
29
29
  # without any unresolved interpolation or parent references.
30
- # It's only set once {Tree::Node#cssize} has been called.
30
+ # It's only set once {Tree::Visitors::Cssize} has been run.
31
31
  #
32
32
  # @return [Selector::CommaSequence]
33
33
  attr_accessor :resolved_rules
@@ -82,26 +82,6 @@ module Sass::Tree
82
82
  last.is_a?(String) && last[-1] == ?,
83
83
  end
84
84
 
85
- # @see Node#to_sass
86
- def to_sass(tabs, opts = {})
87
- name = selector_to_sass(rule, opts)
88
- name = "\\" + name if name[0] == ?:
89
- name.gsub(/^/, ' ' * tabs) + children_to_src(tabs, opts, :sass)
90
- end
91
-
92
- # @see Node#to_scss
93
- def to_scss(tabs, opts = {})
94
- name = selector_to_scss(rule, tabs, opts)
95
- res = name + children_to_src(tabs, opts, :scss)
96
-
97
- if children.last.is_a?(CommentNode) && children.last.silent
98
- res.slice!(-3..-1)
99
- res << "\n" << (' ' * tabs) << "}\n"
100
- end
101
-
102
- res
103
- end
104
-
105
85
  # Extends this Rule's selector with the given `extends`.
106
86
  #
107
87
  # @see Node#do_extend
@@ -111,120 +91,6 @@ module Sass::Tree
111
91
  node
112
92
  end
113
93
 
114
- protected
115
-
116
- # Computes the CSS for the rule.
117
- #
118
- # @param tabs [Fixnum] The level of indentation for the CSS
119
- # @return [String] The resulting CSS
120
- def _to_s(tabs)
121
- output_style = style
122
- tabs = tabs + self.tabs
123
-
124
- rule_separator = output_style == :compressed ? ',' : ', '
125
- line_separator =
126
- case output_style
127
- when :nested, :expanded; "\n"
128
- when :compressed; ""
129
- else; " "
130
- end
131
- rule_indent = ' ' * (tabs - 1)
132
- per_rule_indent, total_indent = [:nested, :expanded].include?(output_style) ? [rule_indent, ''] : ['', rule_indent]
133
-
134
- total_rule = total_indent + resolved_rules.members.
135
- map {|seq| seq.to_a.join.gsub(/([^,])\n/m, style == :compressed ? '\1 ' : "\\1\n")}.
136
- join(rule_separator).split("\n").map do |line|
137
- per_rule_indent + line.strip
138
- end.join(line_separator)
139
-
140
- to_return = ''
141
- old_spaces = ' ' * (tabs - 1)
142
- spaces = ' ' * tabs
143
- if output_style != :compressed
144
- if @options[:debug_info]
145
- to_return << debug_info_rule.to_s(tabs) << "\n"
146
- elsif @options[:line_comments]
147
- to_return << "#{old_spaces}/* line #{line}"
148
-
149
- if filename
150
- relative_filename = if @options[:css_filename]
151
- begin
152
- Pathname.new(filename).relative_path_from(
153
- Pathname.new(File.dirname(@options[:css_filename]))).to_s
154
- rescue ArgumentError
155
- nil
156
- end
157
- end
158
- relative_filename ||= filename
159
- to_return << ", #{relative_filename}"
160
- end
161
-
162
- to_return << " */\n"
163
- end
164
- end
165
-
166
- if output_style == :compact
167
- properties = children.map { |a| a.to_s(1) }.join(' ')
168
- to_return << "#{total_rule} { #{properties} }#{"\n" if group_end}"
169
- elsif output_style == :compressed
170
- properties = children.map { |a| a.to_s(1) }.join(';')
171
- to_return << "#{total_rule}{#{properties}}"
172
- else
173
- properties = children.map { |a| a.to_s(tabs + 1) }.join("\n")
174
- end_props = (output_style == :expanded ? "\n" + old_spaces : ' ')
175
- to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n" if group_end}"
176
- end
177
-
178
- to_return
179
- end
180
-
181
- # Runs SassScript interpolation in the selector,
182
- # and then parses the result into a {Sass::Selector::CommaSequence}.
183
- #
184
- # @param environment [Sass::Environment] The lexical environment containing
185
- # variable and mixin values
186
- def perform!(environment)
187
- @parsed_rules = Sass::SCSS::StaticParser.new(run_interp(@rule, environment), self.line).
188
- parse_selector(self.filename)
189
- super
190
- end
191
-
192
- # Converts nested rules into a flat list of rules.
193
- #
194
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
195
- # The extensions defined for this tree
196
- # @param parent [RuleNode, nil] The parent node of this node,
197
- # or nil if the parent isn't a {RuleNode}
198
- def _cssize(extends, parent)
199
- node = super
200
- rules = node.children.select {|c| c.is_a?(RuleNode) || c.is_a?(MediaNode)}
201
- props = node.children.reject {|c| c.is_a?(RuleNode) || c.is_a?(MediaNode) || c.invisible?}
202
-
203
- unless props.empty?
204
- node.children = props
205
- rules.each {|r| r.tabs += 1} if style == :nested
206
- rules.unshift(node)
207
- end
208
-
209
- rules.last.group_end = true unless parent || rules.empty?
210
-
211
- rules
212
- end
213
-
214
- # Resolves parent references and nested selectors,
215
- # and updates the indentation based on the parent's indentation.
216
- #
217
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
218
- # The extensions defined for this tree
219
- # @param parent [RuleNode, nil] The parent node of this node,
220
- # or nil if the parent isn't a {RuleNode}
221
- # @raise [Sass::SyntaxError] if the rule has no parents but uses `&`
222
- def cssize!(extends, parent)
223
- # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
224
- self.resolved_rules ||= @parsed_rules.resolve_parent_refs(parent && parent.resolved_rules)
225
- super
226
- end
227
-
228
94
  # A hash that will be associated with this rule in the CSS document
229
95
  # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
230
96
  # This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
@@ -234,27 +100,5 @@ module Sass::Tree
234
100
  {:filename => filename && ("file://" + URI.escape(File.expand_path(filename))),
235
101
  :line => self.line}
236
102
  end
237
-
238
- private
239
-
240
- def debug_info_rule
241
- node = DirectiveNode.new("@media -sass-debug-info")
242
- debug_info.map {|k, v| [k.to_s, v.to_s]}.sort.each do |k, v|
243
- rule = RuleNode.new([""])
244
- rule.resolved_rules = Sass::Selector::CommaSequence.new(
245
- [Sass::Selector::Sequence.new(
246
- [Sass::Selector::SimpleSequence.new(
247
- [Sass::Selector::Element.new(k.to_s.gsub(/[^\w-]/, "\\\\\\0"), nil)])
248
- ])
249
- ])
250
- prop = PropNode.new([""], "", :new)
251
- prop.resolved_name = "font-family"
252
- prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
253
- rule << prop
254
- node << rule
255
- end
256
- node.options = @options.merge(:debug_info => false, :line_comments => false, :style => :compressed)
257
- node
258
- end
259
103
  end
260
104
  end
@@ -4,36 +4,27 @@ module Sass
4
4
  #
5
5
  # @see Sass::Tree
6
6
  class VariableNode < Node
7
+ # The name of the variable.
8
+ # @return [String]
9
+ attr_reader :name
10
+
11
+ # The parse tree for the variable value.
12
+ # @return [Script::Node]
13
+ attr_reader :expr
14
+
15
+ # Whether this is a guarded variable assignment (`!default`).
16
+ # @return [Boolean]
17
+ attr_reader :guarded
18
+
7
19
  # @param name [String] The name of the variable
8
- # @param expr [Script::Node] The parse tree for the initial variable value
9
- # @param guarded [Boolean] Whether this is a guarded variable assignment (`||=`)
20
+ # @param expr [Script::Node] See \{#expr}
21
+ # @param guarded [Boolean] See \{#guarded}
10
22
  def initialize(name, expr, guarded)
11
23
  @name = name
12
24
  @expr = expr
13
25
  @guarded = guarded
14
26
  super()
15
27
  end
16
-
17
- protected
18
-
19
- # @see Node#to_src
20
- def to_src(tabs, opts, fmt)
21
- "#{' ' * tabs}$#{dasherize(@name, opts)}: #{@expr.to_sass(opts)}#{' !default' if @guarded}#{semi fmt}\n"
22
- end
23
-
24
- # Loads the new variable value into the environment.
25
- #
26
- # @param environment [Sass::Environment] The lexical environment containing
27
- # variable and mixin values
28
- def _perform(environment)
29
- return [] if @guarded && !environment.var(@name).nil?
30
- val = @expr.perform(environment)
31
- if @expr.context == :equals && val.is_a?(Sass::Script::String)
32
- val = Sass::Script::String.new(val.value)
33
- end
34
- environment.set_var(@name, val)
35
- []
36
- end
37
28
  end
38
29
  end
39
30
  end