inversion 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
data.tar.gz.sig CHANGED
Binary file
data/Manifest.txt CHANGED
@@ -12,12 +12,14 @@ lib/inversion/renderstate.rb
12
12
  lib/inversion/sinatra.rb
13
13
  lib/inversion/template.rb
14
14
  lib/inversion/template/attrtag.rb
15
+ lib/inversion/template/begintag.rb
15
16
  lib/inversion/template/calltag.rb
16
17
  lib/inversion/template/codetag.rb
17
18
  lib/inversion/template/commenttag.rb
18
19
  lib/inversion/template/conditionaltag.rb
19
20
  lib/inversion/template/configtag.rb
20
21
  lib/inversion/template/containertag.rb
22
+ lib/inversion/template/defaulttag.rb
21
23
  lib/inversion/template/elsetag.rb
22
24
  lib/inversion/template/elsiftag.rb
23
25
  lib/inversion/template/endtag.rb
@@ -30,25 +32,66 @@ lib/inversion/template/node.rb
30
32
  lib/inversion/template/parser.rb
31
33
  lib/inversion/template/pptag.rb
32
34
  lib/inversion/template/publishtag.rb
35
+ lib/inversion/template/rescuetag.rb
33
36
  lib/inversion/template/subscribetag.rb
34
37
  lib/inversion/template/tag.rb
35
38
  lib/inversion/template/textnode.rb
39
+ lib/inversion/template/timedeltatag.rb
36
40
  lib/inversion/template/unlesstag.rb
37
41
  lib/inversion/template/uriencodetag.rb
38
42
  lib/inversion/template/yieldtag.rb
39
43
  lib/inversion/tilt.rb
40
44
  lib/inversion/utils.rb
45
+ manual/layouts/default.erb
46
+ manual/lib/api-filter.rb
47
+ manual/lib/editorial-filter.rb
48
+ manual/lib/examples-filter.rb
49
+ manual/lib/links-filter.rb
50
+ manual/resources/css/manual.css
51
+ manual/resources/fonts/GraublauWeb.otf
52
+ manual/resources/fonts/GraublauWebBold.otf
53
+ manual/resources/fonts/Inconsolata.otf
54
+ manual/resources/images/arrow_225_small.png
55
+ manual/resources/images/arrow_315_small.png
56
+ manual/resources/images/arrow_skip.png
57
+ manual/resources/images/cc-by.png
58
+ manual/resources/images/dialog-error.png
59
+ manual/resources/images/dialog-information.png
60
+ manual/resources/images/dialog-warning.png
61
+ manual/resources/images/emblem-important.png
62
+ manual/resources/images/help.png
63
+ manual/resources/images/information.png
64
+ manual/resources/images/magnifier.png
65
+ manual/resources/images/magnifier_left.png
66
+ manual/resources/images/page_white_code.png
67
+ manual/resources/images/page_white_copy.png
68
+ manual/resources/images/printer.png
69
+ manual/resources/images/question.png
70
+ manual/resources/images/scripts_code.png
71
+ manual/resources/images/wrap.png
72
+ manual/resources/images/wrapping.png
73
+ manual/resources/js/jquery-1.4.4.min.js
74
+ manual/resources/js/manual.js
75
+ manual/resources/js/sh.js
76
+ manual/resources/swf/clipboard.swf
77
+ manual/src/examples.page
78
+ manual/src/gettingstarted.page
79
+ manual/src/index.page
80
+ manual/src/tags.page
81
+ manual/src/templates.page
41
82
  spec/data/sinatra/hello.inversion
42
83
  spec/inversion/mixins_spec.rb
43
84
  spec/inversion/monkeypatches_spec.rb
44
85
  spec/inversion/renderstate_spec.rb
45
86
  spec/inversion/sinatra_spec.rb
46
87
  spec/inversion/template/attrtag_spec.rb
88
+ spec/inversion/template/begintag_spec.rb
47
89
  spec/inversion/template/calltag_spec.rb
48
90
  spec/inversion/template/codetag_spec.rb
49
91
  spec/inversion/template/commenttag_spec.rb
50
92
  spec/inversion/template/configtag_spec.rb
51
93
  spec/inversion/template/containertag_spec.rb
94
+ spec/inversion/template/defaulttag_spec.rb
52
95
  spec/inversion/template/elsetag_spec.rb
53
96
  spec/inversion/template/elsiftag_spec.rb
54
97
  spec/inversion/template/endtag_spec.rb
@@ -61,9 +104,11 @@ spec/inversion/template/node_spec.rb
61
104
  spec/inversion/template/parser_spec.rb
62
105
  spec/inversion/template/pptag_spec.rb
63
106
  spec/inversion/template/publishtag_spec.rb
107
+ spec/inversion/template/rescuetag_spec.rb
64
108
  spec/inversion/template/subscribetag_spec.rb
65
109
  spec/inversion/template/tag_spec.rb
66
110
  spec/inversion/template/textnode_spec.rb
111
+ spec/inversion/template/timedeltatag_spec.rb
67
112
  spec/inversion/template/unlesstag_spec.rb
68
113
  spec/inversion/template/uriencodetag_spec.rb
69
114
  spec/inversion/template/yieldtag_spec.rb
data/lib/inversion.rb CHANGED
@@ -26,10 +26,10 @@ module Inversion
26
26
  require 'inversion/monkeypatches'
27
27
 
28
28
  # Library version constant
29
- VERSION = '0.0.1'
29
+ VERSION = '0.0.2'
30
30
 
31
31
  # Version-control revision constant
32
- REVISION = %q$Revision: 73c3d8215868 $
32
+ REVISION = %q$Revision: 08e77b056c67 $
33
33
 
34
34
  #
35
35
  # Logging
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ require 'inversion/mixins'
5
+ require 'inversion/template/attrtag'
6
+ require 'inversion/template/containertag'
7
+ require 'inversion/template/conditionaltag'
8
+ require 'inversion/template/rescuetag'
9
+
10
+
11
+ # Inversion 'begin' tag.
12
+ #
13
+ # This tag causes a section of the template to be rendered only if no exceptions are raised
14
+ # while it's being rendered. If an exception is raised, it is checked against any 'rescue'
15
+ # blocks, and the first one with a matching exception is rendered instead. If no 'rescue' block
16
+ # is found, the exception is handled by the configured exception behavior for the template,
17
+ # and the resulting replaces the block.
18
+ #
19
+ # == Syntax
20
+ #
21
+ # <?begin ?><?call employees.length ?><?end?>
22
+ #
23
+ # <?begin ?>
24
+ # <?for employee in employees.all ?>
25
+ # <?attr employee.name ?> --> <?attr employee.title ?>
26
+ # <?end for?>
27
+ # <?rescue DatabaseError => err ?>
28
+ # Oh no!! I can't talk to the database for some reason. The
29
+ # error was as follows:
30
+ # <pre>
31
+ # <?attr err.message ?>
32
+ # </pre>
33
+ # <?end?>
34
+ #
35
+ class Inversion::Template::BeginTag < Inversion::Template::Tag
36
+ include Inversion::Loggable,
37
+ Inversion::Template::ContainerTag
38
+
39
+
40
+ ### Initialize a new BeginTag.
41
+ def initialize( body='', linenum=nil, colnum=nil ) # :notnew:
42
+ super
43
+ @rescue_clauses = [] # [ [RuntimeError, ArgumentError], [subnodes] ]
44
+ end
45
+
46
+
47
+ ######
48
+ public
49
+ ######
50
+
51
+ # The tuples of rescue clauses handled by the begin
52
+ attr_reader :rescue_clauses
53
+
54
+
55
+ ### Override the append operator to separate out RescueTags and the nodes that follow
56
+ ### them.
57
+ def <<( subnode )
58
+ case
59
+
60
+ # If this node is a <?rescue?>, add a container for the subnodes that belong to it
61
+ # and the list of exception types that it rescues
62
+ when subnode.is_a?( Inversion::Template::RescueTag )
63
+ @rescue_clauses << [ subnode.exception_types, [] ]
64
+
65
+ # If there's already at least one rescue clause in effect, add any subnodes to
66
+ # the last one
67
+ when !@rescue_clauses.empty?
68
+ @rescue_clauses.last[1] << subnode
69
+
70
+ # Append nodes in the begin, but before any rescue to the begin tag
71
+ else
72
+ super
73
+ end
74
+
75
+ return self
76
+ end
77
+
78
+
79
+ ### Render the tag's contents if the condition is true, or any else or elsif sections
80
+ ### if the condition isn't true.
81
+ def render( state )
82
+ output = []
83
+
84
+ errhandler = self.method( :handle_exception )
85
+ state.with_destination( output ) do
86
+ state.with_error_handler( errhandler ) do
87
+ catch( :stop_rendering ) do
88
+ self.render_subnodes( state )
89
+ end
90
+ self.log.debug " leaving the error-handler block"
91
+ end
92
+ self.log.debug " leaving the overridden output block"
93
+ end
94
+
95
+ self.log.debug "Rendered begin section as: %p" % [ output ]
96
+ return output
97
+ end
98
+
99
+
100
+ ### The replacement exception-handler provided to RenderState.
101
+ def handle_exception( state, node, exception )
102
+ self.log.debug "Handling %p raised by %p: %s" % [ exception.class, node, exception.message ]
103
+ state.destination.clear
104
+
105
+ self.rescue_clauses.each do |errclasses, nodes|
106
+ self.log.debug " considering rescue clause: %p -> %p" % [ errclasses, nodes ]
107
+ if errclasses.any? {|eclass| eclass === exception }
108
+ self.log.debug " rescued by a clause for %p" % [ errclasses ]
109
+ nodes.each {|node| state << node }
110
+ throw :stop_rendering
111
+ end
112
+ end
113
+
114
+ # Use the default error handler
115
+ self.log.debug " no rescue clause for a %p: falling back to the default error handler" %
116
+ [ exception.class ]
117
+ state.destination << state.default_error_handler( state, node, exception )
118
+ throw :stop_rendering
119
+ end
120
+
121
+ end # class Inversion::Template::BeginTag
122
+
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ require 'inversion/template/codetag'
5
+
6
+ # Inversion 'default' tag.
7
+ #
8
+ # The default tag sets the default value of an attribute to a constant, the value of
9
+ # another attribute, or the results of evaluating a methodchain on an attribute.
10
+ #
11
+ # == Syntax
12
+ # <!-- Set a default width that can be overridden by the controller -->
13
+ # <?default width to 120 ?>
14
+ # <?default employees to [] ?>
15
+ #
16
+ # <!-- Default an attribute to the value of a second attribute -->
17
+ # <?default content to body ?>
18
+ #
19
+ # <!-- Set the title to the employee's name if it hasn't been set explicitly -->
20
+ # <?default title to "%s, %s" % [ employee.lastname, employee.firstname ] ?>
21
+ #
22
+ class Inversion::Template::DefaultTag < Inversion::Template::CodeTag
23
+
24
+ # <?default «identifier» to "%s" % foo ?>
25
+ tag_pattern '$(ident) sp $(ident) sp tstring_beg $(tstring_content) tstring_end sp* $(op) sp* $( .* )' do |tag, match|
26
+ op = match.string( 4 )
27
+ raise Inversion::ParseError, "expected '%%', got %p instead" % [ op ] unless op == '%'
28
+ raise Inversion::ParseError, "invalid operator: expected 'to', got %p for %p" %
29
+ [ match.string(2), tag.body ] unless match.string(2) == 'to'
30
+
31
+ tag.name = match.string( 1 )
32
+ tag.format = match.string( 3 )
33
+ tag.literal = match.string( 5 )
34
+ end
35
+
36
+ # <?default «identifer» to «identifier».«methodchain» ?>
37
+ tag_pattern "$(ident) sp $(ident) sp $(ident) $( .* )" do |tag, match|
38
+ raise Inversion::ParseError, "invalid operator: expected 'to', got %p for %p" %
39
+ [ match.string(2), tag.body ] unless match.string(2) == 'to'
40
+
41
+ tag.name = match.string( 1 )
42
+ tag.identifiers << match.string( 3 )
43
+ tag.methodchain = match.string( 4 )
44
+ end
45
+
46
+ # <?default «identifer» to «literal» ?>
47
+ tag_pattern "$(ident) sp $(ident) sp $( .* )" do |tag, match|
48
+ raise Inversion::ParseError, "invalid operator: expected 'to', got %p for %p" %
49
+ [ match.string(2), tag.body ] unless match.string(2) == 'to'
50
+
51
+ tag.name = match.string( 1 )
52
+ tag.literal = match.string( 3 )
53
+ end
54
+
55
+
56
+ ### Create a new DefaultTag with the given +name+, which should be a valid
57
+ ### Ruby identifier.
58
+ def initialize( body, linenum=nil, colnum=nil )
59
+ @name = nil
60
+ @methodchain = nil
61
+ @literal = nil
62
+ @format = nil
63
+
64
+ super
65
+
66
+ # Add an identifier for the tag name
67
+ self.identifiers << self.name.untaint.to_sym
68
+ end
69
+
70
+
71
+ ######
72
+ public
73
+ ######
74
+
75
+ # the name of the attribute
76
+ attr_accessor :name
77
+
78
+ # the format string used to format the attribute in the template (if
79
+ # one was declared)
80
+ attr_accessor :format
81
+
82
+ # The literal, if the tag had one (as opposed to an attribute or methodchain)
83
+ attr_accessor :literal
84
+
85
+ # the chain of methods that should be called (if any).
86
+ attr_accessor :methodchain
87
+
88
+
89
+ ### Render the tag as the body of a comment, suitable for template debugging.
90
+ def as_comment_body
91
+ comment = "%s '%s': { " % [ self.tagname, self.name ]
92
+ if self.methodchain
93
+ comment << "template.%s%s" % [ self.identifiers.first, self.methodchain ]
94
+ else
95
+ comment << self.literal
96
+ end
97
+ comment << " }"
98
+ comment << " with format: %p" % [ self.format ] if self.format
99
+
100
+ return comment
101
+ end
102
+
103
+
104
+ ### Set the specified value (if it's nil) before rendering.
105
+ def before_rendering( renderstate )
106
+ if val = renderstate.attributes[ self.name.to_sym ]
107
+ self.log.info "Not defaulting %s: already set to %p" %
108
+ [ self.name, val ]
109
+ return nil
110
+ end
111
+
112
+ default = nil
113
+ if chain = self.methodchain
114
+ self.log.debug "Using methodchain %p to set default for %p" %
115
+ [ chain, self.name ]
116
+ default = renderstate.eval( 'self' + '.' + self.identifiers.first + chain )
117
+ else
118
+ self.log.debug "Using literal %p to set default for %p" %
119
+ [ self.literal, self.name ]
120
+ default = renderstate.eval( self.literal )
121
+ default = self.format % default if self.format
122
+ end
123
+
124
+ self.log.debug " default value: %p" % [ default ]
125
+ renderstate.attributes[ self.name.to_sym ] = default
126
+ end
127
+
128
+
129
+ ### Render as the empty string.
130
+ def render( renderstate )
131
+ return ''
132
+ end
133
+
134
+ end # class Inversion::Template::DefaultTag
135
+
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+ require 'inversion/template/tag'
5
+
6
+
7
+ # Inversion 'rescue' tag.
8
+ #
9
+ # This tag adds a logical switch to a BeginTag. If rendering any of the BeginTag's nodes raises
10
+ # an exception of the type specified by the RescueTag, the nodes following the RescueTag are
11
+ # rendered instead.
12
+ #
13
+ # == Syntax
14
+ #
15
+ # <?begin ?>
16
+ # <?for employee in employees.all ?>
17
+ # <?attr employee.name ?> --> <?attr employee.title ?>
18
+ # <?end for?>
19
+ # <?rescue DatabaseError => err ?>
20
+ # Oh no!! I can't talk to the database for some reason. The
21
+ # error was as follows:
22
+ #
23
+ # <?attr err.message ?>
24
+ #
25
+ # <?end?>
26
+ #
27
+ class Inversion::Template::RescueTag < Inversion::Template::Tag
28
+ include Inversion::Loggable
29
+
30
+
31
+ ### Overridden to default body to nothing, and raise an error if it has one.
32
+ def initialize( body='', linenum=nil, colnum=nil ) # :notnew:
33
+ super
34
+ @exception_types = parse_exception_types( self.body )
35
+ end
36
+
37
+
38
+ ######
39
+ public
40
+ ######
41
+
42
+ # The exception classes the rescue will handle (an Array of Class objects)
43
+ attr_reader :exception_types
44
+
45
+
46
+ ### Parsing callback -- check to be sure the node tree can have the
47
+ ### 'else' tag appended to it.
48
+ def before_appending( parsestate )
49
+ condtag = parsestate.node_stack.reverse.find do |node|
50
+ case node
51
+
52
+ # If there was a previous 'begin', the 'rescue' belongs to it. Also
53
+ # allow it to be appended to a 'comment' section so you can comment out a
54
+ # rescue clause without commenting out the begin
55
+ when Inversion::Template::BeginTag,
56
+ Inversion::Template::CommentTag
57
+ break node
58
+
59
+ # If it's some other kind of container, it's an error
60
+ when Inversion::Template::ContainerTag
61
+ raise Inversion::ParseError, "'%s' tags can't have '%s' clauses" %
62
+ [ node.tagname.downcase, self.tagname.downcase ]
63
+ end
64
+ end
65
+
66
+ # If there wasn't a valid container, it's an error too
67
+ raise Inversion::ParseError, "orphaned '%s' tag" % [ self.tagname.downcase ] unless condtag
68
+ end
69
+
70
+
71
+ #######
72
+ private
73
+ #######
74
+
75
+ ### Parse one or more exception classes from the given +rescuespec+ and return them.
76
+ def parse_exception_types( rescuespec )
77
+ return [ ::RuntimeError ] if rescuespec.nil? || rescuespec == ''
78
+
79
+ # Turn a comma-delimited list of exception names into the corresponding classes
80
+ return rescuespec.split( /\s*,\s*/ ).collect do |classname|
81
+ classname.split( '::' ).
82
+ reject( &:empty? ).
83
+ inject( Object ) do |klass, name|
84
+ klass = klass.const_get( name ) or
85
+ raise "No such exception class %s" % [ classname ]
86
+ klass
87
+ end
88
+ end
89
+ end
90
+
91
+ end # class Inversion::Template::RescueTag
92
+