axlsx_styler 0.1.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +23 -0
- data/README.md +50 -26
- data/Rakefile +18 -4
- data/lib/axlsx_styler.rb +4 -23
- data/lib/axlsx_styler/axlsx_cell.rb +32 -30
- data/lib/axlsx_styler/axlsx_package.rb +17 -0
- data/lib/axlsx_styler/axlsx_styles.rb +36 -0
- data/lib/axlsx_styler/axlsx_workbook.rb +26 -43
- data/lib/axlsx_styler/axlsx_worksheet.rb +34 -17
- data/lib/axlsx_styler/version.rb +1 -1
- data/test/dummy_app/Rakefile +7 -0
- data/test/dummy_app/app/assets/config/manifest.js +3 -0
- data/test/dummy_app/app/assets/javascripts/application.js +0 -0
- data/test/dummy_app/app/assets/stylesheets/application.css +3 -0
- data/test/dummy_app/app/controllers/application_controller.rb +3 -0
- data/test/dummy_app/app/controllers/spreadsheets_controller.rb +7 -0
- data/test/dummy_app/app/models/application_record.rb +3 -0
- data/test/dummy_app/app/views/layouts/application.html.erb +14 -0
- data/{examples/colors_and_borders.rb → test/dummy_app/app/views/spreadsheets/test.xlsx.axlsx} +2 -7
- data/test/dummy_app/config.ru +4 -0
- data/test/dummy_app/config/application.rb +56 -0
- data/test/dummy_app/config/boot.rb +10 -0
- data/test/dummy_app/config/database.yml +25 -0
- data/test/dummy_app/config/environment.rb +5 -0
- data/test/dummy_app/config/environments/development.rb +30 -0
- data/test/dummy_app/config/environments/production.rb +60 -0
- data/test/dummy_app/config/environments/test.rb +41 -0
- data/test/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy_app/config/initializers/inflections.rb +10 -0
- data/test/dummy_app/config/initializers/mime_types.rb +5 -0
- data/test/dummy_app/config/initializers/secret_token.rb +11 -0
- data/test/dummy_app/config/initializers/session_store.rb +8 -0
- data/test/dummy_app/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy_app/config/locales/en.yml +5 -0
- data/test/dummy_app/config/routes.rb +3 -0
- data/test/dummy_app/config/secrets.yml +22 -0
- data/test/dummy_app/db/schema.rb +15 -0
- data/test/dummy_app/db/test.sqlite3 +0 -0
- data/test/dummy_app/log/test.log +1004 -0
- data/test/helper_methods.rb +12 -0
- data/test/integration/application_test.rb +18 -0
- data/test/test_helper.rb +31 -4
- data/test/unit/borders_test.rb +127 -0
- data/test/unit/examples_test.rb +20 -0
- data/test/unit/merge_styles_test.rb +56 -0
- data/test/unit/regresssions_test.rb +44 -0
- data/test/unit/serialize_test.rb +34 -0
- data/test/unit/to_stream_test.rb +34 -0
- metadata +152 -47
- data/.gitignore +0 -24
- data/Gemfile +0 -4
- data/axlsx_styler.gemspec +0 -36
- data/examples/vanilla_axlsx.md +0 -70
- data/spreadsheet.png +0 -0
- data/test/cell_test.rb +0 -14
- data/test/integration_test.rb +0 -234
- data/test/workbook_test.rb +0 -10
data/.gitignore
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
.bundle
|
4
|
-
.config
|
5
|
-
.yardoc
|
6
|
-
Gemfile.lock
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
18
|
-
*.bundle
|
19
|
-
*.so
|
20
|
-
*.o
|
21
|
-
*.a
|
22
|
-
mkmf.log
|
23
|
-
*.xlsx
|
24
|
-
*.xlsx#
|
data/Gemfile
DELETED
data/axlsx_styler.gemspec
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'axlsx_styler/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'axlsx_styler'
|
8
|
-
spec.version = AxlsxStyler::VERSION
|
9
|
-
spec.authors = ['Anton Sakovich']
|
10
|
-
spec.email = ['sakovias@gmail.com']
|
11
|
-
spec.summary = %q(This gem allows to separate data from styles when using Axlsx gem.)
|
12
|
-
spec.description = %q(
|
13
|
-
Axlsx gem is an excellent tool to build Excel worksheets. The sheets are
|
14
|
-
created row-by-row and styles are immediately added to each cell when a
|
15
|
-
row is created. This gem allows to follow an alternative route: fill out
|
16
|
-
a spreadsheet with data and apply styles later. Styles can be added
|
17
|
-
to individual cells as well as to ranges of cells. As a bonus, this gem
|
18
|
-
also simplifies drawing borders around groups of cells.
|
19
|
-
)
|
20
|
-
spec.homepage = 'https://github.com/sakovias/axlsx_styler'
|
21
|
-
spec.license = 'MIT'
|
22
|
-
|
23
|
-
spec.files = `git ls-files -z`.split("\x0")
|
24
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
25
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
|
-
spec.require_paths = ['lib']
|
27
|
-
spec.required_ruby_version = '>= 1.9.3'
|
28
|
-
|
29
|
-
spec.add_dependency 'axlsx', '~> 2.0'
|
30
|
-
spec.add_dependency 'activesupport', '>= 3.1'
|
31
|
-
|
32
|
-
spec.add_development_dependency 'bundler', '~> 1.6'
|
33
|
-
spec.add_development_dependency 'rake', '~> 0.9'
|
34
|
-
spec.add_development_dependency 'minitest', '~> 5.0'
|
35
|
-
spec.add_development_dependency 'awesome_print', '~> 1.6'
|
36
|
-
end
|
data/examples/vanilla_axlsx.md
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
This gem is supposed to make styling spreadsheets easier.
|
2
|
-
|
3
|
-
Here's how the [example from the README](../README.md) compares to that implemented with plain `axlsx`.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'axlsx'
|
7
|
-
axlsx = Axlsx::Package.new
|
8
|
-
wb = axlsx.workbook
|
9
|
-
border_color = '000000'
|
10
|
-
wb.add_worksheet do |sheet|
|
11
|
-
# top row
|
12
|
-
header_hash = { b: true, bg_color: '95AFBA' }
|
13
|
-
top_left_corner = wb.styles.add_style header_hash.merge({
|
14
|
-
border: { style: :thin, color: border_color, edges: [:top, :left, :bottom] }
|
15
|
-
})
|
16
|
-
top_edge = wb.styles.add_style header_hash.merge({
|
17
|
-
border: { style: :thin, color: border_color, edges: [:top, :bottom] }
|
18
|
-
})
|
19
|
-
top_right_corner = wb.styles.add_style header_hash.merge({
|
20
|
-
border: { style: :thin, color: border_color, edges: [:top, :right, :bottom] }
|
21
|
-
})
|
22
|
-
sheet.add_row
|
23
|
-
sheet.add_row(["", "Product", "Category", "Price"],
|
24
|
-
style: [ nil, top_left_corner, top_edge, top_right_corner ]
|
25
|
-
)
|
26
|
-
|
27
|
-
# middle rows
|
28
|
-
color_hash = { bg_color: 'E2F89C' }
|
29
|
-
left_edge = wb.styles.add_style color_hash.merge(
|
30
|
-
b: true,
|
31
|
-
border: {
|
32
|
-
style: :thin, color: border_color, edges: [:left]
|
33
|
-
}
|
34
|
-
)
|
35
|
-
inner = wb.styles.add_style color_hash
|
36
|
-
right_edge = wb.styles.add_style color_hash.merge(
|
37
|
-
alignment: { horizontal: :left },
|
38
|
-
border: {
|
39
|
-
style: :thin, color: border_color, edges: [:right]
|
40
|
-
}
|
41
|
-
)
|
42
|
-
sheet.add_row(
|
43
|
-
["", "Butter", "Dairy", 4.99],
|
44
|
-
style: [nil, left_edge, inner, right_edge]
|
45
|
-
)
|
46
|
-
sheet.add_row(
|
47
|
-
["", "Bread", "Baked Goods", 3.45],
|
48
|
-
style: [nil, left_edge, inner, right_edge]
|
49
|
-
)
|
50
|
-
|
51
|
-
# last row
|
52
|
-
bottom_left_corner = wb.styles.add_style color_hash.merge({
|
53
|
-
b: true,
|
54
|
-
border: { style: :thin, color: border_color, edges: [:left, :bottom] }
|
55
|
-
})
|
56
|
-
bottom_edge = wb.styles.add_style color_hash.merge({
|
57
|
-
border: { style: :thin, color: border_color, edges: [:bottom] }
|
58
|
-
})
|
59
|
-
bottom_right_corner = wb.styles.add_style color_hash.merge({
|
60
|
-
alignment: { horizontal: :left },
|
61
|
-
border: { style: :thin, color: border_color, edges: [:right, :bottom] }
|
62
|
-
})
|
63
|
-
sheet.add_row(["", "Broccoli", "Produce", 2.99],
|
64
|
-
style: [nil, bottom_left_corner, bottom_edge, bottom_right_corner]
|
65
|
-
)
|
66
|
-
|
67
|
-
sheet.column_widths 5, 20, 20, 20
|
68
|
-
end
|
69
|
-
axlsx.serialize "grocery.xlsx"
|
70
|
-
```
|
data/spreadsheet.png
DELETED
Binary file
|
data/test/cell_test.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class CellTest < MiniTest::Test
|
4
|
-
def test_can_add_style
|
5
|
-
p = Axlsx::Package.new
|
6
|
-
wb = p.workbook
|
7
|
-
sheet = wb.add_worksheet
|
8
|
-
row = sheet.add_row ["x", "y"]
|
9
|
-
cell = row.cells.first
|
10
|
-
|
11
|
-
cell.add_style b: true
|
12
|
-
assert_equal({ b: true }, cell.raw_style)
|
13
|
-
end
|
14
|
-
end
|
data/test/integration_test.rb
DELETED
@@ -1,234 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class IntegrationTest < MiniTest::Test
|
4
|
-
def setup
|
5
|
-
@axlsx = Axlsx::Package.new
|
6
|
-
@workbook = @axlsx.workbook
|
7
|
-
end
|
8
|
-
|
9
|
-
# Save to a file using Axlsx::Package#serialize
|
10
|
-
def serialize(filename)
|
11
|
-
@axlsx.serialize File.expand_path("../../tmp/#{filename}.xlsx", __FILE__)
|
12
|
-
assert_equal true, @workbook.styles_applied
|
13
|
-
end
|
14
|
-
|
15
|
-
# Save to a file by getting contents from stream
|
16
|
-
def to_stream(filename)
|
17
|
-
File.open(File.expand_path("../../tmp/#{filename}.xlsx", __FILE__), 'w') do |f|
|
18
|
-
f.write @axlsx.to_stream.read
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# New functionality as of 0.1.5 (serialize)
|
23
|
-
def test_works_without_apply_styles_serialize
|
24
|
-
filename = 'without_apply_styles_serialize'
|
25
|
-
assert_equal nil, @workbook.styles_applied
|
26
|
-
@workbook.add_worksheet do |sheet|
|
27
|
-
sheet.add_row ['A1', 'B1']
|
28
|
-
sheet.add_style 'A1:B1', b: true
|
29
|
-
end
|
30
|
-
serialize(filename)
|
31
|
-
assert_equal 1, @workbook.style_index.count
|
32
|
-
end
|
33
|
-
|
34
|
-
# New functionality as of 0.1.5 (to_stream)
|
35
|
-
def test_works_without_apply_styles_to_stream
|
36
|
-
filename = 'without_apply_styles_to_stream'
|
37
|
-
assert_equal nil, @workbook.styles_applied
|
38
|
-
@workbook.add_worksheet do |sheet|
|
39
|
-
sheet.add_row ['A1', 'B1']
|
40
|
-
sheet.add_style 'A1:B1', b: true
|
41
|
-
end
|
42
|
-
to_stream(filename)
|
43
|
-
assert_equal 1, @workbook.style_index.count
|
44
|
-
end
|
45
|
-
|
46
|
-
# Backwards compatibility with pre 0.1.5 (serialize)
|
47
|
-
def test_works_with_apply_styles_serialize
|
48
|
-
filename = 'with_apply_styles_serialize'
|
49
|
-
assert_equal nil, @workbook.styles_applied
|
50
|
-
@workbook.add_worksheet do |sheet|
|
51
|
-
sheet.add_row ['A1', 'B1']
|
52
|
-
sheet.add_style 'A1:B1', b: true
|
53
|
-
end
|
54
|
-
@workbook.apply_styles # important for backwards compatibility
|
55
|
-
assert_equal 1, @workbook.style_index.count
|
56
|
-
serialize(filename)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Backwards compatibility with pre 0.1.5 (to_stream)
|
60
|
-
def test_works_with_apply_styles_to_stream
|
61
|
-
filename = 'with_apply_styles_to_stream'
|
62
|
-
assert_equal nil, @workbook.styles_applied
|
63
|
-
@workbook.add_worksheet do |sheet|
|
64
|
-
sheet.add_row ['A1', 'B1']
|
65
|
-
sheet.add_style 'A1:B1', b: true
|
66
|
-
end
|
67
|
-
@workbook.apply_styles # important for backwards compatibility
|
68
|
-
assert_equal 1, @workbook.style_index.count
|
69
|
-
to_stream(filename)
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_table_with_borders
|
73
|
-
filename = 'borders_test'
|
74
|
-
@workbook.add_worksheet do |sheet|
|
75
|
-
sheet.add_row
|
76
|
-
sheet.add_row ['', 'Product', 'Category', 'Price']
|
77
|
-
sheet.add_row ['', 'Butter', 'Dairy', 4.99]
|
78
|
-
sheet.add_row ['', 'Bread', 'Baked Goods', 3.45]
|
79
|
-
sheet.add_row ['', 'Broccoli', 'Produce', 2.99]
|
80
|
-
sheet.add_row ['', 'Pizza', 'Frozen Foods', 4.99]
|
81
|
-
sheet.column_widths 5, 20, 20, 20
|
82
|
-
|
83
|
-
sheet.add_style 'B2:D2', b: true
|
84
|
-
sheet.add_style 'B2:B6', b: true
|
85
|
-
sheet.add_style 'B2:D2', bg_color: '95AFBA'
|
86
|
-
sheet.add_style 'B3:D6', bg_color: 'E2F89C'
|
87
|
-
sheet.add_style 'D3:D6', alignment: { horizontal: :left }
|
88
|
-
sheet.add_border 'B2:D6'
|
89
|
-
sheet.add_border 'B3:D3', [:top]
|
90
|
-
sheet.add_border 'B3:D3', edges: [:bottom], style: :medium
|
91
|
-
sheet.add_border 'B3:D3', edges: [:bottom], style: :medium, color: '32f332'
|
92
|
-
end
|
93
|
-
serialize(filename)
|
94
|
-
assert_equal 12, @workbook.style_index.count
|
95
|
-
assert_equal 12 + 2, @workbook.style_index.keys.max
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_duplicate_borders
|
99
|
-
filename = 'duplicate_borders_test'
|
100
|
-
@workbook.add_worksheet do |sheet|
|
101
|
-
sheet.add_row
|
102
|
-
sheet.add_row ['', 'B2', 'C2', 'D2']
|
103
|
-
sheet.add_row ['', 'B3', 'C3', 'D3']
|
104
|
-
sheet.add_row ['', 'B4', 'C4', 'D4']
|
105
|
-
|
106
|
-
sheet.add_border 'B2:D4'
|
107
|
-
sheet.add_border 'B2:D4'
|
108
|
-
end
|
109
|
-
serialize(filename)
|
110
|
-
assert_equal 8, @workbook.style_index.count
|
111
|
-
assert_equal 8, @workbook.styled_cells.count
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_multiple_style_borders_on_same_sells
|
115
|
-
filename = 'multiple_style_borders'
|
116
|
-
@workbook.add_worksheet do |sheet|
|
117
|
-
sheet.add_row
|
118
|
-
sheet.add_row ['', 'B2', 'C2', 'D2']
|
119
|
-
sheet.add_row ['', 'B3', 'C3', 'D3']
|
120
|
-
|
121
|
-
sheet.add_border 'B2:D3', :all
|
122
|
-
sheet.add_border 'B2:D2', edges: [:bottom], style: :thick, color: 'ff0000'
|
123
|
-
end
|
124
|
-
serialize(filename)
|
125
|
-
assert_equal 6, @workbook.style_index.count
|
126
|
-
assert_equal 6, @workbook.styled_cells.count
|
127
|
-
|
128
|
-
b2_cell_style = {
|
129
|
-
border: {
|
130
|
-
style: :thick,
|
131
|
-
color: 'ff0000',
|
132
|
-
edges: [:bottom, :left, :top]
|
133
|
-
}
|
134
|
-
}
|
135
|
-
assert_equal b2_cell_style, @workbook.style_index
|
136
|
-
.find { |_, v| v[:border][:edges] == [:bottom, :left, :top] }[1]
|
137
|
-
|
138
|
-
d3_cell_style = {
|
139
|
-
border: {
|
140
|
-
style: :thin,
|
141
|
-
color: '000000',
|
142
|
-
edges: [:bottom, :right]
|
143
|
-
}
|
144
|
-
}
|
145
|
-
assert_equal d3_cell_style, @workbook.style_index
|
146
|
-
.find { |_, v| v[:border][:edges] == [:bottom, :right] }[1]
|
147
|
-
end
|
148
|
-
|
149
|
-
def test_table_with_num_fmt
|
150
|
-
filename = 'num_fmt_test'
|
151
|
-
t = Time.now
|
152
|
-
day = 24 * 60 * 60
|
153
|
-
@workbook.add_worksheet do |sheet|
|
154
|
-
sheet.add_row %w(Date Count Percent)
|
155
|
-
sheet.add_row [t - 2 * day, 2, 2.to_f.round(2) / 11]
|
156
|
-
sheet.add_row [t - 1 * day, 3, 3.to_f.round(2) / 11]
|
157
|
-
sheet.add_row [t, 6, 6.to_f.round(2) / 11]
|
158
|
-
|
159
|
-
sheet.add_style 'A1:B1', b: true
|
160
|
-
sheet.add_style 'A2:A4', format_code: 'YYYY-MM-DD hh:mm:ss'
|
161
|
-
end
|
162
|
-
serialize(filename)
|
163
|
-
assert_equal 2, @workbook.style_index.count
|
164
|
-
assert_equal 2 + 2, @workbook.style_index.keys.max
|
165
|
-
assert_equal 5, @workbook.styled_cells.count
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_duplicate_styles
|
169
|
-
filename = 'duplicate_styles'
|
170
|
-
@workbook.add_worksheet do |sheet|
|
171
|
-
sheet.add_row %w(Index City)
|
172
|
-
sheet.add_row [1, 'Ottawa']
|
173
|
-
sheet.add_row [2, 'Boston']
|
174
|
-
|
175
|
-
sheet.add_border 'A1:B1', [:bottom]
|
176
|
-
sheet.add_border 'A1:B1', [:bottom]
|
177
|
-
sheet.add_style 'A1:A3', b: true
|
178
|
-
sheet.add_style 'A1:A3', b: true
|
179
|
-
end
|
180
|
-
serialize(filename)
|
181
|
-
assert_equal 4, @workbook.styled_cells.count
|
182
|
-
assert_equal 3, @workbook.style_index.count
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_multiple_named_styles
|
186
|
-
filename = 'multiple_named_styles'
|
187
|
-
bold_blue = { b: true, fg_color: '0000FF' }
|
188
|
-
large = { sz: 16 }
|
189
|
-
red = { fg_color: 'FF0000' }
|
190
|
-
@workbook.add_worksheet do |sheet|
|
191
|
-
sheet.add_row %w(Index City)
|
192
|
-
sheet.add_row [1, 'Ottawa']
|
193
|
-
sheet.add_row [2, 'Boston']
|
194
|
-
|
195
|
-
sheet.add_style 'A1:B1', bold_blue, large
|
196
|
-
sheet.add_style 'A1:A3', red
|
197
|
-
end
|
198
|
-
serialize(filename)
|
199
|
-
assert_equal 4, @workbook.styled_cells.count
|
200
|
-
assert_equal 3, @workbook.style_index.count
|
201
|
-
end
|
202
|
-
|
203
|
-
# Overriding borders (part 1)
|
204
|
-
def test_mixed_borders_1
|
205
|
-
@filename = 'mixed_borders_1'
|
206
|
-
@workbook.add_worksheet do |sheet|
|
207
|
-
sheet.add_row
|
208
|
-
sheet.add_row ['', '1', '2', '3']
|
209
|
-
sheet.add_row ['', '4', '5', '6']
|
210
|
-
sheet.add_row ['', '7', '8', '9']
|
211
|
-
sheet.add_style 'B2:D4', border: { style: :thin, color: '000000' }
|
212
|
-
sheet.add_border 'C3:D4', style: :medium
|
213
|
-
end
|
214
|
-
@workbook.apply_styles
|
215
|
-
assert_equal 9, @workbook.styled_cells.count
|
216
|
-
assert_equal 2, @workbook.style_index.count
|
217
|
-
end
|
218
|
-
|
219
|
-
# Overriding borders (part 2)
|
220
|
-
def test_mixed_borders
|
221
|
-
@filename = 'mixed_borders_2'
|
222
|
-
@workbook.add_worksheet do |sheet|
|
223
|
-
sheet.add_row
|
224
|
-
sheet.add_row ['', '1', '2', '3']
|
225
|
-
sheet.add_row ['', '4', '5', '6']
|
226
|
-
sheet.add_row ['', '7', '8', '9']
|
227
|
-
sheet.add_border 'B2:D4', style: :medium
|
228
|
-
sheet.add_style 'D2:D4', border: { style: :thin, color: '000000' }
|
229
|
-
end
|
230
|
-
@workbook.apply_styles
|
231
|
-
assert_equal 8, @workbook.styled_cells.count
|
232
|
-
assert_equal 6, @workbook.style_index.count
|
233
|
-
end
|
234
|
-
end
|
data/test/workbook_test.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
class WorkbookTest < MiniTest::Test
|
2
|
-
def test_adding_styled_cells
|
3
|
-
p = Axlsx::Package.new
|
4
|
-
wb = p.workbook
|
5
|
-
wb.add_styled_cell 'Cell 1'
|
6
|
-
wb.add_styled_cell 'Cell 2'
|
7
|
-
assert_equal ['Cell 1', 'Cell 2'].to_set, wb.styled_cells
|
8
|
-
assert_equal nil, wb.styles_applied
|
9
|
-
end
|
10
|
-
end
|