attachy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE +21 -0
- data/README.md +108 -0
- data/lib/assets/javascripts/attachy.js +289 -0
- data/lib/attachy.rb +13 -0
- data/lib/attachy/builders/attachy/form_builder.rb +15 -0
- data/lib/attachy/engine.rb +16 -0
- data/lib/attachy/helpers/attachy/view_helper.rb +31 -0
- data/lib/attachy/models/attachy/extension.rb +79 -0
- data/lib/attachy/models/attachy/file.rb +59 -0
- data/lib/attachy/models/attachy/viewer.rb +170 -0
- data/lib/attachy/version.rb +3 -0
- data/lib/generators/attachy/install_generator.rb +25 -0
- data/lib/generators/attachy/templates/config/attachy.yml.erb +15 -0
- data/lib/generators/attachy/templates/db/migrate/create_attachy_files_table.rb +19 -0
- data/lib/generators/attachy/templates/public/cloudinary_cors.html +46 -0
- data/spec/builders/attachy/form_builder/attachy_content_spec.rb +35 -0
- data/spec/builders/attachy/form_builder/attachy_file_field_spec.rb +23 -0
- data/spec/builders/attachy/form_builder/attachy_spec.rb +35 -0
- data/spec/factories/attachy/file.rb +12 -0
- data/spec/factories/user.rb +5 -0
- data/spec/helpers/attachy/attachy_content_spec.rb +21 -0
- data/spec/helpers/attachy/attachy_file_field_spec.rb +21 -0
- data/spec/helpers/attachy/attachy_spec.rb +35 -0
- data/spec/models/attachy/callback/destroy_file_spec.rb +55 -0
- data/spec/models/attachy/callback/remove_tmp_tag_spec.rb +11 -0
- data/spec/models/attachy/extension/user/avatar_spec.rb +91 -0
- data/spec/models/attachy/extension/user/photos_spec.rb +88 -0
- data/spec/models/attachy/file/config_spec.rb +11 -0
- data/spec/models/attachy/file/default_spec.rb +26 -0
- data/spec/models/attachy/file/path_spec.rb +16 -0
- data/spec/models/attachy/file/transform_spec.rb +86 -0
- data/spec/models/attachy/file_spec.rb +14 -0
- data/spec/models/attachy/viewer/attachments_spec.rb +28 -0
- data/spec/models/attachy/viewer/button_label_options_spec.rb +15 -0
- data/spec/models/attachy/viewer/button_label_spec.rb +34 -0
- data/spec/models/attachy/viewer/content_options_spec.rb +29 -0
- data/spec/models/attachy/viewer/content_spec.rb +62 -0
- data/spec/models/attachy/viewer/field_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/field_spec.rb +56 -0
- data/spec/models/attachy/viewer/file_button_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/file_button_spec.rb +57 -0
- data/spec/models/attachy/viewer/file_field_options_spec.rb +90 -0
- data/spec/models/attachy/viewer/file_field_spec.rb +25 -0
- data/spec/models/attachy/viewer/hidden_field_spec.rb +22 -0
- data/spec/models/attachy/viewer/image_spec.rb +170 -0
- data/spec/models/attachy/viewer/link_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/link_spec.rb +131 -0
- data/spec/models/attachy/viewer/node_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/node_spec.rb +134 -0
- data/spec/models/attachy/viewer/nodes_spec.rb +21 -0
- data/spec/models/attachy/viewer/remove_button_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/transform_spec.rb +44 -0
- data/spec/models/attachy/viewer/value_spec.rb +83 -0
- data/spec/models/user_spec.rb +9 -0
- data/spec/rails_helper.rb +11 -0
- data/spec/support/common.rb +20 -0
- data/spec/support/database_cleaner.rb +19 -0
- data/spec/support/db/migrate/create_users_table.rb +7 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/html_matchers.rb +5 -0
- data/spec/support/migrate.rb +4 -0
- data/spec/support/models/user.rb +5 -0
- data/spec/support/shoulda.rb +8 -0
- metadata +365 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Attachy::Viewer, '.file_field_options' do
|
4
|
+
let!(:object) { create :user }
|
5
|
+
let!(:method) { :avatar }
|
6
|
+
|
7
|
+
let!(:file) do
|
8
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
9
|
+
|
10
|
+
create :file, attachable: object, scope: method
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { described_class.new method, object }
|
14
|
+
|
15
|
+
context 'when :accept has invalid mime type' do
|
16
|
+
context 'with one type' do
|
17
|
+
before do
|
18
|
+
allow(subject).to receive(:metadata) { { accept: :abc } }
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does not added as attribute' do
|
22
|
+
el = subject.file_field_options
|
23
|
+
|
24
|
+
expect(el).to eq(class: :attachy__fileupload)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with more than one type' do
|
29
|
+
before do
|
30
|
+
allow(subject).to receive(:metadata) { { accept: [:abc, :png] } }
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'is added as attribute only the valid one' do
|
34
|
+
el = subject.file_field_options
|
35
|
+
|
36
|
+
expect(el).to eq(accept: 'image/png', class: :attachy__fileupload)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when :accept is a valid mime type' do
|
42
|
+
context 'with one type' do
|
43
|
+
before do
|
44
|
+
allow(subject).to receive(:metadata) { { accept: :jpg } }
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'is added as attribute' do
|
48
|
+
el = subject.file_field_options
|
49
|
+
|
50
|
+
expect(el).to eq(accept: 'image/jpeg', class: :attachy__fileupload)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with more than one type' do
|
55
|
+
before do
|
56
|
+
allow(subject).to receive(:metadata) { { accept: [:jpg, :png] } }
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'is added as attribute' do
|
60
|
+
el = subject.file_field_options
|
61
|
+
|
62
|
+
expect(el).to eq(accept: 'image/jpeg,image/png', class: :attachy__fileupload)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when :multiple is true' do
|
68
|
+
before do
|
69
|
+
allow(subject).to receive(:metadata) { { multiple: true } }
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'turns the field multiple' do
|
73
|
+
el = subject.file_field_options
|
74
|
+
|
75
|
+
expect(el).to eq(multiple: true, class: :attachy__fileupload)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when :multiple is false' do
|
80
|
+
before do
|
81
|
+
allow(subject).to receive(:metadata) { { multiple: false } }
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'does not adds the multiple attribute' do
|
85
|
+
el = subject.file_field_options
|
86
|
+
|
87
|
+
expect(el).to eq(class: :attachy__fileupload)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
require 'cloudinary'
|
3
|
+
|
4
|
+
RSpec.describe Attachy::Viewer, '.file_field' do
|
5
|
+
let!(:method) { :avatar }
|
6
|
+
let!(:object) { create :user }
|
7
|
+
let!(:options) { {} }
|
8
|
+
let!(:view) { double }
|
9
|
+
|
10
|
+
let!(:file) do
|
11
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
12
|
+
|
13
|
+
create :file, attachable: object, scope: method
|
14
|
+
end
|
15
|
+
|
16
|
+
before { allow(subject).to receive(:file_field_options) { { key: :value } } }
|
17
|
+
|
18
|
+
subject { described_class.new method, object, options, view }
|
19
|
+
|
20
|
+
it 'returns the hidden field with attachments value' do
|
21
|
+
allow(view).to receive(:cl_image_upload_tag).with(method, html: subject.file_field_options, tags: [Attachy::ENV_TAG, Attachy::TMP_TAG]) { :input }
|
22
|
+
|
23
|
+
expect(subject.file_field).to eq :input
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Attachy::Viewer, '.hidden_field' do
|
4
|
+
let!(:object) { create :user }
|
5
|
+
let!(:method) { :avatar }
|
6
|
+
|
7
|
+
let!(:file) do
|
8
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
9
|
+
|
10
|
+
create :file, attachable: object, scope: method
|
11
|
+
end
|
12
|
+
|
13
|
+
before { allow(subject).to receive(:value) { :value } }
|
14
|
+
|
15
|
+
subject { described_class.new method, object }
|
16
|
+
|
17
|
+
it 'returns the hidden field with attachments value' do
|
18
|
+
el = subject.hidden_field
|
19
|
+
|
20
|
+
expect(el).to have_tag :input, with: { name: 'user[avatar]', type: 'hidden', value: 'value' }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Attachy::Viewer, '.image' do
|
4
|
+
let!(:method) { :avatar }
|
5
|
+
let!(:object) { create :user }
|
6
|
+
let!(:viewer) { described_class.new method, object, options }
|
7
|
+
let!(:default_html) { { alt: :image, height: 50, width: 150 } }
|
8
|
+
let!(:default_t) { { height: 100, width: 200 } }
|
9
|
+
let!(:options) { { t: default_t, html: default_html } }
|
10
|
+
|
11
|
+
let!(:file) do
|
12
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
13
|
+
|
14
|
+
create :file, attachable: object
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when :html is present' do
|
18
|
+
let!(:html_attributes) { { alt: :alt, invalid: :invalid, height: 11, width: 22 } }
|
19
|
+
|
20
|
+
context 'and :t is blank' do
|
21
|
+
let!(:t_attributes) { {} }
|
22
|
+
|
23
|
+
before do
|
24
|
+
allow_any_instance_of(Attachy::File).to receive(:url).with(t_attributes) { 'http://example.org' }
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'adds all attributes on image' do
|
28
|
+
el = viewer.image(t: t_attributes, html: html_attributes)
|
29
|
+
|
30
|
+
expect(el).to have_tag 'img', with: html_attributes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'and :t is present' do
|
35
|
+
let!(:t_attributes) { { height: 1, width: 2 } }
|
36
|
+
|
37
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(t_attributes) { 'http://example.org' } }
|
38
|
+
|
39
|
+
it 'gives priority to :html' do
|
40
|
+
el = viewer.image(t: t_attributes, html: html_attributes)
|
41
|
+
|
42
|
+
expect(el).to have_tag 'img', with: html_attributes
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'and :t is not given' do
|
47
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(default_t) { 'http://example.org' } }
|
48
|
+
|
49
|
+
it 'uses the :html attributes and transform with default :t' do
|
50
|
+
el = viewer.image(html: html_attributes)
|
51
|
+
|
52
|
+
expect(el).to have_tag 'img', with: {
|
53
|
+
'data-crop' => 'fill',
|
54
|
+
'data-format' => file.format,
|
55
|
+
'data-height' => 100,
|
56
|
+
'data-secure' => true,
|
57
|
+
'data-sign-url' => true,
|
58
|
+
'data-version' => file.version,
|
59
|
+
'data-width' => 200,
|
60
|
+
alt: 'alt',
|
61
|
+
height: 11,
|
62
|
+
invalid: 'invalid',
|
63
|
+
src: 'http://example.org',
|
64
|
+
width: 22
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when :html is blank' do
|
71
|
+
let!(:html_attributes) { {} }
|
72
|
+
|
73
|
+
context 'and :t is blank' do
|
74
|
+
let!(:t_attributes) { {} }
|
75
|
+
|
76
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(t_attributes) { 'http://example.org' } }
|
77
|
+
|
78
|
+
it 'adds only the default transformation with file attributes' do
|
79
|
+
el = viewer.image(t: t_attributes, html: html_attributes)
|
80
|
+
|
81
|
+
expect(el).to have_tag 'img', with: {
|
82
|
+
'data-format' => file.format,
|
83
|
+
'data-secure' => true,
|
84
|
+
'data-sign-url' => true,
|
85
|
+
'data-version' => file.version
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'and :t is present' do
|
91
|
+
let!(:t_attributes) { { height: 1, width: 2 } }
|
92
|
+
|
93
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(t_attributes) { 'http://example.org' } }
|
94
|
+
|
95
|
+
it 'adds the :t attributes on html attributes with default data' do
|
96
|
+
el = viewer.image(t: t_attributes, html: html_attributes)
|
97
|
+
|
98
|
+
expect(el).to have_tag 'img', with: {
|
99
|
+
'data-format' => file.format,
|
100
|
+
'data-public-id' => file.public_id,
|
101
|
+
'data-secure' => true,
|
102
|
+
'data-sign-url' => true,
|
103
|
+
'data-version' => file.version,
|
104
|
+
height: 1,
|
105
|
+
width: 2
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when :html is not given' do
|
112
|
+
context 'and :t is not given' do
|
113
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(default_t) { 'http://example.org' } }
|
114
|
+
|
115
|
+
it 'uses the default :html with default :t' do
|
116
|
+
el = viewer.image
|
117
|
+
|
118
|
+
expect(el).to have_tag 'img', with: {
|
119
|
+
'alt' => 'Example',
|
120
|
+
'data-crop' => 'fill',
|
121
|
+
'data-format' => file.format,
|
122
|
+
'data-height' => 100,
|
123
|
+
'data-public-id' => file.public_id,
|
124
|
+
'data-secure' => true,
|
125
|
+
'data-sign-url' => true,
|
126
|
+
'data-version' => file.version,
|
127
|
+
'data-width' => 200,
|
128
|
+
'height' => 100,
|
129
|
+
'src' => 'http://example.org',
|
130
|
+
'width' => 200
|
131
|
+
}
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'but :t is given' do
|
136
|
+
let!(:t_attributes) { { height: 1, width: 2 } }
|
137
|
+
|
138
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(t_attributes) { 'http://example.org' } }
|
139
|
+
|
140
|
+
it 'uses the default :html with given :t overriding the default :t' do
|
141
|
+
el = viewer.image(t: t_attributes)
|
142
|
+
|
143
|
+
expect(el).to have_tag 'img', with: {
|
144
|
+
'alt' => 'Example',
|
145
|
+
'data-crop' => 'fill',
|
146
|
+
'data-format' => file.format,
|
147
|
+
'data-height' => 1,
|
148
|
+
'data-public-id' => file.public_id,
|
149
|
+
'data-secure' => true,
|
150
|
+
'data-sign-url' => true,
|
151
|
+
'data-version' => file.version,
|
152
|
+
'data-width' => 2,
|
153
|
+
'height' => 1,
|
154
|
+
'src' => 'http://example.org',
|
155
|
+
'width' => 2
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'when given a :file' do
|
162
|
+
let!(:file) { build :file, format: :png, version: 7 }
|
163
|
+
|
164
|
+
it 'is used' do
|
165
|
+
expect(file).to receive(:url).with(default_t) { 'http://example.org' }
|
166
|
+
|
167
|
+
viewer.image file
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Attachy::Viewer, '.link_options' do
|
4
|
+
let!(:object) { create :user }
|
5
|
+
let!(:method) { :avatar }
|
6
|
+
|
7
|
+
let!(:file) do
|
8
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
9
|
+
|
10
|
+
create :file, attachable: object, scope: method
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { described_class.new method, object }
|
14
|
+
|
15
|
+
it 'returns the default link options' do
|
16
|
+
expect(subject.link_options).to eq(class: :attachy__link)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Attachy::Viewer, '.link' do
|
4
|
+
let!(:method) { :avatar }
|
5
|
+
let!(:object) { create :user }
|
6
|
+
let!(:default_html) { { alt: :image, height: 50, width: 150 } }
|
7
|
+
let!(:default_t) { { height: 100, width: 200 } }
|
8
|
+
let!(:options) { { t: default_t, html: default_html } }
|
9
|
+
|
10
|
+
let!(:file) do
|
11
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
12
|
+
|
13
|
+
create :file, attachable: object
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { described_class.new method, object, options }
|
17
|
+
|
18
|
+
describe 'default options' do
|
19
|
+
before do
|
20
|
+
allow_any_instance_of(Attachy::File).to receive(:url).with(crop: :none) { 'http://example.org' }
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'adds the link options' do
|
24
|
+
expect(subject).to receive(:image).with(file, t: default_t) { :image }
|
25
|
+
|
26
|
+
el = subject.link
|
27
|
+
|
28
|
+
expect(el).to have_tag :a, with: { class: 'attachy__link' }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when :t is not given' do
|
33
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url) { 'http://example.org' } }
|
34
|
+
|
35
|
+
it 'builds the imagem with generic transform' do
|
36
|
+
expect(subject).to receive(:image).with(file, t: default_t) { :image }
|
37
|
+
|
38
|
+
el = subject.link
|
39
|
+
|
40
|
+
expect(el).to have_tag :a do
|
41
|
+
with_text 'image'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when :t is given' do
|
47
|
+
let!(:t) { { height: 7, width: 17 } }
|
48
|
+
|
49
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url) { 'http://example.org' } }
|
50
|
+
|
51
|
+
it 'builds the imagem with given transform' do
|
52
|
+
expect(subject).to receive(:image).with(file, t: t) { :image }
|
53
|
+
|
54
|
+
el = subject.link(t: t)
|
55
|
+
|
56
|
+
expect(el).to have_tag :a do
|
57
|
+
with_text 'image'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when :t is not given' do
|
63
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(crop: :none) { 'http://example.org' } }
|
64
|
+
|
65
|
+
it 'builds the link url with :crop :none' do
|
66
|
+
expect(subject).to receive(:image).with(file, t: default_t) { :image }
|
67
|
+
|
68
|
+
el = subject.link
|
69
|
+
|
70
|
+
expect(el).to have_tag :a, with: { href: 'http://example.org' }
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'adds it on data attributes' do
|
74
|
+
expect(subject).to receive(:image).with(file, t: default_t) { :image }
|
75
|
+
|
76
|
+
el = subject.link
|
77
|
+
|
78
|
+
expect(el).to have_tag :a, with: { 'data-crop' => 'none' }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when :tl is given' do
|
83
|
+
let!(:tl) { { height: 4, width: 8 } }
|
84
|
+
|
85
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url).with(tl) { 'http://example.org' } }
|
86
|
+
|
87
|
+
it 'builds the link url with given transform' do
|
88
|
+
expect(subject).to receive(:image).with(file, t: default_t) { :image }
|
89
|
+
|
90
|
+
el = subject.link(tl: tl)
|
91
|
+
|
92
|
+
expect(el).to have_tag :a, with: { href: 'http://example.org' }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when :html is present' do
|
97
|
+
let!(:html) { { invalid: :invalid, target: :blank } }
|
98
|
+
|
99
|
+
before { allow_any_instance_of(Attachy::File).to receive(:url) { 'http://example.org' } }
|
100
|
+
|
101
|
+
it 'is added to html attributes' do
|
102
|
+
allow(subject).to receive(:image) { :image }
|
103
|
+
|
104
|
+
el = subject.link(html: html)
|
105
|
+
|
106
|
+
expect(el).to have_tag 'a', with: { invalid: 'invalid', target: 'blank' }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when given a :file' do
|
111
|
+
let!(:file) { build :file }
|
112
|
+
|
113
|
+
it 'is used' do
|
114
|
+
expect(file).to receive(:url).twice { 'http://example.org' }
|
115
|
+
|
116
|
+
subject.link file
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'when a block is given' do
|
121
|
+
let!(:html) { { target: :blank } }
|
122
|
+
let!(:tl) { { width: 10 } }
|
123
|
+
|
124
|
+
it 'yields the :html and :attachments' do
|
125
|
+
subject.link(tl: tl, html: html) do |htm, attachments|
|
126
|
+
expect(attachments).to eq [file]
|
127
|
+
expect(htm).to eq(data: { width: 10 }, target: :blank, class: :attachy__link)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|