jekyll-import 0.21.0 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -32,17 +32,17 @@ module JekyllImport
32
32
  end
33
33
 
34
34
  def self.specify_options(c)
35
- c.option "engine", "--engine ENGINE", "Database engine, (default: 'mysql', postgres also supported)"
36
- c.option "dbname", "--dbname DB", "Database name"
37
- c.option "user", "--user USER", "Database user name"
38
- c.option "password", "--password PW", "Database user's password, (default: '')"
39
- c.option "host", "--host HOST", 'Database host name (default: "localhost")'
40
- c.option "port", "--port PORT", "Custom database port connect to (optional)"
41
- c.option "blog_id", "--blog_id ID", "Specify a single Movable Type blog ID to import (default: all blogs)"
42
- c.option "categories", "--categories", "If true, save post's categories in its YAML front matter. (default: true)"
35
+ c.option "dbname", "--dbname DB", "Database name."
36
+ c.option "user", "--user USER", "Database user name."
37
+ c.option "engine", "--engine ENGINE", "Database engine ('mysql' or 'postgres'). (default: 'mysql')"
38
+ c.option "password", "--password PW", "Database user's password. (default: '')"
39
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
40
+ c.option "port", "--port PORT", "Custom database port connect to. (default: null)"
41
+ c.option "blog_id", "--blog_id ID", "Specify a single Movable Type blog ID to import. (default: null (all blogs))"
42
+ c.option "categories", "--categories", "When true, save post's categories in its YAML front matter. (default: true)"
43
43
  c.option "src_encoding", "--src_encoding ENCODING", "Encoding of strings from database. (default: UTF-8)"
44
44
  c.option "dest_encoding", "--dest_encoding ENCODING", "Encoding of output strings. (default: UTF-8)"
45
- c.option "comments", "--comments", "If true, output comments in _comments directory (default: false)"
45
+ c.option "comments", "--comments", "When true, output comments in `_comments` directory. (default: false)"
46
46
  end
47
47
 
48
48
  # By default this migrator will include posts for all your MovableType blogs.
@@ -242,7 +242,7 @@ module JekyllImport
242
242
  Sequel.sqlite(dbname)
243
243
  when "mysql", "postgres"
244
244
  db_connect_opts = {
245
- :host => options.fetch("host", "localhost"),
245
+ :host => options.fetch("host", "127.0.0.1"),
246
246
  :user => options.fetch("user"),
247
247
  :password => options.fetch("password", ""),
248
248
  }
@@ -0,0 +1,97 @@
1
+ module JekyllImport
2
+ module Importers
3
+ class Pebble < Importer
4
+ def self.require_deps
5
+ JekyllImport.require_with_fallback(%w(
6
+ nokogiri
7
+ safe_yaml
8
+ ))
9
+ end
10
+
11
+ def self.specify_options(c)
12
+ c.option "directory", "--directory PATH", "Pebble source directory"
13
+ end
14
+
15
+ def self.process(opts)
16
+ options = {
17
+ directory: opts.fetch("directory", "")
18
+ }
19
+
20
+ FileUtils.mkdir_p("_posts")
21
+ FileUtils.mkdir_p("_drafts")
22
+
23
+ traverse_posts_within(options[:directory]) do |file|
24
+ next if file.end_with?('categories.xml')
25
+ process_file(file)
26
+ end
27
+ end
28
+
29
+ def self.traverse_posts_within(directory, &block)
30
+ Dir.foreach(directory) do |fd|
31
+ path = File.join(directory, fd)
32
+ if fd == '.' || fd == '..'
33
+ next
34
+ elsif File.directory?(path)
35
+ traverse_posts_within(path, &block)
36
+ elsif path.end_with?('xml')
37
+ yield(path) if block_given?
38
+ else
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.process_file(file)
44
+ xml = File.open(file) { |f| Nokogiri::XML(f) }
45
+ raise "There doesn't appear to be any XML items at the source (#{file}) provided." unless xml
46
+
47
+ doc = xml.xpath("blogEntry")
48
+
49
+ title = kebabize(doc.xpath('title').text).gsub('_', '-')
50
+ date = Date.parse(doc.xpath('date').text)
51
+
52
+ directory = "_posts"
53
+ name = "#{date.strftime('%Y-%m-%d')}-#{title}"
54
+
55
+ header = {
56
+ "layout" => 'post',
57
+ "title" => doc.xpath("title").text,
58
+ "tags" => doc.xpath("tags").text.split(", "),
59
+ "categories" => doc.xpath('category').text.split(', ')
60
+ }
61
+ header["render_with_liquid"] = false
62
+
63
+ path = File.join(directory, "#{name}.html")
64
+ File.open(path, "w") do |f|
65
+ f.puts header.to_yaml
66
+ f.puts "---\n\n"
67
+ f.puts doc.xpath("body").text
68
+ end
69
+
70
+ Jekyll.logger.info "Wrote file #{path} successfully!"
71
+ end
72
+
73
+ def self.kebabize(string)
74
+ kebab = '-'.freeze
75
+ string.gsub!(/[^\w\-_]+/, kebab)
76
+
77
+ unless kebab.nil? || kebab.empty?
78
+ if kebab == "-".freeze
79
+ re_duplicate_kebab = /-{2,}/
80
+ re_leading_trailing_kebab = /^-|-$/
81
+ else
82
+ re_sep = Regexp.escape(kebab)
83
+ re_duplicate_kebab = /#{re_sep}{2,}/
84
+ re_leading_trailing_kebab = /^#{re_sep}|#{re_sep}$/
85
+ end
86
+ # No more than one of the kebab in a row.
87
+ string.gsub!(re_duplicate_kebab, kebab)
88
+ # Remove leading/trailing kebab.
89
+ string.gsub!(re_leading_trailing_kebab, "".freeze)
90
+ end
91
+
92
+ string.downcase!
93
+ string
94
+ end
95
+ end
96
+ end
97
+ end
@@ -12,9 +12,9 @@ module JekyllImport
12
12
  end
13
13
 
14
14
  def self.specify_options(c)
15
- c.option "source", "--source NAME", "The PluXML data directory to import"
16
- c.option "layout", "--layout NAME", "The layout to apply"
17
- c.option "avoid_liquid", "--avoid_liquid true", "Will add render_with_liquid: false in frontmatter"
15
+ c.option "source", "--source NAME", "The PluXml data directory to import."
16
+ c.option "layout", "--layout NAME", "The layout to apply. (default: 'post')"
17
+ c.option "avoid_liquid", "--avoid_liquid", "Will add `render_with_liquid: false` in front matter. (default: false)"
18
18
  end
19
19
 
20
20
  def self.validate(options)
@@ -14,19 +14,19 @@ module JekyllImport
14
14
  end
15
15
 
16
16
  def self.specify_options(c)
17
- c.option "dbname", "--dbname DB", "Database name (default: '')"
18
- c.option "socket", "--socket SOCKET", "Database socket (default: '')"
19
- c.option "user", "--user USER", "Database user name (default: '')"
20
- c.option "password", "--password PW", "Database user's password (default: '')"
21
- c.option "host", "--host HOST", "Database host name (default: 'localhost')"
22
- c.option "port", "--port PORT", "Database port number (default: '3306')"
23
- c.option "clean_entities", "--clean_entities", "Whether to clean entities (default: true)"
24
- c.option "comments", "--comments", "Whether to import comments (default: true)"
25
- c.option "categories", "--categories", "Whether to import categories (default: true)"
26
- c.option "tags", "--tags", "Whether to import tags (default: true)"
17
+ c.option "dbname", "--dbname DB", "Database name."
18
+ c.option "user", "--user USER", "Database user name."
19
+ c.option "password", "--password PW", "Database user's password."
20
+ c.option "socket", "--socket SOCKET", "Database socket. (default: null)"
21
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
22
+ c.option "port", "--port PORT", "Database port number. (default: '3306')"
23
+ c.option "clean_entities", "--clean_entities", "Whether to clean entities. (default: true)"
24
+ c.option "comments", "--comments", "Whether to import comments. (default: true)"
25
+ c.option "categories", "--categories", "Whether to import categories. (default: true)"
26
+ c.option "tags", "--tags", "Whether to import tags. (default: true)"
27
27
 
28
28
  c.option "status", "--status STATUS,STATUS2", Array,
29
- "Array of allowed statuses (default: ['PUBLISHED'], other options: 'DRAFT')"
29
+ "Array of allowed statuses (either ['PUBLISHED'] or ['DRAFT']). (default: ['PUBLISHED'])"
30
30
  end
31
31
 
32
32
  # Main migrator function. Call this to perform the migration.
@@ -64,7 +64,7 @@ module JekyllImport
64
64
  options = {
65
65
  :user => opts.fetch("user", ""),
66
66
  :pass => opts.fetch("password", ""),
67
- :host => opts.fetch("host", "localhost"),
67
+ :host => opts.fetch("host", "127.0.0.1"),
68
68
  :port => opts.fetch("port", "3306"),
69
69
  :socket => opts.fetch("socket", nil),
70
70
  :dbname => opts.fetch("dbname", ""),
@@ -4,13 +4,16 @@ module JekyllImport
4
4
  module Importers
5
5
  class RSS < Importer
6
6
  def self.specify_options(c)
7
- c.option "source", "--source NAME", "The RSS file or URL to import"
8
- c.option "tag", "--tag NAME", "Add a tag to posts"
9
- c.option "render_audio", "--render_audio", "Render <audio> element as necessary"
7
+ c.option "source", "--source NAME", "The RSS file or URL to import."
8
+ c.option "tag", "--tag NAME", "Add a specific tag to all posts."
9
+ c.option "extract_tags", "--extract_tags KEY", "Copies tags from the given subfield on the RSS `<item>` to front matter. (default: null)"
10
+ c.option "render_audio", "--render_audio", "Render `<audio>` element in posts for the enclosure URLs. (default: false)"
11
+ c.option "canonical_link", "--canonical_link", "Add original link as `canonical_url` to post front matter. (default: false)"
10
12
  end
11
13
 
12
14
  def self.validate(options)
13
15
  abort "Missing mandatory option --source." if options["source"].nil?
16
+ abort "Provide either --tag or --extract_tags option." if options["extract_tags"] && options["tag"]
14
17
  end
15
18
 
16
19
  def self.require_deps
@@ -33,7 +36,7 @@ module JekyllImport
33
36
  source = options.fetch("source")
34
37
 
35
38
  content = ""
36
- open(source) { |s| content = s.read }
39
+ URI.open(source) { |s| content = s.read }
37
40
  rss = ::RSS::Parser.parse(content, false)
38
41
 
39
42
  raise "There doesn't appear to be any RSS items at the source (#{source}) provided." unless rss
@@ -52,13 +55,14 @@ module JekyllImport
52
55
  post_name = Jekyll::Utils.slugify(item.title, :mode => "latin")
53
56
  name = "#{formatted_date}-#{post_name}"
54
57
  audio = render_audio && item.enclosure.url
58
+ canonical_link = options.fetch("canonical_link", false)
55
59
 
56
60
  header = {
57
- "layout" => "post",
58
- "title" => item.title,
59
- }
60
-
61
- header["tag"] = options["tag"] unless options["tag"].nil? || options["tag"].empty?
61
+ "layout" => "post",
62
+ "title" => item.title,
63
+ "canonical_url" => (canonical_link ? item.link : nil),
64
+ "tag" => get_tags(item, options),
65
+ }.compact
62
66
 
63
67
  frontmatter.each do |value|
64
68
  header[value] = item.send(value)
@@ -91,6 +95,21 @@ module JekyllImport
91
95
  f.puts output
92
96
  end
93
97
  end
98
+
99
+ def self.get_tags(item, options)
100
+ explicit_tag = options["tag"]
101
+ return explicit_tag unless explicit_tag.nil? || explicit_tag.empty?
102
+
103
+ tags_reference = options["extract_tags"]
104
+ return unless tags_reference
105
+
106
+ tags_from_feed = item.instance_variable_get("@#{tags_reference}")
107
+ return unless tags_from_feed.is_a?(Array)
108
+
109
+ tags = tags_from_feed.map { |feed_tag| feed_tag.content.downcase }
110
+ tags.empty? ? nil : tags.tap(&:uniq!)
111
+ end
112
+ private_class_method :get_tags
94
113
  end
95
114
  end
96
115
  end
@@ -17,25 +17,25 @@ module JekyllImport
17
17
  end
18
18
 
19
19
  def self.specify_options(c)
20
- c.option "dbname", "--dbname DB", "Database name (default: '')"
21
- c.option "socket", "--socket SOCKET", "Database socket (default: '')"
22
- c.option "user", "--user USER", "Database user name (default: '')"
23
- c.option "password", "--password PW", "Database user's password (default: '')"
24
- c.option "host", "--host HOST", "Database host name (default: 'localhost')"
25
- c.option "port", "--port PORT", "Custom database port connect to (default: 3306)"
26
- c.option "table_prefix", "--table_prefix PREFIX", "Table prefix name (default: 'serendipity_')"
27
- c.option "clean_entities", "--clean_entities", "Whether to clean entities (default: true)"
28
- c.option "comments", "--comments", "Whether to import comments (default: true)"
29
- c.option "categories", "--categories", "Whether to import categories (default: true)"
30
- c.option "tags", "--tags", "Whether to import tags (default: true)"
31
- c.option "drafts", "--drafts", "Whether to export drafts as well"
32
- c.option "markdown", "--markdown", "convert into markdown format (default: false)"
33
- c.option "permalinks", "--permalinks", "preserve S9Y permalinks (default: false)"
34
- c.option "excerpt_separator", "--excerpt_separator", "Demarkation for excerpts (default: '<a id=\"extended\"></a>')"
35
- c.option "includeentry", "--includeentry", "Replace macros from the includeentry plugin (default: false)"
36
- c.option "imgfig", "--imgfig", "Replace nested img and youtube divs with HTML figure tags (default: true)"
37
- c.option "linebreak", "--linebreak", "Line break processing: wp, nokogiri, ignore (default: wp)"
38
- c.option "relative", "--relative", "Convert links with this prefix to relative (default:nil)"
20
+ c.option "dbname", "--dbname DB", "Database name. (default: '')"
21
+ c.option "socket", "--socket SOCKET", "Database socket. (default: '')"
22
+ c.option "user", "--user USER", "Database user name. (default: '')"
23
+ c.option "password", "--password PW", "Database user's password. (default: '')"
24
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
25
+ c.option "port", "--port PORT", "Custom database port connect to. (default: 3306)"
26
+ c.option "table_prefix", "--table_prefix PREFIX", "Table prefix name. (default: 'serendipity_')"
27
+ c.option "clean_entities", "--clean_entities", "Whether to clean entities. (default: true)"
28
+ c.option "comments", "--comments", "Whether to import comments. (default: true)"
29
+ c.option "categories", "--categories", "Whether to import categories. (default: true)"
30
+ c.option "tags", "--tags", "Whether to import tags. (default: true)"
31
+ c.option "drafts", "--drafts", "Whether to export drafts as well. (default: true)"
32
+ c.option "markdown", "--markdown", "convert into markdown format. (default: false)"
33
+ c.option "permalinks", "--permalinks", "preserve S9Y permalinks. (default: false)"
34
+ c.option "excerpt_separator", "--excerpt_separator", "Demarkation for excerpts. (default: '<a id=\"extended\"></a>')"
35
+ c.option "includeentry", "--includeentry", "Replace macros from the includeentry plugin. (default: false)"
36
+ c.option "imgfig", "--imgfig", "Replace nested img and youtube divs with HTML figure tags. (default: true)"
37
+ c.option "linebreak", "--linebreak", "Line break processing: wp, nokogiri, ignore. (default: wp)"
38
+ c.option "relative", "--relative", "Convert links with this prefix to relative. (default: nil)"
39
39
  end
40
40
 
41
41
  # Main migrator function. Call this to perform the migration.
@@ -99,7 +99,7 @@ module JekyllImport
99
99
  options = {
100
100
  :user => opts.fetch("user", ""),
101
101
  :pass => opts.fetch("password", ""),
102
- :host => opts.fetch("host", "localhost"),
102
+ :host => opts.fetch("host", "127.0.0.1"),
103
103
  :port => opts.fetch("port", 3306),
104
104
  :socket => opts.fetch("socket", nil),
105
105
  :dbname => opts.fetch("dbname", ""),
@@ -27,17 +27,17 @@ module JekyllImport
27
27
  end
28
28
 
29
29
  def self.specify_options(c)
30
- c.option "dbname", "--dbname DB", "Database name"
31
- c.option "user", "--user USER", "Database user name"
32
- c.option "password", "--password PW", "Database user's password"
33
- c.option "host", "--host HOST", 'Database host name (default: "localhost")'
30
+ c.option "dbname", "--dbname DB", "Database name."
31
+ c.option "user", "--user USER", "Database user name."
32
+ c.option "password", "--password PW", "Database user's password. (default: '')"
33
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
34
34
  end
35
35
 
36
36
  def self.process(options)
37
37
  dbname = options.fetch("dbname")
38
38
  user = options.fetch("user")
39
39
  pass = options.fetch("password", "")
40
- host = options.fetch("host", "localhost")
40
+ host = options.fetch("host", "127.0.0.1")
41
41
 
42
42
  db = Sequel.mysql2(dbname, :user => user, :password => pass, :host => host, :encoding => "utf8")
43
43
 
@@ -19,11 +19,11 @@ module JekyllImport
19
19
  end
20
20
 
21
21
  def specify_options(c)
22
- c.option "url", "--url URL", "Tumblr URL"
23
- c.option "format", "--format FORMAT", 'Output format (default: "html")'
24
- c.option "grab_images", "--grab_images", "Whether to grab images (default: false)"
25
- c.option "add_highlights", "--add_highlights", "Whether to add highlights (default: false)"
26
- c.option "rewrite_urls", "--rewrite_urls", "Whether to rewrite URLs (default: false)"
22
+ c.option "url", "--url URL", "Tumblr URL."
23
+ c.option "format", "--format FORMAT", "Output format. (default: 'html')"
24
+ c.option "grab_images", "--grab_images", "Whether to grab images. (default: false)"
25
+ c.option "add_highlights", "--add_highlights", "Whether to add highlights. (default: false)"
26
+ c.option "rewrite_urls", "--rewrite_urls", "Whether to rewrite URLs. (default: false)"
27
27
  end
28
28
 
29
29
  def process(options)
@@ -31,11 +31,11 @@ module JekyllImport
31
31
  end
32
32
 
33
33
  def self.specify_options(c)
34
- c.option "server", "--server TYPE", 'Server type ("mysql" or "postgres")'
35
- c.option "dbname", "--dbname DB", "Database name"
36
- c.option "user", "--user USER", "Database user name"
37
- c.option "password", "--password PW", "Database user's password (default: '')"
38
- c.option "host", "--host HOST", "Database host name"
34
+ c.option "server", "--server TYPE", "Server type ('mysql' or 'postgres')."
35
+ c.option "dbname", "--dbname DB", "Database name."
36
+ c.option "user", "--user USER", "Database user name."
37
+ c.option "password", "--password PW", "Database user's password. (default: '')"
38
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
39
39
  end
40
40
 
41
41
  def self.process(options)
@@ -43,7 +43,7 @@ module JekyllImport
43
43
  dbname = options.fetch("dbname")
44
44
  user = options.fetch("user")
45
45
  pass = options.fetch("password", "")
46
- host = options.fetch("host", "localhost")
46
+ host = options.fetch("host", "127.0.0.1")
47
47
 
48
48
  FileUtils.mkdir_p "_posts"
49
49
  case server.intern
@@ -14,23 +14,23 @@ module JekyllImport
14
14
  end
15
15
 
16
16
  def self.specify_options(c)
17
- c.option "dbname", "--dbname DB", "Database name (default: '')"
18
- c.option "socket", "--socket SOCKET", "Database socket (default: '')"
19
- c.option "user", "--user USER", "Database user name (default: '')"
20
- c.option "password", "--password PW", "Database user's password (default: '')"
21
- c.option "host", "--host HOST", "Database host name (default: 'localhost')"
22
- c.option "port", "--port PORT", "Database port number (default: '')"
23
- c.option "table_prefix", "--table_prefix PREFIX", "Table prefix name (default: 'wp_')"
24
- c.option "site_prefix", "--site_prefix PREFIX", "Site prefix name (default: '')"
25
- c.option "clean_entities", "--clean_entities", "Whether to clean entities (default: true)"
26
- c.option "comments", "--comments", "Whether to import comments (default: true)"
27
- c.option "categories", "--categories", "Whether to import categories (default: true)"
28
- c.option "tags", "--tags", "Whether to import tags (default: true)"
29
- c.option "more_excerpt", "--more_excerpt", "Whether to use more excerpt (default: true)"
30
- c.option "more_anchor", "--more_anchor", "Whether to use more anchor (default: true)"
17
+ c.option "dbname", "--dbname DB", "Database name. (default: '')"
18
+ c.option "socket", "--socket SOCKET", "Database socket. (default: '')"
19
+ c.option "user", "--user USER", "Database user name. (default: '')"
20
+ c.option "password", "--password PW", "Database user's password. (default: '')"
21
+ c.option "host", "--host HOST", "Database host name. (default: 'localhost')"
22
+ c.option "port", "--port PORT", "Database port number. (default: '')"
23
+ c.option "table_prefix", "--table_prefix PREFIX", "Table prefix name. (default: 'wp_')"
24
+ c.option "site_prefix", "--site_prefix PREFIX", "Site prefix name. (default: '')"
25
+ c.option "clean_entities", "--clean_entities", "Whether to clean entities. (default: true)"
26
+ c.option "comments", "--comments", "Whether to import comments. (default: true)"
27
+ c.option "categories", "--categories", "Whether to import categories. (default: true)"
28
+ c.option "tags", "--tags", "Whether to import tags. (default: true)"
29
+ c.option "more_excerpt", "--more_excerpt", "Whether to use more excerpt. (default: true)"
30
+ c.option "more_anchor", "--more_anchor", "Whether to use more anchor. (default: true)"
31
31
 
32
32
  c.option "status", "--status STATUS,STATUS2", Array,
33
- "Array of allowed statuses (default: ['publish'], other options: 'draft', 'private', 'revision')"
33
+ "Array of allowed statuses ('publish', 'draft', 'private', 'revision'). (default: ['publish'])"
34
34
  end
35
35
 
36
36
  # Main migrator function. Call this to perform the migration.
@@ -81,7 +81,7 @@ module JekyllImport
81
81
  options = {
82
82
  :user => opts.fetch("user", ""),
83
83
  :pass => opts.fetch("password", ""),
84
- :host => opts.fetch("host", "localhost"),
84
+ :host => opts.fetch("host", "127.0.0.1"),
85
85
  :port => opts.fetch("port", "3306"),
86
86
  :socket => opts.fetch("socket", nil),
87
87
  :dbname => opts.fetch("dbname", ""),
@@ -16,9 +16,9 @@ module JekyllImport
16
16
  end
17
17
 
18
18
  def self.specify_options(c)
19
- c.option "source", "--source FILE", 'WordPress export XML file (default: "wordpress.xml")'
20
- c.option "no_fetch_images", "--no-fetch-images", "Do not fetch the images referenced in the posts"
21
- c.option "assets_folder", "--assets_folder FOLDER", "Folder where assets such as images will be downloaded to (default: assets)"
19
+ c.option "source", "--source FILE", "WordPress export XML file (default: 'wordpress.xml')"
20
+ c.option "no_fetch_images", "--no-fetch-images", "Do not fetch the images referenced in the posts (default: false)"
21
+ c.option "assets_folder", "--assets_folder FOLDER", "Folder where assets such as images will be downloaded to (default: 'assets')"
22
22
  end
23
23
 
24
24
  # Will modify post DOM tree
@@ -28,7 +28,7 @@ module JekyllImport
28
28
 
29
29
  Jekyll.logger.info "Downloading images for ", title
30
30
  images.each do |i|
31
- uri = i["src"]
31
+ uri = URI::DEFAULT_PARSER.escape(i["src"])
32
32
 
33
33
  dst = File.join(assets_folder, File.basename(uri))
34
34
  i["src"] = File.join("{{ site.baseurl }}", dst)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllImport
4
- VERSION = "0.21.0"
4
+ VERSION = "0.23.0"
5
5
  end