slim 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11a9cb2acf2b4cdc15e88f19f4b83e7b4ac35ef2bcfe3cce9faff694cd08a761
4
- data.tar.gz: 4f097cd7b0c48768b8be27c1d3983826bbdb0dd370b4e617667a6c2b5da7b05e
3
+ metadata.gz: 7876d1b9fd825ae7f0afc3a94ceae2464b34d14a74018ad90f812b512d8cc4c0
4
+ data.tar.gz: b522e774b1d808a57842796a414df8f9380ea8b24491d3799a1bd237c5ba71d1
5
5
  SHA512:
6
- metadata.gz: 2eedadac31b851ef0c1d5552c5f199a36ff11cb4a6b6ac8c80b0c0725e81404327b1edc2d43c01033dcb47d5eefbb7145d989ac3619aa635cd9903d390998d2c
7
- data.tar.gz: 71ea954ab4041ee8b02f39e056c4954d0ed814b8eaf9e368a48d5a639a314825717996e263bdab0c414c63143a0fe8de1aed29d3ce68c37ebc6a591e1829750e
6
+ metadata.gz: db31ed4b35df749588fb4acf91e7180c8971931c3647b754afbcaf4f2c654aa65b908e1af13f86a68510a00774cddb2e23fc28eae56f60d0ba13b63c0df4fc12
7
+ data.tar.gz: 77494b4cdac5ecb85d1ba4d569adcba6ebe01fb4024e5a4a02da4db6f96bf5af10919365af57783ad88b79ddcef75e113af20412225ab3166b2948f1a3967b3c
data/CHANGES CHANGED
@@ -1,3 +1,11 @@
1
+ 5.1.0 (2023-03-06)
2
+
3
+ * Allow whitespace markers for verbatim text: `|<`, `|>`, and `|<>` - #912
4
+ * Do not swallow single quote after output line indicator - #911
5
+ * Support Tilt 2.1.0 - #910
6
+ * Fix Railtie load error - #904
7
+ * Fix attribute parsing with square brackets - #796
8
+
1
9
  5.0.0 (2023-01-23)
2
10
 
3
11
  * Fix markdown interpolation #773
data/Gemfile CHANGED
@@ -2,11 +2,10 @@ source 'https://rubygems.org/'
2
2
 
3
3
  gemspec
4
4
 
5
- group :perf do
6
- gem 'benchmark-ips'
7
- gem 'erubi'
8
- gem 'haml'
9
- end
5
+ gem 'test-unit', '~> 3.5'
6
+ gem 'minitest', '~> 5.15'
7
+ gem 'rake', '~> 13.0'
8
+ gem 'kramdown', '~> 2.4'
10
9
 
11
10
  if ENV['TEMPLE'] && ENV['TEMPLE'] != 'master'
12
11
  gem 'temple', "= #{ENV['TEMPLE']}"
@@ -34,11 +33,6 @@ if ENV['RAILS']
34
33
  end
35
34
  end
36
35
 
37
- gem 'test-unit', '~> 3.5'
38
- gem 'minitest', '~> 5.15'
39
- gem 'rake', '~> 13.0'
40
- gem 'kramdown', '~> 2.4'
41
-
42
36
  if ENV['SINATRA']
43
37
  gem 'rack-test'
44
38
 
@@ -48,13 +42,3 @@ if ENV['SINATRA']
48
42
  gem 'sinatra', :tag => "v#{ENV['SINATRA']}"
49
43
  end
50
44
  end
51
-
52
- if ENV['TASK'] == 'bench'
53
- gem 'benchmark-ips'
54
- gem 'erubi'
55
- gem 'haml'
56
- end
57
-
58
- if ENV['CODECLIMATE_REPO_TOKEN']
59
- gem 'codeclimate-test-reporter'
60
- end
data/README.jp.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://img.shields.io/gem/v/slim.svg)](http://rubygems.org/gems/slim)
4
4
  ![Build Status](https://github.com/slim-template/slim/actions/workflows/test.yml/badge.svg)
5
- [![Code Climate](https://codeclimate.com/github/slim-template/slim/badges/gpa.svg)](https://codeclimate.com/github/slim-template/slim)
6
- [![Test Coverage](https://codeclimate.com/github/slim-template/slim/badges/coverage.svg)](https://codeclimate.com/github/slim-template/slim/coverage)
7
5
  [![GitHub Sponsors](https://img.shields.io/github/sponsors/slim-template)](https://github.com/sponsors/slim-template)
8
6
 
9
7
  Slim は 不可解にならない程度に view の構文を本質的な部品まで減らすことを目指したテンプレート言語です。標準的な HTML テンプレートからどれだけのものを減らせるか、検証するところから始まりました。(<, >, 閉じタグなど) 多くの人が Slim に興味を持ったことで, 機能的で柔軟な構文に成長しました。
data/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://img.shields.io/gem/v/slim.svg)](http://rubygems.org/gems/slim)
4
4
  ![Build Status](https://github.com/slim-template/slim/actions/workflows/test.yml/badge.svg)
5
- [![Code Climate](https://codeclimate.com/github/slim-template/slim/badges/gpa.svg)](https://codeclimate.com/github/slim-template/slim)
6
- [![Test Coverage](https://codeclimate.com/github/slim-template/slim/badges/coverage.svg)](https://codeclimate.com/github/slim-template/slim/coverage)
7
5
  [![GitHub Sponsors](https://img.shields.io/github/sponsors/slim-template)](https://github.com/sponsors/slim-template)
8
6
 
9
7
  Slim is a template language whose goal is to reduce the view syntax to the essential parts without becoming cryptic. It started as an exercise to see how much could be removed from a standard html template (<, >, closing tags, etc...). As more people took an interest in Slim, the functionality grew and so did the flexibility of the syntax.
@@ -155,6 +153,17 @@ You can also embed html in the text line
155
153
  | <tr><td>#{a.name}</td><td>#{a.description}</td></tr>
156
154
  ~~~
157
155
 
156
+ #### Verbatim text with leading and/or treailing white space `|<` `|>` `|<>`
157
+
158
+ You can add white space around verbatim text in the same way as for `=` output:
159
+ ~~~ slim
160
+ | This line will not have any extra white space.
161
+ | This line will have a leading space, but it is difficult to see.
162
+ |< This line will have a leading white space.
163
+ |> This line will have a trailing white space.
164
+ |<> This line will have both leading and trailing white space.
165
+ ~~~
166
+
158
167
  ### Verbatim text with trailing white space `'`
159
168
 
160
169
  The single quote tells Slim to copy the line (similar to `|`), but makes sure that a single trailing white space is appended.
data/Rakefile CHANGED
@@ -6,11 +6,6 @@ end
6
6
 
7
7
  require 'rake/testtask'
8
8
 
9
- desc 'Run Slim benchmarks! (default parameters slow=false)'
10
- task :bench, :slow do
11
- ruby('benchmarks/run-benchmarks.rb')
12
- end
13
-
14
9
  task 'test' => %w(test:core test:literate test:logic_less test:translator test:smart test:include)
15
10
 
16
11
  namespace 'test' do
data/lib/slim/parser.rb CHANGED
@@ -79,7 +79,7 @@ module Slim
79
79
  @attr_list_delims_re = /\A\s*([#{keys}])/
80
80
  @embedded_re = /\A(#{Regexp.union(Embedded.engines.keys.map(&:to_s))})(?:\s*(?:(.*)))?:(\s*)/
81
81
  keys = Regexp.escape ('"\'></='.split(//) + @attr_list_delims.flatten + @code_attr_delims.flatten).uniq.join
82
- @attr_name = "\\A\\s*([^\0\s#{keys}]+)"
82
+ @attr_name = "\\A\\s*([^\\0\\s#{keys}]+)"
83
83
  @quoted_attr_re = /#{@attr_name}\s*=(=?)\s*("|')/
84
84
  @code_attr_re = /#{@attr_name}\s*=(=?)\s*/
85
85
 
@@ -209,10 +209,12 @@ module Slim
209
209
  when /\A\//
210
210
  # Slim comment
211
211
  parse_comment_block
212
- when /\A([\|'])( ?)/
212
+ when /\A([\|'])([<>]{1,2}(?: |\z)| ?)/
213
213
  # Found verbatim text block.
214
- trailing_ws = $1 == "'"
215
- @stacks.last << [:slim, :text, :verbatim, parse_text_block($', @indents.last + $2.size + 1)]
214
+ leading_ws = $2.include?('<'.freeze)
215
+ trailing_ws = ($1 == "'") || $2.include?('>'.freeze)
216
+ @stacks.last << [:static, ' '] if leading_ws
217
+ @stacks.last << [:slim, :text, :verbatim, parse_text_block($', @indents.last + $2.count(' ') + 1)]
216
218
  @stacks.last << [:static, ' '] if trailing_ws
217
219
  when /\A</
218
220
  # Inline html
@@ -226,13 +228,14 @@ module Slim
226
228
  block = [:multi]
227
229
  @stacks.last << [:slim, :control, parse_broken_line, block]
228
230
  @stacks << block
229
- when /\A=(=?)(['<>]*)/
231
+ when /\A=(=?)([<>]*)/
230
232
  # Found an output block.
231
233
  # We expect the line to be broken or the next line to be indented.
232
234
  @line = $'
235
+ leading_ws = $2.include?('<'.freeze)
233
236
  trailing_ws = $2.include?('>'.freeze)
234
237
  block = [:multi]
235
- @stacks.last << [:static, ' '] if $2.include?('<'.freeze)
238
+ @stacks.last << [:static, ' '] if leading_ws
236
239
  @stacks.last << [:slim, :output, $1.empty?, parse_broken_line, block]
237
240
  @stacks.last << [:static, ' '] if trailing_ws
238
241
  @stacks << block
data/lib/slim/railtie.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Slim
2
- class Railtie < Rails::Railtie
2
+ class Railtie < ::Rails::Railtie
3
3
  initializer "initialize slim template handler" do
4
4
  ActiveSupport.on_load(:action_view) do
5
5
  Slim::RailsTemplate = Temple::Templates::Rails(Slim::Engine,
data/lib/slim/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Slim
2
2
  # Slim version string
3
3
  # @api public
4
- VERSION = '5.0.0'
4
+ VERSION = '5.1.0'
5
5
  end
data/slim.gemspec CHANGED
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.required_ruby_version = '>= 2.5.0'
20
20
 
21
21
  s.add_runtime_dependency('temple', ['~> 0.10.0'])
22
- s.add_runtime_dependency('tilt', ['>= 2.0.6', '< 2.1'])
22
+ s.add_runtime_dependency('tilt', ['>= 2.0.6', '< 2.2'])
23
23
  end
@@ -311,6 +311,12 @@ p[id="marvin" class="martian" data-info="Illudium Q-36"] = output_number
311
311
  assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">1337</p>', source
312
312
  end
313
313
 
314
+ # Regression test for bug #796
315
+ def test_square_brackets_around_attributes_multiline_with_tabs
316
+ source = "div\n\tp[\n\t\tclass=\"martian\"\n\t]\n\tp Next line"
317
+ assert_html '<div><p class="martian"></p><p>Next line</p></div>', source
318
+ end
319
+
314
320
  def test_parens_around_attributes_with_equal_sign_snug_to_right_paren
315
321
  source = %q{
316
322
  p(id="marvin" class="martian" data-info="Illudium Q-36")= output_number
@@ -27,6 +27,22 @@ renders as
27
27
  Text block
28
28
  ~~~
29
29
 
30
+ You can add leading or trailing white space with the `<` and `>` markers:
31
+
32
+ ~~~ slim
33
+ |< Text with leading whitespace.
34
+ | Text with leading whitespace.
35
+ |> Text with trailing whitespace.
36
+ |<> Text with both leading and trailing whitespace.
37
+ ~~~
38
+
39
+ renders as
40
+
41
+ ~~~ html
42
+ Text with leading whitespace. Text with leading whitespace.Text with trailing whitespace. Text with both leading and trailing whitespace.
43
+ ~~~
44
+
45
+
30
46
  Multiple lines can be indented beneath the first text line.
31
47
 
32
48
  ~~~ slim
@@ -77,6 +93,30 @@ Text
77
93
  lines
78
94
  ~~~
79
95
 
96
+ ~~~ slim
97
+ |><
98
+
99
+ Text
100
+ block
101
+
102
+ with
103
+
104
+ multiple
105
+ lines
106
+ ~~~
107
+
108
+ renders as
109
+
110
+ ~~~ html
111
+ Text
112
+ block
113
+
114
+ with
115
+
116
+ multiple
117
+ lines
118
+ ~~~
119
+
80
120
  You can nest text blocks beneath tags.
81
121
 
82
122
  ~~~ slim
@@ -104,6 +144,16 @@ renders as
104
144
  <a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>
105
145
  ~~~
106
146
 
147
+ ~~~ slim
148
+ |<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>
149
+ ~~~
150
+
151
+ renders as
152
+
153
+ ~~~ html
154
+ <a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>
155
+ ~~~
156
+
107
157
  ### Text with trailing white space `'`
108
158
 
109
159
  A text blocks with trailing white space starts with the `'` as line indicator.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slim
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-01-23 00:00:00.000000000 Z
13
+ date: 2023-03-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: temple
@@ -35,7 +35,7 @@ dependencies:
35
35
  version: 2.0.6
36
36
  - - "<"
37
37
  - !ruby/object:Gem::Version
38
- version: '2.1'
38
+ version: '2.2'
39
39
  type: :runtime
40
40
  prerelease: false
41
41
  version_requirements: !ruby/object:Gem::Requirement
@@ -45,7 +45,7 @@ dependencies:
45
45
  version: 2.0.6
46
46
  - - "<"
47
47
  - !ruby/object:Gem::Version
48
- version: '2.1'
48
+ version: '2.2'
49
49
  description: Slim is a template language whose goal is reduce the syntax to the essential
50
50
  parts without becoming cryptic.
51
51
  email:
@@ -66,14 +66,6 @@ files:
66
66
  - README.jp.md
67
67
  - README.md
68
68
  - Rakefile
69
- - benchmarks/context.rb
70
- - benchmarks/profile-parser.rb
71
- - benchmarks/profile-render.rb
72
- - benchmarks/run-benchmarks.rb
73
- - benchmarks/run-diffbench.rb
74
- - benchmarks/view.erb
75
- - benchmarks/view.haml
76
- - benchmarks/view.slim
77
69
  - bin/slimrb
78
70
  - doc/include.md
79
71
  - doc/jp/include.md
@@ -1,11 +0,0 @@
1
- class Context
2
- def header
3
- 'Colors'
4
- end
5
-
6
- def item
7
- [ { name: 'red', current: true, url: '#red' },
8
- { name: 'green', current: false, url: '#green' },
9
- { name: 'blue', current: false, url: '#blue' } ]
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
-
5
- require 'slim'
6
-
7
- content = File.read(File.dirname(__FILE__) + '/view.slim')
8
- engine = Slim::Engine.new
9
-
10
- 1000.times { engine.call(content) }
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
-
5
- require 'slim'
6
- require 'context'
7
-
8
- content = File.read(File.dirname(__FILE__) + '/view.slim')
9
- slim = Slim::Template.new { content }
10
- context = Context.new
11
-
12
- 10000.times { slim.render(context) }
@@ -1,115 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
-
5
- require 'slim'
6
- require 'context'
7
-
8
- require 'benchmark/ips'
9
- require 'tilt'
10
- require 'erubi'
11
- require 'erb'
12
- require 'haml'
13
-
14
- class SlimBenchmarks
15
- def initialize(slow)
16
- @benches = Hash.new { |h, k| h[k] = [] }
17
-
18
- @erb_code = File.read(File.dirname(__FILE__) + '/view.erb')
19
- @haml_code = File.read(File.dirname(__FILE__) + '/view.haml')
20
- @slim_code = File.read(File.dirname(__FILE__) + '/view.slim')
21
-
22
- init_compiled_benches
23
- init_tilt_benches
24
- init_parsing_benches if slow
25
- end
26
-
27
- def init_compiled_benches
28
- context = Context.new
29
-
30
- context.instance_eval %{
31
- def run_erb; #{ERB.new(@erb_code).src}; end
32
- def run_erubi; #{Erubi::Engine.new(@erb_code).src}; end
33
- def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end
34
- def run_slim_pretty; #{Slim::Engine.new(pretty: true).call @slim_code}; end
35
- def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end
36
- def run_haml; #{Haml::Engine.new.call @haml_code}; end
37
- }
38
-
39
- bench(:compiled, 'erb') { context.run_erb }
40
- bench(:compiled, 'erubi') { context.run_erubi }
41
- bench(:compiled, 'temple erb') { context.run_temple_erb }
42
- bench(:compiled, 'slim pretty') { context.run_slim_pretty }
43
- bench(:compiled, 'slim ugly') { context.run_slim_ugly }
44
- bench(:compiled, 'haml') { context.run_haml }
45
- end
46
-
47
- def init_tilt_benches
48
- tilt_erb = Tilt::ERBTemplate.new { @erb_code }
49
- tilt_erubi = Tilt::ErubiTemplate.new { @erb_code }
50
- tilt_temple_erb = Temple::ERB::Template.new { @erb_code }
51
- tilt_haml = Tilt::HamlTemplate.new(format: :html5) { @haml_code }
52
- tilt_slim_pretty = Slim::Template.new(pretty: true) { @slim_code }
53
- tilt_slim_ugly = Slim::Template.new { @slim_code }
54
-
55
- context = Context.new
56
-
57
- bench(:tilt, 'erb') { tilt_erb.render(context) }
58
- bench(:tilt, 'erubi') { tilt_erubi.render(context) }
59
- bench(:tilt, 'temple erb') { tilt_temple_erb.render(context) }
60
- bench(:tilt, 'slim pretty') { tilt_slim_pretty.render(context) }
61
- bench(:tilt, 'slim ugly') { tilt_slim_ugly.render(context) }
62
- bench(:tilt, 'haml') { tilt_haml.render(context) }
63
- end
64
-
65
- def init_parsing_benches
66
- context = Context.new
67
- context_binding = context.instance_eval { binding }
68
-
69
- bench(:parsing, 'erb') { ERB.new(@erb_code).result(context_binding) }
70
- bench(:parsing, 'erubi') { Erubi::Engine.new(@erb_code).result(context_binding) }
71
- bench(:parsing, 'temple erb') { Temple::ERB::Template.new { @erb_code }.render(context) }
72
- bench(:parsing, 'slim pretty') { Slim::Template.new(pretty: true) { @slim_code }.render(context) }
73
- bench(:parsing, 'slim ugly') { Slim::Template.new { @slim_code }.render(context) }
74
- bench(:parsing, 'haml') { Haml::Engine.new(@haml_code, format: :html5).render(context) }
75
- end
76
-
77
- def run
78
- @benches.each do |group_name, group_benches|
79
- puts "Running #{group_name} benchmarks:"
80
-
81
- Benchmark.ips do |x|
82
- group_benches.each do |name, block|
83
- x.report("#{group_name} #{name}", &block)
84
- end
85
-
86
- x.compare!
87
- end
88
- end
89
-
90
- puts "
91
- Compiled benchmark: Template is parsed before the benchmark and
92
- generated ruby code is compiled into a method.
93
- This is the fastest evaluation strategy because it benchmarks
94
- pure execution speed of the generated ruby code.
95
-
96
- Compiled Tilt benchmark: Template is compiled with Tilt, which gives a more
97
- accurate result of the performance in production mode in frameworks like
98
- Sinatra, Ramaze and Camping. (Rails still uses its own template
99
- compilation.)
100
-
101
- Parsing benchmark: Template is parsed every time.
102
- This is not the recommended way to use the template engine
103
- and Slim is not optimized for it. Activate this benchmark with 'rake bench slow=1'.
104
-
105
- Temple ERB is the ERB implementation using the Temple framework. It shows the
106
- overhead added by the Temple framework compared to ERB.
107
- "
108
- end
109
-
110
- def bench(group, name, &block)
111
- @benches[group].push([name, block])
112
- end
113
- end
114
-
115
- SlimBenchmarks.new(ENV['slow']).run
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
-
5
- require 'slim'
6
- require 'context'
7
- require 'diffbench'
8
-
9
- content = File.read(File.dirname(__FILE__) + '/view.slim')
10
- engine = Slim::Engine.new
11
- template = Slim::Template.new { content }
12
- context = Context.new
13
-
14
- DiffBench.bm do
15
- report("Parse") do
16
- 2000.times { engine.call(content) }
17
- end
18
- report("Render") do
19
- 100000.times { template.render(context) }
20
- end
21
- end
data/benchmarks/view.erb DELETED
@@ -1,25 +0,0 @@
1
- <!DOCTYPE HTML>
2
-
3
- <html lang="en">
4
- <head>
5
- <title>Simple Benchmark</title>
6
- <meta charset="utf-8">
7
- <meta name="description" content="This is an example of a meta description.">
8
- </head>
9
- <body>
10
- <h1><%= header %></h1>
11
- <% unless item.empty? %>
12
- <ul>
13
- <% for i in item %>
14
- <% if i[:current] %>
15
- <li><strong><%= i[:name] %></strong></li>
16
- <% else %>
17
- <li><a href="<%= i[:url] %>"><%= i[:name] %></a></li>
18
- <% end %>
19
- <% end %>
20
- </ul>
21
- <% else %>
22
- <p>The list is empty.</p>
23
- <% end %>
24
- </body>
25
- </html>
data/benchmarks/view.haml DELETED
@@ -1,20 +0,0 @@
1
- !!! html
2
-
3
- %html{ lang: "en" }
4
- %head
5
- %title Simple Benchmark
6
- %meta{ charset: "utf-8" }
7
- %meta{ name: "description", content: "This is an example of a meta description." }
8
- %body
9
- %h1= header
10
- - unless item.empty?
11
- %ul
12
- - for i in item
13
- - if i[:current]
14
- %li
15
- %strong= i[:name]
16
- - else
17
- %li
18
- %a{:href => i[:url]}= i[:name]
19
- - else
20
- %p The list is empty.
data/benchmarks/view.slim DELETED
@@ -1,19 +0,0 @@
1
- doctype html
2
- html lang="en"
3
- head
4
- title Simple Benchmark
5
- meta charset="utf-8"
6
- meta name="description" content="This is an example of a meta description."
7
- body
8
- h1 == header
9
- - unless item.empty?
10
- ul
11
- - for i in item
12
- - if i[:current]
13
- li
14
- strong == i[:name]
15
- - else
16
- li
17
- a href==i[:url] == i[:name]
18
- - else
19
- p The list is empty.