sutty-migration 0.4.0rc0 → 0.4.0rc1
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41536e494891ca8e5b5a6ea4f98dcf2cdd780bb8f1a16cdfc10bcee9f5195eb6
|
|
4
|
+
data.tar.gz: d73e41285e4bfd4080aad2beb3b9b3a29332ee0f31e64b4438fd0bcc7a479952
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b7e64d51403a731be28d4eae8385747dee6abc99e3e5c7b8220240a673b1dee555584706ef0d10f203751eacb51b89022c02ec1d9019b3854a547650f9489e1d
|
|
7
|
+
data.tar.gz: f7ae65bde83caa3404d7de2b825fe751fdc0490fda3c399f4c98f2cf320e037323172b065ec82e9e7af4a5e09ecc5c27e095f3b955c19268e1fe0cc55522a557
|
data/README.md
CHANGED
|
@@ -119,48 +119,17 @@ a backup, put them there so the plugin finds them.
|
|
|
119
119
|
### WordPress XML
|
|
120
120
|
|
|
121
121
|
If you have the XML dump from a WordPress site, you can migrate content
|
|
122
|
-
by
|
|
122
|
+
by using the XML migration plugin and hooking to its steps.
|
|
123
123
|
|
|
124
124
|
```ruby
|
|
125
|
+
# _plugins/wordpress.rb
|
|
125
126
|
# frozen_string_literal: true
|
|
126
127
|
|
|
127
|
-
require '
|
|
128
|
-
require '
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# Run after reading the site
|
|
133
|
-
Jekyll::Hooks.register :site, :post_read do |site|
|
|
134
|
-
# Put the XML dump at _files/wordpress.xml
|
|
135
|
-
xml = SuttyMigration::WordpressXml.new site: site, file: '_files/wordpress.xml'
|
|
136
|
-
|
|
137
|
-
# Download all files
|
|
138
|
-
xml.attachments.values.map(&:download)
|
|
139
|
-
|
|
140
|
-
# Migrate posts. You can move metadata around and recover
|
|
141
|
-
# relationships or any info your theme requires.
|
|
142
|
-
xml.posts.values.each do |post|
|
|
143
|
-
# Update documents already migrated.
|
|
144
|
-
doc = Jekyll::Document.find_or_create(site: site, collection: locale, title: post.title, slug: post.slug, date: post.date)
|
|
145
|
-
# Don't change the UUIDv4
|
|
146
|
-
d.data['uuid'] ||= SecureRandom.uuid
|
|
147
|
-
d.data['draft'] = post.draft?
|
|
148
|
-
d.data['layout'] = 'post'
|
|
149
|
-
d.data['last_modified_at'] = post.last_modified_at
|
|
150
|
-
|
|
151
|
-
d.data['categories'] = post.categories.map { |c| c[:title] }
|
|
152
|
-
d.data['tags'] = post.tags.map { |t| t[:title] }
|
|
153
|
-
|
|
154
|
-
d.data['author'] = post.author[:email]
|
|
155
|
-
d.data['description'] = post.description
|
|
156
|
-
d.content = post.content
|
|
157
|
-
|
|
158
|
-
doc.save
|
|
159
|
-
rescue => e
|
|
160
|
-
Jekyll.logger.warn "Couldn't migrate #{post.title}"
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
exit # Stop here
|
|
128
|
+
require 'jekyll-wordpress-xml-migration'
|
|
129
|
+
require 'pry'
|
|
130
|
+
|
|
131
|
+
Jekyll::Hooks.register :wordpress_post, :post_init do |item|
|
|
132
|
+
binding.pry
|
|
164
133
|
end
|
|
165
134
|
```
|
|
166
135
|
|
|
@@ -10,10 +10,79 @@
|
|
|
10
10
|
# can use `wordpress_url`.
|
|
11
11
|
#
|
|
12
12
|
# JEKYLL_ENV=migration bundle exec jekyll build
|
|
13
|
-
Jekyll::Hooks.register :site, :post_read, priority: :high do |
|
|
13
|
+
Jekyll::Hooks.register :site, :post_read, priority: :high do |site|
|
|
14
14
|
next unless Jekyll.env == 'migration'
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
file = '_files/wordpress.xml'
|
|
17
17
|
|
|
18
|
-
Jekyll.logger.abort_with 'Migration:', "#{
|
|
18
|
+
Jekyll.logger.abort_with 'Migration:', "#{file} is missing!" unless File.exist? file
|
|
19
|
+
|
|
20
|
+
require 'sutty_migration/wordpress_xml'
|
|
21
|
+
require 'sutty_migration/jekyll/document_creator'
|
|
22
|
+
require 'jekyll-write-and-commit-changes'
|
|
23
|
+
|
|
24
|
+
wordpress = SuttyMigration::WordpressXml.new(site:, file:)
|
|
25
|
+
migrated_posts = []
|
|
26
|
+
|
|
27
|
+
Jekyll::Hooks.trigger :migration, :post_init, wordpress
|
|
28
|
+
|
|
29
|
+
wordpress.attachments.values.uniq.each do |attachment|
|
|
30
|
+
Jekyll::Hooks.trigger :wordpress_attachment, :post_init, attachment.item
|
|
31
|
+
|
|
32
|
+
Jekyll::Hooks.trigger :wordpress_attachment, :pre_render, attachment
|
|
33
|
+
# Download and convert to Sutty's public/
|
|
34
|
+
attachment.public_path
|
|
35
|
+
Jekyll::Hooks.trigger :wordpress_attachment, :post_convert, attachment
|
|
36
|
+
Jekyll::Hooks.trigger :wordpress_attachment, :post_render, attachment
|
|
37
|
+
Jekyll::Hooks.trigger :wordpress_attachment, :post_write, attachment
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
wordpress.posts.each_value do |post|
|
|
41
|
+
Jekyll::Hooks.trigger :wordpress_post, :post_init, post.item
|
|
42
|
+
Jekyll::Hooks.trigger :wordpress_post, :pre_render, post
|
|
43
|
+
Jekyll::Document.find_or_create(site:, slug: post.slug, title: post.title, date: post.date,
|
|
44
|
+
collection: 'posts').tap do |doc|
|
|
45
|
+
# If you want to customize the layout, change it with a :post_init
|
|
46
|
+
# hook.
|
|
47
|
+
doc.data['layout'] = 'post'
|
|
48
|
+
doc.data['permalink'] = post.permalink
|
|
49
|
+
doc.data['created_at'] = post.date
|
|
50
|
+
doc.data['last_modified_at'] = post.last_modified_at&.localtime
|
|
51
|
+
doc.data['uuid'] ||= SecureRandom.uuid
|
|
52
|
+
doc.data['categories'] = post.categories.map { _1[:title] }
|
|
53
|
+
doc.data['tags'] = post.tags.map { _1[:title] }
|
|
54
|
+
doc.data['draft'] = post.draft?
|
|
55
|
+
|
|
56
|
+
unless (attachment_id = post.meta['_thumbnail_id'].to_i).zero?
|
|
57
|
+
attachment = wordpress.attachments[attachment_id]
|
|
58
|
+
|
|
59
|
+
if attachment
|
|
60
|
+
doc.data['image'] = {
|
|
61
|
+
'path' => attachment.public_path,
|
|
62
|
+
'description' => ''
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Jekyll::Hooks.trigger :wordpress_post, :post_convert, doc
|
|
68
|
+
|
|
69
|
+
doc.content = post.beautiful_content
|
|
70
|
+
|
|
71
|
+
Jekyll::Hooks.trigger :wordpress_post, :post_render, doc
|
|
72
|
+
|
|
73
|
+
migrated_posts << doc
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
Jekyll::Hooks.trigger :migration, :post_convert, wordpress
|
|
78
|
+
Jekyll::Hooks.trigger :migration, :post_render, migrated_posts
|
|
79
|
+
|
|
80
|
+
# Save them all at the end
|
|
81
|
+
migrated_posts.each do |doc|
|
|
82
|
+
doc.save
|
|
83
|
+
|
|
84
|
+
Jekyll::Hooks.trigger :wordpress_post, :post_write, doc
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
Jekyll::Hooks.trigger :migration, :post_write, migrated_posts
|
|
19
88
|
end
|
|
@@ -17,11 +17,19 @@ module SuttyMigration
|
|
|
17
17
|
@attachment_url ||= attribute_value('attachment_url') || attribute_value('guid')
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def parsed_url
|
|
21
|
+
@parsed_url ||= Addressable::URI.parse(attachment_url)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def normalized_url
|
|
25
|
+
@normalized_url ||= parsed_url.normalize
|
|
26
|
+
end
|
|
27
|
+
|
|
20
28
|
# File destination
|
|
21
29
|
#
|
|
22
30
|
# @return [String]
|
|
23
31
|
def dest
|
|
24
|
-
@dest ||= CGI.unescape(
|
|
32
|
+
@dest ||= CGI.unescape(parsed_url.path.sub(%r{\A/}, '').unicode_normalize)
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
# Metadata, with file information as a Hash
|
|
@@ -41,32 +49,30 @@ module SuttyMigration
|
|
|
41
49
|
def download(progress: true)
|
|
42
50
|
return true if File.exist? dest
|
|
43
51
|
|
|
44
|
-
::Jekyll.logger.info 'Downloading:', dest
|
|
45
|
-
|
|
46
52
|
FileUtils.mkdir_p File.dirname(dest)
|
|
47
53
|
|
|
48
54
|
File.open(dest, 'w') do |f|
|
|
49
|
-
head = Faraday.head(
|
|
55
|
+
head = Faraday.head(normalized_url)
|
|
50
56
|
|
|
51
57
|
if head.status > 399
|
|
52
|
-
::Jekyll.logger.warn 'Error:', head.status
|
|
58
|
+
::Jekyll.logger.warn 'Error:', "#{head.status} #{normalized_url}"
|
|
53
59
|
return false
|
|
54
60
|
end
|
|
55
61
|
|
|
56
62
|
content_length = head.headers['content-length'].to_i
|
|
57
63
|
|
|
58
64
|
if content_length.zero?
|
|
59
|
-
::Jekyll.logger.warn 'Error:',
|
|
65
|
+
::Jekyll.logger.warn 'Error:', "Content length is zero for #{normalized_url}"
|
|
60
66
|
return false
|
|
61
67
|
end
|
|
62
68
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
::Jekyll.logger.info 'Downloading:', dest
|
|
70
|
+
|
|
71
|
+
progress_bar =
|
|
72
|
+
(ProgressBar.create(title: File.basename(dest), total: content_length, output: $stderr) if progress)
|
|
67
73
|
|
|
68
74
|
begin
|
|
69
|
-
Faraday.get(
|
|
75
|
+
Faraday.get(normalized_url) do |req|
|
|
70
76
|
req.options.on_data = proc do |chunk, downloaded_bytes|
|
|
71
77
|
if downloaded_bytes > content_length
|
|
72
78
|
raise Faraday::Error, 'File is bigger than informed, aborting download'
|
|
@@ -74,15 +80,16 @@ module SuttyMigration
|
|
|
74
80
|
|
|
75
81
|
f.write chunk
|
|
76
82
|
|
|
77
|
-
progress_bar
|
|
83
|
+
progress_bar&.progress = downloaded_bytes
|
|
78
84
|
end
|
|
79
85
|
end
|
|
80
86
|
rescue Faraday::Error => e
|
|
81
87
|
::Jekyll.logger.warn 'Error:', e.message
|
|
82
88
|
end
|
|
89
|
+
|
|
90
|
+
progress_bar&.stop
|
|
83
91
|
end
|
|
84
92
|
|
|
85
|
-
progress_bar.stop if progress
|
|
86
93
|
File.exist? dest
|
|
87
94
|
end
|
|
88
95
|
|
|
@@ -94,6 +101,8 @@ module SuttyMigration
|
|
|
94
101
|
#
|
|
95
102
|
# @return [String]
|
|
96
103
|
def public_path
|
|
104
|
+
return unless digest
|
|
105
|
+
|
|
97
106
|
@public_path ||= File.join('public', digest[..27], dest.split('/').last).tap do
|
|
98
107
|
next if File.exist? _1
|
|
99
108
|
|
|
@@ -102,8 +111,8 @@ module SuttyMigration
|
|
|
102
111
|
# or old thumbnails.
|
|
103
112
|
dir = File.dirname(_1)
|
|
104
113
|
if File.directory?(dir) && !Dir.empty?(dir)
|
|
105
|
-
Jekyll
|
|
106
|
-
|
|
114
|
+
::Jekyll.logger.warn 'Migration:',
|
|
115
|
+
"#{dir} is not empty, you probably have the same file with different names"
|
|
107
116
|
end
|
|
108
117
|
|
|
109
118
|
FileUtils.mkdir_p(File.dirname(_1))
|
|
@@ -120,9 +129,7 @@ module SuttyMigration
|
|
|
120
129
|
begin
|
|
121
130
|
require 'digest'
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
Digest::SHA2.file(dest).hexdigest
|
|
132
|
+
Digest::SHA2.file(dest).hexdigest if download
|
|
126
133
|
end
|
|
127
134
|
end
|
|
128
135
|
end
|
|
@@ -25,7 +25,7 @@ module SuttyMigration
|
|
|
25
25
|
data-turbo href id name referrerpolicy rel reversed rowspan src start target title type]
|
|
26
26
|
# rubocop:enable Style/MutableConstant
|
|
27
27
|
SLASH = '/'
|
|
28
|
-
THUMBNAIL_PREFIX =
|
|
28
|
+
THUMBNAIL_PREFIX = /-\d+x\d+(\.....?)\z/
|
|
29
29
|
# TODO: Move to wordpress-formatting
|
|
30
30
|
WORDPRESS_ELEMENT_START = /\[(\w+ [^\]]+)\]/
|
|
31
31
|
WORDPRESS_ELEMENT_END = %r{\[(/\w+)\]}
|
|
@@ -50,13 +50,13 @@ module SuttyMigration
|
|
|
50
50
|
|
|
51
51
|
# Permalink. Absolute URL to the post.
|
|
52
52
|
#
|
|
53
|
-
# @return [String]
|
|
53
|
+
# @return [String, nil]
|
|
54
54
|
def permalink
|
|
55
55
|
@permalink ||=
|
|
56
56
|
begin
|
|
57
|
-
p = attribute_value('link')&.
|
|
57
|
+
p = attribute_value('link')&.sub(wordpress.url, '')&.split('?', 2)&.first
|
|
58
58
|
|
|
59
|
-
unless p.nil?
|
|
59
|
+
unless p.nil? || p.blank?
|
|
60
60
|
p << SLASH if !p.end_with?(SLASH) && File.extname(p).empty?
|
|
61
61
|
|
|
62
62
|
p.squeeze(SLASH)
|
|
@@ -104,10 +104,10 @@ module SuttyMigration
|
|
|
104
104
|
#
|
|
105
105
|
# @return [Time, nil]
|
|
106
106
|
def last_modified_at
|
|
107
|
-
@last_modified_at ||=
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
@last_modified_at ||= %w[post_modified_gmt post_modified].map do |date_attr|
|
|
108
|
+
::Jekyll::Utils.parse_date attribute_value(date_attr)
|
|
109
|
+
rescue StandardError
|
|
110
|
+
end.compact.first
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
# Content as an HTML string, converting Wordpress [tags] to <tags>
|
|
@@ -135,10 +135,17 @@ module SuttyMigration
|
|
|
135
135
|
@parsed_content ||= Nokogiri::HTML.fragment(sanitized_content).tap do |html|
|
|
136
136
|
html.css('[src]').each do |element|
|
|
137
137
|
# Remove the thumbnail suffix, we only want the original files
|
|
138
|
-
element['src'] = element['src'].sub(THUMBNAIL_PREFIX, '\\
|
|
138
|
+
element['src'] = element['src'].sub(THUMBNAIL_PREFIX, '\\1')
|
|
139
139
|
|
|
140
140
|
if element['src'].start_with? wordpress.url
|
|
141
|
-
|
|
141
|
+
attachment = wordpress.attachments[CGI.unescape element['src']]
|
|
142
|
+
|
|
143
|
+
unless attachment
|
|
144
|
+
::Jekyll.logger.warn 'Error:', "Not found #{element['src']}"
|
|
145
|
+
next
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
element['src'] = attachment.public_path
|
|
142
149
|
|
|
143
150
|
# Move the element into a <figure> like our editor does
|
|
144
151
|
unless element.parent && element.parent.name == '#document-fragment'
|
|
@@ -15,7 +15,13 @@ module SuttyMigration
|
|
|
15
15
|
def initialize(site:, file:)
|
|
16
16
|
@site = site
|
|
17
17
|
@file = file
|
|
18
|
-
@xml = Nokogiri::XML File.read(file)
|
|
18
|
+
@xml = Nokogiri::XML File.read(file).delete("\b").delete("\u0002")
|
|
19
|
+
|
|
20
|
+
if xml.errors.empty?
|
|
21
|
+
::Jekyll.logger.info 'Migration:', "#{file} parsed correctly"
|
|
22
|
+
else
|
|
23
|
+
::Jekyll.logger.warn 'Migration:', "#{xml.errors.count} parsing errors found on #{file}!"
|
|
24
|
+
end
|
|
19
25
|
|
|
20
26
|
# Make things easier by removing namespaces.
|
|
21
27
|
xml.remove_namespaces!
|
|
@@ -108,8 +114,8 @@ module SuttyMigration
|
|
|
108
114
|
#
|
|
109
115
|
# @return [Hash]
|
|
110
116
|
def posts
|
|
111
|
-
@posts ||= items_find_by('post_type', 'post').map do |
|
|
112
|
-
{ attribute_value(
|
|
117
|
+
@posts ||= items_find_by('post_type', 'post').map do |item|
|
|
118
|
+
{ attribute_value(item, 'post_id').to_i => Post.new(wordpress: self, item:) }
|
|
113
119
|
end.reduce(&:merge)
|
|
114
120
|
end
|
|
115
121
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sutty-migration
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.0rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- f
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|