jekyll 1.2.1 → 1.3.0.rc

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/History.markdown +58 -0
  3. data/README.markdown +2 -1
  4. data/Rakefile +8 -1
  5. data/bin/jekyll +14 -17
  6. data/features/create_sites.feature +11 -0
  7. data/features/data.feature +65 -0
  8. data/features/include_tag.feature +13 -0
  9. data/features/site_configuration.feature +29 -0
  10. data/features/step_definitions/jekyll_steps.rb +27 -12
  11. data/features/support/env.rb +36 -0
  12. data/jekyll.gemspec +22 -10
  13. data/lib/jekyll.rb +2 -1
  14. data/lib/jekyll/cleaner.rb +8 -8
  15. data/lib/jekyll/commands/build.rb +14 -8
  16. data/lib/jekyll/commands/serve.rb +2 -0
  17. data/lib/jekyll/configuration.rb +5 -1
  18. data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -1
  19. data/lib/jekyll/convertible.rb +17 -6
  20. data/lib/jekyll/core_ext.rb +15 -0
  21. data/lib/jekyll/filters.rb +10 -0
  22. data/lib/jekyll/post.rb +2 -2
  23. data/lib/jekyll/site.rb +68 -19
  24. data/lib/jekyll/tags/gist.rb +9 -1
  25. data/lib/jekyll/tags/highlight.rb +1 -1
  26. data/lib/jekyll/tags/include.rb +72 -28
  27. data/lib/jekyll/tags/post_url.rb +4 -2
  28. data/lib/site_template/css/main.css +15 -15
  29. data/site/_includes/docs_contents.html +1 -1
  30. data/site/_includes/docs_contents_mobile.html +1 -1
  31. data/site/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown +19 -0
  32. data/site/docs/configuration.md +18 -0
  33. data/site/docs/datafiles.md +63 -0
  34. data/site/docs/installation.md +10 -0
  35. data/site/docs/migrations.md +12 -3
  36. data/site/docs/pagination.md +16 -37
  37. data/site/docs/plugins.md +66 -6
  38. data/site/docs/structure.md +17 -0
  39. data/site/docs/templates.md +31 -7
  40. data/site/docs/upgrading.md +3 -3
  41. data/site/docs/usage.md +1 -1
  42. data/site/docs/variables.md +2 -2
  43. data/test/helper.rb +4 -1
  44. data/test/source/_data/languages.yml +2 -0
  45. data/test/source/_data/members.yaml +7 -0
  46. data/test/source/_data/products.yml +4 -0
  47. data/test/source/_layouts/post/simple.html +1 -0
  48. data/test/source/products.yml +4 -0
  49. data/test/test_convertible.rb +1 -1
  50. data/test/test_filters.rb +11 -0
  51. data/test/test_kramdown.rb +32 -5
  52. data/test/test_site.rb +58 -1
  53. data/test/test_tags.rb +21 -23
  54. metadata +71 -27
@@ -182,51 +182,30 @@ page with links to all but the current page.
182
182
 
183
183
  {% highlight html %}
184
184
  {% raw %}
185
- <div id="post-pagination" class="pagination">
185
+ {% if paginator.total_pages > 1 %}
186
+ <div class="pagination">
186
187
  {% if paginator.previous_page %}
187
- <p class="previous">
188
- {% if paginator.previous_page == 1 %}
189
- <a href="/">Previous</a>
190
- {% else %}
191
- <a href="{{ paginator.previous_page_path }}">Previous</a>
192
- {% endif %}
193
- </p>
188
+ <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
194
189
  {% else %}
195
- <p class="previous disabled">
196
- <span>Previous</span>
197
- </p>
190
+ <span>&laquo; Prev</span>
198
191
  {% endif %}
199
192
 
200
- <ul class="pages">
201
- <li class="page">
202
- {% if paginator.page == 1 %}
203
- <span class="current-page">1</span>
204
- {% else %}
205
- <a href="/">1</a>
206
- {% endif %}
207
- </li>
208
-
209
- {% for count in (2..paginator.total_pages) %}
210
- <li class="page">
211
- {% if count == paginator.page %}
212
- <span class="current-page">{{ count }}</span>
213
- {% else %}
214
- <a href="/page{{ count }}">{{ count }}</a>
215
- {% endif %}
216
- </li>
217
- {% endfor %}
218
- </ul>
193
+ {% for page in (1..paginator.total_pages) %}
194
+ {% if page == paginator.page %}
195
+ <em>{{ page }}</em>
196
+ {% elsif page == 1 %}
197
+ <a href="{{ '/index.html' | prepend: site.baseurl | replace: '//', '/' }}">{{ page }}</a>
198
+ {% else %}
199
+ <a href="{{ site.paginate_path | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>
200
+ {% endif %}
201
+ {% endfor %}
219
202
 
220
203
  {% if paginator.next_page %}
221
- <p class="next">
222
- <a href="{{ paginator.next_page_path }}">Next</a>
223
- </p>
204
+ <a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
224
205
  {% else %}
225
- <p class="next disabled">
226
- <span>Next</span>
227
- </p>
206
+ <span>Next &raquo;</span>
228
207
  {% endif %}
229
-
230
208
  </div>
209
+ {% endif %}
231
210
  {% endraw %}
232
211
  {% endhighlight %}
@@ -25,9 +25,27 @@ having to modify the Jekyll source itself.
25
25
 
26
26
  ## Installing a plugin
27
27
 
28
- In your site source root, make a `_plugins` directory. Place your plugins here.
29
- Any file ending in `*.rb` inside this directory will be loaded before Jekyll
30
- generates your site.
28
+ You have 2 options for installing plugins:
29
+
30
+ 1. In your site source root, make a `_plugins` directory. Place your plugins here.
31
+ Any file ending in `*.rb` inside this directory will be loaded before Jekyll
32
+ generates your site.
33
+ 2. In your `_config.yml` file, add a new array with the key `gems` and the values
34
+ of the gem names of the plugins you'd like to use. An example:
35
+
36
+ gems: [jekyll-test-plugin, jekyll-jsonify, jekyll-assets]
37
+ # This will require each of these gems automatically.
38
+
39
+ <div class="note info">
40
+ <h5>
41
+ <code>_plugins</code> and <code>gems</code>
42
+ can be used simultaneously
43
+ </h5>
44
+ <p>
45
+ You may use both of the aforementioned plugin options simultaneously in the
46
+ same site if you so choose. Use of one does not restrict the use of the other
47
+ </p>
48
+ </div>
31
49
 
32
50
  In general, plugins you make will fall into one of three categories:
33
51
 
@@ -38,7 +56,45 @@ In general, plugins you make will fall into one of three categories:
38
56
  ## Generators
39
57
 
40
58
  You can create a generator when you need Jekyll to create additional content
41
- based on your own rules. For example, a generator might look like this:
59
+ based on your own rules.
60
+
61
+ A generator is a subclass of `Jekyll::Generator` that defines a `generate`
62
+ method, which receives an instance of
63
+ [`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb).
64
+
65
+ Generation is triggered for its side-effects, the return value of `generate` is
66
+ ignored. Jekyll does not assume any particular side-effect to happen, it just
67
+ runs the method.
68
+
69
+ Generators run after Jekyll has made an inventory of the existing content, and
70
+ before the site is generated. Pages with YAML front-matters are stored as
71
+ instances of
72
+ [`Jekyll::Page`]({{ site.repository }}/blob/master/lib/jekyll/page.rb)
73
+ and are available via `site.pages`. Static files become instances of
74
+ [`Jekyll::StaticFile`]({{ site.repository }}/blob/master/lib/jekyll/static_file.rb)
75
+ and are available via `site.static_files`. See
76
+ [`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb)
77
+ for more details.
78
+
79
+ For instance, a generator can inject values computed at build time for template
80
+ variables. In the following example the template `reading.html` has two
81
+ variables `ongoing` and `done` that we fill in the generator:
82
+
83
+ {% highlight ruby %}
84
+ module Reading
85
+ class Generator < Jekyll::Generator
86
+ def generate(site)
87
+ ongoing, done = Book.all.partition(&:ongoing?)
88
+
89
+ reading = site.pages.detect {|page| page.name == 'reading.html'}
90
+ reading.data['ongoing'] = ongoing
91
+ reading.data['done'] = done
92
+ end
93
+ end
94
+ end
95
+ {% endhighlight %}
96
+
97
+ This is a more complex generator that generates new pages:
42
98
 
43
99
  {% highlight ruby %}
44
100
  module Jekyll
@@ -95,7 +151,7 @@ Generators are only required to implement one method:
95
151
  <p><code>generate</code></p>
96
152
  </td>
97
153
  <td>
98
- <p>String output of the content being generated.</p>
154
+ <p>Generates content as a side-effect.</p>
99
155
  </td>
100
156
  </tr>
101
157
  </tbody>
@@ -356,7 +412,7 @@ You can find a few useful plugins at the following locations:
356
412
 
357
413
  - [ArchiveGenerator by Ilkka Laukkanen](https://gist.github.com/707909): Uses [this archive page](https://gist.github.com/707020) to generate archives.
358
414
  - [LESS.js Generator by Andy Fowler](https://gist.github.com/642739): Renders LESS.js files during generation.
359
- - [Version Reporter by Blake Smith](https://gist.github.com/449491): Creates a version.html file containing the Jekyll version.
415
+ - [Version Reporter by Blake Smith](https://gist.github.com/449491): Creates a version.html file containing the Jekyll version.
360
416
  - [Sitemap.xml Generator by Michael Levin](https://github.com/kinnetica/jekyll-plugins): Generates a sitemap.xml file by traversing all of the available posts and pages.
361
417
  - [Full-text search by Pascal Widdershoven](https://github.com/PascalW/jekyll_indextank): Adds full-text search to your Jekyll site with a plugin and a bit of JavaScript.
362
418
  - [AliasGenerator by Thomas Mango](https://github.com/tsmango/jekyll_alias_generator): Generates redirect pages for posts when an alias is specified in the YAML Front Matter.
@@ -430,6 +486,10 @@ You can find a few useful plugins at the following locations:
430
486
  - [Jekyll Image Tag](https://github.com/robwierzbowski/jekyll-image-tag): Better images for Jekyll. Save image presets, generate resized images, and add classes, alt text, and other attributes.
431
487
  - [Ditaa Tag](https://github.com/matze/jekyll-ditaa) by [matze](https://github.com/matze): Renders ASCII diagram art into PNG images and inserts a figure tag.
432
488
  - [Good Include](https://github.com/penibelst/jekyll-good-include) by [Anatol Broder](http://penibelst.de/): Strips newlines and whitespaces from the end of include files before processing.
489
+ - [Jekyll Suggested Tweet](https://github.com/davidensinger/jekyll-suggested-tweet) by [David Ensinger](https://github.com/davidensinger/): A Liquid tag for Jekyll that allows for the embedding of suggested tweets via Twitter’s Web Intents API.
490
+ - [Jekyll Date Chart](https://github.com/GSI/jekyll_date_chart) by [GSI](https://github.com/GSI): Block that renders date line charts based on textile-formatted tables.
491
+ - [Jekyll Image Encode](https://github.com/GSI/jekyll_image_encode) by [GSI](https://github.com/GSI): Tag that renders base64 codes of images fetched from the web.
492
+ - [Jekyll Quick Man](https://github.com/GSI/jekyll_quick_man) by [GSI](https://github.com/GSI): Tag that renders pretty links to man page sources on the internet.
433
493
 
434
494
  #### Collections
435
495
 
@@ -31,6 +31,8 @@ A basic Jekyll site usually looks something like this:
31
31
  ├── _posts
32
32
  | ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
33
33
  | └── 2009-04-26-barcamp-boston-4-roundup.textile
34
+ ├── _data
35
+ | └── members.yml
34
36
  ├── _site
35
37
  └── index.html
36
38
  {% endhighlight %}
@@ -121,6 +123,21 @@ An overview of what each of these does:
121
123
  </p>
122
124
  </td>
123
125
  </tr>
126
+ <tr>
127
+ <td>
128
+ <p><code>_data</code></p>
129
+ </td>
130
+ <td>
131
+ <p>
132
+
133
+ Well-formatted site data should be placed here. The jekyll engine will
134
+ autoload all yaml files (ends with <code>.yml</code> or <code>.yaml</code>)
135
+ in this directory. If there's a file <code>members.yml</code> under the directory,
136
+ then you can access contents of the file through <code>site.data.members</code>.
137
+
138
+ </p>
139
+ </td>
140
+ </tr>
124
141
  <tr>
125
142
  <td>
126
143
  <p><code>_site</code></p>
@@ -7,9 +7,9 @@ permalink: /docs/templates/
7
7
  ---
8
8
 
9
9
  Jekyll uses the [Liquid](http://wiki.shopify.com/Liquid) templating language to
10
- process templates. All of the [standard Liquid tags and
11
- filters](http://wiki.github.com/shopify/liquid/liquid-for-designers) are
12
- supported, Jekyll even adds a few handy filters and tags of its own to make
10
+ process templates. All of the standard Liquid [tags](http://wiki.shopify.com/Logic) and
11
+ [filters](http://wiki.shopify.com/Filters) are
12
+ supported. Jekyll even adds a few handy filters and tags of its own to make
13
13
  common tasks easier.
14
14
 
15
15
  ## Filters
@@ -33,7 +33,7 @@ common tasks easier.
33
33
  <code class='filter'>{% raw %}{{ site.time | date_to_xmlschema }}{% endraw %}</code>
34
34
  </p>
35
35
  <p>
36
- <code class='output'>2008-11-17T13:07:54-08:00</code>
36
+ <code class='output'>2008-11-07T13:07:54-08:00</code>
37
37
  </p>
38
38
  </td>
39
39
  </tr>
@@ -47,7 +47,7 @@ common tasks easier.
47
47
  <code class='filter'>{% raw %}{{ site.time | date_to_rfc822 }}{% endraw %}</code>
48
48
  </p>
49
49
  <p>
50
- <code class='output'>Mon, 17 Nov 2008 13:07:54 -0800</code>
50
+ <code class='output'>Mon, 07 Nov 2008 13:07:54 -0800</code>
51
51
  </p>
52
52
  </td>
53
53
  </tr>
@@ -61,7 +61,7 @@ common tasks easier.
61
61
  <code class='filter'>{% raw %}{{ site.time | date_to_string }}{% endraw %}</code>
62
62
  </p>
63
63
  <p>
64
- <code class='output'>17 Nov 2008</code>
64
+ <code class='output'>07 Nov 2008</code>
65
65
  </p>
66
66
  </td>
67
67
  </tr>
@@ -75,7 +75,7 @@ common tasks easier.
75
75
  <code class='filter'>{% raw %}{{ site.time | date_to_long_string }}{% endraw %}</code>
76
76
  </p>
77
77
  <p>
78
- <code class='output'>17 November 2008</code>
78
+ <code class='output'>07 November 2008</code>
79
79
  </p>
80
80
  </td>
81
81
  </tr>
@@ -173,6 +173,17 @@ common tasks easier.
173
173
  </p>
174
174
  </td>
175
175
  </tr>
176
+ <tr>
177
+ <td>
178
+ <p class='name'><strong>Data To JSON</strong></p>
179
+ <p>Convert Hash or Array to JSON.</p>
180
+ </td>
181
+ <td class='align-center'>
182
+ <p>
183
+ <code class='filter'>{% raw %}{{ site.data.projects | jsonify }}{% endraw %}</code>
184
+ </p>
185
+ </td>
186
+ </tr>
176
187
  </tbody>
177
188
  </table>
178
189
  </div>
@@ -192,6 +203,19 @@ Jekyll expects all include files to be placed in an `_includes` directory at the
192
203
  root of your source directory. This will embed the contents of
193
204
  `<source>/_includes/footer.html` into the calling file.
194
205
 
206
+ <div class="note">
207
+ <h5>ProTip™: Use variables as file name</h5>
208
+ <p>
209
+
210
+ The name of the file you wish to embed can be literal (as in the example above),
211
+ or you can use a variable, using liquid-like variable syntax as in
212
+ <code>{% raw %}{% include {{my_variable}} %}{% endraw %}</code>.
213
+
214
+ Note that unlike usual liquid variable syntax, you cannot have spaces inside the curly braces.
215
+
216
+ </p>
217
+ </div>
218
+
195
219
  You can also pass parameters to an include:
196
220
 
197
221
  {% highlight ruby %}
@@ -42,7 +42,7 @@ rebuild each time a file changes, just add the `--watch` flag at the end.
42
42
  ### Absolute Permalinks
43
43
 
44
44
  In Jekyll v1.0, we introduced absolute permalinks for pages in subdirectories.
45
- Until v1.1, it is **opt-in**. Starting with v1.1, however, absolute permalinks
45
+ Until v2.0, it is **opt-in**. Starting with v2.0, however, absolute permalinks
46
46
  will become **opt-out**, meaning Jekyll will default to using absolute permalinks
47
47
  instead of relative permalinks.
48
48
 
@@ -50,9 +50,9 @@ instead of relative permalinks.
50
50
  * To continue using relative permalinks, set `relative_permalinks: true` in your configuration file.
51
51
 
52
52
  <div class="note warning" id="absolute-permalinks-warning">
53
- <h5 markdown="1">Absolute permalinks will be default in v1.1 and on</h5>
53
+ <h5 markdown="1">Absolute permalinks will be default in v2.0 and on</h5>
54
54
  <p markdown="1">
55
- Starting with Jekyll v1.1.0, `relative_permalinks` will default to `false`,
55
+ Starting with Jekyll v2.0, `relative_permalinks` will default to `false`,
56
56
  meaning all pages will be built using the absolute permalink behaviour.
57
57
  The switch will still exist until v2.0.
58
58
  </p>
@@ -40,7 +40,7 @@ $ jekyll serve --watch
40
40
  # => Same as `jekyll serve`, but watch for changes and regenerate automatically.
41
41
  {% endhighlight %}
42
42
 
43
- This is just a few of the available [configuration options](../configuration/).
43
+ These are just a few of the available [configuration options](../configuration/).
44
44
  Many configuration options can either be specified as flags on the command line,
45
45
  or alternatively (and more commonly) they can be specified in a `_config.yml`
46
46
  file at the root of the source directory. Jekyll will automatically use the
@@ -2,14 +2,14 @@
2
2
  layout: docs
3
3
  title: Variables
4
4
  prev_section: pages
5
- next_section: migrations
5
+ next_section: datafiles
6
6
  permalink: /docs/variables/
7
7
  ---
8
8
 
9
9
  Jekyll traverses your site looking for files to process. Any files with [YAML
10
10
  Front Matter](../frontmatter/) are subject to processing. For each of these
11
11
  files, Jekyll makes a variety of data available via the [Liquid templating
12
- system](http://wiki.github.com/shopify/liquid/liquid-for-designers). The
12
+ system](http://wiki.shopify.com/Liquid). The
13
13
  following is a reference of the available data.
14
14
 
15
15
  ## Global Variables
@@ -1,7 +1,10 @@
1
- if RUBY_VERSION > '1.9' && ENV["COVERAGE"] == "true"
1
+ if RUBY_VERSION > '1.9'
2
2
  require 'simplecov'
3
3
  require 'simplecov-gem-adapter'
4
4
  SimpleCov.start('gem')
5
+
6
+ require 'coveralls'
7
+ Coveralls.wear_merged!
5
8
  end
6
9
 
7
10
  require 'rubygems'
@@ -0,0 +1,2 @@
1
+ - java
2
+ - ruby
@@ -0,0 +1,7 @@
1
+ - name: Jack
2
+ age: 27
3
+ blog: http://example.com/jack
4
+
5
+ - name: John
6
+ age: 32
7
+ blog: http://example.com/john
@@ -0,0 +1,4 @@
1
+ - name: sugar
2
+ price: 5.3
3
+ - name: salt
4
+ price: 2.5
@@ -0,0 +1 @@
1
+ <<< {{ content }} >>>
@@ -0,0 +1,4 @@
1
+ - name: sugar
2
+ price: 5.3
3
+ - name: salt
4
+ price: 2.5
@@ -40,7 +40,7 @@ class TestConvertible < Test::Unit::TestCase
40
40
  should "not parse if there is encoding error in file" do
41
41
  name = 'broken_front_matter3.erb'
42
42
  out = capture_stdout do
43
- ret = @convertible.read_yaml(@base, name)
43
+ ret = @convertible.read_yaml(@base, name, :encoding => 'utf-8')
44
44
  assert_equal({}, ret)
45
45
  end
46
46
  assert_match(/invalid byte sequence in UTF-8/, out)
@@ -98,5 +98,16 @@ class TestFilters < Test::Unit::TestCase
98
98
  should "escape space as %20" do
99
99
  assert_equal "my%20things", @filter.uri_escape("my things")
100
100
  end
101
+
102
+ context "jsonify filter" do
103
+ should "convert hash to json" do
104
+ assert_equal "{\"age\":18}", @filter.jsonify({:age => 18})
105
+ end
106
+
107
+ should "convert array to json" do
108
+ assert_equal "[1,2]", @filter.jsonify([1, 2])
109
+ assert_equal "[{\"name\":\"Jack\"},{\"name\":\"Smith\"}]", @filter.jsonify([{:name => 'Jack'}, {:name => 'Smith'}])
110
+ end
111
+ end
101
112
  end
102
113
  end
@@ -12,24 +12,51 @@ class TestKramdown < Test::Unit::TestCase
12
12
  'footnote_nr' => 1,
13
13
  'entity_output' => 'as_char',
14
14
  'toc_levels' => '1..6',
15
- 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo'
15
+ 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
16
+
17
+ 'use_coderay' => true,
18
+ 'coderay_bold_every'=> 12,
19
+ 'coderay' => {
20
+ 'coderay_css' => :style,
21
+ 'coderay_bold_every' => 8
22
+ }
16
23
  }
17
24
  }
25
+ @config = Jekyll.configuration(@config)
26
+ @markdown = Converters::Markdown.new(@config)
18
27
  end
19
28
 
20
29
  # http://kramdown.rubyforge.org/converter/html.html#options
21
30
  should "pass kramdown options" do
22
- markdown = Converters::Markdown.new(@config)
23
- assert_equal "<h1>Some Header</h1>", markdown.convert('# Some Header #').strip
31
+ assert_equal "<h1>Some Header</h1>", @markdown.convert('# Some Header #').strip
24
32
  end
25
33
 
26
34
  should "convert quotes to smart quotes" do
27
- markdown = Converters::Markdown.new(@config)
28
- assert_match /<p>(&#8220;|“)Pit(&#8217;|’)hy(&#8221;|”)<\/p>/, markdown.convert(%{"Pit'hy"}).strip
35
+ assert_match /<p>(&#8220;|“)Pit(&#8217;|’)hy(&#8221;|”)<\/p>/, @markdown.convert(%{"Pit'hy"}).strip
29
36
 
30
37
  override = { 'kramdown' => { 'smart_quotes' => 'lsaquo,rsaquo,laquo,raquo' } }
31
38
  markdown = Converters::Markdown.new(@config.deep_merge(override))
32
39
  assert_match /<p>(&#171;|«)Pit(&#8250;|›)hy(&#187;|»)<\/p>/, markdown.convert(%{"Pit'hy"}).strip
33
40
  end
41
+
42
+ context "moving up nested coderay options" do
43
+ setup do
44
+ @markdown.convert('some markup')
45
+ @converter_config = @markdown.instance_variable_get(:@config)['kramdown']
46
+ end
47
+
48
+ should "work correctly" do
49
+ assert_equal :style, @converter_config['coderay_css']
50
+ end
51
+
52
+ should "also work for defaults" do
53
+ default = Jekyll::Configuration::DEFAULTS['kramdown']['coderay']['coderay_tab_width']
54
+ assert_equal default, @converter_config['coderay_tab_width']
55
+ end
56
+
57
+ should "not overwrite" do
58
+ assert_equal 12, @converter_config['coderay_bold_every']
59
+ end
60
+ end
34
61
  end
35
62
  end