inversion 1.3.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Examples.md +134 -0
  4. data/GettingStarted.md +50 -0
  5. data/Guide.md +14 -0
  6. data/{History.rdoc → History.md} +59 -43
  7. data/{README.rdoc → README.md} +43 -34
  8. data/Tags.md +555 -0
  9. data/bin/inversion +4 -8
  10. data/lib/inversion/cli/api.rb +75 -0
  11. data/lib/inversion/cli/tagtokens.rb +34 -0
  12. data/lib/inversion/cli/tree.rb +70 -0
  13. data/lib/inversion/cli.rb +406 -0
  14. data/lib/inversion/exceptions.rb +0 -1
  15. data/lib/inversion/mixins.rb +10 -11
  16. data/lib/inversion/parser.rb +5 -6
  17. data/lib/inversion/refinements.rb +18 -0
  18. data/lib/inversion/renderstate.rb +24 -25
  19. data/lib/inversion/sinatra.rb +0 -1
  20. data/lib/inversion/template/attrtag.rb +7 -5
  21. data/lib/inversion/template/begintag.rb +0 -1
  22. data/lib/inversion/template/calltag.rb +0 -1
  23. data/lib/inversion/template/codetag.rb +37 -28
  24. data/lib/inversion/template/commenttag.rb +0 -1
  25. data/lib/inversion/template/configtag.rb +3 -4
  26. data/lib/inversion/template/containertag.rb +1 -2
  27. data/lib/inversion/template/defaulttag.rb +1 -2
  28. data/lib/inversion/template/elsetag.rb +0 -1
  29. data/lib/inversion/template/elsiftag.rb +0 -1
  30. data/lib/inversion/template/endtag.rb +2 -3
  31. data/lib/inversion/template/escapetag.rb +1 -2
  32. data/lib/inversion/template/fortag.rb +2 -3
  33. data/lib/inversion/template/fragmenttag.rb +1 -2
  34. data/lib/inversion/template/iftag.rb +3 -1
  35. data/lib/inversion/template/importtag.rb +2 -3
  36. data/lib/inversion/template/includetag.rb +1 -2
  37. data/lib/inversion/template/node.rb +4 -5
  38. data/lib/inversion/template/pptag.rb +1 -2
  39. data/lib/inversion/template/publishtag.rb +2 -3
  40. data/lib/inversion/template/rescuetag.rb +1 -2
  41. data/lib/inversion/template/subscribetag.rb +3 -4
  42. data/lib/inversion/template/tag.rb +3 -4
  43. data/lib/inversion/template/textnode.rb +1 -2
  44. data/lib/inversion/template/timedeltatag.rb +1 -2
  45. data/lib/inversion/template/unlesstag.rb +0 -1
  46. data/lib/inversion/template/uriencodetag.rb +1 -2
  47. data/lib/inversion/template/yieldtag.rb +0 -1
  48. data/lib/inversion/template.rb +18 -22
  49. data/lib/inversion/tilt.rb +1 -2
  50. data/lib/inversion.rb +2 -3
  51. data/lib/roda/plugins/inversion.rb +225 -0
  52. data/spec/helpers.rb +19 -13
  53. data/spec/inversion/mixins_spec.rb +1 -1
  54. data/spec/inversion/parser_spec.rb +1 -1
  55. data/spec/inversion/refinements_spec.rb +22 -0
  56. data/spec/inversion/renderstate_spec.rb +1 -1
  57. data/spec/inversion/sinatra_spec.rb +1 -1
  58. data/spec/inversion/template/attrtag_spec.rb +1 -1
  59. data/spec/inversion/template/begintag_spec.rb +1 -1
  60. data/spec/inversion/template/calltag_spec.rb +1 -1
  61. data/spec/inversion/template/codetag_spec.rb +24 -1
  62. data/spec/inversion/template/commenttag_spec.rb +1 -1
  63. data/spec/inversion/template/configtag_spec.rb +1 -1
  64. data/spec/inversion/template/containertag_spec.rb +1 -1
  65. data/spec/inversion/template/defaulttag_spec.rb +1 -1
  66. data/spec/inversion/template/elsetag_spec.rb +1 -1
  67. data/spec/inversion/template/elsiftag_spec.rb +1 -1
  68. data/spec/inversion/template/endtag_spec.rb +1 -1
  69. data/spec/inversion/template/escapetag_spec.rb +1 -1
  70. data/spec/inversion/template/fortag_spec.rb +1 -1
  71. data/spec/inversion/template/fragmenttag_spec.rb +1 -1
  72. data/spec/inversion/template/iftag_spec.rb +1 -1
  73. data/spec/inversion/template/importtag_spec.rb +1 -1
  74. data/spec/inversion/template/includetag_spec.rb +1 -1
  75. data/spec/inversion/template/node_spec.rb +1 -1
  76. data/spec/inversion/template/pptag_spec.rb +1 -1
  77. data/spec/inversion/template/publishtag_spec.rb +1 -1
  78. data/spec/inversion/template/rescuetag_spec.rb +1 -1
  79. data/spec/inversion/template/subscribetag_spec.rb +1 -1
  80. data/spec/inversion/template/tag_spec.rb +1 -1
  81. data/spec/inversion/template/textnode_spec.rb +1 -1
  82. data/spec/inversion/template/timedeltatag_spec.rb +1 -1
  83. data/spec/inversion/template/unlesstag_spec.rb +1 -1
  84. data/spec/inversion/template/uriencodetag_spec.rb +1 -1
  85. data/spec/inversion/template/yieldtag_spec.rb +1 -1
  86. data/spec/inversion/template_spec.rb +1 -1
  87. data/spec/inversion/tilt_spec.rb +1 -1
  88. data/spec/inversion_spec.rb +1 -1
  89. data/spec/roda/plugins/inversion_spec.rb +91 -0
  90. data.tar.gz.sig +0 -0
  91. metadata +90 -58
  92. metadata.gz.sig +0 -0
  93. data/Examples.rdoc +0 -134
  94. data/GettingStarted.rdoc +0 -44
  95. data/Guide.rdoc +0 -47
  96. data/Manifest.txt +0 -86
  97. data/Rakefile +0 -7
  98. data/Tags.rdoc +0 -560
  99. data/lib/inversion/command.rb +0 -278
  100. data/lib/inversion/monkeypatches.rb +0 -21
  101. data/spec/inversion/monkeypatches_spec.rb +0 -25
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'inversion/template' unless defined?( Inversion::Template )
@@ -31,7 +30,7 @@ class Inversion::Template::PublishTag < Inversion::Template::Tag
31
30
  include Inversion::Template::ContainerTag
32
31
 
33
32
 
34
- ### Create a new PublishTag with the given +body+.
33
+ ### Create a new PublishTag with the given `body`.
35
34
  def initialize( body, line=nil, column=nil )
36
35
  super
37
36
 
@@ -50,7 +49,7 @@ class Inversion::Template::PublishTag < Inversion::Template::Tag
50
49
  attr_reader :key
51
50
 
52
51
 
53
- ### Render the published subnodes in the context of the given +renderstate+, but
52
+ ### Render the published subnodes in the context of the given `renderstate`, but
54
53
  ### save them for publication after the render is done.
55
54
  def render( renderstate )
56
55
  self.log.debug "Publishing %d nodes as %s" % [ self.subnodes.length, self.key ]
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'inversion/template' unless defined?( Inversion::Template )
@@ -72,7 +71,7 @@ class Inversion::Template::RescueTag < Inversion::Template::Tag
72
71
  private
73
72
  #######
74
73
 
75
- ### Parse one or more exception classes from the given +rescuespec+ and return them.
74
+ ### Parse one or more exception classes from the given `rescuespec` and return them.
76
75
  def parse_exception_types( rescuespec )
77
76
  return [ ::RuntimeError ] if rescuespec.nil? || rescuespec == ''
78
77
 
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'inversion/template' unless defined?( Inversion::Template )
@@ -29,7 +28,7 @@ require 'inversion/template/tag'
29
28
  #
30
29
  class Inversion::Template::SubscribeTag < Inversion::Template::Tag
31
30
 
32
- ### Create a new SubscribeTag with the given +body+.
31
+ ### Create a new SubscribeTag with the given `body`.
33
32
  def initialize( body, line=nil, column=nil )
34
33
  super
35
34
 
@@ -60,7 +59,7 @@ class Inversion::Template::SubscribeTag < Inversion::Template::Tag
60
59
  attr_reader :content
61
60
 
62
61
 
63
- ### Tell the +renderstate+ that this tag is interested in nodes that are published with
62
+ ### Tell the `renderstate` that this tag is interested in nodes that are published with
64
63
  ### its key.
65
64
  def before_rendering( renderstate )
66
65
  @content.clear
@@ -74,7 +73,7 @@ class Inversion::Template::SubscribeTag < Inversion::Template::Tag
74
73
  end
75
74
 
76
75
 
77
- ### Pub/sub callback. Called from the RenderState when a PublishTag publishes +nodes+
76
+ ### Pub/sub callback. Called from the RenderState when a PublishTag publishes `nodes`
78
77
  ### with the same key as the current tag.
79
78
  def publish( *nodes )
80
79
  self.log.debug "Adding published nodes %p to %p" % [ nodes, @content ]
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'loggability'
@@ -105,7 +104,7 @@ class Inversion::Template::Tag < Inversion::Template::Node
105
104
  end
106
105
 
107
106
 
108
- ### Safely load the specified +tagfile+.
107
+ ### Safely load the specified `tagfile`.
109
108
  def self::load( tagfile )
110
109
  tagrequire = tagfile[ %r{inversion/template/\w+tag} ] or
111
110
  raise "tag file %p doesn't look like a tag plugin" % [ tagfile ]
@@ -118,7 +117,7 @@ class Inversion::Template::Tag < Inversion::Template::Node
118
117
  end
119
118
 
120
119
 
121
- ### Create a new Inversion::Template::Tag from the specified +tagname+ and +body+.
120
+ ### Create a new Inversion::Template::Tag from the specified `tagname` and `body`.
122
121
  def self::create( tagname, body, linenum=nil, colnum=nil )
123
122
  tagname =~ /^(\w+)$/i or raise ArgumentError, "invalid tag name %p" % [ tagname ]
124
123
  tagtype = $1.downcase
@@ -137,7 +136,7 @@ class Inversion::Template::Tag < Inversion::Template::Node
137
136
  ### I N S T A N C E M E T H O D S
138
137
  ########################################################################
139
138
 
140
- ### Create a new Inversion::Template::Tag with the specified +body+.
139
+ ### Create a new Inversion::Template::Tag with the specified `body`.
141
140
  def initialize( body, linenum=nil, colnum=nil )
142
141
  super
143
142
  @body = body.to_s.strip
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'inversion/template' unless defined?( Inversion::Template )
@@ -8,7 +7,7 @@ require 'inversion/template/node'
8
7
  # Inversion text node class -- container for static content in templates between tags.
9
8
  class Inversion::Template::TextNode < Inversion::Template::Node
10
9
 
11
- ### Create a new TextNode with the specified +source+.
10
+ ### Create a new TextNode with the specified `source`.
12
11
  def initialize( body, linenum=nil, colnum=nil )
13
12
  @body = body
14
13
  super
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'uri'
@@ -74,7 +73,7 @@ class Inversion::Template::TimeDeltaTag < Inversion::Template::AttrTag
74
73
  private
75
74
  #######
76
75
 
77
- ### Return a string describing +seconds+ as an approximate interval of time.
76
+ ### Return a string describing `seconds` as an approximate interval of time.
78
77
  def timeperiod( seconds )
79
78
  return case
80
79
  when seconds < MINUTES - 5
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'inversion/mixins'
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'uri'
@@ -19,7 +18,7 @@ class Inversion::Template::UriencodeTag < Inversion::Template::AttrTag
19
18
  include Inversion::Escaping
20
19
 
21
20
 
22
- ### Render the method chains against the attributes of the specified +render_state+
21
+ ### Render the method chains against the attributes of the specified `render_state`
23
22
  ### and return them.
24
23
  def render( render_state )
25
24
  raw = super
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'pathname'
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'loggability'
@@ -28,23 +27,23 @@ end
28
27
  #
29
28
  # == Template Options
30
29
  #
31
- # Inversion supports the {Configurability}[http://rubygems.org/gems/configurability]
32
- # API, and registers itself with the +templates+ key. This means you can either add
33
- # a +templates+ section to your Configurability config, or call
30
+ # Inversion supports the [Configurability](http://rubygems.org/gems/configurability)
31
+ # API, and registers itself with the `templates` key. This means you can either add
32
+ # a `templates` section to your Configurability config, or call
34
33
  # ::configure yourself with a config Hash (or something that quacks like one).
35
34
  #
36
35
  # To set options on a per-template basis, you can pass an options hash to either
37
36
  # Inversion::Template::load or Inversion::Template::new, or set them from within the template
38
- # itself using the {config tag}[rdoc-ref:Tags@config].
37
+ # itself using the [config tag](rdoc-ref:Tags@config).
39
38
  #
40
39
  # The available options are:
41
40
  #
42
41
  # [:ignore_unknown_tags]
43
42
  # Setting to false causes unknown tags used in templates to raise an
44
- # Inversion::ParseError. Defaults to +true+.
43
+ # Inversion::ParseError. Defaults to `true`.
45
44
  #
46
45
  # [:on_render_error]
47
- # Dictates the behavior of exceptions during rendering. Defaults to +:comment+.
46
+ # Dictates the behavior of exceptions during rendering. Defaults to `:comment`.
48
47
  #
49
48
  # [:ignore]
50
49
  # Exceptions are silently ignored.
@@ -55,7 +54,7 @@ end
55
54
  #
56
55
  #
57
56
  # [:debugging_comments]
58
- # Insert various Inversion parse and render statements while rendering. Defaults to +false+.
57
+ # Insert various Inversion parse and render statements while rendering. Defaults to `false`.
59
58
  #
60
59
  # [:comment_start]
61
60
  # When rendering debugging comments, the comment is started with these characters.
@@ -71,16 +70,16 @@ end
71
70
  # last checked member of this. Defaults to <code>[]</code>.
72
71
  #
73
72
  # [:escape_format]
74
- # The escaping used by tags such as +escape+ and +pp+. Default: +:html+.
73
+ # The escaping used by tags such as `escape` and `pp`. Default: `:html`.
75
74
  #
76
75
  # [:strip_tag_lines]
77
76
  # If a tag's presence introduces a blank line into the output, this option
78
- # removes it. Defaults to +true+.
77
+ # removes it. Defaults to `true`.
79
78
  #
80
79
  # [:stat_delay]
81
80
  # Templates know when they've been altered on disk, and can dynamically
82
81
  # reload themselves in long running applications. Setting this option creates
83
- # a purposeful delay between reloads for busy servers. Defaults to +0+
82
+ # a purposeful delay between reloads for busy servers. Defaults to `0`
84
83
  # (disabled).
85
84
  #
86
85
  # [:strict_attributes]
@@ -111,9 +110,6 @@ class Inversion::Template
111
110
  require 'inversion/template/tag'
112
111
  require 'inversion/renderstate'
113
112
 
114
- # Alias to maintain backward compatibility with <0.2.0 code
115
- Parser = Inversion::Parser
116
-
117
113
  # Valid actions for 'on_render_error'
118
114
  VALID_ERROR_ACTIONS = [
119
115
  :ignore,
@@ -165,7 +161,7 @@ class Inversion::Template
165
161
  end
166
162
 
167
163
 
168
- ### Read a template object from the specified +path+.
164
+ ### Read a template object from the specified `path`.
169
165
  def self::load( path, parsestate=nil, opts={} )
170
166
 
171
167
  # Shift the options hash over if there isn't a parse state
@@ -210,10 +206,10 @@ class Inversion::Template
210
206
  end
211
207
 
212
208
 
213
- ### Add one or more extension +modules+ to Inversion::Template. This allows tags to decorate
209
+ ### Add one or more extension `modules` to Inversion::Template. This allows tags to decorate
214
210
  ### the template class with new functionality.
215
211
  ###
216
- ### Each one of the given +modules+ will be included as a mixin, and if it also
212
+ ### Each one of the given `modules` will be included as a mixin, and if it also
217
213
  ### contains a constant called ClassMethods and/or PrependedMethods, it will
218
214
  ### also be extended/prepended (respectively) with it.
219
215
  ###
@@ -260,7 +256,7 @@ class Inversion::Template
260
256
  end
261
257
 
262
258
 
263
- ### Create a new Inversion:Template with the given +source+.
259
+ ### Create a new Inversion:Template with the given `source`.
264
260
  def initialize( source, parsestate=nil, opts={} )
265
261
  if parsestate.is_a?( Hash )
266
262
  # self.log.debug "Shifting template options: %p" % [ parsestate ]
@@ -325,7 +321,7 @@ class Inversion::Template
325
321
  end
326
322
 
327
323
 
328
- ### Returns +true+ if the template was loaded from a file and the file's mtime
324
+ ### Returns `true` if the template was loaded from a file and the file's mtime
329
325
  ### is after the time the template was created.
330
326
  def changed?
331
327
  return false unless file = self.source_file
@@ -408,7 +404,7 @@ class Inversion::Template
408
404
  end
409
405
 
410
406
 
411
- ### Parse the given +source+ into the template node tree.
407
+ ### Parse the given `source` into the template node tree.
412
408
  def parse( source, parsestate=nil )
413
409
  opts = self.class.config.merge( self.options )
414
410
  parser = Inversion::Parser.new( self, opts )
@@ -442,7 +438,7 @@ class Inversion::Template
442
438
  end
443
439
 
444
440
 
445
- ### Add attributes for the given +node+'s identifiers.
441
+ ### Add attributes for the given `node`'s identifiers.
446
442
  def add_attributes_from_node( node )
447
443
  if node.respond_to?( :identifiers )
448
444
  node.identifiers.each do |id|
@@ -453,7 +449,7 @@ class Inversion::Template
453
449
  end
454
450
 
455
451
 
456
- ### Install reader and writer methods for the attribute associated with the specified +key+.
452
+ ### Install reader and writer methods for the attribute associated with the specified `key`.
457
453
  def install_accessors( key )
458
454
  reader, writer = self.make_attribute_accessors( key )
459
455
 
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'tilt'
@@ -36,7 +35,7 @@ if defined?( ::Tilt )
36
35
  self.evaluate( *args )
37
36
  end
38
37
 
39
- ### Tilt::Template API: render the template with the given +scope+, +locals+, and +block+.
38
+ ### Tilt::Template API: render the template with the given `scope`, `locals`, and `block`.
40
39
  def evaluate( scope, locals, &block )
41
40
  @template.attributes.merge!( scope.to_h ) if scope.respond_to?( :to_h )
42
41
  @template.attributes.merge!( locals )
data/lib/inversion.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # -*- ruby -*-
2
- # frozen_string_literal: true
3
2
  # vim: set noet nosta sw=4 ts=4 :
4
3
 
5
4
  require 'loggability'
@@ -26,7 +25,7 @@ module Inversion
26
25
  warn ">>> Inversion requires Ruby 2.4.0 or later. <<<" if RUBY_VERSION < '2.4.0'
27
26
 
28
27
  # Library version constant
29
- VERSION = '1.3.1'
28
+ VERSION = '1.5.0'
30
29
 
31
30
  # Version-control revision constant
32
31
  REVISION = %q$Revision$
@@ -40,8 +39,8 @@ module Inversion
40
39
  end
41
40
 
42
41
  require 'inversion/exceptions'
42
+ require 'inversion/refinements'
43
43
  require 'inversion/mixins'
44
- require 'inversion/monkeypatches'
45
44
  require 'inversion/template'
46
45
 
47
46
  end # module Inversion
@@ -0,0 +1,225 @@
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4 ft=ruby:
3
+
4
+ require 'inversion'
5
+ require 'loggability'
6
+
7
+ class Roda
8
+ module RodaPlugins
9
+
10
+ # A templated content-generation plugin for Roda Apps. It uses the
11
+ # Inversion[http://deveiate.org/projects/Inversion] templating system.
12
+ #
13
+ # It adds:
14
+ #
15
+ # * a preloaded/cached template table
16
+ # * a mechanism for fetching templates from the table
17
+ # * a global layout template which is automatically wrapped around responses
18
+ #
19
+ # Note: This is based almost entirely off the Strelka plugin of identical
20
+ # function.
21
+ #
22
+ # == Usage
23
+ #
24
+ # To use it, just load the <tt>:inversion</tt> plugin in your app:
25
+ #
26
+ # plugin :inversion, '/path/to/templates/directory'
27
+ #
28
+ # You can specify more than one templates directory; they'll be searched in the order
29
+ # you specify for the named template and the first match wins:
30
+ #
31
+ # plugin :inversion '/more/specific/templates', '/generic/app/templates'
32
+ #
33
+ # Then declare one or more templates that your application will use:
34
+ #
35
+ # templates console: 'views/console.tmpl',
36
+ # proctable: 'partials/proctable.tmpl'
37
+ #
38
+ # Then, inside your app, you can fetch a copy of one or more of the templates and
39
+ # return it as the response:
40
+ #
41
+ # r.root do
42
+ # tmpl = template( :console )
43
+ # tmpl.message = "Everything's up."
44
+ # tmpl.proctable = proctable
45
+ # return tmpl
46
+ # end
47
+ #
48
+ #
49
+ # You can also just return the template if you don't need to do anything else to the
50
+ # response.
51
+ #
52
+ # When returning a template, either in the body of the response or directly, it will
53
+ # automatically set a few attributes for commonly-used objects:
54
+ #
55
+ # request :: The current Roda::Request
56
+ # response :: The current Roda::Response
57
+ # app :: The application object (Roda::App instance).
58
+ #
59
+ # If your app will *only* be loading and returning a template without doing anything
60
+ # with it, you can return just its name:
61
+ #
62
+ # r.root do
63
+ # return :console
64
+ # end
65
+ #
66
+ # It will be loaded, set as the response body, and the above common objects added to it.
67
+ #
68
+ #
69
+ # === Layouts
70
+ #
71
+ # Very often, you'll want all or most of the views in your app to share a common page
72
+ # layout. To accomplish this, you can declare a layout template:
73
+ #
74
+ # layout 'layout.tmpl'
75
+ #
76
+ # Any template that you return will be set as the 'body' attribute of this layout
77
+ # template (which you'd place into the layout with <tt><?attr body ?></tt>) and the
78
+ # layout rendered as the body of the response.
79
+ #
80
+ # Note that if you want any of the "common objects" from above with a layout template,
81
+ # they'll be set on it since it's the top-level template, but you can still access them
82
+ # using the <tt><?import ?></tt> directive:
83
+ #
84
+ # <?import request, app ?>
85
+ #
86
+ #
87
+ # == Template Locations
88
+ #
89
+ # Inversion looks for templates in a load path much like Ruby does for libraries that
90
+ # you 'require'. It contains just the current working directory by default. You can add
91
+ # your own template directories via the config file (under +template_paths+ in
92
+ # the +templates+ section), or programmatically from your application.
93
+ #
94
+ module Inversion
95
+
96
+ ### Add the specified +template_paths+ to Inversion.
97
+ def self::configure( app, *template_paths )
98
+ ::Inversion::Template.template_paths.concat( template_paths )
99
+ end
100
+
101
+
102
+ module ClassMethods
103
+
104
+ ### Add this Gem's template location to the Inversion search path.
105
+ def self::extended( subclass )
106
+ subclass.instance_variable_set( :@template_map, {} )
107
+ subclass.instance_variable_set( :@layout_template, nil )
108
+
109
+ super
110
+ end
111
+
112
+
113
+ # The map of template names to template file paths.
114
+ attr_reader :template_map
115
+
116
+ # An optional layout/wrap template.
117
+ attr_accessor :layout_template
118
+
119
+
120
+ ### Load instances for all the template paths specified in the App's class
121
+ ### and return them in a hash keyed by name (Symbol).
122
+ def templates( hash )
123
+ @template_map = hash.each_with_object( {} ) do |(name, path), map|
124
+ enc = Encoding.default_internal || Encoding::UTF_8
125
+ map[ name ] = ::Inversion::Template.load( path, encoding: enc )
126
+ map
127
+ end
128
+
129
+ return self.template_map
130
+ end
131
+
132
+
133
+ ### Load an Inversion::Template for the layout template.
134
+ def layout( tmpl )
135
+ enc = Encoding.default_internal || Encoding::UTF_8
136
+ self.layout_template = ::Inversion::Template.load( tmpl, encoding: enc )
137
+ return self.layout_template
138
+ end
139
+ end
140
+
141
+
142
+ module InstanceMethods
143
+
144
+ ### Return a previously declared template object.
145
+ def template( tmpl )
146
+ template = self.class.template_map[ tmpl ] or
147
+ raise ArgumentError, "no %p template registered!" % [ tmpl ]
148
+ template.reload if template.changed?
149
+ return template.dup
150
+ end
151
+ end
152
+
153
+
154
+ module RequestMethods
155
+
156
+ ### Hook block results for template rendering.
157
+ def block_result_body( result )
158
+ if ( template = self.extract_template_from_result( result ) )
159
+
160
+ # Wrap the template in a layout if there is one
161
+ template = self.wrap_in_layout( template )
162
+
163
+ # Set some default stuff on the top-level template
164
+ self.set_common_attributes( template )
165
+
166
+ return template.render
167
+ else
168
+ super
169
+ end
170
+ end
171
+
172
+
173
+ #########
174
+ protected
175
+ #########
176
+
177
+ ### Fetch the template from the +result+ (if there is one) and return it.
178
+ def extract_template_from_result( result )
179
+ templates = self.scope.class.template_map
180
+
181
+ # Result is a template name.
182
+ if result.is_a?( Symbol ) && templates.key?( result )
183
+ return scope.template( result )
184
+
185
+ # Result is a template object.
186
+ elsif result.respond_to?( :render )
187
+ return result
188
+ end
189
+
190
+ # Not templated; returned as-is
191
+ return nil
192
+ end
193
+
194
+
195
+ ### Wrap the specified +content+ template in the layout template and
196
+ ### return it. If there isn't a layout declared, just return +content+ as-is.
197
+ def wrap_in_layout( content )
198
+ layout = self.scope.class.layout_template or return content
199
+
200
+ layout.reload if layout.changed?
201
+ l_template = layout.dup
202
+ l_template.body = content
203
+
204
+ return l_template
205
+ end
206
+
207
+
208
+ ### Set some default values from the request in the given top-level +template+.
209
+ def set_common_attributes( template )
210
+ template.request = self
211
+ template.response = self.scope.response
212
+ template.app = self.scope
213
+ end
214
+
215
+ end
216
+
217
+ end # module Inversion
218
+
219
+
220
+ # Hook: Inform Roda that we exist.
221
+ register_plugin :inversion, Inversion
222
+
223
+ end # module RodaPlugins
224
+ end # class Roda
225
+
data/spec/helpers.rb CHANGED
@@ -11,7 +11,7 @@ require 'loggability/spechelpers'
11
11
 
12
12
  require 'inversion'
13
13
 
14
- Inversion::Template::Tag.load_all
14
+ # Inversion::Template::Tag.load_all
15
15
 
16
16
 
17
17
  ### RSpec helper functions.
@@ -21,14 +21,14 @@ module Inversion::SpecHelpers
21
21
  module_function
22
22
  ###############
23
23
 
24
- ### Make an easily-comparable version vector out of +ver+ and return it.
24
+ ### Make an easily-comparable version vector out of `ver` and return it.
25
25
  def vvec( ver )
26
26
  return ver.split('.').collect {|char| char.to_i }.pack('N*')
27
27
  end
28
28
 
29
29
 
30
- ### Create a string containing an XML Processing Instruction with the given +name+
31
- ### and +data+.
30
+ ### Create a string containing an XML Processing Instruction with the given `name`
31
+ ### and `data`.
32
32
  def create_pi( name, data )
33
33
  return "<?#{name} #{data} ?>"
34
34
  end
@@ -37,19 +37,25 @@ end
37
37
 
38
38
 
39
39
  ### Mock with RSpec
40
- RSpec.configure do |c|
40
+ RSpec.configure do |config|
41
41
 
42
- c.run_all_when_everything_filtered = true
43
- c.filter_run :focus
44
- c.order = 'random'
45
- c.mock_with( :rspec ) do |mock|
42
+ config.mock_with( :rspec ) do |mock|
46
43
  mock.syntax = :expect
47
44
  end
48
- c.wait_timeout = 3
49
- c.example_status_persistence_file_path = 'spec/.state'
50
45
 
51
- c.include( Inversion::SpecHelpers )
52
- c.include( Loggability::SpecHelpers )
46
+ config.disable_monkey_patching!
47
+ config.example_status_persistence_file_path = "spec/.status"
48
+ config.filter_run :focus
49
+ config.filter_run_when_matching :focus
50
+ config.order = :random
51
+ config.profile_examples = 5
52
+ config.run_all_when_everything_filtered = true
53
+ config.shared_context_metadata_behavior = :apply_to_host_groups
54
+ config.wait_timeout = 3
55
+ # config.warnings = true
56
+
57
+ config.include( Inversion::SpecHelpers )
58
+ config.include( Loggability::SpecHelpers )
53
59
  end
54
60
 
55
61
  # vim: set nosta noet ts=4 sw=4:
@@ -7,7 +7,7 @@ require 'set'
7
7
  require 'inversion/mixins'
8
8
 
9
9
 
10
- describe Inversion, "mixins" do
10
+ RSpec.describe Inversion, "mixins" do
11
11
 
12
12
  describe Inversion::HashUtilities do
13
13
  it "includes a function for stringifying Hash keys" do
@@ -5,7 +5,7 @@ require_relative '../helpers'
5
5
 
6
6
  require 'inversion/parser'
7
7
 
8
- describe Inversion::Parser do
8
+ RSpec.describe Inversion::Parser do
9
9
 
10
10
  before( :all ) do
11
11
  Inversion::Template::Tag.load_all
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rspec -cfd -b
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+
4
+
5
+ require_relative '../helpers'
6
+
7
+ require 'ripper'
8
+ require 'inversion/refinements'
9
+
10
+
11
+ RSpec.describe Inversion, "refinements" do
12
+
13
+ using Inversion::Refinements
14
+
15
+ it "exposes the Ripper::TokenPattern::MatchData's #tokens array" do
16
+ tagpattern = Ripper::TokenPattern.compile( '$(ident) $(sp) $(ident)' )
17
+ matchdata = tagpattern.match( "foo bar" )
18
+ expect( matchdata.tokens.map {|tok| tok[1]} ).to eq([ :on_ident, :on_sp, :on_ident ])
19
+ end
20
+
21
+ end
22
+
@@ -11,7 +11,7 @@ require 'inversion/template/fragmenttag'
11
11
  require 'inversion/template/subscribetag'
12
12
  require 'inversion/template/publishtag'
13
13
 
14
- describe Inversion::RenderState do
14
+ RSpec.describe Inversion::RenderState do
15
15
 
16
16
 
17
17
  it "provides access to the block it was constructed with if there was one" do