cadenza 0.7.0.rc1 → 0.7.0

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.
@@ -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