isodoc 0.10.4 → 1.0.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 +4 -4
- data/Gemfile.lock +3 -4
- data/lib/isodoc/common.rb +1 -0
- data/lib/isodoc/function/blocks.rb +19 -77
- data/lib/isodoc/function/references.rb +56 -63
- data/lib/isodoc/function/reqt.rb +89 -0
- data/lib/isodoc/function/table.rb +5 -12
- data/lib/isodoc/function/to_word_html.rb +4 -2
- data/lib/isodoc/html_function/comments.rb +6 -0
- data/lib/isodoc/html_function/html.rb +37 -39
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/body.rb +7 -3
- data/lib/isodoc/word_function/postprocess.rb +7 -0
- data/spec/isodoc/blocks_spec.rb +32 -34
- data/spec/isodoc/footnotes_spec.rb +7 -20
- data/spec/isodoc/i18n_spec.rb +3 -3
- data/spec/isodoc/postproc_spec.rb +37 -6
- data/spec/isodoc/ref_spec.rb +1 -1
- data/spec/isodoc/section_spec.rb +1 -1
- data/spec/isodoc/table_spec.rb +28 -28
- data/spec/isodoc/xref_spec.rb +28 -28
- data/spec/spec_helper.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d11b5b991f38839676489ade5b30d9369d21bbeb27950a4e5fcf573f4b521179
|
4
|
+
data.tar.gz: 05de6af9b9f493f3d71dd81684e267a81c8db31c07d55189503af75296d73f10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdf155b3bb0b87a6ee716414c50613b76113e619a107a7eff90dc3af287c94150f322cbfd30a2a96923d580853549a0b6065ea72316b794e568237219e8da879
|
7
|
+
data.tar.gz: e863371fe9dde7d63d72d83c6835de6b64e93d0c2a1a6c739adba2b7c74539f10ccea6aa6c93a62ed79d111444f0ad3647dfaaf15ad7f7afac2973cba5786def
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
isodoc (0.
|
4
|
+
isodoc (1.0.0)
|
5
5
|
asciimath
|
6
6
|
html2doc (~> 0.8.11)
|
7
7
|
htmlentities (~> 4.3.4)
|
@@ -68,7 +68,7 @@ GEM
|
|
68
68
|
mime-types-data (3.2019.0331)
|
69
69
|
mini_portile2 (2.4.0)
|
70
70
|
nenv (0.3.0)
|
71
|
-
nokogiri (1.10.
|
71
|
+
nokogiri (1.10.4)
|
72
72
|
mini_portile2 (~> 2.4.0)
|
73
73
|
notiffany (0.1.3)
|
74
74
|
nenv (~> 0.1)
|
@@ -108,9 +108,8 @@ GEM
|
|
108
108
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
109
109
|
ruby-progressbar (1.10.1)
|
110
110
|
ruby_dep (1.5.0)
|
111
|
-
sassc (2.0
|
111
|
+
sassc (2.1.0)
|
112
112
|
ffi (~> 1.9)
|
113
|
-
rake
|
114
113
|
shellany (0.0.1)
|
115
114
|
simplecov (0.17.0)
|
116
115
|
docile (~> 1.1)
|
data/lib/isodoc/common.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative "./function/to_word_html"
|
|
11
11
|
require_relative "./function/utils"
|
12
12
|
require_relative "./function/xref_gen"
|
13
13
|
require_relative "./function/xref_sect_gen"
|
14
|
+
require_relative "./function/reqt"
|
14
15
|
require_relative "./class_utils"
|
15
16
|
|
16
17
|
module IsoDoc
|
@@ -43,16 +43,10 @@ module IsoDoc::Function
|
|
43
43
|
|
44
44
|
def figure_name_parse(node, div, name)
|
45
45
|
return if name.nil? && node.at(ns("./figure"))
|
46
|
-
div.p **{ class: "FigureTitle",
|
46
|
+
div.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
|
47
47
|
lbl = anchor(node['id'], :label, false)
|
48
48
|
lbl.nil? or p << l10n("#{@figure_lbl} #{lbl}")
|
49
49
|
name and !lbl.nil? and p << " — "
|
50
|
-
=begin
|
51
|
-
get_anchors[node['id']][:label].nil? or
|
52
|
-
p << l10n("#{@figure_lbl} #{get_anchors[node['id']][:label]}")
|
53
|
-
name and !get_anchors[node['id']][:label].nil? and
|
54
|
-
p << " — "
|
55
|
-
=end
|
56
50
|
name and name.children.each { |n| parse(n, div) }
|
57
51
|
end
|
58
52
|
end
|
@@ -83,8 +77,9 @@ module IsoDoc::Function
|
|
83
77
|
end
|
84
78
|
|
85
79
|
EXAMPLE_TBL_ATTR =
|
86
|
-
{ valign: "top",
|
87
|
-
|
80
|
+
#{ valign: "top",
|
81
|
+
{ class: "example_label", style: "width:82.8pt;padding:0 0 0 0;\
|
82
|
+
margin-left:0pt;vertical-align:top;" }.freeze
|
88
83
|
|
89
84
|
# used if we are boxing examples
|
90
85
|
def example_div_parse(node, out)
|
@@ -100,8 +95,7 @@ module IsoDoc::Function
|
|
100
95
|
|
101
96
|
def example_table_attr(node)
|
102
97
|
attr_code(id: node["id"], class: "example",
|
103
|
-
|
104
|
-
style: "border-collapse:collapse" )
|
98
|
+
style: "border-collapse:collapse;border-spacing:0;" )
|
105
99
|
end
|
106
100
|
|
107
101
|
def example_table_parse(node, out)
|
@@ -110,7 +104,7 @@ module IsoDoc::Function
|
|
110
104
|
tr.td **EXAMPLE_TBL_ATTR do |td|
|
111
105
|
td << example_label(node)
|
112
106
|
end
|
113
|
-
tr.td **{
|
107
|
+
tr.td **{ style: "vertical-align:top;padding:0;", class: "example" } do |td|
|
114
108
|
node.children.each { |n| parse(n, td) }
|
115
109
|
end
|
116
110
|
end
|
@@ -122,13 +116,13 @@ module IsoDoc::Function
|
|
122
116
|
end
|
123
117
|
|
124
118
|
def sourcecode_name_parse(_node, div, name)
|
125
|
-
div.p **{ class: "SourceTitle",
|
119
|
+
div.p **{ class: "SourceTitle", style: "text-align:center;" } do |p|
|
126
120
|
name.children.each { |n| parse(n, p) }
|
127
121
|
end
|
128
122
|
end
|
129
123
|
|
130
124
|
def admonition_name_parse(_node, div, name)
|
131
|
-
div.p **{ class: "AdmonitionTitle",
|
125
|
+
div.p **{ class: "AdmonitionTitle", style: "text-align:center;" } do |p|
|
132
126
|
name.children.each { |n| parse(n, p) }
|
133
127
|
end
|
134
128
|
end
|
@@ -152,10 +146,14 @@ module IsoDoc::Function
|
|
152
146
|
def annotation_parse(node, out)
|
153
147
|
@sourcecode = false
|
154
148
|
@annotation = true
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
149
|
+
node.at("./preceding-sibling::*[local-name() = 'annotation']") or
|
150
|
+
out << "<br/>"
|
151
|
+
out << "<br/>"
|
152
|
+
#out.span **{ class: "zzMoveToFollowing" } do |s|
|
153
|
+
out << "<#{node.at(ns("//callout[@target='#{node['id']}']")).text}> "
|
154
|
+
#end
|
155
|
+
#node.children.each { |n| parse(n, out) }
|
156
|
+
out << node&.children&.text&.strip
|
159
157
|
@annotation = false
|
160
158
|
end
|
161
159
|
|
@@ -193,10 +191,8 @@ module IsoDoc::Function
|
|
193
191
|
div.p do |p|
|
194
192
|
parse(node.at(ns("./stem")), div)
|
195
193
|
lbl = anchor(node['id'], :label, false)
|
196
|
-
#unless get_anchors[node['id']][:label].nil?
|
197
194
|
unless lbl.nil?
|
198
195
|
insert_tab(div, 1)
|
199
|
-
#div << "(#{get_anchors[node['id']][:label]})"
|
200
196
|
div << "(#{lbl})"
|
201
197
|
end
|
202
198
|
end
|
@@ -222,8 +218,8 @@ module IsoDoc::Function
|
|
222
218
|
def para_attrs(node)
|
223
219
|
attrs = { class: para_class(node), id: node["id"] }
|
224
220
|
unless node["align"].nil?
|
225
|
-
attrs[:align] = node["align"] unless node["align"] == "justify"
|
226
|
-
attrs[:style] = "text-align:#{node['align']}"
|
221
|
+
#attrs[:align] = node["align"] unless node["align"] == "justify"
|
222
|
+
attrs[:style] = "text-align:#{node['align']};"
|
227
223
|
end
|
228
224
|
attrs
|
229
225
|
end
|
@@ -261,7 +257,7 @@ module IsoDoc::Function
|
|
261
257
|
|
262
258
|
def image_title_parse(out, caption)
|
263
259
|
unless caption.nil?
|
264
|
-
out.p **{ class: "FigureTitle",
|
260
|
+
out.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
|
265
261
|
p.b { |b| b << caption.to_s }
|
266
262
|
end
|
267
263
|
end
|
@@ -275,59 +271,5 @@ module IsoDoc::Function
|
|
275
271
|
out.img **attr_code(attrs)
|
276
272
|
image_title_parse(out, caption)
|
277
273
|
end
|
278
|
-
|
279
|
-
def recommendation_name(node, out, type)
|
280
|
-
label = node.at(ns("./label"))
|
281
|
-
title = node.at(ns("./title"))
|
282
|
-
out.p **{ class: "AdmonitionTitle" } do |b|
|
283
|
-
lbl = anchor(node['id'], :label, false)
|
284
|
-
b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
|
285
|
-
if label || title
|
286
|
-
b.br
|
287
|
-
label and label.children.each { |n| parse(n,b) }
|
288
|
-
b << "#{clausedelim} " if label && title
|
289
|
-
title and title.children.each { |n| parse(n,b) }
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def recommendation_parse(node, out)
|
295
|
-
out.div **{ class: "recommend" } do |t|
|
296
|
-
recommendation_name(node, t, @recommendation_lbl)
|
297
|
-
node.children.each do |n|
|
298
|
-
parse(n, t) unless %w(label title).include? n.name
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def requirement_parse(node, out)
|
304
|
-
out.div **{ class: "require" } do |t|
|
305
|
-
recommendation_name(node, t, @requirement_lbl)
|
306
|
-
node.children.each do |n|
|
307
|
-
parse(n, t) unless %w(label title).include? n.name
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
def permission_parse(node, out)
|
313
|
-
out.div **{ class: "permission" } do |t|
|
314
|
-
recommendation_name(node, t, @permission_lbl)
|
315
|
-
node.children.each do |n|
|
316
|
-
parse(n, t) unless %w(label title).include? n.name
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
def requirement_component_parse(node, out)
|
322
|
-
return if node["exclude"] == "true"
|
323
|
-
out.div **{ class: "requirement-" + node.name } do |div|
|
324
|
-
node.children.each do |n|
|
325
|
-
parse(n, div)
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
def requirement_skip_parse(node, out)
|
331
|
-
end
|
332
274
|
end
|
333
275
|
end
|
@@ -8,21 +8,55 @@ module IsoDoc::Function
|
|
8
8
|
x.gsub(/All Parts/i, @all_parts_lbl.downcase)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
# TODO generate formatted ref if not present
|
12
|
+
def nonstd_bibitem(list, b, ordinal, bibliography)
|
13
|
+
list.p **attr_code(iso_bibitem_entry_attrs(b, bibliography)) do |r|
|
14
|
+
id = bibitem_ref_code(b)
|
15
|
+
if bibliography
|
16
|
+
ref_entry_code(r, ordinal, id)
|
17
|
+
else
|
18
|
+
r << "#{id}, "
|
19
|
+
end
|
20
|
+
reference_format(b, r)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def std_bibitem_entry(list, b, ordinal, biblio)
|
25
|
+
list.p **attr_code(iso_bibitem_entry_attrs(b, biblio)) do |ref|
|
26
|
+
prefix_bracketed_ref(ref, ordinal) if biblio
|
27
|
+
ref << bibitem_ref_code(b)
|
28
|
+
date_note_process(b, ref)
|
29
|
+
ref << ", "
|
30
|
+
reference_format(b, ref)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# if t is just a number, only use that ([1] Non-Standard)
|
35
|
+
# else, use both ordinal, as prefix, and t
|
36
|
+
def ref_entry_code(r, ordinal, t)
|
37
|
+
if /^\d+$/.match(t)
|
38
|
+
prefix_bracketed_ref(r, t)
|
39
|
+
else
|
40
|
+
prefix_bracketed_ref(r, ordinal)
|
41
|
+
r << "#{t}, "
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def bibitem_ref_code(b)
|
46
|
+
id = b.at(ns("./docidentifier[not(@type = 'DOI' or @type = 'metanorma')]"))
|
47
|
+
id ||= b.at(ns("./docidentifier[not(@type = 'DOI')]"))
|
48
|
+
id ||= b.at(ns("./docidentifier")) or return "(NO ID)"
|
49
|
+
docid_prefix(id["type"], id.text.sub(/^\[/, "").sub(/\]$/, ""))
|
16
50
|
end
|
17
51
|
|
18
52
|
def docid_prefix(prefix, docid)
|
19
|
-
docid = "#{prefix} #{docid}"
|
20
|
-
docid
|
53
|
+
docid = "#{prefix} #{docid}" if prefix && !omit_docid_prefix(prefix)
|
54
|
+
docid_l10n(docid)
|
21
55
|
end
|
22
56
|
|
23
57
|
def omit_docid_prefix(prefix)
|
24
58
|
return true if prefix.nil? || prefix.empty?
|
25
|
-
return ["ISO", "IEC"].include? prefix
|
59
|
+
return ["ISO", "IEC", "metanorma"].include? prefix
|
26
60
|
end
|
27
61
|
|
28
62
|
def date_note_process(b, ref)
|
@@ -56,27 +90,6 @@ module IsoDoc::Function
|
|
56
90
|
insert_tab(ref, 1)
|
57
91
|
end
|
58
92
|
|
59
|
-
def iso_bibitem_entry(list, b, ordinal, biblio)
|
60
|
-
return if implicit_reference(b)
|
61
|
-
list.p **attr_code(iso_bibitem_entry_attrs(b, biblio)) do |ref|
|
62
|
-
prefix_bracketed_ref(ref, ordinal) if biblio
|
63
|
-
ref << iso_bibitem_ref_code(b)
|
64
|
-
date_note_process(b, ref)
|
65
|
-
ref << ", "
|
66
|
-
ref.i { |i| i << " #{iso_title(b).text}" }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def ref_entry_code(r, ordinal, prefix, t)
|
71
|
-
t = docid_prefix(prefix, t)
|
72
|
-
if /^\d+$/.match(t) && !prefix
|
73
|
-
prefix_bracketed_ref(r, t)
|
74
|
-
else
|
75
|
-
prefix_bracketed_ref(r, ordinal)
|
76
|
-
r << "#{t}, "
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
93
|
def reference_format(b, r)
|
81
94
|
if ftitle = b.at(ns("./formattedref"))
|
82
95
|
ftitle&.children&.each { |n| parse(n, r) }
|
@@ -88,46 +101,29 @@ module IsoDoc::Function
|
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
91
|
-
# TODO generate formatted ref if not present
|
92
|
-
def noniso_bibitem(list, b, ordinal, bibliography)
|
93
|
-
list.p **attr_code(iso_bibitem_entry_attrs(b, bibliography)) do |r|
|
94
|
-
if bibliography
|
95
|
-
id = docid_l10n(b.at(ns("./docidentifier")).text.gsub(/[\[\]]/, ""))
|
96
|
-
prefix = b&.at(ns("./docidentifier/@type"))&.text
|
97
|
-
ref_entry_code(r, ordinal, prefix, id)
|
98
|
-
else
|
99
|
-
r << "#{iso_bibitem_ref_code(b)}, "
|
100
|
-
end
|
101
|
-
reference_format(b, r)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
104
|
ISO_PUBLISHER_XPATH =
|
106
105
|
"./contributor[xmlns:role/@type = 'publisher']/"\
|
107
106
|
"organization[abbreviation = 'ISO' or xmlns:abbreviation = 'IEC' or "\
|
108
107
|
"xmlns:name = 'International Organization for Standardization' or "\
|
109
108
|
"xmlns:name = 'International Electrotechnical Commission']".freeze
|
110
109
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
non_iso_bibitem << x
|
117
|
-
else
|
118
|
-
iso_bibitem << x
|
119
|
-
end
|
110
|
+
def is_standard(b)
|
111
|
+
ret = false
|
112
|
+
b.xpath(ns("./docidentifier")).each do |id|
|
113
|
+
next if id["type"].nil? || %w(metanorma DOI).include?(id["type"])
|
114
|
+
ret = true
|
120
115
|
end
|
121
|
-
|
116
|
+
ret
|
122
117
|
end
|
123
118
|
|
124
119
|
def biblio_list(f, div, bibliography)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
120
|
+
f.xpath(ns("./bibitem")).each_with_index do |b, i|
|
121
|
+
next if implicit_reference(b)
|
122
|
+
if(is_standard(b))
|
123
|
+
std_bibitem_entry(div, b, i + 1, bibliography)
|
124
|
+
else
|
125
|
+
nonstd_bibitem(div, b, i + 1, bibliography)
|
126
|
+
end
|
131
127
|
end
|
132
128
|
end
|
133
129
|
|
@@ -135,10 +131,7 @@ module IsoDoc::Function
|
|
135
131
|
refs = f.elements.select do |e|
|
136
132
|
["reference", "bibitem"].include? e.name
|
137
133
|
end
|
138
|
-
pref =
|
139
|
-
else
|
140
|
-
@norm_with_refs_pref
|
141
|
-
end
|
134
|
+
pref = refs.empty? ? @norm_empty_pref : @norm_with_refs_pref
|
142
135
|
div.p pref
|
143
136
|
end
|
144
137
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module IsoDoc::Function
|
2
|
+
module Blocks
|
3
|
+
def recommendation_labels(node)
|
4
|
+
[node.at(ns("./label")), node.at(ns("./title")),
|
5
|
+
anchor(node['id'], :label, false)]
|
6
|
+
end
|
7
|
+
|
8
|
+
def recommendation_name(node, out, type)
|
9
|
+
label, title, lbl = recommendation_labels(node)
|
10
|
+
#label = node.at(ns("./label"))
|
11
|
+
#title = node.at(ns("./title"))
|
12
|
+
out.p **{ class: "AdmonitionTitle" } do |b|
|
13
|
+
#lbl = anchor(node['id'], :label, false)
|
14
|
+
b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
|
15
|
+
if label || title
|
16
|
+
b.br
|
17
|
+
label and label.children.each { |n| parse(n,b) }
|
18
|
+
b << "#{clausedelim} " if label && title
|
19
|
+
title and title.children.each { |n| parse(n,b) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def recommendation_attributes1(node)
|
25
|
+
out = []
|
26
|
+
oblig = node["obligation"] and out << "Obligation: #{oblig}"
|
27
|
+
subj = node&.at(ns("./subject"))&.text and out << "Subject: #{subj}"
|
28
|
+
node.xpath(ns("./classification")).each do |c|
|
29
|
+
tag = c.at(ns("./tag"))
|
30
|
+
value = c.at(ns("./value"))
|
31
|
+
tag && value or next
|
32
|
+
out << "#{tag.text.capitalize}: #{value.text}"
|
33
|
+
end
|
34
|
+
out
|
35
|
+
end
|
36
|
+
|
37
|
+
def recommendation_attributes(node, out)
|
38
|
+
ret = recommendation_attributes1(node)
|
39
|
+
return if ret.empty?
|
40
|
+
out.p do |p|
|
41
|
+
p.i do |i|
|
42
|
+
i << ret.join("<br/>")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def recommendation_parse(node, out)
|
48
|
+
out.div **{ class: "recommend" } do |t|
|
49
|
+
recommendation_name(node, t, @recommendation_lbl)
|
50
|
+
recommendation_attributes(node, out)
|
51
|
+
node.children.each do |n|
|
52
|
+
parse(n, t) unless %w(label title).include? n.name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def requirement_parse(node, out)
|
58
|
+
out.div **{ class: "require" } do |t|
|
59
|
+
recommendation_name(node, t, @requirement_lbl)
|
60
|
+
recommendation_attributes(node, out)
|
61
|
+
node.children.each do |n|
|
62
|
+
parse(n, t) unless %w(label title).include? n.name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def permission_parse(node, out)
|
68
|
+
out.div **{ class: "permission" } do |t|
|
69
|
+
recommendation_name(node, t, @permission_lbl)
|
70
|
+
recommendation_attributes(node, out)
|
71
|
+
node.children.each do |n|
|
72
|
+
parse(n, t) unless %w(label title).include? n.name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def requirement_component_parse(node, out)
|
78
|
+
return if node["exclude"] == "true"
|
79
|
+
out.div **{ class: "requirement-" + node.name } do |div|
|
80
|
+
node.children.each do |n|
|
81
|
+
parse(n, div)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def requirement_skip_parse(node, out)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|