jekyll-import 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -68,13 +68,16 @@ module JekyllImport
68
68
  # Writes a post out to disk
69
69
  def self.write_post(post, use_markdown, add_highlights)
70
70
  content = post[:content]
71
- if use_markdown
72
- content = html_to_markdown content
73
- content = add_syntax_highlights content if add_highlights
74
- end
75
71
 
76
- File.open("_posts/tumblr/#{post[:name]}", "w") do |f|
77
- f.puts post[:header].to_yaml + "---\n" + content
72
+ if content
73
+ if use_markdown
74
+ content = html_to_markdown content
75
+ content = add_syntax_highlights content if add_highlights
76
+ end
77
+
78
+ File.open("_posts/tumblr/#{post[:name]}", "w") do |f|
79
+ f.puts post[:header].to_yaml + "---\n" + content
80
+ end
78
81
  end
79
82
  end
80
83
 
@@ -125,6 +128,9 @@ module JekyllImport
125
128
  unless post["video-caption"].nil?
126
129
  content << "<br/>" + post["video-caption"]
127
130
  end
131
+ when "answer"
132
+ title = post["question"]
133
+ content = post["answer"]
128
134
  end
129
135
  date = Date.parse(post['date']).to_s
130
136
  title = Nokogiri::HTML(title).text
@@ -140,7 +146,7 @@ module JekyllImport
140
146
  "layout" => "post",
141
147
  "title" => title,
142
148
  "date" => Time.parse(post['date']).xmlschema,
143
- "tags" => post["tags"],
149
+ "tags" => (post["tags"] or []),
144
150
  "tumblr_url" => post["url-with-slug"]
145
151
  },
146
152
  :content => content,
@@ -115,6 +115,7 @@ module JekyllImport
115
115
  posts.post_title AS `title`,
116
116
  posts.post_name AS `slug`,
117
117
  posts.post_date AS `date`,
118
+ posts.post_date_gmt AS `date_gmt`,
118
119
  posts.post_content AS `content`,
119
120
  posts.post_excerpt AS `excerpt`,
120
121
  posts.comment_count AS `comment_count`,
@@ -276,7 +277,8 @@ module JekyllImport
276
277
  'more_anchor' => more_anchor,
277
278
  'wordpress_id' => post[:id],
278
279
  'wordpress_url' => post[:guid].to_s,
279
- 'date' => date,
280
+ 'date' => date.to_s,
281
+ 'date_gmt' => post[:date_gmt].to_s,
280
282
  'categories' => options[:categories] ? categories : nil,
281
283
  'tags' => options[:tags] ? tags : nil,
282
284
  'comments' => options[:comments] ? comments : nil,
@@ -286,7 +288,7 @@ module JekyllImport
286
288
  File.open("_posts/#{name}", "w") do |f|
287
289
  f.puts data
288
290
  f.puts "---"
289
- f.puts content
291
+ f.puts Util.wpautop(content)
290
292
  end
291
293
  end
292
294
 
@@ -26,6 +26,19 @@ module JekyllImport
26
26
  import_count = Hash.new(0)
27
27
  doc = Hpricot::XML(File.read(source))
28
28
 
29
+ # Fetch authors data from header
30
+ authors = Hash[
31
+ (doc/:channel/'wp:author').map do |author|
32
+ [author.at("wp:author_login").inner_text.strip, {
33
+ "login" => author.at("wp:author_login").inner_text.strip,
34
+ "email" => author.at("wp:author_email").inner_text,
35
+ "display_name" => author.at("wp:author_display_name").inner_text,
36
+ "first_name" => author.at("wp:author_first_name").inner_text,
37
+ "last_name" => author.at("wp:author_last_name").inner_text
38
+ }]
39
+ end
40
+ ] rescue {}
41
+
29
42
  (doc/:channel/:item).each do |item|
30
43
  title = item.at(:title).inner_text.strip
31
44
  permalink_title = item.at('wp:post_name').inner_text
@@ -51,9 +64,11 @@ module JekyllImport
51
64
  item.search("wp:postmeta").each do |meta|
52
65
  key = meta.at('wp:meta_key').inner_text
53
66
  value = meta.at('wp:meta_value').inner_text
54
- metas[key] = value;
67
+ metas[key] = value
55
68
  end
56
69
 
70
+ author_login = item.at('dc:creator').inner_text.strip
71
+
57
72
  name = "#{date.strftime('%Y-%m-%d')}-#{permalink_title}.html"
58
73
  header = {
59
74
  'layout' => type,
@@ -63,7 +78,8 @@ module JekyllImport
63
78
  'status' => status,
64
79
  'type' => type,
65
80
  'published' => published,
66
- 'meta' => metas
81
+ 'meta' => metas,
82
+ 'author' => authors[author_login]
67
83
  }
68
84
 
69
85
  begin
@@ -71,7 +87,7 @@ module JekyllImport
71
87
  File.open("_#{type}s/#{name}", "w") do |f|
72
88
  f.puts header.to_yaml
73
89
  f.puts '---'
74
- f.puts item.at('content:encoded').inner_text
90
+ f.puts Util.wpautop(item.at('content:encoded').inner_text)
75
91
  end
76
92
  rescue => e
77
93
  puts "Couldn't import post!"
@@ -0,0 +1,76 @@
1
+ module JekyllImport
2
+ module Util
3
+
4
+ # Ruby translation of wordpress wpautop (see https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php)
5
+ #
6
+ # A group of regex replaces used to identify text formatted with newlines and
7
+ # replace double line-breaks with HTML paragraph tags. The remaining
8
+ # line-breaks after conversion become <<br />> tags, unless $br is set to false
9
+ #
10
+ # @param string pee The text which has to be formatted.
11
+ # @param bool br Optional. If set, this will convert all remaining line-breaks after paragraphing. Default true.
12
+ # @return string Text which has been converted into correct paragraph tags.
13
+ #
14
+ def self.wpautop(pee, br = true)
15
+ return '' if pee.strip == ''
16
+
17
+ allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|noscript|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'
18
+ pre_tags = {}
19
+ pee = pee + "\n"
20
+
21
+ if pee.include?('<pre')
22
+ pee_parts = pee.split('</pre>')
23
+ last_pee = pee_parts.pop
24
+ pee = ''
25
+ pee_parts.each_with_index do |pee_part, i|
26
+ start = pee_part.index('<pre')
27
+
28
+ unless start
29
+ pee += pee_part
30
+ continue
31
+ end
32
+
33
+ name = "<pre wp-pre-tag-#{i}></pre>"
34
+ pre_tags[name] = pee_part[start..-1] + '</pre>'
35
+
36
+ pee += pee_part[0, start] + name
37
+ end
38
+ pee += last_pee
39
+ end
40
+
41
+ pee = pee.gsub(Regexp.new('<br />\s*<br />'), "\n\n")
42
+ pee = pee.gsub(Regexp.new("(<" + allblocks + "[^>]*>)"), "\n\\1")
43
+ pee = pee.gsub(Regexp.new("(</" + allblocks + ">)"), "\\1\n\n")
44
+ pee = pee.gsub("\r\n", "\n").gsub("\r", "\n")
45
+ if pee.include? '<object'
46
+ pee = pee.gsub(Regexp.new('\s*<param([^>]*)>\s*'), "<param\\1>")
47
+ pee = pee.gsub(Regexp.new('\s*</embed>\s*'), '</embed>')
48
+ end
49
+
50
+ pees = pee.split(/\n\s*\n/).compact
51
+ pee = ''
52
+ pees.each { |tinkle| pee += '<p>' + tinkle.chomp("\n") + "</p>\n" }
53
+ pee = pee.gsub(Regexp.new('<p>\s*</p>'), '')
54
+ pee = pee.gsub(Regexp.new('<p>([^<]+)</(div|address|form)>'), "<p>\\1</p></\\2>")
55
+ pee = pee.gsub(Regexp.new('<p>\s*(</?' + allblocks + '[^>]*>)\s*</p>'), "\\1")
56
+ pee = pee.gsub(Regexp.new('<p>(<li.+?)</p>'), "\\1")
57
+ pee = pee.gsub(Regexp.new('<p><blockquote([^>]*)>', 'i'), "<blockquote\\1><p>")
58
+ pee = pee.gsub('</blockquote></p>', '</p></blockquote>')
59
+ pee = pee.gsub(Regexp.new('<p>\s*(</?' + allblocks + '[^>]*>)'), "\\1")
60
+ pee = pee.gsub(Regexp.new('(</?' + allblocks + '[^>]*>)\s*</p>'), "\\1")
61
+ if br
62
+ pee = pee.gsub(Regexp.new('<(script|style).*?</\1>')) { |match| match.gsub("\n", "<WPPreserveNewline />") }
63
+ pee = pee.gsub(Regexp.new('(?<!<br />)\s*\n'), "<br />\n")
64
+ pee = pee.gsub('<WPPreserveNewline />', "\n")
65
+ end
66
+ pee = pee.gsub(Regexp.new('(</?' + allblocks + '[^>]*>)\s*<br />'), "\\1")
67
+ pee = pee.gsub(Regexp.new('<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)'), "\\1")
68
+ pee = pee.gsub(Regexp.new('\n</p>$'), '</p>')
69
+
70
+ pre_tags.each do |name, value|
71
+ pee.gsub!(name, value)
72
+ end
73
+ pee
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module JekyllImport
2
+ VERSION = '0.2.0'
3
+ end
@@ -5,6 +5,7 @@ require 'jekyll-import'
5
5
  module Jekyll
6
6
  module Commands
7
7
  class Import < Command
8
+
8
9
  IMPORTERS = {
9
10
  :behance => 'Behance',
10
11
  :csv => 'CSV',
@@ -28,26 +29,47 @@ module Jekyll
28
29
  :wordpressdotcom => 'WordpressDotCom'
29
30
  }
30
31
 
31
- def self.abort_on_invalid_migrator(migrator)
32
- msg = "Sorry, '#{migrator}' isn't a valid migrator. Valid choices:\n"
33
- IMPORTERS.keys.each do |k, v|
34
- msg += "* #{k}\n"
32
+ class << self
33
+
34
+ def init_with_program(prog)
35
+ prog.command(:import) do |c|
36
+ c.syntax 'import <platform> [options]'
37
+ c.description 'Import your old blog to Jekyll'
38
+ importers = JekyllImport.add_importer_commands(c)
39
+
40
+ c.action do |args, options|
41
+ if args.empty?
42
+ Jekyll.logger.warn "You must specify an importer."
43
+ Jekyll.logger.info "Valid options are:"
44
+ importers.each { |i| Jekyll.logger.info "*", "#{i}" }
45
+ end
46
+ end
47
+ end
35
48
  end
36
- abort msg
37
- end
38
49
 
39
- def self.process(migrator, options)
40
- migrator = migrator.to_s.downcase
50
+ def process(migrator, options)
51
+ migrator = migrator.to_s.downcase
41
52
 
42
- if IMPORTERS.keys.include?(migrator.to_sym)
43
- if JekyllImport::Importers.const_defined?(IMPORTERS[migrator.to_sym])
44
- klass = JekyllImport::Importers.const_get(IMPORTERS[migrator.to_sym])
45
- klass.run(options.__hash__)
53
+ if IMPORTERS.keys.include?(migrator.to_sym)
54
+ if JekyllImport::Importers.const_defined?(IMPORTERS[migrator.to_sym])
55
+ klass = JekyllImport::Importers.const_get(IMPORTERS[migrator.to_sym])
56
+ klass.run(options.__hash__)
57
+ end
58
+ else
59
+ abort_on_invalid_migrator(migrator)
46
60
  end
47
- else
48
- abort_on_invalid_migrator(migrator)
49
61
  end
62
+
63
+ def abort_on_invalid_migrator(migrator)
64
+ msg = "Sorry, '#{migrator}' isn't a valid migrator. Valid choices:\n"
65
+ IMPORTERS.keys.each do |k, v|
66
+ msg += "* #{k}\n"
67
+ end
68
+ abort msg
69
+ end
70
+
50
71
  end
72
+
51
73
  end
52
74
  end
53
75
  end
@@ -0,0 +1,16 @@
1
+ ---
2
+ layout: news_item
3
+ title: 'jekyll-import 0.2.0 Released'
4
+ date: 2014-03-16 01:05:25 -0400
5
+ author: parkr
6
+ version: 0.2.0
7
+ categories: [release]
8
+ ---
9
+
10
+ It seems jekyll-import has been collecting some dust lately. There are some
11
+ great fixes and feature improvements in here so, hey, why let them lay
12
+ unutilized? No reason at all, my dear Watson, no reason at all.
13
+
14
+ Please enjoy! Check out the [GitHub Release][] for more specifics.
15
+
16
+ [GitHub Release]: https://github.com/jekyll/jekyll-import/releases/tag/v0.2.0
@@ -220,17 +220,16 @@ body > footer a:hover img {
220
220
  .quickstart .code {
221
221
  font-size: 12px;
222
222
  display: block;
223
- margin: 0 0 -30px;
223
+ margin: 10px 0 20px;
224
224
  }
225
225
 
226
226
  @media (min-width: 768px){
227
227
  .quickstart .code {
228
228
  font-size: 18px;
229
- margin: -30px 0;
230
- float: right;
229
+ margin: 10px 0 30px;
231
230
  }
232
231
  .quickstart h4 {
233
- margin: 50px 0 0;
232
+ margin: 20px 0 0;
234
233
  text-align: center;
235
234
  }
236
235
  }
@@ -15,9 +15,25 @@ $ ruby -rubygems -e 'require "jekyll-import";
15
15
  "dbname" => "name",
16
16
  "user" => "myuser",
17
17
  "password" => "mypassword",
18
- "host" => "myhost"
18
+ "host" => "myhost",
19
+ "comments" => true
19
20
  })'
20
21
  {% endhighlight %}
21
22
 
23
+ Posts will be generated and placed in `_posts` directory.
24
+
22
25
  The only required fields are `dbname` and `user`. `password` defaults to `""`
23
- and `host` defaults to `"localhost"`.
26
+ and `host` defaults to `"localhost"`.
27
+
28
+ `comments`, which defaults to false, control the generation of
29
+ comment. If `comments` set to true, posts will be generated and placed
30
+ in `_comments` directory.
31
+
32
+
33
+ All of the posts and comments will include `post_id` in YAML front
34
+ matter to link a post and its comments.
35
+
36
+ To include imported comments as part of a post, use the yet to merge
37
+ [fork of mt-static-comments](https://github.com/shigeya/jekyll-static-comments/tree/mt_static_comments)
38
+ to include statically generate comments in your post. Fork and provide
39
+ feedback if necessary.
@@ -13,12 +13,12 @@ To import your posts from [Tumblr](http://tumblr.com), run:
13
13
  $ ruby -rubygems -e 'require "jekyll-import";
14
14
  JekyllImport::Importers::Tumblr.run({
15
15
  "url" => "http://myblog.tumblr.com",
16
- "user" => "html", # or "md"
17
- "password" => false, # whether to download images as well.
16
+ "format" => "html", # or "md"
17
+ "grab_images" => false, # whether to download images as well.
18
18
  "add_highlights" => false, # whether to wrap code blocks (indented 4 spaces) in a Liquid "highlight" tag
19
19
  "rewrite_urls" => false # whether to write pages that redirect from the old Tumblr paths to the new Jekyll paths
20
20
  })'
21
21
  {% endhighlight %}
22
22
 
23
23
  The only required field is `url`. The other fields default to their above
24
- values.
24
+ values.
@@ -29,3 +29,12 @@ $ ruby -rubygems -e 'require "jekyll-import";
29
29
  {% endhighlight %}
30
30
 
31
31
  None of the fields are required. Their defaults are as you see above.
32
+
33
+ <div class="note info">
34
+ <h5>This only imports post &amp; page data &amp; content</h5>
35
+ <p>
36
+ This importer only converts your posts and creates YAML front-matter.
37
+ It does not import any layouts, styling, or external files
38
+ (images, CSS, etc.).
39
+ </p>
40
+ </div>
@@ -37,10 +37,10 @@ overview: true
37
37
  </section>
38
38
  <section class="quickstart">
39
39
  <div class="grid">
40
- <div class="unit golden-small center-on-mobiles">
40
+ <div class="unit whole center-on-mobiles">
41
41
  <h4>Get up and running <em>in&nbsp;seconds</em>.</h4>
42
42
  </div>
43
- <div class="unit golden-large code">
43
+ <div class="unit whole center-on-mobiles code">
44
44
  <p class="title">Quick-start Instructions</p>
45
45
  <div class="shell">
46
46
  <p class="line">
@@ -61,12 +61,7 @@ overview: true
61
61
  <p class="line">
62
62
  <span class="path">~/my-awesome-site</span>
63
63
  <span class="prompt">$</span>
64
- <span class="command">jekyll import wordpress \ </span>
65
- </p>
66
- <p class="line">
67
- <span class="path"> </span>
68
- <span class="prompt"> </span>
69
- <span class="command">--source wordpress.xml</span>
64
+ <span class="command">jekyll import wordpressdotcom --source wordpress.xml</span>
70
65
  </p>
71
66
  <p class="line">
72
67
  <span class="path">~/my-awesome-site</span>
@@ -3,59 +3,88 @@ require 'json'
3
3
 
4
4
  class TestTumblrImporter < Test::Unit::TestCase
5
5
 
6
- context "A Tumblr blog" do
7
- setup do
6
+ context "A Tumblr blog" do
7
+ setup do
8
8
  Importers::Tumblr.require_deps
9
- @jsonPayload = '{"tumblelog":{"title":"JekyllImport","description":"Jekyll Importer Test.","name":"JekyllImport","timezone":"Canada\/Atlantic","cname":"https://github.com/jekyll/jekyll-import/","feeds":[]},"posts-start":0,"posts-total":"1","posts-type":false,"posts":[{"id":54759400073,"url":"https:\/\/github.com\/post\/54759400073","url-with-slug":"http:\/\/github.com\/post\/54759400073\/jekyll-test","type":"regular","date-gmt":"2013-07-06 16:27:23 GMT","date":"Sat, 06 Jul 2013 13:27:23","bookmarklet":null,"mobile":null,"feed-item":"","from-feed-id":0,"unix-timestamp":1373128043,"format":"html","reblog-key":"0L6yPcHr","slug":"jekyll-test","regular-title":"Jekyll: Test","regular-body":"<p>Testing...<\/p>","tags":["jekyll"]}]}'
10
- @posts = JSON.parse(@jsonPayload)
11
- end
9
+ @jsonPayload = '{"tumblelog":{"title":"JekyllImport","description":"Jekyll Importer Test.","name":"JekyllImport","timezone":"Canada\/Atlantic","cname":"https://github.com/jekyll/jekyll-import/","feeds":[]},"posts-start":0,"posts-total":"2","posts-type":false,"posts":[{"id":54759400073,"url":"https:\/\/github.com\/post\/54759400073","url-with-slug":"http:\/\/github.com\/post\/54759400073\/jekyll-test","type":"regular","date-gmt":"2013-07-06 16:27:23 GMT","date":"Sat, 06 Jul 2013 13:27:23","bookmarklet":null,"mobile":null,"feed-item":"","from-feed-id":0,"unix-timestamp":1373128043,"format":"html","reblog-key":"0L6yPcHr","slug":"jekyll-test","regular-title":"Jekyll: Test","regular-body":"<p>Testing...<\/p>","tags":["jekyll"]},{"id":"71845593082","url":"http:\/\/example.com\/post\/71845593082","url-with-slug":"http:\/\/example.com\/post\/71845593082\/knock-knock","type":"answer","date-gmt":"2014-01-01 14:08:45 GMT","date":"Wed, 01 Jan 2014 09:08:45","bookmarklet":0,"mobile":0,"feed-item":"","from-feed-id":0,"unix-timestamp":1388585325,"format":"html","reblog-key":"jPfWHFnT","slug":"knock-knock","question":"Knock knock?","answer":"<p>Who is there?<\/p>"}]}'
10
+ @posts = JSON.parse(@jsonPayload)
11
+ @batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
12
+ end
12
13
 
13
- should "have a post" do
14
- assert_equal(1, @posts["posts"].size)
15
- end
14
+ should "have a post" do
15
+ assert_equal(2, @posts["posts"].size)
16
+ end
17
+
18
+ should "convert post into hash" do
19
+ refute_nil(@batch, "a batch with a valid post should exist")
20
+ end
16
21
 
17
- should "have a regular post" do
18
- assert_equal("regular", @posts['posts'][0]['type'])
19
- end
22
+ context "post" do
23
+ should "have a corresponding type" do
24
+ assert_equal("regular", @posts['posts'][0]['type'])
25
+ end
26
+
27
+ should "have a hash with a valid name" do
28
+ assert_equal("2013-07-06-jekyll-test.html", @batch[0][:name])
29
+ end
30
+
31
+ should "have a hash with a valid layout" do
32
+ assert_equal("post", @batch[0][:header]['layout'])
33
+ end
34
+
35
+ should "have a hash with a valid title" do
36
+ assert_equal("Jekyll: Test", @batch[0][:header]['title'])
37
+ end
38
+
39
+ should "have a hash with valid tags" do
40
+ assert_equal("jekyll", @batch[0][:header]['tags'][0])
41
+ end
42
+
43
+ should "have a hash with valid content" do
44
+ assert_equal("<p>Testing...</p>", @batch[0][:content])
45
+ end
46
+
47
+ should "have a hash with a valid url" do
48
+ assert_equal("https://github.com/post/54759400073", @batch[0][:url])
49
+ end
50
+
51
+ should "have a hash with a valid slug" do
52
+ assert_equal("http://github.com/post/54759400073/jekyll-test", @batch[0][:slug])
53
+ end
54
+ end
20
55
 
21
- should "convert post into hash" do
22
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
23
- refute_nil(batch, "a batch with a valid post should exist")
24
- end
25
-
26
- should "have a hash with a valid name" do
27
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
28
- assert_equal("2013-07-06-jekyll-test.html", batch[0][:name])
29
- end
30
-
31
- should "have a hash with a valid layout" do
32
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
33
- assert_equal("post", batch[0][:header]['layout'])
34
- end
35
-
36
- should "have a hash with a valid title" do
37
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
38
- assert_equal("Jekyll: Test", batch[0][:header]['title'])
39
- end
40
-
41
- should "have a hash with valid tags" do
42
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
43
- assert_equal("jekyll", batch[0][:header]['tags'][0])
44
- end
45
-
46
- should "have a hash with valid content" do
47
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
48
- assert_equal("<p>Testing...</p>", batch[0][:content])
49
- end
50
-
51
- should "have a hash with a valid url" do
52
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
53
- assert_equal("https://github.com/post/54759400073", batch[0][:url])
54
- end
55
-
56
- should "have a hash with a valid slug" do
57
- batch = @posts["posts"].map { |post| Importers::Tumblr.post_to_hash(post, 'html') }
58
- assert_equal("http://github.com/post/54759400073/jekyll-test", batch[0][:slug])
59
- end
60
- end
61
- end
56
+ context "answer" do
57
+ should "have a corresponding type" do
58
+ assert_equal("answer", @posts['posts'][1]['type'])
59
+ end
60
+
61
+ should "have a hash with a valid name" do
62
+ assert_equal("2014-01-01-knock-knock.html", @batch[1][:name])
63
+ end
64
+
65
+ should "have a hash with a valid layout" do
66
+ assert_equal("post", @batch[1][:header]['layout'])
67
+ end
68
+
69
+ should "have a hash with a valid title" do
70
+ assert_equal("Knock knock?", @batch[1][:header]['title'])
71
+ end
72
+
73
+ should "have a hash with valid tags" do
74
+ assert_equal([], @batch[1][:header]['tags'])
75
+ end
76
+
77
+ should "have a hash with valid content" do
78
+ assert_equal("<p>Who is there?</p>", @batch[1][:content])
79
+ end
80
+
81
+ should "have a hash with a valid url" do
82
+ assert_equal("http://example.com/post/71845593082", @batch[1][:url])
83
+ end
84
+
85
+ should "have a hash with a valid slug" do
86
+ assert_equal("http://example.com/post/71845593082/knock-knock", @batch[1][:slug])
87
+ end
88
+ end
89
+ end
90
+ end