henrik-jekyll 0.5.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 (47) hide show
  1. data/History.txt +115 -0
  2. data/README.textile +545 -0
  3. data/Rakefile +91 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/jekyll +140 -0
  6. data/lib/jekyll/albino.rb +120 -0
  7. data/lib/jekyll/converters/csv.rb +26 -0
  8. data/lib/jekyll/converters/mephisto.rb +79 -0
  9. data/lib/jekyll/converters/mt.rb +59 -0
  10. data/lib/jekyll/converters/textpattern.rb +50 -0
  11. data/lib/jekyll/converters/typo.rb +49 -0
  12. data/lib/jekyll/converters/wordpress.rb +54 -0
  13. data/lib/jekyll/convertible.rb +82 -0
  14. data/lib/jekyll/core_ext.rb +22 -0
  15. data/lib/jekyll/filters.rb +43 -0
  16. data/lib/jekyll/layout.rb +36 -0
  17. data/lib/jekyll/page.rb +67 -0
  18. data/lib/jekyll/post.rb +205 -0
  19. data/lib/jekyll/site.rb +238 -0
  20. data/lib/jekyll/tags/highlight.rb +56 -0
  21. data/lib/jekyll/tags/include.rb +31 -0
  22. data/lib/jekyll.rb +83 -0
  23. data/test/helper.rb +24 -0
  24. data/test/source/_includes/sig.markdown +3 -0
  25. data/test/source/_layouts/default.html +27 -0
  26. data/test/source/_layouts/simple.html +1 -0
  27. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  28. data/test/source/_posts/2008-02-02-published.textile +8 -0
  29. data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
  30. data/test/source/_posts/2008-11-21-complex.textile +8 -0
  31. data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
  32. data/test/source/_posts/2008-12-13-include.markdown +8 -0
  33. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  34. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  35. data/test/source/_posts/2009-01-27-category.textile +7 -0
  36. data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
  37. data/test/source/css/screen.css +76 -0
  38. data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
  39. data/test/source/index.html +22 -0
  40. data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
  41. data/test/suite.rb +9 -0
  42. data/test/test_filters.rb +41 -0
  43. data/test/test_generated_site.rb +38 -0
  44. data/test/test_post.rb +145 -0
  45. data/test/test_site.rb +57 -0
  46. data/test/test_tags.rb +35 -0
  47. metadata +163 -0
@@ -0,0 +1,56 @@
1
+ module Jekyll
2
+
3
+ class HighlightBlock < Liquid::Block
4
+ include Liquid::StandardFilters
5
+
6
+ # we need a language, but the linenos argument is optional.
7
+ SYNTAX = /(\w+)\s?(:?linenos)?\s?/
8
+
9
+ def initialize(tag_name, markup, tokens)
10
+ super
11
+ if markup =~ SYNTAX
12
+ @lang = $1
13
+ if defined? $2
14
+ # additional options to pass to Albino.
15
+ @options = { 'O' => 'linenos=inline' }
16
+ else
17
+ @options = {}
18
+ end
19
+ else
20
+ raise SyntaxError.new("Syntax Error in 'highlight' - Valid syntax: highlight <lang> [linenos]")
21
+ end
22
+ end
23
+
24
+ def render(context)
25
+ if context.registers[:site].pygments
26
+ render_pygments(context, super.to_s)
27
+ else
28
+ render_codehighlighter(context, super.to_s)
29
+ end
30
+ end
31
+
32
+ def render_pygments(context, code)
33
+ if context["content_type"] == :markdown
34
+ return "\n" + Albino.new(code, @lang).to_s(@options) + "\n"
35
+ elsif context["content_type"] == :textile
36
+ return "<notextile>" + Albino.new(code, @lang).to_s(@options) + "</notextile>"
37
+ else
38
+ return Albino.new(code, @lang).to_s(@options)
39
+ end
40
+ end
41
+
42
+ def render_codehighlighter(context, code)
43
+ #The div is required because RDiscount blows ass
44
+ <<-HTML
45
+ <div>
46
+ <pre>
47
+ <code class='#{@lang}'>#{h(code).strip}</code>
48
+ </pre>
49
+ </div>
50
+ HTML
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ Liquid::Template.register_tag('highlight', Jekyll::HighlightBlock)
@@ -0,0 +1,31 @@
1
+ module Jekyll
2
+
3
+ class IncludeTag < Liquid::Tag
4
+ def initialize(tag_name, file, tokens)
5
+ super
6
+ @file = file.strip
7
+ end
8
+
9
+ def render(context)
10
+ if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
11
+ return "Include file '#{@file}' contains invalid characters or sequences"
12
+ end
13
+
14
+ Dir.chdir(File.join(context.registers[:site].source, '_includes')) do
15
+ choices = Dir['**/*'].reject { |x| File.symlink?(x) }
16
+ if choices.include?(@file)
17
+ source = File.read(@file)
18
+ partial = Liquid::Template.parse(source)
19
+ context.stack do
20
+ partial.render(context)
21
+ end
22
+ else
23
+ "Included file '#{@file}' not found in _includes directory"
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ Liquid::Template.register_tag('include', Jekyll::IncludeTag)
data/lib/jekyll.rb ADDED
@@ -0,0 +1,83 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ # rubygems
4
+ require 'rubygems'
5
+
6
+ # core
7
+ require 'fileutils'
8
+ require 'time'
9
+ require 'yaml'
10
+
11
+ # stdlib
12
+
13
+ # 3rd party
14
+ require 'liquid'
15
+ require 'redcloth'
16
+
17
+ # internal requires
18
+ require 'jekyll/core_ext'
19
+ require 'jekyll/site'
20
+ require 'jekyll/convertible'
21
+ require 'jekyll/layout'
22
+ require 'jekyll/page'
23
+ require 'jekyll/post'
24
+ require 'jekyll/filters'
25
+ require 'jekyll/tags/highlight'
26
+ require 'jekyll/tags/include'
27
+ require 'jekyll/albino'
28
+
29
+ module Jekyll
30
+ # Default options. Overriden by values in _config.yaml or command-line opts.
31
+ # (Strings rather symbols used for compatability with YAML)
32
+ DEFAULTS = {
33
+ 'auto' => false,
34
+ 'server' => false,
35
+ 'server_port' => 4000,
36
+
37
+ 'source' => '.',
38
+ 'destination' => File.join('.', '_site'),
39
+
40
+ 'lsi' => false,
41
+ 'pygments' => false,
42
+ 'markdown' => 'maruku',
43
+ 'permalink' => 'date',
44
+
45
+ 'maruku' => {
46
+ 'use_tex' => false,
47
+ 'use_divs' => false,
48
+ 'png_engine' => 'blahtex',
49
+ 'png_dir' => 'images/latex',
50
+ 'png_url' => '/images/latex'
51
+ }
52
+ }
53
+
54
+ # Generate a Jekyll configuration Hash by merging the default options
55
+ # with anything in _config.yml, and adding the given options on top
56
+ # +override+ is a Hash of config directives
57
+ #
58
+ # Returns Hash
59
+ def self.configuration(override)
60
+ # _config.yml may override default source location, but until
61
+ # then, we need to know where to look for _config.yml
62
+ source = override['source'] || Jekyll::DEFAULTS['source']
63
+
64
+ # Get configuration from <source>/_config.yaml
65
+ config = {}
66
+ config_file = File.join(source, '_config.yml')
67
+ begin
68
+ config = YAML.load_file(config_file)
69
+ puts "Configuration from #{config_file}"
70
+ rescue => err
71
+ puts "WARNING: Could not read configuration. Using defaults (and options)."
72
+ puts "\t" + err
73
+ end
74
+
75
+ # Merge DEFAULTS < _config.yml < override
76
+ Jekyll::DEFAULTS.deep_merge(config).deep_merge(override)
77
+ end
78
+
79
+ def self.version
80
+ yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
81
+ "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
82
+ end
83
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib jekyll])
2
+
3
+ require 'test/unit'
4
+ require 'redgreen'
5
+ require 'shoulda'
6
+ require 'rr'
7
+
8
+ include Jekyll
9
+
10
+ class Test::Unit::TestCase
11
+ include RR::Adapters::TestUnit
12
+
13
+ def dest_dir(*subdirs)
14
+ File.join(File.dirname(__FILE__), 'dest', *subdirs)
15
+ end
16
+
17
+ def source_dir(*subdirs)
18
+ File.join(File.dirname(__FILE__), 'source', *subdirs)
19
+ end
20
+
21
+ def clear_dest
22
+ FileUtils.rm_rf(dest_dir)
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ --
2
+ Tom Preston-Werner
3
+ github.com/mojombo
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
5
+ <head>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <title>{{ page.title }}</title>
8
+ <meta name="author" content="<%= @page.author %>" />
9
+
10
+ <!-- CodeRay syntax highlighting CSS -->
11
+ <link rel="stylesheet" href="/css/coderay.css" type="text/css" />
12
+
13
+ <!-- Homepage CSS -->
14
+ <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen, projection" />
15
+ </head>
16
+ <body>
17
+
18
+ <div class="site">
19
+ <div class="title">
20
+ Tom Preston-Werner
21
+ </div>
22
+
23
+ {{ content }}
24
+ </div>
25
+
26
+ </body>
27
+ </html>
@@ -0,0 +1 @@
1
+ <<< {{ content }} >>>
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Not published!
4
+ published: false
5
+ category: publish_test
6
+ ---
7
+
8
+ This should *not* be published!
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Publish
4
+ category: publish_test
5
+ ---
6
+
7
+ This should be published.
8
+
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Foo Bar
4
+ ---
5
+
6
+ h1. {{ page.title }}
7
+
8
+ Best *post* ever
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Complex
4
+ ---
5
+
6
+ url: {{ page.url }}
7
+ date: {{ page.date }}
8
+ id: {{ page.id }}
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Post with Permalink
3
+ permalink: my_category/permalinked-post
4
+ ---
5
+
6
+ h1. {{ page.title }}
7
+
8
+
9
+ <p>Best <strong>post</strong> ever</p>
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Include
4
+ ---
5
+
6
+ {% include sig.markdown %}
7
+
8
+ This _is_ cool
@@ -0,0 +1,10 @@
1
+ ---
2
+ layout: default
3
+ title: Array categories in YAML
4
+ categories:
5
+ - foo
6
+ - bar
7
+ - baz
8
+ ---
9
+
10
+ Best *post* ever
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: default
3
+ title: Categories in YAML
4
+ categories: foo bar baz
5
+ ---
6
+
7
+ Best *post* ever
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: default
3
+ title: Category in YAML
4
+ category: foo
5
+ ---
6
+
7
+ Best *post* ever
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: default
3
+ title: Categories
4
+ ---
5
+
6
+ Categories _should_ work
@@ -0,0 +1,76 @@
1
+ /*****************************************************************************/
2
+ /*
3
+ /* Common
4
+ /*
5
+ /*****************************************************************************/
6
+
7
+ /* Global Reset */
8
+
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ html, body {
15
+ height: 100%;
16
+ }
17
+
18
+ body {
19
+ background-color: white;
20
+ font: 13.34px helvetica, arial, clean, sans-serif;
21
+ *font-size: small;
22
+ text-align: center;
23
+ }
24
+
25
+ h1, h2, h3, h4, h5, h6 {
26
+ font-size: 100%;
27
+ }
28
+
29
+ h1 {
30
+ margin-bottom: 1em;
31
+ }
32
+
33
+ p {
34
+ margin: 1em 0;
35
+ }
36
+
37
+ a {
38
+ color: #00a;
39
+ }
40
+
41
+ a:hover {
42
+ color: black;
43
+ }
44
+
45
+ a:visited {
46
+ color: #a0a;
47
+ }
48
+
49
+ table {
50
+ font-size: inherit;
51
+ font: 100%;
52
+ }
53
+
54
+ /*****************************************************************************/
55
+ /*
56
+ /* Site
57
+ /*
58
+ /*****************************************************************************/
59
+
60
+ .site {
61
+ font-size: 110%;
62
+ text-align: justify;
63
+ width: 40em;
64
+ margin: 3em auto 2em auto;
65
+ line-height: 1.5em;
66
+ }
67
+
68
+ .title {
69
+ color: #a00;
70
+ font-weight: bold;
71
+ margin-bottom: 2em;
72
+ }
73
+
74
+ .site .meta {
75
+ color: #aaa;
76
+ }
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: default
3
+ title: Topical Post
4
+ ---
5
+
6
+ h1. {{ page.title }}
7
+
8
+ This post has a topic.
@@ -0,0 +1,22 @@
1
+ ---
2
+ layout: default
3
+ title: Tom Preston-Werner
4
+ ---
5
+
6
+ h1. Welcome to my site
7
+
8
+ h2. Please read our {{ site.posts | size }} Posts
9
+
10
+ <ul>
11
+ {% for post in site.posts %}
12
+ <li>{{ post.date }} <a href="{{ post.url }}">{{ post.title }}</a></li>
13
+ {% endfor %}
14
+ </ul>
15
+
16
+ {% assign first_post = site.posts.first %}
17
+ <div id="first_post">
18
+ <h1>{{ first_post.title }}</h1>
19
+ <div>
20
+ {{ first_post.content }}
21
+ </div>
22
+ </div>
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: default
3
+ title: Categories
4
+ ---
5
+
6
+ Categories _should_ work. Even if ordered after index.
data/test/suite.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'test/unit'
2
+
3
+ # for some reason these tests fail when run via TextMate
4
+ # but succeed when run on the command line.
5
+
6
+ tests = Dir["#{File.dirname(__FILE__)}/test_*.rb"]
7
+ tests.each do |file|
8
+ require file
9
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestFilters < Test::Unit::TestCase
4
+ class JekyllFilter
5
+ include Jekyll::Filters
6
+ end
7
+
8
+ context "filters" do
9
+ setup do
10
+ @filter = JekyllFilter.new
11
+ end
12
+
13
+ should "textilize with simple string" do
14
+ assert_equal "<p>something <strong>really</strong> simple</p>", @filter.textilize("something *really* simple")
15
+ end
16
+
17
+ should "convert array to sentence string with no args" do
18
+ assert_equal "", @filter.array_to_sentence_string([])
19
+ end
20
+
21
+ should "convert array to sentence string with one arg" do
22
+ assert_equal "1", @filter.array_to_sentence_string([1])
23
+ assert_equal "chunky", @filter.array_to_sentence_string(["chunky"])
24
+ end
25
+
26
+ should "convert array to sentence string with two args" do
27
+ assert_equal "1 and 2", @filter.array_to_sentence_string([1, 2])
28
+ assert_equal "chunky and bacon", @filter.array_to_sentence_string(["chunky", "bacon"])
29
+ end
30
+
31
+ should "convert array to sentence string with multiple args" do
32
+ assert_equal "1, 2, 3, and 4", @filter.array_to_sentence_string([1, 2, 3, 4])
33
+ assert_equal "chunky, bacon, bits, and pieces", @filter.array_to_sentence_string(["chunky", "bacon", "bits", "pieces"])
34
+ end
35
+
36
+ should "escape xml with ampersands" do
37
+ assert_equal "AT&amp;T", @filter.xml_escape("AT&T")
38
+ assert_equal "&lt;code&gt;command &amp;lt;filename&amp;gt;&lt;/code&gt;", @filter.xml_escape("<code>command &lt;filename&gt;</code>")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestGeneratedSite < Test::Unit::TestCase
4
+ context "generated sites" do
5
+ setup do
6
+ clear_dest
7
+ stub(Jekyll).configuration do
8
+ Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
9
+ end
10
+
11
+ @site = Site.new(Jekyll.configuration)
12
+ @site.process
13
+ @index = File.read(dest_dir('index.html'))
14
+ end
15
+
16
+ should "insert site.posts into the index" do
17
+ assert @index.include?("#{@site.posts.size} Posts")
18
+ end
19
+
20
+ should "render post.content" do
21
+ latest_post = Dir[source_dir('_posts', '*')].last
22
+ post = Post.new(@site, source_dir, '', File.basename(latest_post))
23
+ post.transform
24
+ assert @index.include?(post.content)
25
+ end
26
+
27
+ should "hide unpublished posts" do
28
+ published = Dir[dest_dir('publish_test/2008/02/02/*.html')].map {|f| File.basename(f)}
29
+
30
+ assert_equal 1, published.size
31
+ assert_equal "published.html", published.first
32
+ end
33
+
34
+ should "not copy _posts directory" do
35
+ assert !File.exist?(dest_dir('_posts'))
36
+ end
37
+ end
38
+ end
data/test/test_post.rb ADDED
@@ -0,0 +1,145 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestPost < Test::Unit::TestCase
4
+ def setup_post(file)
5
+ Post.new(@site, source_dir, '', file)
6
+ end
7
+
8
+ def do_render(post)
9
+ layouts = { "default" => Layout.new(@site, source_dir('_layouts'), "simple.html")}
10
+ post.render(layouts, {"site" => {"posts" => []}})
11
+ end
12
+
13
+ context "A Post" do
14
+ setup do
15
+ clear_dest
16
+ stub(Jekyll).configuration { Jekyll::DEFAULTS }
17
+ @site = Site.new(Jekyll.configuration)
18
+ end
19
+
20
+ should "ensure valid posts are valid" do
21
+ assert Post.valid?("2008-10-19-foo-bar.textile")
22
+ assert Post.valid?("foo/bar/2008-10-19-foo-bar.textile")
23
+
24
+ assert !Post.valid?("lol2008-10-19-foo-bar.textile")
25
+ assert !Post.valid?("blah")
26
+ end
27
+
28
+ context "processing posts" do
29
+ setup do
30
+ @post = Post.allocate
31
+ @post.site = @site
32
+
33
+ @real_file = "2008-10-18-foo-bar.textile"
34
+ @fake_file = "2008-10-19-foo-bar.textile"
35
+ @source = source_dir('_posts')
36
+ end
37
+
38
+ should "keep date, title, and markup type" do
39
+ @post.process(@fake_file)
40
+
41
+ assert_equal Time.parse("2008-10-19"), @post.date
42
+ assert_equal "foo-bar", @post.slug
43
+ assert_equal ".textile", @post.ext
44
+ end
45
+
46
+ should "create url based on date and title" do
47
+ @post.categories = []
48
+ @post.process(@fake_file)
49
+ assert_equal "/2008/10/19/foo-bar.html", @post.url
50
+ end
51
+
52
+ should "respect permalink" do
53
+ file = "2008-12-03-permalinked-post.textile"
54
+ @post.process(file)
55
+ @post.read_yaml(@source, file)
56
+
57
+ assert_equal "my_category/permalinked-post", @post.permalink
58
+ assert_equal "my_category/", @post.dir
59
+ assert_equal "my_category/permalinked-post", @post.url
60
+ end
61
+
62
+ should "read yaml front-matter" do
63
+ @post.read_yaml(@source, @real_file)
64
+
65
+ assert_equal({"title" => "Foo Bar", "layout" => "default"}, @post.data)
66
+ assert_equal "\nh1. {{ page.title }}\n\nBest *post* ever", @post.content
67
+ end
68
+
69
+ should "transform textile" do
70
+ @post.process(@real_file)
71
+ @post.read_yaml(@source, @real_file)
72
+ @post.transform
73
+
74
+ assert_equal "<h1>{{ page.title }}</h1>\n<p>Best <strong>post</strong> ever</p>", @post.content
75
+ end
76
+ end
77
+
78
+ context "initializing posts" do
79
+ should "publish when published yaml is no specified" do
80
+ post = setup_post("2008-02-02-published.textile")
81
+ assert_equal true, post.published
82
+ end
83
+
84
+ should "not published when published yaml is false" do
85
+ post = setup_post("2008-02-02-not-published.textile")
86
+ assert_equal false, post.published
87
+ end
88
+
89
+ should "recognize category in yaml" do
90
+ post = setup_post("2009-01-27-category.textile")
91
+ assert post.categories.include?('foo')
92
+ end
93
+
94
+ should "recognize several categories in yaml" do
95
+ post = setup_post("2009-01-27-categories.textile")
96
+ assert post.categories.include?('foo')
97
+ assert post.categories.include?('bar')
98
+ assert post.categories.include?('baz')
99
+ end
100
+
101
+ context "rendering" do
102
+ setup do
103
+ clear_dest
104
+ end
105
+
106
+ should "render properly" do
107
+ post = setup_post("2008-10-18-foo-bar.textile")
108
+ do_render(post)
109
+ assert_equal "<<< <h1>Foo Bar</h1>\n<p>Best <strong>post</strong> ever</p> >>>", post.output
110
+ end
111
+
112
+ should "write properly" do
113
+ post = setup_post("2008-10-18-foo-bar.textile")
114
+ do_render(post)
115
+ post.write(dest_dir)
116
+
117
+ assert File.directory?(dest_dir)
118
+ assert File.exists?(File.join(dest_dir, '2008', '10', '18', 'foo-bar.html'))
119
+ end
120
+
121
+ should "insert data" do
122
+ post = setup_post("2008-11-21-complex.textile")
123
+ do_render(post)
124
+
125
+ assert_equal "<<< <p>url: /2008/11/21/complex.html<br />\ndate: #{Time.parse("2008-11-21")}<br />\nid: /2008/11/21/complex</p> >>>", post.output
126
+ end
127
+
128
+ should "include templates" do
129
+ post = setup_post("2008-12-13-include.markdown")
130
+ post.site.source = File.join(File.dirname(__FILE__), 'source')
131
+ do_render(post)
132
+
133
+ assert_equal "<<< <hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n\n<p>This <em>is</em> cool</p> >>>", post.output
134
+ end
135
+ end
136
+ end
137
+
138
+ should "generate categories and topics" do
139
+ post = Post.new(@site, File.join(File.dirname(__FILE__), *%w[source]), 'foo', 'bar/2008-12-12-topical-post.textile')
140
+ assert_equal ['foo'], post.categories
141
+ assert_equal ['bar'], post.topics
142
+ end
143
+
144
+ end
145
+ end