bri 0.5.0 → 1.0.0.pre.beta1

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog +0 -2
  3. data/TODO +2 -3
  4. data/bin/bri +21 -8
  5. data/lib/bri/mall.rb +12 -17
  6. data/lib/bri/match/base.rb +2 -7
  7. data/lib/bri/match/class.rb +6 -3
  8. data/lib/bri/match/method.rb +3 -3
  9. data/lib/bri/renderer/blank_line.rb +9 -0
  10. data/lib/bri/renderer/default.rb +27 -0
  11. data/lib/bri/renderer/document.rb +11 -0
  12. data/lib/bri/renderer/heading.rb +9 -0
  13. data/lib/bri/renderer/list/base.rb +18 -0
  14. data/lib/bri/renderer/list/bullet.rb +15 -0
  15. data/lib/bri/renderer/list/labeled.rb +15 -0
  16. data/lib/bri/renderer/list/lower_lettered.rb +18 -0
  17. data/lib/bri/renderer/list/note.rb +15 -0
  18. data/lib/bri/renderer/list/numbered.rb +18 -0
  19. data/lib/bri/renderer/list/upper_lettered.rb +18 -0
  20. data/lib/bri/renderer/list.rb +24 -0
  21. data/lib/bri/renderer/list_item.rb +24 -0
  22. data/lib/bri/renderer/paragraph.rb +11 -0
  23. data/lib/bri/renderer/result.rb +73 -0
  24. data/lib/bri/renderer/rule.rb +9 -0
  25. data/lib/bri/renderer/verbatim.rb +14 -0
  26. data/lib/bri/renderer.rb +28 -188
  27. data/lib/bri/search/class.rb +3 -1
  28. data/lib/bri/search/method.rb +3 -3
  29. data/lib/bri/templates.rb +7 -38
  30. data/lib/bri/text_formatting_utils.rb +92 -0
  31. data/lib/bri.rb +18 -15
  32. metadata +27 -17
  33. data/spec/bri_dummy_spec_class.rb +0 -132
  34. data/spec/lib/bri/mall_spec.rb +0 -38
  35. data/spec/lib/bri/match/class_spec.rb +0 -125
  36. data/spec/lib/bri/match/method_spec.rb +0 -116
  37. data/spec/lib/bri/matcher_spec.rb +0 -70
  38. data/spec/lib/bri/renderer_spec.rb +0 -338
  39. data/spec/lib/bri/search/class_method_spec.rb +0 -173
  40. data/spec/lib/bri/search/class_spec.rb +0 -66
  41. data/spec/lib/bri/search/instance_method_spec.rb +0 -174
  42. data/spec/lib/bri/search/method_spec.rb +0 -41
  43. data/spec/spec_helper.rb +0 -22
@@ -1,338 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Bri::Renderer do
4
- def render_description_for_method( method_name )
5
- search_instance = Bri::Search::InstanceMethod.new( "BriDummySpecClass##{method_name}_rendering_test_method" )
6
- search_instance.search( :fully_qualified )
7
- search_instance.matches.first.to_s
8
- end
9
-
10
- let( :green ) { Regexp.escape( Term::ANSIColor::green ) }
11
- let( :yellow ) { Regexp.escape( Term::ANSIColor::yellow ) }
12
- let( :cyan ) { Regexp.escape( Term::ANSIColor::cyan ) }
13
- let( :bold ) { Regexp.escape( Term::ANSIColor::bold ) }
14
- let( :italic ) { Regexp.escape( Term::ANSIColor::italic ) }
15
- let( :underline ) { Regexp.escape( Term::ANSIColor::underline ) }
16
- let( :reset ) { Regexp.escape( Term::ANSIColor::reset ) }
17
-
18
- describe "headers" do
19
- context " for level one headlines" do
20
- subject { render_description_for_method( "basic_headline_and_paragraph" ) }
21
-
22
- it "should be marked in green" do
23
- subject.should =~ /#{green}This is a headline#{reset}\n/
24
- end
25
- end
26
-
27
- context "for level two headlines" do
28
- subject { render_description_for_method( "level_two_headline_and_line_wrapping" ) }
29
-
30
- it "should be marked in green" do
31
- subject.should =~ /#{green}This is a level two headline#{reset}\n/
32
- end
33
- end
34
- end
35
-
36
- describe "paragraphs" do
37
- subject { render_description_for_method( "basic_headline_and_paragraph" ) }
38
-
39
- it "should be indented by two spaces" do
40
- subject.should =~ /^ Followed by some introduction text.\s*\n/
41
- end
42
-
43
- context "containing long rows" do
44
- subject { render_description_for_method( "level_two_headline_and_line_wrapping" ) }
45
-
46
- it "should be wrapped" do
47
- subject.should =~ /\n This is a paragraph with a really really really really really really\s*\n really really really really long line that needs to be wrapped\.\n/
48
- end
49
- end
50
- end
51
-
52
- describe "horizontal rules" do
53
- subject { render_description_for_method( "horizontal_rule" ) }
54
-
55
- it "should be rendered as an indented row of dashes" do
56
- rule = "-" * Bri.width
57
- subject.should =~ /\n #{rule}\n/
58
- end
59
- end
60
-
61
- describe "bulleted lists with *" do
62
- subject { render_description_for_method( "bulleted_list" ) }
63
- it "should indent the list with one space" do
64
- subject.should =~ /\n . First item in a bulleted list/
65
- end
66
-
67
- it "should prefix each list item with a '*' bullet" do
68
- subject.should =~ /\* First item in a bulleted list/
69
- subject.should =~ /\* Second item in a bulleted list/
70
- subject.should =~ /\* Ending a bulleted list/
71
- end
72
-
73
- it "should wrap long lines" do
74
- subject.should =~ /\n \* Ending a bulleted list with a really really really really really \n really really really long line that needs to be wrapped\n/
75
- end
76
-
77
- it "should start second lines of a list item with the same left alignment as the first list items content" do
78
- subject.should =~ /\n \* First item in a bulleted list(?:\s*?)\n With a second line\n/
79
- end
80
-
81
- context "contained verbatim text" do
82
- subject { render_description_for_method( "list_containing_verbatim_text" ) }
83
-
84
- it "should correctly display verbatim text" do
85
- subject.should =~ /\n Containing verbatim text\n/
86
- end
87
- end
88
-
89
- context "a nested bulleted list" do
90
- it "should indent the second level with five spaces" do
91
- subject.should =~ /\n . First item of a nested bulleted list/
92
- subject.should =~ /\n . Second item of a nested bulleted list/
93
- end
94
- end
95
-
96
- context "a nested numbered list" do
97
- subject { render_description_for_method( "mixed_list" ) }
98
- it "should indent the second level with four spaces" do
99
- subject.should =~ /\n \d\. And numbers in a sublist\n/
100
- end
101
- end
102
- end
103
-
104
- describe "bulleted lists with -" do
105
- subject { render_description_for_method "second_bulleted_list" }
106
- it "should indent the list with one space" do
107
- subject.should =~ /\n . A second bulleted list/
108
- end
109
-
110
- it "should prefix each list item with a '*' bullet" do
111
- subject.should =~ /\* A second bulleted list/
112
- subject.should =~ /\* Second item in second bulleted list/
113
- subject.should =~ /\* Ending the second bulleted list/
114
- end
115
-
116
- it "should indent the second level with four spaces" do
117
- subject.should =~ /\n . Nested bulleted list/
118
- subject.should =~ /\n . Second nested bulleted list item/
119
- end
120
- end
121
-
122
- describe "numbered lists" do
123
- subject { render_description_for_method "numbered_list" }
124
-
125
- it "should not indent the list items" do
126
- subject.should =~ /\n\d\. First numbered list item/
127
- end
128
-
129
- it "should prefix each list item with a consecutive number" do
130
- subject.should =~ /1\. First numbered list item/
131
- subject.should =~ /2\. Second numbered list/
132
- subject.should =~ /3\. Ending the main numbered list item/
133
- end
134
-
135
- context "nested numbered lists" do
136
- it "should indent the second level with four spaces" do
137
- subject.should =~ /\n \d\. Nested numbered list item/
138
- subject.should =~ /\n \d\. Second nested numbered list item/
139
- end
140
-
141
- it "should restart the numbering for nested lists" do
142
- subject.should =~ /1\. Nested numbered list item/
143
- subject.should =~ /2\. Second nested numbered list item/
144
- end
145
- end
146
-
147
- context "nested bulleted lists" do
148
- subject { render_description_for_method "second_mixed_list" }
149
- it "should indent the second level with five spaces" do
150
- subject.should =~ /\n . Nested bulleted list/
151
- end
152
-
153
- it "should prefix each nested list item with a '*' bullet" do
154
- subject.should =~ /\* Nested bulleted list/
155
- end
156
- end
157
- end
158
-
159
- describe "lettered lists" do
160
- subject { render_description_for_method "lettered_list" }
161
-
162
- it "should not indent the list items" do
163
- subject.should =~ /\n.\. Some goes for lettered lists/
164
- end
165
-
166
- it "should prefix each list item with a consecutive letter" do
167
- subject.should =~ /a\. Some goes for lettered lists/
168
- subject.should =~ /b\. Second item in a lettered list/
169
- subject.should =~ /c\. Ending the main lettered list item/
170
- end
171
-
172
- context "nested lettered lists" do
173
- it "should indent the second level with four spaces" do
174
- subject.should =~ /\n .\. And a nested lettered list item/
175
- end
176
-
177
- it "should restart the lettering for nested lists" do
178
- subject.should =~ /a\. And a nested lettered list item/
179
- subject.should =~ /b\. Second nested lettered list item/
180
- end
181
- end
182
- end
183
-
184
- describe "labeled lists" do
185
- subject { render_description_for_method "labeled_list" }
186
-
187
- context "with plain labels" do
188
- it "should indent the list with two spaces" do
189
- subject.should =~ /\n \w+: And this is the list item body/
190
- end
191
-
192
- it "should prefix each list item with its note" do
193
- subject.should =~ /First: And this is the list item body/
194
- subject.should =~ /Second: Another labled list item/
195
- end
196
- end
197
-
198
- context "with aligned labels" do
199
- subject { render_description_for_method "lined_up_labeled_list" }
200
-
201
- it "should intent the list with two spaces" do
202
- subject.should =~ /\n \w+:\s+With some text\./
203
- end
204
-
205
- it "should prefix each list item with its note" do
206
- subject.should =~ /First:\s+With some text\./
207
- subject.should =~ /Secondarily:\s+Lets see if this lines up\./
208
- end
209
-
210
- it "should have the list item bodies left aligned to the same position" do
211
- subject.should =~ /First: With some text\./
212
- subject.should =~ /Secondarily: Lets see if this lines up\./
213
- end
214
- end
215
- end
216
-
217
- describe "text stylings" do
218
- context "for bold text" do
219
- it "should mark *bold* text with an ANSI bold code" do
220
- text = render_description_for_method( "simple_styling" )
221
- text.should =~ /#{bold}bold#{reset},/
222
- end
223
-
224
- it "should mark <b>bold</b> text with an ANSI bold code" do
225
- text = render_description_for_method( "html_styling" )
226
- text.should =~ /#{bold}Bold#{reset},/
227
- end
228
-
229
- it "should not mark escaped \<b>bold\</b> text" do
230
- text = render_description_for_method( "escaped_styling" )
231
- text.should =~ /<b>Not bold<\/b>,/
232
- end
233
- end
234
-
235
- context "for emphasized text" do
236
- it "should mark _emphasized_ text with an ANSI yellow code" do
237
- text = render_description_for_method( "simple_styling" )
238
- text.should =~ /, #{yellow}emphasized#{reset} and/
239
- end
240
-
241
- it "should mark <em>emphasized</em> text with an ANSI yellow code" do
242
- text = render_description_for_method( "html_styling" )
243
- text.should =~ /, #{yellow}emphasized#{reset},/
244
- end
245
-
246
- it "should mark <i>emphasized</i> text with an ANSI yellow code" do
247
- text = render_description_for_method( "html_styling" )
248
- text.should =~ /, #{yellow}also emphasized#{reset}/
249
- end
250
-
251
- it "should not mark escaped \<em>emphasized\</em> text" do
252
- text = render_description_for_method( "escaped_styling" )
253
- text.should =~ /<em>not emphasized<\/em>/
254
- end
255
- end
256
-
257
- context "for code" do
258
- it "should mark +code+ with an ANSI cyan code" do
259
- text = render_description_for_method( "simple_styling" )
260
- text.should =~ /and #{cyan}monospaced#{reset}/
261
- end
262
-
263
- it "should mark <tt>code</tt> with an ANSI cyan code" do
264
- text = render_description_for_method( "html_styling" )
265
- text.should =~ /#{cyan}monospaced tt#{reset}/
266
- end
267
-
268
- it "should mark <code>code</code> with an ANSI cyan code" do
269
- text = render_description_for_method( "html_styling" )
270
- text.should =~ /#{cyan}monospaced code#{reset}/
271
- end
272
- end
273
- end
274
-
275
- describe "links" do
276
- context "raw links" do
277
- subject { render_description_for_method "raw_link" }
278
-
279
- it "should underline raw http links" do
280
- subject.should =~ /#{underline}http:\/\/www.google.com#{reset}/
281
- end
282
-
283
- it "should underline raw mailto links" do
284
- subject.should =~ /#{underline}mailto:spamidyspam@spam.com#{reset}/
285
- end
286
-
287
- it "should underline raw ftp links" do
288
- subject.should =~ /#{underline}ftp:\/\/warez.teuto.de#{reset}/
289
- end
290
-
291
- it "should underline plain www links" do
292
- subject.should =~ /#{underline}www.test.com#{reset}/
293
- end
294
-
295
- it "should underline local file links" do
296
- subject.should =~ /#{underline}\/etc\/fstab#{reset}/
297
- end
298
- end
299
-
300
- context "labeled links" do
301
- subject { render_description_for_method "labeled_link" }
302
-
303
- context "with single word labels" do
304
- it "should show the link underlined after the label in brackets" do
305
- subject.should =~ /Labled links SingleWordLabel \(#{underline}http:\/\/duckduckgo.com#{reset}\)/
306
- end
307
- end
308
-
309
- context "with multi word labels" do
310
- it "should show the link underlined after the label in brackets and remove the rdoc label curly braces" do
311
- subject.should =~ /Multi\s+Word\s+Labels\s+\(#{underline}http:\/\/www.github.com#{reset}\)/m
312
- end
313
- end
314
- end
315
- end
316
-
317
- describe "conversion characters" do
318
- subject { render_description_for_method "conversion_character" }
319
-
320
- it "should leave -- as is" do
321
- subject.should =~ /this: -- or/
322
- end
323
-
324
- it "should leave --- as is" do
325
- subject.should =~ /or --- should/
326
- end
327
-
328
- it "should leave (c) as is" do
329
- subject.should =~ /Copyright: \(c\)/
330
- end
331
-
332
- it "should leave (r) as is" do
333
- subject.should =~ /registered trademark \(r\)/
334
- end
335
- end
336
-
337
-
338
- end
@@ -1,173 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Bri::Search::ClassMethod do
4
- context "the searches" do
5
- let( :paragraph ) { RDoc::Markup::Paragraph.new( "Foo Description" ) }
6
- let( :document ) { double( RDoc::Markup::Document, :parts => [ paragraph ] ) }
7
- let( :comment ) { double( RDoc::Comment, :instance_variable_get => document ) }
8
- let( :rdoc_method ) { double( RDoc::AnyMethod, :full_name => "Foo",
9
- :arglists => "",
10
- :comment => comment ) }
11
- before( :each ) do
12
- store_one = double( RDoc::RI::Store, :load_cache => true,
13
- :load_class => true,
14
- :load_method => rdoc_method,
15
- :friendly_path => "ruby core",
16
- :modules => %w{ ClassThree },
17
- :class_methods => { "ClassThree" => [ "method" ] } )
18
- store_two = double( RDoc::RI::Store, :load_cache => true,
19
- :load_class => true,
20
- :load_method => rdoc_method,
21
- :friendly_path => "ruby core",
22
- :modules => %w{ ClassOne ClassTwo },
23
- :class_methods => { "ClassOne" => [ "method" ],
24
- "ClassTwo" => [ "method", "my_other_method" ] } )
25
- allow(Bri::Mall.instance).to receive( :stores ).and_return( [ store_one, store_two ] )
26
- allow(Bri::Match::Class).to receive( :new ).and_return( double( Bri::Match::Class ) )
27
- end
28
-
29
- describe "a fully qualified search" do
30
- context "if there are no matching methods in any store" do
31
- subject { Bri::Search::ClassMethod.new( "I::Dont::Exist.go_away" ) }
32
- it "should have no matches" do
33
- subject.search( :fully_qualified )
34
- subject.matches.should == []
35
- end
36
- end
37
-
38
- context "if there are matching methods in the stores" do
39
- subject { Bri::Search::ClassMethod.new( "ClassOne.method" ) }
40
- it "should have a match for each method" do
41
- subject.search( :fully_qualified )
42
- subject.matches.size.should == 1
43
- end
44
- end
45
- end
46
-
47
- describe "a partially qualified search" do
48
- context "if there are no matching methods in any store" do
49
- subject { Bri::Search::ClassMethod.new( ".go_away" ) }
50
- it "should have no matches" do
51
- subject.search( :partially_qualified )
52
- subject.matches.should == []
53
- end
54
- end
55
-
56
- context "if there are matching methods in the stores" do
57
- subject { Bri::Search::ClassMethod.new( ".method" ) }
58
- it "should have a match for each method" do
59
- subject.search( :partially_qualified )
60
- subject.matches.size.should == 3
61
- end
62
- end
63
- end
64
-
65
- describe "an unqualified search" do
66
- context "if there are no matching methods in any store" do
67
- subject { Bri::Search::ClassMethod.new( "go_away" ) }
68
- it "should have no matches" do
69
- subject.search( :unqualified )
70
- subject.matches.should == []
71
- end
72
- end
73
-
74
- context "if there are matching methods in the stores" do
75
- context "if there are matching methods, where the match starts at the beginning of the method name" do
76
- subject { Bri::Search::ClassMethod.new( "method" ) }
77
- it "should have a match for each method" do
78
- subject.search( :unqualified )
79
- subject.matches.size.should == 3
80
- end
81
- end
82
-
83
- context "if there are matching methods, but none where the match starts at the beginning of the method name" do
84
- subject { Bri::Search::ClassMethod.new( "other" ) }
85
- it "should have a match for each method" do
86
- subject.search( :unqualified )
87
- subject.matches.size.should == 1
88
- end
89
- end
90
- end
91
- end
92
- end
93
-
94
- context "real searches going through rdoc" do
95
- context "a fully qualified search" do
96
- context "with no matching methods" do
97
- it "should have no matches" do
98
- search_instance = Bri::Search::ClassMethod.new( "BriDummySpecClass.i_dont_exist" )
99
- search_instance.search( :fully_qualified )
100
- search_instance.matches.should be_empty
101
- end
102
- end
103
-
104
- context "with a matching method" do
105
- it "should have a match" do
106
- search_instance = Bri::Search::ClassMethod.new( "BriDummySpecClass.bri_dummy_spec_singleton_method" )
107
- search_instance.search( :fully_qualified )
108
- search_instance.matches.should_not be_empty
109
- search_instance.matches.first.full_name.should == "BriDummySpecClass::bri_dummy_spec_singleton_method"
110
- end
111
- end
112
- end
113
-
114
- context "a partially qualified search" do
115
- context "with no matching methods" do
116
- it "should have no matches" do
117
- search_instance = Bri::Search::ClassMethod.new( ".i_dont_exist" )
118
- search_instance.search( :partially_qualified )
119
- search_instance.matches.should be_empty
120
- end
121
- end
122
-
123
- context "with one matching method" do
124
- it "should have one match" do
125
- search_instance = Bri::Search::ClassMethod.new( ".bri_dummy_spec_singleton_method" )
126
- search_instance.search( :partially_qualified )
127
- search_instance.matches.should_not be_empty
128
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClass::bri_dummy_spec_singleton_method" }.should be(true)
129
- end
130
- end
131
-
132
- context "with multiple matching methods" do
133
- it "should have all matches" do
134
- search_instance = Bri::Search::ClassMethod.new( ".bri_dummy_spec_second_singleton_method" )
135
- search_instance.search( :partially_qualified )
136
- search_instance.matches.should_not be_empty
137
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClass::bri_dummy_spec_second_singleton_method" }.should be(true)
138
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClassTwo::bri_dummy_spec_second_singleton_method" }.should be(true)
139
- end
140
- end
141
- end
142
-
143
- context "an unqualified search" do
144
- context "with no matching methods" do
145
- it "should have no matches" do
146
- search_instance = Bri::Search::ClassMethod.new( "i_dont_exist_go_away" )
147
- search_instance.search( :unqualified )
148
- search_instance.matches.should be_empty
149
- end
150
- end
151
-
152
- context "with one matching method" do
153
- it "should have one match" do
154
- search_instance = Bri::Search::ClassMethod.new( "bri_dummy_spec_singleton_method" )
155
- search_instance.search( :unqualified )
156
- search_instance.matches.should_not be_empty
157
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClass::bri_dummy_spec_singleton_method" }.should be(true)
158
- end
159
- end
160
-
161
- context "with multiple matching methods" do
162
- it "should have all matches" do
163
- search_instance = Bri::Search::ClassMethod.new( "bri_dummy_spec" )
164
- search_instance.search( :unqualified )
165
- search_instance.matches.should_not be_empty
166
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClass::bri_dummy_spec_singleton_method" }.should be(true)
167
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClass::bri_dummy_spec_second_singleton_method" }.should be(true)
168
- search_instance.matches.any? { |match| match.full_name == "BriDummySpecClassTwo::bri_dummy_spec_second_singleton_method" }.should be(true)
169
- end
170
- end
171
- end
172
- end
173
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Bri::Search::Class do
4
- describe "#initialize" do
5
- context "for an empty search" do
6
- subject { Bri::Search::Class.new( "term" ) }
7
- its( :term ) { should == "term" }
8
- its( :matches ) { should be_empty }
9
- end
10
- end
11
-
12
-
13
- describe "#search" do
14
- context "basic functionality" do
15
- before( :each ) do
16
- store_one = double( RDoc::Store, :load_cache => true,
17
- :load_class => true,
18
- :friendly_path => "ruby core",
19
- :module_names => %w{ ClassThree } )
20
- store_two = double( RDoc::Store, :load_cache => true,
21
- :load_class => true,
22
- :friendly_path => "ruby core",
23
- :module_names => %w{ ClassOne ClassTwo } )
24
- allow(Bri::Mall.instance).to receive( :stores ).and_return( [ store_one, store_two ] )
25
- allow(Bri::Match::Class).to receive( :new ).and_return( double( Bri::Match::Class ) )
26
- end
27
-
28
- context "if there are no matching modules in any store" do
29
- subject { Bri::Search::Class.new( "I::Dont::Exist" ) }
30
- it "should have no matches" do
31
- subject.search
32
- subject.matches.should == []
33
- end
34
- end
35
-
36
- context "if there is a matching module in the stores" do
37
- subject { Bri::Search::Class.new( "ClassOne" ) }
38
- it "should have a match for each name" do
39
- subject.search
40
- subject.matches.size.should == 1
41
- end
42
- end
43
- end
44
-
45
- context "for the type :fully_qualified" do
46
- context "when searching for the class BriDummySpecClass" do
47
- subject { Bri::Search::Class.new( "BriDummySpecClass" ) }
48
-
49
- it "should have matches" do
50
- subject.search
51
- subject.matches.should_not be_empty
52
- subject.matches.any?{ |match| match.name == "BriDummySpecClass < Object" }.should be(true)
53
- end
54
- end
55
-
56
- context "when searching for the class IAmQuiteCertainIDontExist" do
57
- subject { Bri::Search::Class.new( "IAmQuiteCertainIDontExist" ) }
58
-
59
- it "should not have any matches" do
60
- subject.search
61
- subject.matches.any? { |match| match.name == "IAmQuiteCertainIDontExist" }.should be(false)
62
- end
63
- end
64
- end
65
- end
66
- end