wp2middleman 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: