jekyll-import 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jekyll-import.rb +10 -8
- data/lib/jekyll-import/importer.rb +1 -1
- data/lib/jekyll-import/importers.rb +1 -1
- data/lib/jekyll-import/importers/behance.rb +20 -20
- data/lib/jekyll-import/importers/blogger.rb +108 -118
- data/lib/jekyll-import/importers/csv.rb +7 -7
- data/lib/jekyll-import/importers/drupal6.rb +5 -6
- data/lib/jekyll-import/importers/drupal7.rb +7 -13
- data/lib/jekyll-import/importers/drupal_common.rb +57 -59
- data/lib/jekyll-import/importers/easyblog.rb +30 -30
- data/lib/jekyll-import/importers/enki.rb +28 -29
- data/lib/jekyll-import/importers/ghost.rb +46 -33
- data/lib/jekyll-import/importers/google_reader.rb +9 -9
- data/lib/jekyll-import/importers/joomla.rb +32 -32
- data/lib/jekyll-import/importers/joomla3.rb +41 -39
- data/lib/jekyll-import/importers/jrnl.rb +16 -17
- data/lib/jekyll-import/importers/marley.rb +25 -26
- data/lib/jekyll-import/importers/mephisto.rb +26 -26
- data/lib/jekyll-import/importers/mt.rb +76 -75
- data/lib/jekyll-import/importers/posterous.rb +30 -29
- data/lib/jekyll-import/importers/rss.rb +13 -10
- data/lib/jekyll-import/importers/s9y.rb +16 -17
- data/lib/jekyll-import/importers/s9y_database.rb +98 -89
- data/lib/jekyll-import/importers/textpattern.rb +18 -17
- data/lib/jekyll-import/importers/tmp.rb +0 -0
- data/lib/jekyll-import/importers/tumblr.rb +146 -143
- data/lib/jekyll-import/importers/typo.rb +31 -31
- data/lib/jekyll-import/importers/wordpress.rb +100 -100
- data/lib/jekyll-import/importers/wordpressdotcom.rb +70 -60
- data/lib/jekyll-import/util.rb +24 -24
- data/lib/jekyll-import/version.rb +1 -1
- data/lib/jekyll/commands/import.rb +32 -35
- metadata +14 -13
@@ -2,59 +2,58 @@ module JekyllImport
|
|
2
2
|
module Importers
|
3
3
|
class Marley < Importer
|
4
4
|
def self.validate(options)
|
5
|
-
if options[
|
5
|
+
if options["marley_data_dir"].nil?
|
6
6
|
Jekyll.logger.abort_with "Missing mandatory option --marley_data_dir."
|
7
7
|
else
|
8
|
-
unless File.directory?(options[
|
9
|
-
raise ArgumentError, "marley dir '#{options[
|
8
|
+
unless File.directory?(options["marley_data_dir"])
|
9
|
+
raise ArgumentError, "marley dir '#{options["marley_data_dir"]}' not found"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.regexp
|
15
|
-
{ :id
|
16
|
-
:title
|
17
|
-
:title_with_date =>
|
18
|
-
:published_on
|
19
|
-
:perex
|
20
|
-
:meta
|
21
|
-
}
|
15
|
+
{ :id => %r!^\d{0,4}-{0,1}(.*)$!,
|
16
|
+
:title => %r!^#\s*(.*)\s+$!,
|
17
|
+
:title_with_date => %r!^#\s*(.*)\s+\(([0-9\/]+)\)$!,
|
18
|
+
:published_on => %r!.*\s+\(([0-9\/]+)\)$!,
|
19
|
+
:perex => %r!^([^\#\n]+\n)$!,
|
20
|
+
:meta => %r!^\{\{\n(.*)\}\}\n$!mi, } # Multiline Regexp
|
22
21
|
end
|
23
22
|
|
24
23
|
def self.require_deps
|
25
|
-
JekyllImport.require_with_fallback(%w
|
24
|
+
JekyllImport.require_with_fallback(%w(
|
26
25
|
fileutils
|
27
26
|
safe_yaml
|
28
|
-
|
27
|
+
))
|
29
28
|
end
|
30
29
|
|
31
30
|
def self.specify_options(c)
|
32
|
-
c.option
|
31
|
+
c.option "marley_data_dir", "--marley_data_dir DIR", "The dir containing your marley data"
|
33
32
|
end
|
34
33
|
|
35
34
|
def self.process(options)
|
36
|
-
marley_data_dir = options.fetch(
|
35
|
+
marley_data_dir = options.fetch("marley_data_dir")
|
37
36
|
|
38
37
|
FileUtils.mkdir_p "_posts"
|
39
38
|
|
40
39
|
posts = 0
|
41
40
|
Dir["#{marley_data_dir}/**/*.txt"].each do |f|
|
42
|
-
next unless File.
|
41
|
+
next unless File.exist?(f)
|
43
42
|
|
44
|
-
#copied over from marley's app/lib/post.rb
|
43
|
+
# copied over from marley's app/lib/post.rb
|
45
44
|
file_content = File.read(f)
|
46
|
-
meta_content = file_content.slice!(
|
47
|
-
body = file_content.sub(
|
45
|
+
meta_content = file_content.slice!(self.regexp[:meta])
|
46
|
+
body = file_content.sub(self.regexp[:title], "").sub(self.regexp[:perex], "").strip
|
48
47
|
|
49
|
-
title = file_content.scan(
|
50
|
-
prerex = file_content.scan(
|
51
|
-
published_on = DateTime.parse(
|
52
|
-
meta =
|
53
|
-
meta[
|
54
|
-
meta[
|
48
|
+
title = file_content.scan(self.regexp[:title]).first.to_s.strip
|
49
|
+
prerex = file_content.scan(self.regexp[:perex]).first.to_s.strip
|
50
|
+
published_on = DateTime.parse(post[:published_on]) rescue File.mtime(File.dirname(f))
|
51
|
+
meta = meta_content ? YAML.safe_load(meta_content.scan(self.regexp[:meta]).to_s) : {}
|
52
|
+
meta["title"] = title
|
53
|
+
meta["layout"] = "post"
|
55
54
|
|
56
|
-
formatted_date = published_on.strftime(
|
57
|
-
post_name =
|
55
|
+
formatted_date = published_on.strftime("%Y-%m-%d")
|
56
|
+
post_name = File.dirname(f).split(%r!/!).last.gsub(%r!\A\d+-!, "")
|
58
57
|
|
59
58
|
name = "#{formatted_date}-#{post_name}"
|
60
59
|
File.open("_posts/#{name}.markdown", "w") do |f|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module JekyllImport
|
2
2
|
module Importers
|
3
3
|
class Mephisto < Importer
|
4
|
-
#Accepts a hash with database config variables, exports mephisto posts into a csv
|
5
|
-
#export PGPASSWORD if you must
|
4
|
+
# Accepts a hash with database config variables, exports mephisto posts into a csv
|
5
|
+
# export PGPASSWORD if you must
|
6
6
|
def self.postgres(c)
|
7
7
|
sql = <<-SQL
|
8
8
|
BEGIN;
|
@@ -12,14 +12,14 @@ module JekyllImport
|
|
12
12
|
COPY jekyll TO STDOUT WITH CSV HEADER;
|
13
13
|
ROLLBACK;
|
14
14
|
SQL
|
15
|
-
command = %
|
15
|
+
command = %(psql -h #{c[:host] || "localhost"} -c "#{sql.strip}" #{c[:database]} #{c[:username]} -o #{c[:filename] || "posts.csv"})
|
16
16
|
puts command
|
17
17
|
`#{command}`
|
18
18
|
CSV.process
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.validate(options)
|
22
|
-
%w
|
22
|
+
%w(dbname user).each do |option|
|
23
23
|
if options[option].nil?
|
24
24
|
abort "Missing mandatory option --#{option}."
|
25
25
|
end
|
@@ -27,19 +27,20 @@ module JekyllImport
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.require_deps
|
30
|
-
JekyllImport.require_with_fallback(%w
|
30
|
+
JekyllImport.require_with_fallback(%w(
|
31
31
|
rubygems
|
32
32
|
sequel
|
33
|
+
mysql2
|
33
34
|
fastercsv
|
34
35
|
fileutils
|
35
|
-
|
36
|
+
))
|
36
37
|
end
|
37
38
|
|
38
39
|
def self.specify_options(c)
|
39
|
-
c.option
|
40
|
-
c.option
|
41
|
-
c.option
|
42
|
-
c.option
|
40
|
+
c.option "dbname", "--dbname DB", "Database name"
|
41
|
+
c.option "user", "--user USER", "Database user name"
|
42
|
+
c.option "password", "--password PW", "Database user's password (default: '')"
|
43
|
+
c.option "host", "--host HOST", 'Database host name (default: "localhost")'
|
43
44
|
end
|
44
45
|
|
45
46
|
# This query will pull blog posts from all entries across all blogs. If
|
@@ -54,18 +55,18 @@ module JekyllImport
|
|
54
55
|
WHERE user_id = 1 AND \
|
55
56
|
type = 'Article' AND \
|
56
57
|
published_at IS NOT NULL \
|
57
|
-
ORDER BY published_at"
|
58
|
+
ORDER BY published_at".freeze
|
58
59
|
|
59
60
|
def self.process(options)
|
60
|
-
dbname = options.fetch(
|
61
|
-
user = options.fetch(
|
62
|
-
pass = options.fetch(
|
63
|
-
host = options.fetch(
|
61
|
+
dbname = options.fetch("dbname")
|
62
|
+
user = options.fetch("user")
|
63
|
+
pass = options.fetch("password", "")
|
64
|
+
host = options.fetch("host", "localhost")
|
64
65
|
|
65
|
-
db = Sequel.
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
db = Sequel.mysql2(dbname, :user => user,
|
67
|
+
:password => pass,
|
68
|
+
:host => host,
|
69
|
+
:encoding => "utf8")
|
69
70
|
|
70
71
|
FileUtils.mkdir_p "_posts"
|
71
72
|
|
@@ -78,13 +79,13 @@ module JekyllImport
|
|
78
79
|
# Ideally, this script would determine the post format (markdown,
|
79
80
|
# html, etc) and create files with proper extensions. At this point
|
80
81
|
# it just assumes that markdown will be acceptable.
|
81
|
-
name = [date.year, date.month, date.day, slug].join(
|
82
|
+
name = [date.year, date.month, date.day, slug].join("-") + ".markdown"
|
82
83
|
|
83
84
|
data = {
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
"layout" => "post",
|
86
|
+
"title" => title.to_s,
|
87
|
+
"mt_id" => post[:entry_id],
|
88
|
+
}.delete_if { |_k, v| v.nil? || v == "" }.to_yaml
|
88
89
|
|
89
90
|
File.open("_posts/#{name}", "w") do |f|
|
90
91
|
f.puts data
|
@@ -92,8 +93,7 @@ module JekyllImport
|
|
92
93
|
f.puts content
|
93
94
|
end
|
94
95
|
end
|
95
|
-
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
99
|
-
end
|
99
|
+
end
|
@@ -1,44 +1,46 @@
|
|
1
1
|
module JekyllImport
|
2
2
|
module Importers
|
3
3
|
class MT < Importer
|
4
|
-
|
5
|
-
SUPPORTED_ENGINES = %{mysql postgres sqlite}
|
4
|
+
SUPPORTED_ENGINES = %(mysql postgres sqlite).freeze
|
6
5
|
|
7
6
|
STATUS_DRAFT = 1
|
8
7
|
STATUS_PUBLISHED = 2
|
9
|
-
MORE_CONTENT_SEPARATOR =
|
8
|
+
MORE_CONTENT_SEPARATOR = "<!--more-->".freeze
|
10
9
|
|
11
10
|
def self.default_options
|
12
11
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
"blog_id" => nil,
|
13
|
+
"categories" => true,
|
14
|
+
"dest_encoding" => "utf-8",
|
15
|
+
"src_encoding" => "utf-8",
|
16
|
+
"comments" => false,
|
18
17
|
}
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.require_deps
|
22
|
-
JekyllImport.require_with_fallback(%w
|
21
|
+
JekyllImport.require_with_fallback(%w(
|
23
22
|
rubygems
|
24
23
|
sequel
|
24
|
+
sqlite3
|
25
|
+
mysql2
|
26
|
+
pg
|
25
27
|
fileutils
|
26
28
|
safe_yaml
|
27
|
-
|
29
|
+
))
|
28
30
|
end
|
29
31
|
|
30
32
|
def self.specify_options(c)
|
31
|
-
c.option
|
32
|
-
c.option
|
33
|
-
c.option
|
34
|
-
c.option
|
35
|
-
c.option
|
36
|
-
c.option
|
37
|
-
c.option
|
38
|
-
c.option
|
39
|
-
c.option
|
40
|
-
c.option
|
41
|
-
c.option
|
33
|
+
c.option "engine", "--engine ENGINE", "Database engine, (default: 'mysql', postgres also supported)"
|
34
|
+
c.option "dbname", "--dbname DB", "Database name"
|
35
|
+
c.option "user", "--user USER", "Database user name"
|
36
|
+
c.option "password", "--password PW", "Database user's password, (default: '')"
|
37
|
+
c.option "host", "--host HOST", 'Database host name (default: "localhost")'
|
38
|
+
c.option "port", "--port PORT", "Custom database port connect to (optional)"
|
39
|
+
c.option "blog_id", "--blog_id ID", "Specify a single Movable Type blog ID to import (default: all blogs)"
|
40
|
+
c.option "categories", "--categories", "If true, save post's categories in its YAML front matter. (default: true)"
|
41
|
+
c.option "src_encoding", "--src_encoding ENCODING", "Encoding of strings from database. (default: UTF-8)"
|
42
|
+
c.option "dest_encoding", "--dest_encoding ENCODING", "Encoding of output strings. (default: UTF-8)"
|
43
|
+
c.option "comments", "--comments", "If true, output comments in _comments directory (default: false)"
|
42
44
|
end
|
43
45
|
|
44
46
|
# By default this migrator will include posts for all your MovableType blogs.
|
@@ -67,7 +69,7 @@ module JekyllImport
|
|
67
69
|
def self.process(options)
|
68
70
|
options = default_options.merge(options)
|
69
71
|
|
70
|
-
comments = options.fetch(
|
72
|
+
comments = options.fetch("comments")
|
71
73
|
posts_name_by_id = {} if comments
|
72
74
|
|
73
75
|
db = database_from_opts(options)
|
@@ -77,20 +79,20 @@ module JekyllImport
|
|
77
79
|
FileUtils.mkdir_p "_posts"
|
78
80
|
|
79
81
|
posts = db[:mt_entry]
|
80
|
-
posts = posts.filter(:entry_blog_id => options[
|
82
|
+
posts = posts.filter(:entry_blog_id => options["blog_id"]) if options["blog_id"]
|
81
83
|
posts.each do |post|
|
82
84
|
categories = post_categories.filter(
|
83
85
|
:mt_placement__placement_entry_id => post[:entry_id]
|
84
|
-
).map {|ea| encode(ea[:category_basename], options) }
|
86
|
+
).map { |ea| encode(ea[:category_basename], options) }
|
85
87
|
|
86
88
|
file_name = post_file_name(post, options)
|
87
89
|
|
88
90
|
data = post_metadata(post, options)
|
89
|
-
data[
|
90
|
-
yaml_front_matter = data.delete_if { |_,v| v.nil? || v ==
|
91
|
+
data["categories"] = categories if !categories.empty? && options["categories"]
|
92
|
+
yaml_front_matter = data.delete_if { |_, v| v.nil? || v == "" }.to_yaml
|
91
93
|
|
92
94
|
# save post path for comment processing
|
93
|
-
posts_name_by_id[data[
|
95
|
+
posts_name_by_id[data["post_id"]] = file_name if comments
|
94
96
|
|
95
97
|
content = post_content(post, options)
|
96
98
|
|
@@ -107,38 +109,36 @@ module JekyllImport
|
|
107
109
|
|
108
110
|
comments = db[:mt_comment]
|
109
111
|
comments.each do |comment|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
112
|
+
next unless posts_name_by_id.key?(comment[:comment_entry_id]) # if the entry exists
|
113
|
+
dir_name, base_name = comment_file_dir_and_base_name(posts_name_by_id, comment, options)
|
114
|
+
FileUtils.mkdir_p "_comments/#{dir_name}"
|
115
|
+
|
116
|
+
data = comment_metadata(comment, options)
|
117
|
+
content = comment_content(comment, options)
|
118
|
+
yaml_front_matter = data.delete_if { |_, v| v.nil? || v == "" }.to_yaml
|
119
|
+
|
120
|
+
File.open("_comments/#{dir_name}/#{base_name}", "w") do |f|
|
121
|
+
f.puts yaml_front_matter
|
122
|
+
f.puts "---"
|
123
|
+
f.puts encode(content, options)
|
123
124
|
end
|
124
125
|
end
|
125
126
|
end
|
126
|
-
|
127
127
|
end
|
128
128
|
|
129
129
|
# Extracts metadata for YAML front matter from post
|
130
130
|
def self.post_metadata(post, options = default_options)
|
131
131
|
metadata = {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
132
|
+
"layout" => "post",
|
133
|
+
"title" => encode(post[:entry_title], options),
|
134
|
+
"date" => post_date(post).strftime("%Y-%m-%d %H:%M:%S %z"),
|
135
|
+
"excerpt" => encode(post[:entry_excerpt].to_s, options),
|
136
|
+
"mt_id" => post[:entry_id],
|
137
|
+
"blog_id" => post[:entry_blog_id],
|
138
|
+
"post_id" => post[:entry_id], # for link with comments
|
139
|
+
"basename" => post[:entry_basename],
|
140
140
|
}
|
141
|
-
metadata[
|
141
|
+
metadata["published"] = false if post[:entry_status] != STATUS_PUBLISHED
|
142
142
|
metadata
|
143
143
|
end
|
144
144
|
|
@@ -152,7 +152,7 @@ module JekyllImport
|
|
152
152
|
post[:entry_text_more].nil? || post[:entry_text_more].strip.empty?
|
153
153
|
end
|
154
154
|
|
155
|
-
def self.post_content(post,
|
155
|
+
def self.post_content(post, _options = default_options)
|
156
156
|
if extra_entry_text_empty?(post)
|
157
157
|
post[:entry_text]
|
158
158
|
else
|
@@ -160,27 +160,27 @@ module JekyllImport
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
def self.post_file_name(post,
|
163
|
+
def self.post_file_name(post, _options = default_options)
|
164
164
|
date = post_date(post)
|
165
165
|
slug = post[:entry_basename]
|
166
166
|
file_ext = suffix(post[:entry_convert_breaks])
|
167
167
|
|
168
|
-
"#{date.strftime(
|
168
|
+
"#{date.strftime("%Y-%m-%d")}-#{slug}.#{file_ext}"
|
169
169
|
end
|
170
170
|
|
171
171
|
# Extracts metadata for YAML front matter from comment
|
172
172
|
def self.comment_metadata(comment, options = default_options)
|
173
173
|
metadata = {
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
174
|
+
"layout" => "comment",
|
175
|
+
"comment_id" => comment[:comment_id],
|
176
|
+
"post_id" => comment[:comment_entry_id],
|
177
|
+
"author" => encode(comment[:comment_author], options),
|
178
|
+
"email" => comment[:comment_email],
|
179
|
+
"commenter_id" => comment[:comment_commenter_id],
|
180
|
+
"date" => comment_date(comment).strftime("%Y-%m-%d %H:%M:%S %z"),
|
181
|
+
"visible" => comment[:comment_visible] == 1,
|
182
|
+
"ip" => comment[:comment_ip],
|
183
|
+
"url" => comment[:comment_url],
|
184
184
|
}
|
185
185
|
metadata
|
186
186
|
end
|
@@ -190,12 +190,12 @@ module JekyllImport
|
|
190
190
|
comment[:comment_modified_on] || comment[:comment_created_on]
|
191
191
|
end
|
192
192
|
|
193
|
-
def self.comment_content(comment,
|
193
|
+
def self.comment_content(comment, _options = default_options)
|
194
194
|
comment[:comment_text]
|
195
195
|
end
|
196
196
|
|
197
|
-
def self.comment_file_dir_and_base_name(posts_name_by_id, comment,
|
198
|
-
post_basename = posts_name_by_id[comment[:comment_entry_id]].sub(
|
197
|
+
def self.comment_file_dir_and_base_name(posts_name_by_id, comment, _options = default_options)
|
198
|
+
post_basename = posts_name_by_id[comment[:comment_entry_id]].sub(%r!\.\w+$!, "")
|
199
199
|
comment_id = comment[:comment_id]
|
200
200
|
|
201
201
|
[post_basename, "#{comment_id}.markdown"]
|
@@ -203,7 +203,7 @@ module JekyllImport
|
|
203
203
|
|
204
204
|
def self.encode(str, options = default_options)
|
205
205
|
if str.respond_to?(:encoding)
|
206
|
-
str.encode(options[
|
206
|
+
str.encode(options["dest_encoding"], options["src_encoding"])
|
207
207
|
else
|
208
208
|
str
|
209
209
|
end
|
@@ -230,26 +230,27 @@ module JekyllImport
|
|
230
230
|
end
|
231
231
|
|
232
232
|
def self.database_from_opts(options)
|
233
|
-
engine
|
234
|
-
dbname
|
233
|
+
engine = options.fetch("engine", "mysql")
|
234
|
+
dbname = options.fetch("dbname")
|
235
|
+
sequel_engine = engine == "mysql" ? "mysql2" : engine
|
235
236
|
|
236
237
|
case engine
|
237
238
|
when "sqlite"
|
238
239
|
Sequel.sqlite(dbname)
|
239
240
|
when "mysql", "postgres"
|
240
241
|
db_connect_opts = {
|
241
|
-
:host
|
242
|
-
:user
|
243
|
-
:password => options.fetch(
|
242
|
+
:host => options.fetch("host", "localhost"),
|
243
|
+
:user => options.fetch("user"),
|
244
|
+
:password => options.fetch("password", ""),
|
244
245
|
}
|
245
|
-
db_connect_opts = options[
|
246
|
+
db_connect_opts = options["port"] if options["port"]
|
246
247
|
Sequel.public_send(
|
247
|
-
|
248
|
+
sequel_engine,
|
248
249
|
dbname,
|
249
250
|
db_connect_opts
|
250
251
|
)
|
251
252
|
else
|
252
|
-
abort("Unsupported engine: '#{engine}'. Must be one of #{SUPPORTED_ENGINES.join(
|
253
|
+
abort("Unsupported engine: '#{engine}'. Must be one of #{SUPPORTED_ENGINES.join(", ")}")
|
253
254
|
end
|
254
255
|
end
|
255
256
|
end
|