liquid 1.9.0 → 2.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.
- data/Manifest.txt +0 -31
- data/Rakefile +1 -1
- data/lib/extras/liquid_view.rb +15 -2
- data/lib/liquid.rb +15 -15
- data/lib/liquid/block.rb +1 -2
- data/lib/liquid/context.rb +89 -99
- data/lib/liquid/drop.rb +6 -4
- data/lib/liquid/errors.rb +1 -0
- data/lib/liquid/standardfilters.rb +56 -11
- data/lib/liquid/strainer.rb +1 -1
- data/lib/liquid/tags/assign.rb +1 -1
- data/lib/liquid/tags/case.rb +2 -2
- data/lib/liquid/tags/cycle.rb +3 -4
- data/lib/liquid/tags/for.rb +53 -35
- data/lib/liquid/tags/if.rb +3 -3
- data/lib/liquid/template.rb +8 -7
- data/lib/liquid/variable.rb +10 -11
- metadata +5 -35
- data/example/server/example_servlet.rb +0 -37
- data/example/server/liquid_servlet.rb +0 -28
- data/example/server/server.rb +0 -12
- data/example/server/templates/index.liquid +0 -6
- data/example/server/templates/products.liquid +0 -45
- data/test/block_test.rb +0 -58
- data/test/condition_test.rb +0 -109
- data/test/context_test.rb +0 -418
- data/test/drop_test.rb +0 -141
- data/test/error_handling_test.rb +0 -78
- data/test/extra/breakpoint.rb +0 -547
- data/test/extra/caller.rb +0 -80
- data/test/file_system_test.rb +0 -30
- data/test/filter_test.rb +0 -98
- data/test/helper.rb +0 -20
- data/test/html_tag_test.rb +0 -31
- data/test/if_else_test.rb +0 -127
- data/test/include_tag_test.rb +0 -114
- data/test/module_ex_test.rb +0 -89
- data/test/output_test.rb +0 -121
- data/test/parsing_quirks_test.rb +0 -29
- data/test/regexp_test.rb +0 -40
- data/test/security_test.rb +0 -41
- data/test/standard_filter_test.rb +0 -126
- data/test/standard_tag_test.rb +0 -383
- data/test/statements_test.rb +0 -137
- data/test/strainer_test.rb +0 -16
- data/test/template_test.rb +0 -26
- data/test/unless_else_test.rb +0 -27
- data/test/variable_test.rb +0 -135
data/test/module_ex_test.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.dirname(__FILE__) + '/helper'
|
3
|
-
|
4
|
-
class TestClassA
|
5
|
-
liquid_methods :allowedA, :chainedB
|
6
|
-
def allowedA
|
7
|
-
'allowedA'
|
8
|
-
end
|
9
|
-
def restrictedA
|
10
|
-
'restrictedA'
|
11
|
-
end
|
12
|
-
def chainedB
|
13
|
-
TestClassB.new
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class TestClassB
|
18
|
-
liquid_methods :allowedB, :chainedC
|
19
|
-
def allowedB
|
20
|
-
'allowedB'
|
21
|
-
end
|
22
|
-
def chainedC
|
23
|
-
TestClassC.new
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class TestClassC
|
28
|
-
liquid_methods :allowedC
|
29
|
-
def allowedC
|
30
|
-
'allowedC'
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class TestClassC::LiquidDropClass
|
35
|
-
def another_allowedC
|
36
|
-
'another_allowedC'
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class ModuleExTest < Test::Unit::TestCase
|
41
|
-
include Liquid
|
42
|
-
|
43
|
-
def setup
|
44
|
-
@a = TestClassA.new
|
45
|
-
@b = TestClassB.new
|
46
|
-
@c = TestClassC.new
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_should_create_LiquidDropClass
|
50
|
-
assert TestClassA::LiquidDropClass
|
51
|
-
assert TestClassB::LiquidDropClass
|
52
|
-
assert TestClassC::LiquidDropClass
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_should_respond_to_liquid
|
56
|
-
assert @a.respond_to?(:to_liquid)
|
57
|
-
assert @b.respond_to?(:to_liquid)
|
58
|
-
assert @c.respond_to?(:to_liquid)
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_should_return_LiquidDropClass_object
|
62
|
-
assert @a.to_liquid.is_a?(TestClassA::LiquidDropClass)
|
63
|
-
assert @b.to_liquid.is_a?(TestClassB::LiquidDropClass)
|
64
|
-
assert @c.to_liquid.is_a?(TestClassC::LiquidDropClass)
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_should_respond_to_liquid_methods
|
68
|
-
assert @a.to_liquid.respond_to?(:allowedA)
|
69
|
-
assert @a.to_liquid.respond_to?(:chainedB)
|
70
|
-
assert @b.to_liquid.respond_to?(:allowedB)
|
71
|
-
assert @b.to_liquid.respond_to?(:chainedC)
|
72
|
-
assert @c.to_liquid.respond_to?(:allowedC)
|
73
|
-
assert @c.to_liquid.respond_to?(:another_allowedC)
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_should_not_respond_to_restricted_methods
|
77
|
-
assert ! @a.to_liquid.respond_to?(:restricted)
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_should_use_regular_objects_as_drops
|
81
|
-
assert_equal 'allowedA', Liquid::Template.parse("{{ a.allowedA }}").render('a'=>@a)
|
82
|
-
assert_equal 'allowedB', Liquid::Template.parse("{{ a.chainedB.allowedB }}").render('a'=>@a)
|
83
|
-
assert_equal 'allowedC', Liquid::Template.parse("{{ a.chainedB.chainedC.allowedC }}").render('a'=>@a)
|
84
|
-
assert_equal 'another_allowedC', Liquid::Template.parse("{{ a.chainedB.chainedC.another_allowedC }}").render('a'=>@a)
|
85
|
-
assert_equal '', Liquid::Template.parse("{{ a.restricted }}").render('a'=>@a)
|
86
|
-
assert_equal '', Liquid::Template.parse("{{ a.unknown }}").render('a'=>@a)
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
data/test/output_test.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.dirname(__FILE__) + '/helper'
|
3
|
-
|
4
|
-
module FunnyFilter
|
5
|
-
|
6
|
-
def make_funny(input)
|
7
|
-
'LOL'
|
8
|
-
end
|
9
|
-
|
10
|
-
def cite_funny(input)
|
11
|
-
"LOL: #{input}"
|
12
|
-
end
|
13
|
-
|
14
|
-
def add_smiley(input, smiley = ":-)")
|
15
|
-
"#{input} #{smiley}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_tag(input, tag = "p", id = "foo")
|
19
|
-
%|<#{tag} id="#{id}">#{input}</#{tag}>|
|
20
|
-
end
|
21
|
-
|
22
|
-
def paragraph(input)
|
23
|
-
"<p>#{input}</p>"
|
24
|
-
end
|
25
|
-
|
26
|
-
def link_to(name, url)
|
27
|
-
%|<a href="#{url}">#{name}</a>|
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
class OutputTest < Test::Unit::TestCase
|
33
|
-
include Liquid
|
34
|
-
|
35
|
-
def setup
|
36
|
-
@assigns = {
|
37
|
-
'best_cars' => 'bmw',
|
38
|
-
'car' => {'bmw' => 'good', 'gm' => 'bad'}
|
39
|
-
}
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_variable
|
44
|
-
text = %| {{best_cars}} |
|
45
|
-
|
46
|
-
expected = %| bmw |
|
47
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_variable_traversing
|
51
|
-
text = %| {{car.bmw}} {{car.gm}} {{car.bmw}} |
|
52
|
-
|
53
|
-
expected = %| good bad good |
|
54
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_variable_piping
|
58
|
-
text = %( {{ car.gm | make_funny }} )
|
59
|
-
expected = %| LOL |
|
60
|
-
|
61
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_variable_piping_with_input
|
65
|
-
text = %( {{ car.gm | cite_funny }} )
|
66
|
-
expected = %| LOL: bad |
|
67
|
-
|
68
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_variable_piping_with_args
|
72
|
-
text = %! {{ car.gm | add_smiley : ':-(' }} !
|
73
|
-
expected = %| bad :-( |
|
74
|
-
|
75
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_variable_piping_with_no_args
|
79
|
-
text = %! {{ car.gm | add_smiley }} !
|
80
|
-
expected = %| bad :-) |
|
81
|
-
|
82
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_multiple_variable_piping_with_args
|
86
|
-
text = %! {{ car.gm | add_smiley : ':-(' | add_smiley : ':-('}} !
|
87
|
-
expected = %| bad :-( :-( |
|
88
|
-
|
89
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_variable_piping_with_args
|
93
|
-
text = %! {{ car.gm | add_tag : 'span', 'bar'}} !
|
94
|
-
expected = %| <span id="bar">bad</span> |
|
95
|
-
|
96
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_variable_piping_with_variable_args
|
100
|
-
text = %! {{ car.gm | add_tag : 'span', car.bmw}} !
|
101
|
-
expected = %| <span id="good">bad</span> |
|
102
|
-
|
103
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_multiple_pipings
|
107
|
-
text = %( {{ best_cars | cite_funny | paragraph }} )
|
108
|
-
expected = %| <p>LOL: bmw</p> |
|
109
|
-
|
110
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_link_to
|
114
|
-
text = %( {{ 'Typo' | link_to: 'http://typo.leetsoft.com' }} )
|
115
|
-
expected = %| <a href="http://typo.leetsoft.com">Typo</a> |
|
116
|
-
|
117
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
118
|
-
end
|
119
|
-
|
120
|
-
|
121
|
-
end
|
data/test/parsing_quirks_test.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.dirname(__FILE__) + '/helper'
|
3
|
-
|
4
|
-
class ParsingQuirksTest < Test::Unit::TestCase
|
5
|
-
include Liquid
|
6
|
-
|
7
|
-
def test_error_with_css
|
8
|
-
text = %| div { font-weight: bold; } |
|
9
|
-
template = Template.parse(text)
|
10
|
-
|
11
|
-
assert_equal text, template.render
|
12
|
-
assert_equal [String], template.root.nodelist.collect {|i| i.class}
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_raise_on_single_close_bracet
|
16
|
-
assert_raise(SyntaxError) do
|
17
|
-
Template.parse("text {{method} oh nos!")
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def test_error_on_empty_filter
|
23
|
-
assert_nothing_raised do
|
24
|
-
Template.parse("{{test |a|b|}}")
|
25
|
-
Template.parse("{{test}}")
|
26
|
-
Template.parse("{{|test|}}")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/test/regexp_test.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/helper'
|
2
|
-
|
3
|
-
class RegexpTest < Test::Unit::TestCase
|
4
|
-
include Liquid
|
5
|
-
|
6
|
-
def test_empty
|
7
|
-
assert_equal [], ''.scan(QuotedFragment)
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_quote
|
11
|
-
assert_equal ['"arg 1"'], '"arg 1"'.scan(QuotedFragment)
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
def test_words
|
16
|
-
assert_equal ['arg1', 'arg2'], 'arg1 arg2'.scan(QuotedFragment)
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_quoted_words
|
20
|
-
assert_equal ['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment)
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_quoted_words
|
24
|
-
assert_equal ['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment)
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_quoted_words_in_the_middle
|
28
|
-
assert_equal ['arg1', 'arg2', '"arg 3"', 'arg4'], 'arg1 arg2 "arg 3" arg4 '.scan(QuotedFragment)
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_variable_parser
|
32
|
-
assert_equal ['var'], 'var'.scan(VariableParser)
|
33
|
-
assert_equal ['var', 'method'], 'var.method'.scan(VariableParser)
|
34
|
-
assert_equal ['var', '[method]'], 'var[method]'.scan(VariableParser)
|
35
|
-
assert_equal ['var', '[method]', '[0]'], 'var[method][0]'.scan(VariableParser)
|
36
|
-
assert_equal ['var', '["method"]', '[0]'], 'var["method"][0]'.scan(VariableParser)
|
37
|
-
assert_equal ['var', '[method]', '[0]', 'method'], 'var[method][0].method'.scan(VariableParser)
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
data/test/security_test.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/helper'
|
2
|
-
|
3
|
-
module SecurityFilter
|
4
|
-
def add_one(input)
|
5
|
-
"#{input} + 1"
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class SecurityTest < Test::Unit::TestCase
|
10
|
-
include Liquid
|
11
|
-
|
12
|
-
def test_no_instance_eval
|
13
|
-
text = %( {{ '1+1' | instance_eval }} )
|
14
|
-
expected = %| 1+1 |
|
15
|
-
|
16
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_no_existing_instance_eval
|
20
|
-
text = %( {{ '1+1' | __instance_eval__ }} )
|
21
|
-
expected = %| 1+1 |
|
22
|
-
|
23
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
def test_no_instance_eval_after_mixing_in_new_filter
|
28
|
-
text = %( {{ '1+1' | instance_eval }} )
|
29
|
-
expected = %| 1+1 |
|
30
|
-
|
31
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
def test_no_instance_eval_later_in_chain
|
36
|
-
text = %( {{ '1+1' | add_one | instance_eval }} )
|
37
|
-
expected = %| 1+1 + 1 |
|
38
|
-
|
39
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => SecurityFilter)
|
40
|
-
end
|
41
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.dirname(__FILE__) + '/helper'
|
3
|
-
|
4
|
-
|
5
|
-
class Filters
|
6
|
-
include Liquid::StandardFilters
|
7
|
-
end
|
8
|
-
|
9
|
-
|
10
|
-
class StandardFiltersTest < Test::Unit::TestCase
|
11
|
-
include Liquid
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@filters = Filters.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_size
|
18
|
-
assert_equal 3, @filters.size([1,2,3])
|
19
|
-
assert_equal 0, @filters.size([])
|
20
|
-
assert_equal 0, @filters.size(nil)
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_downcase
|
24
|
-
assert_equal 'testing', @filters.downcase("Testing")
|
25
|
-
assert_equal '', @filters.downcase(nil)
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_upcase
|
29
|
-
assert_equal 'TESTING', @filters.upcase("Testing")
|
30
|
-
assert_equal '', @filters.upcase(nil)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_upcase
|
34
|
-
assert_equal 'TESTING', @filters.upcase("Testing")
|
35
|
-
assert_equal '', @filters.upcase(nil)
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_truncate
|
39
|
-
assert_equal '1234...', @filters.truncate('1234567890', 7)
|
40
|
-
assert_equal '1234567890', @filters.truncate('1234567890', 20)
|
41
|
-
assert_equal '...', @filters.truncate('1234567890', 0)
|
42
|
-
assert_equal '1234567890', @filters.truncate('1234567890')
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_escape
|
46
|
-
assert_equal '<strong>', @filters.escape('<strong>')
|
47
|
-
assert_equal '<strong>', @filters.h('<strong>')
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_truncatewords
|
51
|
-
assert_equal 'one two three', @filters.truncatewords('one two three', 4)
|
52
|
-
assert_equal 'one two...', @filters.truncatewords('one two three', 2)
|
53
|
-
assert_equal 'one two three', @filters.truncatewords('one two three')
|
54
|
-
assert_equal 'Two small (13” x 5.5” x 10” high) baskets fit inside one large basket (13”...', @filters.truncatewords('Two small (13” x 5.5” x 10” high) baskets fit inside one large basket (13” x 16” x 10.5” high) with cover.', 15)
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_strip_html
|
58
|
-
assert_equal 'test', @filters.strip_html("<div>test</div>")
|
59
|
-
assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
|
60
|
-
assert_equal '', @filters.strip_html(nil)
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_join
|
64
|
-
assert_equal '1 2 3 4', @filters.join([1,2,3,4])
|
65
|
-
assert_equal '1 - 2 - 3 - 4', @filters.join([1,2,3,4], ' - ')
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_sort
|
69
|
-
assert_equal [1,2,3,4], @filters.sort([4,3,2,1])
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_date
|
73
|
-
assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
|
74
|
-
assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
|
75
|
-
assert_equal 'July', @filters.date(Time.parse("2006-07-05 10:00:00"), "%B")
|
76
|
-
|
77
|
-
assert_equal 'May', @filters.date("2006-05-05 10:00:00", "%B")
|
78
|
-
assert_equal 'June', @filters.date("2006-06-05 10:00:00", "%B")
|
79
|
-
assert_equal 'July', @filters.date("2006-07-05 10:00:00", "%B")
|
80
|
-
|
81
|
-
assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
|
82
|
-
assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
|
83
|
-
assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
|
84
|
-
assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", nil)
|
85
|
-
|
86
|
-
assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
|
87
|
-
|
88
|
-
assert_equal "07/16/2004", @filters.date("Fri Jul 16 01:00:00 EDT 2004", "%m/%d/%Y")
|
89
|
-
|
90
|
-
assert_equal nil, @filters.date(nil, "%B")
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
def test_first_last
|
95
|
-
assert_equal 1, @filters.first([1,2,3])
|
96
|
-
assert_equal 3, @filters.last([1,2,3])
|
97
|
-
assert_equal nil, @filters.first([])
|
98
|
-
assert_equal nil, @filters.last([])
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_replace
|
102
|
-
assert_equal 'b b b b', @filters.replace("a a a a", 'a', 'b')
|
103
|
-
assert_equal 'b a a a', @filters.replace_first("a a a a", 'a', 'b')
|
104
|
-
assert_template_result 'b a a a', "{{ 'a a a a' | replace_first: 'a', 'b' }}"
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_remove
|
108
|
-
assert_equal ' ', @filters.remove("a a a a", 'a')
|
109
|
-
assert_equal 'a a a', @filters.remove_first("a a a a", 'a ')
|
110
|
-
assert_template_result 'a a a', "{{ 'a a a a' | remove_first: 'a ' }}"
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_strip_newlines
|
114
|
-
assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_newlines_to_br
|
118
|
-
assert_template_result "a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc"
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
|