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
@@ -12,7 +12,15 @@ module Jekyll
12
12
  gist_id, filename = tag_contents[0], tag_contents[1]
13
13
  gist_script_tag(gist_id, filename)
14
14
  else
15
- "Error parsing gist id"
15
+ raise ArgumentError.new <<-eos
16
+ Syntax error in tag 'gist' while parsing the following markup:
17
+
18
+ #{@markup}
19
+
20
+ Valid syntax:
21
+ for public gists: {% gist 1234567 %}
22
+ for private gists: {% gist user/1234567 %}
23
+ eos
16
24
  end
17
25
  end
18
26
 
@@ -14,7 +14,7 @@ module Jekyll
14
14
  def initialize(tag_name, markup, tokens)
15
15
  super
16
16
  if markup.strip =~ SYNTAX
17
- @lang = $1
17
+ @lang = $1.downcase
18
18
  @options = {}
19
19
  if defined?($2) && $2 != ''
20
20
  $2.split.each do |opt|
@@ -1,21 +1,33 @@
1
1
  module Jekyll
2
2
  module Tags
3
+ class IncludeTagError < StandardError
4
+ attr_accessor :path
5
+
6
+ def initialize(msg, path)
7
+ super(msg)
8
+ @path = path
9
+ end
10
+ end
11
+
3
12
  class IncludeTag < Liquid::Tag
4
13
 
5
- MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
14
+ SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}"
15
+
16
+ VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
17
+
18
+ INCLUDES_DIR = '_includes'
6
19
 
7
20
  def initialize(tag_name, markup, tokens)
8
21
  super
9
22
  @file, @params = markup.strip.split(' ', 2);
23
+ validate_params if @params
10
24
  end
11
25
 
12
26
  def parse_params(context)
13
- validate_syntax
14
-
15
27
  params = {}
16
28
  markup = @params
17
29
 
18
- while match = MATCHER.match(markup) do
30
+ while match = VALID_SYNTAX.match(markup) do
19
31
  markup = markup[match.end(0)..-1]
20
32
 
21
33
  value = if match[2]
@@ -31,59 +43,91 @@ module Jekyll
31
43
  params
32
44
  end
33
45
 
34
- # ensure the entire markup string from start to end is valid syntax, and params are separated by spaces
35
- def validate_syntax
36
- full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z')
37
- unless @params =~ full_matcher
38
- raise SyntaxError.new <<-eos
46
+ def validate_file_name
47
+ if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
48
+ raise ArgumentError.new <<-eos
49
+ Invalid syntax for include tag. File contains invalid characters or sequences:
50
+
51
+ #{@file}
52
+
53
+ Valid syntax:
54
+
55
+ #{SYNTAX_EXAMPLE}
56
+
57
+ eos
58
+ end
59
+ end
60
+
61
+ def validate_params
62
+ full_valid_syntax = Regexp.compile('\A\s*(?:' + VALID_SYNTAX.to_s + '(?=\s|\z)\s*)*\z')
63
+ unless @params =~ full_valid_syntax
64
+ raise ArgumentError.new <<-eos
39
65
  Invalid syntax for include tag:
40
66
 
41
67
  #{@params}
42
68
 
43
69
  Valid syntax:
44
70
 
45
- {% include file.ext param='value' param2="value" %}
71
+ #{SYNTAX_EXAMPLE}
46
72
 
47
73
  eos
48
74
  end
49
75
  end
50
76
 
51
- def render(context)
52
- includes_dir = File.join(context.registers[:site].source, '_includes')
77
+ # Grab file read opts in the context
78
+ def file_read_opts(context)
79
+ context.registers[:site].file_read_opts
80
+ end
53
81
 
54
- if error = validate_file(includes_dir)
55
- return error
82
+ def retrieve_variable(context)
83
+ if /\{\{([\w\-\.]+)\}\}/ =~ @file
84
+ raise ArgumentError.new("No variable #{$1} was found in include tag") if context[$1].nil?
85
+ @file = context[$1]
56
86
  end
87
+ end
88
+
89
+ def render(context)
90
+ dir = File.join(context.registers[:site].source, INCLUDES_DIR)
91
+ validate_dir(dir, context.registers[:site].safe)
92
+
93
+ retrieve_variable(context)
94
+ validate_file_name
57
95
 
58
- source = File.read(File.join(includes_dir, @file))
59
- partial = Liquid::Template.parse(source)
96
+ file = File.join(dir, @file)
97
+ validate_file(file, context.registers[:site].safe)
98
+
99
+ partial = Liquid::Template.parse(source(file, context))
60
100
 
61
101
  context.stack do
62
102
  context['include'] = parse_params(context) if @params
63
- partial.render(context)
103
+ partial.render!(context)
64
104
  end
105
+ rescue => e
106
+ raise IncludeTagError.new e.message, File.join(INCLUDES_DIR, @file)
65
107
  end
66
108
 
67
- def validate_file(includes_dir)
68
- if File.symlink?(includes_dir)
69
- return "Includes directory '#{includes_dir}' cannot be a symlink"
70
- end
71
-
72
- if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
73
- return "Include file '#{@file}' contains invalid characters or sequences"
109
+ def validate_dir(dir, safe)
110
+ if File.symlink?(dir) && safe
111
+ raise IOError.new "Includes directory '#{dir}' cannot be a symlink"
74
112
  end
113
+ end
75
114
 
76
- file = File.join(includes_dir, @file)
115
+ def validate_file(file, safe)
77
116
  if !File.exists?(file)
78
- return "Included file #{@file} not found in _includes directory"
79
- elsif File.symlink?(file)
80
- return "The included file '_includes/#{@file}' should not be a symlink"
117
+ raise IOError.new "Included file '#{@file}' not found in '#{INCLUDES_DIR}' directory"
118
+ elsif File.symlink?(file) && safe
119
+ raise IOError.new "The included file '#{INCLUDES_DIR}/#{@file}' should not be a symlink"
81
120
  end
82
121
  end
83
122
 
84
123
  def blank?
85
124
  false
86
125
  end
126
+
127
+ # This method allows to modify the file content by inheriting from the class.
128
+ def source(file, context)
129
+ File.read_with_options(file, file_read_opts(context))
130
+ end
87
131
  end
88
132
  end
89
133
  end
@@ -50,9 +50,11 @@ module Jekyll
50
50
  end
51
51
  end
52
52
 
53
- puts "ERROR: post_url: \"#{@orig_post}\" could not be found"
53
+ raise ArgumentError.new <<-eos
54
+ Could not find post "#{@orig_post}" in tag 'post_url'.
54
55
 
55
- return "#"
56
+ Make sure the post exists and the name is correct.
57
+ eos
56
58
  end
57
59
  end
58
60
  end
@@ -34,16 +34,16 @@ a:visited { color: #a0a; }
34
34
  /* Home
35
35
  /*
36
36
  /*****************************************************************************/
37
- ul.posts {
37
+ .posts {
38
38
  list-style-type: none;
39
39
  margin-bottom: 2em;
40
40
  }
41
41
 
42
- ul.posts li {
42
+ .posts li {
43
43
  line-height: 1.75em;
44
44
  }
45
45
 
46
- ul.posts span {
46
+ .posts span {
47
47
  color: #aaa;
48
48
  font-family: Monaco, "Courier New", monospace;
49
49
  font-size: 80%;
@@ -63,38 +63,38 @@ ul.posts span {
63
63
  line-height: 1.5em;
64
64
  }
65
65
 
66
- .site .header a {
66
+ .header a {
67
67
  font-weight: bold;
68
68
  text-decoration: none;
69
69
  }
70
70
 
71
- .site .header h1.title {
71
+ .title {
72
72
  display: inline-block;
73
73
  margin-bottom: 2em;
74
74
  }
75
75
 
76
- .site .header h1.title a {
76
+ .title a {
77
77
  color: #a00;
78
78
  }
79
79
 
80
- .site .header h1.title a:hover {
80
+ .title a:hover {
81
81
  color: #000;
82
82
  }
83
83
 
84
- .site .header a.extra {
84
+ .header a.extra {
85
85
  color: #aaa;
86
86
  margin-left: 1em;
87
87
  }
88
88
 
89
- .site .header a.extra:hover {
89
+ .header a.extra:hover {
90
90
  color: #000;
91
91
  }
92
92
 
93
- .site .meta {
93
+ .meta {
94
94
  color: #aaa;
95
95
  }
96
96
 
97
- .site .footer {
97
+ .footer {
98
98
  font-size: 80%;
99
99
  color: #666;
100
100
  border-top: 4px solid #eee;
@@ -102,22 +102,22 @@ ul.posts span {
102
102
  overflow: hidden;
103
103
  }
104
104
 
105
- .site .footer .contact {
105
+ .footer .contact {
106
106
  float: left;
107
107
  margin-right: 3em;
108
108
  }
109
109
 
110
- .site .footer .contact a {
110
+ .footer .contact a {
111
111
  color: #8085C1;
112
112
  }
113
113
 
114
- .site .footer .rss {
114
+ .footer .rss {
115
115
  margin-top: 1.1em;
116
116
  margin-right: -.2em;
117
117
  float: right;
118
118
  }
119
119
 
120
- .site .footer .rss img {
120
+ .footer .rss img {
121
121
  border: 0;
122
122
  }
123
123
 
@@ -3,7 +3,7 @@
3
3
  <h4>Getting Started</h4>
4
4
  {% include docs_ul.html items='home quickstart installation usage structure configuration' %}
5
5
  <h4>Your Content</h4>
6
- {% include docs_ul.html items='frontmatter posts drafts pages variables migrations' %}
6
+ {% include docs_ul.html items='frontmatter posts drafts pages variables datafiles migrations' %}
7
7
  <h4>Customization</h4>
8
8
  {% include docs_ul.html items='templates permalinks pagination plugins extras' %}
9
9
  <h4>Deployment</h4>
@@ -5,7 +5,7 @@
5
5
  {% include docs_option.html items='home quickstart installation usage structure configuration' %}
6
6
  </optgroup>
7
7
  <optgroup label="Your Content">
8
- {% include docs_option.html items='frontmatter posts drafts pages variables migrations' %}
8
+ {% include docs_option.html items='frontmatter posts drafts pages variables datafiles migrations' %}
9
9
  </optgroup>
10
10
  <optgroup label="Customization">
11
11
  {% include docs_option.html items='templates permalinks pagination plugins extras' %}
@@ -0,0 +1,19 @@
1
+ ---
2
+ layout: news_item
3
+ title: 'Jekyll 1.3.0.rc1 Released'
4
+ date: 2013-10-28 20:14:39 -0500
5
+ author: mattr-
6
+ version: 1.3.0.rc1
7
+ categories: [release]
8
+ ---
9
+
10
+ Jekyll 1.3.0 is going to be a big release! In order to make sure we
11
+ didn't screw anything up too badly, we're making a release candidate
12
+ available for any early adopters who want to give the latest and
13
+ greatest code a spin without having to clone a repository from git.
14
+
15
+ Please take this prerelease for a spin and [let us
16
+ know](https://github.com/mojombo/jekyll/issues/new) if you run into any
17
+ issues!
18
+
19
+
@@ -99,6 +99,22 @@ class="flag">flags</code> (specified on the command-line) that control them.
99
99
  <p><code class="option">timezone: TIMEZONE</code></p>
100
100
  </td>
101
101
  </tr>
102
+ <tr class='setting'>
103
+ <td>
104
+ <p class='name'><strong>Encoding</strong></p>
105
+ <p class="description">
106
+ Set the encoding of files by name. Only available for Ruby
107
+ 1.9 or later).
108
+ The default value is nil, which use Ruby default,
109
+ <code>ASCII-8BIT</code>.
110
+ Available encoding for the ruby in use, can be shown by
111
+ command <code>ruby -e 'puts Encoding::list.join("\n")'</code>
112
+ </p>
113
+ </td>
114
+ <td class='align-center'>
115
+ <p><code class="option">encoding: ENCODING</code></p>
116
+ </td>
117
+ </tr>
102
118
  </tbody>
103
119
  </table>
104
120
  </div>
@@ -265,7 +281,9 @@ layouts: ./_layouts
265
281
  include: ['.htaccess']
266
282
  exclude: []
267
283
  keep_files: ['.git','.svn']
284
+ gems: []
268
285
  timezone: nil
286
+ encoding: nil
269
287
 
270
288
  future: true
271
289
  show_drafts: nil
@@ -0,0 +1,63 @@
1
+ ---
2
+ layout: docs
3
+ title: Data Files
4
+ prev_section: variables
5
+ next_section: migrations
6
+ permalink: /docs/datafiles/
7
+ ---
8
+
9
+ In addition to the [built-in variables](../variables/) available from Jekyll,
10
+ you can specify your own custom data that can be accessed via the [Liquid
11
+ templating system](http://wiki.github.com/shopify/liquid/liquid-for-designers).
12
+
13
+ Jekyll supports loading data from [YAML](http://yaml.org/) files located in the
14
+ `_data` directory.
15
+
16
+ This powerful features allows you to avoid repetition in your templates and to
17
+ set site specific options without changing `_config.yml`.
18
+
19
+ Plugins/themes can also leverage Data Files to set configuration variables.
20
+
21
+ ## The Data Folder
22
+
23
+ As explained on the [directory structure](../structure/) page, the `_data`
24
+ folder is where you can store additional data for Jekyll to use when generating
25
+ your site. These files must be YAML files (using either the `.yml` or `.yaml`
26
+ extension) and they will be accessible via `site.data`.
27
+
28
+ ## Example: List of members
29
+
30
+ Here is a basic example of using Data Files to avoid copy-pasting large chunks of
31
+ code in your Jekyll templates:
32
+
33
+ In `_data/members.yml`:
34
+
35
+ {% highlight yaml %}
36
+ - name: Tom Preston-Werner
37
+ github: mojombo
38
+
39
+ - name: Parker Moore
40
+ github: parkr
41
+
42
+ - name: Liu Fengyun
43
+ github: liufengyun
44
+ {% endhighlight %}
45
+
46
+ This data can be accessed via `site.data.members` (notice that the filename
47
+ determines the variable name).
48
+
49
+ You can now render the list of members in a template:
50
+
51
+ {% highlight html %}
52
+ {% raw %}
53
+ <ul>
54
+ {% for member in site.data.members %}
55
+ <li>
56
+ <a href="https://github.com/{{ member.github }}">
57
+ {{ member.name }}
58
+ </a>
59
+ </li>
60
+ {% end %}
61
+ </ul>
62
+ {% endraw %}
63
+ {% endhighlight %}
@@ -46,6 +46,16 @@ installing Jekyll, check out the [troubleshooting](../troubleshooting/) page or
46
46
  [report an issue]({{ site.repository }}/issues/new) so the Jekyll
47
47
  community can improve the experience for everyone.
48
48
 
49
+ <div class="note info">
50
+ <h5>Installing Xcode Command-Line Tools</h5>
51
+ <p>
52
+ If you run into issues installing Jekyll's dependencies which make use of
53
+ native extensions and are using Mac OS X, you will need to install Xcode
54
+ and the Command-Line Tools it ships with. Download in
55
+ <code>Preferences &#8594; Downloads &#8594; Components</code>.
56
+ </p>
57
+ </div>
58
+
49
59
  ## Optional Extras
50
60
 
51
61
  There are a number of (optional) extra features that Jekyll supports that you
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  layout: docs
3
3
  title: Blog migrations
4
- prev_section: variables
4
+ prev_section: datafiles
5
5
  next_section: templates
6
6
  permalink: /docs/migrations/
7
7
  ---
@@ -24,6 +24,15 @@ Jekyll's standard command line interface.
24
24
  $ gem install jekyll-import --pre
25
25
  {% endhighlight %}
26
26
 
27
+ <div class="note warning">
28
+ <h5>Jekyll-import requires you to manually install some dependencies.</h5>
29
+ <p markdown="1">If you are importing your blog from Drupal 6,7, Joomla,
30
+ Mephisto, Movable Type, Textpattern, or Typo (with mysql db), you need to install
31
+ `mysql` and `sequel` gems. If you are importing from a WordPress database, you
32
+ need to install `mysql2` and `sequel` gems, and if you are importing from Enki
33
+ or Typo (with postgresql db) you need to install `pg` and `sequel` gems.</p>
34
+ </div>
35
+
27
36
  You should now be all set to run the importers below. If you ever get stuck, you
28
37
  can see help for each importer:
29
38
 
@@ -74,7 +83,7 @@ here's how:
74
83
 
75
84
  {% highlight bash %}
76
85
  $ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress";
77
- JekyllImport::WordPress.process({:database => "database", :user => "user", :pass => "pass"})'
86
+ JekyllImport::WordPress.process({:dbname => "database", :user => "user", :pass => "pass"})'
78
87
  {% endhighlight %}
79
88
 
80
89
  If you are using Webfaction and have to set up an [SSH
@@ -85,7 +94,7 @@ authentication system:
85
94
 
86
95
  {% highlight bash %}
87
96
  $ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress";
88
- JekyllImport::WordPress.process("database", "user", "pass", "127.0.0.1")'
97
+ JekyllImport::WordPress.process({:host => "127.0.0.1", :dbname => "database", :user => "user", :pass => "pass"})'
89
98
  {% endhighlight %}
90
99
 
91
100
  ### Further WordPress migration alternatives