cadenza 0.7.0.rc1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,31 @@
1
1
  module Cadenza
2
-
2
+ # The {BlockNode} is a general container with a given name meant to implement
3
+ # Cadenza's template inheritance feature. Blocks defined in a template will
4
+ # override the definition of blocks defined in the parent template.
3
5
  class BlockNode
4
- attr_accessor :name, :children
6
+ # @return [String] the name of the node
7
+ attr_accessor :name
5
8
 
6
- def initialize(name, children)
9
+ # @return [Array] the child nodes belonging to this block
10
+ attr_accessor :children
11
+
12
+ # creates a new block node with the given name and child nodes
13
+ # @param [String] name the name for this block node
14
+ # @param [Array] children the child nodes belonging to this block node
15
+ def initialize(name, children=[])
7
16
  @name = name
8
17
  @children = children
9
18
  end
10
19
 
20
+ # @return [Array] a list of any implied global variable names defined by
21
+ # this block's children.
11
22
  def implied_globals
12
23
  @children.map(&:implied_globals).flatten.uniq
13
24
  end
14
25
 
26
+ # @param [BlockNode] rhs
27
+ # @return [Boolean] true if the given {BlockNode} is equivalent to the this
28
+ # node by value.
15
29
  def ==(rhs)
16
30
  @name == rhs.name and
17
31
  @children == rhs.children
@@ -1,16 +1,27 @@
1
1
  module Cadenza
2
+ # The {BooleanInverseNode} takes an expression and evaluates the logical inverse
3
+ # of that expression so any expression that evaluates to true will return false
4
+ # and vice versa.
2
5
  class BooleanInverseNode
6
+ # @return [OperationNode] an evaluatable expression node
3
7
  attr_accessor :expression
4
8
 
9
+ # creates a new {BooleanInverseNode} with the given expression
10
+ # @param [OperationNode] the node this one will invert
5
11
  def initialize(expression)
6
12
  @expression = expression
7
13
  end
8
14
 
15
+ # @param [BooleanInverseNode] rhs
16
+ # @return [Boolean] if the given {BooleanInverseNode} is equivalent by value
9
17
  def ==(rhs)
10
18
  @expression == rhs.expression
11
19
  end
12
20
 
21
+ # @param [Context] context
22
+ # @return the value of this node evaluated with the data in the given {Context}
13
23
  def eval(context)
24
+ #TODO: rename me to .evaluate
14
25
  !@expression.eval(context)
15
26
  end
16
27
  end
@@ -1,19 +1,29 @@
1
1
  module Cadenza
2
+ # The {ConstantNode} holds a value which is not affected by any context given
3
+ # to it, such as numbers or strings.
2
4
  class ConstantNode
5
+ # @return [Object] the value of this node
3
6
  attr_accessor :value
4
7
 
8
+ # constructs a new {ConstantNode} with the given value.
9
+ # @param [Object] value the value of this constant node
5
10
  def initialize(value)
6
11
  @value = value
7
12
  end
8
13
 
14
+ # @return [Array] any global variable applied to this node (none)
9
15
  def implied_globals
10
16
  []
11
17
  end
12
18
 
19
+ # @param [Context] context
20
+ # @return [Object] the value of this node evaluated in the given context
13
21
  def eval(context)
14
22
  @value
15
23
  end
16
24
 
25
+ # @param [ConstantNode] rhs
26
+ # @return [Boolean] if this node and the given one are equivalent by value
17
27
  def ==(rhs)
18
28
  @value == rhs.value
19
29
  end
@@ -1,24 +1,46 @@
1
1
  module Cadenza
2
+ # The {DocumentNode} is intended to be the root node of any parsed AST in
3
+ # Cadenza. In addition to holding the primary children it also holds data
4
+ # that affects the entire document, such as block definitions and the name of
5
+ # any extended template.
2
6
  class DocumentNode
7
+ # @return [String] the name of the template this document will inherit from
3
8
  attr_accessor :extends
9
+
10
+ # @return [Array] any child nodes belonging to this one
4
11
  attr_accessor :children
12
+
13
+ # @return [Hash] a mapping of any blocks defined in this document where the
14
+ # key is the name of the block and the value is the {BlockNode}
15
+ # itself
5
16
  attr_accessor :blocks
6
17
 
18
+ # creates a new {DocumentNode} with the optional children nodes attached to
19
+ # it.
20
+ # @param [Array] children any child nodes to initially assign to this node.
7
21
  def initialize(children=[])
8
22
  @children = children
9
23
  @blocks = {}
10
24
  end
11
25
 
26
+ # @param [DocumentNode] rhs
27
+ # @return [Boolean] if the given {DocumentNode} is equivalent by value to this one.
12
28
  def ==(rhs)
13
29
  @children == rhs.children and
14
30
  @extends == rhs.extends and
15
31
  @blocks == rhs.blocks
16
32
  end
17
33
 
34
+ # adds the given {BlockNode} to this document replacing any existing definition
35
+ # of the same name.
36
+ # @param [BlockNode] block
18
37
  def add_block(block)
19
38
  @blocks[block.name] = block
20
39
  end
21
40
 
41
+ # returns a list of any global variable names implied by examining the children
42
+ # of this node.
43
+ # @return [Array]
22
44
  def implied_globals
23
45
  @children.map(&:implied_globals).flatten.uniq
24
46
  end
@@ -1,22 +1,41 @@
1
1
 
2
2
  module Cadenza
3
+ # The {FilterNode} is a node which contains the definition for a variable
4
+ # filter along with any parameters it is defined with.
3
5
  class FilterNode
4
- attr_accessor :identifier, :parameters
6
+ # @return [String] the name of the filter
7
+ attr_accessor :identifier
5
8
 
9
+ # @return [Array] a list of parameter nodes given to the filter
10
+ attr_accessor :parameters
11
+
12
+ # constructs a new {FilterNode} with the given identifier and parameters
13
+ # @param [String] identifier the name of the filter
14
+ # @param [Array] parameters the parameters given to the filter
6
15
  def initialize(identifier, parameters=[])
7
16
  @identifier = identifier
8
17
  @parameters = parameters
9
18
  end
10
19
 
20
+ # @param [FilterNode] rhs
21
+ # @return [Boolean] true if the given filter node is equivalent by value to
22
+ # this node.
11
23
  def ==(rhs)
12
24
  @identifier == rhs.identifier and
13
25
  @parameters == rhs.parameters
14
26
  end
15
27
 
28
+ # @return [Array] a list of implied global variable names for this node
16
29
  def implied_globals
17
30
  @parameters.map(&:implied_globals).flatten.uniq
18
31
  end
19
32
 
33
+ # evaluates the filter with the given context and input value and returns
34
+ # the output of the evaluation.
35
+ #
36
+ # @param [Context] context the context to evaluate with
37
+ # @param [String] value the input value to filter
38
+ # @return the input value when passed through this evaluated filter
20
39
  def evaluate(context, value)
21
40
  params = [value] + @parameters.map {|x| x.eval(context) }
22
41
  context.evaluate_filter(@identifier, params)
@@ -1,37 +1,53 @@
1
1
  module Cadenza
2
- class ForNode
3
- attr_accessor :iterator, :iterable, :children
4
-
5
- MAGIC_LOCALS = %w(forloop.counter forloop.counter0 forloop.first forloop.last)
6
-
7
- def initialize(iterator, iterable, children)
8
- @iterator = iterator
9
- @iterable = iterable
10
- @children = children
11
- end
2
+ # The {ForNode} describe a loop in the template code. The loop should iterate
3
+ # over all the elements of the iterable and render its children each time.
4
+ class ForNode
5
+ # @return [VariableNode] the iterator object for the loop
6
+ attr_accessor :iterator
7
+
8
+ # @return [VariableNode] the iterable object for the loop
9
+ attr_accessor :iterable
10
+
11
+ # @return [Array] the list of children associated with this loop
12
+ attr_accessor :children
13
+
14
+ MAGIC_LOCALS = %w(forloop.counter forloop.counter0 forloop.first forloop.last)
15
+
16
+ # constructs a new {ForNode} with the given iterator, iterable and child
17
+ # nodes.
18
+ def initialize(iterator, iterable, children)
19
+ @iterator = iterator
20
+ @iterable = iterable
21
+ @children = children
22
+ end
23
+
24
+ # @return [Array] of all global variable names defined by this node and
25
+ # it's child nodes.
26
+ def implied_globals
27
+ iterable_globals = @iterable.implied_globals
28
+ iterator_globals = @iterator.implied_globals
12
29
 
13
- def implied_globals
14
- iterable_globals = @iterable.implied_globals
15
- iterator_globals = @iterator.implied_globals
30
+ iterator_regex = Regexp.new("^#{@iterator.identifier}[\.](.+)$")
16
31
 
17
- iterator_regex = Regexp.new("^#{@iterator.identifier}[\.](.+)$")
32
+ all_children_globals = @children.map(&:implied_globals).flatten
18
33
 
19
- all_children_globals = @children.map(&:implied_globals).flatten
34
+ children_globals = all_children_globals.reject {|x| x =~ iterator_regex }
20
35
 
21
- children_globals = all_children_globals.reject {|x| x =~ iterator_regex }
36
+ iterator_children_globals = all_children_globals.select {|x| x =~ iterator_regex }.map do |identifier|
37
+ "#{iterable.identifier}.#{iterator_regex.match(identifier)[1]}"
38
+ end
22
39
 
23
- iterator_children_globals = all_children_globals.select {|x| x =~ iterator_regex }.map do |identifier|
24
- "#{iterable.identifier}.#{iterator_regex.match(identifier)[1]}"
40
+ (iterable_globals | children_globals | iterator_children_globals) - MAGIC_LOCALS - iterator_globals
25
41
  end
26
42
 
27
- (iterable_globals | children_globals | iterator_children_globals) - MAGIC_LOCALS - iterator_globals
28
- end
43
+ # @param [ForNode] rhs
44
+ # @return [Boolean] true if the given {ForNode} is equivalent by value to
45
+ # this node.
46
+ def ==(rhs)
47
+ @iterator == rhs.iterator and
48
+ @iterable == rhs.iterable and
49
+ @children == rhs.children
50
+ end
29
51
 
30
- def ==(rhs)
31
- @iterator == rhs.iterator and
32
- @iterable == rhs.iterable and
33
- @children == rhs.children
34
52
  end
35
-
36
- end
37
53
  end
@@ -1,17 +1,38 @@
1
1
  module Cadenza
2
+ # The {GenericBlockNode} allows the end user of Cadenza to provide custom
3
+ # block rendering logic via a proc defined on {Context}.
2
4
  class GenericBlockNode
3
- attr_accessor :identifier, :children, :parameters
5
+ # @return [String] the name of the block as defined in {Context}
6
+ attr_accessor :identifier
4
7
 
8
+ # @return [Array] a list of Node objects which are this block's child nodes
9
+ attr_accessor :children
10
+
11
+ # @return [Array] a list of Node objects which hold the value of parameters
12
+ # passed to this block.
13
+ attr_accessor :parameters
14
+
15
+ # Creates a new generic block with the given name, children and parameters.
16
+ # @param [String] identifier the name of the node as defined in {Context}
17
+ # @param [Array] children the child nodes belonging to this block
18
+ # @param [Array] parameters the nodes holding the value of parameters
19
+ # passed to this block.
5
20
  def initialize(identifier, children, parameters=[])
6
21
  @identifier = identifier
7
22
  @children = children
8
23
  @parameters = parameters
9
24
  end
10
25
 
26
+ # @return [Array] a list of variable names implied to be globals in the node
27
+ # @note not yet implemented
11
28
  def implied_globals
29
+ #TODO: implement me please, kthxbai
12
30
  []
13
31
  end
14
32
 
33
+ # @param [GenericBlockNode] rhs
34
+ # @return [Boolean] true if the given node is equivalent by value to the
35
+ # current node.
15
36
  def ==(rhs)
16
37
  @identifier == rhs.identifier and
17
38
  @children == rhs.children and
@@ -1,42 +1,68 @@
1
1
  module Cadenza
2
- class IfNode
3
- attr_accessor :expression, :true_children, :false_children
2
+ # The {IfNode} is a structure for rendering one of it's two given blocks
3
+ # based on the evaluation of an expression in the current {Context}.
4
+ class IfNode
5
+ # @return [OperationNode|BooleanInverseNode] the evaluatable expression
6
+ # used to determine which set of nodes to render.
7
+ attr_accessor :expression
4
8
 
5
- def initialize(expression, true_children=[], false_children=[])
6
- @expression = expression
7
- @true_children = true_children
8
- @false_children = false_children
9
- end
9
+ # @return [Array] A list of nodes which will be rendered if the {#expression}
10
+ # evaluates to true in the given {Context}.
11
+ attr_accessor :true_children
10
12
 
11
- def implied_globals
12
- (@expression.implied_globals + true_children.map(&:implied_globals).flatten + false_children.map(&:implied_globals).flatten).uniq
13
- end
13
+ # @return [Array] A list of nodes which will be rendered if the {#expression}
14
+ # evaluates to false in the given {Context}.
15
+ attr_accessor :false_children
16
+
17
+ # creates a new {IfNode} with the given evaluatable expression and pair of
18
+ # blocks.
19
+ # @param [OperationNode|BooleanInverseNode] expression the expression to evaluate
20
+ # @param [Array] true_children a list of Node objects which will be rendered
21
+ # if the {#expression} evaluates to true in the given {Context}.
22
+ # @param [Array] false_children a list of Node objects which will be
23
+ # rendered if the {#expression} evaluates to false in the given {Context}.
24
+ def initialize(expression, true_children=[], false_children=[])
25
+ @expression = expression
26
+ @true_children = true_children
27
+ @false_children = false_children
28
+ end
14
29
 
15
- def evaluate_expression_for_children(context)
16
- value = @expression.eval(context)
30
+ # @return [Array] a list of variable names implied to be global for this node.
31
+ def implied_globals
32
+ (@expression.implied_globals + true_children.map(&:implied_globals).flatten + false_children.map(&:implied_globals).flatten).uniq
33
+ end
34
+
35
+ # @param [Context] context
36
+ # @return [Array] evalutes the expression in the given context and returns
37
+ # a list of nodes which should be rendered based on the result of
38
+ # that evaluation.
39
+ def evaluate_expression_for_children(context)
40
+ value = @expression.eval(context)
17
41
 
18
- if value == true
19
- return @true_children
42
+ if value == true
43
+ return @true_children
20
44
 
21
- elsif value == false
22
- return @false_children
45
+ elsif value == false
46
+ return @false_children
23
47
 
24
- elsif value.is_a?(String)
25
- return value.length == 0 || value =~ /\s+/ ? @false_children : @true_children
48
+ elsif value.is_a?(String)
49
+ return value.length == 0 || value =~ /\s+/ ? @false_children : @true_children
26
50
 
27
- elsif value.is_a?(Float) or value.is_a?(Fixnum)
28
- return value == 0 ? @false_children : @true_children
51
+ elsif value.is_a?(Float) or value.is_a?(Fixnum)
52
+ return value == 0 ? @false_children : @true_children
29
53
 
30
- else
31
- return !!value ? @true_children : @false_children
32
-
54
+ else
55
+ return !!value ? @true_children : @false_children
56
+
57
+ end
33
58
  end
34
- end
35
59
 
36
- def ==(rhs)
37
- @expression == rhs.expression and
38
- @true_children == rhs.true_children and
39
- @false_children == rhs.false_children
60
+ # @param [IfNode] rhs
61
+ # @return [Boolean] true if the given node is equivalent by value to this node.
62
+ def ==(rhs)
63
+ @expression == rhs.expression and
64
+ @true_children == rhs.true_children and
65
+ @false_children == rhs.false_children
66
+ end
40
67
  end
41
- end
42
68
  end
@@ -1,23 +1,46 @@
1
1
  module Cadenza
2
+ # The {InjectNode} is intended to write the given variable into the rendered
3
+ # output by evaluating it in the given {Context} and passing it through an
4
+ # optional series of {FilterNode}s.
2
5
  class InjectNode
3
- attr_accessor :value, :filters, :parameters
6
+ # @return [VariableNode|OperationNode|BooleanInverseNode|ConstantNode] the value being evaluated
7
+ attr_accessor :value
8
+
9
+ # @return [Array] a list of {FilterNode} to evaluate the value with, once the
10
+ # value has itself been evaluated.
11
+ attr_accessor :filters
12
+
13
+ # @return [Array] a list of Node objects passed to the {#value} for use in a
14
+ # functional variable. See {Context#define_functional_variable}.
15
+ attr_accessor :parameters
4
16
 
17
+ # creates a new {InjectNode} with the given value, filters and parameters
18
+ # @param [VariableNode|OperationNode|BooleanInverseNode|ConstantNode] value see {#value}
19
+ # @param [Array] filters see {#filters}
20
+ # @param [Array] parameters see {#parameters}
5
21
  def initialize(value, filters=[], parameters=[])
6
22
  @value = value
7
23
  @filters = filters
8
24
  @parameters = parameters
9
25
  end
10
26
 
27
+ # @param [InjectNode] rhs
28
+ # @return [Boolean] true if the given InjectNode is equivalent by value to this node.
11
29
  def ==(rhs)
12
30
  self.value == rhs.value and
13
31
  self.filters == rhs.filters and
14
32
  self.parameters == rhs.parameters
15
33
  end
16
34
 
35
+ # @return [Array] a list of variable names implied to be global by this node
17
36
  def implied_globals
18
37
  (@value.implied_globals + @filters.map(&:implied_globals).flatten).uniq
19
38
  end
20
39
 
40
+ # @param [Context] context
41
+ # @return [String] returns the evaluated {#value} of this node in the given
42
+ # {Context} with any applicable {#parameters} after passed through
43
+ # the given {#filters}.
21
44
  def evaluate(context)
22
45
  value = @value.eval(context)
23
46