Class: Sass::Tree::Node

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/sass/tree/node.rb

Overview

The abstract superclass of all parse-tree nodes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNode

Returns a new instance of Node.



59
60
61
# File 'lib/sass/tree/node.rb', line 59

def initialize
  @children = []
end

Instance Attribute Details

#childrenArray<Tree::Node>

The child nodes of this node.

Returns:



34
35
36
# File 'lib/sass/tree/node.rb', line 34

def children
  @children
end

#filenameString

The name of the document on which this node appeared.

Returns:

  • (String)


81
82
83
# File 'lib/sass/tree/node.rb', line 81

def filename
  @filename || (@options && @options[:filename])
end

#has_childrenBoolean

Whether or not this node has child nodes. This may be true even when #children is empty, in which case this node has an empty block (e.g. {}).

Returns:

  • (Boolean)


41
42
43
# File 'lib/sass/tree/node.rb', line 41

def has_children
  @has_children
end

#lineFixnum

The line of the document on which this node appeared.

Returns:

  • (Fixnum)


46
47
48
# File 'lib/sass/tree/node.rb', line 46

def line
  @line
end

#options{Symbol => Object}

The options hash for the node. See the Sass options documentation.

Returns:

  • ({Symbol => Object})


57
58
59
# File 'lib/sass/tree/node.rb', line 57

def options
  @options
end

Instance Method Details

#<<(child)

Appends a child to the node.

Parameters:

Raises:

See Also:



90
91
92
93
94
95
# File 'lib/sass/tree/node.rb', line 90

def <<(child)
  return if child.nil?
  check_child! child
  self.has_children = true
  @children << child
end

#==(other) ⇒ Boolean

Compares this node and another object (only other Sass::Tree::Nodes will be equal). This does a structural comparison; if the contents of the nodes and all the child nodes are equivalent, then the nodes are as well.

Only static nodes need to override this.

Parameters:

  • other (Object)

    The object to compare with

Returns:

  • (Boolean)

    Whether or not this node and the other object are the same

See Also:



119
120
121
# File 'lib/sass/tree/node.rb', line 119

def ==(other)
  self.class == other.class && other.children == children
end

#_cssize(extends, parent) ⇒ Tree::Node+ (protected)

Converts this static Sass node into a static CSS node, returning the new node. This doesn't modify this node or any of its children.

Parameters:

Returns:

Raises:

See Also:



283
284
285
286
287
# File 'lib/sass/tree/node.rb', line 283

def _cssize(extends, parent)
  node = dup
  node.cssize!(extends, parent)
  node
end

#_perform(environment) ⇒ Tree::Node+ (protected)

Runs any dynamic Sass code in this particular node. This doesn't modify this node or any of its children.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

See Also:



310
311
312
313
314
# File 'lib/sass/tree/node.rb', line 310

def _perform(environment)
  node = dup
  node.perform!(environment)
  node
end

#_to_sString? (protected)

Computes the CSS corresponding to this particular Sass node.

This method should never raise SyntaxErrors. Such errors will not be properly annotated with Sass backtrace information. All error conditions should be checked in earlier transformations, such as #cssize and #perform.

Parameters:

  • args (Array)

    ignored

Returns:

  • (String, nil)

    The resulting CSS

Raises:

  • (NotImplementedError)

See Also:



267
268
269
# File 'lib/sass/tree/node.rb', line 267

def _to_s
  raise NotImplementedError.new("All static-node subclasses of Sass::Tree::Node must override #_to_s or #to_s.")
end

#balance(*args) (protected)

Raises:

See Also:

  • Haml::Shared.balance


355
356
357
358
359
# File 'lib/sass/tree/node.rb', line 355

def balance(*args)
  res = Haml::Shared.balance(*args)
  return res if res
  raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
end

#check_child!(child)

Raises an error if the given child node is invalid.

Parameters:

Raises:

See Also:



102
103
104
105
106
# File 'lib/sass/tree/node.rb', line 102

def check_child!(child)
  if msg = invalid_child?(child)
    raise Sass::SyntaxError.new(msg, :line => child.line)
  end
end

#children_to_src(tabs, opts, fmt) ⇒ String (protected)

Converts the children of this node to a Sass or SCSS string. This will return the trailing newline for the previous line, including brackets if this is SCSS.

Parameters:

  • tabs (Fixnum)

    The amount of tabulation to use for the Sass code

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    The Sass or CSS code corresponding to the children



404
405
406
407
408
# File 'lib/sass/tree/node.rb', line 404

def children_to_src(tabs, opts, fmt)
  (fmt == :sass ? "\n" : " {\n") +
    children.map {|c| c.send("to_#{fmt}", tabs + 1, opts)}.join.rstrip +
    (fmt == :sass ? "\n" : " }\n")
end

#cssize(extends, parent = nil) ⇒ Tree::Node

Converts a static Sass tree (e.g. the output of #perform) into a static CSS tree.

#cssize shouldn't be overridden directly; instead, override #_cssize or #cssize!.

Parameters:

Returns:

  • (Tree::Node)

    The resulting tree of static nodes

Raises:

See Also:



199
200
201
202
203
204
# File 'lib/sass/tree/node.rb', line 199

def cssize(extends, parent = nil)
  _cssize(extends, (parent if parent.class == self.class))
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#cssize!(extends, parent) (protected)

Destructively converts this static Sass node into a static CSS node. This does modify this node, but will be run non-destructively by #_cssize.

Parameters:

See Also:



298
299
300
# File 'lib/sass/tree/node.rb', line 298

def cssize!(extends, parent)
  self.children = children.map {|c| c.cssize(extends, self)}.flatten
end

#dasherize(s, opts) ⇒ String (protected)

Convert any underscores in a string into hyphens, but only if the :dasherize option is set.

Parameters:

  • s (String)

    The string to convert

  • opts ({Symbol => Object})

    The options hash

Returns:

  • (String)

    The converted string



416
417
418
419
420
421
422
# File 'lib/sass/tree/node.rb', line 416

def dasherize(s, opts)
  if opts[:dasherize]
    s.gsub('_', '-')
  else
    s
  end
end

#do_extend(extends) ⇒ Tree::Node

TODO:

Link this to the reference documentation on @extend when such a thing exists.

Converts a static CSS tree (e.g. the output of #cssize) into another static CSS tree, with the given extensions applied to all relevant RuleNodes.

Parameters:

Returns:

  • (Tree::Node)

    The resulting tree of static CSS nodes.

Raises:

  • (Sass::SyntaxError)

    Only if there's a programmer error and this is not a static CSS tree



177
178
179
180
181
182
183
184
# File 'lib/sass/tree/node.rb', line 177

def do_extend(extends)
  node = dup
  node.children = children.map {|c| c.do_extend(extends)}
  node
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#each {|node| ... }

Iterates through each node in the tree rooted at this node in a pre-order walk.

Yields:

  • node

Yield Parameters:

  • node (Node)

    a node in the tree



231
232
233
234
# File 'lib/sass/tree/node.rb', line 231

def each(&block)
  yield self
  children.each {|c| c.each(&block)}
end

#invalid_child?(child) ⇒ Boolean, String (protected)

Returns an error message if the given child node is invalid, and false otherwise.

By default, all child nodes except those only allowed under specific nodes (MixinDefNode, ImportNode, ExtendNode) are valid. This is expected to be overriden by subclasses for which some children are invalid.

Parameters:

Returns:

  • (Boolean, String)

    Whether or not the child node is valid, as well as the error message to display if it is invalid



372
373
374
375
376
377
378
379
380
381
# File 'lib/sass/tree/node.rb', line 372

def invalid_child?(child)
  case child
  when Tree::MixinDefNode
    "Mixins may only be defined at the root of a document."
  when Tree::ImportNode
    "Import directives may only be used at the root of a document."
  when Tree::ExtendNode
    "Extend directives may only be used within rules."
  end
end

#invisible?Boolean

True if #to_s will return nil; that is, if the node shouldn't be rendered. Should only be called in a static tree.

Returns:

  • (Boolean)


139
# File 'lib/sass/tree/node.rb', line 139

def invisible?; false; end

#perform(environment) ⇒ Tree::Node

Converts a dynamic tree into a static Sass tree. That is, runs the dynamic Sass code: mixins, variables, control directives, and so forth. This doesn't modify this node or any of its children.

#perform shouldn't be overridden directly; instead, override #_perform or #perform!.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

  • (Tree::Node)

    The resulting tree of static nodes

Raises:

See Also:



219
220
221
222
223
224
# File 'lib/sass/tree/node.rb', line 219

def perform(environment)
  _perform(environment)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#perform!(environment) (protected)

Destructively runs dynamic Sass code in this particular node. This does modify this node, but will be run non-destructively by #_perform.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

See Also:



323
324
325
# File 'lib/sass/tree/node.rb', line 323

def perform!(environment)
  self.children = perform_children(Environment.new(environment))
end

#perform_children(environment) ⇒ Array<Tree::Node> (protected)

Non-destructively runs #perform on all children of the current node.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

  • (Array<Tree::Node>)

    The resulting static nodes



332
333
334
# File 'lib/sass/tree/node.rb', line 332

def perform_children(environment)
  children.map {|c| c.perform(environment)}.flatten
end

#render

Runs the dynamic Sass code and computes the CSS for the tree.

See Also:



127
128
129
130
131
132
# File 'lib/sass/tree/node.rb', line 127

def render
  extends = Haml::Util::SubsetMap.new
  result = perform(Environment.new).cssize(extends)
  result = result.do_extend(extends) unless extends.empty?
  result.to_s
end

#run_interp(text, environment) ⇒ String (protected)

Replaces SassScript in a chunk of text with the resulting value.

Parameters:

Returns:

  • (String)

    The interpolated text



343
344
345
346
347
348
349
350
351
# File 'lib/sass/tree/node.rb', line 343

def run_interp(text, environment)
  text.map do |r|
    next r if r.is_a?(String)
    val = r.perform(environment)
    # Interpolated strings should never render with quotes
    next val.value if val.is_a?(Sass::Script::String)
    val.to_s
  end.join.strip
end

#semi(fmt) ⇒ String (protected)

Returns a semicolon if this is SCSS, or an empty string if this is Sass.

Parameters:

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    A semicolon or the empty string



428
429
430
# File 'lib/sass/tree/node.rb', line 428

def semi(fmt)
  fmt == :sass ? "" : ";"
end

#styleSymbol

The output style. See the Sass options documentation.

Returns:

  • (Symbol)


144
145
146
# File 'lib/sass/tree/node.rb', line 144

def style
  @options[:style]
end

#to_s(*args) ⇒ String?

Computes the CSS corresponding to this static CSS tree.

#to_s shouldn't be overridden directly; instead, override #_to_s. Only static-node subclasses need to implement #to_s.

This may return nil, but it will only do so if #invisible? is true.

Parameters:

  • args (Array)

    Passed on to #_to_s

Returns:

  • (String, nil)

    The resulting CSS

See Also:



158
159
160
161
162
163
# File 'lib/sass/tree/node.rb', line 158

def to_s(*args)
  _to_s(*args)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#to_sass(tabs = 0, opts = {}) ⇒ String

Converts a node to Sass code that will generate it.

Parameters:

  • tabs (Fixnum) (defaults to: 0)

    The amount of tabulation to use for the Sass code

  • opts ({Symbol => Object}) (defaults to: {})

    An options hash (see CSS#initialize)

Returns:

  • (String)

    The Sass code corresponding to the node



241
242
243
# File 'lib/sass/tree/node.rb', line 241

def to_sass(tabs = 0, opts = {})
  to_src(tabs, opts, :sass)
end

#to_scss(tabs = 0, opts = {}) ⇒ String

Converts a node to SCSS code that will generate it.

Parameters:

  • tabs (Fixnum) (defaults to: 0)

    The amount of tabulation to use for the SCSS code

  • opts ({Symbol => Object}) (defaults to: {})

    An options hash (see CSS#initialize)

Returns:

  • (String)

    The Sass code corresponding to the node



250
251
252
# File 'lib/sass/tree/node.rb', line 250

def to_scss(tabs = 0, opts = {})
  to_src(tabs, opts, :scss)
end

#to_src(tabs, opts, fmt) ⇒ String (protected)

Converts a node to Sass or SCSS code that will generate it.

This method is called by the default #to_sass and #to_scss methods, so that the same code can be used for both with minor variations.

Parameters:

  • tabs (Fixnum)

    The amount of tabulation to use for the SCSS code

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    The Sass or SCSS code corresponding to the node

Raises:

  • (NotImplementedError)


392
393
394
# File 'lib/sass/tree/node.rb', line 392

def to_src(tabs, opts, fmt)
  raise NotImplementedError.new("All static-node subclasses of Sass::Tree::Node must override #to_#{fmt}.")
end