inversion 0.1.1 → 0.2.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.
- data.tar.gz.sig +0 -0
- data/ChangeLog +157 -28
- data/History.rdoc +8 -0
- data/Manifest.txt +2 -3
- data/Rakefile +1 -3
- data/lib/inversion.rb +2 -2
- data/lib/inversion/exceptions.rb +1 -1
- data/lib/inversion/{template/parser.rb → parser.rb} +5 -5
- data/lib/inversion/renderstate.rb +55 -5
- data/lib/inversion/template.rb +5 -3
- data/lib/inversion/template/attrtag.rb +19 -12
- data/lib/inversion/template/begintag.rb +1 -2
- data/lib/inversion/template/configtag.rb +7 -1
- data/lib/inversion/template/containertag.rb +8 -3
- data/lib/inversion/template/elsetag.rb +16 -0
- data/lib/inversion/template/elsiftag.rb +16 -0
- data/lib/inversion/template/escapetag.rb +1 -1
- data/lib/inversion/template/fortag.rb +2 -5
- data/lib/inversion/template/iftag.rb +17 -35
- data/lib/inversion/template/importtag.rb +2 -1
- data/lib/inversion/template/includetag.rb +2 -0
- data/lib/inversion/template/node.rb +1 -1
- data/lib/inversion/template/tag.rb +5 -2
- data/lib/inversion/template/textnode.rb +1 -2
- data/lib/inversion/template/unlesstag.rb +16 -26
- data/lib/inversion/template/yieldtag.rb +3 -8
- data/spec/inversion/{template/parser_spec.rb → parser_spec.rb} +14 -14
- data/spec/inversion/renderstate_spec.rb +242 -165
- data/spec/inversion/template/attrtag_spec.rb +10 -18
- data/spec/inversion/template/begintag_spec.rb +13 -12
- data/spec/inversion/template/configtag_spec.rb +5 -7
- data/spec/inversion/template/elsetag_spec.rb +5 -5
- data/spec/inversion/template/elsiftag_spec.rb +5 -5
- data/spec/inversion/template/endtag_spec.rb +1 -1
- data/spec/inversion/template/fortag_spec.rb +22 -1
- data/spec/inversion/template/iftag_spec.rb +14 -0
- data/spec/inversion/template/rescuetag_spec.rb +4 -4
- data/spec/inversion/template/tag_spec.rb +6 -4
- data/spec/inversion/template/unlesstag_spec.rb +12 -6
- data/spec/inversion/template/yieldtag_spec.rb +2 -2
- metadata +31 -32
- metadata.gz.sig +0 -0
- data/lib/inversion/template/conditionaltag.rb +0 -49
data/lib/inversion/template.rb
CHANGED
@@ -27,11 +27,13 @@ class Inversion::Template
|
|
27
27
|
|
28
28
|
|
29
29
|
# Load subordinate classes
|
30
|
-
require 'inversion/
|
30
|
+
require 'inversion/parser'
|
31
31
|
require 'inversion/template/node'
|
32
32
|
require 'inversion/template/tag'
|
33
33
|
require 'inversion/renderstate'
|
34
34
|
|
35
|
+
# Alias to maintain backward compatibility with <0.2.0 code
|
36
|
+
Parser = Inversion::Parser
|
35
37
|
|
36
38
|
# Valid actions for 'on_render_error'
|
37
39
|
VALID_ERROR_ACTIONS = [
|
@@ -116,7 +118,7 @@ class Inversion::Template
|
|
116
118
|
end
|
117
119
|
|
118
120
|
@source = source
|
119
|
-
@parser = Inversion::
|
121
|
+
@parser = Inversion::Parser.new( self, opts )
|
120
122
|
@node_tree = [] # Parser expects this to always be an Array
|
121
123
|
@init_options = opts
|
122
124
|
@options = nil
|
@@ -176,7 +178,7 @@ class Inversion::Template
|
|
176
178
|
# Pre-render hook
|
177
179
|
self.walk_tree {|node| node.before_rendering(state) }
|
178
180
|
|
179
|
-
self.log.debug " rendering node tree: %p" % [ @node_tree ]
|
181
|
+
# self.log.debug " rendering node tree: %p" % [ @node_tree ]
|
180
182
|
self.walk_tree {|node| state << node }
|
181
183
|
|
182
184
|
# Post-render hook
|
@@ -77,12 +77,26 @@ class Inversion::Template::AttrTag < Inversion::Template::CodeTag
|
|
77
77
|
attr_accessor :methodchain
|
78
78
|
|
79
79
|
|
80
|
-
### Render the tag attributes of the specified +
|
81
|
-
def render(
|
82
|
-
self.log.debug "Rendering %p with state: %p" % [ self,
|
80
|
+
### Render the tag attributes of the specified +renderstate+ and return them.
|
81
|
+
def render( renderstate )
|
82
|
+
self.log.debug "Rendering %p with state: %p" % [ self, renderstate ]
|
83
83
|
|
84
|
+
# Evaluate the tag body and return either false value
|
85
|
+
value = self.evaluate( renderstate ) or return value
|
86
|
+
|
87
|
+
# Apply the format if there is one
|
88
|
+
if self.format
|
89
|
+
return self.format % value
|
90
|
+
else
|
91
|
+
return value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
### Evaluate the body of the tag in the context of +renderstate+ and return the results.
|
97
|
+
def evaluate( renderstate )
|
84
98
|
value = nil
|
85
|
-
attribute =
|
99
|
+
attribute = renderstate.attributes[ self.name.to_sym ]
|
86
100
|
self.log.debug " initial attribute: %p" % [ attribute ]
|
87
101
|
|
88
102
|
# Evaluate the method chain (if there is one) against the attribute
|
@@ -95,14 +109,7 @@ class Inversion::Template::AttrTag < Inversion::Template::CodeTag
|
|
95
109
|
end
|
96
110
|
self.log.debug " evaluated value: %p" % [ value ]
|
97
111
|
|
98
|
-
return value
|
99
|
-
|
100
|
-
# Apply the format if there is one
|
101
|
-
if self.format
|
102
|
-
return self.format % value
|
103
|
-
else
|
104
|
-
return value
|
105
|
-
end
|
112
|
+
return value
|
106
113
|
end
|
107
114
|
|
108
115
|
|
@@ -4,7 +4,6 @@
|
|
4
4
|
require 'inversion/mixins'
|
5
5
|
require 'inversion/template/attrtag'
|
6
6
|
require 'inversion/template/containertag'
|
7
|
-
require 'inversion/template/conditionaltag'
|
8
7
|
require 'inversion/template/rescuetag'
|
9
8
|
|
10
9
|
|
@@ -85,7 +84,7 @@ class Inversion::Template::BeginTag < Inversion::Template::Tag
|
|
85
84
|
state.with_destination( output ) do
|
86
85
|
state.with_error_handler( errhandler ) do
|
87
86
|
catch( :stop_rendering ) do
|
88
|
-
|
87
|
+
super
|
89
88
|
end
|
90
89
|
self.log.debug " leaving the error-handler block"
|
91
90
|
end
|
@@ -51,10 +51,16 @@ class Inversion::Template::ConfigTag < Inversion::Template::Tag
|
|
51
51
|
|
52
52
|
|
53
53
|
### Override the options in the +parsestate+ when the config is appended to
|
54
|
-
### tree.
|
54
|
+
### the tree.
|
55
55
|
def before_appending( parsestate )
|
56
56
|
parsestate.options.merge!( self.options )
|
57
57
|
end
|
58
58
|
|
59
|
+
|
60
|
+
### Override the options in the +renderstate+ when the config is rendered.
|
61
|
+
def before_rendering( renderstate )
|
62
|
+
renderstate.options.merge!( self.options )
|
63
|
+
end
|
64
|
+
|
59
65
|
end # class Inversion::Template::ConfigTag
|
60
66
|
|
@@ -33,11 +33,16 @@ module Inversion::Template::ContainerTag
|
|
33
33
|
alias_method :container?, :is_container?
|
34
34
|
|
35
35
|
|
36
|
+
### Default render method for containertags; rendering each of its subnodes and
|
37
|
+
### don't render anything for the container itself.
|
38
|
+
def render( renderstate )
|
39
|
+
self.render_subnodes( renderstate )
|
40
|
+
end
|
41
|
+
|
42
|
+
|
36
43
|
### Append the container's subnodes to the +renderstate+.
|
37
44
|
def render_subnodes( renderstate )
|
38
|
-
self.subnodes.each
|
39
|
-
renderstate << node
|
40
|
-
end
|
45
|
+
self.subnodes.each {|node| renderstate << node }
|
41
46
|
end
|
42
47
|
|
43
48
|
end # module Inversion::Template::ContainerTag
|
@@ -58,5 +58,21 @@ class Inversion::Template::ElseTag < Inversion::Template::Tag
|
|
58
58
|
raise Inversion::ParseError, "orphaned '%s' tag" % [ self.tagname.downcase ] unless condtag
|
59
59
|
end
|
60
60
|
|
61
|
+
|
62
|
+
### Toggle rendering for the iftag's container if rendering hasn't yet been
|
63
|
+
### toggled.
|
64
|
+
def render( renderstate )
|
65
|
+
if renderstate.tag_data[ :rendering_was_enabled ]
|
66
|
+
self.log.debug " rendering was previously enabled: disabling"
|
67
|
+
renderstate.disable_rendering
|
68
|
+
else
|
69
|
+
self.log.debug " rendering was previously disabled: enabling"
|
70
|
+
renderstate.tag_data[ :rendering_was_enabled ] = true
|
71
|
+
renderstate.enable_rendering
|
72
|
+
end
|
73
|
+
|
74
|
+
return nil
|
75
|
+
end
|
76
|
+
|
61
77
|
end # class Inversion::Template::ElseTag
|
62
78
|
|
@@ -45,5 +45,21 @@ class Inversion::Template::ElsifTag < Inversion::Template::AttrTag
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
|
49
|
+
### Toggle rendering for the iftag's container if rendering hasn't yet been
|
50
|
+
### toggled.
|
51
|
+
def render( renderstate )
|
52
|
+
if renderstate.tag_data[ :rendering_was_enabled ]
|
53
|
+
self.log.debug "Rendering was previously enabled; disabling"
|
54
|
+
renderstate.disable_rendering
|
55
|
+
elsif self.evaluate( renderstate )
|
56
|
+
self.log.debug "Rendering was previously disabled, and condition is true; enabling"
|
57
|
+
renderstate.tag_data[ :rendering_was_enabled ] = true
|
58
|
+
renderstate.enable_rendering
|
59
|
+
end
|
60
|
+
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
48
64
|
end # class Inversion::Template::ElsifTag
|
49
65
|
|
@@ -19,7 +19,7 @@ class Inversion::Template::EscapeTag < Inversion::Template::AttrTag
|
|
19
19
|
### Render the method chains against the attributes of the specified +render_state+
|
20
20
|
### and return them.
|
21
21
|
def render( render_state )
|
22
|
-
|
22
|
+
return self.escape( super, render_state )
|
23
23
|
end
|
24
24
|
|
25
25
|
end # class Inversion::Template::EscapeTag
|
@@ -82,7 +82,6 @@ class Inversion::Template::ForTag < Inversion::Template::CodeTag
|
|
82
82
|
### Iterate over the enumerator in +state+ and render the tag's
|
83
83
|
### contents for each iteration.
|
84
84
|
def render( state )
|
85
|
-
result = []
|
86
85
|
lvalue = state.eval( self.enumerator ) or return nil
|
87
86
|
|
88
87
|
self.log.debug "Rendering %p via block args: %p" % [ lvalue, self.block_args ]
|
@@ -95,13 +94,11 @@ class Inversion::Template::ForTag < Inversion::Template::CodeTag
|
|
95
94
|
# Overlay the block args from the 'for' over the template attributes and render
|
96
95
|
# each subnode
|
97
96
|
state.with_attributes( overrides ) do
|
98
|
-
|
99
|
-
result << node.render( state )
|
100
|
-
end
|
97
|
+
super
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
104
|
-
return
|
101
|
+
return nil
|
105
102
|
end
|
106
103
|
|
107
104
|
|
@@ -4,7 +4,6 @@
|
|
4
4
|
require 'inversion/mixins'
|
5
5
|
require 'inversion/template/attrtag'
|
6
6
|
require 'inversion/template/containertag'
|
7
|
-
require 'inversion/template/conditionaltag'
|
8
7
|
require 'inversion/template/elsiftag'
|
9
8
|
require 'inversion/template/elsetag'
|
10
9
|
|
@@ -20,50 +19,33 @@ require 'inversion/template/elsetag'
|
|
20
19
|
#
|
21
20
|
class Inversion::Template::IfTag < Inversion::Template::AttrTag
|
22
21
|
include Inversion::Loggable,
|
23
|
-
Inversion::Template::ContainerTag
|
24
|
-
Inversion::Template::ConditionalTag
|
22
|
+
Inversion::Template::ContainerTag
|
25
23
|
|
26
24
|
# Inherits AttrTag's tag patterns
|
27
25
|
|
28
26
|
### Render the tag's contents if the condition is true, or any else or elsif sections
|
29
27
|
### if the condition isn't true.
|
30
28
|
def render( state )
|
31
|
-
self.enable_rendering if super
|
32
|
-
self.render_subnodes( state )
|
33
|
-
return nil
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
### Render the tag's subnodes according to the tag's logical state.
|
38
|
-
def render_subnodes( renderstate )
|
39
|
-
self.log.debug "Rendering subnodes. Rendering initially %s" %
|
40
|
-
[ self.rendering_enabled? ? "enabled" : "disabled" ]
|
41
|
-
|
42
|
-
# walk the subtree, modifying the logic flags for else and elsif tags,
|
43
|
-
# and rendering nodes if rendering is enabled
|
44
|
-
self.subnodes.each do |node|
|
45
|
-
case node
|
46
|
-
when Inversion::Template::ElsifTag
|
47
|
-
self.log.debug " logic switch: %p..." % [ node ]
|
48
|
-
if !self.rendering_was_enabled? && node.render( renderstate )
|
49
|
-
self.enable_rendering
|
50
|
-
else
|
51
|
-
self.disable_rendering
|
52
|
-
end
|
53
29
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
30
|
+
# Start out with rendering enabled if the tag body evaluates trueishly
|
31
|
+
if self.evaluate( state )
|
32
|
+
self.log.debug "Initial state was TRUE; enabling rendering"
|
33
|
+
state.enable_rendering
|
34
|
+
else
|
35
|
+
self.log.debug "Initial state was FALSE; disabling rendering"
|
36
|
+
state.disable_rendering
|
37
|
+
end
|
61
38
|
|
62
|
-
|
63
|
-
|
64
|
-
|
39
|
+
# Set the tag state to track whether or not rendering has been enabled during the
|
40
|
+
# 'if' for an 'else' or 'elsif' tag.
|
41
|
+
state.with_tag_data( :rendering_was_enabled => state.rendering_enabled? ) do
|
42
|
+
super
|
65
43
|
end
|
44
|
+
|
45
|
+
state.enable_rendering
|
46
|
+
return nil
|
66
47
|
end
|
67
48
|
|
49
|
+
|
68
50
|
end # class Inversion::Template::IfTag
|
69
51
|
|
@@ -34,7 +34,8 @@ class Inversion::Template::ImportTag < Inversion::Template::Tag
|
|
34
34
|
### Merge the inherited renderstate into the current template's +renderstate+.
|
35
35
|
def render( renderstate )
|
36
36
|
if (( cstate = renderstate.containerstate ))
|
37
|
-
self.log.debug "Importing inherited attributes: %p from %p" %
|
37
|
+
self.log.debug "Importing inherited attributes: %p from %p" %
|
38
|
+
[ @attributes, cstate.attributes ]
|
38
39
|
|
39
40
|
# Pick out the attributes that are being imported
|
40
41
|
inherited_attrs = @attributes.inject( {} ) do |attrs, key|
|
@@ -43,6 +43,8 @@ class Inversion::Template::IncludeTag < Inversion::Template::Tag
|
|
43
43
|
end
|
44
44
|
|
45
45
|
|
46
|
+
### Parser callback -- append the nodes from the included template onto the
|
47
|
+
### tree of the including template.
|
46
48
|
def after_appending( parsestate )
|
47
49
|
parsestate.append_tree( @included_template.node_tree )
|
48
50
|
end
|
@@ -5,7 +5,7 @@ require 'inversion/mixins'
|
|
5
5
|
require 'inversion/template' unless defined?( Inversion::Template )
|
6
6
|
|
7
7
|
# Inversion template node base class. Template text is parsed by the
|
8
|
-
# Inversion::
|
8
|
+
# Inversion::Parser into nodes, and appended to a tree
|
9
9
|
# that is later walked when the template is rendered.
|
10
10
|
#
|
11
11
|
# This class is abstract; it just defines the API that other nodes
|
@@ -41,6 +41,7 @@ class Inversion::Template::Tag < Inversion::Template::Node
|
|
41
41
|
def self::inherited( subclass )
|
42
42
|
# Inversion.log.debug "%p inherited from %p" % [ subclass, self ]
|
43
43
|
Inversion::Template::Tag.derivatives << subclass
|
44
|
+
Inversion.log.debug "Loaded tag type %p" % [ subclass ]
|
44
45
|
super
|
45
46
|
end
|
46
47
|
|
@@ -58,8 +59,8 @@ class Inversion::Template::Tag < Inversion::Template::Node
|
|
58
59
|
|
59
60
|
Gem.find_files( TAG_PLUGIN_PATTERN ).each do |tagfile|
|
60
61
|
tagname = tagfile[ %r{/(\w+)tag\.rb$}, 1 ].untaint
|
62
|
+
next unless tagname
|
61
63
|
|
62
|
-
Inversion.log.debug "Loading tag type %p from %p" % [ tagname, tagfile ]
|
63
64
|
self.load( tagfile )
|
64
65
|
|
65
66
|
# Inversion.log.debug "Looking for class for %p tag" % [ tagname ]
|
@@ -93,7 +94,9 @@ class Inversion::Template::Tag < Inversion::Template::Node
|
|
93
94
|
|
94
95
|
### Safely load the specified +tagfile+.
|
95
96
|
def self::load( tagfile )
|
96
|
-
|
97
|
+
tagrequire = tagfile[ %r{inversion/template/\w+tag} ] or
|
98
|
+
raise "tag file %p doesn't look like a tag plugin" % [ tagfile ]
|
99
|
+
require( tagrequire )
|
97
100
|
rescue => err
|
98
101
|
Inversion.log.error "%s while loading tag plugin %p: %s" %
|
99
102
|
[ err.class.name, tagfile, err.message ]
|
@@ -3,8 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'inversion/template/node'
|
5
5
|
|
6
|
-
# Inversion text node class -- static content in templates between tags
|
7
|
-
# in a text node.
|
6
|
+
# Inversion text node class -- container for static content in templates between tags.
|
8
7
|
class Inversion::Template::TextNode < Inversion::Template::Node
|
9
8
|
include Inversion::Loggable
|
10
9
|
|
@@ -4,7 +4,6 @@
|
|
4
4
|
require 'inversion/mixins'
|
5
5
|
require 'inversion/template/attrtag'
|
6
6
|
require 'inversion/template/containertag'
|
7
|
-
require 'inversion/template/conditionaltag'
|
8
7
|
require 'inversion/template/elsetag'
|
9
8
|
|
10
9
|
|
@@ -20,40 +19,31 @@ require 'inversion/template/elsetag'
|
|
20
19
|
#
|
21
20
|
class Inversion::Template::UnlessTag < Inversion::Template::AttrTag
|
22
21
|
include Inversion::Loggable,
|
23
|
-
Inversion::Template::ContainerTag
|
24
|
-
Inversion::Template::ConditionalTag
|
22
|
+
Inversion::Template::ContainerTag
|
25
23
|
|
26
24
|
# Inherits AttrTag's tag patterns
|
27
25
|
|
28
26
|
### Render the tag's contents if the condition is true, or any else or elsif sections
|
29
27
|
### if the condition isn't true.
|
30
28
|
def render( state )
|
31
|
-
self.enable_rendering unless super
|
32
|
-
self.render_subnodes( state )
|
33
29
|
|
34
|
-
|
35
|
-
|
30
|
+
# Start out with rendering *disabled* if the tag body evaluates trueishly
|
31
|
+
if self.evaluate( state )
|
32
|
+
self.log.debug "Initial state was TRUE; disabling rendering"
|
33
|
+
state.disable_rendering
|
34
|
+
else
|
35
|
+
self.log.debug "Initial state was FALSE; enabling rendering"
|
36
|
+
state.enable_rendering
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# walk the subtree, modifying the logic flags for else and elsif tags,
|
43
|
-
# and rendering nodes if rendering is enabled
|
44
|
-
self.subnodes.each do |node|
|
45
|
-
if node.is_a?( Inversion::Template::ElseTag )
|
46
|
-
self.log.debug " logic switch: %p..." % [ node ]
|
47
|
-
if !self.rendering_was_enabled?
|
48
|
-
self.enable_rendering
|
49
|
-
else
|
50
|
-
self.disable_rendering
|
51
|
-
end
|
52
|
-
|
53
|
-
else
|
54
|
-
renderstate << node if self.rendering_enabled?
|
55
|
-
end
|
39
|
+
# Set the tag state to track whether or not rendering has been enabled during the
|
40
|
+
# 'unless' for an 'else' tag.
|
41
|
+
state.with_tag_data( :rendering_was_enabled => state.rendering_enabled? ) do
|
42
|
+
self.render_subnodes( state )
|
56
43
|
end
|
44
|
+
|
45
|
+
state.enable_rendering
|
46
|
+
return nil
|
57
47
|
end
|
58
48
|
|
59
49
|
end # class Inversion::Template::UnlessTag
|
@@ -19,12 +19,6 @@ class Inversion::Template::YieldTag < Inversion::Template::Tag
|
|
19
19
|
include Inversion::Loggable
|
20
20
|
|
21
21
|
|
22
|
-
### Set up a YieldTag's instance variables.
|
23
|
-
def initialize( * )
|
24
|
-
@block_value = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
22
|
######
|
29
23
|
public
|
30
24
|
######
|
@@ -34,7 +28,7 @@ class Inversion::Template::YieldTag < Inversion::Template::Tag
|
|
34
28
|
def before_rendering( renderstate )
|
35
29
|
if renderstate.block
|
36
30
|
self.log.debug "Yielding to %p before rendering." % [ renderstate.block ]
|
37
|
-
|
31
|
+
renderstate.tag_data[ self ] = renderstate.block.call( renderstate )
|
38
32
|
self.log.debug " render block returned: %p" % [ @block_value ]
|
39
33
|
end
|
40
34
|
end
|
@@ -44,8 +38,9 @@ class Inversion::Template::YieldTag < Inversion::Template::Tag
|
|
44
38
|
### #before_rendering (if there was a block).
|
45
39
|
def render( renderstate )
|
46
40
|
self.log.debug "Rendering as block return value: %p" % [ @block_value ]
|
47
|
-
return
|
41
|
+
return renderstate.tag_data[ self ]
|
48
42
|
end
|
49
43
|
|
44
|
+
|
50
45
|
end # class Inversion::Template::YieldTag
|
51
46
|
|