temple 0.2.0 → 0.3.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.
Files changed (54) hide show
  1. data/.yardopts +2 -1
  2. data/CHANGES +63 -0
  3. data/EXPRESSIONS.md +250 -0
  4. data/README.md +24 -12
  5. data/lib/temple.rb +34 -18
  6. data/lib/temple/engine.rb +11 -7
  7. data/lib/temple/erb/engine.rb +5 -3
  8. data/lib/temple/erb/parser.rb +5 -2
  9. data/lib/temple/erb/template.rb +11 -0
  10. data/lib/temple/erb/trimming.rb +9 -1
  11. data/lib/temple/filter.rb +2 -0
  12. data/lib/temple/filters/control_flow.rb +43 -0
  13. data/lib/temple/filters/dynamic_inliner.rb +29 -32
  14. data/lib/temple/filters/eraser.rb +22 -0
  15. data/lib/temple/filters/escapable.rb +39 -0
  16. data/lib/temple/filters/multi_flattener.rb +4 -1
  17. data/lib/temple/filters/static_merger.rb +11 -10
  18. data/lib/temple/filters/validator.rb +15 -0
  19. data/lib/temple/generators.rb +41 -100
  20. data/lib/temple/grammar.rb +56 -0
  21. data/lib/temple/hash.rb +48 -0
  22. data/lib/temple/html/dispatcher.rb +10 -4
  23. data/lib/temple/html/fast.rb +50 -38
  24. data/lib/temple/html/filter.rb +8 -0
  25. data/lib/temple/html/pretty.rb +25 -14
  26. data/lib/temple/mixins/dispatcher.rb +103 -0
  27. data/lib/temple/{mixins.rb → mixins/engine_dsl.rb} +10 -95
  28. data/lib/temple/mixins/grammar_dsl.rb +166 -0
  29. data/lib/temple/mixins/options.rb +28 -0
  30. data/lib/temple/mixins/template.rb +25 -0
  31. data/lib/temple/templates.rb +2 -0
  32. data/lib/temple/utils.rb +11 -57
  33. data/lib/temple/version.rb +1 -1
  34. data/test/filters/test_control_flow.rb +92 -0
  35. data/test/filters/test_dynamic_inliner.rb +7 -7
  36. data/test/filters/test_eraser.rb +55 -0
  37. data/test/filters/{test_escape_html.rb → test_escapable.rb} +13 -6
  38. data/test/filters/test_multi_flattener.rb +1 -1
  39. data/test/filters/test_static_merger.rb +3 -3
  40. data/test/helper.rb +8 -0
  41. data/test/html/test_fast.rb +42 -57
  42. data/test/html/test_pretty.rb +10 -7
  43. data/test/mixins/test_dispatcher.rb +31 -0
  44. data/test/mixins/test_grammar_dsl.rb +86 -0
  45. data/test/test_engine.rb +73 -57
  46. data/test/test_erb.rb +0 -7
  47. data/test/test_filter.rb +26 -0
  48. data/test/test_generator.rb +57 -36
  49. data/test/test_grammar.rb +52 -0
  50. data/test/test_hash.rb +39 -0
  51. data/test/test_utils.rb +11 -38
  52. metadata +34 -10
  53. data/lib/temple/filters/debugger.rb +0 -26
  54. data/lib/temple/filters/escape_html.rb +0 -33
@@ -6,10 +6,10 @@ describe Temple::HTML::Pretty do
6
6
  end
7
7
 
8
8
  it 'should indent nested tags' do
9
- @html.call([:html, :tag, 'div', [:multi], false,
10
- [:html, :tag, 'p', [:multi], false, [:multi, [:static, 'text'], [:dynamic, 'code']]]
9
+ @html.call([:html, :tag, 'div', [:multi],
10
+ [:html, :tag, 'p', [:multi], [:multi, [:static, 'text'], [:dynamic, 'code']]]
11
11
  ]).should.equal [:multi,
12
- [:block, "_temple_pre_tags = /<pre|<textarea/"],
12
+ [:code, "_temple_html_pretty1 = /<code|<pre|<textarea/"],
13
13
  [:multi,
14
14
  [:static, "<div"],
15
15
  [:multi],
@@ -20,17 +20,20 @@ describe Temple::HTML::Pretty do
20
20
  [:static, ">"],
21
21
  [:multi,
22
22
  [:static, "text"],
23
- [:dynamic, 'Temple::Utils.indent((code), "\n ", _temple_pre_tags)']],
23
+ [:multi,
24
+ [:code, "_temple_html_pretty2 = (code).to_s"],
25
+ [:code, '_temple_html_pretty2.gsub!("\n", "\n ") if _temple_html_pretty1 !~ _temple_html_pretty2'],
26
+ [:dynamic, "_temple_html_pretty2"]]],
24
27
  [:static, "</p>"]],
25
28
  [:static, "\n</div>"]]]
26
29
  end
27
30
 
28
31
 
29
32
  it 'should not indent preformatted tags' do
30
- @html.call([:html, :tag, 'pre', [:multi], false,
31
- [:html, :tag, 'p', [:multi], false, [:static, 'text']]
33
+ @html.call([:html, :tag, 'pre', [:multi],
34
+ [:html, :tag, 'p', [:multi], [:static, 'text']]
32
35
  ]).should.equal [:multi,
33
- [:block, "_temple_pre_tags = /<pre|<textarea/"],
36
+ [:code, "_temple_html_pretty1 = /<code|<pre|<textarea/"],
34
37
  [:multi,
35
38
  [:static, "<pre"],
36
39
  [:multi],
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ class FilterWithDispatcherMixin
4
+ include Temple::Mixins::Dispatcher
5
+
6
+ def on_test(arg)
7
+ [:on_test, arg]
8
+ end
9
+
10
+ def on_second_test(arg)
11
+ [:on_second_test, arg]
12
+ end
13
+ end
14
+
15
+ describe Temple::Mixins::Dispatcher do
16
+ before do
17
+ @filter = FilterWithDispatcherMixin.new
18
+ end
19
+
20
+ it 'should return unhandled expressions' do
21
+ @filter.call([:unhandled]).should.equal [:unhandled]
22
+ end
23
+
24
+ it 'should dispatch first level' do
25
+ @filter.call([:test, 42]).should.equal [:on_test, 42]
26
+ end
27
+
28
+ it 'should dispatch second level' do
29
+ @filter.call([:second, :test, 42]).should.equal [:on_second_test, 42]
30
+ end
31
+ end
@@ -0,0 +1,86 @@
1
+ require 'helper'
2
+
3
+ module BasicGrammar
4
+ extend Temple::Mixins::GrammarDSL
5
+
6
+ Expression <<
7
+ Symbol |
8
+ Answer |
9
+ [:zero_or_more, 'Expression*'] |
10
+ [:one_or_more, 'Expression+'] |
11
+ [:zero_or_one, 'Expression?'] |
12
+ [:bool, Bool] |
13
+ nil
14
+
15
+ Bool <<
16
+ true | false
17
+
18
+ Answer <<
19
+ Value(42)
20
+
21
+ end
22
+
23
+ module ExtendedGrammar
24
+ extend BasicGrammar
25
+
26
+ Expression << [:extended, Expression]
27
+ end
28
+
29
+ describe Temple::Mixins::GrammarDSL do
30
+ it 'should support class types' do
31
+ BasicGrammar.should.match :symbol
32
+ BasicGrammar.should.not.match [:symbol]
33
+ BasicGrammar.should.not.match 'string'
34
+ BasicGrammar.should.not.match ['string']
35
+ end
36
+
37
+ it 'should support value types' do
38
+ BasicGrammar.should.match 42
39
+ BasicGrammar.should.not.match 43
40
+ end
41
+
42
+ it 'should support nesting' do
43
+ BasicGrammar.should.match [:zero_or_more, [:zero_or_more]]
44
+ end
45
+
46
+ it 'should support *' do
47
+ BasicGrammar.should.match [:zero_or_more]
48
+ BasicGrammar.should.match [:zero_or_more, nil, 42]
49
+ end
50
+
51
+ it 'should support +' do
52
+ BasicGrammar.should.not.match [:one_or_more]
53
+ BasicGrammar.should.match [:one_or_more, 42]
54
+ BasicGrammar.should.match [:one_or_more, 42, nil]
55
+ end
56
+
57
+ it 'should support ?' do
58
+ BasicGrammar.should.not.match [:zero_or_one, nil, 42]
59
+ BasicGrammar.should.match [:zero_or_one]
60
+ BasicGrammar.should.match [:zero_or_one, 42]
61
+ end
62
+
63
+ it 'should support extended grammars' do
64
+ ExtendedGrammar.should.match [:extended, [:extended, 42]]
65
+ BasicGrammar.should.not.match [:zero_or_more, [:extended, nil]]
66
+ BasicGrammar.should.not.match [:extended, [:extended, 42]]
67
+ end
68
+
69
+ it 'should have validate!' do
70
+ grammar_validate BasicGrammar,
71
+ [:zero_or_more, [:zero_or_more, [:unknown]]],
72
+ "BasicGrammar::Expression did not match\n[:unknown]\n"
73
+
74
+ grammar_validate BasicGrammar,
75
+ [:zero_or_more, [:one_or_more]],
76
+ "BasicGrammar::Expression did not match\n[:one_or_more]\n"
77
+
78
+ grammar_validate BasicGrammar,
79
+ [:zero_or_more, 123, [:unknown]],
80
+ "BasicGrammar::Expression did not match\n123\n"
81
+
82
+ grammar_validate BasicGrammar,
83
+ [:bool, 123],
84
+ "BasicGrammar::Bool did not match\n123\n"
85
+ end
86
+ end
data/test/test_engine.rb CHANGED
@@ -50,86 +50,94 @@ describe Temple::Engine do
50
50
  end
51
51
 
52
52
  it 'should instantiate chain' do
53
- e = TestEngine.new
54
- e.chain[0].should.be.instance_of Method
55
- e.chain[1].should.be.instance_of Method
56
- e.chain[2].should.be.instance_of Method
57
- e.chain[3].should.be.instance_of Temple::HTML::Pretty
58
- e.chain[4].should.be.instance_of Temple::Filters::MultiFlattener
59
- e.chain[5].should.be.instance_of Temple::Generators::ArrayBuffer
60
- e.chain[6].should.be.instance_of OtherCallable
53
+ call_chain = TestEngine.new.send(:call_chain)
54
+ call_chain[0].should.be.instance_of Method
55
+ call_chain[1].should.be.instance_of Method
56
+ call_chain[2].should.be.instance_of Method
57
+ call_chain[3].should.be.instance_of Temple::HTML::Pretty
58
+ call_chain[4].should.be.instance_of Temple::Filters::MultiFlattener
59
+ call_chain[5].should.be.instance_of Temple::Generators::ArrayBuffer
60
+ call_chain[6].should.be.instance_of OtherCallable
61
61
  end
62
62
 
63
63
  it 'should have #append' do
64
- e = TestEngine.new do |engine|
65
- engine.append :MyFilter3 do |exp|
66
- exp
67
- end
68
- engine.chain.size.should.equal 8
69
- engine.chain[7].first.should.equal :MyFilter3
70
- engine.chain[7].size.should.equal 2
71
- engine.chain[7].last.should.be.instance_of Method
64
+ engine = TestEngine.new
65
+ call_chain = engine.send(:call_chain)
66
+ call_chain.size.should.equal 7
67
+
68
+ engine.append :MyFilter3 do |exp|
69
+ exp
72
70
  end
73
- e.chain.size.should.equal 8
74
- e.chain[7].should.be.instance_of Method
71
+
72
+ TestEngine.chain.size.should.equal 7
73
+ engine.chain.size.should.equal 8
74
+ engine.chain[7].first.should.equal :MyFilter3
75
+ engine.chain[7].size.should.equal 2
76
+ engine.chain[7].last.should.be.instance_of Method
77
+
78
+ call_chain = engine.send(:call_chain)
79
+ call_chain.size.should.equal 8
80
+ call_chain[7].should.be.instance_of Method
75
81
  end
76
82
 
77
83
  it 'should have #prepend' do
78
- e = TestEngine.new do |engine|
79
- engine.prepend :MyFilter0 do |exp|
80
- exp
81
- end
82
- engine.chain.size.should.equal 8
83
- engine.chain[0].first.should.equal :MyFilter0
84
- engine.chain[0].size.should.equal 2
85
- engine.chain[0].last.should.be.instance_of Method
86
- engine.chain[1].first.should.equal :Parser
84
+ engine = TestEngine.new
85
+ call_chain = engine.send(:call_chain)
86
+ call_chain.size.should.equal 7
87
+
88
+ engine.prepend :MyFilter0 do |exp|
89
+ exp
87
90
  end
88
- e.chain.size.should.equal 8
89
- e.chain[0].should.be.instance_of Method
91
+
92
+ TestEngine.chain.size.should.equal 7
93
+ engine.chain.size.should.equal 8
94
+ engine.chain[0].first.should.equal :MyFilter0
95
+ engine.chain[0].size.should.equal 2
96
+ engine.chain[0].last.should.be.instance_of Method
97
+ engine.chain[1].first.should.equal :Parser
98
+
99
+ call_chain = engine.send(:call_chain)
100
+ call_chain.size.should.equal 8
101
+ call_chain[0].should.be.instance_of Method
90
102
  end
91
103
 
92
104
  it 'should have #after' do
93
- e = TestEngine.new do |engine|
94
- engine.after :Parser, :MyFilter0 do |exp|
95
- exp
96
- end
97
- engine.chain.size.should.equal 8
98
- engine.chain[0].first.should.equal :Parser
99
- engine.chain[1].first.should.equal :MyFilter0
100
- engine.chain[2].first.should.equal :MyFilter1
105
+ engine = TestEngine.new
106
+ engine.after :Parser, :MyFilter0 do |exp|
107
+ exp
101
108
  end
109
+ engine.chain.size.should.equal 8
110
+ engine.chain[0].first.should.equal :Parser
111
+ engine.chain[1].first.should.equal :MyFilter0
112
+ engine.chain[2].first.should.equal :MyFilter1
102
113
  end
103
114
 
104
115
  it 'should have #before' do
105
- e = TestEngine.new do |engine|
106
- engine.before :MyFilter1, :MyFilter0 do |exp|
107
- exp
108
- end
109
- engine.chain.size.should.equal 8
110
- engine.chain[0].first.should.equal :Parser
111
- engine.chain[1].first.should.equal :MyFilter0
112
- engine.chain[2].first.should.equal :MyFilter1
116
+ engine = TestEngine.new
117
+ engine.before :MyFilter1, :MyFilter0 do |exp|
118
+ exp
113
119
  end
120
+ engine.chain.size.should.equal 8
121
+ engine.chain[0].first.should.equal :Parser
122
+ engine.chain[1].first.should.equal :MyFilter0
123
+ engine.chain[2].first.should.equal :MyFilter1
114
124
  end
115
125
 
116
126
  it 'should have #remove' do
117
- e = TestEngine.new do |engine|
118
- engine.remove :MyFilter1
119
- engine.chain.size.should.equal 6
120
- engine.chain[0].first.should.equal :Parser
121
- engine.chain[1].first.should.equal :MyFilter2
122
- end
127
+ engine = TestEngine.new
128
+ engine.remove :MyFilter1
129
+ engine.chain.size.should.equal 6
130
+ engine.chain[0].first.should.equal :Parser
131
+ engine.chain[1].first.should.equal :MyFilter2
123
132
  end
124
133
 
125
134
  it 'should have #replace' do
126
- e = TestEngine.new do |engine|
127
- engine.before :Parser, :MyParser do |exp|
128
- exp
129
- end
130
- engine.chain.size.should.equal 8
131
- engine.chain[0].first.should.equal :MyParser
135
+ engine = TestEngine.new
136
+ engine.before :Parser, :MyParser do |exp|
137
+ exp
132
138
  end
139
+ engine.chain.size.should.equal 8
140
+ engine.chain[0].first.should.equal :MyParser
133
141
  end
134
142
 
135
143
  it 'should work with inheritance' do
@@ -141,4 +149,12 @@ describe Temple::Engine do
141
149
  inherited_engine.chain.size.should.equal 8
142
150
  TestEngine.chain.size.should.equal 7
143
151
  end
152
+
153
+ it 'should support chain option' do
154
+ engine = TestEngine.new(:chain => proc {|e| e.remove :MyFilter1 })
155
+ TestEngine.chain.size.should.equal 7
156
+ engine.chain.size.should.equal 6
157
+ engine.chain[0].first.should.equal :Parser
158
+ engine.chain[1].first.should.equal :MyFilter2
159
+ end
144
160
  end
data/test/test_erb.rb CHANGED
@@ -2,14 +2,7 @@ require 'helper'
2
2
  require 'erb'
3
3
  require 'tilt'
4
4
 
5
- class Bacon::Context
6
- def erb(src, options = {})
7
- Temple::Templates::Tilt(Temple::ERB::Engine).new(options) { src }.render
8
- end
9
- end
10
-
11
5
  describe Temple::ERB::Engine do
12
-
13
6
  it 'should compile erb' do
14
7
  src = %q{
15
8
  %% hi
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+
3
+ class SimpleFilter < Temple::Filter
4
+ def on_test(arg)
5
+ [:on_test, arg]
6
+ end
7
+ end
8
+
9
+ describe Temple::Filter do
10
+ it 'should support options' do
11
+ Temple::Filter.should.respond_to :default_options
12
+ Temple::Filter.should.respond_to :set_default_options
13
+ Temple::Filter.new.options.should.be.instance_of Temple::ImmutableHash
14
+ Temple::Filter.new(:key => 3).options[:key].should.equal 3
15
+ end
16
+
17
+ it 'should implement call' do
18
+ Temple::Filter.new.call([:exp]).should.equal [:exp]
19
+ end
20
+
21
+ it 'should process expressions' do
22
+ filter = SimpleFilter.new
23
+ filter.call([:unhandled]).should.equal [:unhandled]
24
+ filter.call([:test, 42]).should.equal [:on_test, 42]
25
+ end
26
+ end
@@ -17,8 +17,8 @@ class SimpleGenerator < Temple::Generator
17
17
  concat "D:#{s}"
18
18
  end
19
19
 
20
- def on_block(s)
21
- "B:#{s}"
20
+ def on_code(s)
21
+ "C:#{s}"
22
22
  end
23
23
  end
24
24
 
@@ -26,69 +26,90 @@ describe Temple::Generator do
26
26
  it 'should compile simple expressions' do
27
27
  gen = SimpleGenerator.new
28
28
 
29
- gen.call([:static, "test"]).should.match(/ << \(S:test\)/)
30
- gen.call([:dynamic, "test"]).should.match(/ << \(D:test\)/)
31
- gen.call([:block, "test"]).should.match(/B:test/)
29
+ gen.call([:static, 'test']).should.equal '_buf = BUFFER; _buf << (S:test); _buf'
30
+ gen.call([:dynamic, 'test']).should.equal '_buf = BUFFER; _buf << (D:test); _buf'
31
+ gen.call([:code, 'test']).should.equal '_buf = BUFFER; C:test; _buf'
32
32
  end
33
33
 
34
34
  it 'should compile multi expression' do
35
35
  gen = SimpleGenerator.new(:buffer => "VAR")
36
- str = gen.call([:multi,
36
+ gen.call([:multi,
37
37
  [:static, "static"],
38
38
  [:dynamic, "dynamic"],
39
- [:block, "block"]
40
- ])
41
-
42
- str.should.match(/VAR = BUFFER/)
43
- str.should.match(/VAR << \(S:static\)/)
44
- str.should.match(/VAR << \(D:dynamic\)/)
45
- str.should.match(/ B:block /)
39
+ [:code, "code"]
40
+ ]).should.equal 'VAR = BUFFER; VAR << (S:static); VAR << (D:dynamic); C:code; VAR'
46
41
  end
47
42
 
48
43
  it 'should compile capture' do
49
44
  gen = SimpleGenerator.new(:buffer => "VAR", :capture_generator => SimpleGenerator)
50
- str = gen.call([:capture, "foo", [:static, "test"]])
51
-
52
- str.should.match(/foo = BUFFER/)
53
- str.should.match(/foo << \(S:test\)/)
54
- str.should.match(/VAR\Z/)
45
+ gen.call([:capture, "foo",
46
+ [:static, "test"]
47
+ ]).should.equal 'VAR = BUFFER; foo = BUFFER; foo << (S:test); foo; VAR'
55
48
  end
56
49
 
57
50
  it 'should compile capture with multi' do
58
51
  gen = SimpleGenerator.new(:buffer => "VAR", :capture_generator => SimpleGenerator)
59
- str = gen.call([:multi,
52
+ gen.call([:multi,
60
53
  [:static, "before"],
61
54
 
62
55
  [:capture, "foo", [:multi,
63
56
  [:static, "static"],
64
57
  [:dynamic, "dynamic"],
65
- [:block, "block"]]],
58
+ [:code, "code"]]],
66
59
 
67
60
  [:static, "after"]
68
- ])
69
-
70
- str.should.match(/VAR << \(S:before\)/)
71
- str.should.match( /foo = BUFFER/)
72
- str.should.match( /foo << \(S:static\)/)
73
- str.should.match( /foo << \(D:dynamic\)/)
74
- str.should.match( / B:block /)
75
- str.should.match(/VAR << \(S:after\)/)
76
- str.should.match(/VAR\Z/)
61
+ ]).should.equal 'VAR = BUFFER; VAR << (S:before); foo = BUFFER; foo << (S:static); ' +
62
+ 'foo << (D:dynamic); C:code; foo; VAR << (S:after); VAR'
77
63
  end
78
64
 
79
65
  it 'should compile newlines' do
80
66
  gen = SimpleGenerator.new(:buffer => "VAR")
81
- str = gen.call([:multi,
67
+ gen.call([:multi,
82
68
  [:static, "static"],
83
69
  [:newline],
84
70
  [:dynamic, "dynamic"],
85
71
  [:newline],
86
- [:block, "block"]
87
- ])
72
+ [:code, "code"]
73
+ ]).should.equal "VAR = BUFFER; VAR << (S:static); \n; " +
74
+ "VAR << (D:dynamic); \n; C:code; VAR"
75
+ end
76
+ end
88
77
 
89
- lines = str.split("\n")
90
- lines[0].should.match(/VAR << \(S:static\)/)
91
- lines[1].should.match(/VAR << \(D:dynamic\)/)
92
- lines[2].should.match(/ B:block /)
78
+ describe Temple::Generators::Array do
79
+ it 'should compile simple expressions' do
80
+ gen = Temple::Generators::Array.new
81
+ gen.call([:static, 'test']).should.equal '_buf = []; _buf << ("test"); _buf'
82
+ gen.call([:dynamic, 'test']).should.equal '_buf = []; _buf << (test); _buf'
83
+ gen.call([:code, 'test']).should.equal '_buf = []; test; _buf'
84
+ end
85
+ end
86
+
87
+ describe Temple::Generators::ArrayBuffer do
88
+ it 'should compile simple expressions' do
89
+ gen = Temple::Generators::ArrayBuffer.new
90
+ gen.call([:static, 'test']).should.equal '_buf = []; _buf << ("test"); _buf = _buf.join'
91
+ gen.call([:dynamic, 'test']).should.equal '_buf = []; _buf << (test); _buf = _buf.join'
92
+ gen.call([:code, 'test']).should.equal '_buf = []; test; _buf = _buf.join'
93
+ end
94
+ end
95
+
96
+ describe Temple::Generators::StringBuffer do
97
+ it 'should compile simple expressions' do
98
+ gen = Temple::Generators::StringBuffer.new
99
+ gen.call([:static, 'test']).should.equal '_buf = \'\'; _buf << ("test"); _buf'
100
+ gen.call([:dynamic, 'test']).should.equal '_buf = \'\'; _buf << ((test).to_s); _buf'
101
+ gen.call([:code, 'test']).should.equal '_buf = \'\'; test; _buf'
102
+ end
103
+ end
104
+
105
+ describe Temple::Generators::RailsOutputBuffer do
106
+ it 'should compile simple expressions' do
107
+ gen = Temple::Generators::RailsOutputBuffer.new
108
+ gen.call([:static, 'test']).should.equal '@output_buffer = ActionView::OutputBuffer.new; ' +
109
+ '@output_buffer.safe_concat(("test")); @output_buffer'
110
+ gen.call([:dynamic, 'test']).should.equal '@output_buffer = ActionView::OutputBuffer.new; ' +
111
+ '@output_buffer.safe_concat(((test).to_s)); @output_buffer'
112
+ gen.call([:code, 'test']).should.equal '@output_buffer = ActionView::OutputBuffer.new; ' +
113
+ 'test; @output_buffer'
93
114
  end
94
115
  end