inversion 0.0.1 → 0.0.2

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 (50) hide show
  1. data.tar.gz.sig +0 -0
  2. data/Manifest.txt +45 -0
  3. data/lib/inversion.rb +2 -2
  4. data/lib/inversion/template/begintag.rb +122 -0
  5. data/lib/inversion/template/defaulttag.rb +135 -0
  6. data/lib/inversion/template/rescuetag.rb +92 -0
  7. data/lib/inversion/template/timedeltatag.rb +93 -0
  8. data/manual/layouts/default.erb +87 -0
  9. data/manual/lib/api-filter.rb +96 -0
  10. data/manual/lib/editorial-filter.rb +59 -0
  11. data/manual/lib/examples-filter.rb +238 -0
  12. data/manual/lib/links-filter.rb +111 -0
  13. data/manual/resources/css/manual.css +764 -0
  14. data/manual/resources/fonts/GraublauWeb.otf +0 -0
  15. data/manual/resources/fonts/GraublauWebBold.otf +0 -0
  16. data/manual/resources/fonts/Inconsolata.otf +0 -0
  17. data/manual/resources/images/arrow_225_small.png +0 -0
  18. data/manual/resources/images/arrow_315_small.png +0 -0
  19. data/manual/resources/images/arrow_skip.png +0 -0
  20. data/manual/resources/images/cc-by.png +0 -0
  21. data/manual/resources/images/dialog-error.png +0 -0
  22. data/manual/resources/images/dialog-information.png +0 -0
  23. data/manual/resources/images/dialog-warning.png +0 -0
  24. data/manual/resources/images/emblem-important.png +0 -0
  25. data/manual/resources/images/help.png +0 -0
  26. data/manual/resources/images/information.png +0 -0
  27. data/manual/resources/images/magnifier.png +0 -0
  28. data/manual/resources/images/magnifier_left.png +0 -0
  29. data/manual/resources/images/page_white_code.png +0 -0
  30. data/manual/resources/images/page_white_copy.png +0 -0
  31. data/manual/resources/images/printer.png +0 -0
  32. data/manual/resources/images/question.png +0 -0
  33. data/manual/resources/images/scripts_code.png +0 -0
  34. data/manual/resources/images/wrap.png +0 -0
  35. data/manual/resources/images/wrapping.png +0 -0
  36. data/manual/resources/js/jquery-1.4.4.min.js +167 -0
  37. data/manual/resources/js/manual.js +30 -0
  38. data/manual/resources/js/sh.js +580 -0
  39. data/manual/resources/swf/clipboard.swf +0 -0
  40. data/manual/src/examples.page +154 -0
  41. data/manual/src/gettingstarted.page +64 -0
  42. data/manual/src/index.page +97 -0
  43. data/manual/src/tags.page +501 -0
  44. data/manual/src/templates.page +74 -0
  45. data/spec/inversion/template/begintag_spec.rb +217 -0
  46. data/spec/inversion/template/defaulttag_spec.rb +60 -0
  47. data/spec/inversion/template/rescuetag_spec.rb +109 -0
  48. data/spec/inversion/template/timedeltatag_spec.rb +215 -0
  49. metadata +72 -27
  50. metadata.gz.sig +0 -0
@@ -0,0 +1,74 @@
1
+ ---
2
+ # vim: set et nosta sw=4 ts=4 ft=textile :
3
+ title: Templates
4
+ layout: default
5
+ index: 1
6
+ filters:
7
+ - erb
8
+ - links
9
+ - api
10
+ - examples
11
+ - textile
12
+ ---
13
+
14
+ h2. <%= page.config['title'] %>
15
+
16
+ <div id="auto-toc"></div>
17
+
18
+ Inversion <?api "templates":Inversion::Template ?> are the primary objects you'll be interacting with. Templates can be created from a string via <?api "Template#new":Inversion::Template.new ?>, or from a file with <?api "Template#load":Inversion::Template.load ?>.
19
+
20
+ h3(#options). Template Options
21
+
22
+ You can set Inversion's configuration options in a number of ways.
23
+
24
+ To set global options, Inversion supports the "Configurability":https://bitbucket.org/ged/configurability API, and registers itself with the @templates@ key. This means you can either add a 'templates' section to your Configurability config, or call <?api Inversion::Template.configure ?> yourself with an object that can be passed to @Hash#merge@.
25
+
26
+ To set options on a per-template basis, you can pass an options hash to either @.load@ or @.new@, or set them from within the template itself using the <?link "configure tag":Tags#configure-tag ?>.
27
+
28
+ The available options are:
29
+
30
+ <notextile>
31
+ <dl>
32
+ <dt>:ignore_unknown_tags</dt>
33
+ <dd>Setting to false causes unknown tags used in templates to raise an <code>Inversion::ParseError</code>.</dd>
34
+ <dd class="default">Default: true</dd>
35
+
36
+ <dt>:on_render_error</dt>
37
+ <dd>
38
+ Dictates the behavior of exceptions during rendering.
39
+ <dl>
40
+ <dt>:ignore</dt>
41
+ <dd>Exceptions are silently ignored.</dd>
42
+ <dt>:comment</dt>
43
+ <dd>Exceptions are rendered inline as comments.</dd>
44
+ <dt>:propagate</dt>
45
+ <dd>Exceptions bubble up to the caller of #render.</dd>
46
+ </dl>
47
+ </dd>
48
+ <dd class="default">Default: <code>:comment</code></dd>
49
+
50
+ <dt>:debugging_comments</dt>
51
+ <dd>Insert various Inversion parse and render statements while rendering.</dd>
52
+ <dd class="default">Default: <code>false</code></dd>
53
+
54
+ <dt>:comment_start</dt>
55
+ <dd>When rendering debugging comments, the comment is started with these characters.</dd>
56
+ <dd class="default">Default: <code>"&lt;!--"</code></dd>
57
+
58
+ <dt>:comment_end</dt>
59
+ <dd>When rendering debugging comments, the comment is finished with these characters.</dd>
60
+ <dd class="default">Default: <code>"--&gt;"</code></dd>
61
+
62
+ <dt>:template_paths</dt>
63
+ <dd>An array of filesystem paths to search for templates within, when loaded or included with a relative path. The current working directory is always the last checked member of this.</dd>
64
+ <dd class="default">Default: <code>[]</code></dd>
65
+
66
+ <dt>:escape_format</dt>
67
+ <dd>The escaping <?api "strategy":Inversion::Escaping ?> used by tags such as <code>escape</code> and <code>pp</code>.</dd>
68
+ <dd class="default">Default: <code>:html</code></dd>
69
+
70
+ <dt>:strip_tag_lines</dt>
71
+ <dd>If a tag's presence introduces a blank line into the output, this option removes it.</dd>
72
+ <dd class="default">Default: <code>true</code></dd>
73
+ </dl>
74
+ </notextile>
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env rspec -cfd -b
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
7
+ libdir = basedir + 'lib'
8
+
9
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'rspec'
14
+ require 'ostruct'
15
+ require 'spec/lib/helpers'
16
+ require 'inversion/template/begintag'
17
+ require 'inversion/template/textnode'
18
+ require 'inversion/template/attrtag'
19
+ require 'inversion/template/rescuetag'
20
+ require 'inversion/template/endtag'
21
+ require 'inversion/renderstate'
22
+
23
+ describe Inversion::Template::BeginTag do
24
+
25
+ before( :all ) do
26
+ setup_logging( :fatal )
27
+ end
28
+
29
+ after( :all ) do
30
+ reset_logging()
31
+ end
32
+
33
+
34
+ context "without any rescue clauses" do
35
+
36
+ before( :each ) do
37
+ @tag = Inversion::Template::BeginTag.new( ' ' )
38
+ @tag << Inversion::Template::AttrTag.new( 'foo.baz' )
39
+ @tag << Inversion::Template::TextNode.new( ':the stuff after the attr' )
40
+ end
41
+
42
+ it "should render its subnodes as-is if none of them raise an exception" do
43
+ renderstate = Inversion::RenderState.new( :foo => OpenStruct.new(:baz => 'the body') )
44
+ renderstate << @tag
45
+ renderstate.to_s.should == 'the body:the stuff after the attr'
46
+ end
47
+
48
+ it "should use the configured error behavior of the template if a subnode raises any exception" do
49
+ renderstate = Inversion::RenderState.new
50
+ renderstate << @tag
51
+ renderstate.to_s.should =~ /NoMethodError/
52
+ renderstate.to_s.should_not =~ /the stuff after the attr/i
53
+ end
54
+
55
+ end
56
+
57
+ context "with a single rescue clause with no exception type" do
58
+
59
+ before( :each ) do
60
+ @tag = Inversion::Template::BeginTag.new( ' ' )
61
+
62
+ @attrtag = Inversion::Template::AttrTag.new( 'foo.baz' )
63
+ @normal_textnode = Inversion::Template::TextNode.new( ':the stuff after the attr' )
64
+ @rescue_textnode = Inversion::Template::TextNode.new( 'rescue stuff' )
65
+
66
+ @tag << @attrtag << @normal_textnode
67
+ @tag << Inversion::Template::RescueTag.new( '' )
68
+ @tag << @rescue_textnode
69
+
70
+ @renderstate = Inversion::RenderState.new
71
+ end
72
+
73
+ it "contains one rescue clause for RuntimeErrors" do
74
+ @tag.rescue_clauses.should == [ [[::RuntimeError], [@rescue_textnode]] ]
75
+ end
76
+
77
+ it "should render its subnodes as-is if none of them raise an exception" do
78
+ renderstate = Inversion::RenderState.new( :foo => OpenStruct.new(:baz => 'the body') )
79
+ renderstate << @tag
80
+ renderstate.to_s.should == 'the body:the stuff after the attr'
81
+ end
82
+
83
+ it "should render the rescue section if a subnode raises a RuntimeError" do
84
+ fooobj = Object.new
85
+ def fooobj.baz; raise "An exception"; end
86
+
87
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
88
+ renderstate << @tag
89
+ renderstate.to_s.should == 'rescue stuff'
90
+ end
91
+
92
+ it "should use the configured error behavior of the template if a subnode raises an " +
93
+ "exception other than RuntimeError" do
94
+ fooobj = Object.new
95
+ def fooobj.baz; raise Errno::ENOENT, "No such file or directory"; end
96
+
97
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
98
+ renderstate << @tag
99
+ renderstate.to_s.should =~ /ENOENT/i
100
+ renderstate.to_s.should_not =~ /rescue stuff/i
101
+ renderstate.to_s.should_not =~ /the stuff after the attr/i
102
+ end
103
+ end
104
+
105
+
106
+ context "with a single rescue clause with an exception type" do
107
+ before( :each ) do
108
+ @tag = Inversion::Template::BeginTag.new( ' ' )
109
+
110
+ @attrtag = Inversion::Template::AttrTag.new( 'foo.baz' )
111
+ @normal_textnode = Inversion::Template::TextNode.new( ':the stuff after the attr' )
112
+ @rescue_textnode = Inversion::Template::TextNode.new( 'rescue stuff' )
113
+
114
+ @tag << @attrtag << @normal_textnode
115
+ @tag << Inversion::Template::RescueTag.new( 'SystemCallError' )
116
+ @tag << @rescue_textnode
117
+
118
+ @renderstate = Inversion::RenderState.new
119
+ end
120
+
121
+ it "contains one rescue clause for the specified exception type" do
122
+ @tag.rescue_clauses.should == [ [[::SystemCallError], [@rescue_textnode]] ]
123
+ end
124
+
125
+ it "should render its subnodes as-is if none of them raise an exception" do
126
+ renderstate = Inversion::RenderState.new( :foo => OpenStruct.new(:baz => 'the body') )
127
+ renderstate << @tag
128
+ renderstate.to_s.should == 'the body:the stuff after the attr'
129
+ end
130
+
131
+ it "should render the rescue section if a subnode raises the specified exception type" do
132
+ fooobj = Object.new
133
+ def fooobj.baz; raise Errno::ENOENT, "no such file or directory"; end
134
+
135
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
136
+ renderstate << @tag
137
+ renderstate.to_s.should == 'rescue stuff'
138
+ end
139
+
140
+ it "should use the configured error behavior of the template if a subnode raises an " +
141
+ "exception other than the specified type" do
142
+ fooobj = Object.new
143
+ def fooobj.baz; raise "SPlat!"; end
144
+
145
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
146
+ renderstate << @tag
147
+ renderstate.to_s.should =~ /RuntimeError/i
148
+ renderstate.to_s.should_not =~ /rescue stuff/i
149
+ renderstate.to_s.should_not =~ /the stuff after the attr/i
150
+ end
151
+ end
152
+
153
+ context "with multiple rescue clauses" do
154
+ before( :each ) do
155
+ @tag = Inversion::Template::BeginTag.new( ' ' )
156
+
157
+ @attrtag = Inversion::Template::AttrTag.new( 'foo.baz' )
158
+ @normal_textnode = Inversion::Template::TextNode.new( ':the stuff after the attr' )
159
+ @rescue_textnode = Inversion::Template::TextNode.new( 'rescue stuff' )
160
+ @rescue_textnode2 = Inversion::Template::TextNode.new( 'alternative rescue stuff' )
161
+
162
+ @tag << @attrtag << @normal_textnode
163
+ @tag << Inversion::Template::RescueTag.new( '' )
164
+ @tag << @rescue_textnode
165
+ @tag << Inversion::Template::RescueTag.new( 'Errno::ENOENT, Errno::EWOULDBLOCK' )
166
+ @tag << @rescue_textnode2
167
+
168
+ @renderstate = Inversion::RenderState.new
169
+ end
170
+
171
+ it "contains a rescue tuple for each rescue tag" do
172
+ @tag.rescue_clauses.should == [
173
+ [[::RuntimeError], [@rescue_textnode]],
174
+ [[Errno::ENOENT, Errno::EWOULDBLOCK], [@rescue_textnode2]],
175
+ ]
176
+ end
177
+
178
+ it "should render its subnodes as-is if none of them raise an exception" do
179
+ renderstate = Inversion::RenderState.new( :foo => OpenStruct.new(:baz => 'the body') )
180
+ renderstate << @tag
181
+ renderstate.to_s.should == 'the body:the stuff after the attr'
182
+ end
183
+
184
+ it "should render the first rescue section if a subnode raises the exception it " +
185
+ "specifies" do
186
+ fooobj = Object.new
187
+ def fooobj.baz; raise "An exception"; end
188
+
189
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
190
+ renderstate << @tag
191
+ renderstate.to_s.should == 'rescue stuff'
192
+ end
193
+
194
+ it "should render the second rescue section if a subnode raises the exception it " +
195
+ "specifies" do
196
+ fooobj = Object.new
197
+ def fooobj.baz; raise Errno::ENOENT, "no such file or directory"; end
198
+
199
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
200
+ renderstate << @tag
201
+ renderstate.to_s.should == 'alternative rescue stuff'
202
+ end
203
+
204
+ it "should use the configured error behavior of the template if a subnode raises an " +
205
+ "exception other than those specified by the rescue clauses" do
206
+ fooobj = Object.new
207
+ def fooobj.baz; raise Errno::ENOMEM, "All out!"; end
208
+
209
+ renderstate = Inversion::RenderState.new( :foo => fooobj )
210
+ renderstate << @tag
211
+ renderstate.to_s.should =~ /ENOMEM/i
212
+ renderstate.to_s.should_not =~ /rescue stuff/i
213
+ renderstate.to_s.should_not =~ /the stuff after the attr/i
214
+ end
215
+ end
216
+
217
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env rspec -cfd -b
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
7
+ libdir = basedir + 'lib'
8
+
9
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'rspec'
14
+ require 'spec/lib/helpers'
15
+ require 'inversion/template/defaulttag'
16
+
17
+ describe Inversion::Template::DefaultTag do
18
+
19
+ before( :all ) do
20
+ setup_logging( :fatal )
21
+ end
22
+
23
+ after( :all ) do
24
+ reset_logging()
25
+ end
26
+
27
+
28
+ it "sets a template attribute to a default value" do
29
+ tmpl = Inversion::Template.new( '<?default foo to 11883 ?><?attr foo ?>' )
30
+ tmpl.render.should == '11883'
31
+ end
32
+
33
+ it "doesn't override a value set on the template as an attribute" do
34
+ tmpl = Inversion::Template.new( '<?default foo to 11883 ?><?attr foo ?>' )
35
+ tmpl.foo = 'bar'
36
+ tmpl.render.should == 'bar'
37
+ end
38
+
39
+ it "can set a template attribute to the result of calling a methodchain" do
40
+ tmpl = Inversion::Template.
41
+ new( '<?default width to foo.length ?><?attr foo ?>:<?attr width ?>' )
42
+ tmpl.foo = 'bar'
43
+ tmpl.render.should == 'bar:3'
44
+ end
45
+
46
+ it "can format the default value" do
47
+ tmpl = Inversion::Template.
48
+ new( '<?default width to "[%02d]" % [ foo.length ] ?><?attr foo ?>:<?attr width ?>' )
49
+ tmpl.foo = 'bar'
50
+ tmpl.render.should == 'bar:[03]'
51
+ end
52
+
53
+ it "can render itself as a comment for template debugging" do
54
+ tag = Inversion::Template::DefaultTag.new( 'width to foo.length' )
55
+ tag.as_comment_body.should == "Default 'width': { template.foo.length }"
56
+ end
57
+
58
+ end
59
+
60
+
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env rspec -cfd -b
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
7
+ libdir = basedir + 'lib'
8
+
9
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'rspec'
14
+ require 'spec/lib/helpers'
15
+ require 'inversion/template/begintag'
16
+ require 'inversion/template/rescuetag'
17
+ require 'inversion/template/commenttag'
18
+ require 'inversion/template/fortag'
19
+ require 'inversion/renderstate'
20
+
21
+ describe Inversion::Template::RescueTag do
22
+
23
+ before( :all ) do
24
+ setup_logging( :fatal )
25
+ end
26
+
27
+ after( :all ) do
28
+ reset_logging()
29
+ end
30
+
31
+ it "handles a non-existant body" do
32
+ tag = Inversion::Template::RescueTag.new( nil )
33
+ tag.exception_types.should == [ ::RuntimeError ]
34
+ end
35
+
36
+ it "parses its body into classes" do
37
+ tag = Inversion::Template::RescueTag.new( 'ScriptError' )
38
+ tag.exception_types.should == [ ::ScriptError ]
39
+ end
40
+
41
+ it "handles fully-qualified class names" do
42
+ tag = Inversion::Template::RescueTag.new( '::ScriptError' )
43
+ tag.exception_types.should == [ ::ScriptError ]
44
+ end
45
+
46
+ it "can parse multiple exception class names" do
47
+ tag = Inversion::Template::RescueTag.new( '::ScriptError, Inversion::ParseError' )
48
+ tag.exception_types.should == [ ::ScriptError, Inversion::ParseError ]
49
+ end
50
+
51
+ it "can be appended to a 'begin' tag" do
52
+ template = double( "template object" )
53
+ parserstate = Inversion::Template::Parser::State.new( template )
54
+ begintag = Inversion::Template::BeginTag.new
55
+ rescuetag = Inversion::Template::RescueTag.new
56
+ textnode = Inversion::Template::TextNode.new( 'Yeah!' )
57
+ endtag = Inversion::Template::EndTag.new
58
+
59
+ parserstate << begintag << rescuetag << textnode << endtag
60
+
61
+ parserstate.tree.should == [ begintag, endtag ]
62
+ begintag.rescue_clauses.should == [ [[::RuntimeError], [textnode]] ]
63
+ end
64
+
65
+ it "can be appended to a 'comment' tag" do
66
+ template = double( "template object" )
67
+ parserstate = Inversion::Template::Parser::State.new( template )
68
+ commenttag = Inversion::Template::CommentTag.new( 'rescue section for later' )
69
+ rescuetag = Inversion::Template::RescueTag.new
70
+ endtag = Inversion::Template::EndTag.new
71
+
72
+ parserstate << commenttag << rescuetag << endtag
73
+
74
+ parserstate.tree.should == [ commenttag, endtag ]
75
+ commenttag.subnodes.should include( rescuetag )
76
+ end
77
+
78
+ it "raises an error if it's about to be appended to anything other than a 'begin' or " +
79
+ "'comment' tag" do
80
+ template = double( "template object" )
81
+ parserstate = Inversion::Template::Parser::State.new( template )
82
+ parserstate << Inversion::Template::ForTag.new( 'foo in bar' )
83
+
84
+ expect {
85
+ parserstate << Inversion::Template::RescueTag.new
86
+ }.to raise_exception( Inversion::ParseError, /'for' tags can't have 'rescue' clauses/i )
87
+ end
88
+
89
+
90
+ it "raises an error if it's about to be appended without an opening 'begin'" do
91
+ template = double( "template object" )
92
+ parserstate = Inversion::Template::Parser::State.new( template )
93
+
94
+ expect {
95
+ parserstate << Inversion::Template::RescueTag.new
96
+ }.to raise_exception( Inversion::ParseError, /orphaned 'rescue' tag/i )
97
+ end
98
+
99
+
100
+ it "doesn't render as anything by itself" do
101
+ renderstate = Inversion::RenderState.new
102
+ tag = Inversion::Template::RescueTag.new
103
+ tag.render( renderstate ).should be_nil()
104
+ end
105
+
106
+ end
107
+
108
+
109
+