jekyll-import 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.markdown +2 -1
- data/lib/jekyll/commands/import.rb +1 -1
- data/lib/jekyll-import/importers/blogger.rb +54 -66
- data/lib/jekyll-import/importers/csv.rb +2 -2
- data/lib/jekyll-import/importers/dotclear.rb +147 -88
- data/lib/jekyll-import/importers/drupal6.rb +7 -3
- data/lib/jekyll-import/importers/drupal8.rb +65 -0
- data/lib/jekyll-import/importers/drupal_common.rb +6 -5
- data/lib/jekyll-import/importers/easyblog.rb +7 -7
- data/lib/jekyll-import/importers/enki.rb +4 -4
- data/lib/jekyll-import/importers/joomla.rb +8 -8
- data/lib/jekyll-import/importers/joomla3.rb +8 -8
- data/lib/jekyll-import/importers/jrnl.rb +4 -4
- data/lib/jekyll-import/importers/marley.rb +1 -1
- data/lib/jekyll-import/importers/medium.rb +36 -0
- data/lib/jekyll-import/importers/mephisto.rb +3 -3
- data/lib/jekyll-import/importers/mt.rb +10 -10
- data/lib/jekyll-import/importers/pluxml.rb +3 -3
- data/lib/jekyll-import/importers/roller.rb +12 -12
- data/lib/jekyll-import/importers/rss.rb +64 -27
- data/lib/jekyll-import/importers/s9y_database.rb +270 -56
- data/lib/jekyll-import/importers/textpattern.rb +5 -5
- data/lib/jekyll-import/importers/tumblr.rb +5 -5
- data/lib/jekyll-import/importers/typo.rb +6 -6
- data/lib/jekyll-import/importers/wordpress.rb +16 -16
- data/lib/jekyll-import/importers/wordpressdotcom.rb +3 -3
- data/lib/jekyll-import/version.rb +1 -1
- metadata +34 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba591570a71e1a96e2a064ba583010d114d8051d9cb4fa810ff45a7e382b621e
|
4
|
+
data.tar.gz: ac515c173bc2bb258d75da253cbdd83aa5f3a9074a97ba8c68a02193b4d15449
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 716d363903258758c63a266d81a865bee73e174816d9cdd854f8d8079511ec3b75fccb1576aa82700b3212c8fa4fe59144196f0e4010084489c7e7c0f8127268
|
7
|
+
data.tar.gz: 65a01c5fbf3b3d69d2a2808ea2e4233b6a7034e056e91950487cdef84d03d9048ea95fefd52eb8b48cd3e0608bfb269b6ef35d347ab59e94a698779088d57069
|
data/README.markdown
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# jekyll-import
|
2
2
|
|
3
|
-
[](https://rubygems.org/gems/jekyll-import)
|
4
|
+
[](https://github.com/jekyll/jekyll-import/actions/workflows/ci.yml)
|
4
5
|
|
5
6
|
The new __Jekyll__ command for importing from various blogs to Jekyll format.
|
6
7
|
|
@@ -39,7 +39,7 @@ module Jekyll
|
|
39
39
|
if args.empty?
|
40
40
|
Jekyll.logger.warn "You must specify an importer."
|
41
41
|
Jekyll.logger.info "Valid options are:"
|
42
|
-
importers.each { |i| Jekyll.logger.info "*", i.to_s }
|
42
|
+
importers.sort.each { |i| Jekyll.logger.info "*", i.to_s }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -5,17 +5,14 @@ module JekyllImport
|
|
5
5
|
class Blogger < Importer
|
6
6
|
def self.specify_options(c)
|
7
7
|
c.option "source", "--source NAME", "The XML file (blog-MM-DD-YYYY.xml) path to import"
|
8
|
-
c.option "no-blogger-info", "--no-blogger-info", "not to leave blogger-URL info (id and old URL) in the front matter (default: false)"
|
8
|
+
c.option "no-blogger-info", "--no-blogger-info", "not to leave blogger-URL info (id and old URL) in the front matter. (default: false)"
|
9
9
|
c.option "replace-internal-link", "--replace-internal-link", "replace internal links using the post_url liquid tag. (default: false)"
|
10
|
-
c.option "comments", "--comments", "import comments to _comments collection"
|
10
|
+
c.option "comments", "--comments", "import comments to _comments collection. (default: false)"
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.validate(options)
|
14
|
-
if options["source"].nil?
|
15
|
-
|
16
|
-
elsif !File.exist?(options["source"])
|
17
|
-
raise Errno::ENOENT, "File not found: #{options["source"]}"
|
18
|
-
end
|
14
|
+
raise "Missing mandatory option: --source" if options["source"].nil?
|
15
|
+
raise Errno::ENOENT, "File not found: #{options["source"]}" unless File.exist?(options["source"])
|
19
16
|
end
|
20
17
|
|
21
18
|
def self.require_deps
|
@@ -42,7 +39,6 @@ module JekyllImport
|
|
42
39
|
source = options.fetch("source")
|
43
40
|
|
44
41
|
listener = BloggerAtomStreamListener.new
|
45
|
-
|
46
42
|
listener.leave_blogger_info = !options.fetch("no-blogger-info", false)
|
47
43
|
listener.comments = options.fetch("comments", false)
|
48
44
|
|
@@ -52,7 +48,6 @@ module JekyllImport
|
|
52
48
|
end
|
53
49
|
|
54
50
|
options["original-url-base"] = listener.original_url_base
|
55
|
-
|
56
51
|
postprocess(options)
|
57
52
|
end
|
58
53
|
|
@@ -63,32 +58,32 @@ module JekyllImport
|
|
63
58
|
# Returns nothing.
|
64
59
|
def self.postprocess(options)
|
65
60
|
# Replace internal link URL
|
66
|
-
|
67
|
-
original_url_base = options.fetch("original-url-base", nil)
|
68
|
-
if original_url_base
|
69
|
-
orig_url_pattern = Regexp.new(" href=([\"\'])(?:#{Regexp.escape(original_url_base)})?/([0-9]{4})/([0-9]{2})/([^\"\']+\.html)\\1")
|
70
|
-
|
71
|
-
Dir.glob("_posts/*.*") do |filename|
|
72
|
-
body = nil
|
73
|
-
File.open(filename, "r") do |f|
|
74
|
-
f.flock(File::LOCK_SH)
|
75
|
-
body = f.read
|
76
|
-
end
|
61
|
+
return unless options.fetch("replace-internal-link", false)
|
77
62
|
|
78
|
-
|
79
|
-
|
80
|
-
quote = Regexp.last_match(1)
|
81
|
-
post_file = Dir.glob("_posts/#{Regexp.last_match(2)}-#{Regexp.last_match(3)}-*-#{Regexp.last_match(4).to_s.tr("/", "-")}").first
|
82
|
-
raise "Could not found: _posts/#{Regexp.last_match(2)}-#{Regexp.last_match(3)}-*-#{Regexp.last_match(4).to_s.tr("/", "-")}" if post_file.nil?
|
63
|
+
original_url_base = options.fetch("original-url-base", nil)
|
64
|
+
return unless original_url_base
|
83
65
|
|
84
|
-
|
85
|
-
end
|
66
|
+
orig_url_pattern = Regexp.new(" href=([\"\'])(?:#{Regexp.escape(original_url_base)})?/([0-9]{4})/([0-9]{2})/([^\"\']+\.html)\\1")
|
86
67
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
68
|
+
Dir.glob("_posts/*.*") do |filename|
|
69
|
+
body = nil
|
70
|
+
File.open(filename, "r") do |f|
|
71
|
+
f.flock(File::LOCK_SH)
|
72
|
+
body = f.read
|
73
|
+
end
|
74
|
+
|
75
|
+
body.gsub!(orig_url_pattern) do
|
76
|
+
# for post_url
|
77
|
+
quote = Regexp.last_match(1)
|
78
|
+
post_file = Dir.glob("_posts/#{Regexp.last_match(2)}-#{Regexp.last_match(3)}-*-#{Regexp.last_match(4).to_s.tr("/", "-")}").first
|
79
|
+
raise "Could not found: _posts/#{Regexp.last_match(2)}-#{Regexp.last_match(3)}-*-#{Regexp.last_match(4).to_s.tr("/", "-")}" if post_file.nil?
|
80
|
+
|
81
|
+
" href=#{quote}{{ site.baseurl }}{% post_url #{File.basename(post_file, ".html")} %}#{quote}"
|
82
|
+
end
|
83
|
+
|
84
|
+
File.open(filename, "w") do |f|
|
85
|
+
f.flock(File::LOCK_EX)
|
86
|
+
f << body
|
92
87
|
end
|
93
88
|
end
|
94
89
|
end
|
@@ -118,9 +113,7 @@ module JekyllImport
|
|
118
113
|
|
119
114
|
@in_entry_elem = { :meta => {}, :body => nil }
|
120
115
|
when "title"
|
121
|
-
if @in_entry_elem
|
122
|
-
raise 'only <title type="text"></title> is supported' if attrs["type"] != "text"
|
123
|
-
end
|
116
|
+
raise 'only <title type="text"></title> is supported' if @in_entry_elem && attrs["type"] != "text"
|
124
117
|
when "category"
|
125
118
|
if @in_entry_elem
|
126
119
|
if attrs["scheme"] == "http://www.blogger.com/atom/ns#"
|
@@ -150,25 +143,23 @@ module JekyllImport
|
|
150
143
|
end
|
151
144
|
|
152
145
|
def text(text)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
171
|
-
end
|
146
|
+
return unless @in_entry_elem
|
147
|
+
|
148
|
+
case @tag_bread.last
|
149
|
+
when "id"
|
150
|
+
@in_entry_elem[:meta][:id] = text
|
151
|
+
when "published"
|
152
|
+
@in_entry_elem[:meta][:published] = text
|
153
|
+
when "updated"
|
154
|
+
@in_entry_elem[:meta][:updated] = text
|
155
|
+
when "title"
|
156
|
+
@in_entry_elem[:meta][:title] = text
|
157
|
+
when "content"
|
158
|
+
@in_entry_elem[:body] = text
|
159
|
+
when "name"
|
160
|
+
@in_entry_elem[:meta][:author] = text if @tag_bread[-2..-1] == %w(author name)
|
161
|
+
when "app:draft"
|
162
|
+
@in_entry_elem[:meta][:draft] = true if @tag_bread[-2..-1] == %w(app:control app:draft) && text == "yes"
|
172
163
|
end
|
173
164
|
end
|
174
165
|
|
@@ -186,7 +177,7 @@ module JekyllImport
|
|
186
177
|
|
187
178
|
FileUtils.mkdir_p(target_dir)
|
188
179
|
|
189
|
-
file_name = URI.
|
180
|
+
file_name = URI.decode_www_form_component("#{post_data[:filename]}.html")
|
190
181
|
File.open(File.join(target_dir, file_name), "w") do |f|
|
191
182
|
f.flock(File::LOCK_EX)
|
192
183
|
|
@@ -203,7 +194,7 @@ module JekyllImport
|
|
203
194
|
|
204
195
|
FileUtils.mkdir_p(target_dir)
|
205
196
|
|
206
|
-
file_name = URI.
|
197
|
+
file_name = URI::DEFAULT_PARSER.unescape("#{post_data[:filename]}.html")
|
207
198
|
File.open(File.join(target_dir, file_name), "w") do |f|
|
208
199
|
f.flock(File::LOCK_EX)
|
209
200
|
|
@@ -264,19 +255,16 @@ module JekyllImport
|
|
264
255
|
{ :filename => filename, :header => header, :body => body }
|
265
256
|
elsif @in_entry_elem[:meta][:kind] == "comment"
|
266
257
|
timestamp = Time.parse(@in_entry_elem[:meta][:published]).strftime("%Y-%m-%d")
|
267
|
-
|
268
|
-
@comment_seq ||= 1
|
258
|
+
raise "Original URL is missing" unless @in_entry_elem[:meta][:original_url]
|
269
259
|
|
270
|
-
|
271
|
-
original_path = original_uri.path.to_s
|
272
|
-
filename = format("%s-%s-%s", timestamp, File.basename(original_path, File.extname(original_path)), @comment_seq)
|
260
|
+
@comment_seq ||= 1
|
273
261
|
|
274
|
-
|
262
|
+
original_uri = URI.parse(@in_entry_elem[:meta][:original_url])
|
263
|
+
original_path = original_uri.path.to_s
|
264
|
+
filename = format("%s-%s-%s", timestamp, File.basename(original_path, File.extname(original_path)), @comment_seq)
|
275
265
|
|
276
|
-
|
277
|
-
|
278
|
-
raise "Original URL is missing"
|
279
|
-
end
|
266
|
+
@comment_seq += 1
|
267
|
+
@original_url_base = "#{original_uri.scheme}://#{original_uri.host}"
|
280
268
|
|
281
269
|
header = {
|
282
270
|
"date" => @in_entry_elem[:meta][:published],
|
@@ -12,8 +12,8 @@ module JekyllImport
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.specify_options(c)
|
15
|
-
c.option "file", "--file NAME",
|
16
|
-
c.option "no-front-matter", "--no-front-matter", "Do not add the default front matter to the post body"
|
15
|
+
c.option "file", "--file NAME", "The CSV file to import. (default: 'posts.csv')"
|
16
|
+
c.option "no-front-matter", "--no-front-matter", "Do not add the default front matter to the post body. (default: false)"
|
17
17
|
end
|
18
18
|
|
19
19
|
# Reads a csv with title, permalink, body, published_at, and filter.
|
@@ -1,121 +1,180 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Tested with dotClear 2.1.5
|
4
3
|
module JekyllImport
|
5
4
|
module Importers
|
6
5
|
class Dotclear < Importer
|
7
|
-
|
8
|
-
c
|
9
|
-
|
10
|
-
|
6
|
+
class << self
|
7
|
+
def specify_options(c)
|
8
|
+
c.option "datafile", "--datafile PATH", "Dotclear export file."
|
9
|
+
c.option "mediafolder", "--mediafolder DIR", "Dotclear media export folder (unpacked media.zip)."
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
fileutils
|
16
|
-
safe_yaml
|
17
|
-
date
|
18
|
-
active_support
|
19
|
-
active_support/core_ext/string/inflections
|
20
|
-
csv
|
21
|
-
pp
|
22
|
-
))
|
23
|
-
end
|
12
|
+
def require_deps
|
13
|
+
JekyllImport.require_with_fallback(%w())
|
14
|
+
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
16
|
+
def validate(opts)
|
17
|
+
file_path = opts["datafile"]
|
18
|
+
log_undefined_flag_error("datafile") if file_path.nil? || file_path.empty?
|
29
19
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
20
|
+
file_path = File.expand_path(file_path)
|
21
|
+
if File.open(file_path, "rb", &:readline).start_with?("///DOTCLEAR|")
|
22
|
+
@data = read_export(file_path)
|
23
|
+
Jekyll.logger.info "Export File:", file_path
|
24
|
+
else
|
25
|
+
Jekyll.logger.abort_with "Import Error:", "#{file_path.inspect} is not a valid Dotclear export file!"
|
26
|
+
end
|
37
27
|
|
38
|
-
|
39
|
-
|
40
|
-
:datafile => opts.fetch("datafile", ""),
|
41
|
-
:mediafolder => opts.fetch("mediafolder", ""),
|
42
|
-
}
|
28
|
+
assets = @data["media"]
|
29
|
+
return if !assets || assets.empty?
|
43
30
|
|
44
|
-
|
45
|
-
FileUtils.mkdir_p("_drafts")
|
31
|
+
Jekyll.logger.info "", "Media files detected in export data."
|
46
32
|
|
47
|
-
|
48
|
-
|
49
|
-
posts_and_drafts = {}
|
50
|
-
keywords = {}
|
33
|
+
media_dir = opts["mediafolder"]
|
34
|
+
log_undefined_flag_error("mediafolder") if media_dir.nil? || media_dir.empty?
|
51
35
|
|
52
|
-
|
53
|
-
|
36
|
+
media_dir = File.expand_path(media_dir)
|
37
|
+
log_invalid_media_dir_error(media_dir) if !File.directory?(media_dir) || Dir.empty?(media_dir)
|
38
|
+
end
|
54
39
|
|
55
|
-
|
40
|
+
def process(opts)
|
41
|
+
import_posts
|
42
|
+
import_assets(opts["mediafolder"])
|
43
|
+
Jekyll.logger.info "", "and, done!"
|
44
|
+
end
|
56
45
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
46
|
+
private
|
47
|
+
|
48
|
+
# Parse backup sections into a Hash of arrays.
|
49
|
+
#
|
50
|
+
# Each section is of following shape:
|
51
|
+
#
|
52
|
+
# [key alpha,beta,gamma,...]
|
53
|
+
# lorem,ipsum,dolor,...
|
54
|
+
# red,blue,green,...
|
55
|
+
#
|
56
|
+
# Returns Hash of shape:
|
57
|
+
#
|
58
|
+
# {key => [{alpha => lorem,...}, {alpha => red,...}]}
|
59
|
+
#
|
60
|
+
def read_export(file)
|
61
|
+
ignored_sections = %w(category comment link setting)
|
62
|
+
|
63
|
+
File.read(file, :encoding => "utf-8").split("\n\n").each_with_object({}) do |section, data|
|
64
|
+
next unless %r!^\[(?<key>.*?) (?<header>.*)\]\n(?<rows>.*)!m =~ section
|
65
|
+
next if ignored_sections.include?(key)
|
66
|
+
|
67
|
+
headers = header.split(",")
|
68
|
+
|
69
|
+
data[key] = rows.each_line.with_object([]) do |line, bucket|
|
70
|
+
bucket << headers.zip(sanitize_line!(line)).to_h
|
71
|
+
end
|
72
|
+
|
73
|
+
data
|
61
74
|
end
|
75
|
+
end
|
62
76
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
draft = (elts[headers[type_data].index("post_status")] != "1")
|
77
|
+
def register_post_tags
|
78
|
+
@data["meta"].each_with_object({}) do |entry, tags|
|
79
|
+
next unless entry["meta_type"] == "tag"
|
67
80
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
81
|
+
post_id = entry["post_id"]
|
82
|
+
tags[post_id] ||= []
|
83
|
+
tags[post_id] << entry["meta_id"]
|
84
|
+
end
|
85
|
+
end
|
72
86
|
|
73
|
-
|
74
|
-
|
87
|
+
def log_undefined_flag_error(label)
|
88
|
+
Jekyll.logger.abort_with "Import Error:", "--#{label} flag cannot be undefined, null or empty!"
|
89
|
+
end
|
75
90
|
|
76
|
-
|
91
|
+
def log_invalid_media_dir_error(media_dir)
|
92
|
+
Jekyll.logger.error "Import Error:", "--mediafolder should be a non-empty directory."
|
93
|
+
Jekyll.logger.abort_with "", "Please check #{media_dir.inspect}."
|
94
|
+
end
|
77
95
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
96
|
+
def sanitize_line!(line)
|
97
|
+
line.strip!
|
98
|
+
line.split('","').tap do |items|
|
99
|
+
items[0].delete_prefix!('"')
|
100
|
+
items[-1].delete_suffix!('"')
|
101
|
+
end
|
102
|
+
end
|
85
103
|
|
86
|
-
|
87
|
-
POST_FILE
|
104
|
+
# -
|
88
105
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
106
|
+
REPLACE_MAP = {
|
107
|
+
'\"' => '"',
|
108
|
+
'\r\n' => "\n",
|
109
|
+
'\n' => "\n",
|
110
|
+
"/dotclear/public/" => "/assets/dotclear/",
|
111
|
+
"/public/" => "/assets/dotclear/",
|
112
|
+
}.freeze
|
93
113
|
|
94
|
-
|
95
|
-
dst_path = File.join(Dir.pwd, "assets", "images", mediafilepath.to_s)
|
114
|
+
REPLACE_RE = Regexp.union(REPLACE_MAP.keys)
|
96
115
|
|
97
|
-
|
98
|
-
FileUtils.cp(src_path, dst_path)
|
99
|
-
elsif type_data == "meta"
|
100
|
-
keywords[elts[headers[type_data].index("post_id")]] ||= []
|
101
|
-
keywords[elts[headers[type_data].index("post_id")]] << elts[headers[type_data].index("meta_id")]
|
102
|
-
elsif type_data == "link"
|
116
|
+
private_constant :REPLACE_MAP, :REPLACE_RE
|
103
117
|
|
104
|
-
|
118
|
+
# -
|
105
119
|
|
106
|
-
|
120
|
+
def adjust_post_contents!(content)
|
121
|
+
content.strip!
|
122
|
+
content.gsub!(REPLACE_RE, REPLACE_MAP)
|
123
|
+
content
|
124
|
+
end
|
107
125
|
|
126
|
+
def import_posts
|
127
|
+
tags = register_post_tags
|
128
|
+
posts = @data["post"]
|
129
|
+
|
130
|
+
FileUtils.mkdir_p("_drafts") unless posts.empty?
|
131
|
+
Jekyll.logger.info "Importing posts.."
|
132
|
+
|
133
|
+
posts.each do |post|
|
134
|
+
date, title = post.values_at("post_creadt", "post_title")
|
135
|
+
path = File.join("_drafts", Date.parse(date).strftime("%Y-%m-%d-") + Jekyll::Utils.slugify(title) + ".html")
|
136
|
+
|
137
|
+
excerpt = adjust_post_contents!(post["post_excerpt_xhtml"].to_s)
|
138
|
+
excerpt = nil if excerpt.empty?
|
139
|
+
|
140
|
+
# Unlike the paradigm in Jekyll-generated HTML, `post_content_xhtml` in the export data
|
141
|
+
# doesn't begin with `post_excerpt_xhtml`.
|
142
|
+
# Instead of checking whether the excerpt content exists elsewhere in the exported content
|
143
|
+
# string, always prepend excerpt onto content with an empty line in between.
|
144
|
+
content = [excerpt, post["post_content_xhtml"]].tap(&:compact!).join("\n\n")
|
145
|
+
|
146
|
+
front_matter_data = {
|
147
|
+
"layout" => "post",
|
148
|
+
"title" => title,
|
149
|
+
"date" => date,
|
150
|
+
"lang" => post["post_lang"],
|
151
|
+
"tags" => tags[post["post_id"]],
|
152
|
+
"original_url" => post["post_url"], # URL as included in the export-file.
|
153
|
+
"excerpt" => excerpt,
|
154
|
+
}.tap(&:compact!)
|
155
|
+
|
156
|
+
Jekyll.logger.info "Creating:", path
|
157
|
+
File.write(path, "#{YAML.dump(front_matter_data)}---\n\n#{adjust_post_contents!(content)}\n")
|
108
158
|
end
|
109
159
|
end
|
110
160
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
161
|
+
def import_assets(src_dir)
|
162
|
+
assets = @data["media"]
|
163
|
+
FileUtils.mkdir_p("assets/dotclear") if assets && !assets.empty?
|
164
|
+
Jekyll.logger.info "Importing assets.."
|
165
|
+
|
166
|
+
assets.each do |asset|
|
167
|
+
file_path = File.join(src_dir, asset["media_file"])
|
168
|
+
if File.exist?(file_path)
|
169
|
+
dest_path = File.join("assets/dotclear", asset["media_file"])
|
170
|
+
FileUtils.mkdir_p(File.dirname(dest_path))
|
171
|
+
|
172
|
+
Jekyll.logger.info "Copying:", file_path
|
173
|
+
Jekyll.logger.info "To:", dest_path
|
174
|
+
FileUtils.cp_r file_path, dest_path
|
175
|
+
else
|
176
|
+
Jekyll.logger.info "Not found:", file_path
|
177
|
+
end
|
119
178
|
end
|
120
179
|
end
|
121
180
|
end
|
@@ -19,15 +19,17 @@ module JekyllImport
|
|
19
19
|
nr.teaser,
|
20
20
|
n.created,
|
21
21
|
n.status,
|
22
|
+
ua.dst AS alias,
|
22
23
|
n.type,
|
23
24
|
GROUP_CONCAT( td.name SEPARATOR '|' ) AS 'tags'
|
24
|
-
FROM #{prefix}node_revisions AS nr,
|
25
|
+
FROM #{prefix}node_revisions AS nr, url_alias AS ua,
|
25
26
|
#{prefix}node AS n
|
26
27
|
LEFT OUTER JOIN #{prefix}term_node AS tn ON tn.nid = n.nid
|
27
28
|
LEFT OUTER JOIN #{prefix}term_data AS td ON tn.tid = td.tid
|
28
29
|
WHERE (#{types})
|
29
30
|
AND n.vid = nr.vid
|
30
|
-
|
31
|
+
AND ua.src = CONCAT( 'node/', n.nid)
|
32
|
+
GROUP BY n.nid, ua.dst
|
31
33
|
SQL
|
32
34
|
|
33
35
|
query
|
@@ -44,9 +46,11 @@ SQL
|
|
44
46
|
|
45
47
|
data = {
|
46
48
|
"excerpt" => summary,
|
47
|
-
"categories" => tags.split("|"),
|
49
|
+
"categories" => tags.split("|").uniq,
|
48
50
|
}
|
49
51
|
|
52
|
+
data["permalink"] = "/" + sql_post_data[:alias] if sql_post_data[:alias]
|
53
|
+
|
50
54
|
[data, content]
|
51
55
|
end
|
52
56
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll-import/importers/drupal_common"
|
4
|
+
|
5
|
+
module JekyllImport
|
6
|
+
module Importers
|
7
|
+
class Drupal8 < Importer
|
8
|
+
include DrupalCommon
|
9
|
+
extend DrupalCommon::ClassMethods
|
10
|
+
|
11
|
+
def self.build_query(prefix, types, engine)
|
12
|
+
types = types.join("' OR n.type = '")
|
13
|
+
types = "n.type = '#{types}'"
|
14
|
+
|
15
|
+
tag_group = if engine == "postgresql"
|
16
|
+
<<POSTGRESQL
|
17
|
+
(SELECT STRING_AGG(td.name, '|')
|
18
|
+
FROM #{prefix}taxonomy_term_field_data td, #{prefix}taxonomy_index ti
|
19
|
+
WHERE ti.tid = td.tid AND ti.nid = n.nid) AS tags
|
20
|
+
POSTGRESQL
|
21
|
+
else
|
22
|
+
<<SQL
|
23
|
+
(SELECT GROUP_CONCAT(td.name SEPARATOR '|')
|
24
|
+
FROM #{prefix}taxonomy_term_field_data td, #{prefix}taxonomy_index ti
|
25
|
+
WHERE ti.tid = td.tid AND ti.nid = n.nid) AS 'tags'
|
26
|
+
SQL
|
27
|
+
end
|
28
|
+
|
29
|
+
query = <<QUERY
|
30
|
+
SELECT n.nid,
|
31
|
+
n.title,
|
32
|
+
nb.body_value,
|
33
|
+
nb.body_summary,
|
34
|
+
n.created,
|
35
|
+
n.status,
|
36
|
+
n.type,
|
37
|
+
#{tag_group}
|
38
|
+
FROM #{prefix}node_field_data AS n
|
39
|
+
LEFT JOIN #{prefix}node__body AS nb
|
40
|
+
ON nb.entity_id = n.nid
|
41
|
+
WHERE (#{types})
|
42
|
+
QUERY
|
43
|
+
|
44
|
+
query
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.aliases_query(prefix)
|
48
|
+
"SELECT source, alias FROM #{prefix}url_alias WHERE source = ?"
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.post_data(sql_post_data)
|
52
|
+
content = sql_post_data[:body_value].to_s
|
53
|
+
summary = sql_post_data[:body_summary].to_s
|
54
|
+
tags = (sql_post_data[:tags] || "").downcase.strip
|
55
|
+
|
56
|
+
data = {
|
57
|
+
"excerpt" => summary,
|
58
|
+
"categories" => tags.split("|"),
|
59
|
+
}
|
60
|
+
|
61
|
+
[data, content]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|