jekyll 0.11.2 → 0.12.0

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.

@@ -3,14 +3,19 @@ module Jekyll
3
3
  class HighlightBlock < Liquid::Block
4
4
  include Liquid::StandardFilters
5
5
 
6
- # We need a language, but the linenos argument is optional.
7
- SYNTAX = /(\w+)\s?([\w\s=]+)*/
6
+ # The regular expression syntax checker. Start with the language specifier.
7
+ # Follow that by zero or more space separated options that take one of two
8
+ # forms:
9
+ #
10
+ # 1. name
11
+ # 2. name=value
12
+ SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=\w+)?)*)$/
8
13
 
9
14
  def initialize(tag_name, markup, tokens)
10
15
  super
11
- if markup =~ SYNTAX
16
+ if markup.strip =~ SYNTAX
12
17
  @lang = $1
13
- if defined? $2
18
+ if defined?($2) && $2 != ''
14
19
  tmp_options = {}
15
20
  $2.split.each do |opt|
16
21
  key, value = opt.split('=')
@@ -23,7 +28,7 @@ module Jekyll
23
28
  end
24
29
  tmp_options[key] = value
25
30
  end
26
- tmp_options = tmp_options.to_a.collect { |opt| opt.join('=') }
31
+ tmp_options = tmp_options.to_a.sort.collect { |opt| opt.join('=') }
27
32
  # additional options to pass to Albino
28
33
  @options = { 'O' => tmp_options.join(',') }
29
34
  else
@@ -43,7 +48,13 @@ module Jekyll
43
48
  end
44
49
 
45
50
  def render_pygments(context, code)
46
- output = add_code_tags(Albino.new(code, @lang).to_s(@options), @lang)
51
+ @options[:encoding] = 'utf-8'
52
+
53
+ output = add_code_tags(
54
+ Pygments.highlight(code, :lexer => @lang, :options => @options),
55
+ @lang
56
+ )
57
+
47
58
  output = context["pygments_prefix"] + output if context["pygments_prefix"]
48
59
  output = output + context["pygments_suffix"] if context["pygments_suffix"]
49
60
  output
@@ -0,0 +1,38 @@
1
+ module Jekyll
2
+
3
+ class PostComparer
4
+ MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/
5
+
6
+ attr_accessor :date, :slug
7
+
8
+ def initialize(name)
9
+ who, cares, date, slug = *name.match(MATCHER)
10
+ @slug = slug
11
+ @date = Time.parse(date)
12
+ end
13
+ end
14
+
15
+ class PostUrl < Liquid::Tag
16
+ def initialize(tag_name, post, tokens)
17
+ super
18
+ @orig_post = post.strip
19
+ @post = PostComparer.new(@orig_post)
20
+ end
21
+
22
+ def render(context)
23
+ site = context.registers[:site]
24
+
25
+ site.posts.each do |p|
26
+ if p == @post
27
+ return p.url
28
+ end
29
+ end
30
+
31
+ puts "ERROR: post_url: \"#{@orig_post}\" could not be found"
32
+
33
+ return "#"
34
+ end
35
+ end
36
+ end
37
+
38
+ Liquid::Template.register_tag('post_url', Jekyll::PostUrl)
@@ -0,0 +1,5 @@
1
+ # Some stuff on the first line
2
+ ---
3
+ test: good
4
+ ---
5
+ Real content starts here
@@ -0,0 +1,4 @@
1
+ ---
2
+ test: good
3
+ ---
4
+ Real content starts here
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+ require 'ostruct'
3
+
4
+ class TestConvertible < Test::Unit::TestCase
5
+ context "yaml front-matter" do
6
+ setup do
7
+ @convertible = OpenStruct.new
8
+ @convertible.extend Jekyll::Convertible
9
+ @base = File.expand_path('../fixtures', __FILE__)
10
+ end
11
+
12
+ should "parse the front-matter correctly" do
13
+ ret = @convertible.read_yaml(@base, 'front_matter.erb')
14
+ assert_equal({'test' => 'good'}, ret)
15
+ end
16
+
17
+ should "not parse if the front-matter is not at the start of the file" do
18
+ ret = @convertible.read_yaml(@base, 'broken_front_matter1.erb')
19
+ assert_equal({}, ret)
20
+ end
21
+ end
22
+ end
@@ -3,21 +3,31 @@ require 'helper'
3
3
  class TestKramdown < Test::Unit::TestCase
4
4
  context "kramdown" do
5
5
  setup do
6
- config = {
6
+ @config = {
7
7
  'markdown' => 'kramdown',
8
8
  'kramdown' => {
9
9
  'auto_ids' => false,
10
10
  'footnote_nr' => 1,
11
11
  'entity_output' => 'as_char',
12
- 'toc_levels' => '1..6'
12
+ 'toc_levels' => '1..6',
13
+ 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo'
13
14
  }
14
15
  }
15
- @markdown = MarkdownConverter.new config
16
16
  end
17
17
 
18
18
  # http://kramdown.rubyforge.org/converter/html.html#options
19
19
  should "pass kramdown options" do
20
- assert_equal "<h1>Some Header</h1>", @markdown.convert('# Some Header #').strip
20
+ markdown = MarkdownConverter.new(@config)
21
+ assert_equal "<h1>Some Header</h1>", markdown.convert('# Some Header #').strip
22
+ end
23
+
24
+ should "convert quotes to smart quotes" do
25
+ markdown = MarkdownConverter.new(@config)
26
+ assert_equal "<p>&ldquo;Pit&rsquo;hy&rdquo;</p>", markdown.convert(%{"Pit'hy"}).strip
27
+
28
+ override = { 'kramdown' => { 'smart_quotes' => 'lsaquo,rsaquo,laquo,raquo' } }
29
+ markdown = MarkdownConverter.new(@config.deep_merge(override))
30
+ assert_equal "<p>&laquo;Pit&rsaquo;hy&raquo;</p>", markdown.convert(%{"Pit'hy"}).strip
21
31
  end
22
32
  end
23
33
  end
@@ -141,6 +141,19 @@ class TestPost < Test::Unit::TestCase
141
141
  end
142
142
  end
143
143
 
144
+ context "with space (categories)" do
145
+ setup do
146
+ @post.categories << "French cuisine"
147
+ @post.categories << "Belgian beer"
148
+ @post.process(@fake_file)
149
+ end
150
+
151
+ should "process the url correctly" do
152
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
153
+ assert_equal "/French%20cuisine/Belgian%20beer/2008/09/09/foo-bar.html", @post.url
154
+ end
155
+ end
156
+
144
157
  context "with none style" do
145
158
  setup do
146
159
  @post.site.permalink_style = :none
@@ -5,8 +5,8 @@ class TestRdiscount < Test::Unit::TestCase
5
5
  context "rdiscount" do
6
6
  setup do
7
7
  config = {
8
- 'rdiscount' => { 'extensions' => ['smart'] },
9
- 'markdown' => 'rdiscount'
8
+ 'markdown' => 'rdiscount',
9
+ 'rdiscount' => { 'extensions' => ['smart', 'generate_toc'], 'toc_token' => '{:toc}' }
10
10
  }
11
11
  @markdown = MarkdownConverter.new config
12
12
  end
@@ -14,5 +14,9 @@ class TestRdiscount < Test::Unit::TestCase
14
14
  should "pass rdiscount extensions" do
15
15
  assert_equal "<p>&ldquo;smart&rdquo;</p>", @markdown.convert('"smart"').strip
16
16
  end
17
+
18
+ should "render toc" do
19
+ assert_equal "<h1 id=\"Header+1\">Header 1</h1>\n\n<h2 id=\"Header+2\">Header 2</h2>\n\n<p>\n <ul>\n <li><a href=\"#Header+1\">Header 1</a>\n <ul>\n <li><a href=\"#Header+2\">Header 2</a> </li>\n </ul>\n </li>\n </ul>\n\n</p>", @markdown.convert("# Header 1\n\n## Header 2\n\n{:toc}").strip
20
+ end
17
21
  end
18
22
  end
@@ -1,10 +1,10 @@
1
- require File.dirname(__FILE__) + '/helper'
1
+ require 'helper'
2
2
 
3
3
  class TestRedcarpet < Test::Unit::TestCase
4
4
  context "redcarpet" do
5
5
  setup do
6
6
  config = {
7
- 'redcarpet' => { 'extensions' => ['smart'] },
7
+ 'redcarpet' => { 'extensions' => ['smart', 'strikethrough', 'filter_html'] },
8
8
  'markdown' => 'redcarpet'
9
9
  }
10
10
  @markdown = MarkdownConverter.new config
@@ -14,8 +14,26 @@ class TestRedcarpet < Test::Unit::TestCase
14
14
  assert_equal "<h1>Some Header</h1>", @markdown.convert('# Some Header #').strip
15
15
  end
16
16
 
17
- should "pass redcarpet extensions" do
17
+ should "pass redcarpet SmartyPants options" do
18
18
  assert_equal "<p>&ldquo;smart&rdquo;</p>", @markdown.convert('"smart"').strip
19
19
  end
20
+
21
+ should "pass redcarpet extensions" do
22
+ assert_equal "<p><del>deleted</del></p>", @markdown.convert('~~deleted~~').strip
23
+ end
24
+
25
+ should "pass redcarpet render options" do
26
+ assert_equal "<p><strong>bad code not here</strong>: i am bad</p>", @markdown.convert('**bad code not here**: <script>i am bad</script>').strip
27
+ end
28
+
29
+ should "render fenced code blocks" do
30
+ assert_equal "<div class=\"highlight\"><pre><code class=\"ruby\"><span class=\"nb\">puts</span> <span class=\"s2\">&quot;Hello world&quot;</span>\n</code></pre></div>", @markdown.convert(
31
+ <<-EOS
32
+ ```ruby
33
+ puts "Hello world"
34
+ ```
35
+ EOS
36
+ ).strip
37
+ end
20
38
  end
21
39
  end
@@ -0,0 +1,86 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestRedCloth < Test::Unit::TestCase
4
+
5
+ context "RedCloth default (no explicit config) hard_breaks enabled" do
6
+ setup do
7
+ @textile = TextileConverter.new
8
+ end
9
+
10
+ should "preserve single line breaks in HTML output" do
11
+ assert_equal "<p>line1<br />\nline2</p>", @textile.convert("p. line1\nline2").strip
12
+ end
13
+ end
14
+
15
+ context "Default hard_breaks enabled w/ redcloth section, no hard_breaks value" do
16
+ setup do
17
+ config = {
18
+ 'redcloth' => {}
19
+ }
20
+ @textile = TextileConverter.new config
21
+ end
22
+
23
+ should "preserve single line breaks in HTML output" do
24
+ assert_equal "<p>line1<br />\nline2</p>", @textile.convert("p. line1\nline2").strip
25
+ end
26
+ end
27
+
28
+ context "RedCloth with hard_breaks enabled" do
29
+ setup do
30
+ config = {
31
+ 'redcloth' => {
32
+ 'hard_breaks' => true # default
33
+ }
34
+ }
35
+ @textile = TextileConverter.new config
36
+ end
37
+
38
+ should "preserve single line breaks in HTML output" do
39
+ assert_equal "<p>line1<br />\nline2</p>", @textile.convert("p. line1\nline2").strip
40
+ end
41
+ end
42
+
43
+ context "RedCloth with hard_breaks disabled" do
44
+ setup do
45
+ config = {
46
+ 'redcloth' => {
47
+ 'hard_breaks' => false
48
+ }
49
+ }
50
+ @textile = TextileConverter.new config
51
+ end
52
+
53
+ should "not generate break tags in HTML output" do
54
+ assert_equal "<p>line1\nline2</p>", @textile.convert("p. line1\nline2").strip
55
+ end
56
+ end
57
+
58
+ context "RedCloth w/no_span_caps set to false" do
59
+ setup do
60
+ config = {
61
+ 'redcloth' => {
62
+ 'no_span_caps' => false
63
+ }
64
+ }
65
+ @textile = TextileConverter.new config
66
+ end
67
+ should "generate span tags around capitalized words" do
68
+ assert_equal "<p><span class=\"caps\">NSC</span></p>", @textile.convert("NSC").strip
69
+ end
70
+ end
71
+
72
+ context "RedCloth w/no_span_caps set to true" do
73
+ setup do
74
+ config = {
75
+ 'redcloth' => {
76
+ 'no_span_caps' => true
77
+ }
78
+ }
79
+ @textile = TextileConverter.new config
80
+ end
81
+
82
+ should "not generate span tags around capitalized words" do
83
+ assert_equal "<p>NSC</p>", @textile.convert("NSC").strip
84
+ end
85
+ end
86
+ end
@@ -1,6 +1,32 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestSite < Test::Unit::TestCase
4
+ context "configuring sites" do
5
+ should "have an array for plugins by default" do
6
+ site = Site.new(Jekyll::DEFAULTS)
7
+ assert_equal [File.join(Dir.pwd, '_plugins')], site.plugins
8
+ end
9
+
10
+ should "have an array for plugins if passed as a string" do
11
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => '/tmp/plugins'}))
12
+ assert_equal ['/tmp/plugins'], site.plugins
13
+ end
14
+
15
+ should "have an array for plugins if passed as an array" do
16
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => ['/tmp/plugins', '/tmp/otherplugins']}))
17
+ assert_equal ['/tmp/plugins', '/tmp/otherplugins'], site.plugins
18
+ end
19
+
20
+ should "have an empty array for plugins if nothing is passed" do
21
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => []}))
22
+ assert_equal [], site.plugins
23
+ end
24
+
25
+ should "have an empty array for plugins if nil is passed" do
26
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => nil}))
27
+ assert_equal [], site.plugins
28
+ end
29
+ end
4
30
  context "creating sites" do
5
31
  setup do
6
32
  stub(Jekyll).configuration do
@@ -126,12 +152,20 @@ class TestSite < Test::Unit::TestCase
126
152
 
127
153
  should "filter entries with exclude" do
128
154
  excludes = %w[README TODO]
129
- includes = %w[index.html site.css]
155
+ files = %w[index.html site.css .htaccess]
130
156
 
131
157
  @site.exclude = excludes
132
- assert_equal includes, @site.filter_entries(excludes + includes)
158
+ assert_equal files, @site.filter_entries(excludes + files)
133
159
  end
134
160
 
161
+ should "not filter entries within include" do
162
+ includes = %w[_index.html .htaccess]
163
+ files = %w[index.html _index.html .htaccess]
164
+
165
+ @site.include = includes
166
+ assert_equal files, @site.filter_entries(files)
167
+ end
168
+
135
169
  context 'with orphaned files in destination' do
136
170
  setup do
137
171
  clear_dest
@@ -6,9 +6,14 @@ class TestTags < Test::Unit::TestCase
6
6
 
7
7
  def create_post(content, override = {}, converter_class = Jekyll::MarkdownConverter)
8
8
  stub(Jekyll).configuration do
9
- Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override)
9
+ Jekyll::DEFAULTS.deep_merge({'pygments' => true}).deep_merge(override)
10
10
  end
11
11
  site = Site.new(Jekyll.configuration)
12
+
13
+ if override['read_posts']
14
+ site.read_posts('')
15
+ end
16
+
12
17
  info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
13
18
  @converter = site.converters.find { |c| c.class == converter_class }
14
19
  payload = { "pygments_prefix" => @converter.pygments_prefix,
@@ -31,6 +36,41 @@ CONTENT
31
36
  create_post(content, override)
32
37
  end
33
38
 
39
+ context "language name" do
40
+ should "match only the required set of chars" do
41
+ r = Jekyll::HighlightBlock::SYNTAX
42
+ assert_match r, "ruby"
43
+ assert_match r, "c#"
44
+ assert_match r, "xml+cheetah"
45
+ assert_match r, "x.y"
46
+ assert_match r, "coffee-script"
47
+
48
+ assert_no_match r, "blah^"
49
+
50
+ assert_match r, "ruby key=val"
51
+ assert_match r, "ruby a=b c=d"
52
+ end
53
+ end
54
+
55
+ context "initialized tag" do
56
+ should "work" do
57
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby ', ["test", "{% endhighlight %}", "\n"])
58
+ assert_equal({}, tag.instance_variable_get(:@options))
59
+
60
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos ', ["test", "{% endhighlight %}", "\n"])
61
+ assert_equal({'O' => "linenos=inline"}, tag.instance_variable_get(:@options))
62
+
63
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table ', ["test", "{% endhighlight %}", "\n"])
64
+ assert_equal({'O' => "linenos=table"}, tag.instance_variable_get(:@options))
65
+
66
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table nowrap', ["test", "{% endhighlight %}", "\n"])
67
+ assert_equal({'O' => "linenos=table,nowrap=true"}, tag.instance_variable_get(:@options))
68
+
69
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"])
70
+ assert_equal({'O' => "cssclass=hl,linenos=table"}, tag.instance_variable_get(:@options))
71
+ end
72
+ end
73
+
34
74
  context "post content has highlight tag" do
35
75
  setup do
36
76
  fill_post("test")
@@ -137,4 +177,25 @@ CONTENT
137
177
  end
138
178
  end
139
179
  end
180
+
181
+ context "simple page with post linking" do
182
+ setup do
183
+ content = <<CONTENT
184
+ ---
185
+ title: Post linking
186
+ ---
187
+
188
+ {% post_url 2008-11-21-complex %}
189
+ CONTENT
190
+ create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
191
+ end
192
+
193
+ should "not cause an error" do
194
+ assert_no_match /markdown\-html\-error/, @result
195
+ end
196
+
197
+ should "have the url to the \"complex\" post from 2008-11-21" do
198
+ assert_match %r{/2008/11/21/complex/}, @result
199
+ end
200
+ end
140
201
  end