raw 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/doc/CONTRIBUTORS +106 -0
  2. data/doc/LICENSE +32 -0
  3. data/doc/coding_conventions.txt +11 -0
  4. data/lib/raw.rb +42 -0
  5. data/lib/raw/adapter.rb +113 -0
  6. data/lib/raw/adapter/cgi.rb +41 -0
  7. data/lib/raw/adapter/fastcgi.rb +48 -0
  8. data/lib/raw/adapter/mongrel.rb +146 -0
  9. data/lib/raw/adapter/script.rb +94 -0
  10. data/lib/raw/adapter/webrick.rb +144 -0
  11. data/lib/raw/adapter/webrick/vcr.rb +91 -0
  12. data/lib/raw/cgi.rb +323 -0
  13. data/lib/raw/cgi/cookie.rb +47 -0
  14. data/lib/raw/cgi/http.rb +62 -0
  15. data/lib/raw/compiler.rb +138 -0
  16. data/lib/raw/compiler/filter/cleanup.rb +21 -0
  17. data/lib/raw/compiler/filter/elements.rb +166 -0
  18. data/lib/raw/compiler/filter/elements/element.rb +210 -0
  19. data/lib/raw/compiler/filter/localization.rb +23 -0
  20. data/lib/raw/compiler/filter/markup.rb +32 -0
  21. data/lib/raw/compiler/filter/morph.rb +123 -0
  22. data/lib/raw/compiler/filter/morph/each.rb +34 -0
  23. data/lib/raw/compiler/filter/morph/for.rb +11 -0
  24. data/lib/raw/compiler/filter/morph/if.rb +26 -0
  25. data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
  26. data/lib/raw/compiler/filter/morph/standard.rb +55 -0
  27. data/lib/raw/compiler/filter/morph/times.rb +27 -0
  28. data/lib/raw/compiler/filter/script.rb +116 -0
  29. data/lib/raw/compiler/filter/squeeze.rb +16 -0
  30. data/lib/raw/compiler/filter/static_include.rb +74 -0
  31. data/lib/raw/compiler/filter/template.rb +121 -0
  32. data/lib/raw/compiler/reloader.rb +96 -0
  33. data/lib/raw/context.rb +154 -0
  34. data/lib/raw/context/flash.rb +157 -0
  35. data/lib/raw/context/global.rb +88 -0
  36. data/lib/raw/context/request.rb +338 -0
  37. data/lib/raw/context/response.rb +57 -0
  38. data/lib/raw/context/session.rb +198 -0
  39. data/lib/raw/context/session/drb.rb +11 -0
  40. data/lib/raw/context/session/file.rb +15 -0
  41. data/lib/raw/context/session/memcached.rb +13 -0
  42. data/lib/raw/context/session/memory.rb +12 -0
  43. data/lib/raw/context/session/og.rb +15 -0
  44. data/lib/raw/context/session/pstore.rb +13 -0
  45. data/lib/raw/control.rb +18 -0
  46. data/lib/raw/control/attribute.rb +91 -0
  47. data/lib/raw/control/attribute/checkbox.rb +25 -0
  48. data/lib/raw/control/attribute/datetime.rb +21 -0
  49. data/lib/raw/control/attribute/file.rb +20 -0
  50. data/lib/raw/control/attribute/fixnum.rb +26 -0
  51. data/lib/raw/control/attribute/float.rb +26 -0
  52. data/lib/raw/control/attribute/options.rb +38 -0
  53. data/lib/raw/control/attribute/password.rb +16 -0
  54. data/lib/raw/control/attribute/text.rb +16 -0
  55. data/lib/raw/control/attribute/textarea.rb +16 -0
  56. data/lib/raw/control/none.rb +16 -0
  57. data/lib/raw/control/relation.rb +59 -0
  58. data/lib/raw/control/relation/belongs_to.rb +0 -0
  59. data/lib/raw/control/relation/has_many.rb +97 -0
  60. data/lib/raw/control/relation/joins_many.rb +0 -0
  61. data/lib/raw/control/relation/many_to_many.rb +0 -0
  62. data/lib/raw/control/relation/refers_to.rb +29 -0
  63. data/lib/raw/controller.rb +37 -0
  64. data/lib/raw/controller/publishable.rb +160 -0
  65. data/lib/raw/dispatcher.rb +209 -0
  66. data/lib/raw/dispatcher/format.rb +108 -0
  67. data/lib/raw/dispatcher/format/atom.rb +31 -0
  68. data/lib/raw/dispatcher/format/css.rb +0 -0
  69. data/lib/raw/dispatcher/format/html.rb +42 -0
  70. data/lib/raw/dispatcher/format/json.rb +31 -0
  71. data/lib/raw/dispatcher/format/rss.rb +33 -0
  72. data/lib/raw/dispatcher/format/xoxo.rb +31 -0
  73. data/lib/raw/dispatcher/mounter.rb +60 -0
  74. data/lib/raw/dispatcher/router.rb +111 -0
  75. data/lib/raw/errors.rb +19 -0
  76. data/lib/raw/helper.rb +86 -0
  77. data/lib/raw/helper/benchmark.rb +23 -0
  78. data/lib/raw/helper/buffer.rb +60 -0
  79. data/lib/raw/helper/cookie.rb +32 -0
  80. data/lib/raw/helper/debug.rb +28 -0
  81. data/lib/raw/helper/default.rb +16 -0
  82. data/lib/raw/helper/feed.rb +451 -0
  83. data/lib/raw/helper/form.rb +284 -0
  84. data/lib/raw/helper/javascript.rb +59 -0
  85. data/lib/raw/helper/layout.rb +40 -0
  86. data/lib/raw/helper/navigation.rb +87 -0
  87. data/lib/raw/helper/pager.rb +305 -0
  88. data/lib/raw/helper/table.rb +247 -0
  89. data/lib/raw/helper/xhtml.rb +218 -0
  90. data/lib/raw/helper/xml.rb +125 -0
  91. data/lib/raw/mixin/magick.rb +35 -0
  92. data/lib/raw/mixin/sweeper.rb +71 -0
  93. data/lib/raw/mixin/thumbnails.rb +1 -0
  94. data/lib/raw/mixin/webfile.rb +165 -0
  95. data/lib/raw/render.rb +271 -0
  96. data/lib/raw/render/builder.rb +26 -0
  97. data/lib/raw/render/caching.rb +81 -0
  98. data/lib/raw/render/call.rb +43 -0
  99. data/lib/raw/render/send_file.rb +46 -0
  100. data/lib/raw/render/stream.rb +39 -0
  101. data/lib/raw/scaffold.rb +13 -0
  102. data/lib/raw/scaffold/controller.rb +25 -0
  103. data/lib/raw/scaffold/model.rb +157 -0
  104. data/lib/raw/test.rb +5 -0
  105. data/lib/raw/test/assertions.rb +169 -0
  106. data/lib/raw/test/context.rb +55 -0
  107. data/lib/raw/test/testcase.rb +79 -0
  108. data/lib/raw/util/attr.rb +128 -0
  109. data/lib/raw/util/encode_uri.rb +149 -0
  110. data/lib/raw/util/html_filter.rb +538 -0
  111. data/lib/raw/util/markup.rb +130 -0
  112. data/test/glue/tc_webfile.rb +1 -0
  113. data/test/nitro/CONFIG.rb +3 -0
  114. data/test/nitro/adapter/raw_post1.bin +9 -0
  115. data/test/nitro/adapter/tc_webrick.rb +16 -0
  116. data/test/nitro/cgi/tc_cookie.rb +14 -0
  117. data/test/nitro/cgi/tc_request.rb +61 -0
  118. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  119. data/test/nitro/compiler/tc_compiler.rb +25 -0
  120. data/test/nitro/dispatcher/tc_mounter.rb +47 -0
  121. data/test/nitro/helper/tc_feed.rb +135 -0
  122. data/test/nitro/helper/tc_navbar.rb +74 -0
  123. data/test/nitro/helper/tc_pager.rb +35 -0
  124. data/test/nitro/helper/tc_table.rb +68 -0
  125. data/test/nitro/helper/tc_xhtml.rb +19 -0
  126. data/test/nitro/tc_caching.rb +19 -0
  127. data/test/nitro/tc_cgi.rb +222 -0
  128. data/test/nitro/tc_context.rb +17 -0
  129. data/test/nitro/tc_controller.rb +103 -0
  130. data/test/nitro/tc_controller_aspect.rb +32 -0
  131. data/test/nitro/tc_controller_params.rb +885 -0
  132. data/test/nitro/tc_dispatcher.rb +109 -0
  133. data/test/nitro/tc_element.rb +85 -0
  134. data/test/nitro/tc_flash.rb +59 -0
  135. data/test/nitro/tc_helper.rb +47 -0
  136. data/test/nitro/tc_render.rb +119 -0
  137. data/test/nitro/tc_router.rb +61 -0
  138. data/test/nitro/tc_server.rb +35 -0
  139. data/test/nitro/tc_session.rb +66 -0
  140. data/test/nitro/tc_template.rb +71 -0
  141. data/test/nitro/util/tc_encode_url.rb +87 -0
  142. data/test/nitro/util/tc_markup.rb +31 -0
  143. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  144. data/test/public/blog/inc1.xhtml +2 -0
  145. data/test/public/blog/inc2.xhtml +1 -0
  146. data/test/public/blog/list.xhtml +9 -0
  147. data/test/public/dummy_mailer/registration.xhtml +5 -0
  148. metadata +244 -0
@@ -0,0 +1,284 @@
1
+ require "glue/builder/xml"
2
+
3
+ require 'raw/control'
4
+ require 'raw/control/none'
5
+
6
+ require 'raw/control/attribute/fixnum'
7
+ require 'raw/control/attribute/float'
8
+ require 'raw/control/attribute/text'
9
+ require 'raw/control/attribute/password'
10
+ require 'raw/control/attribute/textarea'
11
+ require 'raw/control/attribute/checkbox'
12
+ require 'raw/control/attribute/options'
13
+ require 'raw/control/attribute/file'
14
+
15
+ require 'raw/control/relation/refers_to'
16
+ require 'raw/control/relation/has_many'
17
+
18
+ module Raw
19
+
20
+ module FormHelper
21
+
22
+ # A specialized Builder for dynamically building of forms.
23
+ # Provides extra support for forms backed by managed objects
24
+ # (entities).
25
+ #--
26
+ # TODO: allow multiple objects per form.
27
+ # TODO: use more generalized controls.
28
+ #++
29
+
30
+ class FormXmlBuilder < ::Glue::XmlBuilder
31
+
32
+ # Mappings of control names to controls.
33
+
34
+ setting :control_map, :doc => 'Mappings of control names to controls', :default => {
35
+ :fixnum => FixnumControl,
36
+ :integer => FixnumControl,
37
+ :float => FloatControl,
38
+ :true_class => CheckboxControl,
39
+ :boolean => CheckboxControl,
40
+ :checkbox => CheckboxControl,
41
+ :string => TextControl,
42
+ :password => PasswordControl,
43
+ :textarea => TextareaControl,
44
+ :file => FileControl,
45
+ :webfile => FileControl,
46
+ =begin
47
+ :array => ArrayControl,
48
+ =end
49
+ :options => OptionsControl,
50
+ :refers_to => RefersToControl,
51
+ :has_one => RefersToControl,
52
+ :belongs_to => RefersToControl,
53
+ :has_many => HasManyControl,
54
+ :many_to_many => HasManyControl,
55
+ :joins_many => HasManyControl
56
+ }
57
+
58
+ # Returns a control for the given objects attribute.
59
+
60
+ def self.control_for(obj, a, anno, options)
61
+ raise "Invalid attribute '#{a}' for object '#{obj}'" if anno.nil?
62
+ name = anno[:control] || anno[:class].to_s.demodulize.underscore.to_sym
63
+ control_class = self.control_map.fetch(name, NoneControl)
64
+ return control_class.new(obj, a, options)
65
+ end
66
+
67
+ # Returns a control for the given objects relation.
68
+
69
+ def self.control_for_relation(obj, rel, options)
70
+ name = rel[:control] || rel.class.to_s.demodulize.underscore.to_sym
71
+ control_class = self.control_map.fetch(name, NoneControl)
72
+ return control_class.new(obj, rel, options)
73
+ end
74
+
75
+ def initialize(buffer = '', options = {})
76
+ super
77
+ @obj = options[:object]
78
+ @errors = options[:errors]
79
+ end
80
+
81
+ # Render a control+label for the given property of the form
82
+ # object.
83
+
84
+ def attribute(a, options = {})
85
+ if anno = @obj.class.ann(a)
86
+ control = self.class.control_for(@obj, a, anno, options)
87
+ print element(a, anno, control.render)
88
+ else
89
+ raise "Undefined attribute '#{a}' for class '#{@obj.class}'."
90
+ end
91
+ end
92
+ alias_method :attr, :attribute
93
+
94
+ # Render controls for all attributes of the form object.
95
+ # It only considers serializable attributes.
96
+
97
+ def all_attributes(options = {})
98
+ for a in @obj.class.serializable_attributes
99
+ prop = @obj.class.ann(a)
100
+ unless options[:all]
101
+ next if a == @obj.class.primary_key or prop[:control] == :none or prop[:relation] or [options[:exclude]].flatten.include?(a)
102
+ end
103
+ attribute a, options
104
+ end
105
+ end
106
+ alias_method :attributes, :all_attributes
107
+ alias_method :serializable_attributes, :all_attributes
108
+
109
+ # === Input
110
+ #
111
+ # * rel = The relation name as symbol, or the actual
112
+ # relation object.
113
+ #--
114
+ # FIXME: Fix the mismatch with the attributes.
115
+ #++
116
+
117
+ def relation(rel, options = {})
118
+ # If the relation name is passed, lookup the actual
119
+ # relation.
120
+
121
+ if rel.is_a? Symbol
122
+ rel = @obj.class.relation(rel)
123
+ end
124
+
125
+ control = self.class.control_for_relation(@obj, rel, options)
126
+ print element(rel[:symbol], rel, control.render)
127
+ end
128
+ alias_method :rel, :relation
129
+
130
+ # Render controls for all relations of the form object.
131
+
132
+ def all_relations(options = {})
133
+ for rel in @obj.class.relations
134
+ unless options[:all]
135
+ # Ignore polymorphic_marker relations.
136
+ #--
137
+ # gmosx: should revisit the handling of polymorphic
138
+ # relations, feels hacky.
139
+ #++
140
+ next if (rel[:control] == :none) or rel.polymorphic_marker?
141
+ end
142
+ relation rel, options
143
+ end
144
+ end
145
+ alias_method :relations, :all_relations
146
+
147
+ # Renders a control to select a file for upload.
148
+
149
+ def select_file(name, options = {})
150
+ print %|<input type="file" name="#{name}" />|
151
+ end
152
+
153
+ # If flash[:ERRORS] is filled with errors structured as
154
+ # name/message pairs the method creates a div containing them,
155
+ # otherwise it returns an empty string.
156
+ #
157
+ # So you can write code like
158
+ # #{form_errors}
159
+ # <form>... </form>
160
+ #
161
+ # and redirect the user to the form in case of errors, thus
162
+ # allowing him to see what was wrong.
163
+
164
+ def form_errors
165
+ res = ''
166
+
167
+ unless @errors.empty?
168
+ res << %{<div class="error">\n<ul>\n}
169
+ for err in @errors
170
+ if err.is_a? Array
171
+ res << "<li><strong>#{err[0].to_s.humanize}</strong>: #{err[1]}</li>\n"
172
+ else
173
+ res << "<li>#{err}</li>\n"
174
+ end
175
+ end
176
+ res << %{</ul>\n</div>\n}
177
+ end
178
+
179
+ print(res)
180
+ end
181
+
182
+ private
183
+
184
+ # Emit a form element. Override this method to customize the
185
+ # rendering for your application needs.
186
+
187
+ def element(a, anno, html)
188
+ # TODO: give better form id!
189
+ %{
190
+ <p id="form_#{a}">
191
+ #{html}
192
+ </p>
193
+ }
194
+ end
195
+
196
+ end
197
+
198
+ private
199
+
200
+ # A sophisticated form generation helper method.
201
+ # If no block is provided, render all attributes.
202
+ #
203
+ # === Options
204
+ #
205
+ # * :object, :entity, :class = The object that acts as model
206
+ # for this form. If you pass a class an empty object is
207
+ # instantiated.
208
+ #
209
+ # * :action = The action of this form. The parameter is
210
+ # passed through the R operator (encode_uri) to support
211
+ # advanced uri transformation.
212
+ #
213
+ # * :errors = An optional collection of errors.
214
+ #
215
+ # === Example
216
+ #
217
+ # #{form(:object => @owner, :action => :save_profile) do |f|
218
+ # f.property :name, :editable => false
219
+ # f.property :password
220
+ # f.br
221
+ # f.submit 'Update'
222
+ # end}
223
+
224
+ def form(options = {}, &block)
225
+ obj = (options[:object] ||= options[:entity] || options[:class])
226
+
227
+ # If the passed obj is a Class instantiate an empty object
228
+ # of this class.
229
+
230
+ if obj.is_a? Class
231
+ obj = options[:object] = obj.allocate
232
+ end
233
+
234
+ # Convert virtual :multipart method to method="post",
235
+ # enctype="multipart/form-data"
236
+
237
+ if options[:method] == :multipart
238
+ options[:method] = 'POST'
239
+ options[:enctype] = 'multipart/form-data'
240
+ end
241
+
242
+ options[:errors] ||= []
243
+
244
+ if errors = flash[:ERRORS]
245
+ if errors.is_a? Array
246
+ options[:errors].concat(errors)
247
+ elsif errors.is_a? Glue::Validation::Errors
248
+ options[:errors].concat(errors.to_a)
249
+ else
250
+ options[:errors] << errors
251
+ end
252
+ end
253
+
254
+ if obj and errors = obj.errors
255
+ options[:errors].concat(errors.to_a)
256
+ end
257
+
258
+ b = FormXmlBuilder.new('', options)
259
+
260
+ b << '<form'
261
+ b << %| action="#{R options[:action]}"| if options[:action]
262
+ b << %| method="#{options[:method]}"| if options[:method]
263
+ b << %| accept-charset="#{options[:charset]}"| if options[:charset]
264
+ b << %| enctype="#{options[:enctype]}"| if options[:enctype]
265
+ b << '>'
266
+
267
+ b.hidden(:oid, obj.oid) if obj and obj.saved?
268
+
269
+ # If no block is provided, render all attributes.
270
+
271
+ if block_given?
272
+ yield b
273
+ else
274
+ b.all_attributes
275
+ end
276
+
277
+ b << '</form>'
278
+
279
+ return b
280
+ end
281
+
282
+ end
283
+
284
+ end
@@ -0,0 +1,59 @@
1
+ require "facets/core/inflect"
2
+
3
+ module Raw
4
+
5
+ # Javascript code manager.
6
+ #--
7
+ # TODO: Add support for synthesizing compound Javascript files from
8
+ # multiple smaller files.
9
+ #++
10
+
11
+ module Javascript
12
+
13
+ # The javascript files to auto include.
14
+
15
+ setting :required_files, :default => [], :doc => "The javascript files to auto include"
16
+
17
+ # The root directory where javascript files reside.
18
+
19
+ setting :root_dir, :default => "public/js", :doc => "The root directory where javascript files reside"
20
+
21
+ def self.require(path)
22
+ end
23
+
24
+ end
25
+
26
+ # Javascript utilities.
27
+
28
+ module JavascriptUtils
29
+
30
+ private
31
+ # Escape carrier returns and single and double quotes for JavaScript segments.
32
+
33
+ def escape_javascript(js)
34
+ (js || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
35
+ end
36
+ alias_method :escape, :escape_javascript
37
+
38
+ # Converts a Ruby hash to a Javascript hash.
39
+
40
+ def hash_to_js(options)
41
+ '{' + options.map {|k, v| "#{k}:#{v}"}.join(', ') + '}'
42
+ end
43
+
44
+ # Converts the name of a javascript file to the actual
45
+ # filename. Override if you don't like the defaults.
46
+
47
+ def name_to_jsfile(name)
48
+ "/js/#{name}.js"
49
+ end
50
+
51
+ # Generate javascript confirm code for links.
52
+
53
+ def confirm(text = 'Are you sure?')
54
+ %|onclick="return confirm('#{text}')"|
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,40 @@
1
+ require "facets/core/inflect"
2
+
3
+ require "raw/element"
4
+
5
+ module Raw
6
+
7
+ # This helper uses Nitro's powerfull Elements mechanism to
8
+ # implement a simple Rails style Layout helper. Perhaps this
9
+ # may be useful for people coming over from Rails.
10
+ #
11
+ # WARNING: This is not enabled by default. You have to insert
12
+ # the LayoutCompiler before the ElementsCompiler for layout to
13
+ # work.
14
+
15
+ module LayoutHelper
16
+
17
+ def self.included(base)
18
+ base.module_eval do
19
+ # Enclose all templates of this controller with the
20
+ # given element.
21
+
22
+ def self.layout(name = nil)
23
+ klass = name.to_s.camelize
24
+
25
+ unless klass
26
+ if defined? 'Nitro::Element::Layout'
27
+ klass = Nitro::Element::Layout
28
+ end
29
+ end
30
+
31
+ if klass
32
+ ann :self, :layout => klass
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,87 @@
1
+ module Raw
2
+
3
+ # A helper mixin for programmatically building Navigation Menus
4
+ # through easy to style XHTML.
5
+ # The code resulting from these methods is in line with that found in most examples at
6
+ # listamatic, thus you can use prebuilt CSS and Javascript to create horizontal or vertical menus.
7
+ # Basically it generates something like
8
+ # <div id="navcontainer">
9
+ # <ul id="navlist">
10
+ # <li id="active"> <a href="/foo" id="current"> Current Page </a></li>
11
+ # <li> <a href="/bar"> Other page </a> </li>
12
+ # </ul>
13
+ # </div>
14
+ #
15
+ # This helper takes care of setting of putting the special CSS
16
+ # identifiers for the current controller automatically.
17
+ # You could override menuitem_active_on(path)
18
+ # to change the behaviour that choose the active item,
19
+ # for example to keep the item "Wiki" active both for
20
+ # /wiki/pageone and /wiki/pagetwo
21
+ #
22
+ # Example of horizontal bar at listamatic:
23
+ # http://css.maxdesign.com.au/listamatic/horizontal26.htm
24
+ # Vertical example
25
+ # http://css.maxdesign.com.au/listamatic/vertical09.htm
26
+ #
27
+ # NOTE: No tests were made with Publishable objects which are not
28
+ # subclass of Nitro::Controller, but it _should_ work.
29
+
30
+ module NavigationHelper
31
+
32
+ TEMPLATE=<<Eof
33
+ <div id="navcontainer">
34
+ <ul id="navlist">
35
+ LIST
36
+ </ul>
37
+ </div>
38
+ Eof
39
+
40
+ # Takes a list of controllers and builds a menu
41
+ # using #mount_path as the uri and the controller name as text.
42
+ # An eventual "Controller" suffix will be stripped, so i.e. for controllers
43
+ # named +HomeController+, +Pages+, +FeedCtl+ it will use
44
+ # +Home+, +Page+, +FeedCtl+.
45
+ #
46
+ # For more finegrained control you can pass a block to this function, each
47
+ # controller will be passed to it and the result will be used as the text
48
+ # for the menu item.
49
+ #
50
+ #
51
+ # Otherwise you can specify pairs of path/text using #navigation_for_hash
52
+
53
+ def menu_for(*controllers) #:yields:
54
+ hash= {}
55
+ controllers.each do |c|
56
+ hash[c.mount_path] = block_given? ? yield(c) : c.name.gsub(/Controller/,'')
57
+ end
58
+ menu_from_hash(hash)
59
+ end
60
+
61
+ # The argument must be an hash of pairs {'path'=>'text for menu item'},
62
+ # no control will be applied on these values, they will be used directly.
63
+ # You can use the method like
64
+ # navigation_for_hash '/foo/bar'=>'Page One', '/foo/baz'=>'Page Two'
65
+ #
66
+ # The method takes care of setting the CSS values as expected.
67
+ #
68
+ # To avoid specifying everything the method #navigation_menu can be used.
69
+
70
+ def menu_from_hash(hash)
71
+ list=hash.map do |path,name|
72
+ if menuitem_active_on?(path)
73
+ %{<li id="active"><a href="#{path}" id="current"> #{name} </a></li>}
74
+ else
75
+ %{<li><a href="#{path}"> #{name} </a></li>}
76
+ end
77
+ end.join("\n")
78
+ TEMPLATE.gsub("LIST",list)
79
+ end
80
+
81
+ def menuitem_active_on?(path)
82
+ path == request.path
83
+ end
84
+
85
+ end
86
+
87
+ end