jekyll_ghost_importer 0.3.0 → 0.4.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.md +5 -1
- data/bin/jekyll_ghost_importer +92 -29
- data/features/import_posts.feature +110 -0
- data/jekyll_ghost_importer.gemspec +4 -12
- data/lib/jekyll_ghost_importer.rb +0 -1
- metadata +9 -66
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3103e2b999a9e1f32d2a6164fdaae346e34bf761
|
|
4
|
+
data.tar.gz: 3f908a60dfcf85d8131aca3a87864af729c0e664
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a1fb01587e48ef2f421d3302feeab4c2ee19c0e919f25231d52c50974962c9ed5fbc70305ec71f8b5f356e7c8700fb344251815c2d5d8b7a857698cd7e4564c
|
|
7
|
+
data.tar.gz: eb8f7d251b4a749da61becc674d71f3c84d891935e0a140cdf3d550a79bc82a0073c72731d7972fc74876ff7e0a0e8a769941daef133daf0e687a13268bbc709
|
data/README.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
[](https://codeclimate.com/github/eloyesp/jekyll_ghost_importer)
|
|
2
|
+
[](https://codeship.com/projects/153176)
|
|
3
|
+
[](https://rubygems.org/gems/jekyll_ghost_importer)
|
|
4
|
+
|
|
1
5
|
# Jekyll ghost importer
|
|
2
6
|
|
|
3
7
|
This program let you import your post on [ghost][1] to [jekyll][2]. It uses a
|
|
4
8
|
[ghost backup][3] to read the data and creates posts and drafts from them.
|
|
5
9
|
|
|
6
|
-
[1]: https://ghost.org/
|
|
10
|
+
[1]: https://ghost.org/about/
|
|
7
11
|
[2]: http://jekyllrb.com/
|
|
8
12
|
[3]: http://support.ghost.org/import-and-export-my-ghost-blog-settings-and-data/
|
|
9
13
|
|
data/bin/jekyll_ghost_importer
CHANGED
|
@@ -8,43 +8,106 @@ require 'yaml'
|
|
|
8
8
|
FileUtils.mkdir_p("_posts")
|
|
9
9
|
FileUtils.mkdir_p("_drafts")
|
|
10
10
|
|
|
11
|
-
json = JSON.parse File.read(ARGV.pop), symbolize_names: true
|
|
11
|
+
$json = JSON.parse File.read(ARGV.pop), symbolize_names: true
|
|
12
12
|
|
|
13
|
-
unless json[:data].nil?
|
|
14
|
-
posts = json[:data][:posts]
|
|
13
|
+
unless $json[:data].nil?
|
|
14
|
+
posts = $json[:data][:posts]
|
|
15
15
|
else
|
|
16
|
-
posts = json[:db].first[:data][:posts]
|
|
16
|
+
posts = $json[:db].first[:data][:posts]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def there_are_tags?
|
|
20
|
+
@tags ||=
|
|
21
|
+
$json[:db] &&
|
|
22
|
+
$json[:db].first[:data][:posts_tags] &&
|
|
23
|
+
$json[:db].first[:data][:tags]
|
|
17
24
|
end
|
|
18
25
|
|
|
19
26
|
@imported = Hash.new(0)
|
|
20
27
|
|
|
28
|
+
class Post
|
|
29
|
+
# the source of the post
|
|
30
|
+
attr_reader :post
|
|
31
|
+
|
|
32
|
+
def initialize post
|
|
33
|
+
@post = post
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def import
|
|
37
|
+
puts "Importing #{ filename }"
|
|
38
|
+
File.write filename, full_body
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def draft?
|
|
42
|
+
post[:status] == 'draft'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def folder
|
|
48
|
+
draft? ? '_drafts' : '_posts'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def filename
|
|
52
|
+
File.join folder, basename
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def date
|
|
56
|
+
case post[:published_at]
|
|
57
|
+
when String
|
|
58
|
+
DateTime.parse(post[:published_at])
|
|
59
|
+
when Integer
|
|
60
|
+
Time.at(post[:published_at] / 1000).utc.to_datetime
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def front_matter
|
|
65
|
+
front_matter_hash = {
|
|
66
|
+
'layout' => "post",
|
|
67
|
+
'title' => post[:title]
|
|
68
|
+
}
|
|
69
|
+
unless draft?
|
|
70
|
+
front_matter_hash['date'] = date.strftime('%Y-%m-%d %H:%M:%S') if date
|
|
71
|
+
end
|
|
72
|
+
front_matter_hash['tags'] = tags if tags && !tags.empty?
|
|
73
|
+
front_matter_hash
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def slug
|
|
77
|
+
post[:slug]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def tags
|
|
81
|
+
if there_are_tags?
|
|
82
|
+
post_tags = $json[:db].first[:data][:posts_tags].select do |pt|
|
|
83
|
+
pt[:post_id] == post[:id]
|
|
84
|
+
end
|
|
85
|
+
tags_ids = post_tags.map { |pt| pt[:tag_id] }
|
|
86
|
+
tags = $json[:db].first[:data][:tags].select do |t|
|
|
87
|
+
tags_ids.include? t[:id]
|
|
88
|
+
end
|
|
89
|
+
tags.map { |t| t[:slug] }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def full_body
|
|
94
|
+
front_matter.to_yaml + "---\n\n" + post[:markdown]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def basename
|
|
98
|
+
if draft?
|
|
99
|
+
"#{ slug }.markdown"
|
|
100
|
+
else
|
|
101
|
+
"#{ date.strftime('%Y-%m-%d') }-#{ slug }.markdown"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
21
106
|
posts.each do |post|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
DateTime.parse(post[:published_at])
|
|
25
|
-
when Integer
|
|
26
|
-
Time.at(post[:published_at] / 1000).utc.to_datetime
|
|
27
|
-
end
|
|
28
|
-
slug = post[:slug]
|
|
29
|
-
front_matter_hash = {
|
|
30
|
-
'layout' => "post",
|
|
31
|
-
'title' => post[:title]
|
|
32
|
-
}
|
|
33
|
-
front_matter_hash['date'] = date.strftime('%Y-%m-%d %H:%M:%S') if date
|
|
34
|
-
|
|
35
|
-
body = front_matter_hash.to_yaml + "---\n\n" + post[:markdown]
|
|
36
|
-
draft = post[:status] == 'draft'
|
|
37
|
-
basename = if draft
|
|
38
|
-
"#{ slug }.markdown"
|
|
39
|
-
else
|
|
40
|
-
"#{ date.strftime('%Y-%m-%d') }-#{ slug }.markdown"
|
|
41
|
-
end
|
|
42
|
-
folder = draft ? '_drafts' : '_posts'
|
|
43
|
-
filename = File.join folder, basename
|
|
44
|
-
puts "Importing #{ filename }"
|
|
45
|
-
File.write filename, body
|
|
107
|
+
post = Post.new post
|
|
108
|
+
post.import
|
|
46
109
|
@imported[:posts] += 1
|
|
47
|
-
@imported[:drafts] += 1 if draft
|
|
110
|
+
@imported[:drafts] += 1 if post.draft?
|
|
48
111
|
end
|
|
49
112
|
|
|
50
113
|
puts "#{ @imported[:posts] } posts imported ( #{ @imported[:drafts] } draft )"
|
|
@@ -252,6 +252,8 @@ Feature: Import posts
|
|
|
252
252
|
layout: post
|
|
253
253
|
title: Welcome to Ghost
|
|
254
254
|
date: '2015-02-19 11:49:14'
|
|
255
|
+
tags:
|
|
256
|
+
- getting-started
|
|
255
257
|
---
|
|
256
258
|
|
|
257
259
|
You're live!
|
|
@@ -261,3 +263,111 @@ Feature: Import posts
|
|
|
261
263
|
"""
|
|
262
264
|
Something here
|
|
263
265
|
"""
|
|
266
|
+
|
|
267
|
+
Scenario: Import a draft with an invalid published_at date
|
|
268
|
+
Given a file named "draft_with_invalid_date.json" with:
|
|
269
|
+
"""
|
|
270
|
+
{
|
|
271
|
+
"db": [
|
|
272
|
+
{
|
|
273
|
+
"meta": {
|
|
274
|
+
"exported_on": 1424346829618,
|
|
275
|
+
"version": "003"
|
|
276
|
+
},
|
|
277
|
+
"data": {
|
|
278
|
+
"posts": [
|
|
279
|
+
{
|
|
280
|
+
"id": 824,
|
|
281
|
+
"uuid": "3f932273-14ef-4a7d-8119-25cfee021b0c",
|
|
282
|
+
"title": "Are you using a fixed width font for development?",
|
|
283
|
+
"slug": "temp-slug-9",
|
|
284
|
+
"markdown": "This is just a draft, so the date doesn't really matter",
|
|
285
|
+
"html": "<p>This is just a draft, so the date doesn't really matter</p>",
|
|
286
|
+
"image": null,
|
|
287
|
+
"featured": 0,
|
|
288
|
+
"page": 0,
|
|
289
|
+
"status": "draft",
|
|
290
|
+
"language": "en_US",
|
|
291
|
+
"meta_title": null,
|
|
292
|
+
"meta_description": null,
|
|
293
|
+
"author_id": 1,
|
|
294
|
+
"created_at": "2013-05-22T08:30:25.000Z",
|
|
295
|
+
"created_by": 1,
|
|
296
|
+
"updated_at": "2013-05-22T08:30:25.000Z",
|
|
297
|
+
"updated_by": 1,
|
|
298
|
+
"published_at": "0000-00-00 00:00:00",
|
|
299
|
+
"published_by": 1,
|
|
300
|
+
"visibility": "public",
|
|
301
|
+
"mobiledoc": null
|
|
302
|
+
}
|
|
303
|
+
],
|
|
304
|
+
"users": [
|
|
305
|
+
{
|
|
306
|
+
"id": 1,
|
|
307
|
+
"uuid": "6a013e8f-24d3-4c77-901a-7e57f6537f47",
|
|
308
|
+
"name": "test test2",
|
|
309
|
+
"slug": "test",
|
|
310
|
+
"password": "some_password",
|
|
311
|
+
"email": "my_email",
|
|
312
|
+
"image": null,
|
|
313
|
+
"cover": null,
|
|
314
|
+
"bio": null,
|
|
315
|
+
"website": null,
|
|
316
|
+
"location": null,
|
|
317
|
+
"accessibility": null,
|
|
318
|
+
"status": "active",
|
|
319
|
+
"language": "en_US",
|
|
320
|
+
"meta_title": null,
|
|
321
|
+
"meta_description": null,
|
|
322
|
+
"last_login": 1424346712870,
|
|
323
|
+
"created_at": 1424346562473,
|
|
324
|
+
"created_by": 1,
|
|
325
|
+
"updated_at": 1424346712870,
|
|
326
|
+
"updated_by": 1
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
"tags": [
|
|
330
|
+
{
|
|
331
|
+
"id": 1,
|
|
332
|
+
"uuid": "befcb6c7-c777-4a65-a272-6e2577cade61",
|
|
333
|
+
"name": "Getting Started",
|
|
334
|
+
"slug": "getting-started",
|
|
335
|
+
"description": null,
|
|
336
|
+
"image": null,
|
|
337
|
+
"hidden": 0,
|
|
338
|
+
"parent_id": null,
|
|
339
|
+
"meta_title": null,
|
|
340
|
+
"meta_description": null,
|
|
341
|
+
"created_at": 1424346554967,
|
|
342
|
+
"created_by": 1,
|
|
343
|
+
"updated_at": 1424346554967,
|
|
344
|
+
"updated_by": 1
|
|
345
|
+
}
|
|
346
|
+
],
|
|
347
|
+
"posts_tags": [
|
|
348
|
+
{
|
|
349
|
+
"id": 1,
|
|
350
|
+
"post_id": 1,
|
|
351
|
+
"tag_id": 1
|
|
352
|
+
}
|
|
353
|
+
]
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
"""
|
|
359
|
+
When I run `jekyll_ghost_importer draft_with_invalid_date.json`
|
|
360
|
+
Then it should pass with:
|
|
361
|
+
"""
|
|
362
|
+
1 posts imported ( 1 draft )
|
|
363
|
+
"""
|
|
364
|
+
And a directory named "_drafts" should exist
|
|
365
|
+
And the file "_drafts/temp-slug-9.markdown" should contain:
|
|
366
|
+
"""
|
|
367
|
+
---
|
|
368
|
+
layout: post
|
|
369
|
+
title: Are you using a fixed width font for development?
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
This is just a draft, so the date doesn't really matter
|
|
373
|
+
"""
|
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require 'jekyll_ghost_importer'
|
|
5
|
-
|
|
6
2
|
Gem::Specification.new do |spec|
|
|
7
3
|
spec.name = "jekyll_ghost_importer"
|
|
8
|
-
spec.version =
|
|
4
|
+
spec.version = "0.4.0"
|
|
9
5
|
spec.authors = ["Eloy Espinaco"]
|
|
10
6
|
spec.email = ["eloyesp@gmail.com"]
|
|
11
7
|
spec.summary = %q{Import your posts from a ghost backup file.}
|
|
12
8
|
spec.homepage = ""
|
|
13
|
-
spec.license = "
|
|
9
|
+
spec.license = "GPL-3.0+"
|
|
14
10
|
|
|
15
11
|
spec.files = `git ls-files -z`.split("\x0")
|
|
16
12
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
17
13
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
18
14
|
spec.require_paths = ["lib"]
|
|
19
15
|
|
|
20
|
-
spec.add_development_dependency "
|
|
21
|
-
spec.add_development_dependency "
|
|
22
|
-
spec.add_development_dependency "cucumber"
|
|
23
|
-
spec.add_development_dependency "aruba"
|
|
24
|
-
spec.add_development_dependency "guard"
|
|
25
|
-
spec.add_development_dependency "guard-cucumber"
|
|
16
|
+
spec.add_development_dependency "cucumber", '~> 1.3'
|
|
17
|
+
spec.add_development_dependency "aruba", '~> 0'
|
|
26
18
|
end
|
metadata
CHANGED
|
@@ -1,97 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll_ghost_importer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eloy Espinaco
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.6'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.6'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: rake
|
|
14
|
+
name: cucumber
|
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
|
30
16
|
requirements:
|
|
31
17
|
- - "~>"
|
|
32
18
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
19
|
+
version: '1.3'
|
|
34
20
|
type: :development
|
|
35
21
|
prerelease: false
|
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
23
|
requirements:
|
|
38
24
|
- - "~>"
|
|
39
25
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: cucumber
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - ">="
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - ">="
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '0'
|
|
26
|
+
version: '1.3'
|
|
55
27
|
- !ruby/object:Gem::Dependency
|
|
56
28
|
name: aruba
|
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
|
58
30
|
requirements:
|
|
59
|
-
- - "
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: guard
|
|
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: guard-cucumber
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - ">="
|
|
31
|
+
- - "~>"
|
|
88
32
|
- !ruby/object:Gem::Version
|
|
89
33
|
version: '0'
|
|
90
34
|
type: :development
|
|
91
35
|
prerelease: false
|
|
92
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
37
|
requirements:
|
|
94
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
95
39
|
- !ruby/object:Gem::Version
|
|
96
40
|
version: '0'
|
|
97
41
|
description:
|
|
@@ -118,7 +62,7 @@ files:
|
|
|
118
62
|
- lib/jekyll_ghost_importer.rb
|
|
119
63
|
homepage: ''
|
|
120
64
|
licenses:
|
|
121
|
-
-
|
|
65
|
+
- GPL-3.0+
|
|
122
66
|
metadata: {}
|
|
123
67
|
post_install_message:
|
|
124
68
|
rdoc_options: []
|
|
@@ -136,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
136
80
|
version: '0'
|
|
137
81
|
requirements: []
|
|
138
82
|
rubyforge_project:
|
|
139
|
-
rubygems_version: 2.
|
|
83
|
+
rubygems_version: 2.5.1
|
|
140
84
|
signing_key:
|
|
141
85
|
specification_version: 4
|
|
142
86
|
summary: Import your posts from a ghost backup file.
|
|
@@ -145,4 +89,3 @@ test_files:
|
|
|
145
89
|
- features/import_posts.feature
|
|
146
90
|
- features/step_definitions/backup_files.rb
|
|
147
91
|
- features/support/requires.rb
|
|
148
|
-
has_rdoc:
|