ramaze 2009.05 → 2009.06
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/MANIFEST +11 -7
- data/README.md +3 -3
- data/Rakefile +17 -15
- data/bin/ramaze +7 -2
- data/doc/AUTHORS +6 -5
- data/doc/CHANGELOG +10057 -12259
- data/doc/meta/announcement.txt +93 -46
- data/doc/tutorial/todolist.html +22 -58
- data/doc/tutorial/todolist.txt +20 -39
- data/examples/app/wikore/src/model.rb +7 -1
- data/examples/app/wiktacular/template/html_layout.xhtml +1 -1
- data/lib/proto/config.ru +5 -1
- data/lib/ramaze/cache/localmemcache.rb +1 -1
- data/lib/ramaze/cache/memcache.rb +26 -1
- data/lib/ramaze/cache/sequel.rb +9 -6
- data/lib/ramaze/contrib/addressable_route.rb +55 -0
- data/lib/ramaze/contrib/facebook/facebook.rb +4 -4
- data/lib/ramaze/controller.rb +28 -18
- data/lib/ramaze/gestalt.rb +1 -1
- data/lib/ramaze/helper/auth.rb +0 -5
- data/lib/ramaze/helper/cache.rb +0 -9
- data/lib/ramaze/helper/form.rb +14 -2
- data/lib/ramaze/helper/formatting.rb +1 -1
- data/lib/ramaze/helper/layout.rb +97 -0
- data/lib/ramaze/helper/link.rb +6 -25
- data/lib/ramaze/helper/paginate.rb +2 -2
- data/lib/ramaze/helper/user.rb +3 -3
- data/lib/ramaze/helper.rb +1 -0
- data/lib/ramaze/setup.rb +22 -9
- data/lib/ramaze/spec/bacon.rb +34 -0
- data/lib/ramaze/spec/helper/template_examples.rb +13 -23
- data/lib/ramaze/spec.rb +8 -9
- data/lib/ramaze/tool/bin.rb +16 -6
- data/lib/ramaze/tool/project_creator.rb +1 -1
- data/lib/ramaze/version.rb +1 -1
- data/lib/ramaze.rb +8 -8
- data/lib/vendor/etag.rb +4 -2
- data/lib/vendor/route_exceptions.rb +6 -11
- data/ramaze.gemspec +52 -8
- data/spec/contrib/addressable_route.rb +32 -0
- data/spec/contrib/rest.rb +1 -1
- data/spec/examples/caching.rb +1 -1
- data/spec/examples/css.rb +1 -1
- data/spec/examples/element.rb +1 -1
- data/spec/examples/hello.rb +1 -1
- data/spec/examples/helpers/httpdigest.rb +1 -1
- data/spec/examples/linking.rb +1 -1
- data/spec/examples/simple.rb +1 -1
- data/spec/examples/templates/template_erubis.rb +3 -2
- data/spec/examples/templates/template_ezamar.rb +3 -2
- data/spec/examples/templates/template_haml.rb +3 -2
- data/spec/examples/templates/template_liquid.rb +3 -2
- data/spec/examples/templates/template_markaby.rb +5 -4
- data/spec/examples/templates/template_nagoro.rb +3 -3
- data/spec/examples/templates/template_redcloth.rb +3 -2
- data/spec/examples/templates/template_remarkably.rb +3 -2
- data/spec/examples/templates/template_tenjin.rb +3 -2
- data/spec/helper.rb +1 -2
- data/spec/ramaze/app.rb +1 -1
- data/spec/ramaze/bin/ramaze.rb +91 -0
- data/spec/ramaze/cache/memcache.rb +6 -0
- data/spec/ramaze/controller/actionless_templates.rb +1 -1
- data/spec/ramaze/controller/lonely_mapping.rb +16 -0
- data/spec/ramaze/controller/mapping.rb +0 -14
- data/spec/ramaze/controller/provide_inheritance.rb +1 -1
- data/spec/ramaze/controller/resolve.rb +1 -1
- data/spec/ramaze/controller/subclass.rb +1 -1
- data/spec/ramaze/controller/template_resolving.rb +1 -1
- data/spec/ramaze/dispatcher/directory.rb +1 -1
- data/spec/ramaze/dispatcher/file.rb +7 -7
- data/spec/ramaze/error.rb +2 -2
- data/spec/ramaze/files.rb +1 -1
- data/spec/ramaze/helper/auth.rb +1 -1
- data/spec/ramaze/helper/bench.rb +2 -1
- data/spec/ramaze/helper/cache.rb +1 -1
- data/spec/ramaze/helper/flash.rb +1 -1
- data/spec/ramaze/helper/form.rb +2 -2
- data/spec/ramaze/helper/httpdigest.rb +3 -3
- data/spec/ramaze/helper/layout/default.xhtml +5 -0
- data/spec/ramaze/helper/layout.rb +79 -0
- data/spec/ramaze/helper/link.rb +32 -11
- data/spec/ramaze/helper/localize.rb +1 -1
- data/spec/ramaze/helper/maruku.rb +1 -1
- data/spec/ramaze/helper/pager.rb +1 -1
- data/spec/ramaze/helper/paginate.rb +1 -1
- data/spec/ramaze/helper/request_accessor.rb +1 -1
- data/spec/ramaze/helper/sequel_form.rb +1 -1
- data/spec/ramaze/helper/simple_captcha.rb +1 -1
- data/spec/ramaze/helper/stack.rb +1 -1
- data/spec/ramaze/helper/user.rb +1 -1
- data/spec/ramaze/params.rb +4 -5
- data/spec/ramaze/session/memcache.rb +66 -0
- data/spec/ramaze/view/erubis.rb +1 -1
- data/spec/ramaze/view/ezamar.rb +1 -1
- data/spec/ramaze/view/gestalt.rb +1 -1
- data/spec/ramaze/view/haml.rb +1 -1
- data/spec/ramaze/view/liquid.rb +1 -1
- data/spec/ramaze/view/nagoro.rb +1 -1
- data/spec/ramaze/view/redcloth.rb +1 -1
- data/spec/ramaze/view/remarkably.rb +1 -1
- data/spec/ramaze/view/sass.rb +1 -1
- data/spec/ramaze/view/tagz.rb +1 -1
- data/spec/ramaze/view/tenjin.rb +1 -1
- data/spec/ramaze/view.rb +1 -1
- data/tasks/changelog.rake +3 -1
- data/tasks/{gem_installer.rake → gem_setup.rake} +45 -22
- data/tasks/release.rake +6 -4
- data/tasks/setup.rake +3 -21
- data/tasks/todo.rake +2 -4
- metadata +164 -10
- data/CHANGELOG +0 -16918
- data/doc/tutorial/todolist.mkd +0 -787
- data/lib/ramaze/snippets/divide.rb +0 -22
- data/lib/ramaze/snippets/object/acquire.rb +0 -37
- data/spec/snippets/kernel/constant.rb +0 -23
- data/tasks/install_dependencies.rake +0 -6
@@ -9,15 +9,15 @@ require 'spec/helper'
|
|
9
9
|
module Ramaze
|
10
10
|
# minimal middleware, no exception handling
|
11
11
|
middleware!(:spec){|m|
|
12
|
-
m.apps
|
12
|
+
m.apps Rack::ConditionalGet, Rack::ETag
|
13
13
|
m.innate
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
17
17
|
describe 'Serving static files' do
|
18
|
-
behaves_like :
|
18
|
+
behaves_like :rack_test
|
19
19
|
|
20
|
-
Ramaze.map('/', lambda{|env| [200, {}, 'nothing']})
|
20
|
+
Ramaze.map('/', lambda{|env| [200, {}, ['nothing']]})
|
21
21
|
|
22
22
|
it 'serves from public root' do
|
23
23
|
css = File.read(__DIR__('public/test_download.css'))
|
@@ -32,9 +32,9 @@ describe 'Serving static files' do
|
|
32
32
|
last_response.body.should == 'hi'
|
33
33
|
end
|
34
34
|
|
35
|
-
it 'sends
|
35
|
+
it 'sends Etag for string bodies' do
|
36
36
|
get '/'
|
37
|
-
last_response['
|
37
|
+
last_response['Etag'].size.should > 1
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'sends Last-Modified for file bodies' do
|
@@ -45,10 +45,10 @@ describe 'Serving static files' do
|
|
45
45
|
last_response['Last-Modified'].should == mtime.httpdate
|
46
46
|
end
|
47
47
|
|
48
|
-
it 'respects
|
48
|
+
it 'respects Etag with HTTP_IF_NONE_MATCH' do
|
49
49
|
get '/'
|
50
50
|
|
51
|
-
etag = last_response['
|
51
|
+
etag = last_response['Etag']
|
52
52
|
etag.should.not.be.nil
|
53
53
|
|
54
54
|
header 'HTTP_IF_NONE_MATCH', etag
|
data/spec/ramaze/error.rb
CHANGED
@@ -35,7 +35,7 @@ class SpecErrorHandling < SpecError
|
|
35
35
|
end
|
36
36
|
|
37
37
|
describe 'Error handling' do
|
38
|
-
behaves_like :
|
38
|
+
behaves_like :rack_test
|
39
39
|
|
40
40
|
Ramaze.options.mode = :dev
|
41
41
|
|
@@ -66,7 +66,7 @@ describe 'Error handling' do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'uses Rack::RouteExceptions when a route is set' do
|
69
|
-
Rack::RouteExceptions
|
69
|
+
Rack::RouteExceptions.route(NameError, '/handle/name_error')
|
70
70
|
|
71
71
|
got = get('/raises')
|
72
72
|
[got.status, got['Content-Type']].should == [200, 'text/html']
|
data/spec/ramaze/files.rb
CHANGED
@@ -17,7 +17,7 @@ Ramaze::App[:other].options.publics = 'files/public_2'
|
|
17
17
|
Ramaze.middleware!(:spec){|m| m.run(Ramaze::AppMap) }
|
18
18
|
|
19
19
|
describe Ramaze::Files do
|
20
|
-
behaves_like :
|
20
|
+
behaves_like :rack_test
|
21
21
|
|
22
22
|
it 'serves files for core app from public_1' do
|
23
23
|
get('/plain.txt').body.should == "Just some text in a file\n"
|
data/spec/ramaze/helper/auth.rb
CHANGED
data/spec/ramaze/helper/bench.rb
CHANGED
@@ -12,6 +12,7 @@ describe Ramaze::Helper::Bench do
|
|
12
12
|
result = bench{ sleep 0.1; 'result' }
|
13
13
|
result.should == 'result'
|
14
14
|
log.size.should == 1
|
15
|
-
|
15
|
+
# output between ruby 1.8 and 1.9 differs...
|
16
|
+
log.pop.should =~ %r!^Bench #{__FILE__}:#{__LINE__ - 4}:.* \d\.\d+$!
|
16
17
|
end
|
17
18
|
end
|
data/spec/ramaze/helper/cache.rb
CHANGED
data/spec/ramaze/helper/flash.rb
CHANGED
data/spec/ramaze/helper/form.rb
CHANGED
@@ -42,7 +42,7 @@ class SpecHelperForm < Ramaze::Controller
|
|
42
42
|
|
43
43
|
def select_array_multiple
|
44
44
|
languages = %w[ English German Japanese ]
|
45
|
-
form_select('Languages', :languages, languages, :multiple =>
|
45
|
+
form_select('Languages', :languages, languages, :multiple => 1)
|
46
46
|
end
|
47
47
|
|
48
48
|
def select_array_selected
|
@@ -57,7 +57,7 @@ class SpecHelperForm < Ramaze::Controller
|
|
57
57
|
end
|
58
58
|
|
59
59
|
describe Ramaze::Helper::Form do
|
60
|
-
behaves_like :
|
60
|
+
behaves_like :rack_test
|
61
61
|
|
62
62
|
it 'provides empty text input' do
|
63
63
|
got = get('/text')
|
@@ -49,7 +49,7 @@ end
|
|
49
49
|
|
50
50
|
describe Ramaze::Helper::HttpDigest do
|
51
51
|
describe 'headers' do
|
52
|
-
behaves_like :
|
52
|
+
behaves_like :rack_test
|
53
53
|
|
54
54
|
it 'sends out all the required header information' do
|
55
55
|
get '/authenticate'
|
@@ -72,7 +72,7 @@ end
|
|
72
72
|
__END__
|
73
73
|
|
74
74
|
describe 'Digest authentication' do
|
75
|
-
behaves_like :
|
75
|
+
behaves_like :rack_test
|
76
76
|
|
77
77
|
it 'authenticates a user with a block' do
|
78
78
|
digest_authorize 'foo', 'oof'
|
@@ -90,7 +90,7 @@ __END__
|
|
90
90
|
end
|
91
91
|
|
92
92
|
describe 'Plaintext authentication' do
|
93
|
-
behaves_like :
|
93
|
+
behaves_like :rack_test
|
94
94
|
|
95
95
|
it 'authenticates a user with the plaintext method' do
|
96
96
|
get '/plaintext/authenticate'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
3
|
+
|
4
|
+
require 'spec/helper'
|
5
|
+
|
6
|
+
class LayoutHelperOne < Ramaze::Controller
|
7
|
+
map '/one'
|
8
|
+
set_layout 'default'
|
9
|
+
|
10
|
+
def laid_out1; end
|
11
|
+
def laid_out2; end
|
12
|
+
def laid_out3; end
|
13
|
+
end
|
14
|
+
|
15
|
+
class LayoutHelperTwo < Ramaze::Controller
|
16
|
+
map '/two'
|
17
|
+
set_layout 'default' => [:laid_out1, :laid_out2]
|
18
|
+
|
19
|
+
def laid_out1; end
|
20
|
+
def laid_out2; end
|
21
|
+
|
22
|
+
def not_laid_out; end
|
23
|
+
end
|
24
|
+
|
25
|
+
class LayoutHelper < Ramaze::Controller
|
26
|
+
map '/three'
|
27
|
+
set_layout_except 'default' => [:not_laid_out1, :not_laid_out2]
|
28
|
+
|
29
|
+
def laid_out1; end
|
30
|
+
def laid_out2; end
|
31
|
+
|
32
|
+
def not_laid_out1; end
|
33
|
+
def not_laid_out2; end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe Ramaze::Helper::Layout do
|
38
|
+
behaves_like :rack_test
|
39
|
+
|
40
|
+
it 'lays out all actions' do
|
41
|
+
get '/one/laid_out1'
|
42
|
+
last_response.status.should == 200
|
43
|
+
last_response.body.should.match /laid out/
|
44
|
+
get '/one/laid_out2'
|
45
|
+
last_response.status.should == 200
|
46
|
+
last_response.body.should.match /laid out/
|
47
|
+
get '/one/laid_out3'
|
48
|
+
last_response.status.should == 200
|
49
|
+
last_response.body.should.match /laid out/
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'lays out only a whitelist of actions' do
|
53
|
+
get '/two/laid_out1'
|
54
|
+
last_response.status.should == 200
|
55
|
+
last_response.body.should.match /laid out/
|
56
|
+
get '/two/laid_out2'
|
57
|
+
last_response.status.should == 200
|
58
|
+
last_response.body.should.match /laid out/
|
59
|
+
get '/two/not_laid_out'
|
60
|
+
last_response.status.should == 200
|
61
|
+
last_response.body.should.not.match /laid out/
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'lays out all actions except a blacklist' do
|
65
|
+
get '/three/laid_out1'
|
66
|
+
last_response.status.should == 200
|
67
|
+
last_response.body.should.match /laid out/
|
68
|
+
get '/three/laid_out2'
|
69
|
+
last_response.status.should == 200
|
70
|
+
last_response.body.should.match /laid out/
|
71
|
+
get '/three/not_laid_out1'
|
72
|
+
last_response.status.should == 200
|
73
|
+
last_response.body.should.not.match /laid out/
|
74
|
+
get '/three/not_laid_out2'
|
75
|
+
last_response.status.should == 200
|
76
|
+
last_response.body.should.not.match /laid out/
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/spec/ramaze/helper/link.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
# All files in this distribution are subject to the terms of the Ruby license.
|
3
3
|
|
4
4
|
require 'spec/helper'
|
5
|
-
require 'ramaze/helper/link'
|
6
5
|
|
7
6
|
class SpecHelperLink < Ramaze::Controller
|
8
7
|
map '/'
|
@@ -12,18 +11,18 @@ class SpecHelperLinkTwo < Ramaze::Controller
|
|
12
11
|
map '/two'
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
class SpecHelperApp < Ramaze::Controller
|
15
|
+
map '/', :other
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
18
|
+
class SpecHelperAppTwo < Ramaze::Controller
|
19
|
+
map '/two', :other
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
Ramaze::App[:other].location = '/other'
|
23
|
+
|
24
|
+
describe Ramaze::Helper::Link do
|
25
|
+
extend Ramaze::Helper::Link
|
27
26
|
|
28
27
|
it 'lays out breadcrumbs' do
|
29
28
|
SpecHelperLink.breadcrumbs('/file/dir/listing/is/cool').
|
@@ -46,4 +45,26 @@ describe Ramaze::Helper::Link do
|
|
46
45
|
'<a href="/prefix/path/file/dir/listing/is/cool">cool</a>'
|
47
46
|
].join('/')
|
48
47
|
end
|
48
|
+
|
49
|
+
it "builds routes and links to other applications" do
|
50
|
+
SpecHelperApp.r(:foo).to_s.should == '/other/foo'
|
51
|
+
SpecHelperApp.a(:foo, :bar).should == '<a href="/other/bar">foo</a>'
|
52
|
+
SpecHelperAppTwo.r(:foo).to_s.should == '/other/two/foo'
|
53
|
+
SpecHelperAppTwo.a(:foo, :bar).should == '<a href="/other/two/bar">foo</a>'
|
54
|
+
end
|
55
|
+
it "builds routes when Ramaze.options.prefix is present" do
|
56
|
+
Ramaze.options.prefix = '/prfx'
|
57
|
+
SpecHelperLink.r(:foo).to_s.should == '/prfx/foo'
|
58
|
+
SpecHelperLinkTwo.r(:foo).to_s.should == '/prfx/two/foo'
|
59
|
+
SpecHelperApp.r(:foo).to_s.should == '/prfx/other/foo'
|
60
|
+
SpecHelperAppTwo.r(:foo).to_s.should == '/prfx/other/two/foo'
|
61
|
+
|
62
|
+
end
|
63
|
+
it "builds links when Ramaze.options.prefix is present" do
|
64
|
+
Ramaze.options.prefix = '/prfx'
|
65
|
+
SpecHelperLink.a(:foo, :bar).should == '<a href="/prfx/bar">foo</a>'
|
66
|
+
SpecHelperLinkTwo.a(:foo, :bar).should == '<a href="/prfx/two/bar">foo</a>'
|
67
|
+
SpecHelperApp.a(:foo, :bar).should == '<a href="/prfx/other/bar">foo</a>'
|
68
|
+
SpecHelperAppTwo.a(:foo, :bar).should == '<a href="/prfx/other/two/bar">foo</a>'
|
69
|
+
end
|
49
70
|
end
|
@@ -28,7 +28,7 @@ DICTIONARY.load(:de, :hash => {'one' => 'eins', 'two' => 'zwei'})
|
|
28
28
|
DICTIONARY.load(:ja, :hash => {'one' => '一', 'three' => '三'})
|
29
29
|
|
30
30
|
describe Ramaze::Helper::Localize do
|
31
|
-
behaves_like :
|
31
|
+
behaves_like :rack_test
|
32
32
|
|
33
33
|
should 'default to a language' do
|
34
34
|
get('/').body.should == 'en'
|
data/spec/ramaze/helper/pager.rb
CHANGED
data/spec/ramaze/helper/stack.rb
CHANGED
data/spec/ramaze/helper/user.rb
CHANGED
data/spec/ramaze/params.rb
CHANGED
@@ -51,7 +51,7 @@ class TCParamsController2 < Ramaze::Controller
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def keys
|
54
|
-
request.params.keys.
|
54
|
+
request.params.keys.inspect
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -64,7 +64,7 @@ class TCParamsController3 < Ramaze::Controller
|
|
64
64
|
end
|
65
65
|
|
66
66
|
describe "Simple Parameters" do
|
67
|
-
behaves_like :
|
67
|
+
behaves_like :rack_test
|
68
68
|
|
69
69
|
def handle(*url)
|
70
70
|
Ramaze::Mock.get(*url).body
|
@@ -103,8 +103,7 @@ describe "Simple Parameters" do
|
|
103
103
|
end
|
104
104
|
|
105
105
|
it "action that takes all params but needs at least one (not given here)" do
|
106
|
-
lambda{ handle('/at_least_one') }.
|
107
|
-
should.raise(ArgumentError)
|
106
|
+
lambda{ handle('/at_least_one') }.should.raise(ArgumentError)
|
108
107
|
end
|
109
108
|
|
110
109
|
it "one default" do
|
@@ -149,6 +148,6 @@ describe "Simple Parameters" do
|
|
149
148
|
end
|
150
149
|
|
151
150
|
it 'should handle valueless params' do
|
152
|
-
handle('/jo/keys?foo').should == '"foo"'
|
151
|
+
handle('/jo/keys?foo').should == '["foo"]'
|
153
152
|
end
|
154
153
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
3
|
+
|
4
|
+
require 'spec/helper'
|
5
|
+
|
6
|
+
spec_precondition 'memcached is running' do
|
7
|
+
require 'memcache'
|
8
|
+
cache = MemCache.new(['localhost:11211'])
|
9
|
+
cache.set('active', true)
|
10
|
+
end
|
11
|
+
|
12
|
+
class SpecSession < Ramaze::Controller
|
13
|
+
map '/'
|
14
|
+
engine :None
|
15
|
+
|
16
|
+
def index
|
17
|
+
'No session here'
|
18
|
+
end
|
19
|
+
|
20
|
+
def init
|
21
|
+
session[:counter] = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def view
|
25
|
+
session[:counter]
|
26
|
+
end
|
27
|
+
|
28
|
+
def increment
|
29
|
+
session[:counter] += 1
|
30
|
+
end
|
31
|
+
|
32
|
+
def decrement
|
33
|
+
session[:counter] -= 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset
|
37
|
+
session.clear
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Ramaze::Cache.options.session = Ramaze::Cache::MemCache
|
42
|
+
|
43
|
+
describe Innate::Session do
|
44
|
+
behaves_like :rack_test
|
45
|
+
|
46
|
+
should 'initiate session as needed' do
|
47
|
+
get '/'
|
48
|
+
last_response.body.should == 'No session here'
|
49
|
+
last_response['Set-Cookie'].should == nil
|
50
|
+
|
51
|
+
get('/init')
|
52
|
+
last_response.body.should == '0'
|
53
|
+
|
54
|
+
1.upto(10) do |n|
|
55
|
+
get('/increment').body.should == n.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
get('/reset')
|
59
|
+
get('/view').body.should == ''
|
60
|
+
get('/init').body.should == '0'
|
61
|
+
|
62
|
+
-1.downto(-10) do |n|
|
63
|
+
get('/decrement').body.should == n.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|