haml-edge 2.1.21 → 2.1.22

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.
Files changed (61) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/FAQ.md +142 -0
  3. data/{README.rdoc → README.md} +141 -141
  4. data/Rakefile +29 -17
  5. data/VERSION +1 -1
  6. data/lib/haml/buffer.rb +63 -27
  7. data/lib/haml/engine.rb +103 -80
  8. data/lib/haml/error.rb +7 -7
  9. data/lib/haml/exec.rb +80 -26
  10. data/lib/haml/filters.rb +106 -40
  11. data/lib/haml/helpers/action_view_extensions.rb +34 -39
  12. data/lib/haml/helpers/action_view_mods.rb +132 -139
  13. data/lib/haml/helpers.rb +207 -153
  14. data/lib/haml/html.rb +40 -21
  15. data/lib/haml/precompiler.rb +2 -0
  16. data/lib/haml/shared.rb +34 -3
  17. data/lib/haml/template/patch.rb +1 -1
  18. data/lib/haml/template/plugin.rb +0 -2
  19. data/lib/haml/template.rb +5 -0
  20. data/lib/haml/util.rb +136 -1
  21. data/lib/haml/version.rb +16 -4
  22. data/lib/haml.rb +502 -481
  23. data/lib/sass/css.rb +106 -68
  24. data/lib/sass/engine.rb +55 -22
  25. data/lib/sass/environment.rb +52 -21
  26. data/lib/sass/error.rb +23 -12
  27. data/lib/sass/files.rb +27 -0
  28. data/lib/sass/plugin/merb.rb +2 -2
  29. data/lib/sass/plugin/rails.rb +0 -2
  30. data/lib/sass/plugin.rb +32 -23
  31. data/lib/sass/repl.rb +7 -0
  32. data/lib/sass/script/bool.rb +9 -5
  33. data/lib/sass/script/color.rb +87 -1
  34. data/lib/sass/script/funcall.rb +23 -2
  35. data/lib/sass/script/functions.rb +93 -44
  36. data/lib/sass/script/lexer.rb +33 -3
  37. data/lib/sass/script/literal.rb +93 -1
  38. data/lib/sass/script/node.rb +14 -0
  39. data/lib/sass/script/number.rb +128 -4
  40. data/lib/sass/script/operation.rb +16 -1
  41. data/lib/sass/script/parser.rb +51 -21
  42. data/lib/sass/script/string.rb +7 -4
  43. data/lib/sass/script/unary_operation.rb +14 -1
  44. data/lib/sass/script/variable.rb +12 -1
  45. data/lib/sass/script.rb +26 -5
  46. data/lib/sass/tree/attr_node.rb +46 -9
  47. data/lib/sass/tree/comment_node.rb +41 -1
  48. data/lib/sass/tree/debug_node.rb +8 -0
  49. data/lib/sass/tree/directive_node.rb +20 -0
  50. data/lib/sass/tree/file_node.rb +12 -0
  51. data/lib/sass/tree/for_node.rb +15 -0
  52. data/lib/sass/tree/if_node.rb +22 -0
  53. data/lib/sass/tree/mixin_def_node.rb +12 -1
  54. data/lib/sass/tree/mixin_node.rb +13 -0
  55. data/lib/sass/tree/node.rb +136 -6
  56. data/lib/sass/tree/rule_node.rb +66 -7
  57. data/lib/sass/tree/variable_node.rb +10 -0
  58. data/lib/sass/tree/while_node.rb +11 -1
  59. data/lib/sass.rb +544 -534
  60. metadata +7 -6
  61. data/FAQ +0 -138
data/lib/sass/script.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'strscan'
2
+ require 'sass/script/node'
2
3
  require 'sass/script/variable'
3
4
  require 'sass/script/funcall'
4
5
  require 'sass/script/operation'
@@ -6,22 +7,43 @@ require 'sass/script/literal'
6
7
  require 'sass/script/parser'
7
8
 
8
9
  module Sass
9
- # This module contains various SassScript-related functionality.
10
+ # SassScript is code that's embedded in Sass documents
11
+ # to allow for property values to be computed from variables.
12
+ #
13
+ # This module contains code that handles the parsing and evaluation of SassScript.
10
14
  module Script
11
- # :stopdoc:
12
15
  # The character that begins a variable.
13
16
  VARIABLE_CHAR = ?!
14
17
 
15
- # The regular expression used to parse variables
18
+ # The regular expression used to parse variables.
16
19
  MATCH = /^!([a-zA-Z_]\w*)\s*((?:\|\|)?=)\s*(.+)/
17
20
 
18
- # The regular expression used to validate variables without matching
21
+ # The regular expression used to validate variables without matching.
19
22
  VALIDATE = /^![a-zA-Z_]\w*$/
20
23
 
24
+ # Parses and evaluates a string of SassScript.
25
+ #
26
+ # @param value [String] The SassScript
27
+ # @param line [Fixnum] The number of the line on which the SassScript appeared.
28
+ # Used for error reporting
29
+ # @param offset [Fixnum] The number of characters in on `line` that the SassScript started.
30
+ # Used for error reporting
31
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
32
+ # @return [String] The string result of evaluating the SassScript
21
33
  def self.resolve(value, line, offset, environment)
22
34
  parse(value, line, offset).perform(environment).to_s
23
35
  end
24
36
 
37
+ # Parses a string of SassScript
38
+ #
39
+ # @param value [String] The SassScript
40
+ # @param line [Fixnum] The number of the line on which the SassScript appeared.
41
+ # Used for error reporting
42
+ # @param offset [Fixnum] The number of characters in on `line` that the SassScript started.
43
+ # Used for error reporting
44
+ # @param filename [String] The path to the file in which the SassScript appeared.
45
+ # Used for error reporting
46
+ # @return [Script::Node] The root node of the parse tree
25
47
  def self.parse(value, line, offset, filename = nil)
26
48
  Parser.parse(value, line, offset, filename)
27
49
  rescue Sass::SyntaxError => e
@@ -33,6 +55,5 @@ module Sass
33
55
  e.sass_line = line
34
56
  raise e
35
57
  end
36
- # :startdoc:
37
58
  end
38
59
  end
@@ -1,7 +1,23 @@
1
1
  module Sass::Tree
2
+ # A static node reprenting a CSS property.
3
+ #
4
+ # @see Sass::Tree
2
5
  class AttrNode < Node
3
- attr_accessor :name, :value
4
-
6
+ # The name of the property.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :name
10
+
11
+ # The value of the property,
12
+ # either a plain string or a SassScript parse tree.
13
+ #
14
+ # @return [String, Script::Node]
15
+ attr_accessor :value
16
+
17
+ # @param name [String] See \{#name}
18
+ # @param value [String] See \{#value}
19
+ # @param attr_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
20
+ # `:old` if it uses `:a b`-style syntax
5
21
  def initialize(name, value, attr_syntax)
6
22
  @name = name
7
23
  @value = value
@@ -9,10 +25,21 @@ module Sass::Tree
9
25
  super()
10
26
  end
11
27
 
28
+ # Compares the names and values of two properties.
29
+ #
30
+ # @param other [Object] The object to compare with
31
+ # @return [Boolean] Whether or not this node and the other object
32
+ # are the same
12
33
  def ==(other)
13
34
  self.class == other.class && name == other.name && value == other.value && super
14
35
  end
15
36
 
37
+ # Computes the CSS for the property.
38
+ #
39
+ # @param tabs [Fixnum] The level of indentation for the CSS
40
+ # @param parent_name [String] The name of the parent property (e.g. `text`) or nil
41
+ # @return [String] The resulting CSS
42
+ # @raise [Sass::SyntaxError] if the attribute uses invalid syntax
16
43
  def to_s(tabs, parent_name = nil)
17
44
  if @options[:attribute_syntax] == :normal && @attr_syntax == :new
18
45
  raise Sass::SyntaxError.new("Illegal attribute syntax: can't use alternate syntax when :attribute_syntax => :normal is set.")
@@ -50,23 +77,33 @@ module Sass::Tree
50
77
  end
51
78
 
52
79
  protected
53
-
80
+
81
+ # Runs any SassScript that may be embedded in the property.
82
+ #
83
+ # @param environment [Sass::Environment] The lexical environment containing
84
+ # variable and mixin values
54
85
  def perform!(environment)
55
86
  @name = interpolate(@name, environment)
56
87
  @value = @value.is_a?(String) ? interpolate(@value, environment) : @value.perform(environment).to_s
57
88
  super
58
89
  end
59
90
 
60
- private
61
-
62
- def declaration
63
- @attr_syntax == :new ? "#{name}: #{value}" : ":#{name} #{value}"
64
- end
65
-
91
+ # Returns an error message if the given child node is invalid,
92
+ # and false otherwise.
93
+ #
94
+ # {AttrNode} only allows other {AttrNode}s and {CommentNode}s as children.
95
+ # @param child [Tree::Node] A potential child node
96
+ # @return [String] An error message if the child is invalid, or nil otherwise
66
97
  def invalid_child?(child)
67
98
  if !child.is_a?(AttrNode) && !child.is_a?(CommentNode)
68
99
  "Illegal nesting: Only attributes may be nested beneath attributes."
69
100
  end
70
101
  end
102
+
103
+ private
104
+
105
+ def declaration
106
+ @attr_syntax == :new ? "#{name}: #{value}" : ":#{name} #{value}"
107
+ end
71
108
  end
72
109
  end
@@ -1,11 +1,27 @@
1
1
  require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
+ # A static node representing a Sass comment (silent or loud).
5
+ #
6
+ # @see Sass::Tree
4
7
  class CommentNode < Node
8
+ # The lines of text nested beneath the comment.
9
+ #
10
+ # @return [Array<Sass::Engine::Line>]
5
11
  attr_accessor :lines
12
+
13
+ # The text on the same line as the comment starter.
14
+ #
15
+ # @return [String]
6
16
  attr_accessor :value
17
+
18
+ # Whether or not the comment is silent (that is, doesn't output to CSS).
19
+ #
20
+ # @return [Boolean]
7
21
  attr_accessor :silent
8
22
 
23
+ # @param value [String] See \{#value}
24
+ # @param silent [Boolean] See \{#silent}
9
25
  def initialize(value, silent)
10
26
  @lines = []
11
27
  @value = value[2..-1].strip
@@ -13,11 +29,25 @@ module Sass::Tree
13
29
  super()
14
30
  end
15
31
 
32
+ # Compares the contents of two comments.
33
+ #
34
+ # @param other [Object] The object to compare with
35
+ # @return [Boolean] Whether or not this node and the other object
36
+ # are the same
16
37
  def ==(other)
17
38
  self.class == other.class && value == other.value && silent == other.silent && lines == other.lines
18
39
  end
19
40
 
20
- def to_s(tabs = 0, parent_name = nil)
41
+ # Computes the CSS for the comment.
42
+ #
43
+ # Returns `nil` if this is a silent comment
44
+ # or the current style doesn't render comments.
45
+ #
46
+ # @overload to_s(tabs = 0)
47
+ # @param tabs [Fixnum] The level of indentation for the CSS
48
+ # @return [String, nil] The resulting CSS
49
+ # @see #invisible?
50
+ def to_s(tabs = 0, _ = nil)
21
51
  return if invisible?
22
52
 
23
53
  spaces = ' ' * (tabs - 1)
@@ -25,12 +55,22 @@ module Sass::Tree
25
55
  map{|l| l.sub(%r{ ?\*/ *$},'')}.join(style == :compact ? ' ' : "\n#{spaces} * ") + " */"
26
56
  end
27
57
 
58
+ # Returns `true` if this is a silent comment
59
+ # or the current style doesn't render comments.
60
+ #
61
+ # @return [Boolean]
28
62
  def invisible?
29
63
  style == :compressed || @silent
30
64
  end
31
65
 
32
66
  protected
33
67
 
68
+ # Removes this node from the tree if it's a silent comment.
69
+ #
70
+ # @param environment [Sass::Environment] The lexical environment containing
71
+ # variable and mixin values
72
+ # @return [Tree::Node, Array<Tree::Node>] The resulting static nodes
73
+ # @see Sass::Tree
34
74
  def _perform(environment)
35
75
  return [] if @silent
36
76
  self
@@ -1,6 +1,10 @@
1
1
  module Sass
2
2
  module Tree
3
+ # A dynamic node representing a Sass `@debug` statement.
4
+ #
5
+ # @see Sass::Tree
3
6
  class DebugNode < Node
7
+ # @param expr [Script::Node] The expression to print
4
8
  def initialize(expr)
5
9
  @expr = expr
6
10
  super()
@@ -8,6 +12,10 @@ module Sass
8
12
 
9
13
  protected
10
14
 
15
+ # Prints the expression to STDERR.
16
+ #
17
+ # @param environment [Sass::Environment] The lexical environment containing
18
+ # variable and mixin values
11
19
  def _perform(environment)
12
20
  res = @expr.perform(environment)
13
21
  if filename
@@ -1,12 +1,32 @@
1
1
  module Sass::Tree
2
+ # A static node representing an unproccessed Sass `@`-directive.
3
+ # Directives known to Sass, like `@for` and `@debug`,
4
+ # are handled by their own nodes;
5
+ # only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
6
+ #
7
+ # `@import` is a bit of a weird case;
8
+ # if it's importing a Sass file,
9
+ # it becomes a {FileNode},
10
+ # but if it's importing a plain CSS file,
11
+ # it becomes a {DirectiveNode}.
12
+ #
13
+ # @see Sass::Tree
2
14
  class DirectiveNode < Node
15
+ # The text of the directive, `@` and all.
16
+ #
17
+ # @return [String]
3
18
  attr_accessor :value
4
19
 
20
+ # @param value [String] See \{#value}
5
21
  def initialize(value)
6
22
  @value = value
7
23
  super()
8
24
  end
9
25
 
26
+ # Computes the CSS for the directive.
27
+ #
28
+ # @param tabs [Fixnum] The level of indentation for the CSS
29
+ # @return [String] The resulting CSS
10
30
  def to_s(tabs)
11
31
  if children.empty?
12
32
  value + ";"
@@ -1,11 +1,18 @@
1
1
  module Sass
2
2
  module Tree
3
+ # A static node that wraps the {Sass::Tree} for an `@import`ed file.
4
+ # It doesn't have a functional purpose other than to add the `@import`ed file
5
+ # to the backtrace if an error occurs.
3
6
  class FileNode < Node
7
+ # @param filename [String] The name of the imported file
4
8
  def initialize(filename)
5
9
  @filename = filename
6
10
  super()
7
11
  end
8
12
 
13
+ # Computes the CSS for the imported file.
14
+ #
15
+ # @param args [Array] Ignored
9
16
  def to_s(*args)
10
17
  @to_s ||= (style == :compressed ? super().strip : super())
11
18
  rescue Sass::SyntaxError => e
@@ -17,6 +24,11 @@ module Sass
17
24
 
18
25
  protected
19
26
 
27
+ # Parses the imported file
28
+ # and runs the dynamic Sass for it.
29
+ #
30
+ # @param environment [Sass::Environment] The lexical environment containing
31
+ # variable and mixin values
20
32
  def perform!(environment)
21
33
  self.children = Sass::Files.tree_for(filename, @options).children
22
34
  self.children = perform_children(environment)
@@ -1,7 +1,15 @@
1
1
  require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
+ # A dynamic node representing a Sass `@for` loop.
5
+ #
6
+ # @see Sass::Tree
4
7
  class ForNode < Node
8
+ # @param var [String] The name of the loop variable
9
+ # @param from [Script::Node] The parse tree for the initial expression
10
+ # @param to [Script::Node] The parse tree for the final expression
11
+ # @param exclusive [Boolean] Whether to include `to` in the loop
12
+ # or stop just before
5
13
  def initialize(var, from, to, exclusive)
6
14
  @var = var
7
15
  @from = from
@@ -12,6 +20,13 @@ module Sass::Tree
12
20
 
13
21
  protected
14
22
 
23
+ # Runs the child nodes once for each time through the loop,
24
+ # varying the variable each time.
25
+ #
26
+ # @param environment [Sass::Environment] The lexical environment containing
27
+ # variable and mixin values
28
+ # @return [Array<Tree::Node>] The resulting static nodes
29
+ # @see Sass::Tree
15
30
  def _perform(environment)
16
31
  from = @from.perform(environment).to_i
17
32
  to = @to.perform(environment).to_i
@@ -1,15 +1,30 @@
1
1
  require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
+ # A dynamic node representing a Sass `@if` statement.
5
+ #
6
+ # {IfNode}s are a little odd, in that they also represent `@else` and `@else if`s.
7
+ # This is done as a linked list:
8
+ # each {IfNode} has a link (\{#else}) to the next {IfNode}.
9
+ #
10
+ # @see Sass::Tree
4
11
  class IfNode < Node
12
+ # The next {IfNode} in the if-else list, or `nil`.
13
+ #
14
+ # @return [IfNode]
5
15
  attr_accessor :else
6
16
 
17
+ # @param expr [Script::Expr] The conditional expression.
18
+ # If this is nil, this is an `@else` node, not an `@else if`
7
19
  def initialize(expr)
8
20
  @expr = expr
9
21
  @last_else = self
10
22
  super()
11
23
  end
12
24
 
25
+ # Append an `@else` node to the end of the list.
26
+ #
27
+ # @param node [IfNode] The `@else` node to append
13
28
  def add_else(node)
14
29
  @last_else.else = node
15
30
  @last_else = node
@@ -22,6 +37,13 @@ module Sass::Tree
22
37
 
23
38
  protected
24
39
 
40
+ # Runs the child nodes if the conditional expression is true;
41
+ # otherwise, tries the \{#else} nodes.
42
+ #
43
+ # @param environment [Sass::Environment] The lexical environment containing
44
+ # variable and mixin values
45
+ # @return [Array<Tree::Node>] The resulting static nodes
46
+ # @see Sass::Tree
25
47
  def _perform(environment)
26
48
  environment = Sass::Environment.new(environment)
27
49
  return perform_children(environment) if @expr.nil? || @expr.perform(environment).to_bool
@@ -1,14 +1,25 @@
1
1
  module Sass
2
2
  module Tree
3
+ # A dynamic node representing a mixin definition.
4
+ #
5
+ # @see Sass::Tree
3
6
  class MixinDefNode < Node
7
+ # @param name [String] The mixin name
8
+ # @param args [Array<(String, Script::Node)>] The arguments for the mixin.
9
+ # Each element is a tuple containing the name of the argument
10
+ # and the parse tree for the default value of the argument
4
11
  def initialize(name, args)
5
12
  @name = name
6
13
  @args = args
7
14
  super()
8
15
  end
9
16
 
10
- private
17
+ protected
11
18
 
19
+ # Loads the mixin into the environment.
20
+ #
21
+ # @param environment [Sass::Environment] The lexical environment containing
22
+ # variable and mixin values
12
23
  def _perform(environment)
13
24
  environment.set_mixin(@name, Sass::Mixin.new(@name, @args, environment, children))
14
25
  []
@@ -1,7 +1,12 @@
1
1
  require 'sass/tree/node'
2
2
 
3
3
  module Sass::Tree
4
+ # A dynamic node representing a mixin include.
5
+ #
6
+ # @see Sass::Tree
4
7
  class MixinNode < Node
8
+ # @param name [String] The name of the mixin
9
+ # @param args [Array<Script::Node>] The arguments to the mixin
5
10
  def initialize(name, args)
6
11
  @name = name
7
12
  @args = args
@@ -10,6 +15,14 @@ module Sass::Tree
10
15
 
11
16
  protected
12
17
 
18
+ # Runs the mixin.
19
+ #
20
+ # @param environment [Sass::Environment] The lexical environment containing
21
+ # variable and mixin values
22
+ # @return [Array<Tree::Node>] The resulting static nodes
23
+ # @raise [Sass::SyntaxError] if there is no mixin with the given name
24
+ # @raise [Sass::SyntaxError] if an incorrect number of arguments was passed
25
+ # @see Sass::Tree
13
26
  def _perform(environment)
14
27
  raise Sass::SyntaxError.new("Undefined mixin '#{@name}'.", @line) unless mixin = environment.mixin(@name)
15
28
 
@@ -1,24 +1,69 @@
1
1
  module Sass
2
+ # A namespace for nodes in the Sass parse tree.
3
+ #
4
+ # The Sass parse tree has two states.
5
+ # When it's first parsed, it has nodes for mixin definitions
6
+ # and for loops and so forth,
7
+ # in addition to nodes for CSS rules and properties.
8
+ #
9
+ # However, {Tree::Node#perform} returns a different sort of tree.
10
+ # This tree maps more closely to the resulting CSS document
11
+ # than it does to the original Sass document.
12
+ # It still has nodes for CSS rules and properties,
13
+ # but it doesn't have any dynamic-generation-related nodes.
14
+ #
15
+ # Nodes that only appear in the pre-perform state are called **dynamic nodes**;
16
+ # those that appear in both states are called **static nodes**.
2
17
  module Tree
18
+ # This class doubles as the root node of the parse tree
19
+ # and the superclass of all other parse-tree nodes.
3
20
  class Node
21
+ # The child nodes of this node.
22
+ #
23
+ # @return [Array<Tree::Node>]
4
24
  attr_accessor :children
25
+
26
+ # The line of the document on which this node appeared.
27
+ #
28
+ # @return [Fixnum]
5
29
  attr_accessor :line
30
+
31
+ # The name of the document on which this node appeared.
32
+ #
33
+ # @return [String]
6
34
  attr_writer :filename
35
+
36
+ # The options hash for the node.
37
+ # See [the Sass options documentation](../../Sass.html#sass_options).
38
+ #
39
+ # @return [Hash<Symbol, Object>]
7
40
  attr_reader :options
8
41
 
9
42
  def initialize
10
43
  @children = []
11
44
  end
12
45
 
46
+ # Sets the options hash for the node and all its children.
47
+ #
48
+ # @param options [Hash<Symbol, Object>] The options
49
+ # @see #options
13
50
  def options=(options)
14
51
  children.each {|c| c.options = options}
15
52
  @options = options
16
53
  end
17
54
 
55
+ # The name of the document on which this node appeared.
56
+ #
57
+ # @return [String]
18
58
  def filename
19
59
  @filename || @options[:filename]
20
60
  end
21
61
 
62
+ # Appends a child to the node.
63
+ #
64
+ # @param child [Tree::Node] The child node
65
+ # @raise [Sass::SyntaxError] if `child` is invalid
66
+ # @see #invalid_child?
22
67
  def <<(child)
23
68
  if msg = invalid_child?(child)
24
69
  raise Sass::SyntaxError.new(msg, child.line)
@@ -26,21 +71,54 @@ module Sass
26
71
  @children << child
27
72
  end
28
73
 
29
- # We need this because Node duck types as an Array in engine.rb
74
+ # Return the last child node.
75
+ #
76
+ # We need this because {Tree::Node} duck types as an Array for {Sass::Engine}.
77
+ #
78
+ # @return [Tree::Node] The last child node
30
79
  def last
31
80
  children.last
32
81
  end
33
82
 
83
+ # Compares this node and another object (only other {Tree::Node}s will be equal).
84
+ # This does a structural comparison;
85
+ # if the contents of the nodes and all the child nodes are equivalent,
86
+ # then the nodes are as well.
87
+ #
88
+ # Only static nodes need to override this.
89
+ #
90
+ # @param other [Object] The object to compare with
91
+ # @return [Boolean] Whether or not this node and the other object
92
+ # are the same
93
+ # @see Sass::Tree
34
94
  def ==(other)
35
95
  self.class == other.class && other.children == children
36
96
  end
37
97
 
98
+ # Runs the dynamic Sass code *and* computes the CSS for the tree.
99
+ #
100
+ # @see #perform
101
+ # @see #to_s
38
102
  def render
39
103
  perform(Environment.new).to_s
40
104
  end
41
105
 
106
+ # True if \{#to\_s} will return `nil`;
107
+ # that is, if the node shouldn't be rendered.
108
+ # Should only be called in a static tree.
109
+ #
110
+ # @return [Boolean]
42
111
  def invisible?; false; end
43
112
 
113
+ # Computes the CSS corresponding to this Sass tree.
114
+ #
115
+ # Only static-node subclasses need to implement \{#to\_s}.
116
+ #
117
+ # This may return `nil`, but it will only do so if \{#invisible?} is true.
118
+ #
119
+ # @return [String, nil] The resulting CSS
120
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
121
+ # @see Sass::Tree
44
122
  def to_s
45
123
  result = String.new
46
124
  children.each do |child|
@@ -56,32 +134,77 @@ module Sass
56
134
  rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
57
135
  end
58
136
 
137
+ # Runs the dynamic Sass code:
138
+ # mixins, variables, control structures, and so forth.
139
+ # This doesn't modify this node or any of its children.
140
+ #
141
+ # \{#perform} shouldn't be overridden directly;
142
+ # if you want to return a new node (or list of nodes),
143
+ # override \{#\_perform};
144
+ # if you want to destructively modify this node,
145
+ # override \{#perform!}.
146
+ #
147
+ # @param environment [Sass::Environment] The lexical environment containing
148
+ # variable and mixin values
149
+ # @return [Tree::Node] The resulting tree of static nodes
150
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
151
+ # @see Sass::Tree
59
152
  def perform(environment)
60
153
  environment.options = @options if self.class == Tree::Node
61
154
  _perform(environment)
62
155
  rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
63
156
  end
64
157
 
158
+ # The output style. See [the Sass options documentation](../../Sass.html#output_style).
159
+ #
160
+ # @return [Symbol]
65
161
  def style
66
162
  @options[:style]
67
163
  end
68
164
 
69
165
  protected
70
166
 
167
+ # Runs any dynamic Sass code in this particular node.
168
+ # This doesn't modify this node or any of its children.
169
+ #
170
+ # @param environment [Sass::Environment] The lexical environment containing
171
+ # variable and mixin values
172
+ # @return [Tree::Node, Array<Tree::Node>] The resulting static nodes
173
+ # @see #perform
174
+ # @see Sass::Tree
71
175
  def _perform(environment)
72
176
  node = dup
73
177
  node.perform!(environment)
74
178
  node
75
179
  end
76
180
 
181
+ # Destructively runs dynamic Sass code in this particular node.
182
+ # This *does* modify this node,
183
+ # but will be run non-destructively by \{#\_perform\}.
184
+ #
185
+ # @param environment [Sass::Environment] The lexical environment containing
186
+ # variable and mixin values
187
+ # @see #perform
77
188
  def perform!(environment)
78
189
  self.children = perform_children(Environment.new(environment))
79
190
  end
80
191
 
192
+ # Non-destructively runs \{#perform} on all children of the current node.
193
+ #
194
+ # @param environment [Sass::Environment] The lexical environment containing
195
+ # variable and mixin values
196
+ # @return [Array<Tree::Node>] The resulting static nodes
81
197
  def perform_children(environment)
82
198
  children.map {|c| c.perform(environment)}.flatten
83
199
  end
84
200
 
201
+ # Replaces SassScript in a chunk of text (via `#{}`)
202
+ # with the resulting value.
203
+ #
204
+ # @param text [String] The text to interpolate
205
+ # @param environment [Sass::Environment] The lexical environment containing
206
+ # variable and mixin values
207
+ # @return [String] The interpolated text
85
208
  def interpolate(text, environment)
86
209
  res = ''
87
210
  rest = Haml::Shared.handle_interpolation text do |scan|
@@ -98,17 +221,24 @@ module Sass
98
221
  res + rest
99
222
  end
100
223
 
224
+ # @see Haml::Shared.balance
225
+ # @raise [Sass::SyntaxError] if the brackets aren't balanced
101
226
  def balance(*args)
102
227
  res = Haml::Shared.balance(*args)
103
228
  return res if res
104
229
  raise Sass::SyntaxError.new("Unbalanced brackets.", line)
105
230
  end
106
231
 
107
- private
108
-
109
- # This method should be overridden by subclasses to return an error message
110
- # if the given child node is invalid,
111
- # and false or nil otherwise.
232
+ # Returns an error message if the given child node is invalid,
233
+ # and false otherwise.
234
+ #
235
+ # By default, all child nodes are valid.
236
+ # This is expected to be overriden by subclasses
237
+ # for which some children are invalid.
238
+ #
239
+ # @param child [Tree::Node] A potential child node
240
+ # @return [Boolean, String] Whether or not the child node is valid,
241
+ # as well as the error message to display if it is invalid
112
242
  def invalid_child?(child)
113
243
  false
114
244
  end