inversion 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|