playgroundbook 0.6.0 → 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/README.md +3 -45
- data/lib/renderer/chapter_collator.rb +24 -1
- data/lib/renderer/page_parser.rb +24 -2
- data/lib/renderer/page_writer.rb +20 -1
- data/lib/renderer/playgroundbook_renderer.rb +25 -5
- data/lib/version.rb +1 -1
- metadata +2 -46
- data/.gitignore +0 -50
- data/.rspec +0 -2
- data/.rubocop.yml +0 -112
- data/.ruby-version +0 -1
- data/Changelog.md +0 -37
- data/CodeOfConduct.md +0 -50
- data/Community.md +0 -52
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -102
- data/Guardfile +0 -14
- data/Rakefile +0 -8
- data/playgroundbook.gemspec +0 -21
- data/spec/fixtures/Starter.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Manifest.plist +0 -15
- data/spec/fixtures/Starter.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Page1.playgroundpage/Contents.swift +0 -8
- data/spec/fixtures/Starter.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Page1.playgroundpage/Manifest.plist +0 -12
- data/spec/fixtures/Starter.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Page2.playgroundpage/Contents.swift +0 -8
- data/spec/fixtures/Starter.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Page2.playgroundpage/Manifest.plist +0 -12
- data/spec/fixtures/Starter.playgroundbook/Contents/Manifest.plist +0 -20
- data/spec/fixtures/assets/file.jpeg +0 -0
- data/spec/fixtures/book.yml +0 -6
- data/spec/fixtures/test_chapter.playground/Contents.swift +0 -17
- data/spec/fixtures/test_chapter.playground/contents.xcplayground +0 -4
- data/spec/fixtures/wrapper/destination/swift_at_artsy_1.swift +0 -200
- data/spec/fixtures/wrapper/source/Swift-at-Artsy.playground/Contents.swift +0 -199
- data/spec/fixtures/wrapper/source/Swift-at-Artsy.playground/contents.xcplayground +0 -4
- data/spec/fixtures/wrapper/source/swift_at_artsy_1.md +0 -183
- data/spec/linter/chapter_linter_spec.rb +0 -30
- data/spec/linter/chapter_manifest_linter_spec.rb +0 -40
- data/spec/linter/contents_linter_spec.rb +0 -18
- data/spec/linter/cutscene_page_linter_spec.rb +0 -14
- data/spec/linter/cutscene_page_manifest_linter_spec.rb +0 -63
- data/spec/linter/manfiest_linter_spec.rb +0 -71
- data/spec/linter/page_linter_spec.rb +0 -19
- data/spec/linter/page_manifest_linter_spec.rb +0 -43
- data/spec/linter/playgroundbook_lint_spec.rb +0 -38
- data/spec/linter/root_manifest_linter_spec.rb +0 -35
- data/spec/renderer/chapter_collator_spec.rb +0 -70
- data/spec/renderer/contents_manfiest_generator_spec.rb +0 -41
- data/spec/renderer/glossary_generator_spec.rb +0 -54
- data/spec/renderer/page_processor_spec.rb +0 -86
- data/spec/renderer/page_writer_spec.rb +0 -70
- data/spec/renderer/playgroundbook_renderer_spec.rb +0 -122
- data/spec/spec_helper.rb +0 -85
- data/spec/wrapper/markdown_wrapper_spec.rb +0 -90
@@ -1,86 +0,0 @@
|
|
1
|
-
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
-
|
3
|
-
module Playgroundbook
|
4
|
-
describe PageProcessor do
|
5
|
-
let(:page_processor) { PageProcessor.new }
|
6
|
-
|
7
|
-
it "removes newlines before markdown blocks" do
|
8
|
-
page_contents = <<-EOS
|
9
|
-
let a = 6
|
10
|
-
|
11
|
-
/*:
|
12
|
-
Some markdown.
|
13
|
-
*/
|
14
|
-
EOS
|
15
|
-
processed_page_contents = <<-EOS
|
16
|
-
let a = 6
|
17
|
-
/*:
|
18
|
-
Some markdown.
|
19
|
-
*/
|
20
|
-
EOS
|
21
|
-
|
22
|
-
expect(page_processor.strip_extraneous_newlines(page_contents)).to eq(processed_page_contents)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "removes newlines after markdown blocks" do
|
26
|
-
page_contents = <<-EOS
|
27
|
-
/*:
|
28
|
-
Some markdown.
|
29
|
-
*/
|
30
|
-
|
31
|
-
let a = 6
|
32
|
-
EOS
|
33
|
-
processed_page_contents = <<-EOS
|
34
|
-
/*:
|
35
|
-
Some markdown.
|
36
|
-
*/
|
37
|
-
let a = 6
|
38
|
-
EOS
|
39
|
-
|
40
|
-
expect(page_processor.strip_extraneous_newlines(page_contents)).to eq(processed_page_contents)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "removes newlines surrounding single-line markdown blocks" do
|
44
|
-
page_contents = <<-EOS
|
45
|
-
let a = 6
|
46
|
-
|
47
|
-
//: Some markdown.
|
48
|
-
|
49
|
-
let b = a
|
50
|
-
EOS
|
51
|
-
processed_page_contents = <<-EOS
|
52
|
-
let a = 6
|
53
|
-
//: Some markdown.
|
54
|
-
let b = a
|
55
|
-
EOS
|
56
|
-
|
57
|
-
expect(page_processor.strip_extraneous_newlines(page_contents)).to eq(processed_page_contents)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "does not strip newlines from code" do
|
61
|
-
page_contents = <<-EOS
|
62
|
-
let a = 6
|
63
|
-
|
64
|
-
let b = a
|
65
|
-
EOS
|
66
|
-
|
67
|
-
expect(page_processor.strip_extraneous_newlines(page_contents)).to eq(page_contents)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "it does not strip newlines from the markdown" do
|
71
|
-
page_contents = <<-EOS
|
72
|
-
/*:
|
73
|
-
|
74
|
-
# Header
|
75
|
-
|
76
|
-
Some markdown. The following lines are purposefull left blank.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
*/
|
81
|
-
EOS
|
82
|
-
|
83
|
-
expect(page_processor.strip_extraneous_newlines(page_contents)).to eq(page_contents)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
-
|
3
|
-
module Playgroundbook
|
4
|
-
describe PageWriter do
|
5
|
-
include FakeFS::SpecHelpers
|
6
|
-
let(:page_writer) { PageWriter.new(page_processor, test_ui) }
|
7
|
-
let(:page_processor) { double(PageProcessor) }
|
8
|
-
let(:test_ui) { Cork::Board.new(silent: true) }
|
9
|
-
let(:page_name) { "test page name" }
|
10
|
-
let(:page_dir_name) { "test page name.playgroundpage" }
|
11
|
-
let(:page_contents) { "// Some swift goes here." }
|
12
|
-
let(:generated_page_contesnts) { "//#-hidden-code\nimport UIKit\n//#-end-hidden-code\n// Some swift goes here." }
|
13
|
-
|
14
|
-
before do
|
15
|
-
allow(page_processor).to receive(:strip_extraneous_newlines) do |page_contents|
|
16
|
-
# Returns the parameter, unprocessed.
|
17
|
-
page_contents
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with a pre-existing page directory" do
|
22
|
-
before do
|
23
|
-
Dir.mkdir(page_dir_name)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "does not explode" do
|
27
|
-
expect { page_writer.write_page(page_name, page_dir_name, ["UIKit"], page_contents) }.to_not raise_error
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
it "calls the page processor" do
|
32
|
-
expect(page_processor).to receive(:strip_extraneous_newlines)
|
33
|
-
page_writer.write_page(page_name, page_dir_name, ["UIKit"], page_contents)
|
34
|
-
end
|
35
|
-
|
36
|
-
context "as a consequence of writing rendering" do
|
37
|
-
before do
|
38
|
-
page_writer.write_page(page_name, page_dir_name, ["UIKit"], page_contents)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "creates a directory" do
|
42
|
-
expect(Dir.exist?(page_dir_name)).to be_truthy
|
43
|
-
end
|
44
|
-
|
45
|
-
it "writes a manifest" do
|
46
|
-
expect(Dir.exist?(page_dir_name)).to be_truthy
|
47
|
-
end
|
48
|
-
|
49
|
-
it "writes a Contents.swift file" do
|
50
|
-
expect(File.exist?("#{page_dir_name}/Contents.swift")).to be_truthy
|
51
|
-
end
|
52
|
-
|
53
|
-
it "has correct Contents.swift contents" do
|
54
|
-
expect(File.read("#{page_dir_name}/Contents.swift")).to eq(generated_page_contesnts)
|
55
|
-
end
|
56
|
-
|
57
|
-
context "the manifest" do
|
58
|
-
let(:manifest) { get_manifest("#{page_dir_name}/#{MANIFEST_FILE_NAME}") }
|
59
|
-
|
60
|
-
it "has a name" do
|
61
|
-
expect(manifest["Name"]).to eq(page_name)
|
62
|
-
end
|
63
|
-
|
64
|
-
it "has a LiveViewMode" do
|
65
|
-
expect(manifest["LiveViewMode"]).to eq("HiddenByDefault")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
-
|
3
|
-
module Playgroundbook
|
4
|
-
describe Renderer do
|
5
|
-
include FakeFS::SpecHelpers
|
6
|
-
let(:renderer) { Renderer.new(yaml_file_name, contents_manifest_generator, page_parser, chapter_collator, glossary_generator, test_ui) }
|
7
|
-
let(:yaml_file_name) { "book.yml" }
|
8
|
-
let(:contents_manifest_generator) { double(ContentsManifestGenerator) }
|
9
|
-
let(:page_parser) { double(PageParser) }
|
10
|
-
let(:chapter_collator) { double(ChapterCollator) }
|
11
|
-
let(:glossary_generator) { double(GlossaryGenerator) }
|
12
|
-
let(:test_ui) { Cork::Board.new(silent: true) }
|
13
|
-
|
14
|
-
before do
|
15
|
-
File.open(yaml_file_name, "w") do |file|
|
16
|
-
file.write(test_book_metadata.to_yaml)
|
17
|
-
end
|
18
|
-
|
19
|
-
allow(contents_manifest_generator).to receive(:generate)
|
20
|
-
allow(chapter_collator).to receive(:collate)
|
21
|
-
allow(glossary_generator).to receive(:generate)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "initializes correctly" do
|
25
|
-
expect(renderer.yaml_file_name) == yaml_file_name
|
26
|
-
end
|
27
|
-
|
28
|
-
it "explodes when there is no playground" do
|
29
|
-
expect { renderer.render }.to raise_error
|
30
|
-
end
|
31
|
-
|
32
|
-
context "with a playground" do
|
33
|
-
before do
|
34
|
-
allow(page_parser).to receive(:parse_chapter_pages)
|
35
|
-
Dir.mkdir("assets")
|
36
|
-
FileUtils.touch("assets/file.png")
|
37
|
-
Dir.mkdir("test_chapter.playground/")
|
38
|
-
File.open("test_chapter.playground/Contents.swift", "w") do |file|
|
39
|
-
file.write("")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
it "creates a directory with book name" do
|
44
|
-
renderer.render
|
45
|
-
|
46
|
-
expect(Dir.exist?("Testing Book.playgroundbook")).to be_truthy
|
47
|
-
end
|
48
|
-
|
49
|
-
it "creates a resources folder" do
|
50
|
-
renderer.render
|
51
|
-
|
52
|
-
expect(Dir.exist?("Testing Book.playgroundbook/Contents/Resources")).to be_truthy
|
53
|
-
end
|
54
|
-
|
55
|
-
it "copies a resources folder contents" do
|
56
|
-
renderer.render
|
57
|
-
|
58
|
-
expect(File.exist?("Testing Book.playgroundbook/Contents/Resources/file.png")).to be_truthy
|
59
|
-
end
|
60
|
-
|
61
|
-
context "within an existing playgroundbook directory" do
|
62
|
-
before do
|
63
|
-
Dir.mkdir("Testing Book.playgroundbook")
|
64
|
-
end
|
65
|
-
|
66
|
-
it "does not explode when the directory already exists" do
|
67
|
-
expect { renderer.render }.to_not raise_error
|
68
|
-
end
|
69
|
-
|
70
|
-
it "creates a Contents directory within the main bundle dir" do
|
71
|
-
renderer.render
|
72
|
-
|
73
|
-
expect(Dir.exist?("Testing Book.playgroundbook/Contents")).to be_truthy
|
74
|
-
end
|
75
|
-
|
76
|
-
context "within the Contents directory" do
|
77
|
-
before do
|
78
|
-
Dir.mkdir("Testing Book.playgroundbook/Contents")
|
79
|
-
end
|
80
|
-
|
81
|
-
it "does not explode when the Contents directory already exists" do
|
82
|
-
expect { renderer.render }.to_not raise_error
|
83
|
-
end
|
84
|
-
|
85
|
-
it "renders main manifest" do
|
86
|
-
expect(contents_manifest_generator).to receive(:generate)
|
87
|
-
|
88
|
-
renderer.render
|
89
|
-
end
|
90
|
-
|
91
|
-
it "creates a Chapters directory within the Contents dir" do
|
92
|
-
renderer.render
|
93
|
-
|
94
|
-
expect(Dir.exist?("Testing Book.playgroundbook/Contents/Chapters")).to be_truthy
|
95
|
-
end
|
96
|
-
|
97
|
-
context "within the Chapters directory" do
|
98
|
-
before do
|
99
|
-
Dir.mkdir("Testing Book.playgroundbook/Contents/Chapters")
|
100
|
-
end
|
101
|
-
|
102
|
-
it "does not explode when the Chapters directory already exists" do
|
103
|
-
expect { renderer.render }.to_not raise_error
|
104
|
-
end
|
105
|
-
|
106
|
-
it "generates each chapter" do
|
107
|
-
expect(chapter_collator).to receive(:collate)
|
108
|
-
|
109
|
-
renderer.render
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
it "generates a glossary" do
|
116
|
-
expect(glossary_generator).to receive(:generate)
|
117
|
-
|
118
|
-
renderer.render
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
require "pathname"
|
2
|
-
require "cork"
|
3
|
-
require "rspec"
|
4
|
-
require "plist"
|
5
|
-
require "fileutils"
|
6
|
-
require "tmpdir"
|
7
|
-
require "fakefs/spec_helpers"
|
8
|
-
|
9
|
-
ROOT = Pathname.new(File.expand_path("../../", __FILE__))
|
10
|
-
$LOAD_PATH.unshift((ROOT + "lib").to_s)
|
11
|
-
$LOAD_PATH.unshift((ROOT + "spec").to_s)
|
12
|
-
|
13
|
-
require "playgroundbook"
|
14
|
-
require "linter/abstract_linter"
|
15
|
-
require "linter/chapter_linter"
|
16
|
-
require "linter/chapter_manifest_linter"
|
17
|
-
require "linter/contents_linter"
|
18
|
-
require "linter/manifest_linter"
|
19
|
-
require "linter/page_linter"
|
20
|
-
require "linter/page_manifest_linter"
|
21
|
-
require "linter/cutscene_page_linter"
|
22
|
-
require "linter/cutscene_page_manifest_linter"
|
23
|
-
require "linter/root_manifest_linter"
|
24
|
-
|
25
|
-
require "renderer/contents_manifest_generator"
|
26
|
-
require "renderer/chapter_collator"
|
27
|
-
require "renderer/page_writer"
|
28
|
-
require "renderer/page_parser"
|
29
|
-
require "renderer/glossary_generator"
|
30
|
-
require "renderer/page_processor"
|
31
|
-
|
32
|
-
RSpec.configure do |config|
|
33
|
-
config.color = true
|
34
|
-
|
35
|
-
config.order = :random
|
36
|
-
Kernel.srand config.seed
|
37
|
-
end
|
38
|
-
RSpec::Expectations.configuration.on_potential_false_positives = :nothing
|
39
|
-
|
40
|
-
Playgroundbook::AbstractLinter.ui = Cork::Board.new(silent: true)
|
41
|
-
|
42
|
-
def test_playground_book
|
43
|
-
"spec/fixtures/Starter.playgroundbook"
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_book_metadata
|
47
|
-
{
|
48
|
-
"name" => "Testing Book",
|
49
|
-
"chapters" => [ "name" => "test_chapter"],
|
50
|
-
"identifier" => "com.ashfurrow.testing",
|
51
|
-
"resources" => "assets",
|
52
|
-
"cover" => "file.jpeg",
|
53
|
-
"glossary" => [
|
54
|
-
{
|
55
|
-
"term" => "definition"
|
56
|
-
}
|
57
|
-
]
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
def get_manifest(file_name = Playgroundbook::ManifestFileName)
|
62
|
-
Plist.parse_xml(file_name)
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_chapter_contents
|
66
|
-
<<-EOSwift
|
67
|
-
import UIKit
|
68
|
-
|
69
|
-
var str = "Hello, playground"
|
70
|
-
|
71
|
-
func sharedFunc() {
|
72
|
-
print("This should be accessible to all pages.")
|
73
|
-
}
|
74
|
-
|
75
|
-
//// Page 1
|
76
|
-
|
77
|
-
str = "Yo, it's page 1."
|
78
|
-
sharedFunc()
|
79
|
-
|
80
|
-
//// Page 2
|
81
|
-
|
82
|
-
str = "Page 2 awww yeah."
|
83
|
-
sharedFunc()
|
84
|
-
EOSwift
|
85
|
-
end
|
@@ -1,90 +0,0 @@
|
|
1
|
-
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
-
|
3
|
-
module Playgroundbook
|
4
|
-
describe MarkdownWrapper do
|
5
|
-
|
6
|
-
it "creates a swift file from a markdown file" do
|
7
|
-
source = "spec/fixtures/wrapper/source/swift_at_artsy_1.md"
|
8
|
-
destination = "spec/fixtures/wrapper/destination/swift_at_artsy_1.swift"
|
9
|
-
subject = MarkdownWrapper.new(source, "Swift at Artsy")
|
10
|
-
contents = File.read(source)
|
11
|
-
expect(subject.swap_code_context(contents)).to eq(File.read(destination))
|
12
|
-
end
|
13
|
-
|
14
|
-
it "creates a playground around the file" do
|
15
|
-
source = "spec/fixtures/wrapper/source/swift_at_artsy_1.md"
|
16
|
-
|
17
|
-
Dir.mktmpdir do |dir|
|
18
|
-
new_source = File.join(dir, File.basename(source))
|
19
|
-
FileUtils.cp(source, new_source)
|
20
|
-
subject = MarkdownWrapper.new(new_source, "Swift at Artsy")
|
21
|
-
|
22
|
-
subject.generate
|
23
|
-
|
24
|
-
playground = File.join(dir, "Swift at Artsy.playground")
|
25
|
-
expect(Dir.exist?(playground)).to eq(true)
|
26
|
-
expect(File.exist?(File.join(playground, "Contents.swift"))).to eq(true)
|
27
|
-
expect(File.exist?(File.join(playground, "timeline.xctimeline"))).to eq(true)
|
28
|
-
expect(File.exist?(File.join(playground, "contents.xcplayground"))).to eq(true)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
it "gets the image files inside the markdown doc" do
|
33
|
-
source = "spec/fixtures/wrapper/source/swift_at_artsy_1.md"
|
34
|
-
subject = MarkdownWrapper.new(source, "Swift at Artsy")
|
35
|
-
expect(subject.get_list_of_images(subject.playground_contents)).to eq(
|
36
|
-
["img/welcome.png", "img/newplayground.png", "img/emptyplayground.png", "img/results.png"]
|
37
|
-
)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "embeds the local images inside the resources folder" do
|
41
|
-
source = "spec/fixtures/wrapper/source/swift_at_artsy_1.md"
|
42
|
-
|
43
|
-
Dir.mktmpdir do |dir|
|
44
|
-
new_source = File.join(dir, File.basename(source))
|
45
|
-
FileUtils.cp(source, new_source)
|
46
|
-
|
47
|
-
# images need to be in the tmpdir relative for picking up
|
48
|
-
Dir.mkdir(File.join(dir, "img"))
|
49
|
-
FileUtils.cp(source, File.join(dir, "img", "welcome.png"))
|
50
|
-
|
51
|
-
subject = MarkdownWrapper.new(new_source, "Swift at Artsy")
|
52
|
-
subject.generate
|
53
|
-
|
54
|
-
embedded_img = File.join(dir, "Swift at Artsy.playground", "Resources", "img/welcome.png")
|
55
|
-
expect(File.exist?(embedded_img)).to eq(true)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
it "embeds remote images inside the resources folder, and changes the MD content to match relative url" do
|
60
|
-
source = "spec/fixtures/wrapper/source/swift_at_artsy_1.md"
|
61
|
-
|
62
|
-
Dir.mktmpdir do |dir|
|
63
|
-
new_source = File.join(dir, File.basename(source))
|
64
|
-
FileUtils.cp(source, new_source)
|
65
|
-
|
66
|
-
subject = MarkdownWrapper.new(new_source, "Swift at Artsy")
|
67
|
-
# Switch out a relative link to a remote one
|
68
|
-
remote_image = "http://ortastuff.s3.amazonaws.com/site/images/twitter_black.png"
|
69
|
-
subject.playground_contents.gsub!("img/welcome.png", remote_image)
|
70
|
-
|
71
|
-
# Quacks like the value of `open`
|
72
|
-
class EmptyOpen
|
73
|
-
def read
|
74
|
-
""
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
allow(subject).to receive(:open).and_return(EmptyOpen.new)
|
79
|
-
subject.generate
|
80
|
-
|
81
|
-
source_path = File.join(dir, "Swift at Artsy.playground", "Contents.swift")
|
82
|
-
expect(File.read(source_path)).to include("twitter_black.png")
|
83
|
-
expect(File.read(source_path)).to_not include(remote_image)
|
84
|
-
|
85
|
-
embedded_img = File.join(dir, "Swift at Artsy.playground", "Resources", "twitter_black.png")
|
86
|
-
expect(File.exist?(embedded_img)).to eq(true)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|