tenjin 0.6.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 (170) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.txt +54 -0
  3. data/benchmark/bench.rb +502 -0
  4. data/benchmark/bench_context.rb +17 -0
  5. data/benchmark/bench_context.yaml +141 -0
  6. data/benchmark/templates/_footer.html +4 -0
  7. data/benchmark/templates/_header.html +52 -0
  8. data/benchmark/templates/bench_eruby.rhtml +29 -0
  9. data/benchmark/templates/bench_tenjin.rbhtml +29 -0
  10. data/bin/rbtenjin +449 -0
  11. data/doc-api/classes/Tenjin.html +141 -0
  12. data/doc-api/classes/Tenjin/ArrayBufferTemplate.html +270 -0
  13. data/doc-api/classes/Tenjin/BaseContext.html +312 -0
  14. data/doc-api/classes/Tenjin/Context.html +126 -0
  15. data/doc-api/classes/Tenjin/ContextHelper.html +433 -0
  16. data/doc-api/classes/Tenjin/Engine.html +616 -0
  17. data/doc-api/classes/Tenjin/ErubisTemplate.html +166 -0
  18. data/doc-api/classes/Tenjin/HtmlHelper.html +359 -0
  19. data/doc-api/classes/Tenjin/Preprocessor.html +242 -0
  20. data/doc-api/classes/Tenjin/Template.html +916 -0
  21. data/doc-api/created.rid +1 -0
  22. data/doc-api/files/README_txt.html +185 -0
  23. data/doc-api/files/lib/tenjin_rb.html +136 -0
  24. data/doc-api/fr_class_index.html +36 -0
  25. data/doc-api/fr_file_index.html +28 -0
  26. data/doc-api/fr_method_index.html +89 -0
  27. data/doc-api/index.html +24 -0
  28. data/doc-api/rdoc-style.css +208 -0
  29. data/doc/docstyle.css +188 -0
  30. data/doc/examples.html +312 -0
  31. data/doc/faq.html +909 -0
  32. data/doc/users-guide.html +1691 -0
  33. data/lib/tenjin.rb +959 -0
  34. data/setup.rb +1331 -0
  35. data/tenjin.gemspec +58 -0
  36. data/test/assert-text-equal.rb +45 -0
  37. data/test/data/examples/form/create.rbhtml +4 -0
  38. data/test/data/examples/form/form.rbhtml +14 -0
  39. data/test/data/examples/form/layout.rbhtml +8 -0
  40. data/test/data/examples/form/main.rb +9 -0
  41. data/test/data/examples/form/main.result +21 -0
  42. data/test/data/examples/form/update.rbhtml +4 -0
  43. data/test/data/examples/preprocessing/helper.rb +16 -0
  44. data/test/data/examples/preprocessing/main.rb +11 -0
  45. data/test/data/examples/preprocessing/main.result +17 -0
  46. data/test/data/examples/preprocessing/select.rbhtml +15 -0
  47. data/test/data/examples/preprocessing/select_P.result +18 -0
  48. data/test/data/examples/table/table.rb +9 -0
  49. data/test/data/examples/table/table.rbhtml +16 -0
  50. data/test/data/examples/table/table.result +20 -0
  51. data/test/data/examples/table/table_s.result +18 -0
  52. data/test/data/faq/ex1.rbhtml +5 -0
  53. data/test/data/faq/ex10-baselayout.rbhtml +27 -0
  54. data/test/data/faq/ex10-content.rbhtml +12 -0
  55. data/test/data/faq/ex10-customlayout.rbhtml +11 -0
  56. data/test/data/faq/ex10_inherit.result +25 -0
  57. data/test/data/faq/ex11-bench.rb +28 -0
  58. data/test/data/faq/ex11-content.rbhtml +9 -0
  59. data/test/data/faq/ex11-layout1.rbhtml +5 -0
  60. data/test/data/faq/ex11-layout2.rbhtml +6 -0
  61. data/test/data/faq/ex11.rb +5 -0
  62. data/test/data/faq/ex11.rbhtml +8 -0
  63. data/test/data/faq/ex11.source +11 -0
  64. data/test/data/faq/ex11_arraybuffer.result +15 -0
  65. data/test/data/faq/ex1_chksyntax.result +3 -0
  66. data/test/data/faq/ex2-content.rbhtml +3 -0
  67. data/test/data/faq/ex2-layout.rbhtml +11 -0
  68. data/test/data/faq/ex2_removenl.result +19 -0
  69. data/test/data/faq/ex3.rb +4 -0
  70. data/test/data/faq/ex3.rbhtml +1 -0
  71. data/test/data/faq/ex3_escapefunc1.result +2 -0
  72. data/test/data/faq/ex3_escapefunc2.result +2 -0
  73. data/test/data/faq/ex5.rbhtml +7 -0
  74. data/test/data/faq/ex5_template_args.source +9 -0
  75. data/test/data/faq/ex6-content.rhtml +6 -0
  76. data/test/data/faq/ex6-layout.rhtml +6 -0
  77. data/test/data/faq/ex6.rb +10 -0
  78. data/test/data/faq/ex6_eruby.result +12 -0
  79. data/test/data/faq/ex7-expr-pattern.rb +34 -0
  80. data/test/data/faq/ex7-expr-pattern.rbhtml +3 -0
  81. data/test/data/faq/ex7_expr_pattern.result +4 -0
  82. data/test/data/faq/ex8-m18n.rb +77 -0
  83. data/test/data/faq/ex8-m18n.rbhtml +4 -0
  84. data/test/data/faq/ex8_m18n.result +10 -0
  85. data/test/data/faq/ex9-baselayout.rbhtml +8 -0
  86. data/test/data/faq/ex9-content.rbhtml +6 -0
  87. data/test/data/faq/ex9-mylayout.rbhtml +5 -0
  88. data/test/data/faq/ex9_changelayout.result +11 -0
  89. data/test/data/users_guide/content6.rbhtml +3 -0
  90. data/test/data/users_guide/content7.rbhtml +5 -0
  91. data/test/data/users_guide/content8.rbhtml +2 -0
  92. data/test/data/users_guide/contextdata.rb +7 -0
  93. data/test/data/users_guide/datafile.rb +5 -0
  94. data/test/data/users_guide/datafile.yaml +10 -0
  95. data/test/data/users_guide/ex.rbhtml +6 -0
  96. data/test/data/users_guide/ex.result +7 -0
  97. data/test/data/users_guide/ex.script +5 -0
  98. data/test/data/users_guide/ex_script.result +7 -0
  99. data/test/data/users_guide/ex_source.result +8 -0
  100. data/test/data/users_guide/example1.rbhtml +12 -0
  101. data/test/data/users_guide/example1.result +17 -0
  102. data/test/data/users_guide/example10.rbhtml +4 -0
  103. data/test/data/users_guide/example10_template_args.result +6 -0
  104. data/test/data/users_guide/example11.rbhtml +5 -0
  105. data/test/data/users_guide/example11_template_args_result +2 -0
  106. data/test/data/users_guide/example12.rbhtml +12 -0
  107. data/test/data/users_guide/example12_preprocessed.result +10 -0
  108. data/test/data/users_guide/example12_preprocessed_source.result +10 -0
  109. data/test/data/users_guide/example13.rbhtml +6 -0
  110. data/test/data/users_guide/example13_preprocessed.result +2 -0
  111. data/test/data/users_guide/example13_preprocessed_source.result +2 -0
  112. data/test/data/users_guide/example14.rb +32 -0
  113. data/test/data/users_guide/example14.rbhtml +6 -0
  114. data/test/data/users_guide/example14_tmplclass.result +15 -0
  115. data/test/data/users_guide/example15.rb +10 -0
  116. data/test/data/users_guide/example15_escapefunc.result +14 -0
  117. data/test/data/users_guide/example16.rbhtml +4 -0
  118. data/test/data/users_guide/example16a.rb +10 -0
  119. data/test/data/users_guide/example16a.result +4 -0
  120. data/test/data/users_guide/example16b.rb +13 -0
  121. data/test/data/users_guide/example16b.result +4 -0
  122. data/test/data/users_guide/example16c.rb +12 -0
  123. data/test/data/users_guide/example16c.result +4 -0
  124. data/test/data/users_guide/example1_S.result +14 -0
  125. data/test/data/users_guide/example1_SXNC.result +10 -0
  126. data/test/data/users_guide/example1_source.result +14 -0
  127. data/test/data/users_guide/example2.rbhtml +3 -0
  128. data/test/data/users_guide/example2_sb.result2 +9 -0
  129. data/test/data/users_guide/example3.rbhtml +5 -0
  130. data/test/data/users_guide/example3_syntaxcheck.result +2 -0
  131. data/test/data/users_guide/example4.rbhtml +13 -0
  132. data/test/data/users_guide/example4_datafile_rb.result +13 -0
  133. data/test/data/users_guide/example4_yaml.result +13 -0
  134. data/test/data/users_guide/example5.rbhtml +9 -0
  135. data/test/data/users_guide/example5_datastr_rb.result +9 -0
  136. data/test/data/users_guide/example5_datastr_yaml.result +9 -0
  137. data/test/data/users_guide/example6.rbhtml +19 -0
  138. data/test/data/users_guide/example6_layout.result +29 -0
  139. data/test/data/users_guide/example6_nested.result +28 -0
  140. data/test/data/users_guide/example7_layout2.result +13 -0
  141. data/test/data/users_guide/example8_layout3.result +8 -0
  142. data/test/data/users_guide/example9.rbhtml +18 -0
  143. data/test/data/users_guide/example9_capture.result +26 -0
  144. data/test/data/users_guide/footer.html +5 -0
  145. data/test/data/users_guide/footer.rbhtml +4 -0
  146. data/test/data/users_guide/layout6.rbhtml +17 -0
  147. data/test/data/users_guide/layout7.rbhtml +9 -0
  148. data/test/data/users_guide/layout8_html.rbhtml +5 -0
  149. data/test/data/users_guide/layout8_xhtml.rbhtml +6 -0
  150. data/test/data/users_guide/layout9.rbhtml +25 -0
  151. data/test/data/users_guide/sidemenu.rbhtml +5 -0
  152. data/test/data/users_guide/user_app.cgi +39 -0
  153. data/test/data/users_guide/user_app.result +30 -0
  154. data/test/data/users_guide/user_create.rbhtml +6 -0
  155. data/test/data/users_guide/user_edit.rbhtml +7 -0
  156. data/test/data/users_guide/user_form.rbhtml +10 -0
  157. data/test/data/users_guide/user_layout.rbhtml +16 -0
  158. data/test/test_all.rb +23 -0
  159. data/test/test_engine.rb +526 -0
  160. data/test/test_engine.yaml +2039 -0
  161. data/test/test_examples.rb +81 -0
  162. data/test/test_faq.rb +60 -0
  163. data/test/test_htmlhelper.rb +78 -0
  164. data/test/test_main.rb +564 -0
  165. data/test/test_main.yaml +174 -0
  166. data/test/test_template.rb +113 -0
  167. data/test/test_template.yaml +1244 -0
  168. data/test/test_users_guide.rb +75 -0
  169. data/test/testcase-helper.rb +166 -0
  170. metadata +226 -0
@@ -0,0 +1,9 @@
1
+ <table>
2
+ <tbody>
3
+ <?rb for i in (1..100) ?>
4
+ <tr id="row#{i}">
5
+ <td>#{i}</td>
6
+ </tr>
7
+ <?rb end ?>
8
+ </tbody>
9
+ </table>
@@ -0,0 +1,5 @@
1
+ <html>
2
+ <body>
3
+ #{@_content}
4
+ </body>
5
+ </html>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <body>
3
+ <?rb _buf << @_content ?>
4
+
5
+ </body>
6
+ </html>
@@ -0,0 +1,5 @@
1
+ require 'tenjin'
2
+ engine = Tenjin::Engine.new(:templateclass=>Tenjin::ArrayBufferTemplate)
3
+ context = { :items=>['AAA', 'BBB', 'CCC'] }
4
+ output = engine.render('ex11.rbhtml', context)
5
+ puts output
@@ -0,0 +1,8 @@
1
+ <table>
2
+ <?rb @items.each_with_index do |item, i| ?>
3
+ <tr>
4
+ <td>#{i}</td>
5
+ <td>${item}</td>
6
+ </tr>
7
+ <?rb end ?>
8
+ </table>
@@ -0,0 +1,11 @@
1
+ $ rbtenjin -s --templateclass=Tenjin::ArrayBufferTemplate ex11.rbhtml
2
+ _buf = []; _buf.push('<table>
3
+ '); @items.each_with_index do |item, i|
4
+ _buf.push(' <tr>
5
+ <td>', (i).to_s, '</td>
6
+ <td>', escape((item).to_s), '</td>
7
+ </tr>
8
+ '); end
9
+ _buf.push('</table>
10
+ ');
11
+ _buf.to_s
@@ -0,0 +1,15 @@
1
+ $ ruby ex11.rb
2
+ <table>
3
+ <tr>
4
+ <td>0</td>
5
+ <td>AAA</td>
6
+ </tr>
7
+ <tr>
8
+ <td>1</td>
9
+ <td>BBB</td>
10
+ </tr>
11
+ <tr>
12
+ <td>2</td>
13
+ <td>CCC</td>
14
+ </tr>
15
+ </table>
@@ -0,0 +1,3 @@
1
+ $ rbtenjin -wz ex1.rbhtml
2
+ ex1.rbhtml:4: syntax error, unexpected kEND, expecting '}'
3
+ ex1.rbhtml:5: syntax error, unexpected $end, expecting '}'
@@ -0,0 +1,3 @@
1
+ foo
2
+ bar
3
+ baz
@@ -0,0 +1,11 @@
1
+ <!-- -->
2
+ #{@_content}
3
+ <!-- -->
4
+
5
+ <!-- -->
6
+ <?rb echo(@_content) ?>
7
+ <!-- -->
8
+
9
+ <!-- -->
10
+ <?rb _buf << @_content ?>
11
+ <!-- -->
@@ -0,0 +1,19 @@
1
+ $ rbtenjin --layout=ex2-layout.rbhtml ex2-content.rbhtml
2
+ <!-- -->
3
+ foo
4
+ bar
5
+ baz
6
+
7
+ <!-- -->
8
+
9
+ <!-- -->
10
+ foo
11
+ bar
12
+ baz
13
+ <!-- -->
14
+
15
+ <!-- -->
16
+ foo
17
+ bar
18
+ baz
19
+ <!-- -->
@@ -0,0 +1,4 @@
1
+ require 'tenjin'
2
+ engine = Tenjin::Engine.new(:escapefunc=>'CGI.escapeHTML')
3
+ template = engine.get_template('ex3.rbhtml')
4
+ print template.script
@@ -0,0 +1 @@
1
+ Hello ${@name}!
@@ -0,0 +1,2 @@
1
+ $ ruby ex3.rb
2
+ _buf << %Q`Hello #{CGI.escapeHTML((@name).to_s)}!\n`
@@ -0,0 +1,2 @@
1
+ $ rbtenjin -sb --escapefunc=CGI.escapeHTML ex3.rbhtml
2
+ _buf << %Q`Hello #{CGI.escapeHTML((@name).to_s)}!\n`
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0 ?>
2
+ <?rb #@ARGS x, y ?>
3
+ <p>
4
+ x = #{x}
5
+ y = #{y}
6
+ z = #{z}
7
+ </p>
@@ -0,0 +1,9 @@
1
+ $ rbtenjin -s ex5.rbhtml
2
+ _buf = ''; _buf << %Q`<?xml version="1.0 ?>\n`
3
+ x = @x; y = @y;
4
+ _buf << %Q`<p>
5
+ x = #{x}
6
+ y = #{y}
7
+ z = #{z}
8
+ </p>\n`
9
+ _buf.to_s
@@ -0,0 +1,6 @@
1
+ <% @title = 'eRuby template example' %>
2
+ <ul>
3
+ <% for item in @items %>
4
+ <li><%=h item %></li>
5
+ <% end %>
6
+ </ul>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <body>
3
+ <h1><%=h @title %></h1>
4
+ <%= @_content %>
5
+ </body>
6
+ </html>
@@ -0,0 +1,10 @@
1
+ require 'erubis'
2
+ require 'tenjin'
3
+
4
+ include Erubis::XmlHelper
5
+
6
+ context = { :items => ['<AAA>', 'B&B', '"CCC"'] }
7
+ engine = Tenjin::Engine.new(:layout=>'ex6-layout.rhtml',
8
+ :templateclass=>Tenjin::ErubisTemplate)
9
+ output = engine.render('ex6-content.rhtml', context)
10
+ print output
@@ -0,0 +1,12 @@
1
+ $ ruby ex6.rb
2
+ <html>
3
+ <body>
4
+ <h1>eRuby template example</h1>
5
+ <ul>
6
+ <li>&lt;AAA&gt;</li>
7
+ <li>B&amp;B</li>
8
+ <li>&quot;CCC&quot;</li>
9
+ </ul>
10
+
11
+ </body>
12
+ </html>
@@ -0,0 +1,34 @@
1
+ require 'tenjin'
2
+
3
+ class MyTemplate < Tenjin::Template
4
+
5
+ ## return pattern object for embedded expressions
6
+ def expr_pattern()
7
+ return /([$#])\{(.*?)\}|<%=(.*?)%>/m
8
+ end
9
+
10
+ ## if you don't use '#{...}', you must escape '#' in addition to '\\' and '`'
11
+ #def escape_str(str)
12
+ # return str.gsub(/[\\`\#]/, '\\\\\&')
13
+ #end
14
+
15
+ ## return expression string and flag whether escape or not from matched object
16
+ def get_expr_and_escapeflag(match)
17
+ if match[1]
18
+ expr = match[2]
19
+ escapeflag = match[1] == '$'
20
+ else
21
+ expr = match[3].strip()
22
+ escapeflag = false
23
+ end
24
+ return expr, escapeflag
25
+ end
26
+
27
+ end
28
+
29
+ if __FILE__ == $0
30
+ context = { :value => 'AAA&BBB' }
31
+ engine = Tenjin::Engine.new(:templateclass=>MyTemplate)
32
+ output = engine.render('ex7-expr-pattern.rbhtml', context)
33
+ puts output
34
+ end
@@ -0,0 +1,3 @@
1
+ <p>HTML escaped: ${@value}</p>
2
+ <p>not escaped: #{@value}</p>
3
+ <p>not escaped: <%= @value %></p>
@@ -0,0 +1,4 @@
1
+ $ ruby ex7-expr-pattern.rb
2
+ <p>HTML escaped: AAA&amp;BBB</p>
3
+ <p>not escaped: AAA&BBB</p>
4
+ <p>not escaped: AAA&BBB</p>
@@ -0,0 +1,77 @@
1
+ require 'tenjin'
2
+
3
+ ##
4
+ ## message catalog to translate message
5
+ ##
6
+ MESSAGE_CATALOG = {
7
+ 'en' => { 'Hello' => 'Hello',
8
+ 'Good bye'=> 'Good bye', },
9
+ 'fr' => { 'Hello' => 'Bonjour',
10
+ 'Good bye'=> 'Au revoir', },
11
+ }
12
+
13
+
14
+ ##
15
+ ## add translation method to Context class
16
+ ##
17
+ class Tenjin::Context
18
+
19
+ def _(message_key)
20
+ message_dict = MESSAGE_CATALOG[@_lang]
21
+ return message_key unless message_dict
22
+ return message_dict[message_key] || message_key
23
+ end
24
+
25
+ end
26
+
27
+
28
+ ##
29
+ ## engine class which supports M17N
30
+ ##
31
+ class M17NEngine < Tenjin::Engine
32
+
33
+ attr_accessor :lang
34
+
35
+ ## constructor takes ':lang' options
36
+ def initialize(properties={})
37
+ super(properties)
38
+ @lang = properties[:lang] || 'en' # set language
39
+ end
40
+
41
+ ## change cache filename to 'file.html.lang.cache'
42
+ def cachename(filename)
43
+ return "#{filename}.#{@lang}.cache"
44
+ end
45
+
46
+ ## set language to context object
47
+ def hook_context(context)
48
+ context = super(context)
49
+ context['_lang'] = @lang
50
+ return context
51
+ end
52
+
53
+ end
54
+
55
+
56
+ ##
57
+ ## test program
58
+ ##
59
+ if $0 == __FILE__
60
+
61
+ template_name = 'ex8-m18n.rbhtml'
62
+ context = { :username => 'World' }
63
+
64
+ ## engine for english
65
+ engine = M17NEngine.new(:preprocess=>true)
66
+ output = engine.render(template_name, context) # same template
67
+ puts "--- lang: %s ---" % engine.lang
68
+ puts output
69
+ puts
70
+
71
+ ## engine for French
72
+ engine = M17NEngine.new(:preprocess=>true, :lang=>'fr')
73
+ output = engine.render(template_name, context) # same template
74
+ puts "--- lang: %s ---" % engine.lang
75
+ puts output
76
+
77
+ end
@@ -0,0 +1,4 @@
1
+ <div>
2
+ <?RB ## '_()' represents translator method ?>
3
+ <p>${{_('Hello')}} ${@username}!</p>
4
+ </div>
@@ -0,0 +1,10 @@
1
+ $ ruby ex8-m18n.rb
2
+ --- lang: en ---
3
+ <div>
4
+ <p>Hello World!</p>
5
+ </div>
6
+
7
+ --- lang: fr ---
8
+ <div>
9
+ <p>Bonjour World!</p>
10
+ </div>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <body>
3
+ <?rb if @title ?>
4
+ <h1>${@title}</h1>
5
+ <?rb end ?>
6
+ <?rb _buf << @_content ?>
7
+ </body>
8
+ </html>
@@ -0,0 +1,6 @@
1
+ <?rb @title = 'Changing Layout Template Test' ?>
2
+ <?rb ## specify layout template name ?>
3
+ <?rb @_layout = 'ex9-mylayout.rbhtml' ?>
4
+ foo
5
+ bar
6
+ baz
@@ -0,0 +1,5 @@
1
+ <?rb ## use default layout template name ?>
2
+ <?rb @_layout = true ?>
3
+ <div id="content">
4
+ <?rb _buf << @_content ?>
5
+ </div>
@@ -0,0 +1,11 @@
1
+ $ rbtenjin --layout=ex9-baselayout.rbhtml ex9-content.rbhtml
2
+ <html>
3
+ <body>
4
+ <h1>Changing Layout Template Test</h1>
5
+ <div id="content">
6
+ foo
7
+ bar
8
+ baz
9
+ </div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,3 @@
1
+ <?rb for item in @items ?>
2
+ <p>${item}</p>
3
+ <?rb end ?>
@@ -0,0 +1,5 @@
1
+ <?rb @title = 'Document Title' ?>
2
+ <?rb @url = '/next/page' ?>
3
+ <table>
4
+ ...content...
5
+ </table>
@@ -0,0 +1,2 @@
1
+ <?rb @_layout = :layout8_xhtml ?>
2
+ <h1>Hello World!</h1>
@@ -0,0 +1,7 @@
1
+ @items = [ '<FOO>', '&BAR', '"BAZ"' ]
2
+ @webmaster_email = 'webmaster@example.com'
3
+ @menu = [
4
+ {'name'=> 'Top', 'url'=> '/' },
5
+ {'name'=> 'Products', 'url'=> '/prod' },
6
+ {'name'=> 'Support', 'url'=> '/support' },
7
+ ]
@@ -0,0 +1,5 @@
1
+ @text = "foo"
2
+ @num = 3.14
3
+ @flag = true
4
+ @items = ["foo", "bar", "baz"]
5
+ @hash = {:x=>1, :y=>2}
@@ -0,0 +1,10 @@
1
+ text: foo
2
+ num: 3.14
3
+ flag: yes
4
+ items:
5
+ - foo
6
+ - bar
7
+ - baz
8
+ hash:
9
+ x: 1
10
+ y: 2
@@ -0,0 +1,6 @@
1
+ Hello #{@name}!
2
+ <ul>
3
+ <?rb for item in @items ?>
4
+ <li>${item}</li>
5
+ <?rb end ?>
6
+ </ul>
@@ -0,0 +1,7 @@
1
+ $ rbtenjin -c "@name='World'; @items=['<AAA>','B&B','\"CCC\"']" ex.rbhtml
2
+ Hello World!
3
+ <ul>
4
+ <li>&lt;AAA&gt;</li>
5
+ <li>B&amp;B</li>
6
+ <li>&quot;CCC&quot;</li>
7
+ </ul>