wp2middleman 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b67863aef362146f51783f4a7ced9cdeb3c0c2f
4
+ data.tar.gz: 19c5c8e3928ca0105aeb94401d16cb7dc04793e9
5
+ SHA512:
6
+ metadata.gz: 35557bbabfae2b1a3a018e42e2697ae94fa2212399a22ec8ecfa58af9948fec267de57c18b260709f18ede882bc692e71eff582ce9be304af32db6777fe36307
7
+ data.tar.gz: f5fa2d3f54cd1814e86f9336e378635a143c5b112d221d6fe0695cc5c42505b137dfbed2915559ccd0259bcedd592454ac07cf8e6efaf87f2879439c7845de4d
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ coverage/
3
+ export/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - ruby-head
4
+ matrix:
5
+ allow_failures:
6
+ - rvm: ruby-head
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "pry"
7
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Mike Ball
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ [![Build Status](https://travis-ci.org/mdb/wp2middleman.png?branch=master)](https://travis-ci.org/mdb/wp2middleman)
2
+
3
+ # wp2middleman
4
+
5
+ Migrate the posts contained in a Wordpress XML export file to Middleman-style markdown files.
6
+
7
+ ## Installation
8
+
9
+ ```
10
+ git clone http://github.com/mdb/wp2middleman
11
+ cd wp2middleman
12
+ bundle install
13
+ rake install
14
+ ```
15
+
16
+ ## Commandline Usage
17
+
18
+ ```
19
+ wp2mm some_wordpress_export.xml
20
+ ```
21
+
22
+ Results in YYYY-MM-DD-Some-Title.html.markdown, formatted as such:
23
+
24
+ ```
25
+ ---
26
+ title: 'Some Title'
27
+ date: YYYY-MM-DD
28
+ tags: foo, bar
29
+ ---
30
+
31
+ <p>The post content in HTML or text, depending on how it was saved to Wordpress.</p>
32
+ <ul>
33
+ <li>list item</li>
34
+ <li>another list item</li>
35
+ </ul>
36
+ ```
37
+
38
+ ### Optional parameters
39
+
40
+ ```
41
+ wp2mm some_wordpress_export.xml --body_to_markdown true
42
+ ```
43
+
44
+ Results in YYYY-MM-DD-Some-Title.html.markdown, formatted as such:
45
+
46
+ ```
47
+ ---
48
+ title: 'Some Title'
49
+ date: YYYY-MM-DD
50
+ tags: foo, bar
51
+ ---
52
+
53
+ The post content in markdown or text, depending on how it was saved to Wordpress.
54
+
55
+ * list item
56
+ * another list item
57
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ task default: :spec
5
+
6
+ RSpec::Core::RakeTask.new
data/bin/wp2mm ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
4
+
5
+ require 'wp2middleman'
6
+
7
+ ARGV.unshift(:wp2mm) if ARGV[0]
8
+
9
+ WP2Middleman::CLI.start
@@ -0,0 +1,31 @@
1
+ require 'thor'
2
+
3
+ module WP2Middleman
4
+ class CLI < Thor
5
+ default_task :wp2mm
6
+
7
+ desc "WORDPRESS XML EXPORT FILE", "Migrate Wordpress posts to Middleman-style markdown files"
8
+ option :body_to_markdown
9
+ def wp2mm(wp_xml_export = nil)
10
+ return usage unless wp_xml_export
11
+
12
+ unless File.file? wp_xml_export
13
+ error "#{wp_xml_export} is not a valid file"
14
+ exit 1
15
+ end
16
+
17
+ WP2Middleman.migrate(wp_xml_export, options[:body_to_markdown])
18
+
19
+ say "Successfully migrated #{wp_xml_export}", "\033[32m"
20
+ end
21
+
22
+ desc "usage", "Display usage banner", hide: true
23
+ def usage
24
+ say "wp2middleman #{WP2Middleman::VERSION}"
25
+ say "https://github.com/mdb/wp2middleman"
26
+ say "\n"
27
+
28
+ help
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,78 @@
1
+ require 'yaml'
2
+
3
+ module WP2Middleman
4
+ class Migrator
5
+
6
+ attr_reader :posts
7
+
8
+ def initialize(wp_xml_export_file, body_to_markdown: false)
9
+ @body_to_markdown = body_to_markdown
10
+ @posts = WP2Middleman::PostCollection.new(wp_xml_export_file).posts
11
+ end
12
+
13
+ def migrate
14
+ ensure_export_directory
15
+
16
+ @posts.each do |post|
17
+ write_file(post)
18
+ end
19
+ end
20
+
21
+ def write_file(post)
22
+ if valid_post_data(post)
23
+ File.open(full_filename(post), "w") do |file|
24
+ file.write(file_content(post))
25
+ end
26
+ end
27
+ end
28
+
29
+ def file_content(post)
30
+ yaml = frontmatter(post).to_yaml.strip
31
+
32
+ <<-EOS.gsub(/^ {8}/, '')
33
+ #{yaml}
34
+ ---
35
+
36
+ #{formatted_post_content(post)}
37
+ EOS
38
+ end
39
+
40
+ def frontmatter(post)
41
+ data = {
42
+ 'title' => post.title,
43
+ 'date' => post.date_published,
44
+ 'tags' => post.tags
45
+ }
46
+
47
+ data['published'] = false if !post.published?
48
+
49
+ data
50
+ end
51
+
52
+ def formatted_post_content(post)
53
+ if @body_to_markdown
54
+ post.markdown_content
55
+ else
56
+ post.content
57
+ end
58
+ end
59
+
60
+ def full_filename(post)
61
+ "#{output_path}#{post.filename}.html.markdown"
62
+ end
63
+
64
+ def valid_post_data(post)
65
+ !(post.post_date.nil? || post.title.nil? || post.date_published.nil? || post.content.nil?)
66
+ end
67
+
68
+ def output_path
69
+ "#{Dir.pwd}/export/"
70
+ end
71
+
72
+ def ensure_export_directory
73
+ unless File.directory? output_path
74
+ FileUtils.mkdir_p output_path
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,73 @@
1
+ require 'html2markdown'
2
+
3
+ module WP2Middleman
4
+ class Post
5
+ attr_accessor :post
6
+
7
+ def initialize(nokogiri_post_doc)
8
+ @post = nokogiri_post_doc
9
+ end
10
+
11
+ def title
12
+ post.css('title').text
13
+ end
14
+
15
+ def title_for_filename
16
+ title.gsub(/[^\w\s_-]+/, '')
17
+ .gsub(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
18
+ .gsub(/\s+/, '-')
19
+ end
20
+
21
+ def filename
22
+ "#{date_published}-#{title_for_filename}"
23
+ end
24
+
25
+ def post_date
26
+ post.xpath("wp:post_date").first.inner_text
27
+ end
28
+
29
+ def date_published
30
+ Date.parse(post_date).to_s
31
+ end
32
+
33
+ def status
34
+ post.xpath("wp:status").first.inner_text
35
+ end
36
+
37
+ def type
38
+ post.xpath("wp:post_type").first.inner_text
39
+ end
40
+
41
+ def published?
42
+ status == 'publish'
43
+ end
44
+
45
+ def content
46
+ post.at_xpath(".//content:encoded").inner_text
47
+ end
48
+
49
+ def markdown_content
50
+ html = HTMLPage.new :contents => content
51
+ html.comment do |node,_|
52
+ "#{node}"
53
+ end
54
+ html.iframe do |node,_|
55
+ "#{node}"
56
+ end
57
+ html.markdown
58
+ end
59
+
60
+ def tags
61
+ tags = []
62
+ categories = post.xpath("category")
63
+
64
+ categories.each do |category|
65
+ tag_name = category.css("@nicename").text
66
+
67
+ tags.push tag_name unless tag_name == 'uncategorized'
68
+ end
69
+
70
+ tags
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ require 'nokogiri'
2
+
3
+ module WP2Middleman
4
+ class PostCollection
5
+ def initialize(wp_xml_export_file)
6
+ @xml = Nokogiri::XML(File.open("#{Dir.pwd}/#{wp_xml_export_file}"))
7
+ end
8
+
9
+ def posts
10
+ @xml.css('item')
11
+ .map { |post| WP2Middleman::Post.new(post) }
12
+ .reject { |post| post.type == 'attachment' }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module WP2Middleman
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'wp2middleman/version'
2
+ require 'wp2middleman/post'
3
+ require 'wp2middleman/post_collection'
4
+ require 'wp2middleman/migrator'
5
+ require 'wp2middleman/cli'
6
+
7
+ module WP2Middleman
8
+ def self.migrate(wp_xml_export_file, body_to_markdown = false)
9
+ migrator = WP2Middleman::Migrator.new wp_xml_export_file, body_to_markdown: body_to_markdown
10
+ migrator.migrate
11
+ end
12
+ end
@@ -0,0 +1,176 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <!-- generator="WordPress/3.6" created="2013-12-05 13:04" -->
3
+ <rss version="2.0" xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="http://wordpress.org/export/1.2/">
4
+
5
+ <channel>
6
+ <title>Some Title</title>
7
+ <link>http://someblog.com</link>
8
+ <description>A description</description>
9
+ <pubDate>Thu, 05 Dec 2013 13:04:16 +0000</pubDate>
10
+ <language>en-US</language>
11
+ <wp:wxr_version>1.2</wp:wxr_version>
12
+ <wp:base_site_url>http://someblog.com</wp:base_site_url>
13
+ <wp:base_blog_url>http://someblog.com</wp:base_blog_url>
14
+
15
+ <wp:author><wp:author_id>1</wp:author_id><wp:author_login>admin</wp:author_login><wp:author_email>clapclapexcitement@gmail.com</wp:author_email><wp:author_display_name><![CDATA[admin]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[]]></wp:author_last_name></wp:author>
16
+
17
+ <wp:category><wp:term_id>4</wp:term_id><wp:category_nicename>code</wp:category_nicename><wp:category_parent></wp:category_parent><wp:cat_name><![CDATA[Code]]></wp:cat_name></wp:category>
18
+ <wp:category><wp:term_id>51</wp:term_id><wp:category_nicename>philadelphia</wp:category_nicename><wp:category_parent></wp:category_parent><wp:cat_name><![CDATA[Philadelphia]]></wp:cat_name></wp:category>
19
+ <wp:category><wp:term_id>74</wp:term_id><wp:category_nicename>virginia</wp:category_nicename><wp:category_parent></wp:category_parent><wp:cat_name><![CDATA[Virginia]]></wp:cat_name></wp:category>
20
+ <wp:tag><wp:term_id>5</wp:term_id><wp:tag_slug>vim</wp:tag_slug><wp:tag_name><![CDATA[vim]]></wp:tag_name></wp:tag>
21
+ <wp:tag><wp:term_id>41</wp:term_id><wp:tag_slug>west-philly</wp:tag_slug><wp:tag_name><![CDATA[west philly]]></wp:tag_name></wp:tag>
22
+
23
+ <generator>http://wordpress.org/?v=3.6</generator>
24
+
25
+ <item>
26
+ <title>A Title</title>
27
+ <link>http://someblog.com/?p=84</link>
28
+ <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
29
+ <dc:creator>admin</dc:creator>
30
+ <guid isPermaLink="false">http://someblog.com/?p=84</guid>
31
+ <description></description>
32
+ <content:encoded>Paragraph one.
33
+
34
+ Paragraph two.
35
+ </content:encoded>
36
+ <excerpt:encoded><![CDATA[]]></excerpt:encoded>
37
+ <wp:post_id>84</wp:post_id>
38
+ <wp:post_date>2012-06-08 03:21:41</wp:post_date>
39
+ <wp:post_date_gmt>0000-00-00 00:00:00</wp:post_date_gmt>
40
+ <wp:comment_status>open</wp:comment_status>
41
+ <wp:ping_status>open</wp:ping_status>
42
+ <wp:post_name></wp:post_name>
43
+ <wp:status>publish</wp:status>
44
+ <wp:post_parent>0</wp:post_parent>
45
+ <wp:menu_order>0</wp:menu_order>
46
+ <wp:post_type>post</wp:post_type>
47
+ <wp:post_password></wp:post_password>
48
+ <wp:is_sticky>0</wp:is_sticky>
49
+ <category domain="category" nicename="uncategorized"><![CDATA[Uncategorized]]></category>
50
+ <wp:postmeta>
51
+ <wp:meta_key>_edit_last</wp:meta_key>
52
+ <wp:meta_value><![CDATA[1]]></wp:meta_value>
53
+ </wp:postmeta>
54
+ </item>
55
+ <item>
56
+ <title>A second title</title>
57
+ <link>http://someblog.com/?p=209</link>
58
+ <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
59
+ <dc:creator>admin</dc:creator>
60
+ <guid isPermaLink="false">http://someblog.com/?p=209</guid>
61
+ <description></description>
62
+ <content:encoded><![CDATA[]]> &lt;strong&gt;Foo&lt;/strong&gt;</content:encoded>
63
+ <excerpt:encoded><![CDATA[]]></excerpt:encoded>
64
+ <wp:post_id>209</wp:post_id>
65
+ <wp:post_date>2011-07-25 13:11:26</wp:post_date>
66
+ <wp:post_date_gmt>0000-00-00 00:00:00</wp:post_date_gmt>
67
+ <wp:comment_status>open</wp:comment_status>
68
+ <wp:ping_status>open</wp:ping_status>
69
+ <wp:post_name></wp:post_name>
70
+ <wp:status>publish</wp:status>
71
+ <wp:post_parent>0</wp:post_parent>
72
+ <wp:menu_order>0</wp:menu_order>
73
+ <wp:post_type>post</wp:post_type>
74
+ <wp:post_password></wp:post_password>
75
+ <wp:is_sticky>0</wp:is_sticky>
76
+ <category domain="category" nicename="some_tag"><![CDATA[Some_tag]]></category>
77
+ <category domain="category" nicename="another tag"><![CDATA[Another Tag]]></category>
78
+ <category domain="post_tag" nicename="tag"><![CDATA[tag]]></category>
79
+ <wp:postmeta>
80
+ <wp:meta_key>_edit_last</wp:meta_key>
81
+ <wp:meta_value><![CDATA[1]]></wp:meta_value>
82
+ </wp:postmeta>
83
+ </item>
84
+ <item>
85
+ <title>A third title: With colon</title>
86
+ <link>http://someblog.com/?p=210</link>
87
+ <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
88
+ <dc:creator>admin</dc:creator>
89
+ <guid isPermaLink="false">http://someblog.com/?p=209</guid>
90
+ <description></description>
91
+ <content:encoded><![CDATA[]]>Foo</content:encoded>
92
+ <excerpt:encoded><![CDATA[]]></excerpt:encoded>
93
+ <wp:post_id>210</wp:post_id>
94
+ <wp:post_date>2011-07-26 13:11:26</wp:post_date>
95
+ <wp:post_date_gmt>0000-00-00 00:00:00</wp:post_date_gmt>
96
+ <wp:comment_status>open</wp:comment_status>
97
+ <wp:ping_status>open</wp:ping_status>
98
+ <wp:post_name></wp:post_name>
99
+ <wp:status>private</wp:status>
100
+ <wp:post_parent>0</wp:post_parent>
101
+ <wp:menu_order>0</wp:menu_order>
102
+ <wp:post_type>post</wp:post_type>
103
+ <wp:post_password></wp:post_password>
104
+ <wp:is_sticky>0</wp:is_sticky>
105
+ <category domain="category" nicename="some_tag"><![CDATA[Some_tag]]></category>
106
+ <category domain="category" nicename="another tag"><![CDATA[Another Tag]]></category>
107
+ <category domain="post_tag" nicename="tag"><![CDATA[tag]]></category>
108
+ <wp:postmeta>
109
+ <wp:meta_key>_edit_last</wp:meta_key>
110
+ <wp:meta_value><![CDATA[1]]></wp:meta_value>
111
+ </wp:postmeta>
112
+ </item>
113
+ <item>
114
+ <title>A fourth item with iframe and comment</title>
115
+ <link>http://someblog.com/?p=210</link>
116
+ <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
117
+ <dc:creator>admin</dc:creator>
118
+ <guid isPermaLink="false">http://someblog.com/?p=209</guid>
119
+ <description></description>
120
+ <content:encoded><![CDATA[Here's a post with an iframe and a comment.
121
+
122
+ <!--more-->
123
+
124
+ <iframe width="400" height="100" style="position: relative; display: block; width: 400px; height: 100px;" src="http://bandcamp.com/EmbeddedPlayer/v=2/track=833121761/size=venti/bgcol=FFFFFF/linkcol=4285BB/" allowtransparency="true" frameborder="0"><a href="http://dihannmoore.bandcamp.com/track/you-do-it-for-me">&quot;YOU DO IT FOR ME&quot; by DIHANN MOORE</a></iframe>]]></content:encoded>
125
+ <excerpt:encoded><![CDATA[]]></excerpt:encoded>
126
+ <wp:post_id>210</wp:post_id>
127
+ <wp:post_date>2011-07-26 13:11:26</wp:post_date>
128
+ <wp:post_date_gmt>0000-00-00 00:00:00</wp:post_date_gmt>
129
+ <wp:comment_status>open</wp:comment_status>
130
+ <wp:ping_status>open</wp:ping_status>
131
+ <wp:post_name></wp:post_name>
132
+ <wp:status>private</wp:status>
133
+ <wp:post_parent>0</wp:post_parent>
134
+ <wp:menu_order>0</wp:menu_order>
135
+ <wp:post_type>post</wp:post_type>
136
+ <wp:post_password></wp:post_password>
137
+ <wp:is_sticky>0</wp:is_sticky>
138
+ <category domain="category" nicename="some_tag"><![CDATA[Some_tag]]></category>
139
+ <category domain="category" nicename="another tag"><![CDATA[Another Tag]]></category>
140
+ <category domain="post_tag" nicename="tag"><![CDATA[tag]]></category>
141
+ <wp:postmeta>
142
+ <wp:meta_key>_edit_last</wp:meta_key>
143
+ <wp:meta_value><![CDATA[1]]></wp:meta_value>
144
+ </wp:postmeta>
145
+ </item>
146
+ <item>
147
+ <title>an image</title>
148
+ <link>http://someblog.com/?attachment_id=280</link>
149
+ <pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
150
+ <dc:creator>admin</dc:creator>
151
+ <guid isPermaLink="false">http://someblog.com/wp-content/uploads/1970/01/an_image.png</guid>
152
+ <description></description>
153
+ <content:encoded><![CDATA[]]>Foo</content:encoded>
154
+ <excerpt:encoded><![CDATA[]]></excerpt:encoded>
155
+ <wp:post_id>280</wp:post_id>
156
+ <wp:post_date>2011-07-26 13:11:26</wp:post_date>
157
+ <wp:post_date_gmt>0000-00-00 00:00:00</wp:post_date_gmt>
158
+ <wp:comment_status>open</wp:comment_status>
159
+ <wp:ping_status>open</wp:ping_status>
160
+ <wp:post_name></wp:post_name>
161
+ <wp:status>private</wp:status>
162
+ <wp:post_parent>0</wp:post_parent>
163
+ <wp:menu_order>0</wp:menu_order>
164
+ <wp:post_type>attachment</wp:post_type>
165
+ <wp:post_password></wp:post_password>
166
+ <wp:is_sticky>0</wp:is_sticky>
167
+ <category domain="category" nicename="some_tag"><![CDATA[Some_tag]]></category>
168
+ <category domain="category" nicename="another tag"><![CDATA[Another Tag]]></category>
169
+ <category domain="post_tag" nicename="tag"><![CDATA[tag]]></category>
170
+ <wp:postmeta>
171
+ <wp:meta_key>_edit_last</wp:meta_key>
172
+ <wp:meta_value><![CDATA[1]]></wp:meta_value>
173
+ </wp:postmeta>
174
+ </item>
175
+ </channel>
176
+ </rss>
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe WP2Middleman::CLI do
4
+
5
+ subject { cli }
6
+ let(:cli) { described_class.new }
7
+
8
+ describe "#wp2mm" do
9
+ before do
10
+ cli.stub :say
11
+ end
12
+
13
+ context "it's not passed any arguments" do
14
+ it "returns usage details" do
15
+ cli.should_receive(:usage).exactly(1).times
16
+ cli.wp2mm
17
+ end
18
+ end
19
+
20
+ context "it's passed a Wordpress XML export file that does not exist" do
21
+ it "reports that it was passed an invalid directory and exits with an exit code of 1" do
22
+ Kernel.stub(:exit).and_return true
23
+ File.stub(:file?).and_return false
24
+ cli.should_receive(:error).with("foo is not a valid file")
25
+ lambda { cli.wp2mm 'foo' }.should exit_with_code(1)
26
+ end
27
+ end
28
+
29
+ context "it's passed a valid Wordpress XML export file" do
30
+ before :each do
31
+ WP2Middleman.stub(:migrate).and_return false
32
+ File.stub(:file?).and_return true
33
+ end
34
+
35
+ it "migrates the posts listed in the XML file" do
36
+ WP2Middleman.should_receive(:migrate).with "foo", nil
37
+ cli.wp2mm "foo"
38
+ end
39
+
40
+ it "reports that the directory has been successfully uploaded" do
41
+ cli.should_receive(:say).with("Successfully migrated foo", "\e[32m")
42
+ cli.wp2mm "foo"
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "#usage" do
48
+ subject(:usage) { cli.usage }
49
+
50
+ it "displays version info, GitHub info, and help" do
51
+ cli.should_receive(:say).with('wp2middleman 0.0.1')
52
+ cli.should_receive(:say).with('https://github.com/mdb/wp2middleman')
53
+ cli.should_receive(:say).with("\n")
54
+ cli.should_receive(:help)
55
+
56
+ usage
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe WP2Middleman::Migrator do
4
+ let(:file) { 'spec/fixtures/fixture.xml' }
5
+ let(:migrator) { WP2Middleman::Migrator.new(file) }
6
+
7
+ it "exists as a class within the WP2Middleman module" do
8
+ WP2Middleman::Migrator.class.should eq Class
9
+ end
10
+
11
+ describe "#migrate" do
12
+
13
+ before :each do
14
+ FileUtils.stub :mkdir_p
15
+ File.stub :write
16
+ end
17
+
18
+ it "ensures there is an export directory" do
19
+ File.stub :open
20
+ migrator.should_receive :ensure_export_directory
21
+ migrator.migrate
22
+ end
23
+
24
+ it "writes a middleman markdown file for each post" do
25
+ migrator.should_receive(:write_file).exactly(4).times
26
+ migrator.migrate
27
+ end
28
+ end
29
+
30
+ describe "#write_file" do
31
+ before :each do
32
+ @post = migrator.posts[0]
33
+ end
34
+
35
+ it "ensures that the post it's passed contains valid data" do
36
+ migrator.should_receive(:valid_post_data).with(@post)
37
+ migrator.write_file(@post)
38
+ end
39
+
40
+ it "writes the proper markdown file" do
41
+ File.should_receive(:open).with( "#{Dir.pwd}/export/2012-06-08-A-Title.html.markdown", "w")
42
+ migrator.write_file(@post)
43
+ end
44
+
45
+ # pending
46
+ xit "writes the proper markdown file" do
47
+ File.should_receive(:write).with(migrator.file_content(@post))
48
+ migrator.write_file(@post)
49
+ end
50
+ end
51
+
52
+ describe "#file_content" do
53
+ it "properly formats a post as a Middleman-style post" do
54
+ expect(migrator.file_content(migrator.posts[1])).to eq("---\ntitle: A second title\ndate: '2011-07-25'\ntags:\n- some_tag\n- another tag\n- tag\n---\n\n <strong>Foo</strong>\n")
55
+ end
56
+
57
+ context "its behavior if @body_to_markdown is true" do
58
+ let(:migrator) { WP2Middleman::Migrator.new(file, body_to_markdown: true) }
59
+
60
+ it "formats the post body as markdown" do
61
+ expect(migrator.file_content(migrator.posts[1])).to eq("---\ntitle: A second title\ndate: '2011-07-25'\ntags:\n- some_tag\n- another tag\n- tag\n---\n\n**Foo**\n")
62
+ end
63
+
64
+ it "includes iframe and comment" do
65
+ expect(migrator.file_content(migrator.posts[3])).to eq("---\ntitle: A fourth item with iframe and comment\ndate: '2011-07-26'\ntags:\n- some_tag\n- another tag\n- tag\npublished: false\n---\n\nHere's a post with an iframe and a comment.\n\n\n<!--more-->\n\n\n<iframe width=\"400\" height=\"100\" style=\"position: relative; display: block; width: 400px; height: 100px;\" src=\"http://bandcamp.com/EmbeddedPlayer/v=2/track=833121761/size=venti/bgcol=FFFFFF/linkcol=4285BB/\" allowtransparency=\"true\" frameborder=\"0\"><a href=\"http://dihannmoore.bandcamp.com/track/you-do-it-for-me\">\"YOU DO IT FOR ME\" by DIHANN MOORE</a></iframe>\n")
66
+ end
67
+ end
68
+
69
+ context "the post is not published" do
70
+ it "reports 'published: false' in the post's frontmatter" do
71
+ expect(migrator.file_content(migrator.posts[2])).to eq("---\ntitle: 'A third title: With colon'\ndate: '2011-07-26'\ntags:\n- some_tag\n- another tag\n- tag\npublished: false\n---\n\nFoo\n")
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#formatted_post_content" do
77
+ it "returns the content of the post it's passed" do
78
+ expect(migrator.formatted_post_content(migrator.posts[1])).to eq(" <strong>Foo</strong>")
79
+ end
80
+
81
+ context "its behavior if @body_to_markdown is true" do
82
+ let(:migrator) { WP2Middleman::Migrator.new(file, body_to_markdown: true) }
83
+
84
+ it "returns the content of the post it's passed as markdown" do
85
+ expect(migrator.formatted_post_content(migrator.posts[1])).to eq("**Foo**")
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "#full_filename" do
91
+ it "returns the full filename for a Middleman-style markdown post" do
92
+ expect(migrator.full_filename(migrator.posts[0])).to eq("#{Dir.pwd}/export/2012-06-08-A-Title.html.markdown")
93
+ end
94
+ end
95
+
96
+ describe "#valid_post_data" do
97
+ context "the post's #post_date, #title, #date_published, and #content are not nil" do
98
+ let(:post) {
99
+ double('Post',
100
+ :post_date => 'post_date',
101
+ :title => 'title',
102
+ :date_published => 'date_published',
103
+ :content => 'content'
104
+ )
105
+ }
106
+
107
+ it "returns true" do
108
+ expect(migrator.valid_post_data(post)).to eq(true)
109
+ end
110
+ end
111
+
112
+ context "the post's #post_date, #title, #date_published, or #content is nil" do
113
+ let(:post) {
114
+ double('Post',
115
+ :post_date => nil,
116
+ :title => 'title',
117
+ :date_published => 'date_published',
118
+ :content => 'content'
119
+ )
120
+ }
121
+
122
+ it "returns false" do
123
+ expect(migrator.valid_post_data(post)).to eq(false)
124
+ end
125
+ end
126
+ end
127
+
128
+ describe "#output_path" do
129
+ subject { migrator.output_path }
130
+
131
+ it { should eq("#{Dir.pwd}/export/") }
132
+ end
133
+
134
+ describe "#ensure_export_directory" do
135
+ it "makes the export directory if it's not already there" do
136
+ File.stub(:directory?).and_return false
137
+
138
+ FileUtils.should receive(:mkdir_p).with("#{Dir.pwd}/export/")
139
+
140
+ migrator.ensure_export_directory
141
+ end
142
+
143
+ context "the export directory is already there" do
144
+ it "does not create it" do
145
+ File.stub(:directory?).and_return true
146
+
147
+ migrator.ensure_export_directory
148
+
149
+ FileUtils.should_not receive(:mkdir_p).with("#{Dir.pwd}/export/")
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe WP2Middleman::PostCollection do
4
+ let(:file) { 'spec/fixtures/fixture.xml' }
5
+ let(:posts) { WP2Middleman::PostCollection.new(file).posts }
6
+
7
+ it "exists as a class within the WP2Middleman module" do
8
+ WP2Middleman::PostCollection.class.should eq Class
9
+ end
10
+
11
+ describe "#title" do
12
+ it "returns an array of posts" do
13
+ posts.class.should eq Array
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe WP2Middleman::Post do
4
+ let(:file) { Nokogiri::XML(File.open("#{ENV['PWD']}/spec/fixtures/fixture.xml")) }
5
+ let(:post_one) { WP2Middleman::Post.new(file.css('item')[0]) }
6
+ let(:post_two) { WP2Middleman::Post.new(file.css('item')[1]) }
7
+ let(:post_three) { WP2Middleman::Post.new(file.css('item')[2]) }
8
+
9
+ it "exists as a class within the WP2Middleman module" do
10
+ WP2Middleman::Post.class.should eq Class
11
+ end
12
+
13
+ describe "#title" do
14
+ subject { post_one.title }
15
+
16
+ it { should eq "A Title" }
17
+ end
18
+
19
+ describe "#title_for_filename" do
20
+ subject { post_one.title_for_filename }
21
+
22
+ it { should eq "A-Title" }
23
+ end
24
+
25
+ describe "#filename" do
26
+ subject { post_one.filename }
27
+
28
+ it { should eq "2012-06-08-A-Title" }
29
+
30
+ context "post titles with odd characters such as colons" do
31
+ subject { post_three.filename }
32
+
33
+ it { should eq "2011-07-26-A-third-title-With-colon" }
34
+ end
35
+ end
36
+
37
+ describe "#post_date" do
38
+ subject { post_one.post_date }
39
+
40
+ it { should eq "2012-06-08 03:21:41" }
41
+ end
42
+
43
+ describe "#date_published" do
44
+ subject { post_one.date_published }
45
+
46
+ it { should eq "2012-06-08" }
47
+ end
48
+
49
+ describe "#status" do
50
+ subject { post_three.status }
51
+
52
+ it { should eq "private" }
53
+ end
54
+
55
+ describe "#published?" do
56
+ subject { post_one.published? }
57
+
58
+ it { should eq true }
59
+
60
+ context "#status is not 'publish'" do
61
+ subject { post_three.published? }
62
+
63
+ it { should eq false }
64
+
65
+ end
66
+ end
67
+
68
+ describe "#content" do
69
+ subject { post_one.content }
70
+
71
+ it { should eq "Paragraph one.\n\n Paragraph two.\n " }
72
+ end
73
+
74
+ describe "#markdown_content" do
75
+ subject { post_two.markdown_content }
76
+
77
+ it { should eq "**Foo**" }
78
+ end
79
+
80
+ describe "#tags" do
81
+ subject { post_two.tags }
82
+
83
+ it { should eq ["some_tag", "another tag", "tag"] }
84
+
85
+ context "the post only has an 'Uncategorized' tag" do
86
+ subject { post_one.tags }
87
+
88
+ it { should eq [] }
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe WP2Middleman do
4
+ it "exists as a module" do
5
+ WP2Middleman.class.should eq Module
6
+ end
7
+
8
+ describe ".migrate" do
9
+ before :each do
10
+ @migrator_double = double(WP2Middleman::Migrator)
11
+ end
12
+
13
+ it "migrates the posts in the wordpress XML export file it's passed" do
14
+ WP2Middleman::Migrator.should_receive(:new).with('foo', body_to_markdown: false).and_return(@migrator_double)
15
+ @migrator_double.should_receive(:migrate)
16
+
17
+ WP2Middleman.migrate 'foo'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ require 'bundler/setup'
2
+ require 'json'
3
+
4
+ Bundler.require(:development)
5
+
6
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
7
+
8
+ SimpleCov.start
9
+
10
+ require 'wp2middleman'
11
+
12
+ RSpec.configure do |config|
13
+ # some (optional) config here
14
+ end
@@ -0,0 +1,25 @@
1
+ RSpec::Matchers.define :exit_with_code do |exp_code|
2
+ actual = nil
3
+
4
+ match do |block|
5
+ begin
6
+ block.call
7
+ rescue SystemExit => e
8
+ actual = e.status
9
+ end
10
+ actual and actual == exp_code
11
+ end
12
+
13
+ failure_message_for_should do |block|
14
+ "expected block to call exit(#{exp_code}) but exit" +
15
+ (actual.nil? ? " not called" : "(#{actual}) was called")
16
+ end
17
+
18
+ failure_message_for_should_not do |block|
19
+ "expected block not to call exit(#{exp_code})"
20
+ end
21
+
22
+ description do
23
+ "expect block to call exit(#{exp_code})"
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wp2middleman/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wp2middleman"
8
+ spec.version = WP2Middleman::VERSION
9
+ spec.authors = ["Mike Ball"]
10
+ spec.email = ["mikedball@gmail.com"]
11
+ spec.description = %q{Migrate a Wordpress export XML file to middleman}
12
+ spec.summary = %q{Migrate your Wordpress blog posts to middleman}
13
+ spec.homepage = "http://github.com/mdb/wp2middleman"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "nokogiri"
22
+ spec.add_dependency "html2markdown"
23
+ spec.add_dependency "thor"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "simplecov"
29
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wp2middleman
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mike Ball
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: html2markdown
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Migrate a Wordpress export XML file to middleman
112
+ email:
113
+ - mikedball@gmail.com
114
+ executables:
115
+ - wp2mm
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - .rspec
121
+ - .ruby-version
122
+ - .travis.yml
123
+ - Gemfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bin/wp2mm
128
+ - lib/wp2middleman.rb
129
+ - lib/wp2middleman/cli.rb
130
+ - lib/wp2middleman/migrator.rb
131
+ - lib/wp2middleman/post.rb
132
+ - lib/wp2middleman/post_collection.rb
133
+ - lib/wp2middleman/version.rb
134
+ - spec/fixtures/fixture.xml
135
+ - spec/lib/wp2middleman/cli_spec.rb
136
+ - spec/lib/wp2middleman/migrator_spec.rb
137
+ - spec/lib/wp2middleman/post_collection_spec.rb
138
+ - spec/lib/wp2middleman/post_spec.rb
139
+ - spec/lib/wp2middleman_spec.rb
140
+ - spec/spec_helper.rb
141
+ - spec/support/matchers/exit_with_code.rb
142
+ - wp2middleman.gemspec
143
+ homepage: http://github.com/mdb/wp2middleman
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.0.6
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Migrate your Wordpress blog posts to middleman
167
+ test_files:
168
+ - spec/fixtures/fixture.xml
169
+ - spec/lib/wp2middleman/cli_spec.rb
170
+ - spec/lib/wp2middleman/migrator_spec.rb
171
+ - spec/lib/wp2middleman/post_collection_spec.rb
172
+ - spec/lib/wp2middleman/post_spec.rb
173
+ - spec/lib/wp2middleman_spec.rb
174
+ - spec/spec_helper.rb
175
+ - spec/support/matchers/exit_with_code.rb
176
+ has_rdoc: